| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211 |
- <template>
- <div class="w-1/1">
- <el-button class="w-1/1" @click="openDrawer">点击配置</el-button>
- <el-drawer v-model="drawerVisible" title="配置设备绑定" direction="ltr" size="520px">
- <el-empty v-if="!devices.length" description="当前组态项目未绑定设备" />
- <template v-else>
- <el-form ref="formRef" :model="formModel" label-position="top" size="small">
- <div
- v-for="(bindItem, index) in formModel.deviceBinds"
- :key="bindItem.id"
- class="mb-12px">
- <el-form-item
- label="选择设备"
- :prop="`deviceBinds.${index}.deviceId`"
- :rules="rules.deviceId">
- <el-select
- v-model="bindItem.deviceId"
- filterable
- clearable
- class="w-1/1"
- placeholder="请选择设备"
- :disabled="!bindItem.editing"
- @change="onDeviceChange(bindItem)">
- <el-option
- v-for="device in devices"
- :key="device.id"
- :label="formatDeviceLabel(device)"
- :value="device.id" />
- </el-select>
- </el-form-item>
- <el-form-item
- label="设备属性"
- :prop="`deviceBinds.${index}.deviceProp`"
- :rules="rules.deviceProp">
- <el-select
- v-model="bindItem.deviceProp"
- filterable
- clearable
- class="w-1/1"
- placeholder="请选择设备属性"
- :disabled="!bindItem.editing || !bindItem.deviceId">
- <el-option
- v-for="deviceProp in getDeviceProps(bindItem.deviceId)"
- :key="deviceProp.value"
- :label="deviceProp.label"
- :value="deviceProp.value" />
- </el-select>
- </el-form-item>
- <el-form-item
- label="图形属性"
- :prop="`deviceBinds.${index}.nodeProp`"
- :rules="rules.nodeProp">
- <el-select
- v-model="bindItem.nodeProp"
- filterable
- clearable
- class="w-1/1"
- placeholder="请选择图形属性"
- :disabled="!bindItem.editing">
- <el-option
- v-for="nodeProp in nodePropOptions"
- :key="nodeProp.value"
- :label="nodeProp.label"
- :value="nodeProp.value" />
- </el-select>
- </el-form-item>
- <el-button
- v-if="bindItem.editing"
- type="success"
- size="small"
- class="w-1/1"
- @click="saveBind(index)">
- 绑定
- </el-button>
- <el-button v-else type="danger" size="small" class="w-1/1" @click="removeBind(index)">
- 解绑
- </el-button>
- <el-divider />
- </div>
- </el-form>
- <el-button type="primary" size="small" class="w-1/1" @click="addBind">新增</el-button>
- </template>
- </el-drawer>
- </div>
- </template>
- <script setup lang="ts">
- import type { WebtopoProjectLinkedDeviceVO } from '@/api/pms/maotu'
- import type { IDoneJson, IDoneJsonDeviceBind } from '@/components/mt-edit/store/types'
- import { ElMessage, type FormInstance, type FormItemRule } from 'element-plus'
- import { computed, reactive, ref } from 'vue'
- type DeviceBindRow = IDoneJsonDeviceBind & {
- editing?: boolean
- }
- type Props = {
- item: IDoneJson
- devices?: WebtopoProjectLinkedDeviceVO[]
- }
- const props = withDefaults(defineProps<Props>(), {
- devices: () => []
- })
- const drawerVisible = ref(false)
- const formRef = ref<FormInstance>()
- const formModel = reactive({
- deviceBinds: [] as DeviceBindRow[]
- })
- const rules: Record<string, FormItemRule | FormItemRule[]> = {
- deviceId: [{ required: true, message: '请选择设备', trigger: 'change' }],
- deviceProp: [{ required: true, message: '请选择设备属性', trigger: 'change' }],
- nodeProp: [{ required: true, message: '请选择图形属性', trigger: 'change' }]
- }
- const nodePropOptions = computed(() => {
- return Object.entries(props.item.props || {})
- .filter(([, prop]) => !prop.disabled)
- .map(([key, prop]) => ({
- label: prop.title,
- value: `props.${key}.val`
- }))
- })
- function randomId() {
- return `device-bind-${Date.now()}-${Math.random().toString(36).slice(2)}`
- }
- function getChineseName(value?: string) {
- return (value || '').split('~~')[0]
- }
- function formatDeviceLabel(device: WebtopoProjectLinkedDeviceVO) {
- return [device.deviceCode, getChineseName(device.deviceName)].filter(Boolean).join(' - ')
- }
- function updateItemDeviceBinds(item: IDoneJson, deviceBinds: IDoneJsonDeviceBind[]) {
- item.deviceBinds = deviceBinds
- }
- function syncDeviceBinds() {
- updateItemDeviceBinds(
- props.item,
- formModel.deviceBinds.map(({ editing, ...item }) => item)
- )
- }
- async function openDrawer() {
- formModel.deviceBinds = (props.item.deviceBinds || []).map((item) => ({
- ...item,
- editing: false
- }))
- drawerVisible.value = true
- }
- function addBind() {
- if (formModel.deviceBinds.some((item) => item.editing)) {
- ElMessage.error('请先完成当前绑定')
- return
- }
- formModel.deviceBinds.push({
- id: randomId(),
- deviceId: undefined,
- deviceProp: '',
- nodeProp: '',
- editing: true
- })
- }
- function onDeviceChange(bindItem: DeviceBindRow) {
- bindItem.deviceProp = ''
- }
- function getDeviceProps(deviceId?: number) {
- const device = props.devices.find((item) => item.id === deviceId)
- return (device?.pointParams || [])
- .filter((item) => item.paramCode)
- .map((item) => ({
- label: item.paramName || item.paramCode!,
- value: item.paramCode!
- }))
- }
- async function saveBind(index: number) {
- await formRef.value?.validateField([
- `deviceBinds.${index}.deviceId`,
- `deviceBinds.${index}.deviceProp`,
- `deviceBinds.${index}.nodeProp`
- ])
- formModel.deviceBinds[index].editing = false
- syncDeviceBinds()
- ElMessage.success('绑定成功')
- }
- function removeBind(index: number) {
- formModel.deviceBinds.splice(index, 1)
- syncDeviceBinds()
- ElMessage.success('解绑成功')
- }
- </script>
|