This commit is contained in:
磷叶 2025-03-01 18:02:57 +08:00
parent 19e4d729cb
commit 92fe012388
7 changed files with 398 additions and 116 deletions
src
api/system
components
Business
CollapsePanel
views/system/device

View File

@ -207,3 +207,15 @@ export function deviceInitTotalEle(deviceId) {
method: 'put'
})
}
// 修改电量系数
export function deviceSetWxs(deviceId, wxs) {
return request({
url: `/system/device/setWxs`,
method: 'put',
data: {
deviceId,
wxs
}
})
}

View File

@ -27,7 +27,7 @@ export default {
props:{
size: {
type: String,
default: "medium"
default: null
},
placeholder: {
type: String,

View File

@ -96,7 +96,7 @@ export default {
//
size: {
type: String,
default: "medium"
default: null
},
//
disabled: {

View File

@ -0,0 +1,75 @@
<template>
<div>
<div class="collapse-title" @click="onChange" >
<div class="title-text">{{title}}</div>
<el-link type="primary" :underline="false">
<template v-if="show">
收起<i class="el-icon-arrow-up"/>
</template>
<template v-else>
展开<i class="el-icon-arrow-down"/>
</template>
</el-link>
</div>
<div class="collapse-content">
<el-collapse-transition>
<div v-show="show">
<slot></slot>
</div>
</el-collapse-transition>
</div>
</div>
</template>
<script>
export default {
name: "CollapsePanel",
props: {
title: {
type: String,
default: null
},
value: {
type: Boolean,
default: false
}
},
data() {
return {
show: this.value
}
},
watch: {
value(val) {
this.show = val;
}
},
methods: {
onChange() {
this.show = !this.show;
this.$emit('input', this.show);
}
}
}
</script>
<style scoped lang="scss">
.collapse-title {
display: flex;
justify-content: space-between;
margin-bottom: 8px;
background-color: #e1dfff2c;
padding: 8px;
border-radius: 8px;
cursor: pointer;
transition: .25s;
&:hover {
background-color: #a39ef925;
}
.title-text {
font-size: 14px;
color: #8883F0;
flex: 1;
}
}
</style>

View File

@ -0,0 +1,230 @@
<template>
<el-dialog :visible.sync="dialogVisible" :title="title" @open="handleOpen" :close-on-click-modal="false" width="900px" append-to-body>
<el-form ref="form" :model="form" size="small" :rules="rules" label-width="6em">
<el-row :gutter="gutter">
<form-col :span="span" label="自定义图片" prop="customPicture">
<image-upload v-model="form.customPicture" :limit="1" :is-show-tip="false"/>
</form-col>
<form-col :span="span" label="型号" prop="modelId">
<model-select v-model="form.modelId" :show-value.sync="form.model" @submit="onSubmitModel"/>
</form-col>
<form-col :span="span" label="MAC-1" prop="mac">
<el-input v-model="form.mac" placeholder="请输入设备MAC-1"/>
</form-col>
<form-col :span="span" label="MAC-2" prop="mac2">
<el-input v-model="form.mac2" placeholder="请输入设备MAC-2"/>
</form-col>
<form-col :span="span" label="SN" prop="deviceNo">
<el-input v-model="form.deviceNo" placeholder="请输入设备SN" />
</form-col>
<form-col :span="span *2" label="名称" prop="deviceName">
<el-input v-model="form.deviceName" placeholder="请输入设备名称" />
</form-col>
<form-col :span="span * 2" label="备注" prop="remark">
<el-input v-model="form.remark" type="textarea" placeholder="请输入备注" maxlength="500" show-word-limit/>
</form-col>
</el-row>
<collapse-panel title="费用设置" :value="true">
<el-row :gutter="gutter">
<form-col :span="12" label="服务模式" prop="serviceMode">
<el-radio-group v-model="form.serviceMode">
<el-radio v-for="item of dict.type.device_service_mode" :label="item.value" :key="item.value">{{item.label}}</el-radio>
</el-radio-group>
</form-col>
<template v-if="form.serviceMode === DeviceServiceMode.AGENT">
<form-col :span="12" label="代理商" prop="agentId">
<user-input v-model="form.agentId" :query="{type: SmUserType.AGENT}" />
</form-col>
<form-col :span="12" label="代理服务费" prop="agentServiceRate" label-width="7em">
<el-input v-model="form.agentServiceRate" placeholder="请输入代理服务费" type="number">
<template #append>%</template>
</el-input>
</form-col>
</template>
<template v-else>
<form-col :span="12" label="服务费" prop="serviceRate">
<el-input v-model="form.serviceRate" placeholder="请输入服务费" type="number">
<template #append>%</template>
</el-input>
</form-col>
</template>
<form-col :span="12" label="设备月费" prop="monthFee">
<el-input v-model="form.monthFee" placeholder="请输入月费" type="number" :min="0">
<template #append>
/
</template>
</el-input>
</form-col>
</el-row>
</collapse-panel>
<collapse-panel title="风控设置" :value="true">
<el-row :gutter="gutter">
<form-col :span="12" label="限制充值" prop="limitRechargeTime">
<el-date-picker type="datetime" v-model="form.limitRechargeTime" style="width: 100%" placeholder="请选择限制充值时间" value-format="yyyy-MM-dd HH:mm:ss" :clearable="false"/>
</form-col>
<form-col :span="12" label="限制原因" prop="limitRechargeReason">
<el-input v-model="form.limitRechargeReason" type="textarea" placeholder="请输入限制充值的原因(展示给用户查看)" show-word-limit maxlength="200"/>
</form-col>
</el-row>
</collapse-panel>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button type="primary" @click="submitForm"> </el-button>
<el-button @click="cancel"> </el-button>
</div>
</el-dialog>
</template>
<script>
import { getDevice, addDevice, updateDevice } from '@/api/system/device'
import ModelSelect from "@/components/Business/Model/modelSelect.vue";
import UserInput from '@/components/Business/SmUser/UserInput.vue'
import { DeviceServiceMode, SmUserType } from '@/utils/constants'
import CollapsePanel from '@/components/CollapsePanel/index.vue'
export default {
name: 'DeviceEditDialog',
components: { UserInput, ModelSelect, CollapsePanel },
dicts: ['device_service_mode'],
props: {
visible: {
type: Boolean,
default: false
},
deviceId: {
type: String,
default: null,
}
},
data() {
return {
showFee: true,
form: {
deviceId: null,
picture: null,
modelId: null,
mac: null,
deviceNo: null,
deviceName: null,
serviceType: '1',
serviceRate: null,
remark: null,
startTime: null,
startUnit: "3",
startPrice: null,
overTime: null,
overUnit: "3",
overPrice: null,
serviceMode: '1'
},
span: 8,
gutter: 8,
rules: {
modelId: [
{ required: true, message: "型号不能为空", trigger: "change" }
],
mac: [
{ required: true, message: "设备MAC不能为空", trigger: "change" }
],
serviceMode: [
{ required: true, message: "服务模式不能为空", trigger: "change" }
],
agentId: [
{ required: true, message: "代理商不能为空", trigger: "change" }
],
agentServiceRate: [
{ required: true, message: "代理商服务费率不能为空", trigger: "blur" }
]
}
}
},
computed: {
title() {
return this.form.deviceId == null ? '新增设备' : '修改设备';
},
dialogVisible: {
get() {
return this.visible;
},
set(val) {
this.$emit('update:visible', val);
}
},
DeviceServiceMode() {
return DeviceServiceMode
},
SmUserType() {
return SmUserType
}
},
methods: {
handleOpen() {
if (this.deviceId != null) {
getDevice(this.deviceId).then(response => {
this.form = response.data;
});
} else {
this.reset();
}
},
reset() {
this.form = {
deviceId: null,
picture: null,
modelId: null,
mac: null,
deviceNo: null,
deviceName: null,
serviceType: '1',
serviceRate: null,
remark: null,
startTime: null,
startUnit: "3",
startPrice: null,
overTime: null,
overUnit: "3",
overPrice: null,
serviceMode: '1'
};
this.$nextTick(() => {
this.$refs.form?.resetFields();
});
},
cancel() {
this.dialogVisible = false;
this.reset();
},
onSubmitModel(model) {
this.form.model = model?.modelName;
//
if (this.form.deviceId == null) {
this.form.serviceType = model?.serviceType;
this.form.serviceRate = model?.serviceRate;
}
},
submitForm() {
this.$refs.form.validate(valid => {
if (valid) {
if (this.form.deviceId != null) {
updateDevice(this.form).then(response => {
this.$modal.msgSuccess("修改成功");
this.dialogVisible = false;
this.$emit('success');
});
} else {
addDevice(this.form).then(response => {
this.$modal.msgSuccess("新增成功");
this.dialogVisible = false;
this.$emit('success');
});
}
}
});
}
}
}
</script>
<style lang="scss" scoped>
</style>

View File

@ -8,7 +8,7 @@
<!-- 主要信息 -->
<div class="device-title">
<i class="el-icon-monitor"></i>
<span class="device-name">{{deviceData.deviceName | defaultValue}}</span>
<span class="device-name">{{deviceData.deviceName | dv}}</span>
<dot-status :active="deviceData.onlineStatus === DeviceOnlineStatus.ONLINE" show-text/>
<dot-status :active="isOpen" show-text active-text="已开启" inactive-text="已关闭"/>
<dot-status
@ -20,7 +20,7 @@
<span class="last-online-time">
<i class="el-icon-time"></i>
最后在线:
{{deviceData.lastOnlineTime | defaultValue}}
{{deviceData.lastOnlineTime | dv}}
</span>
</div>
@ -44,44 +44,44 @@
<div class="info-item">
<i class="el-icon-document"></i>
<span class="label">SN:</span>
<span>{{deviceData.deviceNo | defaultValue}}</span>
<span>{{deviceData.deviceNo | dv}}</span>
</div>
<div class="info-item">
<i class="el-icon-connection"></i>
<span class="label">MAC-1:</span>
<span>{{deviceData.mac | defaultValue}}</span>
<span>{{deviceData.mac | dv}}</span>
<dot-status v-if="deviceData.mac" :active="deviceData.onlineStatus1 === DeviceOnlineStatus.ONLINE"/>
</div>
<div class="info-item" v-if="deviceData.mac2">
<i class="el-icon-connection"></i>
<span class="label">MAC-2:</span>
<span>{{deviceData.mac2 | defaultValue}}</span>
<span>{{deviceData.mac2 | dv}}</span>
<dot-status :active="deviceData.onlineStatus2 === DeviceOnlineStatus.ONLINE"/>
</div>
<div class="info-item">
<i class="el-icon-collection-tag"></i>
<span class="label">型号:</span>
<span>{{deviceData.model | defaultValue}}</span>
<span>{{deviceData.model | dv}}</span>
</div>
<div class="info-item">
<i class="el-icon-cpu"></i>
<span class="label">SIM卡:</span>
{{deviceData.imsi | defaultValue}}
{{deviceData.imsi | dv}}
</div>
<div class="info-item">
<i class="el-icon-cpu"></i>
<span class="label">产品ID:</span>
<span>{{deviceData.productId | defaultValue}}</span>
<span>{{deviceData.productId | dv}}</span>
</div>
<div class="info-item">
<i class="el-icon-odometer"></i>
<span class="label">版本号:</span>
<span>{{deviceData.version | defaultValue}}</span>
<span>{{deviceData.version | dv}}</span>
</div>
<div class="info-item" v-if="deviceData.modelTags.includes(ModelTag.WIFI)">
<i class="el-icon-magic-stick"></i>
<span class="label">WIFI:</span>
<span>{{deviceData.wifi | defaultValue}}</span>
<span>{{deviceData.wifi | dv}}</span>
</div>
<div class="info-item">
<i class="el-icon-open"></i>
@ -109,7 +109,7 @@
</div>
<div class="last-update-time">
<i class="el-icon-time"></i>
最后更新: {{deviceData.lastPullTime | defaultValue}}
最后更新: {{deviceData.lastPullTime | dv}}
</div>
</el-row>
</template>
@ -125,11 +125,11 @@
<div class="data-grid">
<div class="data-item">
<div class="item-label">剩余时长数据库</div>
<div class="item-value">{{surplusTimeDesc(surplusTime).text}}</div>
<div class="item-value">{{surplusTimeDesc(surplusTime).text | dv}}</div>
</div>
<div class="data-item">
<div class="item-label">剩余时长设备</div>
<div class="item-value">{{surplusTimeDesc(deviceData.remainTime).text}}</div>
<div class="item-value">{{surplusTimeDesc(deviceData.remainTime).text | dv}}</div>
</div>
</div>
</div>
@ -144,11 +144,11 @@
<div class="data-grid">
<div class="data-item">
<div class="item-label">剩余电量数据库</div>
<div class="item-value">{{deviceData.surplusEleDb | fix2}} </div>
<div class="item-value">{{deviceData.surplusEleDb | fix2 | dv}} </div>
</div>
<div class="data-item">
<div class="item-label">剩余电量设备</div>
<div class="item-value">{{deviceData.surplusEle | fix2}} </div>
<div class="item-value">{{deviceData.surplusEle | fix2 | dv}} </div>
</div>
</div>
</div>
@ -163,19 +163,19 @@
<div class="data-grid">
<div class="data-item">
<div class="item-label">电压</div>
<div class="item-value">{{deviceData.voltage | fix2}} V</div>
<div class="item-value">{{deviceData.voltage | fix2 | dv}} V</div>
</div>
<div class="data-item">
<div class="item-label">电流</div>
<div class="item-value">{{deviceData.electricity | fix2}} A</div>
<div class="item-value">{{deviceData.electricity | fix2 | dv}} A</div>
</div>
<div class="data-item">
<div class="item-label">功率</div>
<div class="item-value">{{deviceData.realTimePower | fix2}} W</div>
<div class="item-value">{{deviceData.realTimePower | fix2 | dv}} W</div>
</div>
<div class="data-item">
<div class="item-label">电压系数</div>
<div class="item-value">{{deviceData.vxs | fix3 | defaultValue}}</div>
<div class="item-value">{{deviceData.vxs | fix3 | dv}}</div>
</div>
</div>
</div>
@ -188,13 +188,13 @@
<span><i class="el-icon-reading"></i>累计用电</span>
<div class="reset-time">
最近重置: {{deviceData.lastInitReading | defaultValue}}
最近重置: {{deviceData.lastInitReading | dv}}
</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 class="item-value">{{deviceData.totalElectriQuantity | money | dv}} </div>
</div>
<div class="data-item">
<div class="item-label">
@ -203,7 +203,16 @@
<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 class="item-value">{{deviceData.totalElectriQuantity - deviceData.initReading | money | dv}} </div>
</div>
<div class="data-item">
<div class="item-label">
电量系数
<el-tooltip content="修改电量系数" placement="top">
<el-link @click="handleSetWxs" type="primary" icon="el-icon-edit" class="reset-btn"></el-link>
</el-tooltip>
</div>
<div class="item-value">{{deviceData.wxs | dv}}</div>
</div>
</div>
</div>
@ -214,17 +223,17 @@
<el-card class="box-card" >
<el-descriptions title="系统信息" :column="4">
<el-descriptions-item label="限制充值时间">
{{deviceData.limitRechargeTime | defaultValue}}
{{deviceData.limitRechargeTime | dv}}
<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}}
{{deviceData.limitRechargeReason | dv}}
</el-descriptions-item>
<el-descriptions-item label="用户手动操作时间">
{{deviceData.userOperaTime | defaultValue}}
{{deviceData.userOperaTime | dv}}
</el-descriptions-item>
<el-descriptions-item label="用户手动操作电量">
{{deviceData.userOpereEle | defaultValue}}
{{deviceData.userOpereEle | dv}}
</el-descriptions-item>
<el-descriptions-item label="用户手动操作类型">
<dict-tag :options="dict.type.device_user_opera_type" :value="deviceData.userOperaType" size="mini"/>
@ -257,16 +266,16 @@
<store-link :name="deviceData.storeName" :id="deviceData.storeId"/>
</el-descriptions-item>
<el-descriptions-item label="月费">
{{deviceData.monthFee | money | defaultValue}} /
到期时间{{deviceData.rentTime | defaultValue}}
{{deviceData.monthFee | money | dv}} /
到期时间{{deviceData.rentTime | dv}}
</el-descriptions-item>
<el-descriptions-item label="平台服务费" v-if="deviceData.serviceMode === DeviceServiceMode.DIRECT">
{{deviceData.realServiceRate | money | defaultValue}} %
{{deviceData.realServiceRate | money | dv}} %
</el-descriptions-item>
<el-descriptions-item label="代理服务费" v-if="deviceData.serviceMode === DeviceServiceMode.AGENT">
{{deviceData.agentServiceRate | money | defaultValue}} %
{{deviceData.agentServiceRate | money | dv}} %
</el-descriptions-item>
<el-descriptions-item label="备注">{{deviceData.remark | defaultValue}}</el-descriptions-item>
<el-descriptions-item label="备注">{{deviceData.remark | dv}}</el-descriptions-item>
</el-descriptions>
</el-card>
<el-card class="box-card" header="分成信息">
@ -277,7 +286,7 @@
{{bonus.arrivalName}}
</el-row>
</template>
<template>{{bonus.point | money | defaultValue }} %</template>
<template>{{bonus.point | money | dv }} %</template>
</line-field>
</el-card>
</el-col>
@ -340,6 +349,7 @@
import {
addEle,
addTime, deviceInitTotalEle,
deviceSetWxs,
getDevice,
refreshIot,
resetDevice,
@ -480,6 +490,27 @@ export default {
clearInterval(this.timer);
},
methods: {
handleSetWxs() {
this.$prompt('请输入电量系数', '修改电量系数', {
confirmButtonText: '确定',
cancelButtonText: '取消',
inputPattern: /^\d+(\.\d{0,3})?$/,
inputErrorMessage: '请输入最多3位小数的数字',
inputValidator: (val) => {
if (val <= 0.02) {
return "输入的电量系数不允许小于0.02";
}
return true;
}
}).then(({ value }) => {
deviceSetWxs(this.deviceData.deviceId, value).then(res => {
if (res.code === 200) {
this.$message.success("操作成功");
this.deviceData.wxs = value;
}
})
})
},
handleInitReading() {
this.$confirm(`是否初始化电量读数?`, {
confirmButtonText: '确定',

View File

@ -172,82 +172,17 @@
<sn-input :show.sync="showBindSn" @submit="onSubmitSn"></sn-input>
<!-- 添加或修改设备对话框 -->
<el-dialog :title="title" :visible.sync="open" width="800px" append-to-body :close-on-click-modal="false">
<el-form ref="form" :model="form" :rules="rules" label-width="6em">
<el-row :gutter="gutter">
<form-col :span="span" label="自定义图片" prop="customPicture">
<image-upload v-model="form.customPicture" :limit="1"/>
</form-col>
<form-col :span="span" label="型号" prop="modelId">
<model-select v-model="form.modelId" :show-value.sync="form.model" @submit="onSubmitModel"/>
</form-col>
<form-col :span="span" label="MAC-1" prop="mac">
<el-input v-model="form.mac" placeholder="请输入设备MAC-1"/>
</form-col>
<form-col :span="span" label="MAC-2" prop="mac2">
<el-input v-model="form.mac2" placeholder="请输入设备MAC-2"/>
</form-col>
<form-col :span="span" label="SN" prop="deviceNo">
<el-input v-model="form.deviceNo" placeholder="请输入设备SN" />
</form-col>
<form-col :span="span" label="名称" prop="deviceName">
<el-input v-model="form.deviceName" placeholder="请输入设备名称" />
</form-col>
<form-col :span="span * 2" label="备注" prop="remark">
<el-input v-model="form.remark" type="textarea" placeholder="请输入备注" maxlength="500" show-word-limit/>
</form-col>
<form-col :span="span" label="设备月费" prop="monthFee">
<el-input v-model="form.monthFee" placeholder="请输入月费" type="number" :min="0">
<template #append>
/
</template>
</el-input>
</form-col>
<form-col :span="span" label="服务模式" prop="serviceMode">
<el-radio-group v-model="form.serviceMode">
<el-radio v-for="item of dict.type.device_service_mode" :label="item.value" :key="item.value">{{item.label}}</el-radio>
</el-radio-group>
</form-col>
<template v-if="form.serviceMode === DeviceServiceMode.AGENT">
<form-col :span="span" label="代理商" prop="agentId">
<user-input v-model="form.agentId" :query="{type: SmUserType.AGENT}" />
</form-col>
<form-col :span="span" label="代理服务费" prop="agentServiceRate" label-width="7em">
<el-input v-model="form.agentServiceRate" placeholder="请输入代理服务费" type="number">
<template #append>%</template>
</el-input>
</form-col>
</template>
<template v-else>
<form-col :span="span" label="服务费" prop="serviceRate">
<el-input v-model="form.serviceRate" placeholder="请输入服务费" type="number">
<template #append>%</template>
</el-input>
</form-col>
</template>
</el-row>
<el-row :gutter="gutter">
<form-col :span="10" label="限制充值至" prop="limitRechargeTime">
<el-date-picker type="datetime" v-model="form.limitRechargeTime" placeholder="请选择限制充值时间" value-format="yyyy-MM-dd HH:mm:ss" :clearable="false"/>
</form-col>
<form-col :span="14" label="限制充值原因" prop="limitRechargeReason" label-width="7em">
<el-input v-model="form.limitRechargeReason" type="textarea" placeholder="请输入限制充值的原因(展示给用户查看)" show-word-limit maxlength="200"/>
</form-col>
</el-row>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button type="primary" @click="submitForm"> </el-button>
<el-button @click="cancel"> </el-button>
</div>
</el-dialog>
<!--型号选择弹窗-->
<model-dialog
:show.sync="showCheckModel"
@select="onSubmitBatchModel"
/>
<device-edit-dialog
:visible.sync="showEditDialog"
:device-id="selectedDeviceId"
@success="getList"
/>
</div>
</template>
@ -277,6 +212,7 @@ import { $serviceType, $view } from '@/utils/mixins'
import ModelSimpleSelect from '@/components/Business/Model/ModelSimpleSelect.vue'
import { DeviceServiceMode, SmUserType } from '@/utils/constants'
import DeviceTable from '@/views/system/device/components/DeviceTable.vue'
import DeviceEditDialog from '@/views/system/device/components/DeviceEditDialog.vue'
import { listAllApp } from '@/api/ss/app';
@ -289,7 +225,7 @@ const defaultSort = {
export default {
name: "Device",
mixins: [$serviceType, $view],
components: { DeviceTable, ModelSimpleSelect, DeviceLink, StoreLink, UserLink, ModelDialog, UserInput, StoreInput, SnInput, QrCode, SmUserSelect, ModelSelect},
components: { DeviceEditDialog, DeviceTable, ModelSimpleSelect, DeviceLink, StoreLink, UserLink, ModelDialog, UserInput, StoreInput, SnInput, QrCode, SmUserSelect, ModelSelect},
dicts: ['sm_device_online_status', 'sm_device_status', 'sm_device_outage_way','sm_device_notice_way', 'service_type', 'time_unit', 'device_service_mode'],
props: {
query: {
@ -303,6 +239,10 @@ export default {
return {
//
showCheckModel: false,
//
showEditDialog: false,
// ID
selectedDeviceId: null,
span: 12,
gutter: 8,
//
@ -507,9 +447,8 @@ export default {
},
/** 新增按钮操作 */
handleAdd() {
this.reset();
this.open = true;
this.title = "添加设备";
this.selectedDeviceId = null;
this.showEditDialog = true;
},
//
handleResetService(row) {
@ -530,13 +469,8 @@ export default {
},
/** 修改按钮操作 */
handleUpdate(row) {
this.reset();
const deviceId = row.deviceId || this.ids
getDevice(deviceId).then(response => {
this.form = response.data;
this.open = true;
this.title = "修改设备";
});
this.selectedDeviceId = row.deviceId || this.ids;
this.showEditDialog = true;
},
/** 提交按钮 */
submitForm() {