| | |
| | | }); |
| | | }; |
| | | |
| | | // 绑定物联设备到库存 |
| | | export const bindIotDevice = (id, warehouse) => { |
| | | // 批量获取物联设备实时数采数据(POST请求,传递设备ID数组) |
| | | export const batchGetIotRealtimeData = (deviceIds) => { |
| | | return request({ |
| | | url: `/stockInventory/bindIotDevice/${id}`, |
| | | method: "put", |
| | | data: { warehouse }, |
| | | url: `/stockInventory/iotRealtime`, |
| | | method: "post", |
| | | data: deviceIds, |
| | | }); |
| | | }; |
| | | |
| | |
| | | <script setup> |
| | | import { ref, computed, onMounted, getCurrentInstance } from "vue"; |
| | | import { getLedgerPage } from "@/api/equipmentManagement/ledger.js"; |
| | | import { bindIotDevice } from "@/api/inventoryManagement/stockInventory.js"; |
| | | import { createStockInventory } from "@/api/inventoryManagement/stockInventory.js"; |
| | | |
| | | const props = defineProps({ |
| | | visible: { |
| | |
| | | submitLoading.value = true; |
| | | // 将设备ID数组转换为逗号分隔的字符串 |
| | | const warehouse = formState.value.deviceIds.join(","); |
| | | bindIotDevice(props.record.id, warehouse) |
| | | // 使用库存新增/编辑接口,warehouse 字段传设备ID |
| | | const submitData = { |
| | | id: props.record.id, |
| | | productModelId: props.record.productModelId, |
| | | batchNo: props.record.batchNo, |
| | | qualitity: props.record.qualitity, |
| | | warehouse: warehouse, |
| | | }; |
| | | createStockInventory(submitData) |
| | | .then(res => { |
| | | submitLoading.value = false; |
| | | proxy.$modal.msgSuccess("绑定成功"); |
| | |
| | | </div> |
| | | <div class="device-status"> |
| | | <span class="status-dot" :class="getStatusClass(device.status)"></span> |
| | | <span :class="getStatusTextClass(device.status)">{{ device.status || '未知' }}</span> |
| | | <span :class="getStatusTextClass(device.status)">{{ getStatusLabel(device.status) }}</span> |
| | | </div> |
| | | </div> |
| | | </template> |
| | |
| | | </el-row> |
| | | </div> |
| | | <div v-else class="device-offline"> |
| | | <el-alert :title="device.statusMessage || '设备离线'" type="warning" :closable="false" show-icon /> |
| | | <el-alert :title="device.statusMessage || (device.status === 'error' ? '设备异常' : '设备离线')" :type="device.status === 'error' ? 'error' : 'warning'" :closable="false" show-icon /> |
| | | </div> |
| | | </el-card> |
| | | </div> |
| | |
| | | |
| | | <script setup> |
| | | import { ref, computed, onMounted, onUnmounted, watch } from "vue"; |
| | | import { getIotRealtimeData } from "@/api/inventoryManagement/stockInventory.js"; |
| | | import { batchGetIotRealtimeData } from "@/api/inventoryManagement/stockInventory.js"; |
| | | import { Refresh, Sunny, Drizzling, WindPower, Sunrise, Lightning } from "@element-plus/icons-vue"; |
| | | |
| | | const props = defineProps({ |
| | |
| | | } |
| | | }; |
| | | |
| | | const getStatusLabel = (status) => { |
| | | switch (status) { |
| | | case "在线": |
| | | return "在线"; |
| | | case "offline": |
| | | return "离线"; |
| | | case "error": |
| | | return "异常"; |
| | | default: |
| | | return "离线"; |
| | | } |
| | | }; |
| | | |
| | | const fetchData = async () => { |
| | | if (!props.record.id) return; |
| | | const deviceIdsStr = props.record?.warehouse; |
| | | console.log("fetchData called, warehouse:", deviceIdsStr); |
| | | if (!deviceIdsStr) { |
| | | console.warn("warehouse is empty, skip fetch"); |
| | | deviceData.value = { inventoryId: null, iotDeviceIds: "", devices: [] }; |
| | | return; |
| | | } |
| | | loading.value = true; |
| | | try { |
| | | const res = await getIotRealtimeData(props.record.id); |
| | | const deviceIds = deviceIdsStr.split(",").map(id => id.trim()).filter(id => id); |
| | | const res = await batchGetIotRealtimeData(deviceIds); |
| | | |
| | | if (res.code === 200 && res.data) { |
| | | deviceData.value = res.data; |
| | | } else { |
| | | deviceData.value = { inventoryId: null, iotDeviceIds: deviceIdsStr, devices: [] }; |
| | | } |
| | | } catch (error) { |
| | | console.error("获取物联设备数据失败:", error); |
| | |
| | | isShow.value = false; |
| | | }; |
| | | |
| | | // 监听弹窗显示状态,每次打开时获取数据 |
| | | watch(() => props.visible, (val) => { |
| | | console.log("visible changed:", val, "record:", props.record); |
| | | if (val) { |
| | | fetchData(); |
| | | } else { |
| | | // 关闭时停止自动刷新 |
| | | autoRefresh.value = false; |
| | | } |
| | | }, { immediate: true }); |
| | | |
| | | // 自动刷新 |
| | | watch(autoRefresh, (val) => { |
| | | if (val) { |
| | |
| | | refreshTimer = null; |
| | | } |
| | | } |
| | | }); |
| | | |
| | | onMounted(() => { |
| | | fetchData(); |
| | | }); |
| | | |
| | | onUnmounted(() => { |
| | |
| | | <el-table-column label="批号" |
| | | prop="batchNo" |
| | | show-overflow-tooltip /> |
| | | <el-table-column label="仓库" |
| | | <el-table-column label="物联设备" |
| | | prop="warehouse" |
| | | show-overflow-tooltip /> |
| | | show-overflow-tooltip |
| | | min-width="150"> |
| | | <template #default="scope"> |
| | | {{ getDeviceNames(scope.row.warehouse) }} |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="合格库存数量" |
| | | prop="qualifiedQuantity" |
| | | show-overflow-tooltip /> |
| | |
| | | show-overflow-tooltip /> |
| | | <el-table-column fixed="right" |
| | | label="操作" |
| | | min-width="190" |
| | | width="210" |
| | | align="center"> |
| | | <template #default="scope"> |
| | | <el-button link |
| | |
| | | import { ref, reactive, toRefs, onMounted, getCurrentInstance } from "vue"; |
| | | import { ElMessage, ElMessageBox } from "element-plus"; |
| | | import { getStockInventoryListPageCombined } from "@/api/inventoryManagement/stockInventory.js"; |
| | | import { getLedgerPage } from "@/api/equipmentManagement/ledger.js"; |
| | | const props = defineProps({ |
| | | productId: { |
| | | type: Number, |
| | |
| | | const isShowBindDeviceModal = ref(false); |
| | | // 是否显示物联数采弹框 |
| | | const isShowIotDataModal = ref(false); |
| | | // 设备列表(用于显示设备名称) |
| | | const deviceList = ref([]); |
| | | const data = reactive({ |
| | | searchForm: { |
| | | productName: "", |
| | |
| | | }); |
| | | }; |
| | | |
| | | // 获取设备列表 |
| | | const getDeviceList = async () => { |
| | | try { |
| | | const res = await getLedgerPage({ |
| | | isIotDevice: 1, |
| | | page: 1, |
| | | size: 999, |
| | | }); |
| | | if (res.data && res.data.records) { |
| | | deviceList.value = res.data.records; |
| | | } |
| | | } catch (error) { |
| | | console.error("获取设备列表失败:", error); |
| | | } |
| | | }; |
| | | |
| | | // 根据设备ID获取设备名称 |
| | | const getDeviceNames = (warehouse) => { |
| | | if (!warehouse) return "-"; |
| | | const deviceIds = warehouse.split(",").map(id => id.trim()); |
| | | const names = deviceIds |
| | | .map(id => { |
| | | const device = deviceList.value.find(d => String(d.id) === id); |
| | | return device ? device.deviceName : id; |
| | | }) |
| | | .filter(name => name); |
| | | return names.length > 0 ? names.join(", ") : warehouse; |
| | | }; |
| | | |
| | | onMounted(() => { |
| | | getList(); |
| | | getDeviceList(); |
| | | }); |
| | | </script> |
| | | |
| | |
| | | selectedRows.value = rows; |
| | | dialogVisible.value = true; |
| | | |
| | | // 计算选中行的总数量 |
| | | const totalQuantity = rows.reduce((sum, row) => sum + (Number(row.quantity) || 0), 0); |
| | | |
| | | // 加载用户列表 |
| | | const userListsRes = await userListNoPage(); |
| | | userList.value = userListsRes.data; |
| | |
| | | form.value = { |
| | | checkResult: '', |
| | | testStandardId: '', |
| | | quantity: undefined, |
| | | qualifiedQuantity: undefined, |
| | | unqualifiedQuantity: undefined, |
| | | quantity: totalQuantity, |
| | | qualifiedQuantity: totalQuantity, |
| | | unqualifiedQuantity: 0, |
| | | checkCompany: '', |
| | | checkName: '', |
| | | checkTime: '', |