Commit 5b8eb4a4 authored by Vben's avatar Vben

feat: dark mode

parent f05cc6d3
...@@ -11,6 +11,7 @@ ...@@ -11,6 +11,7 @@
- 移除 useFullScreen 函数 - 移除 useFullScreen 函数
- tinymce 由 Cdn 改为 npm(打包体积偏大) - tinymce 由 Cdn 改为 npm(打包体积偏大)
- Dashboard 重构 - Dashboard 重构
- 移除 ApexCharts 及示例
### 🐛 Bug Fixes ### 🐛 Bug Fixes
......
...@@ -2,11 +2,7 @@ import { generate } from '@ant-design/colors'; ...@@ -2,11 +2,7 @@ import { generate } from '@ant-design/colors';
export const primaryColor = '#0960bd'; export const primaryColor = '#0960bd';
export const borderColorBase = '#d9d9d9'; export const darkMode = 'light';
export const themeMode = 'light';
export type ThemeMode = 'dark' | 'light';
type Fn = (...arg: any) => any; type Fn = (...arg: any) => any;
...@@ -17,18 +13,17 @@ export interface GenerateColorsParams { ...@@ -17,18 +13,17 @@ export interface GenerateColorsParams {
color?: string; color?: string;
} }
export function generateAntColors(color: string, mode: ThemeMode) { export function generateAntColors(color: string) {
return generate(color, { return generate(color, {
theme: mode == 'dark' ? 'dark' : 'default', theme: 'default',
}); });
} }
export function getThemeColors(color?: string, theme?: ThemeMode) { export function getThemeColors(color?: string) {
const tc = color || primaryColor; const tc = color || primaryColor;
const tm = theme || themeMode; const colors = generateAntColors(tc);
const colors = generateAntColors(tc, tm);
const primary = colors[5]; const primary = colors[5];
const modeColors = generateAntColors(primary, tm === 'dark' ? 'light' : 'dark'); const modeColors = generateAntColors(primary);
return [...colors, ...modeColors]; return [...colors, ...modeColors];
} }
...@@ -71,36 +66,3 @@ export function generateColors({ ...@@ -71,36 +66,3 @@ export function generateColors({
.filter((item) => item !== '#000000'); .filter((item) => item !== '#000000');
return [...lightens, ...darkens, ...alphaColors, ...tinycolorDarkens, ...tinycolorLightens]; return [...lightens, ...darkens, ...alphaColors, ...tinycolorDarkens, ...tinycolorLightens];
} }
/**
* less global variable
*/
export function generateModifyVars() {
const palettes = generateAntColors(primaryColor, themeMode);
const primary = palettes[5];
const primaryColorObj: Record<string, string> = {};
for (let index = 0; index < 10; index++) {
primaryColorObj[`primary-${index + 1}`] = palettes[index];
}
return {
'primary-color': primary,
...primaryColorObj,
'info-color': primary,
'processing-color': primary,
'success-color': '#55D187', // Success color
'error-color': '#ED6F6F', // False color
'warning-color': '#EFBD47', // Warning color
'disabled-color': 'rgba(0, 0, 0, 0.25)', // Failure color
'heading-color': 'rgba(0, 0, 0, 0.85)', // Title color
'text-color': 'rgba(0, 0, 0, 0.85)', // Main text color
'text-color-secondary': 'rgba(0, 0, 0, 0.45)', // Subtext color
'font-size-base': '14px', // Main font size
'box-shadow-base': '0 2px 8px rgba(0, 0, 0, 0.15)', // Floating shadow
'border-color-base': borderColorBase, // Border color,
'border-radius-base': '2px', // Component/float fillet
'link-color': primary, // Link color
};
}
import { generateAntColors, primaryColor } from '../config/themeConfig';
import { getThemeVariables } from 'ant-design-vue/dist/theme';
import { resolve } from 'path';
/**
* less global variable
*/
export function generateModifyVars(dark = false) {
const palettes = generateAntColors(primaryColor);
const primary = palettes[5];
const primaryColorObj: Record<string, string> = {};
for (let index = 0; index < 10; index++) {
primaryColorObj[`primary-${index + 1}`] = palettes[index];
}
const modifyVars = getThemeVariables({ dark });
return {
...modifyVars,
// Used for global import to avoid the need to import each style file separately
// reference: Avoid repeated references
hack: `${modifyVars.hack} @import (reference) "${resolve('src/design/config.less')}";`,
'primary-color': primary,
...primaryColorObj,
'info-color': primary,
'processing-color': primary,
'success-color': '#55D187', // Success color
'error-color': '#ED6F6F', // False color
'warning-color': '#EFBD47', // Warning color
'font-size-base': '14px', // Main font size
'border-radius-base': '2px', // Component/float fillet
'link-color': primary, // Link color
};
}
...@@ -62,7 +62,7 @@ export function createVitePlugins(viteEnv: ViteEnv, isBuild: boolean) { ...@@ -62,7 +62,7 @@ export function createVitePlugins(viteEnv: ViteEnv, isBuild: boolean) {
vitePlugins.push(configVisualizerConfig()); vitePlugins.push(configVisualizerConfig());
//vite-plugin-theme //vite-plugin-theme
vitePlugins.push(configThemePlugin()); vitePlugins.push(configThemePlugin(isBuild));
// The following plugins only work in the production environment // The following plugins only work in the production environment
if (isBuild) { if (isBuild) {
......
...@@ -2,18 +2,50 @@ ...@@ -2,18 +2,50 @@
* Vite plugin for website theme color switching * Vite plugin for website theme color switching
* https://github.com/anncwb/vite-plugin-theme * https://github.com/anncwb/vite-plugin-theme
*/ */
import { viteThemePlugin, mixLighten, mixDarken, tinycolor } from 'vite-plugin-theme'; import type { Plugin } from 'vite';
import {
viteThemePlugin,
antdDarkThemePlugin,
mixLighten,
mixDarken,
tinycolor,
} from 'vite-plugin-theme';
import { getThemeColors, generateColors } from '../../config/themeConfig'; import { getThemeColors, generateColors } from '../../config/themeConfig';
import { generateModifyVars } from '../../generate/generateModifyVars';
export function configThemePlugin() { export function configThemePlugin(isBuild: boolean): Plugin[] {
const colors = generateColors({ const colors = generateColors({
mixDarken, mixDarken,
mixLighten, mixLighten,
tinycolor, tinycolor,
}); });
const plugin = viteThemePlugin({ const plugin = [
colorVariables: [...getThemeColors(), ...colors], viteThemePlugin({
}); resolveSelector: (s) => `[data-theme] ${s}`,
return plugin; colorVariables: [...getThemeColors(), ...colors],
}),
antdDarkThemePlugin({
filter: (id) => {
if (isBuild) {
return !id.endsWith('antd.less');
}
return true;
},
// extractCss: false,
darkModifyVars: {
...generateModifyVars(true),
'text-color': '#c9d1d9',
'text-color-base': '#c9d1d9',
'component-background': '#151515',
// black: '#0e1117',
// #8b949e
'text-color-secondary': '#8b949e',
'border-color-base': '#30363d',
'item-active-bg': '#111b26',
},
}),
];
return (plugin as unknown) as Plugin[];
} }
<!DOCTYPE html> <!DOCTYPE html>
<html lang="en"> <html lang="en" id="htmlRoot">
<head> <head>
<meta charset="UTF-8" /> <meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" /> <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
...@@ -13,8 +13,24 @@ ...@@ -13,8 +13,24 @@
<link rel="icon" href="/favicon.ico" /> <link rel="icon" href="/favicon.ico" />
</head> </head>
<body> <body>
<script>
(() => {
var htmlRoot = document.getElementById('htmlRoot');
const theme = window.localStorage.getItem('__APP__DARK__MODE__');
if (!htmlRoot || !theme) return;
htmlRoot.setAttribute('data-theme', theme);
})();
</script>
<div id="app"> <div id="app">
<style> <style>
html[data-theme='dark'] .app-loading {
background: #2c344a;
}
html[data-theme='dark'] .app-loading .app-loading-title {
color: rgba(255, 255, 255, 0.85);
}
.app-loading { .app-loading {
display: flex; display: flex;
width: 100%; width: 100%;
......
...@@ -35,7 +35,6 @@ ...@@ -35,7 +35,6 @@
"@vueuse/core": "^4.7.0", "@vueuse/core": "^4.7.0",
"@zxcvbn-ts/core": "^0.3.0", "@zxcvbn-ts/core": "^0.3.0",
"ant-design-vue": "^2.1.2", "ant-design-vue": "^2.1.2",
"apexcharts": "^3.26.0",
"axios": "^0.21.1", "axios": "^0.21.1",
"cropperjs": "^1.5.11", "cropperjs": "^1.5.11",
"crypto-js": "^4.0.0", "crypto-js": "^4.0.0",
...@@ -51,7 +50,7 @@ ...@@ -51,7 +50,7 @@
"vditor": "^3.8.4", "vditor": "^3.8.4",
"vue": "3.0.11", "vue": "3.0.11",
"vue-i18n": "^9.0.0", "vue-i18n": "^9.0.0",
"vue-router": "^4.0.5", "vue-router": "^4.0.6",
"vue-types": "^3.0.2", "vue-types": "^3.0.2",
"vuex": "^4.0.0", "vuex": "^4.0.0",
"vuex-module-decorators": "^1.0.1", "vuex-module-decorators": "^1.0.1",
...@@ -110,12 +109,12 @@ ...@@ -110,12 +109,12 @@
"vite-plugin-compression": "^0.2.4", "vite-plugin-compression": "^0.2.4",
"vite-plugin-html": "^2.0.6", "vite-plugin-html": "^2.0.6",
"vite-plugin-imagemin": "^0.3.0", "vite-plugin-imagemin": "^0.3.0",
"vite-plugin-mock": "^2.4.2", "vite-plugin-mock": "^2.5.0",
"vite-plugin-purge-icons": "^0.7.0", "vite-plugin-purge-icons": "^0.7.0",
"vite-plugin-pwa": "^0.6.5", "vite-plugin-pwa": "^0.6.5",
"vite-plugin-style-import": "^0.9.2", "vite-plugin-style-import": "^0.9.2",
"vite-plugin-svg-icons": "^0.4.1", "vite-plugin-svg-icons": "^0.4.1",
"vite-plugin-theme": "^0.5.0", "vite-plugin-theme": "^0.6.0",
"vite-plugin-windicss": "0.12.5", "vite-plugin-windicss": "0.12.5",
"vue-eslint-parser": "^7.6.0" "vue-eslint-parser": "^7.6.0"
}, },
......
<?xml version="1.0" encoding="iso-8859-1"?>
<svg version="1.1" id="Capa_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 499.712 499.712" style="enable-background: new 0 0 499.712 499.712;" xml:space="preserve">
<path style="fill: #FFD93B;" d="M146.88,375.528c126.272,0,228.624-102.368,228.624-228.64c0-55.952-20.16-107.136-53.52-146.88
C425.056,33.096,499.696,129.64,499.696,243.704c0,141.392-114.608,256-256,256c-114.064,0-210.608-74.64-243.696-177.712
C39.744,355.368,90.944,375.528,146.88,375.528z"/>
<path style="fill: #F4C534;" d="M401.92,42.776c34.24,43.504,54.816,98.272,54.816,157.952c0,141.392-114.608,256-256,256
c-59.68,0-114.448-20.576-157.952-54.816c46.848,59.472,119.344,97.792,200.928,97.792c141.392,0,256-114.608,256-256
C499.712,162.12,461.392,89.64,401.92,42.776z"/>
<g>
<polygon style="fill: #FFD83B;" points="128.128,99.944 154.496,153.4 213.472,161.96 170.8,203.56 180.864,262.296
128.128,234.568 75.376,262.296 85.44,203.56 42.768,161.96 101.744,153.4"/>
<polygon style="fill: #FFD83B;" points="276.864,82.84 290.528,110.552 321.104,114.984 298.976,136.552 304.208,166.984
276.864,152.616 249.52,166.984 254.752,136.552 232.624,114.984 263.2,110.552"/>
</g>
</svg>
<?xml version="1.0" encoding="iso-8859-1"?>
<svg version="1.1" id="Capa_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 60 60" style="enable-background: new 0 0 60 60;" xml:space="preserve">
<g>
<path style="fill: #F0C419;" d="M30,0c-0.552,0-1,0.448-1,1v6c0,0.552,0.448,1,1,1s1-0.448,1-1V1C31,0.448,30.552,0,30,0z"/>
<path style="fill: #F0C419;" d="M30,52c-0.552,0-1,0.448-1,1v6c0,0.552,0.448,1,1,1s1-0.448,1-1v-6C31,52.448,30.552,52,30,52z"/>
<path style="fill: #F0C419;" d="M59,29h-6c-0.552,0-1,0.448-1,1s0.448,1,1,1h6c0.552,0,1-0.448,1-1S59.552,29,59,29z"/>
<path style="fill: #F0C419;" d="M8,30c0-0.552-0.448-1-1-1H1c-0.552,0-1,0.448-1,1s0.448,1,1,1h6C7.552,31,8,30.552,8,30z"/>
<path style="fill: #F0C419;" d="M46.264,14.736c0.256,0,0.512-0.098,0.707-0.293l5.736-5.736c0.391-0.391,0.391-1.023,0-1.414
s-1.023-0.391-1.414,0l-5.736,5.736c-0.391,0.391-0.391,1.023,0,1.414C45.752,14.639,46.008,14.736,46.264,14.736z"/>
<path style="fill: #F0C419;" d="M13.029,45.557l-5.736,5.736c-0.391,0.391-0.391,1.023,0,1.414C7.488,52.902,7.744,53,8,53
s0.512-0.098,0.707-0.293l5.736-5.736c0.391-0.391,0.391-1.023,0-1.414S13.42,45.166,13.029,45.557z"/>
<path style="fill: #F0C419;" d="M46.971,45.557c-0.391-0.391-1.023-0.391-1.414,0s-0.391,1.023,0,1.414l5.736,5.736
C51.488,52.902,51.744,53,52,53s0.512-0.098,0.707-0.293c0.391-0.391,0.391-1.023,0-1.414L46.971,45.557z"/>
<path style="fill: #F0C419;" d="M8.707,7.293c-0.391-0.391-1.023-0.391-1.414,0s-0.391,1.023,0,1.414l5.736,5.736
c0.195,0.195,0.451,0.293,0.707,0.293s0.512-0.098,0.707-0.293c0.391-0.391,0.391-1.023,0-1.414L8.707,7.293z"/>
<path style="fill: #F0C419;" d="M50.251,21.404c0.162,0.381,0.532,0.61,0.921,0.61c0.13,0,0.263-0.026,0.39-0.08l2.762-1.172
c0.508-0.216,0.746-0.803,0.53-1.311s-0.804-0.746-1.311-0.53l-2.762,1.172C50.272,20.309,50.035,20.896,50.251,21.404z"/>
<path style="fill: #F0C419;" d="M9.749,38.596c-0.216-0.508-0.803-0.746-1.311-0.53l-2.762,1.172
c-0.508,0.216-0.746,0.803-0.53,1.311c0.162,0.381,0.532,0.61,0.921,0.61c0.13,0,0.263-0.026,0.39-0.08l2.762-1.172
C9.728,39.691,9.965,39.104,9.749,38.596z"/>
<path style="fill: #F0C419;" d="M54.481,38.813L51.7,37.688c-0.511-0.207-1.095,0.041-1.302,0.553
c-0.207,0.512,0.041,1.095,0.553,1.302l2.782,1.124c0.123,0.049,0.25,0.073,0.374,0.073c0.396,0,0.771-0.236,0.928-0.626
C55.241,39.603,54.994,39.02,54.481,38.813z"/>
<path style="fill: #F0C419;" d="M5.519,21.188L8.3,22.312c0.123,0.049,0.25,0.073,0.374,0.073c0.396,0,0.771-0.236,0.928-0.626
c0.207-0.512-0.041-1.095-0.553-1.302l-2.782-1.124c-0.513-0.207-1.095,0.04-1.302,0.553C4.759,20.397,5.006,20.98,5.519,21.188z"
/>
<path style="fill: #F0C419;" d="M39.907,50.781c-0.216-0.508-0.803-0.745-1.311-0.53c-0.508,0.216-0.746,0.803-0.53,1.311
l1.172,2.762c0.162,0.381,0.532,0.61,0.921,0.61c0.13,0,0.263-0.026,0.39-0.08c0.508-0.216,0.746-0.803,0.53-1.311L39.907,50.781z"
/>
<path style="fill: #F0C419;" d="M21.014,9.829c0.13,0,0.263-0.026,0.39-0.08c0.508-0.216,0.746-0.803,0.53-1.311l-1.172-2.762
c-0.215-0.509-0.802-0.747-1.311-0.53c-0.508,0.216-0.746,0.803-0.53,1.311l1.172,2.762C20.254,9.6,20.625,9.829,21.014,9.829z"/>
<path style="fill: #F0C419;" d="M21.759,50.398c-0.511-0.205-1.095,0.04-1.302,0.553l-1.124,2.782
c-0.207,0.512,0.041,1.095,0.553,1.302c0.123,0.049,0.25,0.073,0.374,0.073c0.396,0,0.771-0.236,0.928-0.626l1.124-2.782
C22.519,51.188,22.271,50.605,21.759,50.398z"/>
<path style="fill: #F0C419;" d="M38.615,9.675c0.396,0,0.771-0.236,0.928-0.626l1.124-2.782c0.207-0.512-0.041-1.095-0.553-1.302
c-0.511-0.207-1.095,0.041-1.302,0.553L37.688,8.3c-0.207,0.512,0.041,1.095,0.553,1.302C38.364,9.651,38.491,9.675,38.615,9.675z"
/>
</g>
<circle style="fill: #F0C419;" cx="30" cy="30" r="20"/>
<circle style="fill: #EDE21B;" cx="30" cy="30" r="15"/>
</svg>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="6395" height="1080" viewBox="0 0 6395 1080">
<defs>
<clipPath id="clip-path">
<rect id="Rectangle_73" data-name="Rectangle 73" width="6395" height="1079" transform="translate(-5391)" fill="#fff"/>
</clipPath>
<linearGradient id="linear-gradient" x1="0.631" y1="0.5" x2="0.958" y2="0.488" gradientUnits="objectBoundingBox">
<stop offset="0" stop-color="#2e364a"/>
<stop offset="1" stop-color="#2c344a"/>
</linearGradient>
</defs>
<g id="Web_1920_1" data-name="Web 1920 – 1" clip-path="url(#clip-Web_1920_1)">
<g id="Mask_Group_1" data-name="Mask Group 1" transform="translate(5391)" clip-path="url(#clip-path)">
<g id="Group_118" data-name="Group 118" transform="translate(-419.333 -1.126)">
<path id="Path_142" data-name="Path 142" d="M6271.734-6.176s-222.478,187.809-55.349,583.254c44.957,106.375,81.514,205.964,84.521,277,8.164,192.764-156.046,268.564-156.046,268.564l-653.53-26.8L5475.065-21.625Z" transform="translate(-4876.383)" fill="#2d3750"/>
<path id="Union_6" data-name="Union 6" d="M-2631.1,1081.8v-1.6H-8230.9V.022h5599.8V0h759.7s-187.845,197.448-91.626,488.844c49.167,148.9,96.309,256.289,104.683,362.118,7.979,100.852-57.98,201.711-168.644,254.286-65.858,31.29-144.552,42.382-223.028,42.383C-2441.2,1147.632-2631.1,1081.8-2631.1,1081.8Z" transform="translate(3259.524 0.803)" fill="url(#linear-gradient)"/>
</g>
</g>
</g>
</svg>
...@@ -4,8 +4,8 @@ ...@@ -4,8 +4,8 @@
<rect id="Rectangle_73" data-name="Rectangle 73" width="6395" height="1079" transform="translate(-5391)" fill="#fff"/> <rect id="Rectangle_73" data-name="Rectangle 73" width="6395" height="1079" transform="translate(-5391)" fill="#fff"/>
</clipPath> </clipPath>
<linearGradient id="linear-gradient" x1="0.747" y1="0.222" x2="0.973" y2="0.807" gradientUnits="objectBoundingBox"> <linearGradient id="linear-gradient" x1="0.747" y1="0.222" x2="0.973" y2="0.807" gradientUnits="objectBoundingBox">
<stop offset="0" stop-color="#2b51b4"/> <stop offset="0" stop-color="#2c41b4"/>
<stop offset="1" stop-color="#1c3faa"/> <stop offset="1" stop-color="#1b4fab"/>
</linearGradient> </linearGradient>
</defs> </defs>
<g id="Mask_Group_1" data-name="Mask Group 1" transform="translate(5391)" clip-path="url(#clip-path)"> <g id="Mask_Group_1" data-name="Mask Group 1" transform="translate(5391)" clip-path="url(#clip-path)">
......
...@@ -2,6 +2,7 @@ import AppLogo from './src/AppLogo.vue'; ...@@ -2,6 +2,7 @@ import AppLogo from './src/AppLogo.vue';
import AppProvider from './src/AppProvider.vue'; import AppProvider from './src/AppProvider.vue';
import AppSearch from './src/search/AppSearch.vue'; import AppSearch from './src/search/AppSearch.vue';
import AppLocalePicker from './src/AppLocalePicker.vue'; import AppLocalePicker from './src/AppLocalePicker.vue';
import AppDarkModeToggle from './src/AppDarkModeToggle.vue';
export { useAppProviderContext } from './src/useAppContext'; export { useAppProviderContext } from './src/useAppContext';
export { AppLogo, AppProvider, AppSearch, AppLocalePicker }; export { AppLogo, AppProvider, AppSearch, AppLocalePicker, AppDarkModeToggle };
<template>
<div
v-if="getShowDarkModeToggle"
:class="[
prefixCls,
`${prefixCls}--${size}`,
{
[`${prefixCls}--dark`]: isDark,
},
]"
@click="toggleDarkMode"
>
<div :class="`${prefixCls}-inner`"> </div>
<SvgIcon size="14" name="sun" />
<SvgIcon size="14" name="moon" />
</div>
</template>
<script lang="ts">
import { defineComponent, computed } from 'vue';
import { useDesign } from '/@/hooks/web/useDesign';
import { SvgIcon } from '/@/components/Icon';
import { useRootSetting } from '/@/hooks/setting/useRootSetting';
import { updateHeaderBgColor, updateSidebarBgColor } from '/@/logics/theme/updateBackground';
import { updateDarkTheme } from '/@/logics/theme/dark';
import { ThemeEnum } from '/@/enums/appEnum';
export default defineComponent({
name: 'DarkModeToggle',
components: { SvgIcon },
props: {
size: {
type: String,
default: 'default',
validate: (val) => ['default', 'large'].includes(val),
},
},
setup() {
const { prefixCls } = useDesign('dark-mode-toggle');
const { getDarkMode, setDarkMode, getShowDarkModeToggle } = useRootSetting();
const isDark = computed(() => getDarkMode.value === ThemeEnum.DARK);
function toggleDarkMode() {
const darkMode = getDarkMode.value === ThemeEnum.DARK ? ThemeEnum.LIGHT : ThemeEnum.DARK;
setDarkMode(darkMode);
updateDarkTheme(darkMode);
updateHeaderBgColor();
updateSidebarBgColor();
}
return {
isDark,
prefixCls,
toggleDarkMode,
getShowDarkModeToggle,
};
},
});
</script>
<style lang="less" scoped>
@prefix-cls: ~'@{namespace}-dark-mode-toggle';
html[data-theme='dark'] {
.@{prefix-cls} {
border: 1px solid rgb(196, 188, 188);
}
}
.@{prefix-cls} {
position: relative;
display: flex;
width: 50px;
height: 26px;
padding: 0 6px;
margin-left: auto;
cursor: pointer;
background-color: #151515;
border-radius: 30px;
justify-content: space-between;
align-items: center;
&-inner {
position: absolute;
z-index: 1;
width: 18px;
height: 18px;
background-color: #fff;
border-radius: 50%;
transition: transform 0.5s, background-color 0.5s;
will-change: transform;
}
&--dark {
.@{prefix-cls}-inner {
transform: translateX(calc(100% + 2px));
}
}
&--large {
width: 72px;
height: 34px;
padding: 0 10px;
.@{prefix-cls}-inner {
width: 26px;
height: 26px;
}
}
}
</style>
...@@ -42,9 +42,9 @@ ...@@ -42,9 +42,9 @@
padding: 0 16px; padding: 0 16px;
font-size: 12px; font-size: 12px;
color: #666; color: #666;
background: rgb(255 255 255); background: @component-background;
border-top: 1px solid @border-color-base;
border-radius: 0 0 16px 16px; border-radius: 0 0 16px 16px;
box-shadow: 0 -1px 0 0 #e0e3e8, 0 -3px 6px 0 rgba(69, 98, 155, 0.12);
align-items: center; align-items: center;
flex-shrink: 0; flex-shrink: 0;
......
...@@ -190,12 +190,10 @@ ...@@ -190,12 +190,10 @@
&-content { &-content {
position: relative; position: relative;
width: 632px; width: 632px;
// padding: 14px;
margin: 0 auto auto auto; margin: 0 auto auto auto;
background: #f5f6f7; background: @component-background;
border-radius: 16px; border-radius: 16px;
box-shadow: 0 25px 50px -12px rgba(0, 0, 0, 0.25); box-shadow: 0 25px 50px -12px rgba(0, 0, 0, 0.25);
// box-shadow: inset 1px 1px 0 0 hsla(0, 0%, 100%, 0.5), 0 3px 8px 0 #555a64;
flex-direction: column; flex-direction: column;
} }
...@@ -253,8 +251,7 @@ ...@@ -253,8 +251,7 @@
font-size: 14px; font-size: 14px;
color: @text-color-base; color: @text-color-base;
cursor: pointer; cursor: pointer;
// background: @primary-color; background: @component-background;
background: #fff;
border-radius: 4px; border-radius: 4px;
box-shadow: 0 1px 3px 0 #d4d9e1; box-shadow: 0 1px 3px 0 #d4d9e1;
align-items: center; align-items: center;
......
...@@ -101,7 +101,7 @@ ...@@ -101,7 +101,7 @@
@prefix-cls: ~'@{namespace}-collapse-container'; @prefix-cls: ~'@{namespace}-collapse-container';
.@{prefix-cls} { .@{prefix-cls} {
background: #fff; background: @component-background;
border-radius: 2px; border-radius: 2px;
transition: all 0.3s ease-in-out; transition: all 0.3s ease-in-out;
......
...@@ -22,7 +22,7 @@ ...@@ -22,7 +22,7 @@
&:not(.ant-menu-item-disabled):hover { &:not(.ant-menu-item-disabled):hover {
color: @text-color-base; color: @text-color-base;
background: #eee; background: @item-hover-bg;
} }
} }
} }
...@@ -36,7 +36,7 @@ ...@@ -36,7 +36,7 @@
width: 156px; width: 156px;
margin: 0; margin: 0;
list-style: none; list-style: none;
background-color: #fff; background-color: @component-background;
border: 1px solid rgba(0, 0, 0, 0.08); border: 1px solid rgba(0, 0, 0, 0.08);
border-radius: 0.25rem; border-radius: 0.25rem;
box-shadow: 0 2px 2px 0 rgba(0, 0, 0, 0.14), 0 3px 1px -2px rgba(0, 0, 0, 0.1), box-shadow: 0 2px 2px 0 rgba(0, 0, 0, 0.14), 0 3px 1px -2px rgba(0, 0, 0, 0.1),
......
...@@ -221,7 +221,7 @@ ...@@ -221,7 +221,7 @@
.ant-drawer-body { .ant-drawer-body {
height: calc(100% - @header-height); height: calc(100% - @header-height);
padding: 0; padding: 0;
background-color: #fff; background-color: @component-background;
.scrollbar__wrap { .scrollbar__wrap {
padding: 16px !important; padding: 16px !important;
......
...@@ -74,7 +74,7 @@ ...@@ -74,7 +74,7 @@
width: 100%; width: 100%;
padding: 0 12px 0 20px; padding: 0 12px 0 20px;
text-align: right; text-align: right;
background: #fff; background: @component-background;
border-top: 1px solid @border-color-base; border-top: 1px solid @border-color-base;
> * { > * {
......
...@@ -258,7 +258,7 @@ ...@@ -258,7 +258,7 @@
const { label, helpMessage, helpComponentProps, subLabel } = props.schema; const { label, helpMessage, helpComponentProps, subLabel } = props.schema;
const renderLabel = subLabel ? ( const renderLabel = subLabel ? (
<span> <span>
{label} <span style="color:#00000073">{subLabel}</span> {label} <span class="text-secondary">{subLabel}</span>
</span> </span>
) : ( ) : (
label label
......
<template> <template>
<section class="full-loading" :class="{ absolute }" v-show="loading" :style="getStyle"> <section class="full-loading" :class="{ absolute }" v-show="loading">
<Spin v-bind="$attrs" :tip="tip" :size="size" :spinning="loading" /> <Spin v-bind="$attrs" :tip="tip" :size="size" :spinning="loading" />
</section> </section>
</template> </template>
<script lang="ts"> <script lang="ts">
import { computed, CSSProperties, PropType } from 'vue'; import { PropType } from 'vue';
import { defineComponent } from 'vue'; import { defineComponent } from 'vue';
import { Spin } from 'ant-design-vue'; import { Spin } from 'ant-design-vue';
import { SizeEnum } from '/@/enums/sizeEnum'; import { SizeEnum } from '/@/enums/sizeEnum';
import { ThemeEnum } from '/@/enums/appEnum';
export default defineComponent({ export default defineComponent({
name: 'Loading', name: 'Loading',
...@@ -38,25 +37,6 @@ ...@@ -38,25 +37,6 @@
background: { background: {
type: String as PropType<string>, type: String as PropType<string>,
}, },
theme: {
type: String as PropType<'dark' | 'light'>,
default: 'light',
},
},
setup(props) {
const getStyle = computed(
(): CSSProperties => {
const { background, theme } = props;
const bgColor = background
? background
: theme === ThemeEnum.DARK
? 'rgba(0, 0, 0, 0.2)'
: 'rgba(240, 242, 245, 0.4)';
return { background: bgColor };
}
);
return { getStyle };
}, },
}); });
</script> </script>
...@@ -71,6 +51,7 @@ ...@@ -71,6 +51,7 @@
height: 100%; height: 100%;
justify-content: center; justify-content: center;
align-items: center; align-items: center;
background: rgba(240, 242, 245, 0.4);
&.absolute { &.absolute {
position: absolute; position: absolute;
...@@ -79,4 +60,10 @@ ...@@ -79,4 +60,10 @@
z-index: 300; z-index: 300;
} }
} }
html[data-theme='dark'] {
.full-loading {
background: @modal-mask-bg;
}
}
</style> </style>
...@@ -10,7 +10,7 @@ ...@@ -10,7 +10,7 @@
onUnmounted, onUnmounted,
nextTick, nextTick,
computed, computed,
watchEffect, watch,
} from 'vue'; } from 'vue';
import Vditor from 'vditor'; import Vditor from 'vditor';
import 'vditor/dist/index.css'; import 'vditor/dist/index.css';
...@@ -18,6 +18,7 @@ ...@@ -18,6 +18,7 @@
import { propTypes } from '/@/utils/propTypes'; import { propTypes } from '/@/utils/propTypes';
import { useLocale } from '/@/locales/useLocale'; import { useLocale } from '/@/locales/useLocale';
import { useModalContext } from '../../Modal'; import { useModalContext } from '../../Modal';
import { useRootSetting } from '/@/hooks/setting/useRootSetting';
type Lang = 'zh_CN' | 'en_US' | 'ja_JP' | 'ko_KR' | undefined; type Lang = 'zh_CN' | 'en_US' | 'ja_JP' | 'ko_KR' | undefined;
export default defineComponent({ export default defineComponent({
...@@ -35,8 +36,24 @@ ...@@ -35,8 +36,24 @@
const modalFn = useModalContext(); const modalFn = useModalContext();
const { getLocale } = useLocale(); const { getLocale } = useLocale();
const { getDarkMode } = useRootSetting();
watchEffect(() => {}); watch(
[() => getDarkMode.value, () => initedRef.value],
([val]) => {
const vditor = unref(vditorRef);
if (!vditor) {
return;
}
const theme = val === 'dark' ? 'dark' : undefined;
vditor.setTheme(theme as 'dark');
},
{
immediate: true,
flush: 'post',
}
);
const getCurrentLang = computed((): 'zh_CN' | 'en_US' | 'ja_JP' | 'ko_KR' => { const getCurrentLang = computed((): 'zh_CN' | 'en_US' | 'ja_JP' | 'ko_KR' => {
let lang: Lang; let lang: Lang;
...@@ -60,6 +77,7 @@ ...@@ -60,6 +77,7 @@
if (!wrapEl) return; if (!wrapEl) return;
const bindValue = { ...attrs, ...props }; const bindValue = { ...attrs, ...props };
vditorRef.value = new Vditor(wrapEl, { vditorRef.value = new Vditor(wrapEl, {
theme: 'classic',
lang: unref(getCurrentLang), lang: unref(getCurrentLang),
mode: 'sv', mode: 'sv',
preview: { preview: {
......
...@@ -38,8 +38,8 @@ ...@@ -38,8 +38,8 @@
align-items: center; align-items: center;
padding: 0 24px; padding: 0 24px;
line-height: 44px; line-height: 44px;
background: #fff; background: @component-background;
border-top: 1px solid #f0f0f0; border-top: 1px solid @border-color-base;
box-shadow: 0 -6px 16px -8px rgba(0, 0, 0, 0.08), 0 -9px 28px 0 rgba(0, 0, 0, 0.05), box-shadow: 0 -6px 16px -8px rgba(0, 0, 0, 0.08), 0 -9px 28px 0 rgba(0, 0, 0, 0.05),
0 -12px 48px 16px rgba(0, 0, 0, 0.03); 0 -12px 48px 16px rgba(0, 0, 0, 0.03);
transition: width 0.2s; transition: width 0.2s;
......
...@@ -17,11 +17,7 @@ ...@@ -17,11 +17,7 @@
<slot :name="item" v-bind="data"></slot> <slot :name="item" v-bind="data"></slot>
</template> </template>
</PageHeader> </PageHeader>
<div <div class="overflow-hidden" :class="getContentClass" :style="getContentStyle">
class="overflow-hidden"
:class="[`${prefixCls}-content`, contentClass]"
:style="getContentStyle"
>
<slot></slot> <slot></slot>
</div> </div>
<PageFooter v-if="getShowFooter" ref="footerRef"> <PageFooter v-if="getShowFooter" ref="footerRef">
...@@ -87,14 +83,12 @@ ...@@ -87,14 +83,12 @@
const getContentStyle = computed( const getContentStyle = computed(
(): CSSProperties => { (): CSSProperties => {
const { contentBackground, contentFullHeight, contentStyle, fixedHeight } = props; const { contentFullHeight, contentStyle, fixedHeight } = props;
const bg = contentBackground ? { backgroundColor: '#fff' } : {};
if (!contentFullHeight) { if (!contentFullHeight) {
return { ...bg, ...contentStyle }; return { ...contentStyle };
} }
const height = `${unref(pageHeight)}px`; const height = `${unref(pageHeight)}px`;
return { return {
...bg,
...contentStyle, ...contentStyle,
minHeight: height, minHeight: height,
...(fixedHeight ? { height } : {}), ...(fixedHeight ? { height } : {}),
...@@ -103,6 +97,17 @@ ...@@ -103,6 +97,17 @@
} }
); );
const getContentClass = computed(() => {
const { contentBackground, contentClass } = props;
return [
`${prefixCls}-content`,
contentClass,
{
[`${prefixCls}-content-bg`]: contentBackground,
},
];
});
watch( watch(
() => [contentHeight?.value, getShowFooter.value], () => [contentHeight?.value, getShowFooter.value],
() => { () => {
...@@ -170,6 +175,7 @@ ...@@ -170,6 +175,7 @@
getShowFooter, getShowFooter,
pageHeight, pageHeight,
omit, omit,
getContentClass,
}; };
}, },
}); });
...@@ -190,6 +196,10 @@ ...@@ -190,6 +196,10 @@
} }
} }
&-content-bg {
background: @component-background;
}
&--dense { &--dense {
.@{prefix-cls}-content { .@{prefix-cls}-content {
margin: 0; margin: 0;
......
...@@ -11,9 +11,9 @@ ...@@ -11,9 +11,9 @@
&-dark&-vertical .@{simple-prefix-cls}__children, &-dark&-vertical .@{simple-prefix-cls}__children,
&-dark&-popup .@{simple-prefix-cls}__children { &-dark&-popup .@{simple-prefix-cls}__children {
background-color: @sider-dark-lighten-1-bg-color; background-color: @sider-dark-lighten-bg-color;
> .@{prefix-cls}-submenu-title { > .@{prefix-cls}-submenu-title {
background-color: @sider-dark-lighten-1-bg-color; background-color: @sider-dark-lighten-bg-color;
} }
} }
......
...@@ -298,6 +298,26 @@ ...@@ -298,6 +298,26 @@
@prefix-cls: ~'@{namespace}-basic-table'; @prefix-cls: ~'@{namespace}-basic-table';
html[data-theme='light'] {
.@{prefix-cls} {
&-row__striped {
td {
background: #fafafa;
}
}
}
}
html[data-theme='dark'] {
.@{prefix-cls} {
&-row__striped {
td {
background: rgb(255 255 255 / 4%);
}
}
}
}
.@{prefix-cls} { .@{prefix-cls} {
&-form-container { &-form-container {
padding: 16px; padding: 16px;
...@@ -305,17 +325,11 @@ ...@@ -305,17 +325,11 @@
.ant-form { .ant-form {
padding: 12px 10px 6px 10px; padding: 12px 10px 6px 10px;
margin-bottom: 16px; margin-bottom: 16px;
background: #fff; background: @component-background;
border-radius: 4px; border-radius: 4px;
} }
} }
&-row__striped {
td {
background: #fafafa;
}
}
&--inset { &--inset {
.ant-table-wrapper { .ant-table-wrapper {
padding: 0; padding: 0;
...@@ -328,7 +342,7 @@ ...@@ -328,7 +342,7 @@
.ant-table-wrapper { .ant-table-wrapper {
padding: 6px; padding: 6px;
background: #fff; background: @component-background;
border-radius: 2px; border-radius: 2px;
.ant-table-title { .ant-table-title {
...@@ -340,7 +354,6 @@ ...@@ -340,7 +354,6 @@
} }
} }
//
.ant-table { .ant-table {
width: 100%; width: 100%;
overflow-x: hidden; overflow-x: hidden;
......
...@@ -324,7 +324,7 @@ ...@@ -324,7 +324,7 @@
const showTitle = title || toolbar || search || slots.headerTitle; const showTitle = title || toolbar || search || slots.headerTitle;
const scrollStyle: CSSProperties = { height: 'calc(100% - 38px)' }; const scrollStyle: CSSProperties = { height: 'calc(100% - 38px)' };
return ( return (
<div class={[prefixCls, 'h-full bg-white', attrs.class]}> <div class={[prefixCls, 'h-full', attrs.class]}>
{showTitle && ( {showTitle && (
<TreeHeader <TreeHeader
checkable={checkable} checkable={checkable}
...@@ -361,6 +361,8 @@ ...@@ -361,6 +361,8 @@
@prefix-cls: ~'@{namespace}-basic-tree'; @prefix-cls: ~'@{namespace}-basic-tree';
.@{prefix-cls} { .@{prefix-cls} {
background: @component-background;
.ant-tree-node-content-wrapper { .ant-tree-node-content-wrapper {
position: relative; position: relative;
......
.file-table { .file-table {
width: 100%; width: 100%;
border-collapse: collapse; border-collapse: collapse;
// border: 1px solid @border-color-light;
.center { .center {
text-align: center; text-align: center;
...@@ -21,12 +20,12 @@ ...@@ -21,12 +20,12 @@
} }
thead { thead {
background-color: @background-color-dark; background-color: @background-color-light;
} }
table, table,
td, td,
th { th {
border: 1px solid @border-color-light; border: 1px solid @border-color-base;
} }
} }
...@@ -61,9 +61,9 @@ ...@@ -61,9 +61,9 @@
&.ant-btn-link.is-disabled { &.ant-btn-link.is-disabled {
color: rgba(0, 0, 0, 0.25) !important; color: rgba(0, 0, 0, 0.25) !important;
text-shadow: none; text-shadow: none;
cursor: not-allowed; cursor: not-allowed !important;
background-color: transparent; background-color: transparent !important;
border-color: transparent; border-color: transparent !important;
box-shadow: none; box-shadow: none;
} }
...@@ -187,7 +187,7 @@ ...@@ -187,7 +187,7 @@
&-ghost { &-ghost {
color: @button-ghost-color; color: @button-ghost-color;
background-color: @white; background-color: transparent;
border-color: @button-ghost-color; border-color: @button-ghost-color;
border-width: 1px; border-width: 1px;
...@@ -205,4 +205,14 @@ ...@@ -205,4 +205,14 @@
border-color: fade(@button-ghost-color, 40%); border-color: fade(@button-ghost-color, 40%);
} }
} }
&-ghost.ant-btn-link:not([disabled='disabled']) {
color: @button-ghost-color;
&:hover,
&:focus {
color: @button-ghost-hover-color;
border-color: transparent;
}
}
} }
html[data-theme='dark'] {
.ant-pagination {
&.mini {
.ant-pagination-prev,
.ant-pagination-next,
.ant-pagination-item {
background: rgb(255 255 255 / 4%) !important;
a {
color: #8b949e !important;
}
}
.ant-select-arrow {
color: @text-color-secondary !important;
}
.ant-pagination-item-active {
background: @primary-color !important;
border: none;
border-radius: none !important;
a {
color: @white !important;
}
}
}
}
}
.ant-pagination { .ant-pagination {
&.mini { &.mini {
.ant-pagination-prev, .ant-pagination-prev,
......
:root { html {
// header // header
--header-bg-color: #394664; --header-bg-color: #394664;
--header-bg-hover-color: #273352; --header-bg-hover-color: #273352;
...@@ -7,16 +7,13 @@ ...@@ -7,16 +7,13 @@
// sider // sider
--sider-dark-bg-color: #273352; --sider-dark-bg-color: #273352;
--sider-dark-darken-bg-color: #273352; --sider-dark-darken-bg-color: #273352;
--sider-dark-lighten-1-bg-color: #273352; --sider-dark-lighten-bg-color: #273352;
--sider-dark-lighten-2-bg-color: #273352;
} }
@white: #fff; @white: #fff;
@content-bg: #f4f7f9; @content-bg: #f4f7f9;
// @content-bg: #f0f2f5;
@basic-mask-color: fade(@white, 30%);
// :export { // :export {
// name: "less"; // name: "less";
// mainColor: @mainColor; // mainColor: @mainColor;
...@@ -35,10 +32,7 @@ ...@@ -35,10 +32,7 @@
@border-color-shallow-dark: #cececd; @border-color-shallow-dark: #cececd;
// Light-dark // Light-dark
@border-color-light: #ebeef5; @border-color-light: @border-color-base;
// Light-light
@border-color-shallow-light: #f2f6fc;
// ================================= // =================================
// ==============message============== // ==============message==============
...@@ -53,17 +47,6 @@ ...@@ -53,17 +47,6 @@
// danger-bg-color // danger-bg-color
@danger-background-color: #fef0f0; @danger-background-color: #fef0f0;
// =================================
// ==============bg color============
// =================================
// dark
@background-color-dark: #f4f7f9;
// light
@background-color-light: #f5f7fa;
// layout content background
@layout-content-bg-color: #f1f1f6;
// ================================= // =================================
// ==============Header============= // ==============Header=============
// ================================= // =================================
...@@ -83,14 +66,11 @@ ...@@ -83,14 +66,11 @@
// let -menu // let -menu
@sider-dark-bg-color: var(--sider-dark-bg-color); @sider-dark-bg-color: var(--sider-dark-bg-color);
@sider-dark-darken-bg-color: var(--sider-dark-darken-bg-color); @sider-dark-darken-bg-color: var(--sider-dark-darken-bg-color);
@sider-dark-lighten-1-bg-color: var(--sider-dark-lighten-1-bg-color); @sider-dark-lighten-bg-color: var(--sider-dark-lighten-bg-color);
@sider-dark-lighten-2-bg-color: var(--sider-dark-lighten-2-bg-color);
// trigger // trigger
@trigger-dark-hover-bg-color: rgba(255, 255, 255, 0.2); @trigger-dark-hover-bg-color: rgba(255, 255, 255, 0.2);
@trigger-dark-bg-color: rgba(255, 255, 255, 0.1); @trigger-dark-bg-color: rgba(255, 255, 255, 0.1);
@trigger-light-bg-color: @white;
@trigger-light-hover-bg-color: rgba(255, 255, 255, 0.7);
// ================================= // =================================
// ==============tree============ // ==============tree============
...@@ -119,9 +99,6 @@ ...@@ -119,9 +99,6 @@
// Auxiliary information color-dark // Auxiliary information color-dark
@text-color-help-dark: #909399; @text-color-help-dark: #909399;
// Auxiliary information color-light color
@text-color-help-light: #c0c4cc;
// ================================= // =================================
// ==============breadcrumb========= // ==============breadcrumb=========
// ================================= // =================================
......
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
@import 'var/index.less'; @import 'var/index.less';
@import 'public.less'; @import 'public.less';
@import 'ant/index.less'; @import 'ant/index.less';
@import './theme.less';
input:-webkit-autofill { input:-webkit-autofill {
-webkit-box-shadow: 0 0 0 1000px white inset !important; -webkit-box-shadow: 0 0 0 1000px white inset !important;
......
.bg-white {
background: @component-background !important;
}
html[data-theme='light'] {
.text-secondary {
color: rgba(0, 0, 0, 0.45);
}
}
html[data-theme='dark'] {
.text-secondary {
color: #8b949e;
}
.ant-card-grid-hoverable:hover {
box-shadow: 0 3px 6px -4px rgb(0 0 0 / 48%), 0 6px 16px 0 rgb(0 0 0 / 32%),
0 9px 28px 8px rgb(0 0 0 / 20%);
}
.ant-alert-message,
.ant-alert-with-description .ant-alert-message,
.ant-alert-description {
color: rgba(0, 0, 0, 0.85);
}
.ant-checkbox-checked .ant-checkbox-inner::after {
border-top: 0;
border-left: 0;
}
}
...@@ -5,14 +5,12 @@ const loadingDirective: Directive = { ...@@ -5,14 +5,12 @@ const loadingDirective: Directive = {
mounted(el, binding) { mounted(el, binding) {
const tip = el.getAttribute('loading-tip'); const tip = el.getAttribute('loading-tip');
const background = el.getAttribute('loading-background'); const background = el.getAttribute('loading-background');
const theme = el.getAttribute('loading-theme');
const size = el.getAttribute('loading-size'); const size = el.getAttribute('loading-size');
const fullscreen = !!binding.modifiers.fullscreen; const fullscreen = !!binding.modifiers.fullscreen;
const instance = createLoading( const instance = createLoading(
{ {
tip, tip,
background, background,
theme,
size: size || 'large', size: size || 'large',
loading: !!binding.value, loading: !!binding.value,
absolute: !fullscreen, absolute: !fullscreen,
......
...@@ -8,17 +8,9 @@ export enum ContentEnum { ...@@ -8,17 +8,9 @@ export enum ContentEnum {
FIXED = 'fixed', FIXED = 'fixed',
} }
// app current theme
export enum ThemeModeEnum {
LIGHT = 'light-mode',
DARK = 'dark-mode',
SEMI_DARK = 'semi-dark-mode',
}
// menu theme enum // menu theme enum
export enum ThemeEnum { export enum ThemeEnum {
DARK = 'dark', DARK = 'dark',
LIGHT = 'light', LIGHT = 'light',
} }
......
...@@ -15,6 +15,8 @@ export const PROJ_CFG_KEY = 'PROJ__CFG__KEY__'; ...@@ -15,6 +15,8 @@ export const PROJ_CFG_KEY = 'PROJ__CFG__KEY__';
// lock info // lock info
export const LOCK_INFO_KEY = 'LOCK__INFO__KEY__'; export const LOCK_INFO_KEY = 'LOCK__INFO__KEY__';
export const APP_DARK_MODE_KEY_ = '__APP__DARK__MODE__';
// base global local key // base global local key
export const APP_LOCAL_CACHE_KEY = 'COMMON__LOCAL__KEY__'; export const APP_LOCAL_CACHE_KEY = 'COMMON__LOCAL__KEY__';
......
...@@ -4,6 +4,7 @@ import { computed, unref } from 'vue'; ...@@ -4,6 +4,7 @@ import { computed, unref } from 'vue';
import { appStore } from '/@/store/modules/app'; import { appStore } from '/@/store/modules/app';
import { ContentEnum } from '/@/enums/appEnum'; import { ContentEnum } from '/@/enums/appEnum';
import { ThemeEnum } from '../../enums/appEnum';
type RootSetting = Omit< type RootSetting = Omit<
ProjectConfig, ProjectConfig,
...@@ -48,6 +49,10 @@ const getGrayMode = computed(() => unref(getRootSetting).grayMode); ...@@ -48,6 +49,10 @@ const getGrayMode = computed(() => unref(getRootSetting).grayMode);
const getLockTime = computed(() => unref(getRootSetting).lockTime); const getLockTime = computed(() => unref(getRootSetting).lockTime);
const getShowDarkModeToggle = computed(() => unref(getRootSetting).showDarkModeToggle);
const getDarkMode = computed(() => appStore.getDarkMode);
const getLayoutContentMode = computed(() => const getLayoutContentMode = computed(() =>
unref(getRootSetting).contentMode === ContentEnum.FULL ? ContentEnum.FULL : ContentEnum.FIXED unref(getRootSetting).contentMode === ContentEnum.FULL ? ContentEnum.FULL : ContentEnum.FIXED
); );
...@@ -56,6 +61,10 @@ function setRootSetting(setting: Partial<RootSetting>) { ...@@ -56,6 +61,10 @@ function setRootSetting(setting: Partial<RootSetting>) {
appStore.commitProjectConfigState(setting); appStore.commitProjectConfigState(setting);
} }
function setDarkMode(mode: ThemeEnum) {
appStore.commitDarkMode(mode);
}
export function useRootSetting() { export function useRootSetting() {
return { return {
setRootSetting, setRootSetting,
...@@ -80,5 +89,8 @@ export function useRootSetting() { ...@@ -80,5 +89,8 @@ export function useRootSetting() {
getContentMode, getContentMode,
getLockTime, getLockTime,
getThemeColor, getThemeColor,
getDarkMode,
setDarkMode,
getShowDarkModeToggle,
}; };
} }
import { useTimeoutFn } from '/@/hooks/core/useTimeout';
import { unref, Ref, nextTick } from 'vue';
import { tryOnUnmounted } from '@vueuse/core';
interface CallBackFn {
(instance: Nullable<ApexCharts>): void;
}
export function useApexCharts(elRef: Ref<HTMLDivElement>) {
let chartInstance: Nullable<ApexCharts> = null;
function setOptions(options: any, callback?: CallBackFn) {
nextTick(() => {
useTimeoutFn(async () => {
const el = unref(elRef);
if (!el || !unref(el)) return;
const ApexCharts = await (await import('apexcharts')).default;
chartInstance = new ApexCharts(el, options);
chartInstance && chartInstance.render();
// The callback method is added to setOptions to return the chartInstance to facilitate the re-operation of the chart, such as calling the updateOptions method to update the chart
callback && callback(chartInstance);
}, 30);
});
}
// Call the updateOptions method of ApexCharts to update the chart
function updateOptions(
chartInstance: Nullable<ApexCharts>,
options: any,
redraw = false,
animate = true,
updateSyncedCharts = true,
callback: CallBackFn
) {
nextTick(() => {
useTimeoutFn(() => {
chartInstance && chartInstance.updateOptions(options, redraw, animate, updateSyncedCharts);
callback && callback(chartInstance);
}, 30);
});
}
tryOnUnmounted(() => {
if (!chartInstance) return;
chartInstance?.destroy?.();
chartInstance = null;
});
return {
setOptions,
updateOptions,
};
}
import { useTimeoutFn } from '/@/hooks/core/useTimeout'; import { useTimeoutFn } from '/@/hooks/core/useTimeout';
import { tryOnUnmounted } from '@vueuse/core'; import { tryOnUnmounted } from '@vueuse/core';
import { unref, Ref, nextTick } from 'vue'; import { unref, Ref, nextTick, watch, computed, ref } from 'vue';
import type { EChartsOption } from 'echarts'; import type { EChartsOption } from 'echarts';
import { useDebounce } from '/@/hooks/core/useDebounce'; import { useDebounce } from '/@/hooks/core/useDebounce';
import { useEventListener } from '/@/hooks/event/useEventListener'; import { useEventListener } from '/@/hooks/event/useEventListener';
import { useBreakpoint } from '/@/hooks/event/useBreakpoint'; import { useBreakpoint } from '/@/hooks/event/useBreakpoint';
import echarts from '/@/plugins/echarts'; import echarts from '/@/plugins/echarts';
import { useRootSetting } from '../setting/useRootSetting';
export function useECharts( export function useECharts(
elRef: Ref<HTMLDivElement>, elRef: Ref<HTMLDivElement>,
theme: 'light' | 'dark' | 'default' = 'light' theme: 'light' | 'dark' | 'default' = 'light'
) { ) {
const { getDarkMode } = useRootSetting();
let chartInstance: echarts.ECharts | null = null; let chartInstance: echarts.ECharts | null = null;
let resizeFn: Fn = resize; let resizeFn: Fn = resize;
const cacheOptions = ref<EChartsOption>({});
let removeResizeFn: Fn = () => {}; let removeResizeFn: Fn = () => {};
const [debounceResize] = useDebounce(resize, 200); const [debounceResize] = useDebounce(resize, 200);
resizeFn = debounceResize; resizeFn = debounceResize;
function initCharts() { const getOptions = computed(
(): EChartsOption => {
if (getDarkMode.value !== 'dark') {
return cacheOptions.value;
}
return {
backgroundColor: '#151515',
...cacheOptions.value,
};
}
);
function initCharts(t = theme) {
const el = unref(elRef); const el = unref(elRef);
if (!el || !unref(el)) { if (!el || !unref(el)) {
return; return;
} }
chartInstance = echarts.init(el, theme); chartInstance = echarts.init(el, t);
const { removeEvent } = useEventListener({ const { removeEvent } = useEventListener({
el: window, el: window,
name: 'resize', name: 'resize',
...@@ -41,22 +56,23 @@ export function useECharts( ...@@ -41,22 +56,23 @@ export function useECharts(
} }
function setOptions(options: EChartsOption, clear = true) { function setOptions(options: EChartsOption, clear = true) {
cacheOptions.value = options;
if (unref(elRef)?.offsetHeight === 0) { if (unref(elRef)?.offsetHeight === 0) {
useTimeoutFn(() => { useTimeoutFn(() => {
setOptions(options); setOptions(unref(getOptions));
}, 30); }, 30);
return; return;
} }
nextTick(() => { nextTick(() => {
useTimeoutFn(() => { useTimeoutFn(() => {
if (!chartInstance) { if (!chartInstance) {
initCharts(); initCharts(getDarkMode.value);
if (!chartInstance) return; if (!chartInstance) return;
} }
clear && chartInstance?.clear(); clear && chartInstance?.clear();
chartInstance?.setOption(options); chartInstance?.setOption(unref(getOptions));
}, 30); }, 30);
}); });
} }
...@@ -65,6 +81,17 @@ export function useECharts( ...@@ -65,6 +81,17 @@ export function useECharts(
chartInstance?.resize(); chartInstance?.resize();
} }
watch(
() => getDarkMode.value,
(theme) => {
if (chartInstance) {
chartInstance.dispose();
initCharts(theme);
setOptions(cacheOptions.value);
}
}
);
tryOnUnmounted(() => { tryOnUnmounted(() => {
if (!chartInstance) return; if (!chartInstance) return;
removeResizeFn(); removeResizeFn();
......
...@@ -112,7 +112,6 @@ ...@@ -112,7 +112,6 @@
@prefix-cls: ~'@{namespace}-layout-multiple-header'; @prefix-cls: ~'@{namespace}-layout-multiple-header';
.@{prefix-cls} { .@{prefix-cls} {
// margin-left: 1px;
transition: width 0.2s; transition: width 0.2s;
flex: 0 0 auto; flex: 0 0 auto;
......
...@@ -91,7 +91,6 @@ ...@@ -91,7 +91,6 @@
position: relative; position: relative;
height: 240px; height: 240px;
padding: 130px 30px 60px 30px; padding: 130px 30px 60px 30px;
background: #fff;
border-radius: 10px; border-radius: 10px;
} }
......
...@@ -131,10 +131,6 @@ ...@@ -131,10 +131,6 @@
cursor: pointer; cursor: pointer;
align-items: center; align-items: center;
&:hover {
background: @header-light-bg-hover-color;
}
img { img {
width: 24px; width: 24px;
height: 24px; height: 24px;
......
...@@ -131,7 +131,7 @@ ...@@ -131,7 +131,7 @@
} }
&--light { &--light {
background: @white; background: @white !important;
border-bottom: 1px solid @header-light-bottom-border-color; border-bottom: 1px solid @header-light-bottom-border-color;
border-left: 1px solid @header-light-bottom-border-color; border-left: 1px solid @header-light-bottom-border-color;
...@@ -165,8 +165,9 @@ ...@@ -165,8 +165,9 @@
} }
&--dark { &--dark {
background: @header-dark-bg-color; background: @header-dark-bg-color !important;
border-bottom: 1px solid @border-color-base;
border-left: 1px solid @border-color-base;
.@{header-prefix-cls}-logo { .@{header-prefix-cls}-logo {
&:hover { &:hover {
background: @header-dark-bg-hover-color; background: @header-dark-bg-hover-color;
......
...@@ -3,13 +3,15 @@ import { BasicDrawer } from '/@/components/Drawer/index'; ...@@ -3,13 +3,15 @@ import { BasicDrawer } from '/@/components/Drawer/index';
import { Divider } from 'ant-design-vue'; import { Divider } from 'ant-design-vue';
import { import {
TypePicker, TypePicker,
ThemePicker, ThemeColorPicker,
SettingFooter, SettingFooter,
SwitchItem, SwitchItem,
SelectItem, SelectItem,
InputNumberItem, InputNumberItem,
} from './components'; } from './components';
import { AppDarkModeToggle } from '/@/components/Application';
import { MenuTypeEnum, TriggerEnum } from '/@/enums/menuEnum'; import { MenuTypeEnum, TriggerEnum } from '/@/enums/menuEnum';
import { useRootSetting } from '/@/hooks/setting/useRootSetting'; import { useRootSetting } from '/@/hooks/setting/useRootSetting';
...@@ -52,6 +54,7 @@ export default defineComponent({ ...@@ -52,6 +54,7 @@ export default defineComponent({
getColorWeak, getColorWeak,
getGrayMode, getGrayMode,
getLockTime, getLockTime,
getShowDarkModeToggle,
getThemeColor, getThemeColor,
} = useRootSetting(); } = useRootSetting();
...@@ -116,7 +119,7 @@ export default defineComponent({ ...@@ -116,7 +119,7 @@ export default defineComponent({
function renderHeaderTheme() { function renderHeaderTheme() {
return ( return (
<ThemePicker <ThemeColorPicker
colorList={HEADER_PRESET_BG_COLOR_LIST} colorList={HEADER_PRESET_BG_COLOR_LIST}
def={unref(getHeaderBgColor)} def={unref(getHeaderBgColor)}
event={HandlerEnum.HEADER_THEME} event={HandlerEnum.HEADER_THEME}
...@@ -126,7 +129,7 @@ export default defineComponent({ ...@@ -126,7 +129,7 @@ export default defineComponent({
function renderSiderTheme() { function renderSiderTheme() {
return ( return (
<ThemePicker <ThemeColorPicker
colorList={SIDE_BAR_BG_COLOR_LIST} colorList={SIDE_BAR_BG_COLOR_LIST}
def={unref(getMenuBgColor)} def={unref(getMenuBgColor)}
event={HandlerEnum.MENU_THEME} event={HandlerEnum.MENU_THEME}
...@@ -136,7 +139,7 @@ export default defineComponent({ ...@@ -136,7 +139,7 @@ export default defineComponent({
function renderMainTheme() { function renderMainTheme() {
return ( return (
<ThemePicker <ThemeColorPicker
colorList={APP_PRESET_COLOR_LIST} colorList={APP_PRESET_COLOR_LIST}
def={unref(getThemeColor)} def={unref(getThemeColor)}
event={HandlerEnum.CHANGE_THEME_COLOR} event={HandlerEnum.CHANGE_THEME_COLOR}
...@@ -404,6 +407,8 @@ export default defineComponent({ ...@@ -404,6 +407,8 @@ export default defineComponent({
width={330} width={330}
wrapClassName="setting-drawer" wrapClassName="setting-drawer"
> >
{unref(getShowDarkModeToggle) && <Divider>{() => t('layout.setting.darkMode')}</Divider>}
{unref(getShowDarkModeToggle) && <AppDarkModeToggle class="mx-auto" size="large" />}
<Divider>{() => t('layout.setting.navMode')}</Divider> <Divider>{() => t('layout.setting.navMode')}</Divider>
{renderSidebar()} {renderSidebar()}
<Divider>{() => t('layout.setting.sysTheme')}</Divider> <Divider>{() => t('layout.setting.sysTheme')}</Divider>
......
...@@ -26,7 +26,7 @@ ...@@ -26,7 +26,7 @@
import { HandlerEnum } from '../enum'; import { HandlerEnum } from '../enum';
export default defineComponent({ export default defineComponent({
name: 'ThemePicker', name: 'ThemeColorPicker',
components: { CheckOutlined }, components: { CheckOutlined },
props: { props: {
colorList: { colorList: {
......
...@@ -74,7 +74,8 @@ ...@@ -74,7 +74,8 @@
content: ''; content: '';
} }
&--sidebar { &--sidebar,
&--light {
&::before { &::before {
top: 0; top: 0;
left: 0; left: 0;
...@@ -124,6 +125,10 @@ ...@@ -124,6 +125,10 @@
} }
} }
&--dark {
background-color: #273352;
}
&--mix-sidebar { &--mix-sidebar {
&::before { &::before {
top: 0; top: 0;
...@@ -152,17 +157,6 @@ ...@@ -152,17 +157,6 @@
} }
} }
// &::after {
// position: absolute;
// top: 50%;
// left: 50%;
// width: 0;
// height: 0;
// content: '';
// opacity: 0;
// transition: all 0.3s;
// }
&:hover, &:hover,
&--active { &--active {
padding: 12px; padding: 12px;
......
import { createAsyncComponent } from '/@/utils/factory/createAsyncComponent'; import { createAsyncComponent } from '/@/utils/factory/createAsyncComponent';
export const TypePicker = createAsyncComponent(() => import('./TypePicker.vue')); export const TypePicker = createAsyncComponent(() => import('./TypePicker.vue'));
export const ThemePicker = createAsyncComponent(() => import('./ThemePicker.vue')); export const ThemeColorPicker = createAsyncComponent(() => import('./ThemeColorPicker.vue'));
export const SettingFooter = createAsyncComponent(() => import('./SettingFooter.vue')); export const SettingFooter = createAsyncComponent(() => import('./SettingFooter.vue'));
export const SwitchItem = createAsyncComponent(() => import('./SwitchItem.vue')); export const SwitchItem = createAsyncComponent(() => import('./SwitchItem.vue'));
export const SelectItem = createAsyncComponent(() => import('./SelectItem.vue')); export const SelectItem = createAsyncComponent(() => import('./SelectItem.vue'));
......
...@@ -14,6 +14,7 @@ const { t } = useI18n(); ...@@ -14,6 +14,7 @@ const { t } = useI18n();
export enum HandlerEnum { export enum HandlerEnum {
CHANGE_LAYOUT, CHANGE_LAYOUT,
CHANGE_THEME_COLOR, CHANGE_THEME_COLOR,
CHANGE_THEME,
// menu // menu
MENU_HAS_DRAG, MENU_HAS_DRAG,
MENU_ACCORDION, MENU_ACCORDION,
......
...@@ -6,15 +6,20 @@ import { updateGrayMode } from '/@/logics/theme/updateGrayMode'; ...@@ -6,15 +6,20 @@ import { updateGrayMode } from '/@/logics/theme/updateGrayMode';
import { appStore } from '/@/store/modules/app'; import { appStore } from '/@/store/modules/app';
import { ProjectConfig } from '/#/config'; import { ProjectConfig } from '/#/config';
import { changeTheme } from '/@/logics/theme'; import { changeTheme } from '/@/logics/theme';
import { updateDarkTheme } from '/@/logics/theme/dark';
import { useRootSetting } from '/@/hooks/setting/useRootSetting'; import { useRootSetting } from '/@/hooks/setting/useRootSetting';
export function baseHandler(event: HandlerEnum, value: any) { export function baseHandler(event: HandlerEnum, value: any) {
const config = handler(event, value); const config = handler(event, value);
appStore.commitProjectConfigState(config); appStore.commitProjectConfigState(config);
if (event === HandlerEnum.CHANGE_THEME) {
updateHeaderBgColor();
updateSidebarBgColor();
}
} }
export function handler(event: HandlerEnum, value: any): DeepPartial<ProjectConfig> { export function handler(event: HandlerEnum, value: any): DeepPartial<ProjectConfig> {
const { getThemeColor } = useRootSetting(); const { getThemeColor, getDarkMode } = useRootSetting();
switch (event) { switch (event) {
case HandlerEnum.CHANGE_LAYOUT: case HandlerEnum.CHANGE_LAYOUT:
const { mode, type, split } = value; const { mode, type, split } = value;
...@@ -36,8 +41,17 @@ export function handler(event: HandlerEnum, value: any): DeepPartial<ProjectConf ...@@ -36,8 +41,17 @@ export function handler(event: HandlerEnum, value: any): DeepPartial<ProjectConf
return {}; return {};
} }
changeTheme(value); changeTheme(value);
return { themeColor: value }; return { themeColor: value };
case HandlerEnum.CHANGE_THEME:
if (getDarkMode.value === value) {
return {};
}
updateDarkTheme(value);
return { darkMode: value };
case HandlerEnum.MENU_HAS_DRAG: case HandlerEnum.MENU_HAS_DRAG:
return { menuSetting: { canDrag: value } }; return { menuSetting: { canDrag: value } };
......
...@@ -403,7 +403,7 @@ ...@@ -403,7 +403,7 @@
} }
} }
} }
@border-color: @sider-dark-lighten-1-bg-color; @border-color: @sider-dark-lighten-bg-color;
&.dark { &.dark {
&.open { &.open {
......
@prefix-cls: ~'@{namespace}-multiple-tabs'; @prefix-cls: ~'@{namespace}-multiple-tabs';
html[data-theme='dark'] {
.@{prefix-cls} {
.ant-tabs-tab {
border-bottom: 1px solid @border-color-base;
}
}
}
.@{prefix-cls} { .@{prefix-cls} {
z-index: 10; z-index: 10;
height: @multiple-height + 2; height: @multiple-height + 2;
line-height: @multiple-height + 2; line-height: @multiple-height + 2;
background: @white; background: @component-background;
border-bottom: 1px solid @border-color-base;
box-shadow: 0 1px 2px 0 rgba(29, 35, 41, 0.05); box-shadow: 0 1px 2px 0 rgba(29, 35, 41, 0.05);
.ant-tabs-small { .ant-tabs-small {
...@@ -15,7 +24,7 @@ ...@@ -15,7 +24,7 @@
.ant-tabs-card-bar { .ant-tabs-card-bar {
height: @multiple-height; height: @multiple-height;
margin: 0; margin: 0;
background: @white; background: @component-background;
border: 0; border: 0;
box-shadow: none; box-shadow: none;
...@@ -28,35 +37,14 @@ ...@@ -28,35 +37,14 @@
height: calc(@multiple-height - 2px); height: calc(@multiple-height - 2px);
padding-right: 12px; padding-right: 12px;
line-height: calc(@multiple-height - 2px); line-height: calc(@multiple-height - 2px);
color: @text-color-call-out; color: @text-color-base;
background: @white; background: @component-background;
border-bottom: 1px solid @header-light-bottom-border-color;
transition: none; transition: none;
// &:not(.ant-tabs-tab-active)::before {
// position: absolute;
// top: -1px;
// left: 50%;
// width: 100%;
// height: 2px;
// background-color: @primary-color;
// content: '';
// opacity: 0;
// transform: translate(-50%, 0) scaleX(0);
// transform-origin: center;
// transition: none;
// }
&:hover { &:hover {
.ant-tabs-close-x { .ant-tabs-close-x {
opacity: 1; opacity: 1;
} }
// &:not(.ant-tabs-tab-active)::before {
// opacity: 1;
// transform: translate(-50%, 0) scaleX(1);
// transition: all 0.3s ease-in-out;
// }
} }
.ant-tabs-close-x { .ant-tabs-close-x {
...@@ -85,26 +73,20 @@ ...@@ -85,26 +73,20 @@
} }
} }
.ant-tabs-tab:not(.ant-tabs-tab-active) {
&:hover {
color: @primary-color;
}
}
.ant-tabs-tab-active { .ant-tabs-tab-active {
position: relative; position: relative;
padding-left: 26px; padding-left: 18px;
color: @white; color: @white;
background: fade(@primary-color, 100%); background: @primary-color;
border: 0; border: 0;
transition: none; transition: none;
&::before {
position: absolute;
top: calc(50% - 3px);
left: 8px;
width: 6px;
height: 6px;
background: #fff;
border-radius: 50%;
content: '';
transition: none;
}
.ant-tabs-close-x { .ant-tabs-close-x {
opacity: 1; opacity: 1;
} }
...@@ -158,10 +140,10 @@ ...@@ -158,10 +140,10 @@
width: 36px; width: 36px;
height: @multiple-height; height: @multiple-height;
line-height: @multiple-height; line-height: @multiple-height;
color: #666; color: @text-color-secondary;
text-align: center; text-align: center;
cursor: pointer; cursor: pointer;
border-left: 1px solid #eee; border-left: 1px solid @border-color-base;
&:hover { &:hover {
color: @text-color-base; color: @text-color-base;
......
...@@ -14,4 +14,7 @@ export default { ...@@ -14,4 +14,7 @@ export default {
redo: 'Refresh', redo: 'Refresh',
back: 'Back', back: 'Back',
light: 'Light',
dark: 'Dark',
}; };
...@@ -30,6 +30,7 @@ export default { ...@@ -30,6 +30,7 @@ export default {
drawerTitle: 'Configuration', drawerTitle: 'Configuration',
darkMode: 'Dark mode',
navMode: 'Navigation mode', navMode: 'Navigation mode',
interfaceFunction: 'Interface function', interfaceFunction: 'Interface function',
interfaceDisplay: 'Interface display', interfaceDisplay: 'Interface display',
......
...@@ -6,5 +6,4 @@ export default { ...@@ -6,5 +6,4 @@ export default {
map: 'Map', map: 'Map',
line: 'Line', line: 'Line',
pie: 'Pie', pie: 'Pie',
apexChart: 'ApexChart',
}; };
...@@ -14,4 +14,7 @@ export default { ...@@ -14,4 +14,7 @@ export default {
redo: '刷新', redo: '刷新',
back: '返回', back: '返回',
light: '亮色主题',
dark: '黑暗主题',
}; };
...@@ -29,6 +29,7 @@ export default { ...@@ -29,6 +29,7 @@ export default {
drawerTitle: '项目配置', drawerTitle: '项目配置',
darkMode: '主题',
navMode: '导航栏模式', navMode: '导航栏模式',
interfaceFunction: '界面功能', interfaceFunction: '界面功能',
interfaceDisplay: '界面显示', interfaceDisplay: '界面显示',
......
...@@ -6,5 +6,4 @@ export default { ...@@ -6,5 +6,4 @@ export default {
map: '地图', map: '地图',
line: '折线图', line: '折线图',
pie: '饼图', pie: '饼图',
apexChart: 'ApexChart',
}; };
...@@ -9,6 +9,7 @@ import projectSetting from '/@/settings/projectSetting'; ...@@ -9,6 +9,7 @@ import projectSetting from '/@/settings/projectSetting';
import { updateHeaderBgColor, updateSidebarBgColor } from '/@/logics/theme/updateBackground'; import { updateHeaderBgColor, updateSidebarBgColor } from '/@/logics/theme/updateBackground';
import { updateColorWeak } from '/@/logics/theme/updateColorWeak'; import { updateColorWeak } from '/@/logics/theme/updateColorWeak';
import { updateGrayMode } from '/@/logics/theme/updateGrayMode'; import { updateGrayMode } from '/@/logics/theme/updateGrayMode';
import { updateDarkTheme } from '/@/logics/theme/dark';
import { changeTheme } from '/@/logics/theme'; import { changeTheme } from '/@/logics/theme';
import { appStore } from '/@/store/modules/app'; import { appStore } from '/@/store/modules/app';
...@@ -19,30 +20,43 @@ import { getCommonStoragePrefix, getStorageShortName } from '/@/utils/env'; ...@@ -19,30 +20,43 @@ import { getCommonStoragePrefix, getStorageShortName } from '/@/utils/env';
import { primaryColor } from '../../build/config/themeConfig'; import { primaryColor } from '../../build/config/themeConfig';
import { Persistent } from '/@/utils/cache/persistent'; import { Persistent } from '/@/utils/cache/persistent';
import { deepMerge } from '/@/utils'; import { deepMerge } from '/@/utils';
import { ThemeEnum } from '../enums/appEnum';
// Initial project configuration // Initial project configuration
export function initAppConfigStore() { export function initAppConfigStore() {
let projCfg: ProjectConfig = Persistent.getLocal(PROJ_CFG_KEY) as ProjectConfig; let projCfg: ProjectConfig = Persistent.getLocal(PROJ_CFG_KEY) as ProjectConfig;
projCfg = deepMerge(projectSetting, projCfg || {}); projCfg = deepMerge(projectSetting, projCfg || {});
const darkMode = appStore.getDarkMode;
const {
colorWeak,
grayMode,
themeColor,
headerSetting: { bgColor: headerBgColor } = {},
menuSetting: { bgColor } = {},
} = projCfg;
try { try {
const {
colorWeak,
grayMode,
themeColor,
headerSetting: { bgColor: headerBgColor } = {},
menuSetting: { bgColor } = {},
} = projCfg;
if (themeColor && themeColor !== primaryColor) { if (themeColor && themeColor !== primaryColor) {
changeTheme(themeColor); changeTheme(themeColor);
} }
headerBgColor && updateHeaderBgColor(headerBgColor);
bgColor && updateSidebarBgColor(bgColor);
grayMode && updateGrayMode(grayMode); grayMode && updateGrayMode(grayMode);
colorWeak && updateColorWeak(colorWeak); colorWeak && updateColorWeak(colorWeak);
} catch (error) { } catch (error) {
console.log(error); console.log(error);
} }
appStore.commitProjectConfigState(projCfg); appStore.commitProjectConfigState(projCfg);
// init dark mode
updateDarkTheme(darkMode);
if (darkMode === ThemeEnum.DARK) {
updateHeaderBgColor();
updateSidebarBgColor();
} else {
headerBgColor && updateHeaderBgColor(headerBgColor);
bgColor && updateSidebarBgColor(bgColor);
}
// init store
localeStore.initLocale(); localeStore.initLocale();
setTimeout(() => { setTimeout(() => {
......
import { darkCssIsReady, loadDarkThemeCss } from 'vite-plugin-theme/es/client';
export async function updateDarkTheme(mode: string | null = 'light') {
const htmlRoot = document.getElementById('htmlRoot');
if (mode === 'dark') {
if (import.meta.env.PROD && !darkCssIsReady) {
await loadDarkThemeCss();
}
htmlRoot?.setAttribute('data-theme', 'dark');
} else {
htmlRoot?.setAttribute('data-theme', 'light');
}
}
import { getThemeColors, ThemeMode, generateColors } from '../../../build/config/themeConfig'; import { getThemeColors, generateColors } from '../../../build/config/themeConfig';
import { replaceStyleVariables } from 'vite-plugin-theme/es/client'; import { replaceStyleVariables } from 'vite-plugin-theme/es/client';
import { mixLighten, mixDarken, tinycolor } from 'vite-plugin-theme/es/colorUtils'; import { mixLighten, mixDarken, tinycolor } from 'vite-plugin-theme/es/colorUtils';
export async function changeTheme(color: string, theme?: ThemeMode) { export async function changeTheme(color: string) {
const colors = generateColors({ const colors = generateColors({
mixDarken, mixDarken,
mixLighten, mixLighten,
...@@ -12,6 +12,6 @@ export async function changeTheme(color: string, theme?: ThemeMode) { ...@@ -12,6 +12,6 @@ export async function changeTheme(color: string, theme?: ThemeMode) {
}); });
return await replaceStyleVariables({ return await replaceStyleVariables({
colorVariables: [...getThemeColors(color, theme), ...colors], colorVariables: [...getThemeColors(color), ...colors],
}); });
} }
import { isHexColor, colorIsDark, lighten, darken } from '/@/utils/color'; import { colorIsDark, lighten, darken } from '/@/utils/color';
import { appStore } from '/@/store/modules/app'; import { appStore } from '/@/store/modules/app';
import { ThemeEnum } from '/@/enums/appEnum'; import { ThemeEnum } from '/@/enums/appEnum';
import { setCssVar } from './util'; import { setCssVar } from './util';
...@@ -9,29 +9,35 @@ const HEADER_MENU_ACTIVE_BG_COLOR_VAR = '--header-active-menu-bg-color'; ...@@ -9,29 +9,35 @@ const HEADER_MENU_ACTIVE_BG_COLOR_VAR = '--header-active-menu-bg-color';
const SIDER_DARK_BG_COLOR = '--sider-dark-bg-color'; const SIDER_DARK_BG_COLOR = '--sider-dark-bg-color';
const SIDER_DARK_DARKEN_BG_COLOR = '--sider-dark-darken-bg-color'; const SIDER_DARK_DARKEN_BG_COLOR = '--sider-dark-darken-bg-color';
const SIDER_LIGHTEN_1_BG_COLOR = '--sider-dark-lighten-1-bg-color'; const SIDER_LIGHTEN_BG_COLOR = '--sider-dark-lighten-bg-color';
const SIDER_LIGHTEN_2_BG_COLOR = '--sider-dark-lighten-2-bg-color';
/** /**
* Change the background color of the top header * Change the background color of the top header
* @param color * @param color
*/ */
export function updateHeaderBgColor(color: string) { export function updateHeaderBgColor(color?: string) {
if (!isHexColor(color)) return; const darkMode = appStore.getDarkMode === ThemeEnum.DARK;
if (!color) {
if (darkMode) {
color = '#151515';
} else {
color = appStore.getProjectConfig.headerSetting.bgColor;
}
}
// bg color // bg color
setCssVar(HEADER_BG_COLOR_VAR, color); setCssVar(HEADER_BG_COLOR_VAR, color);
// hover color // hover color
const hoverColor = lighten(color, 6); const hoverColor = lighten(color!, 6);
setCssVar(HEADER_BG_HOVER_COLOR_VAR, hoverColor); setCssVar(HEADER_BG_HOVER_COLOR_VAR, hoverColor);
setCssVar(HEADER_MENU_ACTIVE_BG_COLOR_VAR, hoverColor); setCssVar(HEADER_MENU_ACTIVE_BG_COLOR_VAR, hoverColor);
// Determine the depth of the color value and automatically switch the theme // Determine the depth of the color value and automatically switch the theme
const isDark = colorIsDark(color); const isDark = colorIsDark(color!);
appStore.commitProjectConfigState({ appStore.commitProjectConfigState({
headerSetting: { headerSetting: {
theme: isDark ? ThemeEnum.DARK : ThemeEnum.LIGHT, theme: isDark || darkMode ? ThemeEnum.DARK : ThemeEnum.LIGHT,
}, },
}); });
} }
...@@ -40,21 +46,27 @@ export function updateHeaderBgColor(color: string) { ...@@ -40,21 +46,27 @@ export function updateHeaderBgColor(color: string) {
* Change the background color of the left menu * Change the background color of the left menu
* @param color bg color * @param color bg color
*/ */
export function updateSidebarBgColor(color: string) { export function updateSidebarBgColor(color?: string) {
if (!isHexColor(color)) return; // if (!isHexColor(color)) return;
const darkMode = appStore.getDarkMode === ThemeEnum.DARK;
if (!color) {
if (darkMode) {
color = '#212121';
} else {
color = appStore.getProjectConfig.menuSetting.bgColor;
}
}
setCssVar(SIDER_DARK_BG_COLOR, color); setCssVar(SIDER_DARK_BG_COLOR, color);
setCssVar(SIDER_DARK_DARKEN_BG_COLOR, darken(color, 6)); setCssVar(SIDER_DARK_DARKEN_BG_COLOR, darken(color!, 6));
setCssVar(SIDER_LIGHTEN_1_BG_COLOR, lighten(color, 5)); setCssVar(SIDER_LIGHTEN_BG_COLOR, lighten(color!, 5));
setCssVar(SIDER_LIGHTEN_2_BG_COLOR, lighten(color, 8));
// only #ffffff is light // only #ffffff is light
// Only when the background color is #fff, the theme of the menu will be changed to light // Only when the background color is #fff, the theme of the menu will be changed to light
const isLight = ['#fff', '#ffffff'].includes(color.toLowerCase()); const isLight = ['#fff', '#ffffff'].includes(color!.toLowerCase());
appStore.commitProjectConfigState({ appStore.commitProjectConfigState({
menuSetting: { menuSetting: {
theme: isLight ? ThemeEnum.LIGHT : ThemeEnum.DARK, theme: isLight && !darkMode ? ThemeEnum.LIGHT : ThemeEnum.DARK,
}, },
}); });
} }
...@@ -21,11 +21,6 @@ const menu: MenuModule = { ...@@ -21,11 +21,6 @@ const menu: MenuModule = {
path: 'googleMap', path: 'googleMap',
name: t('routes.demo.charts.googleMap'), name: t('routes.demo.charts.googleMap'),
}, },
{
path: 'apexChart',
name: t('routes.demo.charts.apexChart'),
},
{ {
path: 'echarts', path: 'echarts',
name: 'Echarts', name: 'Echarts',
......
...@@ -38,14 +38,6 @@ const charts: AppRouteModule = { ...@@ -38,14 +38,6 @@ const charts: AppRouteModule = {
component: () => import('/@/views/demo/charts/map/Google.vue'), component: () => import('/@/views/demo/charts/map/Google.vue'),
}, },
{
path: 'apexChart',
name: 'ApexChart',
meta: {
title: t('routes.demo.charts.apexChart'),
},
component: () => import('/@/views/demo/charts/apex/index.vue'),
},
{ {
path: 'echarts', path: 'echarts',
name: 'Echarts', name: 'Echarts',
......
import { ThemeEnum } from '../enums/appEnum';
export default { export default {
prefixCls: 'vben', prefixCls: 'vben',
}; };
export const darkMode = ThemeEnum.LIGHT;
// app theme preset color // app theme preset color
export const APP_PRESET_COLOR_LIST: string[] = [ export const APP_PRESET_COLOR_LIST: string[] = [
'#0960bd', '#0960bd',
...@@ -18,6 +21,7 @@ export const APP_PRESET_COLOR_LIST: string[] = [ ...@@ -18,6 +21,7 @@ export const APP_PRESET_COLOR_LIST: string[] = [
// header preset color // header preset color
export const HEADER_PRESET_BG_COLOR_LIST: string[] = [ export const HEADER_PRESET_BG_COLOR_LIST: string[] = [
'#ffffff', '#ffffff',
'#151515',
'#009688', '#009688',
'#5172DC', '#5172DC',
'#018ffb', '#018ffb',
...@@ -32,6 +36,7 @@ export const HEADER_PRESET_BG_COLOR_LIST: string[] = [ ...@@ -32,6 +36,7 @@ export const HEADER_PRESET_BG_COLOR_LIST: string[] = [
// sider preset color // sider preset color
export const SIDE_BAR_BG_COLOR_LIST: string[] = [ export const SIDE_BAR_BG_COLOR_LIST: string[] = [
'#001529', '#001529',
'#212121',
'#273352', '#273352',
'#ffffff', '#ffffff',
'#191b24', '#191b24',
......
...@@ -9,13 +9,16 @@ import { ...@@ -9,13 +9,16 @@ import {
SettingButtonPositionEnum, SettingButtonPositionEnum,
} from '/@/enums/appEnum'; } from '/@/enums/appEnum';
import { SIDE_BAR_BG_COLOR_LIST, HEADER_PRESET_BG_COLOR_LIST } from './designSetting'; import { SIDE_BAR_BG_COLOR_LIST, HEADER_PRESET_BG_COLOR_LIST } from './designSetting';
import { primaryColor, themeMode } from '../../build/config/themeConfig'; import { primaryColor } from '../../build/config/themeConfig';
// ! You need to clear the browser cache after the change // ! You need to clear the browser cache after the change
const setting: ProjectConfig = { const setting: ProjectConfig = {
// Whether to show the configuration button // Whether to show the configuration button
showSettingButton: true, showSettingButton: true,
// Whether to show the theme switch button
showDarkModeToggle: true,
// `Settings` button position // `Settings` button position
settingButtonPosition: SettingButtonPositionEnum.AUTO, settingButtonPosition: SettingButtonPositionEnum.AUTO,
...@@ -28,9 +31,6 @@ const setting: ProjectConfig = { ...@@ -28,9 +31,6 @@ const setting: ProjectConfig = {
// color // color
themeColor: primaryColor, themeColor: primaryColor,
// TODO dark theme
themeMode: themeMode,
// Website gray mode, open for possible mourning dates // Website gray mode, open for possible mourning dates
grayMode: false, grayMode: false,
......
...@@ -4,13 +4,16 @@ import type { BeforeMiniState } from '../types'; ...@@ -4,13 +4,16 @@ import type { BeforeMiniState } from '../types';
import { VuexModule, getModule, Module, Mutation, Action } from 'vuex-module-decorators'; import { VuexModule, getModule, Module, Mutation, Action } from 'vuex-module-decorators';
import store from '/@/store'; import store from '/@/store';
import { PROJ_CFG_KEY } from '/@/enums/cacheEnum'; import { PROJ_CFG_KEY, APP_DARK_MODE_KEY_ } from '/@/enums/cacheEnum';
import { hotModuleUnregisterModule } from '/@/utils/helper/vuexHelper'; import { hotModuleUnregisterModule } from '/@/utils/helper/vuexHelper';
import { Persistent } from '/@/utils/cache/persistent'; import { Persistent } from '/@/utils/cache/persistent';
import { deepMerge } from '/@/utils'; import { deepMerge } from '/@/utils';
import { resetRouter } from '/@/router'; import { resetRouter } from '/@/router';
import { ThemeEnum } from '../../enums/appEnum';
import { darkMode } from '/@/settings/designSetting';
export interface LockInfo { export interface LockInfo {
pwd: string | undefined; pwd: string | undefined;
...@@ -22,6 +25,8 @@ const NAME = 'app'; ...@@ -22,6 +25,8 @@ const NAME = 'app';
hotModuleUnregisterModule(NAME); hotModuleUnregisterModule(NAME);
@Module({ dynamic: true, namespaced: true, store, name: NAME }) @Module({ dynamic: true, namespaced: true, store, name: NAME })
export default class App extends VuexModule { export default class App extends VuexModule {
private darkMode;
// Page loading status // Page loading status
private pageLoadingState = false; private pageLoadingState = false;
...@@ -38,6 +43,10 @@ export default class App extends VuexModule { ...@@ -38,6 +43,10 @@ export default class App extends VuexModule {
return this.pageLoadingState; return this.pageLoadingState;
} }
get getDarkMode() {
return this.darkMode || localStorage.getItem(APP_DARK_MODE_KEY_) || darkMode;
}
get getBeforeMiniState() { get getBeforeMiniState() {
return this.beforeMiniState; return this.beforeMiniState;
} }
...@@ -55,6 +64,12 @@ export default class App extends VuexModule { ...@@ -55,6 +64,12 @@ export default class App extends VuexModule {
this.pageLoadingState = loading; this.pageLoadingState = loading;
} }
@Mutation
commitDarkMode(mode: ThemeEnum): void {
this.darkMode = mode;
localStorage.setItem(APP_DARK_MODE_KEY_, mode);
}
@Mutation @Mutation
commitBeforeMiniState(state: BeforeMiniState): void { commitBeforeMiniState(state: BeforeMiniState): void {
this.beforeMiniState = state; this.beforeMiniState = state;
......
...@@ -32,7 +32,6 @@ ...@@ -32,7 +32,6 @@
return; return;
} }
setOptions({ setOptions({
backgroundColor: '#fff',
legend: { legend: {
bottom: 0, bottom: 0,
data: ['访问', '购买'], data: ['访问', '购买'],
......
...@@ -32,7 +32,6 @@ ...@@ -32,7 +32,6 @@
return; return;
} }
setOptions({ setOptions({
backgroundColor: '#fff',
legend: { legend: {
bottom: 0, bottom: 0,
data: ['Visits', 'Sales'], data: ['Visits', 'Sales'],
......
...@@ -32,7 +32,6 @@ ...@@ -32,7 +32,6 @@
return; return;
} }
setOptions({ setOptions({
backgroundColor: '#fff',
legend: { legend: {
bottom: 0, bottom: 0,
data: ['Visits', 'Sales'], data: ['Visits', 'Sales'],
......
<template>
<div ref="chartRef" :style="{ width: '100%' }"></div>
</template>
<script lang="ts">
import { defineComponent, ref, Ref, onMounted } from 'vue';
import { useApexCharts } from '/@/hooks/web/useApexCharts';
export default defineComponent({
setup() {
const chartRef = ref<HTMLDivElement | null>(null);
const { setOptions } = useApexCharts(chartRef as Ref<HTMLDivElement>);
onMounted(() => {
setOptions({
series: [
{
name: 'series1',
data: [31, 40, 28, 51, 42, 109, 100],
},
{
name: 'series2',
data: [11, 32, 45, 32, 34, 52, 41],
},
],
chart: {
height: 350,
type: 'area',
},
dataLabels: {
enabled: false,
},
stroke: {
curve: 'smooth',
},
xaxis: {
type: 'datetime',
categories: [
'2018-09-19T00:00:00.000Z',
'2018-09-19T01:30:00.000Z',
'2018-09-19T02:30:00.000Z',
'2018-09-19T03:30:00.000Z',
'2018-09-19T04:30:00.000Z',
'2018-09-19T05:30:00.000Z',
'2018-09-19T06:30:00.000Z',
],
},
tooltip: {
x: {
format: 'dd/MM/yy HH:mm',
},
},
});
});
return { chartRef };
},
});
</script>
<template>
<div ref="chartRef" :style="{ width: '100%' }"></div>
</template>
<script lang="ts">
import { defineComponent, ref, Ref, onMounted } from 'vue';
import { useApexCharts } from '/@/hooks/web/useApexCharts';
export default defineComponent({
setup() {
const chartRef = ref<HTMLDivElement | null>(null);
const { setOptions } = useApexCharts(chartRef as Ref<HTMLDivElement>);
onMounted(() => {
setOptions({
series: [
{
data: [400, 430, 448, 470, 540, 580, 690, 1100, 1200, 1380],
},
],
chart: {
type: 'bar',
height: 350,
},
plotOptions: {
bar: {
horizontal: true,
},
},
dataLabels: {
enabled: false,
},
xaxis: {
categories: [
'South Korea',
'Canada',
'United Kingdom',
'Netherlands',
'Italy',
'France',
'Japan',
'United States',
'China',
'Germany',
],
},
});
});
return { chartRef };
},
});
</script>
<template>
<div ref="chartRef" :style="{ width: '100%' }"></div>
</template>
<script lang="ts">
import { defineComponent, ref, Ref, onMounted } from 'vue';
import { useApexCharts } from '/@/hooks/web/useApexCharts';
export default defineComponent({
setup() {
const chartRef = ref<HTMLDivElement | null>(null);
const { setOptions } = useApexCharts(chartRef as Ref<HTMLDivElement>);
onMounted(() => {
setOptions({
series: [
{
name: 'Desktops',
data: [10, 41, 35, 51, 49, 62, 69, 91, 148],
},
],
chart: {
height: 350,
type: 'line',
zoom: {
enabled: false,
},
},
dataLabels: {
enabled: false,
},
stroke: {
curve: 'straight',
},
title: {
text: 'Product Trends by Month',
align: 'left',
},
grid: {
row: {
colors: ['#f3f3f3', 'transparent'], // takes an array which will be repeated on columns
opacity: 0.5,
},
},
xaxis: {
categories: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep'],
},
});
});
return { chartRef };
},
});
</script>
<template>
<div ref="chartRef" :style="{ width: '100%' }"></div>
</template>
<script lang="ts">
import { defineComponent, ref, Ref, onMounted } from 'vue';
import { useApexCharts } from '/@/hooks/web/useApexCharts';
export default defineComponent({
setup() {
const chartRef = ref<HTMLDivElement | null>(null);
const { setOptions } = useApexCharts(chartRef as Ref<HTMLDivElement>);
onMounted(() => {
setOptions({
series: [
{
name: 'Income',
type: 'column',
data: [1.4, 2, 2.5, 1.5, 2.5, 2.8, 3.8, 4.6],
},
{
name: 'Cashflow',
type: 'column',
data: [1.1, 3, 3.1, 4, 4.1, 4.9, 6.5, 8.5],
},
{
name: 'Revenue',
type: 'line',
data: [20, 29, 37, 36, 44, 45, 50, 58],
},
],
chart: {
height: 350,
type: 'line',
stacked: false,
},
dataLabels: {
enabled: false,
},
stroke: {
width: [1, 1, 4],
},
title: {
text: 'XYZ - Stock Analysis (2009 - 2016)',
align: 'left',
offsetX: 110,
},
xaxis: {
categories: [2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016],
},
yaxis: [
{
axisTicks: {
show: true,
},
axisBorder: {
show: true,
color: '#008FFB',
},
labels: {
style: {
colors: '#008FFB',
},
},
title: {
text: 'Income (thousand crores)',
style: {
color: '#008FFB',
},
},
tooltip: {
enabled: true,
},
},
{
seriesName: 'Income',
opposite: true,
axisTicks: {
show: true,
},
axisBorder: {
show: true,
color: '#00E396',
},
labels: {
style: {
colors: '#00E396',
},
},
title: {
text: 'Operating Cashflow (thousand crores)',
style: {
color: '#00E396',
},
},
},
{
seriesName: 'Revenue',
opposite: true,
axisTicks: {
show: true,
},
axisBorder: {
show: true,
color: '#FEB019',
},
labels: {
style: {
colors: '#FEB019',
},
},
title: {
text: 'Revenue (thousand crores)',
style: {
color: '#FEB019',
},
},
},
],
tooltip: {
fixed: {
enabled: true,
position: 'topLeft', // topRight, topLeft, bottomRight, bottomLeft
offsetY: 30,
offsetX: 60,
},
},
legend: {
horizontalAlign: 'left',
offsetX: 40,
},
});
});
return { chartRef };
},
});
</script>
<template>
<div ref="chartRef" :style="{ width: '100%' }"></div>
</template>
<script lang="ts">
import { defineComponent, Ref, ref, onMounted } from 'vue';
import { useApexCharts } from '/@/hooks/web/useApexCharts';
export default defineComponent({
setup() {
const chartRef = ref<HTMLDivElement | null>(null);
const { setOptions } = useApexCharts(chartRef as Ref<HTMLDivElement>);
onMounted(() => {
setOptions({
series: [
{ name: 'Visits', data: [90, 50, 86, 40, 100, 20] },
{ name: 'Sales', data: [70, 75, 70, 76, 20, 85] },
],
chart: {
height: 350,
type: 'radar',
toolbar: {
show: false,
},
},
yaxis: {
show: false,
},
title: {
show: false,
},
markers: {
// size: 0,
},
xaxis: {
categories: ['2016', '2017', '2018', '2019', '2020', '2021'],
},
stroke: {
width: 0,
},
colors: ['#9f8ed7', '#1edec5'],
fill: {
type: 'gradient',
gradient: {
shade: 'dark',
gradientToColors: ['#8e9ad6', '#1fcadb'],
shadeIntensity: 1,
type: 'horizontal',
opacityFrom: 1,
opacityTo: 1,
stops: [0, 100, 100, 100],
},
},
});
});
return { chartRef };
},
});
</script>
<template>
<div class="apex-demo p-4">
<div class="demo-box">
<Line />
</div>
<div class="demo-box">
<Bar />
</div>
<div class="demo-box">
<Area />
</div>
<div class="demo-box">
<Mixed />
</div>
<div class="demo-box">
<SaleRadar />
</div>
</div>
</template>
<script>
import { defineComponent } from 'vue';
import Line from './Line.vue';
import Bar from './Bar.vue';
import Area from './Area.vue';
import Mixed from './Mixed.vue';
import SaleRadar from './SaleRadar.vue';
export default defineComponent({
components: { Line, Bar, Area, Mixed, SaleRadar },
setup() {},
});
</script>
<style lang="less" scoped>
.apex-demo {
display: flex;
flex-wrap: wrap;
justify-content: space-between;
.demo-box {
width: 49%;
margin-bottom: 20px;
background: #fff;
border-radius: 10px;
}
}
</style>
...@@ -29,7 +29,7 @@ ...@@ -29,7 +29,7 @@
height: 2000px; height: 2000px;
margin: 20px auto; margin: 20px auto;
text-align: center; text-align: center;
background: #fff; background: @component-background;
justify-content: center; justify-content: center;
flex-direction: column; flex-direction: column;
align-items: center; align-items: center;
......
...@@ -33,7 +33,7 @@ ...@@ -33,7 +33,7 @@
height: 2000px; height: 2000px;
margin: 20px auto; margin: 20px auto;
text-align: center; text-align: center;
background: #fff; background: @component-background;
justify-content: center; justify-content: center;
flex-direction: column; flex-direction: column;
align-items: center; align-items: center;
......
...@@ -54,6 +54,6 @@ ...@@ -54,6 +54,6 @@
.scroll-wrap { .scroll-wrap {
width: 50%; width: 50%;
height: 300px; height: 300px;
background: #fff; background: @component-background;
} }
</style> </style>
...@@ -50,7 +50,7 @@ ...@@ -50,7 +50,7 @@
&-wrap { &-wrap {
display: flex; display: flex;
margin: 0 30%; margin: 0 30%;
background: #fff; background: @component-background;
justify-content: center; justify-content: center;
} }
...@@ -58,7 +58,7 @@ ...@@ -58,7 +58,7 @@
height: 40px; height: 40px;
padding: 0 20px; padding: 0 20px;
line-height: 40px; line-height: 40px;
border-bottom: 1px solid #ddd; border-bottom: 1px solid @border-color-base;
} }
} }
</style> </style>
...@@ -26,6 +26,6 @@ ...@@ -26,6 +26,6 @@
.scroll-wrap { .scroll-wrap {
width: 50%; width: 50%;
height: 300px; height: 300px;
background: #fff; background: @component-background;
} }
</style> </style>
...@@ -26,7 +26,7 @@ ...@@ -26,7 +26,7 @@
<style lang="less" scoped> <style lang="less" scoped>
.demo-wrap { .demo-wrap {
width: 50%; width: 50%;
background: #fff; background: @component-background;
border-radius: 10px; border-radius: 10px;
} }
</style> </style>
...@@ -3,17 +3,18 @@ ...@@ -3,17 +3,18 @@
Current Param : {{ params }} Current Param : {{ params }}
<br /> <br />
Keep Alive Keep Alive
<input /> <Input />
</PageWrapper> </PageWrapper>
</template> </template>
<script lang="ts"> <script lang="ts">
import { computed, defineComponent, unref } from 'vue'; import { computed, defineComponent, unref } from 'vue';
import { useRouter } from 'vue-router'; import { useRouter } from 'vue-router';
import { PageWrapper } from '/@/components/Page'; import { PageWrapper } from '/@/components/Page';
import { Input } from 'ant-design-vue';
export default defineComponent({ export default defineComponent({
name: 'TestTab', name: 'TestTab',
components: { PageWrapper }, components: { PageWrapper, Input },
setup() { setup() {
const { currentRoute } = useRouter(); const { currentRoute } = useRouter();
return { return {
......
...@@ -2,10 +2,11 @@ ...@@ -2,10 +2,11 @@
<div class="p-5"> <div class="p-5">
多层级缓存-页面1-1-1 多层级缓存-页面1-1-1
<br /> <br />
<input /> <Input />
</div> </div>
</template> </template>
<script lang="ts"> <script lang="ts">
import { defineComponent } from 'vue'; import { defineComponent } from 'vue';
export default defineComponent({ name: 'Menu111Demo' }); import { Input } from 'ant-design-vue';
export default defineComponent({ name: 'Menu111Demo', components: { Input } });
</script> </script>
...@@ -2,10 +2,11 @@ ...@@ -2,10 +2,11 @@
<div class="p-5"> <div class="p-5">
多层级缓存-页面1-2 多层级缓存-页面1-2
<br /> <br />
<input /> <Input />
</div> </div>
</template> </template>
<script lang="ts"> <script lang="ts">
import { defineComponent } from 'vue'; import { defineComponent } from 'vue';
export default defineComponent({ name: 'Menu12Demo' }); import { Input } from 'ant-design-vue';
export default defineComponent({ name: 'Menu12Demo', components: { Input } });
</script> </script>
...@@ -2,12 +2,14 @@ ...@@ -2,12 +2,14 @@
<div class="p-5"> <div class="p-5">
多层级缓存-页面2 多层级缓存-页面2
<br /> <br />
<input /> <Input />
</div> </div>
</template> </template>
<script lang="ts"> <script lang="ts">
import { defineComponent } from 'vue'; import { defineComponent } from 'vue';
import { Input } from 'ant-design-vue';
export default defineComponent({ export default defineComponent({
name: 'Menu2Demo', name: 'Menu2Demo',
components: { Input },
}); });
</script> </script>
...@@ -64,7 +64,6 @@ ...@@ -64,7 +64,6 @@
margin-bottom: 5px; margin-bottom: 5px;
font-size: 16px; font-size: 16px;
font-weight: 500; font-weight: 500;
color: rgba(0, 0, 0, 0.85);
.icon { .icon {
margin-top: -5px; margin-top: -5px;
...@@ -75,19 +74,18 @@ ...@@ -75,19 +74,18 @@
&-num { &-num {
margin-left: 24px; margin-left: 24px;
line-height: 36px; line-height: 36px;
color: #7d7a7a; color: @text-color-secondary;
span { span {
margin-left: 5px; margin-left: 5px;
font-size: 18px; font-size: 18px;
color: #000;
} }
} }
&-download { &-download {
float: right; float: right;
font-size: 20px !important; font-size: 20px !important;
color: #1890ff; color: @primary-color;
} }
} }
} }
......
...@@ -102,7 +102,7 @@ ...@@ -102,7 +102,7 @@
&-top { &-top {
padding: 10px; padding: 10px;
margin: 16px 16px 12px 16px; margin: 16px 16px 12px 16px;
background: #fff; background: @component-background;
border-radius: 3px; border-radius: 3px;
&__avatar { &__avatar {
...@@ -144,7 +144,7 @@ ...@@ -144,7 +144,7 @@
&-bottom { &-bottom {
padding: 10px; padding: 10px;
margin: 0 16px 16px 16px; margin: 0 16px 16px 16px;
background: #fff; background: @component-background;
border-radius: 3px; border-radius: 3px;
} }
} }
......
...@@ -48,14 +48,14 @@ ...@@ -48,14 +48,14 @@
<style lang="less"> <style lang="less">
.account-setting { .account-setting {
margin: 12px; margin: 12px;
background: #fff; background: @component-background;
.base-title { .base-title {
padding-left: 0; padding-left: 0;
} }
.ant-tabs-tab-active { .ant-tabs-tab-active {
background-color: #e6f7ff; background-color: @item-active-bg;
} }
} }
</style> </style>
...@@ -93,6 +93,6 @@ ...@@ -93,6 +93,6 @@
<style lang="less" scoped> <style lang="less" scoped>
.desc-wrap { .desc-wrap {
padding: 16px; padding: 16px;
background: #fff; background: @component-background;
} }
</style> </style>
...@@ -62,6 +62,6 @@ ...@@ -62,6 +62,6 @@
<style lang="less" scoped> <style lang="less" scoped>
.form-wrap { .form-wrap {
padding: 24px; padding: 24px;
background: #fff; background: @component-background;
} }
</style> </style>
...@@ -78,18 +78,18 @@ ...@@ -78,18 +78,18 @@
margin: 0 0 12px; margin: 0 0 12px;
font-size: 16px; font-size: 16px;
line-height: 32px; line-height: 32px;
color: rgba(0, 0, 0, 0.45); color: @text-color;
} }
h4 { h4 {
margin: 0 0 4px; margin: 0 0 4px;
font-size: 14px; font-size: 14px;
line-height: 22px; line-height: 22px;
color: rgba(0, 0, 0, 0.45); color: @text-color;
} }
p { p {
color: rgba(0, 0, 0, 0.45); color: @text-color;
} }
} }
......
...@@ -44,6 +44,6 @@ ...@@ -44,6 +44,6 @@
.desc-wrap { .desc-wrap {
padding: 24px 40px; padding: 24px 40px;
margin-top: 24px; margin-top: 24px;
background: #fafafa; background: @background-color-light;
} }
</style> </style>
...@@ -85,7 +85,7 @@ ...@@ -85,7 +85,7 @@
<style lang="less" scoped> <style lang="less" scoped>
.step-form-content { .step-form-content {
padding: 24px; padding: 24px;
background: #fff; background: @component-background;
} }
.step-form-form { .step-form-form {
......
...@@ -86,25 +86,25 @@ ...@@ -86,25 +86,25 @@
&__top { &__top {
padding: 24px; padding: 24px;
text-align: center; text-align: center;
background: #fff; background: @component-background;
&-col { &-col {
&:not(:last-child) { &:not(:last-child) {
border-right: 1px dashed rgba(206, 206, 206, 0.4); border-right: 1px dashed @border-color-base;
} }
div { div {
margin-bottom: 12px; margin-bottom: 12px;
font-size: 14px; font-size: 14px;
line-height: 22px; line-height: 22px;
color: rgba(0, 0, 0, 0.45); color: @text-color;
} }
p { p {
margin: 0; margin: 0;
font-size: 24px; font-size: 24px;
line-height: 32px; line-height: 32px;
color: rgba(0, 0, 0, 0.85); color: @text-color;
} }
} }
} }
...@@ -112,7 +112,7 @@ ...@@ -112,7 +112,7 @@
&__content { &__content {
padding: 24px; padding: 24px;
margin-top: 12px; margin-top: 12px;
background: #fff; background: @component-background;
.list { .list {
position: relative; position: relative;
...@@ -127,7 +127,7 @@ ...@@ -127,7 +127,7 @@
top: 20px; top: 20px;
right: 15px; right: 15px;
font-weight: normal; font-weight: normal;
color: #1890ff; color: @primary-color;
cursor: pointer; cursor: pointer;
} }
......
...@@ -84,7 +84,7 @@ ...@@ -84,7 +84,7 @@
margin-bottom: 5px; margin-bottom: 5px;
font-size: 16px; font-size: 16px;
font-weight: 500; font-weight: 500;
color: rgba(0, 0, 0, 0.85); color: @text-color;
.icon { .icon {
margin-top: -5px; margin-top: -5px;
...@@ -97,7 +97,7 @@ ...@@ -97,7 +97,7 @@
padding-top: 10px; padding-top: 10px;
padding-left: 30px; padding-left: 30px;
font-size: 14px; font-size: 14px;
color: rgba(0, 0, 0, 0.5); color: @text-color-secondary;
} }
} }
} }
......
...@@ -91,7 +91,7 @@ ...@@ -91,7 +91,7 @@
&__container { &__container {
padding: 12px; padding: 12px;
background: #fff; background: @component-background;
} }
&__title { &__title {
...@@ -100,7 +100,7 @@ ...@@ -100,7 +100,7 @@
} }
&__content { &__content {
color: rgba(0, 0, 0, 0.65); color: @text-color-secondary;
} }
&__action { &__action {
...@@ -109,7 +109,7 @@ ...@@ -109,7 +109,7 @@
&-item { &-item {
display: inline-block; display: inline-block;
padding: 0 16px; padding: 0 16px;
color: rgba(0, 0, 0, 0.45); color: @text-color-secondary;
&:nth-child(1) { &:nth-child(1) {
padding-left: 0; padding-left: 0;
...@@ -117,7 +117,7 @@ ...@@ -117,7 +117,7 @@
&:nth-child(1), &:nth-child(1),
&:nth-child(2) { &:nth-child(2) {
border-right: 1px solid rgba(206, 206, 206, 0.4); border-right: 1px solid @border-color-base;
} }
} }
......
...@@ -34,17 +34,16 @@ ...@@ -34,17 +34,16 @@
<style lang="less" scoped> <style lang="less" scoped>
.result-error { .result-error {
padding: 48px 32px; padding: 48px 32px;
background: #fff; background: @component-background;
&__content { &__content {
padding: 24px 40px; padding: 24px 40px;
background: #fafafa; background: @background-color-light;
&-title { &-title {
margin-bottom: 16px; margin-bottom: 16px;
font-size: 16px; font-size: 16px;
font-weight: 500; font-weight: 500;
color: rgba(0, 0, 0, 0.85);
} }
&-icon { &-icon {
......
...@@ -48,11 +48,11 @@ ...@@ -48,11 +48,11 @@
<style lang="less" scoped> <style lang="less" scoped>
.result-success { .result-success {
padding: 48px 32px; padding: 48px 32px;
background: #fff; background: @component-background;
&__content { &__content {
padding: 24px 40px; padding: 24px 40px;
background: #fafafa; background: @background-color-light;
} }
} }
</style> </style>
...@@ -83,6 +83,6 @@ ...@@ -83,6 +83,6 @@
</script> </script>
<style lang="less" scoped> <style lang="less" scoped>
.demo { .demo {
background: #fff; background: @component-background;
} }
</style> </style>
...@@ -38,6 +38,6 @@ ...@@ -38,6 +38,6 @@
</script> </script>
<style lang="less" scoped> <style lang="less" scoped>
.demo { .demo {
background: #fff; background: @component-background;
} }
</style> </style>
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment