index.vue 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982
  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. uni.request({
  446. url: instockScanURL,
  447. method: 'POST',
  448. header: {
  449. batoken: token.value
  450. },
  451. data: {
  452. order_no: valiFormData.orderNum,
  453. weight: valiFormData.weight,
  454. space_code: valiFormData.space_code,
  455. is_save_goods: is_save_goods,
  456. images
  457. },
  458. success: (res: any) => {
  459. loading.value = false;
  460. if (res.data.code == 1) {
  461. messageType.value = 'success';
  462. messageText.value = res.data.msg;
  463. message.value.open();
  464. console.log('res.data.data---', res.data.data);
  465. const historyItem = {
  466. orderNum: valiFormData.orderNum,
  467. createTime: new Date(),
  468. space: spaceRes.value,
  469. type: '入库',
  470. status: true
  471. };
  472. instockHistory.value.unshift(historyItem);
  473. uni.setStorageSync('instockHistory', instockHistory.value);
  474. getHistory();
  475. if (res.data.data.express_label) {
  476. console.log('有打印面单');
  477. selectPrinter.value = sendToPeinter.value.length > 0 ? printers.value[0].value : 0;
  478. printerDialog.value.open();
  479. } else {
  480. st = setTimeout(() => {
  481. reset();
  482. st && clearTimeout(st);
  483. }, 1000);
  484. }
  485. } else {
  486. messageType.value = 'error';
  487. messageText.value = res.data.msg;
  488. message.value.open();
  489. const historyItem = {
  490. orderNum: valiFormData.orderNum,
  491. createTime: new Date(),
  492. space: spaceRes.value,
  493. type: '入库',
  494. status: false
  495. };
  496. instockHistory.value.unshift(historyItem);
  497. uni.setStorageSync('instockHistory', instockHistory.value);
  498. getHistory();
  499. st = setTimeout(() => {
  500. reset();
  501. st && clearTimeout(st);
  502. }, 1000);
  503. }
  504. }
  505. });
  506. };
  507. const scanOutstock = () => {
  508. console.log(valiFormData.orderNum, valiFormData.batch_number);
  509. if (valiFormData.orderNum.length === 0 && valiFormData.batch_number.length === 0) {
  510. messageType.value = 'error';
  511. messageText.value = '单号或批次号至少填一个';
  512. message.value.open();
  513. return;
  514. }
  515. loading.value = true;
  516. uni.request({
  517. url: outStockScanURL,
  518. method: 'POST',
  519. header: {
  520. batoken: token.value
  521. },
  522. data: {
  523. order_no: valiFormData.orderNum,
  524. batch_number: valiFormData.batch_number
  525. },
  526. success: (res: any) => {
  527. loading.value = false;
  528. if (res.data.code == 1) {
  529. messageType.value = 'success';
  530. messageText.value = res.data.msg;
  531. message.value.open();
  532. const historyItem = {
  533. orderNum: valiFormData.orderNum,
  534. batch_text: batchText(valiFormData.batch_number),
  535. createTime: new Date(),
  536. type: '出库',
  537. status: true
  538. };
  539. instockHistory.value.unshift(historyItem);
  540. instockHistory.value.length > 10 && (instockHistory.value.length = 10);
  541. uni.setStorageSync('instockHistory', instockHistory.value);
  542. getHistory();
  543. if (res.data.data.labels && res.data.data.labels.length > 0) {
  544. console.log('有打印面单');
  545. selectPrinter.value = sendToPeinter.value.length > 0 ? printers.value[0].value : 0;
  546. printerDialog.value.open();
  547. } else {
  548. st = setTimeout(() => {
  549. reset();
  550. st && clearTimeout(st);
  551. }, 700);
  552. }
  553. } else {
  554. messageType.value = 'error';
  555. messageText.value = res.data.msg;
  556. message.value.open();
  557. const historyItem = {
  558. orderNum: valiFormData.orderNum,
  559. batch_text: batchText(valiFormData.batch_number),
  560. createTime: new Date(),
  561. type: '出库',
  562. status: false
  563. };
  564. instockHistory.value.unshift(historyItem);
  565. instockHistory.value.length > 10 && (instockHistory.value.length = 10);
  566. uni.setStorageSync('instockHistory', instockHistory.value);
  567. getHistory();
  568. st = setTimeout(() => {
  569. reset();
  570. st && clearTimeout(st);
  571. }, 700);
  572. }
  573. }
  574. });
  575. };
  576. const weighScan = () => {
  577. loading.value = true;
  578. uni.request({
  579. url: weighScanURL,
  580. method: 'POST',
  581. header: {
  582. batoken: token.value
  583. },
  584. data: {
  585. order_no: valiFormData.orderNum,
  586. weight: valiFormData.weight
  587. },
  588. success: (res: any) => {
  589. loading.value = false;
  590. if (res.data.code == 1) {
  591. messageType.value = 'success';
  592. messageText.value = res.data.msg;
  593. message.value.open();
  594. const historyItem = {
  595. orderNum: valiFormData.orderNum,
  596. createTime: new Date(),
  597. type: '称重',
  598. status: true
  599. };
  600. instockHistory.value.unshift(historyItem);
  601. instockHistory.value.length > 10 && (instockHistory.value.length = 10);
  602. uni.setStorageSync('instockHistory', instockHistory.value);
  603. getHistory();
  604. } else {
  605. messageType.value = 'error';
  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: false
  613. };
  614. instockHistory.value.unshift(historyItem);
  615. instockHistory.value.length > 10 && (instockHistory.value.length = 10);
  616. uni.setStorageSync('instockHistory', instockHistory.value);
  617. getHistory();
  618. }
  619. st = setTimeout(() => {
  620. reset();
  621. st && clearTimeout(st);
  622. }, 700);
  623. }
  624. });
  625. };
  626. const close = () => {
  627. printerDialog.value.close();
  628. st = setTimeout(() => {
  629. reset();
  630. st && clearTimeout(st);
  631. }, 700);
  632. };
  633. const dialogConfirm = () => {
  634. instockScan(1);
  635. };
  636. const dialogClose = () => {
  637. instockScan(0);
  638. };
  639. const sendToPeinterFun = (res: any) => {
  640. if (!res.detail.value.length > 0) {
  641. selectPrinter.value = 0;
  642. } else {
  643. selectPrinter.value = printers.value[0].value;
  644. }
  645. };
  646. const printConfirm = () => {
  647. subLoading.value = true;
  648. uni.request({
  649. url: printWaybillLabelURL,
  650. method: 'POST',
  651. header: {
  652. batoken: token.value
  653. },
  654. data: {
  655. order_no: valiFormData.orderNum,
  656. printer_code: selectPrinter
  657. },
  658. success: (res) => {
  659. close();
  660. subLoading.value = false;
  661. console.log('打印成功', res);
  662. messageType.value = 'success';
  663. messageText.value = '打印成功';
  664. message.value.open();
  665. }
  666. });
  667. };
  668. const onsubmit = () => {
  669. valiForm.value
  670. .validate()
  671. .then((res) => {
  672. warehouseScan();
  673. })
  674. .catch((err) => {
  675. console.log('err', err);
  676. });
  677. };
  678. const getHistory = () => {
  679. // this.instockHistory = uni.getStorageSync('history')
  680. };
  681. const getImages = () => {
  682. const res = images.value.map((item: any) => {
  683. return {
  684. name: item.name,
  685. savePath: item.serverUrl,
  686. fileSize: item.size,
  687. mimeType: item.type
  688. };
  689. });
  690. console.log('res22 ', res);
  691. return res;
  692. };
  693. // 获取阿里云oss签名
  694. const getAliyunOssSignature = (rawFiles) => {
  695. uni.request({
  696. url: getAliyunOssSignatureUrl,
  697. method: 'GET',
  698. header: {
  699. batoken: token.value
  700. },
  701. success: ({ data }: any) => {
  702. const signature = data.data.signature;
  703. const uploadPromises = rawFiles.map((image) => {
  704. return upLoadFile(signature, image);
  705. });
  706. Promise.all(uploadPromises)
  707. .then((results) => {
  708. console.log('所有图片加载成功:', results);
  709. uni.showToast({
  710. title: '加载成功',
  711. icon: 'success'
  712. });
  713. })
  714. .catch((error) => {
  715. console.error('加载失败:', error);
  716. uni.showToast({
  717. title: '加载失败',
  718. icon: 'none'
  719. });
  720. });
  721. },
  722. fail: (err) => {
  723. console.log(err);
  724. }
  725. });
  726. };
  727. const upLoadFile = (signature, image) => {
  728. const fileData = {
  729. policy: signature.policy,
  730. signature: signature.signature,
  731. ossaccessKeyId: signature.ossAccessKeyId,
  732. key: signature.dir + dayjs().format('YYYYMMDD') + '/' + uuid() + '_' + image.name,
  733. dir: signature.dir,
  734. host: signature.host,
  735. file: image.file
  736. };
  737. return new Promise((resolve, reject) => {
  738. const uploadTask = uni.uploadFile({
  739. url: signature.host, // 你的上传接口地址
  740. filePath: image.path,
  741. name: image.name, // 这里根据后端需要的字段来定义
  742. formData: fileData,
  743. success: (uploadFileRes) => {
  744. if (uploadFileRes.statusCode === 204 || uploadFileRes.statusCode === 200) {
  745. image!.serverUrl = fileData.key;
  746. resolve(uploadFileRes);
  747. } else {
  748. reject(uploadFileRes);
  749. }
  750. },
  751. fail: (error) => {
  752. console.log('error++', error);
  753. reject(error);
  754. },
  755. // 更新上传进度
  756. complete: () => {
  757. console.log('complete---');
  758. image.progress = 100;
  759. }
  760. });
  761. // 可选:监听上传进度变化
  762. uploadTask.onProgressUpdate((progressEvent) => {
  763. image.progress = progressEvent.progress; // 更新进度
  764. });
  765. });
  766. };
  767. const chooseImage = () => {
  768. uni.chooseImage({
  769. count: maxImages.value - images.value.length,
  770. success: (res) => {
  771. images.value = images.value.concat(
  772. res.tempFiles.map((item) => {
  773. return {
  774. name: item.name,
  775. size: item.size,
  776. type: item.type,
  777. path: item.path,
  778. progress: 0,
  779. file: item
  780. };
  781. })
  782. );
  783. const paddingImages = images.value.filter((image) => image.progress === 0);
  784. nextTick(() => {
  785. getAliyunOssSignature(paddingImages);
  786. });
  787. },
  788. fail: (err) => {
  789. console.error(err);
  790. }
  791. });
  792. };
  793. const deleteImage = (index) => {
  794. images.value.splice(index, 1);
  795. };
  796. const openPreview = (image) => {
  797. previewImage.value = image; // 设置放大预览的图片
  798. };
  799. const closePreview = () => {
  800. previewImage.value = null; // 关闭预览
  801. };
  802. </script>
  803. <style lang="scss">
  804. .example {
  805. padding: 15px;
  806. background-color: #fff;
  807. }
  808. .checkbox-cum {
  809. margin-bottom: 20rpx;
  810. font-size: 14rpx;
  811. }
  812. .sub-choice {
  813. margin-bottom: 20rpx;
  814. margin-left: 20rpx;
  815. font-size: 14rpx;
  816. }
  817. .button-group {
  818. margin-top: 15px;
  819. display: flex;
  820. flex-direction: row;
  821. justify-content: space-around;
  822. button {
  823. display: flex;
  824. align-items: center;
  825. justify-content: center;
  826. height: 35px;
  827. width: 50%;
  828. margin-left: 10px;
  829. font-size: 16rpx;
  830. }
  831. .uni-icons {
  832. margin-right: 10px;
  833. }
  834. }
  835. .weight-right {
  836. padding-right: 10rpx;
  837. font-size: 14rpx;
  838. }
  839. .history {
  840. display: flex;
  841. width: 100%;
  842. flex-direction: column;
  843. justify-items: start;
  844. .title {
  845. padding: 20rpx;
  846. font-size: 24rpx;
  847. font-weight: 600;
  848. }
  849. .code {
  850. font-weight: 600;
  851. }
  852. .item {
  853. padding: 20rpx;
  854. font-size: 20rpx;
  855. color: #666;
  856. .status {
  857. padding-left: 20rpx;
  858. }
  859. .fail {
  860. font-weight: 600;
  861. color: #f00;
  862. }
  863. }
  864. }
  865. </style>
  866. <style scoped>
  867. .upload-container {
  868. padding: 16px;
  869. }
  870. .preview {
  871. display: flex;
  872. flex-wrap: wrap;
  873. }
  874. .image-container {
  875. position: relative;
  876. margin-right: 10px;
  877. margin-bottom: 10px;
  878. }
  879. .preview-image {
  880. width: 130rpx;
  881. height: 130rpx;
  882. }
  883. .delete-icon {
  884. position: absolute;
  885. top: 0;
  886. right: 0;
  887. cursor: pointer;
  888. }
  889. .choose-image-container {
  890. width: 130rpx;
  891. /* 与图片大小一致 */
  892. height: 130rpx;
  893. /* 与图片大小一致 */
  894. display: flex;
  895. align-items: center;
  896. justify-content: center;
  897. background-color: #fff;
  898. /* 背景颜色为白色 */
  899. border: 1px dashed #cccccc;
  900. /* 虚线边框 */
  901. border-radius: 5px;
  902. /* 圆角 */
  903. cursor: pointer;
  904. }
  905. .preview-modal {
  906. position: fixed;
  907. top: 0;
  908. left: 0;
  909. right: 0;
  910. bottom: 0;
  911. background-color: rgba(0, 0, 0, 0.8);
  912. /* 半透明背景 */
  913. display: flex;
  914. align-items: center;
  915. justify-content: center;
  916. z-index: 999;
  917. }
  918. .preview-large {
  919. max-width: 90%;
  920. /* 最大宽度 */
  921. max-height: 90%;
  922. /* 最大高度 */
  923. }
  924. .progress-bar {
  925. position: absolute;
  926. bottom: 0;
  927. left: 0;
  928. width: 100%;
  929. }
  930. </style>