feat: add new stores for cron, locale, providers, script, shared data, skills, and user info

- Implemented `cron` store to manage scheduled tasks with CRUD operations.
- Created `locale` store for language settings with persistence and system language detection.
- Added `providers` store to handle provider accounts and configurations with API interactions.
- Developed `script` store for managing automation scripts, including recording and execution.
- Introduced `sharedStore` for managing shared data across components.
- Established `skills` store for fetching, installing, and managing skills from a marketplace.
- Created `userinfo` store for user authentication and session management.

chore: update path aliases from `@store` to `@stores` in TypeScript configuration and Vite config
This commit is contained in:
duanshuwen
2026-04-15 21:49:25 +08:00
parent 364db041eb
commit e77c815a86
32 changed files with 192 additions and 128 deletions

1199
src/stores/chat.ts Normal file

File diff suppressed because it is too large Load Diff

145
src/stores/cron.ts Normal file
View File

@@ -0,0 +1,145 @@
/**
* Cron State Store
* Manages scheduled task state
*/
import { defineStore } from 'pinia';
import { ref, computed } from 'vue';
import { hostApiFetch } from '@lib/host-api';
import type { CronJob, CronJobCreateInput, CronJobUpdateInput } from '@lib/cron-types';
export const MOCK_CRON_JOBS: CronJob[] = [];
export const useCronStore = defineStore('cron', () => {
const jobs = ref<CronJob[]>([]);
const loading = ref(false);
const error = ref<string | null>(null);
const safeJobs = computed(() => (Array.isArray(jobs.value) ? jobs.value : []));
const activeJobs = computed(() => safeJobs.value.filter((j) => j.enabled));
const pausedJobs = computed(() => safeJobs.value.filter((j) => !j.enabled));
const failedJobs = computed(() => safeJobs.value.filter((j) => j.lastRun && !j.lastRun.success));
const fetchJobs = async () => {
const currentJobs = safeJobs.value;
if (currentJobs.length === 0) {
loading.value = true;
}
error.value = null;
try {
const result = await hostApiFetch<CronJob[]>('/api/cron/jobs');
jobs.value = result;
} catch (err) {
error.value = err instanceof Error ? err.message : String(err);
// Fallback to mock data on error for demo/development
jobs.value = MOCK_CRON_JOBS;
} finally {
loading.value = false;
}
};
const createJob = async (input: CronJobCreateInput) => {
const job: CronJob = {
id: `local-${Date.now()}`,
...input,
enabled: input.enabled ?? true,
createdAt: new Date().toISOString(),
updatedAt: new Date().toISOString(),
};
try {
const result = await hostApiFetch<CronJob>('/api/cron/jobs', {
method: 'POST',
body: JSON.stringify(input),
});
jobs.value = [...safeJobs.value, result];
return result;
} catch (err) {
console.warn('Failed to create cron job via API, using local fallback:', err);
jobs.value = [...safeJobs.value, job];
return job;
}
};
const updateJob = async (id: string, input: CronJobUpdateInput) => {
try {
const updatedJob = await hostApiFetch<CronJob>(`/api/cron/jobs/${encodeURIComponent(id)}`, {
method: 'PUT',
body: JSON.stringify(input),
});
jobs.value = safeJobs.value.map((job) => (job.id === id ? updatedJob : job));
} catch (err) {
console.warn('Failed to update cron job via API, using local fallback:', err);
jobs.value = safeJobs.value.map((job) =>
job.id === id
? { ...job, ...input, updatedAt: new Date().toISOString() }
: job,
);
}
};
const deleteJob = async (id: string) => {
try {
await hostApiFetch(`/api/cron/jobs/${encodeURIComponent(id)}`, {
method: 'DELETE',
});
} catch (err) {
console.warn('Failed to delete cron job via API, using local fallback:', err);
}
jobs.value = safeJobs.value.filter((job) => job.id !== id);
};
const toggleJob = async (id: string, enabled: boolean) => {
try {
await hostApiFetch('/api/cron/toggle', {
method: 'POST',
body: JSON.stringify({ id, enabled }),
});
} catch (err) {
console.warn('Failed to toggle cron job via API, using local fallback:', err);
}
jobs.value = safeJobs.value.map((job) =>
job.id === id ? { ...job, enabled, updatedAt: new Date().toISOString() } : job,
);
};
const triggerJob = async (id: string) => {
try {
const result = await hostApiFetch('/api/cron/trigger', {
method: 'POST',
body: JSON.stringify({ id }),
});
console.log('Cron trigger result:', result);
} catch (err) {
console.warn('Failed to trigger cron job via API, using local fallback:', err);
}
// Update lastRun locally as fallback
jobs.value = safeJobs.value.map((job) =>
job.id === id
? {
...job,
lastRun: {
time: new Date().toISOString(),
success: true,
},
updatedAt: new Date().toISOString(),
}
: job,
);
};
return {
jobs,
loading,
error,
safeJobs,
activeJobs,
pausedJobs,
failedJobs,
fetchJobs,
createJob,
updateJob,
deleteJob,
toggleJob,
triggerJob,
};
});

129
src/stores/locale.ts Normal file
View File

@@ -0,0 +1,129 @@
import { defineStore } from 'pinia';
import { i18n, setLanguage, getLanguage, type LanguageCode } from '@src/i18n';
import { SUPPORTED_LANGUAGES, SUPPORTED_LANGUAGE_CODES } from '@src/i18n/constants';
import { resolveSupportedLanguage, detectSystemLanguage } from '@src/i18n/resolver';
// 持久化键
const STORAGE_KEY = 'diona-language';
interface LocaleState {
language: LanguageCode;
initialized: boolean;
}
export const useLocaleStore = defineStore('locale', {
state: (): LocaleState => ({
language: 'zh',
initialized: false,
}),
getters: {
currentLanguage: (state) => state.language,
isChinese: (state) => state.language === 'zh',
isEnglish: (state) => state.language === 'en',
isJapanese: (state) => state.language === 'ja',
languageLabel: (state) => {
const lang = SUPPORTED_LANGUAGES.find(l => l.code === state.language);
return lang?.label || '中文';
},
},
actions: {
/**
* 初始化语言设置
* 优先级:持久化设置 > 系统语言 > 默认中文
*/
async init() {
if (this.initialized) return;
try {
// 1. 尝试从 localStorage 读取持久化设置
const saved = localStorage.getItem(STORAGE_KEY);
let lang: LanguageCode = 'zh';
if (saved && SUPPORTED_LANGUAGE_CODES.includes(saved as LanguageCode)) {
lang = saved as LanguageCode;
} else {
// 2. 检测系统语言
lang = detectSystemLanguage();
}
// 3. 应用语言设置
await this.setLanguage(lang, false); // 不持久化,因为已经是持久化的值
this.initialized = true;
} catch (error) {
console.error('Failed to initialize locale store:', error);
// 降级处理:使用默认中文
await this.setLanguage('zh', false);
this.initialized = true;
}
},
/**
* 设置语言
* @param language 目标语言代码
* @param persist 是否持久化到 localStorage默认为 true
*/
async setLanguage(language: LanguageCode, persist: boolean = true) {
// 验证语言代码有效性
const resolvedLang = resolveSupportedLanguage(language);
if (resolvedLang === this.language) {
return; // 语言未变化
}
try {
// 1. 更新 i18n 实例
await setLanguage(resolvedLang, i18n);
// 2. 更新 store 状态
this.language = resolvedLang;
// 3. 持久化到 localStorage
if (persist) {
localStorage.setItem(STORAGE_KEY, resolvedLang);
}
// 4. 触发语言变化事件(供其他组件监听)
window.dispatchEvent(new CustomEvent('language-changed', {
detail: { language: resolvedLang }
}));
} catch (error) {
console.error('Failed to set language:', error);
throw error;
}
},
/**
* 切换语言(轮换支持的语言)
*/
async toggleLanguage() {
const currentIndex = SUPPORTED_LANGUAGE_CODES.indexOf(this.language);
const nextIndex = (currentIndex + 1) % SUPPORTED_LANGUAGE_CODES.length;
const nextLanguage = SUPPORTED_LANGUAGE_CODES[nextIndex];
await this.setLanguage(nextLanguage);
},
/**
* 重置为系统语言
*/
async resetToSystemLanguage() {
const systemLang = detectSystemLanguage();
await this.setLanguage(systemLang);
},
/**
* 同步 i18n 实例与 store 状态(用于外部更改的情况)
*/
syncWithI18n() {
const currentLang = getLanguage();
if (currentLang !== this.language) {
this.language = currentLang as LanguageCode;
}
},
},
});
// 导出类型
export type { LanguageCode };

343
src/stores/providers.ts Normal file
View File

@@ -0,0 +1,343 @@
import { defineStore } from 'pinia';
import { ref } from 'vue';
import { hostApiFetch } from '@lib/host-api';
import { fetchProviderSnapshot } from '@lib/provider-accounts';
import type {
ProviderAccount,
ProviderConfig,
ProviderVendorInfo,
ProviderWithKeyInfo,
} from '@lib/providers';
export const useProviderStore = defineStore('providers', () => {
const statuses = ref<ProviderWithKeyInfo[]>([]);
const accounts = ref<ProviderAccount[]>([]);
const vendors = ref<ProviderVendorInfo[]>([]);
const defaultAccountId = ref<string | null>(null);
const loading = ref(false);
const error = ref<string | null>(null);
const init = async () => {
await refreshProviderSnapshot();
// 自动兜底:如果有账户但没设默认,自动将第一个设为默认
if (accounts.value.length > 0 && !defaultAccountId.value) {
try {
await setDefaultAccount(accounts.value[0].id);
} catch (err) {
console.error('Auto-set default account failed:', err);
}
}
};
const refreshProviderSnapshot = async () => {
loading.value = true;
error.value = null;
try {
const snapshot = await fetchProviderSnapshot();
statuses.value = snapshot.statuses ?? [];
accounts.value = snapshot.accounts ?? [];
vendors.value = snapshot.vendors ?? [];
defaultAccountId.value = snapshot.defaultAccountId ?? null;
loading.value = false;
} catch (err) {
error.value = String(err);
loading.value = false;
}
};
const fetchProviders = async () => {
await refreshProviderSnapshot();
};
const addProvider = async (config: Omit<ProviderConfig, 'createdAt' | 'updatedAt'>, apiKey?: string) => {
try {
const fullConfig: ProviderConfig = {
...config,
createdAt: new Date().toISOString(),
updatedAt: new Date().toISOString(),
};
const result = await hostApiFetch<{ success: boolean; error?: string }>('/api/providers', {
method: 'POST',
body: JSON.stringify({ config: fullConfig, apiKey }),
});
if (!result.success) {
throw new Error(result.error || 'Failed to save provider');
}
await refreshProviderSnapshot();
} catch (err) {
console.error('Failed to add provider:', err);
throw err;
}
};
const createAccount = async (account: ProviderAccount, apiKey?: string) => {
try {
const result = await hostApiFetch<{ success: boolean; error?: string }>('/api/provider-accounts', {
method: 'POST',
body: JSON.stringify({ account, apiKey }),
});
if (!result.success) {
throw new Error(result.error || 'Failed to create provider account');
}
await refreshProviderSnapshot();
} catch (err) {
console.error('Failed to add account:', err);
throw err;
}
};
const addAccount = async (account: ProviderAccount, apiKey?: string) => {
return createAccount(account, apiKey);
};
const updateProvider = async (providerId: string, updates: Partial<ProviderConfig>, apiKey?: string) => {
try {
const existing = statuses.value.find((p) => p.id === providerId);
if (!existing) {
throw new Error('Provider not found');
}
const { hasKey: _hasKey, keyMasked: _keyMasked, ...providerConfig } = existing;
const updatedConfig: ProviderConfig = {
...providerConfig,
...updates,
updatedAt: new Date().toISOString(),
};
const result = await hostApiFetch<{ success: boolean; error?: string }>(`/api/providers/${encodeURIComponent(providerId)}`, {
method: 'PUT',
body: JSON.stringify({ updates: updatedConfig, apiKey }),
});
if (!result.success) {
throw new Error(result.error || 'Failed to update provider');
}
await refreshProviderSnapshot();
} catch (err) {
console.error('Failed to update provider:', err);
throw err;
}
};
const updateAccount = async (accountId: string, updates: Partial<ProviderAccount>, apiKey?: string) => {
try {
const result = await hostApiFetch<{ success: boolean; error?: string }>(`/api/provider-accounts/${encodeURIComponent(accountId)}`, {
method: 'PUT',
body: JSON.stringify({ updates, apiKey }),
});
if (!result.success) {
throw new Error(result.error || 'Failed to update provider account');
}
await refreshProviderSnapshot();
} catch (err) {
console.error('Failed to update account:', err);
throw err;
}
};
const deleteProvider = async (providerId: string) => {
try {
const result = await hostApiFetch<{ success: boolean; error?: string }>(`/api/providers/${encodeURIComponent(providerId)}`, {
method: 'DELETE',
});
if (!result.success) {
throw new Error(result.error || 'Failed to delete provider');
}
await refreshProviderSnapshot();
} catch (err) {
console.error('Failed to delete provider:', err);
throw err;
}
};
const removeAccount = async (accountId: string) => {
try {
const result = await hostApiFetch<{ success: boolean; error?: string }>(`/api/provider-accounts/${encodeURIComponent(accountId)}`, {
method: 'DELETE',
});
if (!result.success) {
throw new Error(result.error || 'Failed to delete provider account');
}
await refreshProviderSnapshot();
} catch (err) {
console.error('Failed to delete account:', err);
throw err;
}
};
const deleteAccount = async (accountId: string) => {
return removeAccount(accountId);
};
const setApiKey = async (providerId: string, apiKey: string) => {
try {
const result = await hostApiFetch<{ success: boolean; error?: string }>(`/api/providers/${encodeURIComponent(providerId)}`, {
method: 'PUT',
body: JSON.stringify({ updates: {}, apiKey }),
});
if (!result.success) {
throw new Error(result.error || 'Failed to set API key');
}
await refreshProviderSnapshot();
} catch (err) {
console.error('Failed to set API key:', err);
throw err;
}
};
const updateProviderWithKey = async (providerId: string, updates: Partial<ProviderConfig>, apiKey?: string) => {
try {
const result = await hostApiFetch<{ success: boolean; error?: string }>(`/api/providers/${encodeURIComponent(providerId)}`, {
method: 'PUT',
body: JSON.stringify({ updates, apiKey }),
});
if (!result.success) {
throw new Error(result.error || 'Failed to update provider');
}
await refreshProviderSnapshot();
} catch (err) {
console.error('Failed to update provider with key:', err);
throw err;
}
};
const deleteApiKey = async (providerId: string) => {
try {
const result = await hostApiFetch<{ success: boolean; error?: string }>(
`/api/providers/${encodeURIComponent(providerId)}?apiKeyOnly=1`,
{ method: 'DELETE' },
);
if (!result.success) {
throw new Error(result.error || 'Failed to delete API key');
}
await refreshProviderSnapshot();
} catch (err) {
console.error('Failed to delete API key:', err);
throw err;
}
};
const setDefaultProvider = async (providerId: string) => {
try {
const result = await hostApiFetch<{ success: boolean; error?: string }>('/api/providers/default', {
method: 'PUT',
body: JSON.stringify({ providerId }),
});
if (!result.success) {
throw new Error(result.error || 'Failed to set default provider');
}
await refreshProviderSnapshot();
} catch (err) {
console.error('Failed to set default provider:', err);
throw err;
}
};
const setDefaultAccount = async (accountId: string) => {
try {
const result = await hostApiFetch<{ success: boolean; error?: string }>('/api/provider-accounts/default', {
method: 'PUT',
body: JSON.stringify({ accountId }),
});
if (!result.success) {
throw new Error(result.error || 'Failed to set default provider account');
}
await refreshProviderSnapshot();
} catch (err) {
console.error('Failed to set default account:', err);
throw err;
}
};
const validateAccountApiKey = async (
providerId: string,
apiKey: string,
options?: { baseUrl?: string; apiProtocol?: ProviderAccount['apiProtocol'] }
) => {
try {
const result = await hostApiFetch<{ valid: boolean; error?: string }>('/api/providers/validate', {
method: 'POST',
body: JSON.stringify({ providerId, apiKey, options }),
});
return result;
} catch (err) {
return { valid: false, error: String(err) };
}
};
const validateApiKey = async (
providerId: string,
apiKey: string,
options?: { baseUrl?: string; apiProtocol?: ProviderAccount['apiProtocol'] }
) => {
return validateAccountApiKey(providerId, apiKey, options);
};
const getAccountApiKey = async (providerId: string) => {
try {
const result = await hostApiFetch<{ apiKey: string | null }>(`/api/providers/${encodeURIComponent(providerId)}/api-key`);
return result.apiKey;
} catch {
return null;
}
};
const getApiKey = async (providerId: string) => {
return getAccountApiKey(providerId);
};
return {
statuses,
accounts,
vendors,
defaultAccountId,
loading,
error,
init,
refreshProviderSnapshot,
fetchProviders,
addProvider,
createAccount,
addAccount,
updateProvider,
updateAccount,
deleteProvider,
removeAccount,
deleteAccount,
setApiKey,
updateProviderWithKey,
deleteApiKey,
setDefaultProvider,
setDefaultAccount,
validateAccountApiKey,
validateApiKey,
getAccountApiKey,
getApiKey,
};
});

176
src/stores/script.ts Normal file
View File

@@ -0,0 +1,176 @@
import { defineStore } from 'pinia';
import { ref, computed } from 'vue';
import { scriptApi } from '@lib/script-api';
import type {
AutomationScript,
ScriptSaveInput,
ScriptExecutionResult,
ScriptRecordingStatus,
} from '@lib/script-types';
export const useScriptStore = defineStore('script', () => {
const scripts = ref<AutomationScript[]>([]);
const loading = ref(false);
const error = ref<string | null>(null);
const recordingStatus = ref<ScriptRecordingStatus>('idle');
const executionLogs = ref<Record<string, ScriptExecutionResult>>({});
const safeScripts = computed(() => (Array.isArray(scripts.value) ? scripts.value : []));
const enabledScripts = computed(() => safeScripts.value.filter((s) => s.enabled));
const scriptsByChannel = computed(() => {
const map = new Map<string, AutomationScript[]>();
for (const script of safeScripts.value) {
const list = map.get(script.channel) || [];
list.push(script);
map.set(script.channel, list);
}
return map;
});
const fetchScripts = async () => {
const currentScripts = safeScripts.value;
if (currentScripts.length === 0) {
loading.value = true;
}
error.value = null;
try {
const result = await scriptApi.list();
scripts.value = result;
} catch (err) {
error.value = err instanceof Error ? err.message : String(err);
} finally {
loading.value = false;
}
};
const saveScript = async (input: ScriptSaveInput) => {
try {
const result = await scriptApi.save(input);
if (input.id) {
scripts.value = safeScripts.value.map((s) => (s.id === input.id ? result : s));
} else {
scripts.value = [...safeScripts.value, result];
}
return result;
} catch (err) {
const msg = err instanceof Error ? err.message : String(err);
error.value = msg;
throw err;
}
};
const deleteScript = async (id: string) => {
try {
await scriptApi.delete(id);
scripts.value = safeScripts.value.filter((s) => s.id !== id);
delete executionLogs.value[id];
} catch (err) {
const msg = err instanceof Error ? err.message : String(err);
error.value = msg;
throw err;
}
};
const toggleScript = async (id: string, enabled: boolean) => {
try {
await scriptApi.toggle(id, enabled);
scripts.value = safeScripts.value.map((s) =>
s.id === id ? { ...s, enabled, updatedAt: new Date().toISOString() } : s,
);
} catch (err) {
const msg = err instanceof Error ? err.message : String(err);
error.value = msg;
throw err;
}
};
const runScript = async (id: string) => {
try {
const result = await scriptApi.run(id);
executionLogs.value = { ...executionLogs.value, [id]: result };
// 更新本地 lastRun
scripts.value = safeScripts.value.map((s) =>
s.id === id
? {
...s,
lastRun: {
time: new Date().toISOString(),
success: result.success,
error: result.error,
},
updatedAt: new Date().toISOString(),
}
: s,
);
return result;
} catch (err) {
const msg = err instanceof Error ? err.message : String(err);
error.value = msg;
throw err;
}
};
const startRecording = async (url?: string) => {
recordingStatus.value = 'recording';
try {
const result = await scriptApi.startRecording(url);
if (!result.success) {
recordingStatus.value = 'idle';
}
return result;
} catch (err) {
recordingStatus.value = 'idle';
throw err;
}
};
const stopRecording = async () => {
try {
const result = await scriptApi.stopRecording();
recordingStatus.value = 'stopped';
return result;
} catch (err) {
recordingStatus.value = 'idle';
throw err;
}
};
const resetRecording = () => {
recordingStatus.value = 'idle';
};
const codegen = async (id: string, url?: string) => {
try {
const result = await scriptApi.codegen(id, url);
if (!result.success) {
error.value = result.error || 'Codegen failed';
}
return result;
} catch (err) {
const msg = err instanceof Error ? err.message : String(err);
error.value = msg;
throw err;
}
};
return {
scripts,
loading,
error,
recordingStatus,
executionLogs,
safeScripts,
enabledScripts,
scriptsByChannel,
fetchScripts,
saveScript,
deleteScript,
toggleScript,
runScript,
startRecording,
stopRecording,
resetRecording,
codegen,
};
});

25
src/stores/sharedStore.ts Normal file
View File

@@ -0,0 +1,25 @@
import { defineStore } from 'pinia'
import { isEqual } from 'lodash-es'
export const useSharedStore = defineStore('shared', {
state: () => ({
sharedData: {},
}),
actions: {
updateSharedData(data: any) {
this.sharedData = Object.assign(this.sharedData, data)
const cloneData = JSON.parse(JSON.stringify(this.sharedData))
if (!isEqual(this.sharedData, data)) {
// 同步状态到主进程
try {
} catch (error) {
}
}
}
}
})

123
src/stores/skills.ts Normal file
View File

@@ -0,0 +1,123 @@
import { defineStore } from 'pinia';
import type { Skill, MarketplaceSkill } from '@src/lib/skills-types';
import {
apiFetchSkills,
apiSearchSkills,
apiInstallSkill,
apiUninstallSkill,
apiUpdateSkillConfig,
} from '@src/lib/skills-api';
const INSTALL_ERROR_CODES = new Set(['installTimeoutError', 'installRateLimitError']);
const FETCH_ERROR_CODES = new Set(['fetchTimeoutError', 'fetchRateLimitError', 'timeoutError', 'rateLimitError']);
const SEARCH_ERROR_CODES = new Set(['searchTimeoutError', 'searchRateLimitError', 'timeoutError', 'rateLimitError']);
export const useSkillsStore = defineStore('skills', {
state: () => ({
skills: [] as Skill[],
searchResults: [] as MarketplaceSkill[],
loading: false,
searching: false,
searchError: null as string | null,
installing: {} as Record<string, boolean>,
error: null as string | null,
}),
getters: {
sourceStats: (state) => {
const safeSkills = Array.isArray(state.skills) ? state.skills : [];
return {
all: safeSkills.length,
builtIn: safeSkills.filter(s => s.isBundled).length,
marketplace: safeSkills.filter(s => !s.isBundled).length,
};
},
},
actions: {
async fetchSkills() {
if (this.skills.length === 0) {
this.loading = true;
}
this.error = null;
try {
this.skills = await apiFetchSkills();
} catch (error) {
console.error('Failed to fetch skills:', error);
const msg = error instanceof Error ? error.message : String(error);
this.error = FETCH_ERROR_CODES.has(msg) ? msg : msg;
} finally {
this.loading = false;
}
},
async searchSkills(query: string) {
this.searching = true;
this.searchError = null;
try {
this.searchResults = await apiSearchSkills(query);
} catch (error) {
const msg = error instanceof Error ? error.message : String(error);
this.searchError = SEARCH_ERROR_CODES.has(msg) ? msg : msg;
} finally {
this.searching = false;
}
},
async installSkill(slug: string, version?: string) {
this.installing[slug] = true;
try {
await apiInstallSkill(slug, version);
await this.fetchSkills();
} finally {
delete this.installing[slug];
}
},
async uninstallSkill(slug: string) {
this.installing[slug] = true;
try {
await apiUninstallSkill(slug);
await this.fetchSkills();
} finally {
delete this.installing[slug];
}
},
async enableSkill(skillId: string) {
const skill = this.skills.find(s => s.id === skillId);
if (!skill) return;
try {
await apiUpdateSkillConfig(skillId, { enabled: true });
skill.enabled = true;
} catch (error) {
console.error('Failed to enable skill:', error);
throw error;
}
},
async disableSkill(skillId: string) {
const skill = this.skills.find(s => s.id === skillId);
if (!skill) return;
if (skill.isCore) {
throw new Error('Cannot disable core skill');
}
try {
await apiUpdateSkillConfig(skillId, { enabled: false });
skill.enabled = false;
} catch (error) {
console.error('Failed to disable skill:', error);
throw error;
}
},
updateSkill(skillId: string, updates: Partial<Skill>) {
const skill = this.skills.find(s => s.id === skillId);
if (skill) {
Object.assign(skill, updates);
}
},
},
});
export { INSTALL_ERROR_CODES, FETCH_ERROR_CODES, SEARCH_ERROR_CODES };

73
src/stores/userinfo.ts Normal file
View File

@@ -0,0 +1,73 @@
import { defineStore } from 'pinia'
import { authOauth2TokenUsingPost } from "@src/api"
import { Session } from '@utils/storage'
import { encryption } from '@utils/other'
export const useUserStore = defineStore('userInfo', {
state: () => ({
token: Session.get('token'),
}),
actions: {
/**
* 登录方法
* @function login
* @async
* @param {Object} data - 登录数据
* @returns {Promise<Object>}
*/
async login(data: any) {
data.grant_type = 'password';
data.scope = 'server';
// const { VITE_OAUTH2_PASSWORD_CLIENT, VITE_PWD_ENC_KEY } = (import.meta as any).env
// const basicAuth = 'Basic ' + window.btoa(VITE_OAUTH2_PASSWORD_CLIENT);
// Session.set('basicAuth', basicAuth);
// let encPassword = data.password;
// 密码加密
// if (VITE_PWD_ENC_KEY) {
// encPassword = encryption(data.password, VITE_PWD_ENC_KEY);
// }
return new Promise((resolve, reject) => {
authOauth2TokenUsingPost({
body: { clientId: '', ...data },
options: {
headers: {
isToken: true,
// Authorization: basicAuth,
'Content-Type': 'application/x-www-form-urlencoded',
'Authorization': 'Basic Y3VzdG9tUEM6Y3VzdG9tUEM='
}
}
})
.then((res: any) => {
// 存储token 信息
Session.set('token', res.access_token);
Session.set('refresh_token', res.refresh_token);
resolve(res)
})
.catch((err) => {
reject(err);
});
});
},
// 退出系统
logOut() {
return new Promise((resolve, reject) => {
// logout(this.token).then(() => {
// this.token = ''
// this.roles = []
// this.permissions = []
// removeToken()
// resolve()
// }).catch(error => {
// reject(error)
// })
})
}
}
})