# Conflicts:
#	src/views/mes/deviceledger/index.vue
pull/1/head
黄伟杰 2 months ago
commit 513b6030b7

@ -12,6 +12,10 @@ export interface RecipePointRecordVO {
export const RecipePointRecordApi = { export const RecipePointRecordApi = {
// 新增记录 // 新增记录
createRecipePointRecord: async (data: RecipePointRecordVO) => {
return await request.post({ url: `/iot/recipe-point-record/create`, data })
},
// 批量新增记录
createRecipePointRecordBatch: async (data: RecipePointRecordVO[]) => { createRecipePointRecordBatch: async (data: RecipePointRecordVO[]) => {
return await request.post({ url: `/iot/recipe-point-record/batch-create`, data }) return await request.post({ url: `/iot/recipe-point-record/batch-create`, data })
}, },

@ -3006,7 +3006,22 @@ export default {
manualTableDataTypeColumn: 'Data Type', manualTableDataTypeColumn: 'Data Type',
manualTableDataUnitColumn: 'Unit', manualTableDataUnitColumn: 'Unit',
manualTableReferColumn: 'Reference Value', manualTableReferColumn: 'Reference Value',
manualTableRemarkColumn: 'Remark' manualTableRemarkColumn: 'Remark',
manualTableInputTimeColumn: 'Input Time',
manualTableEnteringAction:'Re-enroll',
manualFormTitleLabel: 'Re-recorded collected values',
nanualFormNameLabel:'Name',
nanualFormNamePlaceholder:'Please enter name',
nanualFormDataTypeLabel:'Data Type',
nanualFormDataTypePlaceholder:'Please select data type',
nanualFormDataUnitLabel:'Unit',
nanualFormDataUnitPlaceholder:'Please select unit',
nanualFormReferLabel:'Reference Value',
nanualFormReferPlaceholder:'Please enter reference value',
nanualFormRemarkLabel:'Remark',
nanualFormRemarkPlaceholder:'Please enter remark',
nanualFormInputTimeLabel:'Input Time',
nanualFormInputTimePlaceholder:'Please select input time',
} }
}, },
EnergyManagement: { EnergyManagement: {
@ -3997,7 +4012,10 @@ export default {
attributeValidatorRemarkTooLong: 'Remark can not exceed 100 characters', attributeValidatorRemarkTooLong: 'Remark can not exceed 100 characters',
messageSelectDeviceRequired: 'Please select a device', messageSelectDeviceRequired: 'Please select a device',
messageDeviceInfoMissingForRules: 'Device information is missing, unable to load point rules' messageDeviceInfoMissingForRules: 'Device information is missing, unable to load point rules',
gridView:'gridView',
sudoku:'sudoku',
}, },
RunReport: { RunReport: {
moduleName: 'Device Operation Report', moduleName: 'Device Operation Report',

@ -2520,7 +2520,21 @@ export default {
manualTableDataTypeColumn: '数据类型', manualTableDataTypeColumn: '数据类型',
manualTableDataUnitColumn: '单位', manualTableDataUnitColumn: '单位',
manualTableReferColumn: '参考值', manualTableReferColumn: '参考值',
manualTableRemarkColumn: '备注' manualTableRemarkColumn: '备注',
manualTableInputTimeColumn: '录入时间',
manualTableEnteringAction: '补录',
manualFormTitleLabel: '补录采集值',
nanualFormNameLabel: '名称',
nanualFormNamePlaceholder: '请输入名称',
nanualFormDataTypeLabel: '数据类型',
nanualFormDataTypePlaceholder: '请输入数据类型',
nanualFormDataUnitLabel: '单位',
nanualFormDataUnitPlaceholder: '请选择单位',
nanualFormReferLabel: '参考值',
nanualFormReferPlaceholder: '请输入参考值',
nanualFormRemarkLabel: '备注',
nanualFormRemarkPlaceholder: '请输入备注',
} }
}, },
FactoryModeling: { FactoryModeling: {
@ -3836,7 +3850,10 @@ export default {
attributeValidatorRemarkTooLong: '备注不能超过100字', attributeValidatorRemarkTooLong: '备注不能超过100字',
messageSelectDeviceRequired: '请选择一个物联设备', messageSelectDeviceRequired: '请选择一个物联设备',
messageDeviceInfoMissingForRules: '设备信息缺失,无法加载点位规则' messageDeviceInfoMissingForRules: '设备信息缺失,无法加载点位规则',
gridView:'表格视图',
sudoku:'九宫格',
}, },
RunReport: { RunReport: {
moduleName: '设备运行报表', moduleName: '设备运行报表',

@ -46,58 +46,62 @@
/> />
</el-tab-pane> </el-tab-pane>
<el-tab-pane :label="t('RecipeManagement.RecipeLibrary.detailTabManualLabel')" name="manual"> <el-tab-pane :label="t('RecipeManagement.RecipeLibrary.detailTabManualLabel')" name="manual">
<!-- <el-form <el-form
class="-mb-15px" class="-mb-15px"
:model="queryParams" :model="queryParams"
ref="queryFormRef" ref="queryFormRef"
:inline="true" :inline="true"
label-width="68px" label-width="68px"
> >
<el-form-item label="名称" prop="name"> <!-- <el-form-item label="名称" prop="name">
<el-input <el-input
v-model="queryParams.name" v-model="queryParams.name"
placeholder="请输入名称" placeholder="请输入名称"
clearable clearable
@keyup.enter="handleQuery" @keyup.enter="handleQuery"
class="!w-240px" class="!w-240px"
/> />
</el-form-item> </el-form-item>
<el-form-item label="参考值" prop="refer"> <el-form-item label="参考值" prop="refer">
<el-input <el-input
v-model="queryParams.refer" v-model="queryParams.refer"
placeholder="请输入参考值" placeholder="请输入参考值"
clearable clearable
@keyup.enter="handleQuery" @keyup.enter="handleQuery"
class="!w-240px" class="!w-240px"
/> />
</el-form-item> </el-form-item>
<el-form-item label="单位" prop="dataUnit"> <el-form-item label="单位" prop="dataUnit">
<el-input <el-input
v-model="queryParams.dataUnit" v-model="queryParams.dataUnit"
placeholder="请输入单位" placeholder="请输入单位"
clearable clearable
@keyup.enter="handleQuery" @keyup.enter="handleQuery"
class="!w-240px" class="!w-240px"
/> />
</el-form-item> </el-form-item>
<el-form-item label="备注" prop="remark"> <el-form-item label="备注" prop="remark">
<el-input <el-input
v-model="queryParams.remark" v-model="queryParams.remark"
placeholder="请输入备注" placeholder="请输入备注"
clearable clearable
@keyup.enter="handleQuery" @keyup.enter="handleQuery"
class="!w-240px" class="!w-240px"
/> />
</el-form-item> </el-form-item>-->
<el-form-item> <el-form-item>
<el-button @click="handleQuery"> <!-- <el-button @click="handleQuery">
<Icon icon="ep:search" class="mr-5px" /> 查询 <Icon icon="ep:search" class="mr-5px" /> 查询
</el-button> </el-button>
<el-button @click="resetQuery"> <el-button @click="resetQuery">
<Icon icon="ep:refresh" class="mr-5px" /> 重置 <Icon icon="ep:refresh" class="mr-5px" /> 重置
</el-button>-->
<el-button type="primary" plain @click="openCReferDialog()">
<Icon icon="ep:plus" class="mr-5px" />
{{ t('RecipeManagement.RecipeLibrary.createButtonText') }}
</el-button> </el-button>
</el-form-item> </el-form-item>
</el-form> --> </el-form>
<el-table v-loading="loading" :data="list" :stripe="true" :show-overflow-tooltip="true" row-key="id"> <el-table v-loading="loading" :data="list" :stripe="true" :show-overflow-tooltip="true" row-key="id">
<!-- <el-table-column type="index" :label="t('RecipeManagement.RecipeLibrary.detailIndexColumn')" align="center" width="70" /> --> <!-- <el-table-column type="index" :label="t('RecipeManagement.RecipeLibrary.detailIndexColumn')" align="center" width="70" /> -->
<el-table-column <el-table-column
@ -105,13 +109,13 @@
align="center" align="center"
prop="name" prop="name"
min-width="140" min-width="140"
sortable /> sortable />
<el-table-column <el-table-column
:label="t('RecipeManagement.RecipeLibrary.manualTableDataTypeColumn')" :label="t('RecipeManagement.RecipeLibrary.manualTableDataTypeColumn')"
align="center" align="center"
prop="dataType" prop="dataType"
width="140" width="140"
sortable /> sortable />
<el-table-column <el-table-column
:label="t('RecipeManagement.RecipeLibrary.manualTableDataUnitColumn')" :label="t('RecipeManagement.RecipeLibrary.manualTableDataUnitColumn')"
align="center" align="center"
@ -134,14 +138,14 @@
prop="remark" prop="remark"
min-width="180" min-width="180"
/> />
<el-table-column label="录入时间" align="center" prop="updateTime" min-width="180" sortable> <el-table-column :label="t('RecipeManagement.RecipeLibrary.manualTableInputTimeColumn')" align="center" prop="updateTime" min-width="180" sortable>
<template #default="scope"> <template #default="scope">
{{ formatTime(scope.row?.updateTime) }} {{ formatTime(scope.row?.updateTime) }}
</template> </template>
</el-table-column> </el-table-column>
<el-table-column align="center" fixed="right" label="操作" width="120"> <el-table-column align="center" fixed="right" :label="t('RecipeManagement.RecipeLibrary.tableOperateColumn')" width="120">
<template #default="scope"> <template #default="scope">
<el-button link type="primary" @click="openReferDialog(scope.row)"></el-button> <el-button link type="primary" @click="openReferDialog(scope.row)">{{t('RecipeManagement.RecipeLibrary.manualTableEnteringAction')}}</el-button>
</template> </template>
</el-table-column> </el-table-column>
</el-table> </el-table>
@ -154,22 +158,32 @@
</el-tab-pane> </el-tab-pane>
</el-tabs> </el-tabs>
<Dialog v-model="referDialogVisible" title="补录采集值" width="520px"> <Dialog v-model="referDialogVisible" :title="t('RecipeManagement.RecipeLibrary.manualFormTitleLabel')" width="520px">
<el-form :model="referForm" label-width="90px"> <el-form ref="referFormRef" :model="referForm" label-width="90px">
<el-form-item label="名称"> <el-form-item :label="t('RecipeManagement.RecipeLibrary.nanualFormNameLabel')">
<el-input :model-value="referForm.name" disabled /> <el-input v-model="referForm.name" :disabled="isEdit" :placeholder="t('RecipeManagement.RecipeLibrary.nanualFormNamePlaceholder')"/>
</el-form-item> </el-form-item>
<el-form-item label="数据类型"> <el-form-item :label="t('RecipeManagement.RecipeLibrary.nanualFormDataTypeLabel')">
<el-input :model-value="referForm.dataType" disabled /> <el-input v-model="referForm.dataType" :disabled="isEdit" :placeholder="t('RecipeManagement.RecipeLibrary.nanualFormDataTypePlaceholder')" />
</el-form-item> </el-form-item>
<el-form-item label="单位"> <!-- <el-form-item label="单位">
<el-input :model-value="referForm.dataUnitLabel" disabled /> <el-input v-model="referForm.dataUnitLabel" :disabled="isEdit" />
</el-form-item>-->
<el-form-item :label="t('RecipeManagement.RecipeLibrary.nanualFormDataUnitLabel')" prop="dataUnit">
<el-select v-model="referForm.dataUnit" :disabled="isEdit" :placeholder="t('RecipeManagement.RecipeLibrary.nanualFormDataUnitPlaceholder')" class="!w-1/1">
<el-option
v-for="item in unitList"
:key="item.id"
:label="item.name"
:value="item.id"
/>
</el-select>
</el-form-item> </el-form-item>
<el-form-item label="备注"> <el-form-item :label="t('RecipeManagement.RecipeLibrary.nanualFormRemarkLabel')">
<el-input :model-value="referForm.remark" type="textarea" disabled /> <el-input v-model="referForm.remark" type="textarea" :disabled="isEdit" :placeholder="t('RecipeManagement.RecipeLibrary.nanualFormRemarkPlaceholder')" />
</el-form-item> </el-form-item>
<el-form-item label="参考值"> <el-form-item :label="t('RecipeManagement.RecipeLibrary.nanualFormReferLabel')">
<el-input v-model="referForm.refer" /> <el-input v-model="referForm.refer" :placeholder="t('RecipeManagement.RecipeLibrary.nanualFormReferPlaceholder')" />
</el-form-item> </el-form-item>
</el-form> </el-form>
<template #footer> <template #footer>
@ -183,10 +197,12 @@
<script setup lang="ts"> <script setup lang="ts">
import dayjs from 'dayjs' import dayjs from 'dayjs'
import { RecipePointRecordApi } from '@/api/iot/recipepointrecord' import {RecipePointRecordApi, RecipePointRecordVO} from '@/api/iot/recipepointrecord'
import { RecipeDeviceRecordApi } from '@/api/iot/recipeDeviceRecord' import { RecipeDeviceRecordApi } from '@/api/iot/recipeDeviceRecord'
import { RecipePointVO } from '@/api/iot/recipePoint' import { RecipePointVO } from '@/api/iot/recipePoint'
import { ProductUnitApi, ProductUnitVO } from '@/api/erp/product/unit' import { ProductUnitApi, ProductUnitVO } from '@/api/erp/product/unit'
import {ElMessage} from "element-plus";
import {ErrorRecordVO} from "@/api/mes/errorrecord";
defineOptions({ name: 'FormulaLibraryDetailTabs' }) defineOptions({ name: 'FormulaLibraryDetailTabs' })
@ -203,7 +219,7 @@ const props = defineProps({
const activeTab = ref<'detail' | 'manual'>('detail') const activeTab = ref<'detail' | 'manual'>('detail')
const detailList = ref<{ key: string; pointName: string; value: string; unit: string }[]>([]) const detailList = ref<{ key: string; pointName: string; value: string; unit: string }[]>([])
const isEdit = ref(true)
const loading = ref(false) const loading = ref(false)
const list = ref<RecipePointVO[]>([]) const list = ref<RecipePointVO[]>([])
const total = ref(0) const total = ref(0)
@ -318,10 +334,10 @@ const resetQuery = () => {
queryFormRef.value?.resetFields?.() queryFormRef.value?.resetFields?.()
handleQuery() handleQuery()
} }
const referFormRef = ref()
const referDialogVisible = ref(false) const referDialogVisible = ref(false)
const referSubmitting = ref(false) const referSubmitting = ref(false)
const referForm = reactive({ const referForm = ref({
id: '' as string, id: '' as string,
recipeId: '' as string, recipeId: '' as string,
name: '' as string, name: '' as string,
@ -333,10 +349,35 @@ const referForm = reactive({
remark: '' as string, remark: '' as string,
refer: '' as string refer: '' as string
}) })
const openCReferDialog = () => {
isEdit.value = false
resetDialogForm()
referDialogVisible.value = true
}
const resetDialogForm = () => {
referForm.value.id= undefined
referForm.value.recipeId= undefined,
referForm.value.name= '' as string,
referForm.value.max= '' as string,
referForm.value.min='' as string,
referForm.value.dataType= '' as string,
referForm.value.dataUnit= '' as string,
referForm.value.dataUnitLabel= '' as string,
referForm.value.remark= '' as string,
referForm.value.refer= '' as string
/* const form = unref(referFormRef)
if (!form) {
ElMessage.warning('表单实例未找到')
return
}
//
form.resetFields()*/
//referFormRef.value?.resetFields?.()
}
const openReferDialog = (row: RecipePointVO) => { const openReferDialog = (row: RecipePointVO) => {
const id = row?.id === undefined || row?.id === null ? '' : String(row.id) const id = row?.id === undefined || row?.id === null ? '' : String(row.id)
referForm.id = id /* referForm.id = id
referForm.recipeId = row?.recipeId === undefined || row?.recipeId === null ? '' : String(row.recipeId) referForm.recipeId = row?.recipeId === undefined || row?.recipeId === null ? '' : String(row.recipeId)
referForm.name = row?.name ?? '' referForm.name = row?.name ?? ''
referForm.max = row?.max ?? '' referForm.max = row?.max ?? ''
@ -345,27 +386,38 @@ const openReferDialog = (row: RecipePointVO) => {
referForm.dataUnit = row?.dataUnit ?? '' referForm.dataUnit = row?.dataUnit ?? ''
referForm.dataUnitLabel = getUnitLabel(row?.dataUnit) referForm.dataUnitLabel = getUnitLabel(row?.dataUnit)
referForm.remark = row?.remark ?? '' referForm.remark = row?.remark ?? ''
referForm.refer = row?.refer ?? '' referForm.refer = row?.refer ?? ''*/
referForm.value =row
referForm.value.id = id
isEdit.value = true
referDialogVisible.value = true referDialogVisible.value = true
} }
const submitRefer = async () => { const submitRefer = async () => {
if (referSubmitting.value) return if (referSubmitting.value) return
if (!referForm.id) return // if (!referForm.id) return
referSubmitting.value = true referSubmitting.value = true
try { try {
await RecipePointRecordApi.updateRecipePointRecord({ if(!referForm.value.id){
id: referForm.id, await referFormRef.value.validate()
recipeId: referForm.recipeId ? referForm.recipeId : undefined, referForm.value.recipeId = props.recipeId !== undefined && props.recipeId !== null ? String(props.recipeId) : undefined
name: referForm.name, const data = referForm.value as unknown as RecipePointRecordVO
max: referForm.max, await RecipePointRecordApi.createRecipePointRecord(data)
min: referForm.min, message.success(t('common.createSuccess'))
dataType: referForm.dataType, }else{
dataUnit: referForm.dataUnit, await RecipePointRecordApi.updateRecipePointRecord({
remark: referForm.remark, id: referForm.value.id,
refer: referForm.refer recipeId: referForm.value.recipeId ? referForm.value.recipeId : undefined,
}) name: referForm.value.name,
message.success(t('common.updateSuccess')) max: referForm.value.max,
min: referForm.value.min,
dataType: referForm.value.dataType,
dataUnit: referForm.value.dataUnit,
remark: referForm.value.remark,
refer: referForm.value.refer
})
message.success(t('common.updateSuccess'))
}
referDialogVisible.value = false referDialogVisible.value = false
await refreshManual() await refreshManual()
} finally { } finally {
@ -380,6 +432,7 @@ watch(
getList() getList()
}, },
{ immediate: true } { immediate: true }
) )
watch( watch(

@ -64,12 +64,22 @@
<el-button type="danger" plain @click="handleBatchDelete" v-hasPermi="['iot:device:delete']"> <el-button type="danger" plain @click="handleBatchDelete" v-hasPermi="['iot:device:delete']">
<Icon icon="ep:delete" class="mr-5px" /> {{ t('DataCollection.Device.batchDelete') }} <Icon icon="ep:delete" class="mr-5px" /> {{ t('DataCollection.Device.batchDelete') }}
</el-button> </el-button>
<!-- 视图切换按钮 -->
<el-button
:type="currentView === 'grid' ? 'primary' : 'default'"
:icon="currentView === 'grid' ? Menu : Grid"
@click="toggleView"
class="view-toggle-btn"
>
{{ currentView === 'grid' ? t('DataCollection.Device.gridView') : t('DataCollection.Device.sudoku') }}
</el-button>
</el-form-item> </el-form-item>
</el-form> </el-form>
</ContentWrap> </ContentWrap>
<!-- 列表 --> <!-- 列表 GridView Sudoku-->
<ContentWrap> <ContentWrap>
<div v-show="currentView === 'table'" class="simple-table-view">
<el-table <el-table
ref="tableRef" v-loading="loading" :data="list" :stripe="true" :show-overflow-tooltip="true" row-key="id" ref="tableRef" v-loading="loading" :data="list" :stripe="true" :show-overflow-tooltip="true" row-key="id"
@selection-change="handleSelectionChange" @row-click="handleShowAttribute"> @selection-change="handleSelectionChange" @row-click="handleShowAttribute">
@ -179,6 +189,81 @@
<Pagination <Pagination
:total="total" v-model:page="queryParams.pageNo" v-model:limit="queryParams.pageSize" :total="total" v-model:page="queryParams.pageNo" v-model:limit="queryParams.pageSize"
@pagination="getList" /> @pagination="getList" />
</div>
<!-- 九宫格视图 -->
<div v-show="currentView === 'grid'" class="simple-grid-view">
<div v-if="!list || list.length === 0" class="empty-grid">
<el-empty description="暂无设备数据"/>
</div>
<div v-else class="grid-container">
<div
v-for="(item, index) in list"
:key="item.id || index"
class="grid-card"
@click="handleShowAttribute(item)"
>
<!-- 设备状态指示 status-${item.deviceStatus} -->
<div class="status-indicator" :class="getStatusText(item.operatingStatus)"></div>
<!-- 设备图标 -->
<!-- <div class="card-icon">
<el-icon :size="32" :color="getEquipmentColor(item.type)">
<component :is="getEquipmentIcon(item.type)"/>
</el-icon>
</div>-->
<!-- 设备基本信息 -->
<div class="card-content">
<!-- 设备状态 -->
<div class="card-status">
<el-tag
:type="getStatusTag(item.operatingStatus)"
size="small"
class="status-tag"
>
{{ item.operatingStatus }}
</el-tag>
</div>
<div class="card-title"> {{ t('DataCollection.Device.deviceName') }}:{{ item.deviceName }}</div>
<div class="card-code"> {{ t('DataCollection.Device.deviceCode') }}:{{ item.deviceCode }}</div>
<div class="card-model"> {{ t('DataCollection.Device.collectionTime') }}:{{ item.collectionTime }}</div>
<!-- &lt;!&ndash; 运行信息 &ndash;&gt;
<div v-if="item.runningHours" class="card-running">
<span>运行: {{ formatRunningHours(item.runningHours) }}</span>
</div>
&lt;!&ndash; 位置信息 &ndash;&gt;
<div v-if="item.location" class="card-location">
<el-icon :size="12">
<Location/>
</el-icon>
<span>{{ item.location }}</span>
</div>-->
</div>
</div>
</div>
<Pagination
:total="total" v-model:page="queryParams.pageNo" v-model:limit="queryParams.pageSize"
@pagination="getList"/>
<!-- 分页 -->
<!-- <div class="simple-pagination">
<el-pagination
v-model:current-page="queryParams.pageNo"
v-model:page-size="queryParams.pageSize"
:page-sizes="[12, 24, 48, 96]"
layout="total, sizes, prev, pager, next"
:total="total"
@size-change="handleSizeChange"
@current-change="handlePageChange"
/>
</div>-->
</div>
</ContentWrap> </ContentWrap>
<!-- 表单弹窗添加/修改 --> <!-- 表单弹窗添加/修改 -->
@ -600,7 +685,77 @@ import request from '@/config/axios'
import { DeviceApi, DeviceConnectParams, DeviceVO } from '@/api/iot/device' import { DeviceApi, DeviceConnectParams, DeviceVO } from '@/api/iot/device'
import DeviceForm from './DeviceForm.vue' import DeviceForm from './DeviceForm.vue'
import DeviceAttributeList from './components/DeviceAttributeList.vue' import DeviceAttributeList from './components/DeviceAttributeList.vue'
import {
Refresh,
Grid,
Menu,
Search,
Location
} from '@element-plus/icons-vue'
import {useRouter} from "vue-router";
const currentView = ref('table') // 'table' 'grid'
//
const router = useRouter()
//
const handleView = (row) => {
router.push({
path: '/equipment/detail',
query: {id: row.id}
})
}
/** 设备类型 列表 */
//defineOptions({name: 'DeviceLedger'})
const getEquipmentColor = (type) => {
const colorMap = {
'production': '#409eff',
'inspection': '#67c23a',
'packaging': '#e6a23c',
'transport': '#f56c6c',
'other': '#909399'
}
return colorMap[type] || '#409eff'
}
const getEquipmentIcon = (type) => {
const iconMap = {
'production': 'Monitor',
'inspection': 'Search',
'packaging': 'Box',
'transport': 'Truck',
'other': 'Tools'
}
return iconMap[type] || 'Tools'
}
//
const getStatusTag = (status) => {
const tagMap = {
'运行': 'success',//running
'待机中': 'info',//standby
'故障中': 'danger',//fault
'报警中': 'warning',//maintenance
'离线': 'info'//stopped
}
return tagMap[status] || 'info'
}
const getStatusText = (status) => {
const textMap = {
'运行': 'status-running',
'待机中': 'status-standby',
'故障中': 'status-fault',
'报警中': 'status-maintenance',
'离线': 'status-stopped'
}
return textMap[status] || '未知'
}
//
const toggleView = () => {
currentView.value = currentView.value === 'table' ? 'grid' : 'table'
//
localStorage.setItem('equipment-view', currentView.value)
}
/** 物联设备 列表 */ /** 物联设备 列表 */
defineOptions({ name: 'Device' }) defineOptions({ name: 'Device' })
@ -1342,3 +1497,216 @@ const handleShowDeviceAlarmHistory = async () => {
} }
</script> </script>
<style lang="scss" scoped>
.simple-grid-view {
background-color: #fff;
border-radius: 4px;
padding: 16px;
max-height: calc(100vh - 546px);
overflow-y: auto;
.empty-grid { //
display: flex;
align-items: center;
justify-content: center;
height: 300px;
}
.grid-container {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
gap: 16px;
padding: 8px;
.grid-card {
position: relative;
border: 1px solid #ebeef5;
border-radius: 8px;
padding: 18px;
background-color: #fafafa;
cursor: pointer;
transition: all 0.3s ease;
display: flex;
align-items: center;
gap: 16px;
&:hover {
border-color: #409eff;
box-shadow: 0 4px 12px rgba(64, 158, 255, 0.1);
transform: translateY(-2px);
background-color: #fff;
}
.status-indicator {
position: absolute;
top: 0;
left: 0;
width: 6px;
height: 100%;
border-radius: 8px 0 0 8px;
&.status-running {
background-color: #67c23a;
}
&.status-standby {
background-color: #909399;
}
&.status-fault {
background-color: #f56c6c;
}
&.status-maintenance {
background-color: #e6a23c;
}
&.status-stopped {
background-color: #909399;
}
}
.card-icon {
flex-shrink: 0;
display: flex;
align-items: center;
justify-content: center;
width: 60px;
height: 60px;
background-color: #f5f7fa;
border-radius: 8px;
}
.card-content {
flex: 1;
min-width: 0;
.card-title {
font-size: 16px;
font-weight: 600;
color: #303133;
margin-bottom: 4px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
margin-left: 50px;
}
.card-code {
font-size: 12px;
color: #909399;
margin-bottom: 2px;
margin-left: 50px;
}
.card-model {
font-size: 13px;
color: #606266;
margin-bottom: 8px;
margin-left: 50px;
}
.card-status {
margin-bottom: 8px;
.status-tag {
width: 50px;
justify-content: center;
}
}
.card-running {
font-size: 12px;
color: #606266;
margin-bottom: 4px;
}
.card-location {
display: flex;
align-items: center;
gap: 4px;
font-size: 12px;
color: #909399;
.el-icon {
color: #909399;
}
}
}
}
}
.simple-pagination {
margin-top: 24px;
padding-top: 16px;
border-top: 1px solid #ebeef5;
text-align: center;
}
}
//
@media (max-width: 768px) {
.equipment-simple {
padding: 12px;
.simple-toolbar {
flex-direction: column;
gap: 12px;
.toolbar-left {
width: 100%;
.simple-search {
flex: 1;
width: 100%;
}
.status-filter,
.type-filter {
width: 100px;
}
}
.toolbar-right {
width: 100%;
justify-content: flex-end;
}
}
.simple-grid-view {
.grid-container {
grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
}
}
}
}
@media (max-width: 480px) {
.equipment-simple {
.simple-grid-view {
.grid-container {
grid-template-columns: 1fr;
}
}
.simple-toolbar {
.toolbar-left {
flex-wrap: wrap;
.simple-search {
width: 100%;
}
.status-filter,
.type-filter {
flex: 1;
min-width: 120px;
}
}
}
}
}
</style>

File diff suppressed because it is too large Load Diff

@ -25,7 +25,9 @@
@keyup.enter="handleQuery" @keyup.enter="handleQuery"
class="!w-240px"> class="!w-240px">
<el-option <el-option
v-for="dict in getDictOptions('classification')" :key="dict.value" :label="dict.label" v-for="dict in getIntDictOptions(DICT_TYPE.Classification)"
:key="dict.value"
:label="dict.label"
:value="dict.value" /> :value="dict.value" />
</el-select> </el-select>
</el-form-item> </el-form-item>

@ -54,7 +54,7 @@
</el-button> </el-button>
<el-button type="success" plain @click="handleExport" :loading="exportLoading"> <el-button type="success" plain @click="handleExport" :loading="exportLoading">
<Icon icon="ep:download" class="mr-5px" /> <Icon icon="ep:download" class="mr-5px" />
导出 {{ t('action.export') }}
</el-button> </el-button>
</el-form-item> </el-form-item>
</el-form> </el-form>

Loading…
Cancel
Save