Jelajahi Sumber

Merge remote-tracking branch 'origin/master'

lipenghui 4 bulan lalu
induk
melakukan
f25a90adb4

+ 57 - 0
src/api/pms/iotlockstock/index.ts

@@ -0,0 +1,57 @@
+import request from '@/config/axios'
+
+// PMS 本地 库存 VO
+export interface IotLockStockVO {
+  id: number // 主键
+  deptId: number // 组织部门id
+  factory: string // 工厂(SAP) 专业公司
+  projectDepartment: string // 库存地点 - SAP 部门 项目部级
+  costCenter: string // 成本中心(SAP) 库存地点 小队
+  pickingListNumber: string // 领料单号
+  materialCode: string // 物料编码
+  materialName: string // 物料名称
+  materialGroupName: string // 物料组
+  materialGroupId: number // 物料组id
+  quantity: number // 数量
+  unitPrice: number // 单价
+  unit: string // 单位
+  storageTime: Date // 入库时间
+  sort: number // 排序
+  status: number // 状态 0启用  1停用
+  processInstanceId: string // 流程实例id
+  auditStatus: number // 审批状态 未提交、审批中、审批通过、审批不通过、已取消
+  remark: string // 备注
+}
+
+// PMS 本地 库存 API
+export const IotLockStockApi = {
+  // 查询PMS 本地 库存分页
+  getIotLockStockPage: async (params: any) => {
+    return await request.get({ url: `/pms/iot-lock-stock/page`, params })
+  },
+
+  // 查询PMS 本地 库存详情
+  getIotLockStock: async (id: number) => {
+    return await request.get({ url: `/pms/iot-lock-stock/get?id=` + id })
+  },
+
+  // 新增PMS 本地 库存
+  createIotLockStock: async (data: IotLockStockVO) => {
+    return await request.post({ url: `/pms/iot-lock-stock/create`, data })
+  },
+
+  // 修改PMS 本地 库存
+  updateIotLockStock: async (data: IotLockStockVO) => {
+    return await request.put({ url: `/pms/iot-lock-stock/update`, data })
+  },
+
+  // 删除PMS 本地 库存
+  deleteIotLockStock: async (id: number) => {
+    return await request.delete({ url: `/pms/iot-lock-stock/delete?id=` + id })
+  },
+
+  // 导出PMS 本地 库存 Excel
+  exportIotLockStock: async (params) => {
+    return await request.download({ url: `/pms/iot-lock-stock/export-excel`, params })
+  },
+}

+ 60 - 0
src/api/pms/iotoutbound/index.ts

@@ -0,0 +1,60 @@
+import request from '@/config/axios'
+
+// PMS 出库 VO
+export interface IotOutboundVO {
+  id: number // 主键
+  storageId: number // 入库id
+  deptId: number // 组织部门id
+  factory: string // 工厂(SAP) 专业公司
+  projectDepartment: string // 库存地点 - SAP 部门 项目部级
+  costCenter: string // 成本中心(SAP) 库存地点 小队
+  materialCode: string // 物料编码
+  materialName: string // 物料名称
+  materialGroupName: string // 物料组
+  materialGroupId: number // 物料组id
+  quantity: number // 出库数量
+  unitPrice: number // 单价
+  unit: string // 单位
+  bomNodeId: number // 使用方向 对应BOM节点
+  type: number // 使用类型(1维修 2保养 3临时)
+  deliveryTime: Date // 出库时间
+  reason: string // 出库原因
+  sort: number // 排序
+  status: number // 状态 0启用  1停用
+  remark: string // 备注
+  processInstanceId: string // 流程实例id
+  auditStatus: number // 审批状态 未提交、审批中、审批通过、审批不通过、已取消
+}
+
+// PMS 出库 API
+export const IotOutboundApi = {
+  // 查询PMS 出库分页
+  getIotOutboundPage: async (params: any) => {
+    return await request.get({ url: `/pms/iot-outbound/page`, params })
+  },
+
+  // 查询PMS 出库详情
+  getIotOutbound: async (id: number) => {
+    return await request.get({ url: `/pms/iot-outbound/get?id=` + id })
+  },
+
+  // 新增PMS 出库
+  createIotOutbound: async (data: IotOutboundVO) => {
+    return await request.post({ url: `/pms/iot-outbound/create`, data })
+  },
+
+  // 修改PMS 出库
+  updateIotOutbound: async (data: IotOutboundVO) => {
+    return await request.put({ url: `/pms/iot-outbound/update`, data })
+  },
+
+  // 删除PMS 出库
+  deleteIotOutbound: async (id: number) => {
+    return await request.delete({ url: `/pms/iot-outbound/delete?id=` + id })
+  },
+
+  // 导出PMS 出库 Excel
+  exportIotOutbound: async (params) => {
+    return await request.download({ url: `/pms/iot-outbound/export-excel`, params })
+  },
+}

+ 59 - 0
src/api/pms/iotsapstock/index.ts

@@ -0,0 +1,59 @@
+import request from '@/config/axios'
+
+// PMS SAP 库存(通用库存/项目部库存) VO
+export interface IotSapStockVO {
+  id: number // 主键
+  deptId: number // 组织部门id
+  factory: string // 工厂(SAP) 专业公司
+  projectDepartment: string // 库存地点 - SAP 部门 项目部级 通用库 项目部库
+  materialCode: string // 物料编码
+  materialName: string // 物料名称
+  materialGroupName: string // 物料组
+  materialGroupId: number // 物料组id
+  quantity: number // 数量
+  unitPrice: number // 单价
+  unit: string // 单位
+  safetyStock: number // 安全库存
+  shelvesId: number // 货架id
+  cargoLocationId: number // 库位id
+  type: number // 类型(通用库 项目部库)
+  syncStatus: number // 同步状态 0未同步 1同步成功 2同步失败
+  syncTime: Date // 最后一次同步时间
+  syncError: string // 同步失败时的错误信息
+  sort: number // 排序
+  status: number // 状态 0启用  1停用
+  remark: string // 备注
+}
+
+// PMS SAP 库存(通用库存/项目部库存) API
+export const IotSapStockApi = {
+  // 查询PMS SAP 库存(通用库存/项目部库存)分页
+  getIotSapStockPage: async (params: any) => {
+    return await request.get({ url: `/pms/iot-sap-stock/page`, params })
+  },
+
+  // 查询PMS SAP 库存(通用库存/项目部库存)详情
+  getIotSapStock: async (id: number) => {
+    return await request.get({ url: `/pms/iot-sap-stock/get?id=` + id })
+  },
+
+  // 新增PMS SAP 库存(通用库存/项目部库存)
+  createIotSapStock: async (data: IotSapStockVO) => {
+    return await request.post({ url: `/pms/iot-sap-stock/create`, data })
+  },
+
+  // 修改PMS SAP 库存(通用库存/项目部库存)
+  updateIotSapStock: async (data: IotSapStockVO) => {
+    return await request.put({ url: `/pms/iot-sap-stock/update`, data })
+  },
+
+  // 删除PMS SAP 库存(通用库存/项目部库存)
+  deleteIotSapStock: async (id: number) => {
+    return await request.delete({ url: `/pms/iot-sap-stock/delete?id=` + id })
+  },
+
+  // 导出PMS SAP 库存(通用库存/项目部库存) Excel
+  exportIotSapStock: async (params) => {
+    return await request.download({ url: `/pms/iot-sap-stock/export-excel`, params })
+  },
+}

+ 41 - 0
src/api/system/deptsaporg/index.ts

@@ -0,0 +1,41 @@
+import request from '@/config/axios'
+
+// PMS 组织部门与SAP工厂/成本中心 对应关系 VO
+export interface DeptSapOrgVO {
+  id: number // id
+  deptId: number // 组织部门id
+  sapOrgId: number // SAP组织id(工厂/成本中心)
+}
+
+// PMS 组织部门与SAP工厂/成本中心 对应关系 API
+export const DeptSapOrgApi = {
+  // 查询PMS 组织部门与SAP工厂/成本中心 对应关系分页
+  getDeptSapOrgPage: async (params: any) => {
+    return await request.get({ url: `/system/dept-sap-org/page`, params })
+  },
+
+  // 查询PMS 组织部门与SAP工厂/成本中心 对应关系详情
+  getDeptSapOrg: async (id: number) => {
+    return await request.get({ url: `/system/dept-sap-org/get?id=` + id })
+  },
+
+  // 新增PMS 组织部门与SAP工厂/成本中心 对应关系
+  createDeptSapOrg: async (data: DeptSapOrgVO) => {
+    return await request.post({ url: `/system/dept-sap-org/create`, data })
+  },
+
+  // 修改PMS 组织部门与SAP工厂/成本中心 对应关系
+  updateDeptSapOrg: async (data: DeptSapOrgVO) => {
+    return await request.put({ url: `/system/dept-sap-org/update`, data })
+  },
+
+  // 删除PMS 组织部门与SAP工厂/成本中心 对应关系
+  deleteDeptSapOrg: async (id: number) => {
+    return await request.delete({ url: `/system/dept-sap-org/delete?id=` + id })
+  },
+
+  // 导出PMS 组织部门与SAP工厂/成本中心 对应关系 Excel
+  exportDeptSapOrg: async (params) => {
+    return await request.download({ url: `/system/dept-sap-org/export-excel`, params })
+  },
+}

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

@@ -0,0 +1,50 @@
+import request from '@/config/axios'
+
+// SAP中的组织主数据(工厂 成本中心) VO
+export interface SapOrgVO {
+  id: number // 主键id
+  factoryCode: string // sap工厂编号
+  factoryName: string // sap工厂名称
+  costCenterCode: string // SAP成本中心编码
+  costCenterName: string // SAP成本中心名称
+  storageLocationCode: string // SAP库位编码
+  storageLocationName: string // SAP库位名称
+  type: number // 类型(1工厂 2成本中心 3库位)
+  responsiblePerson: string // 责任人id(多个逗号分隔)
+  sort: number // 分类排序
+  status: number // 部门状态(0正常 1停用)
+  remark: string // 备注
+}
+
+// SAP中的组织主数据(工厂 成本中心) API
+export const SapOrgApi = {
+  // 查询SAP中的组织主数据(工厂 成本中心)分页
+  getSapOrgPage: async (params: any) => {
+    return await request.get({ url: `/system/sap-org/page`, params })
+  },
+
+  // 查询SAP中的组织主数据(工厂 成本中心)详情
+  getSapOrg: async (id: number) => {
+    return await request.get({ url: `/system/sap-org/get?id=` + id })
+  },
+
+  // 新增SAP中的组织主数据(工厂 成本中心)
+  createSapOrg: async (data: SapOrgVO) => {
+    return await request.post({ url: `/system/sap-org/create`, data })
+  },
+
+  // 修改SAP中的组织主数据(工厂 成本中心)
+  updateSapOrg: async (data: SapOrgVO) => {
+    return await request.put({ url: `/system/sap-org/update`, data })
+  },
+
+  // 删除SAP中的组织主数据(工厂 成本中心)
+  deleteSapOrg: async (id: number) => {
+    return await request.delete({ url: `/system/sap-org/delete?id=` + id })
+  },
+
+  // 导出SAP中的组织主数据(工厂 成本中心) Excel
+  exportSapOrg: async (params) => {
+    return await request.download({ url: `/system/sap-org/export-excel`, params })
+  },
+}

+ 185 - 0
src/views/pms/iotlockstock/IotLockStockForm.vue

@@ -0,0 +1,185 @@
+<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="deptId">
+        <el-input v-model="formData.deptId" placeholder="请输入组织部门id" />
+      </el-form-item>
+      <el-form-item label="工厂(SAP) 专业公司" prop="factory">
+        <el-input v-model="formData.factory" placeholder="请输入工厂(SAP) 专业公司" />
+      </el-form-item>
+      <el-form-item label="库存地点 - SAP 部门 项目部级" prop="projectDepartment">
+        <el-input v-model="formData.projectDepartment" placeholder="请输入库存地点 - SAP 部门 项目部级" />
+      </el-form-item>
+      <el-form-item label="成本中心(SAP) 库存地点 小队" prop="costCenter">
+        <el-input v-model="formData.costCenter" placeholder="请输入成本中心(SAP) 库存地点 小队" />
+      </el-form-item>
+      <el-form-item label="领料单号" prop="pickingListNumber">
+        <el-input v-model="formData.pickingListNumber" placeholder="请输入领料单号" />
+      </el-form-item>
+      <el-form-item label="物料编码" prop="materialCode">
+        <el-input v-model="formData.materialCode" placeholder="请输入物料编码" />
+      </el-form-item>
+      <el-form-item label="物料名称" prop="materialName">
+        <el-input v-model="formData.materialName" placeholder="请输入物料名称" />
+      </el-form-item>
+      <el-form-item label="物料组" prop="materialGroupName">
+        <el-input v-model="formData.materialGroupName" placeholder="请输入物料组" />
+      </el-form-item>
+      <el-form-item label="物料组id" prop="materialGroupId">
+        <el-input v-model="formData.materialGroupId" placeholder="请输入物料组id" />
+      </el-form-item>
+      <el-form-item label="数量" prop="quantity">
+        <el-input v-model="formData.quantity" placeholder="请输入数量" />
+      </el-form-item>
+      <el-form-item label="单价" prop="unitPrice">
+        <el-input v-model="formData.unitPrice" placeholder="请输入单价" />
+      </el-form-item>
+      <el-form-item label="单位" prop="unit">
+        <el-input v-model="formData.unit" placeholder="请输入单位" />
+      </el-form-item>
+      <el-form-item label="入库时间" prop="storageTime">
+        <el-date-picker
+          v-model="formData.storageTime"
+          type="date"
+          value-format="x"
+          placeholder="选择入库时间"
+        />
+      </el-form-item>
+      <el-form-item label="排序" prop="sort">
+        <el-input v-model="formData.sort" placeholder="请输入排序" />
+      </el-form-item>
+      <el-form-item label="状态 0启用  1停用" prop="status">
+        <el-radio-group v-model="formData.status">
+          <el-radio value="1">请选择字典生成</el-radio>
+        </el-radio-group>
+      </el-form-item>
+      <el-form-item label="流程实例id" prop="processInstanceId">
+        <el-input v-model="formData.processInstanceId" placeholder="请输入流程实例id" />
+      </el-form-item>
+      <el-form-item label="审批状态 未提交、审批中、审批通过、审批不通过、已取消" prop="auditStatus">
+        <el-radio-group v-model="formData.auditStatus">
+          <el-radio value="1">请选择字典生成</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 { IotLockStockApi, IotLockStockVO } from '@/api/pms/iotlockstock'
+
+/** PMS 本地 库存 表单 */
+defineOptions({ name: 'IotLockStockForm' })
+
+const { t } = useI18n() // 国际化
+const message = useMessage() // 消息弹窗
+
+const dialogVisible = ref(false) // 弹窗的是否展示
+const dialogTitle = ref('') // 弹窗的标题
+const formLoading = ref(false) // 表单的加载中:1)修改时的数据加载;2)提交的按钮禁用
+const formType = ref('') // 表单的类型:create - 新增;update - 修改
+const formData = ref({
+  id: undefined,
+  deptId: undefined,
+  factory: undefined,
+  projectDepartment: undefined,
+  costCenter: undefined,
+  pickingListNumber: undefined,
+  materialCode: undefined,
+  materialName: undefined,
+  materialGroupName: undefined,
+  materialGroupId: undefined,
+  quantity: undefined,
+  unitPrice: undefined,
+  unit: undefined,
+  storageTime: undefined,
+  sort: undefined,
+  status: undefined,
+  processInstanceId: undefined,
+  auditStatus: undefined,
+  remark: undefined,
+})
+const formRules = reactive({
+})
+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 IotLockStockApi.getIotLockStock(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 IotLockStockVO
+    if (formType.value === 'create') {
+      await IotLockStockApi.createIotLockStock(data)
+      message.success(t('common.createSuccess'))
+    } else {
+      await IotLockStockApi.updateIotLockStock(data)
+      message.success(t('common.updateSuccess'))
+    }
+    dialogVisible.value = false
+    // 发送操作成功的事件
+    emit('success')
+  } finally {
+    formLoading.value = false
+  }
+}
+
+/** 重置表单 */
+const resetForm = () => {
+  formData.value = {
+    id: undefined,
+    deptId: undefined,
+    factory: undefined,
+    projectDepartment: undefined,
+    costCenter: undefined,
+    pickingListNumber: undefined,
+    materialCode: undefined,
+    materialName: undefined,
+    materialGroupName: undefined,
+    materialGroupId: undefined,
+    quantity: undefined,
+    unitPrice: undefined,
+    unit: undefined,
+    storageTime: undefined,
+    sort: undefined,
+    status: undefined,
+    processInstanceId: undefined,
+    auditStatus: undefined,
+    remark: undefined,
+  }
+  formRef.value?.resetFields()
+}
+</script>

+ 384 - 0
src/views/pms/iotlockstock/index.vue

@@ -0,0 +1,384 @@
+<template>
+  <ContentWrap>
+    <!-- 搜索工作栏 -->
+    <el-form
+      class="-mb-15px"
+      :model="queryParams"
+      ref="queryFormRef"
+      :inline="true"
+      label-width="68px"
+    >
+      <el-form-item label="组织部门id" prop="deptId">
+        <el-input
+          v-model="queryParams.deptId"
+          placeholder="请输入组织部门id"
+          clearable
+          @keyup.enter="handleQuery"
+          class="!w-240px"
+        />
+      </el-form-item>
+      <el-form-item label="工厂(SAP) 专业公司" prop="factory">
+        <el-input
+          v-model="queryParams.factory"
+          placeholder="请输入工厂(SAP) 专业公司"
+          clearable
+          @keyup.enter="handleQuery"
+          class="!w-240px"
+        />
+      </el-form-item>
+      <el-form-item label="库存地点 - SAP 部门 项目部级" prop="projectDepartment">
+        <el-input
+          v-model="queryParams.projectDepartment"
+          placeholder="请输入库存地点 - SAP 部门 项目部级"
+          clearable
+          @keyup.enter="handleQuery"
+          class="!w-240px"
+        />
+      </el-form-item>
+      <el-form-item label="成本中心(SAP) 库存地点 小队" prop="costCenter">
+        <el-input
+          v-model="queryParams.costCenter"
+          placeholder="请输入成本中心(SAP) 库存地点 小队"
+          clearable
+          @keyup.enter="handleQuery"
+          class="!w-240px"
+        />
+      </el-form-item>
+      <el-form-item label="领料单号" prop="pickingListNumber">
+        <el-input
+          v-model="queryParams.pickingListNumber"
+          placeholder="请输入领料单号"
+          clearable
+          @keyup.enter="handleQuery"
+          class="!w-240px"
+        />
+      </el-form-item>
+      <el-form-item label="物料编码" prop="materialCode">
+        <el-input
+          v-model="queryParams.materialCode"
+          placeholder="请输入物料编码"
+          clearable
+          @keyup.enter="handleQuery"
+          class="!w-240px"
+        />
+      </el-form-item>
+      <el-form-item label="物料名称" prop="materialName">
+        <el-input
+          v-model="queryParams.materialName"
+          placeholder="请输入物料名称"
+          clearable
+          @keyup.enter="handleQuery"
+          class="!w-240px"
+        />
+      </el-form-item>
+      <el-form-item label="物料组" prop="materialGroupName">
+        <el-input
+          v-model="queryParams.materialGroupName"
+          placeholder="请输入物料组"
+          clearable
+          @keyup.enter="handleQuery"
+          class="!w-240px"
+        />
+      </el-form-item>
+      <el-form-item label="物料组id" prop="materialGroupId">
+        <el-input
+          v-model="queryParams.materialGroupId"
+          placeholder="请输入物料组id"
+          clearable
+          @keyup.enter="handleQuery"
+          class="!w-240px"
+        />
+      </el-form-item>
+      <el-form-item label="数量" prop="quantity">
+        <el-input
+          v-model="queryParams.quantity"
+          placeholder="请输入数量"
+          clearable
+          @keyup.enter="handleQuery"
+          class="!w-240px"
+        />
+      </el-form-item>
+      <el-form-item label="单价" prop="unitPrice">
+        <el-input
+          v-model="queryParams.unitPrice"
+          placeholder="请输入单价"
+          clearable
+          @keyup.enter="handleQuery"
+          class="!w-240px"
+        />
+      </el-form-item>
+      <el-form-item label="单位" prop="unit">
+        <el-input
+          v-model="queryParams.unit"
+          placeholder="请输入单位"
+          clearable
+          @keyup.enter="handleQuery"
+          class="!w-240px"
+        />
+      </el-form-item>
+      <el-form-item label="入库时间" prop="storageTime">
+        <el-date-picker
+          v-model="queryParams.storageTime"
+          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-220px"
+        />
+      </el-form-item>
+      <el-form-item label="排序" prop="sort">
+        <el-input
+          v-model="queryParams.sort"
+          placeholder="请输入排序"
+          clearable
+          @keyup.enter="handleQuery"
+          class="!w-240px"
+        />
+      </el-form-item>
+      <el-form-item label="状态 0启用  1停用" prop="status">
+        <el-select
+          v-model="queryParams.status"
+          placeholder="请选择状态 0启用  1停用"
+          clearable
+          class="!w-240px"
+        >
+          <el-option label="请选择字典生成" value="" />
+        </el-select>
+      </el-form-item>
+      <el-form-item label="流程实例id" prop="processInstanceId">
+        <el-input
+          v-model="queryParams.processInstanceId"
+          placeholder="请输入流程实例id"
+          clearable
+          @keyup.enter="handleQuery"
+          class="!w-240px"
+        />
+      </el-form-item>
+      <el-form-item label="审批状态 未提交、审批中、审批通过、审批不通过、已取消" prop="auditStatus">
+        <el-select
+          v-model="queryParams.auditStatus"
+          placeholder="请选择审批状态 未提交、审批中、审批通过、审批不通过、已取消"
+          clearable
+          class="!w-240px"
+        >
+          <el-option label="请选择字典生成" value="" />
+        </el-select>
+      </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="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-220px"
+        />
+      </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="['pms:iot-lock-stock:create']"
+        >
+          <Icon icon="ep:plus" class="mr-5px" /> 新增
+        </el-button>
+        <el-button
+          type="success"
+          plain
+          @click="handleExport"
+          :loading="exportLoading"
+          v-hasPermi="['pms:iot-lock-stock: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="主键" align="center" prop="id" />
+      <el-table-column label="组织部门id" align="center" prop="deptId" />
+      <el-table-column label="工厂(SAP) 专业公司" align="center" prop="factory" />
+      <el-table-column label="库存地点 - SAP 部门 项目部级" align="center" prop="projectDepartment" />
+      <el-table-column label="成本中心(SAP) 库存地点 小队" align="center" prop="costCenter" />
+      <el-table-column label="领料单号" align="center" prop="pickingListNumber" />
+      <el-table-column label="物料编码" align="center" prop="materialCode" />
+      <el-table-column label="物料名称" align="center" prop="materialName" />
+      <el-table-column label="物料组" align="center" prop="materialGroupName" />
+      <el-table-column label="物料组id" align="center" prop="materialGroupId" />
+      <el-table-column label="数量" align="center" prop="quantity" />
+      <el-table-column label="单价" align="center" prop="unitPrice" />
+      <el-table-column label="单位" align="center" prop="unit" />
+      <el-table-column
+        label="入库时间"
+        align="center"
+        prop="storageTime"
+        :formatter="dateFormatter"
+        width="180px"
+      />
+      <el-table-column label="排序" align="center" prop="sort" />
+      <el-table-column label="状态 0启用  1停用" align="center" prop="status" />
+      <el-table-column label="流程实例id" align="center" prop="processInstanceId" />
+      <el-table-column label="审批状态 未提交、审批中、审批通过、审批不通过、已取消" align="center" prop="auditStatus" />
+      <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" min-width="120px">
+        <template #default="scope">
+          <el-button
+            link
+            type="primary"
+            @click="openForm('update', scope.row.id)"
+            v-hasPermi="['pms:iot-lock-stock:update']"
+          >
+            编辑
+          </el-button>
+          <el-button
+            link
+            type="danger"
+            @click="handleDelete(scope.row.id)"
+            v-hasPermi="['pms:iot-lock-stock: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>
+
+  <!-- 表单弹窗:添加/修改 -->
+  <IotLockStockForm ref="formRef" @success="getList" />
+</template>
+
+<script setup lang="ts">
+import { dateFormatter } from '@/utils/formatTime'
+import download from '@/utils/download'
+import { IotLockStockApi, IotLockStockVO } from '@/api/pms/iotlockstock'
+import IotLockStockForm from './IotLockStockForm.vue'
+
+/** PMS 本地 库存 列表 */
+defineOptions({ name: 'IotLockStock' })
+
+const message = useMessage() // 消息弹窗
+const { t } = useI18n() // 国际化
+
+const loading = ref(true) // 列表的加载中
+const list = ref<IotLockStockVO[]>([]) // 列表的数据
+const total = ref(0) // 列表的总页数
+const queryParams = reactive({
+  pageNo: 1,
+  pageSize: 10,
+  deptId: undefined,
+  factory: undefined,
+  projectDepartment: undefined,
+  costCenter: undefined,
+  pickingListNumber: undefined,
+  materialCode: undefined,
+  materialName: undefined,
+  materialGroupName: undefined,
+  materialGroupId: undefined,
+  quantity: undefined,
+  unitPrice: undefined,
+  unit: undefined,
+  storageTime: [],
+  sort: undefined,
+  status: undefined,
+  processInstanceId: undefined,
+  auditStatus: undefined,
+  remark: undefined,
+  createTime: [],
+})
+const queryFormRef = ref() // 搜索的表单
+const exportLoading = ref(false) // 导出的加载中
+
+/** 查询列表 */
+const getList = async () => {
+  loading.value = true
+  try {
+    const data = await IotLockStockApi.getIotLockStockPage(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 IotLockStockApi.deleteIotLockStock(id)
+    message.success(t('common.delSuccess'))
+    // 刷新列表
+    await getList()
+  } catch {}
+}
+
+/** 导出按钮操作 */
+const handleExport = async () => {
+  try {
+    // 导出的二次确认
+    await message.exportConfirm()
+    // 发起导出
+    exportLoading.value = true
+    const data = await IotLockStockApi.exportIotLockStock(queryParams)
+    download.excel(data, 'PMS 本地 库存.xls')
+  } catch {
+  } finally {
+    exportLoading.value = false
+  }
+}
+
+/** 初始化 **/
+onMounted(() => {
+  getList()
+})
+</script>

+ 202 - 0
src/views/pms/iotoutbound/IotOutboundForm.vue

@@ -0,0 +1,202 @@
+<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="storageId">
+        <el-input v-model="formData.storageId" placeholder="请输入入库id" />
+      </el-form-item>
+      <el-form-item label="组织部门id" prop="deptId">
+        <el-input v-model="formData.deptId" placeholder="请输入组织部门id" />
+      </el-form-item>
+      <el-form-item label="工厂(SAP) 专业公司" prop="factory">
+        <el-input v-model="formData.factory" placeholder="请输入工厂(SAP) 专业公司" />
+      </el-form-item>
+      <el-form-item label="库存地点 - SAP 部门 项目部级" prop="projectDepartment">
+        <el-input v-model="formData.projectDepartment" placeholder="请输入库存地点 - SAP 部门 项目部级" />
+      </el-form-item>
+      <el-form-item label="成本中心(SAP) 库存地点 小队" prop="costCenter">
+        <el-input v-model="formData.costCenter" placeholder="请输入成本中心(SAP) 库存地点 小队" />
+      </el-form-item>
+      <el-form-item label="物料编码" prop="materialCode">
+        <el-input v-model="formData.materialCode" placeholder="请输入物料编码" />
+      </el-form-item>
+      <el-form-item label="物料名称" prop="materialName">
+        <el-input v-model="formData.materialName" placeholder="请输入物料名称" />
+      </el-form-item>
+      <el-form-item label="物料组" prop="materialGroupName">
+        <el-input v-model="formData.materialGroupName" placeholder="请输入物料组" />
+      </el-form-item>
+      <el-form-item label="物料组id" prop="materialGroupId">
+        <el-input v-model="formData.materialGroupId" placeholder="请输入物料组id" />
+      </el-form-item>
+      <el-form-item label="出库数量" prop="quantity">
+        <el-input v-model="formData.quantity" placeholder="请输入出库数量" />
+      </el-form-item>
+      <el-form-item label="单价" prop="unitPrice">
+        <el-input v-model="formData.unitPrice" placeholder="请输入单价" />
+      </el-form-item>
+      <el-form-item label="单位" prop="unit">
+        <el-input v-model="formData.unit" placeholder="请输入单位" />
+      </el-form-item>
+      <el-form-item label="使用方向 对应BOM节点" prop="bomNodeId">
+        <el-input v-model="formData.bomNodeId" placeholder="请输入使用方向 对应BOM节点" />
+      </el-form-item>
+      <el-form-item label="使用类型(1维修 2保养 3临时)" prop="type">
+        <el-select v-model="formData.type" placeholder="请选择使用类型(1维修 2保养 3临时)">
+          <el-option label="请选择字典生成" value="" />
+        </el-select>
+      </el-form-item>
+      <el-form-item label="出库时间" prop="deliveryTime">
+        <el-date-picker
+          v-model="formData.deliveryTime"
+          type="date"
+          value-format="x"
+          placeholder="选择出库时间"
+        />
+      </el-form-item>
+      <el-form-item label="出库原因" prop="reason">
+        <el-input v-model="formData.reason" placeholder="请输入出库原因" />
+      </el-form-item>
+      <el-form-item label="排序" prop="sort">
+        <el-input v-model="formData.sort" placeholder="请输入排序" />
+      </el-form-item>
+      <el-form-item label="状态 0启用  1停用" prop="status">
+        <el-radio-group v-model="formData.status">
+          <el-radio value="1">请选择字典生成</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-item label="流程实例id" prop="processInstanceId">
+        <el-input v-model="formData.processInstanceId" placeholder="请输入流程实例id" />
+      </el-form-item>
+      <el-form-item label="审批状态 未提交、审批中、审批通过、审批不通过、已取消" prop="auditStatus">
+        <el-radio-group v-model="formData.auditStatus">
+          <el-radio value="1">请选择字典生成</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 { IotOutboundApi, IotOutboundVO } from '@/api/pms/iotoutbound'
+
+/** PMS 出库 表单 */
+defineOptions({ name: 'IotOutboundForm' })
+
+const { t } = useI18n() // 国际化
+const message = useMessage() // 消息弹窗
+
+const dialogVisible = ref(false) // 弹窗的是否展示
+const dialogTitle = ref('') // 弹窗的标题
+const formLoading = ref(false) // 表单的加载中:1)修改时的数据加载;2)提交的按钮禁用
+const formType = ref('') // 表单的类型:create - 新增;update - 修改
+const formData = ref({
+  id: undefined,
+  storageId: undefined,
+  deptId: undefined,
+  factory: undefined,
+  projectDepartment: undefined,
+  costCenter: undefined,
+  materialCode: undefined,
+  materialName: undefined,
+  materialGroupName: undefined,
+  materialGroupId: undefined,
+  quantity: undefined,
+  unitPrice: undefined,
+  unit: undefined,
+  bomNodeId: undefined,
+  type: undefined,
+  deliveryTime: undefined,
+  reason: undefined,
+  sort: undefined,
+  status: undefined,
+  remark: undefined,
+  processInstanceId: undefined,
+  auditStatus: undefined,
+})
+const formRules = reactive({
+})
+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 IotOutboundApi.getIotOutbound(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 IotOutboundVO
+    if (formType.value === 'create') {
+      await IotOutboundApi.createIotOutbound(data)
+      message.success(t('common.createSuccess'))
+    } else {
+      await IotOutboundApi.updateIotOutbound(data)
+      message.success(t('common.updateSuccess'))
+    }
+    dialogVisible.value = false
+    // 发送操作成功的事件
+    emit('success')
+  } finally {
+    formLoading.value = false
+  }
+}
+
+/** 重置表单 */
+const resetForm = () => {
+  formData.value = {
+    id: undefined,
+    storageId: undefined,
+    deptId: undefined,
+    factory: undefined,
+    projectDepartment: undefined,
+    costCenter: undefined,
+    materialCode: undefined,
+    materialName: undefined,
+    materialGroupName: undefined,
+    materialGroupId: undefined,
+    quantity: undefined,
+    unitPrice: undefined,
+    unit: undefined,
+    bomNodeId: undefined,
+    type: undefined,
+    deliveryTime: undefined,
+    reason: undefined,
+    sort: undefined,
+    status: undefined,
+    remark: undefined,
+    processInstanceId: undefined,
+    auditStatus: undefined,
+  }
+  formRef.value?.resetFields()
+}
+</script>

+ 418 - 0
src/views/pms/iotoutbound/index.vue

@@ -0,0 +1,418 @@
+<template>
+  <ContentWrap>
+    <!-- 搜索工作栏 -->
+    <el-form
+      class="-mb-15px"
+      :model="queryParams"
+      ref="queryFormRef"
+      :inline="true"
+      label-width="68px"
+    >
+      <el-form-item label="入库id" prop="storageId">
+        <el-input
+          v-model="queryParams.storageId"
+          placeholder="请输入入库id"
+          clearable
+          @keyup.enter="handleQuery"
+          class="!w-240px"
+        />
+      </el-form-item>
+      <el-form-item label="组织部门id" prop="deptId">
+        <el-input
+          v-model="queryParams.deptId"
+          placeholder="请输入组织部门id"
+          clearable
+          @keyup.enter="handleQuery"
+          class="!w-240px"
+        />
+      </el-form-item>
+      <el-form-item label="工厂(SAP) 专业公司" prop="factory">
+        <el-input
+          v-model="queryParams.factory"
+          placeholder="请输入工厂(SAP) 专业公司"
+          clearable
+          @keyup.enter="handleQuery"
+          class="!w-240px"
+        />
+      </el-form-item>
+      <el-form-item label="库存地点 - SAP 部门 项目部级" prop="projectDepartment">
+        <el-input
+          v-model="queryParams.projectDepartment"
+          placeholder="请输入库存地点 - SAP 部门 项目部级"
+          clearable
+          @keyup.enter="handleQuery"
+          class="!w-240px"
+        />
+      </el-form-item>
+      <el-form-item label="成本中心(SAP) 库存地点 小队" prop="costCenter">
+        <el-input
+          v-model="queryParams.costCenter"
+          placeholder="请输入成本中心(SAP) 库存地点 小队"
+          clearable
+          @keyup.enter="handleQuery"
+          class="!w-240px"
+        />
+      </el-form-item>
+      <el-form-item label="物料编码" prop="materialCode">
+        <el-input
+          v-model="queryParams.materialCode"
+          placeholder="请输入物料编码"
+          clearable
+          @keyup.enter="handleQuery"
+          class="!w-240px"
+        />
+      </el-form-item>
+      <el-form-item label="物料名称" prop="materialName">
+        <el-input
+          v-model="queryParams.materialName"
+          placeholder="请输入物料名称"
+          clearable
+          @keyup.enter="handleQuery"
+          class="!w-240px"
+        />
+      </el-form-item>
+      <el-form-item label="物料组" prop="materialGroupName">
+        <el-input
+          v-model="queryParams.materialGroupName"
+          placeholder="请输入物料组"
+          clearable
+          @keyup.enter="handleQuery"
+          class="!w-240px"
+        />
+      </el-form-item>
+      <el-form-item label="物料组id" prop="materialGroupId">
+        <el-input
+          v-model="queryParams.materialGroupId"
+          placeholder="请输入物料组id"
+          clearable
+          @keyup.enter="handleQuery"
+          class="!w-240px"
+        />
+      </el-form-item>
+      <el-form-item label="出库数量" prop="quantity">
+        <el-input
+          v-model="queryParams.quantity"
+          placeholder="请输入出库数量"
+          clearable
+          @keyup.enter="handleQuery"
+          class="!w-240px"
+        />
+      </el-form-item>
+      <el-form-item label="单价" prop="unitPrice">
+        <el-input
+          v-model="queryParams.unitPrice"
+          placeholder="请输入单价"
+          clearable
+          @keyup.enter="handleQuery"
+          class="!w-240px"
+        />
+      </el-form-item>
+      <el-form-item label="单位" prop="unit">
+        <el-input
+          v-model="queryParams.unit"
+          placeholder="请输入单位"
+          clearable
+          @keyup.enter="handleQuery"
+          class="!w-240px"
+        />
+      </el-form-item>
+      <el-form-item label="使用方向 对应BOM节点" prop="bomNodeId">
+        <el-input
+          v-model="queryParams.bomNodeId"
+          placeholder="请输入使用方向 对应BOM节点"
+          clearable
+          @keyup.enter="handleQuery"
+          class="!w-240px"
+        />
+      </el-form-item>
+      <el-form-item label="使用类型(1维修 2保养 3临时)" prop="type">
+        <el-select
+          v-model="queryParams.type"
+          placeholder="请选择使用类型(1维修 2保养 3临时)"
+          clearable
+          class="!w-240px"
+        >
+          <el-option label="请选择字典生成" value="" />
+        </el-select>
+      </el-form-item>
+      <el-form-item label="出库时间" prop="deliveryTime">
+        <el-date-picker
+          v-model="queryParams.deliveryTime"
+          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-220px"
+        />
+      </el-form-item>
+      <el-form-item label="出库原因" prop="reason">
+        <el-input
+          v-model="queryParams.reason"
+          placeholder="请输入出库原因"
+          clearable
+          @keyup.enter="handleQuery"
+          class="!w-240px"
+        />
+      </el-form-item>
+      <el-form-item label="排序" prop="sort">
+        <el-input
+          v-model="queryParams.sort"
+          placeholder="请输入排序"
+          clearable
+          @keyup.enter="handleQuery"
+          class="!w-240px"
+        />
+      </el-form-item>
+      <el-form-item label="状态 0启用  1停用" prop="status">
+        <el-select
+          v-model="queryParams.status"
+          placeholder="请选择状态 0启用  1停用"
+          clearable
+          class="!w-240px"
+        >
+          <el-option label="请选择字典生成" value="" />
+        </el-select>
+      </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="流程实例id" prop="processInstanceId">
+        <el-input
+          v-model="queryParams.processInstanceId"
+          placeholder="请输入流程实例id"
+          clearable
+          @keyup.enter="handleQuery"
+          class="!w-240px"
+        />
+      </el-form-item>
+      <el-form-item label="审批状态 未提交、审批中、审批通过、审批不通过、已取消" prop="auditStatus">
+        <el-select
+          v-model="queryParams.auditStatus"
+          placeholder="请选择审批状态 未提交、审批中、审批通过、审批不通过、已取消"
+          clearable
+          class="!w-240px"
+        >
+          <el-option label="请选择字典生成" 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-220px"
+        />
+      </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="['pms:iot-outbound:create']"
+        >
+          <Icon icon="ep:plus" class="mr-5px" /> 新增
+        </el-button>
+        <el-button
+          type="success"
+          plain
+          @click="handleExport"
+          :loading="exportLoading"
+          v-hasPermi="['pms:iot-outbound: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="主键" align="center" prop="id" />
+      <el-table-column label="入库id" align="center" prop="storageId" />
+      <el-table-column label="组织部门id" align="center" prop="deptId" />
+      <el-table-column label="工厂(SAP) 专业公司" align="center" prop="factory" />
+      <el-table-column label="库存地点 - SAP 部门 项目部级" align="center" prop="projectDepartment" />
+      <el-table-column label="成本中心(SAP) 库存地点 小队" align="center" prop="costCenter" />
+      <el-table-column label="物料编码" align="center" prop="materialCode" />
+      <el-table-column label="物料名称" align="center" prop="materialName" />
+      <el-table-column label="物料组" align="center" prop="materialGroupName" />
+      <el-table-column label="物料组id" align="center" prop="materialGroupId" />
+      <el-table-column label="出库数量" align="center" prop="quantity" />
+      <el-table-column label="单价" align="center" prop="unitPrice" />
+      <el-table-column label="单位" align="center" prop="unit" />
+      <el-table-column label="使用方向 对应BOM节点" align="center" prop="bomNodeId" />
+      <el-table-column label="使用类型(1维修 2保养 3临时)" align="center" prop="type" />
+      <el-table-column
+        label="出库时间"
+        align="center"
+        prop="deliveryTime"
+        :formatter="dateFormatter"
+        width="180px"
+      />
+      <el-table-column label="出库原因" align="center" prop="reason" />
+      <el-table-column label="排序" align="center" prop="sort" />
+      <el-table-column label="状态 0启用  1停用" align="center" prop="status" />
+      <el-table-column label="备注" align="center" prop="remark" />
+      <el-table-column label="流程实例id" align="center" prop="processInstanceId" />
+      <el-table-column label="审批状态 未提交、审批中、审批通过、审批不通过、已取消" align="center" prop="auditStatus" />
+      <el-table-column
+        label="创建时间"
+        align="center"
+        prop="createTime"
+        :formatter="dateFormatter"
+        width="180px"
+      />
+      <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="['pms:iot-outbound:update']"
+          >
+            编辑
+          </el-button>
+          <el-button
+            link
+            type="danger"
+            @click="handleDelete(scope.row.id)"
+            v-hasPermi="['pms:iot-outbound: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>
+
+  <!-- 表单弹窗:添加/修改 -->
+  <IotOutboundForm ref="formRef" @success="getList" />
+</template>
+
+<script setup lang="ts">
+import { dateFormatter } from '@/utils/formatTime'
+import download from '@/utils/download'
+import { IotOutboundApi, IotOutboundVO } from '@/api/pms/iotoutbound'
+import IotOutboundForm from './IotOutboundForm.vue'
+
+/** PMS 出库 列表 */
+defineOptions({ name: 'IotOutbound' })
+
+const message = useMessage() // 消息弹窗
+const { t } = useI18n() // 国际化
+
+const loading = ref(true) // 列表的加载中
+const list = ref<IotOutboundVO[]>([]) // 列表的数据
+const total = ref(0) // 列表的总页数
+const queryParams = reactive({
+  pageNo: 1,
+  pageSize: 10,
+  storageId: undefined,
+  deptId: undefined,
+  factory: undefined,
+  projectDepartment: undefined,
+  costCenter: undefined,
+  materialCode: undefined,
+  materialName: undefined,
+  materialGroupName: undefined,
+  materialGroupId: undefined,
+  quantity: undefined,
+  unitPrice: undefined,
+  unit: undefined,
+  bomNodeId: undefined,
+  type: undefined,
+  deliveryTime: [],
+  reason: undefined,
+  sort: undefined,
+  status: undefined,
+  remark: undefined,
+  processInstanceId: undefined,
+  auditStatus: undefined,
+  createTime: [],
+})
+const queryFormRef = ref() // 搜索的表单
+const exportLoading = ref(false) // 导出的加载中
+
+/** 查询列表 */
+const getList = async () => {
+  loading.value = true
+  try {
+    const data = await IotOutboundApi.getIotOutboundPage(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 IotOutboundApi.deleteIotOutbound(id)
+    message.success(t('common.delSuccess'))
+    // 刷新列表
+    await getList()
+  } catch {}
+}
+
+/** 导出按钮操作 */
+const handleExport = async () => {
+  try {
+    // 导出的二次确认
+    await message.exportConfirm()
+    // 发起导出
+    exportLoading.value = true
+    const data = await IotOutboundApi.exportIotOutbound(queryParams)
+    download.excel(data, 'PMS 出库.xls')
+  } catch {
+  } finally {
+    exportLoading.value = false
+  }
+}
+
+/** 初始化 **/
+onMounted(() => {
+  getList()
+})
+</script>

+ 197 - 0
src/views/pms/iotsapstock/IotSapStockForm.vue

@@ -0,0 +1,197 @@
+<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="deptId">
+        <el-input v-model="formData.deptId" placeholder="请输入组织部门id" />
+      </el-form-item>
+      <el-form-item label="工厂(SAP) 专业公司" prop="factory">
+        <el-input v-model="formData.factory" placeholder="请输入工厂(SAP) 专业公司" />
+      </el-form-item>
+      <el-form-item label="库存地点 - SAP 部门 项目部级 通用库 项目部库" prop="projectDepartment">
+        <el-input v-model="formData.projectDepartment" placeholder="请输入库存地点 - SAP 部门 项目部级 通用库 项目部库" />
+      </el-form-item>
+      <el-form-item label="物料编码" prop="materialCode">
+        <el-input v-model="formData.materialCode" placeholder="请输入物料编码" />
+      </el-form-item>
+      <el-form-item label="物料名称" prop="materialName">
+        <el-input v-model="formData.materialName" placeholder="请输入物料名称" />
+      </el-form-item>
+      <el-form-item label="物料组" prop="materialGroupName">
+        <el-input v-model="formData.materialGroupName" placeholder="请输入物料组" />
+      </el-form-item>
+      <el-form-item label="物料组id" prop="materialGroupId">
+        <el-input v-model="formData.materialGroupId" placeholder="请输入物料组id" />
+      </el-form-item>
+      <el-form-item label="数量" prop="quantity">
+        <el-input v-model="formData.quantity" placeholder="请输入数量" />
+      </el-form-item>
+      <el-form-item label="单价" prop="unitPrice">
+        <el-input v-model="formData.unitPrice" placeholder="请输入单价" />
+      </el-form-item>
+      <el-form-item label="单位" prop="unit">
+        <el-input v-model="formData.unit" placeholder="请输入单位" />
+      </el-form-item>
+      <el-form-item label="安全库存" prop="safetyStock">
+        <el-input v-model="formData.safetyStock" placeholder="请输入安全库存" />
+      </el-form-item>
+      <el-form-item label="货架id" prop="shelvesId">
+        <el-input v-model="formData.shelvesId" placeholder="请输入货架id" />
+      </el-form-item>
+      <el-form-item label="库位id" prop="cargoLocationId">
+        <el-input v-model="formData.cargoLocationId" placeholder="请输入库位id" />
+      </el-form-item>
+      <el-form-item label="类型(通用库 项目部库)" prop="type">
+        <el-select v-model="formData.type" placeholder="请选择类型(通用库 项目部库)">
+          <el-option label="请选择字典生成" value="" />
+        </el-select>
+      </el-form-item>
+      <el-form-item label="同步状态 0未同步 1同步成功 2同步失败" prop="syncStatus">
+        <el-radio-group v-model="formData.syncStatus">
+          <el-radio value="1">请选择字典生成</el-radio>
+        </el-radio-group>
+      </el-form-item>
+      <el-form-item label="最后一次同步时间" prop="syncTime">
+        <el-date-picker
+          v-model="formData.syncTime"
+          type="date"
+          value-format="x"
+          placeholder="选择最后一次同步时间"
+        />
+      </el-form-item>
+      <el-form-item label="同步失败时的错误信息" prop="syncError">
+        <el-input v-model="formData.syncError" placeholder="请输入同步失败时的错误信息" />
+      </el-form-item>
+      <el-form-item label="排序" prop="sort">
+        <el-input v-model="formData.sort" placeholder="请输入排序" />
+      </el-form-item>
+      <el-form-item label="状态 0启用  1停用" prop="status">
+        <el-radio-group v-model="formData.status">
+          <el-radio value="1">请选择字典生成</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 { IotSapStockApi, IotSapStockVO } from '@/api/pms/iotsapstock'
+
+/** PMS SAP 库存(通用库存/项目部库存) 表单 */
+defineOptions({ name: 'IotSapStockForm' })
+
+const { t } = useI18n() // 国际化
+const message = useMessage() // 消息弹窗
+
+const dialogVisible = ref(false) // 弹窗的是否展示
+const dialogTitle = ref('') // 弹窗的标题
+const formLoading = ref(false) // 表单的加载中:1)修改时的数据加载;2)提交的按钮禁用
+const formType = ref('') // 表单的类型:create - 新增;update - 修改
+const formData = ref({
+  id: undefined,
+  deptId: undefined,
+  factory: undefined,
+  projectDepartment: undefined,
+  materialCode: undefined,
+  materialName: undefined,
+  materialGroupName: undefined,
+  materialGroupId: undefined,
+  quantity: undefined,
+  unitPrice: undefined,
+  unit: undefined,
+  safetyStock: undefined,
+  shelvesId: undefined,
+  cargoLocationId: undefined,
+  type: undefined,
+  syncStatus: undefined,
+  syncTime: undefined,
+  syncError: undefined,
+  sort: undefined,
+  status: undefined,
+  remark: undefined,
+})
+const formRules = reactive({
+})
+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 IotSapStockApi.getIotSapStock(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 IotSapStockVO
+    if (formType.value === 'create') {
+      await IotSapStockApi.createIotSapStock(data)
+      message.success(t('common.createSuccess'))
+    } else {
+      await IotSapStockApi.updateIotSapStock(data)
+      message.success(t('common.updateSuccess'))
+    }
+    dialogVisible.value = false
+    // 发送操作成功的事件
+    emit('success')
+  } finally {
+    formLoading.value = false
+  }
+}
+
+/** 重置表单 */
+const resetForm = () => {
+  formData.value = {
+    id: undefined,
+    deptId: undefined,
+    factory: undefined,
+    projectDepartment: undefined,
+    materialCode: undefined,
+    materialName: undefined,
+    materialGroupName: undefined,
+    materialGroupId: undefined,
+    quantity: undefined,
+    unitPrice: undefined,
+    unit: undefined,
+    safetyStock: undefined,
+    shelvesId: undefined,
+    cargoLocationId: undefined,
+    type: undefined,
+    syncStatus: undefined,
+    syncTime: undefined,
+    syncError: undefined,
+    sort: undefined,
+    status: undefined,
+    remark: undefined,
+  }
+  formRef.value?.resetFields()
+}
+</script>

+ 407 - 0
src/views/pms/iotsapstock/index.vue

@@ -0,0 +1,407 @@
+<template>
+  <ContentWrap>
+    <!-- 搜索工作栏 -->
+    <el-form
+      class="-mb-15px"
+      :model="queryParams"
+      ref="queryFormRef"
+      :inline="true"
+      label-width="68px"
+    >
+      <el-form-item label="组织部门id" prop="deptId">
+        <el-input
+          v-model="queryParams.deptId"
+          placeholder="请输入组织部门id"
+          clearable
+          @keyup.enter="handleQuery"
+          class="!w-240px"
+        />
+      </el-form-item>
+      <el-form-item label="工厂(SAP) 专业公司" prop="factory">
+        <el-input
+          v-model="queryParams.factory"
+          placeholder="请输入工厂(SAP) 专业公司"
+          clearable
+          @keyup.enter="handleQuery"
+          class="!w-240px"
+        />
+      </el-form-item>
+      <el-form-item label="库存地点 - SAP 部门 项目部级 通用库 项目部库" prop="projectDepartment">
+        <el-input
+          v-model="queryParams.projectDepartment"
+          placeholder="请输入库存地点 - SAP 部门 项目部级 通用库 项目部库"
+          clearable
+          @keyup.enter="handleQuery"
+          class="!w-240px"
+        />
+      </el-form-item>
+      <el-form-item label="物料编码" prop="materialCode">
+        <el-input
+          v-model="queryParams.materialCode"
+          placeholder="请输入物料编码"
+          clearable
+          @keyup.enter="handleQuery"
+          class="!w-240px"
+        />
+      </el-form-item>
+      <el-form-item label="物料名称" prop="materialName">
+        <el-input
+          v-model="queryParams.materialName"
+          placeholder="请输入物料名称"
+          clearable
+          @keyup.enter="handleQuery"
+          class="!w-240px"
+        />
+      </el-form-item>
+      <el-form-item label="物料组" prop="materialGroupName">
+        <el-input
+          v-model="queryParams.materialGroupName"
+          placeholder="请输入物料组"
+          clearable
+          @keyup.enter="handleQuery"
+          class="!w-240px"
+        />
+      </el-form-item>
+      <el-form-item label="物料组id" prop="materialGroupId">
+        <el-input
+          v-model="queryParams.materialGroupId"
+          placeholder="请输入物料组id"
+          clearable
+          @keyup.enter="handleQuery"
+          class="!w-240px"
+        />
+      </el-form-item>
+      <el-form-item label="数量" prop="quantity">
+        <el-input
+          v-model="queryParams.quantity"
+          placeholder="请输入数量"
+          clearable
+          @keyup.enter="handleQuery"
+          class="!w-240px"
+        />
+      </el-form-item>
+      <el-form-item label="单价" prop="unitPrice">
+        <el-input
+          v-model="queryParams.unitPrice"
+          placeholder="请输入单价"
+          clearable
+          @keyup.enter="handleQuery"
+          class="!w-240px"
+        />
+      </el-form-item>
+      <el-form-item label="单位" prop="unit">
+        <el-input
+          v-model="queryParams.unit"
+          placeholder="请输入单位"
+          clearable
+          @keyup.enter="handleQuery"
+          class="!w-240px"
+        />
+      </el-form-item>
+      <el-form-item label="安全库存" prop="safetyStock">
+        <el-input
+          v-model="queryParams.safetyStock"
+          placeholder="请输入安全库存"
+          clearable
+          @keyup.enter="handleQuery"
+          class="!w-240px"
+        />
+      </el-form-item>
+      <el-form-item label="货架id" prop="shelvesId">
+        <el-input
+          v-model="queryParams.shelvesId"
+          placeholder="请输入货架id"
+          clearable
+          @keyup.enter="handleQuery"
+          class="!w-240px"
+        />
+      </el-form-item>
+      <el-form-item label="库位id" prop="cargoLocationId">
+        <el-input
+          v-model="queryParams.cargoLocationId"
+          placeholder="请输入库位id"
+          clearable
+          @keyup.enter="handleQuery"
+          class="!w-240px"
+        />
+      </el-form-item>
+      <el-form-item label="类型(通用库 项目部库)" prop="type">
+        <el-select
+          v-model="queryParams.type"
+          placeholder="请选择类型(通用库 项目部库)"
+          clearable
+          class="!w-240px"
+        >
+          <el-option label="请选择字典生成" value="" />
+        </el-select>
+      </el-form-item>
+      <el-form-item label="同步状态 0未同步 1同步成功 2同步失败" prop="syncStatus">
+        <el-select
+          v-model="queryParams.syncStatus"
+          placeholder="请选择同步状态 0未同步 1同步成功 2同步失败"
+          clearable
+          class="!w-240px"
+        >
+          <el-option label="请选择字典生成" value="" />
+        </el-select>
+      </el-form-item>
+      <el-form-item label="最后一次同步时间" prop="syncTime">
+        <el-date-picker
+          v-model="queryParams.syncTime"
+          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-220px"
+        />
+      </el-form-item>
+      <el-form-item label="同步失败时的错误信息" prop="syncError">
+        <el-input
+          v-model="queryParams.syncError"
+          placeholder="请输入同步失败时的错误信息"
+          clearable
+          @keyup.enter="handleQuery"
+          class="!w-240px"
+        />
+      </el-form-item>
+      <el-form-item label="排序" prop="sort">
+        <el-input
+          v-model="queryParams.sort"
+          placeholder="请输入排序"
+          clearable
+          @keyup.enter="handleQuery"
+          class="!w-240px"
+        />
+      </el-form-item>
+      <el-form-item label="状态 0启用  1停用" prop="status">
+        <el-select
+          v-model="queryParams.status"
+          placeholder="请选择状态 0启用  1停用"
+          clearable
+          class="!w-240px"
+        >
+          <el-option label="请选择字典生成" value="" />
+        </el-select>
+      </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="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-220px"
+        />
+      </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="['pms:iot-sap-stock:create']"
+        >
+          <Icon icon="ep:plus" class="mr-5px" /> 新增
+        </el-button>
+        <el-button
+          type="success"
+          plain
+          @click="handleExport"
+          :loading="exportLoading"
+          v-hasPermi="['pms:iot-sap-stock: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="主键" align="center" prop="id" />
+      <el-table-column label="组织部门id" align="center" prop="deptId" />
+      <el-table-column label="工厂(SAP) 专业公司" align="center" prop="factory" />
+      <el-table-column label="库存地点 - SAP 部门 项目部级 通用库 项目部库" align="center" prop="projectDepartment" />
+      <el-table-column label="物料编码" align="center" prop="materialCode" />
+      <el-table-column label="物料名称" align="center" prop="materialName" />
+      <el-table-column label="物料组" align="center" prop="materialGroupName" />
+      <el-table-column label="物料组id" align="center" prop="materialGroupId" />
+      <el-table-column label="数量" align="center" prop="quantity" />
+      <el-table-column label="单价" align="center" prop="unitPrice" />
+      <el-table-column label="单位" align="center" prop="unit" />
+      <el-table-column label="安全库存" align="center" prop="safetyStock" />
+      <el-table-column label="货架id" align="center" prop="shelvesId" />
+      <el-table-column label="库位id" align="center" prop="cargoLocationId" />
+      <el-table-column label="类型(通用库 项目部库)" align="center" prop="type" />
+      <el-table-column label="同步状态 0未同步 1同步成功 2同步失败" align="center" prop="syncStatus" />
+      <el-table-column
+        label="最后一次同步时间"
+        align="center"
+        prop="syncTime"
+        :formatter="dateFormatter"
+        width="180px"
+      />
+      <el-table-column label="同步失败时的错误信息" align="center" prop="syncError" />
+      <el-table-column label="排序" align="center" prop="sort" />
+      <el-table-column label="状态 0启用  1停用" align="center" prop="status" />
+      <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" min-width="120px">
+        <template #default="scope">
+          <el-button
+            link
+            type="primary"
+            @click="openForm('update', scope.row.id)"
+            v-hasPermi="['pms:iot-sap-stock:update']"
+          >
+            编辑
+          </el-button>
+          <el-button
+            link
+            type="danger"
+            @click="handleDelete(scope.row.id)"
+            v-hasPermi="['pms:iot-sap-stock: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>
+
+  <!-- 表单弹窗:添加/修改 -->
+  <IotSapStockForm ref="formRef" @success="getList" />
+</template>
+
+<script setup lang="ts">
+import { dateFormatter } from '@/utils/formatTime'
+import download from '@/utils/download'
+import { IotSapStockApi, IotSapStockVO } from '@/api/pms/iotsapstock'
+import IotSapStockForm from './IotSapStockForm.vue'
+
+/** PMS SAP 库存(通用库存/项目部库存) 列表 */
+defineOptions({ name: 'IotSapStock' })
+
+const message = useMessage() // 消息弹窗
+const { t } = useI18n() // 国际化
+
+const loading = ref(true) // 列表的加载中
+const list = ref<IotSapStockVO[]>([]) // 列表的数据
+const total = ref(0) // 列表的总页数
+const queryParams = reactive({
+  pageNo: 1,
+  pageSize: 10,
+  deptId: undefined,
+  factory: undefined,
+  projectDepartment: undefined,
+  materialCode: undefined,
+  materialName: undefined,
+  materialGroupName: undefined,
+  materialGroupId: undefined,
+  quantity: undefined,
+  unitPrice: undefined,
+  unit: undefined,
+  safetyStock: undefined,
+  shelvesId: undefined,
+  cargoLocationId: undefined,
+  type: undefined,
+  syncStatus: undefined,
+  syncTime: [],
+  syncError: undefined,
+  sort: undefined,
+  status: undefined,
+  remark: undefined,
+  createTime: [],
+})
+const queryFormRef = ref() // 搜索的表单
+const exportLoading = ref(false) // 导出的加载中
+
+/** 查询列表 */
+const getList = async () => {
+  loading.value = true
+  try {
+    const data = await IotSapStockApi.getIotSapStockPage(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 IotSapStockApi.deleteIotSapStock(id)
+    message.success(t('common.delSuccess'))
+    // 刷新列表
+    await getList()
+  } catch {}
+}
+
+/** 导出按钮操作 */
+const handleExport = async () => {
+  try {
+    // 导出的二次确认
+    await message.exportConfirm()
+    // 发起导出
+    exportLoading.value = true
+    const data = await IotSapStockApi.exportIotSapStock(queryParams)
+    download.excel(data, 'PMS SAP 库存(通用库存/项目部库存).xls')
+  } catch {
+  } finally {
+    exportLoading.value = false
+  }
+}
+
+/** 初始化 **/
+onMounted(() => {
+  getList()
+})
+</script>

+ 98 - 0
src/views/system/deptsaporg/DeptSapOrgForm.vue

@@ -0,0 +1,98 @@
+<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="deptId">
+        <el-input v-model="formData.deptId" placeholder="请输入组织部门id" />
+      </el-form-item>
+      <el-form-item label="SAP组织id(工厂/成本中心)" prop="sapOrgId">
+        <el-input v-model="formData.sapOrgId" placeholder="请输入SAP组织id(工厂/成本中心)" />
+      </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 { DeptSapOrgApi, DeptSapOrgVO } from '@/api/system/deptsaporg'
+
+/** PMS 组织部门与SAP工厂/成本中心 对应关系 表单 */
+defineOptions({ name: 'DeptSapOrgForm' })
+
+const { t } = useI18n() // 国际化
+const message = useMessage() // 消息弹窗
+
+const dialogVisible = ref(false) // 弹窗的是否展示
+const dialogTitle = ref('') // 弹窗的标题
+const formLoading = ref(false) // 表单的加载中:1)修改时的数据加载;2)提交的按钮禁用
+const formType = ref('') // 表单的类型:create - 新增;update - 修改
+const formData = ref({
+  id: undefined,
+  deptId: undefined,
+  sapOrgId: undefined,
+})
+const formRules = reactive({
+  deptId: [{ required: true, message: '组织部门id不能为空', trigger: 'blur' }],
+  sapOrgId: [{ required: true, message: 'SAP组织id(工厂/成本中心)不能为空', 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 DeptSapOrgApi.getDeptSapOrg(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 DeptSapOrgVO
+    if (formType.value === 'create') {
+      await DeptSapOrgApi.createDeptSapOrg(data)
+      message.success(t('common.createSuccess'))
+    } else {
+      await DeptSapOrgApi.updateDeptSapOrg(data)
+      message.success(t('common.updateSuccess'))
+    }
+    dialogVisible.value = false
+    // 发送操作成功的事件
+    emit('success')
+  } finally {
+    formLoading.value = false
+  }
+}
+
+/** 重置表单 */
+const resetForm = () => {
+  formData.value = {
+    id: undefined,
+    deptId: undefined,
+    sapOrgId: undefined,
+  }
+  formRef.value?.resetFields()
+}
+</script>

+ 198 - 0
src/views/system/deptsaporg/index.vue

@@ -0,0 +1,198 @@
+<template>
+  <ContentWrap>
+    <!-- 搜索工作栏 -->
+    <el-form
+      class="-mb-15px"
+      :model="queryParams"
+      ref="queryFormRef"
+      :inline="true"
+      label-width="68px"
+    >
+      <el-form-item label="组织部门id" prop="deptId">
+        <el-input
+          v-model="queryParams.deptId"
+          placeholder="请输入组织部门id"
+          clearable
+          @keyup.enter="handleQuery"
+          class="!w-240px"
+        />
+      </el-form-item>
+      <el-form-item label="SAP组织id(工厂/成本中心)" prop="sapOrgId">
+        <el-input
+          v-model="queryParams.sapOrgId"
+          placeholder="请输入SAP组织id(工厂/成本中心)"
+          clearable
+          @keyup.enter="handleQuery"
+          class="!w-240px"
+        />
+      </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-220px"
+        />
+      </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="['system:dept-sap-org:create']"
+        >
+          <Icon icon="ep:plus" class="mr-5px" /> 新增
+        </el-button>
+        <el-button
+          type="success"
+          plain
+          @click="handleExport"
+          :loading="exportLoading"
+          v-hasPermi="['system:dept-sap-org: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="组织部门id" align="center" prop="deptId" />
+      <el-table-column label="SAP组织id(工厂/成本中心)" align="center" prop="sapOrgId" />
+      <el-table-column
+        label="创建时间"
+        align="center"
+        prop="createTime"
+        :formatter="dateFormatter"
+        width="180px"
+      />
+      <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="['system:dept-sap-org:update']"
+          >
+            编辑
+          </el-button>
+          <el-button
+            link
+            type="danger"
+            @click="handleDelete(scope.row.id)"
+            v-hasPermi="['system:dept-sap-org: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>
+
+  <!-- 表单弹窗:添加/修改 -->
+  <DeptSapOrgForm ref="formRef" @success="getList" />
+</template>
+
+<script setup lang="ts">
+import { dateFormatter } from '@/utils/formatTime'
+import download from '@/utils/download'
+import { DeptSapOrgApi, DeptSapOrgVO } from '@/api/system/deptsaporg'
+import DeptSapOrgForm from './DeptSapOrgForm.vue'
+
+/** PMS 组织部门与SAP工厂/成本中心 对应关系 列表 */
+defineOptions({ name: 'DeptSapOrg' })
+
+const message = useMessage() // 消息弹窗
+const { t } = useI18n() // 国际化
+
+const loading = ref(true) // 列表的加载中
+const list = ref<DeptSapOrgVO[]>([]) // 列表的数据
+const total = ref(0) // 列表的总页数
+const queryParams = reactive({
+  pageNo: 1,
+  pageSize: 10,
+  deptId: undefined,
+  sapOrgId: undefined,
+  createTime: [],
+})
+const queryFormRef = ref() // 搜索的表单
+const exportLoading = ref(false) // 导出的加载中
+
+/** 查询列表 */
+const getList = async () => {
+  loading.value = true
+  try {
+    const data = await DeptSapOrgApi.getDeptSapOrgPage(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 DeptSapOrgApi.deleteDeptSapOrg(id)
+    message.success(t('common.delSuccess'))
+    // 刷新列表
+    await getList()
+  } catch {}
+}
+
+/** 导出按钮操作 */
+const handleExport = async () => {
+  try {
+    // 导出的二次确认
+    await message.exportConfirm()
+    // 发起导出
+    exportLoading.value = true
+    const data = await DeptSapOrgApi.exportDeptSapOrg(queryParams)
+    download.excel(data, 'PMS 组织部门与SAP工厂/成本中心 对应关系.xls')
+  } catch {
+  } finally {
+    exportLoading.value = false
+  }
+}
+
+/** 初始化 **/
+onMounted(() => {
+  getList()
+})
+</script>

+ 145 - 0
src/views/system/saporg/SapOrgForm.vue

@@ -0,0 +1,145 @@
+<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="sap工厂编号" prop="factoryCode">
+        <el-input v-model="formData.factoryCode" placeholder="请输入sap工厂编号" />
+      </el-form-item>
+      <el-form-item label="sap工厂名称" prop="factoryName">
+        <el-input v-model="formData.factoryName" placeholder="请输入sap工厂名称" />
+      </el-form-item>
+      <el-form-item label="SAP成本中心编码" prop="costCenterCode">
+        <el-input v-model="formData.costCenterCode" placeholder="请输入SAP成本中心编码" />
+      </el-form-item>
+      <el-form-item label="SAP成本中心名称" prop="costCenterName">
+        <el-input v-model="formData.costCenterName" placeholder="请输入SAP成本中心名称" />
+      </el-form-item>
+      <el-form-item label="SAP库位编码" prop="storageLocationCode">
+        <el-input v-model="formData.storageLocationCode" placeholder="请输入SAP库位编码" />
+      </el-form-item>
+      <el-form-item label="SAP库位名称" prop="storageLocationName">
+        <el-input v-model="formData.storageLocationName" placeholder="请输入SAP库位名称" />
+      </el-form-item>
+      <el-form-item label="类型(1工厂 2成本中心 3库位)" prop="type">
+        <el-select v-model="formData.type" placeholder="请选择类型(1工厂 2成本中心 3库位)">
+          <el-option label="请选择字典生成" value="" />
+        </el-select>
+      </el-form-item>
+      <el-form-item label="责任人id(多个逗号分隔)" prop="responsiblePerson">
+        <el-input v-model="formData.responsiblePerson" placeholder="请输入责任人id(多个逗号分隔)" />
+      </el-form-item>
+      <el-form-item label="分类排序" prop="sort">
+        <el-input v-model="formData.sort" placeholder="请输入分类排序" />
+      </el-form-item>
+      <el-form-item label="部门状态(0正常 1停用)" prop="status">
+        <el-radio-group v-model="formData.status">
+          <el-radio value="1">请选择字典生成</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 { SapOrgApi, SapOrgVO } from '@/api/system/saporg'
+
+/** SAP中的组织主数据(工厂 成本中心) 表单 */
+defineOptions({ name: 'SapOrgForm' })
+
+const { t } = useI18n() // 国际化
+const message = useMessage() // 消息弹窗
+
+const dialogVisible = ref(false) // 弹窗的是否展示
+const dialogTitle = ref('') // 弹窗的标题
+const formLoading = ref(false) // 表单的加载中:1)修改时的数据加载;2)提交的按钮禁用
+const formType = ref('') // 表单的类型:create - 新增;update - 修改
+const formData = ref({
+  id: undefined,
+  factoryCode: undefined,
+  factoryName: undefined,
+  costCenterCode: undefined,
+  costCenterName: undefined,
+  storageLocationCode: undefined,
+  storageLocationName: undefined,
+  type: undefined,
+  responsiblePerson: undefined,
+  sort: undefined,
+  status: undefined,
+  remark: undefined,
+})
+const formRules = reactive({
+})
+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 SapOrgApi.getSapOrg(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 SapOrgVO
+    if (formType.value === 'create') {
+      await SapOrgApi.createSapOrg(data)
+      message.success(t('common.createSuccess'))
+    } else {
+      await SapOrgApi.updateSapOrg(data)
+      message.success(t('common.updateSuccess'))
+    }
+    dialogVisible.value = false
+    // 发送操作成功的事件
+    emit('success')
+  } finally {
+    formLoading.value = false
+  }
+}
+
+/** 重置表单 */
+const resetForm = () => {
+  formData.value = {
+    id: undefined,
+    factoryCode: undefined,
+    factoryName: undefined,
+    costCenterCode: undefined,
+    costCenterName: undefined,
+    storageLocationCode: undefined,
+    storageLocationName: undefined,
+    type: undefined,
+    responsiblePerson: undefined,
+    sort: undefined,
+    status: undefined,
+    remark: undefined,
+  }
+  formRef.value?.resetFields()
+}
+</script>

+ 299 - 0
src/views/system/saporg/index.vue

@@ -0,0 +1,299 @@
+<template>
+  <ContentWrap>
+    <!-- 搜索工作栏 -->
+    <el-form
+      class="-mb-15px"
+      :model="queryParams"
+      ref="queryFormRef"
+      :inline="true"
+      label-width="68px"
+    >
+      <el-form-item label="sap工厂编号" prop="factoryCode">
+        <el-input
+          v-model="queryParams.factoryCode"
+          placeholder="请输入sap工厂编号"
+          clearable
+          @keyup.enter="handleQuery"
+          class="!w-240px"
+        />
+      </el-form-item>
+      <el-form-item label="sap工厂名称" prop="factoryName">
+        <el-input
+          v-model="queryParams.factoryName"
+          placeholder="请输入sap工厂名称"
+          clearable
+          @keyup.enter="handleQuery"
+          class="!w-240px"
+        />
+      </el-form-item>
+      <el-form-item label="SAP成本中心编码" prop="costCenterCode">
+        <el-input
+          v-model="queryParams.costCenterCode"
+          placeholder="请输入SAP成本中心编码"
+          clearable
+          @keyup.enter="handleQuery"
+          class="!w-240px"
+        />
+      </el-form-item>
+      <el-form-item label="SAP成本中心名称" prop="costCenterName">
+        <el-input
+          v-model="queryParams.costCenterName"
+          placeholder="请输入SAP成本中心名称"
+          clearable
+          @keyup.enter="handleQuery"
+          class="!w-240px"
+        />
+      </el-form-item>
+      <el-form-item label="SAP库位编码" prop="storageLocationCode">
+        <el-input
+          v-model="queryParams.storageLocationCode"
+          placeholder="请输入SAP库位编码"
+          clearable
+          @keyup.enter="handleQuery"
+          class="!w-240px"
+        />
+      </el-form-item>
+      <el-form-item label="SAP库位名称" prop="storageLocationName">
+        <el-input
+          v-model="queryParams.storageLocationName"
+          placeholder="请输入SAP库位名称"
+          clearable
+          @keyup.enter="handleQuery"
+          class="!w-240px"
+        />
+      </el-form-item>
+      <el-form-item label="类型(1工厂 2成本中心 3库位)" prop="type">
+        <el-select
+          v-model="queryParams.type"
+          placeholder="请选择类型(1工厂 2成本中心 3库位)"
+          clearable
+          class="!w-240px"
+        >
+          <el-option label="请选择字典生成" value="" />
+        </el-select>
+      </el-form-item>
+      <el-form-item label="责任人id(多个逗号分隔)" prop="responsiblePerson">
+        <el-input
+          v-model="queryParams.responsiblePerson"
+          placeholder="请输入责任人id(多个逗号分隔)"
+          clearable
+          @keyup.enter="handleQuery"
+          class="!w-240px"
+        />
+      </el-form-item>
+      <el-form-item label="分类排序" prop="sort">
+        <el-input
+          v-model="queryParams.sort"
+          placeholder="请输入分类排序"
+          clearable
+          @keyup.enter="handleQuery"
+          class="!w-240px"
+        />
+      </el-form-item>
+      <el-form-item label="部门状态(0正常 1停用)" prop="status">
+        <el-select
+          v-model="queryParams.status"
+          placeholder="请选择部门状态(0正常 1停用)"
+          clearable
+          class="!w-240px"
+        >
+          <el-option label="请选择字典生成" value="" />
+        </el-select>
+      </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="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-220px"
+        />
+      </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="['system:sap-org:create']"
+        >
+          <Icon icon="ep:plus" class="mr-5px" /> 新增
+        </el-button>
+        <el-button
+          type="success"
+          plain
+          @click="handleExport"
+          :loading="exportLoading"
+          v-hasPermi="['system:sap-org: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="sap工厂编号" align="center" prop="factoryCode" />
+      <el-table-column label="sap工厂名称" align="center" prop="factoryName" />
+      <el-table-column label="SAP成本中心编码" align="center" prop="costCenterCode" />
+      <el-table-column label="SAP成本中心名称" align="center" prop="costCenterName" />
+      <el-table-column label="SAP库位编码" align="center" prop="storageLocationCode" />
+      <el-table-column label="SAP库位名称" align="center" prop="storageLocationName" />
+      <el-table-column label="类型(1工厂 2成本中心 3库位)" align="center" prop="type" />
+      <el-table-column label="责任人id(多个逗号分隔)" align="center" prop="responsiblePerson" />
+      <el-table-column label="分类排序" align="center" prop="sort" />
+      <el-table-column label="部门状态(0正常 1停用)" align="center" prop="status" />
+      <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" min-width="120px">
+        <template #default="scope">
+          <el-button
+            link
+            type="primary"
+            @click="openForm('update', scope.row.id)"
+            v-hasPermi="['system:sap-org:update']"
+          >
+            编辑
+          </el-button>
+          <el-button
+            link
+            type="danger"
+            @click="handleDelete(scope.row.id)"
+            v-hasPermi="['system:sap-org: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>
+
+  <!-- 表单弹窗:添加/修改 -->
+  <SapOrgForm ref="formRef" @success="getList" />
+</template>
+
+<script setup lang="ts">
+import { dateFormatter } from '@/utils/formatTime'
+import download from '@/utils/download'
+import { SapOrgApi, SapOrgVO } from '@/api/system/saporg'
+import SapOrgForm from './SapOrgForm.vue'
+
+/** SAP中的组织主数据(工厂 成本中心) 列表 */
+defineOptions({ name: 'SapOrg' })
+
+const message = useMessage() // 消息弹窗
+const { t } = useI18n() // 国际化
+
+const loading = ref(true) // 列表的加载中
+const list = ref<SapOrgVO[]>([]) // 列表的数据
+const total = ref(0) // 列表的总页数
+const queryParams = reactive({
+  pageNo: 1,
+  pageSize: 10,
+  factoryCode: undefined,
+  factoryName: undefined,
+  costCenterCode: undefined,
+  costCenterName: undefined,
+  storageLocationCode: undefined,
+  storageLocationName: undefined,
+  type: undefined,
+  responsiblePerson: undefined,
+  sort: undefined,
+  status: undefined,
+  remark: undefined,
+  createTime: [],
+})
+const queryFormRef = ref() // 搜索的表单
+const exportLoading = ref(false) // 导出的加载中
+
+/** 查询列表 */
+const getList = async () => {
+  loading.value = true
+  try {
+    const data = await SapOrgApi.getSapOrgPage(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 SapOrgApi.deleteSapOrg(id)
+    message.success(t('common.delSuccess'))
+    // 刷新列表
+    await getList()
+  } catch {}
+}
+
+/** 导出按钮操作 */
+const handleExport = async () => {
+  try {
+    // 导出的二次确认
+    await message.exportConfirm()
+    // 发起导出
+    exportLoading.value = true
+    const data = await SapOrgApi.exportSapOrg(queryParams)
+    download.excel(data, 'SAP中的组织主数据(工厂 成本中心).xls')
+  } catch {
+  } finally {
+    exportLoading.value = false
+  }
+}
+
+/** 初始化 **/
+onMounted(() => {
+  getList()
+})
+</script>