1102 lines
27 KiB
Vue
1102 lines
27 KiB
Vue
<template>
|
||
<view class="container">
|
||
<!-- 用户信息卡片 -->
|
||
<view class="card user-info-card interactive" role="banner">
|
||
<view class="flex-row-g20">
|
||
<view class="user-avatar">
|
||
<image
|
||
:src="userInfo.avatar || 'https://img1.baidu.com/it/u=2462918877,1866131262&fm=253&fmt=auto&app=138&f=JPEG?w=506&h=500'"
|
||
mode="aspectFill" alt="用户头像" />
|
||
</view>
|
||
<view class="user-details flex-col-g8">
|
||
<view class="title">{{userInfo.nickname || "单卡用户"}}</view>
|
||
<view class="caption">设备已运行:{{formatSecondsToTime(deviceInfo.run_time)}}</view>
|
||
</view>
|
||
<view class="tag-apple" :class="onlineStatus === '在线' ? 'tag-success' : 'tag-warning'">
|
||
{{onlineStatus}}
|
||
</view>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 设备信息卡片 -->
|
||
<view class="card device-status-card">
|
||
<view class="card-header flex-row-sb">
|
||
<view class="title">设备信息</view>
|
||
<view class="info-values flex-row-g20">
|
||
<view class="tag-apple tag-success">{{getOperator(deviceInfo.currentIccid)}}</view>
|
||
</view>
|
||
</view>
|
||
<view class="device-info flex-col-g16">
|
||
<view class="info-row flex-row-sb">
|
||
<view class="info-label">
|
||
<view class="subtitle">当前使用卡:{{deviceInfo.currentIccid || "无"}}</view>
|
||
</view>
|
||
|
||
<view class="info-values flex-row-g20">
|
||
<view class="tag-apple tag-success">{{isRealName ? "已实名" : "未实名"}}</view>
|
||
</view>
|
||
</view>
|
||
|
||
<view class="info-row flex-row-sb">
|
||
<view class="info-label">
|
||
<view class="subtitle">到期时间:{{deviceInfo.expireDate}}</view>
|
||
</view>
|
||
<view class="info-values flex-row-g20">
|
||
<view class="tag-apple tag-primary">{{deviceInfo.statusStr}}</view>
|
||
</view>
|
||
</view>
|
||
|
||
</view>
|
||
|
||
<view class="device-metrics flex-row-sb mt-md">
|
||
<view class="metric-item flex-col-center">
|
||
<view class="caption mb-xs">信号强度</view>
|
||
<view class="metric-value">{{getSignalText(deviceInfo.rssi)}}</view>
|
||
</view>
|
||
<view class="metric-item flex-col-center">
|
||
<view class="caption mb-xs">设备电量</view>
|
||
<view class="metric-value">{{deviceInfo.battery || 0 }} %</view>
|
||
</view>
|
||
<view class="metric-item flex-col-center">
|
||
<view class="caption mb-xs">连接数量</view>
|
||
<view class="metric-value">{{deviceInfo.connCnt || 0}} 台</view>
|
||
</view>
|
||
</view>
|
||
|
||
</view>
|
||
|
||
<!-- 流量监控卡片 -->
|
||
<view class="card traffic-card">
|
||
<view class="card-header flex-row-sb mb-lg">
|
||
<view class="title">本月流量</view>
|
||
<view class="usage-percent">
|
||
<text class="title">{{usedFlowPercent}}</text>
|
||
<text class="caption">%</text>
|
||
</view>
|
||
</view>
|
||
<view class="progress-section mb-lg">
|
||
<view class="progress-apple">
|
||
<view class="progress-fill" :style="{width: usedFlowPercent + '%'}"></view>
|
||
</view>
|
||
</view>
|
||
<view class="traffic-stats flex-row-sb">
|
||
<view class="stat-item flex-col-center">
|
||
<view class="caption mb-xs">已使用</view>
|
||
<view class="stat-value-container">
|
||
<text class="stat-value">{{formatDataSize(deviceInfo.totalBytesCnt)}}</text>
|
||
<text class="stat-unit">GB</text>
|
||
</view>
|
||
</view>
|
||
<view class="stat-item flex-col-center">
|
||
<view class="caption mb-xs">总流量</view>
|
||
<view class="stat-value-container">
|
||
<text class="stat-value">{{formatDataSize(deviceInfo.flowSize)}}</text>
|
||
<text class="stat-unit">GB</text>
|
||
</view>
|
||
</view>
|
||
<view class="stat-item flex-col-center">
|
||
<view class="caption mb-xs">剩余</view>
|
||
<view class="stat-value-container">
|
||
<text
|
||
class="stat-value">{{formatDataSize(deviceInfo.flowSize - deviceInfo.totalBytesCnt)}}</text>
|
||
<text class="stat-unit">GB</text>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- WiFi配置卡片 -->
|
||
<view class="card wifi-card">
|
||
<view class="card-header flex-row-sb">
|
||
<view class="title">WiFi配置</view>
|
||
<view class="btn-group">
|
||
<button class="btn-apple btn-primary btn-mini" style="padding: 20rpx;"
|
||
@tap="modifyWifi">修改配置</button>
|
||
</view>
|
||
</view>
|
||
<view class="wifi-info flex-col-g16 mt-30">
|
||
<view class="wifi-item flex-row-sb">
|
||
<view class="wifi-details flex-col-g8">
|
||
<view class="caption">网络名称</view>
|
||
<view class="subtitle">{{deviceInfo.ssidName}}</view>
|
||
</view>
|
||
<button class="btn-apple btn-primary btn-mini" @tap="copy(deviceInfo.ssidName)">
|
||
复制名称
|
||
</button>
|
||
</view>
|
||
<view class="wifi-item flex-row-sb">
|
||
<view class="wifi-details flex-col-g8">
|
||
<view class="caption">连接密码</view>
|
||
<view class="subtitle">{{deviceInfo.ssidPwd}}</view>
|
||
</view>
|
||
<button class="btn-apple btn-primary btn-mini" @tap="copy(deviceInfo.ssidPwd)">
|
||
复制密码
|
||
</button>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 功能菜单卡片 -->
|
||
<view class="card function-card">
|
||
<view class="card-header">
|
||
<view class="title">功能菜单</view>
|
||
</view>
|
||
<view class="function-grid">
|
||
<view class="function-item interactive card-interactive" @tap="enterDetail('package-order')"
|
||
role="button" tabindex="0">
|
||
<view class="function-icon">
|
||
<image src="/static/shop.png" mode="aspectFit" alt="套餐订购"></image>
|
||
</view>
|
||
<view class="function-name">套餐订购</view>
|
||
</view>
|
||
<view class="function-item interactive card-interactive" @tap="enterDetail('intelligent-diagnosis')"
|
||
role="button" tabindex="0">
|
||
<view class="function-icon">
|
||
<image src="/static/diagnosis.png" mode="aspectFit" alt="智能诊断"></image>
|
||
</view>
|
||
<view class="function-name">智能诊断</view>
|
||
</view>
|
||
<view class="function-item interactive card-interactive" @tap="enterDetail('back')" role="button"
|
||
tabindex="0">
|
||
<view class="function-icon">
|
||
<image src="/static/back.png" mode="aspectFit" alt="后台管理"></image>
|
||
</view>
|
||
<view class="function-name">后台管理</view>
|
||
</view>
|
||
<!-- <view class="function-item interactive card-interactive" @tap="enterDetail('switch')" role="button"
|
||
tabindex="0">
|
||
<view class="function-icon">
|
||
<image src="/static/change.png" mode="aspectFit" alt="切换运营商"></image>
|
||
</view>
|
||
<view class="function-name">切换运营商</view>
|
||
</view> -->
|
||
<view class="function-item interactive card-interactive" @tap="enterDetail('bind')" role="button"
|
||
tabindex="0">
|
||
<view class="function-icon">
|
||
<image src="/static/bind-phone.png" mode="aspectFit" alt="绑定手机号"></image>
|
||
</view>
|
||
<view class="function-name">
|
||
{{alreadyBindPhone ? "已绑定" : "未绑定" }}
|
||
</view>
|
||
</view>
|
||
<view class="function-item interactive card-interactive" @tap="enterDetail('authentication')"
|
||
role="button" tabindex="0">
|
||
<view class="function-icon">
|
||
<image src="/static/authentication.png" mode="aspectFit" alt="实名认证"></image>
|
||
</view>
|
||
<view class="function-name">
|
||
{{isRealName ? "已实名" : "未实名"}}
|
||
</view>
|
||
</view>
|
||
<view class="function-item interactive card-interactive" @tap="enterDetail('recover')" role="button"
|
||
tabindex="0">
|
||
<view class="function-icon">
|
||
<image src="/static/recover.png" mode="aspectFit" alt="重启设备"></image>
|
||
</view>
|
||
<view class="function-name">重启设备</view>
|
||
</view>
|
||
<view class="function-item interactive card-interactive" @tap="enterDetail('restart')" role="button"
|
||
tabindex="0">
|
||
<view class="function-icon">
|
||
<image src="/static/restart.png" mode="aspectFit" alt="恢复出厂"></image>
|
||
</view>
|
||
<view class="function-name">恢复出厂</view>
|
||
</view>
|
||
<view class="function-item interactive card-interactive" @tap="enterDetail('out')" role="button"
|
||
tabindex="0">
|
||
<view class="function-icon">
|
||
<image src="/static/out.png" mode="aspectFit" alt="退出登录"></image>
|
||
</view>
|
||
<view class="function-name">退出登录</view>
|
||
</view>
|
||
</view>
|
||
|
||
|
||
<!-- 修改WIFI -->
|
||
<up-popup :show="showModifyWifi" mode="center" @close="showModifyWifi=false">
|
||
<view class="container mt-30" style="width: 600rpx; padding: 30rpx;">
|
||
<view class="title">
|
||
修改WIFI
|
||
</view>
|
||
<view class="flex-row-g20">
|
||
<label for="">名称: </label>
|
||
<up-input placeholder="WIFI名称" border="surround" v-model="wifi_info.ssid" />
|
||
</view>
|
||
<view class="flex-row-g20">
|
||
<label for="">密码: </label>
|
||
<up-input placeholder="WIFI密码" border="surround" v-model="wifi_info.pwd" />
|
||
</view>
|
||
<view class="btn-group mt-20">
|
||
<button class="btn-apple btn-secondary" @tap="showModifyWifi=false">取消修改</button>
|
||
<button class="btn-apple btn-primary" @tap="confirmModify">确认修改</button>
|
||
</view>
|
||
</view>
|
||
</up-popup>
|
||
|
||
<!-- 重启设备 -->
|
||
<up-modal title="您确定要重启设备吗?" :show="restartShow" showCancelButton @confirm="YesRestart"
|
||
@cancel="restartShow=false" />
|
||
|
||
<!-- 恢复出厂设置 -->
|
||
<up-modal title="您确定要恢复出厂设置吗?" :show="recoverShow" showCancelButton @confirm="YesRecover"
|
||
@cancel="recoverShow=false" />
|
||
|
||
<!-- 退出登录 -->
|
||
<up-modal title="您确定要退出登录吗?" :show="logoutShow" showCancelButton @confirm="YesLogout"
|
||
@cancel="logoutShow=false" />
|
||
</view>
|
||
|
||
<!-- 悬浮联系客服按钮 -->
|
||
<view class="floating-customer-service flex-col-g20" @tap="connectKF">
|
||
<image src="/static/link.png"></image>
|
||
<text style="font-size: 24rpx;">在线客服</text>
|
||
</view>
|
||
</view>
|
||
</template>
|
||
|
||
<script setup>
|
||
import {
|
||
ref,
|
||
reactive,
|
||
onMounted,
|
||
computed
|
||
} from 'vue';
|
||
|
||
import {
|
||
userStore
|
||
} from '@/store/index.js';
|
||
|
||
import {
|
||
convertToGB,
|
||
formatSecondsToTime,
|
||
getSignalText
|
||
} from "@/utils/common.js"
|
||
|
||
let showModifyWifi = ref(false);
|
||
|
||
let restartShow = ref(false)
|
||
|
||
let recoverShow = ref(false)
|
||
|
||
let logoutShow = ref(false)
|
||
|
||
// 设备信息
|
||
let deviceInfo = reactive({
|
||
battery: 0, // 电池
|
||
connect: 0, // 连接数量
|
||
statusStr: "", // 状态
|
||
expireDate: "", // 过期时间
|
||
currentIccid: "", // 当前卡号
|
||
category: "", // 所属运营商
|
||
phone: "", // 实名需要phone
|
||
flowSize: 0, // 总流量
|
||
totalBytesCnt: 0, // 已用流量
|
||
ssidName: "", // wifi名称
|
||
ssidPwd: "", // wifi密码
|
||
rssi: "", // 信号强度
|
||
onlineStatus: "", // 在线状态 2:在线 1:离线
|
||
connCnt: 0, // 连接数
|
||
run_time: 0, // 运行时间
|
||
last_online_time: "", // 上次在线时间
|
||
lan_ip: "", // 后台地址
|
||
kf_url: "https://work.weixin.qq.com/kfid/kfc0fd79f27686fb65e?enc_scene=ENCfR9AVui6UfvvxySGVuvaG&scene_param=commonlink", // 客服
|
||
mchList: [], // 列表
|
||
})
|
||
|
||
let opratorList = reactive([{
|
||
category: "124", // 中国电信
|
||
logo: "https://img2.baidu.com/it/u=139558247,3893370039&fm=253&fmt=auto?w=529&h=500",
|
||
name: "中国电信"
|
||
},
|
||
{
|
||
category: "125", // 中国联通
|
||
logo: "https://img1.baidu.com/it/u=2816777816,1756344384&fm=253&fmt=auto&app=120&f=JPEG?w=500&h=500",
|
||
name: "中国联通"
|
||
},
|
||
{
|
||
category: "126", // 中国移动
|
||
logo: "https://img2.baidu.com/it/u=915783975,1594870591&fm=253&fmt=auto&app=120&f=PNG?w=182&h=182",
|
||
name: "中国移动"
|
||
}
|
||
])
|
||
|
||
let isRealName = ref(false)
|
||
|
||
let alreadyBindPhone = ref(false)
|
||
|
||
let wifi_info = reactive({
|
||
ssid: "",
|
||
pwd: ""
|
||
})
|
||
|
||
let device_id = uni.getStorageSync("device_id")
|
||
|
||
// 获取用户信息
|
||
const getUserInfo = async () => {
|
||
await userStore.actions.getUserInfo()
|
||
}
|
||
|
||
const userInfo = computed(() => {
|
||
return userStore.state.userInfo
|
||
})
|
||
|
||
// 获取设备信息
|
||
const getCardInfo = async () => {
|
||
const result = await userStore.actions.getCardInfo()
|
||
if (result?.entity) {
|
||
deviceInfo.statusStr = result.entity.statusStr
|
||
deviceInfo.expireDate = result.entity.expireDate
|
||
}
|
||
|
||
const mainInfo = await userStore.actions.getSwitchCardList()
|
||
if (mainInfo?.cardEntity) {
|
||
deviceInfo.category = mainInfo.cardEntity.category
|
||
deviceInfo.phone = mainInfo.cardEntity.phone
|
||
deviceInfo.flowSize = convertToGB(mainInfo.cardEntity.flowSize, "flowSize")
|
||
deviceInfo.totalBytesCnt = convertToGB(mainInfo.cardEntity.totalBytesCnt, "totalBytesCnt")
|
||
}
|
||
if (mainInfo?.gswlinfo) {
|
||
deviceInfo.connCnt = mainInfo.gswlinfo.connCnt
|
||
deviceInfo.onlineStatus = mainInfo.gswlinfo.onlineStatus
|
||
deviceInfo.currentIccid = mainInfo.gswlinfo.iccid
|
||
}
|
||
if (mainInfo?.mchList.length > 0) {
|
||
deviceInfo.mchList = mainInfo.mchList
|
||
}
|
||
|
||
const {
|
||
data
|
||
} = await userStore.actions.getDeviceInfoAdmin(device_id)
|
||
const result_admin = data.list || []
|
||
if (result_admin.length > 0) {
|
||
const adminInfo = result_admin[0]
|
||
deviceInfo.ssidName = adminInfo.ssid
|
||
deviceInfo.ssidPwd = adminInfo.wifi_password
|
||
deviceInfo.rssi = adminInfo.rssi
|
||
deviceInfo.battery = adminInfo.battery_level
|
||
deviceInfo.run_time = adminInfo.run_time
|
||
deviceInfo.last_online_time = adminInfo.last_online_time
|
||
deviceInfo.lan_ip = adminInfo.lan_ip
|
||
}
|
||
}
|
||
|
||
// 获取实名信息
|
||
const realName = async () => {
|
||
const {
|
||
alreadyRealName,
|
||
alreadyBind
|
||
} = await userStore.actions.getRealNameInfo()
|
||
|
||
isRealName.value = alreadyRealName
|
||
alreadyBindPhone.value = alreadyBind
|
||
|
||
if (!alreadyRealName) {
|
||
uni.showToast({
|
||
title: '未实名跳转实名页面',
|
||
icon: 'none'
|
||
})
|
||
|
||
uni.navigateTo({
|
||
url: '/pages/auth/auth'
|
||
})
|
||
}
|
||
|
||
}
|
||
|
||
// 修改WiFi
|
||
const modifyWifi = () => {
|
||
wifi_info.ssid = deviceInfo.ssidName
|
||
wifi_info.pwd = deviceInfo.ssidPwd
|
||
showModifyWifi.value = true
|
||
}
|
||
|
||
// 确认修改
|
||
const confirmModify = async () => {
|
||
if (!wifi_info.ssid || !wifi_info.pwd) {
|
||
uni.showToast({
|
||
title: 'WIFI名称和密码不能为空',
|
||
icon: 'none'
|
||
})
|
||
return
|
||
}
|
||
const result = await userStore.actions.modifyWifi({
|
||
cardNo: device_id,
|
||
ssid: wifi_info.ssid,
|
||
password: wifi_info.pwd
|
||
})
|
||
if (result.code === 200) {
|
||
uni.showToast({
|
||
title: result.message,
|
||
icon: 'none'
|
||
})
|
||
} else {
|
||
uni.showToast({
|
||
title: result.message,
|
||
icon: 'none'
|
||
})
|
||
}
|
||
|
||
showModifyWifi.value = false
|
||
}
|
||
|
||
// 连接客服
|
||
const connectKF = () => {
|
||
uni.showToast({
|
||
title: '正在跳转客服',
|
||
icon: 'none'
|
||
})
|
||
|
||
window.location.href = deviceInfo.kf_url
|
||
}
|
||
|
||
const intelligentDiagnosis = async () => {
|
||
await userStore.actions.intelligentDiagnosis()
|
||
uni.showToast({
|
||
title: '设备可以正常使用',
|
||
icon: 'none'
|
||
})
|
||
}
|
||
|
||
const enterBack = () => {
|
||
if (!deviceInfo.lan_ip) {
|
||
uni.showToast({
|
||
title: '后台地址为空',
|
||
icon: 'none'
|
||
})
|
||
}
|
||
window.location.href = `http://${deviceInfo.lan_ip}`
|
||
uni.showToast({
|
||
title: '正在跳转后台: http://' + deviceInfo.lan_ip,
|
||
icon: 'none'
|
||
})
|
||
}
|
||
|
||
// 重启设备
|
||
const YesRestart = async () => {
|
||
const {
|
||
code,
|
||
msg
|
||
} = await userStore.actions.restartDevice(device_id)
|
||
if (code === 200) {
|
||
uni.showToast({
|
||
title: '设备重启成功!',
|
||
icon: 'none'
|
||
})
|
||
} else {
|
||
uni.showToast({
|
||
title: msg,
|
||
icon: 'none'
|
||
})
|
||
}
|
||
|
||
restartShow.value = false
|
||
}
|
||
|
||
const copy = (content) => {
|
||
uni.setClipboardData({
|
||
data: content,
|
||
success: () => {
|
||
uni.showToast({
|
||
title: '复制成功',
|
||
icon: 'none'
|
||
})
|
||
},
|
||
fail: () => {
|
||
uni.showToast({
|
||
title: '复制失败',
|
||
icon: 'none'
|
||
})
|
||
},
|
||
showToast: false
|
||
})
|
||
}
|
||
|
||
// 恢复出厂
|
||
const YesRecover = async () => {
|
||
const result = await userStore.actions.restDevice(device_id)
|
||
uni.showToast({
|
||
title: '恢复出厂',
|
||
icon: 'none'
|
||
})
|
||
recoverShow.value = false
|
||
}
|
||
|
||
// 退出登录
|
||
const YesLogout = async () => {
|
||
try {
|
||
await userStore.actions.logout()
|
||
// 状态清除和跳转逻辑已在store中处理
|
||
logoutShow.value = false
|
||
} catch (error) {
|
||
console.error('退出登录出错:', error);
|
||
uni.showToast({
|
||
title: '退出登录失败',
|
||
icon: 'none'
|
||
})
|
||
logoutShow.value = false
|
||
}
|
||
}
|
||
|
||
// 已使用流量占比 保留两位小数
|
||
const usedFlowPercent = computed(() => {
|
||
if (deviceInfo.flowSize && deviceInfo.totalBytesCnt) {
|
||
const usedFlow = parseFloat(deviceInfo.totalBytesCnt)
|
||
const totalFlow = parseFloat(deviceInfo.flowSize)
|
||
const percent = (usedFlow / totalFlow) * 100
|
||
return percent.toFixed(2)
|
||
}
|
||
return 0
|
||
})
|
||
|
||
const getOperator = computed(() => {
|
||
return (iccid) => {
|
||
const currentInfo = deviceInfo.mchList.find(item => item.iccidMark === iccid);
|
||
if(currentInfo){
|
||
const operator = opratorList.find(item => item.category === currentInfo.category)
|
||
return operator ? operator.name : ''; // 返回运营商名称
|
||
}
|
||
return ''; // 如果没有找到匹配的运营商,返回空字符串
|
||
}
|
||
})
|
||
|
||
// 格式化数据大小为更易读的格式
|
||
const formatDataSize = (size) => {
|
||
if (!size) return '0'
|
||
const num = parseFloat(size)
|
||
if (num < 0.01) return '0'
|
||
return num.toFixed(2)
|
||
}
|
||
|
||
const onlineStatus = computed(() => {
|
||
return deviceInfo.onlineStatus == "1" ? '在线' : '离线'
|
||
})
|
||
|
||
// 清理 URL 中的 code 参数
|
||
const removeCodeFromUrl = () => {
|
||
// 获取当前 URL
|
||
const url = window.location.href;
|
||
const urlParams = new URLSearchParams(window.location.search);
|
||
|
||
// 如果 URL 中包含 code 参数,则清除它
|
||
if (urlParams.has('code')) {
|
||
urlParams.delete('code'); // 删除 code 参数
|
||
|
||
// 使用 replaceState 修改当前的 URL,不会重新加载页面
|
||
window.history.replaceState({}, '', `${url.split('?')[0]}?${urlParams.toString()}`);
|
||
}
|
||
};
|
||
|
||
// 跳转到微信授权页面
|
||
const toAuth = async () => {
|
||
try {
|
||
const result = await userStore.actions.getWxUrl();
|
||
|
||
if (result.wxAuthUrl) {
|
||
// 获取当前页面的URL
|
||
const currentUrl = window.location.href;
|
||
|
||
// 检查当前URL是否已经包含 code 参数
|
||
if (!currentUrl.includes("code=")) {
|
||
// 如果没有code参数,跳转到微信授权页面
|
||
let originalUrl = result.wxAuthUrl;
|
||
|
||
// 目标替换的 redirect_uri
|
||
const newRedirectUri = "https://m1.whjhft.com/pages/index/index";
|
||
|
||
// 替换 "https://open.weixin.qq.com/connect/oauth2/authorize?appid=wxea8c599fe100ce8a&redirect_uri=https://m1.whjhft.com/my/my&response_type=code&scope=snsapi_userinfo&state=cardlogin#wechat_redirect"
|
||
// 使用正则表达式替换 redirect_uri 的值
|
||
const updatedUrl = originalUrl.replace(/(redirect_uri=)[^&]*/,
|
||
`$1${encodeURIComponent(newRedirectUri)}`);
|
||
|
||
if (updatedUrl) {
|
||
window.location.href = updatedUrl;
|
||
}
|
||
} else {
|
||
// 如果已经包含code参数, 就进行授权
|
||
authoration()
|
||
}
|
||
} else {
|
||
uni.showToast({
|
||
title: '该用户已授权',
|
||
icon: 'none'
|
||
})
|
||
|
||
}
|
||
} catch (e) {
|
||
uni.showToast({
|
||
title: e,
|
||
icon: 'none'
|
||
});
|
||
}
|
||
};
|
||
|
||
|
||
// 授权
|
||
const authoration = async () => {
|
||
try {
|
||
// 获取当前页面的完整 URL https://m1.whjhft.com/pages/index/index?code=081KSnml23G2Ug4XViml2VFHyJ0KSnmF&state=cardlogin
|
||
// const url = window.location.href;
|
||
|
||
const code = (location.search.match(/[?&]code=([^&]*)/) || [])[1];
|
||
|
||
if (code) {
|
||
// 如果 code 存在,则调用获取授权的动作
|
||
await userStore.actions.getAuthorize(code);
|
||
removeCodeFromUrl()
|
||
} else {
|
||
// 如果 code 不存在
|
||
uni.showToast({
|
||
title: "微信授权失败!",
|
||
icon: "none"
|
||
});
|
||
}
|
||
|
||
} catch (error) {
|
||
// 错误处理
|
||
console.error('授权失败:', error);
|
||
uni.showToast({
|
||
title: "授权失败,请重试",
|
||
icon: "none"
|
||
});
|
||
}
|
||
};
|
||
|
||
// 实名认证
|
||
const authentication = async () => {
|
||
if (isRealName) {
|
||
uni.showToast({
|
||
title: "您已实名!",
|
||
icon: "none"
|
||
})
|
||
} else {
|
||
const result = await userStore.actions.getRealNameAddress(deviceInfo.currentIccid)
|
||
let url = result.accountEntity.realNameUrl
|
||
if (url) {
|
||
// 替换url里面的 ${iccid} 替换为deviceInfo.currentIccid, ${phone}替换为 deviceInfo.phone
|
||
url = url.replace("${iccid}", deviceInfo.currentIccid).replace("${phone}", deviceInfo.phone)
|
||
uni.showToast({
|
||
title: "正在跳转实名",
|
||
icon: "none"
|
||
})
|
||
window.location.href = url
|
||
} else {
|
||
uni.showToast({
|
||
title: '未获取到实名地址',
|
||
icon: 'none'
|
||
})
|
||
}
|
||
}
|
||
}
|
||
|
||
const enterDetail = (name) => {
|
||
switch (name) {
|
||
case 'package-order':
|
||
uni.navigateTo({
|
||
url: '/pages/package-order/package-order'
|
||
})
|
||
break;
|
||
case 'intelligent-diagnosis':
|
||
intelligentDiagnosis()
|
||
break;
|
||
case 'back':
|
||
enterBack()
|
||
break;
|
||
case 'switch':
|
||
uni.navigateTo({
|
||
url: '/pages/switch/switch?mchList=' + JSON.stringify(deviceInfo.mchList) +
|
||
"¤tIccid=" + deviceInfo.currentIccid
|
||
})
|
||
break;
|
||
case 'bind':
|
||
uni.navigateTo({
|
||
url: '/pages/bind/bind'
|
||
})
|
||
break;
|
||
case 'authentication':
|
||
authentication()
|
||
break;
|
||
case 'recover':
|
||
restartShow.value = true
|
||
break;
|
||
case 'restart':
|
||
restartShow.value = true
|
||
break;
|
||
case 'out':
|
||
logoutShow.value = true
|
||
break;
|
||
default:
|
||
break;
|
||
}
|
||
}
|
||
|
||
onMounted(async () => {
|
||
|
||
await toAuth()
|
||
|
||
// 实名
|
||
await realName()
|
||
|
||
// 获取用户信息
|
||
await getUserInfo()
|
||
|
||
// 获取卡信息
|
||
await getCardInfo()
|
||
})
|
||
</script>
|
||
|
||
<style scoped lang="scss">
|
||
/* 用户信息卡片 */
|
||
.user-info-card {
|
||
color: black;
|
||
|
||
.user-avatar {
|
||
width: 80rpx;
|
||
height: 80rpx;
|
||
border-radius: 16rpx;
|
||
overflow: hidden;
|
||
border: 2rpx solid rgba(255, 255, 255, 0.3);
|
||
|
||
image {
|
||
width: 100%;
|
||
height: 100%;
|
||
object-fit: cover;
|
||
}
|
||
}
|
||
|
||
.user-details {
|
||
flex: 1;
|
||
|
||
.title {
|
||
font-size: 32rpx;
|
||
font-weight: 600;
|
||
}
|
||
|
||
.caption {
|
||
font-size: 24rpx;
|
||
font-weight: 400;
|
||
}
|
||
}
|
||
}
|
||
|
||
/* 设备状态卡片 */
|
||
.device-status-card {
|
||
.card-header {
|
||
|
||
.title {
|
||
color: var(--text-primary);
|
||
}
|
||
}
|
||
|
||
.info-row {
|
||
padding: var(--space-sm) 0;
|
||
border-bottom: 1rpx solid var(--system-gray-6);
|
||
|
||
&:last-child {
|
||
border-bottom: none;
|
||
}
|
||
|
||
.info-label {
|
||
min-width: 200rpx;
|
||
}
|
||
|
||
.info-values {
|
||
flex: 1;
|
||
justify-content: flex-end;
|
||
}
|
||
}
|
||
|
||
.device-metrics {
|
||
background: var(--system-gray-6);
|
||
border-radius: 12rpx;
|
||
padding: 20rpx;
|
||
|
||
.metric-item {
|
||
flex: 1;
|
||
|
||
.caption {
|
||
color: var(--text-tertiary);
|
||
font-size: 22rpx;
|
||
font-weight: 500;
|
||
}
|
||
|
||
.metric-value {
|
||
font-size: 30rpx;
|
||
font-weight: 600;
|
||
color: var(--text-primary);
|
||
margin-top: 8rpx;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
/* 流量监控卡片 */
|
||
.traffic-card {
|
||
.usage-percent {
|
||
display: flex;
|
||
align-items: baseline;
|
||
gap: 4rpx;
|
||
|
||
.title {
|
||
font-size: 35rpx;
|
||
font-weight: 700;
|
||
margin-right: 5rpx;
|
||
}
|
||
|
||
.caption {
|
||
color: var(--text-tertiary);
|
||
font-weight: 500;
|
||
}
|
||
}
|
||
|
||
.traffic-stats {
|
||
background: var(--system-gray-6);
|
||
border-radius: 12rpx;
|
||
padding: 20rpx;
|
||
margin-top: 16rpx;
|
||
|
||
.stat-item {
|
||
flex: 1;
|
||
|
||
.caption {
|
||
color: var(--text-tertiary);
|
||
font-size: 22rpx;
|
||
font-weight: 500;
|
||
}
|
||
|
||
.stat-value-container {
|
||
display: flex;
|
||
align-items: baseline;
|
||
justify-content: center;
|
||
gap: 4rpx;
|
||
margin-top: 8rpx;
|
||
|
||
.stat-value {
|
||
font-size: 32rpx;
|
||
font-weight: 700;
|
||
color: var(--text-primary);
|
||
}
|
||
|
||
.stat-unit {
|
||
font-size: 18rpx;
|
||
font-weight: 500;
|
||
color: var(--text-tertiary);
|
||
margin-top: 2rpx;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
/* WiFi配置卡片 */
|
||
.wifi-card {
|
||
.wifi-item {
|
||
padding: var(--space-md);
|
||
background: var(--system-gray-6);
|
||
border-radius: var(--radius-medium);
|
||
margin-bottom: var(--space-sm);
|
||
|
||
&:last-child {
|
||
margin-bottom: 0;
|
||
}
|
||
|
||
.wifi-details {
|
||
flex: 1;
|
||
|
||
.caption {
|
||
color: var(--text-tertiary);
|
||
font-size: 22rpx;
|
||
}
|
||
|
||
.subtitle {
|
||
color: var(--text-primary);
|
||
font-weight: 600;
|
||
font-size: 30rpx;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
/* 功能菜单卡片 */
|
||
.function-card {
|
||
.function-grid {
|
||
display: grid;
|
||
grid-template-columns: repeat(3, 1fr);
|
||
gap: 16rpx;
|
||
width: 100%;
|
||
|
||
.function-item {
|
||
display: flex;
|
||
flex-direction: column;
|
||
align-items: center;
|
||
justify-content: center;
|
||
padding: 20rpx;
|
||
|
||
.function-icon {
|
||
width: 120rpx;
|
||
height: 120rpx;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
|
||
image {
|
||
width: 100%;
|
||
height: 100%;
|
||
}
|
||
}
|
||
|
||
.function-name {
|
||
font-size: 28rpx;
|
||
font-weight: 500;
|
||
color: var(--text-primary);
|
||
text-align: center;
|
||
margin-top: 15rpx;
|
||
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
/* 响应式设计 */
|
||
@media screen and (max-width: 750rpx) {
|
||
.function-grid {
|
||
grid-template-columns: repeat(2, 1fr);
|
||
gap: 12rpx;
|
||
|
||
.function-item {
|
||
.function-icon {
|
||
width: 56rpx;
|
||
height: 56rpx;
|
||
margin-bottom: 12rpx;
|
||
|
||
image {
|
||
width: 56rpx;
|
||
height: 56rpx;
|
||
}
|
||
}
|
||
|
||
.function-name {
|
||
font-size: 24rpx;
|
||
}
|
||
}
|
||
}
|
||
|
||
.traffic-stats {
|
||
flex-direction: column;
|
||
gap: var(--space-md);
|
||
|
||
.stat-item {
|
||
flex-direction: row;
|
||
justify-content: space-between;
|
||
align-items: center;
|
||
padding: var(--space-sm) 0;
|
||
|
||
.stat-value-container {
|
||
justify-content: flex-end;
|
||
gap: 6rpx;
|
||
|
||
.stat-value {
|
||
font-size: 32rpx;
|
||
}
|
||
|
||
.stat-unit {
|
||
font-size: 18rpx;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
|
||
/* 动画增强 */
|
||
.function-item {
|
||
will-change: transform, opacity;
|
||
backface-visibility: hidden;
|
||
}
|
||
|
||
/* 悬浮联系客服按钮 */
|
||
.floating-customer-service {
|
||
position: fixed;
|
||
bottom: 40rpx;
|
||
right: 30rpx;
|
||
width: 150rpx;
|
||
height: 150rpx;
|
||
gap: 10rpx;
|
||
border-radius: 50%;
|
||
background: rgba(255, 255, 255, 0.95);
|
||
border: none;
|
||
box-shadow: 0 8rpx 24rpx rgba(0, 0, 0, 0.15),
|
||
0 4rpx 12rpx rgba(0, 0, 0, 0.1);
|
||
z-index: 1000;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
|
||
transform: scale(1);
|
||
animation: float 3s ease-in-out infinite, pulse 2s ease-in-out infinite;
|
||
backdrop-filter: blur(10rpx);
|
||
-webkit-backdrop-filter: blur(10rpx);
|
||
cursor: pointer;
|
||
|
||
image {
|
||
width: 70rpx;
|
||
height: 60rpx;
|
||
object-fit: contain;
|
||
}
|
||
}
|
||
|
||
.floating-customer-service:active {
|
||
transform: scale(0.95);
|
||
box-shadow: 0 6rpx 20rpx rgba(0, 0, 0, 0.12),
|
||
0 2rpx 8rpx rgba(0, 0, 0, 0.08);
|
||
}
|
||
|
||
.floating-customer-service:hover {
|
||
transform: scale(1.05);
|
||
box-shadow: 0 12rpx 32rpx rgba(0, 0, 0, 0.18),
|
||
0 6rpx 16rpx rgba(0, 0, 0, 0.12);
|
||
background: rgba(255, 255, 255, 1);
|
||
}
|
||
|
||
/* 悬浮动画 */
|
||
@keyframes float {
|
||
|
||
0%,
|
||
100% {
|
||
transform: translateY(0rpx) scale(1);
|
||
}
|
||
|
||
50% {
|
||
transform: translateY(-10rpx) scale(1);
|
||
}
|
||
}
|
||
|
||
/* 呼吸脉冲动画 */
|
||
@keyframes pulse {
|
||
|
||
0%,
|
||
100% {
|
||
box-shadow: 0 8rpx 24rpx rgba(0, 0, 0, 0.15),
|
||
0 4rpx 12rpx rgba(0, 0, 0, 0.1);
|
||
}
|
||
|
||
50% {
|
||
box-shadow: 0 12rpx 32rpx rgba(0, 0, 0, 0.2),
|
||
0 6rpx 16rpx rgba(0, 0, 0, 0.15);
|
||
}
|
||
}
|
||
|
||
/* 适配小屏幕 */
|
||
@media screen and (max-width: 750rpx) {
|
||
.floating-customer-service {
|
||
width: 100rpx;
|
||
height: 100rpx;
|
||
bottom: 40rpx;
|
||
right: 40rpx;
|
||
|
||
image {
|
||
width: 60rpx;
|
||
height: 60rpx;
|
||
}
|
||
}
|
||
}
|
||
</style> |