From a9074aca3046899466071d9fc124d0196b5a69ed Mon Sep 17 00:00:00 2001 From: xuejiahao Date: Fri, 17 Oct 2025 14:34:31 +0800 Subject: [PATCH] fix --- README.md | 297 ++++++++++++++++++++++----- src/components/basic/PluginInput.vue | 4 +- src/i18n/index.ts | 3 +- src/i18n/lang/en.ts | 1 + src/i18n/lang/ja.ts | 1 + src/js/desktop.ts | 6 +- src/js/mobile.ts | 6 +- vite.config.ts | 2 +- vite.desktop.config.ts | 12 +- vite.mobile.config.ts | 12 +- 10 files changed, 290 insertions(+), 54 deletions(-) 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 目录 },