一键导入远程办公应用

cybozu发表于:2020年02月17日 16:25:47更新于:2020年02月21日 11:21:29

Index

前言

最近新冠肺炎的疫情严重影响了我们的工作和生活。

而我们也想通过自己的努力,让现阶段远程办公这件事变得可行起来。

我们做了一个小小的开发,可以让用户在kintone的门户首页导入一些远程办公的应用。

下面我们就来教大家如何通过自定义首页来做一个我们的应用商店。

这里我们利用到了上一期给大家介绍的一款工具“Kintone Portal Designer”来自定义首页,今天我们就拿他来练练手吧。

公用的库

下面是我们要用到的库:

kintone JS SDK

jQuery

kintone UI Component

※ 这里不对这几个库做具体介绍,如果还不熟悉它们,请先参阅相关文档。

自定义开发

原理

通过应用的json数据,再调用应用的创建和设置的更改下面一系列的REST API,来导入应用。

这里想通过这个实例来教大家如何做这种应用的创建、同步、备份等。

将以下HTML、CSS、JavaScript分别贴到“Kintone Portal Designer” 这个工具里面的HTML、CSS、JavaScript这三个标签里。

0015e4b9590b4c05f496868f0e1648c

HTML:

<div class="app-import-tips">
  <div class="app-import-tips-header app-import-tips-header-icon">
    <h3 class="app-import-tips-title">APP导入</h3>
  </div>
  <div class="app-import-tips-items">
    <ul class="app-import-tips-items-ul">
      <li>
        <span class="app-import-tips-item-icon">
          <img src="https://static.cybozu.cn/contents/k/image/icon/app/appTableBlue.png" width="46" height="46">
         </span>
        <span class="app-import-tips-item-name">公告栏</span>
        <div class="app-import-tips-item-install">
          <a class="app-import-tips-item-install-link" app-import="895">添加此应用</a>
        </div>
      </li>
      <li>
        <span class="app-import-tips-item-icon">
          <img src="https://static.cybozu.cn/contents/k/image/icon/app/binder.png" width="46" height="46">
        </span>
        <span class="app-import-tips-item-name">共享文件</span>
        <div class="app-import-tips-item-install">
          <a class="app-import-tips-item-install-link" app-import="894">添加此应用</a>
        </div>
      </li> 
      <li>
        <span class="app-import-tips-item-icon">
          <img src="https://static.cybozu.cn/contents/k/image/icon/app/appTableBlue.png" width="46" height="46">
        </span>
        <span class="app-import-tips-item-name">任务管理</span>
        <div class="app-import-tips-item-install">
          <a class="app-import-tips-item-install-link" app-import="893">添加此应用</a>
        </div>
      </li> 
      <li>
        <span class="app-import-tips-item-icon">
          <img src="https://static.cybozu.cn/contents/k/image/icon/app/calendar.png" width="46" height="46">
        </span>
        <span class="app-import-tips-item-name">健康打卡</span>
        <div class="app-import-tips-item-install">
          <a class="app-import-tips-item-install-link" app-import="892">添加此应用</a>
        </div>
      </li> 
      <li>
        <span class="app-import-tips-item-icon">
          <img src="https://static.cybozu.cn/contents/k/image/icon/app/fileholder.png" width="46" height="46">
        </span>
        <span class="app-import-tips-item-name">工作日报</span>
        <div class="app-import-tips-item-install">
          <a class="app-import-tips-item-install-link" app-import="891">添加此应用</a>
        </div>
      </li> 
    </ul>
  </div>
</div>

CSS:

.app-import-tips {
  margin: 16px 16px 0px 16px;
  width: auto;
  min-width: 950px;
  background-color: #fff;
  letter-spacing: .04em;
}
.app-import-tips-header {
  height: 56px;
  line-height: 56px;
  position: relative;
  box-sizing: border-box;
  padding: 0 72px 0 80px;
  border-bottom: 1px solid #e3e7e8;
  //background-color: #fff;
  font-size: 20px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  word-wrap: normal;
}
.app-import-tips-header-icon {
  background-image: url('https://cndevdemo.oss-cn-shanghai.aliyuncs.com/images/appstore_56.png');
  background-position: left top;
  background-repeat: no-repeat;
}
.app-import-tips-title {
  display: inline;
}
.app-import-tips-items {
  padding: 0;
  user-select: none;
}
.app-import-tips-items-ul {
  margin: 0;
  padding-left: 0;
  list-style: none;
  display: flex;
  flex-flow: row nowrap;
  justify-content: center;
}
.app-import-tips-items-ul li {
  display: inline-block;
  background-color: #fff;
  margin: 0 1% 2px 0;
  width: 15%;
  padding: 16px;
}
.app-import-tips-item-icon {
  position: absolute;
  padding-top: 4px;
  width: 46px;
  height: 46px;
}
.app-import-tips-item-name {
  font-size: 18px;
  display: block;
  padding-left: 60px;
  color: #000;
}
.app-import-tips-item-provider {
  font-size: 12px;
  line-height: 1.2;
  padding-left: 60px;
}
.app-import-tips-item-install {
  padding-left: 60px;
}
.app-import-tips-item-install-link {
  font-size: 12px;
  cursor: pointer;
  position: relative;
}

JavaScripts:

(function () {
    'use strict';
    var spinner = new kintoneUIComponent.Spinner();
    var body = document.getElementsByTagName("BODY")[0];
    body.appendChild(spinner.render());
    var ExtraTypes = {
        "formFields": ["STATUS", "RECORD_NUMBER", "CREATOR", "CATEGORY", "STATUS_ASSIGNEE", "UPDATED_TIME", "MODIFIER", "CREATED_TIME"],
        "record": ["STATUS", "CATEGORY", "STATUS_ASSIGNEE", "CALC"]
    };
    jQuery("[app-import]").each(function (index, ele) {
        var appid = $(this).attr("app-import");
        $(this).click(downloadApp(appid));
    });
    function downloadApp(appid) {
        return function (e) {
            spinner.show();
            getAppInfo(appid).then(importApp);
        }
    }
    function importApp(appinfo) {
        if (appinfo === false) {
            spinner.hide();
            alert("该应用不存在");
            return;
        }
        var kintoneApp = new kintoneJSSDK.App();
        var appName = appinfo.name;
        var generalSettings = appinfo.generalSettings;
        var newFormFields = generateNewFormFields(appinfo.fields);
        let appLayout = appinfo.layout;
        let appAppStatus = appinfo.appStatus;
        var app;
        return kintoneApp.addPreviewApp({ name: appName }).then(
            function (rsp) {
                app = rsp.app;
                return kintoneApp.addFormFields({ app: app, fields: newFormFields }).then(r => { return rsp });
            }).then(
                function (rsp) {
                    generalSettings.app = app;
                    return kintoneApp.updateGeneralSettings(generalSettings).then(r => { return rsp });
                }
            ).then(
                function (rsp) {
                    return kintoneApp.updateFormLayout({ app: app, layout: appLayout }).then(r => { return rsp });
                }
            ).then(rsp => {
                delete rsp.revision;
                const apps = [
                    rsp
                ];
                const revert = false;
                kintoneApp.deployAppSettings({ apps: apps, revert: revert });
                setTimeout(() => {
                    spinner.hide();
                    window.location.reload();
                }, 3000);
            });
    }
    function generateNewFormFields(fields) {
        for (let fieldName in fields) {
            let type = fields[fieldName].type;
            if (isInArray(type, ExtraTypes.formFields)) {
                delete fields[fieldName];
            }
        }
        return fields;
    }
    function isInArray(search, array) {
        for (let i in array) {
            if (array[i] == search) {
                return true;
            }
        }
        return false;
    }
    function getAppInfo(appid) {
        return kintone.proxy('http://106.14.193.23/getappinfo?appid=' + appid, 'GET', {}, {}).then(function (args) {
            if (args[0] == '') {
                return false;
            }
            else {
                return JSON.parse(args[0]);
            }
        }, function (error) {
            console.log(error);
        });
    }
}());

打包导出

最后我们用这个工具的Export as JavaScript(Desktop)功能来打包我们的代码。这样我们开发的这三段代码就会打包成一个JS文件。(这里我们命名为desktop.js文件)

0015e4b95e52098505dc661239e3220

代码解析

疑问1 

  • 为什么JS源码中没有绑定到portal.show 的事件上但是会在首页加载时执行?

    因为这里用“Kintone Portal Designer”这个工具导出时,他会自动将这段代码绑定到portal.show 这个事件上。

    看下源码

    0015e4b8a033ccfb8ed50a622c722e5

疑问2

  • JS源码中"getAppInfo"函数是从服务器上获取的模板JSON,可以自己写吗?

    可以自己通过API获取相关需要同步或者备份的应用信息来作为模板数据,来进行新应用的创建。

    这里我们已经将应用的模板放在了我们的服务器上,因为这个服务器是临时搭建的,这个模板的JSON文件我们这里也可以提供大家下载。如果这个服务器上无法获取到这个模板JSON,大家可以直接用以下的JSON数据来代替:appinfo.json

导入

最后我们生成的desktop.js导入到门户的 “kintone系统管理” => “通过JavaScript / CSS自定义” 中:

(用到的jQuery,kintone UI Component,kintone JS SDK这几个类库还是需要在这段JS之前加载下。)

0015e4b8b30ef1f00880c96797155b5

效果

0015e4b8b8499b3795154902bab064f

点击添加此应用就能下载到自己kintone环境中了。

其他

权限

下面是一些权限相关的配置,大家可以按照实际需求来配置:

0015e4b9b0827a12f502d8a929db413

0015e4b9b08322e139159cc42430d44

插件

这里我们还提供了 "顶" 插件来丰富 "工作报告" 这个应用,大家可以去下载。

下载:SAMPLE_like_plugin_v1.7.0.zip

文档:顶!插件

注意事项

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

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