style:表管理-新增/编辑弹框及列表表头修改

main
黄伟杰 3 weeks ago
parent 720438a8ff
commit c65aa6a949

@ -1,6 +1,12 @@
import request from '@/config/axios'
// 能源设备 VO
export interface EnergyDeviceOperationRuleVO {
deviceId: number
pointId: number
operator?: string
}
export interface EnergyDeviceVO {
id: number // ID
name: string // 名称
@ -16,6 +22,7 @@ export interface EnergyDeviceVO {
orgId: number // 所属区域id
orgName: string // 所属区域名称
rules: string // 计算规则
operationRulesVOList?: EnergyDeviceOperationRuleVO[]
}
// 能源设备 API

@ -7,78 +7,97 @@
label-width="100px"
v-loading="formLoading"
>
<el-row>
<el-col :span="12">
<el-form-item label="编码" prop="code">
<el-input v-model="formData.code" placeholder="请输入编码" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="名称" prop="name">
<el-input v-model="formData.name" placeholder="请输入名称" />
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :span="12">
<el-form-item label="能耗类型" prop="deviceTypeId">
<el-form-item label="表编码" prop="code">
<el-input v-model="formData.code" placeholder="请输入表编码" />
</el-form-item>
<el-form-item label="表名称" prop="name">
<el-input v-model="formData.name" placeholder="请输入表名称" />
</el-form-item>
<el-form-item label="能源类型" prop="deviceTypeId">
<el-select
v-model="formData.deviceTypeId"
@change="handleQuery"
placeholder="请选择能类型"
@change="handleDeviceTypeChange"
placeholder="请选择能源类型"
clearable
filterable
class="!w-full"
>
<el-option
v-for="item in typeList"
:key="item.id"
:label="item.name"
:value="item.id"
/>
<el-option v-for="item in typeList" :key="item.id" :label="item.name" :value="item.id" />
</el-select>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="单位" prop="unitName">
<el-input disabled v-model="formData.unitName" placeholder="" />
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :span="12">
<el-form-item label="抄表周期cron" prop="checkCron">
<el-input v-model="formData.checkCron" placeholder="" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="是否启用" prop="isEnable">
<el-radio-group v-model="formData.isEnable">
<el-radio
v-for="dict in getBoolDictOptions(DICT_TYPE.INFRA_BOOLEAN_STRING)"
:key="dict.value"
:label="dict.value"
<el-form-item label="所属区域" prop="orgId">
<el-select
v-model="formData.orgId"
placeholder="根据区域结构筛选列表"
clearable
filterable
class="!w-full"
:loading="analysisLoading"
@change="handleOrgChange"
>
<el-option v-for="org in analysisList" :key="org.id" :label="org.name" :value="org.id" />
</el-select>
</el-form-item>
<el-form-item label="计算规则" prop="operationRulesVOList">
<div class="w-full flex flex-col gap-8px">
<div
v-for="(rule, index) in formData.operationRulesVOList"
:key="index"
class="w-full flex items-center gap-8px"
>
<el-tree-select
v-model="rule.pointValue"
:data="equipmentTree"
:props="treeSelectProps"
check-strictly
filterable
clearable
class="!w-full"
placeholder="根据设备选择点位"
:disabled="!formData.orgId"
@change="(val) => handlePointSelected(index, val)"
/>
<template v-if="index < formData.operationRulesVOList.length - 1">
<el-select
v-model="formData.operationRulesVOList[index].operator"
placeholder="运算符"
class="!w-110px"
clearable
>
{{ dict.label }}
</el-radio>
</el-radio-group>
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :span="12">
<el-form-item label="所属区域" prop="orgName">
<el-input v-model="formData.orgName" placeholder="" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="计算规则" prop="rules">
<el-input v-model="formData.rules" placeholder="" />
</el-form-item>
</el-col>
</el-row>
<el-option v-for="op in operatorOptions" :key="op" :label="op" :value="op" />
</el-select>
</template>
<template v-else>
<div class="flex items-center gap-4px">
<el-button link type="primary" @click="addRule">
<Icon icon="ep:plus" />
</el-button>
<el-button
link
type="danger"
:disabled="formData.operationRulesVOList.length <= 1"
@click="removeRule"
>
<Icon icon="ep:minus" />
</el-button>
</div>
</template>
</div>
</div>
</el-form-item>
<el-form-item label="是否启用" prop="isEnable">
<el-switch v-model="formData.isEnable" />
</el-form-item>
</el-form>
<el-form-item label="信息资料" prop="info">
<!-- <el-form-item label="信息资料" prop="info">
<Editor v-model="formData.info" height="250px" />
</el-form-item>
</el-form-item> -->
<template #footer>
<el-button @click="submitForm" type="primary" :disabled="formLoading"> </el-button>
<el-button @click="dialogVisible = false"> </el-button>
@ -86,9 +105,9 @@
</Dialog>
</template>
<script setup lang="ts">
import {getStrDictOptions, DICT_TYPE, getBoolDictOptions} from '@/utils/dict'
import { EnergyDeviceApi, EnergyDeviceVO } from '@/api/mes/energydevice'
import {EnergyTypeApi, EnergyTypeVO} from "@/api/mes/energytype";
import { OrganizationApi, DeviceParameterAnalysisNodeVO } from '@/api/mes/organization'
/** 能源设备 表单 */
defineOptions({ name: 'EnergyDeviceForm' })
@ -113,27 +132,68 @@ const formData = ref({
lastCheckValue: undefined,
unitName: undefined,
isEnable: undefined,
orgId: undefined,
orgName: undefined,
rules: undefined,
operationRulesVOList: [{ deviceId: undefined, pointId: undefined, operator: undefined, pointValue: undefined }],
})
const formRules = reactive({
name: [{ required: true, message: '设备名称不能为空', trigger: 'blur' }],
code: [{ required: true, message: '设备编码不能为空', trigger: 'blur' }],
name: [{ required: true, message: '表名称不能为空', trigger: 'blur' }],
code: [{ required: true, message: '表编码不能为空', trigger: 'blur' }],
orgId: [{ required: true, message: '所属区域不能为空', trigger: 'change' }],
operationRulesVOList: [{ required: true, validator: (_rule, _value, callback) => validateRules(callback), trigger: 'change' }],
isEnable: [{ required: true, message: '是否启用不能为空', trigger: 'blur' }]
})
const formRef = ref() // Ref
const analysisLoading = ref(false)
const analysisList = ref<DeviceParameterAnalysisNodeVO[]>([])
const treeSelectProps = {
label: 'name',
children: 'children',
disabled: 'disabled',
value: 'id'
}
const operatorOptions = ['+', '-', '*', '/']
const currentOrgNode = computed(() => {
return analysisList.value.find((o) => o.id === formData.value.orgId)
})
const equipmentTree = computed(() => {
const equipments = currentOrgNode.value?.equipments ?? []
return equipments.map((eq) => ({
id: `device:${eq.id}`,
name: eq.name,
disabled: true,
children: (eq.parameters ?? []).map((p) => ({
id: `${eq.id}:${p.id}`,
name: `${eq.name}: ${p.name}`
}))
}))
})
/** 打开弹窗 */
const open = async (type: string, id?: number) => {
dialogVisible.value = true
dialogTitle.value = t('action.' + type)
formType.value = type
resetForm()
await loadAnalysis()
//
if (id) {
formLoading.value = true
try {
formData.value = await EnergyDeviceApi.getEnergyDevice(id)
if (!Array.isArray((formData.value as any).operationRulesVOList)) {
;(formData.value as any).operationRulesVOList = [
{ deviceId: undefined, pointId: undefined, operator: undefined, pointValue: undefined }
]
}
hydratePointValues()
} finally {
formLoading.value = false
}
@ -151,6 +211,14 @@ const submitForm = async () => {
try {
const data = formData.value as unknown as EnergyDeviceVO
data.deviceTypeName = typeList.value.find(item => item.id === data.deviceTypeId)?.name
const org = analysisList.value.find((o) => o.id === data.orgId)
if (org) {
;(data as any).orgName = org.name
}
;(data as any).operationRulesVOList = buildOperationRulesPayload()
if (formType.value === 'create') {
await EnergyDeviceApi.createEnergyDevice(data)
message.success(t('common.createSuccess'))
@ -179,7 +247,11 @@ const resetForm = () => {
lastCheckTime: undefined,
lastCheckValue: undefined,
unitName: undefined,
isEnable: true
isEnable: true,
orgId: undefined,
orgName: undefined,
rules: undefined,
operationRulesVOList: [{ deviceId: undefined, pointId: undefined, operator: undefined, pointValue: undefined }]
}
formRef.value?.resetFields()
}
@ -189,8 +261,102 @@ onMounted(async () => {
typeList.value = await EnergyTypeApi.getEnergyTypeList()
})
/** 下拉框 */
const handleQuery = () => {
const loadAnalysis = async () => {
if (analysisList.value.length > 0) {
return
}
analysisLoading.value = true
try {
analysisList.value = await OrganizationApi.deviceParameterAnalysis({})
} finally {
analysisLoading.value = false
}
}
const handleDeviceTypeChange = () => {
formData.value.unitName = typeList.value.find(item => item.id === formData.value.deviceTypeId)?.unit
}
const handleOrgChange = () => {
const org = analysisList.value.find((o) => o.id === formData.value.orgId)
formData.value.orgName = org?.name
formData.value.operationRulesVOList = [
{ deviceId: undefined, pointId: undefined, operator: undefined, pointValue: undefined }
]
}
const handlePointSelected = (index: number, val: any) => {
if (!val || typeof val !== 'string' || !val.includes(':')) {
formData.value.operationRulesVOList[index].deviceId = undefined
formData.value.operationRulesVOList[index].pointId = undefined
return
}
const [deviceIdStr, pointIdStr] = val.split(':')
const deviceId = Number(deviceIdStr)
const pointId = Number(pointIdStr)
formData.value.operationRulesVOList[index].deviceId = Number.isNaN(deviceId) ? undefined : deviceId
formData.value.operationRulesVOList[index].pointId = Number.isNaN(pointId) ? undefined : pointId
}
const addRule = () => {
formData.value.operationRulesVOList.push({
deviceId: undefined,
pointId: undefined,
operator: undefined,
pointValue: undefined
})
}
const removeRule = () => {
if (formData.value.operationRulesVOList.length <= 1) {
return
}
formData.value.operationRulesVOList.pop()
}
const buildOperationRulesPayload = () => {
const list = (formData.value.operationRulesVOList ?? []).map((r, idx) => {
const item: any = {
deviceId: r.deviceId,
pointId: r.pointId
}
if (r.operator) {
item.operator = r.operator
}
return item
})
return list
}
const hydratePointValues = () => {
const list = (formData.value as any).operationRulesVOList as any[]
if (!Array.isArray(list)) {
return
}
list.forEach((r) => {
if (r?.deviceId && r?.pointId) {
r.pointValue = `${r.deviceId}:${r.pointId}`
}
})
}
const validateRules = (callback: any) => {
const list = formData.value.operationRulesVOList ?? []
if (!list.length) {
callback(new Error('计算规则不能为空'))
return
}
for (let i = 0; i < list.length; i++) {
const r = list[i] as any
if (!r?.deviceId || !r?.pointId) {
callback(new Error('请选择设备点位'))
return
}
if (i > 0 && !list[i - 1]?.operator) {
callback(new Error('请选择运算符'))
return
}
}
callback()
}
</script>

@ -3,7 +3,8 @@
<!-- 搜索工作栏 -->
<el-form class="-mb-15px" :model="queryParams" ref="queryFormRef" :inline="true" label-width="68px">
<el-form-item label="名称" prop="name">
<el-input v-model="queryParams.name" placeholder="请输入名称" clearable @keyup.enter="handleQuery"
<el-input
v-model="queryParams.name" placeholder="请输入名称" clearable @keyup.enter="handleQuery"
class="!w-240px" />
</el-form-item>
<el-form-item label="能耗类型" prop="deviceType">
@ -21,7 +22,8 @@
<el-button type="primary" plain @click="openForm('create')" v-hasPermi="['mes:energy-device:create']">
<Icon icon="ep:plus" class="mr-5px" /> 新增
</el-button>
<el-button type="success" plain @click="handleExport" :loading="exportLoading"
<el-button
type="success" plain @click="handleExport" :loading="exportLoading"
v-hasPermi="['mes:energy-device:export']">
<Icon icon="ep:download" class="mr-5px" /> 导出
</el-button>
@ -31,13 +33,14 @@
<!-- 列表 -->
<ContentWrap>
<el-table v-loading="loading" :data="list" :stripe="true" :show-overflow-tooltip="true" highlight-current-row
<el-table
v-loading="loading" :data="list" :stripe="true" :show-overflow-tooltip="true" highlight-current-row
@current-change="handleCurrentChange">
<el-table-column label="表编码" align="center" prop="code" />
<el-table-column label="表名称" align="center" prop="name" />
<el-table-column label="能耗类型" align="center" prop="deviceTypeName" />
<el-table-column label="所属区域" align="center" prop="orgName" />
<el-table-column label="计算规则" align="center" prop="rules" />
<!-- <el-table-column label="计算规则" align="center" prop="rules" /> -->
<!-- <el-table-column label="抄表周期" align="center" prop="checkCron" />
<el-table-column label="最后抄表值" align="center" prop="lastCheckValue" />
<el-table-column label="单位" align="center" prop="unitName" /> -->
@ -73,7 +76,8 @@
>
重置
</el-button> -->
<el-button link type="primary" @click="openForm('update', scope.row.id)"
<el-button
link type="primary" @click="openForm('update', scope.row.id)"
v-hasPermi="['mes:energy-device:update']">
编辑
</el-button>
@ -84,7 +88,8 @@
</el-table-column>
</el-table>
<!-- 分页 -->
<Pagination :total="total" v-model:page="queryParams.pageNo" v-model:limit="queryParams.pageSize"
<Pagination
:total="total" v-model:page="queryParams.pageNo" v-model:limit="queryParams.pageSize"
@pagination="getList" />
</ContentWrap>

Loading…
Cancel
Save