456 lines
12 KiB
JavaScript
456 lines
12 KiB
JavaScript
/**
|
|
* 主题状态管理
|
|
*/
|
|
import {changeColor} from '@/components/ele-admin-pro/packages/style/util.js';
|
|
import setting from '@/config/setting';
|
|
// 不需要本地缓存的state
|
|
const NO_CACHE_STATE = [
|
|
'collapse',
|
|
'tabs',
|
|
'homeComponents',
|
|
'keepAliveInclude',
|
|
'keepAliveExclude',
|
|
'tabKeepAlive',
|
|
'screenWidth',
|
|
'screenHeight'
|
|
];
|
|
|
|
/**
|
|
* 读取缓存的配置
|
|
* @param keyName 缓存的键名
|
|
* @returns {Object}
|
|
*/
|
|
function getCacheSetting(keyName) {
|
|
let cache = {};
|
|
try {
|
|
const value = localStorage.getItem(keyName);
|
|
if (value) {
|
|
const temp = JSON.parse(value);
|
|
if (typeof temp === 'object') {
|
|
cache = temp;
|
|
}
|
|
}
|
|
} catch (e) {
|
|
console.error(e);
|
|
}
|
|
return cache;
|
|
}
|
|
|
|
/**
|
|
* 缓存配置
|
|
* @param keyName 缓存的键名
|
|
* @param key 缓存的配置名
|
|
* @param value 缓存的配置名对应的值
|
|
*/
|
|
function cacheSetting(keyName, key, value) {
|
|
if (NO_CACHE_STATE.includes(key)) {
|
|
return;
|
|
}
|
|
const cache = getCacheSetting(keyName);
|
|
if (cache[key] !== value) {
|
|
cache[key] = value;
|
|
localStorage.setItem(keyName, JSON.stringify(cache));
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 检查state值以兼容旧版本
|
|
* @param key
|
|
* @param value
|
|
* @returns
|
|
*/
|
|
function checkStateValue(key, value) {
|
|
if (typeof value === 'number') {
|
|
if (key === 'sideStyle') {
|
|
return ['light', 'dark'][value < 2 ? value : 1];
|
|
}
|
|
if (key === 'headStyle') {
|
|
return ['light', 'dark', 'primary'][value < 3 ? value : 2];
|
|
}
|
|
if (key === 'tabStyle') {
|
|
return ['default', 'dot', 'card'][value < 3 ? value : 2];
|
|
}
|
|
if (key === 'layoutStyle') {
|
|
return ['side', 'top', 'mix'][value < 3 ? value : 2];
|
|
}
|
|
}
|
|
return value;
|
|
}
|
|
|
|
/**
|
|
* 获取state
|
|
* @param setting 默认配置
|
|
* @returns {Object}
|
|
*/
|
|
function getState(setting) {
|
|
const state = {
|
|
// 侧边栏风格: light(亮色), dark(暗色)
|
|
sideStyle: 'light',
|
|
// 顶栏风格: light(亮色), dark(暗色), primary(主色)
|
|
headStyle: 'primary',
|
|
// 标签页风格: default(默认), dot(圆点), card(卡片)
|
|
tabStyle: 'default',
|
|
// 布局风格: side(默认), top(顶栏菜单), mix(混合菜单)
|
|
layoutStyle: 'side',
|
|
// 侧边栏菜单风格: default(默认), mix(双排菜单)
|
|
sideMenuStyle: 'default',
|
|
// 是否固定侧栏
|
|
fixedSidebar: true,
|
|
// 是否固定顶栏
|
|
fixedHeader: false,
|
|
// 是否固定主体
|
|
fixedBody: false,
|
|
// 内容区域宽度铺满
|
|
bodyFull: true,
|
|
// 是否开启多标签
|
|
showTabs: true,
|
|
// logo是否自适应宽度
|
|
logoAutoSize: true,
|
|
// 侧栏是否多彩图标
|
|
colorfulIcon: true,
|
|
// 侧边栏是否只保持一个子菜单展开
|
|
sideUniqueOpen: true,
|
|
// 是否开启页脚
|
|
showFooter: true,
|
|
// 是否是色弱模式
|
|
weakMode: false,
|
|
// 是否是暗黑模式
|
|
darkMode: false,
|
|
// 主题色
|
|
color: null,
|
|
// 是否折叠侧边栏
|
|
collapse: false,
|
|
// 当前打开的选项卡
|
|
tabs: [],
|
|
// 主页的组件
|
|
homeComponents: [],
|
|
// 需要keep-alive的组件
|
|
keepAliveInclude: [],
|
|
// 不需要keep-alive的组件
|
|
keepAliveExclude: [],
|
|
// 开启多页签是否缓存组件
|
|
tabKeepAlive: true,
|
|
// 屏幕宽度
|
|
screenWidth: document.documentElement.clientWidth || document.body.clientWidth,
|
|
// 屏幕高度
|
|
screenHeight: document.documentElement.clientHeight || document.body.clientHeight
|
|
};
|
|
// 读取缓存的配置及默认配置
|
|
for (let key in state) {
|
|
if (!Object.prototype.hasOwnProperty.call(state, key)) {
|
|
continue;
|
|
}
|
|
const cache = getCacheSetting(setting.themeStoreName);
|
|
if (cache[key] !== undefined) {
|
|
state[key] = checkStateValue(key, cache[key]);
|
|
} else if (setting[key] !== undefined) {
|
|
state[key] = checkStateValue(key, setting[key]);
|
|
}
|
|
}
|
|
|
|
// 恢复色弱模式
|
|
if (state.weakMode) {
|
|
changeWeakMode(true);
|
|
}
|
|
|
|
// 恢复上次主题色
|
|
if (state.color || state.darkMode) {
|
|
window.addEventListener('load', () => {
|
|
doChangeTheme(state.color, state.darkMode).catch((e) => {
|
|
console.error(e);
|
|
});
|
|
});
|
|
}
|
|
return state;
|
|
}
|
|
|
|
/**
|
|
* 切换主题
|
|
* @param value 主题
|
|
* @param dark 是否是暗黑模式
|
|
* @returns {Promise<>}
|
|
*/
|
|
function doChangeTheme(value, dark) {
|
|
return new Promise((resolve, reject) => {
|
|
try {
|
|
changeColor(value, dark);
|
|
resolve();
|
|
} catch (e) {
|
|
reject(e);
|
|
}
|
|
});
|
|
}
|
|
|
|
/**
|
|
* 开关色弱模式
|
|
* @param weakMode 是否开启色弱模式
|
|
*/
|
|
function changeWeakMode(weakMode) {
|
|
const weakClass = 'ele-admin-weak';
|
|
if (weakMode) {
|
|
document.body.classList.add(weakClass);
|
|
} else {
|
|
document.body.classList.remove(weakClass);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 获取需要keep-alive的组件
|
|
* @param tabs 页签数据
|
|
* @param homeComponents 主页组件
|
|
* @returns {any[]}
|
|
*/
|
|
function getKeepAliveInclude(tabs, homeComponents) {
|
|
const components = new Set();
|
|
if (tabs) {
|
|
tabs.forEach((t) => {
|
|
if (t && t.components && t.components.length) {
|
|
t.components.forEach((c) => {
|
|
if (typeof c === 'string' && c) {
|
|
components.add(c);
|
|
}
|
|
});
|
|
}
|
|
});
|
|
}
|
|
if (homeComponents) {
|
|
homeComponents.forEach((c) => {
|
|
components.add(c);
|
|
});
|
|
}
|
|
return Array.from(components);
|
|
}
|
|
|
|
export default {
|
|
namespaced: true,
|
|
state: getState(setting),
|
|
mutations: {
|
|
// 修改state值
|
|
SET: function (state, obj) {
|
|
state[obj.key] = obj.value;
|
|
// 缓存修改的配置
|
|
cacheSetting(setting.themeStoreName, obj.key, obj.value);
|
|
},
|
|
// 更新keepAliveInclude
|
|
UPDATE_KEEP_ALIVE_INCLUDE: function (state) {
|
|
if (state.showTabs && state.tabKeepAlive) {
|
|
state.keepAliveInclude = getKeepAliveInclude(state.tabs, state.homeComponents);
|
|
} else {
|
|
state.keepAliveInclude = [];
|
|
}
|
|
}
|
|
},
|
|
actions: {
|
|
/**
|
|
* 修改配置
|
|
* @param {commit}
|
|
* @param obj
|
|
*/
|
|
set({commit}, obj) {
|
|
commit('SET', obj);
|
|
if (obj.key === 'showTabs' || obj.key === 'tabKeepAlive') {
|
|
commit('UPDATE_KEEP_ALIVE_INCLUDE');
|
|
}
|
|
},
|
|
/**
|
|
* 切换配置(boolean类型的配置)
|
|
* @param {commit, state}
|
|
* @param key 配置名称
|
|
*/
|
|
toggle({commit, state}, key) {
|
|
commit('SET', {key: key, value: !state[key]});
|
|
},
|
|
/**
|
|
* 切换主题色
|
|
* @param {commit, state}
|
|
* @param value 颜色值
|
|
* @returns {Promise<>}
|
|
*/
|
|
setColor({commit, state}, value) {
|
|
return new Promise((resolve, reject) => {
|
|
doChangeTheme(value, state.darkMode).then(() => {
|
|
commit('SET', {key: 'color', value: value});
|
|
return resolve();
|
|
}).catch((e) => {
|
|
reject(e);
|
|
});
|
|
});
|
|
},
|
|
/**
|
|
* 切换暗黑模式
|
|
* @param {commit, state}
|
|
* @param value 是否开启暗黑模式
|
|
* @returns {Promise<>}
|
|
*/
|
|
setDarkMode({commit, state}, value) {
|
|
return new Promise((resolve, reject) => {
|
|
doChangeTheme(state.color, value).then(() => {
|
|
commit('SET', {key: 'darkMode', value: value});
|
|
return resolve();
|
|
}).catch((e) => {
|
|
reject(e);
|
|
});
|
|
});
|
|
},
|
|
/**
|
|
* 切换色弱模式
|
|
* @param {commit}
|
|
* @param value 是否开启色弱模式
|
|
* @returns {Promise<>}
|
|
*/
|
|
setWeakMode({commit}, value) {
|
|
return new Promise((resolve) => {
|
|
changeWeakMode(value);
|
|
commit('SET', {key: 'weakMode', value: value});
|
|
resolve();
|
|
});
|
|
},
|
|
/**
|
|
* 添加tab
|
|
* @param {commit, state}
|
|
* @param obj {{key: String, path: String, fullPath: String, title: String}}
|
|
*/
|
|
tabAdd({commit, state}, obj) {
|
|
if (!obj.key) {
|
|
obj.key = obj.fullPath || obj.path;
|
|
}
|
|
const i = state.tabs.findIndex((d) => d.key === obj.key);
|
|
if (i === -1) {
|
|
commit('SET', {key: 'tabs', value: state.tabs.concat([obj])});
|
|
} else if (obj.fullPath !== state.tabs[i].fullPath) {
|
|
commit('SET', {key: 'tabs', value: state.tabs.slice(0, i).concat([obj]).concat(state.tabs.slice(i + 1))});
|
|
}
|
|
commit('UPDATE_KEEP_ALIVE_INCLUDE');
|
|
},
|
|
/**
|
|
* 移除指定tab
|
|
* @param commit
|
|
* @param state
|
|
* @param key {String}
|
|
* @returns {Promise<Object>}
|
|
*/
|
|
tabRemove({commit, state}, key) {
|
|
return new Promise((resolve) => {
|
|
let index = -1, lastIndex = -1, lastPath, last;
|
|
for (let i = 0; i < state.tabs.length; i++) {
|
|
if (state.tabs[i].key === key || state.tabs[i].fullPath === key) {
|
|
index = i;
|
|
break;
|
|
}
|
|
lastIndex = i;
|
|
last = state.tabs[i];
|
|
lastPath = last.fullPath;
|
|
}
|
|
commit('SET', {key: 'tabs', value: state.tabs.filter((d, i) => i !== index)});
|
|
commit('UPDATE_KEEP_ALIVE_INCLUDE');
|
|
resolve({lastIndex: lastIndex, lastPath: lastPath, last: last});
|
|
});
|
|
},
|
|
/**
|
|
* 移除所有tab
|
|
* @param commit
|
|
*/
|
|
tabRemoveAll({commit}) {
|
|
commit('SET', {key: 'tabs', value: []});
|
|
commit('UPDATE_KEEP_ALIVE_INCLUDE');
|
|
},
|
|
/**
|
|
* 移除左侧tab
|
|
* @param commit
|
|
* @param state
|
|
* @param key {String}
|
|
*/
|
|
tabRemoveLeft({commit, state}, key) {
|
|
for (let i = 0; i < state.tabs.length; i++) {
|
|
if (state.tabs[i].key === key) {
|
|
commit('SET', {key: 'tabs', value: state.tabs.slice(i)});
|
|
commit('UPDATE_KEEP_ALIVE_INCLUDE');
|
|
break;
|
|
}
|
|
}
|
|
},
|
|
/**
|
|
* 移除右侧tab
|
|
* @param commit
|
|
* @param state
|
|
* @param key {String}
|
|
*/
|
|
tabRemoveRight({commit, state}, key) {
|
|
for (let i = 0; i < state.tabs.length; i++) {
|
|
if (state.tabs[i].key === key) {
|
|
commit('SET', {key: 'tabs', value: state.tabs.slice(0, i + 1)});
|
|
commit('UPDATE_KEEP_ALIVE_INCLUDE');
|
|
break;
|
|
}
|
|
}
|
|
},
|
|
/**
|
|
* 移除其他tab
|
|
* @param commit
|
|
* @param state
|
|
* @param key {String}
|
|
*/
|
|
tabRemoveOther({commit, state}, key) {
|
|
commit('SET', {key: 'tabs', value: state.tabs.filter((d) => d.key === key)});
|
|
commit('UPDATE_KEEP_ALIVE_INCLUDE');
|
|
},
|
|
/**
|
|
* 修改指定tab
|
|
* @param commit
|
|
* @param state
|
|
* @param obj {{path: String, title: String, fullPath: String, closable: Boolean}}
|
|
*/
|
|
tabSetTitle({commit, state}, obj) {
|
|
let i = -1;
|
|
if (obj.fullPath) {
|
|
i = state.tabs.findIndex((d) => d.fullPath === obj.fullPath);
|
|
} else if (obj.path) {
|
|
i = state.tabs.findIndex((d) => d.path === obj.path);
|
|
}
|
|
if (i !== -1) {
|
|
const data = Object.assign({}, state.tabs[i]);
|
|
if (typeof obj.title === 'string' && obj.title) {
|
|
data.title = obj.title;
|
|
}
|
|
if (typeof obj.closable === 'boolean') {
|
|
data.closable = obj.closable;
|
|
}
|
|
const tabs = state.tabs.slice(0, i).concat([data]).concat(state.tabs.slice(i + 1));
|
|
commit('SET', {key: 'tabs', value: tabs});
|
|
}
|
|
},
|
|
/**
|
|
* 设置主页的组件名称
|
|
* @param {commit, state}
|
|
* @param components {Array}
|
|
*/
|
|
setHomeComponents({commit}, components) {
|
|
commit('SET', {key: 'homeComponents', value: components});
|
|
commit('UPDATE_KEEP_ALIVE_INCLUDE');
|
|
},
|
|
/**
|
|
* 设置不需要keep-alive的组件
|
|
* @param commit
|
|
* @param value {Array}
|
|
*/
|
|
setKeepAliveExclude({ commit }, value) {
|
|
console.log(value);
|
|
commit('SET', {key: 'keepAliveExclude', value: value});
|
|
},
|
|
/**
|
|
* 更新屏幕尺寸
|
|
* @param {commit, state}
|
|
*/
|
|
updateScreen({commit, state}) {
|
|
const w = document.documentElement.clientWidth || document.body.clientWidth,
|
|
h = document.documentElement.clientHeight || document.body.clientHeight;
|
|
if (w !== state.screenWidth) {
|
|
commit('SET', {key: 'screenWidth', value: w});
|
|
}
|
|
if (h !== state.screenHeight) {
|
|
commit('SET', {key: 'screenHeight', value: h});
|
|
}
|
|
}
|
|
}
|
|
};
|