BigPicking.vue 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289
  1. <template>
  2. <van-dialog v-model:show="orderBigTrueFalseBy"
  3. :title="props.ownerMap[props.model.owner]?props.ownerMap[props.model.owner]+'-大件任务列表':props.model.owner+'-大件任务列表'"
  4. close-on-click-overlay
  5. :show-cancel-button="false"
  6. :show-confirm-button="false"
  7. >
  8. <div class="big-task-list" @click.stop>
  9. <div class="big-task-item" v-for="(item,index) in props.taskDetailList" :key="index" >
  10. <div class="big-task-content" >
  11. <div class="big-content">{{item.orderNo}}</div>
  12. <div class="big-carrier"><van-notice-bar :background="'none'" :speed="10" :text="item.carrierName" /></div>
  13. <div class="big-content" :style="item.hours>=2?'color:#ee0a24;font-weight: 500':''">{{item.totalItemNum}}<span style="font-size: 12px">件</span></div>
  14. </div>
  15. <div class="big-task-button">
  16. <div class="big-button" @click="onTypeOrder(item,'LOCATION_PICK')" >按库位查看</div>
  17. <div class="big-button" @click="onTypeOrder(item,'AISLE_PICK')">按巷道查看</div>
  18. <div class="big-button" @click="onTypeOrder(item,'ITEM_PICK')" >按商品查看</div>
  19. </div>
  20. </div>
  21. </div>
  22. </van-dialog>
  23. <van-dialog v-model:show="subBigOrderTrueFalseBy"
  24. :title="typeMap[taskType]+'拣货任务'+'-'+subModel.orderNo"
  25. show-cancel-button
  26. confirm-button-text="生成任务"
  27. close-on-click-overlay
  28. :beforeClose="onBuildTask"
  29. >
  30. <div class="sub-task-list" >
  31. <div style="display: flex;justify-content: space-between;">
  32. <div><van-checkbox class="sub-task-checkbox" v-model="isCheckAll" :indeterminate="isIndeterminate" @change="checkAllChange">全选</van-checkbox></div>
  33. <div v-if="taskType==='ITEM_PICK'" >
  34. <van-tag type="primary" :plain="sortType==='number'" @click="onSort('sql')">按排序规则</van-tag>
  35. <van-tag type="primary" :plain="sortType==='sql'" @click="onSort('number')">按库位数量</van-tag>
  36. </div>
  37. </div>
  38. <van-checkbox-group v-model="checkedResult" @change="checkedChange">
  39. <van-checkbox class="sub-task-checkbox" v-for="(item,index) in typeTaskList" :key="index" :name="item" :disabled="(item.allowPick===false && taskType==='AISLE_PICK') || item.status!==40" >
  40. <div class="sub-task-item" v-if="taskType==='LOCATION_PICK'">
  41. <div style="font-size: 13px;font-weight: bold" >{{item.location}}</div>
  42. <div class="sub-task-item-content" >
  43. <van-notice-bar :background="'none'" style="font-size:12px" :speed="20" :text="item.barcode" />
  44. </div>
  45. <div class="">{{item.totalItemNum}}<span style="font-size: 12px">件</span></div>
  46. </div>
  47. <div class="sub-task-item" v-if="taskType==='AISLE_PICK'">
  48. <div class="sub-task-item-content">{{item.aisleNo || '未绑定'}}</div>
  49. <div class="sub-task-item-content"><span style="font-size: 12px">库位:</span>{{item.locationNum}}<span style="font-size: 12px">个</span></div>
  50. <div class="sub-task-item-number">{{item.totalItemNum}}<span style="font-size: 12px">件</span></div>
  51. </div>
  52. <div style="display: flex;flex-direction: column;flex: 1" v-if="taskType==='ITEM_PICK'">
  53. <div class="sub-task-item" >
  54. <div class="sub-task-item-content" >{{item.barcode}}</div>
  55. <div class="sub-task-item-number"><span style="font-size: 12px">库位:</span>{{item.locationNum}}<span style="font-size: 12px">个</span></div>
  56. <div class="sub-task-item-number">{{item.totalItemNum}}<span style="font-size: 12px">件</span></div>
  57. </div>
  58. <div class="sub-task-item-tips" >
  59. <div ><van-notice-bar :background="'none'" :speed="10" color="#999" style="font-size: 12px" :text="item.skuName" /></div>
  60. <div >排序:{{item.spu}}</div>
  61. </div>
  62. </div>
  63. </van-checkbox>
  64. </van-checkbox-group>
  65. </div>
  66. </van-dialog>
  67. </template>
  68. <script setup>
  69. import { ref } from 'vue'
  70. import {
  71. getBigPickingAisleNo,
  72. getBigPickingGoods,
  73. getBigPickingList,
  74. getBigPickingLocation,
  75. } from '@/api/picking/index'
  76. import { closeLoading, showLoading } from '@/utils/loading'
  77. import { showToast } from 'vant'
  78. import { useRouter } from 'vue-router'
  79. const router = useRouter()
  80. const props = defineProps({
  81. taskDetailList: Array,
  82. ownerMap:Object,
  83. model:Object,
  84. warehouse:String
  85. });
  86. const typeMap={
  87. 'LOCATION_PICK':'库位',
  88. 'AISLE_PICK':'巷道',
  89. 'ITEM_PICK':'商品'
  90. }
  91. const isIndeterminate=ref(false)
  92. //大件任务列表弹框
  93. const orderBigTrueFalseBy=ref(false)
  94. const show=()=>{
  95. orderBigTrueFalseBy.value=true
  96. }
  97. // 子任务列表
  98. const typeTaskList=ref([])
  99. //任务类型
  100. const taskType=ref('LOCATION_PICK')
  101. //大件任务子订单
  102. const subBigOrderTrueFalseBy=ref(false)
  103. //子任务订单row
  104. const subModel=ref({})
  105. const sortType=ref('sql')
  106. const onTypeOrder=(row,type)=>{
  107. taskType.value=type
  108. subModel.value=row
  109. const params={
  110. warehouse:props.warehouse,
  111. orderNo:row.orderNo,
  112. type,
  113. status:40,
  114. page:1,
  115. size:2000,
  116. }
  117. showLoading()
  118. getBigPickingList(params).then(res=>{
  119. res.data.records.forEach((item,index)=>{
  120. item.sqlIndex=index
  121. })
  122. typeTaskList.value=res.data.records
  123. onSort('sql')
  124. subBigOrderTrueFalseBy.value=true
  125. isIndeterminate.value = false
  126. isCheckAll.value=false
  127. }).catch(err=>{
  128. typeTaskList.value=[]
  129. subBigOrderTrueFalseBy.value=false
  130. isIndeterminate.value = false
  131. isCheckAll.value=false
  132. }).finally(e=>{
  133. closeLoading()
  134. })
  135. }
  136. //是否全选
  137. const isCheckAll = ref(false)
  138. //选中数据
  139. const checkedResult = ref([])
  140. const checkAllChange = (val) => {
  141. let filteredList=typeTaskList.value
  142. if(taskType.value==='AISLE_PICK'){
  143. filteredList = typeTaskList.value.filter(item => item.allowPick !== false )
  144. }else{
  145. typeTaskList.value.filter(item => item.status!==40 )
  146. }
  147. checkedResult.value = val ? filteredList : []
  148. isIndeterminate.value = false
  149. }
  150. const checkedChange = (value) => {
  151. const checkedCount = value.length
  152. isCheckAll.value = checkedCount === typeTaskList.value.length
  153. isIndeterminate.value = checkedCount > 0 && checkedCount < typeTaskList.value.length
  154. }
  155. const onBuildTask=(action)=>
  156. new Promise((resolve) => {
  157. if (action === 'confirm') {
  158. if (checkedResult.value.length === 0) {
  159. showToast('请先选择订单')
  160. return resolve(false)
  161. }
  162. orderBigTrueFalseBy.value=false
  163. const fieldMap = {
  164. 'ITEM_PICK': 'lotNum',
  165. 'AISLE_PICK': 'aisleNo',
  166. 'LOCATION_PICK': 'location'
  167. };
  168. const field = fieldMap[taskType.value];
  169. createPicking(checkedResult.value,field)
  170. }
  171. resolve(true)
  172. })
  173. const createPicking=(checkedResult,field)=>{
  174. let list = []
  175. checkedResult.forEach(item => {
  176. list.push(item[field])
  177. });
  178. const params = {
  179. warehouse: props.warehouse,
  180. orderNo: subModel.value.orderNo,
  181. list
  182. }
  183. // 根据不同的拣货类型选择不同的接口
  184. let api;
  185. if (field === 'aisleNo') {
  186. api = getBigPickingAisleNo;
  187. } else if (field === 'lotNum') {
  188. api = getBigPickingGoods;
  189. } else if (field === 'location') {
  190. api = getBigPickingLocation;
  191. }
  192. showLoading()
  193. api(params).then(res => {
  194. console.log(res,"data")
  195. closeLoading()
  196. showToast({duration:5000,message:'大件任务创建成功!正在跳转'})
  197. router.push({name:'PickingList',query: { code:res.data }})
  198. }).finally(e=>{
  199. closeLoading()
  200. })
  201. }
  202. const onSort = (val) => {
  203. sortType.value = val;
  204. // 提取排序条件的字段
  205. const sortField = val === 'sql' ? 'sqlIndex' : 'locationNum';
  206. // 过滤出 status 为 40 的任务并排序
  207. const sorted = typeTaskList.value
  208. .filter(item => item.status === 40)
  209. .sort((a, b) => b[sortField] - a[sortField]);
  210. // 合并排序后的数组和 status 不等于 40 的任务
  211. typeTaskList.value = [
  212. ...sorted,
  213. ...typeTaskList.value.filter(item => item.status !== 40)
  214. ]
  215. }
  216. defineExpose({show})
  217. </script>
  218. <style lang="sass" scoped>
  219. //大件拣货
  220. .big-task-list
  221. max-height: 70vh
  222. min-height: 20vh
  223. overflow: scroll
  224. padding: 0 10px
  225. .big-task-item
  226. margin-bottom: 10px
  227. //box-shadow: 1px 1px 5px rgba(0, 0, 0, 0.4)
  228. border-radius: 8px
  229. border: 1px solid #d3d3d3
  230. .big-task-content
  231. display: flex
  232. align-items: center
  233. padding: 5px 10px
  234. font-size: 14px
  235. font-weight: bold
  236. .big-carrier
  237. width: 30%
  238. .big-content
  239. flex: 1
  240. .big-task-button
  241. font-size: 14px
  242. font-weight: bold
  243. display: flex
  244. align-items: center
  245. color: #0077ff
  246. border-top: 1px solid #dfdfdf
  247. .big-button
  248. height: 38px
  249. line-height: 38px
  250. flex: 1
  251. border-right: 1px solid #dfdfdf
  252. .big-button:last-child
  253. border-right: 0
  254. .big-button:active
  255. background-color: #d9d9d9
  256. //子任务
  257. .sub-task-list
  258. padding: 5px 10px
  259. max-height: 60vh
  260. overflow: scroll
  261. .sub-task-checkbox
  262. padding: 4px 0
  263. :deep(.van-checkbox__label)
  264. display: flex
  265. flex: 1
  266. .sub-task-item
  267. display: flex
  268. flex: 1
  269. align-items: center
  270. justify-content: space-between
  271. .sub-task-item-content
  272. font-size: 13px
  273. font-weight: bold
  274. flex: 1
  275. text-align: left
  276. .sub-task-item-number
  277. width: 60px
  278. .sub-task-item-tips
  279. font-size: 12px
  280. color: #999
  281. display: flex
  282. justify-content: space-between
  283. div
  284. flex: 1
  285. text-align: right
  286. </style>