diff --git a/README.md b/README.md
index a48ad49..89b5c09 100644
--- a/README.md
+++ b/README.md
@@ -14,6 +14,7 @@
- [@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/)
+
# 使用步骤
首先进行安装
@@ -75,6 +76,7 @@ npm install # 或 yarn
}
```
+
# 编译流程
- `build` 会生成 `dist` 文件夹,以及 `plugin.zip` 文件
@@ -100,43 +102,9 @@ npm run upload # 或 yarn upload
npm run build-upload # 或 yarn build-upload
```
+
# 开发说明
-## 项目结构
-
-```
-├── src
-│ ├── components
-│ │ ├── basic
-│ │ │ ├── PluginInput.vue
-│ │ │ └── PluginLabel.vue
-│ │ └── Config.vue
-│ ├── css
-│ │ ├── 51-modern-default.css
-│ │ └── config.css
-│ ├── i18n
-│ │ ├── lang
-│ │ │ ├── en.ts
-│ │ │ └── ja.ts
-│ │ └── index.ts
-│ ├── js
-│ │ ├── desktop.ts
-│ │ └── mobile.ts
-│ ├── types
-│ │ ├── index.d.ts
-│ │ ├── model.d.ts
-│ │ └── my-kintone.d.ts
-│ ├── main.ts
-│ └── manifest.json
-├── README.md
-├── components.d.ts
-├── env.d.ts
-├── index.html
-├── package.json
-├── tsconfig.json
-└── vite.config.ts
-```
-
当前模板中已经有一个案例,可以参考并且修改。
1. 对于 Config 页面,请修改 `components/Config.vue`
@@ -145,20 +113,76 @@ npm run build-upload # 或 yarn build-upload
这三个文件是强制指定的,请不要修改。
-### 关于 Config 页面
+
+## 项目结构
+
+```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
+├── tsconfig.json
+└── vite.config.ts # 主要的 vite 配置
+└── vite.desktop.config.ts # 用于打包 desktop 文件的配置
+└── vite.mobile.config.ts # 用于打包 mobile 文件的配置
+```
+
+
+## 关于 Config 页面开发
只有 **Config 页面** 的开发可以使用 Vue Template,其他页面请使用 `js` 文件。
基本上和 Vue 开发没有区别,但是有以下一些限制:
1. CSS 样式只能使用 `css` 文件
-2. `kintone-ui-component` 库有一些限制
+2. [`kintone-ui-component` 库有一些限制](#对于-kintone-ui-component-库的限制)
-### 关于 CSS
+## 关于 desktop/mobile 的 app 页面开发
-1. 暂时不支持在 Vue Template 中创建,**只能在 `css` 文件夹下新建 css 文件**
-2. 目前在 `config` 页面引入了 `51-modern-default.css`,里面存放了 kintone 的一些样式
- - 如果不需要使用就在 `manifest.json` 中删除
+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",
@@ -176,14 +200,195 @@ npm run build-upload # 或 yarn build-upload
```
+## 关于 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
+
+
+
+
+
+
+
+
+```
\ No newline at end of file
diff --git a/src/components/basic/PluginInput.vue b/src/components/basic/PluginInput.vue
index 3598592..e70c66c 100644
--- a/src/components/basic/PluginInput.vue
+++ b/src/components/basic/PluginInput.vue
@@ -14,7 +14,7 @@ import { defineProps, defineEmits, computed } from 'vue';
const props = withDefaults(defineProps(), {
- // 布尔值的默认值处理,设置为 undefined 表示未定义
+ // 布尔值的默认值处理,设置为 undefined 表示未定义,否则默认会是 false
disabled: undefined,
requiredIcon: undefined,
visible: undefined,
@@ -25,7 +25,7 @@ const emit = defineEmits<{
}>();
/**
- * 计算属性:生成传递给 KUC Text 组件的属性对象
+ * 生成传递给 KUC Text 组件的属性对象
* 过滤掉未定义的属性,避免传递无效值
*/
const textProps = computed(() => {
diff --git a/src/i18n/index.ts b/src/i18n/index.ts
index d07a102..8530094 100644
--- a/src/i18n/index.ts
+++ b/src/i18n/index.ts
@@ -20,7 +20,8 @@ for (const path in modules) {
// 创建 i18n 实例配置
const i18n = createI18n({
legacy: false, // 使用 Composition API 模式
- locale: kintone.getLoginUser().language || 'ja',
+ locale: kintone.getLoginUser().language,
+ fallbackLocale: 'ja',
messages,
});
diff --git a/src/i18n/lang/en.ts b/src/i18n/lang/en.ts
index 0776d49..de3b946 100644
--- a/src/i18n/lang/en.ts
+++ b/src/i18n/lang/en.ts
@@ -1,6 +1,7 @@
// 英语语言包配置
// 包含配置页面相关的翻译文本
export default {
+ hello: "Hello! ",
config: {
title: 'kintone Vue template',
desc: 'kintone Vue template for creating plugin',
diff --git a/src/i18n/lang/ja.ts b/src/i18n/lang/ja.ts
index bab7211..311cb46 100644
--- a/src/i18n/lang/ja.ts
+++ b/src/i18n/lang/ja.ts
@@ -1,6 +1,7 @@
// 日语语言包配置
// 包含配置页面相关的翻译文本
export default {
+ hello: 'こんにちは!',
config: {
title: 'kintone Vue テンプレート',
desc: 'kintoneプラグイン作成用 Vue テンプレート',
diff --git a/src/js/desktop.ts b/src/js/desktop.ts
index 98c1894..1a97a07 100644
--- a/src/js/desktop.ts
+++ b/src/js/desktop.ts
@@ -1,3 +1,4 @@
+import i18n from '@/i18n';
import type { Setting } from '@/types';
import { KintoneRestAPIClient } from '@kintone/rest-api-client';
@@ -27,6 +28,9 @@ import { Button } from 'kintone-ui-component/lib/button';
throw new Error('このページではヘッダー要素が利用できません。');
}
+ // 测试 i18n
+ const { t } = i18n.global;
+
// 创建按钮
const button = new Button({
text: setting.buttonName,
@@ -42,7 +46,7 @@ import { Button } from 'kintone-ui-component/lib/button';
});
const pluginsInfo = plugins.map((p) => p.name).join('、');
- const message = setting.message + '\n--------\n【Plugins】 ' + pluginsInfo;
+ const message = t('hello') + "\n" + setting.message + '\n--------\n【Plugins】 ' + pluginsInfo;
alert(message);
} catch (error) {
console.error('Failed to fetch plugins:', error);
diff --git a/src/js/mobile.ts b/src/js/mobile.ts
index 3377798..5f7e20f 100644
--- a/src/js/mobile.ts
+++ b/src/js/mobile.ts
@@ -1,3 +1,4 @@
+import i18n from '@/i18n';
import type { Setting } from '@/types';
import { KintoneRestAPIClient } from '@kintone/rest-api-client';
@@ -27,6 +28,9 @@ import { MobileButton } from 'kintone-ui-component/lib/mobile/button';
throw new Error('このページではヘッダー要素が利用できません。');
}
+ // 测试 i18n
+ const { t } = i18n.global;
+
// 创建按钮
const button = new MobileButton({
text: setting.buttonName,
@@ -42,7 +46,7 @@ import { MobileButton } from 'kintone-ui-component/lib/mobile/button';
});
const pluginsInfo = plugins.map((p) => p.name).join('、');
- const message = setting.message + '\n--------\n【Plugins】 ' + pluginsInfo;
+ const message = t('hello') + "\n" + setting.message + '\n--------\n【Plugins】 ' + pluginsInfo;
alert(message);
} catch (error) {
console.error('Failed to fetch plugins:', error);
diff --git a/vite.config.ts b/vite.config.ts
index bb3291f..85d2c51 100644
--- a/vite.config.ts
+++ b/vite.config.ts
@@ -142,7 +142,7 @@ export default defineConfig({
{ src: 'src/assets/*.js', dest: 'dist/src/js' },
{ src: 'src/assets/*.png', dest: 'dist/src/image' },
{ src: 'src/css/*', dest: 'dist/src/css' },
- { src: 'node_modules/kintone-ui-component/umd/kuc.min.js', dest: 'dist/src/js' },
+ // { src: 'node_modules/kintone-ui-component/umd/kuc.min.js', dest: 'dist/src/js' },
],
hook: 'writeBundle' // 指定在何时复制文件
}),
diff --git a/vite.desktop.config.ts b/vite.desktop.config.ts
index 44f1d66..0521ea0 100644
--- a/vite.desktop.config.ts
+++ b/vite.desktop.config.ts
@@ -4,6 +4,16 @@ import * as path from 'path';
* 将桌面端 desktop.ts 文件打包为立即执行函数表达式 (IIFE) 格式
*/
export default {
+ resolve: {
+ alias: {
+ '@': path.resolve(__dirname, 'src'), // 配置 @ 别名指向 src 目录
+ },
+ },
+ define: {
+ 'process.env.NODE_ENV': JSON.stringify('production'),
+ 'process.env': JSON.stringify({}),
+ global: 'window',
+ },
build: {
lib: {
entry: path.resolve(__dirname, 'src/js/desktop.ts'),
@@ -19,7 +29,7 @@ export default {
},
},
},
- sourcemap: false,
+ sourcemap: 'inline', // 生成内联 sourcemap 用于调试,
emptyOutDir: false, // 不清空输出目录,随后拷贝到 dist 目录中之后自动删除
outDir: path.resolve(__dirname, 'dist-iife/desktop'), // 输出到 dist-iife 目录
},
diff --git a/vite.mobile.config.ts b/vite.mobile.config.ts
index ef528a2..f95bda6 100644
--- a/vite.mobile.config.ts
+++ b/vite.mobile.config.ts
@@ -4,6 +4,16 @@ import * as path from 'path';
* 将移动端 mobile.ts 文件打包为立即执行函数表达式 (IIFE) 格式
*/
export default {
+ resolve: {
+ alias: {
+ '@': path.resolve(__dirname, 'src'), // 配置 @ 别名指向 src 目录
+ },
+ },
+ define: {
+ 'process.env.NODE_ENV': JSON.stringify('production'),
+ 'process.env': JSON.stringify({}),
+ global: 'window',
+ },
build: {
lib: {
entry: path.resolve(__dirname, 'src/js/mobile.ts'),
@@ -19,7 +29,7 @@ export default {
},
},
},
- sourcemap: false,
+ sourcemap: 'inline', // 生成内联 sourcemap 用于调试,
emptyOutDir: false, // 不清空输出目录,随后拷贝到 dist 目录中之后自动删除
outDir: path.resolve(__dirname, 'dist-iife/mobile'), // 输出到 dist-iife 目录
},