Merge pull request #75 from Tencent/reafactor/pinia

refactor(pinia): use pinia refactor store
This commit is contained in:
yuyang 2022-03-01 17:27:14 +08:00 committed by GitHub
commit 20d059ce54
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
27 changed files with 478 additions and 537 deletions

View File

@ -21,15 +21,15 @@
"echarts": "~5.1.2", "echarts": "~5.1.2",
"hex-to-hsl": "^1.0.2", "hex-to-hsl": "^1.0.2",
"nprogress": "^0.2.0", "nprogress": "^0.2.0",
"pinia": "^2.0.11",
"qrcode.vue": "^3.2.2", "qrcode.vue": "^3.2.2",
"tdesign-icons-vue-next": "^0.0.6", "tdesign-icons-vue-next": "^0.0.6",
"tdesign-vue-next": "0.8.1", "tdesign-vue-next": "0.9.2",
"tvision-color": "^1.3.1", "tvision-color": "^1.3.1",
"vue": "^3.2.31", "vue": "^3.2.31",
"vue-color-kit": "^1.0.5", "vue-color-kit": "^1.0.5",
"vue-router": "^4.0.11", "vue-router": "^4.0.11",
"vue3-clipboard": "^1.0.0", "vue3-clipboard": "^1.0.0"
"vuex": "^4.0.2"
}, },
"devDependencies": { "devDependencies": {
"@commitlint/cli": "^15.0.0", "@commitlint/cli": "^15.0.0",

View File

@ -3,17 +3,17 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { computed, onMounted } from 'vue'; import { computed, onMounted } from 'vue';
import { useStore } from 'vuex';
import config from '@/config/style'; import config from '@/config/style';
import { useSettingStore } from '@/store';
const store = useStore(); const store = useSettingStore();
const mode = computed(() => { const mode = computed(() => {
return store.getters['setting/mode']; return store.displayMode;
}); });
onMounted(() => { onMounted(() => {
store.dispatch('setting/changeTheme', { ...config }); store.updateConfig({ ...config });
}); });
</script> </script>
<style lang="less"> <style lang="less">

View File

@ -3,8 +3,10 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { computed } from 'vue'; import { computed } from 'vue';
import { useStore } from 'vuex';
import { getBrandColor } from '@/config/color'; import { getBrandColor } from '@/config/color';
import { useSettingStore } from '@/store';
const store = useSettingStore();
const panelColor = const panelColor =
'conic-gradient(from 90deg at 50% 50%, #FF0000 -19.41deg, #FF0000 18.76deg, #FF8A00 59.32deg, #FFE600 99.87deg, #14FF00 141.65deg, #00A3FF 177.72deg, #0500FF 220.23deg, #AD00FF 260.13deg, #FF00C7 300.69deg, #FF0000 340.59deg, #FF0000 378.76deg)'; 'conic-gradient(from 90deg at 50% 50%, #FF0000 -19.41deg, #FF0000 18.76deg, #FF8A00 59.32deg, #FFE600 99.87deg, #14FF00 141.65deg, #00A3FF 177.72deg, #0500FF 220.23deg, #AD00FF 260.13deg, #FF00C7 300.69deg, #FF0000 340.59deg, #FF0000 378.76deg)';
@ -15,11 +17,9 @@ const props = defineProps({
}, },
}); });
const store = useStore();
const style = computed(() => { const style = computed(() => {
const { value } = props; const { value } = props;
const { colorList } = store.state.setting; const { colorList } = store;
return { return {
background: value !== 'dynamic' ? getBrandColor(value, colorList)['@brand-color'] : panelColor, background: value !== 'dynamic' ? getBrandColor(value, colorList)['@brand-color'] : panelColor,
}; };

View File

@ -1,7 +1,7 @@
import hexToHsl from 'hex-to-hsl'; import hexToHsl from 'hex-to-hsl';
/* eslint-disable indent */ /* eslint-disable indent */
export type ColorToken = Record<string, string>; export type TColorToken = Record<string, string>;
export type ColorSeries = Record<string, ColorToken>; export type TColorSeries = Record<string, TColorToken>;
export const defaultLightColor = [ export const defaultLightColor = [
'#0052d9', '#0052d9',
@ -24,7 +24,7 @@ export const defaultDarkColor = [
'#ab87d5', '#ab87d5',
]; ];
export const BACKGROUND_TOKEN: ColorSeries = { export const BACKGROUND_TOKEN: TColorSeries = {
BLUE_GREY: { BLUE_GREY: {
'@gray-color-1': '#F1F2F5', '@gray-color-1': '#F1F2F5',
'@gray-color-2': '#EBEDF1', '@gray-color-2': '#EBEDF1',
@ -60,7 +60,7 @@ export const BACKGROUND_TOKEN: ColorSeries = {
}; };
// eslint-disable-next-line @typescript-eslint/no-unused-vars // eslint-disable-next-line @typescript-eslint/no-unused-vars
export const NEUTRAL_GREY_TOKEN: ColorToken = { export const NEUTRAL_GREY_TOKEN: TColorToken = {
'@gray-color-1': '#F3F3F3', '@gray-color-1': '#F3F3F3',
'@gray-color-2': '#EEEEEE', '@gray-color-2': '#EEEEEE',
'@gray-color-3': '#E7E7E7', '@gray-color-3': '#E7E7E7',
@ -77,7 +77,7 @@ export const NEUTRAL_GREY_TOKEN: ColorToken = {
'@gray-color-14': '#181818', '@gray-color-14': '#181818',
}; };
export const COLOR_TOKEN: ColorSeries = { export const COLOR_TOKEN: TColorSeries = {
DEFAULT: { DEFAULT: {
'@brand-color': '#0052D9', '@brand-color': '#0052D9',
'@brand-color-1': '#e0ebff', '@brand-color-1': '#e0ebff',
@ -185,35 +185,37 @@ export const COLOR_TOKEN: ColorSeries = {
}, },
}; };
export const LIGHT_CHART_COLORS: ColorToken = { export const LIGHT_CHART_COLORS = {
textColor: 'rgba(0, 0, 0, 0.9)', textColor: 'rgba(0, 0, 0, 0.9)',
placeholderColor: 'rgba(0, 0, 0, 0.35)', placeholderColor: 'rgba(0, 0, 0, 0.35)',
borderColor: '#dcdcdc', borderColor: '#dcdcdc',
containerColor: '#fff', containerColor: '#fff',
}; };
export const DARK_CHART_COLORS: ColorToken = { export const DARK_CHART_COLORS = {
textColor: 'rgba(255, 255, 255, 0.9)', textColor: 'rgba(255, 255, 255, 0.9)',
placeholderColor: 'rgba(255, 255, 255, 0.35)', placeholderColor: 'rgba(255, 255, 255, 0.35)',
borderColor: '#5e5e5e', borderColor: '#5e5e5e',
containerColor: '#242424', containerColor: '#242424',
}; };
export type TChartColor = typeof LIGHT_CHART_COLORS;
function toUnderline(name: string): string { function toUnderline(name: string): string {
return name.replace(/([A-Z])/g, '_$1').toUpperCase(); return name.replace(/([A-Z])/g, '_$1').toUpperCase();
} }
export function getGreyColor(type: string): ColorToken { export function getGreyColor(type: string): TColorToken {
const name = toUnderline(type); const name = toUnderline(type);
return BACKGROUND_TOKEN[name] || {}; return BACKGROUND_TOKEN[name] || {};
} }
export function getBrandColor(type: string, colorList: ColorSeries): ColorToken { export function getBrandColor(type: string, colorList: TColorSeries): TColorToken {
const name = /^#[A-F\d]{6}$/i.test(type) ? type : toUnderline(type); const name = /^#[A-F\d]{6}$/i.test(type) ? type : toUnderline(type);
return colorList[name || 'DEFAULT']; return colorList[name || 'DEFAULT'];
} }
export function getColorList(colorArray: Array<ColorToken>): Array<string> { export function getColorList(colorArray: Array<TColorToken>): Array<string> {
const pureColorList = []; const pureColorList = [];
colorArray.map((colorToken) => Object.keys(colorToken).map((key) => pureColorList.push(colorToken[key]))); colorArray.map((colorToken) => Object.keys(colorToken).map((key) => pureColorList.push(colorToken[key])));
@ -262,7 +264,7 @@ export function generateColorMap(theme: string, colorPalette: Array<string>, mod
}; };
return colorMap; return colorMap;
} }
export function insertThemeStylesheet(theme: string, colorMap: ColorToken, mode: 'light' | 'dark') { export function insertThemeStylesheet(theme: string, colorMap: TColorToken, mode: 'light' | 'dark') {
const isDarkMode = mode === 'dark'; const isDarkMode = mode === 'dark';
const root = !isDarkMode ? `:root[theme-color='${theme}']` : `:root[theme-color='${theme}'][theme-mode='dark']`; const root = !isDarkMode ? `:root[theme-color='${theme}']` : `:root[theme-color='${theme}'][theme-mode='dark']`;

View File

@ -35,5 +35,5 @@ export interface NotificationItem {
status: boolean; status: boolean;
collected: boolean; collected: boolean;
date: string; date: string;
quality: 'high' | 'low' | 'middle'; quality: string;
} }

View File

@ -12,7 +12,7 @@
<search :layout="layout" /> <search :layout="layout" />
</div> </div>
</template> </template>
<menu-content v-show="layout !== 'side'" class="header-menu" :nav-data="menu" /> <MenuContent v-show="layout !== 'side'" class="header-menu" :nav-data="menu" />
<template #operations> <template #operations>
<div class="operations-container"> <div class="operations-container">
<!-- 搜索框 --> <!-- 搜索框 -->
@ -65,9 +65,8 @@
<script setup lang="ts"> <script setup lang="ts">
import { PropType, computed } from 'vue'; import { PropType, computed } from 'vue';
import { useStore } from 'vuex';
import { useRouter, useRoute } from 'vue-router'; import { useRouter, useRoute } from 'vue-router';
import { useSettingStore } from '@/store';
import { prefix } from '@/config/global'; import { prefix } from '@/config/global';
import tLogoFull from '@/assets/assets-logo-full.svg?component'; import tLogoFull from '@/assets/assets-logo-full.svg?component';
import { MenuRoute } from '@/interface'; import { MenuRoute } from '@/interface';
@ -107,11 +106,13 @@ const props = defineProps({
}, },
}); });
const store = useStore();
const router = useRouter(); const router = useRouter();
const settingStore = useSettingStore();
const toggleSettingPanel = () => { const toggleSettingPanel = () => {
store.commit('setting/toggleSettingPanel', true); settingStore.updateConfig({
showSettingPanel: true,
});
}; };
const active = computed(() => { const active = computed(() => {
@ -141,7 +142,9 @@ const menuCls = computed(() => {
}); });
const changeCollapsed = () => { const changeCollapsed = () => {
store.commit('setting/toggleSidebarCompact'); settingStore.updateConfig({
isSidebarCompact: !settingStore.isSidebarCompact,
});
}; };
const handleNav = (url) => { const handleNav = (url) => {

View File

@ -46,31 +46,29 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { computed } from 'vue';
import { useRouter } from 'vue-router'; import { useRouter } from 'vue-router';
import { useStore } from 'vuex'; import { storeToRefs } from 'pinia';
import { useNotificationStore } from '@/store';
import { NotificationItem } from '@/interface'; import { NotificationItem } from '@/interface';
const router = useRouter(); const router = useRouter();
const store = useStore(); const store = useNotificationStore();
const { msgData } = store.state.notification; const { msgData, unreadMsg } = storeToRefs(store);
const unreadMsg = computed(() => store.getters['notification/unreadMsg']);
const setRead = (type: string, item?: NotificationItem) => { const setRead = (type: string, item?: NotificationItem) => {
const changeMsg = msgData; const changeMsg = msgData.value;
if (type === 'all') { if (type === 'all') {
changeMsg.forEach((e: NotificationItem) => { changeMsg.forEach((e) => {
e.status = false; e.status = false;
}); });
} else { } else {
changeMsg.forEach((e: NotificationItem) => { changeMsg.forEach((e) => {
if (e.id === item?.id) { if (e.id === item?.id) {
e.status = false; e.status = false;
} }
}); });
} }
store.commit('notification/setMsgData', changeMsg); store.setMsgData(changeMsg);
}; };
const goDetail = () => { const goDetail = () => {

View File

@ -39,8 +39,8 @@
<script setup lang="ts"> <script setup lang="ts">
import { ref } from 'vue'; import { ref } from 'vue';
const layout = defineProps({ defineProps({
type: String, layout: String,
}); });
const isSearchFocus = ref(false); const isSearchFocus = ref(false);

View File

@ -1,18 +1,16 @@
import { defineComponent, PropType, computed, onMounted } from 'vue'; import { defineComponent, PropType, computed, onMounted } from 'vue';
import { useRoute, useRouter } from 'vue-router'; import { useRoute, useRouter } from 'vue-router';
import { useStore } from 'vuex';
import { prefix } from '@/config/global'; import { prefix } from '@/config/global';
import pgk from '../../../package.json'; import pgk from '../../../package.json';
import MenuContent from './MenuContent'; import MenuContent from './MenuContent';
import tLogo from '@/assets/assets-t-logo.svg?component'; import tLogo from '@/assets/assets-t-logo.svg?component';
import tLogoFull from '@/assets/assets-logo-full.svg?component'; import tLogoFull from '@/assets/assets-logo-full.svg?component';
import { useSettingStore } from '@/store';
const MIN_POINT = 992 - 1; const MIN_POINT = 992 - 1;
const useComputed = (props) => { const useComputed = (props) => {
const store = useStore(); const collapsed = computed(() => useSettingStore().isSidebarCompact);
const collapsed = computed(() => store.state.setting.isSidebarCompact);
const sideNavCls = computed(() => { const sideNavCls = computed(() => {
const { isCompact } = props; const { isCompact } = props;
@ -87,16 +85,20 @@ export default defineComponent({
}, },
}, },
setup(props) { setup(props) {
const store = useStore();
const router = useRouter(); const router = useRouter();
const settingStore = useSettingStore();
const changeCollapsed = () => { const changeCollapsed = () => {
store.commit('setting/toggleSidebarCompact'); settingStore.updateConfig({
isSidebarCompact: !settingStore.isSidebarCompact,
});
}; };
const autoCollapsed = () => { const autoCollapsed = () => {
const isCompact = window.innerWidth <= MIN_POINT; const isCompact = window.innerWidth <= MIN_POINT;
store.commit('setting/showSidebarCompact', isCompact); settingStore.updateConfig({
isSidebarCompact: isCompact,
});
}; };
onMounted(() => { onMounted(() => {

View File

@ -1,5 +1,8 @@
import { defineComponent } from 'vue'; import { defineComponent, computed } from 'vue';
import { mapGetters } from 'vuex'; import { storeToRefs } from 'pinia';
import { useRoute } from 'vue-router';
import { usePermissionStore, useSettingStore } from '@/store';
import TDesignHeader from './components/Header.vue'; import TDesignHeader from './components/Header.vue';
import TDesignBreadcrumb from './components/Breadcrumb.vue'; import TDesignBreadcrumb from './components/Breadcrumb.vue';
import TDesignFooter from './components/Footer.vue'; import TDesignFooter from './components/Footer.vue';
@ -8,112 +11,111 @@ import TDesignContent from './components/Content.vue';
import { prefix } from '@/config/global'; import { prefix } from '@/config/global';
import TdesignSetting from './setting.vue'; import TdesignSetting from './setting.vue';
import { SettingType } from '@/interface';
import '@/style/layout.less'; import '@/style/layout.less';
const name = `${prefix}-base-layout`; const name = `${prefix}-base-layout`;
export default defineComponent({ export default defineComponent({
name, name,
computed: { setup() {
...mapGetters({ const route = useRoute();
showSidebar: 'setting/showSidebar', const permissionStore = usePermissionStore();
showHeader: 'setting/showHeader', const settingStore = useSettingStore();
showHeaderLogo: 'setting/showHeaderLogo', const { routers: menuRouters } = storeToRefs(permissionStore);
showSidebarLogo: 'setting/showSidebarLogo', const setting = storeToRefs(settingStore);
showFooter: 'setting/showFooter',
mode: 'setting/mode', const mainLayoutCls = computed(() => [
menuRouters: 'permission/routers', {
}), 't-layout--with-sider': settingStore.showSidebar,
setting(): SettingType { },
return this.$store.state.setting; ]);
},
mainLayoutCls() { const headerMenu = computed(() => {
return [ if (settingStore.layout === 'mix') {
{ if (settingStore.splitMenu) {
't-layout--with-sider': this.showSidebar, console.log(menuRouters);
}, return menuRouters.value.map((menu) => ({
];
},
headerMenu() {
const { layout, splitMenu } = this.$store.state.setting;
const { menuRouters } = this;
if (layout === 'mix') {
if (splitMenu) {
return menuRouters.map((menu) => ({
...menu, ...menu,
children: [], children: [],
})); }));
} }
return []; return [];
} }
return menuRouters; return menuRouters.value;
}, });
sideMenu() {
const { layout, splitMenu } = this.$store.state.setting; const sideMenu = computed(() => {
let { menuRouters } = this; const { layout, splitMenu } = settingStore;
let newMenuRouters = menuRouters.value;
if (layout === 'mix' && splitMenu) { if (layout === 'mix' && splitMenu) {
menuRouters.forEach((menu) => { newMenuRouters.forEach((menu) => {
if (this.$route.path.indexOf(menu.path) === 0) { if (route.path.indexOf(menu.path) === 0) {
menuRouters = menu.children.map((subMenu) => ({ ...subMenu, path: `${menu.path}/${subMenu.path}` })); newMenuRouters = menu.children.map((subMenu) => ({ ...subMenu, path: `${menu.path}/${subMenu.path}` }));
} }
}); });
} }
return menuRouters; return newMenuRouters;
}, });
},
methods: { const renderSidebar = () => {
renderSidebar() {
return ( return (
this.showSidebar && ( settingStore.showSidebar && (
<TDesignSideNav <TDesignSideNav
showLogo={this.showSidebarLogo} showLogo={settingStore.showSidebarLogo}
layout={this.setting.layout} layout={settingStore.layout}
isFixed={this.setting.isSidebarFixed} isFixed={settingStore.isSidebarFixed}
menu={this.sideMenu} menu={sideMenu.value}
theme={this.mode} theme={settingStore.displayMode}
isCompact={this.setting.isSidebarCompact} isCompact={settingStore.isSidebarCompact}
/> />
) )
); );
}, };
renderHeader() {
const renderHeader = () => {
return ( return (
this.showHeader && ( settingStore.showHeader && (
<TDesignHeader <TDesignHeader
showLogo={this.showHeaderLogo} showLogo={settingStore.showHeaderLogo}
theme={this.mode} theme={settingStore.displayMode}
layout={this.setting.layout} layout={settingStore.layout}
isFixed={this.setting.isHeaderFixed} isFixed={settingStore.isHeaderFixed}
menu={this.headerMenu} menu={headerMenu.value}
isCompact={this.setting.isSidebarCompact} isCompact={settingStore.isSidebarCompact}
/> />
) )
); );
}, };
renderContent() {
const { showBreadcrumb } = this.setting; const renderFooter = () => {
const { showFooter } = this; return (
<t-footer class={`${prefix}-footer-layout`}>
<TDesignFooter />
</t-footer>
);
};
const renderContent = () => {
const { showBreadcrumb, showFooter } = settingStore;
return ( return (
<t-layout class={[`${prefix}-layout`]}> <t-layout class={[`${prefix}-layout`]}>
<t-content class={`${prefix}-content-layout`}> <t-content class={`${prefix}-content-layout`}>
{showBreadcrumb && <TDesignBreadcrumb />} {showBreadcrumb && <TDesignBreadcrumb />}
<TDesignContent /> <TDesignContent />
</t-content> </t-content>
{showFooter && this.renderFooter()} {showFooter && renderFooter()}
</t-layout> </t-layout>
); );
}, };
renderFooter() { return {
return ( setting,
<t-footer class={`${prefix}-footer-layout`}> mainLayoutCls,
<TDesignFooter /> renderSidebar,
</t-footer> renderHeader,
); renderContent,
}, };
}, },
render() { render() {
const { layout } = this.setting; const { layout } = this.setting;
const header = this.renderHeader(); const header = this.renderHeader();

View File

@ -92,24 +92,23 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { ref, computed, watch, onMounted, watchEffect } from 'vue'; import { ref, computed, watch, onMounted, watchEffect } from 'vue';
import { useStore } from 'vuex';
import { ColorPicker } from 'vue-color-kit'; import { ColorPicker } from 'vue-color-kit';
import { MessagePlugin, PopupVisibleChangeContext } from 'tdesign-vue-next'; import { MessagePlugin, PopupVisibleChangeContext } from 'tdesign-vue-next';
import { Color } from 'tvision-color'; import { Color } from 'tvision-color';
import useClipboard from 'vue-clipboard3'; import useClipboard from 'vue-clipboard3';
import { useSettingStore } from '@/store';
import 'vue-color-kit/dist/vue-color-kit.css'; import 'vue-color-kit/dist/vue-color-kit.css';
import STYLE_CONFIG from '@/config/style'; import STYLE_CONFIG from '@/config/style';
import { insertThemeStylesheet, generateColorMap } from '@/config/color'; import { insertThemeStylesheet, generateColorMap } from '@/config/color';
import Thumbnail from '@/components/thumbnail/index.vue';
import ColorContainer from '@/components/color/index.vue';
import SettingDarkIcon from '@/assets/assets-setting-dark.svg'; import SettingDarkIcon from '@/assets/assets-setting-dark.svg';
import SettingLightIcon from '@/assets/assets-setting-light.svg'; import SettingLightIcon from '@/assets/assets-setting-light.svg';
import SettingAutoIcon from '@/assets/assets-setting-auto.svg'; import SettingAutoIcon from '@/assets/assets-setting-auto.svg';
const settingStore = useSettingStore();
const LAYOUT_OPTION = ['side', 'top', 'mix']; const LAYOUT_OPTION = ['side', 'top', 'mix'];
const COLOR_OPTIONS = ['default', 'cyan', 'green', 'yellow', 'orange', 'red', 'pink', 'purple', 'dynamic']; const COLOR_OPTIONS = ['default', 'cyan', 'green', 'yellow', 'orange', 'red', 'pink', 'purple', 'dynamic'];
const MODE_OPTIONS = [ const MODE_OPTIONS = [
@ -119,61 +118,63 @@ const MODE_OPTIONS = [
]; ];
const formData = ref({ ...STYLE_CONFIG }); const formData = ref({ ...STYLE_CONFIG });
const store = useStore();
const colors = ref(); const colors = ref();
const isColoPickerDisplay = ref(false); const isColoPickerDisplay = ref(false);
const showSettingPanel = computed({ const showSettingPanel = computed({
get() { get() {
return store.state.setting.showSettingPanel; return settingStore.showSettingPanel;
}, },
set(newVal) { set(newVal: boolean) {
store.commit('setting/toggleSettingPanel', newVal); settingStore.updateConfig({
showSettingPanel: newVal,
});
}, },
}); });
const mode = computed(() => { const mode = computed(() => {
return store.getters['setting/mode']; return settingStore.displayMode;
}); });
watch( watch(
() => colors.value, () => colors.value,
(newColor) => { (newColor) => {
const { hex } = newColor; const { hex } = newColor;
const { setting } = store.state;
// hex // hex
const newPalette = Color.getPaletteByGradation({ const newPalette = Color.getPaletteByGradation({
colors: [hex], colors: [hex],
step: 10, step: 10,
})[0]; })[0];
const { mode } = store.state.setting; const { mode } = settingStore;
const colorMap = generateColorMap(hex, newPalette, mode); const colorMap = generateColorMap(hex, newPalette, mode as 'light' | 'dark');
store.commit('setting/addColor', { [hex]: colorMap }); insertThemeStylesheet(hex, colorMap, mode as 'light' | 'dark');
insertThemeStylesheet(hex, colorMap, mode); settingStore.updateConfig({
[hex]: colorMap,
store.dispatch('setting/changeTheme', { ...setting, brandTheme: hex }); });
settingStore.changeBrandTheme(hex);
}, },
); );
const changeColor = (val) => { const changeColor = (val) => {
const { hex } = val; const { hex } = val;
const { setting } = store.state;
// hex // hex
const newPalette = Color.getPaletteByGradation({ const newPalette = Color.getPaletteByGradation({
colors: [hex], colors: [hex],
step: 10, step: 10,
})[0]; })[0];
const { mode } = store.state.setting; const { mode } = settingStore;
const colorMap = generateColorMap(hex, newPalette, mode); const colorMap = generateColorMap(hex, newPalette, mode as 'light' | 'dark');
store.commit('setting/addColor', { [hex]: colorMap }); settingStore.updateConfig({
[hex]: colorMap,
});
insertThemeStylesheet(hex, colorMap, mode); insertThemeStylesheet(hex, colorMap, mode as 'light' | 'dark');
store.dispatch('setting/changeTheme', { ...setting, brandTheme: hex }); settingStore.changeBrandTheme(hex);
}; };
onMounted(() => { onMounted(() => {
@ -212,7 +213,9 @@ const getModeIcon = (mode: string) => {
}; };
const handleCloseDrawer = () => { const handleCloseDrawer = () => {
store.commit('setting/toggleSettingPanel', false); settingStore.updateConfig({
showSettingPanel: false,
});
}; };
const getThumbnailUrl = (name: string): string => { const getThumbnailUrl = (name: string): string => {
@ -220,7 +223,7 @@ const getThumbnailUrl = (name: string): string => {
}; };
watchEffect(() => { watchEffect(() => {
store.dispatch('setting/changeTheme', formData.value); settingStore.updateConfig(formData.value);
}); });
</script> </script>
<style lang="less"> <style lang="less">

View File

@ -3,11 +3,11 @@ import { createApp } from 'vue';
import TDesign from 'tdesign-vue-next'; import TDesign from 'tdesign-vue-next';
import 'tdesign-vue-next/es/style/index.css'; import 'tdesign-vue-next/es/style/index.css';
import VueClipboard from 'vue3-clipboard'; import VueClipboard from 'vue3-clipboard';
import { store } from './store'; import { store } from './store';
import router from './router'; import router from './router';
import '@/style/index.less'; import '@/style/index.less';
import './permission'; import './permission';
import App from './App.vue'; import App from './App.vue';
const app = createApp(App); const app = createApp(App);

View File

@ -1,10 +1,8 @@
import dayjs from 'dayjs'; import dayjs from 'dayjs';
import * as echarts from 'echarts/core'; import * as echarts from 'echarts/core';
import { Color } from 'tvision-color'; import { Color } from 'tvision-color';
import { getBrandColor, defaultLightColor, defaultDarkColor } from '@/config/color'; import { getBrandColor, defaultLightColor, defaultDarkColor, TChartColor } from '@/config/color';
import store from '@/store'; import { getSettingStore } from '@/store';
const { state } = store;
/** /**
* *
@ -14,8 +12,8 @@ const { state } = store;
* @returns {} * @returns {}
*/ */
export function getColorFromTheme(theme: string) { export function getColorFromTheme(theme: string) {
const { setting } = state as any; const settingStore = getSettingStore();
const { colorList, mode } = setting; const { colorList, mode } = settingStore;
const isDarkMode = mode === 'dark'; const isDarkMode = mode === 'dark';
let themeColorList = []; let themeColorList = [];
const themeColor = getBrandColor(theme, colorList); const themeColor = getBrandColor(theme, colorList);
@ -41,8 +39,9 @@ export function getColorFromTheme(theme: string) {
/** 图表颜色 */ /** 图表颜色 */
function chartListColor(): Array<string> { function chartListColor(): Array<string> {
const { setting } = state as any; const settingStore = getSettingStore();
const res = getColorFromTheme(setting.brandTheme); const { brandTheme } = settingStore;
const res = getColorFromTheme(brandTheme);
return res; return res;
} }
@ -178,7 +177,7 @@ export function constructInitDataset({
dateTime = [], dateTime = [],
placeholderColor, placeholderColor,
borderColor, borderColor,
}: { dateTime: Array<string> } & Record<string, string>) { }: { dateTime: Array<string> } & TChartColor) {
// const dataset: Array<Array<string>> = [['时间'], ['入库'], ['出库']]; // const dataset: Array<Array<string>> = [['时间'], ['入库'], ['出库']];
const divideNum = 10; const divideNum = 10;
const timeArray = []; const timeArray = [];
@ -276,7 +275,7 @@ export function getSmoothLineDataSet({
dateTime = [], dateTime = [],
placeholderColor, placeholderColor,
borderColor, borderColor,
}: { dateTime?: Array<string> } & Record<string, string>) { }: { dateTime?: Array<string> } & TChartColor) {
let dateArray: Array<string> = ['00:00', '02:00', '04:00', '06:00']; let dateArray: Array<string> = ['00:00', '02:00', '04:00', '06:00'];
if (dateTime.length > 0) { if (dateTime.length > 0) {
const divideNum = 7; const divideNum = 7;
@ -383,7 +382,7 @@ export function getFolderLineDataSet({
dateTime = [], dateTime = [],
placeholderColor, placeholderColor,
borderColor, borderColor,
}: { dateTime?: Array<string> } & Record<string, string>) { }: { dateTime?: Array<string> } & TChartColor) {
let dateArray: Array<string> = ['周一', '周二', '周三', '周四', '周五', '周六', '周日']; let dateArray: Array<string> = ['周一', '周二', '周三', '周四', '周五', '周六', '周日'];
if (dateTime.length > 0) { if (dateTime.length > 0) {
const divideNum = 7; const divideNum = 7;
@ -543,7 +542,7 @@ export function getLineChartDataSet({
dateTime = [], dateTime = [],
placeholderColor, placeholderColor,
borderColor, borderColor,
}: { dateTime?: Array<string> } & Record<string, string>) { }: { dateTime?: Array<string> } & TChartColor) {
const divideNum = 10; const divideNum = 10;
const timeArray = []; const timeArray = [];
const inArray = []; const inArray = [];
@ -679,7 +678,7 @@ export function getScatterDataSet({
dateTime = [], dateTime = [],
placeholderColor, placeholderColor,
borderColor, borderColor,
}: { dateTime?: Array<string> } & Record<string, string>): any { }: { dateTime?: Array<string> } & TChartColor): any {
const divideNum = 40; const divideNum = 40;
const timeArray = []; const timeArray = [];
const inArray = []; const inArray = [];
@ -975,7 +974,7 @@ export function get2ColBarChartDataSet({
isMonth = false, isMonth = false,
placeholderColor, placeholderColor,
borderColor, borderColor,
}: { isMonth?: boolean } & Record<string, string>) { }: { isMonth?: boolean } & TChartColor) {
let lastYearListCopy = lastYearList.concat([]); let lastYearListCopy = lastYearList.concat([]);
let thisYearListCopy = lastYearList.concat([]); let thisYearListCopy = lastYearList.concat([]);
@ -1078,7 +1077,7 @@ export function getPieChartDataSet({
textColor, textColor,
placeholderColor, placeholderColor,
containerColor, containerColor,
}: { radius: number } & Record<string, string>) { }: { radius?: number } & Record<string, string>) {
return { return {
color: chartListColor(), color: chartListColor(),
tooltip: { tooltip: {

View File

@ -2,7 +2,7 @@
<div> <div>
<t-row :gutter="[16, 16]"> <t-row :gutter="[16, 16]">
<t-col v-for="(item, index) in PANE_LIST" :key="item.title" :xs="6" :xl="3"> <t-col v-for="(item, index) in PANE_LIST" :key="item.title" :xs="6" :xl="3">
<card :subtitle="item.title" :style="{ height: '168px' }" :class="{ 'main-color': index == 0 }"> <card :subtitle="item.title" size="small" :style="{ height: '168px' }" :class="{ 'main-color': index == 0 }">
<div class="dashboard-item"> <div class="dashboard-item">
<div class="dashboard-item-top"> <div class="dashboard-item-top">
<span :style="{ fontSize: `${resizeTime * 36}px` }">{{ item.number }}</span> <span :style="{ fontSize: `${resizeTime * 36}px` }">{{ item.number }}</span>
@ -204,12 +204,12 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { onMounted, watch, ref, onUnmounted, nextTick, computed } from 'vue'; import { onMounted, watch, ref, onUnmounted, nextTick, computed } from 'vue';
import { useStore } from 'vuex';
import * as echarts from 'echarts/core'; import * as echarts from 'echarts/core';
import { TooltipComponent, LegendComponent, GridComponent } from 'echarts/components'; import { TooltipComponent, LegendComponent, GridComponent } from 'echarts/components';
import { PieChart, LineChart, BarChart } from 'echarts/charts'; import { PieChart, LineChart, BarChart } from 'echarts/charts';
import { CanvasRenderer } from 'echarts/renderers'; import { CanvasRenderer } from 'echarts/renderers';
import { useSettingStore } from '@/store';
import { LAST_7_DAYS } from '@/utils/date'; import { LAST_7_DAYS } from '@/utils/date';
// //
@ -241,10 +241,10 @@ const getThisMonth = (checkedValues?: string[]) => {
return `${date.getFullYear()}-${startMonth}${date2.getFullYear()}-${endMonth}`; return `${date.getFullYear()}-${startMonth}${date2.getFullYear()}-${endMonth}`;
}; };
const store = useStore(); const store = useSettingStore();
const resizeTime = ref(1); const resizeTime = ref(1);
const chartColors = computed(() => store.state.setting.chartColors); const chartColors = computed(() => store.chartColors);
// moneyCharts // moneyCharts
let moneyContainer: HTMLElement; let moneyContainer: HTMLElement;
@ -355,14 +355,14 @@ onUnmounted(() => {
const currentMonth = ref(getThisMonth()); const currentMonth = ref(getThisMonth());
watch( watch(
() => store.state.setting.brandTheme, () => store.brandTheme,
() => { () => {
changeChartsTheme([refundChart, stokeChart, monitorChart, countChart]); changeChartsTheme([refundChart, stokeChart, monitorChart, countChart]);
}, },
); );
watch( watch(
() => store.state.setting.mode, () => store.mode,
() => { () => {
[moneyChart, refundChart, stokeChart, monitorChart, countChart].forEach((item) => { [moneyChart, refundChart, stokeChart, monitorChart, countChart].forEach((item) => {
item.dispose(); item.dispose();

View File

@ -59,7 +59,6 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { nextTick, onMounted, onUnmounted, watch, computed } from 'vue'; import { nextTick, onMounted, onUnmounted, watch, computed } from 'vue';
import { useStore } from 'vuex';
import * as echarts from 'echarts/core'; import * as echarts from 'echarts/core';
import { GridComponent, TooltipComponent, LegendComponent } from 'echarts/components'; import { GridComponent, TooltipComponent, LegendComponent } from 'echarts/components';
@ -70,14 +69,16 @@ import ProductCard from '@/components/card/Card.vue';
import { changeChartsTheme, getFolderLineDataSet, getScatterDataSet } from '../base/index'; import { changeChartsTheme, getFolderLineDataSet, getScatterDataSet } from '../base/index';
import { PANE_LIST_DATA, PRODUCT_LIST } from './constants'; import { PANE_LIST_DATA, PRODUCT_LIST } from './constants';
import { LAST_7_DAYS } from '@/utils/date'; import { LAST_7_DAYS } from '@/utils/date';
import { useSettingStore } from '@/store';
import Trend from '@/components/trend/index.vue'; import Trend from '@/components/trend/index.vue';
import Card from '@/components/card/index.vue'; import Card from '@/components/card/index.vue';
echarts.use([GridComponent, LegendComponent, TooltipComponent, LineChart, ScatterChart, CanvasRenderer]); echarts.use([GridComponent, LegendComponent, TooltipComponent, LineChart, ScatterChart, CanvasRenderer]);
const store = useStore(); const store = useSettingStore();
const chartColors = computed(() => store.state.setting.chartColors); const chartColors = computed(() => store.chartColors);
// lineChart logic // lineChart logic
let lineContainer: HTMLElement; let lineContainer: HTMLElement;
let lineChart: echarts.ECharts; let lineChart: echarts.ECharts;
@ -126,14 +127,14 @@ onUnmounted(() => {
}); });
watch( watch(
() => store.state.setting.mode, () => store.mode,
() => { () => {
renderCharts(); renderCharts();
}, },
); );
watch( watch(
() => store.state.setting.brandTheme, () => store.brandTheme,
() => { () => {
changeChartsTheme([lineChart, scatterChart]); changeChartsTheme([lineChart, scatterChart]);
}, },
@ -144,7 +145,7 @@ const onSatisfyChange = () => {
}; };
const onMaterialChange = (value: string[]) => { const onMaterialChange = (value: string[]) => {
const chartColors = computed(() => store.state.setting.chartColors); const chartColors = computed(() => store.chartColors);
lineChart.setOption(getFolderLineDataSet({ dateTime: value, ...chartColors.value })); lineChart.setOption(getFolderLineDataSet({ dateTime: value, ...chartColors.value }));
}; };
</script> </script>

View File

@ -70,12 +70,12 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { onMounted, onUnmounted, ref, watch, computed } from 'vue'; import { onMounted, onUnmounted, ref, watch, computed } from 'vue';
import { useStore } from 'vuex';
import * as echarts from 'echarts/core'; import * as echarts from 'echarts/core';
import { TitleComponent, ToolboxComponent, TooltipComponent, GridComponent, LegendComponent } from 'echarts/components'; import { TitleComponent, ToolboxComponent, TooltipComponent, GridComponent, LegendComponent } from 'echarts/components';
import { BarChart, LineChart } from 'echarts/charts'; import { BarChart, LineChart } from 'echarts/charts';
import { CanvasRenderer } from 'echarts/renderers'; import { CanvasRenderer } from 'echarts/renderers';
import { useSettingStore } from '@/store';
import { changeChartsTheme, getSmoothLineDataSet, get2ColBarChartDataSet } from '../../dashboard/base/index'; import { changeChartsTheme, getSmoothLineDataSet, get2ColBarChartDataSet } from '../../dashboard/base/index';
import { BASE_INFO_DATA, TABLE_COLUMNS as columns } from './constants'; import { BASE_INFO_DATA, TABLE_COLUMNS as columns } from './constants';
@ -96,9 +96,9 @@ echarts.use([
CanvasRenderer, CanvasRenderer,
]); ]);
const store = useStore(); const store = useSettingStore();
const chartColors = computed(() => store.state.setting.chartColors); const chartColors = computed(() => store.chartColors);
const data = ref([]); const data = ref([]);
const pagination = ref({ const pagination = ref({
defaultPageSize: 10, defaultPageSize: 10,
@ -173,7 +173,7 @@ onMounted(() => {
}); });
watch( watch(
() => store.state.setting.brandTheme, () => store.brandTheme,
() => { () => {
changeChartsTheme([monitorChart, dataChart]); changeChartsTheme([monitorChart, dataChart]);
}, },

View File

@ -50,11 +50,12 @@
</div> </div>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { ref, computed, ComputedRef } from 'vue'; import { ref, computed } from 'vue';
import { useStore } from 'vuex'; import { storeToRefs } from 'pinia';
import { NOTIFICATION_TYPES } from '@/constants'; import { NOTIFICATION_TYPES } from '@/constants';
import { NotificationItem } from '@/interface'; import { NotificationItem } from '@/interface';
import EmptyIcon from '@/assets/assets-empty.svg?component'; import EmptyIcon from '@/assets/assets-empty.svg?component';
import { useNotificationStore } from '@/store';
const TAB_LIST = [ const TAB_LIST = [
{ {
@ -76,14 +77,13 @@ const tabValue = ref('msgData');
const visible = ref(false); const visible = ref(false);
const selectedItem = ref<NotificationItem>(); const selectedItem = ref<NotificationItem>();
const store = useStore(); const store = useNotificationStore();
const { msgData, unreadMsg, readMsg } = storeToRefs(store);
const { msgData } = store.state.notification; const msgDataList = computed(() => {
if (tabValue.value === 'msgData') return msgData.value;
const msgDataList: ComputedRef<NotificationItem[]> = computed(() => { if (tabValue.value === 'unreadMsg') return unreadMsg.value;
if (tabValue.value === 'msgData') return msgData; if (tabValue.value === 'readMsg') return readMsg.value;
if (tabValue.value === 'unreadMsg') return store.getters['notification/unreadMsg'];
if (tabValue.value === 'readMsg') return store.getters['notification/readMsg'];
return []; return [];
}); });
@ -93,25 +93,25 @@ const handleClickDeleteBtn = (item: NotificationItem) => {
}; };
const setReadStatus = (item: NotificationItem) => { const setReadStatus = (item: NotificationItem) => {
const changeMsg = msgData; const changeMsg = msgData.value;
changeMsg.forEach((e: NotificationItem) => { changeMsg.forEach((e: NotificationItem) => {
if (e.id === item.id) { if (e.id === item.id) {
if (e.status) e.status = false; if (e.status) e.status = false;
} }
}); });
store.commit('notification/setMsgData', changeMsg); store.setMsgData(changeMsg);
}; };
const deleteMsg = () => { const deleteMsg = () => {
const item = selectedItem.value; const item = selectedItem.value;
const changeMsg = msgData; const changeMsg = msgData.value;
changeMsg.forEach((e: NotificationItem, index: number) => { changeMsg.forEach((e: NotificationItem, index: number) => {
if (e.id === item?.id) { if (e.id === item?.id) {
changeMsg.splice(index, 1); changeMsg.splice(index, 1);
} }
}); });
visible.value = false; visible.value = false;
store.commit('notification/setMsgData', changeMsg); store.setMsgData(changeMsg);
}; };
</script> </script>
<style lang="less" scoped> <style lang="less" scoped>

View File

@ -16,12 +16,14 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { useStore } from 'vuex';
import LogoFullIcon from '@/assets/assets-logo-full.svg?component'; import LogoFullIcon from '@/assets/assets-logo-full.svg?component';
import { useSettingStore } from '@/store';
const store = useStore(); const settingStore = useSettingStore();
const toggleSettingPanel = () => { const toggleSettingPanel = () => {
store.commit('setting/toggleSettingPanel', true); settingStore.updateConfig({
showSettingPanel: true,
});
}; };
const navToGitHub = () => { const navToGitHub = () => {

View File

@ -73,10 +73,12 @@
<script setup lang="ts"> <script setup lang="ts">
import { ref } from 'vue'; import { ref } from 'vue';
import { useRouter } from 'vue-router'; import { useRouter } from 'vue-router';
import { useStore } from 'vuex';
import QrcodeVue from 'qrcode.vue'; import QrcodeVue from 'qrcode.vue';
import { MessagePlugin } from 'tdesign-vue-next'; import { MessagePlugin } from 'tdesign-vue-next';
import { useCounter } from '@/hooks'; import { useCounter } from '@/hooks';
import { useUserStore } from '@/store';
const userStore = useUserStore();
const INITIAL_DATA = { const INITIAL_DATA = {
phone: '', phone: '',
@ -105,12 +107,12 @@ const switchType = (val: string) => {
}; };
const router = useRouter(); const router = useRouter();
const store = useStore();
const onSubmit = async ({ validateResult }) => { const onSubmit = async ({ validateResult }) => {
if (validateResult === true) { if (validateResult === true) {
try { try {
await store.dispatch('user/login', formData.value); await userStore.login(formData.value);
MessagePlugin.success('登陆成功'); MessagePlugin.success('登陆成功');
router.push({ router.push({
path: '/dashboard/base', path: '/dashboard/base',

View File

@ -91,11 +91,11 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { nextTick, onMounted, onUnmounted, watch, computed } from 'vue'; import { nextTick, onMounted, onUnmounted, watch, computed } from 'vue';
import { useStore } from 'vuex';
import * as echarts from 'echarts/core'; import * as echarts from 'echarts/core';
import { GridComponent, TooltipComponent, LegendComponent } from 'echarts/components'; import { GridComponent, TooltipComponent, LegendComponent } from 'echarts/components';
import { LineChart } from 'echarts/charts'; import { LineChart } from 'echarts/charts';
import { CanvasRenderer } from 'echarts/renderers'; import { CanvasRenderer } from 'echarts/renderers';
import { useSettingStore } from '@/store';
import { LAST_7_DAYS } from '@/utils/date'; import { LAST_7_DAYS } from '@/utils/date';
import { USER_INFO_LIST, TEAM_MEMBERS, PRODUCT_LIST } from './constants'; import { USER_INFO_LIST, TEAM_MEMBERS, PRODUCT_LIST } from './constants';
@ -111,8 +111,8 @@ echarts.use([GridComponent, TooltipComponent, LineChart, CanvasRenderer, LegendC
let lineContainer: HTMLElement; let lineContainer: HTMLElement;
let lineChart: echarts.ECharts; let lineChart: echarts.ECharts;
const store = useStore(); const store = useSettingStore();
const chartColors = computed(() => store.state.setting.chartColors); const chartColors = computed(() => store.chartColors);
const onLineChange = (value) => { const onLineChange = (value) => {
lineChart.setOption(getFolderLineDataSet(value)); lineChart.setOption(getFolderLineDataSet(value));
@ -166,7 +166,7 @@ const getIcon = (type) => {
}; };
watch( watch(
() => store.state.setting.brandTheme, () => store.brandTheme,
() => { () => {
changeChartsTheme([lineChart]); changeChartsTheme([lineChart]);
}, },

View File

@ -2,42 +2,47 @@ import { MessagePlugin } from 'tdesign-vue-next';
import NProgress from 'nprogress'; // progress bar import NProgress from 'nprogress'; // progress bar
import 'nprogress/nprogress.css'; // progress bar style import 'nprogress/nprogress.css'; // progress bar style
import store from '@/store'; import { getPermissionStore, getUserStore } from '@/store';
import router from '@/router'; import router from '@/router';
const permissionStore = getPermissionStore();
const userStore = getUserStore();
NProgress.configure({ showSpinner: false }); NProgress.configure({ showSpinner: false });
const whiteListRouters = store.getters['permission/whiteListRouters']; const { whiteListRouters } = permissionStore;
router.beforeEach(async (to, from, next) => { router.beforeEach(async (to, from, next) => {
NProgress.start(); NProgress.start();
const token = store.getters['user/token']; const { token } = userStore;
if (token) { if (token) {
if (to.path === '/login') { if (to.path === '/login') {
setTimeout(() => { setTimeout(() => {
store.dispatch('user/logout'); userStore.logout();
store.dispatch('permission/restore'); permissionStore.restore();
}); });
next(); next();
return; return;
} }
const roles = store.getters['user/roles']; const { roles } = userStore;
if (roles && roles.length > 0) { if (roles && roles.length > 0) {
next(); next();
} else { } else {
try { try {
await store.dispatch('user/getUserInfo'); await userStore.getUserInfo();
await store.dispatch('permission/initRoutes', store.getters['user/roles']); const { roles } = userStore;
await permissionStore.initRoutes(roles);
next({ ...to }); next({ ...to });
} catch (error) { } catch (error) {
console.log(error);
MessagePlugin.error(error); MessagePlugin.error(error);
await store.commit('user/removeToken'); await userStore.removeToken();
next(`/login?redirect=${to.path}`); next(`/login?redirect=${to.path}`);
NProgress.done(); NProgress.done();
} }

View File

@ -4,6 +4,8 @@ import baseRouters from './modules/base';
import componentsRouters from './modules/components'; import componentsRouters from './modules/components';
import othersRouters from './modules/others'; import othersRouters from './modules/others';
// 关于单层路由meta 中设置 { single: true } 即可为单层路由,{ hidden: true } 即可在侧边栏隐藏该路由
// 存放动态路由 // 存放动态路由
export const asyncRouterList: Array<RouteRecordRaw> = [...baseRouters, ...componentsRouters, ...othersRouters]; export const asyncRouterList: Array<RouteRecordRaw> = [...baseRouters, ...componentsRouters, ...othersRouters];

View File

@ -1,16 +1,12 @@
import { createStore } from 'vuex'; import { createPinia } from 'pinia';
import user from './modules/user';
import notification from './modules/notification';
import setting from './modules/setting';
import permission from './modules/permission';
export const store = createStore({ const store = createPinia();
modules: {
user, export { store };
setting,
notification, export * from './modules/notification';
permission, export * from './modules/permission';
}, export * from './modules/user';
}); export * from './modules/setting';
export default store; export default store;

View File

@ -1,85 +1,76 @@
// 定义的state初始值 import { defineStore } from 'pinia';
import { NotificationItem } from '@/interface'; import { NotificationItem } from '@/interface';
const state = { const msgData = [
msgData: [ {
{ id: '123',
id: '123', content: '腾讯大厦一楼改造施工项目 已通过审核!',
content: '腾讯大厦一楼改造施工项目 已通过审核!', type: '合同动态',
type: '合同动态', status: true,
status: true, collected: false,
collected: false, date: '2021-01-01 08:00',
date: '2021-01-01 08:00', quality: 'high',
quality: 'high',
},
{
id: '124',
content: '三季度生产原材料采购项目 开票成功!',
type: '票务动态',
status: true,
collected: false,
date: '2021-01-01 08:00',
quality: 'low',
},
{
id: '125',
content: '2021-01-01 10:00的【国家电网线下签约】会议即将开始请提前10分钟前往 会议室1 进行签到!',
type: '会议通知',
status: true,
collected: false,
date: '2021-01-01 08:00',
quality: 'middle',
},
{
id: '126',
content: '一季度生产原材料采购项目 开票成功!',
type: '票务动态',
status: true,
collected: false,
date: '2021-01-01 08:00',
quality: 'low',
},
{
id: '127',
content: '二季度生产原材料采购项目 开票成功!',
type: '票务动态',
status: true,
collected: false,
date: '2021-01-01 08:00',
quality: 'low',
},
{
id: '128',
content: '三季度生产原材料采购项目 开票成功!',
type: '票务动态',
status: true,
collected: false,
date: '2021-01-01 08:00',
quality: 'low',
},
],
};
type NotificationStateType = typeof state;
type MsgDataType = typeof state.msgData;
const mutations = {
setMsgData(state: NotificationStateType, data: MsgDataType) {
state.msgData = data;
}, },
}; {
id: '124',
content: '三季度生产原材料采购项目 开票成功!',
type: '票务动态',
status: true,
collected: false,
date: '2021-01-01 08:00',
quality: 'low',
},
{
id: '125',
content: '2021-01-01 10:00的【国家电网线下签约】会议即将开始请提前10分钟前往 会议室1 进行签到!',
type: '会议通知',
status: true,
collected: false,
date: '2021-01-01 08:00',
quality: 'middle',
},
{
id: '126',
content: '一季度生产原材料采购项目 开票成功!',
type: '票务动态',
status: true,
collected: false,
date: '2021-01-01 08:00',
quality: 'low',
},
{
id: '127',
content: '二季度生产原材料采购项目 开票成功!',
type: '票务动态',
status: true,
collected: false,
date: '2021-01-01 08:00',
quality: 'low',
},
{
id: '128',
content: '三季度生产原材料采购项目 开票成功!',
type: '票务动态',
status: true,
collected: false,
date: '2021-01-01 08:00',
quality: 'low',
},
];
const getters = { type MsgDataType = typeof msgData;
unreadMsg: (state: NotificationStateType) => state.msgData.filter((item: NotificationItem) => item.status),
readMsg: (state: NotificationStateType) => state.msgData.filter((item: NotificationItem) => !item.status),
};
const actions = {}; export const useNotificationStore = defineStore('notification', {
state: () => ({
export default { msgData,
namespaced: true, }),
state, getters: {
mutations, unreadMsg: (state) => state.msgData.filter((item: NotificationItem) => item.status),
actions, readMsg: (state) => state.msgData.filter((item: NotificationItem) => !item.status),
getters, },
}; actions: {
setMsgData(data: MsgDataType) {
this.msgData = data;
},
},
});

View File

@ -1,6 +1,9 @@
import { defineStore } from 'pinia';
import { RouteRecordRaw } from 'vue-router';
import router, { asyncRouterList, page404 } from '@/router'; import router, { asyncRouterList, page404 } from '@/router';
import { store } from '@/store';
function filterPermissionsRouters(routes, roles) { function filterPermissionsRouters(routes: Array<RouteRecordRaw>, roles: Array<unknown>) {
const res = []; const res = [];
routes.forEach((route) => { routes.forEach((route) => {
const children = []; const children = [];
@ -18,57 +21,38 @@ function filterPermissionsRouters(routes, roles) {
return res; return res;
} }
const state = { export const usePermissionStore = defineStore('permission', {
whiteListRouters: ['/login'], state: () => ({
routers: [], whiteListRouters: ['/login'],
}; routers: [],
}),
actions: {
async initRoutes(roles: Array<unknown>) {
let accessedRouters;
const mutations = { // special token
setRouters: (state, routers) => { if (roles.includes('ALL_ROUTERS')) {
state.routers = routers; accessedRouters = asyncRouterList;
} else {
accessedRouters = filterPermissionsRouters(asyncRouterList, roles);
}
this.routers = accessedRouters;
// register routers
accessedRouters.concat(page404).forEach((item: RouteRecordRaw) => {
router.addRoute(item);
});
},
async restore() {
this.routers.concat(page404).forEach((item: RouteRecordRaw) => {
if (router.hasRoute(item.name)) router.removeRoute(item.name);
});
this.routers = [];
},
}, },
}; });
const getters = { export function getPermissionStore() {
routers: (state) => { return usePermissionStore(store);
return state.routers; }
},
whiteListRouters: (state) => {
return state.whiteListRouters;
},
};
const actions = {
async initRoutes({ commit }, roles) {
let accessedRouters;
// special token
if (roles.includes('ALL_ROUTERS')) {
accessedRouters = asyncRouterList;
} else {
accessedRouters = filterPermissionsRouters(asyncRouterList, roles);
}
commit('setRouters', accessedRouters);
// register routers
state.routers.concat(page404).forEach((item) => {
router.addRoute(item);
});
},
async restore({ commit, state }) {
// remove routers
state.routers.concat(page404).forEach((item) => {
router.removeRoute(item.name);
});
commit('setRouters', []);
},
};
export default {
namespaced: true,
state,
mutations,
actions,
getters,
};

View File

@ -1,7 +1,8 @@
import { defineStore } from 'pinia';
import { COLOR_TOKEN, LIGHT_CHART_COLORS, DARK_CHART_COLORS } from '@/config/color';
import STYLE_CONFIG from '@/config/style'; import STYLE_CONFIG from '@/config/style';
import { COLOR_TOKEN, ColorSeries, ColorToken, LIGHT_CHART_COLORS, DARK_CHART_COLORS } from '@/config/color'; import { store } from '@/store';
// 定义的state初始值
const state = { const state = {
...STYLE_CONFIG, ...STYLE_CONFIG,
showSettingPanel: false, showSettingPanel: false,
@ -9,98 +10,62 @@ const state = {
chartColors: LIGHT_CHART_COLORS, chartColors: LIGHT_CHART_COLORS,
}; };
type IInitStateType = typeof state; export type TState = typeof state;
interface IStateType extends IInitStateType { export const useSettingStore = defineStore('setting', {
isAsideFooter: boolean; state: () => state,
showSettingPanel: boolean; getters: {
showSidebar: (state) => state.layout !== 'top',
showSidebarLogo: (state) => state.layout === 'side',
showHeaderLogo: (state) => state.layout !== 'side',
displayMode: (state) => {
if (state.mode === 'auto') {
const media = window.matchMedia('(prefers-color-scheme:dark)');
if (media.matches) {
return 'dark';
}
return 'light';
}
return state.mode;
},
},
actions: {
async changeMode(mode: 'dark' | 'light' | 'auto') {
let theme = mode;
if (mode === 'auto') {
const media = window.matchMedia('(prefers-color-scheme:dark)');
if (media.matches) {
theme = 'dark';
} else {
theme = 'light';
}
}
const isDarkMode = theme === 'dark';
document.documentElement.setAttribute('theme-mode', isDarkMode ? 'dark' : '');
this.chartColor = isDarkMode ? DARK_CHART_COLORS : LIGHT_CHART_COLORS;
},
changeBrandTheme(brandTheme: string) {
document.documentElement.setAttribute('theme-color', brandTheme);
},
updateConfig(payload: Partial<TState>) {
for (const key in payload) {
if (payload[key] !== undefined) {
this[key] = payload[key];
}
if (key === 'mode') {
this.changeMode(payload[key]);
}
if (key === 'brandTheme') {
this.changeBrandTheme(payload[key]);
}
}
},
},
});
export function getSettingStore() {
return useSettingStore(store);
} }
const mutations = {
update(state: IStateType, payload: IStateType) {
state.showBreadcrumb = payload.showBreadcrumb;
state.mode = payload.mode;
state.layout = payload.layout;
state.isSidebarCompact = payload.isSidebarCompact;
state.splitMenu = payload.splitMenu;
state.isFooterAside = payload.isFooterAside;
state.isSidebarFixed = payload.isSidebarFixed;
state.isHeaderFixed = payload.isHeaderFixed;
state.showHeader = payload.showHeader;
state.showFooter = payload.showFooter;
state.backgroundTheme = payload.backgroundTheme;
state.brandTheme = payload.brandTheme;
},
toggleSidebarCompact(state: IStateType) {
state.isSidebarCompact = !state.isSidebarCompact;
},
showSidebarCompact(state: IStateType, payload: boolean) {
state.isSidebarCompact = payload;
},
toggleSettingPanel(state: IStateType, payload: boolean) {
state.showSettingPanel = payload;
},
addColor(state: IStateType, payload: ColorSeries) {
state.colorList = { ...state.colorList, ...payload };
},
changeChartColor(state: IStateType, payload: ColorToken) {
state.chartColors = { ...payload };
},
};
const getters = {
showHeader: (state: IStateType) => state.showHeader,
showSidebar: (state: IStateType) => state.layout !== 'top',
showSidebarLogo: (state: IStateType) => state.layout === 'side',
showHeaderLogo: (state: IStateType) => state.layout !== 'side',
showFooter: (state: IStateType) => state.showFooter,
mode: (state: IStateType) => {
if (state.mode === 'auto') {
const media = window.matchMedia('(prefers-color-scheme:dark)');
if (media.matches) {
return 'dark';
}
return 'light';
}
return state.mode;
},
};
const actions = {
async changeTheme({ commit, dispatch }, payload) {
dispatch('changeMode', payload);
dispatch('changeBrandTheme', payload);
commit('update', payload);
},
async changeMode({ commit }, payload: IStateType) {
let theme = payload.mode;
if (payload.mode === 'auto') {
const media = window.matchMedia('(prefers-color-scheme:dark)');
if (media.matches) {
theme = 'dark';
} else {
theme = 'light';
}
}
const isDarkMode = theme === 'dark';
document.documentElement.setAttribute('theme-mode', isDarkMode ? 'dark' : '');
commit('changeChartColor', isDarkMode ? DARK_CHART_COLORS : LIGHT_CHART_COLORS);
},
changeBrandTheme(_: { state: IStateType }, payload: IStateType) {
const { brandTheme } = payload;
document.documentElement.setAttribute('theme-color', brandTheme);
},
};
export default {
namespaced: true,
state,
mutations,
actions,
getters,
};

View File

@ -1,102 +1,86 @@
import { defineStore } from 'pinia';
import { TOKEN_NAME } from '@/config/global'; import { TOKEN_NAME } from '@/config/global';
import { store } from '@/store';
const InitUserInfo = { const InitUserInfo = {
roles: [], roles: [],
}; };
// 定义的state初始值 export const useUserStore = defineStore('user', {
const state = { state: () => ({
token: localStorage.getItem(TOKEN_NAME) || 'main_token', // 默认token不走权限 token: localStorage.getItem(TOKEN_NAME) || 'main_token', // 默认token不走权限
userInfo: InitUserInfo, userInfo: InitUserInfo,
}; }),
getters: {
const mutations = { roles: (state) => {
setToken(state, token) { return state.userInfo?.roles;
localStorage.setItem(TOKEN_NAME, token); },
state.token = token;
}, },
removeToken(state) { actions: {
localStorage.removeItem(TOKEN_NAME); async login(userInfo: Record<string, unknown>) {
state.token = ''; const mockLogin = async (userInfo: Record<string, unknown>) => {
}, // 登录请求流程
setUserInfo(state, userInfo) { console.log(userInfo);
state.userInfo = userInfo; // const { account, password } = userInfo;
}, // if (account !== 'td') {
}; // return {
// code: 401,
const getters = { // message: '账号不存在',
token: (state) => { // };
return state.token; // }
}, // if (['main_', 'dev_'].indexOf(password) === -1) {
roles: (state) => { // return {
return state.userInfo?.roles; // code: 401,
}, // message: '密码错误',
}; // };
// }
const actions = { // const token = {
async login({ commit }, userInfo) { // main_: 'main_token',
const mockLogin = async (userInfo) => { // dev_: 'dev_token',
// 登录请求流程 // }[password];
console.log(userInfo);
// const { account, password } = userInfo;
// if (account !== 'td') {
// return {
// code: 401,
// message: '账号不存在',
// };
// }
// if (['main_', 'dev_'].indexOf(password) === -1) {
// return {
// code: 401,
// message: '密码错误',
// };
// }
// const token = {
// main_: 'main_token',
// dev_: 'dev_token',
// }[password];
return {
code: 200,
message: '登陆成功',
data: 'main_token',
};
};
const res = await mockLogin(userInfo);
if (res.code === 200) {
commit('setToken', res.data);
} else {
throw res;
}
},
async getUserInfo({ commit, state }) {
const mockRemoteUserInfo = async (token) => {
if (token === 'main_token') {
return { return {
name: 'td_main', code: 200,
roles: ['ALL_ROUTERS'], message: '登陆成功',
data: 'main_token',
}; };
}
return {
name: 'td_dev',
roles: ['userIndex', 'dashboardBase', 'login'],
}; };
};
const res = await mockRemoteUserInfo(state.token); const res = await mockLogin(userInfo);
if (res.code === 200) {
this.token = res.data;
} else {
throw res;
}
},
async getUserInfo() {
const mockRemoteUserInfo = async (token: string) => {
if (token === 'main_token') {
return {
name: 'td_main',
roles: ['ALL_ROUTERS'],
};
}
return {
name: 'td_dev',
roles: ['userIndex', 'dashboardBase', 'login'],
};
};
commit('setUserInfo', res); const res = await mockRemoteUserInfo(this.token);
this.userInfo = res;
},
async logout() {
localStorage.removeItem(TOKEN_NAME);
this.token = '';
this.userInfo = InitUserInfo;
},
async removeToken() {
this.token = '';
},
}, },
async logout({ commit }) { });
commit('removeToken');
commit('setUserInfo', InitUserInfo);
},
};
export default { export function getUserStore() {
namespaced: true, return useUserStore(store);
state, }
mutations,
actions,
getters,
};