172 lines
5.8 KiB
Vue
172 lines
5.8 KiB
Vue
<template>
|
|
<div v-if="shown" class="license-status-info">
|
|
<div class="license-content">
|
|
<div class="license-status-text">
|
|
<strong>{{ $t('license.status.label') }}</strong>
|
|
<span v-if="licenseDisplayInfo" v-html="licenseStatusText"></span><span v-else> ... </span>
|
|
</div>
|
|
<div class="license-actions">
|
|
<template v-if="!licenseDisplayInfo.isPaid">
|
|
<button class="action-btn" @click="refreshLicenseStatus" :disabled="checking" ref="checkButton">{{ $t('license.button.checkLicense.label') }}</button>
|
|
<kuc-tooltip :title="$t('license.button.checkLicense.desc')" :container="checkButton"></kuc-tooltip>
|
|
<button class="action-btn main" @click="purchaseLicense" ref="buyButton">{{ $t('license.button.purchase.label') }}
|
|
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" class="open-icon">
|
|
<path d="M10 6H6a2 2 0 00-2 2v10a2 2 0 002 2h10a2 2 0 002-2v-4M14 4h6m0 0v6m0-6L10 14" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
|
</svg>
|
|
</button>
|
|
<kuc-tooltip :title="$t('license.button.purchase.desc')" :container="buyButton"></kuc-tooltip>
|
|
</template>
|
|
<button v-else class="action-btn" @click="hidePaidMsg">{{ $t('license.button.hide') }}</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
|
|
<script setup lang="ts">
|
|
import { ref, onMounted, computed, shallowRef } from 'vue';
|
|
import { useI18n } from 'vue-i18n';
|
|
import { LicenseService } from '@/services/license-service';
|
|
import type { LicenseInfo } from '@/types/license';
|
|
import { LicenseStorage } from '@/utils/license-storage';
|
|
|
|
const { t: $t } = useI18n();// 配置国际化
|
|
|
|
type LicenseDisplayInfo = {
|
|
isPaid: boolean;
|
|
expiryDate: string;
|
|
isExpired: boolean;
|
|
remainingDays: number;
|
|
};
|
|
|
|
// 状态管理
|
|
const licenseInfo = ref<LicenseInfo | undefined>();
|
|
const loading = ref(true);
|
|
const shown = ref(false);
|
|
const checking = ref(false);
|
|
const checkButton = shallowRef<HTMLButtonElement | null>(null);
|
|
const buyButton = shallowRef<HTMLButtonElement | null>(null);
|
|
|
|
// 许可证显示信息
|
|
const licenseDisplayInfo = computed<LicenseDisplayInfo>(() => {
|
|
if (!licenseInfo.value || loading.value) {
|
|
return {
|
|
isPaid: false,
|
|
expiryDate: $t('license.status.unknown'),
|
|
isExpired: false,
|
|
remainingDays: 1,
|
|
};
|
|
}
|
|
|
|
return {
|
|
isPaid: licenseInfo.value.isPaid,
|
|
expiryDate: LicenseService.formatExpiryDate(licenseInfo.value.expiredTime),
|
|
isExpired: licenseInfo.value.expiredTime < Date.now() && !licenseInfo.value.isPaid,
|
|
remainingDays: LicenseService.getDaysRemaining(licenseInfo.value.expiredTime),
|
|
};
|
|
});
|
|
|
|
onMounted(async () => {
|
|
const result = await LicenseService.checkLicense();
|
|
await new Promise((resolve) => setTimeout(resolve, 500));
|
|
licenseInfo.value = result.license;
|
|
|
|
shown.value = isPaidAreaShown();
|
|
if (!shown.value) {
|
|
addPaidLabel();
|
|
}
|
|
loading.value = false;
|
|
});
|
|
|
|
const addPaidLabel = () => {
|
|
const isExist = !!document.querySelector('#license-label')
|
|
if (!shown.value && !isExist) {
|
|
const spanElement = document.createElement('span');
|
|
spanElement.textContent = $t('license.status.permanent'),
|
|
spanElement.id = 'license-label';
|
|
document.querySelector('#app > .settings-heading')?.appendChild(spanElement);
|
|
}
|
|
}
|
|
|
|
const isPaidAreaShown = () => {
|
|
if (!licenseInfo.value?.isPaid) {
|
|
return true;
|
|
}
|
|
const settings = LicenseStorage.getSettings(licenseInfo.value.pluginId);
|
|
if (settings.hideLicenseAreaIfPaid) {
|
|
return false;
|
|
}
|
|
return true;
|
|
};
|
|
|
|
const licenseStatusText = computed(() => {
|
|
if (!licenseDisplayInfo.value) {
|
|
return $t('license.status.unknown');
|
|
}
|
|
|
|
if (loading.value) {
|
|
return $t('license.status.checking');
|
|
}
|
|
|
|
if (licenseDisplayInfo.value.isPaid) {
|
|
return `<span class="text-green">${$t('license.status.permanentDisplay')}</span>`;
|
|
}
|
|
|
|
let status = $t('license.expiry.expiryDate', { date: licenseDisplayInfo.value.expiryDate });
|
|
|
|
if (licenseDisplayInfo.value.isExpired) {
|
|
status += `(<span class="text-red">${$t('license.status.expired')}</span>)`;
|
|
return status;
|
|
}
|
|
|
|
const remainingDays = licenseDisplayInfo.value.remainingDays;
|
|
const days = $t('license.notification.days', remainingDays)
|
|
status += `(${days})`;
|
|
|
|
return status;
|
|
});
|
|
|
|
async function refreshLicenseStatus() {
|
|
checking.value = true;
|
|
loading.value = true;
|
|
// 模拟加载时间,展示 spinner 效果
|
|
await new Promise((resolve) => setTimeout(resolve, 500));
|
|
|
|
const result = await LicenseService.forceRefreshLicense();
|
|
licenseInfo.value = result.license;
|
|
loading.value = false;
|
|
checking.value = false;
|
|
}
|
|
|
|
function purchaseLicense() {
|
|
const { name, email } = kintone.getLoginUser();
|
|
const domain = licenseInfo.value?.domain;
|
|
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 }
|
|
};
|
|
|
|
const queryParams = Object.values(params)
|
|
.filter(param => param.value)
|
|
.map(param => `${param.inputId}=${encodeURIComponent(param.value as string)}`)
|
|
.join('&');
|
|
|
|
window.open(`https://alisurvey.alicorns.co.jp/s/Iuc5RxZv?${queryParams}`);
|
|
}
|
|
|
|
function hidePaidMsg() {
|
|
const pluginId = licenseInfo.value?.pluginId;
|
|
if (!pluginId) {
|
|
return;
|
|
}
|
|
const settings = LicenseStorage.getSettings(pluginId);
|
|
settings.hideLicenseAreaIfPaid = true;
|
|
LicenseStorage.saveSetting(settings, pluginId);
|
|
shown.value = false;
|
|
addPaidLabel();
|
|
}
|
|
</script>
|