设施 绑定商户修改

This commit is contained in:
tx 2025-01-07 11:41:36 +08:00
parent 6d5c289044
commit 17256e8807
2 changed files with 322 additions and 145 deletions

View File

@ -140,3 +140,11 @@ export function getDeviceBySn(sn){
}) })
} }
// 绑定设备设施
export function bindDeviceFacility(data){
return request({
url: '/system/device/bindDeviceFacility/'+data.equipmentId+'/'+data.deviceId,
method: 'post',
// data: data
})
}

View File

@ -8,27 +8,14 @@
<div slot="header" class="card-header"> <div slot="header" class="card-header">
<span>设备信息</span> <span>设备信息</span>
<div class="action-buttons"> <div class="action-buttons">
<el-button <el-button type="primary" plain icon="el-icon-edit" @click="toggleEdit" v-if="!isEditing">
type="primary"
plain
icon="el-icon-edit"
@click="toggleEdit"
v-if="!isEditing">
修改 修改
</el-button> </el-button>
<template v-else> <template v-else>
<el-button <el-button type="success" plain icon="el-icon-check" @click="handleSave">
type="success"
plain
icon="el-icon-check"
@click="handleSave">
保存 保存
</el-button> </el-button>
<el-button <el-button type="info" plain icon="el-icon-close" @click="handleCancel">
type="info"
plain
icon="el-icon-close"
@click="handleCancel">
取消 取消
</el-button> </el-button>
</template> </template>
@ -37,7 +24,8 @@
<qr-code :text="qrCodeText" :width="150" :height="150" /> <qr-code :text="qrCodeText" :width="150" :height="150" />
<p>扫描二维码进行设备绑定</p> <p>扫描二维码进行设备绑定</p>
</div> </div>
<el-button slot="reference" type="primary" plain icon="el-icon-download" @click="downloadQRCode">下载二维码</el-button> <el-button slot="reference" type="primary" plain icon="el-icon-download"
@click="downloadQRCode">下载二维码</el-button>
</el-popover> </el-popover>
</div> </div>
</div> </div>
@ -86,10 +74,7 @@
<span class="label">型号功能:</span> <span class="label">型号功能:</span>
<template v-if="isEditing"> <template v-if="isEditing">
<el-select v-model="editForm.modelTags" multiple size="small" class="edit-input" disabled> <el-select v-model="editForm.modelTags" multiple size="small" class="edit-input" disabled>
<el-option <el-option v-for="tag in modelTagOptions" :key="tag.dictValue" :label="tag.dictLabel"
v-for="tag in modelTagOptions"
:key="tag.dictValue"
:label="tag.dictLabel"
:value="tag.dictValue"> :value="tag.dictValue">
</el-option> </el-option>
</el-select> </el-select>
@ -106,8 +91,9 @@
<div slot="header" class="card-header"> <div slot="header" class="card-header">
<span>归属信息</span> <span>归属信息</span>
<div class="header-buttons"> <div class="header-buttons">
<el-button type="success" plain size="small">绑定商户</el-button> <el-button type="success" icon="el-icon-connection" plain size="small" @click="openBindUserDialog">绑定商户</el-button>
<el-button type="success" plain size="small">绑定代理商</el-button> <el-button type="success" icon="el-icon-connection" plain size="small"
@click="openBindFacilityDialog">绑定设施</el-button>
</div> </div>
</div> </div>
<el-row :gutter="20"> <el-row :gutter="20">
@ -139,10 +125,7 @@
<span class="label">绑定设施:</span> <span class="label">绑定设施:</span>
<template v-if="isEditing"> <template v-if="isEditing">
<el-select v-model="editForm.serviceRate" size="small" class="edit-input" disabled> <el-select v-model="editForm.serviceRate" size="small" class="edit-input" disabled>
<el-option <el-option v-for="option in facilityOptions" :key="option.dictValue" :label="option.dictLabel"
v-for="option in facilityOptions"
:key="option.dictValue"
:label="option.dictLabel"
:value="option.dictValue"> :value="option.dictValue">
</el-option> </el-option>
</el-select> </el-select>
@ -163,7 +146,7 @@
<div class="info-item"> <div class="info-item">
<span class="label">备注:</span> <span class="label">备注:</span>
<template v-if="isEditing"> <template v-if="isEditing">
<el-input v-model="editForm.remark" size="small" class="edit-input" > </el-input> <el-input v-model="editForm.remark" size="small" class="edit-input"> </el-input>
</template> </template>
<span v-else class="value">{{ deviceData.remark || '--' }}</span> <span v-else class="value">{{ deviceData.remark || '--' }}</span>
</div> </div>
@ -320,6 +303,68 @@
<el-tab-pane label="命令日志" name="logs">命令日志内容</el-tab-pane> <el-tab-pane label="命令日志" name="logs">命令日志内容</el-tab-pane>
</el-tabs> </el-tabs>
<el-dialog title="绑定设施" :visible.sync="bindFacilityDialogVisible" width="900px" append-to-body>
<el-table v-loading="facilityTableLoading" :data="facilityList" style="width: 100%" height="500">
<!-- <el-table-column type="selection" width="55" align="center" /> -->
<el-table-column label="设施id" prop="equipmentId" align="center" />
<el-table-column label="设施名称" prop="name" align="center" />
<el-table-column label="设施图片" align="center">
<template slot-scope="scope">
<image-preview :src="scope.row.picture" :width="50" :height="50" />
</template>
</el-table-column>
<el-table-column label="设施类型" prop="type" align="center">
<template slot-scope="scope">
<dict-tag :options="dict.type.ss_equipment_type" :value="scope.row.type" />
</template>
</el-table-column>
<el-table-column label="套餐" prop="feeRuleVOS" align="center">
<template slot-scope="scope">
{{ formatFeeRules(scope.row.feeRuleVOS) }}
</template>
</el-table-column>
<el-table-column label="店铺名" prop="storeName" align="center" />
<el-table-column label="设施状态" prop="status" align="center">
<template slot-scope="scope">
<dict-tag :options="dict.type.ss_equipment_status" :value="scope.row.status" />
</template>
</el-table-column>
<el-table-column label="操作" align="center" fixed="right" width="150">
<template slot-scope="scope">
<el-button size="mini" type="primary" @click="handleBindFacility(scope.row)">绑定</el-button>
</template>
</el-table-column>
</el-table>
<pagination v-show="facilityTotal > 0" :total="facilityTotal" :page.sync="facilityQueryParams.pageNum"
:limit.sync="facilityQueryParams.pageSize" @pagination="getFacilityList" />
</el-dialog>
<!-- 绑定商户对话框 -->
<el-dialog title="绑定商户" :visible.sync="bindUserDialogVisible" width="900px" append-to-body>
<el-table v-loading="userTableLoading" :data="userList" style="width: 100%" height="500">
<el-table-column label="用户编号" prop="userId" align="center" />
<el-table-column label="用户名称" prop="userName" align="center" />
<el-table-column label="手机号" prop="phonenumber" align="center" />
<el-table-column label="类型" align="center">
<template slot-scope="scope">
<dict-tag :options="dict.type.ss_user_type" :value="scope.row.userType" />
</template>
</el-table-column>
<el-table-column label="状态" align="center">
<template slot-scope="scope">
<el-tag :type="scope.row.status === '0' ? 'success' : 'danger'">
{{ scope.row.status === '0' ? '正常' : '停用' }}
</el-tag>
</template>
</el-table-column>
<el-table-column label="操作" align="center" fixed="right" width="150">
<template slot-scope="scope">
<el-button size="mini" type="primary" @click="handleBindUser(scope.row)">绑定</el-button>
</template>
</el-table-column>
</el-table>
<pagination v-show="userTotal > 0" :total="userTotal" :page.sync="userQueryParams.pageNum"
:limit.sync="userQueryParams.pageSize" @pagination="getUserList" />
</el-dialog>
</div> </div>
</template> </template>
@ -331,34 +376,75 @@ import {
handleUnlocking, handleUnlocking,
reboot, reboot,
refreshDevice, refreshDevice,
delDevice delDevice,
bindDeviceFacility,
bindDeviceUser
} from '@/api/system/device' } from '@/api/system/device'
import { listUser } from "@/api/user/user"
import { listData } from '@/api/system/dict/data' import { listData } from '@/api/system/dict/data'
import { listEquipment } from "@/api/system/equipment"
import QrCode from '@/components/QrCode/index.vue' import QrCode from '@/components/QrCode/index.vue'
import QRCode from 'qrcode' import QRCode from 'qrcode'
export default { export default {
name: 'DeviceDetail', name: "DeviceDetail",
components: { QrCode }, components: {
QrCode
},
dicts: ['ss_equipment_type', 'ss_equipment_status', 'ss_user_type'],
data() { data() {
return { return {
deviceData: {}, //
isEditing: false, // deviceData: {
modelTags: [] //
},
loading: false,
isEditing: false,
//
editForm: { editForm: {
deviceId: '', deviceId: undefined,
deviceName: '',
mac: '', mac: '',
mac2: '', mac2: '',
sn: '', sn: '',
model: '', model: '',
productId: '', productId: '',
modelTags: [], deviceName: '',
roomName: '',
storeName: '', storeName: '',
serviceRate: '',
userName: '', userName: '',
remark: '', remark: '',
roomName: '' modelTags: [],
serviceRate: undefined
}, },
//
bindFacilityDialogVisible: false,
facilityTableLoading: false,
facilityList: [],
facilityTotal: 0,
facilityQueryParams: {
pageNum: 1,
pageSize: 10
},
facilityOptions: [],
modelTagOptions: [],
//
bindUserDialogVisible: false,
userTableLoading: false,
userList: [],
userTotal: 0,
userQueryParams: {
pageNum: 1,
pageSize: 10,
userName: undefined,
phonenumber: undefined,
status: undefined,
userType: '01'
},
//
activeTab: 'packages', activeTab: 'packages',
searchForm: { searchForm: {
userName: '', userName: '',
@ -366,161 +452,241 @@ export default {
packageName: '', packageName: '',
chargeMode: '', chargeMode: '',
chargeType: '' chargeType: ''
}, }
queryParams: {
pageNum: 1,
pageSize: 10,
dictType: 'sm_model_tag',
dictLabel: undefined,
status: undefined
},
facilityOptions: [],
modelTagOptions: [],
loading: true
} }
}, },
computed: { computed: {
modelTags() { qrCodeText() {
return this.deviceData.modelTags ? this.deviceData.modelTags.map(tag => { return this.deviceData.sn || ''
const modelTag = this.modelTagOptions.find(option => option.dictValue === tag);
return modelTag ? modelTag.dictLabel : tag;
}) : [];
}, },
serviceModeText() { modelTags() {
switch (this.deviceData.serviceMode) { //
case "1": return "直营模式"; if (!this.deviceData.modelTags) return []
case "2": return "代理模式"; return Array.isArray(this.deviceData.modelTags)
default: return "--"; ? this.deviceData.modelTags
} : this.deviceData.modelTags.split(',').filter(Boolean)
}, },
facilityTag() { facilityTag() {
const facility = this.facilityOptions.find(option => option.dictValue === this.deviceData.serviceRate); return this.deviceData.facilityName || '--'
return facility ? facility.dictLabel : '--';
},
qrCodeText() {
return this.deviceData.qrText || '无二维码信息';
} }
}, },
created() { created() {
const deviceId = this.$route.params.deviceId; const deviceId = this.$route.params.deviceId
if (deviceId) { if (deviceId) {
this.fetchDeviceData(deviceId); this.fetchDeviceData(deviceId)
} }
this.fetchFacilityOptions(); this.fetchFacilityOptions()
this.fetchModelTagOptions(); this.fetchModelTagOptions()
}, },
methods: { methods: {
//
toggleEdit() {
this.isEditing = true;
//
this.editForm = {
deviceId: this.deviceData.deviceId,
deviceName: this.deviceData.deviceName,
mac: this.deviceData.mac,
mac2: this.deviceData.mac2,
sn: this.deviceData.sn,
model: this.deviceData.model,
productId: this.deviceData.productId,
modelTags: this.deviceData.modelTags || [],
storeName: this.deviceData.storeName,
serviceRate: this.deviceData.serviceRate,
userName: this.deviceData.userName,
remark: this.deviceData.remark,
roomName: this.deviceData.monthFee
};
},
//
handleSave() {
updateDevice(this.editForm).then(() => {
this.$message.success("设备信息已更新");
this.isEditing = false;
//
this.fetchDeviceData(this.editForm.deviceId);
}).catch(() => {
this.$message.error("更新设备信息失败");
});
},
//
handleCancel() {
this.isEditing = false;
this.editForm = {};
},
fetchDeviceData(deviceId) { fetchDeviceData(deviceId) {
this.loading = true
getDevice(deviceId).then(response => { getDevice(deviceId).then(response => {
this.deviceData = response.data; if (response.data) {
this.loading = false; // modelTags
this.deviceData = {
...response.data,
modelTags: Array.isArray(response.data.modelTags)
? response.data.modelTags
: (response.data.modelTags ? response.data.modelTags.split(',') : [])
}
}
this.loading = false
}).catch(error => { }).catch(error => {
this.$message.error("获取设备详情失败"); this.$message.error("获取设备详情失败")
this.loading = false; this.loading = false
}); })
},
formatFeeRules(feeRuleVOS) {
if (!feeRuleVOS || !feeRuleVOS.length) {
return '-';
}
return feeRuleVOS.map(rule => rule.explain).join('');
}, },
fetchFacilityOptions() { fetchFacilityOptions() {
listData({ pageNum: 1, pageSize: 10, dictType: 'ss_equipment_type' }).then(response => { listData({ dictType: 'ss_equipment_type' }).then(response => {
this.facilityOptions = response.rows; this.facilityOptions = response.rows || []
}).catch(error => { }).catch(() => {
this.$message.error("获取绑定设施数据失败"); this.$message.error("获取绑定设施数据失败")
}); })
}, },
fetchModelTagOptions() { fetchModelTagOptions() {
listData(this.queryParams).then(response => { listData({ dictType: 'ss_model_tags' }).then(response => {
this.modelTagOptions = response.rows; this.modelTagOptions = response.rows || []
}).catch(error => { }).catch(() => {
this.$message.error("获取modelTags数据失败"); this.$message.error("获取型号功能数据失败")
})
},
getFacilityList() {
this.facilityTableLoading = true;
//
const queryParams = {
pageNum: this.facilityQueryParams.pageNum,
pageSize: this.facilityQueryParams.pageSize,
name: undefined,
type: undefined,
status: undefined
};
listEquipment(queryParams).then(response => {
this.facilityList = response.rows;
this.facilityTotal = response.total;
this.facilityTableLoading = false;
}).catch(() => {
this.$message.error("获取设施列表失败");
this.facilityTableLoading = false;
}); });
},
toggleEdit() {
this.isEditing = true
this.editForm = {
...this.deviceData,
modelTags: Array.isArray(this.deviceData.modelTags)
? [...this.deviceData.modelTags]
: []
}
},
handleSave() {
updateDevice(this.editForm).then(() => {
this.$message.success("保存成功")
this.isEditing = false
this.fetchDeviceData(this.deviceData.deviceId)
}).catch(() => {
this.$message.error("保存失败")
})
},
handleCancel() {
this.isEditing = false
this.editForm = {}
}, },
downloadQRCode() { downloadQRCode() {
const qrText = this.qrCodeText; const qrText = this.qrCodeText
if (!qrText) {
this.$message.warning("没有可用的设备SN码")
return
}
QRCode.toDataURL(qrText, { width: 150, height: 150 }, (err, url) => { QRCode.toDataURL(qrText, { width: 150, height: 150 }, (err, url) => {
if (err) { if (err) {
this.$message.error("生成二维码失败"); this.$message.error("生成二维码失败")
return; return
} }
const link = document.createElement('a'); const link = document.createElement('a')
link.href = url; link.href = url
link.download = `${this.deviceData.sn || 'unknown'}.png`; link.download = `${this.deviceData.sn || 'device'}.png`
link.click(); link.click()
}); })
}, },
handleUnlocking(row) { handleUnlocking(row) {
handleUnlocking(row.deviceId).then(() => { handleUnlocking(row.deviceId).then(() => {
this.$message.success("设备已解锁"); this.$message.success("设备已解锁")
}); })
}, },
handleLock(row) { handleLock(row) {
handleLock(row.deviceId).then(() => { handleLock(row.deviceId).then(() => {
this.$message.success("设备已锁定"); this.$message.success("设备已锁定")
}); })
}, },
reboot(row) { reboot(row) {
reboot(row.deviceId).then(() => { reboot(row.deviceId).then(() => {
this.$message.success("设备已重启"); this.$message.success("设备已重启")
}); })
}, },
refresh(row) { refresh(row) {
refreshDevice(row.deviceId).then(() => { refreshDevice(row.deviceId).then(() => {
this.$message.success("设备已更新"); this.$message.success("设备已更新")
}); })
}, },
handleDelete(row) { handleDelete(row) {
delDevice(row.deviceId).then(() => { this.$modal.confirm('是否确认删除该设备?').then(() => {
this.$message.success("设备已删除"); return delDevice(row.deviceId)
}); }).then(() => {
this.$message.success("设备已删除")
this.$router.push('/system/device')
}).catch(() => {})
},
openBindFacilityDialog() {
this.bindFacilityDialogVisible = true
this.getFacilityList()
},
getFacilityList() {
this.facilityTableLoading = true
listEquipment(this.facilityQueryParams).then(response => {
this.facilityList = response.rows || []
this.facilityTotal = response.total || 0
this.facilityTableLoading = false
})
},
handleBindFacility(row) {
this.$modal.confirm('确认要将该设备绑定到设施"' + row.name + '"吗?').then(() => {
return bindDeviceFacility({
deviceId: this.deviceData.deviceId,
equipmentId: row.equipmentId
})
}).then(() => {
this.$modal.msgSuccess("绑定成功")
this.bindFacilityDialogVisible = false
this.fetchDeviceData(this.deviceData.deviceId)
}).catch(() => {})
},
handleOnline(row) {
const status = row.status === '8' ? '0' : '8'
const statusText = status === '8' ? '禁用' : '启用'
this.$modal.confirm('确认要' + statusText + '该设备吗?').then(() => {
return updateDevice({
deviceId: row.deviceId,
status: status
})
}).then(() => {
this.$modal.msgSuccess(statusText + "成功")
this.fetchDeviceData(row.deviceId)
}).catch(() => {})
},
openBindUserDialog() {
this.bindUserDialogVisible = true
this.getUserList()
},
getUserList() {
this.userTableLoading = true
listUser(this.userQueryParams).then(response => {
this.userList = response.rows || []
this.userTotal = response.total || 0
this.userTableLoading = false
})
},
handleBindUser(row) {
this.$modal.confirm('确认要将该设备绑定到商户"' + row.userName + '"吗?').then(() => {
return bindDeviceUser({
deviceId: this.deviceData.deviceId,
userId: row.userId
})
}).then(() => {
this.$modal.msgSuccess("绑定成功")
this.bindUserDialogVisible = false
this.fetchDeviceData(this.deviceData.deviceId)
}).catch(() => {})
} }
} }
} }
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.device-detail { .device-detail {
padding: 20px; padding: 20px;
@ -653,6 +819,7 @@ export default {
// //
.editing { .editing {
.info-item { .info-item {
.el-input, .el-input,
.el-select { .el-select {
.el-input__inner { .el-input__inner {
@ -672,7 +839,9 @@ export default {
// //
.el-table { .el-table {
th, td {
th,
td {
padding: 8px 0; padding: 8px 0;
} }
@ -705,7 +874,7 @@ export default {
// //
.action-buttons { .action-buttons {
.el-button + .el-button { .el-button+.el-button {
margin-left: 10px; margin-left: 10px;
} }