二维码扫描并输出信息(小程序,IOS,安卓)

js 复制代码
<template>
  <div>
    <van-sticky>
      <div class="header_box">
        <van-nav-bar :border="false" left-text="" left-arrow>
          <template #left>
            <van-icon name="arrow-left" size="22" @click="goto_out" />
          </template>
          <template #title>
            <span>123</span>
          </template>
          <template #right></template>
        </van-nav-bar>
      </div>
      <!-- 搜索-->

      <form action="">
        <van-search v-model.trim="vinNo" placeholder="请输入123" @search="onSearch">
          <template #left-icon>
            <van-icon name="scan" @click="btn_scancode" size="20px" />
          </template>
        </van-search>
      </form>


    </van-sticky>
    <!-- 123 -->
    <!-- 内容 开始 -->
    <div class="content">
      <!-- 提示 -->

      <div class="content_top" v-if="blackobj != null">
        <div class="content_top_img box_img">
          <img :src="blackobj.banner ? blackobj.banner : logoimg" alt="" srcset="">
        </div>
        <div style="margin-left: 5px;">
          <div style="font-size: 16px;padding: 0 0 5px 0;"> {{ vinNo }}</div>
          <div style="color: #A5B4DA;padding: 2px 0;"> {{ blackobj.sku }}</div>
          <div style="color: #A5B4DA;padding: 2px 0;"> {{ blackobj.bikeModel }}</div>
        </div>
      </div>



      <div class="content_bot">
        <FlexLinePI :title="'123'" :dropshow="true">
          <van-field v-model="remark" rows="3" autosize label="" type="textarea" placeholder="请填写123"
            style="border: 1px solid #ddd;border-radius: 10px;" />
        </FlexLinePI>
      </div>
      <div class="content_bot">
        <div style="margin: 10px 0;">
          <div style="font-size: 16px;padding:5px 0;">上传图片</div>
          <div
            style="width: 80px;height: 80px;float: left;margin: 0 10px 10px 0;position: relative;display: flex;justify-content: center;"
            v-for="(it, id) in filepictureList" :key="id" @click="looktype(it, 'img')">
            <img :src="it" alt="" style="max-width: 100%;max-height: 100%;">
            <div class="close" style="" @click.stop="delimg(id)"><van-icon name="cross" /></div>
          </div>
          <van-uploader :max-count="10" multiple accept=".jpg, .jpeg, .png" :after-read="afterReadImg"
            :max-size="10 * 1024 * 1024" @oversize="onOversize" v-if="filepictureList.length < 10" />
          <div style="color: #A5B4DA;width: 100%;display: flex;justify-content: flex-start;">*(JPEG,PEG,最大10M,最多10张)</div>
        </div>
      </div>
      <div class="content_bot">
        <div style="margin: 10px 0;">
          <div style="font-size: 16px;padding:5px 0;">上传视频</div>
          <div
            style="width: 80px;height: 80px;float: left;margin: 0 10px 10px 0;position: relative;display: flex;justify-content: center;"
            v-for="(it, id) in filevideoList" :key="id" @click="looktype(it, 'video')">
            <!-- :autoplay="false"  -->
            <video id="video" :autoplay="false" :controls="false" style="max-width: 100%;max-height: 100%;" :src="it" :poster="generatePosterUrl(it)">
              <!-- <source :src="it" type="video/mp4" />  -->
            </video>
            <!-- <img :src="logoimg" alt="" style="max-width: 100%;max-height: 100%;"> -->
            <div class="close" style="" @click.stop="delvideo(id)"><van-icon name="cross" /></div>
            <van-icon name="play-circle-o" class="open_video" size="30px" color="#fff" />
          </div>
          <van-uploader :max-count="5" multiple accept="video/*" :after-read="afterReadVideo" :max-size="50 * 1024 * 1024"
            @oversize="onOversizevideo" v-if="filevideoList.length < 5" />
          <div style="color: #A5B4DA;width: 100%;display: flex;justify-content: flex-start;">*(MP4,最大50M,最多5个)</div>
        </div>
      </div>
    </div>
    <!-- 内容 结束 -->
    <div class="bottom" style="justify-content: flex-end;">
      <van-button type="info" round size="normal" block style="width: 100%;margin: 0 auto;" @click="btn_from"
        class="">提交</van-button>
    </div>

    <!-- 弹框展示 图片 和视频 -->
    <van-overlay :show="show" @click="show = false">
      <div class="look_type">
        <img :src="content" alt="" v-if="contenttype == 'img'" style="max-width: 100%;max-height: 100%;">
        <video v-if="contenttype == 'video'" :autoplay="true" style="max-width: 100%;max-height: 100%;" :src="content"
          controls disablepictureinpicture></video>
      </div>
    </van-overlay>

    <van-overlay :show="upoadshow" @click="upoadshow = false" :close-on-click-overlay="false">
      <div class="upoadshow_type">
        <van-loading size="24px" vertical>上传中...</van-loading>
      </div>
    </van-overlay>
  </div>
</template>
<script>
import {
  compressImgNew
} from "@/assets/js/picture.js";
import { bikeinfo, fileSave } from '@/api/common.js'
import { flowsave, flowrupdate } from '@/api/index/index.js'
export default {
  data() {
    return {
      logoimg: require('../../../../static/images/back_list.png'),
      vinNo: '',

      blackobj: null,
      remark: "", //理由.
      // 图片信息
      filepictureList: [],
      // 视频信息
      filevideoList: [],

      // 二维码扫描
      html5Qrcode: null,
      error: '',
      isScaning: false,

      // 遮罩
      content: '', //内容
      contenttype: '',
      show: false,

      // 上传
      upoadshow: false
    }
  },
  components: {
  },
  mounted() {
    let _this = this;
    // ios
    window.giantapp_scan_callback = (res) => {
      _this.giantapp_scan_callback(res);
    };

    // 安卓
    window.onLoadQr = (res) => {
      _this.onLoadQr(res);
    };
  },
  computed: {},
  methods: {
    goto_out() {
      const _this = this;
      _this.$router.go(-1)
    },
    // 搜索
    onSearch(val) {
      const _this = this
      // _this.vinNo = val
      bikeinfo({ vinNo: _this.vinNo }).then(res => {
        if (res.status == 200) {
          if (typeof res.data != "object") {
            res.data = JSON.parse(res.data);
          }
          if (res.data.code == 200) {
            _this.blackobj = res.data.data
            _this.isScaning = false
          } else if (res.data.code == 0) {
            _this.$toast(res.data.msg ? res.data.msg : '网络加载失败,请稍后再试');
          } else {
            _this.blackobj = null
            _this.$toast(res.data.msg ? res.data.msg : '网络加载失败,请稍后再试');
          }
        } else {
          _this.$toast(res.data.msg ? res.data.msg : '网络加载失败,请稍后再试');
        }
      })
        .catch(err => {
          _this.$toast('网络加载失败,请稍后再试');
        });
    },
    // 提交
    btn_from() {
      const _this = this;
      if (_this.blackobj == null) {
        _this.$toast('请扫码或搜索进行添加信息');
        return
      }

      if (_this.remark == '') {
        _this.$toast('请输入123');
        return
      }

      let parms = {
        images: _this.filepictureList,
        videos: _this.filevideoList,
        shopCode: _this.GLOBAL.loginUser.mainOrgCode,
        shopName: _this.GLOBAL.loginUser.mainOrgName,
        dealerCode: _this.GLOBAL.loginUser.dealercode,
        sbuCode: _this.GLOBAL.loginUser.sbucode,
        sku: _this.blackobj.sku,
        vinNo: _this.vinNo,
        bikeModel: _this.blackobj.bikeModel,
        banner: _this.blackobj.banner,
        remark: _this.remark,
        dealerName: _this.GLOBAL.loginUser.dealerName,
        sbuName: _this.GLOBAL.loginUser.sbuName,
        staffId: _this.GLOBAL.loginUser.staffId,
      }

      flowsave(
        parms
      ).then(res => {
        if (res.status == 200) {
          if (typeof res.data != "object") {
            res.data = JSON.parse(res.data);
          }
          if (res.data.code == 200) {
            _this.$router.push({
              path: "/",
            })
            _this.$toast(res.data.msg ? res.data.msg : '网络加载失败,请稍后再试');
          } else {
            _this.$toast(res.data.msg ? res.data.msg : '网络加载失败,请稍后再试');
          }
        } else {
          _this.$toast(res.data.msg ? res.data.msg : '网络加载失败,请稍后再试');
        }
      })
        .catch(err => {
          _this.$toast('网络加载失败,请稍后再试');
        });
    },
    // 上传 ======================
    // 上传图片
    afterReadImg(file) {
      const _this = this;
      // let files = compressImgNew(file);
      _this.uploadfile(file, 'img')
    },
    // 上传视频
    afterReadVideo(file) {
      const _this = this;
      _this.uploadfile(file, 'video')
    },
    // 上传文件过大
    onOversize() {
      _this.$toast('图片不能大于10M');
    },
    // 上传文件过大
    onOversizevideo() {
      _this.$toast('图片不能大于50M');
    },

    // 删除图片
    delimg(id) {
      const _this = this;
      _this.filepictureList.splice(id, 1)
    },
    // 删除视频
    delvideo(id) {
      const _this = this;
      _this.filevideoList.splice(id, 1)
    },
    // 上传发布
    uploadfile(file, type) {
      const _this = this;
      _this.upoadshow = true
      let formdata = new FormData();
      formdata.append("file", file.file);
      _this.axios.post(_this.GLOBAL.opo_gcross_api + '/crossSend/fileSave', formdata).then(function (res) {
        if (res.status == 200) {
          if (typeof res.data != "object") {
            res.data = JSON.parse(res.data);
          }
          if (res.data.code == 200) {
            if (type == 'img') {
              _this.filepictureList = _this.filepictureList.concat(res.data.data)
            } else {
              _this.filevideoList = _this.filevideoList.concat(res.data.data)
            }
            _this.upoadshow = false
          } else {
            _this.upoadshow = false
            _this.$toast(res.data.msg ? res.data.msg : '网络加载失败,请稍后再试');
          }
        } else {
          _this.upoadshow = false
          _this.$toast(res.data.msg ? res.data.msg : '网络加载失败,请稍后再试');
        }
      })
    },
    // 视频封面
    generatePosterUrl(videoUrl) {
      // 在这里,你可以使用视频链接 `videoUrl` 来生成封面图像的URL
      // 这个例子中使用了指定尺寸为 80x80 的缩略图
      return `${videoUrl}?vframe/jpg/offset/10/w/80px/h/80px`;
    },
    // 查看信息
    looktype(it, type) {
      const _this = this;
      _this.show = true
      _this.content = it
      _this.contenttype = type
    },
    // 扫描 ==================
    //扫码功能
    btn_scancode() {
      const _this = this;
      if (_this.browser['wx']) {
        _this.axios
          .post(
            "https://wechat.giant.com.cn/third/wechat.ashx?action=jspack2",
            _this.qs.stringify({
              apiname: "Giant",
              apipwd: "Dline!@1587",
              wxname: "giantfwh",
              url: location.href.split("#")[0],
            })
          )
          .then(function (res) {
            var fetch_data = res.data.jspack;
            wx.config({
              debug: false,
              appId: fetch_data.appId, // 必填,公众号的唯一标识
              timestamp: fetch_data.timeStamp, // 必填,生成签名的时间戳
              nonceStr: fetch_data.nonceStr, // 必填,生成签名的随机串
              signature: fetch_data.signatureStr, // 必填,签名
              jsApiList: ["scanQRCode"], // 必填,需要使用的JS接口列表
            });

            wx.ready(function () {
              // config信息验证成功后会执行ready方法,所有接口调用都必须在config接口获得结果之后
              // config 是一个客户端的异步操作,所以如果需要在页面加载时调用相关接口,则须把相关接口放在ready函数中调用来确保正确执行.对于用户触发是才调用的接口,则可以直接调用,不需要放在ready函数中
              wx.checkJsApi({
                // 判断当前客户端版本是否支持指定JS接口
                jsApiList: ["scanQRCode"],
                success: function (res) {
                  // 以键值对的形式返回,可用true,不可用false。如:{"checkResult":{"scanQRCode":true},"errMsg":"checkJsApi:ok"}
                  if (res.checkResult.scanQRCode === true) {
                    wx.scanQRCode({
                      // 微信扫一扫接口
                      desc: "scanQRCode desc",
                      needResult: 1, // 默认为0,扫描结果由微信处理,1则直接返回扫描结果,
                      scanType: ["qrCode", "barCode"], // 可以指定扫二维码还是一维码,默认二者都有
                      success: function (res) {
                        // const value = res.resultStr.split('/').pop();

                        // _this.onSearch(value)
                        // console.log(res,123123)
                        let url_type = 0;
                        if (
                          res.resultStr.indexOf("https://") == 0 ||
                          res.resultStr.indexOf("http://") == 0
                        ) {
                          if (res.resultStr.indexOf("giant.com.cn") == -1) {
                            url_type = 1;
                          }
                          if (res.resultStr.indexOf("qrgiant.com") == -1) {
                            url_type = 1;
                          }
                          if (res.resultStr.indexOf("qrgiant.cn") != -1) {
                            url_type = 1;
                          }
                        } else {
                          url_type = 1;
                        }

                        if (!url_type) {
                          _this.$dialog
                            .alert({
                              title: "提示",
                              message:
                                "您购买的产品可能属于假冒伪劣产品,请与门店确认",
                              confirmButtonText: "我知道了",
                              confirmButtonColor: "#4E66FF",
                              showCancelButton: false,
                            })
                            .then(() => { })
                            .catch(() => { });
                          return false;
                        }

                        const getCode = res.resultStr; // 当needResult 为 1 时,扫码返回的结果
                        let url_index = res.resultStr.lastIndexOf("/");
                        _this.vinNo = res.resultStr.substring(
                          url_index + 1,
                          res.length
                        );
                        _this.onSearch()
                      },
                    });
                  } else {
                    alert("抱歉,当前客户端版本不支持扫一扫");
                  }
                },
                fail: function (res) {
                  // 检测getNetworkType该功能失败时处理
                  alert("fail" + res);
                },
              });
            });

            /* 处理失败验证 */
            wx.error(function (res) {
              // config 信息验证失败会执行error函数,如签名过期导致验证失败,具体错误信息可以打开config的debug模式查看,也可以在返回的res参数中查看,对于SPA可以在这里更新签名
              alert("配置验证失败: " + res.errMsg);
            });
          })
          .catch(function (error) {
            _this.$toast("出现了一些问题:" + error);
          });
      } else if (_this.browser['giantapp']) {
        location.href = "ridelifegc://qrcode/scan";
      } else if (_this.browser['giantopoapp']) {
        if (_this.browser['ios']) {
          window.webkit.messageHandlers.toQr.postMessage("");
        } else {
          android.toQr();
        }
      } else {
        _this.$toast(
          "请在微信端或者捷安特O+O经营助手APP与捷安特骑行APP环境下使用"
        );
        return false;
      }
    },
    giantapp_scan_callback(res) {
      const _this = this;

      let url_type = 0;

      if (res.indexOf("https://") == 0 || res.indexOf("http://") == 0) {
        if (res.indexOf("giant.com.cn") != -1) {
          url_type = 1;
        }
        if (res.indexOf("giantqrcode.kssina.com") != -1) {
          url_type = 1;
        }
        if (res.indexOf("qrgiant.com") != -1) {
          url_type = 1;
        }
        if (res.indexOf("qrgiant.cn") != -1) {
          url_type = 1;
        }
      } else {
        url_type = 1;
      }

      if (!url_type) {
        _this.$dialog
          .alert({
            title: "提示",
            message: "您购买的产品可能属于假冒伪劣产品,请与门店确认",
            confirmButtonText: "我知道了",
            confirmButtonColor: "#4E66FF",
            showCancelButton: false,
          })
          .then(() => { })
          .catch(() => { });
        return false;
      }

      let url_index = res.lastIndexOf("/");
      _this.vinNo = res.substring(url_index + 1, res.length);
      _this.onSearch()

      //_this.$router.push({ path: '/partsview', query: { vin: vinno, vintype: 1 } });
    },
    onLoadQr(res) {
      const _this = this;
      /**
       
       * 生成二维码链接(正式环境):http://qrgiant.com/t0123456788
          生成二维码链接(测试环境):https://giantqrcode.kssina.com/t0123456788
       */

      let url_type = 0;

      if (res.indexOf("https://") == 0 || res.indexOf("http://") == 0) {
        if (res.indexOf("giant.com.cn") != -1) {
          url_type = 1;
        }
        if (res.indexOf("giantqrcode.kssina.com") != -1) {
          url_type = 1;
        }
        if (res.indexOf("qrgiant.com") != -1) {
          url_type = 1;
        }
        if (res.indexOf("qrgiant.cn") != -1) {
          url_type = 1;
        }
      } else {
        url_type = 1;
      }

      if (!url_type) {
        _this.$dialog
          .alert({
            title: "提示",
            message: "您购买的产品可能属于假冒伪劣产品,请与门店确认",
            confirmButtonText: "我知道了",
            confirmButtonColor: "#4E66FF",
            showCancelButton: false,
          })
          .then(() => { })
          .catch(() => { });
        return false;
      }

      let url_index = res.lastIndexOf("/");
      _this.vinNo = res.substring(url_index + 1, res.length);
      _this.onSearch()
    },
  },
}
</script>
<style lang='less' scoped>
/deep/ .van-dropdown-menu__bar {
  box-shadow: none;
}

.title_prompt {
  background: #FFFBF3;
  color: #DD9E1E;
  border-radius: 10px;
  padding: 10px;
  margin: 0 0 10px 0;
}

.content {
  padding: 10px;
  margin-bottom: 60px;

  .content_top {
    display: flex;
    background: #fff;
    border-radius: 10px;
    padding: 10px;

    .content_top_img {
      width: 100px;
      height: 100px;
    }
  }

  .content_bot {
    background: #fff;
    border-radius: 10px;
    margin: 10px 0;
    padding: 0 10px 10px 10px;
  }
}


.line_radios {
  display: inline-block;
  margin: 5px 0;
  color: #DD9E1E;
  border: 1px solid #DD9E1E;
  border-radius: 50px;
  width: 20px;
  height: 20px;
  line-height: 17px;
  text-align: center;
}

.container {
  height: 100%;
  width: 100%;
}

.qrcode {
  position: fixed;
  width: 100%;
  height: 100%;
  top: 0;
  bottom: 0;
  left: 0;
  right: 0;
  z-index: 999;
  background-color: rgba(0, 0, 0, 0.48);

  .close_icon {
    position: absolute;
    right: 10px;
    top: 10px;
  }
}

#reader {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
}


.wrapper {
  position: relative;
  height: 100%;
}


.look_type {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  width: 100%;
  height: 100%;
  display: flex;
  justify-content: center;
  align-items: center;
}




/* 隐藏视频控件 */
.content_bot video::-webkit-media-controls {
  display: none !important;
}

.custom-video-controls button {
  /* 样式化自定义按钮 */
  /* 请根据需要自定义按钮的样式 */
}
</style>
相关推荐
多多*10 分钟前
Spring之Bean的初始化 Bean的生命周期 全站式解析
java·开发语言·前端·数据库·后端·spring·servlet
linweidong14 分钟前
在企业级应用中,你如何构建一个全面的前端测试策略,包括单元测试、集成测试、端到端测试
前端·selenium·单元测试·集成测试·前端面试·mocha·前端面经
满怀101534 分钟前
【HTML 全栈进阶】从语义化到现代 Web 开发实战
前端·html
东锋1.31 小时前
前端动画库 Anime.js 的V4 版本,兼容 Vue、React
前端·javascript·vue.js
满怀10151 小时前
【Flask全栈开发指南】从零构建企业级Web应用
前端·python·flask·后端开发·全栈开发
小杨升级打怪中1 小时前
前端面经-webpack篇--定义、配置、构建流程、 Loader、Tree Shaking、懒加载与预加载、代码分割、 Plugin 机制
前端·webpack·node.js
Yvonne爱编码2 小时前
CSS- 4.4 固定定位(fixed)& 咖啡售卖官网实例
前端·css·html·状态模式·hbuilder
SuperherRo2 小时前
Web开发-JavaEE应用&SpringBoot栈&SnakeYaml反序列化链&JAR&WAR&构建打包
前端·java-ee·jar·反序列化·war·snakeyaml
大帅不是我2 小时前
Python多进程编程执行任务
java·前端·python
前端怎么个事2 小时前
框架的源码理解——V3中的ref和reactive
前端·javascript·vue.js