Compare commits

...

3 Commits

Author SHA1 Message Date
hsueh chiahao
67afc7be3c fix 2025-10-16 21:27:27 +08:00
hsueh chiahao
ee7acb6486 fix 2025-10-16 15:49:27 +08:00
hsueh chiahao
4cba63fc16 update 2025-10-16 15:40:55 +08:00
22 changed files with 3342 additions and 8745 deletions

1
.gitignore vendored
View File

@@ -9,6 +9,7 @@ lerna-debug.log*
node_modules
dist
dist-iife
dist-ssr
*.local

View File

@@ -1,5 +1,5 @@
# data-fetch-plugin
# kintone-data-aggregator-plugin
1. コマンド:
- `package.json`ファイルを開き、`scripts`内の`upload`コマンドのパラメータを接続する必要があるkintoneドメインに変更してください。

1
components.d.ts vendored
View File

@@ -2,6 +2,7 @@
// @ts-nocheck
// Generated by unplugin-vue-components
// Read more: https://github.com/vuejs/core/pull/3399
// biome-ignore lint: disable
export {}
/* prettier-ignore */

4414
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -1,21 +1,18 @@
{
"name": "data-fetch-plugin",
"name": "kintone-data-aggregator-plugin",
"private": true,
"version": "0.0.0",
"type": "module",
"scripts": {
"dev": "vite",
"preview": "vite preview",
"build": "vite build && npm run pkg",
"vite:build": "vite build",
"build-upload": "npm run build && npm run upload",
"build-up2":"npm run build && npm run upload2",
"build": "vite build && npm run pkg",
"build:prod": "cross-env BUILD_MODE=production 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-plugin-uploader --base-url https://mfu07rkgnb7c.cybozu.com --username MXZ --password maxz1205 dist/plugin.zip ",
"upload2": "kintone-plugin-uploader --base-url https://alicorn.cybozu.com --username maxz --password 7ld7i8vd dist/plugin.zip "
"upload": "kintone-plugin-uploader --base-url https://alicorn.cybozu.com --username maxz --password 7ld7i8vd dist/plugin.zip "
},
"dependencies": {
"@kintone/rest-api-client": "^5.7.0",
"@kintone/rest-api-client": "^5.7.5",
"kintone-ui-component": "1.18.0",
"rollup-plugin-css-only": "^4.5.2",
"vue": "^3.5.13",
@@ -26,10 +23,14 @@
"@kintone/dts-gen": "^8.1.1",
"@kintone/plugin-packer": "^8.1.3",
"@kintone/plugin-uploader": "^9.1.2",
"@types/node-rsa": "^1.1.4",
"@vitejs/plugin-vue": "^5.2.1",
"@vue/tsconfig": "^0.7.0",
"cross-env": "^10.1.0",
"eslint": "^8.57.0",
"node-rsa": "^1.1.1",
"rollup-plugin-copy": "^3.5.0",
"terser": "^5.44.0",
"typescript": "^5.7.3",
"unplugin-vue-components": "^28.0.0",
"vite": "^6.0.1",

View File

@@ -1,15 +1,15 @@
-----BEGIN RSA PRIVATE KEY-----
MIICXQIBAAKBgQCF7z/zsYmoe+L1AYTeCYvy9yBXlsXOniTzox6svsXunibVP3y+
f1jEwu2cnTdp/GABOzsVHNSrYGedRDlwG93Y8qxe7qNKLZAFL6ujmJ0FJixuYrh4
xvaWR6SlKIbws+803qAyE6dUN893xeZeJdWGelZNBsCZu8Nwmi28k1flzQIDAQAB
AoGAbWJchJZ2qtejIB5BeWWqmqAiFebZXkniO+j44HReCue3J2pWYu52fRwGG2Z7
H2AyuE67jh6hweVWOibCEkFwCM+MwkSpKNRyFqJwdzZGoMm/oT67dDGYELrmNCx/
9G5DdLgLXsA2dAANxTybaK8wg123Hhrh7NwJDETn9OC+uzECQQDeJTq4OSK9qUw9
RCpgijpVdnzc4hC0CNjKe/+z8bQOPVcX7zLcggwX/7i2UmNxBxfYFrCN8XIGJNGN
VXMpUdCjAkEAmliRAdgAJvoMvaS+gCcJt9tU18F2aunnGudpdwMWDFYdsnztLSJQ
uLPsPQM0TJJYwXWZ+akQuReqXeKg4WgmzwJBAMZAg38VvqN1C81BoHA37IeJDzYx
qqaBnrhWoYV+GCr9I1UA7GtOxGxGlBpivMyKgAUher+y0wgYo8t2jyg5E/ECQCRH
JO42AvMmWtBIZK5ifppEZ1C/HEJM8BEWy2c5xnjn1NsbGfQ92JNRVvmQQz6sN0hh
h+tynYej1Ft05TOV82kCQQCDd0/JtINW3Myj2nWIe8c9IjsBUtNOkaCa13tGOzwJ
3G8Bg0GzdVSC73OnEaguC72kBvyGO4enUFkOq6p6kmFQ
MIICXAIBAAKBgQCIkxa8JuBndXN0U/Fo+iX97nm03VYx0L4BBOfiUEB0innnLntF
Nm6IN7gaR+D1G4CGV6NkM/s7xRUPDFLRFQM0DUTw/Su40jcFdHNLbTntlrzh6lGb
ihPRficSP4Bu0nacTrLwEYwSp17Z95Ly2EliznuWh7ShaABaP6dfiy6SWwIDAQAB
AoGAA9N7E5JTPxK/RUcEwFghsFd5+WMqAwNCD20/wctVwu4ONDfNJEc+GXrWIYZZ
+wPmOd1Cqo/6PdZrnJxPxaO9DzFQelK4a+/5fXzOJm04d22Y8ezDJi9lsZ+wRG/8
ViEchiTB2ZZsRy8MPCVNyW2i1XOKPVZHAbH8hRDx3atbFmECQQD7G9NeNf32cwke
pDTa5bFoOQ9BOL44c1buf1eTIvY/aPBJG426ZXVEbCtknLBBiWj6+ESNKd7Zu8RE
cNgALnbNAkEAizwhFEJTn1TK7zyC3BqysPkDgMpe6naBnnNI3DjsYZpTKdhP5auw
cYe1nCyJgGdsY3OU1a8EOttOYxm4dAcdxwJAa483spsd9XrA5Ucg/MJ2g1Ytmppb
oIKHMhGJyZSoNfEVO7t5seXTnUNYMviK5wec2COP+Yd91XYAU/CiFTHR4QJAH3xF
brNg/ZLLITZp0SQobGSjKiiZNiP+Q7qGK2aj7Z5cWAYWazVb/RBXPS3FGkhI9mRY
r8mYB0c4fqh+UZ6aWQJBAMkM+Zs5Htt8xWnX4MLcGUlBLuUq2012NtMDWqH1GPd9
R5cyDpj2YCr3Wm6cASE7W2VXq6no8rMuoFm5vp4kR3c=
-----END RSA PRIVATE KEY-----

12
scripts/privateKey.ts Normal file
View File

@@ -0,0 +1,12 @@
'use strict';
// @ts-ignore
import RSA from 'node-rsa';
/**
* Create a private key for a kintone plugin
* Copy from https://github.com/kintone/js-sdk/blob/main/packages/create-plugin/src/privateKey.ts
*/
export const generatePrivateKey = () => {
const key = new RSA({ b: 1024 });
return key.exportKey('pkcs1-private');
};

File diff suppressed because one or more lines are too long

2377
src/assets/kuc.min.js vendored

File diff suppressed because one or more lines are too long

View File

@@ -1,7 +1,9 @@
import type { FieldLayout, FieldsJoinMapping, JoinTable, Record, RecordForParameter, SavedData,StringValue, WhereCondition } from "@/types/model";
import { type OneOf, isType } from "./field-types-mobile";
import type { ConditionValue } from "./conditions";
declare var KintoneRestAPIClient: typeof import("@kintone/rest-api-client").KintoneRestAPIClient;
import { KintoneRestAPIClient } from '@kintone/rest-api-client';
import { MobileButton } from 'kintone-ui-component/lib/mobile/button';
import { Spinner } from 'kintone-ui-component/lib/spinner';
export class KintoneIndexEventHandler {
private config: SavedData<FieldLayout>;
private currentApp: string;
@@ -22,12 +24,11 @@ export class KintoneIndexEventHandler {
};
// ボタン追加
if (document.getElementById('btn-data-fetch')) return;
const kuc = Kucs['1.18.0'];
const button = new kuc.MobileButton({
if (document.getElementById('aggregator-plugin:btn-data-fetch')) return;
const button = new MobileButton({
text: this.config.buttonName,
type: "submit",
id: 'btn-data-fetch',
id: 'aggregator-plugin:btn-data-fetch',
});
button.addEventListener('click', () => this.handleButtonClick());
headerSpace.appendChild(button);
@@ -51,8 +52,7 @@ export class KintoneIndexEventHandler {
}
private showSpinner() {
const kuc = Kucs['1.18.0'];
const spinner = new kuc.Spinner({
const spinner = new Spinner({
text: 'データ収集中',
container: document.body
});

View File

@@ -1,7 +1,9 @@
import type { FieldLayout, FieldsJoinMapping, JoinTable, Record, RecordForParameter, SavedData, StringValue,WhereCondition } from "@/types/model";
import { type OneOf, isType } from "./field-types";
import type { ConditionValue } from "./conditions";
declare var KintoneRestAPIClient: typeof import("@kintone/rest-api-client").KintoneRestAPIClient;
import { KintoneRestAPIClient } from '@kintone/rest-api-client';
import { Button } from 'kintone-ui-component/lib/button';
import { Spinner } from 'kintone-ui-component/lib/spinner';
export class KintoneIndexEventHandler {
private config: SavedData<FieldLayout>;
private currentApp: string;
@@ -22,12 +24,11 @@ export class KintoneIndexEventHandler {
};
// ボタン追加
if (document.getElementById('btn-data-fetch')) return;
const kuc = Kucs['1.18.0'];
const button = new kuc.Button({
if (document.getElementById('aggregator-plugin:btn-data-fetch')) return;
const button = new Button({
text: this.config.buttonName,
type: "submit",
id: 'btn-data-fetch',
id: 'aggregator-plugin:btn-data-fetch',
});
button.addEventListener('click', () => this.handleButtonClick());
headerSpace.appendChild(button);
@@ -51,8 +52,7 @@ export class KintoneIndexEventHandler {
}
private showSpinner() {
const kuc = Kucs['1.18.0'];
const spinner = new kuc.Spinner({
const spinner = new Spinner({
text: 'データ収集中',
container: document.body
});

View File

@@ -1,34 +1,32 @@
import type { Field, FieldLayout, SavedData } from "@/types/model";
import { KintoneIndexEventHandler } from "./KintoneIndexEventHandler";
import type { FieldLayout, SavedData } from '@/types/model';
import { KintoneIndexEventHandler } from './KintoneIndexEventHandler';
(function (PLUGIN_ID) {
kintone.events.on('app.record.index.show', (event) => {
try{
try {
const setting = kintone.plugin.app.getConfig(PLUGIN_ID);
const config:SavedData<FieldLayout> = getConfig(setting);
const config: SavedData<FieldLayout> = getConfig(setting);
const currentApp = kintone.app.getId()?.toString();
if(!currentApp) return;
const handler = new KintoneIndexEventHandler(config,currentApp);
handler.init();
}catch(error){
const detailError =(error instanceof Error) ? "\n詳細:" + error.message : "";
const errorMsg = `データ収集中処理中例外発生しました。${ detailError }`;
event.error = errorMsg;
if (!currentApp) return;
const handler = new KintoneIndexEventHandler(config, currentApp);
handler.init();
} catch (error) {
const detailError = error instanceof Error ? '\n詳細:' + error.message : '';
const errorMsg = `データ収集中処理中例外発生しました。${detailError}`;
event.error = errorMsg;
}
return event;
});
/**
* Config設定値を変換する
* @param setting
* @returns
* @param setting
* @returns
*/
function getConfig(setting:any):SavedData<FieldLayout>{
const config:SavedData<FieldLayout>={
buttonName:setting.buttonName,
joinTables:JSON.parse(setting.joinTables)
}
return config;
function getConfig(setting: any): SavedData<FieldLayout> {
const config: SavedData<FieldLayout> = {
buttonName: setting.buttonName,
joinTables: JSON.parse(setting.joinTables),
};
return config;
}
})(kintone.$PLUGIN_ID);

View File

@@ -1,4 +1,4 @@
declare var KintoneRestAPIClient: typeof import("@kintone/rest-api-client").KintoneRestAPIClient;
import { KintoneRestAPIClient } from '@kintone/rest-api-client';
const client = new KintoneRestAPIClient();
export type Properties = Awaited<ReturnType<typeof client.app.getFormFields>>['properties'];
export type Layout = Awaited<ReturnType<typeof client.app.getFormLayout>>['layout'];

View File

@@ -1,4 +1,4 @@
declare var KintoneRestAPIClient: typeof import("@kintone/rest-api-client").KintoneRestAPIClient;
import { KintoneRestAPIClient } from '@kintone/rest-api-client';
const client = new KintoneRestAPIClient();
export type Properties = Awaited<ReturnType<typeof client.app.getFormFields>>['properties'];
export type Layout = Awaited<ReturnType<typeof client.app.getFormLayout>>['layout'];

View File

@@ -1,32 +1,32 @@
import type { Field, FieldLayout, SavedData } from "@/types/model";
import { KintoneIndexEventHandler } from "./KintoneIndexEventHandler.mobile";
import type { FieldLayout, SavedData } from '@/types/model';
import { KintoneIndexEventHandler } from './KintoneIndexEventHandler.mobile';
(function (PLUGIN_ID) {
kintone.events.on('mobile.app.record.index.show', (event) => {
try{
try {
const setting = kintone.plugin.app.getConfig(PLUGIN_ID);
const config:SavedData<FieldLayout> = getConfig(setting);
const config: SavedData<FieldLayout> = getConfig(setting);
const currentApp = kintone.mobile.app.getId()?.toString();
if(!currentApp) return;
const handler = new KintoneIndexEventHandler(config,currentApp);
handler.init();
}catch(error){
const detailError =(error instanceof Error) ? "\n詳細:" + error.message : "";
const errorMsg = `データ収集中処理中例外発生しました。${ detailError }`;
event.error = errorMsg;
if (!currentApp) return;
const handler = new KintoneIndexEventHandler(config, currentApp);
handler.init();
} catch (error) {
const detailError = error instanceof Error ? '\n詳細:' + error.message : '';
const errorMsg = `データ収集中処理中例外発生しました。${detailError}`;
event.error = errorMsg;
}
return event;
});
/**
* Config設定値を変換する
* @param setting
* @returns
* @param setting
* @returns
*/
function getConfig(setting:any):SavedData<FieldLayout>{
const config:SavedData<FieldLayout>={
buttonName:setting.buttonName,
joinTables:JSON.parse(setting.joinTables)
}
function getConfig(setting: any): SavedData<FieldLayout> {
const config: SavedData<FieldLayout> = {
buttonName: setting.buttonName,
joinTables: JSON.parse(setting.joinTables),
};
return config;
}
}
})(kintone.$PLUGIN_ID);

View File

@@ -1,5 +1,5 @@
import { createApp } from 'vue';
import Config from './components/Config.vue';
import i18n from './i18n/index';
import i18n from './i18n';
createApp(Config, { pluginId: kintone.$PLUGIN_ID }).use(i18n).mount('#app');

View File

@@ -5,12 +5,9 @@
"type": "APP",
"desktop": {
"js": [
"js/KintoneRestAPIClient.min.js",
"js/kuc.min.js",
"js/desktop.js"
],
"css": [
"css/51-modern-default.css",
"css/desktop.css"
]
},
@@ -38,8 +35,6 @@
},
"mobile": {
"js": [
"js/KintoneRestAPIClient.min.js",
"js/kuc.min.js",
"js/mobile.js"
],
"css": [

View File

@@ -1,6 +1,3 @@
declare global {
const Kucs: {
[version: string]: any;
};
}
export {};
// 导出所有类型定义
// 主要导出应用设置相关的类型接口
export * from './model';

View File

@@ -6,6 +6,12 @@
"./node_modules/@kintone/dts-gen/kintone.d.ts",
],
"compilerOptions": {
"resolveJsonModule": true,
"moduleResolution": "node",
"esModuleInterop": true,
"allowSyntheticDefaultImports": true,
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true,
"tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo",
"paths": {
"@/*": ["./src/*"]

View File

@@ -1,10 +1,32 @@
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import copy from "rollup-plugin-copy";
import { defineConfig } from 'vite';
import vue from '@vitejs/plugin-vue';
import copy from 'rollup-plugin-copy';
import * as path from 'path';
import * as fs from 'fs';
import * as child_process from 'child_process';
import Components from 'unplugin-vue-components/vite';
import { generatePrivateKey } from './scripts/privateKey';
const packageJson = require('./package.json');
// 从 package.json 读取 kintone-ui-component 版本信息
const kucVersion = packageJson.dependencies['kintone-ui-component'];
const formattedVersion = kucVersion.replace(/\./g, '-'); // 例如1.22.0 -> 1-22-0
// 判断是否为生产环境构建
const isProd = process.env.BUILD_MODE === 'production';
const buildMode = isProd ? 'production' : 'development';
console.log(`Building IIFE versions in ${buildMode} mode...`);
// 检查 private.ppk 是否存在,如果不存在则生成
const privateKeyPath = path.resolve(__dirname, 'private.ppk');
if (!fs.existsSync(privateKeyPath)) {
const privateKey = generatePrivateKey();
fs.writeFileSync(privateKeyPath, privateKey);
}
/**
* 自定义插件 vite-plugin-replace-tags替换 KUC 组件标签为包含版本号的标签,并自动导入组件
*/
function replaceKucTagsPlugin() {
return {
name: 'vite-plugin-replace-tags',
@@ -12,24 +34,28 @@ function replaceKucTagsPlugin() {
if (id.endsWith('.vue')) {
const content = await fs.promises.readFile(id, 'utf-8');
const usedComponent = {}
const usedComponent = {};
// 替换 <kuc-*> 为带有版本号的形式 <kuc-[version]-*>
let res = content
.replace(/<\/kuc-([a-zA-Z0-9-]+)(?![0-9-])>/g, (match, p1) => `</kuc-${p1}-1-18-0>`)
.replace(/<kuc-([a-zA-Z0-9-]+)(?![0-9-])([^>]*)>/g, (match, p1, p2) => {
.replace(new RegExp(`</kuc-([a-zA-Z0-9-]+)(?![0-9-])>`, 'g'), (match, p1) => `</kuc-${p1}-${formattedVersion}>`)
.replace(new RegExp(`<kuc-([a-zA-Z0-9-]+)(?![0-9-])([^>]*)>`, 'g'), (match, p1, p2) => {
usedComponent[p1] = true;
return `<kuc-${p1}-1-18-0${p2}>`
return `<kuc-${p1}-${formattedVersion}${p2}>`;
});
// 如果有 KUC 组件,自动生成 import 脚本
if (Object.keys(usedComponent).length) {
let importScript = '<script lang="ts">'
let importScript = '<script lang="ts">';
Object.keys(usedComponent).forEach((key) => {
const keyPascal = key.split('-')
.map(word => word.charAt(0).toUpperCase() + word.slice(1))
.map((word) => word.charAt(0).toUpperCase() + word.slice(1))
.join('');
// 特殊处理 multi-choice 组件名称
if (key === 'multi-choice') {
key = 'multichoice';
}
importScript += `import * as Kuc${keyPascal} from "kintone-ui-component/lib/${key}";`
importScript += `import * as Kuc${keyPascal} from "kintone-ui-component/lib/${key}";`;
});
importScript += '</script>';
res = importScript + res;
@@ -37,52 +63,122 @@ function replaceKucTagsPlugin() {
return res;
}
}
},
};
}
/**
* 自定义插件 iife-builder构建 desktop.ts 和 mobile.ts 的 IIFE 版本
*/
function buildIIFEVersions() {
return {
name: 'iife-builder',
buildStart() {
console.log('Building IIFE versions...');
try {
// Build desktop IIFE
console.log('Building desktop IIFE...');
child_process.execSync('npx vite build --config vite.iife.config.ts', { stdio: 'inherit', env: { ...process.env, PLATFORM: 'desktop' } });
// Build mobile IIFE
console.log('Building mobile IIFE...');
child_process.execSync('npx vite build --config vite.iife.config.ts', { stdio: 'inherit', env: { ...process.env, PLATFORM: 'mobile' } });
console.log('IIFE builds completed successfully.');
} catch (error) {
console.error('Error building IIFE versions:', error);
throw error;
}
},
generateBundle(options, bundle) {
// 将 IIFE 版本复制到主构建目录覆盖原有文件
const desktopIIFEPath = path.resolve(__dirname, 'dist-iife/desktop/desktop.js');
const mobileIIFEPath = path.resolve(__dirname, 'dist-iife/mobile/mobile.js');
const destDir = path.resolve(__dirname, 'dist/src/js');
if (fs.existsSync(desktopIIFEPath)) {
fs.mkdirSync(destDir, { recursive: true });
fs.copyFileSync(desktopIIFEPath, path.join(destDir, 'desktop.js'));
console.log('Copied desktop.js to dist/src/js/');
}
if (fs.existsSync(mobileIIFEPath)) {
fs.mkdirSync(destDir, { recursive: true });
fs.copyFileSync(mobileIIFEPath, path.join(destDir, 'mobile.js'));
console.log('Copied mobile.js to dist/src/js/');
}
// 清理临时的 dist-iife 目录
if (fs.existsSync(path.resolve(__dirname, 'dist-iife'))) {
fs.rmSync(path.resolve(__dirname, 'dist-iife'), { recursive: true, force: true });
console.log('Cleaned up dist-iife directory');
}
},
};
}
// https://vite.dev/config/
export default defineConfig({
plugins: [
buildIIFEVersions(),
vue({
template: {
compilerOptions: {
isCustomElement: (tag) => tag.startsWith("kuc-"),
}
}
// 将以 kuc- 开头的标签识别为自定义元素,避免 Vue 的警告
isCustomElement: (tag) => tag.startsWith('kuc-'),
},
},
}),
Components(),
Components(), // 自动导入 Vue 组件
copy({
// 将打包 plugin 需要的文件复制到 dist 里面
targets: [
{ src: 'dist/index.html', dest: 'dist/src/html', rename: 'config.html' },
{ src: 'src/manifest.json', dest: 'dist/src' },
{ 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' },
],
hook: 'writeBundle' // 指定在何时复制文件
}),
replaceKucTagsPlugin()
replaceKucTagsPlugin(), // 自定义标签替换插件
],
resolve: {
alias: {
'@': path.resolve(__dirname, 'src'),
'@': path.resolve(__dirname, 'src'), // 配置 @ 别名指向 src 目录
},
},
build: {
target: 'es2022',
rollupOptions: {
input: {
config: path.resolve(__dirname, 'index.html'),
desktop: path.resolve(__dirname, 'src/js/desktop.ts'),
mobile: path.resolve(__dirname, 'src/js/mobile.ts'),
},
output: {
entryFileNames: (chunkInfo) => {
return 'src/js/[name].js'; // 默认处理为 JS 文件
return 'src/js/[name].js'; // 将入口文件输出为 JS 文件
},
assetFileNames: 'src/[ext]/[name].[ext]',
assetFileNames: 'src/[ext]/[name].[ext]', // 设置资源文件输出路径
},
},
sourcemap: 'inline',
}
})
sourcemap: isProd ? false : 'inline', // 生产环境关闭 sourcemap开发环境使用 inline
minify: 'terser', // 强制进行混淆,避免全局变量被污染的问题
...(isProd && {
terserOptions: {
compress: {
drop_console: true, // 移除 console
drop_debugger: true, // 移除 debugger
pure_funcs: ['console.log'], // 移除 console.log
},
mangle: {
toplevel: true, // 混淆顶级作用域的变量名
},
format: {
comments: false, // 移除注释
},
},
}),
},
});

73
vite.iife.config.ts Normal file
View File

@@ -0,0 +1,73 @@
import * as path from 'path';
import { defineConfig, UserConfig } from 'vite';
const packageJson = require('./package.json');
/**
* 生成 IIFE 配置的工厂函数
* @param platform 'desktop' | 'mobile'
*/
function createIIFEConfig(platform: 'desktop' | 'mobile'): UserConfig {
// 判断是否为生产环境构建
const isProd = process.env.BUILD_MODE === 'production';
return {
resolve: {
alias: {
'@': path.resolve(__dirname, 'src'),
},
},
define: {
'process.env.NODE_ENV': JSON.stringify('production'),
'process.env': JSON.stringify({}),
global: 'window',
},
build: {
target: 'es2022',
lib: {
entry: path.resolve(__dirname, `src/js/${platform}.ts`),
name: `${packageJson.name.replaceAll('-', '_')}_${platform}_iife`,
formats: ['iife'],
fileName: () => `${platform}.js`,
},
rollupOptions: {
external: ['kintone'], // kintone 是网站提供的 api需要处理
output: {
globals: {
kintone: 'kintone',
},
},
},
outDir: path.resolve(__dirname, `dist-iife/${platform}`), // 输出到 dist-iife 目录
sourcemap: isProd ? false : 'inline', // 生产环境关闭,开发环境使用 inline
minify: 'terser', // 强制进行混淆,避免全局变量被污染的问题
...(isProd && {
terserOptions: {
compress: {
drop_console: true, // 移除 console
drop_debugger: true, // 移除 debugger
pure_funcs: ['console.log'], // 移除 console.log
},
mangle: {
toplevel: true, // 混淆顶级作用域的变量名
},
format: {
comments: false, // 移除注释
},
},
}),
},
};
}
// 根据环境变量决定构建哪个平台
const platform = process.env.PLATFORM as 'desktop' | 'mobile';
if (!platform || !['desktop', 'mobile'].includes(platform)) {
throw new Error('Please specify PLATFORM environment variable: desktop or mobile');
}
/**
* 统一的 IIFE 构建配置
* 用于将 desktop.ts 和 mobile.ts 打包为 IIFE 格式
*/
export default defineConfig(createIIFEConfig(platform));

4885
yarn.lock

File diff suppressed because it is too large Load Diff