订单电量记录

This commit is contained in:
磷叶 2025-01-06 17:37:24 +08:00
parent 48b391a208
commit d653394d6d
10 changed files with 515 additions and 686 deletions

View File

@ -0,0 +1,104 @@
<template>
<div class="dot-status" :class="{ 'is-active': active }">
<el-tooltip :content="active ? activeText : inactiveText" placement="top">
<div class="status-wrapper">
<span class="status-dot"></span>
<span v-if="showText" class="status-text">{{ active ? activeText : inactiveText }}</span>
</div>
</el-tooltip>
</div>
</template>
<script>
export default {
name: 'DotStatus',
props: {
status: {
type: String,
required: true
},
showText: {
type: Boolean,
default: false
},
activeText: {
type: String,
default: '在线'
},
inactiveText: {
type: String,
default: '离线'
},
active: {
type: Boolean,
default: false,
}
},
}
</script>
<style lang="scss" scoped>
.dot-status {
display: inline-flex;
align-items: center;
margin: 0 4px;
.status-wrapper {
display: inline-flex;
align-items: center;
gap: 4px;
}
.status-dot {
display: inline-block;
width: 6px;
height: 6px;
border-radius: 50%;
background-color: #f56c6c;
transition: all 0.3s ease;
position: relative;
&::after {
content: '';
position: absolute;
width: 6px;
height: 6px;
border-radius: 50%;
background-color: inherit;
opacity: 0.5;
animation: pulse 2s infinite;
}
}
.status-text {
font-size: 12px;
color: #f56c6c;
line-height: 1;
}
&.is-active {
.status-dot {
background-color: #67c23a;
}
.status-text {
color: #67c23a;
}
}
}
@keyframes pulse {
0% {
transform: scale(1);
opacity: 0.5;
}
70% {
transform: scale(2);
opacity: 0;
}
100% {
transform: scale(1);
opacity: 0;
}
}
</style>

View File

@ -237,6 +237,13 @@ export const DeviceOnlineStatus = {
OFFLINE: "0", // 离线
}
// 设备状态
export const DeviceStatus = {
FREE: "1", // 空闲
USING: "2", // 使用中
FIXING: "3", // 维修中
}
// 分成状态
export const BonusStatus = {
UN_DIVIDEND: "1", // 未出账

View File

@ -1,55 +0,0 @@
<template>
<div class="device-actions">
<el-button-group>
<el-button size="small" type="primary" plain icon="el-icon-plus" @click="$emit('add-time')">
增加时长
</el-button>
<el-button
size="small"
type="primary"
plain
icon="el-icon-plus"
v-if="showAddEle"
@click="$emit('add-ele')">
增加电量
</el-button>
</el-button-group>
<el-dropdown trigger="click" @command="handleCommand">
<el-button size="small" type="primary" plain>
更多操作<i class="el-icon-arrow-down el-icon--right"></i>
</el-button>
<el-dropdown-menu slot="dropdown">
<el-dropdown-item command="reset">时长归零</el-dropdown-item>
<el-dropdown-item command="resetEle" v-if="showAddEle">电量归零</el-dropdown-item>
<el-dropdown-item command="switch">
{{isOpen ? '强制关闭' : '强制开启'}}
</el-dropdown-item>
<el-dropdown-item command="refresh">刷新设备</el-dropdown-item>
<el-dropdown-item command="qrcode">设备二维码</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
</div>
</template>
<script>
export default {
name: 'DeviceActions',
props: {
isOpen: Boolean,
showAddEle: Boolean
},
methods: {
handleCommand(command) {
this.$emit(command)
}
}
}
</script>
<style lang="scss" scoped>
.device-actions {
display: flex;
gap: 8px;
}
</style>

View File

@ -1,67 +0,0 @@
<template>
<el-card class="device-info" shadow="hover">
<template #header>
<div class="card-header">
<span>设备信息</span>
</div>
</template>
<el-descriptions :column="3" border>
<el-descriptions-item label="MAC-1">
<div class="desc-content">
{{device.mac | defaultValue}}
<dict-tag :options="dict.type.sm_device_online_status" :value="device.onlineStatus1" size="mini"/>
</div>
</el-descriptions-item>
<el-descriptions-item label="MAC-2">
<div class="desc-content">
{{device.mac2 | defaultValue}}
<template v-if="!isEmpty(device.mac2)">
<dict-tag :options="dict.type.sm_device_online_status" :value="device.onlineStatus2" size="mini"/>
</template>
</div>
</el-descriptions-item>
<el-descriptions-item label="设备型号">
{{device.model | defaultValue}}
</el-descriptions-item>
<el-descriptions-item label="产品ID">
{{device.productId | defaultValue}}
</el-descriptions-item>
<el-descriptions-item label="型号功能">
<dict-tag :options="dict.type.sm_model_tag" :value="device.modelTags" size="mini"/>
</el-descriptions-item>
<el-descriptions-item label="设备状态">
<dict-tag :options="dict.type.sm_device_status" :value="device.status" size="mini"/>
</el-descriptions-item>
</el-descriptions>
</el-card>
</template>
<script>
import { isEmpty } from '@/utils'
export default {
name: 'DeviceInfoCard',
props: {
device: {
type: Object,
required: true
}
},
dicts: ['sm_device_online_status', 'sm_model_tag', 'sm_device_status'],
methods: {
isEmpty
}
}
</script>
<style lang="scss" scoped>
.device-info {
margin-bottom: 16px;
.desc-content {
display: flex;
align-items: center;
gap: 8px;
}
}
</style>

View File

@ -1,101 +0,0 @@
<template>
<el-card class="device-overview" shadow="hover">
<el-row type="flex" align="middle" justify="space-between">
<el-col :span="16">
<div class="device-header">
<div class="device-title">
<span class="name">{{device.deviceName || device.deviceNo || '未命名设备'}}</span>
<el-tag size="small" :type="isOpen ? 'success' : 'info'" class="status-tag">
{{isOpen ? '运行中' : '已关闭'}}
</el-tag>
<dict-tag
:options="dict.type.sm_device_online_status"
:value="device.onlineStatus"
size="small"
/>
</div>
<div class="device-meta">
<span class="meta-item">
<i class="el-icon-cpu"></i>
SN: {{device.deviceNo}}
</span>
<span class="meta-item">
<i class="el-icon-connection"></i>
MAC: {{device.mac}}
</span>
<span class="meta-item">
<i class="el-icon-timer"></i>
最后在线: {{device.lastOnlineTime | defaultValue}}
</span>
</div>
</div>
</el-col>
<el-col :span="8">
<div class="action-group">
<slot name="actions"></slot>
</div>
</el-col>
</el-row>
</el-card>
</template>
<script>
export default {
name: 'DeviceOverview',
props: {
device: {
type: Object,
required: true
},
isOpen: {
type: Boolean,
default: false
}
},
dicts: ['sm_device_online_status']
}
</script>
<style lang="scss" scoped>
.device-overview {
margin-bottom: 16px;
.device-header {
.device-title {
display: flex;
align-items: center;
margin-bottom: 12px;
.name {
font-size: 18px;
font-weight: 500;
color: #303133;
margin-right: 12px;
}
.status-tag {
margin-right: 8px;
}
}
.device-meta {
color: #909399;
font-size: 13px;
.meta-item {
margin-right: 24px;
i {
margin-right: 4px;
}
}
}
}
.action-group {
display: flex;
justify-content: flex-end;
gap: 8px;
}
}
</style>

View File

@ -1,88 +0,0 @@
<template>
<el-card class="device-owner" shadow="hover">
<template #header>
<div class="card-header">
<span>归属信息</span>
<div class="header-actions">
<el-button-group v-if="device.agentId">
<el-button size="small" type="danger" plain icon="el-icon-link" @click="$emit('unbind-agent')">
解绑代理商
</el-button>
</el-button-group>
<bind-agent-button v-else :device-id="device.deviceId" @success="$emit('refresh')"/>
<el-button-group v-if="device.userId" style="margin-left: 8px">
<el-button size="small" type="danger" plain icon="el-icon-link" @click="$emit('unbind-mch')">
解绑商户
</el-button>
</el-button-group>
<bind-mch-button v-else :device-id="device.deviceId" @success="$emit('refresh')"/>
</div>
</div>
</template>
<el-descriptions :column="2" border>
<el-descriptions-item label="设备名称">
{{device.deviceName | defaultValue}}
</el-descriptions-item>
<el-descriptions-item label="服务模式">
<dict-tag :options="dict.type.device_service_mode" :value="device.serviceMode" size="small"/>
</el-descriptions-item>
<el-descriptions-item label="所属代理" v-if="device.serviceMode === DeviceServiceMode.AGENT">
<user-link :name="device.agentName" :id="device.agentId"/>
</el-descriptions-item>
<el-descriptions-item label="所属商户">
<user-link :name="device.userName" :id="device.userId"/>
</el-descriptions-item>
<el-descriptions-item label="店铺名称">
<store-link :name="device.storeName" :id="device.storeId"/>
</el-descriptions-item>
<el-descriptions-item label="月费">
{{device.monthFee | money | defaultValue}} /
到期时间{{device.rentTime | defaultValue}}
</el-descriptions-item>
</el-descriptions>
</el-card>
</template>
<script>
import { DeviceServiceMode } from '@/utils/constants'
import UserLink from '@/components/Business/SmUser/UserLink'
import StoreLink from '@/components/Business/Store/StoreLink'
import BindAgentButton from './BindAgentButton'
import BindMchButton from './BindMchButton'
export default {
name: 'DeviceOwnerCard',
components: {
UserLink,
StoreLink,
BindAgentButton,
BindMchButton
},
props: {
device: {
type: Object,
required: true
}
},
dicts: ['device_service_mode'],
computed: {
DeviceServiceMode() {
return DeviceServiceMode
}
}
}
</script>
<style lang="scss" scoped>
.device-owner {
margin-bottom: 16px;
.card-header {
display: flex;
justify-content: space-between;
align-items: center;
}
}
</style>

View File

@ -1,73 +0,0 @@
<template>
<el-card class="device-status" shadow="hover">
<template #header>
<div class="card-header">
<span>实时状态</span>
<span class="update-time">{{updateTime}}</span>
</div>
</template>
<div class="status-list">
<div v-for="(item, index) in statusItems" :key="index" class="status-item">
<span class="item-label">{{item.label}}</span>
<span class="item-value" :class="item.class">{{item.value}}</span>
</div>
</div>
</el-card>
</template>
<script>
export default {
name: 'DeviceStatusCard',
props: {
updateTime: String,
statusItems: {
type: Array,
required: true
}
}
}
</script>
<style lang="scss" scoped>
.device-status {
margin-bottom: 16px;
.card-header {
display: flex;
justify-content: space-between;
align-items: center;
.update-time {
color: #909399;
font-size: 13px;
}
}
.status-list {
.status-item {
padding: 12px 0;
border-bottom: 1px solid #EBEEF5;
&:last-child {
border-bottom: none;
}
.item-label {
display: block;
color: #909399;
font-size: 13px;
margin-bottom: 4px;
}
.item-value {
font-size: 15px;
color: #303133;
&.warning {
color: #E6A23C;
}
}
}
}
}
</style>

View File

@ -1,71 +0,0 @@
<template>
<div>
<el-table v-loading="loading" :data="recordList">
<el-table-column align="center" type="index" label="#"></el-table-column>
<el-table-column align="center" label="时间" prop="createTime"></el-table-column>
<el-table-column align="center" label="用户名称" prop="userName"></el-table-column>
</el-table>
<pagination
:auto-scroll="false"
v-show="total>0"
:total="total"
:page.sync="queryParams.pageNum"
:limit.sync="queryParams.pageSize"
@pagination="getRecordList"
/>
</div>
</template>
<script>
import {listBindRecord} from "@/api/system/bindRecord";
export default {
name: 'suitList',
props: {
// id
deviceId: {
type: String,
default: null
}
},
data() {
return {
recordList: [], //
loading: false,
total: 0,
queryParams: {
pageNum: 1,
pageSize: 20,
deviceId: null,
}
}
},
watch: {
deviceId(nv, ov) {
this.getRecordList(nv);
}
},
created() {
this.getRecordList(this.deviceId);
},
methods: {
//
getRecordList(deviceId) {
if(deviceId == null) {
this.recordList = [];
this.total = 0;
return;
}
this.loading = true;
this.queryParams.deviceId = deviceId | this.deviceId;
listBindRecord(this.queryParams).then(response => {
this.recordList = response.rows;
this.total = response.total;
}).finally(() => {
this.loading = false;
});
}
}
}
</script>

View File

@ -1,75 +0,0 @@
<template>
<div>
<el-table v-loading="loading" :data="tenantList">
<el-table-column align="center" type="index" label="#"></el-table-column>
<el-table-column align="center" label="头像" prop="avatar">
<template slot-scope="d">
<image-preview :src="d.row.avatar" :width="50" :height="50"/>
</template>
</el-table-column>
<el-table-column align="center" label="用户名称" prop="userName"></el-table-column>
</el-table>
<pagination
:auto-scroll="false"
v-show="total>0"
:total="total"
:page.sync="queryParams.pageNum"
:limit.sync="queryParams.pageSize"
@pagination="getUserList"
/>
</div>
</template>
<script>
import {listSmUser} from "@/api/system/smUser";
export default {
name: 'tenantList',
props: {
// id
deviceId: {
type: String,
default: null
}
},
data() {
return {
tenantList: [], //
loading: false,
total: 0,
queryParams: {
pageNum: 1,
pageSize: 20,
tenantDeviceId: null,
}
}
},
watch: {
deviceId(nv, ov) {
this.getUserList(nv);
}
},
created() {
this.getUserList(this.deviceId);
},
methods: {
//
getUserList(deviceId) {
if(deviceId == null) {
this.recordList = [];
this.total = 0;
return;
}
this.loading = true;
this.queryParams.tenantDeviceId = deviceId | this.deviceId;
listSmUser(this.queryParams).then(response => {
this.tenantList = response.rows;
this.total = response.total;
}).finally(() => {
this.loading = false;
});
}
}
}
</script>

View File

@ -1,71 +1,232 @@
<template>
<div class="app-container" v-loading="loading" >
<div v-if="deviceData">
<el-row :gutter="16">
<el-col :lg="18" :xs="24">
<el-card class="box-card" >
<el-descriptions title="设备信息" :column="4">
<template slot="extra">
<el-button size="small" plain icon="el-icon-plus" @click="handleAddTime">增加时长</el-button>
<el-button size="small" plain icon="el-icon-plus" @click="handleAddEle" v-if="deviceData.modelTags.includes(ModelTag.ELE)">增加电量</el-button>
<el-button size="small" plain icon="el-icon-refresh" @click="handleReset">时长归零</el-button>
<el-button size="small" plain icon="el-icon-refresh" @click="handleResetEle" v-if="deviceData.modelTags.includes(ModelTag.ELE)">电量归零</el-button>
<el-button size="small" plain type="warning" icon="el-icon-switch-button" v-if="!isOpen" @click="handleSwitch(true)">强制开启</el-button>
<el-button size="small" plain type="warning" icon="el-icon-switch-button" v-if="isOpen" @click="handleSwitch(false)">强制关闭</el-button>
<el-button size="small" plain icon="el-icon-refresh" @click="refreshIot(deviceId, true, DeviceOnlineType.COMMAND)" style="margin-right: 1em">刷新设备信息</el-button>
<el-popover
placement="left"
width="180"
trigger="click">
<div class="qr-code-box">
<qr-code :text="qrCodeText(deviceData)" :width="150" :height="150" />
<p>扫描二维码进行设备绑定</p>
</div>
<el-button size="small" slot="reference" type="primary" icon="el-icon-picture">设备二维码</el-button>
</el-popover>
</template>
<el-descriptions-item label="MAC-1">
{{deviceData.mac | defaultValue}}
<dict-tag :options="dict.type.sm_device_online_status" :value="deviceData.onlineStatus1" size="mini"/>
</el-descriptions-item>
<el-descriptions-item label="MAC-2">
{{deviceData.mac2 | defaultValue}}
<template v-if="!isEmpty(deviceData.mac2)">
<dict-tag :options="dict.type.sm_device_online_status" :value="deviceData.onlineStatus2" size="mini"/>
</template>
</el-descriptions-item>
<el-descriptions-item label="SN">
{{deviceData.deviceNo | defaultValue}}
</el-descriptions-item>
<el-descriptions-item label="设备状态">
<dict-tag :options="dict.type.sm_device_status" :value="deviceData.status" size="mini"/>
</el-descriptions-item>
<el-descriptions-item label="型号">{{deviceData.model | defaultValue}}</el-descriptions-item>
<el-descriptions-item label="产品ID">{{deviceData.productId | defaultValue}}</el-descriptions-item>
<el-descriptions-item label="型号功能" :span="2">
<dict-tag :options="dict.type.sm_model_tag" :value="deviceData.modelTags" size="mini"/>
</el-descriptions-item>
<el-descriptions-item label="限制充值时间">
{{deviceData.limitRechargeTime | defaultValue}}
<boolean-tag v-if="deviceData.limitRechargeTime != null" :value="!isLimitRecharge" size="small" true-text="限制充值中" false-text="已解封"/>
</el-descriptions-item>
<el-descriptions-item label="限制充值原因">
{{deviceData.limitRechargeReason | defaultValue}}
</el-descriptions-item>
<el-descriptions-item label="用户手动操作时间">
{{deviceData.userOperaTime | defaultValue}}
</el-descriptions-item>
<el-descriptions-item label="用户手动操作电量">
{{deviceData.userOpereEle | defaultValue}}
</el-descriptions-item>
<el-descriptions-item label="用户手动操作类型">
<dict-tag :options="dict.type.device_user_opera_type" :value="deviceData.userOperaType" size="mini"/>
</el-descriptions-item>
</el-descriptions>
</el-card>
<el-card class="device-info-card">
<!-- 设备基本信息展示区 -->
<div class="device-info-container">
<div class="device-header">
<!-- 主要信息 -->
<div class="device-title">
<i class="el-icon-monitor"></i>
<span class="device-name">{{deviceData.deviceName | defaultValue}}</span>
<dot-status :active="deviceData.onlineStatus === DeviceOnlineStatus.ONLINE" show-text/>
<dot-status :active="isOpen" show-text active-text="已开启" inactive-text="已关闭"/>
<dot-status :active="deviceData.status === DeviceStatus.FREE" show-text active-text="空闲" inactive-text="使用中"/>
<span class="last-online-time">
<i class="el-icon-time"></i>
最后在线:
{{deviceData.lastOnlineTime | defaultValue}}
</span>
</div>
<!-- 操作按钮组 -->
<el-row class="device-actions">
<el-button size="small" plain icon="el-icon-plus" @click="handleAddTime">增加时长</el-button>
<el-button size="small" plain icon="el-icon-plus" @click="handleAddEle" v-if="deviceData.modelTags.includes(ModelTag.ELE)">增加电量</el-button>
<el-button size="small" plain icon="el-icon-refresh" @click="handleReset">时长归零</el-button>
<el-button size="small" plain icon="el-icon-refresh" @click="handleResetEle" v-if="deviceData.modelTags.includes(ModelTag.ELE)">电量归零</el-button>
<el-button size="small" plain type="warning" icon="el-icon-switch-button" v-if="!isOpen" @click="handleSwitch(true)">强制开启</el-button>
<el-button size="small" plain type="warning" icon="el-icon-switch-button" v-if="isOpen" @click="handleSwitch(false)">强制关闭</el-button>
<el-button size="small" plain icon="el-icon-refresh" @click="refreshIot(deviceId, true, DeviceOnlineType.COMMAND)">刷新设备信息</el-button>
<el-popover
placement="left"
width="180"
trigger="click">
<div class="qr-code-box">
<qr-code :text="qrCodeText(deviceData)" :width="150" :height="150" />
<p>扫描二维码进行设备绑定</p>
</div>
<el-button size="small" slot="reference" type="primary" icon="el-icon-picture">设备二维码</el-button>
</el-popover>
</el-row>
</div>
<!-- 次要信息 -->
<div class="device-info">
<div class="info-item">
<i class="el-icon-document"></i>
<span class="label">SN:</span>
<span>{{deviceData.deviceNo | defaultValue}}</span>
</div>
<div class="info-item">
<i class="el-icon-connection"></i>
<span class="label">MAC-1:</span>
<span>{{deviceData.mac | defaultValue}}</span>
<dot-status v-if="deviceData.mac" :active="deviceData.onlineStatus1 === DeviceOnlineStatus.ONLINE"/>
</div>
<div class="info-item">
<i class="el-icon-connection"></i>
<span class="label">MAC-2:</span>
<span>{{deviceData.mac2 | defaultValue}}</span>
<dot-status v-if="deviceData.mac2" :active="deviceData.onlineStatus2 === DeviceOnlineStatus.ONLINE"/>
</div>
<div class="info-item">
<i class="el-icon-cpu"></i>
<span class="label">型号:</span>
<span>{{deviceData.model | defaultValue}}</span>
</div>
<div class="info-item">
<i class="el-icon-cpu"></i>
<span class="label">产品ID:</span>
<span>{{deviceData.productId | defaultValue}}</span>
</div>
<div class="info-item">
<i class="el-icon-odometer"></i>
<span class="label">版本号:</span>
<span>{{deviceData.version | defaultValue}}</span>
</div>
<div class="info-item" v-if="deviceData.modelTags.includes(ModelTag.WIFI)">
<i class="el-icon-wifi"></i>
<span class="label">WIFI:</span>
<span>{{deviceData.wifi | defaultValue}}</span>
</div>
<div class="info-item">
<i class="el-icon-collection-tag"></i>
<span class="label">功能:</span>
<dict-tag :options="dict.type.sm_model_tag" :value="deviceData.modelTags" size="mini"/>
</div>
</div>
</div>
</el-card>
<el-row :gutter="16">
<el-col :lg="16" :xs="24">
<el-card class="box-card">
<el-descriptions title="归属信息" :column="4">
<template #header>
<el-row type="flex" style="justify-content: space-between;align-items: center">
<div class="card-title">
<i class="el-icon-data-line"></i>
实时信息
</div>
<div class="last-update-time">
<i class="el-icon-time"></i>
最后更新: {{deviceData.lastPullTime | defaultValue}}
</div>
</el-row>
</template>
<div class="realtime-info">
<el-row :gutter="16">
<!-- 时长信息 -->
<el-col :span="12">
<div class="info-section">
<div class="section-title">
<span><i class="el-icon-timer"></i>时长信息</span>
</div>
<div class="data-grid">
<div class="data-item">
<div class="item-label">剩余时长数据库</div>
<div class="item-value">{{surplusTimeDesc(surplusTime).text}}</div>
</div>
<div class="data-item">
<div class="item-label">剩余时长设备</div>
<div class="item-value">{{surplusTimeDesc(deviceData.remainTime).text}}</div>
</div>
</div>
</div>
</el-col>
<!-- 电量信息 -->
<el-col :span="12">
<div class="info-section">
<div class="section-title">
<span><i class="el-icon-lightning"></i>电量信息</span>
</div>
<div class="data-grid">
<div class="data-item">
<div class="item-label">剩余电量数据库</div>
<div class="item-value">{{deviceData.surplusEleDb | fix2}} </div>
</div>
<div class="data-item">
<div class="item-label">剩余电量设备</div>
<div class="item-value">{{deviceData.surplusEle | fix2}} </div>
</div>
</div>
</div>
</el-col>
<!-- 电力参数 -->
<el-col :span="12">
<div class="info-section">
<div class="section-title">
<span><i class="el-icon-odometer"></i>电力参数</span>
</div>
<div class="data-grid">
<div class="data-item">
<div class="item-label">电压</div>
<div class="item-value">{{deviceData.voltage | fix2}} V</div>
</div>
<div class="data-item">
<div class="item-label">电流</div>
<div class="item-value">{{deviceData.electricity | fix2}} A</div>
</div>
<div class="data-item">
<div class="item-label">功率</div>
<div class="item-value">{{deviceData.realTimePower | fix2}} W</div>
</div>
<div class="data-item">
<div class="item-label">电压系数</div>
<div class="item-value">{{deviceData.vxs | fix3 | defaultValue}}</div>
</div>
</div>
</div>
</el-col>
<!-- 累计用电信息 -->
<el-col :span="12">
<div class="info-section">
<div class="section-title">
<span><i class="el-icon-reading"></i>累计用电</span>
<div class="reset-time">
最近重置: {{deviceData.lastInitReading | defaultValue}}
</div>
</div>
<div class="data-grid">
<div class="data-item">
<div class="item-label">累计用电量</div>
<div class="item-value">{{deviceData.totalElectriQuantity | money | defaultValue}} </div>
</div>
<div class="data-item">
<div class="item-label">
电量读数
<el-tooltip content="重置读数" placement="top">
<el-link @click="handleInitReading" type="primary" icon="el-icon-refresh" class="reset-btn"></el-link>
</el-tooltip>
</div>
<div class="item-value">{{deviceData.totalElectriQuantity - deviceData.initReading | money | defaultValue}} </div>
</div>
</div>
</div>
</el-col>
</el-row>
</div>
</el-card>
<el-card class="box-card" >
<el-descriptions title="系统信息" :column="4">
<el-descriptions-item label="限制充值时间">
{{deviceData.limitRechargeTime | defaultValue}}
<boolean-tag v-if="deviceData.limitRechargeTime != null" :value="!isLimitRecharge" size="small" true-text="限制充值中" false-text="已解封"/>
</el-descriptions-item>
<el-descriptions-item label="限制充值原因">
{{deviceData.limitRechargeReason | defaultValue}}
</el-descriptions-item>
<el-descriptions-item label="用户手动操作时间">
{{deviceData.userOperaTime | defaultValue}}
</el-descriptions-item>
<el-descriptions-item label="用户手动操作电量">
{{deviceData.userOpereEle | defaultValue}}
</el-descriptions-item>
<el-descriptions-item label="用户手动操作类型">
<dict-tag :options="dict.type.device_user_opera_type" :value="deviceData.userOperaType" size="mini"/>
</el-descriptions-item>
</el-descriptions>
</el-card>
</el-col>
<el-col :lg="8" :xs="24">
<el-card class="box-card">
<el-descriptions title="归属信息" :column="2">
<template #extra>
<el-row type="flex">
<el-button size="small" plain icon="el-icon-link" type="danger" @click="handleUnbindAgent" v-if="deviceData.agentId != null">解绑代理商</el-button>
@ -74,7 +235,6 @@
<bind-mch-button v-else :device-id="deviceData.deviceId" @success="getDevice" style="margin-left: 0.5em"/>
</el-row>
</template>
<el-descriptions-item label="设备名称">{{deviceData.deviceName | defaultValue}}</el-descriptions-item>
<el-descriptions-item label="服务模式">
<dict-tag :options="dict.type.device_service_mode" :value="deviceData.serviceMode" size="small"/>
</el-descriptions-item>
@ -100,39 +260,6 @@
<el-descriptions-item label="备注">{{deviceData.remark | defaultValue}}</el-descriptions-item>
</el-descriptions>
</el-card>
<el-card class="box-card">
<el-descriptions :column="4" title="物联网信息">
<el-descriptions-item label="在线状态">
<dict-tag :options="dict.type.sm_device_online_status" :value="deviceData.onlineStatus" size="mini"/>
</el-descriptions-item>
<el-descriptions-item label="最后在线时间">
{{deviceData.lastOnlineTime | defaultValue}}
</el-descriptions-item>
<el-descriptions-item label="版本号">
{{deviceData.version | defaultValue}}
</el-descriptions-item>
<el-descriptions-item label="WIFI" v-if="deviceData.modelTags.includes(ModelTag.WIFI)">
{{deviceData.wifi | defaultValue}}
<el-link @click="handleSetWifi" type="primary" icon="el-icon-link" style="margin-left: 0.5em">远程配网</el-link>
</el-descriptions-item>
<el-descriptions-item label="开关状态">
<el-tag :type="isOpen ? 'success' : 'danger'" size="mini">{{isOpen ? '已开启' : '已关闭'}}</el-tag>
</el-descriptions-item>
<el-descriptions-item label="总用电量">
{{deviceData.totalElectriQuantity | money | defaultValue}}
</el-descriptions-item>
<el-descriptions-item label="电量读数">
{{deviceData.totalElectriQuantity - deviceData.initReading | money | defaultValue}}
<el-link @click="handleInitReading" type="primary" icon="el-icon-refresh" style="margin-left: 0.5em">重置</el-link>
</el-descriptions-item>
<el-descriptions-item label="最近重置读数时间">
{{deviceData.lastInitReading | defaultValue}}
</el-descriptions-item>
</el-descriptions>
</el-card>
</el-col>
<el-col :lg="6" :xs="24">
<el-card class="box-card" header="分成信息">
<line-field v-for="bonus of deviceData.bonusList" :label="bonus.arrivalName">
<template #label>
@ -144,47 +271,6 @@
<template>{{bonus.point | money | defaultValue }} %</template>
</line-field>
</el-card>
<el-card class="box-card">
<template #header>
<el-row type="flex" style="justify-content: space-between;align-items: center">
<div>实时信息</div>
<div>{{deviceData.lastPullTime | defaultValue}}</div>
</el-row>
</template>
<el-row>
<el-col :span="12">
<el-statistic style="margin-bottom: 8px" title="时长(数据库)">
<template #formatter>{{surplusTimeDesc(surplusTime).text}}</template>
</el-statistic>
</el-col>
<el-col :span="12">
<el-statistic style="margin-bottom: 8px" title="时长(设备)">
<template #formatter>{{surplusTimeDesc(deviceData.remainTime).text}}</template>
</el-statistic>
</el-col>
<el-col :span="12">
<el-statistic style="margin-bottom: 8px" title="电量(数据库)" :value="deviceData.surplusEleDb" :precision="2" suffix="度"/>
</el-col>
<el-col :span="12">
<el-statistic style="margin-bottom: 8px" title="电量(设备)" :value="deviceData.surplusEle" :precision="2" suffix="度"/>
</el-col>
<el-col :span="12">
<el-statistic style="margin-bottom: 8px" title="电压" :value="deviceData.voltage" :precision="2" suffix="V"/>
</el-col>
<el-col :span="12">
<el-statistic style="margin-bottom: 8px" title="电流" :value="deviceData.electricity" :precision="2" suffix="A"/>
</el-col>
<el-col :span="12">
<el-statistic style="margin-bottom: 8px" title="功率" :value="deviceData.realTimePower" :precision="2" suffix="W"/>
</el-col>
<el-col :span="12">
<el-statistic style="margin-bottom: 8px" title="电压系数">
<template #formatter>{{deviceData.vxs | fix3 | defaultValue}}</template>
</el-statistic>
</el-col>
</el-row>
</el-card>
</el-col>
</el-row>
@ -206,9 +292,6 @@
<el-tab-pane label="命令日志" :lazy="true">
<command-log :query="{macList: macList}" :views="views.device"/>
</el-tab-pane>
<!-- <el-tab-pane label="时长/电量变化" :lazy="true">
<record-time :query="{deviceId: deviceData.deviceId}" view="device"/>
</el-tab-pane> -->
<el-tab-pane label="抄表记录" :lazy="true">
<reading-record :device-id="deviceData.deviceId"/>
</el-tab-pane>
@ -263,8 +346,6 @@ import ReadingRecord from "@/views/system/device/components/readingRecord.vue";
import {getWxIndexUrl} from "@/utils/wx";
import BindRecord from "@/views/system/bindRecord/index.vue";
import ResetRecord from "@/views/system/device/components/resetRecord.vue";
import TenantList from "@/views/system/device/components/tenantList.vue";
import SuitList from '@/views/system/device/components/suitList.vue'
import Suit from '@/views/ss/suit/index.vue'
import RecordTime from '@/views/ss/time/index.vue'
import { toDescriptionFromSecond } from '@/utils/date'
@ -273,13 +354,14 @@ import UserLink from '@/components/Business/SmUser/UserLink.vue'
import { $serviceType, $view } from '@/utils/mixins'
import Recharge from '@/views/system/recharge/index.vue'
import BooleanTag from '@/components/BooleanTag/index.vue'
import { DeviceOnlineStatus, DeviceServiceMode, ModelTag, DeviceOnlineType } from '@/utils/constants'
import { DeviceOnlineStatus, DeviceServiceMode, ModelTag, DeviceOnlineType, DeviceStatus } from '@/utils/constants'
import { isEmpty } from '@/utils'
import BindMchButton from '@/views/system/device/components/BindMchButton.vue'
import BindAgentButton from '@/views/system/device/components/BindAgentButton.vue'
import LineField from '@/components/LineField/index.vue'
import DeviceSetWifiDialog from '@/views/system/device/components/DeviceSetWifiDialog.vue'
import CommandLog from "@/views/ss/commandLog/index.vue";
import DotStatus from '@/components/DotStatus/index.vue'
export default {
name: 'Device/:deviceId',
@ -296,9 +378,7 @@ export default {
UserLink,
StoreLink,
RecordTime,
Suit,
SuitList,
TenantList, ResetRecord, BindRecord, ReadingRecord, MeterRecordReport, QrCode, RechargeRecord, LineChart},
Suit, ResetRecord, BindRecord, ReadingRecord, MeterRecordReport, QrCode, RechargeRecord, LineChart, DotStatus},
data() {
return {
showSetWifi: false,
@ -322,6 +402,7 @@ export default {
// ID
deviceId: null,
DeviceOnlineStatus,
DeviceStatus,
ModelTag,
DeviceServiceMode,
DeviceOnlineType
@ -562,15 +643,182 @@ export default {
}
</script>
<style scoped lang="scss">
.remark-text {
color: #ccc;
margin-left: 1em;
}
.statistic {
margin-bottom: 1em;
.el-tag {
line-height: 26px !important;
<style lang="scss" scoped>
.device-info-card {
margin-bottom: 12px;
.device-info-container {
.device-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 12px;
.device-title {
display: flex;
align-items: center;
i {
font-size: 20px;
color: #409EFF;
margin-right: 8px;
}
.device-name {
font-size: 18px;
font-weight: bold;
margin-right: 6px;
}
.last-online-time {
color: #909399;
font-size: 12px;
font-weight: normal;
margin-left: 8px;
i {
font-size: 13px;
margin-right: 0;
color: #909399;
}
}
}
.device-actions {
display: flex;
flex-wrap: wrap;
justify-content: flex-end;
}
}
.device-info {
display: flex;
flex-wrap: wrap;
padding: 12px;
background: #f5f7fa;
border-radius: 4px;
&.model-tags {
margin-top: 8px;
}
.info-item {
display: flex;
align-items: center;
font-size: 12px;
color: #606266;
margin-right: 16px;
i {
font-size: 14px;
color: #909399;
margin-right: 4px;
}
.label {
color: #909399;
margin-right: 4px;
}
:deep(.el-tag) {
margin-right: 4px;
}
}
}
}
}
.box-card {
margin-bottom: 12px;
:deep(.el-card__body) {
padding: 12px;
}
.card-title {
font-size: 16px;
font-weight: 500;
display: flex;
align-items: center;
i {
margin-right: 8px;
color: #409EFF;
}
}
.last-update-time {
color: #909399;
font-size: 13px;
i {
margin-right: 4px;
}
}
.realtime-info {
.info-section {
background: #f8f9fa;
border-radius: 6px;
padding: 12px;
margin-bottom: 12px;
height: calc(100% - 12px);
.section-title {
width: 100%;
font-size: 13px;
font-weight: 500;
color: #606266;
margin-bottom: 12px;
display: flex;
align-items: center;
justify-content: space-between;
i {
margin-right: 4px;
color: #409EFF;
}
.reset-time {
font-size: 12px;
color: #909399;
text-align: right;
}
}
.data-grid {
display: flex;
flex-wrap: nowrap;
.data-item {
flex: 1;
border-radius: 4px;
.item-label {
color: #909399;
font-size: 12px;
display: flex;
align-items: center;
white-space: nowrap;
.reset-btn {
font-size: 12px;
padding: 0 2px;
margin-left: 4px;
}
}
.item-value {
margin-top: 8px;
font-size: 14px;
font-weight: 500;
color: #303133;
}
}
}
}
}
}
</style>