diff --git a/package.json b/package.json index efd04fae..fba2b298 100644 --- a/package.json +++ b/package.json @@ -6,6 +6,7 @@ "serve": "vue-cli-service serve", "serve:dist": "serve dist", "build": "vue-cli-service build", + "build:lt-node-16": "cross-env NODE_OPTIONS=--openssl-legacy-provider vue-cli-service build", "lint": "cross-env NODE_ENV=production vue-cli-service lint" }, "dependencies": { diff --git a/src/data/changelog.json b/src/data/changelog.json index 99012184..dc03a926 100644 --- a/src/data/changelog.json +++ b/src/data/changelog.json @@ -1,4 +1,8 @@ [ + { + "time": "2024-08-27", + "changes": ["【精英材料计算】森空岛功能支持跟随多帐号切换"] + }, { "time": "2024-08-11", "changes": ["【精英材料计算】森空岛功能支持设置 Token"] diff --git a/src/store/skland.js b/src/store/skland.js index 06b87721..7ca9d108 100644 --- a/src/store/skland.js +++ b/src/store/skland.js @@ -1,9 +1,14 @@ import _ from 'lodash'; import { defineStore } from 'pinia'; -import { computed, watch, shallowRef } from 'vue'; -import { useNamespacedLocalStorage } from '@/utils/NamespacedLocalStorage'; +import { ref, computed, watch, shallowRef } from 'vue'; +import NamespacedLocalStorage, { + useDynamicNamespacedLocalStorage, +} from '@/utils/NamespacedLocalStorage'; import { fetchSkland, isNotLoginError, sklandOAuthLogin } from '@/utils/skland'; import { PROXY_SERVER } from '@/utils/env'; +import { DEFAULT_ID as MULTI_ACCOUNT_DEFAULT_ID } from '@/utils/MultiAccount'; + +const STORAGE_NAME = 'skland'; const cnNumTextMap = ['零', '一', '二']; @@ -40,7 +45,8 @@ const handleCharactersCultivateData = list => { }; export const useSklandStore = defineStore('skland', () => { - const storage = useNamespacedLocalStorage('skland', { + const storageName = ref(STORAGE_NAME); + const [storage, storageNameChanging] = useDynamicNamespacedLocalStorage(storageName, { useOAuth: false, oauthToken: '', cred: '', @@ -53,6 +59,7 @@ export const useSklandStore = defineStore('skland', () => { const hasProxyServer = !!PROXY_SERVER; const canUseOAuth = () => hasProxyServer && useOAuth.value && oauthTokenValid.value; + const cultivateCache = new Map(); let cultivateLastFetch = 0; const cultivateCharacters = shallowRef({}); @@ -66,14 +73,19 @@ export const useSklandStore = defineStore('skland', () => { cultivateLastFetch = 0; }; + watch(storageName, (newName, oldName) => { + cultivateCache.set(oldName, [cultivateLastFetch, cultivateCharacters.value]); + [cultivateLastFetch, cultivateCharacters.value] = cultivateCache.get(newName) || [0, {}]; + }); + watch(oauthToken, () => { - if (!oauthTokenValid.value) return; + if (storageNameChanging.value || !oauthTokenValid.value) return; cred.value = ''; resetStates(); }); watch(cred, () => { - if (!credValid.value || canUseOAuth()) return; + if (storageNameChanging.value || !credValid.value || canUseOAuth()) return; resetStates(); }); @@ -163,6 +175,15 @@ export const useSklandStore = defineStore('skland', () => { return parts.filter(_.identity).join('/'); }; + const handleMultiAccountIdChange = id => { + storageName.value = id === MULTI_ACCOUNT_DEFAULT_ID ? STORAGE_NAME : `${STORAGE_NAME}-${id}`; + }; + + const handleMultiAccountIdDelete = id => { + if (id === MULTI_ACCOUNT_DEFAULT_ID) return; + new NamespacedLocalStorage(`${STORAGE_NAME}-${id}`).clear(); + }; + return { ready: computed(() => canUseOAuth() || credValid.value), oauthAvailable: hasProxyServer, @@ -176,5 +197,7 @@ export const useSklandStore = defineStore('skland', () => { updateSklandCultivateIfExpired, getCultivateCharLevelText, getPresetItemCultivateText, + handleMultiAccountIdChange, + handleMultiAccountIdDelete, }; }); diff --git a/src/utils/MultiAccount.js b/src/utils/MultiAccount.js index cd6a62bf..ef5bebfa 100644 --- a/src/utils/MultiAccount.js +++ b/src/utils/MultiAccount.js @@ -40,7 +40,7 @@ export default class MultiAccount { val => { this.updateStoreName(); this.config.setItem(ConfigKey.CURRENT, val); - this.emitter.emit('change'); + this.emitter.emit('change', val); }, ); watch( @@ -83,8 +83,8 @@ export default class MultiAccount { if (this.data.id === targetId) { this.data.id = DEFAULT_ID; } - const storage = new NamespacedLocalStorage(`${this.name}.${targetId}`); - storage.clear(); + new NamespacedLocalStorage(`${this.name}.${targetId}`).clear(); + this.emitter.emit('delete', targetId); } renameAccount(id, name) { diff --git a/src/utils/NamespacedLocalStorage.js b/src/utils/NamespacedLocalStorage.js index d75303f0..0bfb8053 100644 --- a/src/utils/NamespacedLocalStorage.js +++ b/src/utils/NamespacedLocalStorage.js @@ -1,4 +1,5 @@ import _ from 'lodash'; +import { nextTick, ref } from 'vue'; import i18n from '../i18n'; import snackbar from './snackbar'; import { reactive, toRefs, watch } from 'vue'; @@ -152,3 +153,35 @@ export const useNamespacedLocalStorage = (name, defaultValue) => { return refs; }; + +/** + * @template T + * @param {import('vue').Ref} name + * @param {T} defaultValue + * @returns {[import('vue').ToRefs, import('vue').Ref]} + */ +export const useDynamicNamespacedLocalStorage = (name, defaultValue) => { + const nls = new NamespacedLocalStorage(name.value); + const nameChanging = ref(false); + + const refs = toRefs(reactive(mergeObjWithDefault(nls.object(), defaultValue))); + + watch(name, async newName => { + nameChanging.value = true; + nls.name = newName; + _.each(mergeObjWithDefault(nls.object(), defaultValue), (value, key) => { + refs[key].value = value; + }); + await nextTick(); + nameChanging.value = false; + }); + + _.each(refs, (target, key) => { + watch(target, val => { + if (nameChanging.value) return; + nls.setItem(key, val); + }); + }); + + return [refs, nameChanging]; +}; diff --git a/src/views/Material/index.js b/src/views/Material/index.js index bf9a8ea2..a3b3bbb2 100644 --- a/src/views/Material/index.js +++ b/src/views/Material/index.js @@ -966,6 +966,8 @@ export default defineComponent({ 'fetchSklandCultivate', 'updateSklandCultivateIfExpired', 'getPresetItemCultivateText', + 'handleMultiAccountIdChange', + 'handleMultiAccountIdDelete', ]), isPlannerUnavailableItem(id) { return ( @@ -1832,6 +1834,9 @@ export default defineComponent({ if (e.key === 'Escape') this.clearPresetInput(); }); multiAccount.emitter.on('change', this.initFromStorage); + multiAccount.emitter.on('change', this.handleMultiAccountIdChange); + multiAccount.emitter.on('delete', this.handleMultiAccountIdDelete); + this.handleMultiAccountIdChange(multiAccount.data.id); }, activated() { if (this.plannerInited && this.plannerInitedMd5 !== this.curDataMd5) { @@ -1843,5 +1848,7 @@ export default defineComponent({ this.$root.importItemsListening = false; this.$root.$off('import-items', this.handleImportItemsEvent); multiAccount.emitter.off('change', this.initFromStorage); + multiAccount.emitter.off('change', this.handleMultiAccountIdChange); + multiAccount.emitter.off('delete', this.handleMultiAccountIdDelete); }, });