Compare commits

..

6 Commits

@ -1,4 +1,5 @@
import request from '@/config/axios'
import qs from 'qs'
// 物联设备 VO
export interface DeviceVO {
@ -65,6 +66,7 @@ export interface HistoryRecordParams {
deviceId: string | number
collectionStartTime?: string
collectionEndTime?: string
attributeCodes?: string[]
}
export interface DeviceContactModelVO {
@ -143,7 +145,11 @@ export const DeviceApi = {
},
getHistoryRecord: async (params: HistoryRecordParams) => {
return await request.get({ url: `/iot/device/historyRecord`, params })
return await request.get({
url: `/iot/device/historyRecord`,
params,
paramsSerializer: (p) => qs.stringify(p, { allowDots: true, arrayFormat: 'repeat' })
})
},
devicePointList: async () => {
@ -162,7 +168,7 @@ export const DeviceApi = {
return await request.get({ url: `/iot/device/device-attribute/page`, params })
},
// 获得设备属性列表
getDeviceAttributeList: async (deviceId: number) => {
getDeviceAttributeList: async (deviceId: number | string) => {
return await request.get({ url: `/iot/device/device-attribute/list?deviceId=` + deviceId })
},

@ -37,6 +37,7 @@ export default {
toolDes: 'Used to set up custom systems',
query: 'Query',
reset: 'Reset',
noData: 'No data',
shrink: 'Put away',
expand: 'Expand',
confirmTitle: 'System Hint',
@ -59,6 +60,47 @@ export default {
copyError: 'Copy Error',
code:'Auto-generate on Save'
},
ReportDashboard: {
DashboardList: {
searchNameLabel: 'Name',
searchNamePlaceholder: 'Please enter name',
searchRemarkLabel: 'Remark',
searchRemarkPlaceholder: 'Please enter remark',
searchStateLabel: 'Status',
searchStatePlaceholder: 'Please select status',
coverAlt: 'Cover image',
stateEnabled: 'Enabled',
stateDisabled: 'Disabled',
noRemark: 'No description',
dialogCreateTitle: 'Create Dashboard',
dialogEditTitle: 'Edit Dashboard',
dialogNameLabel: 'Name',
dialogNamePlaceholder: 'Please enter name',
dialogTypeLabel: 'Type',
dialogTypePlaceholder: 'Please select type',
dialogOrgLabel: 'Line',
dialogOrgPlaceholder: 'Please select line',
dialogDeviceLabel: 'Device',
dialogDevicePlaceholder: 'Please select device',
dialogPointPlaceholder: 'Please select points',
dialogAddDeviceButton: 'Add device',
dialogContentLabel: 'Content',
dialogContentPlaceholder: 'Please enter content',
dialogRemarkLabel: 'Remark',
dialogRemarkPlaceholder: 'Please enter remark',
dialogStateLabel: 'Status',
validatorNameRequired: 'Name is required',
validatorTypeRequired: 'Dashboard type is required',
validatorOrgRequired: 'Line is required',
messageRouteMissing: 'Preview route is not configured',
messageDevicePointRequired: 'Please configure at least one device and point group',
messageMissingId: 'Missing record ID, unable to edit'
}
},
ErpStock: {
Warehouse: {
name: 'Warehouse Name',
@ -3763,6 +3805,8 @@ export default {
dialogCollectionTimeLabel: 'Collection Time',
dialogCollectionTimeStartPlaceholder: 'Start Time',
dialogCollectionTimeEndPlaceholder: 'End Time',
dialogPointFilterLabel: 'Point Filter',
dialogPointFilterPlaceholder: 'Please select points',
dialogSearchButtonText: 'Search',
dialogResetButtonText: 'Reset',
dialogRecordCollectionTimePrefix: 'Collection Time: ',

@ -37,6 +37,7 @@ export default {
toolDes: '用于设置定制系统',
query: '查询',
reset: '重置',
noData: '暂无数据',
shrink: '收起',
expand: '展开',
confirmTitle: '系统提示',
@ -59,6 +60,47 @@ export default {
copyError: '复制失败',
code: '编码保存后自动生成'
},
ReportDashboard: {
DashboardList: {
searchNameLabel: '名称',
searchNamePlaceholder: '请输入名称',
searchRemarkLabel: '备注',
searchRemarkPlaceholder: '请输入备注',
searchStateLabel: '启用状态',
searchStatePlaceholder: '请选择启用状态',
coverAlt: '封面图',
stateEnabled: '启用',
stateDisabled: '禁用',
noRemark: '暂无描述',
dialogCreateTitle: '新增数据大屏',
dialogEditTitle: '编辑数据大屏',
dialogNameLabel: '名称',
dialogNamePlaceholder: '请输入名称',
dialogTypeLabel: '大屏类型',
dialogTypePlaceholder: '请选择大屏类型',
dialogOrgLabel: '产线',
dialogOrgPlaceholder: '请选择产线',
dialogDeviceLabel: '设备',
dialogDevicePlaceholder: '请选择设备',
dialogPointPlaceholder: '请选择点位',
dialogAddDeviceButton: '添加设备',
dialogContentLabel: '内容',
dialogContentPlaceholder: '请输入内容',
dialogRemarkLabel: '备注',
dialogRemarkPlaceholder: '请输入备注',
dialogStateLabel: '启用状态',
validatorNameRequired: '名称不能为空',
validatorTypeRequired: '大屏类型不能为空',
validatorOrgRequired: '产线不能为空',
messageRouteMissing: '未配置预览路由',
messageDevicePointRequired: '请至少配置一组设备和点位',
messageMissingId: '缺少数据编号,无法编辑'
}
},
ErpStock: {
Warehouse: {
name: '仓库名称',
@ -3607,6 +3649,8 @@ export default {
dialogCollectionTimeLabel: '采集时间',
dialogCollectionTimeStartPlaceholder: '开始时间',
dialogCollectionTimeEndPlaceholder: '结束时间',
dialogPointFilterLabel: '点位筛选',
dialogPointFilterPlaceholder: '请选择点位',
dialogSearchButtonText: '查询',
dialogResetButtonText: '重置',
dialogRecordCollectionTimePrefix: '采集时间:',

@ -7,7 +7,7 @@
:model="queryParams"
ref="queryFormRef"
:inline="true"
label-width="68px"
min-label-width="68px"
>
<el-form-item :label="t('SparePartsManagement.SpareIn.product')" prop="productId">
<el-select

@ -9,7 +9,7 @@
:model="queryParams"
ref="queryFormRef"
:inline="true"
label-width="68px"
min-label-width="68px"
>
<el-form-item :label="t('SparePartsManagement.SpareInfo.name')" prop="name">
<el-input

@ -8,7 +8,7 @@
:model="queryParams"
ref="queryFormRef"
:inline="true"
label-width="68px"
min-label-width="68px"
>
<el-form-item :label="t('SparePartsManagement.SpareStock.product')" prop="productId">
<el-select

@ -6,7 +6,7 @@
:model="queryParams"
ref="queryFormRef"
:inline="true"
label-width="68px"
min-label-width="68px"
>
<el-form-item :label="t('MoldManagement.MoldBrand.code')" prop="code">
<el-input

@ -8,7 +8,7 @@ v-loading="typeTreeLoading" :data="brandTreeData" node-key="id" highlight-curren
<div class="device-ledger-right">
<ContentWrap>
<el-form class="-mb-15px" :model="queryParams" ref="queryFormRef" :inline="true" label-width="68px">
<el-form class="-mb-15px" :model="queryParams" ref="queryFormRef" :inline="true" min-label-width="68px">
<el-form-item :label="t('MoldManagement.Mold.code')" prop="code">
<el-input
v-model="queryParams.code" :placeholder="t('MoldManagement.Mold.code')" clearable @keyup.enter="handleQuery"

@ -6,7 +6,7 @@
:model="queryParams"
ref="queryFormRef"
:inline="true"
label-width="68px"
min-label-width="68px"
>
<el-form-item :label="t('FactoryModeling.ProductCategory.searchNameLabel')" prop="name">
<el-input

@ -6,7 +6,7 @@
:model="queryParams"
ref="queryFormRef"
:inline="true"
label-width="68px"
min-label-width="68px"
>
<el-form-item :label="t('FactoryModeling.ProductUnit.searchNameLabel')" prop="name">
<el-input

@ -1,7 +1,7 @@
<template>
<ContentWrap>
<!-- 搜索工作栏 -->
<el-form class="-mb-15px" :model="queryParams" ref="queryFormRef" :inline="true" label-width="68px">
<el-form class="-mb-15px" :model="queryParams" ref="queryFormRef" :inline="true" min-label-width="68px">
<el-form-item :label="t('DataCollection.Device.deviceCode')" prop="deviceCode">
<el-input
v-model="queryParams.deviceCode"

@ -5,7 +5,7 @@
:model="queryParams"
ref="queryFormRef"
:inline="true"
label-width="80px"
min-label-width="80px"
>
<el-form-item :label="t('DataCollection.DeviceAttributeType.code')" prop="code">
<el-input

@ -1,7 +1,7 @@
<template>
<ContentWrap>
<!-- 搜索工作栏 -->
<el-form class="-mb-15px" :model="queryParams" ref="queryFormRef" :inline="true" label-width="68px">
<el-form class="-mb-15px" :model="queryParams" ref="queryFormRef" :inline="true" min-label-width="68px">
<el-form-item :label="t('DataCollection.DeviceModel.code')" prop="code">
<el-input
v-model="queryParams.code"

@ -1,5 +1,5 @@
<template>
<Dialog v-model="dialogVisible" :title="dialogTitle" width="900" :scroll="true" max-height="80vh" align-center>
<Dialog v-model="dialogVisible" :title="dialogTitle" width="1100" :scroll="true" max-height="80vh" align-center>
<div class="single-device-dialog">
<el-form class="-mb-15px history-single-device-form" :inline="true" label-width="auto">
<el-form-item :label="t('DataCollection.HistoryData.dialogCollectionTimeLabel')">
@ -10,9 +10,30 @@
:start-placeholder="t('DataCollection.HistoryData.dialogCollectionTimeStartPlaceholder')"
:end-placeholder="t('DataCollection.HistoryData.dialogCollectionTimeEndPlaceholder')"
:default-time="[new Date('1 00:00:00'), new Date('1 23:59:59')]"
class="!w-360px"
class="!w-280px"
/>
</el-form-item>
<el-form-item :label="t('DataCollection.HistoryData.dialogPointFilterLabel')">
<el-select
v-model="attributeCodes"
class="!w-280px"
multiple
:max-collapse-tags="1"
collapse-tags
collapse-tags-tooltip
filterable
clearable
:loading="attributeLoading"
:placeholder="t('DataCollection.HistoryData.dialogPointFilterPlaceholder')"
>
<el-option
v-for="item in attributeOptions"
:key="item.attributeCode"
:label="item.label"
:value="item.attributeCode"
/>
</el-select>
</el-form-item>
<el-form-item>
<el-button @click="handleQuery">{{ t('DataCollection.HistoryData.dialogSearchButtonText') }}</el-button>
<el-button @click="resetQuery">{{ t('DataCollection.HistoryData.dialogResetButtonText') }}</el-button>
@ -125,6 +146,14 @@ const loading = ref(false)
const recordGroups = ref<RecordGroup[]>([])
const collectionTimeRange = ref<string[]>([])
const attributeCodes = ref<string[]>([])
const attributeLoading = ref(false)
type AttributeOption = {
attributeCode: string
label: string
}
const attributeOptions = ref<AttributeOption[]>([])
const formatDateTime = (date: Date) => {
const pad = (value: number) => String(value).padStart(2, '0')
@ -204,6 +233,36 @@ const buildSectionsFromGroups = (groups: Record<string, any[]>): Section[] => {
return result
}
const fetchDeviceAttributes = async () => {
if (props.deviceId === undefined || props.deviceId === null || props.deviceId === '') {
attributeOptions.value = []
return
}
attributeLoading.value = true
try {
const res: any = await DeviceApi.getDeviceAttributeList(props.deviceId)
const responseData = res?.data?.data ?? res?.data ?? res
const list: any[] = Array.isArray(responseData?.list)
? responseData.list
: Array.isArray(responseData)
? responseData
: []
attributeOptions.value = list
.map((item: any) => {
const code = String(item?.attributeCode ?? '').trim()
if (!code) return null
const name = String(item?.attributeName ?? '').trim()
return {
attributeCode: code,
label: name ? `${name}(${code})` : code
}
})
.filter(Boolean) as AttributeOption[]
} finally {
attributeLoading.value = false
}
}
const fetchHistory = async () => {
if (props.deviceId === undefined || props.deviceId === null || props.deviceId === '') {
recordGroups.value = []
@ -221,6 +280,9 @@ const fetchHistory = async () => {
params.collectionStartTime = collectionTimeRange.value[0]
params.collectionEndTime = collectionTimeRange.value[1]
}
if (Array.isArray(attributeCodes.value) && attributeCodes.value.length) {
params.attributeCodes = attributeCodes.value
}
const res: any = await DeviceApi.getHistoryRecord(params)
const responseData = res?.data?.data ?? res?.data ?? res
@ -256,6 +318,7 @@ const handleQuery = () => {
const resetQuery = () => {
collectionTimeRange.value = []
attributeCodes.value = []
queryParams.pageNo = 1
queryParams.pageSize = 10
fetchHistory()
@ -268,8 +331,10 @@ watch(
return
}
collectionTimeRange.value = buildLastHoursRange(4)
attributeCodes.value = []
queryParams.pageNo = 1
queryParams.pageSize = 10
fetchDeviceAttributes()
fetchHistory()
}
)

@ -6,7 +6,7 @@
:model="queryParams"
ref="queryFormRef"
:inline="true"
label-width="80px"
min-label-width="80px"
>
<el-form-item :label="t('FactoryModeling.ProductBOM.searchCodeLabel')" prop="code">
<el-input

@ -6,7 +6,7 @@
:model="queryParams"
ref="queryFormRef"
:inline="true"
label-width="120px"
min-label-width="120px"
>
<el-form-item :label="t('EnergyManagement.EnergyType.searchCodeLabel')" prop="code">
<el-input

@ -6,7 +6,7 @@
:model="queryParams"
ref="queryFormRef"
:inline="true"
label-width="68px"
min-label-width="68px"
>
<!-- <el-form-item label="操作类型" prop="operateType">
<el-select

@ -6,7 +6,7 @@
:model="queryParams"
ref="queryFormRef"
:inline="true"
label-width="68px"
min-label-width="68px"
>
<el-form-item :label="t('MoldManagement.MoldReturn.no')" prop="no">
<el-input

@ -1,6 +1,6 @@
<template>
<ContentWrap>
<el-form class="-mb-15px" :model="queryParams" ref="queryFormRef" :inline="true" label-width="68px">
<el-form class="-mb-15px" :model="queryParams" ref="queryFormRef" :inline="true" min-label-width="68px">
<el-form-item :label="t('EquipmentManagement.PlanMaintenance.planName')" prop="planName">
<el-input
v-model="queryParams.planName"

@ -6,7 +6,7 @@
:model="queryParams"
ref="queryFormRef"
:inline="true"
label-width="68px"
min-label-width="68px"
>
<el-form-item :label="t('ProductionPlan.Task.searchCodeLabel')" prop="code">
<el-input

@ -6,7 +6,7 @@
:model="queryParams"
ref="queryFormRef"
:inline="true"
label-width="68px"
min-label-width="68px"
>
<el-form-item :label="t('FactoryModeling.WorkTeam.searchTeamNameLabel')" prop="teamName">
<el-input

@ -1,6 +1,6 @@
<template>
<ContentWrap>
<el-form class="-mb-15px" :model="queryParams" ref="queryFormRef" :inline="true" label-width="68px">
<el-form class="-mb-15px" :model="queryParams" ref="queryFormRef" :inline="true" min-label-width="68px">
<el-form-item :label="t('QualityManagement.ZjTask.code')" prop="code">
<el-input
v-model="queryParams.code"

@ -1,7 +1,7 @@
<template>
<ContentWrap>
<!-- 搜索工作栏 -->
<el-form class="-mb-15px" :model="queryParams" ref="queryFormRef" :inline="true" label-width="68px">
<el-form class="-mb-15px" :model="queryParams" ref="queryFormRef" :inline="true" min-label-width="68px">
<el-form-item :label="t('QualityManagement.ZjSchema.name')" prop="name">
<el-input
v-model="queryParams.name"

@ -6,7 +6,7 @@
:model="queryParams"
ref="queryFormRef"
:inline="true"
label-width="68px"
min-label-width="68px"
>
<el-form-item :label="t('QualityManagement.ZjType.code')" prop="code">
<el-input

@ -1,6 +1,6 @@
<template>
<ContentWrap>
<el-form class="-mb-15px" :model="queryParams" ref="queryFormRef" :inline="true" label-width="68px">
<el-form class="-mb-15px" :model="queryParams" ref="queryFormRef" :inline="true" min-label-width="68px">
<el-form-item :label="t('MoldManagement.MoldInspectionPlan.planName')" prop="planName">
<el-input
v-model="queryParams.planName"

@ -1,6 +1,6 @@
<template>
<ContentWrap>
<el-form class="-mb-15px" :model="queryParams" ref="queryFormRef" :inline="true" label-width="68px">
<el-form class="-mb-15px" :model="queryParams" ref="queryFormRef" :inline="true" min-label-width="68px">
<el-form-item :label="t('MoldManagement.MoldRepair.repairCode')" prop="repairCode">
<el-input
v-model="queryParams.repairCode"

@ -1,6 +1,6 @@
<template>
<ContentWrap>
<el-form class="-mb-15px" :model="queryParams" ref="queryFormRef" :inline="true" label-width="68px">
<el-form class="-mb-15px" :model="queryParams" ref="queryFormRef" :inline="true" min-label-width="68px">
<el-form-item :label="t('MoldManagement.MoldRepairItems.subjectCode')" prop="subjectCode">
<el-input
v-model="queryParams.subjectCode"

@ -5,7 +5,7 @@
:model="queryParams"
ref="queryFormRef"
:inline="true"
label-width="68px"
min-label-width="68px"
>
<el-form-item :label="t('EquipmentManagement.TaskManagement.name')" prop="name">
<el-input

@ -1,6 +1,6 @@
<template>
<ContentWrap>
<el-form class="-mb-15px" :model="queryParams" ref="queryFormRef" :inline="true" label-width="68px">
<el-form class="-mb-15px" :model="queryParams" ref="queryFormRef" :inline="true" min-label-width="68px">
<el-form-item :label="t('MoldManagement.MoldWorkOrderInquiry.planNo')" prop="planNo">
<el-input
v-model="queryParams.planNo"

@ -1,18 +1,18 @@
<template>
<ContentWrap>
<el-form class="-mb-15px" :model="queryParams" ref="queryFormRef" :inline="true" label-width="80px">
<el-form-item label="名称" prop="name">
<el-form class="-mb-15px" :model="queryParams" ref="queryFormRef" :inline="true" min-label-width="80px">
<el-form-item :label="t('ReportDashboard.DashboardList.searchNameLabel')" prop="name">
<el-input
v-model="queryParams.name" placeholder="请输入名称" clearable @keyup.enter="handleQuery"
v-model="queryParams.name" :placeholder="t('ReportDashboard.DashboardList.searchNamePlaceholder')" clearable @keyup.enter="handleQuery"
class="!w-240px" />
</el-form-item>
<el-form-item label="备注" prop="remark">
<el-form-item :label="t('ReportDashboard.DashboardList.searchRemarkLabel')" prop="remark">
<el-input
v-model="queryParams.remark" placeholder="请输入备注" clearable @keyup.enter="handleQuery"
v-model="queryParams.remark" :placeholder="t('ReportDashboard.DashboardList.searchRemarkPlaceholder')" clearable @keyup.enter="handleQuery"
class="!w-240px" />
</el-form-item>
<el-form-item label="启用状态" prop="state">
<el-select v-model="queryParams.state" placeholder="请选择启用状态" clearable class="!w-240px">
<el-form-item :label="t('ReportDashboard.DashboardList.searchStateLabel')" prop="state">
<el-select v-model="queryParams.state" :placeholder="t('ReportDashboard.DashboardList.searchStatePlaceholder')" clearable class="!w-240px">
<el-option
v-for="dict in getStrDictOptions(DICT_TYPE.COMMON_STATUS)" :key="dict.value" :label="dict.label"
:value="dict.value" />
@ -20,13 +20,13 @@ v-for="dict in getStrDictOptions(DICT_TYPE.COMMON_STATUS)" :key="dict.value" :la
</el-form-item>
<el-form-item>
<el-button type="primary" @click="openCreateDialog">
<Icon icon="ep:plus" class="mr-5px" /> 新增
<Icon icon="ep:plus" class="mr-5px" /> {{ t('action.add') }}
</el-button>
<el-button @click="handleQuery">
<Icon icon="ep:search" class="mr-5px" /> 搜索
<Icon icon="ep:search" class="mr-5px" /> {{ t('common.query') }}
</el-button>
<el-button @click="resetQuery">
<Icon icon="ep:refresh" class="mr-5px" /> 重置
<Icon icon="ep:refresh" class="mr-5px" /> {{ t('common.reset') }}
</el-button>
</el-form-item>
</el-form>
@ -34,18 +34,18 @@ v-for="dict in getStrDictOptions(DICT_TYPE.COMMON_STATUS)" :key="dict.value" :la
<ContentWrap>
<div class="dashboard-card-list">
<el-empty v-if="!loading && list.length === 0" description="暂无数据" />
<el-empty v-if="!loading && list.length === 0" :description="t('common.noData')" />
<el-row v-else :gutter="16">
<el-col v-for="item in list" :key="item.id" :xl="6" :lg="8" :md="12" :sm="24" :xs="24" class="mb-16px">
<el-card shadow="hover" class="dashboard-card" :body-style="{ padding: '0' }">
<div class="dashboard-card-image-wrapper" @click="handlePreview(item)">
<img class="dashboard-card-image" :src="getDashboardImage(item)" alt="封面图" />
<img class="dashboard-card-image" :src="getDashboardImage(item)" :alt="t('ReportDashboard.DashboardList.coverAlt')" />
<div class="dashboard-card-state">
<el-tag v-if="item.state === 1" type="success" size="small">
启用
{{ t('ReportDashboard.DashboardList.stateEnabled') }}
</el-tag>
<el-tag v-else type="info" size="small">
禁用
{{ t('ReportDashboard.DashboardList.stateDisabled') }}
</el-tag>
</div>
</div>
@ -55,7 +55,7 @@ v-for="dict in getStrDictOptions(DICT_TYPE.COMMON_STATUS)" :key="dict.value" :la
{{ item.name || '-' }}
</div>
<div class="dashboard-card-remark" :title="item.remark">
{{ item.remark || '暂无描述' }}
{{ item.remark || t('ReportDashboard.DashboardList.noRemark') }}
</div>
</div>
<div class="dashboard-card-actions">
@ -65,8 +65,8 @@ v-for="dict in getStrDictOptions(DICT_TYPE.COMMON_STATUS)" :key="dict.value" :la
</el-button>
<template #dropdown>
<el-dropdown-menu class="dashboard-card-menu">
<el-dropdown-item class="dashboard-card-menu-primary" @click="openEditDialog(item)"></el-dropdown-item>
<el-dropdown-item divided class="dashboard-card-menu-danger" @click="handleDelete(item)"></el-dropdown-item>
<el-dropdown-item class="dashboard-card-menu-primary" @click="openEditDialog(item)">{{ t('action.edit') }}</el-dropdown-item>
<el-dropdown-item divided class="dashboard-card-menu-danger" @click="handleDelete(item)">{{ t('action.delete') }}</el-dropdown-item>
</el-dropdown-menu>
</template>
</el-dropdown>
@ -82,35 +82,35 @@ v-if="total > 0" :total="total" v-model:page="queryParams.pageNo" v-model:limit=
</ContentWrap>
<el-dialog
v-model="createDialogVisible" :title="dialogMode === 'create' ? '新增数据大屏' : '编辑数据大屏'" width="600px"
v-model="createDialogVisible" :title="dialogMode === 'create' ? t('ReportDashboard.DashboardList.dialogCreateTitle') : t('ReportDashboard.DashboardList.dialogEditTitle')" width="600px"
draggable @closed="handleCreateDialogClosed">
<el-form :model="createForm" ref="createFormRef" label-width="80px" :rules="createFormRules">
<el-form-item label="名称" prop="name">
<el-input v-model="createForm.name" placeholder="请输入名称" />
<el-form-item :label="t('ReportDashboard.DashboardList.dialogNameLabel')" prop="name">
<el-input v-model="createForm.name" :placeholder="t('ReportDashboard.DashboardList.dialogNamePlaceholder')" />
</el-form-item>
<el-form-item label="大屏类型" prop="type">
<el-select v-model="createForm.type" placeholder="请选择大屏类型" class="!w-240px">
<el-form-item :label="t('ReportDashboard.DashboardList.dialogTypeLabel')" prop="type">
<el-select v-model="createForm.type" :placeholder="t('ReportDashboard.DashboardList.dialogTypePlaceholder')" class="!w-240px">
<el-option
v-for="dict in getStrDictOptions('mes_goview_type')" :key="dict.value" :label="dict.label"
:value="dict.value" />
</el-select>
</el-form-item>
<el-form-item label="产线" prop="orgId">
<el-form-item :label="t('ReportDashboard.DashboardList.dialogOrgLabel')" prop="orgId">
<el-tree-select
v-model="createForm.orgName" :data="organizationTree" :props="lineTreeProps" filterable clearable
class="!w-240px" placeholder="请选择产线" @change="handleOrgChange" />
class="!w-240px" :placeholder="t('ReportDashboard.DashboardList.dialogOrgPlaceholder')" @change="handleOrgChange" />
</el-form-item>
<el-form-item label="设备" v-if="createForm.type === '1'">
<el-form-item :label="t('ReportDashboard.DashboardList.dialogDeviceLabel')" v-if="createForm.type === '1'">
<div class="dashboard-device-group-list">
<div v-for="(group, index) in deviceAttrSelections" :key="index" class="dashboard-device-group">
<el-select
v-model="group.deviceId" placeholder="请选择设备" clearable filterable class="!w-160px mr-8px"
v-model="group.deviceId" :placeholder="t('ReportDashboard.DashboardList.dialogDevicePlaceholder')" clearable filterable class="!w-160px mr-8px"
@change="(val) => handleDeviceChange(val, index)">
<el-option v-for="item in deviceList" :key="item.id" :label="item.deviceName" :value="item.id" />
</el-select>
<el-select
v-model="group.attributeIds" multiple collapse-tags collapse-tags-tooltip
:disabled="!group.deviceId" placeholder="请选择点位" clearable filterable class="!w-260px">
:disabled="!group.deviceId" :placeholder="t('ReportDashboard.DashboardList.dialogPointPlaceholder')" clearable filterable class="!w-260px">
<el-option
v-for="attr in (deviceAttributeOptionsMap[String(group.deviceId)] || [])" :key="attr.id"
:label="attr.attributeName" :value="attr.id" />
@ -124,24 +124,24 @@ v-if="deviceAttrSelections.length > 1" type="danger" text class="dashboard-devic
<el-button
type="primary" text @click="addDeviceAttrGroup" :disabled="deviceAttrSelections.length >= 8"
class="mt-8px">
<Icon icon="ep:plus" class="mr-5px" /> 添加设备
<Icon icon="ep:plus" class="mr-5px" /> {{ t('ReportDashboard.DashboardList.dialogAddDeviceButton') }}
</el-button>
</div>
</el-form-item>
<el-form-item label="内容">
<el-input v-model="createForm.content" type="textarea" :rows="4" placeholder="请输入内容" />
<el-form-item :label="t('ReportDashboard.DashboardList.dialogContentLabel')">
<el-input v-model="createForm.content" type="textarea" :rows="4" :placeholder="t('ReportDashboard.DashboardList.dialogContentPlaceholder')" />
</el-form-item>
<el-form-item label="备注">
<el-input v-model="createForm.remark" placeholder="请输入备注" />
<el-form-item :label="t('ReportDashboard.DashboardList.dialogRemarkLabel')">
<el-input v-model="createForm.remark" :placeholder="t('ReportDashboard.DashboardList.dialogRemarkPlaceholder')" />
</el-form-item>
<el-form-item label="启用状态">
<el-form-item :label="t('ReportDashboard.DashboardList.dialogStateLabel')">
<el-switch v-model="createForm.state" :active-value="1" :inactive-value="0" />
</el-form-item>
</el-form>
<template #footer>
<el-button @click="createDialogVisible = false"> </el-button>
<el-button @click="createDialogVisible = false">{{ t('common.cancel') }}</el-button>
<el-button type="primary" :loading="createLoading" @click="submitDialog">
{{ t('common.ok') }}
</el-button>
</template>
</el-dialog>
@ -161,6 +161,7 @@ defineOptions({ name: 'DashboardList' })
const router = useRouter()
const message = useMessage()
const { t } = useI18n()
interface DashboardItem {
id: number
@ -182,12 +183,8 @@ const list = ref<DashboardItem[]>([])
const total = ref(0)
const getDashboardImage = (item: DashboardItem) => {
if (item.name === '智能制造产线任务总览') {
return dashboardImage1
}
if (item.name === '产线运行看板') {
return dashboardImage2
}
if (item.type === '2') return dashboardImage1
if (item.type === '1') return dashboardImage2
return item.indexImage || defaultImage
}
@ -220,9 +217,9 @@ const createForm = reactive({
})
const createFormRules = reactive({
name: [{ required: true, message: '名称不能为空', trigger: 'blur' }],
type: [{ required: true, message: '大屏类型不能为空', trigger: 'change' }],
orgId: [{ required: true, message: '产线不能为空', trigger: 'change' }]
name: [{ required: true, message: t('ReportDashboard.DashboardList.validatorNameRequired'), trigger: 'blur' }],
type: [{ required: true, message: t('ReportDashboard.DashboardList.validatorTypeRequired'), trigger: 'change' }],
orgId: [{ required: true, message: t('ReportDashboard.DashboardList.validatorOrgRequired'), trigger: 'change' }]
})
const organizationTree = ref<any[]>([])
@ -266,7 +263,7 @@ const handlePreview = (item: DashboardItem) => {
const typeRoute = getRouteByType(item.type)
const route = typeRoute || item.route || ''
if (!route) {
message.error('未配置预览路由')
message.error(t('ReportDashboard.DashboardList.messageRouteMissing'))
return
}
const path = route.startsWith('/') ? route : `/${route}`
@ -392,7 +389,7 @@ const submitDialog = async () => {
}))
.filter((g) => g.deviceId && g.attributesIds.length)
if (!groups.length) {
message.error('请至少配置一组设备和点位')
message.error(t('ReportDashboard.DashboardList.messageDevicePointRequired'))
return
}
createForm.deviceIdsList = groups.map((g) => ({
@ -416,7 +413,7 @@ const submitDialog = async () => {
createForm.route = route
}
if (dialogMode.value === 'edit' && !editingId.value) {
message.error('缺少数据编号,无法编辑')
message.error(t('ReportDashboard.DashboardList.messageMissingId'))
return
}
createLoading.value = true
@ -426,7 +423,7 @@ const submitDialog = async () => {
url: '/mes/goview/create',
data: createForm
})
message.success('新增成功')
message.success(t('common.createSuccess'))
} else {
await request.put({
url: '/mes/goview/update',
@ -435,7 +432,7 @@ const submitDialog = async () => {
...createForm
}
})
message.success('编辑成功')
message.success(t('common.updateSuccess'))
}
createDialogVisible.value = false
handleQuery()
@ -451,7 +448,7 @@ const handleDelete = async (item: DashboardItem) => {
await request.delete({
url: `/mes/goview/delete?id=${item.id}`
})
message.success('删除成功')
message.success(t('common.delSuccess'))
await getList()
} catch { }
}

@ -48,7 +48,7 @@
</el-tag>
</div>
<div class="header-right">
<span class="device-id">ID: {{ item.deviceId }}</span>
<span class="device-id">{{ t('ReportDashboard.Dashboard1.deviceIdPrefix') }}{{ item.deviceId }}</span>
</div>
</div>
<div class="device-body">
@ -80,7 +80,7 @@
</el-tag>
</div>
<div class="header-right">
<span class="device-id">ID: {{ item.deviceId }}</span>
<span class="device-id">{{ t('ReportDashboard.Dashboard1.deviceIdPrefix') }}{{ item.deviceId }}</span>
</div>
</div>
<div class="device-body">
@ -128,6 +128,7 @@ import ProductionTrend from './components/ProductionTrend.vue'
const route = useRoute()
const goviewId = route.query.goviewId as string
const orgId = route.query.orgId
const { t } = useI18n()
interface DeviceAttribute {
attributeName: string
@ -164,7 +165,7 @@ const loadDeviceAttributes = async () => {
const cards: DeviceCardData[] = list.map((d: any) => {
return {
deviceName: d.deviceName || 'Device',
deviceName: d.deviceName || t('ReportDashboard.Dashboard1.defaultDeviceName'),
deviceId: d.deviceId,
operatingStatus: d.operatingStatus,
attributes: (d.attributes || []).map((attr: any) => ({
@ -193,7 +194,7 @@ const getDeviceStatusType = (status?: string) => {
}
const getDeviceStatusText = (status?: string) => {
if (!status) return '离线'
if (!status) return t('ReportDashboard.Dashboard1.statusOffline')
return status
}

Loading…
Cancel
Save