index.vue 24 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013
  1. <template>
  2. <view class="container">
  3. <view class="example">
  4. <!-- 基础表单校验 -->
  5. <uni-forms ref="valiForm" label-align="right" :rules="rules" :modelValue="valiFormData">
  6. <uni-forms-item label="单号" :required="valiFormData.search_order_choice !== 2" name="orderNum">
  7. <uni-easyinput v-model="valiFormData.orderNum" placeholder="请输入单号" suffixIcon="scan" :focus="focusType" @iconClick="scan" />
  8. </uni-forms-item>
  9. <uni-forms-item v-if="valiFormData.search_order_choice === 2" label="批次号" name="batch_number">
  10. <uni-data-select v-model="valiFormData.batch_number" :localdata="batchOptions" placeholder="请选择批次号"></uni-data-select>
  11. </uni-forms-item>
  12. <uni-forms-item v-if="valiFormData.search_order_choice === 1" label="仓位编码" name="space_code">
  13. <uni-data-select v-model="valiFormData.space_code" :localdata="spaces" placeholder="请选择仓位编码"></uni-data-select>
  14. </uni-forms-item>
  15. <uni-forms-item v-if="valiFormData.search_order_choice !== 2" label="重量" required name="weight">
  16. <uni-easyinput
  17. v-model="valiFormData.weight"
  18. placeholder="请输入重量"
  19. oninput="value=value.replace(/[^\d.]/g,'').replace(/^\./g, '').replace(/\.{2,}/g, '').replace('.', '$#$').replace(/\./g, '').replace('$#$', '.').match(/^\d*(\.?\d{0,2})/g)[0] || null"
  20. >
  21. <template #right>
  22. <view class="weight-right">KG</view>
  23. </template>
  24. </uni-easyinput>
  25. </uni-forms-item>
  26. <uni-forms-item v-if="valiFormData.search_order_choice === 1" label="图片" name="images">
  27. <view class="upload-container">
  28. <view class="preview">
  29. <view v-for="(img, index) in images" :key="index" class="image-container">
  30. <image :src="img.path" class="preview-image" mode="aspectFill" @click="openPreview(img.path)" />
  31. <progress :percent="img.progress || 0" :activeColor="Number(img.progress || 0) === 100 ? '#00ff00' : '#10AEFF'" stroke-width="3" />
  32. <text v-if="img.status === 'success'">1</text>
  33. <uni-icons class="delete-icon" @click="deleteImage(index)" type="clear" size="20" color="red" />
  34. </view>
  35. <view v-if="images.length < maxImages" class="choose-image-container" @click="chooseImage">
  36. <uni-icons type="plusempty" size="40" color="#ccc" />
  37. </view>
  38. </view>
  39. <text style="padding-top: 8px">最多选择6张图片</text>
  40. <!-- 放大预览 -->
  41. <view v-if="previewImage" class="preview-modal" @click="closePreview">
  42. <image :src="previewImage" class="preview-large" mode="aspectFit" @click.stop="closePreview" />
  43. </view>
  44. </view>
  45. </uni-forms-item>
  46. <uni-forms-item>
  47. <view @click="searchPkgChange" class="checkbox-cum" :style="{ color: valiFormData.search_pkg ? '#007AFF' : 'gray' }">
  48. <checkbox :checked="valiFormData.search_pkg" @click="searchPkgChange" />
  49. 搜索寄存包裹
  50. </view>
  51. <view class="sub-choice">
  52. <checkbox :disabled="!valiFormData.search_pkg" :checked="valiFormData.typing" />
  53. <text
  54. @click="
  55. () => {
  56. if (valiFormData.search_pkg) {
  57. valiFormData.typing = !valiFormData.typing;
  58. }
  59. }
  60. "
  61. :style="{
  62. color: valiFormData.search_pkg && valiFormData.typing ? '#007AFF' : 'gray'
  63. }"
  64. >
  65. 包裹寄存、代购、运单都找不到时手工添加包裹
  66. </text>
  67. </view>
  68. <view @click="searchOrderChoiceChange" class="checkbox-cum" :style="{ color: valiFormData.search_order ? '#007AFF' : 'gray' }">
  69. <checkbox :checked="valiFormData.search_order" @click="searchOrderChoiceChange" />
  70. 搜索运单
  71. </view>
  72. <view>
  73. <uni-data-checkbox :disabled="!valiFormData.search_order" v-model="valiFormData.search_order_choice" :localdata="searchOrderChoice" />
  74. </view>
  75. </uni-forms-item>
  76. </uni-forms>
  77. <view class="button-group">
  78. <button type="info" @click="reset">重置</button>
  79. <button type="primary" @click="onsubmit" :loading="loading">
  80. <uni-icons v-if="!loading" type="checkmarkempty" size="18" color="white"></uni-icons>
  81. 提交
  82. </button>
  83. </view>
  84. </view>
  85. <view class="history">
  86. <view class="item" v-for="(item, i) in instockHistory.slice(0, 5)" :key="i">
  87. <text class="code" :style="{ color: item.status ? 'green' : '#666' }">
  88. {{ item.orderNum }}
  89. <text v-if="item.batch_text">批次号: {{ item.batch_text }}</text>
  90. <text v-if="item.space">仓位编码: {{ item.space }}</text>
  91. {{ item.type }}
  92. </text>
  93. <uni-icons v-if="item.status" type="checkmarkempty" class="status" size="16" color="green"></uni-icons>
  94. <text class="status fail" v-else>F</text>
  95. <text style="margin-left: 10rpx; font-weight: 300">
  96. {{ '\r\n' + item.createTime }}
  97. </text>
  98. </view>
  99. </view>
  100. <uni-popup ref="message" type="message">
  101. <uni-popup-message :type="messageType" :message="messageText" :duration="2000"></uni-popup-message>
  102. </uni-popup>
  103. <uni-popup ref="alertDialog" type="dialog">
  104. <uni-popup-dialog
  105. type="info"
  106. cancelText="否"
  107. confirmText="是"
  108. title="提示"
  109. content="是否按默认申报(默认申报为:衣服,10件,单价1)"
  110. @confirm="dialogConfirm"
  111. @close="dialogClose"
  112. ></uni-popup-dialog>
  113. </uni-popup>
  114. <uni-popup ref="printerDialog" type="dialog" :is-mask-click="false">
  115. <view style="width: 90%; margin: 0 auto; min-height: 250px; background-color: #fff; border-radius: 5px">
  116. <view class="" style="font-size: 20px; border-bottom: 1px solid #e1e1e1; padding: 15px 10px">
  117. <view>
  118. <view style="margin-bottom: 20px">
  119. <text>打印尾程面单</text>
  120. </view>
  121. <view>
  122. <view v-if="printerList">
  123. <view>
  124. <uni-data-checkbox
  125. multiple
  126. v-model="sendToPeinter"
  127. :localdata="[
  128. {
  129. text: '发送到标签打印机打印',
  130. value: 1
  131. }
  132. ]"
  133. @change="sendToPeinterFun"
  134. >
  135. >
  136. </uni-data-checkbox>
  137. <uni-data-checkbox :disabled="sendToPeinter.length === 0" v-model="selectPrinter" :localdata="printers"></uni-data-checkbox>
  138. </view>
  139. </view>
  140. </view>
  141. </view>
  142. <view style="text-align: center; position: absolute; bottom: 10px; width: 90%; display: flex; margin: 0 auto; left: 0; right: 0">
  143. <button @click="close" style="width: 35%">关闭</button>
  144. <button
  145. @click="printConfirm"
  146. :hover-stay-time="500"
  147. :loading="subLoading"
  148. :disabled="sendToPeinter.length === 0 || subLoading"
  149. class="my-bt-bg"
  150. style="width: 35%"
  151. >
  152. 打印
  153. </button>
  154. </view>
  155. </view>
  156. </view>
  157. </uni-popup>
  158. </view>
  159. </template>
  160. <script setup lang="ts">
  161. import dayjs from 'dayjs';
  162. import permision from '@/common/permission.js';
  163. import { ref, reactive, nextTick, provide, computed } from 'vue';
  164. import { onShow, onLoad, onUnload, onHide, onBackPress, onNavigationBarButtonTap } from '@dcloudio/uni-app';
  165. import {
  166. getAliyunOssSignatureUrl,
  167. instockScanURL,
  168. outStockScanURL,
  169. weighScanURL,
  170. checkWaybillGoodsURL,
  171. printWaybillLabelURL,
  172. getWarehouseSpaceURL,
  173. getBindParamsURL,
  174. getPrinterListURL
  175. } from '@/utils/api.js';
  176. import { uuid } from '@/utils/random.ts';
  177. const alertDialog = ref();
  178. const message = ref();
  179. const valiForm = ref();
  180. const printerDialog = ref();
  181. const token = ref(null);
  182. const user = ref(null);
  183. const loading = ref(false);
  184. const images = ref([]);
  185. const messageType = ref('');
  186. const messageText = ref('');
  187. const batchOptions = ref([] as any);
  188. const spaces = ref([] as any);
  189. const previewImage = ref(null);
  190. const maxImages = ref(6); // 最大上传图片数量
  191. const uploadData = ref([] as any);
  192. const imageValue = ref([] as any);
  193. const printerList = ref({} as any);
  194. const instockHistory = ref([] as any);
  195. const printers = ref([] as any);
  196. const downloadFile = ref([] as any);
  197. const sendToPeinter = ref([1]);
  198. const selectPrinter = ref(0);
  199. const subLoading = ref(false);
  200. const focusType = ref(true);
  201. const result = ref();
  202. // 校验表单数据
  203. const valiFormData = reactive({
  204. images: [],
  205. orderNum: '',
  206. batch_number: '',
  207. space_code: '',
  208. weight: '',
  209. search_pkg: true,
  210. typing: true,
  211. search_order: true,
  212. search_order_choice: 1 as any
  213. });
  214. const searchOrderChoice = reactive([
  215. {
  216. text: '更新为已入库,状态为【已入库】',
  217. value: 1
  218. },
  219. {
  220. text: '更新为已出库,状态为【已出库】',
  221. value: 2
  222. },
  223. {
  224. text: '称重计费',
  225. value: 3
  226. }
  227. ]);
  228. const rules = computed(() => {
  229. return {
  230. orderNum: {
  231. rules: [
  232. {
  233. required: valiFormData.search_order_choice !== 2,
  234. errorMessage: '单号不能为空'
  235. }
  236. ]
  237. },
  238. weight: {
  239. rules: [
  240. {
  241. required: true,
  242. errorMessage: '重量不能为空'
  243. },
  244. {
  245. format: 'number',
  246. errorMessage: '重量只能输入数字'
  247. }
  248. ]
  249. }
  250. };
  251. });
  252. const spaceRes = computed(() => {
  253. try {
  254. const res = spaces.value.find((item: any) => item.value === valiFormData.space_code) as any;
  255. // console.log(res);
  256. return res?.text;
  257. } catch (e) {
  258. console.log(e);
  259. return '';
  260. }
  261. });
  262. onShow(() => {
  263. focusType.value = true;
  264. loading.value = false;
  265. token.value = uni.getStorageSync('token');
  266. user.value = uni.getStorageSync('user');
  267. getWarehouseSpace();
  268. getBindParams();
  269. getPrinterList();
  270. });
  271. onHide(() => {
  272. focusType.value = false;
  273. loading.value = false;
  274. });
  275. onNavigationBarButtonTap((event: any) => {
  276. if (event.index === 0) {
  277. uni.navigateTo({
  278. url: '/pages/instock/instockLog'
  279. });
  280. }
  281. });
  282. const getWarehouseSpace = () => {
  283. uni.request({
  284. url: getWarehouseSpaceURL,
  285. method: 'POST',
  286. header: {
  287. batoken: token.value
  288. },
  289. data: {
  290. code: ''
  291. },
  292. success: (res: any) => {
  293. if (res.data.code === 1) {
  294. spaces.value = res.data.data.spaces.map((item) => {
  295. return {
  296. text: item.name,
  297. value: item.code
  298. };
  299. });
  300. }
  301. }
  302. });
  303. };
  304. const getBindParams = () => {
  305. uni.request({
  306. url: getBindParamsURL,
  307. method: 'GET',
  308. header: {
  309. batoken: token.value
  310. },
  311. success: (res: any) => {
  312. if (res.data.code === 1) {
  313. batchOptions.value = res.data.data.batch_number.map((item) => {
  314. return {
  315. text: item.name,
  316. value: item.id
  317. };
  318. });
  319. }
  320. },
  321. fail(e) {
  322. console.log('fail--', e);
  323. }
  324. });
  325. };
  326. const getPrinterList = () => {
  327. uni.request({
  328. url: getPrinterListURL,
  329. method: 'GET',
  330. header: {
  331. batoken: token.value
  332. },
  333. success: (res: any) => {
  334. if (res.data.code === 1) {
  335. printerList.value = res.data.data.printers;
  336. printers.value = Object.values(printerList.value).map((item: any) => {
  337. return {
  338. text: item.name,
  339. value: item.value
  340. };
  341. });
  342. }
  343. },
  344. fail(e) {
  345. console.log('fail--', e);
  346. }
  347. });
  348. };
  349. const batchText = (batch_number) => {
  350. return batchOptions.value.find((item: any) => item.value === batch_number)?.text;
  351. };
  352. const searchPkgChange = () => {
  353. valiFormData.search_pkg = !valiFormData.search_pkg;
  354. valiFormData.typing = valiFormData.search_pkg;
  355. };
  356. const searchOrderChoiceChange = () => {
  357. valiFormData.search_order = !valiFormData.search_order;
  358. valiFormData.search_order_choice = valiFormData.search_order ? 3 : '';
  359. };
  360. const reset = () => {
  361. loading.value = false;
  362. focusType.value = false;
  363. images.value = [];
  364. valiFormData.orderNum = '';
  365. // space_code: '',
  366. valiFormData.batch_number = '';
  367. valiFormData.weight = '';
  368. valiFormData.search_pkg = true;
  369. valiFormData.typing = true;
  370. valiFormData.search_order = true;
  371. nextTick(() => {
  372. focusType.value = true;
  373. });
  374. };
  375. const scan = async () => {
  376. // #ifdef APP-PLUS
  377. let status = await checkPermission();
  378. if (status !== 1) {
  379. return;
  380. }
  381. // #endif
  382. uni.scanCode({
  383. success: (res: any) => {
  384. result.value = res.result;
  385. valiFormData.orderNum = res.result;
  386. // this.onsubmit();
  387. },
  388. fail: (err) => {
  389. // 需要注意的是小程序扫码不需要申请相机权限
  390. }
  391. });
  392. };
  393. // #ifdef APP-PLUS
  394. const checkPermission = async () => {
  395. let status = permision.isIOS ? await permision.requestIOS('camera') : await permision.requestAndroid('android.permission.CAMERA');
  396. if (status === null || status === 1) {
  397. status = 1;
  398. } else {
  399. uni.showModal({
  400. content: 'Camera permission required',
  401. confirmText: 'Setting',
  402. success: function (res) {
  403. if (res.confirm) {
  404. permision.gotoAppSetting();
  405. }
  406. }
  407. });
  408. }
  409. return status;
  410. };
  411. // #endif
  412. let st;
  413. const warehouseScan = async () => {
  414. st && clearTimeout(st);
  415. if (valiFormData.search_order_choice === 1) {
  416. await checkWaybillGoods();
  417. } else if (valiFormData.search_order_choice === 2) {
  418. await scanOutstock();
  419. } else if (valiFormData.search_order_choice === 3) {
  420. await weighScan();
  421. }
  422. };
  423. const checkWaybillGoods = async () => {
  424. loading.value = true;
  425. uni.request({
  426. url: checkWaybillGoodsURL,
  427. method: 'POST',
  428. header: {
  429. batoken: token.value
  430. },
  431. data: {
  432. order_no: valiFormData.orderNum
  433. },
  434. success: (res: any) => {
  435. if (res.data.code === 1 && res.data.data.is_goods_empty) {
  436. alertDialog.value.open();
  437. } else {
  438. instockScan(0);
  439. }
  440. }
  441. });
  442. };
  443. const instockScan = (is_save_goods: number) => {
  444. const images = getImages();
  445. console.log('images--', images);
  446. let allImgVerify = true
  447. for (var i = 0; i < images.length; i++) {
  448. if(!images[i].savePath){
  449. allImgVerify = false
  450. }
  451. }
  452. if(!allImgVerify){
  453. messageType.value = 'error';
  454. messageText.value = '图片还没上传完毕,请稍后...';
  455. message.value.open();
  456. loading.value = false;
  457. return
  458. }
  459. uni.request({
  460. url: instockScanURL,
  461. method: 'POST',
  462. header: {
  463. batoken: token.value
  464. },
  465. data: {
  466. order_no: valiFormData.orderNum,
  467. weight: valiFormData.weight,
  468. space_code: valiFormData.space_code,
  469. is_save_goods: is_save_goods,
  470. images
  471. },
  472. success: (res: any) => {
  473. loading.value = false;
  474. if (res.data.code == 1) {
  475. messageType.value = 'success';
  476. messageText.value = res.data.msg;
  477. message.value.open();
  478. console.log('res.data.data---', res.data.data);
  479. const historyItem = {
  480. orderNum: valiFormData.orderNum,
  481. createTime: new Date(),
  482. space: spaceRes.value,
  483. type: '入库',
  484. status: true
  485. };
  486. instockHistory.value.unshift(historyItem);
  487. uni.setStorageSync('instockHistory', instockHistory.value);
  488. getHistory();
  489. if (res.data.data.express_label) {
  490. console.log('有打印面单');
  491. selectPrinter.value = sendToPeinter.value.length > 0 ? printers.value[0].value : 0;
  492. printerDialog.value.open();
  493. } else {
  494. st = setTimeout(() => {
  495. reset();
  496. st && clearTimeout(st);
  497. }, 1000);
  498. }
  499. } else {
  500. messageType.value = 'error';
  501. messageText.value = res.data.msg;
  502. message.value.open();
  503. const historyItem = {
  504. orderNum: valiFormData.orderNum,
  505. createTime: new Date(),
  506. space: spaceRes.value,
  507. type: '入库',
  508. status: false
  509. };
  510. instockHistory.value.unshift(historyItem);
  511. uni.setStorageSync('instockHistory', instockHistory.value);
  512. getHistory();
  513. st = setTimeout(() => {
  514. reset();
  515. st && clearTimeout(st);
  516. }, 1000);
  517. }
  518. }
  519. });
  520. };
  521. const scanOutstock = () => {
  522. console.log(valiFormData.orderNum, valiFormData.batch_number);
  523. if (valiFormData.orderNum.length === 0 && valiFormData.batch_number.length === 0) {
  524. messageType.value = 'error';
  525. messageText.value = '单号或批次号至少填一个';
  526. message.value.open();
  527. return;
  528. }
  529. loading.value = true;
  530. uni.request({
  531. url: outStockScanURL,
  532. method: 'POST',
  533. header: {
  534. batoken: token.value
  535. },
  536. data: {
  537. order_no: valiFormData.orderNum,
  538. batch_number: valiFormData.batch_number
  539. },
  540. success: (res: any) => {
  541. loading.value = false;
  542. if (res.data.code == 1) {
  543. messageType.value = 'success';
  544. messageText.value = res.data.msg;
  545. message.value.open();
  546. const historyItem = {
  547. orderNum: valiFormData.orderNum,
  548. batch_text: batchText(valiFormData.batch_number),
  549. createTime: new Date(),
  550. type: '出库',
  551. status: true
  552. };
  553. instockHistory.value.unshift(historyItem);
  554. instockHistory.value.length > 10 && (instockHistory.value.length = 10);
  555. uni.setStorageSync('instockHistory', instockHistory.value);
  556. getHistory();
  557. if (res.data.data.labels && res.data.data.labels.length > 0) {
  558. console.log('有打印面单');
  559. selectPrinter.value = sendToPeinter.value.length > 0 ? printers.value[0].value : 0;
  560. printerDialog.value.open();
  561. } else {
  562. st = setTimeout(() => {
  563. reset();
  564. st && clearTimeout(st);
  565. }, 700);
  566. }
  567. } else {
  568. messageType.value = 'error';
  569. messageText.value = res.data.msg;
  570. message.value.open();
  571. const historyItem = {
  572. orderNum: valiFormData.orderNum,
  573. batch_text: batchText(valiFormData.batch_number),
  574. createTime: new Date(),
  575. type: '出库',
  576. status: false
  577. };
  578. instockHistory.value.unshift(historyItem);
  579. instockHistory.value.length > 10 && (instockHistory.value.length = 10);
  580. uni.setStorageSync('instockHistory', instockHistory.value);
  581. getHistory();
  582. st = setTimeout(() => {
  583. reset();
  584. st && clearTimeout(st);
  585. }, 700);
  586. }
  587. }
  588. });
  589. };
  590. const weighScan = () => {
  591. loading.value = true;
  592. uni.request({
  593. url: weighScanURL,
  594. method: 'POST',
  595. header: {
  596. batoken: token.value
  597. },
  598. data: {
  599. order_no: valiFormData.orderNum,
  600. weight: valiFormData.weight
  601. },
  602. success: (res: any) => {
  603. loading.value = false;
  604. if (res.data.code == 1) {
  605. messageType.value = 'success';
  606. messageText.value = res.data.msg;
  607. message.value.open();
  608. const historyItem = {
  609. orderNum: valiFormData.orderNum,
  610. createTime: new Date(),
  611. type: '称重',
  612. status: true
  613. };
  614. instockHistory.value.unshift(historyItem);
  615. instockHistory.value.length > 10 && (instockHistory.value.length = 10);
  616. uni.setStorageSync('instockHistory', instockHistory.value);
  617. getHistory();
  618. } else {
  619. messageType.value = 'error';
  620. messageText.value = res.data.msg;
  621. message.value.open();
  622. const historyItem = {
  623. orderNum: valiFormData.orderNum,
  624. createTime: new Date(),
  625. type: '称重',
  626. status: false
  627. };
  628. instockHistory.value.unshift(historyItem);
  629. instockHistory.value.length > 10 && (instockHistory.value.length = 10);
  630. uni.setStorageSync('instockHistory', instockHistory.value);
  631. getHistory();
  632. }
  633. st = setTimeout(() => {
  634. reset();
  635. st && clearTimeout(st);
  636. }, 700);
  637. }
  638. });
  639. };
  640. const close = () => {
  641. printerDialog.value.close();
  642. st = setTimeout(() => {
  643. reset();
  644. st && clearTimeout(st);
  645. }, 700);
  646. };
  647. const dialogConfirm = () => {
  648. instockScan(1);
  649. };
  650. const dialogClose = () => {
  651. instockScan(0);
  652. };
  653. const sendToPeinterFun = (res: any) => {
  654. if (!res.detail.value.length > 0) {
  655. selectPrinter.value = 0;
  656. } else {
  657. selectPrinter.value = printers.value[0].value;
  658. }
  659. };
  660. const printConfirm = () => {
  661. subLoading.value = true;
  662. uni.request({
  663. url: printWaybillLabelURL,
  664. method: 'POST',
  665. header: {
  666. batoken: token.value
  667. },
  668. data: {
  669. order_no: valiFormData.orderNum,
  670. printer_code: selectPrinter
  671. },
  672. success: (res) => {
  673. close();
  674. subLoading.value = false;
  675. console.log('打印成功', res);
  676. messageType.value = 'success';
  677. messageText.value = '打印成功';
  678. message.value.open();
  679. }
  680. });
  681. };
  682. const onsubmit = () => {
  683. valiForm.value
  684. .validate()
  685. .then((res) => {
  686. warehouseScan();
  687. })
  688. .catch((err) => {
  689. console.log('err', err);
  690. });
  691. };
  692. const getHistory = () => {
  693. // this.instockHistory = uni.getStorageSync('history')
  694. };
  695. const getImages = () => {
  696. const res = images.value.map((item: any) => {
  697. return {
  698. name: item.name,
  699. savePath: item.serverUrl,
  700. fileSize: item.size,
  701. mimeType: item.type
  702. };
  703. });
  704. console.log('res22 ', res);
  705. return res;
  706. };
  707. // 获取阿里云oss签名
  708. const getAliyunOssSignature = (rawFiles) => {
  709. uni.request({
  710. url: getAliyunOssSignatureUrl,
  711. method: 'GET',
  712. header: {
  713. batoken: token.value
  714. },
  715. success: ({ data }: any) => {
  716. const signature = data.data.signature;
  717. const uploadPromises = rawFiles.map((image) => {
  718. return upLoadFile(signature, image);
  719. });
  720. Promise.all(uploadPromises)
  721. .then((results) => {
  722. console.log('所有图片加载成功:', results);
  723. uni.showToast({
  724. title: '加载成功',
  725. icon: 'success'
  726. });
  727. })
  728. .catch((error) => {
  729. console.error('加载失败:', error);
  730. uni.showToast({
  731. title: '加载失败',
  732. icon: 'none'
  733. });
  734. });
  735. },
  736. fail: (err) => {
  737. console.log(err);
  738. }
  739. });
  740. };
  741. const upLoadFile = (signature, image) => {
  742. const fileData = {
  743. policy: signature.policy,
  744. signature: signature.signature,
  745. ossaccessKeyId: signature.ossAccessKeyId,
  746. key: signature.dir + dayjs().format('YYYYMMDD') + '/' + uuid() + '_' + image.name,
  747. dir: signature.dir,
  748. host: signature.host,
  749. file: image.file
  750. };
  751. return new Promise((resolve, reject) => {
  752. let name = image.name
  753. // #ifdef APP-PLUS
  754. name = 'file'
  755. // #endif
  756. const uploadTask = uni.uploadFile({
  757. url: signature.host, // 你的上传接口地址
  758. filePath: image.path,
  759. name: name, // 这里根据后端需要的字段来定义
  760. formData: fileData,
  761. success: (uploadFileRes) => {
  762. if (uploadFileRes.statusCode === 204 || uploadFileRes.statusCode === 200) {
  763. image!.serverUrl = fileData.key;
  764. resolve(uploadFileRes);
  765. } else {
  766. reject(uploadFileRes);
  767. }
  768. },
  769. fail: (error) => {
  770. console.log('error++', error);
  771. reject(error);
  772. },
  773. // 更新上传进度
  774. complete: () => {
  775. console.log('complete---');
  776. image.progress = 100;
  777. }
  778. });
  779. // 可选:监听上传进度变化
  780. uploadTask.onProgressUpdate((progressEvent) => {
  781. image.progress = progressEvent.progress; // 更新进度
  782. });
  783. });
  784. };
  785. const chooseImage = () => {
  786. uni.chooseImage({
  787. count: maxImages.value - images.value.length,
  788. success: (res) => {
  789. images.value = images.value.concat(
  790. res.tempFiles.map((item) => {
  791. const res = {
  792. size: item.size,
  793. path: item.path,
  794. name: item.name,
  795. type: item.type,
  796. progress: 0,
  797. file: item
  798. };
  799. // #ifdef APP-PLUS
  800. //文件名操作
  801. //获取文件后缀
  802. const suffix = item.path.substring(item.path.lastIndexOf('.') + 1);
  803. //获取文件名
  804. const fileName = item.path.substring(item.path.lastIndexOf('/') + 1);
  805. res.name = fileName;
  806. res.type = suffix;
  807. // #endif
  808. return res;
  809. })
  810. );
  811. const paddingImages = images.value.filter((image) => image.progress === 0);
  812. nextTick(() => {
  813. getAliyunOssSignature(paddingImages);
  814. });
  815. },
  816. fail: (err) => {
  817. console.error(err);
  818. }
  819. });
  820. };
  821. const deleteImage = (index) => {
  822. images.value.splice(index, 1);
  823. };
  824. const openPreview = (image) => {
  825. previewImage.value = image; // 设置放大预览的图片
  826. };
  827. const closePreview = () => {
  828. previewImage.value = null; // 关闭预览
  829. };
  830. </script>
  831. <style lang="scss">
  832. .example {
  833. padding: 15px;
  834. background-color: #fff;
  835. }
  836. .checkbox-cum {
  837. margin-bottom: 20rpx;
  838. font-size: 14rpx;
  839. }
  840. .sub-choice {
  841. margin-bottom: 20rpx;
  842. margin-left: 20rpx;
  843. font-size: 14rpx;
  844. }
  845. .button-group {
  846. margin-top: 15px;
  847. display: flex;
  848. flex-direction: row;
  849. justify-content: space-around;
  850. button {
  851. display: flex;
  852. align-items: center;
  853. justify-content: center;
  854. height: 35px;
  855. width: 50%;
  856. margin-left: 10px;
  857. font-size: 16rpx;
  858. }
  859. .uni-icons {
  860. margin-right: 10px;
  861. }
  862. }
  863. .weight-right {
  864. padding-right: 10rpx;
  865. font-size: 14rpx;
  866. }
  867. .history {
  868. display: flex;
  869. width: 100%;
  870. flex-direction: column;
  871. justify-items: start;
  872. .title {
  873. padding: 20rpx;
  874. font-size: 24rpx;
  875. font-weight: 600;
  876. }
  877. .code {
  878. font-weight: 600;
  879. }
  880. .item {
  881. padding: 20rpx;
  882. font-size: 20rpx;
  883. color: #666;
  884. .status {
  885. padding-left: 20rpx;
  886. }
  887. .fail {
  888. font-weight: 600;
  889. color: #f00;
  890. }
  891. }
  892. }
  893. </style>
  894. <style scoped>
  895. .upload-container {
  896. padding: 16px;
  897. }
  898. .preview {
  899. display: flex;
  900. flex-wrap: wrap;
  901. }
  902. .image-container {
  903. position: relative;
  904. margin-right: 10px;
  905. margin-bottom: 10px;
  906. }
  907. .preview-image {
  908. width: 130rpx;
  909. height: 130rpx;
  910. }
  911. .delete-icon {
  912. position: absolute;
  913. top: 0;
  914. right: 0;
  915. cursor: pointer;
  916. }
  917. .choose-image-container {
  918. width: 130rpx;
  919. /* 与图片大小一致 */
  920. height: 130rpx;
  921. /* 与图片大小一致 */
  922. display: flex;
  923. align-items: center;
  924. justify-content: center;
  925. background-color: #fff;
  926. /* 背景颜色为白色 */
  927. border: 1px dashed #cccccc;
  928. /* 虚线边框 */
  929. border-radius: 5px;
  930. /* 圆角 */
  931. cursor: pointer;
  932. }
  933. .preview-modal {
  934. position: fixed;
  935. top: 0;
  936. left: 0;
  937. right: 0;
  938. bottom: 0;
  939. background-color: rgba(0, 0, 0, 0.8);
  940. /* 半透明背景 */
  941. display: flex;
  942. align-items: center;
  943. justify-content: center;
  944. z-index: 999;
  945. }
  946. .preview-large {
  947. max-width: 90%;
  948. /* 最大宽度 */
  949. max-height: 90%;
  950. /* 最大高度 */
  951. }
  952. .progress-bar {
  953. position: absolute;
  954. bottom: 0;
  955. left: 0;
  956. width: 100%;
  957. }
  958. </style>