黄伟杰 2 months ago
commit 7137ca46df

@ -544,8 +544,8 @@ export default {
small: 'Small'
},
home:{
welcome: 'Welcome to use the Bishuo Digital Intelligent Central Control Platform',
message: 'The Bishuo Digital Intelligent Central Control Platform takes production operation as the core, uniformly integrating key business modules such as production planning, data collection, warehousing, equipment, energy, molds, quality, formulas and report analysis, to achieve full-process digital management from planning to execution, from equipment to products, and from data to decision-making.',
welcome: 'Welcome to use the Besure Digital Intelligent Central Control Platform',
message: 'The Besure Digital Intelligent Central Control Platform takes production operation as the core, uniformly integrating key business modules such as production planning, data collection, warehousing, equipment, energy, molds, quality, formulas and report analysis, to achieve full-process digital management from planning to execution, from equipment to products, and from data to decision-making.',
productTitle:'Overall production overview',
placeholderCreateTimeStart: 'Start Date',
placeholderCreateTimeEnd: 'End Date',

@ -0,0 +1,902 @@
<template>
<Dialog :title="dialogTitle" v-model="dialogVisible" width="1200px" :show-close="false">
<template v-if="attributeDeviceId">
<div class="mb-10px flex items-center justify-between text-sm text-gray-500">
<div>
{{ t('DataCollection.Device.currentDeviceLabel') }}<span class="font-medium text-gray-700">{{ attributeDeviceName || '-' }}</span>
</div>
<div>
<el-button type="primary" link @click="handleShowDeviceAlarmHistory">
{{ t('DataCollection.Device.alarmHistoryTitle') }}
</el-button>
</div>
</div>
<el-tabs v-model="deviceTabActive">
<el-tab-pane :label="deviceAttributeTabLabel" name="deviceAttribute">
<DeviceAttributeList :device-id="attributeDeviceId" />
</el-tab-pane>
<el-tab-pane :label="deviceRuleTabLabel" name="deviceRule">
<el-form
class="-mb-15px"
:model="ruleQueryParams"
ref="ruleQueryFormRef"
:inline="true"
label-width="120px"
>
<el-form-item :label="t('DataCollection.DeviceModel.ruleIdentifier')" prop="identifier">
<el-input
v-model="ruleQueryParams.identifier"
:placeholder="t('DataCollection.DeviceModel.ruleSearchIdentifierPlaceholder')"
clearable
@keyup.enter="handleRuleQuery"
class="!w-200px"
/>
</el-form-item>
<el-form-item :label="t('DataCollection.DeviceModel.ruleFieldName')" prop="fieldName">
<el-input
v-model="ruleQueryParams.fieldName"
:placeholder="t('DataCollection.DeviceModel.ruleSearchFieldNamePlaceholder')"
clearable
@keyup.enter="handleRuleQuery"
class="!w-200px"
/>
</el-form-item>
<el-form-item :label="t('DataCollection.DeviceModel.ruleDefaultValue')" prop="defaultValue">
<el-input
v-model="ruleQueryParams.defaultValue"
:placeholder="t('DataCollection.DeviceModel.ruleSearchDefaultValuePlaceholder')"
clearable
@keyup.enter="handleRuleQuery"
class="!w-200px"
/>
</el-form-item>
<el-form-item>
<el-button @click="handleRuleQuery">
<Icon icon="ep:search" class="mr-5px" /> {{ t('DataCollection.DeviceModel.ruleSearch') }}
</el-button>
<el-button @click="resetRuleQuery">
<Icon icon="ep:refresh" class="mr-5px" /> {{ t('DataCollection.DeviceModel.ruleReset') }}
</el-button>
</el-form-item>
</el-form>
<div class="mb-10px text-right">
<el-button type="primary" @click="openCreateRuleForm">
{{ t('DataCollection.DeviceModel.ruleCreateButton') }}
</el-button>
</div>
<el-table
v-loading="ruleLoading"
:data="ruleList"
:stripe="true"
:show-overflow-tooltip="true"
row-key="id"
>
<el-table-column :label="t('DataCollection.DeviceModel.ruleIdentifier')" align="center" prop="identifier" />
<el-table-column :label="t('DataCollection.DeviceModel.ruleFieldName')" align="center" prop="fieldName" sortable />
<el-table-column :label="t('DataCollection.DeviceModel.ruleFieldRule')" align="center" prop="fieldRule" />
<el-table-column :label="t('DataCollection.DeviceModel.ruleDefaultValue')" align="center" prop="defaultValue" />
<el-table-column
:label="t('DataCollection.DeviceModel.ruleCreateTime')"
align="center"
prop="createTime"
:formatter="dateFormatter"
width="180px"
sortable
/>
<el-table-column :label="t('DataCollection.DeviceModel.ruleOperate')" align="center" width="160px">
<template #default="scope">
<el-button link type="primary" @click="openRuleForm(scope.row)">
{{ t('DataCollection.DeviceModel.ruleEditRuleButton') }}
</el-button>
<el-button
v-if="(scope.row.identifier || '').toString().toUpperCase() === 'ALARM'"
link
type="danger"
@click="handleRuleDelete(scope.row.id)"
>
{{ t('DataCollection.DeviceModel.ruleDeleteRuleButton') }}
</el-button>
</template>
</el-table-column>
</el-table>
<Pagination
:total="ruleTotal"
v-model:page="ruleQueryParams.pageNo"
v-model:limit="ruleQueryParams.pageSize"
@pagination="getRuleList"
/>
<el-dialog v-model="ruleDialogVisible" :title="t('DataCollection.DeviceModel.ruleDialogTitle')" width="880px" draggable>
<el-form :model="ruleForm" ref="ruleFormRef" label-width="120px">
<el-form-item :label="t('DataCollection.DeviceModel.ruleDialogIdentifier')">
<el-input v-model="ruleForm.identifier" disabled />
</el-form-item>
<el-form-item :label="t('DataCollection.DeviceModel.ruleDialogFieldName')">
<el-input v-model="ruleForm.fieldName" disabled />
</el-form-item>
<el-form-item :label="t('DataCollection.DeviceModel.ruleDialogDefaultValue')">
<el-input v-model="ruleForm.defaultValue" disabled />
</el-form-item>
<el-form-item
v-if="(ruleForm.identifier || '').toString().toUpperCase() === 'ALARM'"
:label="t('DataCollection.DeviceModel.ruleDialogAlarmLevel')"
>
<el-select
v-model="ruleForm.alarmLevel"
:placeholder="t('DataCollection.DeviceModel.ruleDialogAlarmLevelPlaceholder')"
>
<el-option
v-for="dict in getStrDictOptions(DICT_TYPE.IOT_ALARM_REGISTRATION)"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
</el-select>
</el-form-item>
<div class="flex flex-col w-full">
<div class="border border-gray-200 dark:border-gray-600 rounded-md py-12px">
<el-form-item :label="t('DataCollection.DeviceModel.ruleDialogFieldRule')">
<el-select
v-model="ruleForm.fieldRule"
:placeholder="t('DataCollection.DeviceModel.ruleDialogFieldRulePlaceholder')"
class="!w-240px"
:disabled="!currentRuleOptions.length"
>
<el-option
v-for="item in currentRuleOptions"
:key="item.value"
:label="item.label"
:value="item.value"
:disabled="isRuleDisabled(item.value, ruleForm.fieldRule)"
/>
</el-select>
</el-form-item>
<el-form-item :label="t('DataCollection.DeviceModel.ruleDialogRule')">
<div class="flex items-center gap-8px">
<el-select
v-model="ruleForm.ruleAttributeId"
:placeholder="t('DataCollection.DeviceModel.ruleDialogRuleAttributePlaceholder')"
class="!w-240px"
>
<el-option
v-for="item in ruleAttributeOptions"
:key="item.id"
:label="item.attributeName || item.attributeCode"
:value="item.id"
/>
</el-select>
<el-select
v-model="ruleForm.ruleOperator"
:placeholder="t('DataCollection.DeviceModel.ruleDialogRuleOperatorPlaceholder')"
class="!w-160px"
>
<el-option
v-for="item in ruleOperatorOptions"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
<el-input
v-if="ruleForm.ruleOperator !== 'TRUE' && ruleForm.ruleOperator !== 'FALSE'"
v-model="ruleForm.ruleValue"
:placeholder="t('DataCollection.DeviceModel.ruleDialogRuleValuePlaceholder')"
class="!w-200px"
/>
</div>
</el-form-item>
</div>
<div
v-for="(item, index) in extraPointRules"
:key="index"
class="border border-gray-200 dark:border-gray-600 rounded-md px-16px py-12px"
>
<el-form-item :label="t('DataCollection.DeviceModel.ruleDialogFieldRule')">
<el-select
v-model="item.rule"
:placeholder="t('DataCollection.DeviceModel.ruleDialogFieldRulePlaceholder')"
class="!w-240px"
>
<el-option
v-for="opt in currentRuleOptions"
:key="opt.value"
:label="opt.label"
:value="opt.value"
:disabled="isRuleDisabled(opt.value, item.rule)"
/>
</el-select>
</el-form-item>
<el-form-item :label="t('DataCollection.DeviceModel.ruleDialogRule')">
<div class="flex items-center gap-8px">
<el-select
v-model="item.id"
:placeholder="t('DataCollection.DeviceModel.ruleDialogRuleAttributePlaceholder')"
class="!w-240px"
>
<el-option
v-for="attr in ruleAttributeOptions"
:key="attr.id"
:label="attr.attributeName || attr.attributeCode"
:value="attr.id"
/>
</el-select>
<el-select
v-model="item.operator"
:placeholder="t('DataCollection.DeviceModel.ruleDialogRuleOperatorPlaceholder')"
class="!w-160px"
>
<el-option
v-for="opt in ruleOperatorOptions"
:key="opt.value"
:label="opt.label"
:value="opt.value"
/>
</el-select>
<el-input
v-if="item.operator !== 'TRUE' && item.operator !== 'FALSE'"
v-model="item.operatorRule"
:placeholder="t('DataCollection.DeviceModel.ruleDialogRuleValuePlaceholder')"
class="!w-200px"
/>
<el-button type="danger" link @click="handleRemovePointRule(index)">
{{ t('DataCollection.DeviceModel.ruleDeleteRuleButton') }}
</el-button>
</div>
</el-form-item>
</div>
<el-form-item v-if="isRunningIdentifier" label=" ">
<el-button type="primary" link @click="handleAddPointRule">
+ {{ t('DataCollection.DeviceModel.ruleCreateButton') }}
</el-button>
</el-form-item>
</div>
</el-form>
<template #footer>
<span class="dialog-footer">
<el-button @click="ruleDialogVisible = false">{{ t('DataCollection.DeviceModel.dialogCancel') }}</el-button>
<el-button type="primary" :loading="ruleFormLoading" @click="handleRuleSubmit">{{ t('DataCollection.DeviceModel.dialogOk') }}</el-button>
</span>
</template>
</el-dialog>
<el-dialog v-model="createRuleDialogVisible" :title="t('DataCollection.DeviceModel.ruleCreateButton')" width="520px" draggable>
<el-form :model="createRuleForm" ref="createRuleFormRef" label-width="120px">
<el-form-item :label="t('DataCollection.DeviceModel.ruleDialogIdentifier')">
<el-input v-model="createRuleForm.identifier" disabled />
</el-form-item>
<el-form-item :label="t('DataCollection.DeviceModel.ruleDialogFieldName')">
<el-input
v-model="createRuleForm.fieldName"
:placeholder="t('DataCollection.DeviceModel.ruleSearchFieldNamePlaceholder')"
/>
</el-form-item>
<el-form-item :label="t('DataCollection.DeviceModel.ruleDialogDefaultValue')">
<el-input v-model="createRuleForm.defaultValue" disabled />
</el-form-item>
<el-form-item :label="t('DataCollection.DeviceModel.ruleDialogAlarmLevel')">
<el-select
v-model="createRuleForm.alarmLevel"
:placeholder="t('DataCollection.DeviceModel.ruleDialogAlarmLevelPlaceholder')"
>
<el-option
v-for="dict in getStrDictOptions(DICT_TYPE.IOT_ALARM_REGISTRATION)"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
</el-select>
</el-form-item>
</el-form>
<template #footer>
<span class="dialog-footer">
<el-button @click="createRuleDialogVisible = false">{{ t('DataCollection.DeviceModel.dialogCancel') }}</el-button>
<el-button type="primary" :loading="createRuleFormLoading" @click="handleCreateRuleSubmit">
{{ t('DataCollection.DeviceModel.dialogOk') }}
</el-button>
</span>
</template>
</el-dialog>
</el-tab-pane>
</el-tabs>
</template>
<el-empty v-else :description="t('DataCollection.Device.emptyDescription')" />
</Dialog>
<Dialog :title="t('DataCollection.Device.alarmHistoryTitle')" v-model="deviceAlarmDialogVisible" width="1200px">
<el-form
class="-mb-15px"
:model="deviceAlarmQueryParams"
ref="deviceAlarmQueryFormRef"
:inline="true"
label-width="80px"
>
<el-form-item :label="t('DataCollection.Device.alarmRuleName')" prop="ruleId">
<el-select
v-model="deviceAlarmQueryParams.ruleId"
:loading="deviceAlarmRuleLoading"
clearable
filterable
class="!w-220px"
:placeholder="t('DataCollection.DeviceModel.ruleSearchFieldNamePlaceholder')"
>
<el-option
v-for="item in deviceAlarmRuleOptions"
:key="item.id"
:label="item.fieldName || item.ruleName || item.name"
:value="item.id"
/>
</el-select>
</el-form-item>
<el-form-item :label="t('DataCollection.Device.alarmPointName')" prop="modelId">
<el-select
v-model="deviceAlarmQueryParams.modelId"
:loading="deviceAlarmPointLoading"
clearable
filterable
class="!w-220px"
:placeholder="t('DataCollection.Device.placeholderAttributeName')"
>
<el-option
v-for="item in deviceAlarmPointOptions"
:key="item.id"
:label="item.attributeName || item.attributeCode || item.name"
:value="item.id"
/>
</el-select>
</el-form-item>
<el-form-item :label="t('DataCollection.Device.alarmTime')" prop="createTime">
<el-date-picker
v-model="deviceAlarmQueryParams.createTime"
value-format="YYYY-MM-DD HH:mm:ss"
type="daterange"
:default-time="[new Date('1 00:00:00'), new Date('1 23:59:59')]"
:start-placeholder="t('DataCollection.HistoryData.dialogCollectionTimeStartPlaceholder')"
:end-placeholder="t('DataCollection.HistoryData.dialogCollectionTimeEndPlaceholder')"
class="!w-260px"
/>
</el-form-item>
<el-form-item>
<el-button @click="handleDeviceAlarmQuery">
<Icon icon="ep:search" class="mr-5px" />
{{ t('DataCollection.Device.search') }}
</el-button>
<el-button @click="resetDeviceAlarmQuery">
<Icon icon="ep:refresh" class="mr-5px" />
{{ t('DataCollection.Device.reset') }}
</el-button>
</el-form-item>
</el-form>
<el-table
:data="deviceAlarmList"
v-loading="deviceAlarmLoading"
:stripe="true"
:show-overflow-tooltip="true"
:max-height="700"
class="mt-10px"
>
<el-table-column :label="t('DataCollection.Device.alarmRuleName')" align="center" prop="ruleName" sortable />
<el-table-column :label="t('DataCollection.Device.alarmPointName')" align="center" prop="modelName" sortable />
<el-table-column :label="t('DataCollection.Device.alarmPointValue')" align="center" prop="addressValue" />
<el-table-column :label="t('DataCollection.Device.alarmLevel')" align="center" prop="alarmLevel">
<template #default="scope">
<dict-tag :type="DICT_TYPE.IOT_ALARM_REGISTRATION" :value="scope.row.alarmLevel" />
</template>
</el-table-column>
<el-table-column
:label="t('DataCollection.Device.alarmTime')"
align="center"
prop="createTime"
:formatter="dateFormatter"
width="180px"
sortable />
</el-table>
<div class="mt-10px pb-10px flex justify-end">
<Pagination
:total="deviceAlarmTotal"
v-model:page="deviceAlarmQueryParams.pageNo"
v-model:limit="deviceAlarmQueryParams.pageSize"
@pagination="getDeviceAlarmList"
/>
</div>
</Dialog>
</template>
<script setup lang="ts">
import { getStrDictOptions, DICT_TYPE } from '@/utils/dict'
import { dateFormatter } from '@/utils/formatTime'
import download from '@/utils/download'
import request from '@/config/axios'
import DeviceForm from './DeviceForm.vue'
import DeviceAttributeList from './components/DeviceAttributeList.vue'
/** 物联设备 表单 */
defineOptions({ name: 'DeviceForm' })
const attributeDeviceId = ref<number | undefined>(undefined)
const attributeDeviceName = ref('')
const { t } = useI18n() //
const message = useMessage() //
const dialogVisible = ref(false) //
const dialogTitle = ref('') //
const formLoading = ref(false) // 12
const formRef = ref() // Ref
/** 打开弹窗 */
const open = async (id?: number,deviceName?: string) => {
dialogVisible.value = true
attributeDeviceId.value= id
attributeDeviceName.value = deviceName
}
defineExpose({ open }) // open
const deviceAlarmDialogVisible = ref(false)
const deviceAlarmLoading = ref(false)
const deviceAlarmList = ref<any[]>([])
const deviceAlarmTotal = ref(0)
const deviceTabActive = ref('deviceAttribute')
const deviceAlarmQueryFormRef = ref()
const deviceAlarmRuleOptions = ref<any[]>([])
const deviceAlarmPointOptions = ref<any[]>([])
const deviceAlarmRuleLoading = ref(false)
const deviceAlarmPointLoading = ref(false)
const ruleLoading = ref(false)
const ruleTotal = ref(0)
const ruleList = ref<DevicePointRuleVO[]>([])
const ruleQueryFormRef = ref()
const createRuleDialogVisible = ref(false)
const createRuleFormLoading = ref(false)
const createRuleFormRef = ref()
const deviceAttributeTabLabel = computed(() => {
return t('DataCollection.Device.deviceAttributeTabLabel')
})
const deviceRuleTabLabel = computed(() => {
return t('DataCollection.Device.deviceRuleTabLabel')
})
const ruleOperatorOptions = computed(() => getStrDictOptions('czsb_rules_conditions'))
const isRunningIdentifier = computed(() => {
return (ruleForm.identifier || '').toString().toUpperCase() === 'RUNNING'
})
const isRuleDisabled = (value: string, selfRule?: string | number) => {
if (!value) return false
const v = String(value)
const self = selfRule != null ? String(selfRule) : undefined
if (self === v) return false
if (ruleForm.fieldRule && String(ruleForm.fieldRule) === v && self !== v) return true
if (
extraPointRules.value.some(
(item) => item.rule != null && String(item.rule) === v && String(item.rule) !== self
)
) {
return true
}
return false
}
const ruleDialogVisible = ref(false)
const ruleFormLoading = ref(false)
const ruleFormRef = ref()
const ruleForm = reactive<Partial<DevicePointRuleVO>>({
id: undefined,
identifier: '',
fieldName: '',
fieldRule: '',
defaultValue: '',
deviceId: undefined,
ruleAttributeId: undefined,
ruleOperator: undefined,
ruleValue: undefined,
alarmLevel: '',
})
const createRuleForm = reactive({
identifier: 'ALARM',
fieldName: '',
defaultValue: '报警',
alarmLevel: '',
})
const deviceAlarmQueryParams = reactive({
pageNo: 1,
pageSize: 10,
deviceId: undefined as number | undefined,
modelId: undefined as number | undefined,
rule: undefined as string | undefined,
alarmLevel: undefined as string | undefined,
addressValue: undefined as string | undefined,
createTime: [] as string[],
ruleId: undefined as number | undefined,
})
const handleRuleSubmit = async () => {
if (!ruleForm.id) return
try {
ruleFormLoading.value = true
const pointRulesVOList: any[] = []
if (ruleForm.ruleAttributeId && ruleForm.ruleOperator) {
const attr = ruleAttributeOptions.value.find(
(item) => item.id === ruleForm.ruleAttributeId
)
if (attr && attr.attributeCode) {
pointRulesVOList.push({
code: attr.attributeCode,
rule: ruleForm.fieldRule,
operator: ruleForm.ruleOperator,
operatorRule: ruleForm.ruleValue,
})
}
}
extraPointRules.value.forEach((item) => {
if (!item.id || !item.operator) return
const attr = ruleAttributeOptions.value.find((opt) => opt.id === item.id)
if (!attr || !attr.attributeCode) return
pointRulesVOList.push({
code: attr.attributeCode,
rule: item.rule ?? ruleForm.fieldRule,
operator: item.operator,
operatorRule: item.operatorRule,
})
})
const payload = {
id: ruleForm.id,
identifier: ruleForm.identifier,
fieldName: ruleForm.fieldName,
fieldRule: ruleForm.fieldRule,
defaultValue: ruleForm.defaultValue,
deviceId: ruleForm.deviceId ?? attributeDeviceId.value,
alarmLevel: ruleForm.alarmLevel,
pointRulesVOList,
}
await request.put({ url: '/iot/device-point-rules/update', data: payload })
message.success(t('common.updateSuccess'))
ruleDialogVisible.value = false
await getRuleList()
} finally {
ruleFormLoading.value = false
}
}
interface DevicePointRuleVO {
id: number
identifier: string
fieldName: string
fieldRule: string
defaultValue: string
deviceId: number
createTime?: string | number | Date
ruleAttributeId?: number
ruleOperator?: string
ruleValue?: string | number
}
const ruleQueryParams = reactive({
pageNo: 1,
pageSize: 10,
identifier: undefined as string | undefined,
fieldName: undefined as string | undefined,
fieldRule: undefined as string | undefined,
defaultValue: undefined as string | undefined,
alarmLevel: undefined as string | undefined,
deviceId: undefined as number | undefined,
})
const handleDeviceAlarmQuery = () => {
if (!attributeDeviceId.value) return
deviceAlarmQueryParams.pageNo = 1
getDeviceAlarmList()
}
const resetDeviceAlarmQuery = () => {
if (!attributeDeviceId.value) return
deviceAlarmQueryFormRef.value?.resetFields?.()
deviceAlarmQueryParams.pageNo = 1
getDeviceAlarmList()
}
const openCreateRuleForm = () => {
if (!attributeDeviceId.value) {
message.error('请先选择设备')
return
}
createRuleForm.identifier = 'ALARM'
createRuleForm.fieldName = '报警'
createRuleForm.defaultValue = '报警'
createRuleForm.alarmLevel = ''
createRuleDialogVisible.value = true
}
const handleCreateRuleSubmit = async () => {
if (!attributeDeviceId.value) return
if (!createRuleForm.fieldName) {
message.warning('请输入名称')
return
}
try {
createRuleFormLoading.value = true
const payload = {
identifier: createRuleForm.identifier,
fieldName: createRuleForm.fieldName,
defaultValue: createRuleForm.defaultValue,
alarmLevel: createRuleForm.alarmLevel,
deviceId: attributeDeviceId.value,
}
await request.post({ url: '/iot/device-point-rules/create', data: payload })
message.success('新增成功')
createRuleDialogVisible.value = false
await getRuleList()
} finally {
createRuleFormLoading.value = false
}
}
const handleRuleDelete = async (id: number) => {
if (!id) return
try {
await message.delConfirm()
await request.delete({ url: '/iot/device-point-rules/delete?id=' + id })
message.success(t('common.delSuccess'))
await getRuleList()
} catch { }
}
const handleAddPointRule = () => {
if (!isRunningIdentifier.value) return
const allOptions = currentRuleOptions.value || []
const used = new Set<string>()
if (ruleForm.fieldRule) used.add(String(ruleForm.fieldRule))
extraPointRules.value.forEach((item) => {
if (item.rule != null) used.add(String(item.rule))
})
const next = allOptions.find((opt) => !used.has(String(opt.value)))
if (!next) {
message.warning('已没有可用的点位规则可选')
return
}
extraPointRules.value.push({
rule: next.value as any,
id: undefined,
operator: undefined,
operatorRule: undefined,
})
}
const handleRemovePointRule = (index: number) => {
if (index < 0 || index >= extraPointRules.value.length) return
extraPointRules.value.splice(index, 1)
}
const resetRuleQuery = () => {
if (!attributeDeviceId.value) return
ruleQueryFormRef.value?.resetFields?.()
handleRuleQuery()
}
const handleRuleQuery = () => {
if (!attributeDeviceId.value) return
ruleQueryParams.pageNo = 1
getRuleList()
}
const getRuleList = async () => {
if (!attributeDeviceId.value) return
ruleLoading.value = true
try {
const params = {
...ruleQueryParams,
deviceId: attributeDeviceId.value,
}
const data = await request.get({ url: '/iot/device-point-rules/page', params })
const listData = Array.isArray((data as any)?.list) ? (data as any).list : (Array.isArray(data) ? data : [])
const totalData = (data as any)?.total ?? listData.length
ruleList.value = listData as DevicePointRuleVO[]
ruleTotal.value = totalData
} finally {
ruleLoading.value = false
}
}
const handleShowDeviceAlarmHistory = async () => {
if (!attributeDeviceId.value) {
message.error(t('DataCollection.Device.messageSelectDeviceRequired'))
return
}
deviceAlarmQueryParams.pageNo = 1
deviceAlarmQueryParams.pageSize = 10
deviceAlarmQueryParams.modelId = undefined
deviceAlarmQueryParams.rule = undefined
deviceAlarmQueryParams.alarmLevel = undefined
deviceAlarmQueryParams.addressValue = undefined
deviceAlarmQueryParams.createTime = []
deviceAlarmQueryParams.ruleId = undefined
deviceAlarmDialogVisible.value = true
await Promise.all([loadDeviceAlarmRuleOptions(), loadDeviceAlarmPointOptions()])
await getDeviceAlarmList()
}
const getDeviceAlarmList = async () => {
if (!attributeDeviceId.value) return
deviceAlarmLoading.value = true
try {
deviceAlarmQueryParams.deviceId = attributeDeviceId.value
const params = {
pageNo: deviceAlarmQueryParams.pageNo,
pageSize: deviceAlarmQueryParams.pageSize,
deviceId: deviceAlarmQueryParams.deviceId,
modelId: deviceAlarmQueryParams.modelId,
rule: deviceAlarmQueryParams.rule,
alarmLevel: deviceAlarmQueryParams.alarmLevel,
addressValue: deviceAlarmQueryParams.addressValue,
createTime: deviceAlarmQueryParams.createTime,
ruleId: deviceAlarmQueryParams.ruleId,
}
const data = await request.get({
url: '/iot/device-warinning-record/page',
params,
})
const listData = Array.isArray((data as any)?.list)
? (data as any).list
: Array.isArray(data)
? data
: []
const totalData = (data as any)?.total ?? listData.length
deviceAlarmList.value = listData as any[]
deviceAlarmTotal.value = totalData
} finally {
deviceAlarmLoading.value = false
}
}
const loadDeviceAlarmRuleOptions = async () => {
if (!attributeDeviceId.value) return
deviceAlarmRuleLoading.value = true
try {
const res = await request.get({
url: '/iot/device-point-rules/getList',
params: { id: attributeDeviceId.value },
})
const data = (res as any)?.data ?? res
const listData = Array.isArray((data as any)?.list)
? (data as any).list
: Array.isArray(data)
? data
: []
deviceAlarmRuleOptions.value = listData as any[]
} finally {
deviceAlarmRuleLoading.value = false
}
}
const loadDeviceAlarmPointOptions = async () => {
if (!attributeDeviceId.value) return
deviceAlarmPointLoading.value = true
try {
const res = await request.get({
url: '/iot/device/device-attribute/list',
params: { deviceId: attributeDeviceId.value },
})
const data = (res as any)?.data ?? res
const listData = Array.isArray((data as any)?.list)
? (data as any).list
: Array.isArray(data)
? data
: []
deviceAlarmPointOptions.value = listData as any[]
} finally {
deviceAlarmPointLoading.value = false
}
}
const ruleAttributeOptions = ref<any[]>([])
const loadRuleAttributeOptions = async (deviceId: number) => {
try {
const res = await request.get({ url: '/iot/device-contact-model/list', params: { id: deviceId } })
const data = Array.isArray(res) ? res : (res as any)?.list ?? []
ruleAttributeOptions.value = data as any[]
} catch {
ruleAttributeOptions.value = []
}
}
const extraPointRules = ref<
Array<{
id?: number
rule?: string
operator?: string
operatorRule?: string | number
}>
>([])
const currentRuleOptions = computed(() => {
const id = (ruleForm.identifier || '').toString().toUpperCase()
if (id === 'RUNNING') return runningRuleOptions
if (id === 'ALARM') return alarmRuleOptions
return []
})
const runningRuleOptions = [
{ value: '1', label: '运行' },
{ value: '2', label: '待机中(不运行、没故障)' },
{ value: '3', label: '故障中(故障且待机)' },
// { value: '4', label: '' },
]
const alarmRuleOptions = [{ value: '5', label: '报警' }]
const openRuleForm = async (row: DevicePointRuleVO & { pointRulesVOList?: any[] }) => {
const deviceId = row.deviceId || attributeDeviceId.value
if (!deviceId) {
message.error(t('DataCollection.Device.messageDeviceInfoMissingForRules'))
return
}
await loadRuleAttributeOptions(deviceId)
ruleForm.id = row.id
ruleForm.identifier = row.identifier
ruleForm.fieldName = row.fieldName
ruleForm.defaultValue = row.defaultValue
ruleForm.deviceId = row.deviceId
ruleForm.alarmLevel = (row as any).alarmLevel
extraPointRules.value = []
const list = Array.isArray(row.pointRulesVOList) ? row.pointRulesVOList : []
if (list.length) {
const first = list[0] as any
const firstRule = first.rule ?? row.fieldRule
const firstAttrId = (() => {
if (first && first.code != null) {
const target = ruleAttributeOptions.value.find(
(item) => item.attributeCode === first.code
)
return target?.id
}
if (first && first.id != null) return first.id
return undefined
})()
ruleForm.fieldRule = firstRule as any
ruleForm.ruleAttributeId = firstAttrId as any
ruleForm.ruleOperator = first.operator as any
ruleForm.ruleValue = first.operatorRule as any
extraPointRules.value = list.slice(1).map((item: any) => ({
id: (() => {
if (item && item.code != null) {
const target = ruleAttributeOptions.value.find(
(opt) => opt.attributeCode === item.code
)
return target?.id
}
if (item && item.id != null) return item.id
return undefined
})(),
rule: item.rule,
operator: item.operator,
operatorRule: item.operatorRule,
}))
} else {
ruleForm.fieldRule = row.fieldRule
ruleForm.ruleAttributeId = row.ruleAttributeId
ruleForm.ruleOperator = row.ruleOperator
ruleForm.ruleValue = row.ruleValue as any
}
const options = currentRuleOptions.value
if (options.length && !options.some((item) => item.value === ruleForm.fieldRule)) {
ruleForm.fieldRule = options[0].value
}
ruleDialogVisible.value = true
}
/** 初始化 **/
</script>

@ -202,8 +202,11 @@
v-for="(item, index) in list"
:key="item.id || index"
class="grid-card"
@click="handleShowAttribute(item)"
@click="openDetailForm(item?.id,item?.deviceName)"
>
<!-- attributeDeviceId.value = row?.id
attributeDeviceName.value = row?.deviceName ?? ''-->
<!-- 设备状态指示 status-${item.deviceStatus} -->
<div class="status-indicator" :class="getStatusText(item.operatingStatus)"></div>
@ -269,7 +272,7 @@
<!-- 表单弹窗添加/修改 -->
<DeviceForm ref="formRef" @success="getList" />
<!-- 子表的列表 -->
<ContentWrap>
<ContentWrap v-if="ifShow">
<template v-if="attributeDeviceId">
<div class="mb-10px flex items-center justify-between text-sm text-gray-500">
<div>
@ -675,6 +678,9 @@
/>
</div>
</Dialog>
<!-- 表单弹窗弹出设备属性 -->
<DetailForm ref="detailFormRef" />
</template>
<script setup lang="ts">
@ -693,7 +699,9 @@ import {
Location
} from '@element-plus/icons-vue'
import {useRouter} from "vue-router";
import DetailForm from "@/views/iot/device/detailForm.vue";
import {ProductUnitApi, ProductUnitVO} from "@/api/erp/product/unit";
const ifShow =ref(true)
const currentView = ref('table') // 'table' 'grid'
//
const router = useRouter()
@ -752,7 +760,9 @@ const getStatusText = (status) => {
}
//
const toggleView = () => {
currentView.value = currentView.value === 'table' ? 'grid' : 'table'
ifShow.value=currentView.value === 'table' ? true : false;
//
localStorage.setItem('equipment-view', currentView.value)
}
@ -870,6 +880,15 @@ const formRef = ref()
const openForm = (type: string, id?: number) => {
formRef.value.open(type, id)
}
/** 设备属性弹出框 */
const detailFormRef = ref()
const openDetailForm = (id?: number,deviceName?:string) => {
attributeDeviceId.value = undefined
attributeDeviceName.value = ''
detailFormRef.value.open(id,deviceName)
//formRef.value.open(id,deviceName)
}
/** 删除按钮操作 */
const buildIdsParam = (ids: number | number[]) => {
@ -886,6 +905,8 @@ const handleDelete = async (ids: number | number[]) => {
message.success(t('common.delSuccess'))
selectedIds.value = []
tableRef.value?.clearSelection?.()
if (attributeDeviceId.value && idsParam.split(',').includes(String(attributeDeviceId.value))) {
attributeDeviceId.value = undefined
attributeDeviceName.value = ''

@ -51,6 +51,7 @@
<Icon icon="ep:back" />
<span>返回</span>
</div> -->
<Screenfull class="custom-hover" color="var(--top-header-text-color)"/>
<div class="weather">
<Icon icon="fa-solid:cloud-sun" class="weather-icon" />
<div class="weather-meta">
@ -68,7 +69,7 @@ import { ref, onMounted, onUnmounted, watch } from 'vue'
import { useRouter } from 'vue-router'
import { useI18n } from '@/hooks/web/useI18n'
import { useLocaleStore } from '@/store/modules/locale'
import { Screenfull } from '@/layout/components/Screenfull'
const router = useRouter()
const { t } = useI18n('ReportDashboard')
const localeStore = useLocaleStore()

Loading…
Cancel
Save