Initialize profile scoped views before loading
This commit is contained in:
@@ -3,13 +3,22 @@ import { onMounted } from 'vue'
|
|||||||
import { NSpin } from 'naive-ui'
|
import { NSpin } from 'naive-ui'
|
||||||
import { useI18n } from 'vue-i18n'
|
import { useI18n } from 'vue-i18n'
|
||||||
import { useSettingsStore } from '@/stores/hermes/settings'
|
import { useSettingsStore } from '@/stores/hermes/settings'
|
||||||
|
import { useProfilesStore } from '@/stores/hermes/profiles'
|
||||||
import PlatformSettings from '@/components/hermes/settings/PlatformSettings.vue'
|
import PlatformSettings from '@/components/hermes/settings/PlatformSettings.vue'
|
||||||
|
|
||||||
const settingsStore = useSettingsStore()
|
const settingsStore = useSettingsStore()
|
||||||
|
const profilesStore = useProfilesStore()
|
||||||
const { t } = useI18n()
|
const { t } = useI18n()
|
||||||
|
|
||||||
|
async function loadSettingsForProfile() {
|
||||||
|
if (!profilesStore.activeProfileName || profilesStore.profiles.length === 0) {
|
||||||
|
await profilesStore.fetchProfiles()
|
||||||
|
}
|
||||||
|
await settingsStore.fetchSettings()
|
||||||
|
}
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
settingsStore.fetchSettings()
|
void loadSettingsForProfile()
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { ref, onMounted } from 'vue'
|
import { ref, onMounted } from 'vue'
|
||||||
import { useFilesStore } from '@/stores/hermes/files'
|
import { useFilesStore } from '@/stores/hermes/files'
|
||||||
|
import { useProfilesStore } from '@/stores/hermes/profiles'
|
||||||
import FileTree from '@/components/hermes/files/FileTree.vue'
|
import FileTree from '@/components/hermes/files/FileTree.vue'
|
||||||
import FileBreadcrumb from '@/components/hermes/files/FileBreadcrumb.vue'
|
import FileBreadcrumb from '@/components/hermes/files/FileBreadcrumb.vue'
|
||||||
import FileToolbar from '@/components/hermes/files/FileToolbar.vue'
|
import FileToolbar from '@/components/hermes/files/FileToolbar.vue'
|
||||||
@@ -13,6 +14,7 @@ import FileRenameModal from '@/components/hermes/files/FileRenameModal.vue'
|
|||||||
import type { FileEntry } from '@/api/hermes/files'
|
import type { FileEntry } from '@/api/hermes/files'
|
||||||
|
|
||||||
const filesStore = useFilesStore()
|
const filesStore = useFilesStore()
|
||||||
|
const profilesStore = useProfilesStore()
|
||||||
|
|
||||||
const contextMenuRef = ref<InstanceType<typeof FileContextMenu> | null>(null)
|
const contextMenuRef = ref<InstanceType<typeof FileContextMenu> | null>(null)
|
||||||
const showUpload = ref(false)
|
const showUpload = ref(false)
|
||||||
@@ -42,8 +44,15 @@ function handleRename(entry: FileEntry) {
|
|||||||
showRenameModal.value = true
|
showRenameModal.value = true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function loadRoot() {
|
||||||
|
if (!profilesStore.activeProfileName || profilesStore.profiles.length === 0) {
|
||||||
|
await profilesStore.fetchProfiles()
|
||||||
|
}
|
||||||
|
await filesStore.fetchEntries('')
|
||||||
|
}
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
filesStore.fetchEntries('')
|
void loadRoot()
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { ref, computed, watch } from 'vue'
|
import { ref, computed, onMounted } from 'vue'
|
||||||
import { NButton, NSpin } from 'naive-ui'
|
import { NButton, NSpin } from 'naive-ui'
|
||||||
import { useI18n } from 'vue-i18n'
|
import { useI18n } from 'vue-i18n'
|
||||||
import JobsPanel from '@/components/hermes/jobs/JobsPanel.vue'
|
import JobsPanel from '@/components/hermes/jobs/JobsPanel.vue'
|
||||||
@@ -25,11 +25,22 @@ const jobNameMap = computed(() => {
|
|||||||
return map
|
return map
|
||||||
})
|
})
|
||||||
|
|
||||||
watch(activeProfileName, () => {
|
async function ensureProfileSelection() {
|
||||||
|
if (!profilesStore.activeProfileName || profilesStore.profiles.length === 0) {
|
||||||
|
await profilesStore.fetchProfiles()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function reloadJobsForProfile() {
|
||||||
selectedJobId.value = null
|
selectedJobId.value = null
|
||||||
jobsStore.jobs = []
|
jobsStore.jobs = []
|
||||||
void jobsStore.fetchJobs()
|
await ensureProfileSelection()
|
||||||
}, { immediate: true })
|
await jobsStore.fetchJobs()
|
||||||
|
}
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
void reloadJobsForProfile()
|
||||||
|
})
|
||||||
|
|
||||||
function openCreateModal() {
|
function openCreateModal() {
|
||||||
editingJob.value = null
|
editingJob.value = null
|
||||||
|
|||||||
@@ -4,9 +4,11 @@ import { NButton, useMessage } from 'naive-ui'
|
|||||||
import { useI18n } from 'vue-i18n'
|
import { useI18n } from 'vue-i18n'
|
||||||
import MarkdownRenderer from '@/components/hermes/chat/MarkdownRenderer.vue'
|
import MarkdownRenderer from '@/components/hermes/chat/MarkdownRenderer.vue'
|
||||||
import { fetchMemory, saveMemory, type MemoryData } from '@/api/hermes/skills'
|
import { fetchMemory, saveMemory, type MemoryData } from '@/api/hermes/skills'
|
||||||
|
import { useProfilesStore } from '@/stores/hermes/profiles'
|
||||||
|
|
||||||
const { t } = useI18n()
|
const { t } = useI18n()
|
||||||
const message = useMessage()
|
const message = useMessage()
|
||||||
|
const profilesStore = useProfilesStore()
|
||||||
const loading = ref(false)
|
const loading = ref(false)
|
||||||
const data = ref<MemoryData | null>(null)
|
const data = ref<MemoryData | null>(null)
|
||||||
const editingSection = ref<'memory' | 'user' | 'soul' | null>(null)
|
const editingSection = ref<'memory' | 'user' | 'soul' | null>(null)
|
||||||
@@ -18,6 +20,9 @@ onMounted(loadMemory)
|
|||||||
async function loadMemory() {
|
async function loadMemory() {
|
||||||
loading.value = true
|
loading.value = true
|
||||||
try {
|
try {
|
||||||
|
if (!profilesStore.activeProfileName || profilesStore.profiles.length === 0) {
|
||||||
|
await profilesStore.fetchProfiles()
|
||||||
|
}
|
||||||
data.value = await fetchMemory()
|
data.value = await fetchMemory()
|
||||||
} catch (err: any) {
|
} catch (err: any) {
|
||||||
console.error('Failed to load memory:', err)
|
console.error('Failed to load memory:', err)
|
||||||
|
|||||||
@@ -5,17 +5,26 @@ import { useI18n } from 'vue-i18n'
|
|||||||
import ProvidersPanel from '@/components/hermes/models/ProvidersPanel.vue'
|
import ProvidersPanel from '@/components/hermes/models/ProvidersPanel.vue'
|
||||||
import ProviderFormModal from '@/components/hermes/models/ProviderFormModal.vue'
|
import ProviderFormModal from '@/components/hermes/models/ProviderFormModal.vue'
|
||||||
import { useModelsStore } from '@/stores/hermes/models'
|
import { useModelsStore } from '@/stores/hermes/models'
|
||||||
|
import { useProfilesStore } from '@/stores/hermes/profiles'
|
||||||
import { checkCopilotToken } from '@/api/hermes/copilot-auth'
|
import { checkCopilotToken } from '@/api/hermes/copilot-auth'
|
||||||
|
|
||||||
const { t } = useI18n()
|
const { t } = useI18n()
|
||||||
const modelsStore = useModelsStore()
|
const modelsStore = useModelsStore()
|
||||||
|
const profilesStore = useProfilesStore()
|
||||||
const showModal = ref(false)
|
const showModal = ref(false)
|
||||||
|
|
||||||
onMounted(async () => {
|
async function loadProvidersForProfile() {
|
||||||
|
if (!profilesStore.activeProfileName || profilesStore.profiles.length === 0) {
|
||||||
|
await profilesStore.fetchProfiles()
|
||||||
|
}
|
||||||
// 先 invalidate 后端 copilot 缓存(gh logout / VS Code 退出后下一次 list 立刻反映),
|
// 先 invalidate 后端 copilot 缓存(gh logout / VS Code 退出后下一次 list 立刻反映),
|
||||||
// 再拉 providers 与 appStore 的模型显示名配置。check-token 失败不阻断。
|
// 再拉 providers 与 appStore 的模型显示名配置。check-token 失败不阻断。
|
||||||
try { await checkCopilotToken() } catch { /* ignore */ }
|
try { await checkCopilotToken() } catch { /* ignore */ }
|
||||||
await modelsStore.fetchProviders()
|
await modelsStore.fetchProviders()
|
||||||
|
}
|
||||||
|
|
||||||
|
onMounted(async () => {
|
||||||
|
await loadProvidersForProfile()
|
||||||
})
|
})
|
||||||
|
|
||||||
function openCreateModal() {
|
function openCreateModal() {
|
||||||
|
|||||||
@@ -60,6 +60,9 @@ async function loadPlugins() {
|
|||||||
loading.value = true
|
loading.value = true
|
||||||
error.value = ''
|
error.value = ''
|
||||||
try {
|
try {
|
||||||
|
if (!profilesStore.activeProfileName || profilesStore.profiles.length === 0) {
|
||||||
|
await profilesStore.fetchProfiles()
|
||||||
|
}
|
||||||
const data = await fetchPlugins()
|
const data = await fetchPlugins()
|
||||||
plugins.value = data.plugins ?? []
|
plugins.value = data.plugins ?? []
|
||||||
warnings.value = data.warnings ?? []
|
warnings.value = data.warnings ?? []
|
||||||
|
|||||||
@@ -19,8 +19,10 @@ import AccountSettings from "@/components/hermes/settings/AccountSettings.vue";
|
|||||||
import UserManagementSettings from "@/components/hermes/settings/UserManagementSettings.vue";
|
import UserManagementSettings from "@/components/hermes/settings/UserManagementSettings.vue";
|
||||||
import VoiceSettings from "@/components/hermes/settings/VoiceSettings.vue";
|
import VoiceSettings from "@/components/hermes/settings/VoiceSettings.vue";
|
||||||
import { isStoredSuperAdmin } from "@/api/client";
|
import { isStoredSuperAdmin } from "@/api/client";
|
||||||
|
import { useProfilesStore } from "@/stores/hermes/profiles";
|
||||||
|
|
||||||
const settingsStore = useSettingsStore();
|
const settingsStore = useSettingsStore();
|
||||||
|
const profilesStore = useProfilesStore();
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
const canManageUsers = isStoredSuperAdmin();
|
const canManageUsers = isStoredSuperAdmin();
|
||||||
const route = useRoute();
|
const route = useRoute();
|
||||||
@@ -59,8 +61,15 @@ watch(() => route.query.tab, (tab) => {
|
|||||||
activeTab.value = normalizeTab(tab);
|
activeTab.value = normalizeTab(tab);
|
||||||
}, { immediate: true });
|
}, { immediate: true });
|
||||||
|
|
||||||
|
async function loadSettingsForProfile() {
|
||||||
|
if (!profilesStore.activeProfileName || profilesStore.profiles.length === 0) {
|
||||||
|
await profilesStore.fetchProfiles();
|
||||||
|
}
|
||||||
|
await settingsStore.fetchSettings();
|
||||||
|
}
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
settingsStore.fetchSettings();
|
void loadSettingsForProfile();
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
import { computed, onMounted, ref } from 'vue'
|
import { computed, onMounted, ref } from 'vue'
|
||||||
import { useI18n } from 'vue-i18n'
|
import { useI18n } from 'vue-i18n'
|
||||||
import { NButton } from 'naive-ui'
|
import { NButton } from 'naive-ui'
|
||||||
|
import { useProfilesStore } from '@/stores/hermes/profiles'
|
||||||
import {
|
import {
|
||||||
fetchSkillUsageStats,
|
fetchSkillUsageStats,
|
||||||
type SkillUsageDailyRow,
|
type SkillUsageDailyRow,
|
||||||
@@ -10,6 +11,7 @@ import {
|
|||||||
} from '@/api/hermes/skills'
|
} from '@/api/hermes/skills'
|
||||||
|
|
||||||
const { t } = useI18n()
|
const { t } = useI18n()
|
||||||
|
const profilesStore = useProfilesStore()
|
||||||
const periodOptions = [7, 30, 90, 365]
|
const periodOptions = [7, 30, 90, 365]
|
||||||
const maxVisibleChartSkills = 6
|
const maxVisibleChartSkills = 6
|
||||||
const skillPalette = [
|
const skillPalette = [
|
||||||
@@ -125,6 +127,9 @@ function hideTooltip(day: SkillUsageDailyRow) {
|
|||||||
|
|
||||||
async function loadStats(days = selectedDays.value, force = false) {
|
async function loadStats(days = selectedDays.value, force = false) {
|
||||||
selectedDays.value = days
|
selectedDays.value = days
|
||||||
|
if (!profilesStore.activeProfileName || profilesStore.profiles.length === 0) {
|
||||||
|
await profilesStore.fetchProfiles()
|
||||||
|
}
|
||||||
const seq = ++requestSeq
|
const seq = ++requestSeq
|
||||||
latestRequestByPeriod[days] = seq
|
latestRequestByPeriod[days] = seq
|
||||||
loading.value = true
|
loading.value = true
|
||||||
|
|||||||
@@ -6,10 +6,12 @@ import SkillList from '@/components/hermes/skills/SkillList.vue'
|
|||||||
import SkillDetail from '@/components/hermes/skills/SkillDetail.vue'
|
import SkillDetail from '@/components/hermes/skills/SkillDetail.vue'
|
||||||
import MarkdownRenderer from '@/components/hermes/chat/MarkdownRenderer.vue'
|
import MarkdownRenderer from '@/components/hermes/chat/MarkdownRenderer.vue'
|
||||||
import { fetchSkills, type SkillCategory, type SkillSource, type SkillInfo } from '@/api/hermes/skills'
|
import { fetchSkills, type SkillCategory, type SkillSource, type SkillInfo } from '@/api/hermes/skills'
|
||||||
|
import { useProfilesStore } from '@/stores/hermes/profiles'
|
||||||
|
|
||||||
type SourceFilter = SkillSource | 'modified'
|
type SourceFilter = SkillSource | 'modified'
|
||||||
|
|
||||||
const { t, locale } = useI18n()
|
const { t, locale } = useI18n()
|
||||||
|
const profilesStore = useProfilesStore()
|
||||||
const categories = ref<SkillCategory[]>([])
|
const categories = ref<SkillCategory[]>([])
|
||||||
const archived = ref<SkillInfo[]>([])
|
const archived = ref<SkillInfo[]>([])
|
||||||
const loading = ref(false)
|
const loading = ref(false)
|
||||||
@@ -56,6 +58,9 @@ onUnmounted(() => {
|
|||||||
async function loadSkills() {
|
async function loadSkills() {
|
||||||
loading.value = true
|
loading.value = true
|
||||||
try {
|
try {
|
||||||
|
if (!profilesStore.activeProfileName || profilesStore.profiles.length === 0) {
|
||||||
|
await profilesStore.fetchProfiles()
|
||||||
|
}
|
||||||
const data = await fetchSkills()
|
const data = await fetchSkills()
|
||||||
categories.value = data.categories
|
categories.value = data.categories
|
||||||
archived.value = data.archived
|
archived.value = data.archived
|
||||||
|
|||||||
@@ -3,12 +3,14 @@ import { NButton } from 'naive-ui'
|
|||||||
import { onMounted, ref } from 'vue'
|
import { onMounted, ref } from 'vue'
|
||||||
import { useI18n } from 'vue-i18n'
|
import { useI18n } from 'vue-i18n'
|
||||||
import { useUsageStore } from '@/stores/hermes/usage'
|
import { useUsageStore } from '@/stores/hermes/usage'
|
||||||
|
import { useProfilesStore } from '@/stores/hermes/profiles'
|
||||||
import StatCards from '@/components/hermes/usage/StatCards.vue'
|
import StatCards from '@/components/hermes/usage/StatCards.vue'
|
||||||
import ModelBreakdown from '@/components/hermes/usage/ModelBreakdown.vue'
|
import ModelBreakdown from '@/components/hermes/usage/ModelBreakdown.vue'
|
||||||
import DailyTrend from '@/components/hermes/usage/DailyTrend.vue'
|
import DailyTrend from '@/components/hermes/usage/DailyTrend.vue'
|
||||||
|
|
||||||
const { t } = useI18n()
|
const { t } = useI18n()
|
||||||
const usageStore = useUsageStore()
|
const usageStore = useUsageStore()
|
||||||
|
const profilesStore = useProfilesStore()
|
||||||
|
|
||||||
const periodOptions = [
|
const periodOptions = [
|
||||||
{ label: '7d', days: 7 },
|
{ label: '7d', days: 7 },
|
||||||
@@ -19,13 +21,20 @@ const periodOptions = [
|
|||||||
|
|
||||||
const selectedPeriod = ref(30)
|
const selectedPeriod = ref(30)
|
||||||
|
|
||||||
function loadUsage(days = selectedPeriod.value) {
|
async function ensureProfileSelection() {
|
||||||
|
if (!profilesStore.activeProfileName || profilesStore.profiles.length === 0) {
|
||||||
|
await profilesStore.fetchProfiles()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function loadUsage(days = selectedPeriod.value) {
|
||||||
selectedPeriod.value = days
|
selectedPeriod.value = days
|
||||||
usageStore.loadSessions(days)
|
await ensureProfileSelection()
|
||||||
|
await usageStore.loadSessions(days)
|
||||||
}
|
}
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
loadUsage(30)
|
void loadUsage(30)
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user