From 7a3eb40aa97cd340f4526efbf26c54c3b6016200 Mon Sep 17 00:00:00 2001 From: xuejiahao Date: Tue, 21 Oct 2025 16:43:31 +0800 Subject: [PATCH] update license check --- src/js/desktop.ts | 5 +-- src/js/mobile.ts | 5 +-- src/services/licenseService.ts | 78 ++++++++++++++++++---------------- src/types/license.d.ts | 6 +++ src/types/my-kintone.d.ts | 10 +++++ src/utils/licenseStorage.ts | 51 ++++++++++++++++++++-- src/utils/permissions.ts | 2 +- 7 files changed, 110 insertions(+), 47 deletions(-) diff --git a/src/js/desktop.ts b/src/js/desktop.ts index a7abe2a..a71df1d 100644 --- a/src/js/desktop.ts +++ b/src/js/desktop.ts @@ -1,6 +1,6 @@ import i18n from '@/i18n'; import type { Setting } from '@/types'; -import { LicenseService } from '@/services/licenseService'; +import { LicenseService } from '@/services/LicenseService'; import client from '@/plugins/kintoneClient.ts' import { Button } from 'kintone-ui-component/lib/button'; @@ -59,8 +59,7 @@ import { Button } from 'kintone-ui-component/lib/button'; { expiryDialogTitle: '自定义插件到期提示', expiryDialogMessage: '您的自定义插件许可证已过期,请联系管理员购买新的许可证。', - warningDialogTitle: '自定义插件即将到期', - warningDialogMessage: '您的自定义插件许可证还有3天就到期了,请及时续费。', + // warningDialogMessage: '您的自定义插件许可证还有3天就到期了,请及时续费。', }, ); }); diff --git a/src/js/mobile.ts b/src/js/mobile.ts index 6a604dc..2db719e 100644 --- a/src/js/mobile.ts +++ b/src/js/mobile.ts @@ -1,6 +1,6 @@ import i18n from '@/i18n'; import type { Setting } from '@/types'; -import { LicenseService } from '@/services/licenseService'; +import { LicenseService } from '@/services/LicenseService'; import client from '@/plugins/kintoneClient.ts' import { MobileButton } from 'kintone-ui-component/lib/mobile/button'; @@ -59,8 +59,7 @@ import { MobileButton } from 'kintone-ui-component/lib/mobile/button'; { expiryDialogTitle: '自定义插件到期提示', expiryDialogMessage: '您的自定义插件许可证已过期,请联系管理员购买新的许可证。', - warningDialogTitle: '自定义插件即将到期', - warningDialogMessage: '您的自定义插件许可证还有3天就到期了,请及时续费。', + // warningDialogMessage: '您的自定义插件许可证还有3天就到期了,请及时续费。', }, ); }); diff --git a/src/services/licenseService.ts b/src/services/licenseService.ts index b518bf6..6459359 100644 --- a/src/services/licenseService.ts +++ b/src/services/licenseService.ts @@ -1,13 +1,13 @@ import type { LicenseInfo, LicenseCheckResult } from '@/types/license'; -import { LicenseStorage } from '@/utils/licenseStorage'; +import { LicenseStorage } from '@/utils/LicenseStorage'; import { PermissionService } from '@/utils/permissions'; import { Notification } from 'kintone-ui-component/lib/notification'; -import { createApp } from 'vue'; -import i18n from '@/i18n'; +import { MobileNotification } from 'kintone-ui-component/lib/mobile/notification'; export class LicenseService { // 常量定义 private static readonly WARNING_DAYS_BEFORE_EXPIRY = 7; + private static readonly TRIAL_DATE = 1; private static PLUGIN_ID: string = ''; // ============ 基础工具函数 ============ @@ -45,24 +45,27 @@ export class LicenseService { return true; } - const today = new Date(); // 检查存储是否过期(是否同一天) - const fetchDate = new Date(license.fetchTime).toDateString(); - const todayStr = today.toDateString(); - if (fetchDate !== todayStr) { + if (!this.isToday(license.fetchTime)) { // 不是同一天,已过期 return false; } // 检查试用是否到期 const expiredTime = new Date(license.expiredTime); - if (expiredTime < today) { + if (expiredTime < new Date()) { return false; } return true } + static isToday(timestamp: number): boolean { + const fetchDate = new Date(timestamp).toDateString(); + const todayStr = new Date().toDateString(); + return fetchDate == todayStr; + } + /** * 许可证验证 */ @@ -160,36 +163,36 @@ export class LicenseService { /** * 显示到期警告通知 */ - static showExpiryWarning(license: any, options?: { - warningDialogTitle?: string; + static async showExpiryWarning(license: any, options?: { warningDialogMessage?: string; }) { const remainingDays = this.getDaysRemaining(license.expiredTime); - const defaultMessage = `您的插件许可证将在 ${remainingDays} 天后到期,请及时续期以避免服务中断。`; + const msg = remainingDays > 0 ? ` ${remainingDays} 天后` : '今天' + const defaultMessage = `您的插件许可证将在${msg}到期,请及时续期以避免服务中断。`; // 使用自定义消息或默认消息 const message = options?.warningDialogMessage || defaultMessage; // 检查是否已设置不再提醒 - const dontShowKey = `license_notification_dont_show_again_${this.getPluginId()}`; - const dontShowAgain = localStorage.getItem(dontShowKey) === 'true'; - if (dontShowAgain) return; + const settings = LicenseStorage.getSettings(this.getPluginId()); + if (settings.suppressMsgTime && this.isToday(settings.suppressMsgTime)) { + return + } + delete settings.suppressMsgTime + LicenseStorage.saveSetting(settings, this.getPluginId()); - // 使用KUC Notification - const notification = new Notification({ - text: message, - type: 'info', - duration: -1 // 不自动关闭 - }); - - // 添加到页面 - const container = document.body; - container.appendChild(notification); - - // 监听关闭事件 - notification.addEventListener('close', () => { - // 这里可以添加不再提醒的逻辑 - }); + if (await kintone.isMobilePage()) { + const notification = new MobileNotification({ + text: message, + }); + notification.open(); + } else { + const notification = new Notification({ + text: message, + type: 'info', + }); + notification.open(); + } } // ============ 主要入口函数 ============ @@ -203,7 +206,6 @@ export class LicenseService { options?: { expiryDialogTitle?: string; expiryDialogMessage?: string; - warningDialogTitle?: string; warningDialogMessage?: string; } ) { @@ -233,13 +235,14 @@ export class LicenseService { } // 许可证有效,如果快要到期,管理员可以看到警告 - if (isManager && licenseCheck.license && !licenseCheck.license.isPaid && this.isExpiringSoon(licenseCheck.license.expiredTime)) { + if (isManager && + licenseCheck.license && + !licenseCheck.license.isPaid && + this.isExpiringSoon(licenseCheck.license.expiredTime)) { // 管理员可以看到过期弹框 - alert('即将过期') - // this.showExpiryWarning(licenseCheck.license, { - // warningDialogTitle: options?.warningDialogTitle, - // warningDialogMessage: options?.warningDialogMessage - // }); + this.showExpiryWarning(licenseCheck.license, { + warningDialogMessage: options?.warningDialogMessage + }); } // 许可证有效,可以加载插件功能 @@ -275,7 +278,7 @@ export class LicenseService { */ private static mockCreateTrialLicense(): LicenseInfo { const expiryDate = new Date(); - expiryDate.setDate(expiryDate.getDate() + 30); + expiryDate.setDate(expiryDate.getDate() + this.TRIAL_DATE); return { expiredTime: expiryDate.getTime(), @@ -283,6 +286,7 @@ export class LicenseService { domain: this.getDomain(), pluginId: this.getPluginId(), fetchTime: new Date().getTime(), + version: 1, }; } diff --git a/src/types/license.d.ts b/src/types/license.d.ts index bcbd5c4..0b6ba5d 100644 --- a/src/types/license.d.ts +++ b/src/types/license.d.ts @@ -11,6 +11,12 @@ export interface LicenseInfo { pluginId: string; // 获取许可证的时间戳 fetchTime: number; + // 版本号 + version: number; +} + +export interface LicenseSetting { + suppressMsgTime?: number; } export interface LicenseCheckResult { diff --git a/src/types/my-kintone.d.ts b/src/types/my-kintone.d.ts index b954c06..dfec085 100644 --- a/src/types/my-kintone.d.ts +++ b/src/types/my-kintone.d.ts @@ -1,6 +1,16 @@ // 导入官方 REST API 客户端的类型定义 import { KintoneFormFieldProperty } from '@kintone/rest-api-client'; +declare global { + namespace kintone { + /** + * 判断当前页面是否为移动端页面 + * @returns Promise 返回是否为移动端页面 + */ + function isMobilePage(): Promise; + } +} + // KUC 组件事件类型定义 // 定义 kintone UI 组件触发事件的结构 export interface KucEvent { diff --git a/src/utils/licenseStorage.ts b/src/utils/licenseStorage.ts index 61a7826..23fd16b 100644 --- a/src/utils/licenseStorage.ts +++ b/src/utils/licenseStorage.ts @@ -1,9 +1,10 @@ // 本地存储加密工具类 -import { LicenseService } from '@/services/licenseService'; -import type { LicenseInfo } from '@/types/license'; +import { LicenseService } from '@/services/LicenseService'; +import type { LicenseInfo, LicenseSetting } from '@/types/license'; export class LicenseStorage { private static readonly STORAGE_KEY_PREFIX = 'alicorns_plugin_'; + private static readonly STORAGE_SETTING_KEY_PREFIX = this.STORAGE_KEY_PREFIX + 'setting_'; /** * 生成存储key @@ -38,7 +39,7 @@ export class LicenseStorage { const parsedData: LicenseInfo = JSON.parse(storedData); - const isValid = LicenseService.checkLicenseAvailable(parsedData) + const isValid = LicenseService.checkLicenseAvailable(parsedData); if (!isValid) { // 获取许可证信息失败,清理存储 this.clearLicense(pluginId); @@ -62,4 +63,48 @@ export class LicenseStorage { localStorage.removeItem(key); } + /** + * 生成存储key + */ + private static generateSettingStorageKey(pluginId: string): string { + return `${this.STORAGE_SETTING_KEY_PREFIX}${pluginId}`; + } + + /** + * 保存设置信息到本地存储 + */ + static saveSetting(setting: LicenseSetting, pluginId: string): void { + try { + const key = this.generateSettingStorageKey(pluginId); + localStorage.setItem(key, JSON.stringify(setting)); + } catch (error) { + console.error('Failed to save setting:', error); + throw error; + } + } + + /** + * 从本地存储获取设置信息 + */ + static getSettings(pluginId: string): LicenseSetting { + try { + const key = this.generateSettingStorageKey(pluginId); + const storedData = localStorage.getItem(key); + + if (!storedData) return {}; + + return JSON.parse(storedData); + } catch (error) { + console.error('Failed to get setting:', error); + return {}; + } + } + + /** + * 清除设置信息 + */ + static clearSetting(pluginId: string): void { + const key = this.generateSettingStorageKey(pluginId); + localStorage.removeItem(key); + } } diff --git a/src/utils/permissions.ts b/src/utils/permissions.ts index e4f3d34..777239c 100644 --- a/src/utils/permissions.ts +++ b/src/utils/permissions.ts @@ -10,7 +10,7 @@ export class PermissionService { static async checkPermissions(): Promise { try { // 获取应用信息 - const appId = kintone.app.getId(); + const appId = kintone.app.getId() || kintone.mobile.app.getId(); if (!appId) { return this.getDefaultPermissions(); }