|
@@ -1,135 +1,405 @@
|
|
|
<template>
|
|
<template>
|
|
|
<BasicModal
|
|
<BasicModal
|
|
|
v-bind="$attrs"
|
|
v-bind="$attrs"
|
|
|
- title="授权信息"
|
|
|
|
|
:width="980"
|
|
:width="980"
|
|
|
:centered="true"
|
|
:centered="true"
|
|
|
:showCancelBtn="false"
|
|
:showCancelBtn="false"
|
|
|
@register="registerModal"
|
|
@register="registerModal"
|
|
|
@ok="closeModal"
|
|
@ok="closeModal"
|
|
|
>
|
|
>
|
|
|
|
|
+ <template #title>
|
|
|
|
|
+ <div class="authorization-info__title">
|
|
|
|
|
+ <span class="authorization-info__title-icon">
|
|
|
|
|
+ <SafetyCertificateOutlined />
|
|
|
|
|
+ </span>
|
|
|
|
|
+ <span>授权信息</span>
|
|
|
|
|
+ <Tooltip v-if="usingMock" title="开发环境未获取到真实授权数据,当前展示演示数据">
|
|
|
|
|
+ <span class="authorization-info__mock-chip">演示数据</span>
|
|
|
|
|
+ </Tooltip>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </template>
|
|
|
|
|
+
|
|
|
<div :class="prefixCls">
|
|
<div :class="prefixCls">
|
|
|
- <div v-if="loading" class="authorization-info__loading">正在加载授权信息...</div>
|
|
|
|
|
|
|
+ <div v-if="loading" class="authorization-info__loading">
|
|
|
|
|
+ <Skeleton active :paragraph="{ rows: 8 }" />
|
|
|
|
|
+ </div>
|
|
|
|
|
+
|
|
|
|
|
+ <template v-else-if="hasDisplayData">
|
|
|
|
|
+ <section class="authorization-info__hero" :class="statusClass">
|
|
|
|
|
+ <div class="authorization-info__hero-main">
|
|
|
|
|
+ <span class="authorization-info__hero-icon">
|
|
|
|
|
+ <SafetyCertificateOutlined />
|
|
|
|
|
+ </span>
|
|
|
|
|
+ <div class="authorization-info__hero-content">
|
|
|
|
|
+ <div class="authorization-info__hero-title">
|
|
|
|
|
+ <span class="authorization-info__status">{{ statusText }}</span>
|
|
|
|
|
+ <span class="authorization-info__status-hint">{{ statusHint }}</span>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ <div class="authorization-info__hero-subject">{{ unit }}</div>
|
|
|
|
|
+ <div class="authorization-info__hero-meta">
|
|
|
|
|
+ <CalendarOutlined />
|
|
|
|
|
+ <span>授权有效期:{{ expiryText }}</span>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ <div class="authorization-info__hero-stat">
|
|
|
|
|
+ <span class="authorization-info__hero-stat-value" :class="{ 'is-text': isRemainingText }">
|
|
|
|
|
+ {{ remainingValue }}
|
|
|
|
|
+ </span>
|
|
|
|
|
+ <span class="authorization-info__hero-stat-label">{{ remainingLabel }}</span>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </section>
|
|
|
|
|
|
|
|
- <div v-else-if="infoItems.length">
|
|
|
|
|
- <div v-if="isAuthorizationExpiredState" class="authorization-info__expired-banner">
|
|
|
|
|
- {{ authorizationExpiredMessage }}
|
|
|
|
|
|
|
+ <div v-if="usingMock" class="authorization-info__mock-switch">
|
|
|
|
|
+ <span class="authorization-info__mock-switch-label">演示状态</span>
|
|
|
|
|
+ <button
|
|
|
|
|
+ v-for="option in MOCK_STATUS_OPTIONS"
|
|
|
|
|
+ :key="option.value"
|
|
|
|
|
+ type="button"
|
|
|
|
|
+ class="authorization-info__mock-switch-item"
|
|
|
|
|
+ :class="{ 'is-active': mockStatus === option.value }"
|
|
|
|
|
+ @click="setMockStatus(option.value)"
|
|
|
|
|
+ >
|
|
|
|
|
+ {{ option.label }}
|
|
|
|
|
+ </button>
|
|
|
</div>
|
|
</div>
|
|
|
- <div v-else-if="isTrialAuthorization" class="authorization-info__trial-banner">试用授权</div>
|
|
|
|
|
- <div class="authorization-info__list">
|
|
|
|
|
- <div v-for="item in infoItems" :key="item.key" class="authorization-info__item">
|
|
|
|
|
- <div class="authorization-info__label">{{ item.label }}</div>
|
|
|
|
|
- <div
|
|
|
|
|
- class="authorization-info__value"
|
|
|
|
|
- :class="{
|
|
|
|
|
- 'is-trial-value': item.key === 'overDateTime' && isTrialAuthorization,
|
|
|
|
|
- 'is-expired-value': item.key === 'overDateTime' && isAuthorizationExpiredState,
|
|
|
|
|
- }"
|
|
|
|
|
- >
|
|
|
|
|
- {{ item.value }}
|
|
|
|
|
|
|
+
|
|
|
|
|
+ <div class="authorization-info__columns">
|
|
|
|
|
+ <section class="authorization-info__section">
|
|
|
|
|
+ <header class="authorization-info__section-head">
|
|
|
|
|
+ <TeamOutlined />
|
|
|
|
|
+ <span>客户信息</span>
|
|
|
|
|
+ </header>
|
|
|
|
|
+ <div class="authorization-info__fields">
|
|
|
|
|
+ <div class="authorization-info__field">
|
|
|
|
|
+ <span class="authorization-info__field-label">客户编号</span>
|
|
|
|
|
+ <span class="authorization-info__field-value">{{ customerNo }}</span>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ <div class="authorization-info__field">
|
|
|
|
|
+ <span class="authorization-info__field-label">所属单位</span>
|
|
|
|
|
+ <span class="authorization-info__field-value">{{ unit }}</span>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ <div class="authorization-info__field">
|
|
|
|
|
+ <span class="authorization-info__field-label">联系电话</span>
|
|
|
|
|
+ <span class="authorization-info__field-value">{{ phone }}</span>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </section>
|
|
|
|
|
+
|
|
|
|
|
+ <section class="authorization-info__section">
|
|
|
|
|
+ <header class="authorization-info__section-head">
|
|
|
|
|
+ <CalendarOutlined />
|
|
|
|
|
+ <span>授权信息</span>
|
|
|
|
|
+ </header>
|
|
|
|
|
+ <div class="authorization-info__fields">
|
|
|
|
|
+ <div class="authorization-info__field">
|
|
|
|
|
+ <span class="authorization-info__field-label">授权类型</span>
|
|
|
|
|
+ <span class="authorization-info__field-value">{{ statusText }}</span>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ <div class="authorization-info__field">
|
|
|
|
|
+ <span class="authorization-info__field-label">激活时间</span>
|
|
|
|
|
+ <span class="authorization-info__field-value">{{ activeDateTimeText }}</span>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ <div class="authorization-info__field">
|
|
|
|
|
+ <span class="authorization-info__field-label">授权时间</span>
|
|
|
|
|
+ <span class="authorization-info__field-value">{{ authDateTimeText }}</span>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ <div class="authorization-info__field">
|
|
|
|
|
+ <span class="authorization-info__field-label">授权到期</span>
|
|
|
|
|
+ <span class="authorization-info__field-value">{{ expiryText }}</span>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </section>
|
|
|
|
|
+ </div>
|
|
|
|
|
+
|
|
|
|
|
+ <section class="authorization-info__section authorization-info__section--device">
|
|
|
|
|
+ <header class="authorization-info__section-head">
|
|
|
|
|
+ <DesktopOutlined />
|
|
|
|
|
+ <span>设备信息</span>
|
|
|
|
|
+ </header>
|
|
|
|
|
+ <div class="authorization-info__machine">
|
|
|
|
|
+ <div class="authorization-info__machine-main">
|
|
|
|
|
+ <span class="authorization-info__field-label">机器码</span>
|
|
|
|
|
+ <span class="authorization-info__machine-code" :title="machineCode">{{ machineCode }}</span>
|
|
|
</div>
|
|
</div>
|
|
|
|
|
+ <Button size="small" class="authorization-info__copy-btn" @click="copyMachineCode">
|
|
|
|
|
+ <CopyOutlined />
|
|
|
|
|
+ 复制
|
|
|
|
|
+ </Button>
|
|
|
</div>
|
|
</div>
|
|
|
|
|
+ </section>
|
|
|
|
|
+
|
|
|
|
|
+ <div v-if="messageText" class="authorization-info__note">
|
|
|
|
|
+ <InfoCircleOutlined class="authorization-info__note-icon" />
|
|
|
|
|
+ <span>{{ messageText }}</span>
|
|
|
</div>
|
|
</div>
|
|
|
- </div>
|
|
|
|
|
|
|
+ </template>
|
|
|
|
|
|
|
|
- <div v-else class="authorization-info__empty">暂无授权信息</div>
|
|
|
|
|
|
|
+ <div v-else class="authorization-info__empty">
|
|
|
|
|
+ <SafetyCertificateOutlined class="authorization-info__empty-icon" />
|
|
|
|
|
+ <div class="authorization-info__empty-title">暂无授权信息</div>
|
|
|
|
|
+ <div class="authorization-info__empty-desc">请联系管理员确认授权状态,或重新导入授权文件。</div>
|
|
|
|
|
+ </div>
|
|
|
</div>
|
|
</div>
|
|
|
</BasicModal>
|
|
</BasicModal>
|
|
|
</template>
|
|
</template>
|
|
|
|
|
|
|
|
<script lang="ts" setup>
|
|
<script lang="ts" setup>
|
|
|
- import { computed, ref, watch, unref } from 'vue';
|
|
|
|
|
|
|
+ import { computed, ref, unref, watch } from 'vue';
|
|
|
|
|
+ import { Button, Skeleton, Tooltip } from 'ant-design-vue';
|
|
|
|
|
+ import {
|
|
|
|
|
+ CalendarOutlined,
|
|
|
|
|
+ CopyOutlined,
|
|
|
|
|
+ DesktopOutlined,
|
|
|
|
|
+ InfoCircleOutlined,
|
|
|
|
|
+ SafetyCertificateOutlined,
|
|
|
|
|
+ TeamOutlined,
|
|
|
|
|
+ } from '@ant-design/icons-vue';
|
|
|
import { BasicModal, useModalInner } from '@/core/components/Modal';
|
|
import { BasicModal, useModalInner } from '@/core/components/Modal';
|
|
|
import { useDesign } from '@/core/hooks/web/useDesign';
|
|
import { useDesign } from '@/core/hooks/web/useDesign';
|
|
|
import { useMessage } from '@/core/hooks/web/useMessage';
|
|
import { useMessage } from '@/core/hooks/web/useMessage';
|
|
|
import { authorizationInfoApi } from '@/core/api/sys/login';
|
|
import { authorizationInfoApi } from '@/core/api/sys/login';
|
|
|
- import {
|
|
|
|
|
- extractAuthorizationCache,
|
|
|
|
|
- getAuthorizationExpiredMessage,
|
|
|
|
|
- isAuthorizationExpired,
|
|
|
|
|
- isFormalAuthorization,
|
|
|
|
|
- } from '@/core/utils/license';
|
|
|
|
|
|
|
+ import { extractAuthorizationCache, isAuthorizationExpired, isFormalAuthorization } from '@/core/utils/license';
|
|
|
import { useUserStore } from '@/core/store/modules/case';
|
|
import { useUserStore } from '@/core/store/modules/case';
|
|
|
|
|
|
|
|
const { prefixCls } = useDesign('authorization-info-modal');
|
|
const { prefixCls } = useDesign('authorization-info-modal');
|
|
|
const { createMessage } = useMessage();
|
|
const { createMessage } = useMessage();
|
|
|
const userStore = useUserStore();
|
|
const userStore = useUserStore();
|
|
|
|
|
+ const isDev = import.meta.env.DEV;
|
|
|
|
|
+
|
|
|
|
|
+ type MockStatus = 'formal' | 'trial' | 'expired';
|
|
|
|
|
+
|
|
|
|
|
+ const MOCK_STATUS_OPTIONS: Array<{ label: string; value: MockStatus }> = [
|
|
|
|
|
+ { label: '正式授权', value: 'formal' },
|
|
|
|
|
+ { label: '试用授权', value: 'trial' },
|
|
|
|
|
+ { label: '已过期', value: 'expired' },
|
|
|
|
|
+ ];
|
|
|
|
|
+
|
|
|
|
|
+ const MOCK_BASE = {
|
|
|
|
|
+ clientNo: 'QJ-2026-0086',
|
|
|
|
|
+ unit: '中数矩阵(成都)科技有限公司',
|
|
|
|
|
+ phone: '18908093240',
|
|
|
|
|
+ machinecode: 'A9DEBA7C48078E4B78A79A8609EEA5ABA96FAA137E3A720F4E69B01FEF090164',
|
|
|
|
|
+ activeDateTime: '2026-03-01 09:00:00',
|
|
|
|
|
+ authdatetime: '2026-03-01',
|
|
|
|
|
+ };
|
|
|
|
|
+
|
|
|
|
|
+ /** 开发环境演示数据:接口无真实授权信息时用来看排版与三种授权状态 */
|
|
|
|
|
+ const MOCK_AUTHORIZATION_INFO: Record<MockStatus, Record<string, any>> = {
|
|
|
|
|
+ formal: {
|
|
|
|
|
+ ...MOCK_BASE,
|
|
|
|
|
+ overdatetime: '2099-09-09',
|
|
|
|
|
+ message: '正式授权,长期有效。',
|
|
|
|
|
+ },
|
|
|
|
|
+ trial: {
|
|
|
|
|
+ ...MOCK_BASE,
|
|
|
|
|
+ overdatetime: '2027-03-01',
|
|
|
|
|
+ remainingDate: 126,
|
|
|
|
|
+ message: '试用授权,到期前请及时导入正式授权文件。',
|
|
|
|
|
+ },
|
|
|
|
|
+ expired: {
|
|
|
|
|
+ ...MOCK_BASE,
|
|
|
|
|
+ overdatetime: '2026-05-01',
|
|
|
|
|
+ remainingDate: 0,
|
|
|
|
|
+ message: '授权已于 2026-05-01 过期,请重新导入有效授权文件。',
|
|
|
|
|
+ },
|
|
|
|
|
+ };
|
|
|
|
|
|
|
|
const loading = ref(false);
|
|
const loading = ref(false);
|
|
|
const info = ref<Record<string, any> | null>(null);
|
|
const info = ref<Record<string, any> | null>(null);
|
|
|
|
|
+ const usingMock = ref(false);
|
|
|
|
|
+ const mockStatus = ref<MockStatus>('formal');
|
|
|
|
|
|
|
|
function normalizeFieldKey(value: string) {
|
|
function normalizeFieldKey(value: string) {
|
|
|
return value.replace(/[^a-zA-Z0-9]/g, '').toLowerCase();
|
|
return value.replace(/[^a-zA-Z0-9]/g, '').toLowerCase();
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- const overDateTimeValue = computed(() => {
|
|
|
|
|
- const source = info.value || {};
|
|
|
|
|
- const matchedKey = ['overDateTime', 'overdatetime'].find((key) =>
|
|
|
|
|
- Object.prototype.hasOwnProperty.call(source, key),
|
|
|
|
|
|
|
+ function pickField(source: Record<string, any>, keys: string[]) {
|
|
|
|
|
+ if (!source) return undefined;
|
|
|
|
|
+ const matchedKey = keys.find((key) => Object.prototype.hasOwnProperty.call(source, key));
|
|
|
|
|
+ if (matchedKey) return source[matchedKey];
|
|
|
|
|
+ const normalizedKey = Object.keys(source).find((key) =>
|
|
|
|
|
+ keys.some((item) => normalizeFieldKey(item) === normalizeFieldKey(key)),
|
|
|
);
|
|
);
|
|
|
- const matchedNormalizedKey = Object.keys(source).find((key) =>
|
|
|
|
|
- ['overDateTime', 'overdatetime'].some((item) => normalizeFieldKey(item) === normalizeFieldKey(key)),
|
|
|
|
|
- );
|
|
|
|
|
- const value = matchedKey ? source[matchedKey] : matchedNormalizedKey ? source[matchedNormalizedKey] : undefined;
|
|
|
|
|
- return value === null || value === undefined ? '' : `${value}`.trim();
|
|
|
|
|
|
|
+ return normalizedKey ? source[normalizedKey] : undefined;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ function formatDate(value?: unknown) {
|
|
|
|
|
+ const text = String(value ?? '').trim();
|
|
|
|
|
+ if (!text) return '—';
|
|
|
|
|
+ return text.replace('T', ' ').split(' ')[0];
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ function formatDateTime(value?: unknown) {
|
|
|
|
|
+ const text = String(value ?? '').trim();
|
|
|
|
|
+ if (!text) return '—';
|
|
|
|
|
+ return text.replace('T', ' ').replace(/\.\d+$/, '');
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ function calcRemainingDays(overDateTime: string) {
|
|
|
|
|
+ if (!overDateTime) return null;
|
|
|
|
|
+ const end = new Date(overDateTime.replace(/-/g, '/'));
|
|
|
|
|
+ if (Number.isNaN(end.getTime())) return null;
|
|
|
|
|
+ const now = new Date();
|
|
|
|
|
+ const endDay = new Date(end.getFullYear(), end.getMonth(), end.getDate());
|
|
|
|
|
+ const today = new Date(now.getFullYear(), now.getMonth(), now.getDate());
|
|
|
|
|
+ return Math.ceil((endDay.getTime() - today.getTime()) / 86400000);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ const activeInfo = computed<Record<string, any>>(() => {
|
|
|
|
|
+ if (usingMock.value) return MOCK_AUTHORIZATION_INFO[mockStatus.value];
|
|
|
|
|
+ return info.value || {};
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ const hasDisplayData = computed(() => usingMock.value || Object.keys(activeInfo.value).length > 0);
|
|
|
|
|
+
|
|
|
|
|
+ const overDateTimeValue = computed(() => {
|
|
|
|
|
+ const value = pickField(activeInfo.value, ['overDateTime', 'overdatetime']);
|
|
|
|
|
+ return value === null || value === undefined ? '' : String(value).trim();
|
|
|
});
|
|
});
|
|
|
|
|
|
|
|
- const isTrialAuthorization = computed(
|
|
|
|
|
- () => !!overDateTimeValue.value && !isFormalAuthorization(overDateTimeValue.value),
|
|
|
|
|
|
|
+ const isExpired = computed(() => isAuthorizationExpired(overDateTimeValue.value));
|
|
|
|
|
+ const isFormal = computed(() => isFormalAuthorization(overDateTimeValue.value));
|
|
|
|
|
+ const isTrial = computed(() => !!overDateTimeValue.value && !isFormal.value);
|
|
|
|
|
+
|
|
|
|
|
+ const statusClass = computed(() => {
|
|
|
|
|
+ if (isExpired.value) return 'is-expired';
|
|
|
|
|
+ if (isTrial.value) return 'is-trial';
|
|
|
|
|
+ if (isFormal.value) return 'is-formal';
|
|
|
|
|
+ return 'is-unknown';
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ const statusText = computed(() => {
|
|
|
|
|
+ if (isExpired.value) return '已过期';
|
|
|
|
|
+ if (isTrial.value) return '试用授权';
|
|
|
|
|
+ if (isFormal.value) return '正式授权';
|
|
|
|
|
+ return '授权信息';
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ const statusHint = computed(() => {
|
|
|
|
|
+ if (isExpired.value) {
|
|
|
|
|
+ return overDateTimeValue.value ? `已于 ${formatDate(overDateTimeValue.value)} 过期` : '授权已过期';
|
|
|
|
|
+ }
|
|
|
|
|
+ if (isTrial.value) {
|
|
|
|
|
+ return `试用期至 ${formatDate(overDateTimeValue.value)}`;
|
|
|
|
|
+ }
|
|
|
|
|
+ if (isFormal.value) {
|
|
|
|
|
+ return '长期有效,无需续期';
|
|
|
|
|
+ }
|
|
|
|
|
+ return '未获取到授权有效期';
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ const remainingDays = computed(() => {
|
|
|
|
|
+ if (isFormal.value) return null;
|
|
|
|
|
+ const raw = pickField(activeInfo.value, ['remainingDate', 'remainingdate']);
|
|
|
|
|
+ const numeric = Number(raw);
|
|
|
|
|
+ if (raw !== null && raw !== undefined && `${raw}`.trim() !== '' && Number.isFinite(numeric)) {
|
|
|
|
|
+ return Math.max(0, Math.trunc(numeric));
|
|
|
|
|
+ }
|
|
|
|
|
+ const calculated = calcRemainingDays(overDateTimeValue.value);
|
|
|
|
|
+ return calculated === null ? null : Math.max(0, calculated);
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ const remainingValue = computed(() => {
|
|
|
|
|
+ if (isFormal.value) return '长期';
|
|
|
|
|
+ if (isExpired.value) return '已过期';
|
|
|
|
|
+ return remainingDays.value === null ? '—' : String(remainingDays.value);
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ const remainingLabel = computed(() => {
|
|
|
|
|
+ if (isFormal.value) return '授权期限';
|
|
|
|
|
+ if (isExpired.value) return '当前状态';
|
|
|
|
|
+ return '剩余天数';
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ const isRemainingText = computed(() => isFormal.value || isExpired.value || remainingDays.value === null);
|
|
|
|
|
+
|
|
|
|
|
+ const expiryText = computed(() => (isFormal.value ? '长期有效' : formatDate(overDateTimeValue.value)));
|
|
|
|
|
+
|
|
|
|
|
+ const unit = computed(() => {
|
|
|
|
|
+ const value = pickField(activeInfo.value, ['unit']);
|
|
|
|
|
+ return String(value ?? '').trim() || '未设置授权单位';
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ const customerNo = computed(() => {
|
|
|
|
|
+ const value = pickField(activeInfo.value, ['clientNo', 'clientno']);
|
|
|
|
|
+ return String(value ?? '').trim() || '—';
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ const phone = computed(() => {
|
|
|
|
|
+ const value = pickField(activeInfo.value, ['phone']);
|
|
|
|
|
+ return String(value ?? '').trim() || '—';
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ const machineCode = computed(() => {
|
|
|
|
|
+ const value = pickField(activeInfo.value, ['machinecode', 'machineCode']);
|
|
|
|
|
+ return String(value ?? '').trim() || '—';
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ const activeDateTimeText = computed(() =>
|
|
|
|
|
+ formatDateTime(pickField(activeInfo.value, ['activeDateTime', 'activateDateTime', 'activatetime'])),
|
|
|
);
|
|
);
|
|
|
- const isAuthorizationExpiredState = computed(() => isAuthorizationExpired(overDateTimeValue.value));
|
|
|
|
|
- const authorizationExpiredMessage = computed(() => getAuthorizationExpiredMessage(overDateTimeValue.value));
|
|
|
|
|
-
|
|
|
|
|
- const infoItems = computed(() => {
|
|
|
|
|
- const source = info.value || {};
|
|
|
|
|
- const fieldList = [
|
|
|
|
|
- { keys: ['clientNo'], label: '客户名称' },
|
|
|
|
|
- { keys: ['unit'], label: '所属单位' },
|
|
|
|
|
- { keys: ['phone'], label: '联系电话' },
|
|
|
|
|
- { keys: ['activeDateTime', 'activateDateTime', 'activatetime'], label: '激活时间' },
|
|
|
|
|
- { keys: ['authDateTime', 'authdatetime'], label: '授权时间' },
|
|
|
|
|
- {
|
|
|
|
|
- keys: ['overDateTime', 'overdatetime'],
|
|
|
|
|
- label: isTrialAuthorization.value ? '试用结束时间' : '授权结束时间',
|
|
|
|
|
- },
|
|
|
|
|
- { keys: ['remainingDate', 'remainingdate'], label: '剩余天数' },
|
|
|
|
|
- { keys: ['message'], label: '说明' },
|
|
|
|
|
- ];
|
|
|
|
|
-
|
|
|
|
|
- return fieldList
|
|
|
|
|
- .map(({ keys, label }) => {
|
|
|
|
|
- const matchedKey = keys.find((key) => Object.prototype.hasOwnProperty.call(source, key));
|
|
|
|
|
- const matchedNormalizedKey = Object.keys(source).find((key) =>
|
|
|
|
|
- keys.some((item) => normalizeFieldKey(item) === normalizeFieldKey(key)),
|
|
|
|
|
- );
|
|
|
|
|
- const value = matchedKey ? source[matchedKey] : matchedNormalizedKey ? source[matchedNormalizedKey] : undefined;
|
|
|
|
|
- if (value === null || value === undefined || `${value}` === '') return null;
|
|
|
|
|
- return {
|
|
|
|
|
- key: keys[0],
|
|
|
|
|
- label,
|
|
|
|
|
- value: `${value}`,
|
|
|
|
|
- };
|
|
|
|
|
- })
|
|
|
|
|
- .filter(Boolean) as Array<{ key: string; label: string; value: string }>;
|
|
|
|
|
|
|
+
|
|
|
|
|
+ const authDateTimeText = computed(() => formatDate(pickField(activeInfo.value, ['authDateTime', 'authdatetime'])));
|
|
|
|
|
+
|
|
|
|
|
+ const messageText = computed(() => {
|
|
|
|
|
+ const value = pickField(activeInfo.value, ['message']);
|
|
|
|
|
+ return String(value ?? '').trim();
|
|
|
});
|
|
});
|
|
|
|
|
|
|
|
const [registerModal, { closeModal, setModalProps, getOpen }] = useModalInner();
|
|
const [registerModal, { closeModal, setModalProps, getOpen }] = useModalInner();
|
|
|
|
|
|
|
|
|
|
+ function setMockStatus(status: MockStatus) {
|
|
|
|
|
+ mockStatus.value = status;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ async function copyMachineCode() {
|
|
|
|
|
+ if (!machineCode.value || machineCode.value === '—') return;
|
|
|
|
|
+ try {
|
|
|
|
|
+ await navigator.clipboard.writeText(machineCode.value);
|
|
|
|
|
+ createMessage.success('机器码已复制');
|
|
|
|
|
+ } catch {
|
|
|
|
|
+ createMessage.error('复制失败,请手动选择复制');
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
async function loadAuthorizationInfo() {
|
|
async function loadAuthorizationInfo() {
|
|
|
loading.value = true;
|
|
loading.value = true;
|
|
|
info.value = null;
|
|
info.value = null;
|
|
|
|
|
+ usingMock.value = false;
|
|
|
setModalProps({ confirmLoading: false });
|
|
setModalProps({ confirmLoading: false });
|
|
|
try {
|
|
try {
|
|
|
const res = await authorizationInfoApi();
|
|
const res = await authorizationInfoApi();
|
|
|
const raw = (res as Record<string, any> | null) || null;
|
|
const raw = (res as Record<string, any> | null) || null;
|
|
|
const payload =
|
|
const payload =
|
|
|
- raw && typeof raw === 'object' && 'data' in raw && raw.data && typeof raw.data === 'object' ? raw.data : raw;
|
|
|
|
|
- info.value = (payload as Record<string, any> | null) || null;
|
|
|
|
|
|
|
+ raw && typeof raw === 'object' && 'data' in raw
|
|
|
|
|
+ ? raw.data && typeof raw.data === 'object'
|
|
|
|
|
+ ? raw.data
|
|
|
|
|
+ : null
|
|
|
|
|
+ : raw;
|
|
|
|
|
+ const hasData =
|
|
|
|
|
+ !!payload &&
|
|
|
|
|
+ Object.entries(payload).some(([, value]) => value !== null && value !== undefined && `${value}`.trim() !== '');
|
|
|
|
|
+
|
|
|
|
|
+ if (!hasData) {
|
|
|
|
|
+ if (isDev) {
|
|
|
|
|
+ usingMock.value = true;
|
|
|
|
|
+ mockStatus.value = 'formal';
|
|
|
|
|
+ }
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ info.value = payload;
|
|
|
const { authorizationLabel, overDateTime, authorizationUnit } = extractAuthorizationCache(payload);
|
|
const { authorizationLabel, overDateTime, authorizationUnit } = extractAuthorizationCache(payload);
|
|
|
userStore.setPageCache('authorizationLabel', authorizationLabel);
|
|
userStore.setPageCache('authorizationLabel', authorizationLabel);
|
|
|
userStore.setPageCache('licenseOverDateTime', overDateTime);
|
|
userStore.setPageCache('licenseOverDateTime', overDateTime);
|
|
|
userStore.setPageCache('authorizationUnit', authorizationUnit);
|
|
userStore.setPageCache('authorizationUnit', authorizationUnit);
|
|
|
} catch (error: any) {
|
|
} catch (error: any) {
|
|
|
|
|
+ if (isDev) {
|
|
|
|
|
+ usingMock.value = true;
|
|
|
|
|
+ mockStatus.value = 'formal';
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
createMessage.error(error?.message || '获取授权信息失败,请稍后重试');
|
|
createMessage.error(error?.message || '获取授权信息失败,请稍后重试');
|
|
|
} finally {
|
|
} finally {
|
|
|
loading.value = false;
|
|
loading.value = false;
|
|
@@ -150,88 +420,383 @@
|
|
|
@prefix-cls: ~'jeesite-authorization-info-modal';
|
|
@prefix-cls: ~'jeesite-authorization-info-modal';
|
|
|
|
|
|
|
|
.@{prefix-cls} {
|
|
.@{prefix-cls} {
|
|
|
- padding-right: 8px;
|
|
|
|
|
- min-height: 520px;
|
|
|
|
|
display: flex;
|
|
display: flex;
|
|
|
flex-direction: column;
|
|
flex-direction: column;
|
|
|
|
|
+ gap: 16px;
|
|
|
|
|
+ padding-right: 4px;
|
|
|
|
|
|
|
|
- .authorization-info__loading,
|
|
|
|
|
- .authorization-info__empty {
|
|
|
|
|
- min-height: 420px;
|
|
|
|
|
- padding: 46px 0;
|
|
|
|
|
|
|
+ .authorization-info__title {
|
|
|
|
|
+ display: inline-flex;
|
|
|
|
|
+ align-items: center;
|
|
|
|
|
+ gap: 10px;
|
|
|
|
|
+ color: #111827;
|
|
|
font-size: 16px;
|
|
font-size: 16px;
|
|
|
- color: #6b7280;
|
|
|
|
|
- text-align: center;
|
|
|
|
|
|
|
+ font-weight: 600;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- .authorization-info__list {
|
|
|
|
|
- display: grid;
|
|
|
|
|
- grid-template-columns: repeat(2, minmax(0, 1fr));
|
|
|
|
|
|
|
+ .authorization-info__title-icon {
|
|
|
|
|
+ display: inline-flex;
|
|
|
|
|
+ align-items: center;
|
|
|
|
|
+ justify-content: center;
|
|
|
|
|
+ width: 28px;
|
|
|
|
|
+ height: 28px;
|
|
|
|
|
+ color: #fff;
|
|
|
|
|
+ font-size: 16px;
|
|
|
|
|
+ background: #2a50ec;
|
|
|
|
|
+ border-radius: 9px;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ .authorization-info__mock-chip {
|
|
|
|
|
+ padding: 0 8px;
|
|
|
|
|
+ color: #b45309;
|
|
|
|
|
+ font-size: 11px;
|
|
|
|
|
+ font-weight: 500;
|
|
|
|
|
+ line-height: 20px;
|
|
|
|
|
+ background: #fff7ed;
|
|
|
|
|
+ border: 1px solid #fed7aa;
|
|
|
|
|
+ border-radius: 10px;
|
|
|
|
|
+ cursor: default;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ .authorization-info__loading {
|
|
|
|
|
+ padding: 8px 4px;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ .authorization-info__hero {
|
|
|
|
|
+ display: flex;
|
|
|
|
|
+ align-items: center;
|
|
|
|
|
+ justify-content: space-between;
|
|
|
|
|
+ gap: 24px;
|
|
|
|
|
+ padding: 20px 22px;
|
|
|
|
|
+ background: #f4f8ff;
|
|
|
|
|
+ border: 1px solid #dbe7ff;
|
|
|
|
|
+ border-radius: 16px;
|
|
|
|
|
+
|
|
|
|
|
+ &.is-trial {
|
|
|
|
|
+ background: #fff8ef;
|
|
|
|
|
+ border-color: #fde3c8;
|
|
|
|
|
+
|
|
|
|
|
+ .authorization-info__hero-icon {
|
|
|
|
|
+ color: #d97706;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ .authorization-info__status {
|
|
|
|
|
+ color: #b45309;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ .authorization-info__hero-stat-value {
|
|
|
|
|
+ color: #d97706;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ &.is-expired {
|
|
|
|
|
+ background: #fef2f2;
|
|
|
|
|
+ border-color: #fecaca;
|
|
|
|
|
+
|
|
|
|
|
+ .authorization-info__hero-icon {
|
|
|
|
|
+ color: #dc2626;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ .authorization-info__status {
|
|
|
|
|
+ color: #b91c1c;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ .authorization-info__hero-stat-value {
|
|
|
|
|
+ color: #dc2626;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ &.is-unknown {
|
|
|
|
|
+ background: #f8fafc;
|
|
|
|
|
+ border-color: #e5e7eb;
|
|
|
|
|
+
|
|
|
|
|
+ .authorization-info__hero-icon {
|
|
|
|
|
+ color: #6b7280;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ .authorization-info__status {
|
|
|
|
|
+ color: #4b5563;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ .authorization-info__hero-stat-value {
|
|
|
|
|
+ color: #6b7280;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ .authorization-info__hero-main {
|
|
|
|
|
+ display: flex;
|
|
|
|
|
+ align-items: center;
|
|
|
gap: 16px;
|
|
gap: 16px;
|
|
|
- align-content: start;
|
|
|
|
|
|
|
+ min-width: 0;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- .authorization-info__trial-banner {
|
|
|
|
|
- margin-bottom: 14px;
|
|
|
|
|
- font-size: 28px;
|
|
|
|
|
|
|
+ .authorization-info__hero-icon {
|
|
|
|
|
+ display: inline-flex;
|
|
|
|
|
+ flex: 0 0 auto;
|
|
|
|
|
+ align-items: center;
|
|
|
|
|
+ justify-content: center;
|
|
|
|
|
+ width: 52px;
|
|
|
|
|
+ height: 52px;
|
|
|
|
|
+ color: #2a50ec;
|
|
|
|
|
+ font-size: 26px;
|
|
|
|
|
+ background: #fff;
|
|
|
|
|
+ border-radius: 14px;
|
|
|
|
|
+ box-shadow: 0 4px 12px rgb(15 23 42 / 6%);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ .authorization-info__hero-content {
|
|
|
|
|
+ min-width: 0;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ .authorization-info__hero-title {
|
|
|
|
|
+ display: flex;
|
|
|
|
|
+ align-items: center;
|
|
|
|
|
+ flex-wrap: wrap;
|
|
|
|
|
+ gap: 10px;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ .authorization-info__status {
|
|
|
|
|
+ color: #1d4ed8;
|
|
|
|
|
+ font-size: 16px;
|
|
|
font-weight: 700;
|
|
font-weight: 700;
|
|
|
- line-height: 1.2;
|
|
|
|
|
- color: #ef4444;
|
|
|
|
|
- text-align: center;
|
|
|
|
|
- letter-spacing: 2px;
|
|
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- .authorization-info__expired-banner {
|
|
|
|
|
- padding: 14px 16px;
|
|
|
|
|
- margin-bottom: 14px;
|
|
|
|
|
- font-size: 18px;
|
|
|
|
|
|
|
+ .authorization-info__status-hint {
|
|
|
|
|
+ color: #6b7280;
|
|
|
|
|
+ font-size: 12px;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ .authorization-info__hero-subject {
|
|
|
|
|
+ margin-top: 4px;
|
|
|
|
|
+ overflow: hidden;
|
|
|
|
|
+ color: #111827;
|
|
|
|
|
+ font-size: 20px;
|
|
|
|
|
+ font-weight: 600;
|
|
|
|
|
+ line-height: 1.4;
|
|
|
|
|
+ text-overflow: ellipsis;
|
|
|
|
|
+ white-space: nowrap;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ .authorization-info__hero-meta {
|
|
|
|
|
+ display: flex;
|
|
|
|
|
+ align-items: center;
|
|
|
|
|
+ gap: 6px;
|
|
|
|
|
+ margin-top: 6px;
|
|
|
|
|
+ color: #6b7280;
|
|
|
|
|
+ font-size: 12px;
|
|
|
|
|
+
|
|
|
|
|
+ .anticon {
|
|
|
|
|
+ color: #9ca3af;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ .authorization-info__hero-stat {
|
|
|
|
|
+ display: flex;
|
|
|
|
|
+ flex: 0 0 auto;
|
|
|
|
|
+ flex-direction: column;
|
|
|
|
|
+ align-items: flex-end;
|
|
|
|
|
+ gap: 2px;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ .authorization-info__hero-stat-value {
|
|
|
|
|
+ color: #2a50ec;
|
|
|
|
|
+ font-size: 40px;
|
|
|
font-weight: 700;
|
|
font-weight: 700;
|
|
|
- line-height: 1.6;
|
|
|
|
|
- color: #b91c1c;
|
|
|
|
|
- text-align: center;
|
|
|
|
|
- background: #fef2f2;
|
|
|
|
|
- border: 1px solid #fecaca;
|
|
|
|
|
- border-radius: 12px;
|
|
|
|
|
|
|
+ line-height: 1.1;
|
|
|
|
|
+ font-variant-numeric: tabular-nums;
|
|
|
|
|
+
|
|
|
|
|
+ &.is-text {
|
|
|
|
|
+ font-size: 26px;
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- .authorization-info__item {
|
|
|
|
|
- padding: 15px;
|
|
|
|
|
- background: #f8fafc;
|
|
|
|
|
- border: 1px solid #e5e7eb;
|
|
|
|
|
|
|
+ .authorization-info__hero-stat-label {
|
|
|
|
|
+ color: #6b7280;
|
|
|
|
|
+ font-size: 12px;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ .authorization-info__mock-switch {
|
|
|
|
|
+ display: flex;
|
|
|
|
|
+ align-items: center;
|
|
|
|
|
+ flex-wrap: wrap;
|
|
|
|
|
+ gap: 8px;
|
|
|
|
|
+ padding: 8px 12px;
|
|
|
|
|
+ color: #92400e;
|
|
|
|
|
+ font-size: 12px;
|
|
|
|
|
+ background: #fffbeb;
|
|
|
|
|
+ border: 1px solid #fde68a;
|
|
|
border-radius: 10px;
|
|
border-radius: 10px;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- .authorization-info__label {
|
|
|
|
|
|
|
+ .authorization-info__mock-switch-label {
|
|
|
|
|
+ font-weight: 600;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ .authorization-info__mock-switch-item {
|
|
|
|
|
+ padding: 2px 10px;
|
|
|
|
|
+ color: #92400e;
|
|
|
|
|
+ font-size: 12px;
|
|
|
|
|
+ line-height: 20px;
|
|
|
|
|
+ background: #fff;
|
|
|
|
|
+ border: 1px solid #fcd34d;
|
|
|
|
|
+ border-radius: 999px;
|
|
|
|
|
+ cursor: pointer;
|
|
|
|
|
+
|
|
|
|
|
+ &.is-active {
|
|
|
|
|
+ color: #fff;
|
|
|
|
|
+ background: #d97706;
|
|
|
|
|
+ border-color: #d97706;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ .authorization-info__columns {
|
|
|
|
|
+ display: grid;
|
|
|
|
|
+ grid-template-columns: repeat(2, minmax(0, 1fr));
|
|
|
|
|
+ gap: 16px;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ .authorization-info__section {
|
|
|
|
|
+ padding: 16px;
|
|
|
|
|
+ background: #fff;
|
|
|
|
|
+ border: 1px solid #e7edf6;
|
|
|
|
|
+ border-radius: 14px;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ .authorization-info__section-head {
|
|
|
|
|
+ display: flex;
|
|
|
|
|
+ align-items: center;
|
|
|
|
|
+ gap: 8px;
|
|
|
margin-bottom: 10px;
|
|
margin-bottom: 10px;
|
|
|
- font-size: 18px;
|
|
|
|
|
|
|
+ color: #111827;
|
|
|
|
|
+ font-size: 14px;
|
|
|
font-weight: 600;
|
|
font-weight: 600;
|
|
|
|
|
+
|
|
|
|
|
+ .anticon {
|
|
|
|
|
+ color: #2a50ec;
|
|
|
|
|
+ font-size: 15px;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ .authorization-info__field {
|
|
|
|
|
+ display: flex;
|
|
|
|
|
+ gap: 12px;
|
|
|
|
|
+ padding: 10px 0;
|
|
|
|
|
+ border-bottom: 1px dashed #edf1f7;
|
|
|
|
|
+
|
|
|
|
|
+ &:last-child {
|
|
|
|
|
+ border-bottom: 0;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ .authorization-info__field-label {
|
|
|
|
|
+ flex: 0 0 72px;
|
|
|
|
|
+ color: #8a94a6;
|
|
|
|
|
+ font-size: 12px;
|
|
|
|
|
+ line-height: 20px;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ .authorization-info__field-value {
|
|
|
|
|
+ flex: 1 1 auto;
|
|
|
|
|
+ min-width: 0;
|
|
|
color: #111827;
|
|
color: #111827;
|
|
|
|
|
+ font-size: 13px;
|
|
|
|
|
+ line-height: 20px;
|
|
|
|
|
+ word-break: break-all;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ .authorization-info__machine {
|
|
|
|
|
+ display: flex;
|
|
|
|
|
+ align-items: flex-end;
|
|
|
|
|
+ gap: 16px;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ .authorization-info__machine-main {
|
|
|
|
|
+ flex: 1 1 auto;
|
|
|
|
|
+ min-width: 0;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- .authorization-info__value {
|
|
|
|
|
- font-size: 17px;
|
|
|
|
|
- line-height: 1.8;
|
|
|
|
|
- color: #4b5563;
|
|
|
|
|
|
|
+ .authorization-info__machine .authorization-info__field-label {
|
|
|
|
|
+ display: block;
|
|
|
|
|
+ margin-bottom: 6px;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ .authorization-info__machine-code {
|
|
|
|
|
+ display: block;
|
|
|
|
|
+ padding: 8px 10px;
|
|
|
|
|
+ color: #334155;
|
|
|
|
|
+ font-family: Consolas, Monaco, 'Courier New', monospace;
|
|
|
|
|
+ font-size: 12px;
|
|
|
|
|
+ line-height: 18px;
|
|
|
word-break: break-all;
|
|
word-break: break-all;
|
|
|
- white-space: pre-wrap;
|
|
|
|
|
|
|
+ background: #f8fafc;
|
|
|
|
|
+ border: 1px solid #e5e7eb;
|
|
|
|
|
+ border-radius: 8px;
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
- &.is-trial-value {
|
|
|
|
|
- font-size: 24px;
|
|
|
|
|
- font-weight: 700;
|
|
|
|
|
- color: #ef4444;
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ .authorization-info__copy-btn {
|
|
|
|
|
+ flex: 0 0 auto;
|
|
|
|
|
+ margin-bottom: 2px;
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
- &.is-expired-value {
|
|
|
|
|
- font-size: 24px;
|
|
|
|
|
- font-weight: 700;
|
|
|
|
|
- color: #b91c1c;
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ .authorization-info__note {
|
|
|
|
|
+ display: flex;
|
|
|
|
|
+ align-items: flex-start;
|
|
|
|
|
+ gap: 8px;
|
|
|
|
|
+ padding: 12px 14px;
|
|
|
|
|
+ color: #475569;
|
|
|
|
|
+ font-size: 12.5px;
|
|
|
|
|
+ line-height: 1.7;
|
|
|
|
|
+ background: #f8fbff;
|
|
|
|
|
+ border: 1px solid #dbe7ff;
|
|
|
|
|
+ border-radius: 12px;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ .authorization-info__note-icon {
|
|
|
|
|
+ margin-top: 3px;
|
|
|
|
|
+ color: #2a50ec;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ .authorization-info__empty {
|
|
|
|
|
+ display: flex;
|
|
|
|
|
+ flex-direction: column;
|
|
|
|
|
+ align-items: center;
|
|
|
|
|
+ justify-content: center;
|
|
|
|
|
+ min-height: 320px;
|
|
|
|
|
+ text-align: center;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ .authorization-info__empty-icon {
|
|
|
|
|
+ margin-bottom: 14px;
|
|
|
|
|
+ color: #cbd5e1;
|
|
|
|
|
+ font-size: 42px;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ .authorization-info__empty-title {
|
|
|
|
|
+ color: #374151;
|
|
|
|
|
+ font-size: 16px;
|
|
|
|
|
+ font-weight: 600;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ .authorization-info__empty-desc {
|
|
|
|
|
+ margin-top: 6px;
|
|
|
|
|
+ color: #9ca3af;
|
|
|
|
|
+ font-size: 12px;
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
@media screen and (max-width: 767px) {
|
|
@media screen and (max-width: 767px) {
|
|
|
.@{prefix-cls} {
|
|
.@{prefix-cls} {
|
|
|
- .authorization-info__list {
|
|
|
|
|
|
|
+ .authorization-info__hero {
|
|
|
|
|
+ align-items: flex-start;
|
|
|
|
|
+ flex-direction: column;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ .authorization-info__hero-stat {
|
|
|
|
|
+ align-items: flex-start;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ .authorization-info__columns {
|
|
|
grid-template-columns: 1fr;
|
|
grid-template-columns: 1fr;
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|