feat:新增登录验证
This commit is contained in:
@ -7,68 +7,68 @@
|
|||||||
|
|
||||||
<!-- 内容区域 -->
|
<!-- 内容区域 -->
|
||||||
<view class="tabbar-content">
|
<view class="tabbar-content">
|
||||||
<!-- 环境参数详情 -->
|
<!-- 环境参数详情 -->
|
||||||
<view class="parameter-details">
|
<view class="parameter-details">
|
||||||
<!-- 温度卡片 -->
|
<!-- 温度卡片 -->
|
||||||
<view class="detail-card temperature-detail-card">
|
<view class="detail-card temperature-detail-card" @click="navigateToParameterRecord">
|
||||||
<view class="detail-header">
|
<view class="detail-header">
|
||||||
<view class="detail-icon-container">
|
<view class="detail-icon-container">
|
||||||
<view class="detail-icon temperature-icon">🌡️</view>
|
<view class="detail-icon temperature-icon">🌡️</view>
|
||||||
<text class="detail-label">温度</text>
|
<text class="detail-label">温度</text>
|
||||||
</view>
|
|
||||||
<view class="detail-value-container">
|
|
||||||
<text class="detail-value">{{ temperature }}°C</text>
|
|
||||||
<view class="detail-status" :class="temperature > 0 ? 'active' : 'inactive'"></view>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
<view class="detail-progress-bar">
|
|
||||||
<view class="detail-progress-fill temperature-progress" :style="{ width: temperatureProgress + '%' }"></view>
|
|
||||||
</view>
|
|
||||||
<!-- <view class="detail-range">
|
|
||||||
<text class="detail-range-text">{{ 0 }}°C - {{ 100 }}°C</text>
|
|
||||||
</view> -->
|
|
||||||
</view>
|
</view>
|
||||||
|
<view class="detail-value-container">
|
||||||
<!-- 湿度卡片 -->
|
<text class="detail-value">{{ temperature }}°C</text>
|
||||||
<view class="detail-card humidity-detail-card">
|
<view class="detail-status" :class="temperature > 0 ? 'active' : 'inactive'"></view>
|
||||||
<view class="detail-header">
|
|
||||||
<view class="detail-icon-container">
|
|
||||||
<view class="detail-icon humidity-icon">💧</view>
|
|
||||||
<text class="detail-label">湿度</text>
|
|
||||||
</view>
|
|
||||||
<view class="detail-value-container">
|
|
||||||
<text class="detail-value">{{ humidity }}%</text>
|
|
||||||
<view class="detail-status" :class="humidity > 0 ? 'active' : 'inactive'"></view>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
<view class="detail-progress-bar">
|
|
||||||
<view class="detail-progress-fill humidity-progress" :style="{ width: humidityProgress + '%' }"></view>
|
|
||||||
</view>
|
|
||||||
<!-- <view class="detail-range">
|
|
||||||
<text class="detail-range-text">{{ 0 }}% - {{ 100 }}%</text>
|
|
||||||
</view> -->
|
|
||||||
</view>
|
|
||||||
|
|
||||||
<!-- 洁净度卡片 -->
|
|
||||||
<view class="detail-card cleanliness-detail-card">
|
|
||||||
<view class="detail-header">
|
|
||||||
<view class="detail-icon-container">
|
|
||||||
<view class="detail-icon cleanliness-icon">✨</view>
|
|
||||||
<text class="detail-label">洁净度</text>
|
|
||||||
</view>
|
|
||||||
<view class="detail-value-container">
|
|
||||||
<text class="detail-value">{{ cleanliness > 0 ? cleanliness + 'μg/m³' : '-μg/m³' }}</text>
|
|
||||||
<view class="detail-status" :class="cleanliness > 0 ? 'active' : 'inactive'"></view>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
<view class="detail-progress-bar">
|
|
||||||
<view class="detail-progress-fill cleanliness-progress" :style="{ width: cleanlinessProgress + '%' }"></view>
|
|
||||||
</view>
|
|
||||||
<!-- <view class="detail-range">
|
|
||||||
<text class="detail-range-text">{{ 0 }}% - {{ 100 }}%</text>
|
|
||||||
</view> -->
|
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
|
<view class="detail-progress-bar">
|
||||||
|
<view class="detail-progress-fill temperature-progress" :style="{ width: temperatureProgress + '%' }"></view>
|
||||||
|
</view>
|
||||||
|
<!-- <view class="detail-range">
|
||||||
|
<text class="detail-range-text">{{ 0 }}°C - {{ 100 }}°C</text>
|
||||||
|
</view> -->
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 湿度卡片 -->
|
||||||
|
<view class="detail-card humidity-detail-card" @click="navigateToParameterRecord">
|
||||||
|
<view class="detail-header">
|
||||||
|
<view class="detail-icon-container">
|
||||||
|
<view class="detail-icon humidity-icon">💧</view>
|
||||||
|
<text class="detail-label">湿度</text>
|
||||||
|
</view>
|
||||||
|
<view class="detail-value-container">
|
||||||
|
<text class="detail-value">{{ humidity }}%</text>
|
||||||
|
<view class="detail-status" :class="humidity > 0 ? 'active' : 'inactive'"></view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="detail-progress-bar">
|
||||||
|
<view class="detail-progress-fill humidity-progress" :style="{ width: humidityProgress + '%' }"></view>
|
||||||
|
</view>
|
||||||
|
<!-- <view class="detail-range">
|
||||||
|
<text class="detail-range-text">{{ 0 }}% - {{ 100 }}%</text>
|
||||||
|
</view> -->
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 洁净度卡片 -->
|
||||||
|
<view class="detail-card cleanliness-detail-card" @click="navigateToParameterRecord">
|
||||||
|
<view class="detail-header">
|
||||||
|
<view class="detail-icon-container">
|
||||||
|
<view class="detail-icon cleanliness-icon">✨</view>
|
||||||
|
<text class="detail-label">洁净度</text>
|
||||||
|
</view>
|
||||||
|
<view class="detail-value-container">
|
||||||
|
<text class="detail-value">{{ cleanliness > 0 ? cleanliness + 'μg/m³' : '-μg/m³' }}</text>
|
||||||
|
<view class="detail-status" :class="cleanliness > 0 ? 'active' : 'inactive'"></view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="detail-progress-bar">
|
||||||
|
<view class="detail-progress-fill cleanliness-progress" :style="{ width: cleanlinessProgress + '%' }"></view>
|
||||||
|
</view>
|
||||||
|
<!-- <view class="detail-range">
|
||||||
|
<text class="detail-range-text">{{ 0 }}% - {{ 100 }}%</text>
|
||||||
|
</view> -->
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
<!-- 空调设置 -->
|
<!-- 空调设置 -->
|
||||||
<view class="air-conditioner-settings">
|
<view class="air-conditioner-settings">
|
||||||
@ -385,6 +385,13 @@ export default {
|
|||||||
this.loadWsdSettings()
|
this.loadWsdSettings()
|
||||||
// 注意:定时器在 onShow 中启动,避免重复启动
|
// 注意:定时器在 onShow 中启动,避免重复启动
|
||||||
},
|
},
|
||||||
|
navigateToParameterRecord() {
|
||||||
|
try {
|
||||||
|
uni.switchTab({ url: '/pages/parameter/index' })
|
||||||
|
} catch (e) {
|
||||||
|
uni.showToast({ title: '页面跳转失败', icon: 'none' })
|
||||||
|
}
|
||||||
|
},
|
||||||
// 首次进入系统时创建启动事件
|
// 首次进入系统时创建启动事件
|
||||||
async createStartupEventIfNeeded() {
|
async createStartupEventIfNeeded() {
|
||||||
// 检查是否已经创建过启动事件
|
// 检查是否已经创建过启动事件
|
||||||
|
|||||||
@ -17,14 +17,31 @@
|
|||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
<!-- 下部区域:按钮和版本号 -->
|
<!-- 登录表单:账号、密码 -->
|
||||||
<view class="bottom-section">
|
<view class="form-section">
|
||||||
<!-- 进入系统按钮 -->
|
<!-- <view class="form-item">
|
||||||
|
<text class="form-label">账号</text>
|
||||||
|
<input class="form-input" v-model="username" placeholder="请输入账号" placeholder-class="placeholder" confirm-type="next" />
|
||||||
|
</view> -->
|
||||||
|
<view class="form-item">
|
||||||
|
<text class="form-label">密码</text>
|
||||||
|
<input class="form-input" v-model="password" password placeholder="请输入密码" placeholder-class="placeholder" confirm-type="done" />
|
||||||
|
</view>
|
||||||
<view class="action-container">
|
<view class="action-container">
|
||||||
<button class="enter-button" @click="navigateToTabBar">
|
<button class="enter-button" @click="navigateToTabBar">
|
||||||
<text class="button-text">进入系统 →</text>
|
<text class="button-text">进入系统 →</text>
|
||||||
</button>
|
</button>
|
||||||
</view>
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 下部区域:按钮和版本号 -->
|
||||||
|
<view class="bottom-section">
|
||||||
|
<!-- 进入系统按钮 -->
|
||||||
|
<!-- <view class="action-container">
|
||||||
|
<button class="enter-button" @click="navigateToTabBar">
|
||||||
|
<text class="button-text">进入系统 →</text>
|
||||||
|
</button>
|
||||||
|
</view> -->
|
||||||
|
|
||||||
<!-- 版本号 -->
|
<!-- 版本号 -->
|
||||||
<view class="version-container">
|
<view class="version-container">
|
||||||
@ -37,84 +54,141 @@
|
|||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { manualReconnect } from '@/utils/sendMqtt.js'
|
import { manualReconnect } from '@/utils/sendMqtt.js'
|
||||||
|
import { authApi } from '@/utils/api.js'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
title: 'Hello',
|
title: 'Hello',
|
||||||
|
username: '',
|
||||||
|
password: '',
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
canLogin() {
|
||||||
|
// return this.username && this.username.trim().length > 0 && this.password && this.password.trim().length > 0
|
||||||
|
return this.password && this.password.trim().length > 0
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
onLoad() {},
|
onLoad() {},
|
||||||
methods: {
|
methods: {
|
||||||
navigateToTabBar() {
|
async navigateToTabBar() {
|
||||||
console.log('🔧 用户点击进入系统,开始MQTT重连...')
|
if (!this.canLogin) {
|
||||||
|
uni.showToast({
|
||||||
|
title: '请输入密码',
|
||||||
|
icon: 'none',
|
||||||
|
duration: 1200
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
console.log('🔒 开始登录...')
|
||||||
|
|
||||||
// 立即显示连接提示
|
// 先登录
|
||||||
uni.showLoading({
|
|
||||||
title: '正在连接MQTT...',
|
|
||||||
// mask: true
|
|
||||||
})
|
|
||||||
|
|
||||||
// 调用MQTT重连函数
|
|
||||||
try {
|
try {
|
||||||
manualReconnect()
|
uni.showLoading({ title: '正在登录...' })
|
||||||
console.log('✅ MQTT重连函数已调用')
|
const loginRes = await authApi.login({
|
||||||
|
username: this.username || 'admin',
|
||||||
|
password: this.password
|
||||||
|
})
|
||||||
|
|
||||||
// 延迟跳转,给MQTT连接一些时间
|
console.log('🔒 登录结果:', loginRes)
|
||||||
setTimeout(() => {
|
if (loginRes.success) {
|
||||||
// 更新loading文本
|
// 可选:如果返回 token,保存以备后续请求使用
|
||||||
|
if (loginRes && loginRes.token) {
|
||||||
|
const token = loginRes.token;
|
||||||
|
try {
|
||||||
|
uni.setStorageSync('auth_token', token)
|
||||||
|
} catch (e) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
uni.hideLoading()
|
||||||
|
uni.showToast({ title: '登录成功', icon: 'success', duration: 800 })
|
||||||
|
// 立即显示连接提示
|
||||||
uni.showLoading({
|
uni.showLoading({
|
||||||
title: '正在跳转系统...',
|
title: '正在连接MQTT...',
|
||||||
// mask: true
|
// mask: true
|
||||||
})
|
})
|
||||||
uni.hideLoading()
|
|
||||||
// 跳转到tabbar的第一个页面(环境参数页面)
|
// 调用MQTT重连函数
|
||||||
uni.switchTab({
|
try {
|
||||||
url: '/pages/environment/index',
|
manualReconnect()
|
||||||
success: () => {
|
console.log('✅ MQTT重连函数已调用')
|
||||||
console.log('✅ 成功跳转到环境参数页面')
|
|
||||||
uni.showToast({
|
// 延迟跳转,给MQTT连接一些时间
|
||||||
title: '系统连接成功',
|
setTimeout(() => {
|
||||||
icon: 'success',
|
// 更新loading文本
|
||||||
duration: 1000
|
uni.showLoading({
|
||||||
|
title: '正在跳转系统...',
|
||||||
|
// mask: true
|
||||||
})
|
})
|
||||||
},
|
uni.hideLoading()
|
||||||
fail: (err) => {
|
// 跳转到tabbar的第一个页面(环境参数页面)
|
||||||
console.error('❌ 跳转到tabbar失败:', err);
|
uni.switchTab({
|
||||||
// 如果失败,尝试使用redirectTo
|
|
||||||
uni.redirectTo({
|
|
||||||
url: '/pages/environment/index',
|
url: '/pages/environment/index',
|
||||||
success: () => {
|
success: () => {
|
||||||
console.log('✅ 使用redirectTo成功跳转')
|
console.log('✅ 成功跳转到环境参数页面')
|
||||||
uni.showToast({
|
uni.showToast({
|
||||||
title: '系统连接成功',
|
title: '系统连接成功',
|
||||||
icon: 'success',
|
icon: 'success',
|
||||||
duration: 1000
|
duration: 1000
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
fail: (redirectErr) => {
|
fail: (err) => {
|
||||||
console.error('❌ redirectTo也失败:', redirectErr)
|
console.error('❌ 跳转到tabbar失败:', err);
|
||||||
uni.showToast({
|
// 如果失败,尝试使用redirectTo
|
||||||
title: '页面跳转失败',
|
uni.redirectTo({
|
||||||
icon: 'error',
|
url: '/pages/environment/index',
|
||||||
duration: 1000
|
success: () => {
|
||||||
})
|
console.log('✅ 使用redirectTo成功跳转')
|
||||||
|
uni.showToast({
|
||||||
|
title: '系统连接成功',
|
||||||
|
icon: 'success',
|
||||||
|
duration: 1000
|
||||||
|
})
|
||||||
|
},
|
||||||
|
fail: (redirectErr) => {
|
||||||
|
console.error('❌ redirectTo也失败:', redirectErr)
|
||||||
|
uni.showToast({
|
||||||
|
title: '页面跳转失败',
|
||||||
|
icon: 'error',
|
||||||
|
duration: 1000
|
||||||
|
})
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
});
|
})
|
||||||
}
|
|
||||||
|
}, 300) // 1秒后开始跳转
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
console.error('❌ MQTT重连失败:', error)
|
||||||
|
uni.hideLoading()
|
||||||
|
uni.showToast({
|
||||||
|
title: 'MQTT连接失败',
|
||||||
|
icon: 'error',
|
||||||
|
duration: 1000
|
||||||
|
})
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
uni.hideLoading()
|
||||||
|
uni.showToast({
|
||||||
|
title: loginRes?.message || '登录失败',
|
||||||
|
icon: 'none',
|
||||||
|
duration: 1500
|
||||||
})
|
})
|
||||||
|
return
|
||||||
}, 300) // 1秒后开始跳转
|
}
|
||||||
|
} catch (e) {
|
||||||
} catch (error) {
|
|
||||||
console.error('❌ MQTT重连失败:', error)
|
|
||||||
uni.hideLoading()
|
uni.hideLoading()
|
||||||
uni.showToast({
|
uni.showToast({
|
||||||
title: 'MQTT连接失败',
|
title: e?.message || '登录失败',
|
||||||
icon: 'error',
|
icon: 'none',
|
||||||
duration: 1000
|
duration: 1500
|
||||||
})
|
})
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
console.log('🔧 用户点击进入系统,开始MQTT重连...')
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@ -193,6 +267,7 @@ export default {
|
|||||||
/* 进入系统按钮 */
|
/* 进入系统按钮 */
|
||||||
.action-container {
|
.action-container {
|
||||||
margin-bottom: 40rpx;
|
margin-bottom: 40rpx;
|
||||||
|
margin-top: 40px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.enter-button {
|
.enter-button {
|
||||||
@ -210,6 +285,42 @@ export default {
|
|||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 表单样式 */
|
||||||
|
.form-section {
|
||||||
|
width: 100%;
|
||||||
|
max-width: 640rpx;
|
||||||
|
margin-top: 40rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-item {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
background: #f7f8fa;
|
||||||
|
border-radius: 12rpx;
|
||||||
|
padding: 20rpx 24rpx;
|
||||||
|
margin-bottom: 24rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-label {
|
||||||
|
width: 120rpx;
|
||||||
|
font-size: 28rpx;
|
||||||
|
color: #333333;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-input {
|
||||||
|
flex: 1;
|
||||||
|
font-size: 28rpx;
|
||||||
|
color: #111111;
|
||||||
|
}
|
||||||
|
|
||||||
|
.placeholder {
|
||||||
|
color: #999999;
|
||||||
|
}
|
||||||
|
|
||||||
|
.enter-button:disabled {
|
||||||
|
opacity: 0.5;
|
||||||
|
}
|
||||||
|
|
||||||
/* 版本号 */
|
/* 版本号 */
|
||||||
|
|
||||||
.version-text {
|
.version-text {
|
||||||
|
|||||||
@ -5,6 +5,15 @@
|
|||||||
|
|
||||||
import httpService from './http.js'
|
import httpService from './http.js'
|
||||||
|
|
||||||
|
// 认证接口
|
||||||
|
export const authApi = {
|
||||||
|
// 登录
|
||||||
|
login(data) {
|
||||||
|
// 约定字段:username、password
|
||||||
|
return httpService.post('/api/auth/login', data)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// 数据历史接口
|
// 数据历史接口
|
||||||
export const dataHistoryApi = {
|
export const dataHistoryApi = {
|
||||||
// 获取历史数据
|
// 获取历史数据
|
||||||
|
|||||||
@ -282,11 +282,11 @@ const sendMqttData = (data) => {
|
|||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
console.log('✅ MQTT数据发送成功');
|
console.log('✅ MQTT数据发送成功');
|
||||||
uni.showToast({
|
// uni.showToast({
|
||||||
title: '数据发送成功',
|
// title: '数据发送成功',
|
||||||
icon: 'success',
|
// icon: 'success',
|
||||||
duration: 1500
|
// duration: 1500
|
||||||
});
|
// });
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -334,11 +334,11 @@ const sendMqttDataRecall = (data) => {
|
|||||||
duration: 2000
|
duration: 2000
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
uni.showToast({
|
// uni.showToast({
|
||||||
title: '数据发送成功',
|
// title: '数据发送成功',
|
||||||
icon: 'success',
|
// icon: 'success',
|
||||||
duration: 1500
|
// duration: 1500
|
||||||
});
|
// });
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user