StockMoveItemForm.vue 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294
  1. <template>
  2. <el-form
  3. ref="formRef"
  4. :model="formData"
  5. :rules="formRules"
  6. v-loading="formLoading"
  7. label-width="0px"
  8. :inline-message="true"
  9. :disabled="disabled"
  10. >
  11. <el-table :data="formData" show-summary :summary-method="getSummaries" class="-mt-10px">
  12. <el-table-column label="序号" type="index" align="center" width="60" />
  13. <el-table-column label="调出仓库" min-width="125">
  14. <template #default="{ row, $index }">
  15. <el-form-item
  16. :prop="`${$index}.fromWarehouseId`"
  17. :rules="formRules.fromWarehouseId"
  18. class="mb-0px!"
  19. >
  20. <el-select
  21. v-model="row.fromWarehouseId"
  22. filterable
  23. placeholder="请选择调出仓库"
  24. @change="onChangeWarehouse($event, row)"
  25. >
  26. <el-option
  27. v-for="item in warehouseList"
  28. :key="item.id"
  29. :label="item.name"
  30. :value="item.id"
  31. />
  32. </el-select>
  33. </el-form-item>
  34. </template>
  35. </el-table-column>
  36. <el-table-column label="调入仓库" min-width="125">
  37. <template #default="{ row, $index }">
  38. <el-form-item
  39. :prop="`${$index}.toWarehouseId`"
  40. :rules="formRules.toWarehouseId"
  41. class="mb-0px!"
  42. >
  43. <el-select v-model="row.toWarehouseId" filterable placeholder="请选择调入仓库">
  44. <el-option
  45. v-for="item in warehouseList"
  46. :key="item.id"
  47. :label="item.name"
  48. :value="item.id"
  49. />
  50. </el-select>
  51. </el-form-item>
  52. </template>
  53. </el-table-column>
  54. <el-table-column label="产品名称" min-width="180">
  55. <template #default="{ row, $index }">
  56. <el-form-item :prop="`${$index}.productId`" :rules="formRules.productId" class="mb-0px!">
  57. <el-select
  58. v-model="row.productId"
  59. filterable
  60. @change="onChangeProduct($event, row)"
  61. placeholder="请选择产品"
  62. >
  63. <el-option
  64. v-for="item in productList"
  65. :key="item.id"
  66. :label="item.name"
  67. :value="item.id"
  68. />
  69. </el-select>
  70. </el-form-item>
  71. </template>
  72. </el-table-column>
  73. <el-table-column label="库存" min-width="100">
  74. <template #default="{ row }">
  75. <el-form-item class="mb-0px!">
  76. <el-input disabled v-model="row.stockCount" :formatter="erpCountInputFormatter" />
  77. </el-form-item>
  78. </template>
  79. </el-table-column>
  80. <el-table-column label="条码" min-width="150">
  81. <template #default="{ row }">
  82. <el-form-item class="mb-0px!">
  83. <el-input disabled v-model="row.productBarCode" />
  84. </el-form-item>
  85. </template>
  86. </el-table-column>
  87. <el-table-column label="单位" min-width="80">
  88. <template #default="{ row }">
  89. <el-form-item class="mb-0px!">
  90. <el-input disabled v-model="row.productUnitName" />
  91. </el-form-item>
  92. </template>
  93. </el-table-column>
  94. <el-table-column label="数量" prop="count" fixed="right" min-width="140">
  95. <template #default="{ row, $index }">
  96. <el-form-item :prop="`${$index}.count`" :rules="formRules.count" class="mb-0px!">
  97. <el-input-number
  98. v-model="row.count"
  99. controls-position="right"
  100. :min="0.001"
  101. :precision="3"
  102. class="!w-100%"
  103. />
  104. </el-form-item>
  105. </template>
  106. </el-table-column>
  107. <el-table-column label="产品单价" fixed="right" min-width="120">
  108. <template #default="{ row, $index }">
  109. <el-form-item
  110. :prop="`${$index}.productPrice`"
  111. :rules="formRules.productPrice"
  112. class="mb-0px!"
  113. >
  114. <el-input-number
  115. v-model="row.productPrice"
  116. controls-position="right"
  117. :min="0.01"
  118. :precision="2"
  119. class="!w-100%"
  120. />
  121. </el-form-item>
  122. </template>
  123. </el-table-column>
  124. <el-table-column label="合计金额" prop="totalPrice" fixed="right" min-width="100">
  125. <template #default="{ row, $index }">
  126. <el-form-item
  127. :prop="`${$index}.totalPrice`"
  128. :rules="formRules.totalPrice"
  129. class="mb-0px!"
  130. >
  131. <el-input disabled v-model="row.totalPrice" :formatter="erpPriceInputFormatter" />
  132. </el-form-item>
  133. </template>
  134. </el-table-column>
  135. <el-table-column label="备注" min-width="150">
  136. <template #default="{ row, $index }">
  137. <el-form-item :prop="`${$index}.remark`" :rules="formRules.remark" class="mb-0px!">
  138. <el-input v-model="row.remark" placeholder="请输入备注" />
  139. </el-form-item>
  140. </template>
  141. </el-table-column>
  142. <el-table-column align="center" fixed="right" label="操作" width="60">
  143. <template #default="{ $index }">
  144. <el-button @click="handleDelete($index)" link>—</el-button>
  145. </template>
  146. </el-table-column>
  147. </el-table>
  148. </el-form>
  149. <el-row justify="center" class="mt-3" v-if="!disabled">
  150. <el-button @click="handleAdd" round>+ 添加调度产品</el-button>
  151. </el-row>
  152. </template>
  153. <script setup lang="ts">
  154. import { ProductApi, ProductVO } from '@/api/erp/product/product'
  155. import { WarehouseApi, WarehouseVO } from '@/api/erp/stock/warehouse'
  156. import { StockApi } from '@/api/erp/stock/stock'
  157. import {
  158. erpCountInputFormatter,
  159. erpPriceInputFormatter,
  160. erpPriceMultiply,
  161. getSumValue
  162. } from '@/utils'
  163. const props = defineProps<{
  164. items: undefined
  165. disabled: false
  166. }>()
  167. const formLoading = ref(false) // 表单的加载中
  168. const formData = ref([])
  169. const formRules = reactive({
  170. inId: [{ required: true, message: '调度编号不能为空', trigger: 'blur' }],
  171. fromWarehouseId: [{ required: true, message: '调出仓库不能为空', trigger: 'blur' }],
  172. toWarehouseId: [{ required: true, message: '调入仓库不能为空', trigger: 'blur' }],
  173. productId: [{ required: true, message: '产品不能为空', trigger: 'blur' }],
  174. productId: [{ required: true, message: '产品不能为空', trigger: 'blur' }],
  175. count: [{ required: true, message: '产品数量不能为空', trigger: 'blur' }]
  176. })
  177. const formRef = ref([]) // 表单 Ref
  178. const productList = ref<ProductVO[]>([]) // 产品列表
  179. const warehouseList = ref<WarehouseVO[]>([]) // 仓库列表
  180. const defaultWarehouse = ref<WarehouseVO>(undefined) // 默认仓库
  181. /** 初始化设置调度项 */
  182. watch(
  183. () => props.items,
  184. async (val) => {
  185. formData.value = val
  186. },
  187. { immediate: true }
  188. )
  189. /** 监听合同产品变化,计算合同产品总价 */
  190. watch(
  191. () => formData.value,
  192. (val) => {
  193. if (!val || val.length === 0) {
  194. return
  195. }
  196. // 循环处理
  197. val.forEach((item) => {
  198. item.totalPrice = erpPriceMultiply(item.productPrice, item.count)
  199. })
  200. },
  201. { deep: true }
  202. )
  203. /** 合计 */
  204. const getSummaries = (param: SummaryMethodProps) => {
  205. const { columns, data } = param
  206. const sums: string[] = []
  207. columns.forEach((column, index) => {
  208. if (index === 0) {
  209. sums[index] = '合计'
  210. return
  211. }
  212. if (['count', 'totalPrice'].includes(column.property)) {
  213. const sum = getSumValue(data.map((item) => Number(item[column.property])))
  214. sums[index] =
  215. column.property === 'count' ? erpCountInputFormatter(sum) : erpPriceInputFormatter(sum)
  216. } else {
  217. sums[index] = ''
  218. }
  219. })
  220. return sums
  221. }
  222. /** 新增按钮操作 */
  223. const handleAdd = () => {
  224. const row = {
  225. id: undefined,
  226. fromWarehouseId: defaultWarehouse.value?.id,
  227. toWarehouseId: undefined,
  228. productId: undefined,
  229. productUnitName: undefined, // 产品单位
  230. productBarCode: undefined, // 产品条码
  231. productPrice: undefined,
  232. stockCount: undefined,
  233. count: 1,
  234. totalPrice: undefined,
  235. remark: undefined
  236. }
  237. formData.value.push(row)
  238. }
  239. /** 删除按钮操作 */
  240. const handleDelete = (index) => {
  241. formData.value.splice(index, 1)
  242. }
  243. /** 处理仓库变更 */
  244. const onChangeWarehouse = (warehouseId, row) => {
  245. // 加载库存
  246. setStockCount(row)
  247. }
  248. /** 处理产品变更 */
  249. const onChangeProduct = (productId, row) => {
  250. const product = productList.value.find((item) => item.id === productId)
  251. if (product) {
  252. row.productUnitName = product.unitName
  253. row.productBarCode = product.barCode
  254. row.productPrice = product.minPrice
  255. }
  256. // 加载库存
  257. setStockCount(row)
  258. }
  259. /** 加载库存 */
  260. const setStockCount = async (row) => {
  261. if (!row.productId || !row.fromWarehouseId) {
  262. return
  263. }
  264. const stock = await StockApi.getStock2(row.productId, row.fromWarehouseId)
  265. row.stockCount = stock ? stock.count : 0
  266. }
  267. /** 表单校验 */
  268. const validate = () => {
  269. return formRef.value.validate()
  270. }
  271. defineExpose({ validate })
  272. /** 初始化 */
  273. onMounted(async () => {
  274. productList.value = await ProductApi.getProductSimpleList()
  275. warehouseList.value = await WarehouseApi.getWarehouseSimpleList()
  276. defaultWarehouse.value = warehouseList.value.find((item) => item.defaultStatus)
  277. // 默认添加一个
  278. if (formData.value.length === 0) {
  279. handleAdd()
  280. }
  281. })
  282. </script>