SelectSapStock.vue 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243
  1. <template>
  2. <Dialog v-model="dialogVisible"
  3. title="选择SAP库存"
  4. style="width: 1100px; max-height: 800px" @close="handleClose">
  5. <div>
  6. <ContentWrap>
  7. <el-form
  8. class="-mb-15px"
  9. :model="queryParams"
  10. ref="queryFormRef"
  11. :inline="true"
  12. label-width="68px"
  13. >
  14. <el-form-item label="物料名称" prop="materialName">
  15. <el-input
  16. v-model="queryParams.materialName"
  17. placeholder="请输入物料名称"
  18. clearable
  19. @keyup.enter="handleQuery"
  20. class="!w-240px"
  21. />
  22. </el-form-item>
  23. <el-form-item label="物料编码" prop="code">
  24. <el-input
  25. v-model="queryParams.materialCode"
  26. placeholder="请输入物料编码"
  27. clearable
  28. @keyup.enter="handleQuery"
  29. class="!w-240px"
  30. />
  31. </el-form-item>
  32. <el-form-item>
  33. <el-button @click="handleQuery"><Icon icon="ep:search" class="mr-5px" /> 搜索</el-button>
  34. <el-button @click="resetQuery"><Icon icon="ep:refresh" class="mr-5px" /> 重置</el-button>
  35. <el-button @click="handleConfirm" class="custom-green-button"><Icon icon="ep:check" class="mr-5px" /> 确认选择</el-button>
  36. </el-form-item>
  37. </el-form>
  38. </ContentWrap>
  39. <ContentWrap>
  40. <el-table
  41. v-loading="loading"
  42. :data="list"
  43. :stripe="true"
  44. ref="tableRef"
  45. :show-overflow-tooltip="true"
  46. @row-click="handleRowClick"
  47. >
  48. <el-table-column width="60" label="选择">
  49. <template #default="{ row }">
  50. <el-checkbox
  51. :model-value="selectedRows.some(item => item.id === row.id)"
  52. @click.stop="toggleRow(row)"
  53. class="no-label-radio"
  54. />
  55. </template>
  56. </el-table-column>
  57. <el-table-column label="id" align="center" prop="id" width="120" v-if="false"/>
  58. <el-table-column
  59. label="物料编码"
  60. align="center"
  61. prop="materialCode"
  62. :show-overflow-tooltip="true"
  63. />
  64. <el-table-column
  65. label="物料名称"
  66. align="center"
  67. prop="materialName"
  68. :show-overflow-tooltip="true"
  69. />
  70. <el-table-column label="数量" align="center" prop="quantity" width="120" />
  71. <el-table-column label="单位" align="center" prop="unit" width="120" />
  72. <el-table-column label="单价" align="center" prop="unitPrice" width="120" />
  73. <el-table-column label="安全库存" align="center" prop="safetyStock">
  74. <template #default="scope">
  75. <el-input
  76. v-model="scope.row.safetyStock"
  77. @click.stop=""
  78. @focus="handleInputFocus(scope.row)"
  79. />
  80. </template>
  81. </el-table-column>
  82. </el-table>
  83. <!-- 分页 -->
  84. <Pagination
  85. :total="total"
  86. v-model:page="queryParams.pageNo"
  87. v-model:limit="queryParams.pageSize"
  88. @pagination="getList"
  89. />
  90. </ContentWrap>
  91. </div>
  92. </Dialog>
  93. </template>
  94. <script setup lang="ts">
  95. import { DictDataVO } from '@/api/system/dict/dict.data'
  96. import { dateFormatter } from '@/utils/formatTime'
  97. import * as MaterialApi from '@/api/pms/material'
  98. import * as SapStockApi from '@/api/pms/iotsapstock'
  99. import {DICT_TYPE} from "@/utils/dict";
  100. import {ContentWrap} from "@/components/ContentWrap";
  101. import {IotSapStockApi, IotSapStockVO} from "@/api/pms/iotsapstock";
  102. // 调整 emit 类型
  103. const emit = defineEmits<{
  104. (e: 'choose', value: SapStockApi.IotSapStockVO[]): void
  105. (e: 'close'): void
  106. }>()
  107. const dialogVisible = ref(false) // 弹窗的是否展示
  108. const loading = ref(true) // 列表的加载中
  109. const queryFormRef = ref() // 搜索的表单
  110. const list = ref<DictDataVO[]>([]) // 列表的数据
  111. const total = ref(0) // 列表的总页数
  112. const selectedRows = ref<SapStockApi.IotSapStockVO[]>([]); // 多选数据(存储所有选中行的数组)
  113. const tableRef = ref();
  114. const queryParams = reactive({
  115. pageNo: 1,
  116. pageSize: 10,
  117. label: '',
  118. materialName: undefined,
  119. materialCode: undefined,
  120. status: undefined,
  121. })
  122. const selectedRow = ref(null)
  123. // 多选 切换行选中状态
  124. const toggleRow = (row) => {
  125. const index = selectedRows.value.findIndex(item => item.id === row.id);
  126. if (index > -1) {
  127. selectedRows.value.splice(index, 1); // 取消选中
  128. } else {
  129. selectedRows.value.push(row); // 选中
  130. }
  131. };
  132. // 关闭时清空选择
  133. const handleClose = () => {
  134. tableRef.value?.clearSelection();
  135. selectedRows.value = []
  136. emit('close')
  137. };
  138. // 处理单选逻辑
  139. const selectRow = (row) => {
  140. selectedRow.value = selectedRow.value?.id === row.id ? null : row
  141. emit('choose', row)
  142. dialogVisible.value = false
  143. }
  144. // 确认选择
  145. const handleConfirm = () => {
  146. if (selectedRows.value.length === 0) {
  147. ElMessage.warning('请至少选择一个库存')
  148. return
  149. }
  150. emit('choose', selectedRows.value.map(row => ({
  151. ...row,
  152. // 确保返回必要字段
  153. code: row.code,
  154. name: row.name,
  155. unit: row.unit
  156. })))
  157. dialogVisible.value = false;
  158. handleClose()
  159. };
  160. // 点击整行选中
  161. const handleRowClick = (row) => {
  162. toggleRow(row);
  163. }
  164. const open = async (type: string, id?: number) => {
  165. dialogVisible.value = true
  166. await getList()
  167. }
  168. defineExpose({ open }) // 提供 open 方法,用于打开弹窗
  169. const getList = async () => {
  170. loading.value = true
  171. try {
  172. const data = await SapStockApi.IotSapStockApi.getIotSapStockPage(queryParams)
  173. list.value = data.list
  174. total.value = data.total
  175. } finally {
  176. loading.value = false
  177. }
  178. }
  179. // 处理输入框焦点事件(自动选中当前行)
  180. const handleInputFocus = (row: MaterialApi.MaterialVO) => {
  181. // 如果未选中则添加到选中列表
  182. const exists = selectedRows.value.some(item => item.id === row.id)
  183. if (!exists) {
  184. selectedRows.value.push(row)
  185. }
  186. }
  187. /** 搜索按钮操作 */
  188. const handleQuery = () => {
  189. queryParams.pageNo = 1
  190. getList()
  191. }
  192. const choose = (row: DictDataVO) => {
  193. emit('choose', row)
  194. dialogVisible.value = false
  195. }
  196. /** 重置按钮操作 */
  197. const resetQuery = () => {
  198. queryFormRef.value.resetFields()
  199. handleQuery()
  200. }
  201. /** 初始化 **/
  202. </script>
  203. <style lang="scss" scoped>
  204. .no-label-radio .el-radio__label {
  205. display: none;
  206. }
  207. .no-label-radio .el-radio__inner {
  208. margin-right: 0;
  209. }
  210. /* 自定义淡绿色按钮 */
  211. :deep(.custom-green-button) {
  212. background-color: #e1f3d8;
  213. border-color: #e1f3d8;
  214. color: #67c23a;
  215. }
  216. /* 悬停效果 */
  217. :deep(.custom-green-button:hover) {
  218. background-color: #d1e8c0;
  219. border-color: #d1e8c0;
  220. color: #5daf34;
  221. }
  222. /* 点击效果 */
  223. :deep(.custom-green-button:active) {
  224. background-color: #c2dca8;
  225. border-color: #c2dca8;
  226. }
  227. </style>