index.vue 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303
  1. <template>
  2. <div v-if="!show">
  3. <div class="upload">
  4. <Icon type="md-reverse-camera" />
  5. <form id="psd">
  6. <input type="file" accept="image/*" @change="selectImg($event)" />
  7. </form>
  8. </div>
  9. <div class="content">
  10. <div class="list">
  11. <img
  12. v-for="(item, id) in newImg"
  13. :key="id + '6s'"
  14. :src="item.url"
  15. alt=""
  16. />
  17. <p v-for="(item, id) in table" :key="id">
  18. {{ item.name }}:{{ item.num }}
  19. </p>
  20. </div>
  21. <div class="btn">
  22. <Button type="primary" @click="save" size="large">开始</Button>
  23. </div>
  24. </div>
  25. </div>
  26. <div class="loading" v-else>
  27. <div class="spinner"></div>
  28. </div>
  29. </template>
  30. <script>
  31. import { Icon, Button, Notice } from "view-design";
  32. import "view-design/dist/styles/iview.css";
  33. import axios from "@/utils/axios";
  34. import ImageCompressor from "js-image-compressor";
  35. export default {
  36. components: {
  37. Icon,
  38. Button,
  39. },
  40. data() {
  41. return {
  42. show: false,
  43. newImg: [],
  44. table: [],
  45. };
  46. },
  47. methods: {
  48. // 选择多张图片
  49. selectImg(event) {
  50. const file = event.target.files;
  51. const size = 2097152; //2M
  52. const newArr = [];
  53. if (file.length > 1) {
  54. Notice.warning({
  55. desc: "不能超过1张",
  56. });
  57. return;
  58. }
  59. for (let j = 0; j < file.length; j++) {
  60. const el = file[j];
  61. if (el.size >= size) {
  62. Notice.warning({
  63. desc: el.name + "大小超过2M限制请重新上传",
  64. });
  65. break;
  66. } else if (el.size >= size * 0.5) {
  67. Notice.warning({
  68. desc: el.name + "大小超过限制将被压缩",
  69. });
  70. // 压缩
  71. new ImageCompressor({
  72. file: el,
  73. quality: 0.3,
  74. mimeType: "image/jpeg",
  75. success: (result) => {
  76. newArr.push({
  77. url: this.getObjectURL(result),
  78. data: result,
  79. });
  80. },
  81. error: function (msg) {
  82. Notice.warning({
  83. desc: "请重新上传",
  84. });
  85. },
  86. });
  87. continue;
  88. } else {
  89. newArr.push({
  90. url: this.getObjectURL(el),
  91. data: el,
  92. });
  93. }
  94. }
  95. this.newImg = newArr;
  96. document.getElementById("psd").reset();
  97. this.table = [];
  98. },
  99. // 图片临时路径
  100. getObjectURL(file) {
  101. var url = null;
  102. if (window.createObjcectURL != undefined) {
  103. url = window.createOjcectURL(file);
  104. } else if (window.URL != undefined) {
  105. url = window.URL.createObjectURL(file);
  106. } else if (window.webkitURL != undefined) {
  107. url = window.webkitURL.createObjectURL(file);
  108. }
  109. return url;
  110. },
  111. // 识别
  112. async save() {
  113. if (!this.newImg.length) return;
  114. try {
  115. console.log(this.newImg[0].data);
  116. this.show = true;
  117. const formData = new FormData();
  118. formData.append("pic", this.newImg[0].data);
  119. const res = await axios.post("/uploadOneInvoicePic", formData);
  120. this.table = this.setData(res.data.invoice_data.words_result[0].result);
  121. } catch (error) {
  122. Notice.warning({
  123. desc: error,
  124. });
  125. }
  126. this.show = false;
  127. },
  128. // 处理数据
  129. setData(data) {
  130. if (!data && !data.length) return [];
  131. let content = [];
  132. for (const key in data) {
  133. content.push({
  134. name: this.names(key) || "无",
  135. num: data[key].length ? data[key][0].word : "",
  136. });
  137. }
  138. return content;
  139. },
  140. // 名词
  141. names(key) {
  142. let name = "";
  143. switch (key) {
  144. case "AmountInFiguers":
  145. name = "合计";
  146. break;
  147. case "AmountInWords":
  148. name = "合计大写";
  149. break;
  150. case "CheckCode":
  151. name = "校验码";
  152. break;
  153. case "Checker":
  154. name = "复核";
  155. break;
  156. case "InvoiceCode":
  157. name = "发票代码";
  158. break;
  159. case "InvoiceCodeConfirm":
  160. name = "发票代码确认";
  161. break;
  162. case "InvoiceDate":
  163. name = "发票日期";
  164. break;
  165. case "InvoiceNum":
  166. name = "发票编号";
  167. break;
  168. case "InvoiceNumConfirm":
  169. name = "发票编号确认";
  170. break;
  171. case "NoteDrawer":
  172. name = "开票人";
  173. break;
  174. case "Payee":
  175. name = "收款人";
  176. break;
  177. case "PurchaserAddress":
  178. name = "买方地址";
  179. break;
  180. case "PurchaserBank":
  181. name = "买方银行信息";
  182. break;
  183. case "PurchaserName":
  184. name = "买方名称";
  185. break;
  186. case "PurchaserRegisterNum":
  187. name = "买方识别号";
  188. break;
  189. case "SellerAddress":
  190. name = "卖方地址";
  191. break;
  192. case "SellerBank":
  193. name = "卖方银行信息";
  194. break;
  195. case "SellerName":
  196. name = "卖方名称";
  197. break;
  198. case "SellerRegisterNum":
  199. name = "卖方识别号";
  200. break;
  201. default:
  202. break;
  203. }
  204. return name;
  205. },
  206. },
  207. };
  208. </script>
  209. <style lang="less" scoped>
  210. .upload {
  211. width: 0.4rem;
  212. height: 0.4rem;
  213. overflow: hidden;
  214. border: dashed 1px #dcdee2;
  215. color: #dcdee2;
  216. position: relative;
  217. margin: 0 auto;
  218. margin-top: 0.1rem;
  219. font-size: 0.2rem;
  220. text-align: center;
  221. line-height: 0.35rem;
  222. input {
  223. width: 0.4rem;
  224. height: 0.4rem;
  225. position: absolute;
  226. left: 0;
  227. top: 0;
  228. opacity: 0;
  229. }
  230. }
  231. .content {
  232. .list {
  233. padding: 0.1rem 0;
  234. max-height: 6rem;
  235. color: #dcdee2;
  236. text-align: center;
  237. font-size: 0.16rem;
  238. overflow-x: hidden;
  239. overflow-y: auto;
  240. img {
  241. max-width: 100%;
  242. max-height: 3rem;
  243. font-size: 0;
  244. }
  245. p {
  246. text-align: left;
  247. max-width: 4rem;
  248. margin: 0 auto;
  249. }
  250. }
  251. .btn {
  252. text-align: center;
  253. padding-top: 0.1rem;
  254. }
  255. }
  256. .loading {
  257. position: fixed;
  258. width: 100vw;
  259. height: 100vh;
  260. z-index: 96;
  261. left: 0;
  262. top: 0;
  263. background: rgba(0, 0, 0, 0.5);
  264. display: flex;
  265. justify-content: center;
  266. align-items: center;
  267. .spinner {
  268. width: 0.4rem;
  269. height: 0.4rem;
  270. background-color: #dcdee2;
  271. margin: 0 auto;
  272. -webkit-animation: sk-rotateplane 1.2s infinite ease-in-out;
  273. animation: sk-rotateplane 1.2s infinite ease-in-out;
  274. }
  275. @-webkit-keyframes sk-rotateplane {
  276. 0% {
  277. -webkit-transform: perspective(1.2rem);
  278. }
  279. 50% {
  280. -webkit-transform: perspective(1.2rem) rotateY(180deg);
  281. }
  282. 100% {
  283. -webkit-transform: perspective(1.2rem) rotateY(180deg) rotateX(180deg);
  284. }
  285. }
  286. @keyframes sk-rotateplane {
  287. 0% {
  288. transform: perspective(1.2rem) rotateX(0deg) rotateY(0deg);
  289. -webkit-transform: perspective(1.2rem) rotateX(0deg) rotateY(0deg);
  290. }
  291. 50% {
  292. transform: perspective(1.2rem) rotateX(-180.1deg) rotateY(0deg);
  293. -webkit-transform: perspective(1.2rem) rotateX(-180.1deg) rotateY(0deg);
  294. }
  295. 100% {
  296. transform: perspective(1.2rem) rotateX(-180deg) rotateY(-179.9deg);
  297. -webkit-transform: perspective(1.2rem) rotateX(-180deg) rotateY(-179.9deg);
  298. }
  299. }
  300. }
  301. </style>