存证小程序--开发记录

一 路由跳转携带参数问题

1:单个参数用? 后面参数用&

`/index/proof?id=${id}&name=${name}`

2:小程序参数传递,是类似于get传参,所以对单个字段,如果太长,会自动进行截取,那么传递之前,对长数据做一个编码。接收页面再做一个解码

let newProofFileId = encodeURIComponent(obj.ProofFileId);
encodeURIComponent: 函数可把字符串作为 URI 组件进行编码。

在接收参数页面,对数据进行解码

decodeURIComponent(options.newProofFileId)

二 跳转方式

小程序点的层级太多,有时候点击返回,想直接返回原始页。

1.1 最常见的跳转
保留当前页面,跳转到应用内的某个页面。返回时,一层一层的返回

wx.navigateTo({
url: ‘/pages/index/index’,
});
1.2 只能跳转到tabBar配置页面
注意:只能是系统定义的tabBar,如果是自定义tabBar。此方法不管用
wx.switchTab({
url: ‘/pages/index/index’,
});
1.3 设置返回的页数级别

delta:返回的页面数,如果 delta 大于现有页面数,则返回到首页,默认值为1
wx.navigateBack({
delta: 2
})
1.4 关闭当前页面,跳转到应用内的某个页面
单纯的关闭当前页面
wx.redirectTo({
url: ‘/pages/index/index’,
});
1.5 关闭所有页面,打开到应用内的某个页面。
此种跳转,会在页面顶部有一个home图标。点击之后,直接返回首页
wx.reLaunch({
url: ‘/pages/index/index’,
});

三 登录流程,解密UnionID

  1. 登录按钮必须安排上
  2. wx.login获取code
  3. wx.getUserInfo 获取 userInfo,encryptedData,iv

好奇点:

 <button open-type="getUserInfo" lang="zh_CN" @getuserinfo="onGotUserInfo">
 已经有了onGotUserInfo ,就可以获取到userInfo,encryptedData,iv`。
 下面为什么还要再次调用
 wx.getUserInfo.
 因为解密的话,得先走code,不然encryptedData会失效。
 button里面的 @getuserinfo="onGotUserInfo 只是走个形式。
 最终流程还是wx.login -》wx.getUserInfo
要想获取UnionID。小程序必须得关联微信开放平台,

切记切结`:是微信公众平台 不是微信公众平台
代码

 async onGotUserInfo() {
      if (!this.WxUuid) {
        wx.getSetting({
          success: async (res) => {
            console.log(res);
            console.log(res);
            // 判断用户是否拒绝了授权
            if (!res.authSetting["scope.userInfo"]) {
              // 用户拒绝了授权 什么也不操作了就
            } else {
              wx.login({
                success: async (res) => {
                  if (res.code) {
                    this.code = res.code;
                    wx.getUserInfo({
                      success: async (e) => {
                        console.log("wwww", e);
                        const loginData = {
                          AppId: "",
                          Secret: "",
                          Iv: e.iv,
                          encryptedData: e.encryptedData,
                          Code: this.code,
                        };
                        console.log("loginData", loginData);
                        const login = await wxuserinfoApi(loginData);
                        console.log("login", login);
                        uni.setStorageSync("WxUuid", login);
                        // 同意授权,掉接口,跳转、
                        uni.reLaunch({
                          url: "/pages/proof/index",
                        });
                      },
                    });
                  }
                },
              });
            }
          },
        });
      } else {
        uni.reLaunch({
          url: "/pages/proof/index",
        });
      }
    },

录音的授权

wx.getSetting({
        success: (res) => {
          console.log(res);
          if (!res.authSetting["scope.record"]) {
            wx.authorize({
              scope: "scope.record",
              success: (res) => {
                console.log("第一次录音授权成功", res);
                // 用户已经同意小程序使用录音功能,后续调用 wx.startRecord 接口不会弹窗询问
                this.isStart = false;
                console.log("this.isStart", this.isStart);
                this.start();
                const startObj = {
                  duration: 60000,
                };
                recorderManager.start(startObj);
              },
              fail: (res) => {
                wx.showModal({
                  title: "温馨提示",
                  content: "您已拒绝授权,是否去设置打开?",
                  confirmText: "确认",
                  cancelText: "取消",
                  success: (res) => {
                    console.log(res);
                    if (res.confirm) {
                      console.log("用户点击确认");
                      wx.openSetting({
                        success: (res) => {
                          console.log(res);
                          res.authSetting = {
                            "scope.record": true,
                          };
                          console.log("openSetting: success");
                        },
                      });
                    } else {
                      console.log("用户点击取消");
                    }
                  },
                });
              },
            });
          } else {
            wx.authorize({
              scope: "scope.record",
              success: (res) => {
                console.log("第二次授权成功的录音授权成功", res);
                //第二次授权成功的
                this.isStart = false;
                console.log("this.isStart", this.isStart);
                this.start();
                const startObj = {
                  duration: 60000,
                };
                recorderManager.start(startObj);
              },
            });
          }
        },
      });

位置授权,获取经纬度

 wx.getSetting({
        success: (res) => {
          console.log(res);
          if (!res.authSetting["scope.userLocation"]) {
            wx.getLocation({
              type: "wgs84",
              success: (res) => {
                console.log("授权weizhi", res);
                console.log("当前位置的经度:" + res.longitude);
                console.log("当前位置的纬度:" + res.latitude);
                uni.setStorageSync("longitude", res.longitude);
                uni.setStorageSync("latitude", res.latitude);
              },
              fail() {
                wx.showModal({
                  title: "温馨提示",
                  content: "您已拒绝授权,是否去设置打开?",
                  confirmText: "确认",
                  cancelText: "取消",
                  success: (res) => {
                    console.log(res);
                    if (res.confirm) {
                      console.log("用户点击确认");
                      wx.openSetting({
                        success: (res) => {
                          console.log(res);
                          res.authSetting = {
                            "scope.userLocation": true,
                          };
                          console.log("openSetting: success");
                        },
                      });
                    } else {
                      console.log("用户点击取消");
                    }
                  },
                });
              },
            });
          } else {
             wx.getLocation({
              type: "wgs84",
              success: (res) => {
                console.log("授权weizhi", res);
                console.log("当前位置的经度:" + res.longitude);
                console.log("当前位置的纬度:" + res.latitude);
                uni.setStorageSync("longitude", res.longitude);
                uni.setStorageSync("latitude", res.latitude);
              },
          }
        },
      });

获取到经纬度之后,转化成,度 分 秒

对此功能做了单独的封装 data.js

const gps = function (d_data) {
	let d = parseInt(d_data);
	let m = parseInt(((d_data - d) * 60));
	let s = parseInt((((d_data - d) * 60 - m) * 60));
	return d + "°" + m + "′" + s + "″";
}
module.exports = {
	gps
}

使用

import { gps } from "../../utilsProof/date";
data() {
    return {
longitude: gps(uni.getStorageSync("longitude")),
      latitude: gps(uni.getStorageSync("latitude")),
}

效果
在这里插入图片描述

文件转hash(sha256)

  1. 上传 拍照 图片:wx.chooseImage
  2. 上传文件:chooseMessageFile
  3. 上传,拍摄视频 chooseVideo
    这些微信内置的方法。都会返回一个本地的临时路劲。我们可以将这个临时路劲转成二进制文件流
    注意我们只要 ArrayBuffer 格式读取文件的二进制内容。
 wx.chooseImage({
      success: (res)=> {
// 这个适用于任何,不局限于wx.chooseImage
     console.log(wx.getFileSystemManager().readFileSync(res.tempFilePaths[0]))
    var buffer =  wx.getFileSystemManager().readFileSync(res.tempFilePaths[0])
      },
    })

在这里插入图片描述
安装js-sha256
npm install js-sha256 --save
引入
import { sha256 } from "js-sha256";
使用
buffer = sha256(this.base);

如果要转成base64.则这样写

 wx.chooseImage({
      success: (res)=> {
        console.log(wx.getFileSystemManager().readFileSync(res.tempFilePaths[0], "base64"))
      },
    })

总结 : 文件转hash加密
主要是文件类型是ArrayBuffer 格式。所以要将本地临时路径的文件读取出来。然后利用sha256进行加密

将文件保存到到本地,并且设置临时地址

  1. 将base64转化为ArrayBuffer
  2. 获取文件的后缀。以便设置文件后缀
    比如: ’ 37a7a3d0acbc715344e2f4a30a12b27ae510f24.mp4’
    const temp = this.id.split(".")[this.id.split(".").length - 1]; // 根据. 进行分割。取. 后的所有字符
  3. 这样既设置了路劲,也将文件保存至本地。那么此时的文件路劲。我们就可以当做src.在音频,视屏 图片中 随意使用了
const buffer = uni.base64ToArrayBuffer(data[0]);
        this.voicePath = `${wx.env.USER_DATA_PATH}/tmp_base64.${temp}`;
        var fileManager = wx.getFileSystemManager();
        fileManager.writeFile({
          filePath: this.voicePath,
          data: buffer,
          success: (result) => {},
          fail: () => {},
          complete: () => {},
        });

textarea 中字数统计

我也想偷懒,没想到官方没这个功能
在这里插入图片描述

 <view class="contain-input">
        <textarea
          placeholder="500字以内"
          :value="content"
          :maxlength="500"
          placeholder-style=" font-size: 31rpx;font-family: PingFangSC-Medium "
          @input="conInput"
        />
        <view class="max-num"> {{ content.length || 0 }}/500 </view>
      </view>
  //字数
    conInput(e) {
      this.content = e.detail.value;
    },

动态设置标题,面导航条颜色,字体颜色

场景: 有五个功能,都要跳到同一个页面,进行取名操作。但是页面标题都是根据功能类型来显示。这个时候用动态标题,绝对妥。并且在已进入页面(onLoad中设置)

  1. 动态设置标题
onLoad(options) {
    this.title = options.type;
    uni.setNavigationBarTitle({
      title: this.title,
    });
  },
  1. 设置页面导航条颜色
uni.setNavigationBarColor({
    frontColor: '#ffffff', // 仅支持 #ffffff 和 #000000。
    backgroundColor: '#ff0000', //背景颜色值,有效值为十六进制颜色,不拘束于黑白
    //animation为可选项
    animation: {
        duration: 400,
        timingFunc: 'easeIn'
    }
})

自定义tabbar

<template>
  <view class="tarbar" :style="{ marginBottom: isFullSucreen ? '68rpx' : '' }">
    <view
      class=".tarbar-list"
      :style="{
        background: tabBar.backgroundColor,
        color: tabBar.color,
        'border-top':
          tabBar.position == 'bottom' ? '1rpx solid ' + tabBar.borderStyle : 0,
        'border-bottom':
          tabBar.position == 'top' ? '1rpx solid ' + tabBar.borderStyle : 0,
      }"
    >
      <view class="tarbar-list-ul">
        <view
          class="tarbar-list-li"
          v-for="(item, index) in tabBar.list"
          :key="index"
          @click.stop="setSelected(item, index)"
        >
          <block>
            <view class="tarbar-list-li-icon">
              <image
                :src="selected == index ? item.selectedIconPath : item.iconPath"
                mode=""
              ></image>
            </view>
            <view
              :style="selected == index ? 'color:' + tabBar.selectedColor : ''"
              class="tarbar-list-li-name"
              >{{ item.text }}</view
            >
          </block>
        </view>
      </view>
    </view>
  </view>
</template>

<script>
export default {
  data() {
    return {
      isFullSucreen: false,
      tabBar: {
        color: "#999999",
        selectedColor: "#999",
        borderStyle: "white",
        backgroundColor: "#fff",
        position: "bottom",
        list: [
          {
            pagePath: "/pages/proof/index",
            iconPath: "/static/czHome.png",
            selectedIconPath: "/static/czHomeSelect.png",
            text: "首页",
          },
          {
            pagePath: "/pages/proofList/index",
            iconPath: "/static/czProof.png",
            selectedIconPath: "/static/czProofSelect.png",
            text: "证据",
          },
        ],
      },
      selected: 0, //当前激活项
    };
  },
  props: {
    current: {
      type: Number,
      default: 0,
    },
  },
  created() {
    this.isFullSucreen = getApp().globalData.isFullSucreen;
    console.log("this.isFullSucreen", this.isFullSucreen);
    console.log("子组件czChange", this.current);
  },
  watch: {
    current(newValue, oldValue) {
      this.selected = newValue;
    },
  },
  methods: {
    setSelected(tab, index) {
      console.log("11", tab);
      this.selected = index;
      console.log("选中", this.selected, "索引", index);
      this.$emit("czChange", {
        path: tab.pagePath,
        index,
      });
    },
  },
};
</script>

<style>
.tarbar {
  width: 100%;
  z-index: 9999;
  position: fixed;
}

.tarbar-list {
  width: 100%;
  height: 98upx;
  background: #4d586f;
  position: fixed;
  left: 0;
  bottom: 0;
}

.tarbar-list-ul {
  width: 100%;
  height: 100%;
  padding: 0upx 160upx;
  display: flex;
  justify-content: space-between;
  box-sizing: border-box;
}

.tarbar-list-li {
  width: 80upx;
  height: 100%;
  display: flex;
  flex-direction: column;
  justify-content: center;
}

.tarbar-list-li-icon {
  width: 50upx;
  height: 50upx;
  margin: 0 auto;
  display: flex;
  align-items: center;
  justify-content: center;
}

.tarbar-list-li-icon image {
  width: 36rpx;
  height: 36rpx;
}

.tarbar-list-li-name {
  width: 100%;
  text-align: center;
  line-height: 30upx;
  font-size: 24upx;
  height: 30upx;
}

.tarbar-list-li-center {
  width: 100upx;
}
</style>

使用

 <my-tabbar :current="current" @czChange="czChange"></my-tabbar>
czChange(obj) {
      console.log("参数", obj);

      this.current = +obj.index;
      console.log("this.current", this.current);
      if (this.current === 1) {
        this.getQueryProof();
        uni.setNavigationBarTitle({
          title: "证据列表",
        });
        uni.setNavigationBarColor({
          frontColor: "#000000",
          backgroundColor: "#ffffff",
        });
      } else {
        uni.setNavigationBarTitle({
          title: "",
        });
        uni.setNavigationBarColor({
          frontColor: "#ffffff",
          backgroundColor: "#0a47b0",
        });
      }
      console.log("类型", typeof obj.index);
      console.log("索引", this.current);
    },

次策略是万般无奈之举,由于自定义tabbar。每次都会和页面的加载和销毁发生变化。所以底部tabbar会闪一下。为了解决这个问题。把两个页面放在了一起。通过当前点击是tabbaer索引,开控制页面的展示

<view v-if="current === 0">
     aaa页面
     </view>
 <view v-else>
bbb页面
</view>

小技巧

  1. 传值的时候,通过对象传参,取得时候,特别方便
  2. 父子组件传值,很容易出现监听不到问题。所以我这里用了监听器,来监听父组件传值的变化
 watch: {
    current(newValue, oldValue) {
      this.selected = newValue;
    },
  },
  1. 底部适配全屏
const { safeArea, screenHeight } = wx.getSystemInfoSync()
      this.fullScreen = screenHeight - safeArea.height > 40
全面屏动态加样式
 :style="{ marginBottom: isFullSucreen ? '68rpx' : '' }"

几种提示框

  1. 简单的提示,间隔几秒就消失
uni.showToast({
     title: "不支持该类型文件",
      duration: 2000,
       icon: "none",
  });
  1. 数据加载前,加载后的提示
uni.showLoading({
    title: '加载中'
});
  uni.hideLoading();
  1. 操作模态框
uni.showModal({
  title: '提示',
  content: '这是一个模态弹窗',
  success: function (res) {
      if (res.confirm) {
          console.log('用户点击确定');
      } else if (res.cancel) {
          console.log('用户点击取消');
      }
  }
});

上传文件

wx.uploadFile

将本地资源上传到服务器。客户端发起一个 HTTPS POST 请求,其中 content-type 为 multipart/form-data。

wx.chooseImage({
  success (res) {
    const tempFilePaths = res.tempFilePaths
    wx.uploadFile({
      url: 'https://example.weixin.qq.com/upload', //仅为示例,非真实的接口地址
      filePath: tempFilePaths[0],
      name: 'file',
      formData: {
        'user': 'test'
      },
      success (res){
        const data = res.data
        //do something
      }
    })
  }
})

视屏自动全屏播放

看那个时机需要,就放这段话,期中myvideo,是video组件的id

 var videoContext = wx.createVideoContext("myvideo", this);
   videoContext.requestFullScreen(); //执行全屏方法
 <view v-if="hasVidao">
        <video
          :src="voicePath"
          controls
          autoplay
          isFullscreen
          id="myvideo"
          @fullscreenchange="screenChange"
        ></video>
      </view>

检测是否全屏 @fullscreenchange

   screenChange(e) {
      console.log("e全屏非全屏", e);
      let fullScreen = e.detail.fullScreen; //值true为进入全屏,false为退出全屏
      if (!fullScreen) {
        //退出全屏
        this.hasVidao = false;
      } else {
        //进入全屏
        this.hasVidao = true;
      }
    },

录音功能

日期格式化

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值