add global config

This commit is contained in:
2025-11-03 10:24:13 +08:00
parent 393c637163
commit 63a2cfc186
4 changed files with 75 additions and 16 deletions

View File

@@ -3,7 +3,7 @@
使用 Vue 、ts 和 Vite 创建 kintone plugin 的初始化模板,先由 [create-plugin](https://cybozu.dev/ja/kintone/sdk/development-environment/create-plugin/) 生成之后再手动引入 Vue。
并且提供了 [License 检查](#License-检查) 的功能。
并且提供了 [License 检查](#license-检查) 的功能。
> プラグイン開発手順https://cybozu.dev/ja/kintone/tips/development/plugins/development-plugin/
@@ -78,15 +78,35 @@ npm install # 或 yarn
}
```
3. 如果需要使用 License 检查,请参考: [License 检查](#License-检查)
3. 如果需要使用 License 检查,请参考: [License 检查](#license-检查)
一般需要修改 `LicenseStatus.vue` 里面的 `purchaseLicense()` 中打开的链接。
需要修改 `src/config.json`
```diff
function purchaseLicense() {
// ...
+ window.open(`修改购买页面,或者重用也不是不可以`)
- window.open(`https://alisurvey.alicorns.co.jp/s/Iuc5RxZv?${queryParams}`);
{
"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 // 进行提醒的剩余天数
}
}
```

View File

@@ -28,6 +28,7 @@ import { useI18n } from 'vue-i18n';
import { LicenseService } from '@/services/license-service';
import type { LicenseInfo } from '@/types/license';
import { LicenseStorage } from '@/utils/license-storage';
import config from '@/config.json';
const { t: $t } = useI18n();// 配置国际化
@@ -65,6 +66,13 @@ const licenseDisplayInfo = computed<LicenseDisplayInfo>(() => {
});
onMounted(async () => {
if (!config.license.enabled) {
// 许可证功能未启用,不显示组件
shown.value = false;
loading.value = false;
return;
}
const result = await LicenseService.checkLicense();
await new Promise((resolve) => setTimeout(resolve, 500));
licenseInfo.value = result.license;
@@ -144,10 +152,10 @@ function purchaseLicense() {
const pluginId = licenseInfo.value?.pluginId;
const params = {
name: { inputId: 'input1761283314263', value: name },
email: { inputId: 'input1761283275767', value: email },
domain: { inputId: 'input1761283180784', value: domain },
pluginId: { inputId: 'input1761283200616', value: pluginId }
name: { inputId: config.license.purchase.formIds.name, value: name },
email: { inputId: config.license.purchase.formIds.email, value: email },
domain: { inputId: config.license.purchase.formIds.domain, value: domain },
pluginId: { inputId: config.license.purchase.formIds.pluginId, value: pluginId }
};
const queryParams = Object.values(params)
@@ -155,7 +163,7 @@ function purchaseLicense() {
.map(param => `${param.inputId}=${encodeURIComponent(param.value as string)}`)
.join('&');
window.open(`https://alisurvey.alicorns.co.jp/s/Iuc5RxZv?${queryParams}`);
window.open(`${config.license.purchase.url}?${queryParams}`);
}
function hidePaidMsg() {

19
src/config.json Normal file
View File

@@ -0,0 +1,19 @@
{
"license": {
"enabled": true,
"api": {
"checkUrl": "https://kintone.alicorns.co.jp/api/license/check",
"pluginKey": "kintone-vue-template"
},
"purchase": {
"url": "https://alisurvey.alicorns.co.jp/s/Iuc5RxZv",
"formIds": {
"name": "input1761283314263",
"email": "input1761283275767",
"domain": "input1761283180784",
"pluginId": "input1761283200616"
}
},
"warningDaysBeforeExpiry": 7
}
}

View File

@@ -7,12 +7,12 @@ import { MobileNotification } from 'kintone-ui-component/lib/mobile/notification
import manifestJson from '@/manifest.json';
import { KJUR } from 'jsrsasign';
import rsaPublicKey from '../../rsa_public.pem?raw';
import config from '@/config.json';
const { t: $t } = i18n.global;
export class LicenseService {
// 常量定义
private static readonly WARNING_DAYS_BEFORE_EXPIRY = 7;
private static PLUGIN_ID: string = '';
// ============ 基础工具函数 ============
@@ -97,6 +97,12 @@ export class LicenseService {
* 许可证验证
*/
static async checkLicense(): Promise<LicenseCheckResult> {
if (!config.license.enabled || rsaPublicKey.trim() === '') {
return {
isLicenseValid: true,
license: undefined,
};
}
const localLicense = this.getLocalLicenseInfo() || undefined;
if (localLicense) {
return {
@@ -111,13 +117,13 @@ export class LicenseService {
* 调用远程许可证API
*/
private static async callRemoteLicenseAPI(domain: string, pluginId: string): Promise<string | null> {
const url = 'https://kintone.alicorns.co.jp/api/license/check';
const url = config.license.api.checkUrl;
const method = 'POST';
const headers = { 'Content-Type': 'application/json' };
const body = {
domain,
pluginId,
pluginKey: 'kintone-vue-template',
pluginKey: config.license.api.pluginKey,
};
const proxyResponse = await kintone.proxy(url, method, headers, body);
if (proxyResponse[1] !== 200) {
@@ -180,7 +186,7 @@ export class LicenseService {
*/
static isExpiringSoon(expiryTimestamp: number): boolean {
const now = Date.now();
const warningTime = expiryTimestamp - this.WARNING_DAYS_BEFORE_EXPIRY * 24 * 60 * 60 * 1000;
const warningTime = expiryTimestamp - config.license.warningDaysBeforeExpiry * 24 * 60 * 60 * 1000;
return now >= warningTime && expiryTimestamp > now;
}
@@ -247,6 +253,12 @@ export class LicenseService {
static async loadPluginIfAuthorized(pluginId: string, callback: () => void | Promise<void>) {
this.PLUGIN_ID = pluginId;
try {
if (!config.license.enabled) {
// 许可证功能未启用,直接加载插件
await callback();
return;
}
// 检查许可证(内部已经包含本地检查无效时自动获取远程的逻辑)
const licenseCheck = await this.checkLicense();