chore: restructure project and add i18n support
- Reorganize project structure with new electron and shared directories - Add comprehensive i18n support with Chinese, English, and Japanese locales - Update build configurations and TypeScript paths for new structure - Add various UI components including chat interface and task management - Include Windows release binaries and localization files - Update dependencies and fix import paths throughout the codebase
This commit is contained in:
129
src/store/locale.ts
Normal file
129
src/store/locale.ts
Normal 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 };
|
||||
25
src/store/sharedStore.ts
Normal file
25
src/store/sharedStore.ts
Normal 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) {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
73
src/store/userinfo.ts
Normal file
73
src/store/userinfo.ts
Normal 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)
|
||||
// })
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
Reference in New Issue
Block a user