|
|
@@ -1,17 +1,20 @@
|
|
|
-import { getDictData, getMultipleDictData } from '@/api/services/dict';
|
|
|
+import {
|
|
|
+ getDictData,
|
|
|
+ getMultipleDictData
|
|
|
+} from '@/api/services/dict';
|
|
|
import storage from '@/utils/storage';
|
|
|
import staticDict from '@/utils/staticDict';
|
|
|
|
|
|
// 全局字典缓存对象,用于存储已加载的字典数据
|
|
|
const dictCache = {
|
|
|
- // 缓存的字典数据,格式为 { dictType: [{label, value, ...}, ...] }
|
|
|
- data: {},
|
|
|
- // 缓存过期时间,单位为毫秒
|
|
|
- expireTime: 1000 * 60 * 60, // 1小时
|
|
|
- // 缓存最后更新时间
|
|
|
- lastUpdateTime: {},
|
|
|
- // 正在加载的字典类型,用于防止重复请求
|
|
|
- loading: {}
|
|
|
+ // 缓存的字典数据,格式为 { dictType: [{label, value, ...}, ...] }
|
|
|
+ data: {},
|
|
|
+ // 缓存过期时间,单位为毫秒
|
|
|
+ expireTime: 1000 * 60 * 60, // 1小时
|
|
|
+ // 缓存最后更新时间
|
|
|
+ lastUpdateTime: {},
|
|
|
+ // 正在加载的字典类型,用于防止重复请求
|
|
|
+ loading: {}
|
|
|
};
|
|
|
|
|
|
/**
|
|
|
@@ -24,355 +27,505 @@ const dictCache = {
|
|
|
* 5. 在模板中直接使用 dictData 对象获取字典项 v-for="item in dictData.sys_user_sex"
|
|
|
*/
|
|
|
export default {
|
|
|
- data() {
|
|
|
- return {
|
|
|
- // 组件中的字典数据
|
|
|
- dictData: {},
|
|
|
- // 定义组件需要加载的字典类型
|
|
|
- dictTypeList: [],
|
|
|
- // 字典加载状态
|
|
|
- dictLoading: false
|
|
|
- };
|
|
|
- },
|
|
|
- created() {
|
|
|
- // 组件创建时,如果有定义dictTypeList,则自动加载字典数据
|
|
|
- if (this.dictTypeList && this.dictTypeList.length > 0) {
|
|
|
- console.log(`[DictMixin] Component created, loading dictionaries: ${this.dictTypeList.join(', ')}`);
|
|
|
- this.loadDict();
|
|
|
- }
|
|
|
- },
|
|
|
- methods: {
|
|
|
- /**
|
|
|
- * 加载字典数据
|
|
|
- * @param {Array} dictTypes - 字典类型数组,如果不传则使用组件中定义的dictTypeList
|
|
|
- * @returns {Promise} - 返回字典加载的Promise对象
|
|
|
- */
|
|
|
- loadDict(dictTypes) {
|
|
|
- const types = dictTypes || this.dictTypeList;
|
|
|
- if (!types || types.length === 0) {
|
|
|
- return Promise.resolve({});
|
|
|
- }
|
|
|
-
|
|
|
- // 标记加载中
|
|
|
- this.dictLoading = true;
|
|
|
-
|
|
|
- // 需要从服务器获取的字典类型
|
|
|
- const needFetch = [];
|
|
|
-
|
|
|
- // 检查是否有静态字典或缓存
|
|
|
- types.forEach(type => {
|
|
|
- // 先检查是否有静态字典
|
|
|
- if (staticDict[type]) {
|
|
|
- // 使用静态字典数据
|
|
|
- console.log(`[DictMixin] Using static dictionary for ${type}`);
|
|
|
- this.$set(this.dictData, type, staticDict[type]);
|
|
|
- } else {
|
|
|
- // 检查缓存
|
|
|
- const cachedDict = this.getDictFromCache(type);
|
|
|
- if (cachedDict) {
|
|
|
- // 已有缓存,直接使用
|
|
|
- console.log(`[DictMixin] Using cached dictionary for ${type}`);
|
|
|
- this.$set(this.dictData, type, cachedDict);
|
|
|
- } else if (!dictCache.loading[type]) {
|
|
|
- // 需要从服务器获取,并且当前没有其他组件正在加载
|
|
|
- console.log(`[DictMixin] Need to fetch dictionary ${type} from server`);
|
|
|
- needFetch.push(type);
|
|
|
- } else {
|
|
|
- console.log(`[DictMixin] Dictionary ${type} is already being loaded by another component, waiting...`);
|
|
|
- }
|
|
|
- }
|
|
|
- });
|
|
|
-
|
|
|
- // 如果所有字典都已缓存或使用静态数据,直接返回
|
|
|
- if (needFetch.length === 0) {
|
|
|
- this.dictLoading = false;
|
|
|
-
|
|
|
- // 检查是否有正在加载的字典,如果有,等待它们完成
|
|
|
- const loadingTypes = types.filter(type => dictCache.loading[type]);
|
|
|
- if (loadingTypes.length > 0) {
|
|
|
- return this.waitForDictLoading(loadingTypes);
|
|
|
- }
|
|
|
-
|
|
|
- return Promise.resolve(this.dictData);
|
|
|
- }
|
|
|
-
|
|
|
- // 从服务器获取字典数据
|
|
|
- return this.fetchDictData(needFetch).then(res => {
|
|
|
- this.dictLoading = false;
|
|
|
- return this.dictData;
|
|
|
- }).catch(err => {
|
|
|
- this.dictLoading = false;
|
|
|
- console.error('加载字典数据失败:', err);
|
|
|
- return Promise.reject(err);
|
|
|
- });
|
|
|
- },
|
|
|
-
|
|
|
- /**
|
|
|
- * 等待指定类型的字典加载完成
|
|
|
- * @param {Array} types - 字典类型数组
|
|
|
- * @returns {Promise} - 返回等待的Promise对象
|
|
|
- */
|
|
|
- waitForDictLoading(types) {
|
|
|
- return new Promise(resolve => {
|
|
|
- const checkInterval = setInterval(() => {
|
|
|
- const stillLoading = types.some(type => dictCache.loading[type]);
|
|
|
- if (!stillLoading) {
|
|
|
- clearInterval(checkInterval);
|
|
|
-
|
|
|
- // 加载完成后,从缓存中获取数据
|
|
|
- types.forEach(type => {
|
|
|
- const cachedDict = this.getDictFromCache(type);
|
|
|
- if (cachedDict) {
|
|
|
- this.$set(this.dictData, type, cachedDict);
|
|
|
- }
|
|
|
- });
|
|
|
-
|
|
|
- resolve(this.dictData);
|
|
|
- }
|
|
|
- }, 50);
|
|
|
- });
|
|
|
- },
|
|
|
-
|
|
|
- /**
|
|
|
- * 从服务器获取字典数据
|
|
|
- * @param {Array} dictTypes - 字典类型数组
|
|
|
- * @returns {Promise} - 返回字典获取的Promise对象
|
|
|
- */
|
|
|
- fetchDictData(dictTypes) {
|
|
|
- // 标记这些字典类型正在加载
|
|
|
- dictTypes.forEach(type => {
|
|
|
- dictCache.loading[type] = true;
|
|
|
- });
|
|
|
-
|
|
|
- if (dictTypes.length === 1) {
|
|
|
- // 单个字典类型,直接获取
|
|
|
- console.log(`[DictMixin] Fetching single dictionary: ${dictTypes[0]}`);
|
|
|
- return getDictData(dictTypes[0]).then(res => {
|
|
|
- if (res.data.code === 200) {
|
|
|
- const dictType = dictTypes[0];
|
|
|
- const dictList = res.data.data || [];
|
|
|
-
|
|
|
- // 更新组件字典数据
|
|
|
- this.$set(this.dictData, dictType, dictList);
|
|
|
-
|
|
|
- // 更新缓存
|
|
|
- this.updateDictCache(dictType, dictList);
|
|
|
-
|
|
|
- // 取消加载标记
|
|
|
- delete dictCache.loading[dictType];
|
|
|
-
|
|
|
- return dictList;
|
|
|
- } else {
|
|
|
- console.error(`获取字典[${dictTypes[0]}]数据失败:`, res.data.msg);
|
|
|
-
|
|
|
- // 取消加载标记
|
|
|
- delete dictCache.loading[dictTypes[0]];
|
|
|
-
|
|
|
- return Promise.reject(res.data.msg);
|
|
|
- }
|
|
|
- }).catch(err => {
|
|
|
- // 发生错误时取消加载标记
|
|
|
- delete dictCache.loading[dictTypes[0]];
|
|
|
- throw err;
|
|
|
- });
|
|
|
- } else {
|
|
|
- // 多个字典类型,批量获取
|
|
|
- console.log(`[DictMixin] Batch fetching ${dictTypes.length} dictionaries: ${dictTypes.join(', ')}`);
|
|
|
- return getMultipleDictData(dictTypes).then(res => {
|
|
|
- if (res.data.code === 200) {
|
|
|
- const dictMap = res.data.data || {};
|
|
|
-
|
|
|
- // 更新组件字典数据和缓存
|
|
|
- Object.keys(dictMap).forEach(dictType => {
|
|
|
- const dictList = dictMap[dictType] || [];
|
|
|
-
|
|
|
- // 更新组件字典数据
|
|
|
- this.$set(this.dictData, dictType, dictList);
|
|
|
-
|
|
|
- // 更新缓存
|
|
|
- this.updateDictCache(dictType, dictList);
|
|
|
-
|
|
|
- // 取消加载标记
|
|
|
- delete dictCache.loading[dictType];
|
|
|
- });
|
|
|
-
|
|
|
- console.log(`[DictMixin] Successfully loaded ${Object.keys(dictMap).length} dictionaries`);
|
|
|
- return dictMap;
|
|
|
- } else {
|
|
|
- console.error(`获取字典数据失败:`, res.data.msg);
|
|
|
-
|
|
|
- // 取消所有加载标记
|
|
|
- dictTypes.forEach(type => {
|
|
|
- delete dictCache.loading[type];
|
|
|
- });
|
|
|
-
|
|
|
- return Promise.reject(res.data.msg);
|
|
|
- }
|
|
|
- }).catch(err => {
|
|
|
- // 发生错误时取消所有加载标记
|
|
|
- dictTypes.forEach(type => {
|
|
|
- delete dictCache.loading[type];
|
|
|
- });
|
|
|
- throw err;
|
|
|
- });
|
|
|
- }
|
|
|
- },
|
|
|
-
|
|
|
- /**
|
|
|
- * 从缓存中获取字典数据
|
|
|
- * @param {String} dictType - 字典类型
|
|
|
- * @returns {Array|null} - 返回字典数据,不存在或已过期则返回null
|
|
|
- */
|
|
|
- getDictFromCache(dictType) {
|
|
|
- // 判断是否有缓存
|
|
|
- if (!dictCache.data[dictType]) {
|
|
|
- return null;
|
|
|
- }
|
|
|
-
|
|
|
- // 判断缓存是否过期
|
|
|
- const lastUpdateTime = dictCache.lastUpdateTime[dictType] || 0;
|
|
|
- const now = Date.now();
|
|
|
- if (now - lastUpdateTime > dictCache.expireTime) {
|
|
|
- // 缓存已过期,删除缓存
|
|
|
- delete dictCache.data[dictType];
|
|
|
- delete dictCache.lastUpdateTime[dictType];
|
|
|
- return null;
|
|
|
- }
|
|
|
-
|
|
|
- // 返回缓存的字典数据
|
|
|
- return dictCache.data[dictType];
|
|
|
- },
|
|
|
-
|
|
|
- /**
|
|
|
- * 更新字典缓存
|
|
|
- * @param {String} dictType - 字典类型
|
|
|
- * @param {Array} dictList - 字典数据列表
|
|
|
- */
|
|
|
- updateDictCache(dictType, dictList) {
|
|
|
- dictCache.data[dictType] = dictList;
|
|
|
- dictCache.lastUpdateTime[dictType] = Date.now();
|
|
|
-
|
|
|
- // 更新本地存储
|
|
|
- try {
|
|
|
- // 只存储最后更新时间,具体数据保存在内存中
|
|
|
- storage.setDict(`dict_time_${dictType}`, dictCache.lastUpdateTime[dictType]);
|
|
|
- } catch (e) {
|
|
|
- console.error('更新字典缓存失败:', e);
|
|
|
- }
|
|
|
- },
|
|
|
-
|
|
|
- /**
|
|
|
- * 清除字典缓存
|
|
|
- * @param {String} dictType - 字典类型,不传则清除所有缓存
|
|
|
- */
|
|
|
- clearDictCache(dictType) {
|
|
|
- if (dictType) {
|
|
|
- delete dictCache.data[dictType];
|
|
|
- delete dictCache.lastUpdateTime[dictType];
|
|
|
- storage.removeDict(`dict_time_${dictType}`);
|
|
|
- } else {
|
|
|
- dictCache.data = {};
|
|
|
- dictCache.lastUpdateTime = {};
|
|
|
- // 清除所有字典相关的本地存储
|
|
|
- const keys = Object.keys(localStorage);
|
|
|
- keys.forEach(key => {
|
|
|
- if (key.startsWith('dict_time_')) {
|
|
|
- storage.removeDict(key);
|
|
|
- }
|
|
|
- });
|
|
|
- }
|
|
|
- },
|
|
|
-
|
|
|
- /**
|
|
|
- * 根据字典值获取对应的字典标签
|
|
|
- * @param {String} dictType - 字典类型
|
|
|
- * @param {String|Number} value - 字典值
|
|
|
- * @param {String} defaultLabel - 默认标签
|
|
|
- * @returns {String} - 字典标签
|
|
|
- */
|
|
|
- getDictLabel(dictType, value, defaultLabel = '') {
|
|
|
- // 首先检查组件数据
|
|
|
- const dictList = this.dictData[dictType];
|
|
|
- if (dictList) {
|
|
|
- const item = dictList.find(dict => dict.dictValue === value);
|
|
|
- if (item) return item.dictLabel;
|
|
|
- }
|
|
|
-
|
|
|
- // 再检查静态字典
|
|
|
- // const staticDictList = staticDict[dictType];
|
|
|
- // if (staticDictList) {
|
|
|
- // const item = staticDictList.find(dict => dict.value === value);
|
|
|
- // if (item) return item.label;
|
|
|
- // }
|
|
|
-
|
|
|
- // 都没找到,返回默认值
|
|
|
- return defaultLabel;
|
|
|
- },
|
|
|
-
|
|
|
- /**
|
|
|
- * 根据字典标签获取对应的字典值
|
|
|
- * @param {String} dictType - 字典类型
|
|
|
- * @param {String} label - 字典标签
|
|
|
- * @param {String|Number} defaultValue - 默认值
|
|
|
- * @returns {String|Number} - 字典值
|
|
|
- */
|
|
|
- getDictValue(dictType, label, defaultValue = '') {
|
|
|
- // 首先检查组件数据
|
|
|
- const dictList = this.dictData[dictType];
|
|
|
- if (dictList) {
|
|
|
- const item = dictList.find(dict => dict.label === label);
|
|
|
- if (item) return item.value;
|
|
|
- }
|
|
|
-
|
|
|
- // 再检查静态字典
|
|
|
- const staticDictList = staticDict[dictType];
|
|
|
- if (staticDictList) {
|
|
|
- const item = staticDictList.find(dict => dict.label === label);
|
|
|
- if (item) return item.value;
|
|
|
- }
|
|
|
-
|
|
|
- // 都没找到,返回默认值
|
|
|
- return defaultValue;
|
|
|
- },
|
|
|
-
|
|
|
- /**
|
|
|
- * 获取字典列表
|
|
|
- * @param {String} dictType - 字典类型
|
|
|
- * @returns {Array} - 字典列表
|
|
|
- */
|
|
|
- getDictList(dictType) {
|
|
|
- // 首先检查组件数据
|
|
|
- const dictList = this.dictData[dictType];
|
|
|
- if (dictList) return dictList;
|
|
|
-
|
|
|
- // 再检查静态字典
|
|
|
- return staticDict[dictType] || [];
|
|
|
- },
|
|
|
-
|
|
|
- /**
|
|
|
- * 获取字典类型对应的样式类
|
|
|
- * @param {String} dictType - 字典类型
|
|
|
- * @param {String|Number} value - 字典值
|
|
|
- * @param {String} defaultClass - 默认样式类
|
|
|
- * @returns {String} - 字典项的样式类
|
|
|
- */
|
|
|
- getDictClass(dictType, value, defaultClass = '') {
|
|
|
- // 首先检查组件数据
|
|
|
- const dictList = this.dictData[dictType];
|
|
|
- if (dictList) {
|
|
|
- const item = dictList.find(dict => dict.dictValue === value);
|
|
|
- if (item && item.listClass) return item.listClass;
|
|
|
- }
|
|
|
-
|
|
|
- // 再检查静态字典
|
|
|
- // const staticDictList = staticDict[dictType];
|
|
|
- // if (staticDictList) {
|
|
|
- // const item = staticDictList.find(dict => dict.value === value);
|
|
|
- // if (item && item.listClass) return item.listClass;
|
|
|
- // }
|
|
|
-
|
|
|
- // 都没找到,返回默认值
|
|
|
- return defaultClass;
|
|
|
- }
|
|
|
- }
|
|
|
-};
|
|
|
+ data() {
|
|
|
+ return {
|
|
|
+ // 组件中的字典数据
|
|
|
+ dictData: {},
|
|
|
+ // 定义组件需要加载的字典类型
|
|
|
+ dictTypeList: [],
|
|
|
+ // 字典加载状态
|
|
|
+ dictLoading: false
|
|
|
+ };
|
|
|
+ },
|
|
|
+ created() {
|
|
|
+ // 组件创建时,如果有定义dictTypeList,则自动加载字典数据
|
|
|
+ if (this.dictTypeList && this.dictTypeList.length > 0) {
|
|
|
+ console.log(`[DictMixin] Component created, loading dictionaries: ${this.dictTypeList.join(', ')}`);
|
|
|
+ this.loadDict();
|
|
|
+ }
|
|
|
+ },
|
|
|
+ methods: {
|
|
|
+ /**
|
|
|
+ * 加载字典数据
|
|
|
+ * @param {Array} dictTypes - 字典类型数组,如果不传则使用组件中定义的dictTypeList
|
|
|
+ * @returns {Promise} - 返回字典加载的Promise对象
|
|
|
+ */
|
|
|
+ loadDict(dictTypes) {
|
|
|
+ const types = dictTypes || this.dictTypeList;
|
|
|
+ if (!types || types.length === 0) {
|
|
|
+ return Promise.resolve({});
|
|
|
+ }
|
|
|
+
|
|
|
+ // 标记加载中
|
|
|
+ this.dictLoading = true;
|
|
|
+
|
|
|
+ // 需要从服务器获取的字典类型
|
|
|
+ const needFetch = [];
|
|
|
+
|
|
|
+ // 检查是否有静态字典或缓存
|
|
|
+ types.forEach(type => {
|
|
|
+ // 先检查是否有静态字典
|
|
|
+ if (staticDict[type]) {
|
|
|
+ // 使用静态字典数据
|
|
|
+ console.log(`[DictMixin] Using static dictionary for ${type}`);
|
|
|
+ this.$set(this.dictData, type, staticDict[type]);
|
|
|
+ } else {
|
|
|
+ // 检查缓存
|
|
|
+ const cachedDict = this.getDictFromCache(type);
|
|
|
+ if (cachedDict) {
|
|
|
+ // 已有缓存,直接使用
|
|
|
+ console.log(`[DictMixin] Using cached dictionary for ${type}`);
|
|
|
+ this.$set(this.dictData, type, cachedDict);
|
|
|
+ } else if (!dictCache.loading[type]) {
|
|
|
+ // 需要从服务器获取,并且当前没有其他组件正在加载
|
|
|
+ console.log(`[DictMixin] Need to fetch dictionary ${type} from server`);
|
|
|
+ needFetch.push(type);
|
|
|
+ } else {
|
|
|
+ console.log(
|
|
|
+ `[DictMixin] Dictionary ${type} is already being loaded by another component, waiting...`
|
|
|
+ );
|
|
|
+ }
|
|
|
+ }
|
|
|
+ });
|
|
|
+
|
|
|
+ // 如果所有字典都已缓存或使用静态数据,直接返回
|
|
|
+ if (needFetch.length === 0) {
|
|
|
+ this.dictLoading = false;
|
|
|
+
|
|
|
+ // 检查是否有正在加载的字典,如果有,等待它们完成
|
|
|
+ const loadingTypes = types.filter(type => dictCache.loading[type]);
|
|
|
+ if (loadingTypes.length > 0) {
|
|
|
+ return this.waitForDictLoading(loadingTypes);
|
|
|
+ }
|
|
|
+
|
|
|
+ return Promise.resolve(this.dictData);
|
|
|
+ }
|
|
|
+
|
|
|
+ // 从服务器获取字典数据
|
|
|
+ return this.fetchDictData(needFetch).then(res => {
|
|
|
+ this.dictLoading = false;
|
|
|
+ console.log("this.dictData", this.dictData);
|
|
|
+ return this.dictData;
|
|
|
+ }).catch(err => {
|
|
|
+ this.dictLoading = false;
|
|
|
+ console.error('加载字典数据失败:', err);
|
|
|
+ return Promise.reject(err);
|
|
|
+ });
|
|
|
+ },
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 等待指定类型的字典加载完成
|
|
|
+ * @param {Array} types - 字典类型数组
|
|
|
+ * @returns {Promise} - 返回等待的Promise对象
|
|
|
+ */
|
|
|
+ waitForDictLoading(types) {
|
|
|
+ return new Promise(resolve => {
|
|
|
+ const checkInterval = setInterval(() => {
|
|
|
+ const stillLoading = types.some(type => dictCache.loading[type]);
|
|
|
+ if (!stillLoading) {
|
|
|
+ clearInterval(checkInterval);
|
|
|
+
|
|
|
+ // 加载完成后,从缓存中获取数据
|
|
|
+ types.forEach(type => {
|
|
|
+ const cachedDict = this.getDictFromCache(type);
|
|
|
+ if (cachedDict) {
|
|
|
+ this.$set(this.dictData, type, cachedDict);
|
|
|
+ }
|
|
|
+ });
|
|
|
+
|
|
|
+ resolve(this.dictData);
|
|
|
+ }
|
|
|
+ }, 50);
|
|
|
+ });
|
|
|
+ },
|
|
|
+ /**
|
|
|
+ * 从服务器获取字典数据
|
|
|
+ * - 单个字典类型 → 单次请求
|
|
|
+ * - 多个字典类型 → 并发请求
|
|
|
+ * - 支持部分失败:失败的字典会忽略,成功的字典会返回
|
|
|
+ *
|
|
|
+ * @param {Array} dictTypes - 字典类型数组
|
|
|
+ * @returns {Promise<Object|Array>}
|
|
|
+ * - 单个字典时返回 dictList 数组
|
|
|
+ * - 多个字典时返回 { dictType: dictList } 的 Map
|
|
|
+ */
|
|
|
+ fetchDictData(dictTypes) {
|
|
|
+ // 标记这些字典类型正在加载
|
|
|
+ dictTypes.forEach(type => {
|
|
|
+ dictCache.loading[type] = true;
|
|
|
+ });
|
|
|
+
|
|
|
+ // --- 单个字典类型 ---
|
|
|
+ if (dictTypes.length === 1) {
|
|
|
+ const dictType = dictTypes[0];
|
|
|
+ console.log(`[DictMixin] Fetching single dictionary: ${dictType}`);
|
|
|
+ return getDictData(dictType).then(res => {
|
|
|
+ if (res.data.code === 200) {
|
|
|
+ let dictList = [];
|
|
|
+ if (dictType === 'mall_product_category') {
|
|
|
+ dictList.push({
|
|
|
+ dictLabel: '推荐',
|
|
|
+ dictValue: '-1'
|
|
|
+ });
|
|
|
+ dictList.push(...res.data.data);
|
|
|
+ } else {
|
|
|
+ dictList = res.data.data;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 更新组件数据和缓存
|
|
|
+ this.$set(this.dictData, dictType, dictList);
|
|
|
+ this.updateDictCache(dictType, dictList);
|
|
|
+ delete dictCache.loading[dictType];
|
|
|
+
|
|
|
+ return dictList;
|
|
|
+ } else {
|
|
|
+ console.error(`获取字典[${dictType}]数据失败:`, res.data.msg);
|
|
|
+ delete dictCache.loading[dictType];
|
|
|
+ return Promise.reject(res.data.msg);
|
|
|
+ }
|
|
|
+ }).catch(err => {
|
|
|
+ delete dictCache.loading[dictType];
|
|
|
+ throw err;
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ // --- 多个字典类型,并发请求 ---
|
|
|
+ console.log(`[DictMixin] Concurrently fetching ${dictTypes.length} dictionaries: ${dictTypes.join(', ')}`);
|
|
|
+
|
|
|
+ const requests = dictTypes.map(dictType => {
|
|
|
+ return getDictData(dictType).then(res => {
|
|
|
+ if (res.data.code === 200) {
|
|
|
+ let dictList = [];
|
|
|
+ if (dictType === 'mall_product_category') {
|
|
|
+ dictList.push({
|
|
|
+ dictLabel: '推荐',
|
|
|
+ dictValue: '-1'
|
|
|
+ });
|
|
|
+ dictList.push(...res.data.data);
|
|
|
+ } else {
|
|
|
+ dictList = res.data.data;
|
|
|
+ }
|
|
|
+
|
|
|
+ this.$set(this.dictData, dictType, dictList);
|
|
|
+ this.updateDictCache(dictType, dictList);
|
|
|
+ delete dictCache.loading[dictType];
|
|
|
+
|
|
|
+ return {
|
|
|
+ dictType,
|
|
|
+ dictList,
|
|
|
+ success: true
|
|
|
+ };
|
|
|
+ } else {
|
|
|
+ console.error(`获取字典[${dictType}]数据失败:`, res.data.msg);
|
|
|
+ delete dictCache.loading[dictType];
|
|
|
+ return {
|
|
|
+ dictType,
|
|
|
+ dictList: [],
|
|
|
+ success: false,
|
|
|
+ msg: res.data.msg
|
|
|
+ };
|
|
|
+ }
|
|
|
+ }).catch(err => {
|
|
|
+ console.error(`获取字典[${dictType}]异常:`, err);
|
|
|
+ delete dictCache.loading[dictType];
|
|
|
+ return {
|
|
|
+ dictType,
|
|
|
+ dictList: [],
|
|
|
+ success: false,
|
|
|
+ msg: err
|
|
|
+ };
|
|
|
+ });
|
|
|
+ });
|
|
|
+
|
|
|
+ // 等所有请求完成
|
|
|
+ return Promise.allSettled(requests).then(results => {
|
|
|
+ const dictMap = {};
|
|
|
+ const failed = [];
|
|
|
+
|
|
|
+ results.forEach(r => {
|
|
|
+ if (r.status === 'fulfilled') {
|
|
|
+ const {
|
|
|
+ dictType,
|
|
|
+ dictList,
|
|
|
+ success,
|
|
|
+ msg
|
|
|
+ } = r.value;
|
|
|
+ if (success) {
|
|
|
+ dictMap[dictType] = dictList;
|
|
|
+ } else {
|
|
|
+ failed.push({
|
|
|
+ dictType,
|
|
|
+ msg
|
|
|
+ });
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ // 理论上不会走这里,因为 catch 已经返回对象了
|
|
|
+ console.error(`字典请求失败:`, r.reason);
|
|
|
+ }
|
|
|
+ });
|
|
|
+
|
|
|
+ console.log(
|
|
|
+ `[DictMixin] Loaded ${Object.keys(dictMap).length} dictionaries, failed ${failed.length}`
|
|
|
+ );
|
|
|
+
|
|
|
+ if (failed.length > 0) {
|
|
|
+ console.warn('以下字典加载失败:', failed);
|
|
|
+ }
|
|
|
+
|
|
|
+ return dictMap;
|
|
|
+ });
|
|
|
+ },
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 从服务器获取字典数据
|
|
|
+ * @param {Array} dictTypes - 字典类型数组
|
|
|
+ * @returns {Promise} - 返回字典获取的Promise对象
|
|
|
+ */
|
|
|
+ // fetchDictData(dictTypes) {
|
|
|
+ // // 标记这些字典类型正在加载
|
|
|
+ // dictTypes.forEach(type => {
|
|
|
+ // dictCache.loading[type] = true;
|
|
|
+ // });
|
|
|
+
|
|
|
+ // if (dictTypes.length === 1) {
|
|
|
+ // // 单个字典类型,直接获取
|
|
|
+ // console.log(`[DictMixin] Fetching single dictionary: ${dictTypes[0]}`);
|
|
|
+ // return getDictData(dictTypes[0]).then(res => {
|
|
|
+ // if (res.data.code === 200) {
|
|
|
+ // const dictType = dictTypes[0];
|
|
|
+ // var dictList = []
|
|
|
+ // if(dictType === 'mall_product_category'){
|
|
|
+ // dictList.push({
|
|
|
+ // dictLabel:'推荐',
|
|
|
+ // dictValue:'-1'
|
|
|
+ // })
|
|
|
+ // // 展开数组追加
|
|
|
+ // dictList.push(...res.data.data);
|
|
|
+ // }else{
|
|
|
+ // dictList = res.data.data
|
|
|
+ // }
|
|
|
+
|
|
|
+
|
|
|
+ // // 更新组件字典数据
|
|
|
+ // this.$set(this.dictData, dictType, dictList);
|
|
|
+ // // 更新缓存
|
|
|
+ // this.updateDictCache(dictType, dictList);
|
|
|
+
|
|
|
+ // // 取消加载标记
|
|
|
+ // delete dictCache.loading[dictType];
|
|
|
+
|
|
|
+ // return dictList;
|
|
|
+ // } else {
|
|
|
+ // console.error(`获取字典[${dictTypes[0]}]数据失败:`, res.data.msg);
|
|
|
+
|
|
|
+ // // 取消加载标记
|
|
|
+ // delete dictCache.loading[dictTypes[0]];
|
|
|
+
|
|
|
+ // return Promise.reject(res.data.msg);
|
|
|
+ // }
|
|
|
+ // }).catch(err => {
|
|
|
+ // // 发生错误时取消加载标记
|
|
|
+ // delete dictCache.loading[dictTypes[0]];
|
|
|
+ // throw err;
|
|
|
+ // });
|
|
|
+ // } else {
|
|
|
+ // // 多个字典类型,批量获取
|
|
|
+ // console.log(`[DictMixin] Batch fetching ${dictTypes.length} dictionaries: ${dictTypes.join(', ')}`);
|
|
|
+ // return getMultipleDictData(dictTypes).then(res => {
|
|
|
+ // if (res.data.code === 200) {
|
|
|
+ // const dictMap = res.data.data || {};
|
|
|
+
|
|
|
+ // // 更新组件字典数据和缓存
|
|
|
+ // Object.keys(dictMap).forEach(dictType => {
|
|
|
+ // const dictList = dictMap[dictType] || [];
|
|
|
+
|
|
|
+ // // 更新组件字典数据
|
|
|
+ // this.$set(this.dictData, dictType, dictList);
|
|
|
+
|
|
|
+ // // 更新缓存
|
|
|
+ // this.updateDictCache(dictType, dictList);
|
|
|
+
|
|
|
+ // // 取消加载标记
|
|
|
+ // delete dictCache.loading[dictType];
|
|
|
+ // });
|
|
|
+
|
|
|
+ // console.log(`[DictMixin] Successfully loaded ${Object.keys(dictMap).length} dictionaries`);
|
|
|
+ // return dictMap;
|
|
|
+ // } else {
|
|
|
+ // console.error(`获取字典数据失败:`, res.data.msg);
|
|
|
+
|
|
|
+ // // 取消所有加载标记
|
|
|
+ // dictTypes.forEach(type => {
|
|
|
+ // delete dictCache.loading[type];
|
|
|
+ // });
|
|
|
+
|
|
|
+ // return Promise.reject(res.data.msg);
|
|
|
+ // }
|
|
|
+ // }).catch(err => {
|
|
|
+ // // 发生错误时取消所有加载标记
|
|
|
+ // dictTypes.forEach(type => {
|
|
|
+ // delete dictCache.loading[type];
|
|
|
+ // });
|
|
|
+ // throw err;
|
|
|
+ // });
|
|
|
+ // }
|
|
|
+ // },
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 从缓存中获取字典数据
|
|
|
+ * @param {String} dictType - 字典类型
|
|
|
+ * @returns {Array|null} - 返回字典数据,不存在或已过期则返回null
|
|
|
+ */
|
|
|
+ getDictFromCache(dictType) {
|
|
|
+ // 判断是否有缓存
|
|
|
+ if (!dictCache.data[dictType]) {
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 判断缓存是否过期
|
|
|
+ const lastUpdateTime = dictCache.lastUpdateTime[dictType] || 0;
|
|
|
+ const now = Date.now();
|
|
|
+ if (now - lastUpdateTime > dictCache.expireTime) {
|
|
|
+ // 缓存已过期,删除缓存
|
|
|
+ delete dictCache.data[dictType];
|
|
|
+ delete dictCache.lastUpdateTime[dictType];
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 返回缓存的字典数据
|
|
|
+ return dictCache.data[dictType];
|
|
|
+ },
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 更新字典缓存
|
|
|
+ * @param {String} dictType - 字典类型
|
|
|
+ * @param {Array} dictList - 字典数据列表
|
|
|
+ */
|
|
|
+ updateDictCache(dictType, dictList) {
|
|
|
+ dictCache.data[dictType] = dictList;
|
|
|
+ dictCache.lastUpdateTime[dictType] = Date.now();
|
|
|
+
|
|
|
+ // 更新本地存储
|
|
|
+ try {
|
|
|
+ // 只存储最后更新时间,具体数据保存在内存中
|
|
|
+ storage.setDict(`dict_time_${dictType}`, dictCache.lastUpdateTime[dictType]);
|
|
|
+ } catch (e) {
|
|
|
+ console.error('更新字典缓存失败:', e);
|
|
|
+ }
|
|
|
+ },
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 清除字典缓存
|
|
|
+ * @param {String} dictType - 字典类型,不传则清除所有缓存
|
|
|
+ */
|
|
|
+ clearDictCache(dictType) {
|
|
|
+ if (dictType) {
|
|
|
+ delete dictCache.data[dictType];
|
|
|
+ delete dictCache.lastUpdateTime[dictType];
|
|
|
+ storage.removeDict(`dict_time_${dictType}`);
|
|
|
+ } else {
|
|
|
+ dictCache.data = {};
|
|
|
+ dictCache.lastUpdateTime = {};
|
|
|
+ // 清除所有字典相关的本地存储
|
|
|
+ const keys = Object.keys(localStorage);
|
|
|
+ keys.forEach(key => {
|
|
|
+ if (key.startsWith('dict_time_')) {
|
|
|
+ storage.removeDict(key);
|
|
|
+ }
|
|
|
+ });
|
|
|
+ }
|
|
|
+ },
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 根据字典值获取对应的字典标签
|
|
|
+ * @param {String} dictType - 字典类型
|
|
|
+ * @param {String|Number} value - 字典值
|
|
|
+ * @param {String} defaultLabel - 默认标签
|
|
|
+ * @returns {String} - 字典标签
|
|
|
+ */
|
|
|
+ getDictLabel(dictType, value, defaultLabel = '') {
|
|
|
+ // 首先检查组件数据
|
|
|
+ const dictList = this.dictData[dictType];
|
|
|
+ if (dictList) {
|
|
|
+ const item = dictList.find(dict => dict.dictValue === value);
|
|
|
+ if (item) return item.dictLabel;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 再检查静态字典
|
|
|
+ // const staticDictList = staticDict[dictType];
|
|
|
+ // if (staticDictList) {
|
|
|
+ // const item = staticDictList.find(dict => dict.value === value);
|
|
|
+ // if (item) return item.label;
|
|
|
+ // }
|
|
|
+
|
|
|
+ // 都没找到,返回默认值
|
|
|
+ return defaultLabel;
|
|
|
+ },
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 根据字典标签获取对应的字典值
|
|
|
+ * @param {String} dictType - 字典类型
|
|
|
+ * @param {String} label - 字典标签
|
|
|
+ * @param {String|Number} defaultValue - 默认值
|
|
|
+ * @returns {String|Number} - 字典值
|
|
|
+ */
|
|
|
+ getDictValue(dictType, label, defaultValue = '') {
|
|
|
+ // 首先检查组件数据
|
|
|
+ const dictList = this.dictData[dictType];
|
|
|
+ if (dictList) {
|
|
|
+ const item = dictList.find(dict => dict.label === label);
|
|
|
+ if (item) return item.value;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 再检查静态字典
|
|
|
+ const staticDictList = staticDict[dictType];
|
|
|
+ if (staticDictList) {
|
|
|
+ const item = staticDictList.find(dict => dict.label === label);
|
|
|
+ if (item) return item.value;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 都没找到,返回默认值
|
|
|
+ return defaultValue;
|
|
|
+ },
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 获取字典列表
|
|
|
+ * @param {String} dictType - 字典类型
|
|
|
+ * @returns {Array} - 字典列表
|
|
|
+ */
|
|
|
+ getDictList(dictType) {
|
|
|
+ // 首先检查组件数据
|
|
|
+ const dictList = this.dictData[dictType];
|
|
|
+ if (dictList) return dictList;
|
|
|
+
|
|
|
+ // 再检查静态字典
|
|
|
+ return staticDict[dictType] || [];
|
|
|
+ },
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 获取字典类型对应的样式类
|
|
|
+ * @param {String} dictType - 字典类型
|
|
|
+ * @param {String|Number} value - 字典值
|
|
|
+ * @param {String} defaultClass - 默认样式类
|
|
|
+ * @returns {String} - 字典项的样式类
|
|
|
+ */
|
|
|
+ getDictClass(dictType, value, defaultClass = '') {
|
|
|
+ // 首先检查组件数据
|
|
|
+ const dictList = this.dictData[dictType];
|
|
|
+ if (dictList) {
|
|
|
+ const item = dictList.find(dict => dict.dictValue === value);
|
|
|
+ if (item && item.listClass) return item.listClass;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 再检查静态字典
|
|
|
+ // const staticDictList = staticDict[dictType];
|
|
|
+ // if (staticDictList) {
|
|
|
+ // const item = staticDictList.find(dict => dict.value === value);
|
|
|
+ // if (item && item.listClass) return item.listClass;
|
|
|
+ // }
|
|
|
+
|
|
|
+ // 都没找到,返回默认值
|
|
|
+ return defaultClass;
|
|
|
+ }
|
|
|
+ }
|
|
|
+};
|