之前已经完成了使用本地的 Storage 存储信息。
但是Storage存在一个问题,如果用户删除了小程序,那么之前存储的信息也就不复存在了。

使用云函数

创建文件夹 cloudfunctions\

修改
project.config.json 添加

    "cloudfunctionRoot": "cloudfunctions/",

在小程序编辑器中右键单击 cloudfunctions=>新建Node.js 云函数
image.png
创建rouder 函数

修改cloudfunctionsrouterpackage.json 添加需要的插件

{
  "name": "index",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "",
  "license": "ISC",
  "dependencies": {
    "wx-server-sdk": "~2.1.2",
    "tcb-router": "^1.1.2"
  }
}

修改 cloudfunctionsrouterindex.js

// 云函数入口文件 cloudfunctions\router\index.js
// 微信sdk
const cloud = require('wx-server-sdk');
// 上古项目 给小程序云函数加个路由
const TcbRouter = require('tcb-router');
// 登录方法
const login = require('./controller/login');
// 保存用户信息方法
const saveUserInfo = require('./controller/saveUserInfo');
// 日志中间件
const log = require('./unit/log');
cloud.init();

// 云函数入口函数
exports.main = async (event, context) => {
  const app = new TcbRouter({ event });
  // app.use 表示该中间件会适用于所有的路由
  app.use(log);
  // 登录路由
  app.router('login', login);
  // 保存用户信息
  app.router('saveUserInfo', saveUserInfo);
  return app.serve();
};

新建 unit 下文件

// cloudfunctions\router\unit\db.js
const cloud = require('wx-server-sdk');
cloud.init();
const db = cloud.database();

/**
 * 连接数据库 如果没有则创建
 * @param {string} collect 集合名称(表明)
 */
const connect = async collect => {
  return new Promise(async (resolve, reject) => {
    let _db;
    try {
      await db.createCollection(collect);
      _db = await db.collection(collect);
    } catch (error) {
      console.log(collect, '已存在');
    }
    _db = await db.collection(collect).add({ data: { msg: 'creat OK' } });
    resolve(_db);
  });
};

/**
 * 添加数据
 * @param {string} collect 需要更新的集合名称
 * @param {object} data 存储的数据
 */
const add = async ({ collect, data }) => {
  try {
    await db.createCollection(collect);
  } catch (error) {
    console.log(collect, '已存在');
  }
  data.createTime = db.serverDate();
  data.updataTime = db.serverDate();
  let res = await db.collection(collect).add({ data });
  return res;
};

/**
 * 查找数据
 * @param {string} collect 需要更新的集合名称
 * @param {object} filter 过滤条件
 */
const orderBy = async ({
  collect,
  orderKey = 'updataTime',
  order = 'desc',
  field
}) => {
  try {
    await db.createCollection(collect);
  } catch (error) {
    console.log(collect, '已存在');
  }
  let res = await db
    .collection(collect)
    .orderBy(orderKey, order)
    .field(field)
    .get();
  return res;
};
/**
 * 查找数据
 * @param {string} collect 需要更新的集合名称
 * @param {object} filter 过滤条件
 */
const find = async ({ collect, filter, field }) => {
  try {
    await db.createCollection(collect);
  } catch (error) {
    console.log(collect, '已存在');
  }
  let res = await db
    .collection(collect)
    .where(filter)
    .field(field)
    .get();
  return res;
};

/**
 * 更新数据,如果没有则创建
 * @param {string} collect 需要更新的集合名称
 * @param {object} filter 过滤条件
 * @param {object} data 新数据
 */
const update = async ({ collect, filter, data }) => {
  try {
    await db.createCollection(collect);
  } catch (error) {
    console.log(collect, '已存在');
  }
  data.updataTime = db.serverDate();
  let res = await db
    .collection(collect)
    .where(filter)
    .get();
  if (res.data.length) {
    res = await db
      .collection(collect)
      .where(filter)
      .update({
        data
      });
  } else {
    data.createTime = db.serverDate();
    res = await db.collection(collect).add({
      data
    });
  }
  return res;
};

module.exports = {
  connect,
  add,
  find,
  orderBy,
  update
};
// cloudfunctions\router\unit\log.js
const cloud = require('wx-server-sdk');
const log = async (ctx, next) => {
  ctx.data = {};
  ctx.body = {
    code: 200
  };
  ctx.wxContext = cloud.getWXContext();
  // 请求的url
  const url = ctx._req.url;
  // 启动处理时间
  const start = new Date();
  console.log(`${start} =>[${url}]`);
  await next();
  // 结速处理时间
  const endT = new Date();
  const ms = endT - start;
  // 输出日志 ctx.method 请求方式 ctx.url 请求地址
  console.log(`${endT} <=[${url}] [${ms}ms] \n`);
};

module.exports = log;

新建 controller

// cloudfunctions\router\controller\login.js
const { find } = require('../unit/db');

const login = async (ctx, next) => {
  let res = await find({
    collect: 'userInfo',
    filter: {
      OPENID: ctx.wxContext.OPENID
    },
    field: {
      _id: false,
      country: true,
      province: true,
      city: true,
      gender: true,
      language: true,
      avatarUrl: true,
      nickName: true
    }
  });
  if (res.data[0]) {
    ctx.body.data = res.data[0];
  }
  await next(); // 执行下一中间件
};
module.exports = login;
// cloudfunctions\router\controller\login.js
const { update } = require('../unit/db');

const saveUserInfo = async (ctx, next) => {
  let userInfo = Object.assign({}, ctx.wxContext, ctx._req.event.data);
  let res = await update({
    collect: 'userInfo',
    data: userInfo,
    filter: {
      OPENID: ctx.wxContext.OPENID
    }
  });
  ctx.body.data = res;
  await next(); // 执行下一中间件
};
module.exports = saveUserInfo;

编辑完成之后
上传云函数
image.png
可以执行下测试以验证云函数是没有问题~

然后云函数添加完成

在小程序端调用云函数

首先 在 app.tsx 中添加

// 初始化云函数
Taro.cloud.init();

修改 srcstoreuserInfo.ts

// src\store\userInfo.ts
// 引入observable;
import { observable } from 'mobx';
import { getStorageSync, cloud } from '@tarojs/taro';

const userInfoStore = observable({
  // 存储用户基本信息的对象
  userInfo: {},
  // 写入信息的方法
  saveInfo(userInfo: userinfo) {
    if (this!.userInfo) {
      this.userInfo = Object.assign({}, this.userInfo, userInfo);
      cloud.callFunction({
        name: 'router',
        data: {
          $url: 'saveUserInfo',
          data: this.userInfo
        }
      });
    }
  },
  // 从本地读取用户信息
  readInfo() {
    const userInfo = getStorageSync('userInfo');
    this.userInfo = Object.assign({}, this.userInfo, userInfo);
  },
  getCloudInfo() {
    cloud
      .callFunction({
        name: 'router',
        data: {
          $url: 'login'
        }
      })
      .then((res: any) => {
        console.log({ res });
        this.userInfo = res.result.data || {};
      });
  }
});
export default userInfoStore;

然后修改 src\pages\index\index.tsx

import { ComponentType } from 'react';
import Taro, { Component, Config } from '@tarojs/taro';
import { View, Button } from '@tarojs/components';
import { AtAvatar } from 'taro-ui';

// 引入mobx的修饰器
import { observer, inject } from '@tarojs/mobx';
import './index.scss';

// 编辑 src\pages\index\index.tsx 下的props接口类型
type PageStateProps = {
  // 添加 userInfoStore
  userInfoStore: {
    userInfo: userinfo;
    saveInfo: Function;
    getCloudInfo: Function;
  };
};

interface Index {
  props: PageStateProps;
}

// 注入 userInfoStore
@inject('userInfoStore')
@observer
class Index extends Component {
  config: Config = {
    navigationBarTitleText: '首页'
  };

  /**
   * @description: 获取用户信息
   * @param {Object} detail onGetUserInfo 所返回的用户基本信息
   * @return null
   */
  getUserInfo({ detail }) {
    const { userInfoStore } = this.props;
    userInfoStore.saveInfo(detail.userInfo);
  }

  // 添加 didshow钩子,在每次页面显示的时候执行
  componentDidShow() {
    const { userInfoStore } = this.props;
    // 在页面显示的时候读取用户信息
    userInfoStore.getCloudInfo();
  }
  render() {
    const { userInfo } = this.props.userInfoStore;
    return (
      <View className='index'>
        {/* button使用 getUserInfo 可以在小程序中获取用户基本信息 */}
        <Button
          openType='getUserInfo'
          onGetUserInfo={this.getUserInfo.bind(this)}
          className='index-avatarUrl-btn nobtn-style'
        >
          <View className='avatar-box'>
            <AtAvatar
              image={userInfo.avatarUrl}
              size='large'
              circle
              text={userInfo.avatarUrl ? '' : '空'}
            ></AtAvatar>
          </View>

          <View className='nickName-box'>
            {userInfo.nickName || '点击登录'}
          </View>
        </Button>
      </View>
    );
  }
}

export default Index as ComponentType;

这样,在点击用户授权头像之后,获取到的信息会存储在userInfo库中。
每次启动的时候,会从userInfo读取当前用户的信息

git地址


momokara
9 声望0 粉丝

屌丝小厂咸鱼程序狗