update license check
This commit is contained in:
@@ -1,6 +1,6 @@
|
|||||||
import i18n from '@/i18n';
|
import i18n from '@/i18n';
|
||||||
import type { Setting } from '@/types';
|
import type { Setting } from '@/types';
|
||||||
import { LicenseService } from '@/services/licenseService';
|
import { LicenseService } from '@/services/LicenseService';
|
||||||
import client from '@/plugins/kintoneClient.ts'
|
import client from '@/plugins/kintoneClient.ts'
|
||||||
import { Button } from 'kintone-ui-component/lib/button';
|
import { Button } from 'kintone-ui-component/lib/button';
|
||||||
|
|
||||||
@@ -59,8 +59,7 @@ import { Button } from 'kintone-ui-component/lib/button';
|
|||||||
{
|
{
|
||||||
expiryDialogTitle: '自定义插件到期提示',
|
expiryDialogTitle: '自定义插件到期提示',
|
||||||
expiryDialogMessage: '您的自定义插件许可证已过期,请联系管理员购买新的许可证。',
|
expiryDialogMessage: '您的自定义插件许可证已过期,请联系管理员购买新的许可证。',
|
||||||
warningDialogTitle: '自定义插件即将到期',
|
// warningDialogMessage: '您的自定义插件许可证还有3天就到期了,请及时续费。',
|
||||||
warningDialogMessage: '您的自定义插件许可证还有3天就到期了,请及时续费。',
|
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import i18n from '@/i18n';
|
import i18n from '@/i18n';
|
||||||
import type { Setting } from '@/types';
|
import type { Setting } from '@/types';
|
||||||
import { LicenseService } from '@/services/licenseService';
|
import { LicenseService } from '@/services/LicenseService';
|
||||||
import client from '@/plugins/kintoneClient.ts'
|
import client from '@/plugins/kintoneClient.ts'
|
||||||
import { MobileButton } from 'kintone-ui-component/lib/mobile/button';
|
import { MobileButton } from 'kintone-ui-component/lib/mobile/button';
|
||||||
|
|
||||||
@@ -59,8 +59,7 @@ import { MobileButton } from 'kintone-ui-component/lib/mobile/button';
|
|||||||
{
|
{
|
||||||
expiryDialogTitle: '自定义插件到期提示',
|
expiryDialogTitle: '自定义插件到期提示',
|
||||||
expiryDialogMessage: '您的自定义插件许可证已过期,请联系管理员购买新的许可证。',
|
expiryDialogMessage: '您的自定义插件许可证已过期,请联系管理员购买新的许可证。',
|
||||||
warningDialogTitle: '自定义插件即将到期',
|
// warningDialogMessage: '您的自定义插件许可证还有3天就到期了,请及时续费。',
|
||||||
warningDialogMessage: '您的自定义插件许可证还有3天就到期了,请及时续费。',
|
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,13 +1,13 @@
|
|||||||
import type { LicenseInfo, LicenseCheckResult } from '@/types/license';
|
import type { LicenseInfo, LicenseCheckResult } from '@/types/license';
|
||||||
import { LicenseStorage } from '@/utils/licenseStorage';
|
import { LicenseStorage } from '@/utils/LicenseStorage';
|
||||||
import { PermissionService } from '@/utils/permissions';
|
import { PermissionService } from '@/utils/permissions';
|
||||||
import { Notification } from 'kintone-ui-component/lib/notification';
|
import { Notification } from 'kintone-ui-component/lib/notification';
|
||||||
import { createApp } from 'vue';
|
import { MobileNotification } from 'kintone-ui-component/lib/mobile/notification';
|
||||||
import i18n from '@/i18n';
|
|
||||||
|
|
||||||
export class LicenseService {
|
export class LicenseService {
|
||||||
// 常量定义
|
// 常量定义
|
||||||
private static readonly WARNING_DAYS_BEFORE_EXPIRY = 7;
|
private static readonly WARNING_DAYS_BEFORE_EXPIRY = 7;
|
||||||
|
private static readonly TRIAL_DATE = 1;
|
||||||
private static PLUGIN_ID: string = '';
|
private static PLUGIN_ID: string = '';
|
||||||
// ============ 基础工具函数 ============
|
// ============ 基础工具函数 ============
|
||||||
|
|
||||||
@@ -45,24 +45,27 @@ export class LicenseService {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
const today = new Date();
|
|
||||||
// 检查存储是否过期(是否同一天)
|
// 检查存储是否过期(是否同一天)
|
||||||
const fetchDate = new Date(license.fetchTime).toDateString();
|
if (!this.isToday(license.fetchTime)) {
|
||||||
const todayStr = today.toDateString();
|
|
||||||
if (fetchDate !== todayStr) {
|
|
||||||
// 不是同一天,已过期
|
// 不是同一天,已过期
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 检查试用是否到期
|
// 检查试用是否到期
|
||||||
const expiredTime = new Date(license.expiredTime);
|
const expiredTime = new Date(license.expiredTime);
|
||||||
if (expiredTime < today) {
|
if (expiredTime < new Date()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true
|
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?: {
|
static async showExpiryWarning(license: any, options?: {
|
||||||
warningDialogTitle?: string;
|
|
||||||
warningDialogMessage?: string;
|
warningDialogMessage?: string;
|
||||||
}) {
|
}) {
|
||||||
const remainingDays = this.getDaysRemaining(license.expiredTime);
|
const remainingDays = this.getDaysRemaining(license.expiredTime);
|
||||||
const defaultMessage = `您的插件许可证将在 ${remainingDays} 天后到期,请及时续期以避免服务中断。`;
|
const msg = remainingDays > 0 ? ` ${remainingDays} 天后` : '今天'
|
||||||
|
const defaultMessage = `您的插件许可证将在${msg}到期,请及时续期以避免服务中断。`;
|
||||||
|
|
||||||
// 使用自定义消息或默认消息
|
// 使用自定义消息或默认消息
|
||||||
const message = options?.warningDialogMessage || defaultMessage;
|
const message = options?.warningDialogMessage || defaultMessage;
|
||||||
|
|
||||||
// 检查是否已设置不再提醒
|
// 检查是否已设置不再提醒
|
||||||
const dontShowKey = `license_notification_dont_show_again_${this.getPluginId()}`;
|
const settings = LicenseStorage.getSettings(this.getPluginId());
|
||||||
const dontShowAgain = localStorage.getItem(dontShowKey) === 'true';
|
if (settings.suppressMsgTime && this.isToday(settings.suppressMsgTime)) {
|
||||||
if (dontShowAgain) return;
|
return
|
||||||
|
}
|
||||||
|
delete settings.suppressMsgTime
|
||||||
|
LicenseStorage.saveSetting(settings, this.getPluginId());
|
||||||
|
|
||||||
// 使用KUC Notification
|
if (await kintone.isMobilePage()) {
|
||||||
const notification = new Notification({
|
const notification = new MobileNotification({
|
||||||
text: message,
|
text: message,
|
||||||
type: 'info',
|
});
|
||||||
duration: -1 // 不自动关闭
|
notification.open();
|
||||||
});
|
} else {
|
||||||
|
const notification = new Notification({
|
||||||
// 添加到页面
|
text: message,
|
||||||
const container = document.body;
|
type: 'info',
|
||||||
container.appendChild(notification);
|
});
|
||||||
|
notification.open();
|
||||||
// 监听关闭事件
|
}
|
||||||
notification.addEventListener('close', () => {
|
|
||||||
// 这里可以添加不再提醒的逻辑
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ============ 主要入口函数 ============
|
// ============ 主要入口函数 ============
|
||||||
@@ -203,7 +206,6 @@ export class LicenseService {
|
|||||||
options?: {
|
options?: {
|
||||||
expiryDialogTitle?: string;
|
expiryDialogTitle?: string;
|
||||||
expiryDialogMessage?: string;
|
expiryDialogMessage?: string;
|
||||||
warningDialogTitle?: string;
|
|
||||||
warningDialogMessage?: 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, {
|
||||||
// this.showExpiryWarning(licenseCheck.license, {
|
warningDialogMessage: options?.warningDialogMessage
|
||||||
// warningDialogTitle: options?.warningDialogTitle,
|
});
|
||||||
// warningDialogMessage: options?.warningDialogMessage
|
|
||||||
// });
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 许可证有效,可以加载插件功能
|
// 许可证有效,可以加载插件功能
|
||||||
@@ -275,7 +278,7 @@ export class LicenseService {
|
|||||||
*/
|
*/
|
||||||
private static mockCreateTrialLicense(): LicenseInfo {
|
private static mockCreateTrialLicense(): LicenseInfo {
|
||||||
const expiryDate = new Date();
|
const expiryDate = new Date();
|
||||||
expiryDate.setDate(expiryDate.getDate() + 30);
|
expiryDate.setDate(expiryDate.getDate() + this.TRIAL_DATE);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
expiredTime: expiryDate.getTime(),
|
expiredTime: expiryDate.getTime(),
|
||||||
@@ -283,6 +286,7 @@ export class LicenseService {
|
|||||||
domain: this.getDomain(),
|
domain: this.getDomain(),
|
||||||
pluginId: this.getPluginId(),
|
pluginId: this.getPluginId(),
|
||||||
fetchTime: new Date().getTime(),
|
fetchTime: new Date().getTime(),
|
||||||
|
version: 1,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
6
src/types/license.d.ts
vendored
6
src/types/license.d.ts
vendored
@@ -11,6 +11,12 @@ export interface LicenseInfo {
|
|||||||
pluginId: string;
|
pluginId: string;
|
||||||
// 获取许可证的时间戳
|
// 获取许可证的时间戳
|
||||||
fetchTime: number;
|
fetchTime: number;
|
||||||
|
// 版本号
|
||||||
|
version: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface LicenseSetting {
|
||||||
|
suppressMsgTime?: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface LicenseCheckResult {
|
export interface LicenseCheckResult {
|
||||||
|
|||||||
10
src/types/my-kintone.d.ts
vendored
10
src/types/my-kintone.d.ts
vendored
@@ -1,6 +1,16 @@
|
|||||||
// 导入官方 REST API 客户端的类型定义
|
// 导入官方 REST API 客户端的类型定义
|
||||||
import { KintoneFormFieldProperty } from '@kintone/rest-api-client';
|
import { KintoneFormFieldProperty } from '@kintone/rest-api-client';
|
||||||
|
|
||||||
|
declare global {
|
||||||
|
namespace kintone {
|
||||||
|
/**
|
||||||
|
* 判断当前页面是否为移动端页面
|
||||||
|
* @returns Promise<boolean> 返回是否为移动端页面
|
||||||
|
*/
|
||||||
|
function isMobilePage(): Promise<boolean>;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// KUC 组件事件类型定义
|
// KUC 组件事件类型定义
|
||||||
// 定义 kintone UI 组件触发事件的结构
|
// 定义 kintone UI 组件触发事件的结构
|
||||||
export interface KucEvent<T> {
|
export interface KucEvent<T> {
|
||||||
|
|||||||
@@ -1,9 +1,10 @@
|
|||||||
// 本地存储加密工具类
|
// 本地存储加密工具类
|
||||||
import { LicenseService } from '@/services/licenseService';
|
import { LicenseService } from '@/services/LicenseService';
|
||||||
import type { LicenseInfo } from '@/types/license';
|
import type { LicenseInfo, LicenseSetting } from '@/types/license';
|
||||||
|
|
||||||
export class LicenseStorage {
|
export class LicenseStorage {
|
||||||
private static readonly STORAGE_KEY_PREFIX = 'alicorns_plugin_';
|
private static readonly STORAGE_KEY_PREFIX = 'alicorns_plugin_';
|
||||||
|
private static readonly STORAGE_SETTING_KEY_PREFIX = this.STORAGE_KEY_PREFIX + 'setting_';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 生成存储key
|
* 生成存储key
|
||||||
@@ -38,7 +39,7 @@ export class LicenseStorage {
|
|||||||
|
|
||||||
const parsedData: LicenseInfo = JSON.parse(storedData);
|
const parsedData: LicenseInfo = JSON.parse(storedData);
|
||||||
|
|
||||||
const isValid = LicenseService.checkLicenseAvailable(parsedData)
|
const isValid = LicenseService.checkLicenseAvailable(parsedData);
|
||||||
if (!isValid) {
|
if (!isValid) {
|
||||||
// 获取许可证信息失败,清理存储
|
// 获取许可证信息失败,清理存储
|
||||||
this.clearLicense(pluginId);
|
this.clearLicense(pluginId);
|
||||||
@@ -62,4 +63,48 @@ export class LicenseStorage {
|
|||||||
localStorage.removeItem(key);
|
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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ export class PermissionService {
|
|||||||
static async checkPermissions(): Promise<PermissionConfig> {
|
static async checkPermissions(): Promise<PermissionConfig> {
|
||||||
try {
|
try {
|
||||||
// 获取应用信息
|
// 获取应用信息
|
||||||
const appId = kintone.app.getId();
|
const appId = kintone.app.getId() || kintone.mobile.app.getId();
|
||||||
if (!appId) {
|
if (!appId) {
|
||||||
return this.getDefaultPermissions();
|
return this.getDefaultPermissions();
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user