|
@@ -1,5 +1,9 @@
|
|
|
<template>
|
|
|
- <Dialog v-model="dialogVisible" title="选择物料" style="width: 1200px; min-height: 400px">
|
|
|
+ <Dialog v-model="dialogVisible" title="选择物料" style="width: 1400px; min-height: 400px">
|
|
|
+
|
|
|
+ <div ref="measureSpan"
|
|
|
+ style="position:absolute;left:-9999px;top:-9999px;visibility:hidden;white-space:nowrap;padding:0 15px;font:14px Arial, PingFang SC, Microsoft YaHei, sans-serif;">
|
|
|
+ </div>
|
|
|
|
|
|
<!-- 设备分类和BOM节点信息显示 -->
|
|
|
<div style="margin: 0 0px 15px; background: #f5f7fa; padding: 12px 20px; border-radius: 4px;">
|
|
@@ -123,7 +127,7 @@
|
|
|
:data="list"
|
|
|
:stripe="true"
|
|
|
ref="tableRef"
|
|
|
- :show-overflow-tooltip="true"
|
|
|
+ class="adaptive-table"
|
|
|
@row-click="handleRowClick"
|
|
|
:row-class-name="rowClassName"
|
|
|
>
|
|
@@ -152,8 +156,7 @@
|
|
|
:label="t('workOrderMaterial.factory')"
|
|
|
align="center"
|
|
|
prop="factory"
|
|
|
- :show-overflow-tooltip="true"
|
|
|
- class="!w-100px"
|
|
|
+ :width="flexColumnWidth('factory', t('workOrderMaterial.factory'))"
|
|
|
/>
|
|
|
<el-table-column
|
|
|
:label="t('workOrderMaterial.costCenter')"
|
|
@@ -166,8 +169,7 @@
|
|
|
:label="t('workOrderMaterial.costCenter')"
|
|
|
align="center"
|
|
|
prop="costCenter"
|
|
|
- :show-overflow-tooltip="true"
|
|
|
- class="!w-100px"
|
|
|
+ :width="flexColumnWidth('costCenter', t('workOrderMaterial.costCenter'))"
|
|
|
/>
|
|
|
<el-table-column
|
|
|
:label="t('workOrderMaterial.storageLocation')"
|
|
@@ -180,27 +182,23 @@
|
|
|
:label="t('workOrderMaterial.storageLocation')"
|
|
|
align="center"
|
|
|
prop="projectDepartment"
|
|
|
- :show-overflow-tooltip="true"
|
|
|
- class="!w-100px"
|
|
|
+ :width="flexColumnWidth('projectDepartment', t('workOrderMaterial.storageLocation'))"
|
|
|
/>
|
|
|
<el-table-column
|
|
|
:label="t('workOrderMaterial.materialCode')"
|
|
|
align="center"
|
|
|
prop="materialCode"
|
|
|
- :show-overflow-tooltip="true"
|
|
|
- class="!w-100px"
|
|
|
+ :width="flexColumnWidth('materialCode', t('workOrderMaterial.materialCode'))"
|
|
|
/>
|
|
|
<el-table-column
|
|
|
:label="t('workOrderMaterial.materialName')"
|
|
|
align="center"
|
|
|
prop="materialName"
|
|
|
- :show-overflow-tooltip="true"
|
|
|
+ :class-name="'material-name-cell'"
|
|
|
+ :width="materialNameWidth"
|
|
|
/>
|
|
|
- <el-table-column :label="t('workOrderMaterial.unit')" align="center" prop="unit" />
|
|
|
- <el-table-column :label="t('workOrderMaterial.unitPrice')" align="center" prop="unitPrice" />
|
|
|
- <el-table-column :label="t('workOrderMaterial.total')" align="center" prop="totalInventoryQuantity" />
|
|
|
- <el-table-column :label="t('workOrderMaterial.source')" align="center" prop="materialSource" />
|
|
|
- <el-table-column :label="t('workOrderMaterial.ConsumptionQuantity')" align="center" prop="quantity">
|
|
|
+ <el-table-column :label="t('workOrderMaterial.ConsumptionQuantity')" align="center" prop="quantity"
|
|
|
+ :width="flexColumnWidth('quantity', t('workOrderMaterial.ConsumptionQuantity'), 20)">
|
|
|
<template #default="scope">
|
|
|
<el-input
|
|
|
type="number"
|
|
@@ -212,6 +210,15 @@
|
|
|
/>
|
|
|
</template>
|
|
|
</el-table-column>
|
|
|
+ <el-table-column :label="t('workOrderMaterial.unit')" align="center" prop="unit"
|
|
|
+ :width="flexColumnWidth('unit', t('workOrderMaterial.unit'))"/>
|
|
|
+ <el-table-column :label="t('workOrderMaterial.unitPrice')" align="center" prop="unitPrice"
|
|
|
+ :width="flexColumnWidth('unitPrice', t('workOrderMaterial.unitPrice'))"/>
|
|
|
+ <el-table-column :label="t('workOrderMaterial.total')" align="center" prop="totalInventoryQuantity"
|
|
|
+ :width="flexColumnWidth('totalInventoryQuantity', t('workOrderMaterial.total'))"/>
|
|
|
+ <el-table-column :label="t('workOrderMaterial.source')" align="center" prop="materialSource"
|
|
|
+ :width="flexColumnWidth('materialSource', t('workOrderMaterial.source'))"/>
|
|
|
+
|
|
|
</el-table>
|
|
|
<!-- 分页 -->
|
|
|
<Pagination
|
|
@@ -252,8 +259,15 @@ const queryFormRef = ref() // 搜索的表单
|
|
|
const list = ref<WorkOrderBomMaterialApi.IotMainWorkOrderBomMaterialVO[]>([]) // 列表的数据
|
|
|
const total = ref(0) // 列表的总页数
|
|
|
const tableRef = ref()
|
|
|
+const tableContainer = ref<HTMLElement | null>(null) // 表格容器引用
|
|
|
const selectedRows = ref<WorkOrderBomMaterialApi.IotMainWorkOrderBomMaterialVO[]>([]) // 多选数据(存储所有选中行的数组)
|
|
|
|
|
|
+// 物料名称列宽度(作为基准列)
|
|
|
+const materialNameWidth = ref<number | string>(0)
|
|
|
+
|
|
|
+// 测量容器引用
|
|
|
+const measureSpan = ref<HTMLDivElement | null>(null)
|
|
|
+
|
|
|
const showMaterialArea = ref(false) // 控制A区域显示状态
|
|
|
const deviceBomMaterials = ref<any[]>([]) // 存储绑定物料数据
|
|
|
|
|
@@ -356,6 +370,85 @@ const open = async (deptId: number, bomNodeId: number, row: any, type: string) =
|
|
|
|
|
|
defineExpose({ open }) // 提供 open 方法,用于打开弹窗
|
|
|
|
|
|
+// 文本宽度测量
|
|
|
+const getTextWidth = (text: string) => {
|
|
|
+ if (!measureSpan.value) return 0
|
|
|
+ measureSpan.value.innerText = text
|
|
|
+ return measureSpan.value.offsetWidth
|
|
|
+}
|
|
|
+
|
|
|
+// 列宽计算方法
|
|
|
+const flexColumnWidth = (prop: string, label: string, extra: number = 0) => {
|
|
|
+ if (!list.value || list.value.length === 0) {
|
|
|
+ return getTextWidth(label) + extra
|
|
|
+ }
|
|
|
+
|
|
|
+ const contentList = list.value.map(item => {
|
|
|
+ const value = item[prop]
|
|
|
+ if (value == null) return ' '
|
|
|
+ return typeof value === 'number' ? value.toString() : value
|
|
|
+ })
|
|
|
+
|
|
|
+ contentList.push(label)
|
|
|
+ const maxWidth = Math.max(...contentList.map(text => getTextWidth(text)))
|
|
|
+ return Math.min(maxWidth + extra, 400)
|
|
|
+}
|
|
|
+
|
|
|
+// 计算所有列的总宽度(物料名称列除外)
|
|
|
+const calculateTotalColumnWidth = () => {
|
|
|
+ const columns = [
|
|
|
+ // 复选框列(固定60px)
|
|
|
+ 60,
|
|
|
+ // 工厂列
|
|
|
+ flexColumnWidth('factory', t('workOrderMaterial.factory')),
|
|
|
+ // 成本中心列
|
|
|
+ flexColumnWidth('costCenter', t('workOrderMaterial.costCenter')),
|
|
|
+ // 库存地点列
|
|
|
+ flexColumnWidth('projectDepartment', t('workOrderMaterial.storageLocation')),
|
|
|
+ // 物料编码列
|
|
|
+ flexColumnWidth('materialCode', t('workOrderMaterial.materialCode')),
|
|
|
+ // 消耗数量列
|
|
|
+ flexColumnWidth('quantity', t('workOrderMaterial.ConsumptionQuantity'), 20),
|
|
|
+ // 单位列
|
|
|
+ flexColumnWidth('unit', t('workOrderMaterial.unit')),
|
|
|
+ // 单价列
|
|
|
+ flexColumnWidth('unitPrice', t('workOrderMaterial.unitPrice')),
|
|
|
+ // 总库存数量列
|
|
|
+ flexColumnWidth('totalInventoryQuantity', t('workOrderMaterial.total')),
|
|
|
+ // 来源列
|
|
|
+ flexColumnWidth('materialSource', t('workOrderMaterial.source'))
|
|
|
+ ]
|
|
|
+
|
|
|
+ return columns.reduce((total, width) => total + width, 0)
|
|
|
+}
|
|
|
+
|
|
|
+// 调整物料名称列宽度(作为基准列)
|
|
|
+const adjustMaterialNameWidth = () => {
|
|
|
+ nextTick(() => {
|
|
|
+ if (!tableContainer.value) return
|
|
|
+
|
|
|
+ // 获取表格容器的宽度
|
|
|
+ const containerWidth = tableContainer.value.$el.clientWidth
|
|
|
+
|
|
|
+ // 计算所有列的总宽度(物料名称列除外)
|
|
|
+ const totalWidth = calculateTotalColumnWidth()
|
|
|
+
|
|
|
+ // 计算可用空间(预留20px用于边框和滚动条)
|
|
|
+ const availableSpace = containerWidth - totalWidth - 20
|
|
|
+
|
|
|
+ if (availableSpace > 0) {
|
|
|
+ // 如果空间足够,分配剩余空间给物料名称列
|
|
|
+ materialNameWidth.value = Math.max(
|
|
|
+ flexColumnWidth('materialName', t('workOrderMaterial.materialName')),
|
|
|
+ availableSpace
|
|
|
+ )
|
|
|
+ } else {
|
|
|
+ // 如果空间不足,按内容自适应
|
|
|
+ materialNameWidth.value = flexColumnWidth('materialName', t('workOrderMaterial.materialName'))
|
|
|
+ }
|
|
|
+ })
|
|
|
+}
|
|
|
+
|
|
|
const getList = async () => {
|
|
|
loading.value = true
|
|
|
try {
|
|
@@ -366,6 +459,10 @@ const getList = async () => {
|
|
|
total.value = data.total
|
|
|
} finally {
|
|
|
loading.value = false
|
|
|
+ // 数据加载完成后调整基准列宽度
|
|
|
+ nextTick(() => {
|
|
|
+ adjustMaterialNameWidth()
|
|
|
+ })
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -496,6 +593,22 @@ const resetQuery = () => {
|
|
|
Object.assign(queryParams, defaultQueryParams)
|
|
|
handleQuery()
|
|
|
}
|
|
|
+
|
|
|
+// 窗口大小改变时重新计算列宽
|
|
|
+const handleResize = () => {
|
|
|
+ adjustMaterialNameWidth()
|
|
|
+}
|
|
|
+
|
|
|
+onMounted(() => {
|
|
|
+ // 添加窗口大小变化监听器
|
|
|
+ window.addEventListener('resize', handleResize)
|
|
|
+})
|
|
|
+
|
|
|
+onUnmounted(() => {
|
|
|
+ // 移除窗口大小变化监听器
|
|
|
+ window.removeEventListener('resize', handleResize)
|
|
|
+})
|
|
|
+
|
|
|
</script>
|
|
|
<style lang="scss" scoped>
|
|
|
.no-label-radio .el-radio__label {
|
|
@@ -532,4 +645,31 @@ const resetQuery = () => {
|
|
|
:deep(.el-table .bg-blue-5) {
|
|
|
background-color: #3fa5de !important; /* Element Plus 绿色背景 */
|
|
|
}
|
|
|
+
|
|
|
+// 表格自适应样式
|
|
|
+:deep(.adaptive-table) {
|
|
|
+ width: 100%;
|
|
|
+
|
|
|
+ .el-table__cell {
|
|
|
+ .cell {
|
|
|
+ white-space: nowrap; /* 禁止换行 */
|
|
|
+ overflow: hidden;
|
|
|
+ text-overflow: ellipsis;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ // 确保基准列使用可用空间
|
|
|
+ .material-name-cell .cell {
|
|
|
+ display: block;
|
|
|
+ overflow: hidden;
|
|
|
+ text-overflow: ellipsis;
|
|
|
+ max-width: 100%;
|
|
|
+ }
|
|
|
+
|
|
|
+}
|
|
|
+
|
|
|
+// 移除溢出提示(防止省略号)
|
|
|
+:deep(.el-tooltip) {
|
|
|
+ overflow: visible !important;
|
|
|
+}
|
|
|
+
|
|
|
</style>
|