# kintone-vue-template 使用 Vue 、ts 和 Vite 创建 kintone plugin 的初始化模板,先由 [create-plugin](https://cybozu.dev/ja/kintone/sdk/development-environment/create-plugin/) 生成之后再手动引入 Vue。 并且提供了 [License 检查](#license-检查) 的功能。 > プラグイン開発手順:https://cybozu.dev/ja/kintone/tips/development/plugins/development-plugin/ 包括了以下 kintone 库: - [kintone-ui-component (v1.22.0)](https://cybozu.dev/ja/kintone/sdk/library/kintone-ui-component-v1/)([文档](https://ui-component.kintone.dev/ja/)) - [@cybozu/eslint-config](https://cybozu.dev/ja/kintone/sdk/development-environment/eslint-config/) - [@kintone/rest-api-client](https://cybozu.dev/ja/kintone/sdk/rest-api-client/kintone-javascript-client/)([文档](https://github.com/kintone/js-sdk/tree/main/packages/rest-api-client)) - [kintone/plugin-packer](https://cybozu.dev/ja/kintone/sdk/development-environment/plugin-packer/) - [@kintone/plugin-uploader](https://cybozu.dev/ja/kintone/sdk/development-environment/plugin-uploader/) - [@kintone/dts-gen](https://cybozu.dev/ja/kintone/sdk/library/dts-gen/) # 使用步骤 首先进行安装 ```bash npm install # 或 yarn ``` 随后需要修改项目信息: 1. `package.json` ```diff { + "name": "项目名", - "name": "kintone-vue-template", "private": true, + "version": "版本号", - "version": "0.0.0", "type": "module", "scripts": { "vite:build": "vite build", "build": "vite build && npm run pkg", "build-upload": "npm run build && npm run upload", "pkg": "kintone-plugin-packer --ppk private.ppk --out dist/plugin.zip dist/src", + "upload": "修改 kintone 域名、用户名和密码" - "upload": "kintone-plugin-uploader --base-url https://alicorn.cybozu.com --username maxz --password 7ld7i8vd dist/plugin.zip " }, ... ``` 2. `src/manifest.json` ```diff { ... + "icon": "icon 路径", - "icon": "image/icon.png", "config": { ... + "required_params": [ "/config 页面必填的参数" ] - "required_params": [ "buttonName" ] }, + "name": "项目名", - "name": { - "en": "kintone Vue template", - "ja": "kintone Vue テンプレート" - }, + "description": "项目描述", - "description": { - "en": "kintone Vue template for creating plugin", - "ja": "kintoneプラグイン作成用 Vue テンプレート" - }, + "description": "项目网站", - "homepage_url": { - "en": "https://www.alicorns.co.jp/", - "ja": "https://www.alicorns.co.jp/" - }, ... } ``` 3. 如果需要使用 License 检查,请参考: [License 检查](#license-检查) 需要修改 `src/config.json`: ```diff { "license": { "enabled": true, // 是否开启 License 检查 "api": { "checkUrl": "https://kintone.alicorns.co.jp/api/license/check", // server 路径,一般不需要修改 + "pluginKey": 插件的 id,需要和后端数据库中保持一致 - "pluginKey": "kintone-vue-template" }, "purchase": { + "url": 购买页面打开的链接 - "url": "https://alisurvey.alicorns.co.jp/s/Iuc5RxZv", "formIds": { + "name": 表单中存储申请人的名字的 field id, 会设置为 kintone 的登陆用户名,为空就跳过 - "name": "input1761283314263", + "email": 表单中存储申请人 email 的 field id, 会设置为 kintone 的登陆邮箱,为空就跳过 - "email": "input1761283275767", + "domain": 表单中存储用户 url domain 的 field id, 会设置为 url - "domain": "input1761283180784", + "pluginId": 表单中存储用户 plugin id 的 field id, 会设置为 plugin id - "pluginId": "input1761283200616" } }, "warningDaysBeforeExpiry": 7 // 进行提醒的剩余天数 } } ``` # 编译流程 - **build** - `build` 会生成 `dist` 文件夹,以及 `plugin.zip` 文件 > 如果只需要 `dist` 文件夹,可以执行 `vite:build` ```bash npm run build # 或 yarn build # 仅生成 `dist` 文件夹 npm run vite:build # 或 yarn vite:build ``` - **build:prod** - `build:prod` 也是生成 `plugin.zip` 文件,但是会进行压缩和混淆,并且没有 sourceMap,在发布的时候使用 ```bash npm run build:prod # 或 yarn build:prod ``` - **upload** - `upload` 会将 `plugin.zip` 上传到 Kintone plugin ```bash npm run upload # 或 yarn upload ``` - **build-upload** - `build-upload` 会顺序执行上面两步 ```bash npm run build-upload # 或 yarn build-upload ``` # 开发说明 当前模板中已经有一个案例,可以参考并且修改。 1. 对于 Config 页面,请修改 `components/Config.vue` 2. 对于 PC 的 App 页面,请修改 `js/desktop.ts` 3. 对于 Mobile 的 App 页面,请修改 `js/mobile.ts` 这三个文件是强制指定的,请不要修改。 ## 项目结构 ```shell ├── src │ ├── components # config 页面 │ │ ├── basic │ │ │ ├── PluginInput.vue │ │ │ └── PluginLabel.vue │ │ └── Config.vue # config 页面入口 │ ├── css │ │ ├── 51-modern-default.css # config 页面额外引用的样式 css │ │ ├── config.css # config 页面引用的 css │ │ ├── desktop.css # desktop app 页面引用的 css │ │ └── mobile.css # mobile app 页面引用的 css │ ├── i18n # i18n 语言包相关 │ │ ├── lang │ │ │ ├── en.ts │ │ │ └── ja.ts │ │ └── index.ts │ ├── js │ │ ├── desktop.ts # desktop app 页面入口 │ │ └── mobile.ts # mobile app 页面入口 │ ├── types │ │ ├── index.d.ts │ │ ├── model.d.ts │ │ └── my-kintone.d.ts # kintone 相关的 ts 类型 │ ├── main.ts │ └── manifest.json # kintone plugin 需要的配置 ├── .eslintrc.js ├── .gitignore ├── .prettierrc ├── components.d.ts # vue 中自动 import,build 的时候生成 ├── env.d.ts # vue 类型定义 ├── index.html ├── package.json ├── private.ppk # 当前 plugin 密钥,首次 build 自动生成 ├── README.md ├── rsa_private.pem # license 验证密钥 ├── rsa_public.pem # license 公钥,需要被添加到密钥检查的后端系统中 ├── tsconfig.json └── vite.config.ts # 主要的 vite 配置 └── vite.iife.config.ts # 用于打包 desktop/mobile 文件的配置 ``` ## 关于 Config 页面开发 只有 **Config 页面** 的开发可以使用 Vue Template,其他页面请使用 `js` 文件。 基本上和 Vue 开发没有区别,但是有以下一些限制: 1. CSS 样式只能使用 `css` 文件 2. [`kintone-ui-component` 库有一些限制](#对于-kintone-ui-component-库的限制) ## 关于 desktop/mobile 的 app 页面开发 desktop/mobile 的 js 会被 `vite` 使用 `lib` 模式打包,从而将所有 import 合并到同一个文件里面。 ## 关于 CSS 开发 > 暂时不支持在 Vue Template 中创建 css,**只能在 `css` 文件夹下新建 css 文件** `/css` 目录下分别对应了不同环境的 css 样式 - `config.css` - config 页面引用的 css - `desktop.css` - desktop app 页面引用的 css - `mobile.css` - mobile app 页面引用的 css 另外,在 `config` 页面引入了 `51-modern-default.css`,里面存放了 kintone 的一些样式 - 如果不需要使用就在 `manifest.json` 中删除 ```diff "config": { "html": "html/config.html", "js": [ "js/config.js" ], "css": [ - "css/51-modern-default.css", "css/config.css" ], "required_params": [ "buttonName" ] }, ``` ## 关于 KintoneRestAPIClient 在 desktop/mobile,直接使用: ```ts import client from '@/plugins/kintoneClient.ts' client.app... ``` 在 vue 中使用 useKintoneClient(): ```vue import { useKintoneClient } from '@/composables/useKintoneClient'; const client = useKintoneClient();// KintoneRestAPIClient client.app... ``` ## 关于 i18n 在 desktop/mobile: ```ts import i18n from '@/i18n'; const { t } = i18n.global; console.log(t('config.button.label')); ``` 在 vue: ```vue ``` ### 封装组件的问题 当为了解决 v-model 的问题,可能会需要封装组件。我们会使用 `v-bind` 来避免手动来加 kuc 组件的所有属性。(参考 `/src/components/basic/PluginInput.vue` ) ```vue ``` 但是有的 `boolean` 类型的属性,会被默认设置为 `false`,导致问题 - 比如 `visible: false` 就看不到组件了 所以需要手动将这些 `boolean` 属性设置为 `undefined` ```ts const props = withDefaults(defineProps(), { // 布尔值的默认值处理,设置为 undefined 表示未定义,否则默认会是 false disabled: undefined, requiredIcon: undefined, visible: undefined, }); const textProps = computed(() => { const baseProps = { ...props, className: "kuc-text-input " + ${props.className}, // 添加基础样式类 }; // 移除值为 undefined 的属性,确保只传递有效属性 return Object.fromEntries(Object.entries(baseProps).filter(([_, value]) => value !== undefined)) as TextProps; }); ``` ### 关于 spinner 使用 spinner 的时候,如果想要限制在某一个组件上(`:container` 属性),直接使用是不行的,它只会加在 `document.body` 上 不知道为啥,当它创建的时候不会用到 `:container` 参数,即使 HTMLNode 是可见的 所以可以使用 `v-show` 先让它隐藏 > 理论上来说,spinner 使用 new kucs.spinner() 创建更符合习惯,但是我不太想引入 `kuc.min.js` 文件…… ```vue ``` ### 关于 tooltip kuc 没有实现插槽,所以应该当成一个普通组件使用: ```vue ``` --- ## License 检查 目前 License 的检查使用的是后端传一个 RSA 密钥加密的 JWT,前端使用公钥验证是否被修改过,并且保存在 Localstorage 中。 每隔一天都会从后端重新获取新的 License 信息。 默认试用是 30 天,还剩 7 天的时候会进行提醒。(在 `license-service.ts` 中修改) 当点击购买的时候,会跳转到一个外部网站,这里可以使用 AliSurvey 进行表单填写。 ### 创建密钥 创建密钥可以使用 openssl 命令行工具: ```sh openssl genrsa -out ./rsa_private.pem 2048 ``` 然后公钥可以放在同一个文件夹中: ```sh openssl rsa -in ./rsa_private.pem -pubout -out ./rsa_public.pem ``` > 公钥需要被放到后端系统中 ### 使用 在 desktop/mobile 中只要在所有的逻辑外部多包裹一层 `LicenseService.loadPluginIfAuthorized()` : ```ts kintone.events.on('app.record.index.show', async () => { LicenseService.loadPluginIfAuthorized(PLUGIN_ID, // <--- 内部会进行 license 判断 async () => { // 已有的逻辑代码 }, ); }); ``` 在 vue 中只要在顶部引入 ` LicenseStatus.vue`: ```vue