kintone微信小程序SDK使用实例

cybozu发表于:2019年08月30日 14:50:33更新于:2023年03月10日 16:39:58

Index

介绍

大家在做移动端应用开发的时候都会不满足于APP客户端,小程序的应用也越来越广泛了。

现在我们开发了一套kintone在微信小程序上的SDK。基于这个SDK大家就可以做适用于自己的微信小程序了。

SDK做了些什么

这里不得不提到kintone的JS Client (@kintone/rest-api-client),既可以支持Commonjs规范服务端nodejs开发,也可以支持AMD规范的浏览器端的js开发。

此微信小程序SDK就是基于kintone的JS Client (@kintone/rest-api-client)改造而得。使用过JS Client (@kintone/rest-api-client)的开发者相信很快就能上手。

这里面已经封装好了kintone的大部分REST-API,包括上传下载文件,并调用了wx.request,wx.uploadFile,wx.downloadFile来发送请求到kintone。

  callWxAPI(requestConfig) {
    switch (requestConfig.fileMethod) {
      case 'download': {
        return wx.downloadFile(requestConfig);
      }
      case 'upload': {
        return wx.uploadFile(requestConfig);
      }
      case 'read':
        return wx.getFileSystemManager().readFileSync(requestConfig.tempFilePath, 'utf8');
      default: {
        return wx.request(requestConfig);
      }
    }
  }

  wxSendRequest(requestConfig) {
    // Execute request
    return new Promise((resolve, reject) => {
      requestConfig.fail = err => {
        reject(err);
      };

      switch (requestConfig.fileMethod) {
        case 'download': {
          requestConfig.success = res => {
            if (res.statusCode === 200) {
              resolve({tempFilePath: res.tempFilePath});
            } else {
              reject({
                ...res,
                data: JSON.parse(this.callWxAPI({fileMethod: 'read', tempFilePath: res.tempFilePath}))
              });
            }
          };
          break;
        }
        case 'upload': {
          requestConfig.success = res => {
            if (res.statusCode === 200) {
              resolve(JSON.parse(res.data));
            } else {
              reject({...res, data: JSON.parse(res.data)});
            }
          };
          break;
        }
        default: {
          requestConfig.success = res => {
            if (res.statusCode === 200) {
              resolve(res.data);
            } else {
              reject(res);
            }
          };
        }
      }

      this.callWxAPI(requestConfig);
    });
  }


范例

以下是利用这个SDK做的库存管理的微信小程序的范例。在手机端添加数据后,小程序和kintone的PC端都得到了同步更新。

0015d6e2f79b38816d7727610ad875a

部署

Step 1

首先,需要下载好微信开发者工具,并且创建一个JavaScript项目

0015d804d62a82e8022cae21b7ea6a8

微信开发者工具

Step 2

通过npm导入@kintone/rest-api-client-wechat-mp库。

cd your-project-directory 
npm init 
npm install @kintone/rest-api-client-wechat-mp

Step 3

启用增强编译和 使用npm模块 选项来支持async等。
00160235857b88b1b2ffec86a54aaa0


选择 “工具” => “构建npm” 来让微信小程序支持npm。

0015d804310d85056091ea4c9b6dc9b

部署完成了。以下是商品列表的演示画面:

0015d720b7e5deb67e78578991f248a

代码解析

库存管理

在库存管理应用里实现了

  • 商品列表

  • 商品入库

  • 商品添加

  • 商品出库

  • 商品检索

这几个基本的演示功能。

目录结构

以下是此商品库存管理的微信小程序的目录结构:
001602358bfeeb4c50d655fd85873ad

其中:

  • common:

    放置静态资源和公用的函数。

    kintoneConfig.js定义了kintone的配置信息,kintone的字段代码等。

    utility.js定义了一些公用的kintone的连接函数、数据初始化、数据校验等函数。

  • miniprogram_npm:

    微信小程序自动编译的npm第三方库。

  • pages:

    库存管理具体的代码及页面。

  • components:

    检索页面的部件。

添加商品代码

以下是以具体添加商品作为范例来说明SDK的使用方法。

首先了解一下添加商品功能的页面的目录结构。

0015d6e0259d85306ab72481735bd86

  • add.js:逻辑层

    写具体的添加商品的逻辑代码。

    通过page构造器注册页面

    data:初始化数据

    onLoad:在页面初始化的时调用uploadFile函数,自动执行文件上传的API并获取file key。

    还有其他一些formInputChange、formDateChange等函数与前端add.wxml进行数据绑定,

    最后通过在函数submitForm里通过添加记录的API来将数据添加到kintone。

  • add.wxml:视图层

    这是页面模板的页,构建出页面的结构。

    这里选择日期,上传图片,提交表单,数据校验这些都是通过微信的WEUI组件库来实现的。他能带给用户类似于原生视觉体验的UI。

  • add.json:配置

    可以写调用的WEUI组件的信息,小程序的页面路径、界面表现、网络超时时间、底部 tab 等

  • add.wxss:样式

    该页面的样式信息

以下是add.js的代码范例:

const kintoneConfig = require('../../common/kintoneConfig');
const utility = require('../../common/utility');
Page({
  /**
   * 页面的初始数据
   */
  data: {
    warehouses: ["上海A", "上海B", "苏州", "无锡"],
    warehouseIndex: 0,
    warehousePositions: ["1-1", "1-2", "2-1", "2-2"],
    warehousePositionIndex: 0,
    inOutDate: `${utility.formatDate(new Date())}`,
    formData: {
      inOutDate: `${utility.formatDate(new Date())}`,
    },
    rules: [
      {
        name: 'inOutDate',
        rules: [{required: true, message: '日期必填'}],
      },
      { // 多个规则
        name: 'inOutAmount',
        rules: [{required: true, message: '数量必填'}, {
          validator: (rule, value, param, models) => {
            var regPos = /^\d+$/; // 非负整数
            if (!regPos.test(value)) {
              return rule.message;
            }
          },
          message: '数量格式不对',
          valid: true,
        }],
      },
      {
        name: 'commodityName',
        rules: [{required: true, message: '商品名称必填'}]
      },
    ],
    commodityNameTitle: kintoneConfig.field.commodityName.name,
    commodityNumberTitle: kintoneConfig.field.commodityNumber.name,
    inOutDateTitle: kintoneConfig.field.inOutDate.name.in,
    inOutAmountTitle: kintoneConfig.field.inOutAmount.name.in,
    unitTitle: kintoneConfig.field.unit.name,
    inOutNoteTitle: kintoneConfig.field.inOutNote.name,
    warehouseTitle: kintoneConfig.field.warehouse.name,
    warehousePositionTitle: kintoneConfig.field.warehousePosition.name,
    commoditySizeTitle: kintoneConfig.field.commoditySize.name,
    commodityPriceTitle: kintoneConfig.field.commodityPrice.name,
    imageTitle: kintoneConfig.field.image.name,
  },
  onLoad() {
    this.setData({
      uploadFile: this.uploadFile.bind(this)
    });
  },
  formDateChange: function(e) {
    this.setData({
      inOutDate: e.detail.value,
    });
    this.formInputChange(e);
  },
  formInputChange: function(e) {
    const {field} = e.currentTarget.dataset;
    this.setData({
      [`formData.${field}`]: e.detail.value
    });
  },
  warehouseChange: function(e) {
    this.setData({
      warehouseIndex: e.detail.value,
    });
  },
  warehousePositionChange: function(e) {
    this.setData({
      warehousePositionIndex: e.detail.value
    });
  },
  fileKey: '',
  uploadFile: function(files) {
    console.log('upload files', files);
    const kintoneFile = utility.kintoneFileModule();
    return kintoneFile.upload({filePath: files.tempFilePaths[0]}).then(rsp => {
      this.fileKey = rsp.fileKey;
      return {urls: files.tempFilePaths};
    }).catch(e => {
      console.log(e.get());
    });
  },
  deleteFile: function() {
    this.fileKey = '';
  },
  submitForm: function() {
    this.selectComponent('#form').validate((valid, errors) => {
      console.log('valid', valid, errors);
      if (!valid) {
        const firstError = Object.keys(errors);
        if (firstError.length) {
          this.setData({
            error: errors[firstError[0]].message
          });
        }
      } else {
        const kintoneRecord = utility.kintoneRecordModule();
        const record = {};
        record[kintoneConfig.field.commodityName.code] = {value: this.data.formData.commodityName};
        record[kintoneConfig.field.commodityNumber.code] = {value: this.data.formData.commodityNumber};
        record[kintoneConfig.field.warehouse.code] = {value: this.data.warehouses[this.data.warehouseIndex]};
        record[kintoneConfig.field.warehousePosition.code] = {value: this.data.warehousePositions[this.data.warehousePositionIndex]};
        record[kintoneConfig.field.commoditySize.code] = {value: this.data.formData.commoditySize};
        record[kintoneConfig.field.commodityPrice.code] = {value: this.data.formData.commodityPrice};
        record[kintoneConfig.field.unit.code] = {value: this.data.formData.unit};
        if (this.fileKey.length > 0) {
          record[kintoneConfig.field.image.code] = {value: [{fileKey: this.fileKey}]};
        }
        const value = {};
        value[kintoneConfig.field.inOutDate.code] = {value: this.data.formData.inOutDate};
        value[kintoneConfig.field.inOutAmount.code] = {value: parseInt(this.data.formData.inOutAmount)};
        value[kintoneConfig.field.inOutNote.code] = {value: this.data.formData.inOutNote};
        record[kintoneConfig.field.inOutTable.code] = {value: [{value: value}]};
        kintoneRecord.addRecord({app: kintoneConfig.appId, record: record}).then(rsp => {
          wx.redirectTo({url: `../commodity/detail?id=${rsp.id}`});
        }).catch(e => {
          console.log(e.get());
        });
      }
    });
  },
});


资源列表

SDK源码和文档:https://cybozudev.kf5.com/hc/kb/article/1307637

demo源码:https://github.com/kintone-samples/SAMPLE-rest-api-client-wechat-mp-CN

总结

好了,小程序的SDK和范例就介绍到这里,希望能给大家在开发kintone的微信小程序的时候带来帮助,如果有什么疑问或者建议,可以在下面留言哦。

 注意事项

  • 本示例代码不保证其运行。

  • 我们不为本示例代码提供技术支持。