index.vue 25 KB

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