IotConfigSafeStock.vue 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186
  1. <template>
  2. <ContentWrap>
  3. <ContentWrap>
  4. <!-- 搜索工作栏 -->
  5. <el-form
  6. class="-mb-15px"
  7. ref="queryFormRef"
  8. :inline="true"
  9. label-width="68px"
  10. >
  11. <el-form-item>
  12. <el-button @click="openForm" type="warning"
  13. ><Icon icon="ep:plus" class="mr-5px" />
  14. {{ t('stock.selectStock') }}</el-button
  15. >
  16. </el-form-item>
  17. </el-form>
  18. </ContentWrap>
  19. <!-- 列表 -->
  20. <ContentWrap>
  21. <el-table v-loading="loading" :data="list" :stripe="true" :show-overflow-tooltip="true">
  22. <el-table-column
  23. type="index"
  24. :label="t('iotDevice.serial')"
  25. width="70"
  26. align="center"
  27. />
  28. <el-table-column label="id" align="center" prop="id" v-if="false"/>
  29. <el-table-column :label="t('chooseMaintain.materialCode')" align="center" prop="materialCode" />
  30. <el-table-column :label="t('chooseMaintain.materialName')" align="center" prop="materialName" />
  31. <el-table-column :label="t('workOrderMaterial.unit')" align="center" prop="unit" />
  32. <el-table-column :label="t('workOrderMaterial.unitPrice')" align="center" prop="unitPrice" :formatter="erpPriceTableColumnFormatter" />
  33. <el-table-column :label="t('route.quantity')" align="center" prop="quantity" :formatter="erpPriceTableColumnFormatter" />
  34. <el-table-column :label="t('route.safetyStock')" align="center" prop="safetyStock" :formatter="erpPriceTableColumnFormatter" />
  35. <el-table-column :label="t('workplace.operation')" align="center" min-width="120px">
  36. <template #default="scope">
  37. <div style="display: flex; justify-content: center; align-items: center; width: 100%">
  38. <div>
  39. <Icon style="vertical-align: middle; color: #ea3434" icon="ep:zoom-out" />
  40. <el-button
  41. style="vertical-align: middle"
  42. link
  43. type="danger"
  44. @click="handleDelete(scope.row.code)"
  45. >
  46. {{ t('form.delete') }}
  47. </el-button>
  48. </div>
  49. </div>
  50. </template>
  51. </el-table-column>
  52. </el-table>
  53. </ContentWrap>
  54. <SelectSapStock ref="sapStockFormRef" @choose="stockChoose" />
  55. </ContentWrap>
  56. <ContentWrap>
  57. <el-form>
  58. <el-form-item style="float: right">
  59. <el-button @click="submitForm" type="primary" :disabled="formLoading">{{ t('iotMaintain.save') }}</el-button>
  60. <el-button @click="close">{{ t('iotMaintain.cancel') }}</el-button>
  61. </el-form-item>
  62. </el-form>
  63. </ContentWrap>
  64. </template>
  65. <script setup lang="ts">
  66. import { IotLockStockApi, IotLockStockVO } from '@/api/pms/iotlockstock'
  67. import { IotSapStockApi, IotSapStockVO } from '@/api/pms/iotsapstock'
  68. import * as UserApi from '@/api/system/user'
  69. import { useUserStore } from '@/store/modules/user'
  70. import { ref } from 'vue'
  71. import { toRaw } from "vue";
  72. import { useTagsViewStore } from '@/store/modules/tagsView'
  73. import SelectSapStock from "@/views/pms/iotsapstock/SelectSapStock.vue";
  74. import {erpPriceTableColumnFormatter} from "@/utils";
  75. /** 手工入库 表单 */
  76. defineOptions({ name: 'IotConfigSafeStock' })
  77. const { t } = useI18n() // 国际化
  78. const message = useMessage() // 消息弹窗
  79. const { delView } = useTagsViewStore() // 视图操作
  80. const { currentRoute, push } = useRouter()
  81. const deptUsers = ref<UserApi.UserVO[]>([]) // 用户列表
  82. const formLoading = ref(false) // 表单的加载中:1)修改时的数据加载;2)提交的按钮禁用
  83. const list = ref<IotLockStockVO[]>([]) // 入库物料的数据
  84. const { params, name } = useRoute() // 查询参数
  85. const sapStockFormRef = ref()
  86. const openForm = () => {
  87. sapStockFormRef.value.open()
  88. }
  89. const formRef = ref() // 表单 Ref
  90. const close = () => {
  91. delView(unref(currentRoute))
  92. push({ name: 'IotSapStockConfig', params:{}})
  93. }
  94. // 多选 物料
  95. const stockChoose = (selectedStocks) => {
  96. // 转换数据结构(根据你的接口定义调整)
  97. const newItems = selectedStocks.map(stock => ({
  98. id: stock.id,
  99. materialCode: stock.materialCode,
  100. materialName: stock.materialName,
  101. unit: stock.unit,
  102. quantity: stock.quantity,
  103. safetyStock: stock.safetyStock, // 安全库存数量
  104. unitPrice: stock.unitPrice, // 单价
  105. remark: null,
  106. code: stock.materialCode // 移除操作需要
  107. }))
  108. // 合并到现有列表(去重)
  109. newItems.forEach(item => {
  110. const exists = list.value.some(
  111. existing => existing.materialCode === item.materialCode
  112. )
  113. if (!exists) {
  114. list.value.push(item)
  115. }
  116. })
  117. }
  118. /** 提交表单 */
  119. const emit = defineEmits(['success']) // 定义 success 事件,用于操作成功后的回调
  120. const submitForm = async () => {
  121. if (toRaw(list.value).length == 0) {
  122. message.error('请选择库存')
  123. return
  124. }
  125. // 校验表单 校验 单价 数量
  126. if (list.value.length > 0) {
  127. const nullList = list.value.filter((item) => item.quantity===null)
  128. if (nullList.length > 0) {
  129. message.error('请填写数量')
  130. return
  131. }
  132. }
  133. if (list.value.length > 0) {
  134. const nullList = list.value.filter((item) => item.unitPrice===null)
  135. if (nullList.length > 0) {
  136. message.error('请填写单价')
  137. return
  138. }
  139. }
  140. // 提交请求
  141. formLoading.value = true
  142. try {
  143. // await IotLockStockApi.manualWarehouse(list.value)
  144. await IotSapStockApi.batchSetSafetyStock(list.value)
  145. message.success(t('common.createSuccess'))
  146. close()
  147. // 发送操作成功的事件
  148. emit('success')
  149. } finally {
  150. formLoading.value = false
  151. }
  152. }
  153. /** 重置表单 */
  154. const resetForm = () => {
  155. formRef.value?.resetFields()
  156. }
  157. onMounted(async () => {
  158. const deptId = useUserStore().getUser.deptId
  159. // deptUsers.value = await UserApi.getDeptUsersByDeptId(deptId)
  160. })
  161. // 调整删除逻辑
  162. const handleDelete = (code: string) => {
  163. const index = list.value.findIndex(item => item.code === code)
  164. if (index > -1) {
  165. list.value.splice(index, 1)
  166. }
  167. }
  168. </script>
  169. <style scoped>
  170. .base-expandable-content {
  171. overflow: hidden; /* 隐藏溢出的内容 */
  172. transition: max-height 0.3s ease; /* 平滑过渡效果 */
  173. }
  174. </style>