add iot and machine

main
chenshuichuan 2 years ago
parent ee7ea361f3
commit 6aabd2586f

@ -0,0 +1,92 @@
import request from '@/config/axios'
// 物联设备 VO
export interface DeviceVO {
id: number // ID
deviceConfigId: string // 设备配置id
deviceCode: string // 设备编号
deviceName: string // 设备名称
deviceType: string // 设备类型
siemensSeries: string // Siemens系列(S7-300、S7-1500)
siemensConnectParam: string // 连接参数(波特率,数据位,停止位,校验位 例如960081N
readCronType: string // 读取任务方式(0无1有)
readRepeatValue: number // 读取任务时间间隔
readRepeatUnit: string // 读取任务时间间隔单位
readCron: string // 读取任务时间表达式
writeCronType: string // 写入任务时间间隔
writeRepeatValue: number // 写入任务时间间隔
writeRepeatUnit: string // 写入任务时间间隔单位
writeCron: string // 写入任务时间表达式
localPersistent: string // 是否持久化(0不持久化1持久化)
uploadRate: string // 上传方式(1实时2自定义)
rateCount: number // 上传频率
modbusProtocol: string // modbus协议类型(serial-rtu)
modbusPattern: string // modbus模式(client)
portName: string // modbus串口号
modbusConnectParam: string // 连接参数(波特率,数据位,停止位,校验位 例如960081N
modbusReadAddrGap: string // 读地址是否连续(0否1是)
isUpload: string // 是否已下发(0下,1没下)
gatewayId: number // 网关id
orgId: number // 组织设备id
remark: string // 备注
isEnable: boolean // 是否启用
}
// 物联设备 API
export const DeviceApi = {
// 查询物联设备分页
getDevicePage: async (params: any) => {
return await request.get({ url: `/iot/device/page`, params })
},
// 查询物联设备详情
getDevice: async (id: number) => {
return await request.get({ url: `/iot/device/get?id=` + id })
},
// 新增物联设备
createDevice: async (data: DeviceVO) => {
return await request.post({ url: `/iot/device/create`, data })
},
// 修改物联设备
updateDevice: async (data: DeviceVO) => {
return await request.put({ url: `/iot/device/update`, data })
},
// 删除物联设备
deleteDevice: async (id: number) => {
return await request.delete({ url: `/iot/device/delete?id=` + id })
},
// 导出物联设备 Excel
exportDevice: async (params) => {
return await request.download({ url: `/iot/device/export-excel`, params })
},
// ==================== 子表(设备属性) ====================
// 获得设备属性分页
getDeviceAttributePage: async (params) => {
return await request.get({ url: `/iot/device/device-attribute/page`, params })
},
// 新增设备属性
createDeviceAttribute: async (data) => {
return await request.post({ url: `/iot/device/device-attribute/create`, data })
},
// 修改设备属性
updateDeviceAttribute: async (data) => {
return await request.put({ url: `/iot/device/device-attribute/update`, data })
},
// 删除设备属性
deleteDeviceAttribute: async (id: number) => {
return await request.delete({ url: `/iot/device/device-attribute/delete?id=` + id })
},
// 获得设备属性
getDeviceAttribute: async (id: number) => {
return await request.get({ url: `/iot/device/device-attribute/get?id=` + id })
},
}

@ -0,0 +1,72 @@
import request from '@/config/axios'
// 计算公式 VO
export interface FormulaVO {
id: number // ID
name: string // 公式名称
formulaCode: string // 公式编号
formula: string // 公式
resultType: string // 结果类型(产量,电耗,浆耗,水耗,气耗,参数)
machineId: number // 机台ID
remark: string // 备注
isEnable: boolean // 是否启用
}
// 计算公式 API
export const FormulaApi = {
// 查询计算公式分页
getFormulaPage: async (params: any) => {
return await request.get({ url: `/iot/formula/page`, params })
},
// 查询计算公式详情
getFormula: async (id: number) => {
return await request.get({ url: `/iot/formula/get?id=` + id })
},
// 新增计算公式
createFormula: async (data: FormulaVO) => {
return await request.post({ url: `/iot/formula/create`, data })
},
// 修改计算公式
updateFormula: async (data: FormulaVO) => {
return await request.put({ url: `/iot/formula/update`, data })
},
// 删除计算公式
deleteFormula: async (id: number) => {
return await request.delete({ url: `/iot/formula/delete?id=` + id })
},
// 导出计算公式 Excel
exportFormula: async (params) => {
return await request.download({ url: `/iot/formula/export-excel`, params })
},
// ==================== 子表(计算公式明细) ====================
// 获得计算公式明细分页
getFormulaDetailPage: async (params) => {
return await request.get({ url: `/iot/formula/formula-detail/page`, params })
},
// 新增计算公式明细
createFormulaDetail: async (data) => {
return await request.post({ url: `/iot/formula/formula-detail/create`, data })
},
// 修改计算公式明细
updateFormulaDetail: async (data) => {
return await request.put({ url: `/iot/formula/formula-detail/update`, data })
},
// 删除计算公式明细
deleteFormulaDetail: async (id: number) => {
return await request.delete({ url: `/iot/formula/formula-detail/delete?id=` + id })
},
// 获得计算公式明细
getFormulaDetail: async (id: number) => {
return await request.get({ url: `/iot/formula/formula-detail/get?id=` + id })
},
}

@ -0,0 +1,74 @@
import request from '@/config/axios'
// 网关 VO
export interface GatewayVO {
id: number // ID
adminIp: string // 管理地址
username: string // 管理账号
password: string // 管理密码
gatewayName: string // 网关名字
remark: string // 备注
isEnable: boolean // 是否启用
gatewayCode: string // 网关编码
gatewayStatus: string // 网关状态
topic: string // 订阅主题
}
// 网关 API
export const GatewayApi = {
// 查询网关分页
getGatewayPage: async (params: any) => {
return await request.get({ url: `/iot/gateway/page`, params })
},
// 查询网关详情
getGateway: async (id: number) => {
return await request.get({ url: `/iot/gateway/get?id=` + id })
},
// 新增网关
createGateway: async (data: GatewayVO) => {
return await request.post({ url: `/iot/gateway/create`, data })
},
// 修改网关
updateGateway: async (data: GatewayVO) => {
return await request.put({ url: `/iot/gateway/update`, data })
},
// 删除网关
deleteGateway: async (id: number) => {
return await request.delete({ url: `/iot/gateway/delete?id=` + id })
},
// 导出网关 Excel
exportGateway: async (params) => {
return await request.download({ url: `/iot/gateway/export-excel`, params })
},
// ==================== 子表(物联设备) ====================
// 获得物联设备分页
getDevicePage: async (params) => {
return await request.get({ url: `/iot/gateway/device/page`, params })
},
// 新增物联设备
createDevice: async (data) => {
return await request.post({ url: `/iot/gateway/device/create`, data })
},
// 修改物联设备
updateDevice: async (data) => {
return await request.put({ url: `/iot/gateway/device/update`, data })
},
// 删除物联设备
deleteDevice: async (id: number) => {
return await request.delete({ url: `/iot/gateway/device/delete?id=` + id })
},
// 获得物联设备
getDevice: async (id: number) => {
return await request.get({ url: `/iot/gateway/device/get?id=` + id })
},
}

@ -0,0 +1,48 @@
import request from '@/config/axios'
// IOT组织 VO
export interface OrganizationVO {
id: number // 组织id
sort: number // 显示顺序
workerUserId: number // 负责人/工人
orgId: number // 绑定工位id
name: string // 组织名称
parentId: number // 父组织id
status: number // 组织状态
deviceType: string // 设备类型
orgClass: string // 组织等级
machineType: string // 机台类型
}
// IOT组织 API
export const OrganizationApi = {
// 查询IOT组织列表
getOrganizationList: async (params) => {
return await request.get({ url: `/iot/organization/list`, params })
},
// 查询IOT组织详情
getOrganization: async (id: number) => {
return await request.get({ url: `/iot/organization/get?id=` + id })
},
// 新增IOT组织
createOrganization: async (data: OrganizationVO) => {
return await request.post({ url: `/iot/organization/create`, data })
},
// 修改IOT组织
updateOrganization: async (data: OrganizationVO) => {
return await request.put({ url: `/iot/organization/update`, data })
},
// 删除IOT组织
deleteOrganization: async (id: number) => {
return await request.delete({ url: `/iot/organization/delete?id=` + id })
},
// 导出IOT组织 Excel
exportOrganization: async (params) => {
return await request.download({ url: `/iot/organization/export-excel`, params })
},
}

@ -0,0 +1,46 @@
import request from '@/config/axios'
// 物联看板 VO
export interface KanbanVO {
id: number // ID
img: string // 缩略图
remark: string // 备注
isEnable: boolean // 是否启用
code: string // 编码
title: string // 标题
viewUrl: string // 访问地址
tags: string // 标签
}
// 物联看板 API
export const KanbanApi = {
// 查询物联看板分页
getKanbanPage: async (params: any) => {
return await request.get({ url: `/iot/kanban/page`, params })
},
// 查询物联看板详情
getKanban: async (id: number) => {
return await request.get({ url: `/iot/kanban/get?id=` + id })
},
// 新增物联看板
createKanban: async (data: KanbanVO) => {
return await request.post({ url: `/iot/kanban/create`, data })
},
// 修改物联看板
updateKanban: async (data: KanbanVO) => {
return await request.put({ url: `/iot/kanban/update`, data })
},
// 删除物联看板
deleteKanban: async (id: number) => {
return await request.delete({ url: `/iot/kanban/delete?id=` + id })
},
// 导出物联看板 Excel
exportKanban: async (params) => {
return await request.download({ url: `/iot/kanban/export-excel`, params })
},
}

@ -0,0 +1,52 @@
import request from '@/config/axios'
// 机台 VO
export interface MachineComponentVO {
id: number // 装备id
name: string // 装备名称
parentId: number // 父id
sort: number // 显示顺序
orgId: number // 组织机台ID
serialCode: string // 装备SN号
outgoingTime: Date // 出厂日期
outgoingReport: string // 出厂报告
position: string // 位置
standard: string // 规格
remark: string // 备注
status: number // 状态
componentType: number // 组织类型
machineType: string // 机台类型
}
// 机台 API
export const MachineComponentApi = {
// 查询机台列表
getMachineComponentList: async (params) => {
return await request.get({ url: `/mes/machine-component/list`, params })
},
// 查询机台详情
getMachineComponent: async (id: number) => {
return await request.get({ url: `/mes/machine-component/get?id=` + id })
},
// 新增机台
createMachineComponent: async (data: MachineComponentVO) => {
return await request.post({ url: `/mes/machine-component/create`, data })
},
// 修改机台
updateMachineComponent: async (data: MachineComponentVO) => {
return await request.put({ url: `/mes/machine-component/update`, data })
},
// 删除机台
deleteMachineComponent: async (id: number) => {
return await request.delete({ url: `/mes/machine-component/delete?id=` + id })
},
// 导出机台 Excel
exportMachineComponent: async (params) => {
return await request.download({ url: `/mes/machine-component/export-excel`, params })
},
}

@ -237,5 +237,23 @@ export enum DICT_TYPE {
MES_RECORD_STATUS = "mes_record_status",
MES_GROUP_TYPE = "mes_group_type",
MES_WORK_TEAM_USER_ROLE = "mes_work_team_user_role",
MES_PRODUCE_ITEM_REQUISITION = "mes_produce_item_requisition"
MES_PRODUCE_ITEM_REQUISITION = "mes_produce_item_requisition",
MES_DATA_TYPE = "mes_data_type",
MES_MACHINE_STATUS = "mes_machine_status",
MES_MACHINE_TYPE = "mes_machine_type",
//====iot
IOT_SIEMENS_TYPE = "iot_siemens_type",
IOT_MODBUS_TYPE = "iot_modbus_type",
IOT_MODBUS_MOLD = "iot_modbus_mold",
IOT_MODBUS_PORT = "iot_modbus_port",
IOT_1_OR_0 = "iot_1_or_0",
IOT_DEVICE_DATA_UNIT = "iot_dev_data_unit",
IOT_DEVICE_TYPE = "iot_device_type",
IOT_ORG_CLASS = "iot_org_class",
IOT_DEVICE_UPLOADING_TYPE = "iot_device_uploading_type",
IOT_FORMULA_VAR_TYPE = "iot_formula_var_type",
IOT_FORMULA_CAL_RANG = "iot_formula_cal_rang",
IOT_GATEWAY_STATUS = "iot_gateway_status",
IOT_DEVICE_DATA_TRANSFER_TYPE = "iot_device_data_transfer_type",
IOT_DEVICE_DATA_TYPE = "iot_device_data_type",
}

@ -0,0 +1,321 @@
<template>
<Dialog :title="dialogTitle" v-model="dialogVisible">
<el-form
ref="formRef"
:model="formData"
:rules="formRules"
label-width="100px"
v-loading="formLoading"
>
<el-form-item label="设备配置id" prop="deviceConfigId">
<el-input v-model="formData.deviceConfigId" placeholder="请输入设备配置id" />
</el-form-item>
<el-form-item label="设备编号" prop="deviceCode">
<el-input v-model="formData.deviceCode" placeholder="请输入设备编号" />
</el-form-item>
<el-form-item label="设备名称" prop="deviceName">
<el-input v-model="formData.deviceName" placeholder="请输入设备名称" />
</el-form-item>
<el-form-item label="设备类型" prop="deviceType">
<el-radio-group v-model="formData.deviceType">
<el-radio
v-for="dict in getStrDictOptions(DICT_TYPE.IOT_DEVICE_TYPE)"
:key="dict.value"
:label="dict.value"
>
{{ dict.label }}
</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="Siemens系列" prop="siemensSeries">
<el-radio-group v-model="formData.siemensSeries">
<el-radio
v-for="dict in getStrDictOptions(DICT_TYPE.IOT_SIEMENS_TYPE)"
:key="dict.value"
:label="dict.value"
>
{{ dict.label }}
</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="连接参数" prop="siemensConnectParam">
<el-input v-model="formData.siemensConnectParam" placeholder="请输入连接参数(波特率,数据位,停止位,校验位 例如960081N" />
</el-form-item>
<el-form-item label="读取方式" prop="readCronType">
<el-input v-model="formData.readCronType" placeholder="请输入读取方式" />
</el-form-item>
<el-form-item label="读取时间间隔" prop="readRepeatValue">
<el-input v-model="formData.readRepeatValue" placeholder="请输入读取时间间隔" />
</el-form-item>
<el-form-item label="读取时间间隔单位" prop="readRepeatUnit">
<el-radio-group v-model="formData.readRepeatUnit">
<el-radio
v-for="dict in getStrDictOptions(DICT_TYPE.IOT_DEVICE_DATA_UNIT)"
:key="dict.value"
:label="dict.value"
>
{{ dict.label }}
</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="读取时间表达式" prop="readCron">
<el-input v-model="formData.readCron" placeholder="请输入读取时间表达式" />
</el-form-item>
<el-form-item label="写入时间间隔" prop="writeCronType">
<el-input v-model="formData.writeCronType" placeholder="请输入写入方式" />
</el-form-item>
<el-form-item label="写入时间间隔" prop="writeRepeatValue">
<el-input v-model="formData.writeRepeatValue" placeholder="请输入写入时间间隔" />
</el-form-item>
<el-form-item label="写入时间间隔单位" prop="writeRepeatUnit">
<el-radio-group v-model="formData.writeRepeatUnit">
<el-radio
v-for="dict in getStrDictOptions(DICT_TYPE.IOT_DEVICE_DATA_UNIT)"
:key="dict.value"
:label="dict.value"
>
{{ dict.label }}
</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="写入时间表达式" prop="writeCron">
<el-input v-model="formData.writeCron" placeholder="请输入写入时间表达式" />
</el-form-item>
<el-form-item label="是否持久化" prop="localPersistent">
<el-radio-group v-model="formData.localPersistent">
<el-radio
v-for="dict in getStrDictOptions(DICT_TYPE.IOT_1_OR_0)"
:key="dict.value"
:label="dict.value"
>
{{ dict.label }}
</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="上传方式" prop="uploadRate">
<el-radio-group v-model="formData.uploadRate">
<el-radio
v-for="dict in getStrDictOptions(DICT_TYPE.IOT_DEVICE_UPLOADING_TYPE)"
:key="dict.value"
:label="dict.value"
>
{{ dict.label }}
</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="上传频率" prop="rateCount">
<el-input v-model="formData.rateCount" placeholder="请输入上传频率" />
</el-form-item>
<el-form-item label="modbus协议类型" prop="modbusProtocol">
<el-radio-group v-model="formData.modbusProtocol">
<el-radio
v-for="dict in getStrDictOptions(DICT_TYPE.IOT_MODBUS_TYPE)"
:key="dict.value"
:label="dict.value"
>
{{ dict.label }}
</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="modbus模式" prop="modbusPattern">
<el-radio-group v-model="formData.modbusPattern">
<el-radio
v-for="dict in getStrDictOptions(DICT_TYPE.IOT_MODBUS_MOLD)"
:key="dict.value"
:label="dict.value"
>
{{ dict.label }}
</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="modbus串口号" prop="portName">
<el-radio-group v-model="formData.portName">
<el-radio
v-for="dict in getStrDictOptions(DICT_TYPE.IOT_MODBUS_PORT)"
:key="dict.value"
:label="dict.value"
>
{{ dict.label }}
</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="连接参数" prop="modbusConnectParam">
<el-input v-model="formData.modbusConnectParam" placeholder="请输入连接参数(波特率,数据位,停止位,校验位 例如960081N" />
</el-form-item>
<el-form-item label="读地址是否连续" prop="modbusReadAddrGap">
<el-radio-group v-model="formData.modbusReadAddrGap">
<el-radio
v-for="dict in getStrDictOptions(DICT_TYPE.IOT_1_OR_0)"
:key="dict.value"
:label="dict.value"
>
{{ dict.label }}
</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="是否已下发" prop="isUpload">
<el-radio-group v-model="formData.isUpload">
<el-radio
v-for="dict in getStrDictOptions(DICT_TYPE.IOT_1_OR_0)"
:key="dict.value"
:label="dict.value"
>
{{ dict.label }}
</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="网关id" prop="gatewayId">
<el-input v-model="formData.gatewayId" placeholder="请输入网关id" />
</el-form-item>
<el-form-item label="组织设备id" prop="orgId">
<el-input v-model="formData.orgId" placeholder="请输入组织设备id" />
</el-form-item>
<el-form-item label="备注" prop="remark">
<el-input v-model="formData.remark" placeholder="请输入备注" />
</el-form-item>
<el-form-item label="是否启用" prop="isEnable">
<el-radio-group v-model="formData.isEnable">
<el-radio
v-for="dict in getBoolDictOptions(DICT_TYPE.INFRA_BOOLEAN_STRING)"
:key="dict.value"
:label="dict.value"
>
{{ dict.label }}
</el-radio>
</el-radio-group>
</el-form-item>
</el-form>
<template #footer>
<el-button @click="submitForm" type="primary" :disabled="formLoading"> </el-button>
<el-button @click="dialogVisible = false"> </el-button>
</template>
</Dialog>
</template>
<script setup lang="ts">
import {getStrDictOptions, DICT_TYPE, getBoolDictOptions} from '@/utils/dict'
import { DeviceApi, DeviceVO } from '@/api/iot/device'
/** 物联设备 表单 */
defineOptions({ name: 'DeviceForm' })
const { t } = useI18n() //
const message = useMessage() //
const dialogVisible = ref(false) //
const dialogTitle = ref('') //
const formLoading = ref(false) // 12
const formType = ref('') // create - update -
const formData = ref({
id: undefined,
deviceConfigId: undefined,
deviceCode: undefined,
deviceName: undefined,
deviceType: undefined,
siemensSeries: undefined,
siemensConnectParam: undefined,
readCronType: undefined,
readRepeatValue: undefined,
readRepeatUnit: undefined,
readCron: undefined,
writeCronType: undefined,
writeRepeatValue: undefined,
writeRepeatUnit: undefined,
writeCron: undefined,
localPersistent: undefined,
uploadRate: undefined,
rateCount: undefined,
modbusProtocol: undefined,
modbusPattern: undefined,
portName: undefined,
modbusConnectParam: undefined,
modbusReadAddrGap: undefined,
isUpload: undefined,
gatewayId: undefined,
orgId: undefined,
remark: undefined,
isEnable: undefined,
})
const formRules = reactive({
gatewayId: [{ required: true, message: '网关id不能为空', trigger: 'blur' }],
orgId: [{ required: true, message: '组织设备id不能为空', trigger: 'blur' }],
isEnable: [{ required: true, message: '是否启用不能为空', trigger: 'blur' }],
})
const formRef = ref() // Ref
/** 打开弹窗 */
const open = async (type: string, id?: number) => {
dialogVisible.value = true
dialogTitle.value = t('action.' + type)
formType.value = type
resetForm()
//
if (id) {
formLoading.value = true
try {
formData.value = await DeviceApi.getDevice(id)
} finally {
formLoading.value = false
}
}
}
defineExpose({ open }) // open
/** 提交表单 */
const emit = defineEmits(['success']) // success
const submitForm = async () => {
//
await formRef.value.validate()
//
formLoading.value = true
try {
const data = formData.value as unknown as DeviceVO
if (formType.value === 'create') {
await DeviceApi.createDevice(data)
message.success(t('common.createSuccess'))
} else {
await DeviceApi.updateDevice(data)
message.success(t('common.updateSuccess'))
}
dialogVisible.value = false
//
emit('success')
} finally {
formLoading.value = false
}
}
/** 重置表单 */
const resetForm = () => {
formData.value = {
id: undefined,
deviceConfigId: undefined,
deviceCode: undefined,
deviceName: undefined,
deviceType: undefined,
siemensSeries: undefined,
siemensConnectParam: undefined,
readCronType: undefined,
readRepeatValue: undefined,
readRepeatUnit: undefined,
readCron: undefined,
writeCronType: undefined,
writeRepeatValue: undefined,
writeRepeatUnit: undefined,
writeCron: undefined,
localPersistent: undefined,
uploadRate: undefined,
rateCount: undefined,
modbusProtocol: undefined,
modbusPattern: undefined,
portName: undefined,
modbusConnectParam: undefined,
modbusReadAddrGap: undefined,
isUpload: undefined,
gatewayId: undefined,
orgId: undefined,
remark: undefined,
isEnable: undefined,
}
formRef.value?.resetFields()
}
</script>

@ -0,0 +1,304 @@
<template>
<Dialog :title="dialogTitle" v-model="dialogVisible">
<el-form
ref="formRef"
:model="formData"
:rules="formRules"
label-width="100px"
v-loading="formLoading"
>
<el-form-item label="地址编码" prop="attributeCode">
<el-input v-model="formData.attributeCode" placeholder="请输入地址编码" />
</el-form-item>
<el-form-item label="地址" prop="address">
<el-input v-model="formData.address" placeholder="请输入地址" />
</el-form-item>
<el-form-item label="地址名称" prop="attributeName">
<el-input v-model="formData.attributeName" placeholder="请输入地址名称" />
</el-form-item>
<el-form-item label="地址描述" prop="description">
<el-input v-model="formData.description" placeholder="请输入描述" />
</el-form-item>
<el-form-item label="地址类型" prop="addressType">
<el-input v-model="formData.addressType" placeholder="请输入" />
</el-form-item>
<el-form-item label="地址偏移" prop="addressOffset">
<el-input v-model="formData.addressOffset" placeholder="请输入地址偏移" />
</el-form-item>
<el-form-item label="地址2类型" prop="address2Type">
<el-input v-model="formData.address2Type" placeholder="请输入" />
</el-form-item>
<el-form-item label="地址2偏移" prop="address2Offset">
<el-input v-model="formData.address2Offset" placeholder="请输入地址2偏移" />
</el-form-item>
<el-form-item label="所属组" prop="groupName">
<el-input v-model="formData.groupName" placeholder="请输入所属组" />
</el-form-item>
<el-form-item label="所属组id" prop="groupId">
<el-input v-model="formData.groupId" placeholder="请输入所属组id" />
</el-form-item>
<el-form-item label="安全类别" prop="securityType">
<el-input v-model="formData.securityType" placeholder="请输入安全类别" />
</el-form-item>
<el-form-item label="读写状态" prop="ioStatus">
<el-input v-model="formData.ioStatus" placeholder="请输入读写状态" />
</el-form-item>
<el-form-item label="是否线性换算" prop="isLinearTransfer">
<el-radio-group v-model="formData.isLinearTransfer">
<el-radio
v-for="dict in getStrDictOptions(DICT_TYPE.IOT_1_OR_0)"
:key="dict.value"
:label="dict.value"
>
{{ dict.label }}
</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="数据类型" prop="dataType">
<el-select v-model="formData.dataType" placeholder="请选择数据类型">
<el-option
v-for="dict in getStrDictOptions(DICT_TYPE.IOT_DEVICE_DATA_TYPE)"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
</el-select>
</el-form-item>
<el-form-item label="单位" prop="unit">
<el-input v-model="formData.unit" placeholder="请输入单位" />
</el-form-item>
<el-form-item label="输入最小值" prop="inMinValue">
<el-input v-model="formData.inMinValue" placeholder="请输入输入最小值" />
</el-form-item>
<el-form-item label="输入最大值" prop="inMaxValue">
<el-input v-model="formData.inMaxValue" placeholder="请输入输入最大值" />
</el-form-item>
<el-form-item label="输出最小值" prop="outMinValue">
<el-input v-model="formData.outMinValue" placeholder="请输入输出最小值" />
</el-form-item>
<el-form-item label="输出最大值" prop="outMaxValue">
<el-input v-model="formData.outMaxValue" placeholder="请输入输出最大值" />
</el-form-item>
<el-form-item label="输出数据类型" prop="outDataType">
<el-input v-model="formData.outDataType" placeholder="请输入输出数据类型" />
</el-form-item>
<el-form-item label="精度" prop="siemensFieldPrecision">
<el-input v-model="formData.siemensFieldPrecision" placeholder="请输入精度" />
</el-form-item>
<el-form-item label="站号" prop="modbusSlaveId">
<el-input v-model="formData.modbusSlaveId" placeholder="请输入站号" />
</el-form-item>
<el-form-item label="寄存器地址" prop="modbusFieldAddress">
<el-input v-model="formData.modbusFieldAddress" placeholder="请输入寄存器地址" />
</el-form-item>
<el-form-item label="寄存器类型" prop="modbusAddressType">
<el-input v-model="formData.modbusAddressType" placeholder="请输入寄存器类型" />
</el-form-item>
<el-form-item label="个数" prop="modbusFieldSize">
<el-input v-model="formData.modbusFieldSize" placeholder="请输入个数" />
</el-form-item>
<el-form-item label="缩放因子" prop="modbusFieldPrecision">
<el-input v-model="formData.modbusFieldPrecision" placeholder="请输入缩放因子默认值为1大于0的小数" />
</el-form-item>
<el-form-item label="字节顺序" prop="modbusFieldOrder">
<el-input v-model="formData.modbusFieldOrder" placeholder="请输入字节顺序" />
</el-form-item>
<el-form-item label="mqtt进制类型" prop="sourceDataType">
<el-radio-group v-model="formData.sourceDataType">
<el-radio
v-for="dict in getStrDictOptions(DICT_TYPE.IOT_DEVICE_DATA_TRANSFER_TYPE)"
:key="dict.value"
:label="dict.value"
>
{{ dict.label }}
</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="结果进制类型" prop="transferDataType">
<el-radio-group v-model="formData.transferDataType">
<el-radio
v-for="dict in getStrDictOptions(DICT_TYPE.IOT_DEVICE_DATA_TRANSFER_TYPE)"
:key="dict.value"
:label="dict.value"
>
{{ dict.label }}
</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="系数" prop="factor">
<el-input v-model="formData.factor" placeholder="请输入系数" />
</el-form-item>
<el-form-item label="网关id" prop="gatewayId">
<el-input v-model="formData.gatewayId" placeholder="请输入网关id" />
</el-form-item>
<el-form-item label="组织设备id" prop="orgId">
<el-input v-model="formData.orgId" placeholder="请输入组织设备id" />
</el-form-item>
<el-form-item label="备注" prop="remark">
<el-input v-model="formData.remark" placeholder="请输入备注" />
</el-form-item>
<el-form-item label="是否启用" prop="isEnable">
<el-radio-group v-model="formData.isEnable">
<el-radio
v-for="dict in getBoolDictOptions(DICT_TYPE.INFRA_BOOLEAN_STRING)"
:key="dict.value"
:label="dict.value"
>
{{ dict.label }}
</el-radio>
</el-radio-group>
</el-form-item>
</el-form>
<template #footer>
<el-button @click="submitForm" type="primary" :disabled="formLoading"> </el-button>
<el-button @click="dialogVisible = false"> </el-button>
</template>
</Dialog>
</template>
<script setup lang="ts">
import {getStrDictOptions, DICT_TYPE, getBoolDictOptions} from '@/utils/dict'
import { DeviceApi } from '@/api/iot/device'
const { t } = useI18n() //
const message = useMessage() //
const dialogVisible = ref(false) //
const dialogTitle = ref('') //
const formLoading = ref(false) // 12
const formType = ref('') // create - update -
const formData = ref({
id: undefined,
attributeCode: undefined,
address: undefined,
attributeName: undefined,
description: undefined,
addressType: undefined,
addressOffset: undefined,
address2Type: undefined,
address2Offset: undefined,
groupName: undefined,
groupId: undefined,
securityType: undefined,
ioStatus: undefined,
isLinearTransfer: undefined,
dataType: undefined,
unit: undefined,
inMinValue: undefined,
inMaxValue: undefined,
outMinValue: undefined,
outMaxValue: undefined,
outDataType: undefined,
siemensFieldPrecision: undefined,
modbusSlaveId: undefined,
modbusFieldAddress: undefined,
modbusAddressType: undefined,
modbusFieldSize: undefined,
modbusFieldPrecision: 1,
modbusFieldOrder: undefined,
sourceDataType: undefined,
transferDataType: undefined,
factor: undefined,
gatewayId: undefined,
deviceId: undefined,
orgId: undefined,
remark: undefined,
isEnable: undefined,
})
const formRules = reactive({
attributeCode: [{ required: true, message: '地址编码不能为空', trigger: 'blur' }],
attributeName: [{ required: true, message: '地址名称不能为空', trigger: 'blur' }],
dataType: [{ required: true, message: '数据类型不能为空', trigger: 'blur' }],
gatewayId: [{ required: true, message: '网关id不能为空', trigger: 'blur' }],
deviceId: [{ required: true, message: '设备id不能为空', trigger: 'blur' }],
orgId: [{ required: true, message: '组织设备id不能为空', trigger: 'blur' }],
isEnable: [{ required: true, message: '是否启用不能为空', trigger: 'blur' }],
})
const formRef = ref() // Ref
/** 打开弹窗 */
const open = async (type: string, id?: number, deviceId: number) => {
dialogVisible.value = true
dialogTitle.value = t('action.' + type)
formType.value = type
resetForm()
formData.value.deviceId = deviceId
//
if (id) {
formLoading.value = true
try {
formData.value = await DeviceApi.getDeviceAttribute(id)
} finally {
formLoading.value = false
}
}
}
defineExpose({ open }) // open
/** 提交表单 */
const emit = defineEmits(['success']) // success
const submitForm = async () => {
//
await formRef.value.validate()
//
formLoading.value = true
try {
const data = formData.value
if (formType.value === 'create') {
await DeviceApi.createDeviceAttribute(data)
message.success(t('common.createSuccess'))
} else {
await DeviceApi.updateDeviceAttribute(data)
message.success(t('common.updateSuccess'))
}
dialogVisible.value = false
//
emit('success')
} finally {
formLoading.value = false
}
}
/** 重置表单 */
const resetForm = () => {
formData.value = {
id: undefined,
attributeCode: undefined,
address: undefined,
attributeName: undefined,
description: undefined,
addressType: undefined,
addressOffset: undefined,
address2Type: undefined,
address2Offset: undefined,
groupName: undefined,
groupId: undefined,
securityType: undefined,
ioStatus: undefined,
isLinearTransfer: undefined,
dataType: undefined,
unit: undefined,
inMinValue: undefined,
inMaxValue: undefined,
outMinValue: undefined,
outMaxValue: undefined,
outDataType: undefined,
siemensFieldPrecision: undefined,
modbusSlaveId: undefined,
modbusFieldAddress: undefined,
modbusAddressType: undefined,
modbusFieldSize: undefined,
modbusFieldPrecision: undefined,
modbusFieldOrder: undefined,
sourceDataType: undefined,
transferDataType: undefined,
factor: undefined,
gatewayId: undefined,
deviceId: undefined,
orgId: undefined,
remark: undefined,
isEnable: undefined,
}
formRef.value?.resetFields()
}
</script>

@ -0,0 +1,173 @@
<template>
<!-- 列表 -->
<ContentWrap>
<el-button
type="primary"
plain
@click="openForm('create')"
v-hasPermi="['iot:device:create']"
>
<Icon icon="ep:plus" class="mr-5px" /> 新增
</el-button>
<el-table v-loading="loading" :data="list" :stripe="true" :show-overflow-tooltip="true">
<el-table-column label="ID" align="center" prop="id" />
<el-table-column label="地址编码" align="center" prop="attributeCode" />
<el-table-column label="地址" align="center" prop="address" />
<el-table-column label="地址名称" align="center" prop="attributeName" />
<el-table-column label="地址描述" align="center" prop="description" />
<el-table-column label="地址类型" align="center" prop="addressType" />
<el-table-column label="地址偏移" align="center" prop="addressOffset" />
<el-table-column label="地址2类型" align="center" prop="address2Type" />
<el-table-column label="地址2偏移" align="center" prop="address2Offset" />
<el-table-column label="所属组" align="center" prop="groupName" />
<el-table-column label="所属组id" align="center" prop="groupId" />
<el-table-column label="安全类别" align="center" prop="securityType" />
<el-table-column label="读写状态" align="center" prop="ioStatus" />
<el-table-column label="是否线性换算" align="center" prop="isLinearTransfer">
<template #default="scope">
<dict-tag :type="DICT_TYPE.IOT_1_OR_0" :value="scope.row.isLinearTransfer" />
</template>
</el-table-column>
<el-table-column label="数据类型" align="center" prop="dataType">
<template #default="scope">
<dict-tag :type="DICT_TYPE.IOT_DEVICE_DATA_TYPE" :value="scope.row.dataType" />
</template>
</el-table-column>
<el-table-column label="单位" align="center" prop="unit" />
<el-table-column label="输入最小值" align="center" prop="inMinValue" />
<el-table-column label="输入最大值" align="center" prop="inMaxValue" />
<el-table-column label="输出最小值" align="center" prop="outMinValue" />
<el-table-column label="输出最大值" align="center" prop="outMaxValue" />
<el-table-column label="输出数据类型" align="center" prop="outDataType" />
<el-table-column label="精度" align="center" prop="siemensFieldPrecision" />
<el-table-column label="站号" align="center" prop="modbusSlaveId" />
<el-table-column label="寄存器地址" align="center" prop="modbusFieldAddress" />
<el-table-column label="寄存器类型" align="center" prop="modbusAddressType" />
<el-table-column label="个数" align="center" prop="modbusFieldSize" />
<el-table-column label="缩放因子" align="center" prop="modbusFieldPrecision" />
<el-table-column label="字节顺序" align="center" prop="modbusFieldOrder" />
<el-table-column label="mqtt进制类型" align="center" prop="sourceDataType" />
<el-table-column label="结果进制类型" align="center" prop="transferDataType">
<template #default="scope">
<dict-tag :type="DICT_TYPE.IOT_DEVICE_DATA_TRANSFER_TYPE" :value="scope.row.transferDataType" />
</template>
</el-table-column>
<el-table-column label="系数" align="center" prop="factor" />
<el-table-column label="网关id" align="center" prop="gatewayId" />
<el-table-column label="组织设备id" align="center" prop="orgId" />
<el-table-column label="备注" align="center" prop="remark" />
<el-table-column label="是否启用" align="center" prop="isEnable" />
<el-table-column
label="创建时间"
align="center"
prop="createTime"
:formatter="dateFormatter"
width="180px"
/>
<el-table-column label="操作" align="center">
<template #default="scope">
<el-button
link
type="primary"
@click="openForm('update', scope.row.id)"
v-hasPermi="['iot:device:update']"
>
编辑
</el-button>
<el-button
link
type="danger"
@click="handleDelete(scope.row.id)"
v-hasPermi="['iot:device:delete']"
>
删除
</el-button>
</template>
</el-table-column>
</el-table>
<!-- 分页 -->
<Pagination
:total="total"
v-model:page="queryParams.pageNo"
v-model:limit="queryParams.pageSize"
@pagination="getList"
/>
</ContentWrap>
<!-- 表单弹窗添加/修改 -->
<DeviceAttributeForm ref="formRef" @success="getList" />
</template>
<script setup lang="ts">
import { DICT_TYPE } from '@/utils/dict'
import { dateFormatter } from '@/utils/formatTime'
import { DeviceApi } from '@/api/iot/device'
import DeviceAttributeForm from './DeviceAttributeForm.vue'
const { t } = useI18n() //
const message = useMessage() //
const props = defineProps<{
deviceId?: number // id
}>()
const loading = ref(false) //
const list = ref([]) //
const total = ref(0) //
const queryParams = reactive({
pageNo: 1,
pageSize: 10,
deviceId: undefined as unknown
})
/** 监听主表的关联字段的变化,加载对应的子表数据 */
watch(
() => props.deviceId,
(val: number) => {
if (!val) {
return
}
queryParams.deviceId = val
handleQuery()
},
{ immediate: true, deep: true }
)
/** 查询列表 */
const getList = async () => {
loading.value = true
try {
const data = await DeviceApi.getDeviceAttributePage(queryParams)
list.value = data.list
total.value = data.total
} finally {
loading.value = false
}
}
/** 搜索按钮操作 */
const handleQuery = () => {
queryParams.pageNo = 1
getList()
}
/** 添加/修改操作 */
const formRef = ref()
const openForm = (type: string, id?: number) => {
if (!props.deviceId) {
message.error('请选择一个物联设备')
return
}
formRef.value.open(type, id, props.deviceId)
}
/** 删除按钮操作 */
const handleDelete = async (id: number) => {
try {
//
await message.delConfirm()
//
await DeviceApi.deleteDeviceAttribute(id)
message.success(t('common.delSuccess'))
//
await getList()
} catch {}
}
</script>

@ -0,0 +1,347 @@
<template>
<ContentWrap>
<!-- 搜索工作栏 -->
<el-form
class="-mb-15px"
:model="queryParams"
ref="queryFormRef"
:inline="true"
label-width="68px"
>
<el-form-item label="设备编号" prop="deviceCode">
<el-input
v-model="queryParams.deviceCode"
placeholder="请输入设备编号"
clearable
@keyup.enter="handleQuery"
class="!w-240px"
/>
</el-form-item>
<el-form-item label="设备名称" prop="deviceName">
<el-input
v-model="queryParams.deviceName"
placeholder="请输入设备名称"
clearable
@keyup.enter="handleQuery"
class="!w-240px"
/>
</el-form-item>
<el-form-item label="设备类型" prop="deviceType">
<el-select
v-model="queryParams.deviceType"
placeholder="请选择设备类型"
clearable
class="!w-240px"
>
<el-option
v-for="dict in getStrDictOptions(DICT_TYPE.IOT_DEVICE_TYPE)"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
</el-select>
</el-form-item>
<el-form-item label="已下发" prop="isUpload">
<el-select
v-model="queryParams.isUpload"
placeholder="请选择是否已下发"
clearable
class="!w-240px"
>
<el-option
v-for="dict in getStrDictOptions(DICT_TYPE.IOT_1_OR_0)"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
</el-select>
</el-form-item>
<el-form-item label="网关id" prop="gatewayId">
<el-input
v-model="queryParams.gatewayId"
placeholder="请输入网关id"
clearable
@keyup.enter="handleQuery"
class="!w-240px"
/>
</el-form-item>
<el-form-item label="组织设备id" prop="orgId">
<el-input
v-model="queryParams.orgId"
placeholder="请输入组织设备id"
clearable
@keyup.enter="handleQuery"
class="!w-240px"
/>
</el-form-item>
<el-form-item label="备注" prop="remark">
<el-input
v-model="queryParams.remark"
placeholder="请输入备注"
clearable
@keyup.enter="handleQuery"
class="!w-240px"
/>
</el-form-item>
<el-form-item label="是否启用" prop="isEnable">
<el-select
v-model="queryParams.isEnable"
placeholder="请选择是否启用"
clearable
class="!w-240px"
>
<el-option
v-for="dict in getBoolDictOptions(DICT_TYPE.INFRA_BOOLEAN_STRING)"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
</el-select>
</el-form-item>
<el-form-item>
<el-button @click="handleQuery"><Icon icon="ep:search" class="mr-5px" /> 搜索</el-button>
<el-button @click="resetQuery"><Icon icon="ep:refresh" class="mr-5px" /> 重置</el-button>
<el-button
type="primary"
plain
@click="openForm('create')"
v-hasPermi="['iot:device:create']"
>
<Icon icon="ep:plus" class="mr-5px" /> 新增
</el-button>
<el-button
type="success"
plain
@click="handleExport"
:loading="exportLoading"
v-hasPermi="['iot:device:export']"
>
<Icon icon="ep:download" class="mr-5px" /> 导出
</el-button>
</el-form-item>
</el-form>
</ContentWrap>
<!-- 列表 -->
<ContentWrap>
<el-table
v-loading="loading"
:data="list"
:stripe="true"
:show-overflow-tooltip="true"
highlight-current-row
@current-change="handleCurrentChange"
>
<el-table-column label="ID" align="center" prop="id" />
<el-table-column label="设备配置id" align="center" prop="deviceConfigId" />
<el-table-column label="设备编号" align="center" prop="deviceCode" />
<el-table-column label="设备名称" align="center" prop="deviceName" />
<el-table-column label="设备类型" align="center" prop="deviceType" />
<el-table-column label="Siemens系列" align="center" prop="siemensSeries">
<template #default="scope">
<dict-tag :type="DICT_TYPE.IOT_SIEMENS_TYPE" :value="scope.row.siemensSeries" />
</template>
</el-table-column>
<el-table-column label="siemens连接参数" align="center" prop="siemensConnectParam" />
<el-table-column label="modbus协议类型" align="center" prop="modbusProtocol">
<template #default="scope">
<dict-tag :type="DICT_TYPE.IOT_MODBUS_TYPE" :value="scope.row.modbusProtocol" />
</template>
</el-table-column>
<el-table-column label="modbus模式" align="center" prop="modbusPattern">
<template #default="scope">
<dict-tag :type="DICT_TYPE.IOT_MODBUS_MOLD" :value="scope.row.modbusPattern" />
</template>
</el-table-column>
<el-table-column label="modbus串口号" align="center" prop="portName">
<template #default="scope">
<dict-tag :type="DICT_TYPE.IOT_MODBUS_PORT" :value="scope.row.portName" />
</template>
</el-table-column>
<el-table-column label="是否已下发" align="center" prop="isUpload">
<template #default="scope">
<dict-tag :type="DICT_TYPE.IOT_1_OR_0" :value="scope.row.isUpload" />
</template>
</el-table-column>
<el-table-column label="网关id" align="center" prop="gatewayId" />
<el-table-column label="组织设备id" align="center" prop="orgId" />
<el-table-column label="备注" align="center" prop="remark" />
<el-table-column label="是否启用" align="center" prop="isEnable" >
<template #default="scope">
<dict-tag :type="DICT_TYPE.INFRA_BOOLEAN_STRING" :value="scope.row.isEnable" />
</template>
</el-table-column>
<el-table-column
label="创建时间"
align="center"
prop="createTime"
:formatter="dateFormatter"
width="180px"
/>
<el-table-column label="操作" align="center">
<template #default="scope">
<el-button
link
type="primary"
@click="openForm('update', scope.row.id)"
v-hasPermi="['iot:device:update']"
>
编辑
</el-button>
<el-button
link
type="danger"
@click="handleDelete(scope.row.id)"
v-hasPermi="['iot:device:delete']"
>
删除
</el-button>
</template>
</el-table-column>
</el-table>
<!-- 分页 -->
<Pagination
:total="total"
v-model:page="queryParams.pageNo"
v-model:limit="queryParams.pageSize"
@pagination="getList"
/>
</ContentWrap>
<!-- 表单弹窗添加/修改 -->
<DeviceForm ref="formRef" @success="getList" />
<!-- 子表的列表 -->
<ContentWrap>
<el-tabs model-value="deviceAttribute">
<el-tab-pane label="设备属性" name="deviceAttribute">
<DeviceAttributeList :device-id="currentRow.id" />
</el-tab-pane>
</el-tabs>
</ContentWrap>
</template>
<script setup lang="ts">
import {getStrDictOptions, DICT_TYPE, getBoolDictOptions} from '@/utils/dict'
import { dateFormatter } from '@/utils/formatTime'
import download from '@/utils/download'
import { DeviceApi, DeviceVO } from '@/api/iot/device'
import DeviceForm from './DeviceForm.vue'
import DeviceAttributeList from './components/DeviceAttributeList.vue'
/** 物联设备 列表 */
defineOptions({ name: 'Device' })
const message = useMessage() //
const { t } = useI18n() //
const loading = ref(true) //
const list = ref<DeviceVO[]>([]) //
const total = ref(0) //
const queryParams = reactive({
pageNo: 1,
pageSize: 10,
deviceConfigId: undefined,
deviceCode: undefined,
deviceName: undefined,
deviceType: undefined,
siemensSeries: undefined,
siemensConnectParam: undefined,
readCronType: undefined,
readRepeatValue: undefined,
readRepeatUnit: undefined,
readCron: undefined,
writeCronType: undefined,
writeRepeatValue: undefined,
writeRepeatUnit: undefined,
writeCron: undefined,
localPersistent: undefined,
uploadRate: undefined,
rateCount: undefined,
modbusProtocol: undefined,
modbusPattern: undefined,
portName: undefined,
modbusConnectParam: undefined,
modbusReadAddrGap: undefined,
isUpload: undefined,
gatewayId: undefined,
orgId: undefined,
remark: undefined,
isEnable: undefined,
createTime: [],
})
const queryFormRef = ref() //
const exportLoading = ref(false) //
/** 查询列表 */
const getList = async () => {
loading.value = true
try {
const data = await DeviceApi.getDevicePage(queryParams)
list.value = data.list
total.value = data.total
} finally {
loading.value = false
}
}
/** 搜索按钮操作 */
const handleQuery = () => {
queryParams.pageNo = 1
getList()
}
/** 重置按钮操作 */
const resetQuery = () => {
queryFormRef.value.resetFields()
handleQuery()
}
/** 添加/修改操作 */
const formRef = ref()
const openForm = (type: string, id?: number) => {
formRef.value.open(type, id)
}
/** 删除按钮操作 */
const handleDelete = async (id: number) => {
try {
//
await message.delConfirm()
//
await DeviceApi.deleteDevice(id)
message.success(t('common.delSuccess'))
//
await getList()
} catch {}
}
/** 导出按钮操作 */
const handleExport = async () => {
try {
//
await message.exportConfirm()
//
exportLoading.value = true
const data = await DeviceApi.exportDevice(queryParams)
download.excel(data, '物联设备.xls')
} catch {
} finally {
exportLoading.value = false
}
}
/** 选中行操作 */
const currentRow = ref({}) //
const handleCurrentChange = (row) => {
currentRow.value = row
}
/** 初始化 **/
onMounted(() => {
getList()
})
</script>

@ -0,0 +1,140 @@
<template>
<Dialog :title="dialogTitle" v-model="dialogVisible">
<el-form
ref="formRef"
:model="formData"
:rules="formRules"
label-width="100px"
v-loading="formLoading"
>
<el-form-item label="公式名称" prop="name">
<el-input v-model="formData.name" placeholder="请输入公式名称" />
</el-form-item>
<el-form-item label="公式编号" prop="formulaCode">
<el-input v-model="formData.formulaCode" placeholder="请输入公式编号" />
</el-form-item>
<el-form-item label="公式" prop="formula">
<el-input v-model="formData.formula" placeholder="请输入公式" />
</el-form-item>
<el-form-item label="结果含义" prop="resultType">
<el-radio-group v-model="formData.resultType">
<el-radio
v-for="dict in getStrDictOptions(DICT_TYPE.MES_DATA_TYPE)"
:key="dict.value"
:label="dict.value"
>
{{ dict.label }}
</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="机台ID" prop="machineId">
<el-input v-model="formData.machineId" placeholder="请输入机台ID" />
</el-form-item>
<el-form-item label="备注" prop="remark">
<el-input v-model="formData.remark" type="textarea" placeholder="请输入备注" />
</el-form-item>
<el-form-item label="是否启用" prop="isEnable">
<el-radio-group v-model="formData.isEnable">
<el-radio
v-for="dict in getBoolDictOptions(DICT_TYPE.INFRA_BOOLEAN_STRING)"
:key="dict.value"
:label="dict.value"
>
{{ dict.label }}
</el-radio>
</el-radio-group>
</el-form-item>
</el-form>
<template #footer>
<el-button @click="submitForm" type="primary" :disabled="formLoading"> </el-button>
<el-button @click="dialogVisible = false"> </el-button>
</template>
</Dialog>
</template>
<script setup lang="ts">
import {getStrDictOptions, DICT_TYPE, getBoolDictOptions} from '@/utils/dict'
import { FormulaApi, FormulaVO } from '@/api/iot/formula'
/** 计算公式 表单 */
defineOptions({ name: 'FormulaForm' })
const { t } = useI18n() //
const message = useMessage() //
const dialogVisible = ref(false) //
const dialogTitle = ref('') //
const formLoading = ref(false) // 12
const formType = ref('') // create - update -
const formData = ref({
id: undefined,
name: undefined,
formulaCode: undefined,
formula: undefined,
resultType: undefined,
machineId: undefined,
remark: undefined,
isEnable: undefined,
})
const formRules = reactive({
machineId: [{ required: true, message: '机台ID不能为空', trigger: 'blur' }],
isEnable: [{ required: true, message: '是否启用不能为空', trigger: 'blur' }],
})
const formRef = ref() // Ref
/** 打开弹窗 */
const open = async (type: string, id?: number) => {
dialogVisible.value = true
dialogTitle.value = t('action.' + type)
formType.value = type
resetForm()
//
if (id) {
formLoading.value = true
try {
formData.value = await FormulaApi.getFormula(id)
} finally {
formLoading.value = false
}
}
}
defineExpose({ open }) // open
/** 提交表单 */
const emit = defineEmits(['success']) // success
const submitForm = async () => {
//
await formRef.value.validate()
//
formLoading.value = true
try {
const data = formData.value as unknown as FormulaVO
if (formType.value === 'create') {
await FormulaApi.createFormula(data)
message.success(t('common.createSuccess'))
} else {
await FormulaApi.updateFormula(data)
message.success(t('common.updateSuccess'))
}
dialogVisible.value = false
//
emit('success')
} finally {
formLoading.value = false
}
}
/** 重置表单 */
const resetForm = () => {
formData.value = {
id: undefined,
name: undefined,
formulaCode: undefined,
formula: undefined,
resultType: undefined,
machineId: undefined,
remark: undefined,
isEnable: undefined,
}
formRef.value?.resetFields()
}
</script>

@ -0,0 +1,163 @@
<template>
<Dialog :title="dialogTitle" v-model="dialogVisible">
<el-form
ref="formRef"
:model="formData"
:rules="formRules"
label-width="100px"
v-loading="formLoading"
>
<el-form-item label="公式编号" prop="formulaCode">
<el-input v-model="formData.formulaCode" placeholder="请输入公式编号" readonly/>
</el-form-item>
<el-form-item label="变量名称" prop="name">
<el-input v-model="formData.name" placeholder="请输入变量名称" />
</el-form-item>
<el-form-item label="设备ID" prop="deviceId">
<el-input v-model="formData.deviceId" placeholder="请输入设备ID" />
</el-form-item>
<el-form-item label="地址ID" prop="attributeId">
<el-input v-model="formData.attributeId" placeholder="请输入地址ID" />
</el-form-item>
<el-form-item label="地址名称" prop="attributeName">
<el-input v-model="formData.attributeName" placeholder="请输入地址名称" />
</el-form-item>
<el-form-item label="地址" prop="address">
<el-input v-model="formData.address" placeholder="请输入地址" />
</el-form-item>
<el-form-item label="示例值" prop="demoValue">
<el-input v-model="formData.demoValue" placeholder="请输入示例值" />
</el-form-item>
<el-form-item label="累积量类型" prop="sumType">
<el-radio-group v-model="formData.sumType">
<el-radio
v-for="dict in getStrDictOptions(DICT_TYPE.IOT_FORMULA_VAR_TYPE)"
:key="dict.value"
:label="dict.value"
>
{{ dict.label }}
</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="计算范围" prop="sumRange">
<el-radio-group v-model="formData.sumRange">
<el-radio
v-for="dict in getStrDictOptions(DICT_TYPE.IOT_FORMULA_CAL_RANG)"
:key="dict.value"
:label="dict.value"
>
{{ dict.label }}
</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="备注" prop="remark">
<el-input v-model="formData.remark" placeholder="请输入备注" />
</el-form-item>
</el-form>
<template #footer>
<el-button @click="submitForm" type="primary" :disabled="formLoading"> </el-button>
<el-button @click="dialogVisible = false"> </el-button>
</template>
</Dialog>
</template>
<script setup lang="ts">
import { getStrDictOptions, DICT_TYPE } from '@/utils/dict'
import { FormulaApi } from '@/api/iot/formula'
const { t } = useI18n() //
const message = useMessage() //
const dialogVisible = ref(false) //
const dialogTitle = ref('') //
const formLoading = ref(false) // 12
const formType = ref('') // create - update -
const formData = ref({
id: undefined,
formulaId: undefined,
formulaCode: undefined,
name: undefined,
deviceId: undefined,
attributeId: undefined,
attributeName: undefined,
address: undefined,
demoValue: undefined,
sumType: undefined,
sumRange: undefined,
remark: undefined,
isEnable: undefined,
})
const formRules = reactive({
formulaId: [{ required: true, message: '计算公式ID不能为空', trigger: 'blur' }],
name: [{ required: true, message: '变量名称不能为空', trigger: 'blur' }],
deviceId: [{ required: true, message: '设备ID不能为空', trigger: 'blur' }],
attributeId: [{ required: true, message: '地址ID不能为空', trigger: 'blur' }],
attributeName: [{ required: true, message: '地址名称不能为空', trigger: 'blur' }],
})
const formRef = ref() // Ref
/** 打开弹窗 */
const open = async (type: string, id?: number, formulaId: number, formulaCode: string) => {
dialogVisible.value = true
dialogTitle.value = t('action.' + type)
formType.value = type
resetForm()
formData.value.formulaId = formulaId
formData.value.formulaCode = formulaCode
console.log("formulaCode", formulaCode)
//
if (id) {
formLoading.value = true
try {
formData.value = await FormulaApi.getFormulaDetail(id)
} finally {
formLoading.value = false
}
}
}
defineExpose({ open }) // open
/** 提交表单 */
const emit = defineEmits(['success']) // success
const submitForm = async () => {
//
await formRef.value.validate()
//
formLoading.value = true
try {
const data = formData.value
if (formType.value === 'create') {
await FormulaApi.createFormulaDetail(data)
message.success(t('common.createSuccess'))
} else {
await FormulaApi.updateFormulaDetail(data)
message.success(t('common.updateSuccess'))
}
dialogVisible.value = false
//
emit('success')
} finally {
formLoading.value = false
}
}
/** 重置表单 */
const resetForm = () => {
formData.value = {
id: undefined,
formulaId: undefined,
formulaCode: undefined,
name: undefined,
deviceId: undefined,
attributeId: undefined,
attributeName: undefined,
address: undefined,
demoValue: undefined,
sumType: undefined,
sumRange: undefined,
remark: undefined,
isEnable: undefined,
}
formRef.value?.resetFields()
}
</script>

@ -0,0 +1,147 @@
<template>
<!-- 列表 -->
<ContentWrap>
<el-button
type="primary"
plain
@click="openForm('create')"
v-hasPermi="['iot:formula:create']"
>
<Icon icon="ep:plus" class="mr-5px" /> 新增
</el-button>
<el-table v-loading="loading" :data="list" :stripe="true" :show-overflow-tooltip="true">
<el-table-column label="ID" align="center" prop="id" />
<el-table-column label="公式编号" align="center" prop="formulaCode" />
<el-table-column label="变量名称" align="center" prop="name" />
<el-table-column label="设备ID" align="center" prop="deviceId" />
<el-table-column label="地址ID" align="center" prop="attributeId" />
<el-table-column label="地址名称" align="center" prop="attributeName" />
<el-table-column label="地址" align="center" prop="address" />
<el-table-column label="示例值" align="center" prop="demoValue" />
<el-table-column label="累积量类型" align="center" prop="sumType">
<template #default="scope">
<dict-tag :type="DICT_TYPE.IOT_FORMULA_VAR_TYPE" :value="scope.row.sumType" />
</template>
</el-table-column>
<el-table-column label="计算范围" align="center" prop="sumRange">
<template #default="scope">
<dict-tag :type="DICT_TYPE.IOT_FORMULA_CAL_RANG" :value="scope.row.sumRange" />
</template>
</el-table-column>
<el-table-column label="备注" align="center" prop="remark" />
<el-table-column
label="创建时间"
align="center"
prop="createTime"
:formatter="dateFormatter"
width="180px"
/>
<el-table-column label="操作" align="center">
<template #default="scope">
<el-button
link
type="primary"
@click="openForm('update', scope.row.id)"
v-hasPermi="['iot:formula:update']"
>
编辑
</el-button>
<el-button
link
type="danger"
@click="handleDelete(scope.row.id)"
v-hasPermi="['iot:formula:delete']"
>
删除
</el-button>
</template>
</el-table-column>
</el-table>
<!-- 分页 -->
<Pagination
:total="total"
v-model:page="queryParams.pageNo"
v-model:limit="queryParams.pageSize"
@pagination="getList"
/>
</ContentWrap>
<!-- 表单弹窗添加/修改 -->
<FormulaDetailForm ref="formRef" @success="getList" />
</template>
<script setup lang="ts">
import { DICT_TYPE } from '@/utils/dict'
import { dateFormatter } from '@/utils/formatTime'
import { FormulaApi } from '@/api/iot/formula'
import FormulaDetailForm from './FormulaDetailForm.vue'
const { t } = useI18n() //
const message = useMessage() //
const props = defineProps<{
formulaId?: number, // ID
formulaCode?: string
}>()
const loading = ref(false) //
const list = ref([]) //
const total = ref(0) //
const queryParams = reactive({
pageNo: 1,
pageSize: 10,
formulaId: undefined as unknown
})
/** 监听主表的关联字段的变化,加载对应的子表数据 */
watch(
() => props.formulaId,
(val: number) => {
if (!val) {
return
}
queryParams.formulaId = val
handleQuery()
},
{ immediate: true, deep: true }
)
/** 查询列表 */
const getList = async () => {
loading.value = true
try {
const data = await FormulaApi.getFormulaDetailPage(queryParams)
list.value = data.list
total.value = data.total
} finally {
loading.value = false
}
}
/** 搜索按钮操作 */
const handleQuery = () => {
queryParams.pageNo = 1
getList()
}
/** 添加/修改操作 */
const formRef = ref()
const openForm = (type: string, id?: number) => {
if (!props.formulaId) {
message.error('请选择一个计算公式')
return
}
formRef.value.open(type, id, props.formulaId, props.formulaCode)
}
/** 删除按钮操作 */
const handleDelete = async (id: number) => {
try {
//
await message.delConfirm()
//
await FormulaApi.deleteFormulaDetail(id)
message.success(t('common.delSuccess'))
//
await getList()
} catch {}
}
</script>

@ -0,0 +1,277 @@
<template>
<ContentWrap>
<!-- 搜索工作栏 -->
<el-form
class="-mb-15px"
:model="queryParams"
ref="queryFormRef"
:inline="true"
label-width="68px"
>
<el-form-item label="公式名称" prop="name">
<el-input
v-model="queryParams.name"
placeholder="请输入公式名称"
clearable
@keyup.enter="handleQuery"
class="!w-240px"
/>
</el-form-item>
<el-form-item label="公式编号" prop="formulaCode">
<el-input
v-model="queryParams.formulaCode"
placeholder="请输入公式编号"
clearable
@keyup.enter="handleQuery"
class="!w-240px"
/>
</el-form-item>
<el-form-item label="公式" prop="formula">
<el-input
v-model="queryParams.formula"
placeholder="请输入公式"
clearable
@keyup.enter="handleQuery"
class="!w-240px"
/>
</el-form-item>
<el-form-item label="结果类型" prop="resultType">
<el-select
v-model="queryParams.resultType"
placeholder="请选择结果类型"
clearable
class="!w-240px"
>
<el-option
v-for="dict in getStrDictOptions(DICT_TYPE.MES_DATA_TYPE)"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
</el-select>
</el-form-item>
<el-form-item label="机台ID" prop="machineId">
<el-input
v-model="queryParams.machineId"
placeholder="请输入机台ID"
clearable
@keyup.enter="handleQuery"
class="!w-240px"
/>
</el-form-item>
<el-form-item label="是否启用" prop="isEnable">
<el-select
v-model="queryParams.isEnable"
placeholder="请选择是否启用"
clearable
class="!w-240px"
>
<el-option
v-for="dict in getBoolDictOptions(DICT_TYPE.INFRA_BOOLEAN_STRING)"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
</el-select>
</el-form-item>
<el-form-item>
<el-button @click="handleQuery"><Icon icon="ep:search" class="mr-5px" /> 搜索</el-button>
<el-button @click="resetQuery"><Icon icon="ep:refresh" class="mr-5px" /> 重置</el-button>
<el-button
type="primary"
plain
@click="openForm('create')"
v-hasPermi="['iot:formula:create']"
>
<Icon icon="ep:plus" class="mr-5px" /> 新增
</el-button>
<el-button
type="success"
plain
@click="handleExport"
:loading="exportLoading"
v-hasPermi="['iot:formula:export']"
>
<Icon icon="ep:download" class="mr-5px" /> 导出
</el-button>
</el-form-item>
</el-form>
</ContentWrap>
<!-- 列表 -->
<ContentWrap>
<el-table
v-loading="loading"
:data="list"
:stripe="true"
:show-overflow-tooltip="true"
highlight-current-row
@current-change="handleCurrentChange"
>
<el-table-column label="ID" align="center" prop="id" />
<el-table-column label="公式名称" align="center" prop="name" />
<el-table-column label="公式编号" align="center" prop="formulaCode" />
<el-table-column label="公式" align="center" prop="formula" />
<el-table-column label="结果含义" align="center" prop="resultType">
<template #default="scope">
<dict-tag :type="DICT_TYPE.MES_DATA_TYPE" :value="scope.row.resultType" />
</template>
</el-table-column>
<el-table-column label="机台ID" align="center" prop="machineId" />
<el-table-column label="备注" align="center" prop="remark" />
<el-table-column label="是否启用" align="center" prop="isEnable" >
<template #default="scope">
<dict-tag :type="DICT_TYPE.INFRA_BOOLEAN_STRING" :value="scope.row.isEnable" />
</template>
</el-table-column>
<el-table-column
label="创建时间"
align="center"
prop="createTime"
:formatter="dateFormatter"
width="180px"
/>
<el-table-column label="操作" align="center">
<template #default="scope">
<el-button
link
type="primary"
@click="openForm('update', scope.row.id)"
v-hasPermi="['iot:formula:update']"
>
编辑
</el-button>
<el-button
link
type="danger"
@click="handleDelete(scope.row.id)"
v-hasPermi="['iot:formula:delete']"
>
删除
</el-button>
</template>
</el-table-column>
</el-table>
<!-- 分页 -->
<Pagination
:total="total"
v-model:page="queryParams.pageNo"
v-model:limit="queryParams.pageSize"
@pagination="getList"
/>
</ContentWrap>
<!-- 表单弹窗添加/修改 -->
<FormulaForm ref="formRef" @success="getList" />
<!-- 子表的列表 -->
<ContentWrap>
<el-tabs model-value="formulaDetail">
<el-tab-pane label="计算公式明细" name="formulaDetail">
<FormulaDetailList :formula-id="currentRow.id" :formula-code="currentRow.formulaCode" />
</el-tab-pane>
</el-tabs>
</ContentWrap>
</template>
<script setup lang="ts">
import {getStrDictOptions, DICT_TYPE, getBoolDictOptions} from '@/utils/dict'
import { dateFormatter } from '@/utils/formatTime'
import download from '@/utils/download'
import { FormulaApi, FormulaVO } from '@/api/iot/formula'
import FormulaForm from './FormulaForm.vue'
import FormulaDetailList from './components/FormulaDetailList.vue'
/** 计算公式 列表 */
defineOptions({ name: 'Formula' })
const message = useMessage() //
const { t } = useI18n() //
const loading = ref(true) //
const list = ref<FormulaVO[]>([]) //
const total = ref(0) //
const queryParams = reactive({
pageNo: 1,
pageSize: 10,
name: undefined,
formulaCode: undefined,
formula: undefined,
resultType: undefined,
machineId: undefined,
remark: undefined,
isEnable: undefined,
createTime: [],
})
const queryFormRef = ref() //
const exportLoading = ref(false) //
/** 查询列表 */
const getList = async () => {
loading.value = true
try {
const data = await FormulaApi.getFormulaPage(queryParams)
list.value = data.list
total.value = data.total
} finally {
loading.value = false
}
}
/** 搜索按钮操作 */
const handleQuery = () => {
queryParams.pageNo = 1
getList()
}
/** 重置按钮操作 */
const resetQuery = () => {
queryFormRef.value.resetFields()
handleQuery()
}
/** 添加/修改操作 */
const formRef = ref()
const openForm = (type: string, id?: number) => {
formRef.value.open(type, id)
}
/** 删除按钮操作 */
const handleDelete = async (id: number) => {
try {
//
await message.delConfirm()
//
await FormulaApi.deleteFormula(id)
message.success(t('common.delSuccess'))
//
await getList()
} catch {}
}
/** 导出按钮操作 */
const handleExport = async () => {
try {
//
await message.exportConfirm()
//
exportLoading.value = true
const data = await FormulaApi.exportFormula(queryParams)
download.excel(data, '计算公式.xls')
} catch {
} finally {
exportLoading.value = false
}
}
/** 选中行操作 */
const currentRow = ref({}) //
const handleCurrentChange = (row) => {
currentRow.value = row
}
/** 初始化 **/
onMounted(() => {
getList()
})
</script>

@ -0,0 +1,149 @@
<template>
<Dialog :title="dialogTitle" v-model="dialogVisible">
<el-form
ref="formRef"
:model="formData"
:rules="formRules"
label-width="100px"
v-loading="formLoading"
>
<el-form-item label="管理地址" prop="adminIp">
<el-input v-model="formData.adminIp" placeholder="请输入管理地址" />
</el-form-item>
<el-form-item label="管理账号" prop="username">
<el-input v-model="formData.username" placeholder="请输入管理账号" />
</el-form-item>
<el-form-item label="管理密码" prop="password">
<el-input v-model="formData.password" placeholder="请输入管理密码" />
</el-form-item>
<el-form-item label="网关名字" prop="gatewayName">
<el-input v-model="formData.gatewayName" placeholder="请输入网关名字" />
</el-form-item>
<el-form-item label="备注" prop="remark">
<el-input v-model="formData.remark" placeholder="请输入备注" />
</el-form-item>
<el-form-item label="是否启用" prop="isEnable">
<el-radio-group v-model="formData.isEnable">
<el-radio
v-for="dict in getBoolDictOptions(DICT_TYPE.INFRA_BOOLEAN_STRING)"
:key="dict.value"
:label="dict.value"
>
{{ dict.label }}
</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="网关编码" prop="gatewayCode">
<el-input v-model="formData.gatewayCode" placeholder="请输入网关编码" />
</el-form-item>
<el-form-item label="网关状态" prop="gatewayStatus">
<el-radio-group v-model="formData.gatewayStatus">
<el-radio
v-for="dict in getStrDictOptions(DICT_TYPE.IOT_GATEWAY_STATUS)"
:key="dict.value"
:label="dict.value"
>
{{ dict.label }}
</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="订阅主题" prop="topic">
<el-input v-model="formData.topic" placeholder="请输入订阅主题" />
</el-form-item>
</el-form>
<template #footer>
<el-button @click="submitForm" type="primary" :disabled="formLoading"> </el-button>
<el-button @click="dialogVisible = false"> </el-button>
</template>
</Dialog>
</template>
<script setup lang="ts">
import {getStrDictOptions, DICT_TYPE, getBoolDictOptions} from '@/utils/dict'
import { GatewayApi, GatewayVO } from '@/api/iot/gateway'
/** 网关 表单 */
defineOptions({ name: 'GatewayForm' })
const { t } = useI18n() //
const message = useMessage() //
const dialogVisible = ref(false) //
const dialogTitle = ref('') //
const formLoading = ref(false) // 12
const formType = ref('') // create - update -
const formData = ref({
id: undefined,
adminIp: undefined,
username: undefined,
password: undefined,
gatewayName: undefined,
remark: undefined,
isEnable: undefined,
gatewayCode: undefined,
gatewayStatus: undefined,
topic: undefined,
})
const formRules = reactive({
isEnable: [{ required: true, message: '是否启用不能为空', trigger: 'blur' }],
})
const formRef = ref() // Ref
/** 打开弹窗 */
const open = async (type: string, id?: number) => {
dialogVisible.value = true
dialogTitle.value = t('action.' + type)
formType.value = type
resetForm()
//
if (id) {
formLoading.value = true
try {
formData.value = await GatewayApi.getGateway(id)
} finally {
formLoading.value = false
}
}
}
defineExpose({ open }) // open
/** 提交表单 */
const emit = defineEmits(['success']) // success
const submitForm = async () => {
//
await formRef.value.validate()
//
formLoading.value = true
try {
const data = formData.value as unknown as GatewayVO
if (formType.value === 'create') {
await GatewayApi.createGateway(data)
message.success(t('common.createSuccess'))
} else {
await GatewayApi.updateGateway(data)
message.success(t('common.updateSuccess'))
}
dialogVisible.value = false
//
emit('success')
} finally {
formLoading.value = false
}
}
/** 重置表单 */
const resetForm = () => {
formData.value = {
id: undefined,
adminIp: undefined,
username: undefined,
password: undefined,
gatewayName: undefined,
remark: undefined,
isEnable: undefined,
gatewayCode: undefined,
gatewayStatus: undefined,
topic: undefined,
}
formRef.value?.resetFields()
}
</script>

@ -0,0 +1,316 @@
<template>
<Dialog :title="dialogTitle" v-model="dialogVisible">
<el-form
ref="formRef"
:model="formData"
:rules="formRules"
label-width="100px"
v-loading="formLoading"
>
<el-form-item label="设备配置id" prop="deviceConfigId">
<el-input v-model="formData.deviceConfigId" placeholder="请输入设备配置id" />
</el-form-item>
<el-form-item label="设备编号" prop="deviceCode">
<el-input v-model="formData.deviceCode" placeholder="请输入设备编号" />
</el-form-item>
<el-form-item label="设备名称" prop="deviceName">
<el-input v-model="formData.deviceName" placeholder="请输入设备名称" />
</el-form-item>
<el-form-item label="设备类型" prop="deviceType">
<el-radio-group v-model="formData.deviceType">
<el-radio
v-for="dict in getStrDictOptions(DICT_TYPE.IOT_DEVICE_TYPE)"
:key="dict.value"
:label="dict.value"
>
{{ dict.label }}
</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="Siemens系列" prop="siemensSeries">
<el-radio-group v-model="formData.siemensSeries">
<el-radio
v-for="dict in getStrDictOptions(DICT_TYPE.IOT_SIEMENS_TYPE)"
:key="dict.value"
:label="dict.value"
>
{{ dict.label }}
</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="siemens连接参数" prop="siemensConnectParam">
<el-input v-model="formData.siemensConnectParam" placeholder="波特率,数据位,停止位,校验位 例如960081N" />
</el-form-item>
<el-form-item label="读取方式" prop="readCronType">
<el-input v-model="formData.readCronType" placeholder="请输入读取方式" />
</el-form-item>
<el-form-item label="读取时间间隔" prop="readRepeatValue">
<el-input v-model="formData.readRepeatValue" placeholder="请输入读取任务时间间隔" />
</el-form-item>
<el-form-item label="读取时间间隔单位" prop="readRepeatUnit">
<el-radio-group v-model="formData.readRepeatUnit">
<el-radio
v-for="dict in getStrDictOptions(DICT_TYPE.IOT_DEVICE_DATA_UNIT)"
:key="dict.value"
:label="dict.value"
>
{{ dict.label }}
</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="读取任务时间表达式" prop="readCron">
<el-input v-model="formData.readCron" placeholder="请输入读取时间表达式" />
</el-form-item>
<el-form-item label="写入任务时间间隔" prop="writeCronType">
<el-input v-model="formData.writeCronType" placeholder="请输入写入方式" />
</el-form-item>
<el-form-item label="写入任务时间间隔" prop="writeRepeatValue">
<el-input v-model="formData.writeRepeatValue" placeholder="请输入写入时间间隔" />
</el-form-item>
<el-form-item label="写入任务时间间隔单位" prop="writeRepeatUnit">
<el-radio-group v-model="formData.writeRepeatUnit">
<el-radio
v-for="dict in getStrDictOptions(DICT_TYPE.IOT_DEVICE_DATA_UNIT)"
:key="dict.value"
:label="dict.value"
>
{{ dict.label }}
</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="写入时间表达式" prop="writeCron">
<el-input v-model="formData.writeCron" placeholder="请输入写入时间表达式" />
</el-form-item>
<el-form-item label="是否持久化" prop="localPersistent">
<el-radio-group v-model="formData.localPersistent">
<el-radio
v-for="dict in getStrDictOptions(DICT_TYPE.IOT_1_OR_0)"
:key="dict.value"
:label="dict.value"
>
{{ dict.label }}
</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="上传方式" prop="uploadRate">
<el-radio-group v-model="formData.uploadRate">
<el-radio
v-for="dict in getStrDictOptions(DICT_TYPE.IOT_DEVICE_UPLOADING_TYPE)"
:key="dict.value"
:label="dict.value"
>
{{ dict.label }}
</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="上传频率" prop="rateCount">
<el-input v-model="formData.rateCount" placeholder="请输入上传频率" />
</el-form-item>
<el-form-item label="modbus协议类型" prop="modbusProtocol">
<el-radio-group v-model="formData.modbusProtocol">
<el-radio
v-for="dict in getStrDictOptions(DICT_TYPE.IOT_MODBUS_TYPE)"
:key="dict.value"
:label="dict.value"
>
{{ dict.label }}
</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="modbus模式" prop="modbusPattern">
<el-radio-group v-model="formData.modbusPattern">
<el-radio
v-for="dict in getStrDictOptions(DICT_TYPE.IOT_MODBUS_MOLD)"
:key="dict.value"
:label="dict.value"
>
{{ dict.label }}
</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="modbus串口号" prop="portName">
<el-radio-group v-model="formData.portName">
<el-radio
v-for="dict in getStrDictOptions(DICT_TYPE.IOT_MODBUS_PORT)"
:key="dict.value"
:label="dict.value"
>
{{ dict.label }}
</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="modbus连接参数" prop="modbusConnectParam">
<el-input v-model="formData.modbusConnectParam" placeholder="波特率,数据位,停止位,校验位 例如960081N" />
</el-form-item>
<el-form-item label="读地址是否连续" prop="modbusReadAddrGap">
<el-radio-group v-model="formData.modbusReadAddrGap">
<el-radio
v-for="dict in getStrDictOptions(DICT_TYPE.IOT_1_OR_0)"
:key="dict.value"
:label="dict.value"
>
{{ dict.label }}
</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="已下发" prop="isUpload">
<el-radio-group v-model="formData.isUpload">
<el-radio
v-for="dict in getStrDictOptions(DICT_TYPE.IOT_1_OR_0)"
:key="dict.value"
:label="dict.value"
>
{{ dict.label }}
</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="组织设备id" prop="orgId">
<el-input v-model="formData.orgId" placeholder="请输入组织设备id" />
</el-form-item>
<el-form-item label="备注" prop="remark">
<el-input v-model="formData.remark" placeholder="请输入备注" />
</el-form-item>
<el-form-item label="是否启用" prop="isEnable">
<el-radio-group v-model="formData.isEnable">
<el-radio
v-for="dict in getBoolDictOptions(DICT_TYPE.INFRA_BOOLEAN_STRING)"
:key="dict.value"
:label="dict.value"
>
{{ dict.label }}
</el-radio>
</el-radio-group>
</el-form-item>
</el-form>
<template #footer>
<el-button @click="submitForm" type="primary" :disabled="formLoading"> </el-button>
<el-button @click="dialogVisible = false"> </el-button>
</template>
</Dialog>
</template>
<script setup lang="ts">
import {getStrDictOptions, DICT_TYPE, getBoolDictOptions} from '@/utils/dict'
import { GatewayApi } from '@/api/iot/gateway'
const { t } = useI18n() //
const message = useMessage() //
const dialogVisible = ref(false) //
const dialogTitle = ref('') //
const formLoading = ref(false) // 12
const formType = ref('') // create - update -
const formData = ref({
id: undefined,
deviceConfigId: undefined,
deviceCode: undefined,
deviceName: undefined,
deviceType: undefined,
siemensSeries: undefined,
siemensConnectParam: undefined,
readCronType: undefined,
readRepeatValue: undefined,
readRepeatUnit: undefined,
readCron: undefined,
writeCronType: undefined,
writeRepeatValue: undefined,
writeRepeatUnit: undefined,
writeCron: undefined,
localPersistent: undefined,
uploadRate: undefined,
rateCount: undefined,
modbusProtocol: undefined,
modbusPattern: undefined,
portName: undefined,
modbusConnectParam: undefined,
modbusReadAddrGap: undefined,
isUpload: undefined,
gatewayId: undefined,
orgId: undefined,
remark: undefined,
isEnable: undefined,
})
const formRules = reactive({
gatewayId: [{ required: true, message: '网关id不能为空', trigger: 'blur' }],
orgId: [{ required: true, message: '组织设备id不能为空', trigger: 'blur' }],
isEnable: [{ required: true, message: '是否启用不能为空', trigger: 'blur' }],
})
const formRef = ref() // Ref
/** 打开弹窗 */
const open = async (type: string, id?: number, gatewayId: number) => {
dialogVisible.value = true
dialogTitle.value = t('action.' + type)
formType.value = type
resetForm()
formData.value.gatewayId = gatewayId
//
if (id) {
formLoading.value = true
try {
formData.value = await GatewayApi.getDevice(id)
} finally {
formLoading.value = false
}
}
}
defineExpose({ open }) // open
/** 提交表单 */
const emit = defineEmits(['success']) // success
const submitForm = async () => {
//
await formRef.value.validate()
//
formLoading.value = true
try {
const data = formData.value
if (formType.value === 'create') {
await GatewayApi.createDevice(data)
message.success(t('common.createSuccess'))
} else {
await GatewayApi.updateDevice(data)
message.success(t('common.updateSuccess'))
}
dialogVisible.value = false
//
emit('success')
} finally {
formLoading.value = false
}
}
/** 重置表单 */
const resetForm = () => {
formData.value = {
id: undefined,
deviceConfigId: undefined,
deviceCode: undefined,
deviceName: undefined,
deviceType: undefined,
siemensSeries: undefined,
siemensConnectParam: undefined,
readCronType: undefined,
readRepeatValue: undefined,
readRepeatUnit: undefined,
readCron: undefined,
writeCronType: undefined,
writeRepeatValue: undefined,
writeRepeatUnit: undefined,
writeCron: undefined,
localPersistent: undefined,
uploadRate: undefined,
rateCount: undefined,
modbusProtocol: undefined,
modbusPattern: undefined,
portName: undefined,
modbusConnectParam: undefined,
modbusReadAddrGap: undefined,
isUpload: undefined,
gatewayId: undefined,
orgId: undefined,
remark: undefined,
isEnable: undefined,
}
formRef.value?.resetFields()
}
</script>

@ -0,0 +1,172 @@
<template>
<!-- 列表 -->
<ContentWrap>
<el-button
type="primary"
plain
@click="openForm('create')"
v-hasPermi="['iot:gateway:create']"
>
<Icon icon="ep:plus" class="mr-5px" /> 新增
</el-button>
<el-table v-loading="loading" :data="list" :stripe="true" :show-overflow-tooltip="true">
<el-table-column label="ID" align="center" prop="id" />
<el-table-column label="设备配置id" align="center" prop="deviceConfigId" />
<el-table-column label="设备编号" align="center" prop="deviceCode" />
<el-table-column label="设备名称" align="center" prop="deviceName" />
<el-table-column label="设备类型" align="center" prop="deviceType" >
<template #default="scope">
<dict-tag :type="DICT_TYPE.IOT_DEVICE_TYPE" :value="scope.row.deviceType" />
</template>
</el-table-column>
<el-table-column label="Siemens系列" align="center" prop="siemensSeries">
<template #default="scope">
<dict-tag :type="DICT_TYPE.IOT_SIEMENS_TYPE" :value="scope.row.siemensSeries" />
</template>
</el-table-column>
<el-table-column label="读取方式" align="center" prop="readCronType">
<template #default="scope">
<dict-tag :type="DICT_TYPE.IOT_1_OR_0" :value="scope.row.readCronType" />
</template>
</el-table-column>
<el-table-column label="读取时间间隔" align="center" prop="readRepeatValue" />
<el-table-column label="读取时间间隔单位" align="center" prop="readRepeatUnit">
<template #default="scope">
<dict-tag :type="DICT_TYPE.IOT_DEVICE_DATA_UNIT" :value="scope.row.readRepeatUnit" />
</template>
</el-table-column>
<el-table-column label="读取时间表达式" align="center" prop="readCron" />
<el-table-column label="modbus协议类型" align="center" prop="modbusProtocol">
<template #default="scope">
<dict-tag :type="DICT_TYPE.IOT_MODBUS_TYPE" :value="scope.row.modbusProtocol" />
</template>
</el-table-column>
<el-table-column label="已下发" align="center" prop="isUpload">
<template #default="scope">
<dict-tag :type="DICT_TYPE.IOT_1_OR_0" :value="scope.row.isUpload" />
</template>
</el-table-column>
<el-table-column label="组织设备id" align="center" prop="orgId" />
<el-table-column label="备注" align="center" prop="remark" />
<el-table-column label="是否启用" align="center" prop="isEnable" >
<template #default="scope">
<dict-tag :type="DICT_TYPE.INFRA_BOOLEAN_STRING" :value="scope.row.isEnable" />
</template>
</el-table-column>
<el-table-column
label="创建时间"
align="center"
prop="createTime"
:formatter="dateFormatter"
width="180px"
/>
<el-table-column label="操作" align="center">
<template #default="scope">
<el-button
link
type="primary"
@click="openForm('update', scope.row.id)"
v-hasPermi="['iot:gateway:update']"
>
编辑
</el-button>
<el-button
link
type="danger"
@click="handleDelete(scope.row.id)"
v-hasPermi="['iot:gateway:delete']"
>
删除
</el-button>
</template>
</el-table-column>
</el-table>
<!-- 分页 -->
<Pagination
:total="total"
v-model:page="queryParams.pageNo"
v-model:limit="queryParams.pageSize"
@pagination="getList"
/>
</ContentWrap>
<!-- 表单弹窗添加/修改 -->
<DeviceForm ref="formRef" @success="getList" />
</template>
<script setup lang="ts">
import { DICT_TYPE } from '@/utils/dict'
import { dateFormatter } from '@/utils/formatTime'
import { GatewayApi } from '@/api/iot/gateway'
import DeviceForm from './DeviceForm.vue'
const { t } = useI18n() //
const message = useMessage() //
const props = defineProps<{
gatewayId?: number // id
}>()
const loading = ref(false) //
const list = ref([]) //
const total = ref(0) //
const queryParams = reactive({
pageNo: 1,
pageSize: 10,
gatewayId: undefined as unknown
})
/** 监听主表的关联字段的变化,加载对应的子表数据 */
watch(
() => props.gatewayId,
(val: number) => {
if (!val) {
return
}
queryParams.gatewayId = val
handleQuery()
},
{ immediate: true, deep: true }
)
/** 查询列表 */
const getList = async () => {
loading.value = true
try {
const data = await GatewayApi.getDevicePage(queryParams)
list.value = data.list
total.value = data.total
} finally {
loading.value = false
}
}
/** 搜索按钮操作 */
const handleQuery = () => {
queryParams.pageNo = 1
getList()
}
/** 添加/修改操作 */
const formRef = ref()
const openForm = (type: string, id?: number) => {
if (!props.gatewayId) {
message.error('请选择一个网关')
return
}
formRef.value.open(type, id, props.gatewayId)
}
/** 删除按钮操作 */
const handleDelete = async (id: number) => {
try {
//
await message.delConfirm()
//
await GatewayApi.deleteDevice(id)
message.success(t('common.delSuccess'))
//
await getList()
} catch {}
}
</script>

@ -0,0 +1,301 @@
<template>
<ContentWrap>
<!-- 搜索工作栏 -->
<el-form
class="-mb-15px"
:model="queryParams"
ref="queryFormRef"
:inline="true"
label-width="68px"
>
<el-form-item label="管理地址" prop="adminIp">
<el-input
v-model="queryParams.adminIp"
placeholder="请输入管理地址"
clearable
@keyup.enter="handleQuery"
class="!w-240px"
/>
</el-form-item>
<el-form-item label="网关名字" prop="gatewayName">
<el-input
v-model="queryParams.gatewayName"
placeholder="请输入网关名字"
clearable
@keyup.enter="handleQuery"
class="!w-240px"
/>
</el-form-item>
<el-form-item label="备注" prop="remark">
<el-input
v-model="queryParams.remark"
placeholder="请输入备注"
clearable
@keyup.enter="handleQuery"
class="!w-240px"
/>
</el-form-item>
<el-form-item label="是否启用" prop="isEnable">
<el-select
v-model="queryParams.isEnable"
placeholder="请选择是否启用"
clearable
class="!w-240px"
>
<el-option
v-for="dict in getBoolDictOptions(DICT_TYPE.INFRA_BOOLEAN_STRING)"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
</el-select>
</el-form-item>
<el-form-item label="创建时间" prop="createTime">
<el-date-picker
v-model="queryParams.createTime"
value-format="YYYY-MM-DD HH:mm:ss"
type="daterange"
start-placeholder="开始日期"
end-placeholder="结束日期"
:default-time="[new Date('1 00:00:00'), new Date('1 23:59:59')]"
class="!w-240px"
/>
</el-form-item>
<el-form-item label="网关编码" prop="gatewayCode">
<el-input
v-model="queryParams.gatewayCode"
placeholder="请输入网关编码"
clearable
@keyup.enter="handleQuery"
class="!w-240px"
/>
</el-form-item>
<el-form-item label="网关状态" prop="gatewayStatus">
<el-select
v-model="queryParams.gatewayStatus"
placeholder="请选择网关状态"
clearable
class="!w-240px"
>
<el-option
v-for="dict in getStrDictOptions(DICT_TYPE.IOT_GATEWAY_STATUS)"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
</el-select>
</el-form-item>
<el-form-item label="订阅主题" prop="topic">
<el-input
v-model="queryParams.topic"
placeholder="请输入订阅主题"
clearable
@keyup.enter="handleQuery"
class="!w-240px"
/>
</el-form-item>
<el-form-item>
<el-button @click="handleQuery"><Icon icon="ep:search" class="mr-5px" /> 搜索</el-button>
<el-button @click="resetQuery"><Icon icon="ep:refresh" class="mr-5px" /> 重置</el-button>
<el-button
type="primary"
plain
@click="openForm('create')"
v-hasPermi="['iot:gateway:create']"
>
<Icon icon="ep:plus" class="mr-5px" /> 新增
</el-button>
<el-button
type="success"
plain
@click="handleExport"
:loading="exportLoading"
v-hasPermi="['iot:gateway:export']"
>
<Icon icon="ep:download" class="mr-5px" /> 导出
</el-button>
</el-form-item>
</el-form>
</ContentWrap>
<!-- 列表 -->
<ContentWrap>
<el-table
v-loading="loading"
:data="list"
:stripe="true"
:show-overflow-tooltip="true"
highlight-current-row
@current-change="handleCurrentChange"
>
<el-table-column label="网关编码" align="center" prop="gatewayCode" />
<el-table-column label="管理地址" align="center" prop="adminIp" />
<el-table-column label="管理账号" align="center" prop="username" />
<el-table-column label="管理密码" align="center" prop="password" />
<el-table-column label="网关名字" align="center" prop="gatewayName" />
<el-table-column label="备注" align="center" prop="remark" />
<el-table-column label="是否启用" align="center" prop="isEnable" >
<template #default="scope">
<dict-tag :type="DICT_TYPE.INFRA_BOOLEAN_STRING" :value="scope.row.isEnable" />
</template>
</el-table-column>
<el-table-column
label="创建时间"
align="center"
prop="createTime"
:formatter="dateFormatter"
width="180px"
/>
<el-table-column label="网关状态" align="center" prop="gatewayStatus">
<template #default="scope">
<dict-tag :type="DICT_TYPE.IOT_GATEWAY_STATUS" :value="scope.row.gatewayStatus" />
</template>
</el-table-column>
<el-table-column label="订阅主题" align="center" prop="topic" />
<el-table-column label="操作" align="center">
<template #default="scope">
<el-button
link
type="primary"
@click="openForm('update', scope.row.id)"
v-hasPermi="['iot:gateway:update']"
>
编辑
</el-button>
<el-button
link
type="danger"
@click="handleDelete(scope.row.id)"
v-hasPermi="['iot:gateway:delete']"
>
删除
</el-button>
</template>
</el-table-column>
</el-table>
<!-- 分页 -->
<Pagination
:total="total"
v-model:page="queryParams.pageNo"
v-model:limit="queryParams.pageSize"
@pagination="getList"
/>
</ContentWrap>
<!-- 表单弹窗添加/修改 -->
<GatewayForm ref="formRef" @success="getList" />
<!-- 子表的列表 -->
<ContentWrap>
<el-tabs model-value="device">
<el-tab-pane label="物联设备" name="device">
<DeviceList :gateway-id="currentRow.id" />
</el-tab-pane>
</el-tabs>
</ContentWrap>
</template>
<script setup lang="ts">
import {getStrDictOptions, DICT_TYPE, getBoolDictOptions} from '@/utils/dict'
import { dateFormatter } from '@/utils/formatTime'
import download from '@/utils/download'
import { GatewayApi, GatewayVO } from '@/api/iot/gateway'
import GatewayForm from './GatewayForm.vue'
import DeviceList from './components/DeviceList.vue'
/** 网关 列表 */
defineOptions({ name: 'Gateway' })
const message = useMessage() //
const { t } = useI18n() //
const loading = ref(true) //
const list = ref<GatewayVO[]>([]) //
const total = ref(0) //
const queryParams = reactive({
pageNo: 1,
pageSize: 10,
adminIp: undefined,
username: undefined,
password: undefined,
gatewayName: undefined,
remark: undefined,
isEnable: undefined,
createTime: [],
gatewayCode: undefined,
gatewayStatus: undefined,
topic: undefined,
})
const queryFormRef = ref() //
const exportLoading = ref(false) //
/** 查询列表 */
const getList = async () => {
loading.value = true
try {
const data = await GatewayApi.getGatewayPage(queryParams)
list.value = data.list
total.value = data.total
} finally {
loading.value = false
}
}
/** 搜索按钮操作 */
const handleQuery = () => {
queryParams.pageNo = 1
getList()
}
/** 重置按钮操作 */
const resetQuery = () => {
queryFormRef.value.resetFields()
handleQuery()
}
/** 添加/修改操作 */
const formRef = ref()
const openForm = (type: string, id?: number) => {
formRef.value.open(type, id)
}
/** 删除按钮操作 */
const handleDelete = async (id: number) => {
try {
//
await message.delConfirm()
//
await GatewayApi.deleteGateway(id)
message.success(t('common.delSuccess'))
//
await getList()
} catch {}
}
/** 导出按钮操作 */
const handleExport = async () => {
try {
//
await message.exportConfirm()
//
exportLoading.value = true
const data = await GatewayApi.exportGateway(queryParams)
download.excel(data, '网关.xls')
} catch {
} finally {
exportLoading.value = false
}
}
/** 选中行操作 */
const currentRow = ref({}) //
const handleCurrentChange = (row) => {
currentRow.value = row
}
/** 初始化 **/
onMounted(() => {
getList()
})
</script>

@ -0,0 +1,179 @@
<template>
<Dialog :title="dialogTitle" v-model="dialogVisible">
<el-form
ref="formRef"
:model="formData"
:rules="formRules"
label-width="100px"
v-loading="formLoading"
>
<el-form-item label="父组织" prop="parentId">
<el-tree-select
v-model="formData.parentId"
:data="organizationTree"
:props="defaultProps"
check-strictly
default-expand-all
placeholder="请选择父组织"
/>
</el-form-item>
<el-form-item label="组织名称" prop="name">
<el-input v-model="formData.name" placeholder="请输入组织名称" />
</el-form-item>
<el-form-item label="组织等级" prop="orgClass">
<el-radio-group v-model="formData.orgClass">
<el-radio
v-for="dict in getStrDictOptions(DICT_TYPE.IOT_ORG_CLASS)"
:key="dict.value"
:label="dict.value"
>
{{ dict.label }}
</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="显示顺序" prop="sort">
<el-input v-model="formData.sort" placeholder="请输入显示顺序" />
</el-form-item>
<el-form-item label="组织状态" prop="status">
<el-radio-group v-model="formData.status">
<el-radio
v-for="dict in getIntDictOptions(DICT_TYPE.MES_MACHINE_STATUS)"
:key="dict.value"
:label="dict.value"
>
{{ dict.label }}
</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="设备类型" prop="deviceType">
<el-radio-group v-model="formData.deviceType">
<el-radio
v-for="dict in getStrDictOptions(DICT_TYPE.IOT_DEVICE_TYPE)"
:key="dict.value"
:label="dict.value"
>
{{ dict.label }}
</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="机台类型" prop="machineType">
<el-select v-model="formData.machineType" clearable placeholder="请选择机台类型">
<el-option
v-for="dict in getStrDictOptions(DICT_TYPE.MES_ORG_TYPE)"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
</el-select>
</el-form-item>
</el-form>
<template #footer>
<el-button @click="submitForm" type="primary" :disabled="formLoading"> </el-button>
<el-button @click="dialogVisible = false"> </el-button>
</template>
</Dialog>
</template>
<script setup lang="ts">
import { getIntDictOptions, getStrDictOptions, DICT_TYPE } from '@/utils/dict'
import { OrganizationApi, OrganizationVO } from '@/api/iot/iotorganization'
import { defaultProps, handleTree } from '@/utils/tree'
/** IOT组织 表单 */
defineOptions({ name: 'OrganizationForm' })
const { t } = useI18n() //
const message = useMessage() //
const dialogVisible = ref(false) //
const dialogTitle = ref('') //
const formLoading = ref(false) // 12
const formType = ref('') // create - update -
const formData = ref({
id: undefined,
sort: undefined,
workerUserId: undefined,
orgId: undefined,
name: undefined,
parentId: undefined,
status: undefined,
deviceType: undefined,
orgClass: undefined,
machineType: undefined,
})
const formRules = reactive({
name: [{ required: true, message: '组织名称不能为空', trigger: 'blur' }],
parentId: [{ required: true, message: '父组织id不能为空', trigger: 'blur' }],
})
const formRef = ref() // Ref
const organizationTree = ref() //
/** 打开弹窗 */
const open = async (type: string, id?: number) => {
dialogVisible.value = true
dialogTitle.value = t('action.' + type)
formType.value = type
resetForm()
//
if (id) {
formLoading.value = true
try {
formData.value = await OrganizationApi.getOrganization(id)
} finally {
formLoading.value = false
}
}
await getOrganizationTree()
}
defineExpose({ open }) // open
/** 提交表单 */
const emit = defineEmits(['success']) // success
const submitForm = async () => {
//
await formRef.value.validate()
//
formLoading.value = true
try {
const data = formData.value as unknown as OrganizationVO
if (formType.value === 'create') {
await OrganizationApi.createOrganization(data)
message.success(t('common.createSuccess'))
} else {
await OrganizationApi.updateOrganization(data)
message.success(t('common.updateSuccess'))
}
dialogVisible.value = false
//
emit('success')
} finally {
formLoading.value = false
}
}
/** 重置表单 */
const resetForm = () => {
formData.value = {
id: undefined,
sort: undefined,
workerUserId: undefined,
orgId: undefined,
name: undefined,
parentId: undefined,
status: undefined,
deviceType: undefined,
orgClass: undefined,
machineType: undefined,
}
formRef.value?.resetFields()
}
/** 获得IOT组织树 */
const getOrganizationTree = async () => {
organizationTree.value = []
const data = await OrganizationApi.getOrganizationList()
const root: Tree = { id: 0, name: '顶级IOT组织', children: [] }
root.children = handleTree(data, 'id', 'parentId')
organizationTree.value.push(root)
}
</script>

@ -0,0 +1,297 @@
<template>
<ContentWrap>
<!-- 搜索工作栏 -->
<el-form
class="-mb-15px"
:model="queryParams"
ref="queryFormRef"
:inline="true"
label-width="68px"
>
<el-form-item label="名称" prop="name">
<el-input
v-model="queryParams.name"
placeholder="请输入名称"
clearable
@keyup.enter="handleQuery"
class="!w-240px"
/>
</el-form-item>
<el-form-item label="父组织" prop="parentId">
<el-input
v-model="queryParams.parentId"
placeholder="请输入父组织"
clearable
@keyup.enter="handleQuery"
class="!w-240px"
/>
</el-form-item>
<el-form-item label="状态" prop="status">
<el-select
v-model="queryParams.status"
placeholder="请选择状态"
clearable
class="!w-240px"
>
<el-option
v-for="dict in getIntDictOptions(DICT_TYPE.MES_MACHINE_STATUS)"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
</el-select>
</el-form-item>
<el-form-item label="设备类型" prop="deviceType">
<el-select
v-model="queryParams.deviceType"
placeholder="请选择设备类型"
clearable
class="!w-240px"
>
<el-option
v-for="dict in getStrDictOptions(DICT_TYPE.IOT_DEVICE_TYPE)"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
</el-select>
</el-form-item>
<el-form-item label="等级" prop="orgClass">
<el-select
v-model="queryParams.orgClass"
placeholder="请选择等级"
clearable
class="!w-240px"
>
<el-option
v-for="dict in getStrDictOptions(DICT_TYPE.IOT_ORG_CLASS)"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
</el-select>
</el-form-item>
<el-form-item label="机台类型" prop="machineType">
<el-select
v-model="queryParams.machineType"
placeholder="请选择机台类型"
clearable
class="!w-240px"
>
<el-option
v-for="dict in getStrDictOptions(DICT_TYPE.MES_ORG_TYPE)"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
</el-select>
</el-form-item>
<el-form-item>
<el-button @click="handleQuery"><Icon icon="ep:search" class="mr-5px" /> 搜索</el-button>
<el-button @click="resetQuery"><Icon icon="ep:refresh" class="mr-5px" /> 重置</el-button>
<el-button
type="primary"
plain
@click="openForm('create')"
v-hasPermi="['iot:organization:create']"
>
<Icon icon="ep:plus" class="mr-5px" /> 新增
</el-button>
<el-button
type="success"
plain
@click="handleExport"
:loading="exportLoading"
v-hasPermi="['iot:organization:export']"
>
<Icon icon="ep:download" class="mr-5px" /> 导出
</el-button>
<el-button type="danger" plain @click="toggleExpandAll">
<Icon icon="ep:sort" class="mr-5px" /> 展开/折叠
</el-button>
</el-form-item>
</el-form>
</ContentWrap>
<!-- 列表 -->
<ContentWrap>
<el-table
v-loading="loading"
:data="list"
:stripe="true"
:show-overflow-tooltip="true"
row-key="id"
:default-expand-all="isExpandAll"
v-if="refreshTable"
>
<el-table-column label="组织id" align="center" prop="id" />
<el-table-column label="父组织" align="center" prop="parentId" />
<el-table-column label="名称" align="center" prop="name" />
<el-table-column label="显示顺序" align="center" prop="sort" />
<el-table-column label="状态" align="center" prop="status">
<template #default="scope">
<dict-tag :type="DICT_TYPE.MES_MACHINE_STATUS" :value="scope.row.status" />
</template>
</el-table-column>
<el-table-column label="设备类型" align="center" prop="deviceType">
<template #default="scope">
<dict-tag :type="DICT_TYPE.IOT_DEVICE_TYPE" :value="scope.row.deviceType" />
</template>
</el-table-column>
<el-table-column label="等级" align="center" prop="orgClass">
<template #default="scope">
<dict-tag :type="DICT_TYPE.IOT_ORG_CLASS" :value="scope.row.orgClass" />
</template>
</el-table-column>
<el-table-column label="机台类型" align="center" prop="machineType">
<template #default="scope">
<dict-tag :type="DICT_TYPE.MES_ORG_TYPE" :value="scope.row.machineType" />
</template>
</el-table-column>
<el-table-column label="负责人/工人" align="center" prop="workerUserId" />
<el-table-column label="绑定工位" align="center" prop="orgId" />
<!-- <el-table-column-->
<!-- label="创建时间"-->
<!-- align="center"-->
<!-- prop="createTime"-->
<!-- :formatter="dateFormatter"-->
<!-- width="180px"-->
<!-- />-->
<el-table-column label="操作" align="center">
<template #default="scope">
<el-button
link
type="primary"
@click="openForm('update', scope.row.id)"
v-hasPermi="['iot:organization:update']"
>
编辑
</el-button>
<el-button
link
type="danger"
@click="handleDelete(scope.row.id)"
v-hasPermi="['iot:organization:delete']"
>
删除
</el-button>
</template>
</el-table-column>
</el-table>
<!-- 分页 -->
<Pagination
:total="total"
v-model:page="queryParams.pageNo"
v-model:limit="queryParams.pageSize"
@pagination="getList"
/>
</ContentWrap>
<!-- 表单弹窗添加/修改 -->
<OrganizationForm ref="formRef" @success="getList" />
</template>
<script setup lang="ts">
import { getIntDictOptions, getStrDictOptions, DICT_TYPE } from '@/utils/dict'
import { dateFormatter } from '@/utils/formatTime'
import { handleTree } from '@/utils/tree'
import download from '@/utils/download'
import { OrganizationApi, OrganizationVO } from '@/api/iot/iotorganization'
import OrganizationForm from './OrganizationForm.vue'
/** IOT组织 列表 */
defineOptions({ name: 'IotOrganization' })
const message = useMessage() //
const { t } = useI18n() //
const loading = ref(true) //
const list = ref<OrganizationVO[]>([]) //
const queryParams = reactive({
sort: undefined,
workerUserId: undefined,
orgId: undefined,
createTime: [],
name: undefined,
parentId: undefined,
status: undefined,
deviceType: undefined,
orgClass: undefined,
machineType: undefined,
})
const queryFormRef = ref() //
const exportLoading = ref(false) //
/** 查询列表 */
const getList = async () => {
loading.value = true
try {
const data = await OrganizationApi.getOrganizationList(queryParams)
list.value = handleTree(data, 'id', 'parentId')
} finally {
loading.value = false
}
}
/** 搜索按钮操作 */
const handleQuery = () => {
queryParams.pageNo = 1
getList()
}
/** 重置按钮操作 */
const resetQuery = () => {
queryFormRef.value.resetFields()
handleQuery()
}
/** 添加/修改操作 */
const formRef = ref()
const openForm = (type: string, id?: number) => {
formRef.value.open(type, id)
}
/** 删除按钮操作 */
const handleDelete = async (id: number) => {
try {
//
await message.delConfirm()
//
await OrganizationApi.deleteOrganization(id)
message.success(t('common.delSuccess'))
//
await getList()
} catch {}
}
/** 导出按钮操作 */
const handleExport = async () => {
try {
//
await message.exportConfirm()
//
exportLoading.value = true
const data = await OrganizationApi.exportOrganization(queryParams)
download.excel(data, 'IOT组织.xls')
} catch {
} finally {
exportLoading.value = false
}
}
/** 展开/折叠操作 */
const isExpandAll = ref(true) //
const refreshTable = ref(true) //
const toggleExpandAll = async () => {
refreshTable.value = false
isExpandAll.value = !isExpandAll.value
await nextTick()
refreshTable.value = true
}
/** 初始化 **/
onMounted(() => {
getList()
})
</script>

@ -0,0 +1,131 @@
<template>
<Dialog :title="dialogTitle" v-model="dialogVisible">
<el-form
ref="formRef"
:model="formData"
:rules="formRules"
label-width="100px"
v-loading="formLoading"
>
<el-form-item label="缩略图" prop="img">
<UploadImg v-model="formData.img" />
</el-form-item>
<el-form-item label="备注" prop="remark">
<el-input v-model="formData.remark" type="textarea" placeholder="请输入备注" />
</el-form-item>
<el-form-item label="是否启用" prop="isEnable">
<el-radio-group v-model="formData.isEnable">
<el-radio
v-for="dict in getBoolDictOptions(DICT_TYPE.INFRA_BOOLEAN_STRING)"
:key="dict.value"
:label="dict.value"
>
{{ dict.label }}
</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="编码" prop="code">
<el-input v-model="formData.code" placeholder="请输入编码" />
</el-form-item>
<el-form-item label="标题" prop="title">
<el-input v-model="formData.title" placeholder="请输入标题" />
</el-form-item>
<el-form-item label="访问地址" prop="viewUrl">
<el-input v-model="formData.viewUrl" placeholder="请输入访问地址" />
</el-form-item>
<el-form-item label="标签" prop="tags">
<el-input v-model="formData.tags" placeholder="请输入标签" />
</el-form-item>
</el-form>
<template #footer>
<el-button @click="submitForm" type="primary" :disabled="formLoading"> </el-button>
<el-button @click="dialogVisible = false"> </el-button>
</template>
</Dialog>
</template>
<script setup lang="ts">
import { getBoolDictOptions, DICT_TYPE } from '@/utils/dict'
import { KanbanApi, KanbanVO } from '@/api/iot/kanban'
/** 物联看板 表单 */
defineOptions({ name: 'KanbanForm' })
const { t } = useI18n() //
const message = useMessage() //
const dialogVisible = ref(false) //
const dialogTitle = ref('') //
const formLoading = ref(false) // 12
const formType = ref('') // create - update -
const formData = ref({
id: undefined,
img: undefined,
remark: undefined,
isEnable: undefined,
code: undefined,
title: undefined,
viewUrl: undefined,
tags: undefined,
})
const formRules = reactive({
isEnable: [{ required: true, message: '是否启用不能为空', trigger: 'blur' }],
})
const formRef = ref() // Ref
/** 打开弹窗 */
const open = async (type: string, id?: number) => {
dialogVisible.value = true
dialogTitle.value = t('action.' + type)
formType.value = type
resetForm()
//
if (id) {
formLoading.value = true
try {
formData.value = await KanbanApi.getKanban(id)
} finally {
formLoading.value = false
}
}
}
defineExpose({ open }) // open
/** 提交表单 */
const emit = defineEmits(['success']) // success
const submitForm = async () => {
//
await formRef.value.validate()
//
formLoading.value = true
try {
const data = formData.value as unknown as KanbanVO
if (formType.value === 'create') {
await KanbanApi.createKanban(data)
message.success(t('common.createSuccess'))
} else {
await KanbanApi.updateKanban(data)
message.success(t('common.updateSuccess'))
}
dialogVisible.value = false
//
emit('success')
} finally {
formLoading.value = false
}
}
/** 重置表单 */
const resetForm = () => {
formData.value = {
id: undefined,
img: undefined,
remark: undefined,
isEnable: undefined,
code: undefined,
title: undefined,
viewUrl: undefined,
tags: undefined,
}
formRef.value?.resetFields()
}
</script>

@ -0,0 +1,246 @@
<template>
<ContentWrap>
<!-- 搜索工作栏 -->
<el-form
class="-mb-15px"
:model="queryParams"
ref="queryFormRef"
:inline="true"
label-width="68px"
>
<el-form-item label="是否启用" prop="isEnable">
<el-select
v-model="queryParams.isEnable"
placeholder="请选择是否启用"
clearable
class="!w-240px"
>
<el-option
v-for="dict in getBoolDictOptions(DICT_TYPE.INFRA_BOOLEAN_STRING)"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
</el-select>
</el-form-item>
<el-form-item label="创建时间" prop="createTime">
<el-date-picker
v-model="queryParams.createTime"
value-format="YYYY-MM-DD HH:mm:ss"
type="daterange"
start-placeholder="开始日期"
end-placeholder="结束日期"
:default-time="[new Date('1 00:00:00'), new Date('1 23:59:59')]"
class="!w-240px"
/>
</el-form-item>
<el-form-item label="编码" prop="code">
<el-input
v-model="queryParams.code"
placeholder="请输入编码"
clearable
@keyup.enter="handleQuery"
class="!w-240px"
/>
</el-form-item>
<el-form-item label="标题" prop="title">
<el-input
v-model="queryParams.title"
placeholder="请输入标题"
clearable
@keyup.enter="handleQuery"
class="!w-240px"
/>
</el-form-item>
<el-form-item label="访问地址" prop="viewUrl">
<el-input
v-model="queryParams.viewUrl"
placeholder="请输入访问地址"
clearable
@keyup.enter="handleQuery"
class="!w-240px"
/>
</el-form-item>
<el-form-item label="标签" prop="tags">
<el-input
v-model="queryParams.tags"
placeholder="请输入标签"
clearable
@keyup.enter="handleQuery"
class="!w-240px"
/>
</el-form-item>
<el-form-item>
<el-button @click="handleQuery"><Icon icon="ep:search" class="mr-5px" /> 搜索</el-button>
<el-button @click="resetQuery"><Icon icon="ep:refresh" class="mr-5px" /> 重置</el-button>
<el-button
type="primary"
plain
@click="openForm('create')"
v-hasPermi="['iot:kanban:create']"
>
<Icon icon="ep:plus" class="mr-5px" /> 新增
</el-button>
<el-button
type="success"
plain
@click="handleExport"
:loading="exportLoading"
v-hasPermi="['iot:kanban:export']"
>
<Icon icon="ep:download" class="mr-5px" /> 导出
</el-button>
</el-form-item>
</el-form>
</ContentWrap>
<!-- 列表 -->
<ContentWrap>
<el-table v-loading="loading" :data="list" :stripe="true" :show-overflow-tooltip="true">
<el-table-column label="ID" align="center" prop="id" />
<el-table-column label="缩略图" align="center" prop="img" />
<el-table-column label="备注" align="center" prop="remark" />
<el-table-column label="是否启用" align="center" prop="isEnable">
<template #default="scope">
<dict-tag :type="DICT_TYPE.INFRA_BOOLEAN_STRING" :value="scope.row.isEnable" />
</template>
</el-table-column>
<el-table-column
label="创建时间"
align="center"
prop="createTime"
:formatter="dateFormatter"
width="180px"
/>
<el-table-column label="编码" align="center" prop="code" />
<el-table-column label="标题" align="center" prop="title" />
<el-table-column label="访问地址" align="center" prop="viewUrl" />
<el-table-column label="标签" align="center" prop="tags" />
<el-table-column label="操作" align="center">
<template #default="scope">
<el-button
link
type="primary"
@click="openForm('update', scope.row.id)"
v-hasPermi="['iot:kanban:update']"
>
编辑
</el-button>
<el-button
link
type="danger"
@click="handleDelete(scope.row.id)"
v-hasPermi="['iot:kanban:delete']"
>
删除
</el-button>
</template>
</el-table-column>
</el-table>
<!-- 分页 -->
<Pagination
:total="total"
v-model:page="queryParams.pageNo"
v-model:limit="queryParams.pageSize"
@pagination="getList"
/>
</ContentWrap>
<!-- 表单弹窗添加/修改 -->
<KanbanForm ref="formRef" @success="getList" />
</template>
<script setup lang="ts">
import { getBoolDictOptions, DICT_TYPE } from '@/utils/dict'
import { dateFormatter } from '@/utils/formatTime'
import download from '@/utils/download'
import { KanbanApi, KanbanVO } from '@/api/iot/kanban'
import KanbanForm from './KanbanForm.vue'
/** 物联看板 列表 */
defineOptions({ name: 'Kanban' })
const message = useMessage() //
const { t } = useI18n() //
const loading = ref(true) //
const list = ref<KanbanVO[]>([]) //
const total = ref(0) //
const queryParams = reactive({
pageNo: 1,
pageSize: 10,
img: undefined,
remark: undefined,
isEnable: undefined,
createTime: [],
code: undefined,
title: undefined,
viewUrl: undefined,
tags: undefined,
})
const queryFormRef = ref() //
const exportLoading = ref(false) //
/** 查询列表 */
const getList = async () => {
loading.value = true
try {
const data = await KanbanApi.getKanbanPage(queryParams)
list.value = data.list
total.value = data.total
} finally {
loading.value = false
}
}
/** 搜索按钮操作 */
const handleQuery = () => {
queryParams.pageNo = 1
getList()
}
/** 重置按钮操作 */
const resetQuery = () => {
queryFormRef.value.resetFields()
handleQuery()
}
/** 添加/修改操作 */
const formRef = ref()
const openForm = (type: string, id?: number) => {
formRef.value.open(type, id)
}
/** 删除按钮操作 */
const handleDelete = async (id: number) => {
try {
//
await message.delConfirm()
//
await KanbanApi.deleteKanban(id)
message.success(t('common.delSuccess'))
//
await getList()
} catch {}
}
/** 导出按钮操作 */
const handleExport = async () => {
try {
//
await message.exportConfirm()
//
exportLoading.value = true
const data = await KanbanApi.exportKanban(queryParams)
download.excel(data, '物联看板.xls')
} catch {
} finally {
exportLoading.value = false
}
}
/** 初始化 **/
onMounted(() => {
getList()
})
</script>

@ -0,0 +1,206 @@
<template>
<Dialog :title="dialogTitle" v-model="dialogVisible">
<el-form
ref="formRef"
:model="formData"
:rules="formRules"
label-width="100px"
v-loading="formLoading"
>
<el-form-item label="父级装备" prop="parentId">
<el-tree-select
v-model="formData.parentId"
:data="machineComponentTree"
:props="defaultProps"
check-strictly
default-expand-all
placeholder="请选择父级"
/>
</el-form-item>
<el-form-item label="装备名称" prop="name">
<el-input v-model="formData.name" placeholder="请输入装备名称" />
</el-form-item>
<el-form-item label="组织类型" prop="componentType">
<el-radio-group v-model="formData.componentType">
<el-radio
v-for="dict in getIntDictOptions(DICT_TYPE.MES_MACHINE_TYPE)"
:key="dict.value"
:label="dict.value"
>
{{ dict.label }}
</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="显示顺序" prop="sort">
<el-input v-model="formData.sort" placeholder="请输入显示顺序" />
</el-form-item>
<el-form-item label="组织机台" prop="orgId">
<el-input v-model="formData.orgId" placeholder="请输入组织机台" />
</el-form-item>
<el-form-item label="装备SN号" prop="serialCode">
<el-input v-model="formData.serialCode" placeholder="请输入装备SN号" />
</el-form-item>
<el-form-item label="出厂日期" prop="outgoingTime">
<el-date-picker
v-model="formData.outgoingTime"
type="date"
value-format="x"
placeholder="选择出厂日期"
/>
</el-form-item>
<el-form-item label="出厂报告" prop="outgoingReport">
<Editor v-model="formData.outgoingReport" height="150px" />
</el-form-item>
<el-form-item label="位置" prop="position">
<el-input v-model="formData.position" placeholder="请输入位置" />
</el-form-item>
<el-form-item label="规格" prop="standard">
<el-input v-model="formData.standard" placeholder="请输入规格" />
</el-form-item>
<el-form-item label="备注" prop="remark">
<el-input v-model="formData.remark" placeholder="请输入备注" />
</el-form-item>
<el-form-item label="状态" prop="status">
<el-radio-group v-model="formData.status">
<el-radio
v-for="dict in getIntDictOptions(DICT_TYPE.MES_MACHINE_STATUS)"
:key="dict.value"
:label="dict.value"
>
{{ dict.label }}
</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="机台类型" prop="machineType">
<el-select v-model="formData.machineType" placeholder="请选择机台类型">
<el-option
v-for="dict in getStrDictOptions(DICT_TYPE.MES_ORG_TYPE)"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
</el-select>
</el-form-item>
</el-form>
<template #footer>
<el-button @click="submitForm" type="primary" :disabled="formLoading"> </el-button>
<el-button @click="dialogVisible = false"> </el-button>
</template>
</Dialog>
</template>
<script setup lang="ts">
import { getIntDictOptions, getStrDictOptions, DICT_TYPE } from '@/utils/dict'
import { MachineComponentApi, MachineComponentVO } from '@/api/mes/machine'
import { defaultProps, handleTree } from '@/utils/tree'
/** 机台 表单 */
defineOptions({ name: 'MachineComponentForm' })
const { t } = useI18n() //
const message = useMessage() //
const dialogVisible = ref(false) //
const dialogTitle = ref('') //
const formLoading = ref(false) // 12
const formType = ref('') // create - update -
const formData = ref({
id: undefined,
name: undefined,
parentId: undefined,
sort: undefined,
orgId: undefined,
serialCode: undefined,
outgoingTime: undefined,
outgoingReport: undefined,
position: undefined,
standard: undefined,
remark: undefined,
status: undefined,
componentType: undefined,
machineType: undefined,
})
const formRules = reactive({
name: [{ required: true, message: '装备名称不能为空', trigger: 'blur' }],
parentId: [{ required: true, message: '父id不能为空', trigger: 'blur' }],
sort: [{ required: true, message: '显示顺序不能为空', trigger: 'blur' }],
orgId: [{ required: true, message: '组织机台ID不能为空', trigger: 'blur' }],
status: [{ required: true, message: '状态不能为空', trigger: 'blur' }],
componentType: [{ required: true, message: '组织类型不能为空', trigger: 'blur' }],
})
const formRef = ref() // Ref
const machineComponentTree = ref() //
/** 打开弹窗 */
const open = async (type: string, id?: number) => {
dialogVisible.value = true
dialogTitle.value = t('action.' + type)
formType.value = type
resetForm()
//
if (id) {
formLoading.value = true
try {
formData.value = await MachineComponentApi.getMachineComponent(id)
} finally {
formLoading.value = false
}
}
await getMachineComponentTree()
}
defineExpose({ open }) // open
/** 提交表单 */
const emit = defineEmits(['success']) // success
const submitForm = async () => {
//
await formRef.value.validate()
//
formLoading.value = true
try {
const data = formData.value as unknown as MachineComponentVO
if (formType.value === 'create') {
await MachineComponentApi.createMachineComponent(data)
message.success(t('common.createSuccess'))
} else {
await MachineComponentApi.updateMachineComponent(data)
message.success(t('common.updateSuccess'))
}
dialogVisible.value = false
//
emit('success')
} finally {
formLoading.value = false
}
}
/** 重置表单 */
const resetForm = () => {
formData.value = {
id: undefined,
name: undefined,
parentId: undefined,
sort: undefined,
orgId: undefined,
serialCode: undefined,
outgoingTime: undefined,
outgoingReport: undefined,
position: undefined,
standard: undefined,
remark: undefined,
status: undefined,
componentType: undefined,
machineType: undefined,
}
formRef.value?.resetFields()
}
/** 获得机台树 */
const getMachineComponentTree = async () => {
machineComponentTree.value = []
const data = await MachineComponentApi.getMachineComponentList()
const root: Tree = { id: 0, name: '顶级组织', children: [] }
root.children = handleTree(data, 'id', 'parentId')
machineComponentTree.value.push(root)
}
</script>

@ -0,0 +1,330 @@
<template>
<ContentWrap>
<!-- 搜索工作栏 -->
<el-form
class="-mb-15px"
:model="queryParams"
ref="queryFormRef"
:inline="true"
label-width="68px"
>
<el-form-item label="装备名称" prop="name">
<el-input
v-model="queryParams.name"
placeholder="请输入装备名称"
clearable
@keyup.enter="handleQuery"
class="!w-240px"
/>
</el-form-item>
<el-form-item label="父级装备" prop="parentId">
<el-input
v-model="queryParams.parentId"
placeholder="请输入父级装备"
clearable
@keyup.enter="handleQuery"
class="!w-240px"
/>
</el-form-item>
<el-form-item label="组织机台" prop="orgId">
<el-input
v-model="queryParams.orgId"
placeholder="请输入组织机台"
clearable
@keyup.enter="handleQuery"
class="!w-240px"
/>
</el-form-item>
<el-form-item label="装备SN号" prop="serialCode">
<el-input
v-model="queryParams.serialCode"
placeholder="请输入装备SN号"
clearable
@keyup.enter="handleQuery"
class="!w-240px"
/>
</el-form-item>
<el-form-item label="出厂日期" prop="outgoingTime">
<el-date-picker
v-model="queryParams.outgoingTime"
value-format="YYYY-MM-DD HH:mm:ss"
type="daterange"
start-placeholder="开始日期"
end-placeholder="结束日期"
:default-time="[new Date('1 00:00:00'), new Date('1 23:59:59')]"
class="!w-240px"
/>
</el-form-item>
<el-form-item label="规格" prop="standard">
<el-input
v-model="queryParams.standard"
placeholder="请输入规格"
clearable
@keyup.enter="handleQuery"
class="!w-240px"
/>
</el-form-item>
<el-form-item label="备注" prop="remark">
<el-input
v-model="queryParams.remark"
placeholder="请输入备注"
clearable
@keyup.enter="handleQuery"
class="!w-240px"
/>
</el-form-item>
<el-form-item label="状态" prop="status">
<el-select
v-model="queryParams.status"
placeholder="请选择状态"
clearable
class="!w-240px"
>
<el-option
v-for="dict in getIntDictOptions(DICT_TYPE.MES_MACHINE_STATUS)"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
</el-select>
</el-form-item>
<el-form-item label="组织类型" prop="componentType">
<el-select
v-model="queryParams.componentType"
placeholder="请选择组织类型"
clearable
class="!w-240px"
>
<el-option
v-for="dict in getStrDictOptions(DICT_TYPE.MES_MACHINE_TYPE)"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
</el-select>
</el-form-item>
<el-form-item label="机台类型" prop="machineType">
<el-select
v-model="queryParams.machineType"
placeholder="请选择机台类型"
clearable
class="!w-240px"
>
<el-option
v-for="dict in getStrDictOptions(DICT_TYPE.MES_ORG_TYPE)"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
</el-select>
</el-form-item>
<el-form-item>
<el-button @click="handleQuery"><Icon icon="ep:search" class="mr-5px" /> 搜索</el-button>
<el-button @click="resetQuery"><Icon icon="ep:refresh" class="mr-5px" /> 重置</el-button>
<el-button
type="primary"
plain
@click="openForm('create')"
v-hasPermi="['mes:machine-component:create']"
>
<Icon icon="ep:plus" class="mr-5px" /> 新增
</el-button>
<el-button
type="success"
plain
@click="handleExport"
:loading="exportLoading"
v-hasPermi="['mes:machine-component:export']"
>
<Icon icon="ep:download" class="mr-5px" /> 导出
</el-button>
<el-button type="danger" plain @click="toggleExpandAll">
<Icon icon="ep:sort" class="mr-5px" /> 展开/折叠
</el-button>
</el-form-item>
</el-form>
</ContentWrap>
<!-- 列表 -->
<ContentWrap>
<el-table
v-loading="loading"
:data="list"
:stripe="true"
:show-overflow-tooltip="true"
row-key="id"
:default-expand-all="isExpandAll"
v-if="refreshTable"
>
<el-table-column label="装备id" align="center" prop="id" />
<el-table-column label="父装备" align="center" prop="parentId" />
<el-table-column label="装备名称" align="center" prop="name" />
<el-table-column label="装备SN号" align="center" prop="serialCode" />
<el-table-column label="显示顺序" align="center" prop="sort" />
<el-table-column label="组织类型" align="center" prop="componentType">
<template #default="scope">
<dict-tag :type="DICT_TYPE.MES_MACHINE_TYPE" :value="scope.row.componentType" />
</template>
</el-table-column>
<el-table-column label="备注" align="center" prop="remark" />
<el-table-column
label="创建时间"
align="center"
prop="createTime"
:formatter="dateFormatter"
width="180px"
/>
<el-table-column label="状态" align="center" prop="status">
<template #default="scope">
<dict-tag :type="DICT_TYPE.MES_MACHINE_STATUS" :value="scope.row.status" />
</template>
</el-table-column>
<el-table-column label="机台类型" align="center" prop="machineType">
<template #default="scope">
<dict-tag :type="DICT_TYPE.MES_ORG_TYPE" :value="scope.row.machineType" />
</template>
</el-table-column>
<el-table-column label="操作" align="center" min-width="120px" >
<template #default="scope">
<el-button
link
type="primary"
@click="openForm('update', scope.row.id)"
v-hasPermi="['mes:machine-component:update']"
>
编辑
</el-button>
<el-button
link
type="danger"
@click="handleDelete(scope.row.id)"
v-hasPermi="['mes:machine-component:delete']"
>
删除
</el-button>
</template>
</el-table-column>
</el-table>
<!-- 分页 -->
<Pagination
:total="total"
v-model:page="queryParams.pageNo"
v-model:limit="queryParams.pageSize"
@pagination="getList"
/>
</ContentWrap>
<!-- 表单弹窗添加/修改 -->
<MachineComponentForm ref="formRef" @success="getList" />
</template>
<script setup lang="ts">
import { getIntDictOptions, getStrDictOptions, DICT_TYPE } from '@/utils/dict'
import { dateFormatter } from '@/utils/formatTime'
import { handleTree } from '@/utils/tree'
import download from '@/utils/download'
import { MachineComponentApi, MachineComponentVO } from '@/api/mes/machine'
import MachineComponentForm from './MachineComponentForm.vue'
/** 机台 列表 */
defineOptions({ name: 'MachineComponent' })
const message = useMessage() //
const { t } = useI18n() //
const loading = ref(true) //
const list = ref<MachineComponentVO[]>([]) //
const queryParams = reactive({
name: undefined,
parentId: undefined,
sort: undefined,
orgId: undefined,
serialCode: undefined,
outgoingTime: [],
outgoingReport: undefined,
position: undefined,
standard: undefined,
remark: undefined,
createTime: [],
status: undefined,
componentType: undefined,
machineType: undefined,
})
const queryFormRef = ref() //
const exportLoading = ref(false) //
/** 查询列表 */
const getList = async () => {
loading.value = true
try {
const data = await MachineComponentApi.getMachineComponentList(queryParams)
list.value = handleTree(data, 'id', 'parentId')
} finally {
loading.value = false
}
}
/** 搜索按钮操作 */
const handleQuery = () => {
queryParams.pageNo = 1
getList()
}
/** 重置按钮操作 */
const resetQuery = () => {
queryFormRef.value.resetFields()
handleQuery()
}
/** 添加/修改操作 */
const formRef = ref()
const openForm = (type: string, id?: number) => {
formRef.value.open(type, id)
}
/** 删除按钮操作 */
const handleDelete = async (id: number) => {
try {
//
await message.delConfirm()
//
await MachineComponentApi.deleteMachineComponent(id)
message.success(t('common.delSuccess'))
//
await getList()
} catch {}
}
/** 导出按钮操作 */
const handleExport = async () => {
try {
//
await message.exportConfirm()
//
exportLoading.value = true
const data = await MachineComponentApi.exportMachineComponent(queryParams)
download.excel(data, '机台.xls')
} catch {
} finally {
exportLoading.value = false
}
}
/** 展开/折叠操作 */
const isExpandAll = ref(true) //
const refreshTable = ref(true) //
const toggleExpandAll = async () => {
refreshTable.value = false
isExpandAll.value = !isExpandAll.value
await nextTick()
refreshTable.value = true
}
/** 初始化 **/
onMounted(() => {
getList()
})
</script>
Loading…
Cancel
Save