7 files deleted
27 files added
8 files modified
| | |
| | | const config = { |
| | | // baseUrl: "http://120.26.43.34:8081/api/", //测试 |
| | | baseUrl: "https://qx.7drlb.com/api", //生产 |
| | | // baseUrl: "http://192.168.0.9:8081/api", //生产 |
| | | // baseUrl: "http://192.168.0.12:8081/api", //生产 |
| | | }; |
| | | module.exports = config; |
| | |
| | | { |
| | | "name" : "test", |
| | | "appid" : "__UNI__93C3197", |
| | | "description" : "", |
| | | "versionName" : "1.0.0", |
| | | "versionCode" : "100", |
| | | "transformPx" : false, |
| | | /* 5+App特有相关 */ |
| | | "app-plus" : { |
| | | "usingComponents" : true, |
| | | "nvueStyleCompiler" : "uni-app", |
| | | "compilerVersion" : 3, |
| | | "splashscreen" : { |
| | | "alwaysShowBeforeRender" : true, |
| | | "waiting" : true, |
| | | "autoclose" : true, |
| | | "delay" : 0 |
| | | }, |
| | | /* 模块配置 */ |
| | | "modules" : {}, |
| | | /* 应用发布信息 */ |
| | | "distribute" : { |
| | | /* android打包配置 */ |
| | | "android" : { |
| | | "permissions" : [ |
| | | "<uses-permission android:name=\"android.permission.CHANGE_NETWORK_STATE\"/>", |
| | | "<uses-permission android:name=\"android.permission.MOUNT_UNMOUNT_FILESYSTEMS\"/>", |
| | | "<uses-permission android:name=\"android.permission.VIBRATE\"/>", |
| | | "<uses-permission android:name=\"android.permission.READ_LOGS\"/>", |
| | | "<uses-permission android:name=\"android.permission.ACCESS_WIFI_STATE\"/>", |
| | | "<uses-feature android:name=\"android.hardware.camera.autofocus\"/>", |
| | | "<uses-permission android:name=\"android.permission.ACCESS_NETWORK_STATE\"/>", |
| | | "<uses-permission android:name=\"android.permission.CAMERA\"/>", |
| | | "<uses-permission android:name=\"android.permission.GET_ACCOUNTS\"/>", |
| | | "<uses-permission android:name=\"android.permission.READ_PHONE_STATE\"/>", |
| | | "<uses-permission android:name=\"android.permission.CHANGE_WIFI_STATE\"/>", |
| | | "<uses-permission android:name=\"android.permission.WAKE_LOCK\"/>", |
| | | "<uses-permission android:name=\"android.permission.FLASHLIGHT\"/>", |
| | | "<uses-feature android:name=\"android.hardware.camera\"/>", |
| | | "<uses-permission android:name=\"android.permission.WRITE_SETTINGS\"/>" |
| | | ] |
| | | }, |
| | | /* ios打包配置 */ |
| | | "ios" : {}, |
| | | /* SDK配置 */ |
| | | "sdkConfigs" : {} |
| | | } |
| | | }, |
| | | /* 快应用特有相关 */ |
| | | "quickapp" : {}, |
| | | /* 小程序特有相关 */ |
| | | "mp-weixin" : { |
| | | "appid" : "wx41f4c3c007545088", |
| | | "setting" : { |
| | | "urlCheck" : false, |
| | | "es6" : true, |
| | | "postcss" : true, |
| | | "minified" : true |
| | | }, |
| | | "usingComponents" : true |
| | | }, |
| | | "mp-alipay" : { |
| | | "usingComponents" : true |
| | | }, |
| | | "mp-baidu" : { |
| | | "usingComponents" : true |
| | | }, |
| | | "mp-toutiao" : { |
| | | "usingComponents" : true |
| | | }, |
| | | "uniStatistics" : { |
| | | "enable" : false |
| | | }, |
| | | "vueVersion" : "2" |
| | | } |
| | | "name": "test", |
| | | "appid": "__UNI__93C3197", |
| | | "description": "", |
| | | "versionName": "1.0.0", |
| | | "versionCode": "100", |
| | | "transformPx": false, |
| | | /* 5+App特有相关 */ |
| | | "app-plus": { |
| | | "usingComponents": true, |
| | | "nvueStyleCompiler": "uni-app", |
| | | "compilerVersion": 3, |
| | | "splashscreen": { |
| | | "alwaysShowBeforeRender": true, |
| | | "waiting": true, |
| | | "autoclose": true, |
| | | "delay": 0 |
| | | }, |
| | | /* 模块配置 */ |
| | | "modules": {}, |
| | | /* 应用发布信息 */ |
| | | "distribute": { |
| | | /* android打包配置 */ |
| | | "android": { |
| | | "permissions": ["<uses-permission android:name=\"android.permission.CHANGE_NETWORK_STATE\"/>", |
| | | "<uses-permission android:name=\"android.permission.MOUNT_UNMOUNT_FILESYSTEMS\"/>", |
| | | "<uses-permission android:name=\"android.permission.VIBRATE\"/>", |
| | | "<uses-permission android:name=\"android.permission.READ_LOGS\"/>", |
| | | "<uses-permission android:name=\"android.permission.ACCESS_WIFI_STATE\"/>", |
| | | "<uses-feature android:name=\"android.hardware.camera.autofocus\"/>", |
| | | "<uses-permission android:name=\"android.permission.ACCESS_NETWORK_STATE\"/>", |
| | | "<uses-permission android:name=\"android.permission.CAMERA\"/>", |
| | | "<uses-permission android:name=\"android.permission.GET_ACCOUNTS\"/>", |
| | | "<uses-permission android:name=\"android.permission.READ_PHONE_STATE\"/>", |
| | | "<uses-permission android:name=\"android.permission.CHANGE_WIFI_STATE\"/>", |
| | | "<uses-permission android:name=\"android.permission.WAKE_LOCK\"/>", |
| | | "<uses-permission android:name=\"android.permission.FLASHLIGHT\"/>", |
| | | "<uses-feature android:name=\"android.hardware.camera\"/>", |
| | | "<uses-permission android:name=\"android.permission.WRITE_SETTINGS\"/>" |
| | | ] |
| | | }, |
| | | /* ios打包配置 */ |
| | | "ios": {}, |
| | | /* SDK配置 */ |
| | | "sdkConfigs": {} |
| | | } |
| | | }, |
| | | /* 快应用特有相关 */ |
| | | "quickapp": {}, |
| | | /* 小程序特有相关 */ |
| | | "mp-weixin": { |
| | | "appid": "wxf95fb77e0b1f8c09", |
| | | "__usePrivacyCheck__": true, |
| | | "setting": { |
| | | "urlCheck": false, |
| | | "es6": true, |
| | | "postcss": true, |
| | | "minified": true |
| | | }, |
| | | "usingComponents": true |
| | | }, |
| | | "mp-alipay": { |
| | | "usingComponents": true |
| | | }, |
| | | "mp-baidu": { |
| | | "usingComponents": true |
| | | }, |
| | | "mp-toutiao": { |
| | | "usingComponents": true |
| | | }, |
| | | "uniStatistics": { |
| | | "enable": false |
| | | }, |
| | | "vueVersion": "2" |
| | | } |
| | |
| | | "disableSwipeBack": true, |
| | | "navigationStyle": "custom" |
| | | } |
| | | }, { |
| | | "path": "pages/actionChange/secondLevelData/index", |
| | | "style": { |
| | | "navigationBarTitleText": "秒级数据", |
| | | "enablePullDownRefresh": false, |
| | | "disableSwipeBack": true |
| | | } |
| | | } |
| | | ] |
| | | // "tabBar": { |
| | |
| | | id: e.allocationId |
| | | }).then(res => { |
| | | let data = res.data |
| | | data.pageState = data.state === 50 || data.state === 40 ? 'view' : pageState |
| | | data.pageState = e.stateName === '待处理' ? pageState : 'view' |
| | | let myData = JSON.stringify(data) |
| | | uni.navigateTo({ |
| | | url: '/pages/actionChange/workOrderDetails/index?infor=' + myData, |
| | |
| | | let name = item.fileType === 1 ? 'name.png' : 'name.mp4' |
| | | this.fileList.push(`${this.baseUrl}/file/preview/${item.fileId}?${name}`) // 原图 |
| | | }) |
| | | console.log('this.fileList', this.basicInfor.fileBaseList) |
| | | console.log('this.fileList', this.fileList) |
| | | } |
| | | let userInfor = JSON.parse(uni.getStorageSync('userInfor') || '{}') |
| | | console.log('userInfor', userInfor) |
| | | if (this.basicInfor.pageState === 'edit') { |
| | | this.form.changeName = userInfor.userName |
| | | } |
| | | }, |
| | | methods: { |
| | |
| | | <u-cell icon="account-fill" title="账号" :value="userInfor.account"></u-cell> |
| | | <u-cell icon="integral-fill" title="责任单位" :value="unitName"></u-cell> |
| | | <u-cell icon="phone-fill" title="手机号" :value="userInfor.mobile"></u-cell> |
| | | <u-cell icon="clock-fill" title="查看秒级数据" v-if="userInfor.device===1" isLink |
| | | url="/pages/actionChange/secondLevelData/index"></u-cell> |
| | | </u-cell-group> |
| | | </view> |
| | | <view class="bunts"> |
| | |
| | | this.form.escalationUnitId = data |
| | | this.sumbitForm.escalationUnitId = userInfor.unitId |
| | | } |
| | | this.form.escalationName = userInfor.name || '' |
| | | this.sumbitForm.escalationName = userInfor.name || '' |
| | | this.form.escalationName = userInfor.userName || '' |
| | | this.sumbitForm.escalationName = userInfor.userName || '' |
| | | this.form.investigationType = 1 |
| | | this.sumbitForm.investigationType = 1 |
| | | console.log('this.sumbitForm', this.sumbitForm) |
New file |
| | |
| | | <template> |
| | | <view class="rootBg"> |
| | | <view class=""> |
| | | <view class="ridoa"> |
| | | <u-radio-group v-model="value" placement="row" :size='radioOption.size' |
| | | :labelColor='radioOption.labelColor' :labelSize='radioOption.labelSize' @change='changeSearchType'> |
| | | <u-radio activeColor="#19be6b" label="通过站点查询" name="0" :labelSize='radioOption.labelSize' |
| | | :labelColor='radioOption.labelColor'></u-radio> |
| | | <u-radio activeColor="#19be6b" label="通过设查号询" name="1" :labelSize='radioOption.labelSize' |
| | | :labelColor='radioOption.labelColor'></u-radio> |
| | | </u-radio-group> |
| | | </view> |
| | | <view class="" v-if="value==='1'"> |
| | | <u-input placeholder="请输入Mac号" :placeholderStyle='placeholderStyle' color="#fff" v-model='macName'> |
| | | <template slot="suffix"> |
| | | <u-button @tap="searchMacList" text="查询" type="success" size="small"></u-button> |
| | | </template> |
| | | </u-input> |
| | | </view> |
| | | <view class="" v-else> |
| | | <u-form ref="uForm" label-width="80" :model="form"> |
| | | <u-form-item border-bottom @click="showeEscalationTime = true ;hideKeyboard('orgName','orgId')"> |
| | | <u-input v-model="form.orgName" disabled disabled-color="#ffffff" placeholder="请选择组织" |
| | | type="select" /> |
| | | </u-form-item> |
| | | <u-form-item border-bottom @click="selectSite"> |
| | | <u-input v-model="form.siteName" disabled disabled-color="#ffffff" placeholder="请选择站点" |
| | | type="select" /> |
| | | </u-form-item> |
| | | </u-form> |
| | | <u-picker :show="showeEscalationTime" :columns="columns" @confirm="selectBack" keyName="name" |
| | | @cancel="showeEscalationTime = false"></u-picker> |
| | | </view> |
| | | </view> |
| | | <view v-if="wsData2"> |
| | | <u-cell title="风向:" :value="windDirData"></u-cell> |
| | | </view> |
| | | <view class="boxPadd"> |
| | | <u-list v-if="showData.length>0"> |
| | | <u-list-item v-for="(item, index) in showData" :key="index"> |
| | | <u-row customStyle="margin-bottom: 10px"> |
| | | <u-col span="3"> |
| | | <view>{{ item.sensorCode | sensorFilter}}</view> |
| | | </u-col> |
| | | <u-col span="6" textAlign="right"> |
| | | <u-line-progress :percentage="item.alarm" :activeColor="item.colour"></u-line-progress> |
| | | </u-col> |
| | | <u-col span="3" textAlign="right"> |
| | | <view>{{ item.value || ''}} </view> |
| | | </u-col> |
| | | </u-row> |
| | | </u-list-item> |
| | | </u-list> |
| | | </view> |
| | | <u-toast ref="uToast"></u-toast> |
| | | <u-modal :show="showModel" title='请选择Mac号' showCancelButton @cancel='showModel=false' @confirm='selectMac'> |
| | | <view class="slot-content"> |
| | | <u-radio-group v-model="modeleMacSelect" iconPlacement="right" placement='column' borderBottom='true'> |
| | | <view v-for="(item,index) in macList" :key="index" class="ridioBox"> |
| | | <u-radio activeColor="#19be6b" :label="item.mac" :name="item.mac"></u-radio> |
| | | </view> |
| | | </u-radio-group> |
| | | </view> |
| | | </u-modal> |
| | | </view> |
| | | </template> |
| | | <script> |
| | | import json from '@/pages/actionChange/secondLevelData/parameter.json' |
| | | import wsRequest from '@/utils/websoket.js' |
| | | export default { |
| | | data() { |
| | | return { |
| | | modeleMacSelect: '', |
| | | value: '0', |
| | | showModel: false, |
| | | showeEscalationTime: false, |
| | | columns: [], |
| | | form: { |
| | | orgName: '', |
| | | orgId: '', |
| | | siteName: '', |
| | | siteId: '' |
| | | }, |
| | | selectForm: { |
| | | name: '', |
| | | id: '' |
| | | }, |
| | | macList: [], |
| | | radioOption: { |
| | | size: '20px', |
| | | labelColor: '#fff', |
| | | labelSize: '18px' |
| | | }, |
| | | placeholderStyle: 'color: #fff', |
| | | macName: '', |
| | | defaultMonitorItems: [], |
| | | chartSensorKey: [], |
| | | coreMonitorItems: [], |
| | | fixedMonitorItems: [], |
| | | totalArray: [], |
| | | alarmLevel: null, |
| | | aqi: 0, |
| | | baseUrl: '', |
| | | windDir: 'null', |
| | | windDeg: 180, |
| | | wsData2: null, |
| | | // 报警进度条 |
| | | alarmProgress: {}, |
| | | // 报警颜色 |
| | | alarmColour: {}, |
| | | // 报警圆环图片 |
| | | alarmBg: {}, |
| | | timer: '', |
| | | isLoading: true |
| | | } |
| | | }, |
| | | filters: { |
| | | // 过滤器替换websocket实时数据的key值 |
| | | sensorFilter: function(value) { |
| | | if (!value) return '' |
| | | return json[value] |
| | | } |
| | | }, |
| | | computed: { |
| | | windDirData() { |
| | | if (this.wsData2) { |
| | | console.log('this.windDir', this.windDir) |
| | | return `${this.windDir} (${this.wsData2.a01008})` |
| | | } else { |
| | | return '' |
| | | } |
| | | }, |
| | | showData() { |
| | | return [...this.defaultMonitorItems, ...this.coreMonitorItems] |
| | | } |
| | | }, |
| | | created() { |
| | | this.getOrgs() |
| | | }, |
| | | onUnload() { |
| | | let that = this |
| | | this.socketTask.close() |
| | | that.isLoading = false |
| | | that.timer = '' |
| | | }, |
| | | methods: { |
| | | getData() { |
| | | this.queryAlarmByMac() |
| | | this.getHourlyAqi() |
| | | this.sensorLayout() |
| | | }, |
| | | changeSearchType() { |
| | | this.macName = '' |
| | | }, |
| | | selectMac() { |
| | | this.macName = this.modeleMacSelect |
| | | this.showModel = false |
| | | if (this.socketTask) { |
| | | this.socketTask.onClose() |
| | | } |
| | | this.getData() |
| | | }, |
| | | searchMacList() { |
| | | this.$http.httpGet('/AppDevice/fuzzySearch', { |
| | | mac: this.macName |
| | | }).then(res => { |
| | | this.showModel = true |
| | | if (res.data && res.data.length > 10) { |
| | | this.macList = res.data.slice(0, 10) |
| | | } |
| | | }).catch(res => { |
| | | uni.$u.toast(res) |
| | | }) |
| | | }, |
| | | selectSite() { |
| | | if (this.form.orgId === '') { |
| | | uni.showToast({ |
| | | title: '请先选择组织!', |
| | | icon: 'none', |
| | | }) |
| | | } else { |
| | | this.selectForm = { |
| | | name: 'siteName', |
| | | id: 'siteId' |
| | | }, |
| | | this.getSites() |
| | | } |
| | | }, |
| | | hideKeyboard(name, id) { |
| | | this.selectForm = { |
| | | 'name': name, |
| | | 'id': id |
| | | } |
| | | this.getOrgs() |
| | | }, |
| | | selectBack(e) { |
| | | if (this.selectForm.name === 'orgName') { |
| | | this.form = { |
| | | orgName: '', |
| | | orgId: '', |
| | | siteName: '', |
| | | siteId: '' |
| | | } |
| | | } else { |
| | | this.macName = e.value[0].mac |
| | | if (this.socketTask) { |
| | | this.socketTask.onClose() |
| | | } |
| | | this.getData() |
| | | } |
| | | this.form[this.selectForm.name] = e.value[0].name |
| | | this.form[this.selectForm.id] = e.value[0].id |
| | | this.showeEscalationTime = false |
| | | }, |
| | | getOrgs() { |
| | | this.$http.httpGet('/AppDevice/selectOrganization').then(res => { |
| | | this.columns = [] |
| | | this.columns.push(res.data) |
| | | }).catch(res => { |
| | | uni.$u.toast(res) |
| | | }) |
| | | }, |
| | | getSites() { |
| | | let params = { |
| | | organizationId: this.form.orgId |
| | | } |
| | | this.$http.httpGet('/AppDevice/selectDevice', params).then(res => { |
| | | console.log(res) |
| | | this.columns = [] |
| | | this.columns.push(res.data) |
| | | this.showeEscalationTime = true |
| | | }).catch(res => { |
| | | uni.$u.toast(res) |
| | | console.log(res) |
| | | }) |
| | | }, |
| | | sensorLayout() { |
| | | let params = { |
| | | mac: this.macName |
| | | } |
| | | this.$http.httpGet('/organizationLayout/getLayoutByMac', params).then(res => { |
| | | this.chartSensorKey = res.data.chartSensorKey |
| | | this.coreMonitorItems = res.data.coreMonitorItems |
| | | this.defaultMonitorItems = res.data.defaultMonitorItems |
| | | this.fixedMonitorItems = res.data.fixedMonitorItems |
| | | this.totalArray.push(...this.coreMonitorItems, ...this.defaultMonitorItems, ...this |
| | | .fixedMonitorItems) |
| | | this.getSensorMonthAvg() |
| | | this.connectSocket() |
| | | }).catch(res => { |
| | | uni.$u.toast(res) |
| | | console.log(res) |
| | | }) |
| | | }, |
| | | // 请求单台设备某参数月平均值 |
| | | getSensorMonthAvg() { |
| | | let params = { |
| | | sensorCode: this.chartSensorKey[0].sensorCode, |
| | | mac: this.macName |
| | | } |
| | | this.$http.httpGet('/deviceInfo/getMonthAvg', params).then(res => { |
| | | this.average = res.data.avg |
| | | }).catch(res => { |
| | | uni.$u.toast(res) |
| | | console.log(res) |
| | | }) |
| | | }, |
| | | // 设备因子报警值 |
| | | queryAlarmByMac() { |
| | | let params = { |
| | | mac: this.macName |
| | | } |
| | | this.$http.httpGet('/deviceInfo/queryAlarmByMac', params).then(res => { |
| | | this.alarmLevel = res.data.alarmLevel |
| | | }).catch(res => { |
| | | uni.$u.toast(res) |
| | | console.log(res) |
| | | }) |
| | | }, |
| | | // 请求单台设备一个小时 |
| | | getHourlyAqi() { |
| | | let params = { |
| | | mac: this.macName |
| | | } |
| | | this.$http.httpGet('/deviceInfo/getHourlyAqi', params).then(res => { |
| | | this.aqi = res.data.AQI |
| | | }).catch(res => { |
| | | uni.$u.toast(res) |
| | | console.log(res) |
| | | }) |
| | | }, |
| | | handlerMsg(msg) { |
| | | this.wsData2 = JSON.parse(msg.data) |
| | | if (this.wsData2.dustld) { |
| | | this.wsData2.dustld = this.wsData2.dustld.replace(/g/, 'ug') |
| | | } |
| | | // 风向算法 |
| | | if (this.wsData2.a01008) { |
| | | var windDirs = Number(this.wsData2.a01008.substr(0, this.wsData2.a01008.length - 1)) |
| | | this.windDeg = windDirs |
| | | if (windDirs === 0) { |
| | | this.windDir = '北风' |
| | | } else if (windDirs > 0 && windDirs < 90) { |
| | | this.windDir = '东北风' |
| | | } else if (windDirs === 90) { |
| | | this.windDir = '东风' |
| | | } else if (windDirs > 90 && windDirs < 180) { |
| | | this.windDir = '东南风' |
| | | } else if (windDirs === 180) { |
| | | this.windDir = '南风' |
| | | } else if (windDirs > 180 && windDirs < 270) { |
| | | this.windDir = '西南风' |
| | | } else if (windDirs === 270) { |
| | | this.windDir = '西风' |
| | | } else if (windDirs > 270 && windDirs < 360) { |
| | | this.windDir = '西北风' |
| | | } |
| | | } |
| | | this.alarmColour = {} |
| | | this.alarmProgress = {} |
| | | this.alarmBg = {} |
| | | // 报警等级 |
| | | for (const key in this.wsData2) { |
| | | if (this.chartSensorKey && key === this.chartSensorKey[0].sensorCode) { |
| | | this.chartSensorKey[0].value = this.wsData2[key] |
| | | } |
| | | for (const keys in this.alarmLevel) { |
| | | // 遍历进度条颜色 |
| | | if (key === keys && JSON.parse(this.alarmLevel[keys])) { |
| | | if (parseFloat(this.wsData2[key]) >= parseFloat(JSON.parse(this.alarmLevel[keys])[5])) { |
| | | this.alarmColour[keys] = '#000000' |
| | | this.alarmBg[keys] = 5 |
| | | } else if (parseFloat(this.wsData2[key]) >= parseFloat(JSON.parse(this.alarmLevel[keys])[4])) { |
| | | this.alarmColour[keys] = '#c00261' |
| | | this.alarmBg[keys] = 4 |
| | | } else if (parseFloat(this.wsData2[key]) >= parseFloat(JSON.parse(this.alarmLevel[keys])[3])) { |
| | | this.alarmColour[keys] = '#fc0101' |
| | | this.alarmBg[keys] = 3 |
| | | } else if (parseFloat(this.wsData2[key]) >= parseFloat(JSON.parse(this.alarmLevel[keys])[2])) { |
| | | this.alarmColour[keys] = '#ff8202' |
| | | this.alarmBg[keys] = 2 |
| | | } else if (parseFloat(this.wsData2[key]) >= parseFloat(JSON.parse(this.alarmLevel[keys])[1])) { |
| | | this.alarmColour[keys] = '#fdff00' |
| | | this.alarmBg[keys] = 1 |
| | | } else { |
| | | this.alarmColour[keys] = '#00ff01' |
| | | this.alarmBg[keys] = 0 |
| | | } |
| | | } else if (key === keys) { |
| | | this.alarmColour[keys] = '#00ff01' |
| | | this.alarmBg[keys] = 0 |
| | | } |
| | | // 遍历进度条百分比 |
| | | if (key === keys && JSON.parse(this.alarmLevel[keys])) { |
| | | if (JSON.parse(this.alarmLevel[keys])[5]) { |
| | | const percentage = Math.round( |
| | | (parseFloat(this.wsData2[key]) / parseFloat(JSON.parse(this.alarmLevel[keys])[ |
| | | 5])) * 100) |
| | | this.alarmProgress[keys] = percentage |
| | | } else if (JSON.parse(this.alarmLevel[keys])[4]) { |
| | | const percentage = Math.round( |
| | | (parseFloat(this.wsData2[key]) / parseFloat(JSON.parse(this.alarmLevel[keys])[ |
| | | 4])) * 100) |
| | | this.alarmProgress[keys] = percentage |
| | | } else if (JSON.parse(this.alarmLevel[keys])[3]) { |
| | | const percentage = Math.round( |
| | | (parseFloat(this.wsData2[key]) / parseFloat(JSON.parse(this.alarmLevel[keys])[ |
| | | 3])) * 100) |
| | | this.alarmProgress[keys] = percentage |
| | | } else if (JSON.parse(this.alarmLevel[keys])[2]) { |
| | | const percentage = Math.round( |
| | | (parseFloat(this.wsData2[key]) / parseFloat(JSON.parse(this.alarmLevel[keys])[ |
| | | 2])) * 100) |
| | | this.alarmProgress[keys] = percentage |
| | | } else if (JSON.parse(this.alarmLevel[keys])[1]) { |
| | | const percentage = Math.round( |
| | | (parseFloat(this.wsData2[key]) / parseFloat(JSON.parse(this.alarmLevel[keys])[ |
| | | 1])) * 100) |
| | | this.alarmProgress[keys] = percentage |
| | | } else if (JSON.parse(this.alarmLevel[keys])[0]) { |
| | | const percentage = Math.round( |
| | | (parseFloat(this.wsData2[key]) / parseFloat(JSON.parse(this.alarmLevel[keys])[ |
| | | 0])) * 100) |
| | | this.alarmProgress[keys] = percentage |
| | | } |
| | | } else if (key === keys) { |
| | | this.alarmProgress[keys] = 0 |
| | | } |
| | | if (this.alarmProgress[keys] > 100) { |
| | | this.alarmProgress[keys] = 100 |
| | | } |
| | | } |
| | | } |
| | | // 实时数据改变合并数组的值 |
| | | for (let i = 0; i < this.totalArray.length; i++) { |
| | | for (const key in this.wsData2) { |
| | | if (key !== 'time') { |
| | | // 获取数据的小数 |
| | | var tempDecimal = this.wsData2[key].replace(/[^\d.]/g, '').split('.')[1] |
| | | if (this.totalArray[i].sensorCode === key) { |
| | | // 臭气和湿度保留整数 |
| | | if (this.totalArray[i].sensorCode === 'a19002') { |
| | | this.totalArray[i].value = parseInt(this.wsData2[key]) |
| | | } else if (this.totalArray[i].sensorCode === 'a01002') { |
| | | this.totalArray[i].value = parseInt(this.wsData2[key]) + '%' |
| | | // 除了TVOCQ其他因子数据小数是零的就去掉小数 |
| | | } else if (this.totalArray[i].sensorCode !== 'a99054' && Number(tempDecimal) === 0) { |
| | | this.totalArray[i].value = parseInt(this.wsData2[key]) + this.wsData2[key].split(' ')[ |
| | | 1] |
| | | } else { |
| | | this.totalArray[i].value = this.wsData2[key] |
| | | } |
| | | } |
| | | } |
| | | } |
| | | for (const key in this.alarmProgress) { |
| | | if (this.totalArray[i].sensorCode === key) { |
| | | this.totalArray[i].alarm = this.alarmProgress[key] |
| | | } |
| | | } |
| | | console.log('this.totalArray', this.totalArray) |
| | | console.log('this.alarmColour', this.alarmColour) |
| | | for (const key in this.alarmColour) { |
| | | if (this.totalArray[i].sensorCode === key) { |
| | | this.totalArray[i].colour = this.alarmColour[key] |
| | | } |
| | | } |
| | | for (const key in this.alarmBg) { |
| | | if (this.totalArray[i].sensorCode === key) { |
| | | this.totalArray[i].bg = this.alarmBg[key] |
| | | } |
| | | } |
| | | } |
| | | }, |
| | | //连接websocket |
| | | connectSocket() { |
| | | if (!this.isLoading) { |
| | | this.socketTask.close() |
| | | this.socketTask = null |
| | | } |
| | | this.baseUrl = this.$storage.get('baseUrl') |
| | | let that = this |
| | | let socketUrl = this.baseUrl + '/singleDevice/' + this.macName |
| | | socketUrl = socketUrl.replace('https', 'wss').replace('http', 'ws') |
| | | console.log('调用连接websocket') |
| | | this.socketTask = uni.connectSocket({ |
| | | url: socketUrl, |
| | | success(res) { |
| | | console.log('websocket连接成功') |
| | | that.isLoading = true |
| | | }, |
| | | fail(err) { |
| | | console.log('报错', err) |
| | | } |
| | | }, ) |
| | | this.socketTask.onOpen(function(res) { |
| | | console.log('WebSocket连接已打开!') |
| | | that.isLoading = true |
| | | // that.getStatus() |
| | | // that.heart() |
| | | }) |
| | | this.socketTask.onMessage(function(res) { |
| | | console.log('收到服务器内容:' + res.data) |
| | | that.handlerMsg(res) //这里是对获取到的数据进行操作 |
| | | }) |
| | | this.socketTask.onError(function(res) { |
| | | console.log('WebSocket连接打开失败,请检查!') |
| | | console.log(res) |
| | | // this.isSuccess = false |
| | | // that.connectSocket() |
| | | //进入重新连接 |
| | | that.reconnect() |
| | | }) |
| | | // // 监听连接关闭 - |
| | | this.socketTask.onClose(e => { |
| | | console.log('WebSocket连接关闭!') |
| | | clearInterval(that.timer) |
| | | that.timer = '' |
| | | if (!that.isClose) { |
| | | that.reconnect() |
| | | } |
| | | }) |
| | | console.log(this.socketTask) |
| | | }, |
| | | //进入重新连接 |
| | | reconnect() { |
| | | console.log('进入断线重连') |
| | | this.socketTask.close() |
| | | this.socketTask = null |
| | | if (this.isLoading) { |
| | | this.connectSocket() |
| | | } |
| | | }, |
| | | //发送消息 |
| | | sendSocketMessage(msg) { |
| | | console.log('发送信息') |
| | | console.log(msg) |
| | | return new Promise((reslove, reject) => { |
| | | this.socketTask.send({ |
| | | data: msg, |
| | | success(res) { |
| | | console.log('发送成功') |
| | | reslove(res) |
| | | }, |
| | | fail(res) { |
| | | console.log('发送失败') |
| | | console.log(res) |
| | | reject(res) |
| | | } |
| | | }) |
| | | }) |
| | | }, |
| | | //心跳 |
| | | heart() { |
| | | let that = this |
| | | clearInterval(this.timer) |
| | | this.timer = '' |
| | | let msg = { |
| | | 'type': 'heartbeat', |
| | | } |
| | | this.timer = setInterval(() => { |
| | | that.sendSocketMessage(JSON.stringify(msg)).then(res => { |
| | | console.log('心跳成功') |
| | | }).catch(res => { |
| | | console.log('发送失败') |
| | | console.log((res)) |
| | | }) |
| | | }, 2000) |
| | | }, |
| | | beforeDestroy() { |
| | | if (this.socketTask) { |
| | | this.socketTask.close() |
| | | this.socketTask = null |
| | | } |
| | | if (this.timer) { |
| | | clearInterval(this.timer) // 在Vue实例销毁前,清除我们的定时器 |
| | | } |
| | | }, |
| | | } |
| | | } |
| | | </script> |
| | | <style scoped lang="scss"> |
| | | .rootBg { |
| | | min-height: 100%; |
| | | color: #fff; |
| | | /* 背景图垂直、水平均居中 */ |
| | | background-position: center center; |
| | | /* 背景图不平铺 */ |
| | | background-repeat: no-repeat; |
| | | /* 当内容高度大于图片高度时,背景图像的位置相对于viewport固定 */ |
| | | background-attachment: fixed; |
| | | /* 让背景图基于容器大小伸缩 */ |
| | | background-size: cover; |
| | | background-image: url('data:image/jpeg;base64,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se1AznigBXAGMU7aMUw570vzYoAFAOaRgAeKBntSEHPNAEm0YpqAGk+bHtQM54oAGAB4pwUYpNuQSTyKQbscUAKo5NTWygXtv/10X+dVxnPHWp7XP263z/z0X+dDGh13/wAftx/10b+dQ96sXo/02f8A66N/OoMUlsUFFAGT1opiEpaAKX60hiYopTz2ooASilxRQIbS0uKMUANopcUYoASloo60wAUUuKVcA8jPtSEJxTgBtznn0ptLQAtLSAU4UAKjsn3TSMSxyeTRRQAlFLS0ANoxTsUYoENxRS0YoATFLRRTATFKAMHP4UUUhAqFs47cmk7UtJQAYGaDjPtSUUwCkpaSgAooxRQAUoxjmkpaAFU4NK5BGKaBk4pzKAMigAUgDFJkb80qqCM0m35sUAOZhtoVgBikZQBkUqoMZoEJuG7PalYgrxQmElBIDAdjQ4HJ6UgFVhtpA2HyKFUY5oC/NigBXbceTye9OyBxnpTXTC7gOKAoxQIQEbiaVyMYo2jdgE496GUAcUDHKUxycACmBhuz604KMUwjBoAc5GKbR6ZoOM8dKACigiigAooFL+HFMQlLn5SMD60maKAEooooAKKVVLZI7cmkoEFFFFAC0lFFACqpY4H60UlOU7WzgH2oAbQaO9FADi25QMAbfTvTaMUUAGaWhlCtjIPuKTvQAtGaSlBI6UAFFJRQAtHJ6mikoELSUUoFACUUUUAFFFFABR2oooAKWijk9KACiiigBy43c0r4xTKKAJFI200Eb6UKMUm35sUgFfGKUEYprKAM0BRimAKcOaHIx70gX5iKVxgZoAchHGenem5XzG28L2oCjFH3m57elAwcjHvSgjFNZcDNNoAD1ooooASilpKACiikoAWiiigAooooAKKKKAEpe1JR2oAKKKKAClIwaONvQ59aCSxyetACUUUUDCneU2wPjIPpTaAzDoSKAEooooAVSo+8M0lFFAB3opKWgBKO9FFABRRSUDCiiigAooooAKKKKACiiigYlFFLxigBKKKKACiiigABIzjvSUtJQAUY4zRRQMKMcZ7UGkoAWkpcUlAEgYYpoYbiacFG3kU0AbiKAFZgRxShhikZQBxShRigBqsNxJ70OQeBQoG4+1DgDpQA4MMU1SAc07aMU1QCaABiCKdvGOtNYACnbRigBqnmhiCKRRk0rgADFAC7hikVgCc0oUYpFAJNAAzZ4FO3jFNcAdKdtGKAGqcE0MQelCjk0MAKAHbhimqQDzTtoxTUUFuaAByD0pQwxSOoB4pwUYoAap+b61Pbn/Trceki/wA6gUZY1NbAC9t/+ui/zoYLcnvAPts//XRv51XIFT3hP22f/ro386gPPWpRTG8UUtFMAoooxQAUD6UUUAAFGKeo9qNtIBmKKftNNIoAQ9aMUuKSgBKMUtFMAopc8Y7UlABQKUUuPSgApaSlFAC4oopcUAGKUDPelA55o6dOlIQ3FGKdijFADcUYNLiigQ3FFPABU5OMfrQ3Kg/hQAylHDcj8KMc0hyTk0wFZt3YCm4paKBCdaSnc0mKBjaDjPBzSmkpiEopaKAEoopcEdRQAZxzRknqaKKQCru7dKTnPvT1YYpAfnzQAjE45pydOTgUMwxilVhtxQBHzn3px3d6AfmzTmIK4pgNG7HFIM596kUjFKEb723g0hEbFsYPSlG7HFLJgcA5oDDFADRnPHWlYnvQCNxNKxUjHegABbFNp4YYpowzYJwKAEopT1POaSgApc/KB6UlLQADGDkUBiFIHQ0EcnByKSgQUlLRimAlFLikoAKUnJ4GKMUYxQAlFLSYoEFKTk80lFABS0lLQAlL+FFKWLAA9hgUAIaQilooASiiigAooooEFGCegopQxXOD1oASilxSUDCiiigAoopQrNnAzjrQAlGaKKADvSmkooAU44xmlVipyKSigQVatoVZN7DJ7VVqWGdohjGVNS720AmuIUCb1GCOtVQQDyMipJbgyjbjC1Fx3oV7agxwLY4pMnPvTwRimhhuqgEYnvQC2KVyMUoYYoGMBOeOtDE96UEBjSuRigBxCiMFGJPcGosnOaerDFMJyTQApYmkpKWgApKX+VJQAUUUUAFFFBGDQAUmaKKAFoU4YHAPsaKSgBSckn1pKWkoAMUrNuI4AwO1FJQAUUUUAGTjGeKKBjPIzRQAUlLSUDCiiigAooooAKKKBjPNABj1NFSvCFTcDzUVFwEPtQODRRQAdcmigDIJ7CigYlFFFABRRRQAUcUUUDCkpaM8YoAKSlpKAClJyaCMdaSgApcfLnIpKKACgHGfekpcZXOaAEpdp27u1JRk4x2oAUYOcmkpKKBi0lFFAD8MBgU0Zzx1p4cYpobBz60AI2e9KA2OOlDMDwKUMMUANGc8daGz3pQcMc96GYHpQAANj2poznjrT92BzSAqOec+lACNu70uG2+1DMD0pd4xQAwZzx1pTkdaFODSswPSgACsVJHSmjOeKeHGKarYPPegBGznmlw2KGbPSnbxigYxc54pWznmhWweaGbPSgBfmxSDJOR1p28Y96RWA60CBgQeaAGxxQxz0pQ4xQA0Zzx1qe1z9ut8/wDPRf51CrYOT3qe2YG9t8f89F/nQwRLeD/TZ/8Aro386gqzd/8AH7OP+mjfzqEipRbQyinhaNlArDMUVJs4pNlFwsMxTgmaeqgU8ACi40hFTjmnhM9KTNLmpKGlaiZcc1OaYy5poTIaTt0p5GOKbTJExRS0UAJRS0UAL1PFFFFABS4o60YoAdkYxiikp4AxmgAAo/ClxSdaQAKKXFHtTEJjPSkIp1GKAG4pKfj36dqbigQ3qaKdikx+VACUUtFADSOBRTjzSc4x2pgNxQad/KkxQA0ijHGaXFGKABlAUEHJPUUhJPU9KMUHmgBKKXFJigB6qMUgX5sUo3Y4pozn3oAcygDIpQgxTW3Y5pRuxxQIQL82KcygDimhj075pWzjmgByqMZqXzcrtx2xUI3beOlIM5460gsKygDIpQoxTW3YGelKC2OKYAq/NihlAGRTckHPelJJ60AGBt6/NSU5QC3zHA9aSgBKWiigAoNFHSgAoClhkDgUGjJAwDQISiilZixyaAEoo4x0ooAUDJxSspU4NGAYye4pO1AgooooASjFLSs2VUccUAN7miigHBpiCilPU4ptABS0lKDhSPWgAooxR2FAAMZ+bpRn06UUlABRRRQAUUU4IdoYnC5xmgBtFKRgkA596SgAoyRkA9etFFAABk4FFFHFABRRRQAUoBPA60lAJHSgQ5gAcA5pKOtJQAtKrYBGBzTaKAJAoxQ21mGBtAHQU0MQMUmcHOaBisoA4pQoxTSxNAY8CgAC5Yj0pWUAZFIco3vQWJ+lADaKKKAF4zSUUUAFFKaSgAooooAKKKKACiiigAooooAKSiigAooooAKKKUjBxnNAxKKKM0AFJSkjPAwKSgAooooAKKKSgBaKKSgBSxIwSTSUUUDCiiigBKM0UUALSUUUAFLgmkozjvQAUlLRQMSiiigAooooAKKKKAEopaSgAooooGFFFFABRRRQAGkoooAkCjFNC/MRSAkDFAJBzQA51AGRShRimEk9aUMQKAEPWkoooAM8YooooGFFFFABRRRQBJtGKjNLuOMUlAhKk2DFR075se1AAqgmhlA6UgznilJ5+YZoGO2DFNVc5zR82PakBPagQ5hjpShBimNnvSjdj2oAVVyxFTWoxe25H/PRf51X3EGprQk31vn/AJ6L/OhjRcvB/ps//XRv51Ae1WLs/wCmz/8AXRv51XPNQi2ISSaMmjFGKYh4aimjJPFPApALRS4oxQMTrThQBS/SkAUhp1NIoAjNNYYp5U0mzPFMQwKTQRzgVPtwuKjIFFwGYoAp4UUuMUAM20bfenE+tJTAQUuKU4zx0oHSkIAKUUUooABR+FLRQAUUoGacV/SgBmKCMngYxTiKMUCG4pMU4gjrSEUAJikNOxxRigBtJinYowe9MQ3HWk7U/FAwOvSgBvXrRgU7A/D0pMUANNNxUnGDkUmKAGDINJipMUmKAGYoxTsUYoAVSMUgI3Zp4UYpoUbsdqAByCMChWGKVkAHFAQY5pgNDcn0pWIIxQEy+KVlAHFAhFYYpARuzTggxzSBfmxQAMQRgU4ONmKRlAGRQEGKQDDySaMUrLtOM5oyaYCUHGBjr3opaAEopaTFACkg4wPrQDjORmko60AFFLSUABOaSnCkoEJRSgkHI60HJOT1oASloxRQAd6KWkoAKSlIPejFACUUUUCCiiimAUHk9MUrYHTpSUhBRRgiimAlFLRQAlFLikoAKKKKAEpwBYgDqaSjvQAEEHBop5QBgGbg9TTDjJx0oEFJS0UDCikpaACiiigApSCOtOjKg5YZHpTSc0CEooooGBAB4OaPoKUkE8DApOaACkpelHagBKXBxnHFFGSBjtQAlFLSUAFFFFAARjvRRSk7jk9aAEooooAKKXHGc/hQBk4HU0AJQRigggkHrTs5XBPTpQA2ijBooASilpKBhRRRQAUUUUAFJS0DHc0CEooooGGKKKKACiiigAoxSUuaAEpcZ6UlKCRnFACUUUUDEopaKAEopaKAEooooAKKKKAEopaKBiUYxRRQAUUUUAFJS0UAJRRRQAUUUUAFFFKATwBQAlFFFMYUlLSUgCil5xRQAlFFLxj3oASiilxmgBOcZoPNFFABRRRQAYoooyTj2oAKfuGKZ344qTYuBxzQAxWAJzSsQelCqDQy46UDF3DFNUgZzTtoxTVGTQIViD0pQwxTXAHSm0AB61NZ/wDH7b/9dF/nUNTWf/H7b/8AXRf50PYZcu/+P2f/AK6N/Ooamu/+P2f/AK6N/OoxULYoQCkIpc0lMLijinA5NMpcYNAEoIIoNMB5pxapGGacKYKeKBC0UUUDExSrRijFACsOOKhxzzUvWkxQhMaFpdvNPApcZouMiKZo8upcUEUXAh29qTaakI5pwGadxWIwtGKlxSYpXFYjop+KXGaLiEUetO/lQM0uKQxMUYGKdjtS4oAjI/Gm4/OpaCKdwIcYNLjOe1PK+nSmEGgQlA4460vUe9FMBOlJindvaj6UANx0FJTyuKTHNAhuKMU4+lGKAGEUFeKdQR1z96gBvFJT8UYoAQA44pADnjrUgIA5poPzE4oAawPelAbHHSnMQRxzQCAOaAIxkN70rg45707PzZpWII4oAYA2OKbyDUikYpp5NO4DSSetAYgUuKMUCG0U7FGKAG4Iop1JQAlFLiimAlFFFABjPA60AHPI6daM4PFGTzz1oEJ3opaSgYuKSlowcZ7UAAxzkZ9KKXGTRSEFJS9qKAFdy/XHFMNKaOtMBD0pO1LRQAlLxg5P0opKBBRR16UUwENLRRQAUowTg9e1JQODkUhAcg4NFB5OTQRg4NMBKKKKAFpKKKACg0UUAOKYQNkYNNpTSUgCjFFKCR0NMBKKKKACiiigApzAA8HNNpdpChuxpAGfk24GKSilpgAUtnA6daQU7ceeevXFNoAOcUCiigA7UlLRQAlFLx36Urbdx28CgBtKxyc4ApKKAClpKWgAoBxyOtFJQAUUdqKAFxx1pKKKACkpaKAEpWAB4/WijP40AIMZ56UUUUDCiiigBKKWkoAKKKKACijBxntRQAUUUUAFFJS9qAEoopaAEoopTxkA8UDEoooxzzQAUlKevHSigA70E5PpSUUAFFFHNACUUtFAwJ4x2pKUDPFFAhKKKKBhRRRQAlFLRTASgEilopAJRRRQAUUUUDCiiigBKKKWgAopKKAClpKO2KACiiigA7GgUUY4z2oAKUuxpKO9AwBx0o3ZPNBxnjpSYoAXcelAJHSkooAUnNJRRQAVNZ/8f0H/AF0X+dQ1NZ/8ftv/ANdF/nQ9gLl3/wAfs+P+ejfzqH2qe7/4/Z/+ujfzqHgn6VC2GAoxS0UwAKe1LtOKcnSnkcUrjIaWpAlIVyaAGU4HFG3mjaR1oAcGFLkVH0GaUGkA/NLTB1p3agLi4peKAM8UZ/KkAtFJS5HagA6UlHvnNHXmgBaAM0UooAXHpTelPBI5B5pp6UANxRjml5NJ1oEKBzkdKUelAAOPWjpQAvXA70vaijrQMOtHUUpIOO2KVdvO/p2pAMx6Um3NKRikyaYhjKQaMZ7U+j+dFwIz9KMZFPHByOlN6fSmIMZPFJin4ZVB7HpTSMe+aAGkUcD/ABp3t2pMelADcetH86djijHPSmITBxRgUvTPNHakAgUYJ6U5NpcFhxikoAJPAoAV1GCcYpFUYz19qVlI6nNChuoNAAqjfj2pJFAHHFHOehzQwbHNMBmKO+cUtGOfagBuKMU9lAYDOR3NNIGeKAExSU4gZ6cUdKAG4oxTiMcUlAhuKMU6kxTAbRinEUmKAG0UuKKYCUUtFAhKXJxjPFBGKUgA8HNIBKKKKBhRRRTEGKQjHfNFFABSUtFAgYg4wMU2looASilpMUAFFFFABRxnpRR0ODTEFJS0UAJRS0UAJRS0D6UAJRS9qSgA60UoGQT6UUAJRS4pMYoAUHGeM0E57UlFIAoopeMdOaYCUvJ4oAyRnpTnQD7rAikAyiiimAUUtBxnjpQAlFFFABRRRQAUUUUAJS0UGgAxRRRQAUlLRQAlKRjGDmiigBMUUuBjrzShd7cYFIBtFLSUwCkpaKBiYopaKAEopaSgAooooAKSlooAVSO/Sm04tkAYxim0AFFFFAAQR1pQAQc9aMnbjtQCRn3oASiiigApKWigAooooASlo4zzSUDCiiigAooooASiiigBQMnGcUnQ0UUAFJS0lAwopRxSY4zQAUUUUAFFBGOtFACUU4IWBIxxTaACiiigAooooAUMQCMCm0tFAxKKWimAlFLRSASiilxTASiiikAUvGKSigByAEnNDjHSm0UDEpaKKACiiigBKns/+P23/wCui/zqGprP/j+t/wDrov8AOk9gLl2R9tn/AOujfzqHOe1T3Wftk+B1kb+dRbTUrYGIKKdgd6cMYoGAGKd60lKADSGLyQOaPagflS49qBiAUY56UuKcB3pCIivNIf0qYgCozz06U0wGZ596dnBpMY7UvamIVTTs4HFNHGKXPHFIYHmgHik4/wAKXrxQAtH0o6+9ApCFz6UDr9aTPPTHtSjrQA7ORSf5NGfyooAMd6XH/wBak/lR6HmgBe1Ljmkpc0AJThjBOfwpPaigBfrSfzoOelLxigY31z+VJggU7inAcdaBDVAP3s+2KTn608/Tg03uaQxv60N144p2O+KTAx7UxDDn3+lGPWpFzjYO9EkZj6nPpRcLEZ/Sk7YIpxH5Uh5xTEJ1PTmilHWg0AJRx0NL3wetKoUZ3DPpQIaetKpwcijB6mhVyaAHZViAeFoyFO3tQ6jGad1HNAEe7Dc0rN8uKAPnxmlZRjgdKAIvxoxS/TkUdT7UAJjj2opfrQB7UwG4o6cU7FIaAE49M0lO/GkoASjFOxz0pMUANxRS0UANIoxTqTAxQIbj1oxTqKYDKKdikxQITFApcUuKAG0UuKMUAJRRRTASilpKBBSUtFACUUtJQAUlLRQIAcHPpQTuJJ6mikoAKOlLRQAnWloooASilpKACilPPNGKAEopaSgAopT1pKACilpKYB2FFFFABRRS4460gE7UUtJQAUUUY/KgAooooAKSlopgJS8UUUDEopaKBCYoopaAEoAJzxRS80hiUtFOAoAbijFP28UEUDGYpMU/FIRxQAyilpKYhKWiigAzQevWijBJ4oASiiigAooooAKKKKACkpaKBiUUUoBNAhKKKKACiiigAAOKDjHTmlBI6d6SgBKKWigYdqSlooATFFLRQAlJS0UAJiilpeNvvQA2jFLSUDCkpaKAEopaKAEJJo4peMUlABQAMHP4UUYxQAUlLRQAUUUUAJRSgZNHSgBKKKMUAFFFFAwooooAKKKM8HigBKKKKACiiigAooooAKKKKAAAnpU1n/x+wf8AXRf51DU1n/x+wf8AXRf50PYaNC6H+mT/APXRv51F1B54qW6yb2f/AK6N/Oojg1mhie1LRtPrR9RTAX8eaX3oxk8d6cAF56mkMFHc9KcGAbIpvJ57Ucg470gHYpelN5HWjJ+tAAfQUmPelPfjim+/egAPPPrTM4oJ7YpDntVCFzx7Uv8An6UnNKFPGBQAo6dPxoPBp6rg04pntU3GRjnpTqUrijHNFwEwT35pD6AdKXB/ClwOlArCfSj+dKAT24pwjLHngUXCw3AzS8mpFj9+aeFC9OKXMOxEEYj0FPCc808U8AYzUuQ1EgZMHikKnPWrBWmMPyoUgcSHac0nI6VIR37U0g596q4huMfWkHGf1pT7UnFMQowQOacT0qPHenKpz1/+tSHcUjn39KPQmnYIJAOfem45JoAQEg5HWhyzHmnHKjBHBpp9KBDMc470DgU7GKPwpiG9BRinEAn5f1pPw6UAIf0ox6U4jmgryQOlACEjAx170gU9qX8KM4PrQICMDnmlAO2gt7UBu2ORQAzBzxTmDdaOjZpzEnpTAjCnFGMHBqVCpB3dqjznrQA00uMYx0oOM0HigBO9AHHtRjmlydpUcgmgBoxnJGRQR+VLj86TjtQAmM0fSlIo9+9AgPJ7U3HNO4zSeo7CmAmKSnckUUANxSYpwGf8KMd6AG0U7bx70lACY4pMU7FJTATFGMmlo5oENopaMUAIRSU73pMUCEoxS4o4oAbRS0UAJSU6igBtFLiimISjFLilAyaADbxmm0tFACdqO3vS4pQpPSgBvSlGO9FGKAEoxRS0AJQcUpFAODmgBDRSnBOQMUYGeaAE60UDiigAooooAKKKKADpRziijHFABiiiigBKKWigBKKUnjb2pKACiiigAoo70UAFFGKUUAKKljUntUQFWYTikxkiw7TnGaiePb0q4HXbVaUjmpi3cppJFUim04001YhtFLSUxBijHGaKKAEopc8YxSUAFJS0UAJRRRQAUUUUAFFFFABRRRQMKSlooEJRRS0AJRRRQAUUUUAFBxniigjFAB06Ud6DjjFBBA5oASloooGJRRRQAUUUUAFFFFACEUuBtznn0pD1ooAKKKKACg8nn86KKBiUUUUAFFFFABRRRQAUlLRQAlFLRQAg680Hg0UUAFFFFAwoooPFABSUtGKAEopcUDGeaYCUuPlzmkopAFT2n/H9b4/56L/OoKms/wDj9g/66L/Oh7AjRu/+Pyf/AK6N/OocZqzdqDeT84/eN/OoQlZJ6FjQM96cMDr0p3l0BMc0XCwY/AU3vilcZIHak578CgAzk4704c9KTBx0pwGKAFA46c0n40pHOKMc/SkAzvikOKdjIwOlKqAdeadwGhcjIHB605YyTn9Kd9BThxzSbHYFjUdBSlaeMdhSj3qWyrDAvPSgpUmKBgUrhYi20bfapTikzRcLEflk4zxTvKAPrUnHpS/hRcLEe0DtR1px+tAFFwsIB70Ec+1Px7UhHtSuFhAMU8dKTHejOKGNKw4c+1MJHfignFNJ46c+tCQmxDTSp60uc0uaokYV70bR1p+RRxRcLDDHtHNGMVKhVScjOaTZzRcLEWfwFHLHpUjKM0qjB6UXCwwITx+tL5THmpckCnbvzqblqKIBDxzSiH8qm4pSaOZhyohMQ+lIUUDHWpj0pu2i4cpXI5OBQVHGCSe9WdgFLtHpT5hchU2nFJirRTNMMeafMS4FfH51IoG0U8xNjNAgJzng9qfMhcrIQBu9qVgMZxUy2xY8mpPswAyTmjmQcjKm09+gppHH8hVwxDGAKrspDdKFK4SjYiwCaOCCaexBbIGKbjtVECdMUnQ5FP2k8UhGOaAG4544zSkYO3vRjjnpRQAh680mKXt9e1GO5pgJ3NFL1OOlJ2oAQ0UvSjHr0oEJjmk7Y7U4Dn2o68+nagBtJ1p3UdKKYDevWjoc+lLRj1oATAJ54FIR707rx2oI5oAYaMU7HrRjuaBDMUU7FGKAG0lOoBI7UxDaKXFJQAUUtJQAUYoooAMcZpMUtFABRRRQAmMUvTilH50lACYopTR3oAQ0lOIxSUxB1pKWigAwcUhGKWjGKAExRS0lABRS0UAJRilooAbRTulJQAlL296KMcUAGMEZpKKKADvR0oooASjFLRQAcbe+aSlooAARzxRRRQAoqVHCA8Zz0qLgdDS44z2pDJvNP1qNn3Gmk0hHy5zRYAzzSHg4HNFJTAKSlpKYgooooAKSlooASjHGc0vU0lABRRRQMSilooAT60YzRS0AHXoKSlBI6GkxQAUUpGOKTpQAUZoooAKSlpKAFBwc0MCDkjGaSjNABSkk4z2pKKACgknvRRQAUlLRQAlFLRQAlFFFABRRRQMKMUUUAFFLgbc559KSgABKnI60E7jk0YooAbS0UUAFJS0UDEopaSgAopaSgAopcUlABRRRQAUAE/hRSZoAKKU5A+tJQAUUUlAwzRRRTAKKKWkAlTWf/H7b/wDXRf51DU1n/wAftv8A9dF/nQ9gRsXQ/wBMmyP+WjfzqLANXLtR9sm7fvG/nUOwHiuZM1cSHB7UoLDtT/LI5BoAI4Ip3CwzAPUU7yxT9oPak2kdDSuFhrR4PBBphU5xUuSOo/KnZRhii4WK/IFAHzfN+dTFB65ppjIHtVXFYZ2x2pDyadjmm460AKOTmnAUxSefWnA8UASL0OacME4JwO1RZ96Cc0h3H5pN3NJ160mfaiwmx+cjmjdjmmg++KO1AXJQ1G7iouelBNKw+YecZznNKGFRZNLup2FzExPHWjPPXrUOcmlDEUrD5ib2oNRb6cH9RRYfMOxTCD60u7NGaBDSppOcY/Gn9s02mAnbpQPvY70HpSAE0CJB696eMkZFRjJPPFP59aTGhp9qUUuOKMUAGaUGkIpMUh3H0tMBIpwJxSGmO6UYpM06kVcMUYpe1LQMTFGBTqKQxuBS4oooABwc0rNkUlFMBKZIDtIFThRimhRuIPShMTVzPYEdRTccEVoyQhl9KrNbEcg1opGLgyBTt60rEcdxSmFhyKQqRyaq5FmMxzSYPAp5HWm+xpiE7+9H607Gfc+lJjt37g0AJjj3pCPzpe/FB5Oe9ABSYpT1oI9KYCDp0oxxxS49+tJgjp0oATrxnmgj3pcdaKBCfWk9qcefekoAT+dGKUelFACY5pCKf8uz/apP0oAbjml2jucZpT9MUmOuaAGkUmPXpTu1GKYhhFHtTgMkD1pCuDigQ2jkU6kxTASilxxRQAmKCKXHNGKAEopxGDjNGBj3oAbRjPQUtGSeKAEpKWjFACUUtFACYooooAMUGiloENxS0tFACUuOOvNLyetOC8UAMxRjHSpdnr0oMdK4EOKCKlKUjjmncCLFGKeRTSKAG4op1JRcBKKXFFMBtKeaKUcmgBtFLiigBKKXFJQAUuaSlxQAE0UUlABRRRQAlFLSUAFJS0UAJRS4ooATpzR1OKWigBCMHFGKKKAEopaKAEopcUYoASkpwBOcUlAxKKWigBKKWjFACUUUUwCiiigBMUUtFACUUtFACUUtBGD1zQMSiiigQEYODRRRQMDj0xSUtFABikpaKAEpQCTgUlFABRRS5OMetACUZyAPSiikAUUUUwCkpaSgAowcfWiigYUlLRQAlFL2pKADFFFFABSYpaKAEopaSgBQSDn0pAMn0opSAOhzQAh60H2oopjEqez/AOP2D/rov86iUgHkZFS2f/H9B/10X+dJgjfuf+Pub/ro386iqW5z9rm/32/nUYrkNxRTsZ60gpRSKEK56Gm7TUlA5ouFhmDjpUZQE8cVP9aKdwcSuEbNO6cEHNS4o4xg0XJ5SIqD1prJ6VMY8cqePSmdOO9O4NEBU5zQQRxU+Ae1Js/GncmxBnBozzxUjJ14phTAzmqTE7gD+dJmjB7mlwMZoEHQZxSg5NN5xQeBQIfz3pMUgx1xgUoxnnigYEUdDRSc5oEHal7UnT/PSjjtQAYxSgk8UYHTril647UAGf8A9VSDpzUYHPvTxj8aTKQrHpTTk0rcim55oBiU4dPSkxS55FAD1FSAcU1cU8CoZpETFGPSlpckcigY3FJjmlNLQKwgXPFLilpM0DsCqTQQQcGlVsHNDEk80AGOKTNGfSjPagVxwPFOzUf1pwpWKTHUUCjNIYUYpdtLigYnOODS0UUhC5NHWkpc0DEKj0prRowxin0Yp3CxWaFD7VWkiK8Z4q+65xVaRWYknmtIyMZxKoyCP0pTkEhutOKnPK/Sm4/H3NaGQhxjAox0zS9v5UnSgQH9KTtR9adgEjHy8fnTAbmjpS/Wjv6ikAhA9aOe1HQ0vagBKTrS+1GBQAGkH60vHA/nR1oAT3opTx1/GigBMc80lOx+FB5FAhvU5pMU7Ge1H8qYDSOtJin7eM84ptACY70mKd0+lLjJoEMxxSU/BxnHFJTAbijFOpMUAJig0uKPegBOtB4FL7UdTQIQe1JTjz2xRwOnWgBppKdijFMBMUlO7UYx2oAUJxSEYOKeGFNPJpCG470opcU7GcUACrk4HWpEjJNSIgBHrU6RipbKSuReVxS+VmrIQYpSg7VHMaKkym0fBqNo8GrxTAqJl46U1ImUWiiV5qMirLoc+1QsuK0TIIqKdSUxDaKXFFACUdKKWgBKKKMYoASilxRigBKKXFGKAEopcZOKQ9aADHGf0pKUjjNHamAlFFFABRRRQAUUlFABRRS44oASjFFAJHSgBMUUtJQAUpx2pKKAAEjpRRRQAlFLSUDCiiigAooooAKOtFAJHSgBKKWkpgFGaCSTk0UgCkpaSgAooopgFFFFABRRRQMSiloPNABSUuKTFABRS0lABRRRQAUUtJQAUUUo68jNACUlLS7htxgfWgBBjBz17UlL29qCMUAJRRRQMKASpyKKKAEopaSgAoopccf0oAbS0YwfeigApKUUdDQAlWLID7ZBnr5i4/OoDU1n/wAfsH/XRf50nsM37n/j7m/66N/Oo/X0qzcW1x9rmIgkwXb+A+tR/Zbj/nhL/wB8GuS50kYzRUotbj/nhL/3waPstx/zwl/74NAEdFSfZrjP+ol/74NL9muP+eEv/fBoAjzRUgtrj/nhL/3waX7Ncf8APCX/AL4NIZFmkqb7Lcf88Jf++DSfZbj/AJ4S/wDfBouIioIBGDU32a4/54S/98Gj7Ncf88Jf++DRcCvsIPB49KATtxjBqf7Lcf8APCX/AL4NH2Wc/wDLCX/vg07isQEZ61GyVa+yXH/PCX/vg0fZrj/nhL/3waaYrFJkz2qM5FX2s7g/8sJf++DURs7gj/j3lz/uGqUiGmVd3GfWipWs7kHPkS4/3DSC1uf+feX/AL4NXdEjM9KKk+y3H/PvL/3waX7LckD9xLn/AHDS0AizS54681J9luP+feX/AL4NJ9luf+feX/vg0aARjrTu/T8af9kuAP8Aj3lz/uGlFrcgcwy/98GgCMdM0ZPapPstz/zwlz/uGl+y3H/PCX/vg0aARL6U7rTxa3H/ADwlz/uGl+zXHa3l/wC+DSGMB9aQjBqb7Lcf88Jf++DSi1nz80EuP9w0XGV85/CnBqebS5x/qJf++DR9luccQS+3yGjQQ0HnNSBuaRbW4z/qJf8Avg08Wtxn/US/98Gk7FJi5yOOtJnFPW2uB/ywlH/ADS/Zbgj/AFEv/fBqS7kVKKk+zT/88Jf++DSi1uP+eEv/AHwaAIs0h5qb7PcYINvJ/wB8GkFtcf8APCX/AL4NAMjFB6VL9luf+eEmP9w0n2a4PSCX/vg0ARinACni1n/54S/98GnfZbjH+ol/74NIEiOjB7VL9ln/AOeEv/fBoFtcY/1Ev/fBouVYi7Uo96l+zXH/ADwl/wC+DR9mn/54S/8AfBpANBop32a4/wCeEn/fBo+zXH/PCX/vg0DuMzS5pfs9wOkEv/fBpfs9x/zwl/74NAXGUo4p32a4/wCeMv8A3waUW9x/zwl/74NADaKk+zz/APPCT/vg0v2af/nhJ/3waVxkRFNKA9qsfZp8f6iT/vg0n2af/nhJ/wB8mi4FNosng1C8LDpzWibWf/nhL/3wab9ln/54Sf8AfBqlIhwTMsr2xik2Z4HNaD2U5z+4k/74NQGyuP8An3lGP9g1opGThYqlT35pvNWzbXGP+PeX6bDTTZ3Gf9RL/wB8Gq5iGitjjmjoOO/WrBtLn/nhKR/uGkNpcY/495R9ENF0FmV/oaXuPSp2tbh8f6NKMf7BpDaXP/PCX/vg0XQrEJoPHSphaXJbBt5f++DStZXKNtMEpJ77DTuh2IOKKl+yXJP/AB7y8f7Bo+y3P/PvL/3waLhYh+v5UvXrUv2S4PH2eX/vg0fZLjnEEv8A3waLisQ9aMc1MLW4/wCfeX/vg0fZbn/n3l/74NFwsQ/jSdan+yXA4+zy/wDfBo+yXH/PCX/vg0XQWIATjGePSgdc1N9kuM/8e8v/AHwaPslx2gl/74NFwsQcU4AFWHfqDUv2W4H/AC7y/wDfBoNpc4x9nl/74NFxEGeOvHpSYxVgWtyAR9nl5/2DSfZLn/n3l+uw0XQEGKDU/wBkuev2eX/vg0fZLj/n3l/74NFwK5oqf7Hcf8+8v/fBoFpcd7eX2+Q07hYgx69KO+KsfZLn/nhL/wB8Gk+yXP8Az7y/98Gi4WZBgikqwbS5J4t5f++DSfZLk/8ALvL/AN8Gi6FYgx270hGKsfZLnj/R5f8Avg0fY7jB/wBHl/74NF0FiCjB71N9kucf8e8v/fBo+yXOf+PeX/vg0XQWIR60VP8AZLn/AJ95f++DSi0uP+feX/vg0XQrEOKegAOD0qQWdx/z7y/98GpFtLjvby4/3DSuh2HRrgVYRec02O2uOnkS/XYasLbT5z5Ev/fBrOTNaaG0YqX7NP8A88Jf++DS/Zrj/nhJ/wB8GoudFiDFROMGrn2af/nhJ/3waie1uM/6iT/vg00zOotDPkHB9arkc+/cVova3O0jyJP++DVdrS4/595ff5DWqZzNFIjn2ppFWTaXJP8Ax7y/98Gm/ZLn/n3l/wC+DV3FYr4oxzU/2S5/595f++DSfZLkHIt5f++DRdBZkJUjrSVYNrdOf+PeUf8AADTfslz/AM+8v/fBouFmQ0VP9kuf+feX/vg0n2S5/wCfeX/vg0XQWIaKm+yXP/PvL/3waPslz/z7y/8AfBougsQ9KKnNpc55t5c/7hpPslz/AM+8v/fBougsQUVY+yXI5+zy/wDfBpPslz/z7y/98Gi6CxXoqf7Jc/8APvL/AN8Gj7Jc/wDPvL/3wad0Igoqf7Jc/wDPvL/3waPsdz/z7y/98Gi6AgpKsfY7n/n3l/74NJ9kuf8An3l/74NF0FiCip/sdz/z7y/98Gj7Jc/8+8v/AHwaLoLEFFT/AGS5/wCfeX/vg0fZLn/n3l/74NF0FiAgikqc2lz/AM+8v/fBo+yXP/PvL/3waLoCCipvslz/AM+8v/fBo+yXP/PvL/3waLoCGkqf7Jc/8+8v/fBo+yXP/PvL/wB8Gi4EFFT/AGS5/wCfeX/vg0fZLn/n3l/74NFwsQUAc+lTfZLn/n3l/wC+DR9kuf8An3l/74NO6CxCeCQORRU/2O5/595f++DSfZLn/n3l/wC+DRdDIMUVP9juf+feX/vg0fY7n/n3l/74NF0FiCip/sdz/wA+83/fBpPsdz/z7y/98Gi6CxDRU32S5/595f8Avg0fY7n/AJ95f++DRcCGkqf7Hc/8+8v/AHwaPslz/wA+83/fBougIKKsCyuT/wAsJR/wA0n2O5/595v++DRdAQUVN9juf+feb/vg0v2O5/595v8Avg0XQ7Feip/sdz/z7y/98Gj7Hc/8+8v/AHwaLoLEFFT/AGO5/wCfeX/vg0fZLn/n3l/74NF0FiCipvsdz/z7y/8AfBo+x3P/AD7y/wDfBougsQ0VP9kuf+feX/vg0n2O6/59pv8Avg0XQWIaKn+x3X/PtN/3waT7Hc/8+83/AHwaLoLENFTfZLn/AJ95v++DR9juf+feb/vg0XQENJU/2O6/59pf++DS/Y7r/n2m/wC+DRdAQAEjjtSVYFrdAcW83/fBpPsdz/z7S/8AfBougsQUVYFndE4+zy/98Gk+x3P/AD7y/wDfBouhkGTjGeKKn+x3P/PvL/3waT7Hc/8APvN/3waLoLENFTfY7n/n3m/74NH2O5/595v++DRdBYhoqb7Hc/8APvN/3waPslz/AM+03/fBougsQUuKm+x3P/PvN/3waPslz/z7Tf8AfBougIKKn+x3P/PvN/3waPsdz/z7Tf8AfBougIKKn+x3P/PtN/3waPsdz/z7zf8AfBouhkFJU/2O5/59pv8Avg0psroHBt5T/wAANF0BBU1n/wAfsH/XRf50fZLn/n2m/wC+DUtpa3IvICbeUYkXnYfWhgkf/9k='); |
| | | } |
| | | |
| | | .boxPadd { |
| | | padding: 5px 10px; |
| | | } |
| | | |
| | | /deep/.u-line-progress__text { |
| | | color: #000 !important; |
| | | } |
| | | |
| | | /deep/.u-radio-group--row { |
| | | justify-content: center; |
| | | } |
| | | |
| | | .ridoa { |
| | | text-align: center; |
| | | padding: 10px 0px; |
| | | } |
| | | |
| | | /deep/.placeholderColor { |
| | | color: #fff; |
| | | } |
| | | |
| | | /deep/.u-form { |
| | | display: flex; |
| | | justify-content: space-evenly; |
| | | } |
| | | |
| | | .slot-content { |
| | | width: 80%; |
| | | } |
| | | |
| | | /deep/.u-cell__body, |
| | | /deep/.u-cell__title-text, |
| | | /deep/.u-cell__value { |
| | | color: #fff !important; |
| | | } |
| | | |
| | | .ridioBox { |
| | | margin-bottom: 10px; |
| | | } |
| | | </style> |
New file |
| | |
| | | { |
| | | "flylon": "经度", |
| | | "a00e12": "光照强度", |
| | | "a00e34": "TSP", |
| | | "a00e13": "噪音", |
| | | "a21005": "一氧化碳", |
| | | "a21004": "二氧化氮", |
| | | "a21026": "二氧化硫", |
| | | "a21028": "硫化氢", |
| | | "flyhig": "高度", |
| | | "a21001": "氨气", |
| | | "a40002": "苯乙烯", |
| | | "a21022": "氯气", |
| | | "a00e19": "二氧化碳", |
| | | "a40001": "烟气流量", |
| | | "a01001": "温度", |
| | | "a25005": "二甲苯", |
| | | "a05024": "臭氧", |
| | | "a21024": "氯化氢", |
| | | "a40003": "环氧乙烷", |
| | | "a25003": "甲苯", |
| | | "a01002": "湿度", |
| | | "a25002": "苯", |
| | | "a23001": "酚类", |
| | | "a01007": "风速", |
| | | "a01006": "气压", |
| | | "a01008": "风向", |
| | | "a30001": "甲醇", |
| | | "a19002": "臭气浓度", |
| | | "a19001": "氧气", |
| | | "a34002": "PM10", |
| | | "a34004": "PM2.5", |
| | | "dustld": "尘负荷", |
| | | "PORRST": "开机标识", |
| | | "a00e03": "颗粒物0.3", |
| | | "a00e04": "颗粒物2.5", |
| | | "a06001": "雨量", |
| | | "a99054": "TVOC", |
| | | "a35e21": "核辐射", |
| | | "a01011": "烟气流速", |
| | | "a24088": "非甲烷总烃", |
| | | "flylat": "纬度", |
| | | "a31001": "甲醛" |
| | | } |
| | |
| | | <u-button @click="submit">登录</u-button> |
| | | </view> |
| | | </view> |
| | | <ws-wx-privacy id="privacy-popup" enableAutoProtocol></ws-wx-privacy> |
| | | </view> |
| | | </template> |
| | | <script> |
| | |
| | | export default { |
| | | data() { |
| | | return { |
| | | titlePrivacy: '用户隐私保护提示', |
| | | labelStyle: { |
| | | color: '#fff' |
| | | }, |
| | |
| | | uni.hideHomeButton() |
| | | }, |
| | | methods: { |
| | | doRequire() { |
| | | uni.requirePrivacyAuthorize({ |
| | | success: () => { |
| | | console.log('同意') |
| | | // 用户同意授权 |
| | | // 继续小程序逻辑 |
| | | this.getlogin() |
| | | }, |
| | | fail: () => { |
| | | console.log('拒绝') |
| | | }, // 用户拒绝授权 |
| | | complete: () => {} |
| | | }) |
| | | }, |
| | | submit() { |
| | | this.$refs.uForm.validate().then(res => { |
| | | this.getlogin() |
| | | this.doRequire() |
| | | }).catch(errors => {}) |
| | | }, |
| | | //登录 |
New file |
| | |
| | | ## 1.8.3(2023-04-17) |
| | | - 修复 uni-popup 重复打开时的 bug |
| | | ## 1.8.2(2023-02-02) |
| | | - uni-popup-dialog 组件新增 inputType 属性 |
| | | ## 1.8.1(2022-12-01) |
| | | - 修复 nvue 下 v-show 报错 |
| | | ## 1.8.0(2022-11-29) |
| | | - 优化 主题样式 |
| | | ## 1.7.9(2022-04-02) |
| | | - 修复 弹出层内部无法滚动的bug |
| | | ## 1.7.8(2022-03-28) |
| | | - 修复 小程序中高度错误的bug |
| | | ## 1.7.7(2022-03-17) |
| | | - 修复 快速调用open出现问题的Bug |
| | | ## 1.7.6(2022-02-14) |
| | | - 修复 safeArea 属性不能设置为false的bug |
| | | ## 1.7.5(2022-01-19) |
| | | - 修复 isMaskClick 失效的bug |
| | | ## 1.7.4(2022-01-19) |
| | | - 新增 cancelText \ confirmText 属性 ,可自定义文本 |
| | | - 新增 maskBackgroundColor 属性 ,可以修改蒙版颜色 |
| | | - 优化 maskClick属性 更新为 isMaskClick ,解决微信小程序警告的问题 |
| | | ## 1.7.3(2022-01-13) |
| | | - 修复 设置 safeArea 属性不生效的bug |
| | | ## 1.7.2(2021-11-26) |
| | | - 优化 组件示例 |
| | | ## 1.7.1(2021-11-26) |
| | | - 修复 vuedoc 文字错误 |
| | | ## 1.7.0(2021-11-19) |
| | | - 优化 组件UI,并提供设计资源,详见:[https://uniapp.dcloud.io/component/uniui/resource](https://uniapp.dcloud.io/component/uniui/resource) |
| | | - 文档迁移,详见:[https://uniapp.dcloud.io/component/uniui/uni-popup](https://uniapp.dcloud.io/component/uniui/uni-popup) |
| | | ## 1.6.2(2021-08-24) |
| | | - 新增 支持国际化 |
| | | ## 1.6.1(2021-07-30) |
| | | - 优化 vue3下事件警告的问题 |
| | | ## 1.6.0(2021-07-13) |
| | | - 组件兼容 vue3,如何创建vue3项目,详见 [uni-app 项目支持 vue3 介绍](https://ask.dcloud.net.cn/article/37834) |
| | | ## 1.5.0(2021-06-23) |
| | | - 新增 mask-click 遮罩层点击事件 |
| | | ## 1.4.5(2021-06-22) |
| | | - 修复 nvue 平台中间弹出后,点击内容,再点击遮罩无法关闭的Bug |
| | | ## 1.4.4(2021-06-18) |
| | | - 修复 H5平台中间弹出后,点击内容,再点击遮罩无法关闭的Bug |
| | | ## 1.4.3(2021-06-08) |
| | | - 修复 错误的 watch 字段 |
| | | - 修复 safeArea 属性不生效的问题 |
| | | - 修复 点击内容,再点击遮罩无法关闭的Bug |
| | | ## 1.4.2(2021-05-12) |
| | | - 新增 组件示例地址 |
| | | ## 1.4.1(2021-04-29) |
| | | - 修复 组件内放置 input 、textarea 组件,无法聚焦的问题 |
| | | ## 1.4.0 (2021-04-29) |
| | | - 新增 type 属性的 left\right 值,支持左右弹出 |
| | | - 新增 open(String:type) 方法参数 ,可以省略 type 属性 ,直接传入类型打开指定弹窗 |
| | | - 新增 backgroundColor 属性,可定义主窗口背景色,默认不显示背景色 |
| | | - 新增 safeArea 属性,是否适配底部安全区 |
| | | - 修复 App\h5\微信小程序底部安全区占位不对的Bug |
| | | - 修复 App 端弹出等待的Bug |
| | | - 优化 提升低配设备性能,优化动画卡顿问题 |
| | | - 优化 更简单的组件自定义方式 |
| | | ## 1.2.9(2021-02-05) |
| | | - 优化 组件引用关系,通过uni_modules引用组件 |
| | | ## 1.2.8(2021-02-05) |
| | | - 调整为uni_modules目录规范 |
| | | ## 1.2.7(2021-02-05) |
| | | - 调整为uni_modules目录规范 |
| | | - 新增 支持 PC 端 |
| | | - 新增 uni-popup-message 、uni-popup-dialog扩展组件支持 PC 端 |
New file |
| | |
| | | // #ifdef H5 |
| | | export default { |
| | | name: 'Keypress', |
| | | props: { |
| | | disable: { |
| | | type: Boolean, |
| | | default: false |
| | | } |
| | | }, |
| | | mounted () { |
| | | const keyNames = { |
| | | esc: ['Esc', 'Escape'], |
| | | tab: 'Tab', |
| | | enter: 'Enter', |
| | | space: [' ', 'Spacebar'], |
| | | up: ['Up', 'ArrowUp'], |
| | | left: ['Left', 'ArrowLeft'], |
| | | right: ['Right', 'ArrowRight'], |
| | | down: ['Down', 'ArrowDown'], |
| | | delete: ['Backspace', 'Delete', 'Del'] |
| | | } |
| | | const listener = ($event) => { |
| | | if (this.disable) { |
| | | return |
| | | } |
| | | const keyName = Object.keys(keyNames).find(key => { |
| | | const keyName = $event.key |
| | | const value = keyNames[key] |
| | | return value === keyName || (Array.isArray(value) && value.includes(keyName)) |
| | | }) |
| | | if (keyName) { |
| | | // 避免和其他按键事件冲突 |
| | | setTimeout(() => { |
| | | this.$emit(keyName, {}) |
| | | }, 0) |
| | | } |
| | | } |
| | | document.addEventListener('keyup', listener) |
| | | this.$once('hook:beforeDestroy', () => { |
| | | document.removeEventListener('keyup', listener) |
| | | }) |
| | | }, |
| | | render: () => {} |
| | | } |
| | | // #endif |
New file |
| | |
| | | <template> |
| | | <view class="uni-popup-dialog"> |
| | | <view class="uni-dialog-title"> |
| | | <text class="uni-dialog-title-text" :class="['uni-popup__'+dialogType]">{{titleText}}</text> |
| | | </view> |
| | | <view v-if="mode === 'base'" class="uni-dialog-content"> |
| | | <slot> |
| | | <text class="uni-dialog-content-text">{{content}}</text> |
| | | </slot> |
| | | </view> |
| | | <view v-else class="uni-dialog-content"> |
| | | <slot> |
| | | <input class="uni-dialog-input" v-model="val" :type="inputType" :placeholder="placeholderText" :focus="focus" > |
| | | </slot> |
| | | </view> |
| | | <view class="uni-dialog-button-group"> |
| | | <view class="uni-dialog-button" @click="closeDialog"> |
| | | <text class="uni-dialog-button-text">{{closeText}}</text> |
| | | </view> |
| | | <view class="uni-dialog-button uni-border-left" @click="onOk"> |
| | | <text class="uni-dialog-button-text uni-button-color">{{okText}}</text> |
| | | </view> |
| | | </view> |
| | | |
| | | </view> |
| | | </template> |
| | | |
| | | <script> |
| | | import popup from '../uni-popup/popup.js' |
| | | import { |
| | | initVueI18n |
| | | } from '@dcloudio/uni-i18n' |
| | | import messages from '../uni-popup/i18n/index.js' |
| | | const { t } = initVueI18n(messages) |
| | | /** |
| | | * PopUp 弹出层-对话框样式 |
| | | * @description 弹出层-对话框样式 |
| | | * @tutorial https://ext.dcloud.net.cn/plugin?id=329 |
| | | * @property {String} value input 模式下的默认值 |
| | | * @property {String} placeholder input 模式下输入提示 |
| | | * @property {String} type = [success|warning|info|error] 主题样式 |
| | | * @value success 成功 |
| | | * @value warning 提示 |
| | | * @value info 消息 |
| | | * @value error 错误 |
| | | * @property {String} mode = [base|input] 模式、 |
| | | * @value base 基础对话框 |
| | | * @value input 可输入对话框 |
| | | * @property {String} content 对话框内容 |
| | | * @property {Boolean} beforeClose 是否拦截取消事件 |
| | | * @event {Function} confirm 点击确认按钮触发 |
| | | * @event {Function} close 点击取消按钮触发 |
| | | */ |
| | | |
| | | export default { |
| | | name: "uniPopupDialog", |
| | | mixins: [popup], |
| | | emits:['confirm','close'], |
| | | props: { |
| | | inputType:{ |
| | | type: String, |
| | | default: 'text' |
| | | }, |
| | | value: { |
| | | type: [String, Number], |
| | | default: '' |
| | | }, |
| | | placeholder: { |
| | | type: [String, Number], |
| | | default: '' |
| | | }, |
| | | type: { |
| | | type: String, |
| | | default: 'error' |
| | | }, |
| | | mode: { |
| | | type: String, |
| | | default: 'base' |
| | | }, |
| | | title: { |
| | | type: String, |
| | | default: '' |
| | | }, |
| | | content: { |
| | | type: String, |
| | | default: '' |
| | | }, |
| | | beforeClose: { |
| | | type: Boolean, |
| | | default: false |
| | | }, |
| | | cancelText:{ |
| | | type: String, |
| | | default: '' |
| | | }, |
| | | confirmText:{ |
| | | type: String, |
| | | default: '' |
| | | } |
| | | }, |
| | | data() { |
| | | return { |
| | | dialogType: 'error', |
| | | focus: false, |
| | | val: "" |
| | | } |
| | | }, |
| | | computed: { |
| | | okText() { |
| | | return this.confirmText || t("uni-popup.ok") |
| | | }, |
| | | closeText() { |
| | | return this.cancelText || t("uni-popup.cancel") |
| | | }, |
| | | placeholderText() { |
| | | return this.placeholder || t("uni-popup.placeholder") |
| | | }, |
| | | titleText() { |
| | | return this.title || t("uni-popup.title") |
| | | } |
| | | }, |
| | | watch: { |
| | | type(val) { |
| | | this.dialogType = val |
| | | }, |
| | | mode(val) { |
| | | if (val === 'input') { |
| | | this.dialogType = 'info' |
| | | } |
| | | }, |
| | | value(val) { |
| | | this.val = val |
| | | } |
| | | }, |
| | | created() { |
| | | // 对话框遮罩不可点击 |
| | | this.popup.disableMask() |
| | | // this.popup.closeMask() |
| | | if (this.mode === 'input') { |
| | | this.dialogType = 'info' |
| | | this.val = this.value |
| | | } else { |
| | | this.dialogType = this.type |
| | | } |
| | | }, |
| | | mounted() { |
| | | this.focus = true |
| | | }, |
| | | methods: { |
| | | /** |
| | | * 点击确认按钮 |
| | | */ |
| | | onOk() { |
| | | if (this.mode === 'input'){ |
| | | this.$emit('confirm', this.val) |
| | | }else{ |
| | | this.$emit('confirm') |
| | | } |
| | | if(this.beforeClose) return |
| | | this.popup.close() |
| | | }, |
| | | /** |
| | | * 点击取消按钮 |
| | | */ |
| | | closeDialog() { |
| | | this.$emit('close') |
| | | if(this.beforeClose) return |
| | | this.popup.close() |
| | | }, |
| | | close(){ |
| | | this.popup.close() |
| | | } |
| | | } |
| | | } |
| | | </script> |
| | | |
| | | <style lang="scss" > |
| | | .uni-popup-dialog { |
| | | width: 300px; |
| | | border-radius: 11px; |
| | | background-color: #fff; |
| | | } |
| | | |
| | | .uni-dialog-title { |
| | | /* #ifndef APP-NVUE */ |
| | | display: flex; |
| | | /* #endif */ |
| | | flex-direction: row; |
| | | justify-content: center; |
| | | padding-top: 25px; |
| | | } |
| | | |
| | | .uni-dialog-title-text { |
| | | font-size: 16px; |
| | | font-weight: 500; |
| | | } |
| | | |
| | | .uni-dialog-content { |
| | | /* #ifndef APP-NVUE */ |
| | | display: flex; |
| | | /* #endif */ |
| | | flex-direction: row; |
| | | justify-content: center; |
| | | align-items: center; |
| | | padding: 20px; |
| | | } |
| | | |
| | | .uni-dialog-content-text { |
| | | font-size: 14px; |
| | | color: #6C6C6C; |
| | | } |
| | | |
| | | .uni-dialog-button-group { |
| | | /* #ifndef APP-NVUE */ |
| | | display: flex; |
| | | /* #endif */ |
| | | flex-direction: row; |
| | | border-top-color: #f5f5f5; |
| | | border-top-style: solid; |
| | | border-top-width: 1px; |
| | | } |
| | | |
| | | .uni-dialog-button { |
| | | /* #ifndef APP-NVUE */ |
| | | display: flex; |
| | | /* #endif */ |
| | | |
| | | flex: 1; |
| | | flex-direction: row; |
| | | justify-content: center; |
| | | align-items: center; |
| | | height: 45px; |
| | | } |
| | | |
| | | .uni-border-left { |
| | | border-left-color: #f0f0f0; |
| | | border-left-style: solid; |
| | | border-left-width: 1px; |
| | | } |
| | | |
| | | .uni-dialog-button-text { |
| | | font-size: 16px; |
| | | color: #333; |
| | | } |
| | | |
| | | .uni-button-color { |
| | | color: #007aff; |
| | | } |
| | | |
| | | .uni-dialog-input { |
| | | flex: 1; |
| | | font-size: 14px; |
| | | border: 1px #eee solid; |
| | | height: 40px; |
| | | padding: 0 10px; |
| | | border-radius: 5px; |
| | | color: #555; |
| | | } |
| | | |
| | | .uni-popup__success { |
| | | color: #4cd964; |
| | | } |
| | | |
| | | .uni-popup__warn { |
| | | color: #f0ad4e; |
| | | } |
| | | |
| | | .uni-popup__error { |
| | | color: #dd524d; |
| | | } |
| | | |
| | | .uni-popup__info { |
| | | color: #909399; |
| | | } |
| | | </style> |
New file |
| | |
| | | <template> |
| | | <view class="uni-popup-message"> |
| | | <view class="uni-popup-message__box fixforpc-width" :class="'uni-popup__'+type"> |
| | | <slot> |
| | | <text class="uni-popup-message-text" :class="'uni-popup__'+type+'-text'">{{message}}</text> |
| | | </slot> |
| | | </view> |
| | | </view> |
| | | </template> |
| | | |
| | | <script> |
| | | import popup from '../uni-popup/popup.js' |
| | | /** |
| | | * PopUp 弹出层-消息提示 |
| | | * @description 弹出层-消息提示 |
| | | * @tutorial https://ext.dcloud.net.cn/plugin?id=329 |
| | | * @property {String} type = [success|warning|info|error] 主题样式 |
| | | * @value success 成功 |
| | | * @value warning 提示 |
| | | * @value info 消息 |
| | | * @value error 错误 |
| | | * @property {String} message 消息提示文字 |
| | | * @property {String} duration 显示时间,设置为 0 则不会自动关闭 |
| | | */ |
| | | |
| | | export default { |
| | | name: 'uniPopupMessage', |
| | | mixins:[popup], |
| | | props: { |
| | | /** |
| | | * 主题 success/warning/info/error 默认 success |
| | | */ |
| | | type: { |
| | | type: String, |
| | | default: 'success' |
| | | }, |
| | | /** |
| | | * 消息文字 |
| | | */ |
| | | message: { |
| | | type: String, |
| | | default: '' |
| | | }, |
| | | /** |
| | | * 显示时间,设置为 0 则不会自动关闭 |
| | | */ |
| | | duration: { |
| | | type: Number, |
| | | default: 3000 |
| | | }, |
| | | maskShow:{ |
| | | type:Boolean, |
| | | default:false |
| | | } |
| | | }, |
| | | data() { |
| | | return {} |
| | | }, |
| | | created() { |
| | | this.popup.maskShow = this.maskShow |
| | | this.popup.messageChild = this |
| | | }, |
| | | methods: { |
| | | timerClose(){ |
| | | if(this.duration === 0) return |
| | | clearTimeout(this.timer) |
| | | this.timer = setTimeout(()=>{ |
| | | this.popup.close() |
| | | },this.duration) |
| | | } |
| | | } |
| | | } |
| | | </script> |
| | | <style lang="scss" > |
| | | .uni-popup-message { |
| | | /* #ifndef APP-NVUE */ |
| | | display: flex; |
| | | /* #endif */ |
| | | flex-direction: row; |
| | | justify-content: center; |
| | | } |
| | | |
| | | .uni-popup-message__box { |
| | | background-color: #e1f3d8; |
| | | padding: 10px 15px; |
| | | border-color: #eee; |
| | | border-style: solid; |
| | | border-width: 1px; |
| | | flex: 1; |
| | | } |
| | | |
| | | @media screen and (min-width: 500px) { |
| | | .fixforpc-width { |
| | | margin-top: 20px; |
| | | border-radius: 4px; |
| | | flex: none; |
| | | min-width: 380px; |
| | | /* #ifndef APP-NVUE */ |
| | | max-width: 50%; |
| | | /* #endif */ |
| | | /* #ifdef APP-NVUE */ |
| | | max-width: 500px; |
| | | /* #endif */ |
| | | } |
| | | } |
| | | |
| | | .uni-popup-message-text { |
| | | font-size: 14px; |
| | | padding: 0; |
| | | } |
| | | |
| | | .uni-popup__success { |
| | | background-color: #e1f3d8; |
| | | } |
| | | |
| | | .uni-popup__success-text { |
| | | color: #67C23A; |
| | | } |
| | | |
| | | .uni-popup__warn { |
| | | background-color: #faecd8; |
| | | } |
| | | |
| | | .uni-popup__warn-text { |
| | | color: #E6A23C; |
| | | } |
| | | |
| | | .uni-popup__error { |
| | | background-color: #fde2e2; |
| | | } |
| | | |
| | | .uni-popup__error-text { |
| | | color: #F56C6C; |
| | | } |
| | | |
| | | .uni-popup__info { |
| | | background-color: #F2F6FC; |
| | | } |
| | | |
| | | .uni-popup__info-text { |
| | | color: #909399; |
| | | } |
| | | </style> |
New file |
| | |
| | | <template> |
| | | <view class="uni-popup-share"> |
| | | <view class="uni-share-title"><text class="uni-share-title-text">{{shareTitleText}}</text></view> |
| | | <view class="uni-share-content"> |
| | | <view class="uni-share-content-box"> |
| | | <view class="uni-share-content-item" v-for="(item,index) in bottomData" :key="index" @click.stop="select(item,index)"> |
| | | <image class="uni-share-image" :src="item.icon" mode="aspectFill"></image> |
| | | <text class="uni-share-text">{{item.text}}</text> |
| | | </view> |
| | | |
| | | </view> |
| | | </view> |
| | | <view class="uni-share-button-box"> |
| | | <button class="uni-share-button" @click="close">{{cancelText}}</button> |
| | | </view> |
| | | </view> |
| | | </template> |
| | | |
| | | <script> |
| | | import popup from '../uni-popup/popup.js' |
| | | import { |
| | | initVueI18n |
| | | } from '@dcloudio/uni-i18n' |
| | | import messages from '../uni-popup/i18n/index.js' |
| | | const { t } = initVueI18n(messages) |
| | | export default { |
| | | name: 'UniPopupShare', |
| | | mixins:[popup], |
| | | emits:['select'], |
| | | props: { |
| | | title: { |
| | | type: String, |
| | | default: '' |
| | | }, |
| | | beforeClose: { |
| | | type: Boolean, |
| | | default: false |
| | | } |
| | | }, |
| | | data() { |
| | | return { |
| | | bottomData: [{ |
| | | text: '微信', |
| | | icon: 'https://vkceyugu.cdn.bspapp.com/VKCEYUGU-dc-site/c2b17470-50be-11eb-b680-7980c8a877b8.png', |
| | | name: 'wx' |
| | | }, |
| | | { |
| | | text: '支付宝', |
| | | icon: 'https://vkceyugu.cdn.bspapp.com/VKCEYUGU-dc-site/d684ae40-50be-11eb-8ff1-d5dcf8779628.png', |
| | | name: 'wx' |
| | | }, |
| | | { |
| | | text: 'QQ', |
| | | icon: 'https://vkceyugu.cdn.bspapp.com/VKCEYUGU-dc-site/e7a79520-50be-11eb-b997-9918a5dda011.png', |
| | | name: 'qq' |
| | | }, |
| | | { |
| | | text: '新浪', |
| | | icon: 'https://vkceyugu.cdn.bspapp.com/VKCEYUGU-dc-site/0dacdbe0-50bf-11eb-8ff1-d5dcf8779628.png', |
| | | name: 'sina' |
| | | }, |
| | | // { |
| | | // text: '百度', |
| | | // icon: 'https://vkceyugu.cdn.bspapp.com/VKCEYUGU-dc-site/1ec6e920-50bf-11eb-8a36-ebb87efcf8c0.png', |
| | | // name: 'copy' |
| | | // }, |
| | | // { |
| | | // text: '其他', |
| | | // icon: 'https://vkceyugu.cdn.bspapp.com/VKCEYUGU-dc-site/2e0fdfe0-50bf-11eb-b997-9918a5dda011.png', |
| | | // name: 'more' |
| | | // } |
| | | ] |
| | | } |
| | | }, |
| | | created() {}, |
| | | computed: { |
| | | cancelText() { |
| | | return t("uni-popup.cancel") |
| | | }, |
| | | shareTitleText() { |
| | | return this.title || t("uni-popup.shareTitle") |
| | | } |
| | | }, |
| | | methods: { |
| | | /** |
| | | * 选择内容 |
| | | */ |
| | | select(item, index) { |
| | | this.$emit('select', { |
| | | item, |
| | | index |
| | | }) |
| | | this.close() |
| | | |
| | | }, |
| | | /** |
| | | * 关闭窗口 |
| | | */ |
| | | close() { |
| | | if(this.beforeClose) return |
| | | this.popup.close() |
| | | } |
| | | } |
| | | } |
| | | </script> |
| | | <style lang="scss" > |
| | | .uni-popup-share { |
| | | background-color: #fff; |
| | | border-top-left-radius: 11px; |
| | | border-top-right-radius: 11px; |
| | | } |
| | | .uni-share-title { |
| | | /* #ifndef APP-NVUE */ |
| | | display: flex; |
| | | /* #endif */ |
| | | flex-direction: row; |
| | | align-items: center; |
| | | justify-content: center; |
| | | height: 40px; |
| | | } |
| | | .uni-share-title-text { |
| | | font-size: 14px; |
| | | color: #666; |
| | | } |
| | | .uni-share-content { |
| | | /* #ifndef APP-NVUE */ |
| | | display: flex; |
| | | /* #endif */ |
| | | flex-direction: row; |
| | | justify-content: center; |
| | | padding-top: 10px; |
| | | } |
| | | |
| | | .uni-share-content-box { |
| | | /* #ifndef APP-NVUE */ |
| | | display: flex; |
| | | /* #endif */ |
| | | flex-direction: row; |
| | | flex-wrap: wrap; |
| | | width: 360px; |
| | | } |
| | | |
| | | .uni-share-content-item { |
| | | width: 90px; |
| | | /* #ifndef APP-NVUE */ |
| | | display: flex; |
| | | /* #endif */ |
| | | flex-direction: column; |
| | | justify-content: center; |
| | | padding: 10px 0; |
| | | align-items: center; |
| | | } |
| | | |
| | | .uni-share-content-item:active { |
| | | background-color: #f5f5f5; |
| | | } |
| | | |
| | | .uni-share-image { |
| | | width: 30px; |
| | | height: 30px; |
| | | } |
| | | |
| | | .uni-share-text { |
| | | margin-top: 10px; |
| | | font-size: 14px; |
| | | color: #3B4144; |
| | | } |
| | | |
| | | .uni-share-button-box { |
| | | /* #ifndef APP-NVUE */ |
| | | display: flex; |
| | | /* #endif */ |
| | | flex-direction: row; |
| | | padding: 10px 15px; |
| | | } |
| | | |
| | | .uni-share-button { |
| | | flex: 1; |
| | | border-radius: 50px; |
| | | color: #666; |
| | | font-size: 16px; |
| | | } |
| | | |
| | | .uni-share-button::after { |
| | | border-radius: 50px; |
| | | } |
| | | </style> |
New file |
| | |
| | | { |
| | | "uni-popup.cancel": "cancel", |
| | | "uni-popup.ok": "ok", |
| | | "uni-popup.placeholder": "pleace enter", |
| | | "uni-popup.title": "Hint", |
| | | "uni-popup.shareTitle": "Share to" |
| | | } |
New file |
| | |
| | | import en from './en.json' |
| | | import zhHans from './zh-Hans.json' |
| | | import zhHant from './zh-Hant.json' |
| | | export default { |
| | | en, |
| | | 'zh-Hans': zhHans, |
| | | 'zh-Hant': zhHant |
| | | } |
New file |
| | |
| | | { |
| | | "uni-popup.cancel": "取消", |
| | | "uni-popup.ok": "确定", |
| | | "uni-popup.placeholder": "请输入", |
| | | "uni-popup.title": "提示", |
| | | "uni-popup.shareTitle": "分享到" |
| | | } |
New file |
| | |
| | | { |
| | | "uni-popup.cancel": "取消", |
| | | "uni-popup.ok": "確定", |
| | | "uni-popup.placeholder": "請輸入", |
| | | "uni-popup.title": "提示", |
| | | "uni-popup.shareTitle": "分享到" |
| | | } |
New file |
| | |
| | | // #ifdef H5 |
| | | export default { |
| | | name: 'Keypress', |
| | | props: { |
| | | disable: { |
| | | type: Boolean, |
| | | default: false |
| | | } |
| | | }, |
| | | mounted () { |
| | | const keyNames = { |
| | | esc: ['Esc', 'Escape'], |
| | | tab: 'Tab', |
| | | enter: 'Enter', |
| | | space: [' ', 'Spacebar'], |
| | | up: ['Up', 'ArrowUp'], |
| | | left: ['Left', 'ArrowLeft'], |
| | | right: ['Right', 'ArrowRight'], |
| | | down: ['Down', 'ArrowDown'], |
| | | delete: ['Backspace', 'Delete', 'Del'] |
| | | } |
| | | const listener = ($event) => { |
| | | if (this.disable) { |
| | | return |
| | | } |
| | | const keyName = Object.keys(keyNames).find(key => { |
| | | const keyName = $event.key |
| | | const value = keyNames[key] |
| | | return value === keyName || (Array.isArray(value) && value.includes(keyName)) |
| | | }) |
| | | if (keyName) { |
| | | // 避免和其他按键事件冲突 |
| | | setTimeout(() => { |
| | | this.$emit(keyName, {}) |
| | | }, 0) |
| | | } |
| | | } |
| | | document.addEventListener('keyup', listener) |
| | | // this.$once('hook:beforeDestroy', () => { |
| | | // document.removeEventListener('keyup', listener) |
| | | // }) |
| | | }, |
| | | render: () => {} |
| | | } |
| | | // #endif |
New file |
| | |
| | | |
| | | export default { |
| | | data() { |
| | | return { |
| | | |
| | | } |
| | | }, |
| | | created(){ |
| | | this.popup = this.getParent() |
| | | }, |
| | | methods:{ |
| | | /** |
| | | * 获取父元素实例 |
| | | */ |
| | | getParent(name = 'uniPopup') { |
| | | let parent = this.$parent; |
| | | let parentName = parent.$options.name; |
| | | while (parentName !== name) { |
| | | parent = parent.$parent; |
| | | if (!parent) return false |
| | | parentName = parent.$options.name; |
| | | } |
| | | return parent; |
| | | }, |
| | | } |
| | | } |
New file |
| | |
| | | <template> |
| | | <view v-if="showPopup" class="uni-popup" :class="[popupstyle, isDesktop ? 'fixforpc-z-index' : '']"> |
| | | <view @touchstart="touchstart"> |
| | | <uni-transition key="1" v-if="maskShow" name="mask" mode-class="fade" :styles="maskClass" |
| | | :duration="duration" :show="showTrans" @click="onTap" /> |
| | | <uni-transition key="2" :mode-class="ani" name="content" :styles="transClass" :duration="duration" |
| | | :show="showTrans" @click="onTap"> |
| | | <view class="uni-popup__wrapper" :style="{ backgroundColor: bg }" :class="[popupstyle]" @click="clear"> |
| | | <slot /> |
| | | </view> |
| | | </uni-transition> |
| | | </view> |
| | | <!-- #ifdef H5 --> |
| | | <keypress v-if="maskShow" @esc="onTap" /> |
| | | <!-- #endif --> |
| | | </view> |
| | | </template> |
| | | |
| | | <script> |
| | | // #ifdef H5 |
| | | import keypress from './keypress.js' |
| | | // #endif |
| | | |
| | | /** |
| | | * PopUp 弹出层 |
| | | * @description 弹出层组件,为了解决遮罩弹层的问题 |
| | | * @tutorial https://ext.dcloud.net.cn/plugin?id=329 |
| | | * @property {String} type = [top|center|bottom|left|right|message|dialog|share] 弹出方式 |
| | | * @value top 顶部弹出 |
| | | * @value center 中间弹出 |
| | | * @value bottom 底部弹出 |
| | | * @value left 左侧弹出 |
| | | * @value right 右侧弹出 |
| | | * @value message 消息提示 |
| | | * @value dialog 对话框 |
| | | * @value share 底部分享示例 |
| | | * @property {Boolean} animation = [true|false] 是否开启动画 |
| | | * @property {Boolean} maskClick = [true|false] 蒙版点击是否关闭弹窗(废弃) |
| | | * @property {Boolean} isMaskClick = [true|false] 蒙版点击是否关闭弹窗 |
| | | * @property {String} backgroundColor 主窗口背景色 |
| | | * @property {String} maskBackgroundColor 蒙版颜色 |
| | | * @property {Boolean} safeArea 是否适配底部安全区 |
| | | * @event {Function} change 打开关闭弹窗触发,e={show: false} |
| | | * @event {Function} maskClick 点击遮罩触发 |
| | | */ |
| | | |
| | | export default { |
| | | name: 'uniPopup', |
| | | components: { |
| | | // #ifdef H5 |
| | | keypress |
| | | // #endif |
| | | }, |
| | | emits: ['change', 'maskClick'], |
| | | props: { |
| | | // 开启动画 |
| | | animation: { |
| | | type: Boolean, |
| | | default: true |
| | | }, |
| | | // 弹出层类型,可选值,top: 顶部弹出层;bottom:底部弹出层;center:全屏弹出层 |
| | | // message: 消息提示 ; dialog : 对话框 |
| | | type: { |
| | | type: String, |
| | | default: 'center' |
| | | }, |
| | | // maskClick |
| | | isMaskClick: { |
| | | type: Boolean, |
| | | default: null |
| | | }, |
| | | // TODO 2 个版本后废弃属性 ,使用 isMaskClick |
| | | maskClick: { |
| | | type: Boolean, |
| | | default: null |
| | | }, |
| | | backgroundColor: { |
| | | type: String, |
| | | default: 'none' |
| | | }, |
| | | safeArea: { |
| | | type: Boolean, |
| | | default: true |
| | | }, |
| | | maskBackgroundColor: { |
| | | type: String, |
| | | default: 'rgba(0, 0, 0, 0.4)' |
| | | }, |
| | | }, |
| | | |
| | | watch: { |
| | | /** |
| | | * 监听type类型 |
| | | */ |
| | | type: { |
| | | handler: function(type) { |
| | | if (!this.config[type]) return |
| | | this[this.config[type]](true) |
| | | }, |
| | | immediate: true |
| | | }, |
| | | isDesktop: { |
| | | handler: function(newVal) { |
| | | if (!this.config[newVal]) return |
| | | this[this.config[this.type]](true) |
| | | }, |
| | | immediate: true |
| | | }, |
| | | /** |
| | | * 监听遮罩是否可点击 |
| | | * @param {Object} val |
| | | */ |
| | | maskClick: { |
| | | handler: function(val) { |
| | | this.mkclick = val |
| | | }, |
| | | immediate: true |
| | | }, |
| | | isMaskClick: { |
| | | handler: function(val) { |
| | | this.mkclick = val |
| | | }, |
| | | immediate: true |
| | | }, |
| | | // H5 下禁止底部滚动 |
| | | showPopup(show) { |
| | | // #ifdef H5 |
| | | // fix by mehaotian 处理 h5 滚动穿透的问题 |
| | | document.getElementsByTagName('body')[0].style.overflow = show ? 'hidden' : 'visible' |
| | | // #endif |
| | | } |
| | | }, |
| | | data() { |
| | | return { |
| | | duration: 300, |
| | | ani: [], |
| | | showPopup: false, |
| | | showTrans: false, |
| | | popupWidth: 0, |
| | | popupHeight: 0, |
| | | config: { |
| | | top: 'top', |
| | | bottom: 'bottom', |
| | | center: 'center', |
| | | left: 'left', |
| | | right: 'right', |
| | | message: 'top', |
| | | dialog: 'center', |
| | | share: 'bottom' |
| | | }, |
| | | maskClass: { |
| | | position: 'fixed', |
| | | bottom: 0, |
| | | top: 0, |
| | | left: 0, |
| | | right: 0, |
| | | backgroundColor: 'rgba(0, 0, 0, 0.4)' |
| | | }, |
| | | transClass: { |
| | | position: 'fixed', |
| | | left: 0, |
| | | right: 0 |
| | | }, |
| | | maskShow: true, |
| | | mkclick: true, |
| | | popupstyle: this.isDesktop ? 'fixforpc-top' : 'top' |
| | | } |
| | | }, |
| | | computed: { |
| | | isDesktop() { |
| | | return this.popupWidth >= 500 && this.popupHeight >= 500 |
| | | }, |
| | | bg() { |
| | | if (this.backgroundColor === '' || this.backgroundColor === 'none') { |
| | | return 'transparent' |
| | | } |
| | | return this.backgroundColor |
| | | } |
| | | }, |
| | | mounted() { |
| | | const fixSize = () => { |
| | | const { |
| | | windowWidth, |
| | | windowHeight, |
| | | windowTop, |
| | | safeArea, |
| | | screenHeight, |
| | | safeAreaInsets |
| | | } = uni.getSystemInfoSync() |
| | | this.popupWidth = windowWidth |
| | | this.popupHeight = windowHeight + (windowTop || 0) |
| | | // TODO fix by mehaotian 是否适配底部安全区 ,目前微信ios 、和 app ios 计算有差异,需要框架修复 |
| | | if (safeArea && this.safeArea) { |
| | | // #ifdef MP-WEIXIN |
| | | this.safeAreaInsets = screenHeight - safeArea.bottom |
| | | // #endif |
| | | // #ifndef MP-WEIXIN |
| | | this.safeAreaInsets = safeAreaInsets.bottom |
| | | // #endif |
| | | } else { |
| | | this.safeAreaInsets = 0 |
| | | } |
| | | } |
| | | fixSize() |
| | | // #ifdef H5 |
| | | // window.addEventListener('resize', fixSize) |
| | | // this.$once('hook:beforeDestroy', () => { |
| | | // window.removeEventListener('resize', fixSize) |
| | | // }) |
| | | // #endif |
| | | }, |
| | | // #ifndef VUE3 |
| | | // TODO vue2 |
| | | destroyed() { |
| | | this.setH5Visible() |
| | | }, |
| | | // #endif |
| | | // #ifdef VUE3 |
| | | // TODO vue3 |
| | | unmounted() { |
| | | this.setH5Visible() |
| | | }, |
| | | // #endif |
| | | created() { |
| | | // this.mkclick = this.isMaskClick || this.maskClick |
| | | if (this.isMaskClick === null && this.maskClick === null) { |
| | | this.mkclick = true |
| | | } else { |
| | | this.mkclick = this.isMaskClick !== null ? this.isMaskClick : this.maskClick |
| | | } |
| | | if (this.animation) { |
| | | this.duration = 300 |
| | | } else { |
| | | this.duration = 0 |
| | | } |
| | | // TODO 处理 message 组件生命周期异常的问题 |
| | | this.messageChild = null |
| | | // TODO 解决头条冒泡的问题 |
| | | this.clearPropagation = false |
| | | this.maskClass.backgroundColor = this.maskBackgroundColor |
| | | }, |
| | | methods: { |
| | | setH5Visible() { |
| | | // #ifdef H5 |
| | | // fix by mehaotian 处理 h5 滚动穿透的问题 |
| | | document.getElementsByTagName('body')[0].style.overflow = 'visible' |
| | | // #endif |
| | | }, |
| | | /** |
| | | * 公用方法,不显示遮罩层 |
| | | */ |
| | | closeMask() { |
| | | this.maskShow = false |
| | | }, |
| | | /** |
| | | * 公用方法,遮罩层禁止点击 |
| | | */ |
| | | disableMask() { |
| | | this.mkclick = false |
| | | }, |
| | | // TODO nvue 取消冒泡 |
| | | clear(e) { |
| | | // #ifndef APP-NVUE |
| | | e.stopPropagation() |
| | | // #endif |
| | | this.clearPropagation = true |
| | | }, |
| | | |
| | | open(direction) { |
| | | // fix by mehaotian 处理快速打开关闭的情况 |
| | | if (this.showPopup) { |
| | | return |
| | | } |
| | | let innerType = ['top', 'center', 'bottom', 'left', 'right', 'message', 'dialog', 'share'] |
| | | if (!(direction && innerType.indexOf(direction) !== -1)) { |
| | | direction = this.type |
| | | } |
| | | if (!this.config[direction]) { |
| | | console.error('缺少类型:', direction) |
| | | return |
| | | } |
| | | this[this.config[direction]]() |
| | | this.$emit('change', { |
| | | show: true, |
| | | type: direction |
| | | }) |
| | | }, |
| | | close(type) { |
| | | this.showTrans = false |
| | | this.$emit('change', { |
| | | show: false, |
| | | type: this.type |
| | | }) |
| | | clearTimeout(this.timer) |
| | | // // 自定义关闭事件 |
| | | // this.customOpen && this.customClose() |
| | | this.timer = setTimeout(() => { |
| | | this.showPopup = false |
| | | }, 300) |
| | | }, |
| | | // TODO 处理冒泡事件,头条的冒泡事件有问题 ,先这样兼容 |
| | | touchstart() { |
| | | this.clearPropagation = false |
| | | }, |
| | | |
| | | onTap() { |
| | | if (this.clearPropagation) { |
| | | // fix by mehaotian 兼容 nvue |
| | | this.clearPropagation = false |
| | | return |
| | | } |
| | | this.$emit('maskClick') |
| | | if (!this.mkclick) return |
| | | this.close() |
| | | }, |
| | | /** |
| | | * 顶部弹出样式处理 |
| | | */ |
| | | top(type) { |
| | | this.popupstyle = this.isDesktop ? 'fixforpc-top' : 'top' |
| | | this.ani = ['slide-top'] |
| | | this.transClass = { |
| | | position: 'fixed', |
| | | left: 0, |
| | | right: 0, |
| | | backgroundColor: this.bg |
| | | } |
| | | // TODO 兼容 type 属性 ,后续会废弃 |
| | | if (type) return |
| | | this.showPopup = true |
| | | this.showTrans = true |
| | | this.$nextTick(() => { |
| | | if (this.messageChild && this.type === 'message') { |
| | | this.messageChild.timerClose() |
| | | } |
| | | }) |
| | | }, |
| | | /** |
| | | * 底部弹出样式处理 |
| | | */ |
| | | bottom(type) { |
| | | this.popupstyle = 'bottom' |
| | | this.ani = ['slide-bottom'] |
| | | this.transClass = { |
| | | position: 'fixed', |
| | | left: 0, |
| | | right: 0, |
| | | bottom: 0, |
| | | paddingBottom: this.safeAreaInsets + 'px', |
| | | backgroundColor: this.bg |
| | | } |
| | | // TODO 兼容 type 属性 ,后续会废弃 |
| | | if (type) return |
| | | this.showPopup = true |
| | | this.showTrans = true |
| | | }, |
| | | /** |
| | | * 中间弹出样式处理 |
| | | */ |
| | | center(type) { |
| | | this.popupstyle = 'center' |
| | | this.ani = ['zoom-out', 'fade'] |
| | | this.transClass = { |
| | | position: 'fixed', |
| | | /* #ifndef APP-NVUE */ |
| | | display: 'flex', |
| | | flexDirection: 'column', |
| | | /* #endif */ |
| | | bottom: 0, |
| | | left: 0, |
| | | right: 0, |
| | | top: 0, |
| | | justifyContent: 'center', |
| | | alignItems: 'center' |
| | | } |
| | | // TODO 兼容 type 属性 ,后续会废弃 |
| | | if (type) return |
| | | this.showPopup = true |
| | | this.showTrans = true |
| | | }, |
| | | left(type) { |
| | | this.popupstyle = 'left' |
| | | this.ani = ['slide-left'] |
| | | this.transClass = { |
| | | position: 'fixed', |
| | | left: 0, |
| | | bottom: 0, |
| | | top: 0, |
| | | backgroundColor: this.bg, |
| | | /* #ifndef APP-NVUE */ |
| | | display: 'flex', |
| | | flexDirection: 'column' |
| | | /* #endif */ |
| | | } |
| | | // TODO 兼容 type 属性 ,后续会废弃 |
| | | if (type) return |
| | | this.showPopup = true |
| | | this.showTrans = true |
| | | }, |
| | | right(type) { |
| | | this.popupstyle = 'right' |
| | | this.ani = ['slide-right'] |
| | | this.transClass = { |
| | | position: 'fixed', |
| | | bottom: 0, |
| | | right: 0, |
| | | top: 0, |
| | | backgroundColor: this.bg, |
| | | /* #ifndef APP-NVUE */ |
| | | display: 'flex', |
| | | flexDirection: 'column' |
| | | /* #endif */ |
| | | } |
| | | // TODO 兼容 type 属性 ,后续会废弃 |
| | | if (type) return |
| | | this.showPopup = true |
| | | this.showTrans = true |
| | | } |
| | | } |
| | | } |
| | | </script> |
| | | <style lang="scss"> |
| | | .uni-popup { |
| | | position: fixed; |
| | | /* #ifndef APP-NVUE */ |
| | | z-index: 99; |
| | | |
| | | /* #endif */ |
| | | &.top, |
| | | &.left, |
| | | &.right { |
| | | /* #ifdef H5 */ |
| | | top: var(--window-top); |
| | | /* #endif */ |
| | | /* #ifndef H5 */ |
| | | top: 0; |
| | | /* #endif */ |
| | | } |
| | | |
| | | .uni-popup__wrapper { |
| | | /* #ifndef APP-NVUE */ |
| | | display: block; |
| | | /* #endif */ |
| | | position: relative; |
| | | |
| | | /* iphonex 等安全区设置,底部安全区适配 */ |
| | | /* #ifndef APP-NVUE */ |
| | | // padding-bottom: constant(safe-area-inset-bottom); |
| | | // padding-bottom: env(safe-area-inset-bottom); |
| | | /* #endif */ |
| | | &.left, |
| | | &.right { |
| | | /* #ifdef H5 */ |
| | | padding-top: var(--window-top); |
| | | /* #endif */ |
| | | /* #ifndef H5 */ |
| | | padding-top: 0; |
| | | /* #endif */ |
| | | flex: 1; |
| | | } |
| | | } |
| | | } |
| | | |
| | | .fixforpc-z-index { |
| | | /* #ifndef APP-NVUE */ |
| | | z-index: 999; |
| | | /* #endif */ |
| | | } |
| | | |
| | | .fixforpc-top { |
| | | top: 0; |
| | | } |
| | | </style> |
New file |
| | |
| | | { |
| | | "id": "uni-popup", |
| | | "displayName": "uni-popup 弹出层", |
| | | "version": "1.8.3", |
| | | "description": " Popup 组件,提供常用的弹层", |
| | | "keywords": [ |
| | | "uni-ui", |
| | | "弹出层", |
| | | "弹窗", |
| | | "popup", |
| | | "弹框" |
| | | ], |
| | | "repository": "https://github.com/dcloudio/uni-ui", |
| | | "engines": { |
| | | "HBuilderX": "" |
| | | }, |
| | | "directories": { |
| | | "example": "../../temps/example_temps" |
| | | }, |
| | | "dcloudext": { |
| | | "sale": { |
| | | "regular": { |
| | | "price": "0.00" |
| | | }, |
| | | "sourcecode": { |
| | | "price": "0.00" |
| | | } |
| | | }, |
| | | "contact": { |
| | | "qq": "" |
| | | }, |
| | | "declaration": { |
| | | "ads": "无", |
| | | "data": "无", |
| | | "permissions": "无" |
| | | }, |
| | | "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui", |
| | | "type": "component-vue" |
| | | }, |
| | | "uni_modules": { |
| | | "dependencies": [ |
| | | "uni-scss", |
| | | "uni-transition" |
| | | ], |
| | | "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" |
| | | }, |
| | | "快应用": { |
| | | "华为": "u", |
| | | "联盟": "u" |
| | | }, |
| | | "Vue": { |
| | | "vue2": "y", |
| | | "vue3": "y" |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } |
New file |
| | |
| | | |
| | | |
| | | ## Popup 弹出层 |
| | | > **组件名:uni-popup** |
| | | > 代码块: `uPopup` |
| | | > 关联组件:`uni-transition` |
| | | |
| | | |
| | | 弹出层组件,在应用中弹出一个消息提示窗口、提示框等 |
| | | |
| | | ### [查看文档](https://uniapp.dcloud.io/component/uniui/uni-popup) |
| | | #### 如使用过程中有任何问题,或者您对uni-ui有一些好的建议,欢迎加入 uni-ui 交流群:871950839 |
| | | |
| | | |
| | | |
| | | |
| | | |
New file |
| | |
| | | ## 1.3.2(2023-05-04) |
| | | - 修复 NVUE 平台报错的问题 |
| | | ## 1.3.1(2021-11-23) |
| | | - 修复 init 方法初始化问题 |
| | | ## 1.3.0(2021-11-19) |
| | | - 优化 组件UI,并提供设计资源,详见:[https://uniapp.dcloud.io/component/uniui/resource](https://uniapp.dcloud.io/component/uniui/resource) |
| | | - 文档迁移,详见:[https://uniapp.dcloud.io/component/uniui/uni-transition](https://uniapp.dcloud.io/component/uniui/uni-transition) |
| | | ## 1.2.1(2021-09-27) |
| | | - 修复 init 方法不生效的 Bug |
| | | ## 1.2.0(2021-07-30) |
| | | - 组件兼容 vue3,如何创建 vue3 项目,详见 [uni-app 项目支持 vue3 介绍](https://ask.dcloud.net.cn/article/37834) |
| | | ## 1.1.1(2021-05-12) |
| | | - 新增 示例地址 |
| | | - 修复 示例项目缺少组件的 Bug |
| | | ## 1.1.0(2021-04-22) |
| | | - 新增 通过方法自定义动画 |
| | | - 新增 custom-class 非 NVUE 平台支持自定义 class 定制样式 |
| | | - 优化 动画触发逻辑,使动画更流畅 |
| | | - 优化 支持单独的动画类型 |
| | | - 优化 文档示例 |
| | | ## 1.0.2(2021-02-05) |
| | | - 调整为 uni_modules 目录规范 |
New file |
| | |
| | | // const defaultOption = { |
| | | // duration: 300, |
| | | // timingFunction: 'linear', |
| | | // delay: 0, |
| | | // transformOrigin: '50% 50% 0' |
| | | // } |
| | | // #ifdef APP-NVUE |
| | | const nvueAnimation = uni.requireNativePlugin('animation') |
| | | // #endif |
| | | class MPAnimation { |
| | | constructor(options, _this) { |
| | | this.options = options |
| | | // 在iOS10+QQ小程序平台下,传给原生的对象一定是个普通对象而不是Proxy对象,否则会报parameter should be Object instead of ProxyObject的错误 |
| | | this.animation = uni.createAnimation({ |
| | | ...options |
| | | }) |
| | | this.currentStepAnimates = {} |
| | | this.next = 0 |
| | | this.$ = _this |
| | | |
| | | } |
| | | |
| | | _nvuePushAnimates(type, args) { |
| | | let aniObj = this.currentStepAnimates[this.next] |
| | | let styles = {} |
| | | if (!aniObj) { |
| | | styles = { |
| | | styles: {}, |
| | | config: {} |
| | | } |
| | | } else { |
| | | styles = aniObj |
| | | } |
| | | if (animateTypes1.includes(type)) { |
| | | if (!styles.styles.transform) { |
| | | styles.styles.transform = '' |
| | | } |
| | | let unit = '' |
| | | if(type === 'rotate'){ |
| | | unit = 'deg' |
| | | } |
| | | styles.styles.transform += `${type}(${args+unit}) ` |
| | | } else { |
| | | styles.styles[type] = `${args}` |
| | | } |
| | | this.currentStepAnimates[this.next] = styles |
| | | } |
| | | _animateRun(styles = {}, config = {}) { |
| | | let ref = this.$.$refs['ani'].ref |
| | | if (!ref) return |
| | | return new Promise((resolve, reject) => { |
| | | nvueAnimation.transition(ref, { |
| | | styles, |
| | | ...config |
| | | }, res => { |
| | | resolve() |
| | | }) |
| | | }) |
| | | } |
| | | |
| | | _nvueNextAnimate(animates, step = 0, fn) { |
| | | let obj = animates[step] |
| | | if (obj) { |
| | | let { |
| | | styles, |
| | | config |
| | | } = obj |
| | | this._animateRun(styles, config).then(() => { |
| | | step += 1 |
| | | this._nvueNextAnimate(animates, step, fn) |
| | | }) |
| | | } else { |
| | | this.currentStepAnimates = {} |
| | | typeof fn === 'function' && fn() |
| | | this.isEnd = true |
| | | } |
| | | } |
| | | |
| | | step(config = {}) { |
| | | // #ifndef APP-NVUE |
| | | this.animation.step(config) |
| | | // #endif |
| | | // #ifdef APP-NVUE |
| | | this.currentStepAnimates[this.next].config = Object.assign({}, this.options, config) |
| | | this.currentStepAnimates[this.next].styles.transformOrigin = this.currentStepAnimates[this.next].config.transformOrigin |
| | | this.next++ |
| | | // #endif |
| | | return this |
| | | } |
| | | |
| | | run(fn) { |
| | | // #ifndef APP-NVUE |
| | | this.$.animationData = this.animation.export() |
| | | this.$.timer = setTimeout(() => { |
| | | typeof fn === 'function' && fn() |
| | | }, this.$.durationTime) |
| | | // #endif |
| | | // #ifdef APP-NVUE |
| | | this.isEnd = false |
| | | let ref = this.$.$refs['ani'] && this.$.$refs['ani'].ref |
| | | if(!ref) return |
| | | this._nvueNextAnimate(this.currentStepAnimates, 0, fn) |
| | | this.next = 0 |
| | | // #endif |
| | | } |
| | | } |
| | | |
| | | |
| | | const animateTypes1 = ['matrix', 'matrix3d', 'rotate', 'rotate3d', 'rotateX', 'rotateY', 'rotateZ', 'scale', 'scale3d', |
| | | 'scaleX', 'scaleY', 'scaleZ', 'skew', 'skewX', 'skewY', 'translate', 'translate3d', 'translateX', 'translateY', |
| | | 'translateZ' |
| | | ] |
| | | const animateTypes2 = ['opacity', 'backgroundColor'] |
| | | const animateTypes3 = ['width', 'height', 'left', 'right', 'top', 'bottom'] |
| | | animateTypes1.concat(animateTypes2, animateTypes3).forEach(type => { |
| | | MPAnimation.prototype[type] = function(...args) { |
| | | // #ifndef APP-NVUE |
| | | this.animation[type](...args) |
| | | // #endif |
| | | // #ifdef APP-NVUE |
| | | this._nvuePushAnimates(type, args) |
| | | // #endif |
| | | return this |
| | | } |
| | | }) |
| | | |
| | | export function createAnimation(option, _this) { |
| | | if(!_this) return |
| | | clearTimeout(_this.timer) |
| | | return new MPAnimation(option, _this) |
| | | } |
New file |
| | |
| | | <template> |
| | | <!-- #ifndef APP-NVUE --> |
| | | <view v-show="isShow" ref="ani" :animation="animationData" :class="customClass" :style="transformStyles" @click="onClick"><slot></slot></view> |
| | | <!-- #endif --> |
| | | <!-- #ifdef APP-NVUE --> |
| | | <view v-if="isShow" ref="ani" :animation="animationData" :class="customClass" :style="transformStyles" @click="onClick"><slot></slot></view> |
| | | <!-- #endif --> |
| | | </template> |
| | | |
| | | <script> |
| | | import { createAnimation } from './createAnimation' |
| | | |
| | | /** |
| | | * Transition 过渡动画 |
| | | * @description 简单过渡动画组件 |
| | | * @tutorial https://ext.dcloud.net.cn/plugin?id=985 |
| | | * @property {Boolean} show = [false|true] 控制组件显示或隐藏 |
| | | * @property {Array|String} modeClass = [fade|slide-top|slide-right|slide-bottom|slide-left|zoom-in|zoom-out] 过渡动画类型 |
| | | * @value fade 渐隐渐出过渡 |
| | | * @value slide-top 由上至下过渡 |
| | | * @value slide-right 由右至左过渡 |
| | | * @value slide-bottom 由下至上过渡 |
| | | * @value slide-left 由左至右过渡 |
| | | * @value zoom-in 由小到大过渡 |
| | | * @value zoom-out 由大到小过渡 |
| | | * @property {Number} duration 过渡动画持续时间 |
| | | * @property {Object} styles 组件样式,同 css 样式,注意带’-‘连接符的属性需要使用小驼峰写法如:`backgroundColor:red` |
| | | */ |
| | | export default { |
| | | name: 'uniTransition', |
| | | emits:['click','change'], |
| | | props: { |
| | | show: { |
| | | type: Boolean, |
| | | default: false |
| | | }, |
| | | modeClass: { |
| | | type: [Array, String], |
| | | default() { |
| | | return 'fade' |
| | | } |
| | | }, |
| | | duration: { |
| | | type: Number, |
| | | default: 300 |
| | | }, |
| | | styles: { |
| | | type: Object, |
| | | default() { |
| | | return {} |
| | | } |
| | | }, |
| | | customClass:{ |
| | | type: String, |
| | | default: '' |
| | | }, |
| | | onceRender:{ |
| | | type:Boolean, |
| | | default:false |
| | | }, |
| | | }, |
| | | data() { |
| | | return { |
| | | isShow: false, |
| | | transform: '', |
| | | opacity: 1, |
| | | animationData: {}, |
| | | durationTime: 300, |
| | | config: {} |
| | | } |
| | | }, |
| | | watch: { |
| | | show: { |
| | | handler(newVal) { |
| | | if (newVal) { |
| | | this.open() |
| | | } else { |
| | | // 避免上来就执行 close,导致动画错乱 |
| | | if (this.isShow) { |
| | | this.close() |
| | | } |
| | | } |
| | | }, |
| | | immediate: true |
| | | } |
| | | }, |
| | | computed: { |
| | | // 生成样式数据 |
| | | stylesObject() { |
| | | let styles = { |
| | | ...this.styles, |
| | | 'transition-duration': this.duration / 1000 + 's' |
| | | } |
| | | let transform = '' |
| | | for (let i in styles) { |
| | | let line = this.toLine(i) |
| | | transform += line + ':' + styles[i] + ';' |
| | | } |
| | | return transform |
| | | }, |
| | | // 初始化动画条件 |
| | | transformStyles() { |
| | | return 'transform:' + this.transform + ';' + 'opacity:' + this.opacity + ';' + this.stylesObject |
| | | } |
| | | }, |
| | | created() { |
| | | // 动画默认配置 |
| | | this.config = { |
| | | duration: this.duration, |
| | | timingFunction: 'ease', |
| | | transformOrigin: '50% 50%', |
| | | delay: 0 |
| | | } |
| | | this.durationTime = this.duration |
| | | }, |
| | | methods: { |
| | | /** |
| | | * ref 触发 初始化动画 |
| | | */ |
| | | init(obj = {}) { |
| | | if (obj.duration) { |
| | | this.durationTime = obj.duration |
| | | } |
| | | this.animation = createAnimation(Object.assign(this.config, obj),this) |
| | | }, |
| | | /** |
| | | * 点击组件触发回调 |
| | | */ |
| | | onClick() { |
| | | this.$emit('click', { |
| | | detail: this.isShow |
| | | }) |
| | | }, |
| | | /** |
| | | * ref 触发 动画分组 |
| | | * @param {Object} obj |
| | | */ |
| | | step(obj, config = {}) { |
| | | if (!this.animation) return |
| | | for (let i in obj) { |
| | | try { |
| | | if(typeof obj[i] === 'object'){ |
| | | this.animation[i](...obj[i]) |
| | | }else{ |
| | | this.animation[i](obj[i]) |
| | | } |
| | | } catch (e) { |
| | | console.error(`方法 ${i} 不存在`) |
| | | } |
| | | } |
| | | this.animation.step(config) |
| | | return this |
| | | }, |
| | | /** |
| | | * ref 触发 执行动画 |
| | | */ |
| | | run(fn) { |
| | | if (!this.animation) return |
| | | this.animation.run(fn) |
| | | }, |
| | | // 开始过度动画 |
| | | open() { |
| | | clearTimeout(this.timer) |
| | | this.transform = '' |
| | | this.isShow = true |
| | | let { opacity, transform } = this.styleInit(false) |
| | | if (typeof opacity !== 'undefined') { |
| | | this.opacity = opacity |
| | | } |
| | | this.transform = transform |
| | | // 确保动态样式已经生效后,执行动画,如果不加 nextTick ,会导致 wx 动画执行异常 |
| | | this.$nextTick(() => { |
| | | // TODO 定时器保证动画完全执行,目前有些问题,后面会取消定时器 |
| | | this.timer = setTimeout(() => { |
| | | this.animation = createAnimation(this.config, this) |
| | | this.tranfromInit(false).step() |
| | | this.animation.run() |
| | | this.$emit('change', { |
| | | detail: this.isShow |
| | | }) |
| | | }, 20) |
| | | }) |
| | | }, |
| | | // 关闭过度动画 |
| | | close(type) { |
| | | if (!this.animation) return |
| | | this.tranfromInit(true) |
| | | .step() |
| | | .run(() => { |
| | | this.isShow = false |
| | | this.animationData = null |
| | | this.animation = null |
| | | let { opacity, transform } = this.styleInit(false) |
| | | this.opacity = opacity || 1 |
| | | this.transform = transform |
| | | this.$emit('change', { |
| | | detail: this.isShow |
| | | }) |
| | | }) |
| | | }, |
| | | // 处理动画开始前的默认样式 |
| | | styleInit(type) { |
| | | let styles = { |
| | | transform: '' |
| | | } |
| | | let buildStyle = (type, mode) => { |
| | | if (mode === 'fade') { |
| | | styles.opacity = this.animationType(type)[mode] |
| | | } else { |
| | | styles.transform += this.animationType(type)[mode] + ' ' |
| | | } |
| | | } |
| | | if (typeof this.modeClass === 'string') { |
| | | buildStyle(type, this.modeClass) |
| | | } else { |
| | | this.modeClass.forEach(mode => { |
| | | buildStyle(type, mode) |
| | | }) |
| | | } |
| | | return styles |
| | | }, |
| | | // 处理内置组合动画 |
| | | tranfromInit(type) { |
| | | let buildTranfrom = (type, mode) => { |
| | | let aniNum = null |
| | | if (mode === 'fade') { |
| | | aniNum = type ? 0 : 1 |
| | | } else { |
| | | aniNum = type ? '-100%' : '0' |
| | | if (mode === 'zoom-in') { |
| | | aniNum = type ? 0.8 : 1 |
| | | } |
| | | if (mode === 'zoom-out') { |
| | | aniNum = type ? 1.2 : 1 |
| | | } |
| | | if (mode === 'slide-right') { |
| | | aniNum = type ? '100%' : '0' |
| | | } |
| | | if (mode === 'slide-bottom') { |
| | | aniNum = type ? '100%' : '0' |
| | | } |
| | | } |
| | | this.animation[this.animationMode()[mode]](aniNum) |
| | | } |
| | | if (typeof this.modeClass === 'string') { |
| | | buildTranfrom(type, this.modeClass) |
| | | } else { |
| | | this.modeClass.forEach(mode => { |
| | | buildTranfrom(type, mode) |
| | | }) |
| | | } |
| | | |
| | | return this.animation |
| | | }, |
| | | animationType(type) { |
| | | return { |
| | | fade: type ? 1 : 0, |
| | | 'slide-top': `translateY(${type ? '0' : '-100%'})`, |
| | | 'slide-right': `translateX(${type ? '0' : '100%'})`, |
| | | 'slide-bottom': `translateY(${type ? '0' : '100%'})`, |
| | | 'slide-left': `translateX(${type ? '0' : '-100%'})`, |
| | | 'zoom-in': `scaleX(${type ? 1 : 0.8}) scaleY(${type ? 1 : 0.8})`, |
| | | 'zoom-out': `scaleX(${type ? 1 : 1.2}) scaleY(${type ? 1 : 1.2})` |
| | | } |
| | | }, |
| | | // 内置动画类型与实际动画对应字典 |
| | | animationMode() { |
| | | return { |
| | | fade: 'opacity', |
| | | 'slide-top': 'translateY', |
| | | 'slide-right': 'translateX', |
| | | 'slide-bottom': 'translateY', |
| | | 'slide-left': 'translateX', |
| | | 'zoom-in': 'scale', |
| | | 'zoom-out': 'scale' |
| | | } |
| | | }, |
| | | // 驼峰转中横线 |
| | | toLine(name) { |
| | | return name.replace(/([A-Z])/g, '-$1').toLowerCase() |
| | | } |
| | | } |
| | | } |
| | | </script> |
| | | |
| | | <style></style> |
New file |
| | |
| | | { |
| | | "id": "uni-transition", |
| | | "displayName": "uni-transition 过渡动画", |
| | | "version": "1.3.2", |
| | | "description": "元素的简单过渡动画", |
| | | "keywords": [ |
| | | "uni-ui", |
| | | "uniui", |
| | | "动画", |
| | | "过渡", |
| | | "过渡动画" |
| | | ], |
| | | "repository": "https://github.com/dcloudio/uni-ui", |
| | | "engines": { |
| | | "HBuilderX": "" |
| | | }, |
| | | "directories": { |
| | | "example": "../../temps/example_temps" |
| | | }, |
| | | "dcloudext": { |
| | | "sale": { |
| | | "regular": { |
| | | "price": "0.00" |
| | | }, |
| | | "sourcecode": { |
| | | "price": "0.00" |
| | | } |
| | | }, |
| | | "contact": { |
| | | "qq": "" |
| | | }, |
| | | "declaration": { |
| | | "ads": "无", |
| | | "data": "无", |
| | | "permissions": "无" |
| | | }, |
| | | "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui", |
| | | "type": "component-vue" |
| | | }, |
| | | "uni_modules": { |
| | | "dependencies": ["uni-scss"], |
| | | "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" |
| | | }, |
| | | "快应用": { |
| | | "华为": "u", |
| | | "联盟": "u" |
| | | }, |
| | | "Vue": { |
| | | "vue2": "y", |
| | | "vue3": "y" |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } |
New file |
| | |
| | | |
| | | |
| | | ## Transition 过渡动画 |
| | | > **组件名:uni-transition** |
| | | > 代码块: `uTransition` |
| | | |
| | | |
| | | 元素过渡动画 |
| | | |
| | | ### [查看文档](https://uniapp.dcloud.io/component/uniui/uni-transition) |
| | | #### 如使用过程中有任何问题,或者您对uni-ui有一些好的建议,欢迎加入 uni-ui 交流群:871950839 |
New file |
| | |
| | | ## 1.0.10(2023-09-12) |
| | | 支持配置自动获取微信小程序后台的隐私协议名称 |
| | | ## 1.0.9(2023-09-11) |
| | | 增加一些常见问题的解决办法 |
| | | ## 1.0.8(2023-09-11) |
| | | 支持自定义主题色和背景色 |
| | | ## 1.0.7(2023-09-08) |
| | | 优化文档示例 |
| | | ## 1.0.6(2023-09-07) |
| | | 支持不允许不同意协议的功能,disagreeEnabled为false时,不同意按钮点击会提示disagreePromptText的内容 |
| | | ## 1.0.5(2023-09-05) |
| | | ## README中增加关于授权的说明 |
| | | ## 1.0.4(2023-09-02) |
| | | 强化文档中关于隐私指引调试配置的提醒 |
| | | ## 1.0.3(2023-09-01) |
| | | # 请注意 微信后台的用户隐私保护指引必须审核通过之后才可以调试 |
| | | ## 1.0.2(2023-09-01) |
| | | 更新隐私保护指引调试前的配置说明 |
| | | ## 1.0.1(2023-08-31) |
| | | 修复文案中【您点击同意并开始时用产品服务时】出现错别字的问题 |
| | | ## 1.0.0(2023-08-30) |
| | | 微信隐私保护弹出框,支持vue2和vue3 |
New file |
| | |
| | | /** |
| | | * 获取当前页面上下文 |
| | | * @returns 页面对象 |
| | | */ |
| | | export function getContext() { |
| | | // eslint-disable-next-line no-undef |
| | | const pages = getCurrentPages() |
| | | return pages[pages.length - 1] |
| | | } |
| | | |
| | | /** |
| | | * 获取上下文中指定节点组件 |
| | | * @param context 选择器的选择范围,可以传入自定义组件的 this 作为上下文 |
| | | * @param selector 自定义节点选择器 |
| | | */ |
| | | export function getComponent(context, selector ) { |
| | | let component = null |
| | | // #ifdef H5 |
| | | context.$children.forEach((child) => { |
| | | if (`#${child.$attrs.id}` === selector) { |
| | | component = child |
| | | } else if (child.$children && child.$children.length) { |
| | | if (getComponent(child, selector)) { |
| | | component = getComponent(child, selector) |
| | | } |
| | | } |
| | | if (component) { |
| | | return component |
| | | } |
| | | }) |
| | | // #endif |
| | | // #ifdef MP-WEIXIN |
| | | component = context.selectComponent && context.selectComponent(selector) && context.selectComponent(selector).$vm |
| | | // #endif |
| | | |
| | | // #ifdef MP-ALIPAY |
| | | const alipay = context.$children ? context.$children : context.$vm && context.$vm.$children ? context.$vm |
| | | .$children : [] |
| | | component = alipay.find((component) => { |
| | | return `#${component.$scope.props.id}` === selector |
| | | }) |
| | | // #endif |
| | | // #ifdef APP-PLUS |
| | | const app = context.$children ? context.$children : context.$vm && context.$vm.$children ? context.$vm.$children : |
| | | [] |
| | | component = app.find((component) => { |
| | | return `#${component.$attrs.id}` === selector |
| | | }) |
| | | // #endif |
| | | return component |
| | | } |
New file |
| | |
| | | <template> |
| | | <uni-popup id="privacy" type="center" ref="privacyPopup" :maskClick="false"> |
| | | <view class="ws-privacy-popup" :style="rootStyle"> |
| | | <view class="ws-privacy-popup__header"> |
| | | <!--标题--> |
| | | <view class="ws-picker__title">{{ title }}</view> |
| | | </view> |
| | | <view class="ws-privacy-popup__container"> |
| | | <text>{{ desc }}</text> |
| | | <text class="ws-privacy-popup__container-protocol" :style="protocolStyle" |
| | | @click="openPrivacyContract">{{ privacyContractName||protocol }}</text> |
| | | <text>{{ subDesc }}</text> |
| | | </view> |
| | | <view class="ws-privacy-popup__footer"> |
| | | <button class="is-agree" :style="agreeStyle" id="agree-btn" open-type="agreePrivacyAuthorization" |
| | | @agreeprivacyauthorization="handleAgree"> |
| | | {{agreeText}} |
| | | </button> |
| | | <button class="is-disagree" id="disagree-btn" @click="handleDisagree"> |
| | | {{disagreeText}} |
| | | </button> |
| | | </view> |
| | | </view> |
| | | </uni-popup> |
| | | </template> |
| | | <script> |
| | | import { |
| | | getContext, |
| | | getComponent |
| | | } from './util' |
| | | const privacyResolves = new Set() // onNeedPrivacyAuthorization的reslove |
| | | |
| | | let privacyHandler = null |
| | | // 注册监听 |
| | | if (uni.onNeedPrivacyAuthorization) { |
| | | uni.onNeedPrivacyAuthorization((resolve) => { |
| | | if (typeof privacyHandler === 'function') { |
| | | privacyHandler(resolve) |
| | | } |
| | | }) |
| | | } |
| | | |
| | | export default { |
| | | name: 'wsWxPrivacy', |
| | | emits: ['disagree', 'agree'], |
| | | props: { |
| | | // 标题 |
| | | title: { |
| | | type: String, |
| | | default: '用户隐私保护提示' |
| | | }, |
| | | // 描述 |
| | | desc: { |
| | | type: String, |
| | | default: '感谢您使用本应用,您使用本应用的服务之前请仔细阅读并同意' |
| | | }, |
| | | // 自定义隐私保护指引名称 |
| | | protocol: { |
| | | type: String, |
| | | default: '《用户隐私保护指引》' |
| | | }, |
| | | // 是否自动获取隐私保护指引名称(开启后调用getPrivacySetting获取名称) |
| | | enableAutoProtocol: { |
| | | type: Boolean, |
| | | default: false, // 默认为使用自定义隐私指引名称 |
| | | }, |
| | | // 子描述 |
| | | subDesc: { |
| | | type: String, |
| | | default: '。当您点击同意并开始使用产品服务时,即表示你已理解并同意该条款内容,该条款将对您产生法律约束力。如您拒绝,将无法使用相应服务。' |
| | | }, |
| | | /** |
| | | * 控制是否可以点击不同意按钮并显示提示。 |
| | | * 如果设置为 true,用户可以点击不同意按钮执行后续逻辑。 |
| | | * 如果设置为 false,点击不同意按钮会显示提示信息,但不会执行后续逻辑。 |
| | | * 默认为 true |
| | | */ |
| | | disagreeEnabled: { |
| | | type: Boolean, |
| | | default: true, // 默认为可以点击 |
| | | }, |
| | | /** |
| | | * 配置不同意按钮的提示消息内容。 |
| | | */ |
| | | disagreePromptText: { |
| | | type: String, |
| | | default: '请先仔细阅读并同意隐私协议', // 默认提示消息 |
| | | }, |
| | | // 拒绝按钮文字 |
| | | disagreeText: { |
| | | type: String, |
| | | default: '不同意' |
| | | }, |
| | | // 同意按钮文字 |
| | | agreeText: { |
| | | type: String, |
| | | default: '同意并继续' |
| | | }, |
| | | // 自定义背景颜色 |
| | | bgColor: { |
| | | type: String, |
| | | default: '' |
| | | }, |
| | | // 自定义主题颜色(控制同意按钮和隐私协议名称的颜色) |
| | | themeColor: { |
| | | type: String, |
| | | default: '' |
| | | } |
| | | }, |
| | | data() { |
| | | return { |
| | | privacyContractName: '', |
| | | } |
| | | }, |
| | | computed: { |
| | | rootStyle() { |
| | | if (this.bgColor) { |
| | | return `background:${this.bgColor}` |
| | | } else { |
| | | return '' |
| | | } |
| | | }, |
| | | protocolStyle() { |
| | | if (this.themeColor) { |
| | | return `color:${this.themeColor}` |
| | | } else { |
| | | return '' |
| | | } |
| | | }, |
| | | agreeStyle() { |
| | | if (this.themeColor) { |
| | | return `background:${this.themeColor}` |
| | | } else { |
| | | return '' |
| | | } |
| | | } |
| | | }, |
| | | created() { |
| | | privacyHandler = (resolve) => { |
| | | const context = getContext() |
| | | const privacyPopup = getComponent(context, '#privacy-popup') |
| | | if (privacyPopup) { |
| | | const privacy = getComponent(privacyPopup, '#privacy') |
| | | if (privacy && privacy.open) { |
| | | privacy.open() |
| | | } |
| | | } |
| | | privacyResolves.add(resolve) |
| | | } |
| | | if (this.enableAutoProtocol && uni.getPrivacySetting) { |
| | | uni.getPrivacySetting({ |
| | | success: res => { |
| | | if (res.privacyContractName) { |
| | | this.privacyContractName = res.privacyContractName |
| | | } |
| | | }, |
| | | fail: () => {}, |
| | | complete: () => {} |
| | | }) |
| | | } |
| | | }, |
| | | methods: { |
| | | /** |
| | | * 打开隐私协议 |
| | | */ |
| | | openPrivacyContract() { |
| | | wx.openPrivacyContract({ |
| | | success: (res) => { |
| | | console.log('openPrivacyContract success') |
| | | }, |
| | | fail: (res) => { |
| | | console.error('openPrivacyContract fail', res) |
| | | } |
| | | }) |
| | | }, |
| | | |
| | | /** |
| | | * 拒绝隐私协议 |
| | | */ |
| | | handleDisagree() { |
| | | if (this.disagreeEnabled) { |
| | | this.$refs.privacyPopup.close() |
| | | privacyResolves.forEach((resolve) => { |
| | | resolve({ |
| | | event: 'disagree' |
| | | }) |
| | | }) |
| | | privacyResolves.clear() |
| | | this.$emit('disagree') |
| | | } else { |
| | | uni.showToast({ |
| | | icon: 'none', |
| | | title: this.disagreePromptText |
| | | }) |
| | | } |
| | | |
| | | }, |
| | | |
| | | /** |
| | | * 同意隐私协议 |
| | | */ |
| | | handleAgree() { |
| | | this.$refs.privacyPopup.close() |
| | | privacyResolves.forEach((resolve) => { |
| | | resolve({ |
| | | event: 'agree', |
| | | buttonId: 'agree-btn' |
| | | }) |
| | | }) |
| | | privacyResolves.clear() |
| | | this.$emit('agree') |
| | | } |
| | | } |
| | | } |
| | | </script> |
| | | <style lang="scss" scoped> |
| | | .ws-privacy-popup { |
| | | padding: 48rpx; |
| | | box-sizing: border-box; |
| | | overflow: hidden; |
| | | width: 560rpx; |
| | | background: linear-gradient(180deg, #e5edff 0%, #ffffff 100%); |
| | | border-radius: 24rpx; |
| | | |
| | | &__header { |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: center; |
| | | width: 100%; |
| | | height: 52rpx; |
| | | font-size: 36rpx; |
| | | font-family: PingFangSC-Medium, PingFang SC; |
| | | font-weight: 550; |
| | | color: #1a1a1a; |
| | | line-height: 52rpx; |
| | | margin-bottom: 48rpx; |
| | | } |
| | | |
| | | &__container { |
| | | width: 100%; |
| | | box-sizing: border-box; |
| | | font-size: 28rpx; |
| | | font-family: PingFangSC-Regular, PingFang SC; |
| | | font-weight: 400; |
| | | color: #333333; |
| | | line-height: 48rpx; |
| | | margin-bottom: 48rpx; |
| | | |
| | | &-protocol { |
| | | font-weight: 550; |
| | | color: #4D80F0; |
| | | } |
| | | } |
| | | |
| | | &__footer { |
| | | display: flex; |
| | | flex-direction: column; |
| | | |
| | | .is-disagree, |
| | | .is-agree { |
| | | width: 100%; |
| | | height: 88rpx; |
| | | background: #ffffff; |
| | | border-radius: 44rpx; |
| | | font-size: 32rpx; |
| | | font-family: PingFangSC-Regular, PingFang SC; |
| | | font-weight: 400; |
| | | color: #666666; |
| | | } |
| | | |
| | | .is-agree { |
| | | background: #4D80F0; |
| | | color: #ffffff; |
| | | margin-bottom: 18rpx; |
| | | } |
| | | |
| | | button { |
| | | border: none; |
| | | outline: none; |
| | | |
| | | &::after { |
| | | border: none; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | </style> |
New file |
| | |
| | | { |
| | | "id": "ws-wx-privacy", |
| | | "displayName": "ws-wx-privacy 微信隐私保护弹出框 隐私协议弹出框", |
| | | "version": "1.0.10", |
| | | "description": "微信隐私保护弹出框 隐私协议弹出框,支持vue2和vue3,支持自定义文字和颜色 ws-wx-privacy,有问题评论区沟通,恶意差评走开。", |
| | | "keywords": [ |
| | | "微信小程序", |
| | | "隐私保护", |
| | | "隐私保护指引", |
| | | "隐私协议", |
| | | "隐私" |
| | | ], |
| | | "repository": "", |
| | | "engines": { |
| | | "HBuilderX": "^3.8.6" |
| | | }, |
| | | "dcloudext": { |
| | | "type": "component-vue", |
| | | "sale": { |
| | | "regular": { |
| | | "price": "0.00" |
| | | }, |
| | | "sourcecode": { |
| | | "price": "0.00" |
| | | } |
| | | }, |
| | | "contact": { |
| | | "qq": "" |
| | | }, |
| | | "declaration": { |
| | | "ads": "无", |
| | | "data": "插件不采集任何数据", |
| | | "permissions": "无" |
| | | }, |
| | | "npmurl": "" |
| | | }, |
| | | "uni_modules": { |
| | | "dependencies": ["uni-popup"], |
| | | "encrypt": [], |
| | | "platforms": { |
| | | "cloud": { |
| | | "tcb": "y", |
| | | "aliyun": "y" |
| | | }, |
| | | "client": { |
| | | "Vue": { |
| | | "vue2": "y", |
| | | "vue3": "y" |
| | | }, |
| | | "App": { |
| | | "app-vue": "n", |
| | | "app-nvue": "n" |
| | | }, |
| | | "H5-mobile": { |
| | | "Safari": "n", |
| | | "Android Browser": "n", |
| | | "微信浏览器(Android)": "n", |
| | | "QQ浏览器(Android)": "n" |
| | | }, |
| | | "H5-pc": { |
| | | "Chrome": "n", |
| | | "IE": "n", |
| | | "Edge": "n", |
| | | "Firefox": "n", |
| | | "Safari": "n" |
| | | }, |
| | | "小程序": { |
| | | "微信": "y", |
| | | "阿里": "n", |
| | | "百度": "n", |
| | | "字节跳动": "n", |
| | | "QQ": "n", |
| | | "钉钉": "n", |
| | | "快手": "n", |
| | | "飞书": "n", |
| | | "京东": "n" |
| | | }, |
| | | "快应用": { |
| | | "华为": "n", |
| | | "联盟": "n" |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } |
New file |
| | |
| | | # ws-wx-privacy 隐私保护弹窗组件 |
| | | |
| | | 本组件基于微信小程序官方政策开发,[关于小程序隐私保护指引设置的公告](https://developers.weixin.qq.com/community/develop/doc/00042e3ef54940ce8520e38db61801?blockType=1&page=1#comment-list) |
| | | |
| | | `wsWxPrivacy` 组件用于显示隐私保护提示的弹窗,用户可以选择同意或不同意隐私协议。 |
| | | |
| | | # 请注意 微信后台的用户隐私保护指引必须审核通过之后才可以调试 |
| | | |
| | | ### 注意事项 |
| | | 1. 请使用HbuilderX导入,因为本组件依赖`uni-popup`直接下载会丢失依赖。 |
| | | 2. 部分隐私接口需要用`wx.requirePrivacyAuthorize`接口包装,请仔细阅读[微信小程序隐私协议开发指南](https://developers.weixin.qq.com/miniprogram/dev/framework/user-privacy/PrivacyAuthorize.html) |
| | | 3. popup可以自行替换为自己使用的组件,以减小小程序包体积,不过需要注意使用`util.js`中的方法获取组件并打开,使用ref可能会因为this指向的问题导致无法打开弹出框 |
| | | 4. 导入demo项目请选择vue3版本,导入组件不限。 |
| | | |
| | | ### 隐私指引调试配置(必须配置完成才可以顺利调试) |
| | | 执行完以下三个步骤之后才可以顺利调试隐私指引内容,如有问题请先自查下边三个步骤是否都完成 |
| | | |
| | | #### 1.更新用户隐私保护指引(必需) |
| | | 小程序管理员或开发者可以根据具体小程序涉及到的[隐私相关接口](https://developers.weixin.qq.com/miniprogram/dev/framework/user-privacy/miniprogram-intro.html)来更新微信小程序后台的`用户隐私保护指引`,更新并审核通过后就可以进行相关的开发调试工作。 |
| | | |
| | | `需要注意的是,仅有在指引中声明所处理的用户信息,才可以调用平台提供的对应接口或组件。若未声明,对应接口或组件将直接禁用` |
| | | |
| | | `微信后台的用户隐私保护指引必须审核通过之后才可以调试,必须审核通过!审核通过!审核通过!` |
| | | |
| | | #### 2.配置调试字段__usePrivacyCheck__ (必需) |
| | | 参考 [微信小程序隐私协议开发指南](https://developers.weixin.qq.com/miniprogram/dev/framework/user-privacy/PrivacyAuthorize.html)中的介绍 |
| | | |
| | | 目前 `getPrivacySetting`、`onNeedPrivacyAuthorization`、`requirePrivacyAuthorize` 等接口目前可以正常接入调试。调试说明: |
| | | |
| | | - 在 2023 年 9 月 15 号之前,在 app.json 中配置 `"__usePrivacyCheck__": true` 后,会启用隐私相关功能,如果不配置或者配置为 false 则不会启用。 |
| | | |
| | | - 在 2023 年 9 月 15 号之后,不论 app.json 中是否有配置 **usePrivacyCheck**,隐私相关功能都会启用。 |
| | | |
| | | 所以在基于`uni-app`开发时,我们在 2023 年 9 月 15 号之前进行相关开发调试则需要在`manifest.json`文件`mp-weixin`中添加`"__usePrivacyCheck__": true` |
| | | |
| | | #### 3.配置微信开发工具基础库(必需) |
| | | 将调试基础库改为3.0.0以上。具体路径为: |
| | | 微信开发者工具->详情->本地设置->调试基础库 |
| | | |
| | | #### 4.如果三个步骤都做完了,还是无法调起弹出框 |
| | | 可以使用getPrivacySetting接口查询一下是否已经授权,已经授权就不会调起弹出框了,这时候需要将缓存清除。 |
| | | |
| | | |
| | | ### Props |
| | | |
| | | | 属性 | 类型 | 默认值 | 描述 | |
| | | |------------ |-------- |---------------------------------- |------------------------------------------------------------------------------------------ | |
| | | | title | String | 用户隐私保护提示 | 弹窗标题。 | |
| | | | desc | String | 感谢您使用本应用,... | 弹窗描述。 | |
| | | | protocol | String | 用户隐私保护指引 | 隐私保护指引的名称。 | |
| | | | subDesc | String | 。当您点击同意并开始时... | 子描述,进一步解释同意隐私协议的含义。 | |
| | | | disagreeEnabled | Boolean | true | 是否允许拒绝。控制是否可以点击不同意按钮并执行后续逻辑。如果设置为 true,用户可以点击不同意按钮执行后续逻辑。如果设置为 false,点击不同意按钮会显示提示信息,但不会执行后续逻辑。 | |
| | | | disagreePromptText| String | 请先仔细阅读并同意隐私协议 | 不同意按钮的提示消息内容。 | |
| | | | bgColor | String | - | 自定义背景颜色。 | |
| | | | themeColor | String | - | 自定义主题颜色(控制同意按钮和隐私协议名称的颜色)。 | |
| | | |
| | | ### Events |
| | | |
| | | | 事件 | 参数 | 描述 | |
| | | |-----------|----------------------------------------|----------------------------------------------------------------------------------------| |
| | | | disagree | 无参数 | 用户选择不同意隐私协议时触发的事件。 | |
| | | | agree | 无参数 | 用户选择同意隐私协议时触发的事件。 | |
| | | |
| | | |
| | | ### 使用示例 |
| | | 请确保你已经阅读或了解过[uni-modules 规范](https://uniapp.dcloud.net.cn/plugin/uni_modules.html#uni-modules) |
| | | 使用hbuildX导入组件后可以直接使用,无需import。 |
| | | |
| | | ```vue |
| | | <template> |
| | | <view> |
| | | <!-- #ifdef MP-WEIXIN --> |
| | | <ws-wx-privacy id="privacy-popup"></ws-wx-privacy> |
| | | <!-- #endif --> |
| | | </view> |
| | | </template> |
| | | <script> |
| | | |
| | | export default { |
| | | components: {}, |
| | | methods: { |
| | | handleDisagree() { |
| | | // 处理用户不同意隐私协议的逻辑 |
| | | }, |
| | | handleAgree() { |
| | | // 处理用户同意隐私协议的逻辑 |
| | | } |
| | | } |
| | | } |
| | | </script> |
| | | ``` |
| | | |
| | | 请注意,上述示例中的组件路径和事件处理逻辑可能需要根据实际情况进行调整。其中`id="privacy-popup"`必填,目的是为了解决多个连续页面同时引入,造成的this指向错误的问题。 |
| | | |
| | | ## 授权协议 |
| | | ``` |
| | | 1. 企业或个人可以免费商用。 |
| | | 2. 企业或个人不得复制、改造传播并分发本组件。 |
| | | 3. 如果你想分享本组件及教程,请保留本组件的下载地址以及作者名称。 |
| | | ``` |
| | | |
| | | ## 常见问题 |
| | | ### 1.弹出框弹不出来? |
| | | #### 一、请先自检"隐私指引调试配置(必须配置完成才可以顺利调试)"章节的配置是否完成(隐私协议一定要包含调用的API且隐私协议要审核通过) |
| | | #### 二、然后看看微信开发者工具是否最新 |
| | | #### 三、其次使用getPrivacySetting接口看一下是否已经授权过了 |
| | | |
| | | ### 2.示例项目跑不起来? |
| | | #### 请先看看是否选择了vue3下载,如果不是重新选择vue3下载。 |
| | | |
| | | ### 3.组件是否支持vue2 |
| | | #### 支持 |
| | | |
| | | ### 4.chooseImage同意了但是没有弹出选图片的界面? |
| | | #### 也是参考常见问题1,隐私协议是否审核通过且包含选取图片的API |
| | | |
| | | ### 5.如何知道隐私协议里面该配哪些权限 |
| | | #### 在[隐私相关接口](https://developers.weixin.qq.com/miniprogram/dev/framework/user-privacy/miniprogram-intro.html)里面找你用到的API,例如uni.chooseImage对应“收集你选中的照片或视频信息 ” |
| | | |
| | | |
| | | ## Vue3高颜值组件库推荐 |
| | | 这里推荐一下[wot-design-uni](https://ext.dcloud.net.cn/plugin?id=13889),支持暗黑模式自定义主题的高颜值组件库,提供50+组件。 |
New file |
| | |
| | | class websocketUtil { |
| | | constructor(url, time) { |
| | | this.is_open_socket = false //避免重复连接 |
| | | this.url = url //地址 |
| | | this.data = null |
| | | //心跳检测 |
| | | this.timeout = time //多少秒执行检测 |
| | | this.heartbeatInterval = null //检测服务器端是否还活着 |
| | | this.reconnectTimeOut = null //重连之后多久再次重连 |
| | | try { |
| | | return this.connectSocketInit() |
| | | } catch (e) { |
| | | console.log('catch'); |
| | | this.is_open_socket = false |
| | | this.reconnect(); |
| | | } |
| | | } |
| | | // 进入这个页面的时候创建websocket连接【整个页面随时使用】 |
| | | connectSocketInit() { |
| | | this.socketTask = uni.connectSocket({ |
| | | url: this.url, |
| | | success: () => { |
| | | console.log("正准备建立websocket中..."); |
| | | // 返回实例 |
| | | return this.socketTask |
| | | }, |
| | | }); |
| | | this.socketTask.onOpen((res) => { |
| | | console.log("WebSocket连接正常!"); |
| | | clearTimeout(this.reconnectTimeOut) |
| | | clearTimeout(this.heartbeatInterval) |
| | | this.is_open_socket = true; |
| | | this.start(); |
| | | // 注:只有连接正常打开中 ,才能正常收到消息 |
| | | this.socketTask.onMessage((res) => { |
| | | console.log(res.data) |
| | | }); |
| | | }) |
| | | // 监听连接失败,这里代码我注释掉的原因是因为如果服务器关闭后,和下面的onclose方法一起发起重连操作,这样会导致重复连接 |
| | | // uni.onSocketError((res) => { |
| | | // console.log('WebSocket连接打开失败,请检查!'); |
| | | // this.is_open_socket = false; |
| | | // this.reconnect(); |
| | | // }); |
| | | // 这里仅是事件监听【如果socket关闭了会执行】 |
| | | this.socketTask.onClose(() => { |
| | | console.log("已经被关闭了") |
| | | this.is_open_socket = false; |
| | | this.reconnect(); |
| | | }) |
| | | } |
| | | //发送消息 |
| | | send(value) { |
| | | // 注:只有连接正常打开中 ,才能正常成功发送消息 |
| | | this.socketTask.send({ |
| | | data: value, |
| | | async success() { |
| | | console.log("消息发送成功"); |
| | | }, |
| | | }); |
| | | } |
| | | //开启心跳检测 |
| | | start() { |
| | | this.heartbeatInterval = setTimeout(() => { |
| | | this.data = { |
| | | value: "传输内容", |
| | | method: "方法名称" |
| | | } |
| | | console.log(this.data) |
| | | this.send(JSON.stringify(this.data)); |
| | | }, this.timeout) |
| | | } |
| | | //重新连接 |
| | | reconnect() { |
| | | //停止发送心跳 |
| | | clearInterval(this.heartbeatInterval) |
| | | //如果不是人为关闭的话,进行重连 |
| | | if (!this.is_open_socket) { |
| | | this.reconnectTimeOut = setTimeout(() => { |
| | | this.connectSocketInit(); |
| | | }, 3000) |
| | | } |
| | | } |
| | | //外部获取消息 |
| | | getMessage(callback) { |
| | | this.socketTask.onMessage((res) => { |
| | | return callback(res) |
| | | }) |
| | | } |
| | | } |
| | | module.exports = websocketUtil |