MaterialListDrawer.vue 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205
  1. <template>
  2. <el-drawer
  3. title="物料详情"
  4. :append-to-body="true"
  5. :model-value="modelValue"
  6. @update:model-value="$emit('update:modelValue', $event)"
  7. :show-close="false"
  8. direction="rtl"
  9. :size="computedSize"
  10. :before-close="handleClose"
  11. >
  12. <template v-if="nodeId">
  13. <div v-loading="loading" style="height: 100%">
  14. <div class="info-header">
  15. <div class="info-item">
  16. <span class="info-label">设备分类:</span>
  17. <span class="info-value">{{ rowInfo.deviceCategoryName }}</span>
  18. </div>
  19. <div class="separator"></div> <!-- 分隔线 -->
  20. <div class="info-item">
  21. <span class="info-label">BOM节点:</span>
  22. <span class="info-value">{{ rowInfo.bomNodeName }}</span>
  23. </div>
  24. </div>
  25. <el-table :data="materials" style="width: 100%">
  26. <el-table-column prop="name" label="物料名称" width="180" />
  27. <el-table-column prop="code" label="物料编码" width="180" />
  28. <!-- <el-table-column prop="model" label="规格型号" width="180" /> -->
  29. <el-table-column prop="unit" label="单位" width="180" />
  30. <el-table-column
  31. label="创建时间"
  32. align="center"
  33. prop="createTime"
  34. width="180"
  35. :formatter="dateFormatter"
  36. />
  37. <el-table-column label="操作" align="right">
  38. <template #default="scope">
  39. <el-button
  40. size="small"
  41. type="danger"
  42. @click="handleDelete(scope.row)"
  43. >删除</el-button>
  44. </template>
  45. </el-table-column>
  46. </el-table>
  47. <!-- 分页 -->
  48. <Pagination
  49. :total="total"
  50. v-model:page="queryParams.pageNo"
  51. v-model:limit="queryParams.pageSize"
  52. @pagination="loadMaterials(props.nodeId)"
  53. />
  54. </div>
  55. </template>
  56. </el-drawer>
  57. </template>
  58. <script setup lang="ts">
  59. import { ref, watch, defineOptions, defineEmits } from 'vue'
  60. import { ElMessage } from 'element-plus'
  61. import * as PmsMaterialApi from '@/api/pms/material'
  62. import {CommonBomMaterialApi, CommonBomMaterialVO} from '@/api/pms/commonbommaterial'
  63. import {dateFormatter} from "@/utils/formatTime";
  64. const drawerVisible = ref<boolean>(false)
  65. const emit = defineEmits(['update:modelValue', 'add', 'delete', 'refresh'])
  66. const message = useMessage() // 消息弹窗
  67. const { t } = useI18n() // 国际化
  68. defineOptions({
  69. name: 'MaterialListDrawer'
  70. })
  71. const queryParams = reactive({
  72. pageNo: 1,
  73. pageSize: 10,
  74. createTime: [],
  75. bomId: '',
  76. name: '',
  77. code: ''
  78. })
  79. const windowWidth = ref(window.innerWidth)
  80. // 动态计算百分比
  81. const computedSize = computed(() => {
  82. return windowWidth.value > 1200 ? '60%' : '80%'
  83. })
  84. const loading = ref(false)
  85. const total = ref(0) // 列表的总页数
  86. const materials = ref([])
  87. const props = defineProps({
  88. modelValue: Boolean,
  89. nodeId: Number,
  90. rowInfo: { // 新增props
  91. type: Object,
  92. default: () => ({
  93. deviceCategoryName: '',
  94. bomNodeName: ''
  95. })
  96. }
  97. })
  98. // 监听bom树节点ID变化
  99. watch(() => props.nodeId, async (newVal) => {
  100. if (newVal) {
  101. await loadMaterials(newVal)
  102. }
  103. })
  104. // 加载指定bom节点下的物料数据
  105. const loadMaterials = async (nodeId) => {
  106. queryParams.bomId = nodeId
  107. queryParams.pageNo = 1
  108. try {
  109. loading.value = true
  110. // API调用
  111. const data = await PmsMaterialApi.listByBomId(queryParams)
  112. materials.value = data.list
  113. total.value = data.total
  114. } catch (error) {
  115. ElMessage.error('数据加载失败')
  116. } finally {
  117. loading.value = false
  118. }
  119. }
  120. /** 删除BOM节点已经挂载的物料 */
  121. const handleDelete = async (row) => {
  122. try {
  123. // 删除的二次确认
  124. await message.delConfirm()
  125. // 发起删除
  126. await CommonBomMaterialApi.deleteBomMaterial(props.nodeId, row.code)
  127. message.success(t('common.delSuccess'))
  128. // 刷新列表
  129. loadMaterials(props.nodeId)
  130. } catch {}
  131. }
  132. // 打开抽屉
  133. const openDrawer = () => {
  134. drawerVisible.value = true
  135. }
  136. // 关闭抽屉
  137. const closeDrawer = () => {
  138. drawerVisible.value = false
  139. }
  140. // 关闭抽屉
  141. const handleClose = () => {
  142. emit('update:modelValue', false)
  143. emit('refresh') // 添加刷新事件
  144. materials.value = []
  145. }
  146. defineExpose({ openDrawer, closeDrawer, loadMaterials }) // 暴露方法给父组件
  147. </script>
  148. <style lang="scss" scoped>
  149. .info-header {
  150. display: flex;
  151. align-items: center;
  152. padding: 18px 24px;
  153. background-color: #f5f7fa;
  154. border-bottom: 1px solid #ebeef5;
  155. margin-bottom: 20px;
  156. .info-item {
  157. flex: 1; /* 平分宽度 */
  158. display: flex;
  159. align-items: center; /* 垂直居中 */
  160. }
  161. .separator {
  162. width: 1px;
  163. height: 40px;
  164. background-color: #dcdfe6;
  165. margin: 0 24px;
  166. }
  167. .info-label {
  168. font-weight: bold;
  169. color: #606266;
  170. margin-right: 8px; /* 标签和值之间的间距 */
  171. font-size: 14px;
  172. white-space: nowrap; /* 防止标签换行 */
  173. }
  174. .info-value {
  175. color: #303133;
  176. font-size: 16px;
  177. font-weight: 500;
  178. white-space: nowrap; /* 防止值换行 */
  179. overflow: hidden;
  180. text-overflow: ellipsis; /* 超出部分显示省略号 */
  181. }
  182. }
  183. </style>