ck #3

Merged
besure merged 12 commits from ck into main 2 weeks ago

@ -102,6 +102,9 @@ export const DeviceApi = {
getAvailableList: async () => { getAvailableList: async () => {
return await request.get({ url: `/iot/device/available-list` }) return await request.get({ url: `/iot/device/available-list` })
}, },
getAvailableListPage: async (params: any) => {
return await request.get({ url: `/iot/device/available-page` , params})
},
// 新增物联设备 // 新增物联设备
createDevice: async (data: DeviceVO) => { createDevice: async (data: DeviceVO) => {
return await request.post({ url: `/iot/device/create`, data }) return await request.post({ url: `/iot/device/create`, data })
@ -147,6 +150,10 @@ export const DeviceApi = {
return await request.get({ url: `/iot/device/singleDevice`, params }) return await request.get({ url: `/iot/device/singleDevice`, params })
}, },
getSingleDeviceFrom: async (params: SingleDeviceParams) => {
return await request.get({ url: `/iot/device/singleDeviceFrom`, params })
},
getHistoryRecord: async (params: HistoryRecordParams) => { getHistoryRecord: async (params: HistoryRecordParams) => {
return await request.get({ return await request.get({
url: `/iot/device/historyRecord`, url: `/iot/device/historyRecord`,
@ -155,6 +162,15 @@ export const DeviceApi = {
}) })
}, },
getHistoryAnalyse: async (params: HistoryRecordParams) => {
return await request.get({
url: `/iot/device/historyAnalyse`,
params,
paramsSerializer: (p) => qs.stringify(p, { allowDots: true, arrayFormat: 'repeat' })
})
},
devicePointList: async () => { devicePointList: async () => {
return await request.get({ url: `/iot/device/devicePointList` }) return await request.get({ url: `/iot/device/devicePointList` })
}, },
@ -170,6 +186,10 @@ export const DeviceApi = {
getDeviceAttributePage: async (params) => { getDeviceAttributePage: async (params) => {
return await request.get({ url: `/iot/device/device-attribute/page`, params }) return await request.get({ url: `/iot/device/device-attribute/page`, params })
}, },
// 获得设备属性按类型分租
getDeviceAttributeGroupList: async (params) => {
return await request.get({ url: `/iot/device/device-attribute/groupList`, params })
},
// 获得设备属性列表 // 获得设备属性列表
getDeviceAttributeList: async (deviceId: number | string) => { getDeviceAttributeList: async (deviceId: number | string) => {
return await request.get({ url: `/iot/device/device-attribute/list?deviceId=` + deviceId }) return await request.get({ url: `/iot/device/device-attribute/list?deviceId=` + deviceId })

@ -64,13 +64,16 @@ const props = withDefaults(
pageSize?: number pageSize?: number
initialRows?: any[] initialRows?: any[]
queryParams?: Record<string, any> // queryParams?: Record<string, any> //
/** ✅ 新增 */
defaultSelectedKeys?: (string | number)[]
}>(), }>(),
{ {
selectionType: 'multiple', selectionType: 'multiple',
rowKey: 'id', rowKey: 'id',
pageSize: 10, pageSize: 10,
initialRows: () => [], initialRows: () => [],
queryParams: () => ({}) // queryParams: () => ({}), //
defaultSelectedKeys: () => []
} }
) )
@ -111,6 +114,16 @@ const refreshSelectionOnTable = async () => {
syncingSelection.value = false syncingSelection.value = false
} }
} }
/**
* 新增根据 defaultSelectedKeys 初始化选中状态
*/
const initDefaultSelection = () => {
if (!props.defaultSelectedKeys.length) return
props.defaultSelectedKeys.forEach((key) => {
selectedMap.value.set(key, { [props.rowKey]: key })
})
}
const getList = async () => { const getList = async () => {
loading.value = true loading.value = true
@ -161,12 +174,30 @@ const handleRowClick = (row: any) => {
} }
const open = async (rows?: any[]) => { const open = async (rows?: any[]) => {
/* selectedMap.value.clear()
const initialRows = rows || props.initialRows
const nextRows = isSingleSelect.value ? initialRows.slice(0, 1) : initialRows
nextRows.forEach((row) => {
selectedMap.value.set(resolveRowKey(row), row)
})
queryParams.pageNo = 1
queryParams.pageSize = props.pageSize
dialogVisible.value = true
await getList()*/
selectedMap.value.clear() selectedMap.value.clear()
// 使 defaultSelectedKeys
if (props.defaultSelectedKeys.length) {
initDefaultSelection()
}
// initialRows / rows
const initialRows = rows || props.initialRows const initialRows = rows || props.initialRows
const nextRows = isSingleSelect.value ? initialRows.slice(0, 1) : initialRows const nextRows = isSingleSelect.value ? initialRows.slice(0, 1) : initialRows
nextRows.forEach((row) => { nextRows.forEach((row) => {
selectedMap.value.set(resolveRowKey(row), row) selectedMap.value.set(resolveRowKey(row), row)
}) })
queryParams.pageNo = 1 queryParams.pageNo = 1
queryParams.pageSize = props.pageSize queryParams.pageSize = props.pageSize
dialogVisible.value = true dialogVisible.value = true

@ -1848,6 +1848,8 @@ export default {
moduleName: 'Product Material Information', moduleName: 'Product Material Information',
searchNameLabel: 'Name', searchNameLabel: 'Name',
searchNamePlaceholder: 'Please enter name', searchNamePlaceholder: 'Please enter name',
searchCodeLabel: 'Code',
searchCodePlaceholder: 'Please enter code',
searchButtonText: 'Search', searchButtonText: 'Search',
resetButtonText: 'Reset', resetButtonText: 'Reset',
addButtonText: 'Add', addButtonText: 'Add',
@ -4227,9 +4229,11 @@ export default {
tableCollectionTimeColumn: 'Collection Time', tableCollectionTimeColumn: 'Collection Time',
tableOperateColumn: 'Operation', tableOperateColumn: 'Operation',
tableActionHistoryLabel: 'History', tableActionHistoryLabel: 'History',
tableActionHistoryAnalyseLabel: 'History Data Analysis',
dialogTitlePrefix: 'History: ', dialogTitlePrefix: 'History: ',
dialogCollectionTimeLabel: 'Collection Time', dialogCollectionTimeLabel: 'Collection Time',
dialogPointFilterLabel:'Point Filter',
dialogPointFilterPlaceholder: 'Please enter point name',
dialogCollectionTimeStartPlaceholder: 'Start Time', dialogCollectionTimeStartPlaceholder: 'Start Time',
dialogCollectionTimeEndPlaceholder: 'End Time', dialogCollectionTimeEndPlaceholder: 'End Time',
dialogSearchButtonText: 'Search', dialogSearchButtonText: 'Search',

@ -2680,6 +2680,8 @@ export default {
moduleName: '产品物料信息', moduleName: '产品物料信息',
searchNameLabel: '名称', searchNameLabel: '名称',
searchNamePlaceholder: '请输入名称', searchNamePlaceholder: '请输入名称',
searchCodeLabel: '编码',
searchCodePlaceholder: '请输入编码',
searchButtonText: '搜索', searchButtonText: '搜索',
resetButtonText: '重置', resetButtonText: '重置',
addButtonText: '新增', addButtonText: '新增',
@ -4070,9 +4072,11 @@ export default {
tableCollectionTimeColumn: '采集时间', tableCollectionTimeColumn: '采集时间',
tableOperateColumn: '操作', tableOperateColumn: '操作',
tableActionHistoryLabel: '历史记录', tableActionHistoryLabel: '历史记录',
tableActionHistoryAnalyseLabel: '数据分析',
dialogTitlePrefix: '历史记录:', dialogTitlePrefix: '历史记录:',
dialogCollectionTimeLabel: '采集时间', dialogCollectionTimeLabel: '采集时间',
dialogPointFilterLabel: '点位筛选',
dialogPointFilterPlaceholder: '请输入点位名称',
dialogCollectionTimeStartPlaceholder: '开始时间', dialogCollectionTimeStartPlaceholder: '开始时间',
dialogCollectionTimeEndPlaceholder: '结束时间', dialogCollectionTimeEndPlaceholder: '结束时间',
dialogSearchButtonText: '查询', dialogSearchButtonText: '查询',
@ -4442,9 +4446,11 @@ export default {
tableCollectionTimeColumn: '采集时间', tableCollectionTimeColumn: '采集时间',
tableOperateColumn: '操作', tableOperateColumn: '操作',
tableActionHistoryLabel: '历史记录', tableActionHistoryLabel: '历史记录',
tableActionHistoryAnalyseLabel: '数据分析',
dialogTitlePrefix: '历史记录:', dialogTitlePrefix: '历史记录:',
dialogCollectionTimeLabel: '采集时间', dialogCollectionTimeLabel: '采集时间',
dialogPointFilterLabel: '点位筛选',
dialogPointFilterPlaceholder: '请输入点位名称',
dialogCollectionTimeStartPlaceholder: '开始时间', dialogCollectionTimeStartPlaceholder: '开始时间',
dialogCollectionTimeEndPlaceholder: '结束时间', dialogCollectionTimeEndPlaceholder: '结束时间',
dialogSearchButtonText: '查询', dialogSearchButtonText: '查询',

@ -2,41 +2,29 @@
<template> <template>
<ContentWrap> <ContentWrap>
<!-- 搜索工作栏 --> <!-- 搜索工作栏 -->
<el-form <el-form class="-mb-15px" :model="queryParams" ref="queryFormRef" :inline="true" label-width="auto" @submit.prevent>
class="-mb-15px" <el-form-item :label="t('FactoryModeling.ProductInformation.searchCodeLabel')" prop="barCode">
:model="queryParams" <el-input v-model="queryParams.barCode"
ref="queryFormRef" :placeholder="t('FactoryModeling.ProductInformation.searchCodePlaceholder')" clearable
:inline="true" @keyup.enter="handleQuery" class="!w-240px" />
label-width="120px" </el-form-item>
@submit.prevent
>
<el-form-item :label="t('FactoryModeling.ProductInformation.searchNameLabel')" prop="name"> <el-form-item :label="t('FactoryModeling.ProductInformation.searchNameLabel')" prop="name">
<el-input <el-input v-model="queryParams.name"
v-model="queryParams.name" :placeholder="t('FactoryModeling.ProductInformation.searchNamePlaceholder')" clearable
:placeholder="t('FactoryModeling.ProductInformation.searchNamePlaceholder')" @keyup.enter="handleQuery" class="!w-240px" />
clearable
@keyup.enter="handleQuery"
class="!w-240px"
/>
</el-form-item> </el-form-item>
<el-form-item> <el-form-item>
<el-button @click="handleQuery"><Icon icon="ep:search" class="mr-5px" /> {{ t('FactoryModeling.ProductInformation.searchButtonText') }}</el-button> <el-button @click="handleQuery">
<el-button @click="resetQuery"><Icon icon="ep:refresh" class="mr-5px" /> {{ t('FactoryModeling.ProductInformation.resetButtonText') }}</el-button> <Icon icon="ep:search" class="mr-5px" /> {{ t('FactoryModeling.ProductInformation.searchButtonText') }}
<el-button </el-button>
type="primary" <el-button @click="resetQuery">
plain <Icon icon="ep:refresh" class="mr-5px" /> {{ t('FactoryModeling.ProductInformation.resetButtonText') }}
@click="openForm('create')" </el-button>
v-hasPermi="['erp:product:create']" <el-button type="primary" plain @click="openForm('create')" v-hasPermi="['erp:product:create']">
>
<Icon icon="ep:plus" class="mr-5px" /> {{ t('FactoryModeling.ProductInformation.addButtonText') }} <Icon icon="ep:plus" class="mr-5px" /> {{ t('FactoryModeling.ProductInformation.addButtonText') }}
</el-button> </el-button>
<el-button <el-button type="success" plain @click="handleExport" :loading="exportLoading"
type="success" v-hasPermi="['erp:product:export']">
plain
@click="handleExport"
:loading="exportLoading"
v-hasPermi="['erp:product:export']"
>
<Icon icon="ep:download" class="mr-5px" /> {{ t('FactoryModeling.ProductInformation.exportButtonText') }} <Icon icon="ep:download" class="mr-5px" /> {{ t('FactoryModeling.ProductInformation.exportButtonText') }}
</el-button> </el-button>
</el-form-item> </el-form-item>
@ -47,12 +35,7 @@
<ContentWrap> <ContentWrap>
<el-tabs v-model="activeName" @tab-click="handleTabClick"> <el-tabs v-model="activeName" @tab-click="handleTabClick">
<!-- 使用 v-for 动态生成 el-tab-pane --> <!-- 使用 v-for 动态生成 el-tab-pane -->
<el-tab-pane <el-tab-pane v-for="item in parentList" :key="item.id" :label="item.name" :name="item.id.toString()" />
v-for="item in parentList"
:key="item.id"
:label="item.name"
:name="item.id.toString()"
/>
<!-- <el-tab-pane label="产品" name="2" /> <!-- <el-tab-pane label="产品" name="2" />
<el-tab-pane label="原料" name="1" /> <el-tab-pane label="原料" name="1" />
<el-tab-pane label="备件" name="5" /> <el-tab-pane label="备件" name="5" />
@ -62,60 +45,46 @@
<el-tab-pane label="其他" name="0" /> --> <el-tab-pane label="其他" name="0" /> -->
</el-tabs> </el-tabs>
<el-table v-loading="loading" :data="list" :stripe="true" :show-overflow-tooltip="true"> <el-table v-loading="loading" :data="list" :stripe="true" :show-overflow-tooltip="true">
<el-table-column :label="t('FactoryModeling.ProductInformation.tableBarCodeColumn')" align="center" prop="barCode" sortable/> <el-table-column :label="t('FactoryModeling.ProductInformation.tableBarCodeColumn')" align="center" prop="barCode"
<el-table-column :label="t('FactoryModeling.ProductInformation.tableNameColumn')" align="left" prop="name" width="220px" sortable/> sortable />
<el-table-column :label="t('FactoryModeling.ProductInformation.tableStandardColumn')" align="center" prop="standard" sortable/> <el-table-column :label="t('FactoryModeling.ProductInformation.tableNameColumn')" align="left" prop="name"
<el-table-column :label="t('FactoryModeling.ProductInformation.tableCategoryColumn')" align="center" prop="subCategoryName" sortable/> width="220px" sortable />
<el-table-column :label="t('FactoryModeling.ProductInformation.tableUnitColumn')" align="center" prop="unitName" sortable/> <el-table-column :label="t('FactoryModeling.ProductInformation.tableStandardColumn')" align="center"
<el-table-column :label="t('FactoryModeling.ProductInformation.tableStatusColumn')" align="center" prop="status" sortable> prop="standard" sortable />
<el-table-column :label="t('FactoryModeling.ProductInformation.tableCategoryColumn')" align="center"
prop="subCategoryName" sortable />
<el-table-column :label="t('FactoryModeling.ProductInformation.tableUnitColumn')" align="center" prop="unitName"
sortable />
<el-table-column :label="t('FactoryModeling.ProductInformation.tableStatusColumn')" align="center" prop="status"
sortable>
<template #default="scope"> <template #default="scope">
<dict-tag :type="DICT_TYPE.COMMON_STATUS" :value="scope.row.status" /> <dict-tag :type="DICT_TYPE.COMMON_STATUS" :value="scope.row.status" />
</template> </template>
</el-table-column> </el-table-column>
<el-table-column <el-table-column :label="t('FactoryModeling.ProductInformation.tableCreateTimeColumn')" align="center"
:label="t('FactoryModeling.ProductInformation.tableCreateTimeColumn')" prop="createTime" :formatter="dateFormatter" width="180px" sortable />
align="center"
prop="createTime"
:formatter="dateFormatter"
width="180px"
sortable
/>
<el-table-column :label="t('FactoryModeling.ProductInformation.tableOperateColumn')" align="center" width="150px"> <el-table-column :label="t('FactoryModeling.ProductInformation.tableOperateColumn')" align="center" width="150px">
<template #default="scope"> <template #default="scope">
<!-- <el-button--> <!-- <el-button-->
<!-- v-if="scope.row.categoryId ===2"--> <!-- v-if="scope.row.categoryId ===2"-->
<!-- link--> <!-- link-->
<!-- type="primary"--> <!-- type="primary"-->
<!-- @click="openBomForm('detail', scope.row.id)"--> <!-- @click="openBomForm('detail', scope.row.id)"-->
<!-- >--> <!-- >-->
<!-- BOM--> <!-- BOM-->
<!-- </el-button>--> <!-- </el-button>-->
<el-button <el-button link type="primary" @click="openForm('update', scope.row.id)" v-hasPermi="['erp:product:update']">
link
type="primary"
@click="openForm('update', scope.row.id)"
v-hasPermi="['erp:product:update']"
>
{{ t('FactoryModeling.ProductInformation.tableEditAction') }} {{ t('FactoryModeling.ProductInformation.tableEditAction') }}
</el-button> </el-button>
<el-button <el-button link type="danger" @click="handleDelete(scope.row.id)" v-hasPermi="['erp:product:delete']">
link
type="danger"
@click="handleDelete(scope.row.id)"
v-hasPermi="['erp:product:delete']"
>
{{ t('FactoryModeling.ProductInformation.tableDeleteAction') }} {{ t('FactoryModeling.ProductInformation.tableDeleteAction') }}
</el-button> </el-button>
</template> </template>
</el-table-column> </el-table-column>
</el-table> </el-table>
<!-- 分页 --> <!-- 分页 -->
<Pagination <Pagination :total="total" v-model:page="queryParams.pageNo" v-model:limit="queryParams.pageSize"
:total="total" @pagination="getList" />
v-model:page="queryParams.pageNo"
v-model:limit="queryParams.pageSize"
@pagination="getList"
/>
</ContentWrap> </ContentWrap>
<!-- 表单弹窗添加/修改 --> <!-- 表单弹窗添加/修改 -->
@ -148,6 +117,7 @@ const queryParams = reactive({
pageNo: 1, pageNo: 1,
pageSize: 10, pageSize: 10,
name: undefined, name: undefined,
barCode: undefined,
categoryId: undefined categoryId: undefined
}) })
const queryFormRef = ref() // const queryFormRef = ref() //
@ -195,7 +165,7 @@ const handleDelete = async (id: number) => {
message.success(t('common.delSuccess')) message.success(t('common.delSuccess'))
// //
await getList() await getList()
} catch {} } catch { }
} }
/** 导出按钮操作 */ /** 导出按钮操作 */

File diff suppressed because it is too large Load Diff

@ -322,7 +322,7 @@
<!-- 表单弹窗添加/修改 --> <!-- 表单弹窗添加/修改 -->
<DeviceForm ref="formRef" @success="getList" /> <DeviceForm ref="formRef" @success="getList" />
<!-- 子表的列表 --> <!-- 子表的列表 -->
<ContentWrap v-if="ifShow"> <!-- <ContentWrap v-if="ifShow">
<template v-if="attributeDeviceId"> <template v-if="attributeDeviceId">
<div class="mb-10px flex items-center justify-between text-sm text-gray-500"> <div class="mb-10px flex items-center justify-between text-sm text-gray-500">
<div> <div>
@ -711,7 +711,7 @@
</el-tabs> </el-tabs>
</template> </template>
<el-empty v-else :description="t('DataCollection.Device.emptyDescription')" /> <el-empty v-else :description="t('DataCollection.Device.emptyDescription')" />
</ContentWrap> </ContentWrap>-->
<Dialog :title="t('DataCollection.Device.alarmHistoryTitle')" v-model="deviceAlarmDialogVisible" width="1200px"> <Dialog :title="t('DataCollection.Device.alarmHistoryTitle')" v-model="deviceAlarmDialogVisible" width="1200px">
<el-form <el-form
@ -1141,6 +1141,14 @@ const deviceRuleTabLabel = computed(() => {
const handleShowAttribute = (row: any) => { const handleShowAttribute = (row: any) => {
attributeDeviceId.value = row?.id attributeDeviceId.value = row?.id
attributeDeviceName.value = row?.deviceName ?? '' attributeDeviceName.value = row?.deviceName ?? ''
router.push({
path: '/iot/pointManagement',
query: {
id: row?.id,
name: row?.deviceName
}
});
} }
const ruleLoading = ref(false) const ruleLoading = ref(false)

File diff suppressed because it is too large Load Diff

@ -108,12 +108,15 @@
:label="t('DataCollection.HistoryData.tableOperateColumn')" :label="t('DataCollection.HistoryData.tableOperateColumn')"
align="center" align="center"
fixed="right" fixed="right"
width="150px" width="300px"
> >
<template #default="scope"> <template #default="scope">
<el-button link type="primary" @click="handleSingleView(scope.row)"> <el-button link type="primary" @click="handleSingleView(scope.row)">
{{ t('DataCollection.HistoryData.tableActionHistoryLabel') }} {{ t('DataCollection.HistoryData.tableActionHistoryLabel') }}
</el-button> </el-button>
<el-button link type="primary" @click="handleSingleAnalyseView(scope.row)">
{{ t('DataCollection.HistoryData.tableActionHistoryAnalyseLabel') }}
</el-button>
</template> </template>
</el-table-column> </el-table-column>
</el-table> </el-table>
@ -137,9 +140,10 @@ import { dateFormatter } from '@/utils/formatTime'
import download from '@/utils/download' import download from '@/utils/download'
import { DeviceApi, LineDeviceVO, LineDevicePageParams } from '@/api/iot/device' import { DeviceApi, LineDeviceVO, LineDevicePageParams } from '@/api/iot/device'
import HistorySingleDeviceDialog from './HistorySingleDeviceDialog.vue' import HistorySingleDeviceDialog from './HistorySingleDeviceDialog.vue'
import {useRouter} from "vue-router";
//
const router = useRouter()
defineOptions({ name: 'HistoryData' }) defineOptions({ name: 'HistoryData' })
const message = useMessage() const message = useMessage()
const { t } = useI18n() const { t } = useI18n()
@ -225,6 +229,27 @@ const handleSingleView = (row: LineDeviceVO) => {
singleDialogVisible.value = true singleDialogVisible.value = true
} }
const handleSingleAnalyseView = (row: LineDeviceVO) => {
const deviceId = (row as any)?.deviceId ?? row?.id
if (deviceId === undefined || deviceId === null || deviceId === '') {
return
}
singleDeviceId.value = deviceId
singleDeviceName.value = row.deviceName || ''
router.push({
path: '/iot/historySingleAnalyse',
query: {
id: deviceId,
name: singleDeviceName.value,
deviceCode: row.deviceCode,
lineNode: row.lineNode,
lineName: row.lineName,
collectionTime: row.collectionTime
}
});
}
onMounted(() => { onMounted(() => {
getList() getList()
}) })

@ -7,15 +7,15 @@
</div> </div>
<ContentWrap v-loading="loading"> <ContentWrap v-loading="loading">
<div v-if="sections.length" class="single-device-dialog__table-grid"> <div v-if="sections.length" class="single-device-dialog__table-grid">
<div v-for="section in sections" :key="section.key" class="single-device-dialog__section"> <!-- <div v-for="section in sections" :key="section.key" class="single-device-dialog__section">
<div class="single-device-dialog__section-title"> <div class="single-device-dialog__section-title">
{{ section.title }} {{ section.title }}
</div> </div>-->
<el-empty <!-- <el-empty
v-if="!section.columns.length" v-if="!section.length"
:description="t('DataCollection.RealTimeMonitoring.emptyDescription')" :description="t('DataCollection.RealTimeMonitoring.emptyDescription')"
/> />-->
<el-table <!-- <el-table
v-else :data="section.rows" :border="true" :header-cell-style="headerCellStyle" v-else :data="section.rows" :border="true" :header-cell-style="headerCellStyle"
:cell-style="bodyCellStyle" size="small"> :cell-style="bodyCellStyle" size="small">
<el-table-column <el-table-column
@ -25,8 +25,22 @@ v-for="col in section.columns" :key="col.prop" :prop="col.prop" :label="col.labe
<span>{{ formatCell(scope.row[col.prop]) }}</span> <span>{{ formatCell(scope.row[col.prop]) }}</span>
</template> </template>
</el-table-column> </el-table-column>
</el-table> </el-table>-->
</div> <div v-for="section in sections" :key="section.id" class="form-section">
<h3 v-if="section.title" class="section-title">{{ section.title }}</h3>
<div class="form-grid">
<div
v-for="item in section.items"
:key="item.prop"
class="form-item"
>
<div class="form-label">{{ item.label }}:</div>
<div class="form-value">{{ formatCellTwo(item.value) }}</div>
</div>
</div>
</div>
<!-- </div>-->
</div> </div>
<el-empty <el-empty
v-else v-else
@ -49,10 +63,14 @@ type SectionColumn = {
type SectionRow = Record<string, string | number | null> type SectionRow = Record<string, string | number | null>
type Section = { type Section = {
key: string id: number
title: string title?: string
columns: SectionColumn[] items: FormItem[]
rows: SectionRow[] }
interface FormItem {
prop: string
label: string
value: any
} }
const { t } = useI18n() const { t } = useI18n()
@ -83,8 +101,44 @@ const dialogTitle = computed(() => {
const loading = ref(false) const loading = ref(false)
const deviceName = computed(() => props.deviceName) const deviceName = computed(() => props.deviceName)
const sections = ref<Section[]>([]) const sections = ref<Section[]>([
{
id: 1,
title: '工艺参数监控',
items: [
{ prop: 'addressValue', label: '系统运行', value: 1, unit: '℃' },
{ prop: 'attributeName', label: '烘干湿度', value: 2, unit: '%' },
{ prop: 'attributeName', label: '输送速度', value: 3, unit: 'm/min' },
{ prop: 'attributeName', label: '回风温度', value: 4, unit: '℃' },
{ prop: 'attributeName', label: '排风温度', value: 5, unit: '℃' },
{ prop: 'attributeName', label: '呼叫状态', value: 6 },
{ prop: 'attributeName', label: '在线状态', value: 7 },
{ prop: 'attributeName', label: '运行状态', value: 3 },
{ prop: 'attributeName', label: '主缸速度', value: 0, unit: '%' },
{ prop: 'attributeName', label: '提布辊速度', value: 0 },
{ prop: 'fanSpeed', label: '风机速度', value: '暂无数据' },
{ prop: 'mainLevel', label: '主缸水位', value: 1, unit: '%' },
{ prop: 'mainWater', label: '主缸水量', value: 145, unit: 'L' },
{ prop: 'setTemp', label: '设定温度', value: 0.0, unit: '℃' },
{ prop: 'actualTemp', label: '实际温度', value: 0.0, unit: '℃' },
],
},
])
const formatValue = (item: FormItem) => {
let value = item.value
if (value === null || value === undefined) return '--'
if (typeof value === 'number') {
value = Number.isInteger(value) ? value.toString() : value.toFixed(2)
}
if (item.unit) {
value += ` ${item.unit}`
}
return value
}
const toGroupMap = (value: any): Record<string, any[]> => { const toGroupMap = (value: any): Record<string, any[]> => {
if (!value || typeof value !== 'object' || Array.isArray(value)) { if (!value || typeof value !== 'object' || Array.isArray(value)) {
return {} return {}
@ -136,6 +190,14 @@ const formatCell = (value: string | number | null | undefined) => {
return value return value
} }
const formatCellTwo = (value: any) => {
//
if (typeof value === 'number') {
return value.toFixed(2)
}
return value
}
const buildSectionsFromGroups = (groups: Record<string, any[]>): Section[] => { const buildSectionsFromGroups = (groups: Record<string, any[]>): Section[] => {
const result: Section[] = [] const result: Section[] = []
for (const [key, list] of Object.entries(groups)) { for (const [key, list] of Object.entries(groups)) {
@ -150,12 +212,12 @@ const buildSectionsFromGroups = (groups: Record<string, any[]>): Section[] => {
row[prop] = item?.addressValue ?? '-' row[prop] = item?.addressValue ?? '-'
}) })
} }
result.push({ /* result.push({
key, key,
title: key, title: key,
columns, columns,
rows: columns.length ? [row] : [] rows: columns.length ? [row] : []
}) })*/
} }
return result return result
} }
@ -167,15 +229,16 @@ const fetchList = async () => {
} }
loading.value = true loading.value = true
try { try {
const res: any = await DeviceApi.getSingleDevice({ deviceId: props.deviceId }) const res: any = await DeviceApi.getSingleDeviceFrom({ deviceId: props.deviceId })
const groups = Array.isArray(res) /* const groups = Array.isArray(res)
? { [t('DataCollection.RealTimeMonitoring.defaultGroupName')]: res } ? { [t('DataCollection.RealTimeMonitoring.defaultGroupName')]: res }
: { : {
...toGroupMap(res?.data), ...toGroupMap(res?.data),
...toGroupMap(res?.data?.data), ...toGroupMap(res?.data?.data),
...toGroupMap(res) ...toGroupMap(res)
} }
sections.value = buildSectionsFromGroups(groups) //sections.value = buildSectionsFromGroups(groups)*/
sections.value = res
} finally { } finally {
loading.value = false loading.value = false
} }
@ -222,4 +285,84 @@ watch(
.single-device-dialog__section :deep(.el-table__inner-wrapper) { .single-device-dialog__section :deep(.el-table__inner-wrapper) {
border-radius: 0; border-radius: 0;
} }
/* 表单容器 */
.form-section {
margin-bottom: 24px;
}
/* 标题样式 */
.section-title {
font-size: 13px;
font-weight: bold;
margin-bottom: 12px;
color: var(--el-text-color-primary);
}
/* 三列网格容器 */
.form-grid {
display: grid;
grid-template-columns: repeat(4, 1fr); /* 三列等宽 */
/*gap: 16px;*/ /* 列间距和行间距 */
/* padding: 8px;*/
background-color: #fff;
/* border: 1px solid #dcdfe6; !* 外边框 *!*/
border-radius: 4px;
min-height: 35px;
}
/* 表单项:标签 + 值 */
.form-item {
display: flex;
align-items: center;
justify-content: space-between;
height: 100%;
min-height: 35px;
/* padding: 8px 0;*/
border: 1px solid #dcdfe6;
/* border-right: 1px solid #dcdfe6; !* *!
border-bottom: 1px solid #dcdfe6; !* 下边框 *!*/
}
/* 标签样式 */
.form-label {
font-size: 14px;
display: flex;
align-items: center;
justify-content: center;
color: #666;
height: 100%;
min-height: 35px;
width: 150px; /* 固定标签宽度,避免错位 */
background-color: #f5f7fa; /* 背景色 */
}
/* 值样式 */
.form-value {
flex: 1;
display: flex;
align-items: center;
justify-content: center;
height: 100%;
padding: 6px 12px;
background: white;
min-height: 35px;
box-sizing: border-box;
overflow: hidden;
cursor: default;
transition: all 0.2s;
}
/* 响应式:小屏幕下改为两列或单列 */
@media (max-width: 768px) {
.form-grid {
grid-template-columns: repeat(2, 1fr); /* 平板改为两列 */
}
}
@media (max-width: 480px) {
.form-grid {
grid-template-columns: 1fr; /* 手机改为单列 */
}
}
</style> </style>

@ -79,7 +79,7 @@
</el-tooltip> </el-tooltip>
</span> </span>
</template> </template>
<el-select v-model="formData.orgType" @change="handleOrgTypeChange" :placeholder="t('FactoryModeling.FactoryStructure.dialogOrgTypePlaceholder')"> <el-select v-model="formData.orgType" :placeholder="t('FactoryModeling.FactoryStructure.dialogOrgTypePlaceholder')">
<el-option <el-option
v-for="dict in getStrDictOptions(DICT_TYPE.MES_ORG_TYPE)" v-for="dict in getStrDictOptions(DICT_TYPE.MES_ORG_TYPE)"
:key="dict.value" :key="dict.value"
@ -89,25 +89,20 @@
</el-select> </el-select>
</el-form-item> </el-form-item>
<el-form-item :label="t('FactoryModeling.FactoryStructure.dialogMachineLabel')" v-if="formData.orgClass == 'workplace'" prop="machineId"> <el-form-item :label="t('FactoryModeling.FactoryStructure.dialogMachineLabel')" v-if="formData.orgClass == 'workplace'" prop="machineId">
<!-- <el-tree-select <!-- <el-select v-model="formData.machineId" :placeholder="t('FactoryModeling.FactoryStructure.dialogMachinePlaceholder')" clearable>
v-model="formData.machineId"
:data="machineComponentTree"
:props="defaultProps"
check-strictly
default-expand-all
placeholder="请选择机台"
/> -->
<el-select v-model="formData.machineId" :placeholder="t('FactoryModeling.FactoryStructure.dialogMachinePlaceholder')" clearable>
<el-option <el-option
v-for="item in deviceList" v-for="item in deviceList"
:key="item.id" :key="item.id"
:label="item.deviceName" :label="item.deviceName"
:value="item.id" :value="item.id"
/> />
</el-select> </el-select>-->
<el-input :model-value="displayItemDevice" readonly clearable class="device-ledger-selection-input"
:placeholder="t('FactoryModeling.FactoryStructure.dialogMachinePlaceholder')"
@click="openCriticalComponentDialog" />
</el-form-item> </el-form-item>
<el-form-item :label="t('EquipmentManagement.EquipmentLedger.dvName')" prop="dvId" v-if="formData.orgClass == 'workplace'"> <el-form-item :label="t('EquipmentManagement.EquipmentLedger.dvName')" prop="dvId" v-if="formData.orgClass == 'workplace'">
<el-select v-model="formData.dvId" filterable :placeholder="t('EquipmentManagement.EquipmentLedger.dvId')" clearable> <!-- <el-select v-model="formData.dvId" filterable :placeholder="t('EquipmentManagement.EquipmentLedger.dvId')" clearable>
<el-option <el-option
v-for="item in dvList" v-for="item in dvList"
:key="item.id" :key="item.id"
@ -115,7 +110,10 @@
:value="item.id" :value="item.id"
:disabled="item.selected === true" :disabled="item.selected === true"
/> />
</el-select> </el-select>-->
<el-input :model-value="dvIdItemDevice" readonly clearable class="device-ledger-selection-input"
:placeholder="t('EquipmentManagement.EquipmentLedger.dvId')"
@click="openCaijiComponentDialog" />
</el-form-item> </el-form-item>
<!-- <el-form-item label="组织状态" prop="status"> <!-- <el-form-item label="组织状态" prop="status">
<el-radio-group v-model="formData.status"> <el-radio-group v-model="formData.status">
@ -134,6 +132,61 @@
<el-button @click="dialogVisible = false">{{ t('FactoryModeling.FactoryStructure.dialogCancelButton') }}</el-button> <el-button @click="dialogVisible = false">{{ t('FactoryModeling.FactoryStructure.dialogCancelButton') }}</el-button>
</template> </template>
</Dialog> </Dialog>
<TableSelectDialog
ref="deviceSelectDialogRef"
title="选择设备"
:columns="deviceColumns"
:fetch-api="fetchDeviceLedgerPage"
row-key="id"
@confirm="handleDeviceSelectConfirm"
:query-params="mergedQueryParams"
:selection-type="'single'"
:default-selected-keys="ids"
>
<!-- 使用 header 插槽插入查询表单 -->
<template #header>
<el-form ref="searchFormRef" :model="searchParams" :inline="true" >
<el-form-item label="设备编号" prop="deviceCode">
<el-input v-model="searchParams.deviceCode" placeholder="请输入编号" clearable />
</el-form-item>
<el-form-item label="设备名称" prop="deviceName">
<el-input v-model="searchParams.deviceName" placeholder="请输入名称" clearable />
</el-form-item>
<el-form-item>
<el-button type="primary" @click="handleSearch">{{ t('FactoryModeling.ProductInformation.searchButtonText') }}</el-button>
<el-button @click="resetSearch">{{ t('FactoryModeling.ProductInformation.resetButtonText') }}</el-button>
</el-form-item>
</el-form>
</template>
</TableSelectDialog>
<TableSelectDialog
ref="caiJiSelectDialogRef"
title="选择采集设备"
:columns="caiJiColumns"
:fetch-api="fetchCaiJILedgerPage"
row-key="id"
@confirm="handleCaiJISelectConfirm"
:query-params="mergedQueryParams"
:selection-type="'single'"
:default-selected-keys="CJIds"
>
<!-- 使用 header 插槽插入查询表单 -->
<template #header>
<el-form ref="searchFormRef" :model="searchParams" :inline="true" >
<el-form-item label="设备编号" prop="deviceCode">
<el-input v-model="searchParams.deviceCode" placeholder="请输入编号" clearable />
</el-form-item>
<el-form-item label="设备名称" prop="deviceName">
<el-input v-model="searchParams.deviceName" placeholder="请输入名称" clearable />
</el-form-item>
<el-form-item>
<el-button type="primary" @click="handleCJSearch">{{ t('FactoryModeling.ProductInformation.searchButtonText') }}</el-button>
<el-button @click="resetCJSearch">{{ t('FactoryModeling.ProductInformation.resetButtonText') }}</el-button>
</el-form-item>
</el-form>
</template>
</TableSelectDialog>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { DICT_TYPE, getStrDictOptions } from '@/utils/dict' import { DICT_TYPE, getStrDictOptions } from '@/utils/dict'
@ -142,13 +195,14 @@ import { defaultProps, handleTree } from '@/utils/tree'
import {MachineComponentApi} from "@/api/mes/machine"; import {MachineComponentApi} from "@/api/mes/machine";
import {DeviceLedgerApi, DeviceLedgerVO} from "@/api/mes/deviceledger"; import {DeviceLedgerApi, DeviceLedgerVO} from "@/api/mes/deviceledger";
import { DeviceApi,DeviceVO } from '@/api/iot/device' import { DeviceApi,DeviceVO } from '@/api/iot/device'
import TableSelectDialog from '@/components/TableSelectDialog/TableSelectDialog.vue'
/** 产线工位 表单 */ /** 产线工位 表单 */
defineOptions({ name: 'OrganizationForm' }) defineOptions({ name: 'OrganizationForm' })
const loading = ref(true)
const { t } = useI18n() // const { t } = useI18n() //
const message = useMessage() // const message = useMessage() //
const deviceSelectDialogRef = ref(false)
const caiJiSelectDialogRef = ref(false)
const dvList = ref<DeviceVO[]>([]) // const dvList = ref<DeviceVO[]>([]) //
const deviceList = ref<DeviceLedgerVO[]>([]) // const deviceList = ref<DeviceLedgerVO[]>([]) //
const dialogVisible = ref(false) // const dialogVisible = ref(false) //
@ -179,22 +233,70 @@ const formRules = reactive({
parentId: [{ required: true, message: t('FactoryModeling.FactoryStructure.validatorParentRequired'), trigger: 'blur' }], parentId: [{ required: true, message: t('FactoryModeling.FactoryStructure.validatorParentRequired'), trigger: 'blur' }],
orgClass: [{ required: true, message: t('FactoryModeling.FactoryStructure.validatorOrgClassRequired'), trigger: 'blur' }] orgClass: [{ required: true, message: t('FactoryModeling.FactoryStructure.validatorOrgClassRequired'), trigger: 'blur' }]
}) })
const itemList = ref<DeviceLedgerVO[]>([])
const CJList = ref<DeviceVO[]>([]) //
const mergedQueryParams = computed(() => ({ ...searchParams }))
const formRef = ref() // Ref const formRef = ref() // Ref
const organizationTree = ref() // const organizationTree = ref() //
const deviceColumns = [
{ label: '设备编号', prop: 'deviceCode', minWidth: 140 },
{ label: '设备名称', prop: 'deviceName', minWidth: 160 },
{ label: '设备型号', prop: 'deviceModel', minWidth: 140 },
{ label: '所属车间', prop: 'workshop', minWidth: 140 }
]
const caiJiColumns = [
{ label: '设备编号', prop: 'deviceCode', minWidth: 140 },
{ label: '设备名称', prop: 'deviceName', minWidth: 160 },
]
// 1.
const searchParams = reactive({
deviceCode: undefined,
deviceName: undefined,
})
const handleSearch = () => {
//
deviceSelectDialogRef.value?.reload?.()
}
const searchFormRef = ref()
const resetSearch = () => {
searchFormRef.value?.resetFields()
handleSearch()
}
const handleCJSearch = () => {
//
caiJiSelectDialogRef.value?.reload?.()
}
const searchCJFormRef = ref()
const resetCJSearch = () => {
searchFormRef.value?.resetFields()
handleCJSearch()
}
/** 打开弹窗 */ /** 打开弹窗 */
const open = async (type: string, id?: number) => { const open = async (type: string, id?: number) => {
dialogVisible.value = true dialogVisible.value = true
dialogTitle.value = t('action.' + type) dialogTitle.value = t('action.' + type)
formType.value = type formType.value = type
resetForm() resetForm()
initSelectedItems()
// //
if (id) { if (id) {
formLoading.value = true formLoading.value = true
try { try {
formData.value = await OrganizationApi.getOrganization(id) formData.value = await OrganizationApi.getOrganization(id)
ids.value=formData.value.machineId != undefined
? formData.value.machineId.toString().split(",").map(Number)
: []
CJIds.value=formData.value.dvId!=undefined?formData.value.dvId.toString().split(",").map(Number):[]
} finally { } finally {
formLoading.value = false formLoading.value = false
} }
}else{
ids.value=[]
CJIds.value=[]
} }
await getOrganizationTree() await getOrganizationTree()
if (type == 'create' || typeof formData.value.machineId != 'number') { if (type == 'create' || typeof formData.value.machineId != 'number') {
@ -283,8 +385,115 @@ const getMachineComponentTree = async () => {
root.children = handleTree(data, 'id', 'parentId') root.children = handleTree(data, 'id', 'parentId')
machineComponentTree.value.push(root) machineComponentTree.value.push(root)
} }
const ids = ref([])
const CJIds = ref([])
const displayItemDevice = computed( () => {
if (!ids.value.length)return ''
if (!itemList.value.length) {
return formData.value.machineId ? String(formData.value.machineId) : ''
}
const map = new Map(itemList.value.map((item) => [item.id, item.deviceName]))
const names = ids.value
.map((id) => map.get(id))
.filter((name) => name)
return names.join(',')
})
const dvIdItemDevice = computed( () => {
if (!CJIds.value.length)return ''
if (!CJList.value.length) {
return formData.value.dvId ? String(formData.value.dvId) : ''
}
const map = new Map(CJList.value.map((item) => [item.id, item.deviceName]))
const names = CJIds.value
.map((id) => map.get(id))
.filter((name) => name)
return names.join(',')
})
const fetchDeviceLedgerPage = (params: Record<string, any>) => {
return DeviceLedgerApi.getDeviceLedgerPage({
...params,
})
}
const fetchCaiJILedgerPage = (params: Record<string, any>) => {
return DeviceApi.getAvailableListPage({
...params,
})
}
const selectedDeviceRows = ref<any[]>([])
const selectedCaiJiRows = ref<any[]>([])
/*打开关联设备确认*/
const handleDeviceSelectConfirm = (payload: { ids: (number | string)[]; rows: any[] }) => {
formData.value.devices = payload.rows
.map((item) => {
const id = Number(item.id)
if (!Number.isFinite(id)) return undefined
return {
id,
name: item.deviceName || item.name || item.code || `设备ID:${id}`
}
})
.filter((item): item is { id: number; name: string } => Boolean(item))
selectedDeviceRows.value = payload.rows
formData.value.machineId = payload.ids.join(',')
ids.value = payload.ids.map((id) => Number(id))
}
/*打开关联设备*/
const openCriticalComponentDialog = async () => {
searchParams.deviceCode=''
searchParams.deviceName=''
const rows = selectedDeviceRows.value.map((item) => ({ ...item, id: Number(item.id) }))
deviceSelectDialogRef.value?.open(rows)
let initIds= formData.value.machineId!=undefined?formData.value.machineId.toString().split(","):[]
ids.value=initIds.map((id) => Number(id))
}
/*打开采集设备确认*/
const handleCaiJISelectConfirm = (payload: { ids: (number | string)[]; rows: any[] }) => {
formData.value.devices = payload.rows
.map((item) => {
const id = Number(item.id)
if (!Number.isFinite(id)) return undefined
return {
id,
name: item.deviceName || item.name || item.code || `设备ID:${id}`
}
})
.filter((item): item is { id: number; name: string } => Boolean(item))
selectedCaiJiRows.value = payload.rows
formData.value.dvId = payload.ids.join(',')
CJIds.value = payload.ids.map((id) => Number(id))
}
/*打开采集设备*/
const openCaijiComponentDialog = async () => {
searchParams.deviceCode=''
searchParams.deviceName=''
const rows = selectedCaiJiRows.value.map((item) => ({ ...item, id: Number(item.id) }))
caiJiSelectDialogRef.value?.open(rows)
let initIds= formData.value.dvId!=undefined?formData.value.dvId.toString().split(","):[]
CJIds.value=initIds.map((id) => Number(id))
}
const initSelectedItems = async () => {
if (!itemList.value.length) {
loading.value = true
try {
itemList.value = await DeviceLedgerApi.getDeviceLedgerList()
} finally {
loading.value = false
}
}
if (!CJList.value.length) {
loading.value = true
try {
CJList.value = await DeviceApi.getAvailableList()
} finally {
loading.value = false
}
}
}
/** 初始化 **/ /** 初始化 **/
onMounted(async () => { onMounted(async () => {
//console.log("ssss") //console.log("ssss")

@ -34,7 +34,7 @@
</el-form-item> </el-form-item>
<el-form-item :label="t('MoldManagement.MoldInspectionPlan.subjectName')" prop="subjectIds"> <el-form-item :label="t('MoldManagement.MoldInspectionPlan.subjectName')" prop="subjectIds">
<el-select <!-- <el-select
v-model="formData.subjectIds" v-model="formData.subjectIds"
multiple multiple
filterable filterable
@ -43,7 +43,10 @@
class="!w-full" class="!w-full"
> >
<el-option v-for="item in subjectOptions" :key="item.id" :label="item.subjectName" :value="item.id" /> <el-option v-for="item in subjectOptions" :key="item.id" :label="item.subjectName" :value="item.id" />
</el-select> </el-select>-->
<el-input :model-value="displayItemDevice" readonly clearable class="device-ledger-selection-input"
:placeholder="t('MoldManagement.MoldInspectionPlan.placeholderSubjectSelect')"
@click="openCriticalComponentDialog" />
</el-form-item> </el-form-item>
</el-form> </el-form>
@ -52,13 +55,40 @@
<el-button @click="dialogVisible = false">{{ t('common.cancel') }}</el-button> <el-button @click="dialogVisible = false">{{ t('common.cancel') }}</el-button>
</template> </template>
</Dialog> </Dialog>
<TableSelectDialog
ref="deviceSelectDialogRef"
title="选择设备"
:columns="deviceColumns"
:fetch-api="fetchDeviceLedgerPage"
row-key="id"
@confirm="handleDeviceSelectConfirm"
:query-params="mergedQueryParams"
:default-selected-keys="ids"
>
<!-- 使用 header 插槽插入查询表单 -->
<template #header>
<el-form ref="searchFormRef" :model="searchParams" :inline="true" >
<el-form-item label="设备编号" prop="deviceCode">
<el-input v-model="searchParams.deviceCode" placeholder="请输入编号" clearable />
</el-form-item>
<el-form-item label="设备名称" prop="deviceName">
<el-input v-model="searchParams.deviceName" placeholder="请输入名称" clearable />
</el-form-item>
<el-form-item>
<el-button type="primary" @click="handleSearch">{{ t('FactoryModeling.ProductInformation.searchButtonText') }}</el-button>
<el-button @click="resetSearch">{{ t('FactoryModeling.ProductInformation.resetButtonText') }}</el-button>
</el-form-item>
</el-form>
</template>
</TableSelectDialog>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import type { FormRules } from 'element-plus' import type { FormRules } from 'element-plus'
import { DvSubjectApi, DvSubjectVO } from '@/api/mold/inspectionItems' import { DvSubjectApi, DvSubjectVO } from '@/api/mold/inspectionItems'
import { PlanMaintenanceApi, PlanMaintenanceVO } from '@/api/mold/planmaintenance' import { PlanMaintenanceApi, PlanMaintenanceVO } from '@/api/mold/planmaintenance'
import {DeviceLedgerApi, DeviceLedgerVO} from "@/api/mes/deviceledger";
import TableSelectDialog from '@/components/TableSelectDialog/TableSelectDialog.vue'
defineOptions({ name: 'MoldInspectionPlanForm' }) defineOptions({ name: 'MoldInspectionPlanForm' })
const { t } = useI18n() const { t } = useI18n()
@ -74,6 +104,7 @@ const ensureSubjectOptionsLoaded = async () => {
if (subjectOptions.value.length) return if (subjectOptions.value.length) return
const res = await DvSubjectApi.getMoldSubjectAllList() const res = await DvSubjectApi.getMoldSubjectAllList()
const list = Array.isArray(res) ? res : res?.list const list = Array.isArray(res) ? res : res?.list
itemList.value = (list ?? []) as DvSubjectVO[]
subjectOptions.value = (list ?? []) as DvSubjectVO[] subjectOptions.value = (list ?? []) as DvSubjectVO[]
} }
@ -97,7 +128,94 @@ const parseIds = (value: any): Array<number | string> => {
}) })
.filter((v): v is number | string => v !== undefined) .filter((v): v is number | string => v !== undefined)
} }
const ids = ref([])
const itemList = ref<DvSubjectVO[]>([])
const selectedDeviceRows = ref<any[]>([])
const deviceSelectDialogRef = ref(false)
const mergedQueryParams = computed(() => ({ ...searchParams }))
const deviceColumns = [
{ label: '项目编码', prop: 'subjectCode', minWidth: 140 },
{ label: '项目名称', prop: 'subjectName', minWidth: 160 },
{ label: '项目类型', prop: 'subjectType', minWidth: 140 },
{ label: '项目内容', prop: 'subjectContent', minWidth: 140 }
]
const fetchDeviceLedgerPage = async (params: Record<string, any>) => {
const res = await DvSubjectApi.getDvSubjectPage({
...params,
})
const list = res.list || []
//
const selectedMap = new Map(
selectedDeviceRows.value.map((item) => [item.id, item])
)
return {
...res,
list: list.map((item) => ({
...item,
...selectedMap.get(item.id)
}))
}
}
// 1.
const searchParams = reactive({
subjectCode: undefined,
subjectName: undefined,
})
const displayItemDevice = computed( () => {
if (!ids.value.length)return ''
if (!itemList.value.length) {
return formData.value.subjectIds ? String(formData.value.subjectIds) : ''
}
const map = new Map(itemList.value.map((item) => [item.id, item.subjectName]))
const names = ids.value
.map((id) => map.get(id))
.filter((name) => name)
return names.join(',')
})
const openCriticalComponentDialog = async () => {
searchParams.subjectCode=''
searchParams.subjectName=''
const rows = selectedDeviceRows.value.length
//deviceSelectDialogRef.value?.open(rows)
let initIds= formData.value.subjectIds!=undefined?formData.value.subjectIds.toString().split(","):[]
deviceSelectDialogRef.value?.open([], {
defaultSelectedKeys: initIds
})
ids.value=initIds.map((id) => Number(id))
}
const handleDeviceSelectConfirm = (payload: { ids: (number | string)[]; rows: any[] }) => {
formData.value.subjectIds = payload.rows
.map((item) => {
const id = Number(item.id)
if (!Number.isFinite(id)) return undefined
return {
id,
name: item.subjectName || item.name || item.code || `设备ID:${id}`
}
})
.filter((item): item is { id: number; name: string } => Boolean(item))
selectedDeviceRows.value = payload.rows
formData.value.subjectIds = payload.ids.join(',')
ids.value = payload.ids.map((id) => Number(id))
}
const handleSearch = () => {
//
deviceSelectDialogRef.value?.reload?.()
}
const searchFormRef = ref()
const resetSearch = () => {
searchFormRef.value?.resetFields()
handleSearch()
}
const initFormData = () => ({ const initFormData = () => ({
id: undefined as PlanMaintenanceVO['id'], id: undefined as PlanMaintenanceVO['id'],
planName: '' as string, planName: '' as string,
@ -141,6 +259,9 @@ const open = async (type: 'create' | 'update', row?: Partial<PlanMaintenanceVO>)
description: (row.description as any) ?? '', description: (row.description as any) ?? '',
subjectIds: parseIds((row as any).subjectIds ?? (row as any).subjectIdS) subjectIds: parseIds((row as any).subjectIds ?? (row as any).subjectIdS)
} }
ids.value=parseIds((row as any).subjectIds ?? (row as any).subjectIdS)
}else{
ids.value=[]
} }
} }

Loading…
Cancel
Save