Uniapp 实现全民分销功能

sxkk20081年前知识分享63

前言

前段时间在掘金 app 多了一个推广中心,分享课程链接,若有其他用户从你分享的链接购买,你就可以获得一笔佣金,我们称类似的功能叫全民分销,全民分销在互联网推广中很常见,比如腾讯云、阿里云等都有,只不过叫法不一样、腾讯云叫 SCP,阿里云叫推广云大使。笔者也通过类似的活动,也获得过一些收益,由于全民分销功能使用门槛较低、传播速度快、对于平台商家和用户都是零成本的,成了互联网中热门的推广功能,本篇介绍下全民分销功能实现原理。

掘金推广中心

流程图

全民分销流程图

推广者(也就是老用户)生成唯一的推广链接或者二维码,新用户点击推广者链接记录推广者 ID,用户下单生成推广记录流水,当然还有另外一种方式,拉新获得奖励,比如拉新 3 人获得代金券等

表结构

比如有一张用户表

interface User {
  _id: string
  // 名称
  name: string
  // 头像
  avatar: string
  // weixin  唯一ID
  openid: string
  // 创建时间
  createTime: number
  // 积分
  integral: number
}

一张记录表

interface Record {
  _id: string
  // 获得积分描述
  name: string
  // 发放模式 1 已发放 0 未发放
  mode: number
  // 关联用户表
  userId: string
  // 创建时间
  createTime: number
  // 获得积分
  integral: number
}

积分用来描述用户收益,或者可以用积分来兑换奖励,这部分可以根据不同的活动有不同的实现方式。以上数据字段是简易版设计,实际可以根据活动情况增加字段。

分享的 3 种方式

复制链接

在 web app 中一般会使用复制链接的功能 在现代浏览器(chrome 66+,edge 79+ )中只需要 1 行代码就可以实现复制和粘贴

const copy = (text) => navigator.clipboard.writeText('Hello world!')

粘贴

const text = navigator.clipboard.readText()

如果需要兼容老的浏览器可以使用 clipboard.js

转发

在小程序中会有转发和分享的按钮, 只需要在函数生命周期中加入 2 个函数就可以了。

onShareAppMessage() {
  // 转发
  return {
    title: this.detail.title + ' | 前端面试题库',
    path: '/pages/index/detail?id=' + this.detail._id + '&userId=' + this.vuex_user ? this.vuex_user._id : '',
  }
},
onShareTimeline() {
  // 分享到朋友圈
  return {
    title: this.detail.title + ' | 前端面试题库',
    path: '/pages/index/detail?id=' + this.detail._id + '&userId=' + this.vuex_user ? this.vuex_user._id : '',
  }
}

上述代码是我的面试刷题小程序代码 detail._id 是题目 id,this.vuex_user._id 是当前用户的 id,这样,每一道题目分享出去都会带上当前用户的 id。

生成带参数的二维码

在小程序中可以使用 wxacode.getUnlimited 接口获取小程序码,适用于需要的码数量极多的业务场景。通过该接口生成的小程序码,永久有效,数量暂无限制。

首先需要获得 access_token,这个是接口调用凭证

//封装获取 access_token 的方法, 1分钟1w次
async function getAccessToken(appId, appSecret) {
  const res = await uniCloud.httpclient.request(
    `https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=${appId}&secret=${appSecret}`,
    {
      dataType: 'json',
    }
  )
  return res.data.access_token
}

接下来就可以调用微信提供的接口,生成唯一的小程序码

async function getMpCode(scene, page, access_token) {
  const res = await uniCloud.httpclient.request(
    `https://api.weixin.qq.com/wxa/getwxacodeunlimit?access_token=${access_token}`,
    {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
      },
      data: {
        scene,
        page,
      },
    }
  )
  return res.data
}

参数说明

  • env_version:要打开的小程序版本。正式版为 release,体验版为 trial,开发版为 develop
  • page: 页面 page,例如 pages/index/index,根路径前不要填加 /,不能携带参数(参数请放在 scene 字段里),如果不填写这个字段,默认跳主页面
  • scene:二维码唯一参数, 最大 32 个可见字符,只支持数字,大小写英文以及部分特殊字符:!#$&'()*+,/:;=?@-._~,其它字符请自行编码为合法字符(因不支持%,中文无法使用 urlencode 处理,请使用其他编码方式)

返回值

  • Buffer 返回的图片 Buffer

云函数生成小程序码

exports.main = async (event, context) => {
  const appId = '你的 appId'
  const appSecret = '你的 appSecrets'
  const { page, scene } = event
  const access_token = await getAccessToken(appId, appSecret)
  const res = await getMpCode(scene, page, access_token)
  return res
}

小程序端生成 canvas 海报

uniCloud.callFunction({
  name: 'getmpcode',
  data: {
    scene,
  },
  success: (res) => {
    const imagepath = `${wx.env.USER_DATA_PATH}/mpcode.png`
    const fs = uni.getFileSystemManager()
    fs.writeFileSync(imagepath, uni.arrayBufferToBase64(res.result.data), 'base64')
    canvasdrawImage(imagepath)
  },
})

我们在页面上加一个生成朋友圈海报的按钮,当点击这个按钮触发云函数,生成小程序码,然后生成一个 ${wx.env.USER_DATA_PATH}/mpcode.png 临时文件路径,将接口返回的数据通过 uni.arrayBufferToBase64 转成 base64,最后将 base64 写入临时文件,此时本地就有了带参数的二维码。

接下来将二维码绘制在 canvas 上就可以了

<template>
  <view>
    <canvas canvas-id="myCanvas" style="width:100vw;height:100vw;">canvas>
  view>
template>
function canvasDrawImage(imagepath) {
  const context = uni.createCanvasContext('myCanvas')
  context.drawImage(imagepath, 470, 530, 100, 100)
  context.draw()
}

此时我们可以在页面上看到一个小程序码,drawImage 参数接收一个本地图片路径,在 470,530 的坐标,绘制一个 100,100 的小程序二维码

var img = new Image()
img.onload = function () {
  context.drawImage(img, 0, 0)
}
img.src = 'https://example.com/files/backdround.png'

为了让海报更加好看,我们可以设计一张背景,先在 canvas 上绘制背景,文字等,然后再绘制小程序码。

下载生成的 canvas 海报

methods: {
  saveImage() {
    uni.showLoading({
      title: '加载中...',
      mask: true,
    })
    uni.canvasToTempFilePath({
      //将canvas保存到一个临时文件
      canvasId: 'myCanvas', //画布id
      success: (res) => {
        const fs = uni.getFileSystemManager()

        fs.saveFile({
          tempFilePath: res.tempFilePath, // 传入一个本地临时文件路径
          success: (res) => {
            this.posterImage = res.savedFilePath
            this.saveImageToPhotosAlbum()
          },
          fail: (err) => {
            console.log(err)
          },
        })
        uni.hideLoading()
      },
    })
  },
  saveImageToPhotosAlbum() {
    uni.saveImageToPhotosAlbum({
      filePath: this.posterImage,
      success: () => {
        this.$emit('close-overlay')
        uni.showToast({
          title: '保存图片成功',
          duration: 2000,
        })
      },
      fail(err) {
        const { errMsg } = err
        if (errMsg === 'saveImageToPhotosAlbum:fail auth deny') {
          uni.showModal({
            title: '保存失败',
            content: '请授权保存图片到“相册”的权限',
            success: (result) => {
              const { confirm } = result
              if (confirm) {
                uni.openSetting({})
              }
            },
          })
        }
      },
    })
  },
}

在页面上加一个下载海报按钮,点击就调用 saveImage 函数, 这样就可以将 canvas 海报保存到本地相册了。

注意 虽然是 canvas 下载图,但是需要在微信小程序后台: 开发平台->服务器域名->uploadFile 合法域名要添加上 example.com 否则没办法下载成功图片。

插入记录表

从 url 获得推广者的 id, 我们需要在用户注册或者下单的时候,推广者获得收益和积分等记录存入一张收益记录表, 这样就可以根据记录或者获得查询收益。代码比较简单,这里就不贴了。

小结

本文记录了小程序端全民分销的实现方式,包含前后端的逻辑和思路,总体比较简单,唯一难的就是使用 canvas 绘制海报,若要绘制一张好看的 canvas 海报,可能会花费你不少时间,但是我们可以使用现成的插件,直接在 Dcloud 插件市场搜索关键词“海报”,里面有各种已经封装好的插件,这里我推荐使用 海报画板,支持 xml 和 json 等方式配置,使用比较简单。

最后

我的面试刷题小程序面试狗中也加入了这个功能,邀请一个新用户,可以获得 6 积分,虽然现在积分不能兑换礼品,感兴趣朋友可以体验下。

以上就是本文全部内容,希望这篇文章对大家有所帮助,也可以参考我往期的文章或者在评论区交流你的想法和心得,欢迎一起探索前端。

相关文章

将 React 应用迁移至 Vite

将 React 应用迁移至 Vite

前言当下,在项目开发的过程中,对于大多数人来说,会使用 create react app 来创建 react 应用,它开箱即用,零配置,但随着项目中代码量的增加,你的项目构建时间也会随之增加,开发服务...

人工智能对生活的影响:改变未来,创造无限可能

人工智能对生活的影响:改变未来,创造无限可能

  人工智能(Artificial Intelligence,简称AI)作为一项前沿科技,正逐渐渗透到我们生活的方方面面。它的发展和应用给人类社会带来了巨大的变革,也改变...

在某种程度上,它可能在初学者看来是单调乏味或者不切实际的,但是严格按照这个步骤来做这件事,让你自己决定测试用例是否对你的组件有帮助,会让测试用例变得有意义。

本文将以创建一个 Confirmation 组件来说明,如何在 React 中如何实现测试驱动开发。

Confirmation 组件的特点:

  • Confirmation 标题
  • 确认描述 —— 接收外部程序想要确认的问题
  • 一个确认的按钮,支持外部回调函数
  • 一个取消的按钮,支持外部回调函数

这两个按钮都不知道点击时接下来要做什么事,因为它超出了组件的职责范围,但是组件应该接收这些点击按钮的回调事件。先找个设计图:

image.png

如何测试驱动开发 React 组件?

什么是 TDDTDD(Test-driven development),就是测试驱动开发,是敏捷开发中的一项核心实践和技术,也是一种软件设计方法论。它的原理就是在编写代码之前先编写测试用例,由测试来决...

这是启动后的界面,这个 demo 不是一个简单的页面,而是一个包含了深度嵌套路由的例子。

下图我开发时的截图,Turbopack 直接在命令行中打印出了构建时间,我们看到启动时间只需要 2.3ms

更新速度

试着修改代码,程序会自动热更新,绝大多数次数更新时间都很快,但偶尔有几次更新时间却很长,图片中有一处需要 16s(我使用的是 Mac M1),这其中的原因就不得而知了,尤大也发布了测评,使用 1000 个节点来对比更新速度,数据显示:根组件与 vite 时间几乎相同,叶子节点比 vite 快 68%,与官方称比 vite 快 10 倍相差甚远。当然目前 Turbopack 还处于 alpha 阶段,期待 Turbopack 能够尽快推出正式版。

Turbopack 特点

  • 开箱即用 TypeScript, JSX, CSS, CSS Modules, WebAssembly 等
  • 增量计算: Turbopack 是建立在 Turbo 之上的,Turbo 是基于 Rust 的开源、增量记忆化框架,除了可以缓存代码,还可以缓存函数运行结果。
  • 懒编译:例如,如果访问 localhost:3000,它将仅打包 pages/index.jsx,以及导入的模块。

为什么不选择 Vite 和 Esbuild?

Vite 依赖于浏览器的原生 ES Modules 系统,不需要打包代码,这种方法只需要转换单个 JS 文件,响应更新很快,但是如果文件过多,这种方式会导致浏览器大量级联网络请求,会导致启动时间相对较慢。所以作者选择同 webpack 一样方式,打包,但是使用了 Turbo 构建引擎,一个增量记忆化框架,永远不会重复相同的工作。

Esbuild 是一个非常快速的打包工具,但它并没有做太多的缓存,也没有 HMR(热更新),所以在开发环境下不适用。

你好,Next.js 13

theme: vuepress highlight: monokai文章为稀土掘金技术社区首发签约文章,14 天内禁止转载,14 天后未获授权禁止转载,侵权必究!前言上周发布了 Next.js 的一个...

高通芯片击败英伟达-AI芯片在能效竞争领域迎来新的变革

高通芯片击败英伟达-AI芯片在能效竞争领域迎来新的变革

  在周三公布的一组新的测试数据中,高通公司的AI芯片以 2 比 1 打败了英伟达。  据悉,高通公司推出了一款名为Cloud AI 100的专为云端和边际端供给高性能、低功...

人工智能技术:探索未来的科技进步之路

人工智能技术:探索未来的科技进步之路

  在当今快速发展的科技时代,人工智能技术成为了引领未来的重要力量。人工智能技术的发展不仅仅影响着科学研究和工业生产领域,也改变着我们生活的每一个方面。无论是医疗保健、交通运...

发表评论    

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。