添加了一些页面

This commit is contained in:
qianlile
2021-08-17 13:36:34 +08:00
parent 7c061bbb9b
commit a341927725
47 changed files with 2430 additions and 686 deletions

View File

@@ -1,40 +1,48 @@
// const baseURL = 'http://106.38.203.210:81/prod-api';
const baseURL = 'http://106.12.9.213:80/prod-api';
const token = wx.getStorageSync('token') || '';
const loginApi = (url, params = {} ) => {
return new Promise((resolve,reject) => {
wx.request({
url:baseURL+url,
...params,
success:(res)=>{
resolve(res);
},
fail:(err) => {
reject(err)
}
})
})
}
const token = wx.getStorageSync('token') || '';
const requestApi = ( url, params={} ) => {
return new Promise((resolve,reject) => {
wx.request({
url:baseURL+url,
...params,
header:{
"Authorization":token
},
success:(res)=>{
resolve(res);
},
fail:(err) => {
reject(err)
wx.cloud.callFunction({
name: 'wumeiRequest',
data: {
url:baseURL+url,
params:{
...params,
headers:{
"Authorization":token
}
},
}
})
}).then(res=>{
resolve(res)
}).catch(err=>{
reject(err)
})
})
}
const loginApi = (url, params={})=>{
return new Promise((resolve,reject)=>{
wx.cloud.callFunction({
name: 'wumeiRequest',
data: {
url:baseURL+url,
params:{
...params
}
}
}).then(res=>{
resolve(res)
}).catch(err=>{
reject(err)
})
})
}
module.exports={

View File

@@ -28,7 +28,7 @@ App({
// env 参数决定接下来小程序发起的云开发调用wx.cloud.xxx会默认请求到哪个云环境的资源
// 此处请填入环境 ID, 环境 ID 可打开云控制台查看
// 如不填则使用默认环境(第一个创建的环境)
env: 'mmydev-1ge33h7a9c3abf3fy-env-id',
env: 'mydev-1ge33h7a9c3abf3f',
traceUser: true,
})
}

View File

@@ -1,30 +1,35 @@
{
"pages": [
"pages": [
"pages/login/index",
"pages/index/index",
"pages/roomSystem/index",
"pages/my/index"
"pages/my/index",
"pages/someData/index",
"pages/aboutUs/index",
"pages/PM2.5/index"
],
"window": {
"backgroundColor": "#F6F6F6",
"backgroundTextStyle": "light",
"navigationBarBackgroundColor": "#F6F6F6",
"navigationBarTitleText": "智慧宿舍",
"navigationBarTitleText": "物美",
"navigationBarTextStyle": "black"
},
"tabBar": {
"list": [{
"pagePath": "pages/index/index",
"text": "首页",
"iconPath": "icons/home.png",
"selectedIconPath": "icons/home_selected.png"
},
{
"pagePath": "pages/my/index",
"text": "我的",
"iconPath": "icons/user.png",
"selectedIconPath": "icons/user_selected.png"
}]
"list": [
{
"pagePath": "pages/index/index",
"text": "首页",
"iconPath": "icons/home.png",
"selectedIconPath": "icons/home_selected.png"
},
{
"pagePath": "pages/my/index",
"text": "我的",
"iconPath": "icons/user.png",
"selectedIconPath": "icons/user_selected.png"
}
]
},
"sitemapLocation": "sitemap.json",
"permission": {

View File

@@ -1,337 +0,0 @@
const FATAL_REBUILD_TOLERANCE = 10
const SETDATA_SCROLL_TO_BOTTOM = {
scrollTop: 100000,
scrollWithAnimation: true,
}
Component({
properties: {
envId: String,
collection: String,
groupId: String,
groupName: String,
userInfo: Object,
onGetUserInfo: {
type: Function,
},
getOpenID: {
type: Function,
},
},
data: {
chats: [],
textInputValue: '',
openId: '',
scrollTop: 0,
scrollToMessage: '',
hasKeyboard: false,
},
methods: {
onGetUserInfo(e) {
this.properties.onGetUserInfo(e)
},
getOpenID() {
return this.properties.getOpenID()
},
mergeCommonCriteria(criteria) {
return {
groupId: this.data.groupId,
...criteria,
}
},
async initRoom() {
this.try(async () => {
await this.initOpenID()
const { envId, collection } = this.properties
this.db = wx.cloud.database({
env: envId,
})
const db = this.db
const _ = db.command
const { data: initList } = await db.collection(collection).where(this.mergeCommonCriteria()).orderBy('sendTimeTS', 'desc').get()
console.log('init query chats', initList)
this.setData({
chats: initList.reverse(),
scrollTop: 10000,
})
this.initWatch(initList.length ? {
sendTimeTS: _.gt(initList[initList.length - 1].sendTimeTS),
} : {})
}, '初始化失败')
},
async initOpenID() {
return this.try(async () => {
const openId = await this.getOpenID()
this.setData({
openId,
})
}, '初始化 openId 失败')
},
async initWatch(criteria) {
this.try(() => {
const { collection } = this.properties
const db = this.db
const _ = db.command
console.warn(`开始监听`, criteria)
this.messageListener = db.collection(collection).where(this.mergeCommonCriteria(criteria)).watch({
onChange: this.onRealtimeMessageSnapshot.bind(this),
onError: e => {
if (!this.inited || this.fatalRebuildCount >= FATAL_REBUILD_TOLERANCE) {
this.showError(this.inited ? '监听错误,已断开' : '初始化监听失败', e, '重连', () => {
this.initWatch(this.data.chats.length ? {
sendTimeTS: _.gt(this.data.chats[this.data.chats.length - 1].sendTimeTS),
} : {})
})
} else {
this.initWatch(this.data.chats.length ? {
sendTimeTS: _.gt(this.data.chats[this.data.chats.length - 1].sendTimeTS),
} : {})
}
},
})
}, '初始化监听失败')
},
onRealtimeMessageSnapshot(snapshot) {
console.warn(`收到消息`, snapshot)
if (snapshot.type === 'init') {
this.setData({
chats: [
...this.data.chats,
...[...snapshot.docs].sort((x, y) => x.sendTimeTS - y.sendTimeTS),
],
})
this.scrollToBottom()
this.inited = true
} else {
let hasNewMessage = false
let hasOthersMessage = false
const chats = [...this.data.chats]
for (const docChange of snapshot.docChanges) {
switch (docChange.queueType) {
case 'enqueue': {
hasOthersMessage = docChange.doc._openid !== this.data.openId
const ind = chats.findIndex(chat => chat._id === docChange.doc._id)
if (ind > -1) {
if (chats[ind].msgType === 'image' && chats[ind].tempFilePath) {
chats.splice(ind, 1, {
...docChange.doc,
tempFilePath: chats[ind].tempFilePath,
})
} else chats.splice(ind, 1, docChange.doc)
} else {
hasNewMessage = true
chats.push(docChange.doc)
}
break
}
}
}
this.setData({
chats: chats.sort((x, y) => x.sendTimeTS - y.sendTimeTS),
})
if (hasOthersMessage || hasNewMessage) {
this.scrollToBottom()
}
}
},
async onConfirmSendText(e) {
this.try(async () => {
if (!e.detail.value) {
return
}
const { collection } = this.properties
const db = this.db
const _ = db.command
const doc = {
_id: `${Math.random()}_${Date.now()}`,
groupId: this.data.groupId,
avatar: this.data.userInfo.avatarUrl,
nickName: this.data.userInfo.nickName,
msgType: 'text',
textContent: e.detail.value,
sendTime: new Date(),
sendTimeTS: Date.now(), // fallback
}
this.setData({
textInputValue: '',
chats: [
...this.data.chats,
{
...doc,
_openid: this.data.openId,
writeStatus: 'pending',
},
],
})
this.scrollToBottom(true)
await db.collection(collection).add({
data: doc,
})
this.setData({
chats: this.data.chats.map(chat => {
if (chat._id === doc._id) {
return {
...chat,
writeStatus: 'written',
}
} else return chat
}),
})
}, '发送文字失败')
},
async onChooseImage(e) {
wx.chooseImage({
count: 1,
sourceType: ['album', 'camera'],
success: async res => {
const { envId, collection } = this.properties
const doc = {
_id: `${Math.random()}_${Date.now()}`,
groupId: this.data.groupId,
avatar: this.data.userInfo.avatarUrl,
nickName: this.data.userInfo.nickName,
msgType: 'image',
sendTime: new Date(),
sendTimeTS: Date.now(), // fallback
}
this.setData({
chats: [
...this.data.chats,
{
...doc,
_openid: this.data.openId,
tempFilePath: res.tempFilePaths[0],
writeStatus: 0,
},
]
})
this.scrollToBottom(true)
const uploadTask = wx.cloud.uploadFile({
cloudPath: `${this.data.openId}/${Math.random()}_${Date.now()}.${res.tempFilePaths[0].match(/\.(\w+)$/)[1]}`,
filePath: res.tempFilePaths[0],
config: {
env: envId,
},
success: res => {
this.try(async () => {
await this.db.collection(collection).add({
data: {
...doc,
imgFileID: res.fileID,
},
})
}, '发送图片失败')
},
fail: e => {
this.showError('发送图片失败', e)
},
})
uploadTask.onProgressUpdate(({ progress }) => {
this.setData({
chats: this.data.chats.map(chat => {
if (chat._id === doc._id) {
return {
...chat,
writeStatus: progress,
}
} else return chat
})
})
})
},
})
},
onMessageImageTap(e) {
wx.previewImage({
urls: [e.target.dataset.fileid],
})
},
scrollToBottom(force) {
if (force) {
console.log('force scroll to bottom')
this.setData(SETDATA_SCROLL_TO_BOTTOM)
return
}
this.createSelectorQuery().select('.body').boundingClientRect(bodyRect => {
this.createSelectorQuery().select(`.body`).scrollOffset(scroll => {
if (scroll.scrollTop + bodyRect.height * 3 > scroll.scrollHeight) {
console.log('should scroll to bottom')
this.setData(SETDATA_SCROLL_TO_BOTTOM)
}
}).exec()
}).exec()
},
async onScrollToUpper() {
if (this.db && this.data.chats.length) {
const { collection } = this.properties
const _ = this.db.command
const { data } = await this.db.collection(collection).where(this.mergeCommonCriteria({
sendTimeTS: _.lt(this.data.chats[0].sendTimeTS),
})).orderBy('sendTimeTS', 'desc').get()
this.data.chats.unshift(...data.reverse())
this.setData({
chats: this.data.chats,
scrollToMessage: `item-${data.length}`,
scrollWithAnimation: false,
})
}
},
async try(fn, title) {
try {
await fn()
} catch (e) {
this.showError(title, e)
}
},
showError(title, content, confirmText, confirmCallback) {
console.error(title, content)
wx.showModal({
title,
content: content.toString(),
showCancel: confirmText ? true : false,
confirmText,
success: res => {
res.confirm && confirmCallback()
},
})
},
},
ready() {
global.chatroom = this
this.initRoom()
this.fatalRebuildCount = 0
},
})

View File

@@ -1,85 +0,0 @@
<view class="chatroom">
<view class="header">
<!-- display number of people in the room -->
<view class="left"></view>
<!-- room name -->
<view class="middle">{{groupName}}</view>
<!-- reserved -->
<view class="right"></view>
</view>
<!-- chats -->
<scroll-view
class="body"
scroll-y
scroll-with-animation="{{scrollWithAnimation}}"
scroll-top="{{scrollTop}}"
scroll-into-view="{{scrollToMessage}}"
bindscrolltoupper="onScrollToUpper"
>
<view
wx:for="{{chats}}"
wx:key="{{item._id}}"
id="item-{{index}}"
class="message {{openId == item._openid ? 'message__self' : ''}}"
>
<image
class="avatar"
src="{{item.avatar}}"
mode="scaleToFill"
></image>
<view class="main">
<view class="nickname">{{item.nickName}}</view>
<block wx:if="{{item.msgType === 'image'}}">
<view class="image-wrapper">
<view class="loading" wx:if="{{item.writeStatus > -1}}">{{item.writeStatus}}%</view>
<image
src="{{item.tempFilePath || item.imgFileID}}"
data-fileid="{{item.tempFilePath || item.imgFileID}}"
class="image-content"
style="{{item.imgStyle}}"
mode="scallToFill"
bindtap="onMessageImageTap"></image>
</view>
</block>
<block wx:else>
<view class="text-wrapper">
<view class="loading" wx:if="{{item.writeStatus === 'pending'}}">···</view>
<view class="text-content">{{item.textContent}}</view>
</view>
</block>
</view>
</view>
</scroll-view>
<!-- message sender -->
<view class="footer">
<view class="message-sender" wx:if="{{userInfo}}">
<input
class="text-input"
type="text"
confirm-type="send"
bindconfirm="onConfirmSendText"
cursor-spacing="20"
value="{{textInputValue}}"
></input>
<image
src="./photo.png"
class="btn-send-image"
mode="scaleToFill"
bindtap="onChooseImage"
></image>
</view>
<view class="message-sender" wx:if="{{!userInfo}}">
<button
open-type="getUserInfo"
bindgetuserinfo="onGetUserInfo"
class="userinfo"
>请先登录后参与聊天</button>
</view>
</view>
</view>

View File

@@ -1,161 +0,0 @@
.chatroom {
width: 100%;
height: 100%;
display: flex;
flex-direction: column;
}
.chatroom .header {
flex-basis: fit-content;
display: flex;
flex-direction: row;
border-bottom: 1px solid #ddd;
padding: 20rpx 0 30rpx;
font-size: 30rpx;
/* background: rgb(34, 187, 47);
color: rgba(255, 255, 255, 1) */
/* font-family: 'Microsoft YaHei' */
}
.chatroom .header .left {
flex: 1;
}
.chatroom .header .middle {
flex: 2;
text-align: center;
}
.chatroom .header .right {
flex: 1;
}
.chatroom .body {
flex: 2;
display: flex;
flex-direction: column;
background: rgb(237,237,237);
padding-bottom: 16rpx;
}
.body .message {
display: flex;
flex-direction: row;
position: relative;
margin: 12rpx 0;
}
.body .message.message__self {
flex-direction: row-reverse;
}
.body .message .avatar {
position: relative;
top: 5rpx;
width: 60rpx;
height: 60rpx;
border-radius: 5rpx;
margin: 15rpx;
}
.body .message .main {
flex: 1;
display: flex;
flex-direction: column;
align-items: flex-start;
}
.body .message.message__self .main {
align-items: flex-end;
}
.body .message .nickname {
font-size: 24rpx;
color: #444;
}
.body .message .text-content {
border: 1px solid transparent;
border-radius: 3px;
background-color: #fff;
margin: 2px 0 0 0;
padding: 4px 10px;
font-size: 30rpx;
display: inline-block;
}
.body .message.message__self .text-content {
background-color: paleturquoise;
}
.body .message .text-wrapper {
display: flex;
flex-direction: row;
align-items: center;
max-width: 80%;
}
.body .message.message__self .text-wrapper .loading{
font-size: 16rpx;
margin-right: 18rpx;
}
.body .message .image-wrapper {
display: flex;
flex-direction: row;
align-items: center;
}
.body .message .image-content {
max-width: 240rpx;
max-height: 240rpx;
}
.body .message.message__self .image-wrapper .loading {
font-size: 20rpx;
margin-right: 18rpx;
}
.chatroom .footer {
flex-basis: fit-content;
display: flex;
flex-direction: row;
border-top: 1px solid #ddd;
font-size: 10rpx;
padding: 20rpx 30rpx;
background: rgb(246,246,246);
}
.chatroom .footer .message-sender {
flex: 1;
display: flex;
flex-direction: row;
}
.message-sender .text-input {
flex: 1;
font-size: 16px;
border: 1px solid transparent;
border-radius: 5px;
padding: 3px 6px;
margin: 0 10px 0 5px;
background: #fff;
}
.message-sender .btn-send-image {
width: 50rpx;
height: 50rpx;
align-self: center;
}
button {
font-size: 30rpx;
}
button.userinfo {
background: darkturquoise;
color: aliceblue;
padding: 0 100rpx;
border: 1px solid #ddd;
border-radius: 20px;
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 244 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.6 KiB

View File

@@ -0,0 +1,250 @@
import WxCanvas from './wx-canvas';
import * as echarts from './echarts';
let ctx;
function compareVersion(v1, v2) {
v1 = v1.split('.')
v2 = v2.split('.')
const len = Math.max(v1.length, v2.length)
while (v1.length < len) {
v1.push('0')
}
while (v2.length < len) {
v2.push('0')
}
for (let i = 0; i < len; i++) {
const num1 = parseInt(v1[i])
const num2 = parseInt(v2[i])
if (num1 > num2) {
return 1
} else if (num1 < num2) {
return -1
}
}
return 0
}
Component({
properties: {
canvasId: {
type: String,
value: 'ec-canvas'
},
ec: {
type: Object
},
forceUseOldCanvas: {
type: Boolean,
value: false
}
},
data: {
isUseNewCanvas: false
},
ready: function () {
// Disable prograssive because drawImage doesn't support DOM as parameter
// See https://developers.weixin.qq.com/miniprogram/dev/api/canvas/CanvasContext.drawImage.html
echarts.registerPreprocessor(option => {
if (option && option.series) {
if (option.series.length > 0) {
option.series.forEach(series => {
series.progressive = 0;
});
}
else if (typeof option.series === 'object') {
option.series.progressive = 0;
}
}
});
if (!this.data.ec) {
console.warn('组件需绑定 ec 变量,例:<ec-canvas id="mychart-dom-bar" '
+ 'canvas-id="mychart-bar" ec="{{ ec }}"></ec-canvas>');
return;
}
if (!this.data.ec.lazyLoad) {
this.init();
}
},
methods: {
init: function (callback) {
const version = wx.getSystemInfoSync().SDKVersion
const canUseNewCanvas = compareVersion(version, '2.9.0') >= 0;
const forceUseOldCanvas = this.data.forceUseOldCanvas;
const isUseNewCanvas = canUseNewCanvas && !forceUseOldCanvas;
this.setData({ isUseNewCanvas });
if (forceUseOldCanvas && canUseNewCanvas) {
console.warn('开发者强制使用旧canvas,建议关闭');
}
if (isUseNewCanvas) {
// console.log('微信基础库版本大于2.9.0,开始使用<canvas type="2d"/>');
// 2.9.0 可以使用 <canvas type="2d"></canvas>
this.initByNewWay(callback);
} else {
const isValid = compareVersion(version, '1.9.91') >= 0
if (!isValid) {
console.error('微信基础库版本过低,需大于等于 1.9.91。'
+ '参见https://github.com/ecomfe/echarts-for-weixin'
+ '#%E5%BE%AE%E4%BF%A1%E7%89%88%E6%9C%AC%E8%A6%81%E6%B1%82');
return;
} else {
console.warn('建议将微信基础库调整大于等于2.9.0版本。升级后绘图将有更好性能');
this.initByOldWay(callback);
}
}
},
initByOldWay(callback) {
// 1.9.91 <= version < 2.9.0:原来的方式初始化
ctx = wx.createCanvasContext(this.data.canvasId, this);
const canvas = new WxCanvas(ctx, this.data.canvasId, false);
echarts.setCanvasCreator(() => {
return canvas;
});
// const canvasDpr = wx.getSystemInfoSync().pixelRatio // 微信旧的canvas不能传入dpr
const canvasDpr = 1
var query = wx.createSelectorQuery().in(this);
query.select('.ec-canvas').boundingClientRect(res => {
if (typeof callback === 'function') {
this.chart = callback(canvas, res.width, res.height, canvasDpr);
}
else if (this.data.ec && typeof this.data.ec.onInit === 'function') {
this.chart = this.data.ec.onInit(canvas, res.width, res.height, canvasDpr);
}
else {
this.triggerEvent('init', {
canvas: canvas,
width: res.width,
height: res.height,
canvasDpr: canvasDpr // 增加了dpr可方便外面echarts.init
});
}
}).exec();
},
initByNewWay(callback) {
// version >= 2.9.0:使用新的方式初始化
const query = wx.createSelectorQuery().in(this)
query
.select('.ec-canvas')
.fields({ node: true, size: true })
.exec(res => {
const canvasNode = res[0].node
this.canvasNode = canvasNode
const canvasDpr = wx.getSystemInfoSync().pixelRatio
const canvasWidth = res[0].width
const canvasHeight = res[0].height
const ctx = canvasNode.getContext('2d')
const canvas = new WxCanvas(ctx, this.data.canvasId, true, canvasNode)
echarts.setCanvasCreator(() => {
return canvas
})
if (typeof callback === 'function') {
this.chart = callback(canvas, canvasWidth, canvasHeight, canvasDpr)
} else if (this.data.ec && typeof this.data.ec.onInit === 'function') {
this.chart = this.data.ec.onInit(canvas, canvasWidth, canvasHeight, canvasDpr)
} else {
this.triggerEvent('init', {
canvas: canvas,
width: canvasWidth,
height: canvasHeight,
dpr: canvasDpr
})
}
})
},
canvasToTempFilePath(opt) {
if (this.data.isUseNewCanvas) {
// 新版
const query = wx.createSelectorQuery().in(this)
query
.select('.ec-canvas')
.fields({ node: true, size: true })
.exec(res => {
const canvasNode = res[0].node
opt.canvas = canvasNode
wx.canvasToTempFilePath(opt)
})
} else {
// 旧的
if (!opt.canvasId) {
opt.canvasId = this.data.canvasId;
}
ctx.draw(true, () => {
wx.canvasToTempFilePath(opt, this);
});
}
},
touchStart(e) {
if (this.chart && e.touches.length > 0) {
var touch = e.touches[0];
var handler = this.chart.getZr().handler;
handler.dispatch('mousedown', {
zrX: touch.x,
zrY: touch.y
});
handler.dispatch('mousemove', {
zrX: touch.x,
zrY: touch.y
});
handler.processGesture(wrapTouch(e), 'start');
}
},
touchMove(e) {
if (this.chart && e.touches.length > 0) {
var touch = e.touches[0];
var handler = this.chart.getZr().handler;
handler.dispatch('mousemove', {
zrX: touch.x,
zrY: touch.y
});
handler.processGesture(wrapTouch(e), 'change');
}
},
touchEnd(e) {
if (this.chart) {
const touch = e.changedTouches ? e.changedTouches[0] : {};
var handler = this.chart.getZr().handler;
handler.dispatch('mouseup', {
zrX: touch.x,
zrY: touch.y
});
handler.dispatch('click', {
zrX: touch.x,
zrY: touch.y
});
handler.processGesture(wrapTouch(e), 'end');
}
}
}
});
function wrapTouch(event) {
for (let i = 0; i < event.touches.length; ++i) {
const touch = event.touches[i];
touch.offsetX = touch.x;
touch.offsetY = touch.y;
}
return event;
}

View File

@@ -0,0 +1,4 @@
<!-- 新的接口对其了H5 -->
<canvas wx:if="{{isUseNewCanvas}}" type="2d" class="ec-canvas" canvas-id="{{ canvasId }}" bindinit="init" bindtouchstart="{{ ec.disableTouch ? '' : 'touchStart' }}" bindtouchmove="{{ ec.disableTouch ? '' : 'touchMove' }}" bindtouchend="{{ ec.disableTouch ? '' : 'touchEnd' }}"></canvas>
<!-- 旧的 -->
<canvas wx:else class="ec-canvas" canvas-id="{{ canvasId }}" bindinit="init" bindtouchstart="{{ ec.disableTouch ? '' : 'touchStart' }}" bindtouchmove="{{ ec.disableTouch ? '' : 'touchMove' }}" bindtouchend="{{ ec.disableTouch ? '' : 'touchEnd' }}"></canvas>

View File

@@ -0,0 +1,4 @@
.ec-canvas {
width: 100%;
height: 100%;
}

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,121 @@
export default class WxCanvas {
constructor(ctx, canvasId, isNew, canvasNode) {
this.ctx = ctx;
this.canvasId = canvasId;
this.chart = null;
this.isNew = isNew
if (isNew) {
this.canvasNode = canvasNode;
}
else {
this._initStyle(ctx);
}
// this._initCanvas(zrender, ctx);
this._initEvent();
}
getContext(contextType) {
if (contextType === '2d') {
return this.ctx;
}
}
// canvasToTempFilePath(opt) {
// if (!opt.canvasId) {
// opt.canvasId = this.canvasId;
// }
// return wx.canvasToTempFilePath(opt, this);
// }
setChart(chart) {
this.chart = chart;
}
attachEvent() {
// noop
}
detachEvent() {
// noop
}
_initCanvas(zrender, ctx) {
zrender.util.getContext = function () {
return ctx;
};
zrender.util.$override('measureText', function (text, font) {
ctx.font = font || '12px sans-serif';
return ctx.measureText(text);
});
}
_initStyle(ctx) {
var styles = ['fillStyle', 'strokeStyle', 'globalAlpha',
'textAlign', 'textBaseAlign', 'shadow', 'lineWidth',
'lineCap', 'lineJoin', 'lineDash', 'miterLimit', 'fontSize'];
styles.forEach(style => {
Object.defineProperty(ctx, style, {
set: value => {
if (style !== 'fillStyle' && style !== 'strokeStyle'
|| value !== 'none' && value !== null
) {
ctx['set' + style.charAt(0).toUpperCase() + style.slice(1)](value);
}
}
});
});
ctx.createRadialGradient = () => {
return ctx.createCircularGradient(arguments);
};
}
_initEvent() {
this.event = {};
const eventNames = [{
wxName: 'touchStart',
ecName: 'mousedown'
}, {
wxName: 'touchMove',
ecName: 'mousemove'
}, {
wxName: 'touchEnd',
ecName: 'mouseup'
}, {
wxName: 'touchEnd',
ecName: 'click'
}];
eventNames.forEach(name => {
this.event[name.wxName] = e => {
const touch = e.touches[0];
this.chart.getZr().handler.dispatch(name.ecName, {
zrX: name.wxName === 'tap' ? touch.clientX : touch.x,
zrY: name.wxName === 'tap' ? touch.clientY : touch.y
});
};
});
}
set width(w) {
if (this.canvasNode) this.canvasNode.width = w
}
set height(h) {
if (this.canvasNode) this.canvasNode.height = h
}
get width() {
if (this.canvasNode)
return this.canvasNode.width
return 0
}
get height() {
if (this.canvasNode)
return this.canvasNode.height
return 0
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 48 KiB

View File

@@ -0,0 +1,124 @@
// miniprogram/pages/deviceControl/PM2.5/index.js
import * as echarts from '../../ec-canvas/echarts';
function initChart(canvas, width, height, dpr) {
const chart = echarts.init(canvas, null, {
width: width,
height: height,
devicePixelRatio: dpr // 像素
});
canvas.setChart(chart);
var option = {
title:{ text:'污染物浓度趋势',bottom:15,left:'33%' },
xAxis:{ maxInterval: 3600 * 1000, data:['8:00','9:00','10:00','11:00','12:00','13:00'],nameTextStyle:{
color:'#fff'
} },
yAxis:{ type:'value',name:'μg/m³',max:50, min:0 ,show:true ,splitNumber:5 },
legend:{
data:['PM2.5','PM10','PM1.0'],
z:100
},
legend:{ textStyle:{ color:'#fff' } },
textStyle:{ color:'#fff' },
series:[
{ type:'bar',name:'PM2.5', smooth:true, data: [27, 22, 25, 31, 32, 26] },
{ type:'line',name:'PM10', smooth:true, data: [28, 27, 28, 30, 28, 28] },
{ type:'line',name:'PM1.0', smooth:true, data: [22, 24, 22, 23, 22, 24] }
],
axisPointer:{ show:true,type:'line',snap:true }
};
chart.setOption(option);
return chart;
};
Page({
/**
* 页面的初始数据
*/
data: {
deviceInfo:{},
deviceData:[],
ec: {
onInit:initChart
}
},
/**
* 生命周期函数--监听页面加载
*/
onLoad: function (options) {
// this.getServerData();
// this.getLastPageData();
// this.getDeviceAttribute();
wx.setNavigationBarTitle({
title: 'PM2.5监测',
})
},
//获取上一页的数据
getLastPageData(){
const that = this;
const eventChannel = this.getOpenerEventChannel();
eventChannel.on('getDeviceInfo',(data)=>{
wx.setNavigationBarTitle({
title: data.product_name
});
that.setData({ deviceInfo:data })
})
},
//获取设备属性数据
/**
* 生命周期函数--监听页面初次渲染完成
*/
onReady: function () {
},
/**
* 生命周期函数--监听页面显示
*/
onShow: function () {
},
/**
* 生命周期函数--监听页面隐藏
*/
onHide: function () {
},
/**
* 生命周期函数--监听页面卸载
*/
onUnload: function () {
},
/**
* 页面相关事件处理函数--监听用户下拉动作
*/
onPullDownRefresh: function () {
},
/**
* 页面上拉触底事件的处理函数
*/
onReachBottom: function () {
},
/**
* 用户点击右上角分享
*/
onShareAppMessage: function () {
}
})

View File

@@ -0,0 +1,7 @@
{
"usingComponents": {
"van-circle": "@vant/weapp/circle/index",
"ec-canvas": "../../ec-canvas/ec-canvas"
},
"disableScroll": true
}

View File

@@ -0,0 +1,64 @@
<!--miniprogram/pages/deviceControl/PM2.5/index.wxml-->
<view class='body'>
<!-- <view class='time'>
2021-05-31 13:27
</view> -->
<view class='outroom'>室外空气:良</view>
<view class='airInfo'>
<van-circle
value="26"
layer-color="#fff"
color="lightgreen"
size='280'
stroke-width='10'
>
<slots>
<view class='title'>PM2.5</view>
<view>
<text class='num'>26</text>
<text class='unit'>μg/m³</text>
</view>
<view class='degree'>室内:<text style='color:lightgreen'>优</text></view>
</slots>
</van-circle>
</view>
<view class='small_info'>
<!-- <view class='city'>
<image src='/icon/address.png' />
<text>南京</text>
</view> -->
<view class='particle'>
<text class='name' decode>PM10 :&nbsp;</text>
<text class='index'>32</text>
<text class='explain' style='color:lightgreen' >优</text>
</view>
<view class='particle'>
<text class='name' decode>PM1.0 :&nbsp;</text>
<text class='index'>21</text>
<text class='explain' style='color:lightgreen'>优</text>
</view>
<!-- <view class='updateTime'>今日 11:55 发布</view> -->
</view>
<!-- <view class='others'>
<van-circle
value="{{ value }}"
layer-color="#eeeeee"
color="#ee0a24"
text="PM10"
size='125'
/>
<van-circle
value="{{ value }}"
layer-color="#eeeeee"
color="#ee0a24"
text="PM1.0"
size='125'
/>
</view> -->
<view class='bg'></view>
<view class="container">
<ec-canvas id="mychart-dom-bar" canvas-id="mychart-bar" ec="{{ ec }}"></ec-canvas>
</view>
</view>

View File

@@ -0,0 +1,124 @@
/* miniprogram/pages/deviceControl/PM2.5/index.wxss */
.bg{
position:fixed;
top:0;
left:0;
width:100vw;
height:100vh;
background-image:linear-gradient(120deg, gray , deepskyblue);
z-index:-99;
}
.body{
width:100vw;
height:100vh;
color:#fff;
overflow-x:hidden;
}
.outroom{
display:block;
width:100%;
height:80rpx;
padding: 0 30rpx;
line-height:80rpx;
}
/* .time{
display:block;
width:100%;
height:80rpx;
text-align:center;
line-height:80rpx;
margin:70rpx 0;
} */
.airInfo{
display:flex;
flex-direction:column;
justify-content:center;
align-items:center;
/* margin-top:70rpx; */
}
.airInfo .title{
display:block;
width:100%;
height:80rpx;
/* padding-bottom:40rpx; */
text-align:center;
line-height:80rpx;
font-size:70rpx;
}
slots{
color:#fff;
display:flex;
flex-direction:column;
justify-content:center;
}
slots .num{
font-size:160rpx
}
.degree{
display:block;
/* width:300rpx; */
height:90rpx;
color:yellow;
text-align:center;
line-height:90rpx;
font-size:40rpx;
padding:15rpx 0;
}
.small_info{
/* padding:15rpx 35rpx; */
display:flex;
justify-content:space-around;
border-bottom:2rpx solid #fff;
}
/* .city{
display:flex;
align-items:center;
margin:15rpx 0;
}
.city image{
width:45rpx;
height:45rpx;
}
.city>text{
display:block;
height:45rpx;
line-height:45rpx;
text-align:center;
padding:0 15rpx;
} */
.particle{
margin:30rpx 0;
padding:10rpx 0;
width:45%;
height:60rpx;
border:2rpx solid #ffffff;
text-align:center;
line-height:60rpx;
border-radius:50rpx;
font-size:32rpx;
}
.particle .name{
display:inline-block;
/* width:135rpx; */
}
.particle .index{
display:inline-block;
width:60rpx;
}
/* .updateTime{
margin:10rpx 0;
} */
/* .others{
display:flex;
justify-content:space-around;
} */
.container{
width: 100vw;
height: 450rpx;
}
#mychart-dom-bar{
width: 100vw;
height: 450rpx;
}

View File

@@ -0,0 +1,80 @@
// miniprogram/components/aboutUs/index.js
Page({
/**
* 页面的初始数据
*/
data: {
info:{}
},
/**
* 生命周期函数--监听页面加载
*/
onLoad: function (options) {
this.getLastPageData();
},
getLastPageData(){
const eventChannel = this.getOpenerEventChannel();
eventChannel.on('getInfo',(res)=>{
this.setData({
info:res
});
wx.setNavigationBarTitle({
title: res.name,
})
})
},
/**
* 生命周期函数--监听页面初次渲染完成
*/
onReady: function () {
},
/**
* 生命周期函数--监听页面显示
*/
onShow: function () {
},
/**
* 生命周期函数--监听页面隐藏
*/
onHide: function () {
},
/**
* 生命周期函数--监听页面卸载
*/
onUnload: function () {
},
/**
* 页面相关事件处理函数--监听用户下拉动作
*/
onPullDownRefresh: function () {
},
/**
* 页面上拉触底事件的处理函数
*/
onReachBottom: function () {
},
/**
* 用户点击右上角分享
*/
onShareAppMessage: function () {
}
})

View File

@@ -0,0 +1,3 @@
{
"usingComponents": {}
}

View File

@@ -0,0 +1,35 @@
<!--miniprogram/components/aboutUs/index.wxml-->
<!-- <view class="name">小驿物联</view> -->
<view class="card" wx:if="{{ info.flag==='info' }}">
<view class="title">机构简介</view>
<view class="content">
<text>
南京小驿物联科技技术有限公司专注做开源智能硬件,为用户提供完整的基于微信小程序的物联网解决方案,用户可以在开源产品基础上定制自己产品,快速提高用户开发智能硬件产品效率,我们的使命是加速更多物联网创意产品的起航,让技术不再是阻碍!
</text>
</view>
</view>
<view class="card" wx:if="{{ info.flag==='join' }}">
<view class="title">加入我们</view>
<view class="content">
<text>
网络已深刻改变着人们的生活,本地化生活服务市场前景巨大,生活半径团队坚信本地化生活服务与互联网的结合将会成就一家梦幻的公司,我们脚踏实地的相信梦想,我们相信你的加入会让生活半径更可能成为那家梦幻公司!生活半径人有梦想,有魄力,强执行力,但是要实现这个伟大的梦想,需要更多的有创业精神的你一路前行。公司将提供有竞争力的薪酬、完善的福利(五险一金)、期权、广阔的上升空间。只要你有能力、有激情、有梦想,愿意付出,愿意与公司共同成长,请加入我们!
</text>
<text>
请发送您的简历到libo@xiaoyiiot.com我们会在第一时间联系您
</text>
</view>
</view>
<view class="card" wx:if="{{ info.flag==='address' }}">
<view class="title">联系方式</view>
<view class="content">
<text>
地址南京市建邺区建邺区平良大街89号韶华工坊
</text>
<text>
邮编210019
</text>
<text>
电话14751686604
</text>
</view>
</view>

View File

@@ -0,0 +1,19 @@
/* miniprogram/components/aboutUs/index.wxss */
/* .name{
font-size: 42rpx;
text-align: center;
margin: 15rpx auto;
} */
.card{
margin: 30rpx auto;
width: 80vw;
padding: 30rpx;
box-shadow: 5rpx 5rpx 5rpx #666;
background-color: #ffffff;
}
.title{
width: 50%;
font-size: 38rpx;
padding: 15rpx 0;
border-bottom: 2rpx solid #bfbfbf;
}

View File

@@ -12,7 +12,9 @@ Page({
data: {
weather:{}, //天气信息
products:[],
DeviceList:[],
DeviceList:[],
onlineList:[],
unlineList:[],
fourGDeviceList:[],
show: false,
actions: [
@@ -32,16 +34,29 @@ Page({
// }, 2000);
},
//获取设备列表
async getDevices(){
const res = await requestApi('/system/device/list');
console.log(res);
this.setData({ DeviceList:res.data.rows })
const res = await requestApi('/system/device/list',{ method:'GET' });
console.log(res);
const result = JSON.parse(res.result);
let onlineList = [];
let unlineList = [];
result.rows.forEach(v=>{
if (v.isOnline == 1) {
onlineList.push(v)
} else if (v.isOnline == 0) {
unlineList.push(v);
}
})
this.setData({
onlineList,
unlineList,
DeviceList:result.rows
})
},
//获取天气
getWeather:async function(){
let that = this;
@@ -61,15 +76,28 @@ Page({
},
goToDeviceControl(e){
if (e.currentTarget.dataset.info.categoryId !== 5) {
return;
}
wx.navigateTo({
url: '/pages/roomSystem/index',
success:(res)=>{
res.eventChannel.emit('getDeviceInfo',e.currentTarget.dataset.info)
}
})
switch (e.currentTarget.dataset.info.categoryId) {
case 4:
if (e.currentTarget.dataset.info.deviceNum === 'E8DB84933081') {
wx.navigateTo({
url: '/pages/someData/index',
success:(res)=>{
res.eventChannel.emit('getDeviceInfo',e.currentTarget.dataset.info)
}
})
}
break;
case 5:
wx.navigateTo({
url: '/pages/roomSystem/index',
success:(res)=>{
res.eventChannel.emit('getDeviceInfo',e.currentTarget.dataset.info)
}
})
break;
}
},
deviceFail(){

View File

@@ -24,11 +24,11 @@
<view class='devices'>
<view class='devices_tab'>全部 ({{ DeviceList.length }})</view>
<van-tabs swipeable animated>
<van-tab title="WiFi设备({{ DeviceList.length }})">
<van-tab title="在线设备({{ onlineList.length }})">
<scroll-view scroll-y>
<view class="devices_list">
<block wx:if="{{ DeviceList.length !== 0 }}">
<view wx:for='{{ DeviceList }}' wx:key='index' class='border'>
<block wx:if="{{ onlineList.length !== 0 }}">
<view wx:for='{{ onlineList }}' wx:key='index' class='border'>
<block wx:if="{{ item.isOnline === 2 }}">
<view class='devices_item' style="background-color:rgba(0,0,0,.05)" bindtap='deviceNone' data-info='{{item}}'>
<view class="info">
@@ -73,62 +73,62 @@
</block>
</view>
</block>
<block wx:elif='{{ DeviceList.length === 0 }}'>
<block wx:elif='{{ onlineList.length === 0 }}'>
<view class='noDevice'> 暂无设备,请添加。 </view>
</block>
</view>
</scroll-view>
</van-tab>
<van-tab title="4G设备({{ fourGDeviceList.length }})">
<van-tab title="离线设备({{ unlineList.length }})">
<scroll-view scroll-y>
<view class="devices_list">
<block wx:if="{{ fourGDeviceList.length !== 0 }}">
<view wx:for='{{ fourGDeviceList }}' wx:key='index' class='border'>
<block wx:if="{{ item.status === 1 }}">
<block wx:if="{{ unlineList.length !== 0 }}">
<view wx:for='{{ unlineList }}' wx:key='index' class='border'>
<block wx:if="{{ item.isOnline === 2 }}">
<view class='devices_item' style="background-color:rgba(0,0,0,.05)" bindtap='deviceNone' data-info='{{item}}'>
<view class="info">
<view class='img'>
<image src='/icons/device.jpg' />
<image src='/images/room.jpeg' />
</view>
<view class="_right">
<view style="color:#bfbfbf" class="status">未激活</view>
<view style="font-size:24rpx;color:#666">{{ item.device_name }}</view>
<view style="font-size:24rpx;color:#666">{{ item.categoryName }}</view>
</view>
</view>
<view class='name'>{{ item.product_name }}</view>
<view class='name'>{{ item.deviceName }}</view>
</view>
</block>
<block wx:if="{{ item.status === 2 }}">
<block wx:if="{{ item.isOnline === 1 }}">
<view class='devices_item' bindtap='goToDeviceControl' data-info='{{item}}'>
<view class="info">
<view class='img'>
<image src='/icons/device.jpg' />
<image src='/images/room.jpeg' />
</view>
<view class="_right">
<view style="color:green" class="status">在线</view>
<view style="font-size:24rpx;color:#666">{{ item.device_name }}</view>
<view style="font-size:24rpx;color:#666">{{ item.categoryName }}</view>
</view>
</view>
<view class='name'>{{ item.product_name }}</view>
<view class='name'>{{ item.deviceName }}</view>
</view>
</block>
<block wx:if="{{ item.status === 3 }}">
<block wx:if="{{ item.isOnline === 0 }}">
<view style="background-color:rgba(0,0,0,.05)" class='devices_item' bindtap='deviceFail' data-info='{{item}}'>
<view class="info">
<view class='img'>
<image src='/icons/device.jpg' />
<image src='/images/room.jpeg' />
</view>
<view class="_right">
<view style="color:#ff0000" class="status">离线</view>
<view style="font-size:24rpx;color:#666">{{ item.device_name }}</view>
<view style="font-size:24rpx;color:#666">{{ item.categoryName }}</view>
</view>
</view>
<view class='name'>{{ item.product_name }}</view>
<view class='name'>{{ item.deviceName }}</view>
</view>
</block>
</view>
</block>
<block wx:elif='{{ fourGDeviceList.length === 0 }}'>
<block wx:elif='{{ unlineList.length === 0 }}'>
<view class='noDevice'> 暂无设备,请添加。 </view>
</block>
</view>

View File

@@ -23,32 +23,40 @@ Page({
//获取验证码图片和uuid
async getCaptchaImage(){
const res = await loginApi('/captchaImage',{ method:'GET' });
const res = await loginApi('/captchaImage',{ method:'get' });
const data = JSON.parse(res.result)
this.setData({
img:res.data.img,
uuid:res.data.uuid
img:data.img,
uuid:data.uuid
})
},
//登录
async submit(){
const res = await loginApi('/login',{
wx.showLoading({
title: '正在登录',
})
const res = await loginApi('/login',{
method:'POST',
data:{
body:{
code:this.data.value,
uuid:this.data.uuid,
password: this.data.password,
username: this.data.username
},
json:true
})
if (res.data.code !== 200) {
wx.hideLoading();
if (res.result.code !== 200) {
wx.showToast({
title: '登录失败',
title: res.result.msg,
icon:'error'
});
this.getCaptchaImage();
return;
}
wx.setStorageSync('token', res.data.token);
wx.setStorageSync('token', res.result.token);
wx.switchTab({
url: '/pages/index/index',
})

View File

@@ -1,5 +1,8 @@
<!--miniprogram/pages/index/index.wxml-->
<view class="title">欢迎登录智慧宿舍系统</view>
<view class="top">
<image src="/images/smart.jpg" />
</view>
<view class="title">欢迎登录</view>
<view class="form">
<view class="input">
<van-field

View File

@@ -1,10 +1,13 @@
/* miniprogram/pages/index/index.wxss */
.top{
margin: 120rpx auto 0;
}
.title{
display: block;
width: 80vw;
margin: 60rpx auto;
font-size: 40rpx;
margin-top: 35%;
/* margin-top: 35%; */
}
.form{
width: 80vw;

View File

@@ -3,17 +3,43 @@ var app = getApp();
Page({
data: {
userInfo: {},
mode: ['信息反馈', '联系客服', '关于我们']
mode: [
{ flag:'info',name:'关于我们' },
{ flag:'join',name:'加入我们' },
{ flag:'address',name:'联系方式' }
]
},
onLoad: function () {
},
getOut(){
wx.clearStorage({
wx.showModal({
cancelColor: '#ff0000',
cancelText: '取消',
confirmText: '确定',
content: '您确定要退出吗?',
showCancel: true,
success: (res) => {
wx.reLaunch({
url: '/pages/login/index',
})
if(res.confirm){
wx.clearStorage({
success: (res) => {
wx.reLaunch({
url: '/pages/login/index',
})
},
})
}
},
})
}
},
aboutus(e){
wx.navigateTo({
url: '/pages/aboutUs/index',
success(res){
res.eventChannel.emit('getInfo',e.currentTarget.dataset.data)
}
})
},
})

View File

@@ -8,9 +8,9 @@
</view>
</view>
<view class="wode_item_wrap">
<view class="wode_item" wx:for="{{mode}}">
{{item}}
<span class="arrow_wrap"></span>
<view class="wode_item" wx:for="{{mode}}" bindtap="aboutus" data-data='{{ item }}'>
{{item.name}}
<span class="arrow_wrap">></span>
</view>
</view>
<view class="wode_out" bindtap="getOut">退出</view>

View File

@@ -1,6 +1,6 @@
.personal_info {
padding: 20px 0;
background-color: #FFF;
background-color: skyblue;
}
.photo_wrap {
overflow:hidden;

View File

@@ -0,0 +1,91 @@
// miniprogram/pages/someData/index.js
const { requestApi } = require('../../API/request.js');
let timer = null;
Page({
/**
* 页面的初始数据
*/
data: {
deviceInfo:{},
deviceData:{}
},
/**
* 生命周期函数--监听页面加载
*/
onLoad: function (options) {
wx.setNavigationBarTitle({
title: '环境监测'
})
this.getLastPageData();
this.getData();
timer = setInterval(() => {
this.getData();
}, 1000);
},
async getData(){
let that = this;
const res = await requestApi(`/system/status/newByNum/${this.data.deviceInfo.deviceNum}`,{ method:'GET' });
const data = JSON.parse(res.result);
data.data.remark = JSON.parse(data.data.remark)
this.setData({ deviceData:data.data })
},
getLastPageData(){
const eventChannel = this.getOpenerEventChannel();
eventChannel.on('getDeviceInfo',(data)=>{
this.setData({ deviceInfo:data })
})
},
/**
* 生命周期函数--监听页面初次渲染完成
*/
onReady: function () {
},
/**
* 生命周期函数--监听页面显示
*/
onShow: function () {
},
/**
* 生命周期函数--监听页面隐藏
*/
onHide: function () {
},
/**
* 生命周期函数--监听页面卸载
*/
onUnload: function () {
clearInterval(timer);
},
/**
* 页面相关事件处理函数--监听用户下拉动作
*/
onPullDownRefresh: function () {
},
/**
* 页面上拉触底事件的处理函数
*/
onReachBottom: function () {
},
/**
* 用户点击右上角分享
*/
onShareAppMessage: function () {
}
})

View File

@@ -0,0 +1,5 @@
{
"usingComponents": {
"van-divider": "@vant/weapp/divider/index"
}
}

View File

@@ -0,0 +1,112 @@
<!--miniprogram/pages/someData/index.wxml-->
<div class="bg"></div>
<div class="wave-box">
<div class="wave-cover" style="top:{{100 - deviceData.airTemperature }}%">
<div class="a"></div>
<div class="b"></div>
</div>
<div class="slot">
<div class="temp">
<div class="temp-title">
<image class="big-icon" src="/icons/temp.png" />
<text style="font-size:42rpx">空气温度</text>
</div>
<div class="value">
<text style="font-size:86rpx">{{ deviceData.airTemperature }}</text>
<text>℃</text>
</div>
</div>
<div class="hr"></div>
<div class="humi">
<div class="humi-title">
<image class="sm-icon" src="/icons/humi.png" />
<text style="font-size:32rpx">空气湿度:</text>
</div>
<div class="value">
<text style="font-size:46rpx">{{ deviceData.airHumidity }}</text>
<text>%</text>
</div>
</div>
</div>
</div>
<!-- <div class="info-card">
<div class="card-title">其他数据</div>
<div class="card-body">
<div class="card-item">
<div class="item-name">
<image class="mid-icon" src="/icons/redline.png" />
<text class="item-title">人体红外:</text>
<text wx:if="{{ deviceData.remark.isHuman === 1}}" style="color:green">检测到人体</text>
<text wx:if="{{ deviceData.remark.isHuman === 0}}" style="color:red">未检测到人体</text>
</div>
</div>
<div class="card-item">
<div class="item-name">
<image class="mid-icon" src="/icons/device_temp.png" />
<text class="item-title">设备温度:</text>
<text>{{ deviceData.deviceTemperature||'--' }}</text>
<text>℃</text>
</div>
</div>
<div class="card-item">
<div class="item-name">
<image class="mid-icon" src="/icons/qiya.png" />
<text class="item-title">气压:</text>
<text>{{ deviceData.remark.pressure||'--' }}</text>
<text>Pa</text>
</div>
</div>
<van-divider contentPosition="center" dashed>加速度</van-divider>
<div class="card-item">
<div class="item-name">
<image class="mid-icon" src="/icons/jiasudu.png" />
<text class="item-title">加速度</text>
</div>
<div class="jiasudu">
<div class="jiasudu-item"><div class="point"></div> x方向{{ deviceData.remark.acc_x || '--' }} m/s²</div>
<div class="jiasudu-item"><div class="point"></div> y方向{{ deviceData.remark.acc_y || '--' }} m/s²</div>
<div class="jiasudu-item"><div class="point"></div> z方向{{ deviceData.remark.acc_z ||'--' }} m/s²</div>
</div>
</div>
</div>
</div> -->
<div class="data_one">
<div class="data-item">
<div class="item-name">
<image class="mid-icon" src="/icons/device_temp.png" />
<text class="item-title">设备温度:</text>
<text>{{ deviceData.deviceTemperature||'--' }}</text>
<text>℃</text>
</div>
</div>
<div class="data-item">
<div class="item-name">
<image class="mid-icon" src="/icons/qiya.png" />
<text class="item-title">气压:</text>
<text>{{ deviceData.remark.pressure||'--' }}</text>
<text>Pa</text>
</div>
</div>
<div class="data-item long">
<div class="item-name l">
<image class="mid-icon" src="/icons/redline.png" />
<text class="item-title">人体红外:</text>
<text wx:if="{{ deviceData.remark.isHuman === 1}}" style="color:green">检测到人体</text>
<text wx:if="{{ deviceData.remark.isHuman === 0}}" style="color:red">未检测到人体</text>
</div>
</div>
</div>
<div class="h">
<van-divider contentPosition="center" dashed>加速度</van-divider>
</div>
<div class="data_two">
<div class="data">
<image class="mid-icon" src="/icons/jiasudu.png" />
<text class="item-title">加速度</text>
</div>
<div class="jiasudu">
<div class="jiasudu-item"><div class="point"></div> X 方向:{{ deviceData.remark.acc_x || '--' }} m/s²</div>
<div class="jiasudu-item"><div class="point"></div> Y 方向:{{ deviceData.remark.acc_y || '--' }} m/s²</div>
<div class="jiasudu-item"><div class="point"></div> Z 方向:{{ deviceData.remark.acc_z ||'--' }} m/s²</div>
</div>
</div>

View File

@@ -0,0 +1,210 @@
/* miniprogram/pages/someData/index.wxss */
page{
color: #ffffff;
}
.wave-box{
width: 500rpx;
height: 500rpx;
border-radius: 50%;
box-shadow: 0 0 10rpx 5rpx #31f1ff;
margin: 20rpx auto;
position: relative;
z-index: 99;
overflow: hidden;
/* background-color: rgb(197, 253, 236); */
background-image:linear-gradient(120deg, gray , deepskyblue);
}
.wave-cover{
width: 250%;
height: 250%;
position: absolute;
left: -60%;
top:100%;
}
.wave-cover .a{
width: 100%;
height: 100%;
background-color: #85f7fb;
position: absolute;
z-index: 11;
border-radius: 47% 49% 63% 60% / 60% 48%;
animation: wave 8s linear infinite;
}
.wave-cover .b{
width: 95%;
height: 95%;
background-color: #d0f4ff;
position: absolute;
z-index: 10;
border-radius: 42% 58% 43% 60% / 48% 35%;
animation: wave 7s linear infinite;
}
.slot{
width: 100%;
position: absolute;
top: 50%;
transform: translateY(-50%);
z-index: 99;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
}
.big-icon{
width: 88rpx;
height: 88rpx;
}
.temp,.humi{
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
}
.temp-title,.humi-title{
display: flex;
align-items: center;
}
.hr{
width: 60%;
height: 1rpx;
background-color: #fff0f0;
margin: 15rpx auto;
}
.sm-icon{
width: 44rpx;
height: 44rpx;
}
.humi{
/* color: #666; */
}
@keyframes wave{
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}
/* .info-card{
margin: 0 auto;
width: 70vw;
padding: 100rpx 15rpx 30rpx;
border-radius: 25rpx;
box-shadow: 0 0 10rpx 5rpx #ffffff;
transform: translateY(-100rpx);
background-image:linear-gradient(-120deg, skyblue , gray);
} */
.mid-icon{
width: 66rpx;
height: 66rpx;
margin-right: 10rpx;
}
/* .card-title{
font-size: 42rpx;
display: block;
width: 60%;
margin: 0 auto;
text-align: center;
border-bottom: #bfbfbf 1rpx solid;
padding-bottom: 10rpx;
}
.card-body{
display: flex;
flex-direction: column;
padding: 30rpx 60rpx;
}
.card-item{
margin: 5rpx 0;
padding: 10rpx 0;
} */
.data-item{
width: 50vw;
display: flex;
justify-content: center;
}
.item-name{
display: flex;
align-items: center;
padding:10rpx 15rpx;
width: 80%;
box-shadow: 3rpx 3rpx 5rpx #eee;
border-radius:10rpx ;
margin: 15rpx 0;
/* background-color: skyblue; */
background-color: rgb(87, 181, 204);
}
.long{
width: 100vw;
}
.l{
width: 90%;
}
.item-title{
font-size: 32rpx;
}
.bg{
width: 100vw;
height: 100vh;
position: fixed;
top: 0;
left: 0;
z-index: -1;
/* background-image: linear-gradient(120deg,rgb(119, 217, 255),#eee); */
background-image:linear-gradient(to bottom, #dbdbdb , rgb(94, 214, 253));
}
.jiasudu{
display: flex;
flex-direction: column;
background-color: rgb(87, 181, 204);
border-radius: 0 15rpx 15rpx 15rpx;
padding: 30rpx;
box-shadow: 3rpx 3rpx 3rpx #eee;
}
.jiasudu-item{
margin: 10rpx;
display: block;
padding: 5rpx;
/* color: rgb(85, 85, 85); */
}
.point{
display: inline-block;
width: 15rpx;
height: 15rpx;
border-radius: 50%;
background-color: #85f7fb;
margin-right: 10rpx;
}
.data_one{
width: 100vw;
/* padding: 30rpx; */
display: flex;
flex-wrap: wrap;
}
.h{
width: 90%;
margin: 0 auto;
}
.van-divider{
color: #ffffff !important;
}
.data_two{
width: 90%;
margin: 0 auto;
}
.data{
width: 50%;
display: flex;
align-items: center;
padding:10rpx 15rpx;
border-bottom: 2rpx solid #eee;
background-color: rgb(87, 181, 204);
border-radius:15rpx 15rpx 0 0;
box-shadow: 3rpx 3rpx 3rpx #eee;
}