index.vue 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232
  1. <template>
  2. <div class="register">
  3. <van-nav-bar
  4. title="加工建单" left-arrow fixed placeholder @click-left="goBack" @click-right="onConfirm()">
  5. <template #left>
  6. <van-icon name="arrow-left" size="25" />
  7. <div style="color: #fff">返回</div>
  8. </template>
  9. <template #right>
  10. <div style="color: #fff">提交</div>
  11. </template>
  12. </van-nav-bar>
  13. <van-field v-model="date" type="text" label="登记日期" placeholder="请选择日期"
  14. readonly is-link input-align="right" @click="dateTrueFalseBy=true" required
  15. />
  16. <van-field v-model="ownerCode" type="text" label="登记货主" placeholder="请选择货主" readonly
  17. is-link @click="ownerRef.show(1)" input-align="right" required
  18. />
  19. <van-field v-model="code" type="textarea" label="单据信息" placeholder="请填写快递单号/收货任务号,多个用逗号/空格/换行符进行分割"
  20. show-word-limit maxlength="500" rows="2" autosize required
  21. />
  22. <van-field v-model="note" type="textarea" label="&nbsp;&nbsp;备注信息" placeholder="请输入备注信息"
  23. show-word-limit maxlength="500" rows="1" autosize
  24. />
  25. <div class="register-content">
  26. <div class="add-type">
  27. <van-button type="primary" round size="small" @click="addType">添加类型</van-button>
  28. </div>
  29. <div class="type-box">
  30. <div class="type-title">类型表一览</div>
  31. <div class="type-list">
  32. <div class="type-item">
  33. <div class="type-item-item">类型</div>
  34. <div class="type-item-operate">数量</div>
  35. <div class="type-item-operate">操作</div>
  36. </div>
  37. <div class="type-item" v-for="(item,index) in typeList" v-if="typeList.length>0">
  38. <div class="type-item-item">{{getOperate(item.operate)}}</div>
  39. <div class="type-item-operate">{{item.expectAmount}}</div>
  40. <div class="type-item-delete" @click="del(item,index)" >删除</div>
  41. </div>
  42. <div v-else>
  43. <van-empty :image="<string>nodataUrl" image-size="140" >
  44. <van-button round type="primary" class="bottom-button" size="small" @click="addType">添加</van-button>
  45. </van-empty>
  46. </div>
  47. </div>
  48. </div>
  49. </div>
  50. <owner ref="ownerRef" @onOwner="onOwner" />
  51. <van-calendar first-day-of-week="1" v-model:show="dateTrueFalseBy" @confirm="dateConfirm" />
  52. <add-register-type ref="addRegisterTypeRef"
  53. :processingTypeList="processingTypeList"
  54. @setProcessingType="setProcessingType" />
  55. </div>
  56. </template>
  57. <script setup lang="ts">
  58. import { ref } from 'vue'
  59. import { getHeader, goBack, scanError, scanSuccess } from '@/utils/android'
  60. import { showConfirmDialog, showNotify, showToast } from 'vant'
  61. import { useStore } from '@/store/modules/user'
  62. import { closeLoading, showLoading } from '@/utils/loading'
  63. import Owner from '@/components/Owner.vue'
  64. import { formatDate } from '@/utils/date'
  65. import { useRouter } from 'vue-router'
  66. import nodataUrl from '@/assets/nodata.png'
  67. import AddRegisterType from '@/views/processing/register/components/addRegisterType.vue'
  68. import { createProcessing, getProcessingTypeList } from '@/api/processing'
  69. import { toArray, toMap } from '@/utils/dataType'
  70. const router = useRouter()
  71. try {
  72. getHeader()
  73. }catch (error) {
  74. router.push('/login')
  75. }
  76. const store = useStore()
  77. const warehouse = store.warehouse
  78. const ownerRef = ref(null)
  79. const ownerItem = ref({})
  80. const ownerCode = ref('')
  81. const date = ref(formatDate(new Date()))
  82. const note = ref('')
  83. const code=ref('')
  84. const processingTypeList=ref([])
  85. const processingTypeMap=ref({})
  86. //添加类型
  87. const addRegisterTypeRef=ref(null)
  88. const typeList = ref([])
  89. const dateTrueFalseBy = ref(false)
  90. //选择货主
  91. const onOwner = (item) => {
  92. ownerItem.value = item
  93. ownerCode.value = item.name
  94. }
  95. //选择日期
  96. const dateConfirm = (e) => {
  97. date.value = formatDate(e)
  98. dateTrueFalseBy.value = false
  99. }
  100. //提交登记
  101. const onConfirm = () => {
  102. if(!ownerCode.value){
  103. showNotify({ type: 'warning', duration: 3000, message: '请选择货主' })
  104. scanError()
  105. return
  106. }
  107. if(typeList.value.length==0){
  108. showNotify({ type: 'warning', duration: 3000, message: '请先添加单据类型' })
  109. scanError()
  110. return
  111. }
  112. if(!code.value){
  113. showNotify({ type: 'warning', duration: 3000, message: '请先添加单据信息' })
  114. scanError()
  115. return
  116. }
  117. showConfirmDialog({
  118. title: '温馨提示', message:'是否确认建单' })
  119. .then(() => {
  120. _createProcessing()
  121. }).catch(() => {})
  122. }
  123. const _createProcessing=()=>{
  124. const data={owner:ownerItem.value.id,ownerCode:ownerItem.value.code,note:note.value,warehouse,typeList:typeList.value,noList:toArray(code.value)}
  125. showLoading()
  126. createProcessing(data).then(res=>{
  127. closeLoading()
  128. scanSuccess()
  129. showConfirmDialog({
  130. title: '建单成功',
  131. message:`加工单号为:${res.data}`,
  132. confirmButtonText:'复制'
  133. })
  134. .then(() => {
  135. copyText(res.data)
  136. })
  137. .catch(() => {});
  138. reset()
  139. }).catch(err=>{
  140. scanError()
  141. closeLoading()
  142. })
  143. }
  144. const copyText=(txt) =>{
  145. const textarea = document.createElement('textarea');
  146. textarea.value =txt;
  147. document.body.appendChild(textarea);
  148. textarea.select();
  149. try {
  150. const successful = document.execCommand('copy');
  151. if (successful) {
  152. showNotify({ type: 'success', duration: 3000, message: '已复制' })
  153. } else {
  154. console.error('复制失败');
  155. }
  156. } catch (err) {
  157. showNotify({ type: 'danger', duration: 3000, message: '复制失败' })
  158. } finally {
  159. document.body.removeChild(textarea);
  160. }
  161. }
  162. const reset=()=>{
  163. code.value=""
  164. typeList.value=[]
  165. note.value=""
  166. ownerCode.value=''
  167. }
  168. //添加类型
  169. const addType=()=>{
  170. addRegisterTypeRef.value?.show(typeList.value)
  171. }
  172. const setProcessingType=(data)=>{
  173. typeList.value.push(data)
  174. }
  175. //转换类型名称
  176. const getOperate=(operate)=>{
  177. const result = operate.map(item => processingTypeMap.value[item] || item)
  178. return result.join(',')
  179. }
  180. //获取类型
  181. const _getProcessingTypeList=()=>{
  182. getProcessingTypeList().then(res=>{
  183. processingTypeList.value=res.data
  184. processingTypeMap.value=toMap(res.data,'code','name')
  185. })
  186. }
  187. const del=(item,index)=>{
  188. typeList.value.splice(index,1)
  189. }
  190. _getProcessingTypeList()
  191. </script>
  192. <style scoped lang="sass">
  193. .register
  194. .register-content
  195. background: #fff
  196. padding: 10px
  197. font-size: 14px
  198. .add-type
  199. text-align: right
  200. .type-box
  201. text-align: left
  202. .type-title
  203. line-height: 30px
  204. color: #999
  205. .type-list
  206. border: 1px solid #e9e9e9
  207. border-radius: 6px
  208. padding: 5px 10px
  209. .type-item
  210. display: flex
  211. align-items: center
  212. border-bottom: 1px solid #e9e9e9
  213. padding: 3px 0
  214. .type-item-item
  215. flex: 1
  216. .type-item-operate
  217. width: 70px
  218. text-align: center
  219. .type-item-delete
  220. width: 70px
  221. text-align: center
  222. color: #ff4141
  223. text-decoration: underline
  224. .type-item:last-child
  225. border-bottom: none
  226. </style>