feat: Metrix 平台按需启用与数据源合并为外部储存
This commit is contained in:
@@ -112,7 +112,7 @@
|
||||
</n-layout>
|
||||
</n-layout>
|
||||
|
||||
<LicenseActivationModal v-if="licenseModalVisible" v-model:show="licenseModalVisible" />
|
||||
<LicenseActivationModal v-if="licenseModalVisible" v-model:show="licenseModalVisible" @metrix-changed="onMetrixChanged" />
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
@@ -131,9 +131,10 @@ import {
|
||||
SunnyOutline
|
||||
} from '@vicons/ionicons5';
|
||||
|
||||
import { apiPost, clearToken, getToken, setToken, setUnauthorizedHandler } from './api/client';
|
||||
import type { LoginResponse } from './types';
|
||||
import { apiGet, apiPost, clearToken, getToken, setToken, setUnauthorizedHandler } from './api/client';
|
||||
import type { AppConfig, LoginResponse } from './types';
|
||||
import { pageHeader, resetPageHeader, resolveHeaderValue, type PageHeaderAction } from './composables/pageHeader';
|
||||
import { metrixEnabled } from './composables/metrixEnabled';
|
||||
import { themeName, toggleAppTheme } from './composables/theme';
|
||||
|
||||
const LoginView = defineAsyncComponent(() => import('./components/LoginView.vue'));
|
||||
@@ -172,6 +173,9 @@ const themeToggleTitle = computed(() => (themeName.value === 'dark' ? '切换到
|
||||
onMounted(() => {
|
||||
window.addEventListener('dragover', preventWindowFileDrop, { capture: true });
|
||||
window.addEventListener('drop', preventWindowFileDrop, { capture: true });
|
||||
if (token.value) {
|
||||
void loadMetrixEnabled();
|
||||
}
|
||||
});
|
||||
|
||||
onBeforeUnmount(() => {
|
||||
@@ -198,6 +202,7 @@ async function handleLogin(payload: { username: string; password: string }) {
|
||||
setToken(result.token);
|
||||
token.value = result.token;
|
||||
message.success('登录成功');
|
||||
void loadMetrixEnabled();
|
||||
} catch (error) {
|
||||
message.error(error instanceof Error ? error.message : '登录失败');
|
||||
} finally {
|
||||
@@ -226,6 +231,19 @@ function handleMenuChange(key: string | number) {
|
||||
void router.push({ name: key });
|
||||
}
|
||||
|
||||
function onMetrixChanged(enabled: boolean) {
|
||||
metrixEnabled.value = enabled;
|
||||
}
|
||||
|
||||
async function loadMetrixEnabled() {
|
||||
try {
|
||||
const config = await apiGet<AppConfig>('/api/config/full');
|
||||
metrixEnabled.value = config.metrix_enabled ?? false;
|
||||
} catch {
|
||||
metrixEnabled.value = false;
|
||||
}
|
||||
}
|
||||
|
||||
function handleBrandMarkClick() {
|
||||
brandClickCount.value += 1;
|
||||
if (brandClickResetTimer !== undefined) {
|
||||
|
||||
@@ -16,6 +16,10 @@
|
||||
placeholder="请输入激活码"
|
||||
:disabled="activationLoading"
|
||||
/>
|
||||
<div class="license-metrix-toggle">
|
||||
<n-switch v-model:value="metrixEnabled" :loading="savingMetrix" size="small" @update:value="toggleMetrix" />
|
||||
<span class="license-metrix-label">启用 Metrix 平台</span>
|
||||
</div>
|
||||
</div>
|
||||
<template #footer>
|
||||
<div class="license-dialog-footer">
|
||||
@@ -31,17 +35,21 @@ import { onMounted, ref } from 'vue';
|
||||
import { useMessage } from 'naive-ui';
|
||||
|
||||
import { apiGet, apiPost } from '../api/client';
|
||||
import type { LicenseStatus } from '../types';
|
||||
import type { AppConfig, LicenseStatus } from '../types';
|
||||
|
||||
const visible = defineModel<boolean>('show', { required: true });
|
||||
const emit = defineEmits<{ metrixChanged: [enabled: boolean] }>();
|
||||
const message = useMessage();
|
||||
const activationCode = ref('');
|
||||
const activationLoading = ref(false);
|
||||
const activationKeyLabel = ref('2026/12/30');
|
||||
const licenseMessage = ref('输入激活码可将授权到期日期延长 30 天。');
|
||||
const metrixEnabled = ref(false);
|
||||
const savingMetrix = ref(false);
|
||||
|
||||
onMounted(() => {
|
||||
void loadLicenseStatus();
|
||||
void loadMetrixEnabled();
|
||||
});
|
||||
|
||||
async function loadLicenseStatus() {
|
||||
@@ -55,6 +63,29 @@ async function loadLicenseStatus() {
|
||||
}
|
||||
}
|
||||
|
||||
async function loadMetrixEnabled() {
|
||||
try {
|
||||
const config = await apiGet<AppConfig>('/api/config/full');
|
||||
metrixEnabled.value = config.metrix_enabled ?? false;
|
||||
} catch {
|
||||
metrixEnabled.value = false;
|
||||
}
|
||||
}
|
||||
|
||||
async function toggleMetrix(enabled: boolean) {
|
||||
savingMetrix.value = true;
|
||||
try {
|
||||
await apiPost('/api/config/metrix-enabled', { enabled });
|
||||
metrixEnabled.value = enabled;
|
||||
emit('metrixChanged', enabled);
|
||||
} catch (error) {
|
||||
metrixEnabled.value = !enabled;
|
||||
message.error(error instanceof Error ? error.message : '保存失败');
|
||||
} finally {
|
||||
savingMetrix.value = false;
|
||||
}
|
||||
}
|
||||
|
||||
async function submitActivation() {
|
||||
const code = activationCode.value.trim();
|
||||
if (!code) {
|
||||
@@ -76,3 +107,18 @@ async function submitActivation() {
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.license-metrix-toggle {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
margin-top: 16px;
|
||||
padding-top: 12px;
|
||||
border-top: 1px solid var(--n-border-color, #e0e0e6);
|
||||
}
|
||||
.license-metrix-label {
|
||||
font-size: 13px;
|
||||
color: var(--n-text-color-3, #999);
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -4,16 +4,15 @@
|
||||
|
||||
<n-card size="small" class="work-card settings-tabs-card">
|
||||
<n-tabs type="line" animated class="settings-tabs">
|
||||
<n-tab-pane name="backend" tab="数据源 / 仓库">
|
||||
<n-tab-pane v-if="metrixEnabledRef" name="backend" tab="数据源 / 仓库">
|
||||
<div class="settings-database-panel">
|
||||
<div class="settings-database-stack">
|
||||
<n-card title="后端类型" size="small" class="work-card">
|
||||
<n-form label-placement="top">
|
||||
<n-form-item label="数据源">
|
||||
<n-radio-group v-model:value="sourceType">
|
||||
<n-radio-button value="sftp">SFTP</n-radio-button>
|
||||
<n-radio-button value="ftp">FTP</n-radio-button>
|
||||
<n-radio-button value="metrix">Metrix 存储平台</n-radio-button>
|
||||
<n-radio-button value="external">外部储存</n-radio-button>
|
||||
<n-radio-button value="metrix">Metrix 储存平台</n-radio-button>
|
||||
</n-radio-group>
|
||||
</n-form-item>
|
||||
<n-form-item label="数据仓库">
|
||||
@@ -22,7 +21,7 @@
|
||||
<n-radio-button value="metrix">Metrix 数据库平台</n-radio-button>
|
||||
</n-radio-group>
|
||||
</n-form-item>
|
||||
<p class="form-hint">主数据源和数据仓库可独立选择;CellData 单独配置。</p>
|
||||
<p class="form-hint">数据源和数据仓库可独立选择;CellData 单独配置。</p>
|
||||
</n-form>
|
||||
<template #footer>
|
||||
<n-space justify="end">
|
||||
@@ -819,6 +818,7 @@ import type {
|
||||
RemoteSchedulerStatus
|
||||
} from '../types';
|
||||
import { showDownloadCompleteDialog } from '../composables/downloadFeedback';
|
||||
import { metrixEnabled as metrixEnabledRef } from '../composables/metrixEnabled';
|
||||
import { resetPageHeader, setPageHeader } from '../composables/pageHeader';
|
||||
|
||||
interface ExtractFieldConfig {
|
||||
@@ -882,7 +882,7 @@ const savingCellDataSettings = ref(false);
|
||||
const validatingCellDataSettings = ref(false);
|
||||
const savingBackend = ref(false);
|
||||
const savingMetrix = ref(false);
|
||||
const sourceType = ref<'ftp' | 'sftp' | 'metrix'>('sftp');
|
||||
const sourceType = ref<'external' | 'metrix'>('external');
|
||||
const warehouseType = ref<'mysql' | 'metrix'>('mysql');
|
||||
const savingDirectoryMappings = ref(false);
|
||||
const savingHistoryRetention = ref(false);
|
||||
@@ -1120,7 +1120,7 @@ async function loadConfig() {
|
||||
try {
|
||||
const config = await apiGet<AppConfig>('/api/config/full');
|
||||
configUpdate.value = config.update;
|
||||
sourceType.value = config.source_type || 'sftp';
|
||||
sourceType.value = (config.source_type === 'metrix' ? 'metrix' : 'external') as 'external' | 'metrix';
|
||||
warehouseType.value = config.warehouse_type || 'mysql';
|
||||
if (config.metrix) {
|
||||
metrixForm.base_url = config.metrix.base_url || '';
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
import { ref } from 'vue';
|
||||
|
||||
export const metrixEnabled = ref(false);
|
||||
@@ -96,7 +96,8 @@ export interface CacheSize {
|
||||
|
||||
export interface AppConfig {
|
||||
update: string;
|
||||
source_type: 'ftp' | 'sftp' | 'metrix';
|
||||
metrix_enabled: boolean;
|
||||
source_type: 'external' | 'metrix';
|
||||
warehouse_type: 'mysql' | 'metrix';
|
||||
mysql: {
|
||||
host: string;
|
||||
|
||||
Reference in New Issue
Block a user