more.vue 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295
  1. <template>
  2. <div class="nfc-popup">
  3. <van-popup v-model="visible" get-container="nfc-popup" lock-scroll>
  4. <div class="nfc-panel">
  5. <div>
  6. <p v-if="showBottomBox" class="top-text">将手机背部靠近NFC标签扫描</p>
  7. <div class="image-box">
  8. <img class="background-image" v-if="!nfcImage" src="../../assets/img/NFCphone.png" alt="" >
  9. <img class="nfc-image" v-else :src="imgUrl(nfcImage)" alt="" @click="nfcTakePhotos">
  10. </div>
  11. <!-- <p v-if="file" style="overflow: hidden;text-overflow: ellipsis;white-space: nowrap;">{{'文件名:'+file}}</p>-->
  12. <p v-if="imageError">{{'Error:'+imageError}}</p>
  13. <div v-if="showBottomBox" class="bottom-box">
  14. <div @click="nfcCheck">
  15. <img :src="require('../../assets/img/icon/NFC扫描-01.png')" />
  16. <span >NFC</span>
  17. </div>
  18. <div @click="nfcTakePhotos">
  19. <img :src="require('../../assets/img/icon/camera.png')" />
  20. <span>拍照</span>
  21. </div>
  22. </div>
  23. <div v-else>
  24. <p>{{selectNFC}}</p>
  25. <select-cell title="需要拍照的NFC" v-model="selectNFC" :prop="prop" :dataList="dataList"/>
  26. <van-button v-if="selectNFC" type="info" size="small" block @click="onConfirm">确认该照片</van-button>
  27. </div>
  28. </div>
  29. </div>
  30. <input v-show="false" ref="upload" type='file' accept="image/*" capture="camera" @change="fileChange" @click="useCamera(1)"/>
  31. <!-- <input v-show="false" ref="upload" type='file' accept="image/*" capture="camera" @change="fileChange"/>-->
  32. </van-popup>
  33. </div>
  34. </template>
  35. <script>
  36. import SelectCell from "@/components/selectCell";
  37. import {baseImg} from "@/views/menu/LZRegister/api";
  38. import {upload, uploadBase64} from "@/api/public";
  39. import ImageCompressor from "js-image-compressor";
  40. import config from "@/config";
  41. import {imgUrl} from "@/utils";
  42. export default {
  43. components:{SelectCell},
  44. data(){
  45. return {
  46. //nfc弹窗
  47. visible:false,
  48. //上传的nfc图片
  49. nfcImage:null,
  50. //是否显示底部按钮
  51. showBottomBox:true,
  52. //nfc数据
  53. dataList:[],
  54. //选中的nfc
  55. selectNFC:null,
  56. //自定义字段
  57. prop:{
  58. label:'nfcName',
  59. value:'nfcCode'
  60. },
  61. //提交按钮
  62. showBtn:false,
  63. file:null,
  64. imageError:null
  65. }
  66. },
  67. mounted() {
  68. },
  69. watch:{
  70. visible(val){
  71. if(!this.visible){
  72. this.clear();
  73. this.$emit('close')
  74. }
  75. }
  76. },
  77. methods:{
  78. openCameraCallBack(data){
  79. let params = {};
  80. try{
  81. let img = JSON.parse(data);
  82. params = {
  83. extension: img.extension,
  84. content: img.content,
  85. }
  86. }catch (e) {
  87. if(data.errorCode === 1 || data.errorCode === '1'){
  88. throw new Error("ios取消相机操作")
  89. }
  90. params = {
  91. extension: data.extension,
  92. content: data.content,
  93. }
  94. }
  95. this.$toast.loading({
  96. duration: 0, // 持续展示 toast
  97. forbidClick: true,
  98. message: "上传中..."
  99. });
  100. uploadBase64(params).then(res=>{
  101. this.$toast.clear();
  102. /*上传成功*/
  103. this.$toast.success('上传成功')
  104. //上传成功后,将图片显示在页面上并禁用退出
  105. this.nfcImage = res.data.url;
  106. this.showBottomBox = false;
  107. }).catch((err) => {
  108. /*上传失败*/
  109. this.$toast.fail('上传失败')
  110. });
  111. },
  112. isAndroidOrIos(){
  113. const urls = navigator.userAgent;
  114. let isAndroid = urls.indexOf('Android') > -1 || urls.indexOf('Linux') > -1;
  115. let isIos = !!urls.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/);
  116. if(isAndroid){
  117. return 1;
  118. }
  119. if(isIos){
  120. return 2;
  121. }
  122. },
  123. useCamera(actionType){
  124. window.openCameraCallBack = null;
  125. window.openCameraCallBack = this.openCameraCallBack;
  126. let parms = {};
  127. if(actionType){
  128. parms.actionType = actionType;
  129. parms.compressKb = "500";
  130. }
  131. let system = this.isAndroidOrIos();
  132. if(system === 1){
  133. //android
  134. // 判断当前环境是是否存在 js桥 'sap'
  135. const hasSap = window.hasOwnProperty('sap');
  136. if (hasSap) {
  137. // 判断是否存在方法 ?preview
  138. const fun = sap.hasOwnProperty('openCamera');
  139. if (fun) {
  140. sap.openCamera(JSON.stringify(parms));
  141. }
  142. }
  143. }
  144. if(system === 2){
  145. //ios
  146. // 判断 ios是否存在方法 preview
  147. const preview = window.webkit.messageHandlers.hasOwnProperty('openCamera')
  148. if (preview) {
  149. window.webkit.messageHandlers.openCamera.postMessage(JSON.stringify(parms))
  150. }
  151. }
  152. },
  153. //nfc扫描
  154. nfcCheck(){
  155. this.$emit('checkNFC');
  156. },
  157. onConfirm(){
  158. if(!this.selectNFC) return this.$toast('请选择NFC');
  159. let data = {
  160. nfcCode:this.selectNFC,
  161. url: this.nfcImage,
  162. }
  163. //alert(JSON.stringify(data));
  164. this.$emit('change',data);
  165. this.visible = false;
  166. this.clear();
  167. },
  168. changeNFC(){
  169. this.showBtn = true;
  170. },
  171. //清空数据
  172. clear(){
  173. this.nfcImage = null;
  174. this.showBottomBox = true;
  175. this.selectNFC = null;
  176. this.dataList = [];
  177. this.file = null;
  178. this.imageError = null;
  179. },
  180. //显示弹窗
  181. show(list){
  182. this.visible = true;
  183. this.dataList = list;
  184. //alert( JSON.stringify(this.dataList ))
  185. },
  186. //上传前
  187. async fileChange(e){
  188. let file = e.target.files[0];
  189. this.file = e.target.files[0].name;
  190. // let fileName = e.target.files[0].name;
  191. let imgFile = await this.imageCompress(file);
  192. let formData = new FormData();
  193. formData.append('file',imgFile);
  194. upload(formData,'image').then(res=>{
  195. //上传成功后,将图片显示在页面上并禁用退出
  196. this.nfcImage = res.data.url;
  197. this.showBottomBox = false;
  198. })
  199. },
  200. //压缩图片
  201. imageCompress(file){
  202. this.file = file.name;
  203. return new Promise((resolve,reject)=>{
  204. new ImageCompressor({
  205. file,
  206. quality: 0.6,
  207. success: (result) => {
  208. //this.$toast('图片压缩成功')
  209. console.log(result,'图片压缩后')
  210. let img = new File([result], result.name, {
  211. width: result.width,
  212. height: result.height,
  213. type: result.type,
  214. });
  215. resolve(img);
  216. },
  217. error: (e) => {
  218. console.log('imageError:'+e);
  219. this.$toast('图片压缩失败')
  220. this.imageError = e;
  221. reject(e);
  222. },
  223. });
  224. });
  225. },
  226. //拍照
  227. nfcTakePhotos(){
  228. this.file = null;
  229. this.imageError = null;
  230. this.$refs.upload.click();
  231. },
  232. }
  233. }
  234. </script>
  235. <style lang="scss">
  236. #app{
  237. .nfc-popup{
  238. .van-popup--center{
  239. border-radius: 20px;
  240. }
  241. }
  242. }
  243. </style>
  244. <style scoped lang="scss">
  245. .nfc-panel{
  246. width: 400px;
  247. >div{
  248. padding: 30px;
  249. }
  250. }
  251. .top-text{
  252. text-align: center;
  253. font-size: 26px;
  254. }
  255. .image-box{
  256. width: 100%;
  257. height: 350px;
  258. display: flex;
  259. align-items: center;
  260. justify-content: center;
  261. }
  262. .background-image{
  263. width:240px;
  264. height: 240px;
  265. }
  266. .nfc-image{
  267. width: 100%;
  268. height: 100%;
  269. background-color: #fff;
  270. }
  271. .bottom-box{
  272. display: flex;
  273. justify-content: space-around;
  274. align-items: center;
  275. >div{
  276. display: flex;
  277. flex-direction: column;
  278. &:active{
  279. opacity: .5;
  280. }
  281. >img{
  282. width: 70px;
  283. height: 70px;
  284. }
  285. >span{
  286. text-align: center;
  287. font-size: 25px;
  288. }
  289. }
  290. }
  291. </style>