index.vue 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349
  1. <template>
  2. <z-paging ref="paging" bgColor="#f7f7f7" safe-area-inset-bottom scroll-with-animation>
  3. <template #top>
  4. <ut-navbar :title="'修改包装任务'" :fixed="false" border></ut-navbar>
  5. </template>
  6. <up-form class="p-rtv bg-#fff" labelPosition="top" :model="form" :rules="rules" labelWidth="auto" ref="upFormRef">
  7. <view class="pd-24 bg-#fff mb-10">
  8. <view class="h-1" id="inputStorageIdpppp"></view>
  9. <up-form-item borderBottom label="选择包装对象" prop="inputStorageId" required>
  10. <view class="flex1">
  11. <view class="bg-#FBFDFB card-info-block p-rtv border-#A9D7B4 b-radius">
  12. <ObjectCardStorage :item="form.stroeObject" :showInOutAmount="false"></ObjectCardStorage>
  13. </view>
  14. </view>
  15. </up-form-item>
  16. <view class="h-1" id="storageUseAmountpppp"></view>
  17. <up-form-item borderBottom label="本次包装用量" prop="storageUseAmount" required>
  18. <up-input v-model="form.storageUseAmount" color="#999" readonly placeholder="请输入本次包装用量" border="none" clearable></up-input>
  19. <template #right>
  20. <span class="f-s-30 f-w-5 c-#333">{{ form?.storageUseUnit || 'kg' }}</span>
  21. </template>
  22. </up-form-item>
  23. <view class="h-1" id="capacitypppp"></view>
  24. <view class="h-1" id="unitpppp"></view>
  25. <up-form-item label="包装规格" prop="spec" required class="form-item-bottom-padding-0">
  26. <div class="flex1 d-flex">
  27. <div class="flex1 ov-hd">
  28. <up-form-item prop="capacity" border-bottom class="form-item-top-padding-0">
  29. <up-input v-model="form.capacity" color="#999" readonly placeholder="请输入包装规格" border="none" clearable></up-input>
  30. </up-form-item>
  31. </div>
  32. <div class="pd-5"></div>
  33. <div class="w-200">
  34. <up-form-item prop="storageUseUnit" border-bottom class="form-item-top-padding-0">
  35. <up-input v-model="form.storageUseUnit" color="#999" inputAlign="center" readonly placeholder="单位" border="none" clearable></up-input>
  36. </up-form-item>
  37. </div>
  38. <div class="pd2-0-10 c-#ccc d-flex a-c j-c">/</div>
  39. <div class="w-200">
  40. <ut-action-sheet v-model="form.unit" :tabs="pt_pack_spec_unit" mode="custom" title="选择单位">
  41. <up-form-item prop="unit" border-bottom class="form-item-top-padding-0">
  42. <up-input v-model="form.unit" inputAlign="center" readonly placeholder="单位" border="none" clearable></up-input>
  43. <template #right>
  44. <up-icon size="22rpx" color="#37A954" name="arrow-down-fill"></up-icon>
  45. </template>
  46. </up-form-item>
  47. </ut-action-sheet>
  48. </div>
  49. </div>
  50. </up-form-item>
  51. <view class="h-1" id="packagingDateStartpppp"></view>
  52. <view class="h-1" id="packagingDateEndpppp"></view>
  53. <up-form-item required label="包装日期" class="form-item-bottom-padding-0">
  54. <view class="flex1 d-flex">
  55. <view class="flex1">
  56. <ut-datetime-picker v-model="form.packagingDateStart" :maxDate="form.packagingDateEnd" mode="date">
  57. <up-form-item borderBottom prop="packagingDateStart" class="form-item-top-padding-0">
  58. <up-input v-model="form.packagingDateStart" readonly placeholder="包装开始日期" border="none" clearable></up-input>
  59. <template #right>
  60. <up-icon size="22rpx" color="#37A954" name="arrow-down-fill"></up-icon>
  61. </template>
  62. </up-form-item>
  63. </ut-datetime-picker>
  64. </view>
  65. <view class="pd2-0-20"></view>
  66. <view class="flex1">
  67. <ut-datetime-picker v-model="form.packagingDateEnd" :minDate="form.packagingDateStart" mode="date">
  68. <up-form-item borderBottom prop="packagingDateEnd" class="form-item-top-padding-0">
  69. <up-input v-model="form.packagingDateEnd" readonly placeholder="包装结束日期" border="none" clearable></up-input>
  70. <template #right>
  71. <up-icon size="22rpx" color="#37A954" name="arrow-down-fill"></up-icon>
  72. </template>
  73. </up-form-item>
  74. </ut-datetime-picker>
  75. </view>
  76. </view>
  77. </up-form-item>
  78. <!-- 包装批号 -->
  79. <view class="h-1" id="packSnpppp"></view>
  80. <up-form-item borderBottom label="包装批号" prop="packSn" required>
  81. <up-input v-model="form.packSn" placeholder="请输入包装批号" border="none" clearable></up-input>
  82. <template #right>
  83. <up-button @click="generateBatchCode" type="primary" :customStyle="formItemBtnStyle">随机生成</up-button>
  84. </template>
  85. </up-form-item>
  86. <view class="h-1" id="batchSnpppp"></view>
  87. <up-form-item borderBottom label="成品批号" prop="batchSn" required>
  88. <up-input v-model="form.batchSn" placeholder="请输入成品批号" border="none" clearable></up-input>
  89. </up-form-item>
  90. <!-- 保质期 12月,数字加单位单位两个字段, expireDate,expireDateUnit -->
  91. <view class="h-1" id="expireDatepppp"></view>
  92. <view class="h-1" id="expireDateUnitpppp"></view>
  93. <up-form-item label="保质期" class="form-item-bottom-padding-0">
  94. <div class="flex1 d-flex a-c">
  95. <div class="flex1 ov-hd">
  96. <up-form-item prop="expireDate" border-bottom class="form-item-top-padding-0">
  97. <up-input v-model="form.expireDate" placeholder="请输入保质期" border="none" clearable></up-input>
  98. </up-form-item>
  99. </div>
  100. <div class="pd-5"></div>
  101. <div class="w-200">
  102. <ut-action-sheet v-model="form.expireDateUnit" :tabs="pt_expire_date_unit" mode="custom" title="选择单位">
  103. <up-form-item prop="expireDateUnit" border-bottom class="form-item-top-padding-0">
  104. <up-input v-model="form.expireDateUnit" inputAlign="center" readonly placeholder="单位" border="none" clearable></up-input>
  105. <template #right>
  106. <up-icon size="22rpx" color="#37A954" name="arrow-down-fill"></up-icon>
  107. </template>
  108. </up-form-item>
  109. </ut-action-sheet>
  110. </div>
  111. </div>
  112. </up-form-item>
  113. <!-- 请选择赋码方式 -->
  114. <view class="h-1" id="refTypepppp"></view>
  115. <up-form-item borderBottom label="赋码方式" required prop="refType">
  116. <view v-if="form.refType" class="f-s-30 c-999 f-w-5 flex1">{{ selectDictLabel(pt_pack_ref_type, form.refType) }}</view>
  117. <view v-else class="f-s-30 c-ccc f-w-4 flex1">请选择赋码方式</view>
  118. </up-form-item>
  119. <view class="d-flex a-c pd2-10-0" @click="$u.route({ url: '/tools/view-html/index', params: { url: 'https://yujin-szyy.oss-cn-chengdu.aliyuncs.com/szyy/template/pack_code_type.html', title: '赋码方式区别' } })">
  120. <up-icon size="28rpx" name="question-circle" color="#37A954"></up-icon>
  121. <span class="c-primary f-s-24">两种赋码方式的区别?怎么选择?</span>
  122. </view>
  123. </view>
  124. </up-form>
  125. <view class="d-flex flex-cln a-c pd3-40-24-24">
  126. <view class="f-s-30 c-#333 f-w-5 mb-16">
  127. <span>预计分包数:</span>
  128. <span class="f-s-46 c-primary f-w-7">{{ packResult.packNum || '-' }}</span>
  129. <span>包</span>
  130. </view>
  131. <view class="d-flex a-c mb-30">
  132. <view class="f-s-28 c-#333">包装规格:</view>
  133. <view class="d-flex a-c gap-24">
  134. <view class="bg-#E3EFE6 pd2-12-28 c-primary radius-8 f-s-26">{{ packResult.spec1 || '-' }}</view>
  135. <view v-if="packResult.spec2" class="bg-#E3EFE6 pd2-12-28 c-primary radius-8 f-s-26">{{ packResult.spec2 || '-' }}</view>
  136. </view>
  137. </view>
  138. <up-button type="primary" @click="submit">确认修改</up-button>
  139. </view>
  140. </z-paging>
  141. </template>
  142. <script setup lang="ts">
  143. import { useClientRequest } from '@/utils/request';
  144. import { formItemBtnStyle } from '@/assets/styles/uview-plus';
  145. import { getUrlParams, recursiveDecodeURIComponent } from '@/utils/ruoyi';
  146. import type { PackTaskForm } from './types';
  147. import NP from 'number-precision';
  148. import ObjectCardStorage from '@/plant/models/warehouseCard/object-card-storage.vue';
  149. const { proxy } = getCurrentInstance() as ComponentInternalInstance;
  150. const { pt_pack_ref_type, pt_pack_spec_unit, pt_expire_date_unit } = toRefs<any>(proxy?.useDict('pt_pack_ref_type', 'pt_pack_spec_unit', 'pt_expire_date_unit'));
  151. const upFormRef = ref();
  152. const paging = ref();
  153. const did = ref('');
  154. const form = ref<PackTaskForm>({
  155. storageUseAmount: '',
  156. storageUseUnit: 'kg',
  157. capacity: '',
  158. unit: '',
  159. packagingDateStart: '',
  160. packagingDateEnd: '',
  161. packSn: '',
  162. batchSn: '',
  163. expireDate: '',
  164. expireDateUnit: '',
  165. refType: '',
  166. packCodeType: '3',
  167. });
  168. const rules = reactive<Record<string, any>>({
  169. storageUseUnit: [{ required: true, message: '请选择包装单位' }],
  170. unit: [{ required: true, message: '请选择单位' }],
  171. packagingDateStart: [{ required: true, message: '请选择开始日期' }],
  172. packagingDateEnd: [{ required: true, message: '请选择结束日期' }],
  173. packSn: [{ required: true, message: '请输入包装批号' }],
  174. batchSn: [{ required: true, message: '请输入成品批号' }],
  175. refType: [{ required: true, message: '请选择赋码方式' }],
  176. });
  177. const submit = async () => {
  178. try {
  179. await upFormRef.value?.validate();
  180. } catch (error: any) {
  181. const firstErrorField = error && error[0].field + 'pppp';
  182. paging.value?.scrollIntoViewById(firstErrorField, 30, true);
  183. return;
  184. }
  185. try {
  186. await uni.showLoading({ title: '修改中...', mask: true });
  187. // d
  188. // integer <int64>
  189. // 包装任务ID
  190. // 必需
  191. // packagingDateStart
  192. // string <date>
  193. // 包装开始日期
  194. // 可选
  195. // packagingDateEnd
  196. // string <date>
  197. // 包装结束日期
  198. // 可选
  199. // unit
  200. // string
  201. // 包装单位
  202. // 必需
  203. // batchSn
  204. // string
  205. // 产品批号
  206. // 可选
  207. // packSn
  208. // string
  209. // 包装批号
  210. // 可选
  211. // expireDate
  212. // integer <int32>
  213. // 有效期
  214. // 可选
  215. // expireDateUnit
  216. // string
  217. // 有效期单位;
  218. const payload: any = {
  219. id: did.value,
  220. packagingDateStart: form.value.packagingDateStart,
  221. packagingDateEnd: form.value.packagingDateEnd,
  222. unit: form.value.unit,
  223. batchSn: form.value.batchSn,
  224. packSn: form.value.packSn,
  225. expireDate: form.value.expireDate,
  226. expireDateUnit: form.value.expireDateUnit,
  227. };
  228. delete payload.stroeObject;
  229. const res = await useClientRequest.post('/plt-api/app/packTask/update', payload);
  230. uni.hideLoading();
  231. if (res && res.code === 200) {
  232. uni.$emit('refreshPackTaskList');
  233. await uni.showModal({
  234. title: '修改成功',
  235. content: '若已印刷,请查看已印刷包装上的信息是否正确!以免造成扫码信息与包装信息不一致。',
  236. showCancel: false,
  237. confirmText: '知道了',
  238. });
  239. uni.navigateBack({
  240. delta: 1,
  241. });
  242. }
  243. } catch (e) {
  244. uni.hideLoading();
  245. console.error('保存包装任务失败:', e);
  246. }
  247. };
  248. // 点击随机生成服务端生成唯一的批号
  249. const generateBatchCode = async () => {
  250. uni.showLoading({
  251. title: '生成中...',
  252. });
  253. const res = await useClientRequest.post('/plt-api/app/plantationTask/getBatchCode', {
  254. plType: 'Z',
  255. linkType: 'I',
  256. });
  257. if (res && res.code === 200) {
  258. uni.hideLoading();
  259. form.value.packSn = res.data;
  260. uni.showToast({
  261. title: '批号生成成功',
  262. icon: 'success',
  263. });
  264. }
  265. };
  266. const getStorageInfoById = async (id: string, storageType?: string | number) => {
  267. const type = String(storageType || form.value.packTaskType || '');
  268. let url = `/plt-api/app/storage/getInfo/${id}`;
  269. if (type === '1') {
  270. url = `/plt-api/app/material/getInfo/${id}`;
  271. } else if (type === '2') {
  272. url = `/plt-api/app/storageSeed/getById/${id}`;
  273. }
  274. const res = await useClientRequest.get(url);
  275. if (!res || res.code !== 200) return null;
  276. return {
  277. ...(res.data || {}),
  278. storageType: String((res.data || {})?.storageType || type || ''),
  279. };
  280. };
  281. const getDetailById = async (id: string) => {
  282. const res = await useClientRequest.get(`/plt-api/app/packTask/${id}`);
  283. if (!res || res.code !== 200) return;
  284. const detail = res.data || {};
  285. form.value = {
  286. ...form.value,
  287. ...detail,
  288. };
  289. if (!form.value.packTaskType && detail?.storageType) {
  290. form.value.packTaskType = String(detail.storageType);
  291. }
  292. if (!form.value.inputStorageId) return;
  293. const storageInfo = await getStorageInfoById(form.value.inputStorageId, detail?.packTaskType || detail?.storageType || form.value.packTaskType);
  294. if (storageInfo) {
  295. form.value.stroeObject = storageInfo;
  296. if (!form.value.storageUseUnit) {
  297. form.value.storageUseUnit = storageInfo?.unit || 'kg';
  298. }
  299. } else {
  300. form.value.stroeObject = detail;
  301. }
  302. };
  303. // 计算属性分包结果
  304. const packResult = computed(() => {
  305. // 预计分包数 = 本次包装用量 / 包装规格,向上取整
  306. // 分包数,包装规格,整除的情况,直接除;不整除的情况,向上取整
  307. // 包装规格,整除的时候包装规格只有一个,不整除包装规格有两个,第二个是剩余量
  308. const result: any = {
  309. packNum: 0,
  310. spec1: '',
  311. // 零包规格
  312. spec2: '',
  313. };
  314. if (form.value.storageUseAmount && form.value.capacity) {
  315. const useAmount = Number(form.value.storageUseAmount);
  316. const capacity = Number(form.value.capacity);
  317. if (capacity > 0) {
  318. result.packNum = Math.ceil(useAmount / capacity);
  319. result.spec1 = `${capacity}${form.value.storageUseUnit}/${form.value.unit}`;
  320. if (useAmount % capacity !== 0) {
  321. const lastAmount = NP.round(useAmount - capacity * Math.floor(useAmount / capacity), 2);
  322. result.spec2 = `${lastAmount}${form.value.storageUseUnit}/${form.value.unit}`; // 零包规格
  323. } else {
  324. result.spec2 = ''; // 没有零包规格
  325. }
  326. }
  327. }
  328. return result;
  329. });
  330. onLoad((options: any) => {
  331. did.value = options?.id || getUrlParams(recursiveDecodeURIComponent(options?.q))?.id || '';
  332. if (did.value) {
  333. getDetailById(did.value);
  334. }
  335. });
  336. </script>
  337. <style lang="scss" scoped>
  338. .close-icon {
  339. position: absolute;
  340. top: 0;
  341. right: 0;
  342. z-index: 1;
  343. }
  344. </style>