|
@@ -316,140 +316,6 @@
|
|
|
</div>
|
|
</div>
|
|
|
</el-tab-pane>
|
|
</el-tab-pane>
|
|
|
|
|
|
|
|
- <el-tab-pane label="楼控设备" name="baDevices">
|
|
|
|
|
- <div class="tab-content">
|
|
|
|
|
- <!-- 设备类型选择 -->
|
|
|
|
|
- <div class="ba-device-header">
|
|
|
|
|
- <el-select v-model="selectedBaDeviceModel" placeholder="请选择设备类型" @change="handleBaDeviceTypeChange" style="width: 200px;">
|
|
|
|
|
- <el-option
|
|
|
|
|
- v-for="item in baDeviceModels"
|
|
|
|
|
- :key="item.modelCode"
|
|
|
|
|
- :label="item.modelName"
|
|
|
|
|
- :value="item.modelCode">
|
|
|
|
|
- </el-option>
|
|
|
|
|
- </el-select>
|
|
|
|
|
- <el-button type="primary" icon="el-icon-refresh" @click="refreshBaDevices" :loading="baDeviceLoading" style="margin-left: 10px;">
|
|
|
|
|
- 刷新
|
|
|
|
|
- </el-button>
|
|
|
|
|
- </div>
|
|
|
|
|
-
|
|
|
|
|
- <!-- 设备列表 -->
|
|
|
|
|
- <el-table
|
|
|
|
|
- :data="baDeviceList"
|
|
|
|
|
- border
|
|
|
|
|
- stripe
|
|
|
|
|
- v-loading="baDeviceLoading"
|
|
|
|
|
- @row-click="handleBaDeviceRowClick"
|
|
|
|
|
- ref="baDeviceTable"
|
|
|
|
|
- style="margin-top: 15px;">
|
|
|
|
|
- <el-table-column type="expand" width="50">
|
|
|
|
|
- <template slot-scope="props">
|
|
|
|
|
- <!-- ★★★ 关键修复:添加 @click.stop 阻止事件冒泡 ★★★ -->
|
|
|
|
|
- <div class="device-detail" @click.stop>
|
|
|
|
|
- <el-tabs v-model="props.row.detailTab">
|
|
|
|
|
- <!-- 基础属性 -->
|
|
|
|
|
- <el-tab-pane label="基础属性" name="base">
|
|
|
|
|
- <el-descriptions :column="2" border size="small" v-if="getBaDeviceAttrs(props.row.deviceCode, 'Base').length > 0">
|
|
|
|
|
- <el-descriptions-item
|
|
|
|
|
- v-for="attr in getBaDeviceAttrs(props.row.deviceCode, 'Base')"
|
|
|
|
|
- :key="attr.attrKey"
|
|
|
|
|
- :label="attr.attrName">
|
|
|
|
|
- {{ attr.attrValue || '-' }}
|
|
|
|
|
- </el-descriptions-item>
|
|
|
|
|
- </el-descriptions>
|
|
|
|
|
- <el-empty v-else description="暂无基础属性"></el-empty>
|
|
|
|
|
- </el-tab-pane>
|
|
|
|
|
-
|
|
|
|
|
- <!-- 状态属性 -->
|
|
|
|
|
- <el-tab-pane label="状态属性" name="state">
|
|
|
|
|
- <el-table
|
|
|
|
|
- :data="getBaDeviceAttrs(props.row.deviceCode, 'State')"
|
|
|
|
|
- border
|
|
|
|
|
- size="small"
|
|
|
|
|
- v-if="getBaDeviceAttrs(props.row.deviceCode, 'State').length > 0">
|
|
|
|
|
- <el-table-column prop="attrName" label="属性名称" width="200"></el-table-column>
|
|
|
|
|
- <el-table-column label="属性值" min-width="180">
|
|
|
|
|
- <template slot-scope="scope">
|
|
|
|
|
- <el-tag v-if="scope.row.attrValueType === 'Enum' && scope.row.attrValueName" size="small">
|
|
|
|
|
- {{ scope.row.attrValueName }}
|
|
|
|
|
- </el-tag>
|
|
|
|
|
- <span v-else>
|
|
|
|
|
- {{ formatBaAttrValue(scope.row) }}
|
|
|
|
|
- </span>
|
|
|
|
|
- </template>
|
|
|
|
|
- </el-table-column>
|
|
|
|
|
- <el-table-column prop="updateTime" label="更新时间" width="180"></el-table-column>
|
|
|
|
|
- </el-table>
|
|
|
|
|
- <el-empty v-else description="暂无状态数据"></el-empty>
|
|
|
|
|
- </el-tab-pane>
|
|
|
|
|
- </el-tabs>
|
|
|
|
|
- </div>
|
|
|
|
|
- </template>
|
|
|
|
|
- </el-table-column>
|
|
|
|
|
- <el-table-column prop="deviceCode" label="设备代码" width="160" show-overflow-tooltip></el-table-column>
|
|
|
|
|
- <el-table-column prop="deviceName" label="设备名称" width="200" show-overflow-tooltip></el-table-column>
|
|
|
|
|
- <el-table-column prop="location" label="安装位置" width="180" show-overflow-tooltip></el-table-column>
|
|
|
|
|
- <el-table-column prop="areaCode" label="区域" width="100" align="center">
|
|
|
|
|
- <template slot-scope="scope">
|
|
|
|
|
- {{ scope.row.areaCode && scope.row.areaCode.includes('3001') ? '北区' : '南区' }}
|
|
|
|
|
- </template>
|
|
|
|
|
- </el-table-column>
|
|
|
|
|
- <el-table-column label="设备状态" width="100" align="center">
|
|
|
|
|
- <template slot-scope="scope">
|
|
|
|
|
- <el-tag :type="scope.row.deviceStatus === 1 ? 'success' : 'info'">
|
|
|
|
|
- {{ scope.row.deviceStatus === 1 ? '在线' : '离线' }}
|
|
|
|
|
- </el-tag>
|
|
|
|
|
- </template>
|
|
|
|
|
- </el-table-column>
|
|
|
|
|
- <!-- 新增操作列 -->
|
|
|
|
|
- <el-table-column label="操作" min-width="220" align="center">
|
|
|
|
|
- <template slot-scope="scope">
|
|
|
|
|
- <!-- 获取当前设备模型的能力列表 -->
|
|
|
|
|
- <template v-if="getBaDeviceAbilities(scope.row.deviceModel).length > 0">
|
|
|
|
|
- <template v-for="ability in getBaDeviceAbilities(scope.row.deviceModel)">
|
|
|
|
|
- <!-- 如果能力有 Options 参数定义,展示多个按钮 -->
|
|
|
|
|
- <el-button-group v-if="getParamType(ability.paramDefinition) === 'Options'" :key="ability.abilityKey" style="margin: 2px;">
|
|
|
|
|
- <el-button
|
|
|
|
|
- v-for="option in parseOptions(ability.paramDefinition)"
|
|
|
|
|
- :key="option.value"
|
|
|
|
|
- size="mini"
|
|
|
|
|
- type="primary"
|
|
|
|
|
- @click.stop="executeBaDeviceAbility(scope.row, ability, option.value)"
|
|
|
|
|
- :loading="isBaAbilityExecuting(scope.row.deviceCode, ability.abilityKey, option.value)">
|
|
|
|
|
- {{ option.key }}
|
|
|
|
|
- </el-button>
|
|
|
|
|
- </el-button-group>
|
|
|
|
|
- <!-- 如果能力有其他参数类型(Slider/Input),显示单个按钮 -->
|
|
|
|
|
- <el-button
|
|
|
|
|
- v-else-if="getParamType(ability.paramDefinition) === 'Slider' || getParamType(ability.paramDefinition) === 'Input'"
|
|
|
|
|
- :key="ability.abilityKey"
|
|
|
|
|
- size="mini"
|
|
|
|
|
- type="primary"
|
|
|
|
|
- @click.stop="handleBaDeviceAbilityClick(scope.row, ability)"
|
|
|
|
|
- :loading="isBaAbilityExecuting(scope.row.deviceCode, ability.abilityKey)"
|
|
|
|
|
- style="margin: 2px;">
|
|
|
|
|
- {{ ability.abilityName }}
|
|
|
|
|
- </el-button>
|
|
|
|
|
- <!-- 如果能力无参数,直接执行 -->
|
|
|
|
|
- <el-button
|
|
|
|
|
- v-else
|
|
|
|
|
- :key="ability.abilityKey"
|
|
|
|
|
- size="mini"
|
|
|
|
|
- type="primary"
|
|
|
|
|
- @click.stop="executeBaDeviceAbility(scope.row, ability, null)"
|
|
|
|
|
- :loading="isBaAbilityExecuting(scope.row.deviceCode, ability.abilityKey)"
|
|
|
|
|
- style="margin: 2px;">
|
|
|
|
|
- {{ ability.abilityName }}
|
|
|
|
|
- </el-button>
|
|
|
|
|
- </template>
|
|
|
|
|
- </template>
|
|
|
|
|
- <span v-else style="color: #909399; font-size: 12px;">无可用操作</span>
|
|
|
|
|
- </template>
|
|
|
|
|
- </el-table-column>
|
|
|
|
|
- </el-table>
|
|
|
|
|
- </div>
|
|
|
|
|
- </el-tab-pane>
|
|
|
|
|
-
|
|
|
|
|
<!-- 调用日志标签页 -->
|
|
<!-- 调用日志标签页 -->
|
|
|
<el-tab-pane label="调用日志" name="callLogs">
|
|
<el-tab-pane label="调用日志" name="callLogs">
|
|
|
<div class="tab-content">
|
|
<div class="tab-content">
|
|
@@ -1584,28 +1450,6 @@ export default {
|
|
|
this.$refs.deviceTable?.toggleRowExpansion(row)
|
|
this.$refs.deviceTable?.toggleRowExpansion(row)
|
|
|
},
|
|
},
|
|
|
|
|
|
|
|
- // ★★★ 新增:处理楼控设备行点击 ★★★
|
|
|
|
|
- handleBaDeviceRowClick(row, column, event) {
|
|
|
|
|
- // 如果点击的是展开列本身(箭头),让默认行为处理
|
|
|
|
|
- if (column && column.type === 'expand') {
|
|
|
|
|
- return
|
|
|
|
|
- }
|
|
|
|
|
- // 手动切换展开状态
|
|
|
|
|
- this.$refs.baDeviceTable?.toggleRowExpansion(row)
|
|
|
|
|
- },
|
|
|
|
|
-
|
|
|
|
|
- // ========== 楼控设备相关方法 ==========
|
|
|
|
|
-
|
|
|
|
|
- // 处理楼控设备类型切换
|
|
|
|
|
- handleBaDeviceTypeChange() {
|
|
|
|
|
- this.loadBaDevices()
|
|
|
|
|
- },
|
|
|
|
|
-
|
|
|
|
|
- // 刷新楼控设备
|
|
|
|
|
- refreshBaDevices() {
|
|
|
|
|
- this.loadBaDevices()
|
|
|
|
|
- },
|
|
|
|
|
-
|
|
|
|
|
// 加载楼控设备列表
|
|
// 加载楼控设备列表
|
|
|
async loadBaDevices() {
|
|
async loadBaDevices() {
|
|
|
if (!this.selectedBaDeviceModel) return
|
|
if (!this.selectedBaDeviceModel) return
|
|
@@ -1660,77 +1504,6 @@ export default {
|
|
|
}
|
|
}
|
|
|
},
|
|
},
|
|
|
|
|
|
|
|
- // 获取楼控设备的属性(按组)
|
|
|
|
|
- getBaDeviceAttrs(deviceCode, attrGroup) {
|
|
|
|
|
- // 获取设备所属的模型
|
|
|
|
|
- const device = this.baDeviceList.find(d => d.deviceCode === deviceCode)
|
|
|
|
|
- if (!device) return []
|
|
|
|
|
-
|
|
|
|
|
- // 获取模型定义
|
|
|
|
|
- const modelData = this.baDeviceAttrs['_model_' + device.deviceModel]
|
|
|
|
|
- if (!modelData || !modelData.attrList) return []
|
|
|
|
|
-
|
|
|
|
|
- // 筛选出当前分组的属性定义
|
|
|
|
|
- const modelAttrs = modelData.attrList.filter(attr => attr.attrGroup === attrGroup)
|
|
|
|
|
-
|
|
|
|
|
- // 获取设备的实际属性值
|
|
|
|
|
- const deviceAttrData = this.baDeviceAttrs[deviceCode]
|
|
|
|
|
- const deviceAttrs = deviceAttrData && deviceAttrData[attrGroup] ? deviceAttrData[attrGroup] : []
|
|
|
|
|
-
|
|
|
|
|
- // 将实际值映射到字典
|
|
|
|
|
- const attrValueMap = {}
|
|
|
|
|
- deviceAttrs.forEach(attr => {
|
|
|
|
|
- attrValueMap[attr.attrKey] = attr
|
|
|
|
|
- })
|
|
|
|
|
-
|
|
|
|
|
- // 合并模型定义和实际值
|
|
|
|
|
- const mergedAttrs = modelAttrs.map(modelAttr => {
|
|
|
|
|
- const actualAttr = attrValueMap[modelAttr.attrKey]
|
|
|
|
|
-
|
|
|
|
|
- if (actualAttr) {
|
|
|
|
|
- // 有实际值,返回实际值
|
|
|
|
|
- return actualAttr
|
|
|
|
|
- } else {
|
|
|
|
|
- // 没有实际值,返回模型定义的空属性
|
|
|
|
|
- return {
|
|
|
|
|
- objCode: deviceCode,
|
|
|
|
|
- attrGroup: modelAttr.attrGroup,
|
|
|
|
|
- attrKey: modelAttr.attrKey,
|
|
|
|
|
- attrName: modelAttr.attrName,
|
|
|
|
|
- attrValue: null,
|
|
|
|
|
- attrValueName: null,
|
|
|
|
|
- attrValueType: modelAttr.attrValueType,
|
|
|
|
|
- attrUnit: modelAttr.attrUnit,
|
|
|
|
|
- updateTime: null
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
- })
|
|
|
|
|
-
|
|
|
|
|
- return mergedAttrs
|
|
|
|
|
- },
|
|
|
|
|
-
|
|
|
|
|
- // 格式化楼控设备属性值
|
|
|
|
|
- formatBaAttrValue(attr) {
|
|
|
|
|
- if (!attr.attrValue && attr.attrValue !== 0) {
|
|
|
|
|
- return '-'
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- // 如果有枚举名称,优先显示
|
|
|
|
|
- if (attr.attrValueName) {
|
|
|
|
|
- return attr.attrValueName
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- // 数值类型,保留两位小数
|
|
|
|
|
- if (attr.attrValueType === 'Value') {
|
|
|
|
|
- const numValue = parseFloat(attr.attrValue)
|
|
|
|
|
- if (!isNaN(numValue)) {
|
|
|
|
|
- return numValue.toFixed(2)
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- return attr.attrValue
|
|
|
|
|
- },
|
|
|
|
|
-
|
|
|
|
|
// ========== 标签页切换 ==========
|
|
// ========== 标签页切换 ==========
|
|
|
|
|
|
|
|
handleTabClick(tab) {
|
|
handleTabClick(tab) {
|