nniapp 开发小程序踩坑

217 阅读3分钟

最近接到一个小程序的业务,好久都没有写过了,想着让自己练练手;经过决定用uniapp开发,以前没有用过nuiapp+vue2.0,所以这算是我的第一次uniapp实践项目。好了废话不多说了,现在说说我在用uniapp开发小程序过程中遇到的问题,有不对的地方或者好的建议,欢迎各位大神指教.....

1.实现动态水波图

由于项目中会统计实时充电效果,所以会用的水波图。我自己在网上找了相关的一些实现方法,但是有的不满足实时变化;其中有几种方案,可以给大家看看;如下:

微信截图_20220922180836.png

  • css实现水波图(由于不满足使用需求)
     [可以参考](https://zhuanlan.zhihu.com/p/266588341)
     [可以参考](https://blog.csdn.net/YourNikee/article/details/120265438)
    
  • ECharts(由于Echart比较大,小程序引入进去会出现问题,不建议使用)
     [可以参考](https://blog.csdn.net/IVanLyf/article/details/107247616)
     [可以参考](https://www.freesion.com/article/75701075423/)
    
  • canvas 手写实现(采用方案)
     [可以参考](http://106.14.220.139/dfv2g/admin/upload/hongdaomall/20220923/902c92a910f84b8ea152e1c80a08d066.html)
    

这边直接上代码

//html
<canvas type="2d" id="canvas" style="width: 180px; height: 180px;"></canvas>
//js
onLoad(option) {
    await this.getByConnectorId()  //业务数据接口
    this.getTime() // canvas 画水波图
    this.timer = setInterval(() => {
      if (this.setTimer) {
        clearTimeout(this.setTimer)
      }
      this.getByConnectorId()
      this.getTime()
    }, 1000 * 10)
  },
  methods:{
      getTime() {
      const query = wx.createSelectorQuery();
      // 获取canvas dom
      query.select('#canvas').fields({ node: true, size: true }).exec(res => {
        const canvas = res[0].node;
        const ctx = canvas.getContext("2d");
        //canvas 画图
        this.renderCanvas(canvas, ctx)
      })
    },
    renderCanvas(canvas, ctx) {
      let nowRange = this.orderInfo.soc; //用于做一个临时的range
      //画布属性
      let mW = (canvas.width = 180);
      let mH = (canvas.height = 180);
      let lineWidth = 1;
      let r = mH / 2; //中心
      //Sin 曲线属性
      let sX = 0;
      let axisLength = mW; //轴长
      let waveWidth = 0.01; //波浪宽度,数越小越宽
      let waveHeight = 20; //波浪高度,数越大越高
      let speed = 0.04; //波浪速度,数越大速度越快
      let xOffset = 0; //波浪x偏移量
      ctx.lineWidth = lineWidth;
      //画矩形函数
      let IsdrawCircled = false;
      let drawCircle = function () {
        ctx.strokeStyle = "#eb4d4c";
        ctx.stroke();
        IsdrawCircled = true;
      };
      //画sin 曲线函数
      let drawSin = function (xOffset, color, waveHeight) {
        ctx.save();

        let points = []; //用于存放绘制Sin曲线的点

        //画圆
        ctx.beginPath();
        ctx.linewidth = 21;
        ctx.strokeStyle = '#8b9df7';
        ctx.arc(90, 90, 90, 0, 2 * Math.PI);
        ctx.fillStyle = "#eff2fc";
        ctx.fill();
        // 只显示重叠部分
        ctx.globalCompositeOperation = 'source-in'
        ctx.beginPath();
        //在整个轴长上取点
        for (let x = sX; x < sX + axisLength; x += 20 / axisLength) {
          //此处坐标(x,y)的取点,依靠公式 “振幅高*sin(x*振幅宽 + 振幅偏移量)”
          let y = Math.sin((-sX - x) * waveWidth + xOffset) * 0.8 + 0.1;

          let dY = mH * (1 - nowRange / 100);

          points.push([x, dY + y * waveHeight]);
          ctx.lineTo(x, dY + y * waveHeight);
        }

        //封闭路径
        ctx.lineTo(axisLength, mH);
        ctx.lineTo(sX, mH);
        ctx.lineTo(points[0][0], points[0][1]);
        ctx.fillStyle = color;
        ctx.fill();
        // 只显示重叠部分(小程序真机不支持该属性)
        //canvas globalCompositeOperation可以参考(http://t.zoukankan.com/qiuzhimutou-p-4722823.html)
        // ctx.globalCompositeOperation = 'destination-atop'
        //画圆
        // ctx.beginPath();
        // ctx.linewidth = 21;
        // ctx.strokeStyle = '#8b9df7';
        // ctx.arc(90, 90, 90, 0, 2 * Math.PI);
        // ctx.fillStyle = "#eff2fc";
        // ctx.fill();
        ctx.restore();
      };
      const that = this
      let render = function () {
        console.log('+++++++++')
        ctx.clearRect(0, 0, mW, mH);
        ctx.strokeRect(0, 0, mW, mH);
        ctx.strokeStyle = "#8e9cf900";
        if (IsdrawCircled == false) {
          drawCircle();
        }
        drawSin(xOffset + Math.PI * 0.7, "#c3d0fe", 18);
        // drawSin(xOffset, "#8e9cf9", 18);
        drawText();
        ctx.stroke();
        ctx.closePath();


        xOffset += speed;
        that.setTimer = setTimeout(() => {
          render()
        }, 1000 / 60)
      };
      // 写百分比文本函数
      let drawText = function () {
        ctx.save();

        let size = 36;
        ctx.font = size + "px PingFang SC-Regular";
        ctx.textAlign = "center";
        ctx.fillStyle = "#F69F53";
        ctx.fillText(~~nowRange + "%", r, r);
        ctx.restore();
        ctx.font = "20px PingFang SC-Regular";
        ctx.textAlign = "center";
        ctx.fillStyle = "#000000"
        let orderStatus = that.orderInfo.orderStatus
        switch (orderStatus) {
          case orderStatus = 1:
            ctx.fillText('启动中', r, r + 36);
            break;
          case orderStatus = 2:
            ctx.fillText('充电中', r, r + 36);
            break;
          case orderStatus = 3:
            ctx.fillText('停止中', r, r + 36);
            break;
          case orderStatus = 4:
            ctx.fillText('已结束', r, r + 36);
            break;
          case orderStatus = 7:
            ctx.fillText('放电启动中', r, r + 36);
            break;
          case orderStatus = 8:
            ctx.fillText('放电中', r, r + 36);
            break;
          case orderStatus = 9:
            ctx.fillText('等待中', r, r + 36);
            break;
          default:
            ctx.fillText('未知', r, r + 36);
        }
        // ctx.fillText('充电中', r, r + 36);
        ctx.restore();
        ctx.font = "14px PingFang SC-Regular";
        ctx.textAlign = "center";
        ctx.fillStyle = "#000000"
        if (that.orderInfo.orderType == 1) {
          ctx.fillText('按需充电', r, r + 56);
        } else if (that.orderInfo.orderType == 2) {
          ctx.fillText('有序充电', r, r + 56);
        } else if (that.orderInfo.orderType == 3) {
          ctx.fillText('V2G模式 ', r, r + 56);
        } else {
          ctx.fillText('即插即充模式', r, r + 56);
        }
        ctx.restore();
      };
      render();
      // // })
    }
  }

2.对接企业微信

首先要在微信开发者工具中增加一个企业微信小程序模拟器(设置>扩展设置>模拟器插件>企业微信小程序模拟器),然后就可以选择切换小程序或是企业微信小程序。在对接去企业微信可能会有多个企业对接,可以在选择切换机行那一行有一个手机一样的图标,点击可以选择企业。

  • 调用wx.qy.login的问题 在模拟器端调用wx.qy.login 返回的数据是{code:'......',errMsg:'qy.login:ok'},而真机调用的时候返回的是{code:'......',errMsg:'qy__login:ok'},就是这个errMsg要注意。

  • 调用wx.qy.login,然后调用后台登录接口一直报(invlid code 无效code)

    解决方案: 1.先调用wx.qy.login,拿到code

  1. 然后调用后台接口传入code(后台这个接口是调用腾讯企业微信的接口,如下图) 微信截图_20220923100838.png 3.拿到2返回的userid和session_key存起来,然后依次调用wx.qy.getAvatar(用户头像),wx.qy.getMobile(手机号),wx.qy.getQrCode(个人二维码),然后调用后台登录接口;如图

微信截图_20220923101416.png

微信截图_20220923101432.png

第一次写文章,写的不好希望大家理解,记录我在实际项目开发中遇到的问题,希望对大家有一点点帮助,有不大好的地方希望大佬们批评指正.....