Sfoglia il codice sorgente

pms 本地库存工厂成本中心联动 bom删除包含子节点的节点 设备动态默认选中当前登录人组织

zhangcl 1 mese fa
parent
commit
178cd7a591

+ 4 - 0
src/api/system/saporg/index.ts

@@ -37,6 +37,10 @@ export const SapOrgApi = {
     return await request.get({ url: '/system/sap-org/simple-list?type=' + type })
   },
 
+  filteredSimpleSapOrgList: async (type: number, deptId: number): Promise<SapOrgVO[]> => {
+    return await request.get({ url: '/system/sap-org/filteredSimpleSapOrgList?type=' + type + '&deptId=' + deptId })
+  },
+
   getSelectedList: async (data: any): Promise<SapOrgVO[]> => {
     return await request.post({ url: '/system/sap-org/selectedSimpleList', data })
   },

+ 1 - 1
src/utils/permission.ts

@@ -22,7 +22,7 @@ export function checkRole(value: string[]) {
   if (value && value instanceof Array && value.length > 0) {
     const { wsCache } = useCache()
     const permissionRoles = value
-    const super_admin = 'super_admin'
+    const super_admin = ''
     const userInfo = wsCache.get(CACHE_KEY.USER)
     const roles = userInfo?.roles || []
     const hasRole = roles.some((role: string) => {

+ 33 - 0
src/views/pms/bom/index.vue

@@ -395,6 +395,15 @@ const clearRowSelection = () => {
 /** 删除按钮操作 */
 const handleDelete = async (id: number) => {
   try {
+    // 查找目标节点及其在树中的位置
+    const targetNode = findNodeById(list.value, id);
+
+    // 检查是否存在子节点(使用 children 属性)
+    if (targetNode && targetNode.children && targetNode.children.length > 0) {
+      message.error('当前BOM节点包含子节点,不可删除');
+      return;
+    }
+
     // 删除的二次确认
     await message.delConfirm()
     // 发起删除
@@ -423,6 +432,30 @@ const isExpanded = (row) => {
   return $table?.__vue__.store.states.expandRows.value.includes(row)
 }
 
+/**
+ * 递归查找树节点
+ * 基于 handleTree 处理后的树结构(包含 children 属性)
+ * @param nodes 树节点数组
+ * @param id 要查找的节点ID
+ * @returns 找到的节点或 undefined
+ */
+const findNodeById = (nodes: any[], id: number): any | undefined => {
+  // 遍历当前层级节点
+  for (const node of nodes) {
+    // 1. 检查当前节点是否匹配
+    if (node.id === id) return node;
+
+    // 2. 检查当前节点是否有子节点
+    if (node.children && node.children.length > 0) {
+      // 递归搜索子节点
+      const foundInChildren = findNodeById(node.children, id);
+      if (foundInChildren) return foundInChildren;
+    }
+  }
+
+  return undefined; // 未找到
+};
+
 </script>
 
 <style scoped>

+ 22 - 2
src/views/pms/device/allotlog/ConfigDeviceAllot.vue

@@ -389,8 +389,28 @@ const submitRelations = async () => {
 
 /** 初始化 */
 onMounted(async () => {
-  // 初始化部门树 根据选择的部门 查询设备列表 部门人员列表
-  deptList.value = handleTree(await DeptApi.getSimpleDeptList())
+  try {
+    // 初始化部门树
+    const deptData = await DeptApi.getSimpleDeptList()
+    deptList.value = handleTree(deptData) // 转换为树形结构
+
+    // 设置默认选中的部门(转换后树的第一个节点)
+    if (deptList.value.length > 0) {
+      // 获取转换后树的第一个节点
+      const firstRootNode = deptList.value[0]
+
+      // 设置设备部门的默认值
+      formData.value.deptId1 = firstRootNode.id
+      // 触发设备部门的节点点击事件,加载设备列表
+      await handleDeptDeviceTreeNodeClick(firstRootNode)
+    } else {
+      console.warn("部门树数据为空,无法设置默认值")
+    }
+  } catch (error) {
+    console.error("初始化部门树失败:", error)
+    ElMessage.error("加载部门数据失败")
+  }
+
   nextTick(() => {
     // 强制重新计算布局
     window.dispatchEvent(new Event('resize'))

+ 32 - 0
src/views/pms/device/bom/BomList.vue

@@ -335,9 +335,41 @@ const toggleExpandAll = () => {
   })
 }
 
+/**
+ * 递归查找树节点
+ * 基于 handleTree 处理后的树结构(包含 children 属性)
+ * @param nodes 树节点数组
+ * @param id 要查找的节点ID
+ * @returns 找到的节点或 undefined
+ */
+const findNodeById = (nodes: any[], id: number): any | undefined => {
+  // 遍历当前层级节点
+  for (const node of nodes) {
+    // 1. 检查当前节点是否匹配
+    if (node.id === id) return node;
+
+    // 2. 检查当前节点是否有子节点
+    if (node.children && node.children.length > 0) {
+      // 递归搜索子节点
+      const foundInChildren = findNodeById(node.children, id);
+      if (foundInChildren) return foundInChildren;
+    }
+  }
+
+  return undefined; // 未找到
+};
+
 /** 删除按钮操作 */
 const handleDelete = async (id: number) => {
   try {
+    // 查找目标节点及其在树中的位置
+    const targetNode = findNodeById(list.value, id);
+    // 检查是否存在子节点(使用 children 属性)
+    if (targetNode && targetNode.children && targetNode.children.length > 0) {
+      message.error('当前BOM节点包含子节点,不可删除');
+      return;
+    }
+
     // 删除的二次确认
     await message.delConfirm()
     // 发起删除

+ 26 - 2
src/views/pms/device/personlog/ConfigDevicePerson.vue

@@ -460,8 +460,32 @@ const submitRelations = async () => {
 
 /** 初始化 */
 onMounted(async () => {
-  // 初始化部门树 根据选择的部门 查询设备列表 部门人员列表
-  deptList.value = handleTree(await DeptApi.getSimpleDeptList())
+  try {
+    // 初始化部门树
+    const deptData = await DeptApi.getSimpleDeptList()
+    deptList.value = handleTree(deptData) // 转换为树形结构
+
+    // 设置默认选中的部门(转换后树的第一个节点)
+    if (deptList.value.length > 0) {
+      // 获取转换后树的第一个节点
+      const firstRootNode = deptList.value[0]
+
+      // 设置设备部门的默认值
+      formData.value.deptId1 = firstRootNode.id
+      // 触发设备部门的节点点击事件,加载设备列表
+      await handleDeptDeviceTreeNodeClick(firstRootNode)
+
+      // 设置责任人部门的默认值
+      formData.value.deptId = firstRootNode.id
+      // 触发责任人部门的节点点击事件,加载人员列表
+      await handleDeptUserTreeNodeClick(firstRootNode)
+    } else {
+      console.warn("部门树数据为空,无法设置默认值")
+    }
+  } catch (error) {
+    console.error("初始化部门树失败:", error)
+    ElMessage.error("加载部门数据失败")
+  }
 })
 
 </script>

+ 21 - 4
src/views/pms/device/statuslog/ConfigDeviceStatus.vue

@@ -131,7 +131,6 @@ import { ElMessage } from 'element-plus'
 import {defaultProps, handleTree} from "@/utils/tree";
 import * as DeptApi from "@/api/system/dept";
 import {IotDeviceApi, IotDeviceVO} from "@/api/pms/device";
-import {simpleUserList, UserVO} from "@/api/system/user";
 import {DICT_TYPE, getStrDictOptions} from "@/utils/dict";
 import { useRouter } from 'vue-router'
 import { useTagsViewStore } from "@/store/modules/tagsView";
@@ -345,9 +344,27 @@ const submitRelations = async () => {
 
 /** 初始化 */
 onMounted(async () => {
-  // 初始化部门树 根据选择的部门 查询设备列表 部门人员列表
-  deptList.value = handleTree(await DeptApi.getSimpleDeptList())
-  // getList()
+  try {
+    // 初始化部门树
+    const deptData = await DeptApi.getSimpleDeptList()
+    deptList.value = handleTree(deptData) // 转换为树形结构
+
+    // 设置默认选中的部门(转换后树的第一个节点)
+    if (deptList.value.length > 0) {
+      // 获取转换后树的第一个节点
+      const firstRootNode = deptList.value[0]
+
+      // 设置设备部门的默认值
+      formData.value.deptId1 = firstRootNode.id
+      // 触发设备部门的节点点击事件,加载设备列表
+      await handleDeptDeviceTreeNodeClick(firstRootNode)
+    } else {
+      console.warn("部门树数据为空,无法设置默认值")
+    }
+  } catch (error) {
+    console.error("初始化部门树失败:", error)
+    ElMessage.error("加载部门数据失败")
+  }
 })
 
 </script>

+ 61 - 12
src/views/pms/iotlockstock/index.vue

@@ -8,7 +8,7 @@
       :inline="true"
       label-width="68px"
     >
-      <el-form-item :label="t('workOrderMaterial.factory')" prop="factoryId">
+      <el-form-item :label="t('workOrderMaterial.factory')" prop="factoryId" v-if="!shouldHideComponents">
         <el-select v-model="queryParams.factoryId" clearable filterable :placeholder="t('faultForm.choose')" class="!w-240px" @change="selectedFactoryChange">
           <el-option
             v-for="item in factoryList"
@@ -30,10 +30,10 @@
         </el-select>
       </el-form-item>
       -->
-      <el-form-item :label="t('workOrderMaterial.costCenter')" prop="costCenterId">
+      <el-form-item :label="t('workOrderMaterial.costCenter')" prop="costCenterId" v-if="!shouldHideComponents">
         <el-select v-model="queryParams.costCenterId" clearable filterable :placeholder="t('faultForm.choose')" class="!w-240px">
           <el-option
-            v-for="item in costCenterList"
+            v-for="item in filteredCostCenterList"
             :key="item.id"
             :label="item.costCenterName"
             :value="item.id!"
@@ -159,8 +159,10 @@ import download from '@/utils/download'
 import { IotLockStockApi, IotLockStockVO } from '@/api/pms/iotlockstock'
 import IotLockStockForm from './IotLockStockForm.vue'
 import {erpPriceTableColumnFormatter} from "@/utils";
-import {DICT_TYPE} from "@/utils/dict";
+import { useUserStore } from '@/store/modules/user'
 import {SapOrgApi, SapOrgVO} from "@/api/system/saporg";
+import { checkRole } from '@/utils/permission'
+import { computed } from 'vue'
 
 /** PMS 本地 库存 列表 */
 defineOptions({ name: 'IotLockStock' })
@@ -169,7 +171,8 @@ const message = useMessage() // 消息弹窗
 const { t } = useI18n() // 国际化
 
 const { push } = useRouter() // 路由跳转
-
+// 过滤后的成本中心列表(用于动态显示)
+const filteredCostCenterList = ref<SapOrgVO[]>([])
 const loading = ref(true) // 列表的加载中
 const list = ref<IotLockStockVO[]>([]) // 列表的数据
 const total = ref(0) // 列表的总页数
@@ -210,6 +213,11 @@ const costCenterList = ref([] as SapOrgVO[]) // SAP成本中心列表
 const totalQuantity = ref(0)   // 总数量
 const totalAmount = ref(0)     // 总金额
 
+const shouldHideComponents = computed(() => {
+  // 检查用户是否拥有 'A' 或 'B' 角色
+  return checkRole(['小队队长', '操作员'])
+})
+
 const selectedFactoryReqVO = ref({
   type: 0, // 类型(1工厂 2成本中心 3库位)
   factoryCodes: [] // 已经选择的SAP工厂code 列表
@@ -235,12 +243,30 @@ const getList = async () => {
   } finally {
     loading.value = false
   }
-  // 加载工厂(SAP)列表
-  factoryList.value = await SapOrgApi.getSimpleSapOrgList(1)
-  // 成本中心
-  costCenterList.value = await SapOrgApi.getSimpleSapOrgList(2)
-  // 库存地点
-  storageLocationList.value = await SapOrgApi.getSimpleSapOrgList(3)
+  // 获取当前登录人的部门id 查询部门及子部门关联的所有SAP组织
+  // 获取组织数据(移出统计值处理逻辑)
+  await loadOrgData()
+}
+
+// 新增:单独封装组织数据加载方法
+const loadOrgData = async () => {
+  const deptId = useUserStore().getUser.deptId
+  if (typeof deptId === 'number' && !isNaN(deptId) && deptId > 0) {
+    try {
+      const [factories, costCenters] = await Promise.all([
+        SapOrgApi.filteredSimpleSapOrgList(1, deptId),
+        SapOrgApi.filteredSimpleSapOrgList(2, deptId)
+      ])
+      factoryList.value = factories
+      costCenterList.value = costCenters
+      // 初始化时显示全部成本中心
+      filteredCostCenterList.value = costCenters
+    } catch (error) {
+      console.error('获取组织数据失败:', error)
+    }
+  } else {
+    console.warn('无效的部门ID:', deptId)
+  }
 }
 
 /** 搜索按钮操作 */
@@ -252,6 +278,8 @@ const handleQuery = () => {
 /** 重置按钮操作 */
 const resetQuery = () => {
   queryFormRef.value.resetFields()
+  // 重置后恢复成本中心为完整列表
+  filteredCostCenterList.value = costCenterList.value
   handleQuery()
 }
 
@@ -279,7 +307,7 @@ const handleDelete = async (id: number) => {
 }
 
 /** 已经选择了 SAP工厂 */
-const selectedFactoryChange = async (selectedId: number | undefined) => {
+/* const selectedFactoryChange = async (selectedId: number | undefined) => {
 
   // 获取选中的factoryCode数组
   const selectedFactory = factoryList.value.find(item => item.id === selectedId)
@@ -295,6 +323,27 @@ const selectedFactoryChange = async (selectedId: number | undefined) => {
   selectedFactoryReqVO.value.type = 3
   selectedFactoryReqVO.value.factoryCodes = selectedFactoryCodes
   storageLocationList.value = await SapOrgApi.getSelectedList(selectedFactoryReqVO.value)
+} */
+
+/** 已经选择了 SAP工厂 */
+const selectedFactoryChange = async (selectedId: number | undefined) => {
+  // 清空已选择的成本中心
+  queryParams.costCenterId = undefined
+
+  if (!selectedId) {
+    // 未选择工厂时显示全部成本中心
+    filteredCostCenterList.value = costCenterList.value
+    return
+  }
+
+  // 获取选中的工厂对象
+  const selectedFactory = factoryList.value.find(item => item.id === selectedId)
+  if (!selectedFactory) return
+
+  // 根据工厂代码过滤成本中心
+  filteredCostCenterList.value = costCenterList.value.filter(
+    item => item.factoryCode === selectedFactory.factoryCode
+  )
 }
 
 /** 导出按钮操作 */

+ 1 - 0
src/views/pms/iotmainworkorder/IotMainWorkOrderDetail.vue

@@ -470,6 +470,7 @@
     :node-id="currentBomNodeId"
     :materials="materialList.filter(item => item.bomNodeId === currentBomNodeId)"
     :hide-extra-columns="true"
+    :detail="true"
   />
 </template>
 <script setup lang="ts">