提交 5b8eb4a4 编写于 作者: V Vben

feat: dark mode

上级 f05cc6d3
......@@ -11,6 +11,7 @@
- 移除 useFullScreen 函数
- tinymce 由 Cdn 改为 npm(打包体积偏大)
- Dashboard 重构
- 移除 ApexCharts 及示例
### 🐛 Bug Fixes
......
......@@ -2,11 +2,7 @@ import { generate } from '@ant-design/colors';
export const primaryColor = '#0960bd';
export const borderColorBase = '#d9d9d9';
export const themeMode = 'light';
export type ThemeMode = 'dark' | 'light';
export const darkMode = 'light';
type Fn = (...arg: any) => any;
......@@ -17,18 +13,17 @@ export interface GenerateColorsParams {
color?: string;
}
export function generateAntColors(color: string, mode: ThemeMode) {
export function generateAntColors(color: string) {
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 tm = theme || themeMode;
const colors = generateAntColors(tc, tm);
const colors = generateAntColors(tc);
const primary = colors[5];
const modeColors = generateAntColors(primary, tm === 'dark' ? 'light' : 'dark');
const modeColors = generateAntColors(primary);
return [...colors, ...modeColors];
}
......@@ -71,36 +66,3 @@ export function generateColors({
.filter((item) => item !== '#000000');
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) {
vitePlugins.push(configVisualizerConfig());
//vite-plugin-theme
vitePlugins.push(configThemePlugin());
vitePlugins.push(configThemePlugin(isBuild));
// The following plugins only work in the production environment
if (isBuild) {
......
......@@ -2,18 +2,50 @@
* Vite plugin for website theme color switching
* 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 { generateModifyVars } from '../../generate/generateModifyVars';
export function configThemePlugin() {
export function configThemePlugin(isBuild: boolean): Plugin[] {
const colors = generateColors({
mixDarken,
mixLighten,
tinycolor,
});
const plugin = viteThemePlugin({
colorVariables: [...getThemeColors(), ...colors],
});
return plugin;
const plugin = [
viteThemePlugin({
resolveSelector: (s) => `[data-theme] ${s}`,
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>
<html lang="en">
<html lang="en" id="htmlRoot">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
......@@ -13,8 +13,24 @@
<link rel="icon" href="/favicon.ico" />
</head>
<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">
<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 {
display: flex;
width: 100%;
......
<?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 @@
<rect id="Rectangle_73" data-name="Rectangle 73" width="6395" height="1079" transform="translate(-5391)" fill="#fff"/>
</clipPath>
<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="1" stop-color="#1c3faa"/>
<stop offset="0" stop-color="#2c41b4"/>
<stop offset="1" stop-color="#1b4fab"/>
</linearGradient>
</defs>
<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';
import AppProvider from './src/AppProvider.vue';
import AppSearch from './src/search/AppSearch.vue';
import AppLocalePicker from './src/AppLocalePicker.vue';
import AppDarkModeToggle from './src/AppDarkModeToggle.vue';
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 @@
padding: 0 16px;
font-size: 12px;
color: #666;
background: rgb(255 255 255);
background: @component-background;
border-top: 1px solid @border-color-base;
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;
flex-shrink: 0;
......
......@@ -190,12 +190,10 @@
&-content {
position: relative;
width: 632px;
// padding: 14px;
margin: 0 auto auto auto;
background: #f5f6f7;
background: @component-background;
border-radius: 16px;
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;
}
......@@ -253,8 +251,7 @@
font-size: 14px;
color: @text-color-base;
cursor: pointer;
// background: @primary-color;
background: #fff;
background: @component-background;
border-radius: 4px;
box-shadow: 0 1px 3px 0 #d4d9e1;
align-items: center;
......
......@@ -101,7 +101,7 @@
@prefix-cls: ~'@{namespace}-collapse-container';
.@{prefix-cls} {
background: #fff;
background: @component-background;
border-radius: 2px;
transition: all 0.3s ease-in-out;
......
......@@ -22,7 +22,7 @@
&:not(.ant-menu-item-disabled):hover {
color: @text-color-base;
background: #eee;
background: @item-hover-bg;
}
}
}
......@@ -36,7 +36,7 @@
width: 156px;
margin: 0;
list-style: none;
background-color: #fff;
background-color: @component-background;
border: 1px solid rgba(0, 0, 0, 0.08);
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),
......
......@@ -221,7 +221,7 @@
.ant-drawer-body {
height: calc(100% - @header-height);
padding: 0;
background-color: #fff;
background-color: @component-background;
.scrollbar__wrap {
padding: 16px !important;
......
......@@ -74,7 +74,7 @@
width: 100%;
padding: 0 12px 0 20px;
text-align: right;
background: #fff;
background: @component-background;
border-top: 1px solid @border-color-base;
> * {
......
......@@ -258,7 +258,7 @@
const { label, helpMessage, helpComponentProps, subLabel } = props.schema;
const renderLabel = subLabel ? (
<span>
{label} <span style="color:#00000073">{subLabel}</span>
{label} <span class="text-secondary">{subLabel}</span>
</span>
) : (
label
......
<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" />
</section>
</template>
<script lang="ts">
import { computed, CSSProperties, PropType } from 'vue';
import { PropType } from 'vue';
import { defineComponent } from 'vue';
import { Spin } from 'ant-design-vue';
import { SizeEnum } from '/@/enums/sizeEnum';
import { ThemeEnum } from '/@/enums/appEnum';
export default defineComponent({
name: 'Loading',
......@@ -38,25 +37,6 @@
background: {
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>
......@@ -71,6 +51,7 @@
height: 100%;
justify-content: center;
align-items: center;
background: rgba(240, 242, 245, 0.4);
&.absolute {
position: absolute;
......@@ -79,4 +60,10 @@
z-index: 300;
}
}
html[data-theme='dark'] {
.full-loading {
background: @modal-mask-bg;
}
}
</style>
......@@ -10,7 +10,7 @@
onUnmounted,
nextTick,
computed,
watchEffect,
watch,
} from 'vue';
import Vditor from 'vditor';
import 'vditor/dist/index.css';
......@@ -18,6 +18,7 @@
import { propTypes } from '/@/utils/propTypes';
import { useLocale } from '/@/locales/useLocale';
import { useModalContext } from '../../Modal';
import { useRootSetting } from '/@/hooks/setting/useRootSetting';
type Lang = 'zh_CN' | 'en_US' | 'ja_JP' | 'ko_KR' | undefined;
export default defineComponent({
......@@ -35,8 +36,24 @@
const modalFn = useModalContext();
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' => {
let lang: Lang;
......@@ -60,6 +77,7 @@
if (!wrapEl) return;
const bindValue = { ...attrs, ...props };
vditorRef.value = new Vditor(wrapEl, {
theme: 'classic',
lang: unref(getCurrentLang),
mode: 'sv',
preview: {
......
......@@ -38,8 +38,8 @@
align-items: center;
padding: 0 24px;
line-height: 44px;
background: #fff;
border-top: 1px solid #f0f0f0;
background: @component-background;
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),
0 -12px 48px 16px rgba(0, 0, 0, 0.03);
transition: width 0.2s;
......
......@@ -17,11 +17,7 @@
<slot :name="item" v-bind="data"></slot>
</template>
</PageHeader>
<div
class="overflow-hidden"
:class="[`${prefixCls}-content`, contentClass]"
:style="getContentStyle"
>
<div class="overflow-hidden" :class="getContentClass" :style="getContentStyle">
<slot></slot>
</div>
<PageFooter v-if="getShowFooter" ref="footerRef">
......@@ -87,14 +83,12 @@
const getContentStyle = computed(
(): CSSProperties => {
const { contentBackground, contentFullHeight, contentStyle, fixedHeight } = props;
const bg = contentBackground ? { backgroundColor: '#fff' } : {};
const { contentFullHeight, contentStyle, fixedHeight } = props;
if (!contentFullHeight) {
return { ...bg, ...contentStyle };
return { ...contentStyle };
}
const height = `${unref(pageHeight)}px`;
return {
...bg,
...contentStyle,
minHeight: height,
...(fixedHeight ? { height } : {}),
......@@ -103,6 +97,17 @@
}
);
const getContentClass = computed(() => {
const { contentBackground, contentClass } = props;
return [
`${prefixCls}-content`,
contentClass,
{
[`${prefixCls}-content-bg`]: contentBackground,
},
];
});
watch(
() => [contentHeight?.value, getShowFooter.value],
() => {
......@@ -170,6 +175,7 @@
getShowFooter,
pageHeight,
omit,
getContentClass,
};
},
});
......@@ -190,6 +196,10 @@
}
}
&-content-bg {
background: @component-background;
}
&--dense {
.@{prefix-cls}-content {
margin: 0;
......
......@@ -11,9 +11,9 @@
&-dark&-vertical .@{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 {
background-color: @sider-dark-lighten-1-bg-color;
background-color: @sider-dark-lighten-bg-color;
}
}
......
......@@ -298,6 +298,26 @@
@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} {
&-form-container {
padding: 16px;
......@@ -305,17 +325,11 @@
.ant-form {
padding: 12px 10px 6px 10px;
margin-bottom: 16px;
background: #fff;
background: @component-background;
border-radius: 4px;
}
}
&-row__striped {
td {
background: #fafafa;
}
}
&--inset {
.ant-table-wrapper {
padding: 0;
......@@ -328,7 +342,7 @@
.ant-table-wrapper {
padding: 6px;
background: #fff;
background: @component-background;
border-radius: 2px;
.ant-table-title {
......@@ -340,7 +354,6 @@
}
}
//
.ant-table {
width: 100%;
overflow-x: hidden;
......
......@@ -324,7 +324,7 @@
const showTitle = title || toolbar || search || slots.headerTitle;
const scrollStyle: CSSProperties = { height: 'calc(100% - 38px)' };
return (
<div class={[prefixCls, 'h-full bg-white', attrs.class]}>
<div class={[prefixCls, 'h-full', attrs.class]}>
{showTitle && (
<TreeHeader
checkable={checkable}
......@@ -361,6 +361,8 @@
@prefix-cls: ~'@{namespace}-basic-tree';
.@{prefix-cls} {
background: @component-background;
.ant-tree-node-content-wrapper {
position: relative;
......
.file-table {
width: 100%;
border-collapse: collapse;
// border: 1px solid @border-color-light;
.center {
text-align: center;
......@@ -21,12 +20,12 @@
}
thead {
background-color: @background-color-dark;
background-color: @background-color-light;
}
table,
td,
th {
border: 1px solid @border-color-light;
border: 1px solid @border-color-base;
}
}
......@@ -61,9 +61,9 @@
&.ant-btn-link.is-disabled {
color: rgba(0, 0, 0, 0.25) !important;
text-shadow: none;
cursor: not-allowed;
background-color: transparent;
border-color: transparent;
cursor: not-allowed !important;
background-color: transparent !important;
border-color: transparent !important;
box-shadow: none;
}
......@@ -187,7 +187,7 @@
&-ghost {
color: @button-ghost-color;
background-color: @white;
background-color: transparent;
border-color: @button-ghost-color;
border-width: 1px;
......@@ -205,4 +205,14 @@
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 {
&.mini {
.ant-pagination-prev,
......
:root {
html {
// header
--header-bg-color: #394664;
--header-bg-hover-color: #273352;
......@@ -7,16 +7,13 @@
// sider
--sider-dark-bg-color: #273352;
--sider-dark-darken-bg-color: #273352;
--sider-dark-lighten-1-bg-color: #273352;
--sider-dark-lighten-2-bg-color: #273352;
--sider-dark-lighten-bg-color: #273352;
}
@white: #fff;
@content-bg: #f4f7f9;
// @content-bg: #f0f2f5;
@basic-mask-color: fade(@white, 30%);
// :export {
// name: "less";
// mainColor: @mainColor;
......@@ -35,10 +32,7 @@
@border-color-shallow-dark: #cececd;
// Light-dark
@border-color-light: #ebeef5;
// Light-light
@border-color-shallow-light: #f2f6fc;
@border-color-light: @border-color-base;
// =================================
// ==============message==============
......@@ -53,17 +47,6 @@
// danger-bg-color
@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=============
// =================================
......@@ -83,14 +66,11 @@
// let -menu
@sider-dark-bg-color: var(--sider-dark-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-2-bg-color: var(--sider-dark-lighten-2-bg-color);
@sider-dark-lighten-bg-color: var(--sider-dark-lighten-bg-color);
// trigger
@trigger-dark-hover-bg-color: rgba(255, 255, 255, 0.2);
@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============
......@@ -119,9 +99,6 @@
// Auxiliary information color-dark
@text-color-help-dark: #909399;
// Auxiliary information color-light color
@text-color-help-light: #c0c4cc;
// =================================
// ==============breadcrumb=========
// =================================
......
......@@ -2,6 +2,7 @@
@import 'var/index.less';
@import 'public.less';
@import 'ant/index.less';
@import './theme.less';
input:-webkit-autofill {
-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 = {
mounted(el, binding) {
const tip = el.getAttribute('loading-tip');
const background = el.getAttribute('loading-background');
const theme = el.getAttribute('loading-theme');
const size = el.getAttribute('loading-size');
const fullscreen = !!binding.modifiers.fullscreen;
const instance = createLoading(
{
tip,
background,
theme,
size: size || 'large',
loading: !!binding.value,
absolute: !fullscreen,
......
......@@ -8,17 +8,9 @@ export enum ContentEnum {
FIXED = 'fixed',
}
// app current theme
export enum ThemeModeEnum {
LIGHT = 'light-mode',
DARK = 'dark-mode',
SEMI_DARK = 'semi-dark-mode',
}
// menu theme enum
export enum ThemeEnum {
DARK = 'dark',
LIGHT = 'light',
}
......
......@@ -15,6 +15,8 @@ export const PROJ_CFG_KEY = 'PROJ__CFG__KEY__';
// lock info
export const LOCK_INFO_KEY = 'LOCK__INFO__KEY__';
export const APP_DARK_MODE_KEY_ = '__APP__DARK__MODE__';
// base global local key
export const APP_LOCAL_CACHE_KEY = 'COMMON__LOCAL__KEY__';
......
......@@ -4,6 +4,7 @@ import { computed, unref } from 'vue';
import { appStore } from '/@/store/modules/app';
import { ContentEnum } from '/@/enums/appEnum';
import { ThemeEnum } from '../../enums/appEnum';
type RootSetting = Omit<
ProjectConfig,
......@@ -48,6 +49,10 @@ const getGrayMode = computed(() => unref(getRootSetting).grayMode);
const getLockTime = computed(() => unref(getRootSetting).lockTime);
const getShowDarkModeToggle = computed(() => unref(getRootSetting).showDarkModeToggle);
const getDarkMode = computed(() => appStore.getDarkMode);
const getLayoutContentMode = computed(() =>
unref(getRootSetting).contentMode === ContentEnum.FULL ? ContentEnum.FULL : ContentEnum.FIXED
);
......@@ -56,6 +61,10 @@ function setRootSetting(setting: Partial<RootSetting>) {
appStore.commitProjectConfigState(setting);
}
function setDarkMode(mode: ThemeEnum) {
appStore.commitDarkMode(mode);
}
export function useRootSetting() {
return {
setRootSetting,
......@@ -80,5 +89,8 @@ export function useRootSetting() {
getContentMode,
getLockTime,
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 { 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 { useDebounce } from '/@/hooks/core/useDebounce';
import { useEventListener } from '/@/hooks/event/useEventListener';
import { useBreakpoint } from '/@/hooks/event/useBreakpoint';
import echarts from '/@/plugins/echarts';
import { useRootSetting } from '../setting/useRootSetting';
export function useECharts(
elRef: Ref<HTMLDivElement>,
theme: 'light' | 'dark' | 'default' = 'light'
) {
const { getDarkMode } = useRootSetting();
let chartInstance: echarts.ECharts | null = null;
let resizeFn: Fn = resize;
const cacheOptions = ref<EChartsOption>({});
let removeResizeFn: Fn = () => {};
const [debounceResize] = useDebounce(resize, 200);
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);
if (!el || !unref(el)) {
return;
}
chartInstance = echarts.init(el, theme);
chartInstance = echarts.init(el, t);
const { removeEvent } = useEventListener({
el: window,
name: 'resize',
......@@ -41,22 +56,23 @@ export function useECharts(
}
function setOptions(options: EChartsOption, clear = true) {
cacheOptions.value = options;
if (unref(elRef)?.offsetHeight === 0) {
useTimeoutFn(() => {
setOptions(options);
setOptions(unref(getOptions));
}, 30);
return;
}
nextTick(() => {
useTimeoutFn(() => {
if (!chartInstance) {
initCharts();
initCharts(getDarkMode.value);
if (!chartInstance) return;
}
clear && chartInstance?.clear();
chartInstance?.setOption(options);
chartInstance?.setOption(unref(getOptions));
}, 30);
});
}
......@@ -65,6 +81,17 @@ export function useECharts(
chartInstance?.resize();
}
watch(
() => getDarkMode.value,
(theme) => {
if (chartInstance) {
chartInstance.dispose();
initCharts(theme);
setOptions(cacheOptions.value);
}
}
);
tryOnUnmounted(() => {
if (!chartInstance) return;
removeResizeFn();
......
......@@ -112,7 +112,6 @@
@prefix-cls: ~'@{namespace}-layout-multiple-header';
.@{prefix-cls} {
// margin-left: 1px;
transition: width 0.2s;
flex: 0 0 auto;
......
......@@ -91,7 +91,6 @@
position: relative;
height: 240px;
padding: 130px 30px 60px 30px;
background: #fff;
border-radius: 10px;
}
......
......@@ -131,10 +131,6 @@
cursor: pointer;
align-items: center;
&:hover {
background: @header-light-bg-hover-color;
}
img {
width: 24px;
height: 24px;
......
......@@ -131,7 +131,7 @@
}
&--light {
background: @white;
background: @white !important;
border-bottom: 1px solid @header-light-bottom-border-color;
border-left: 1px solid @header-light-bottom-border-color;
......@@ -165,8 +165,9 @@
}
&--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 {
&:hover {
background: @header-dark-bg-hover-color;
......
......@@ -3,13 +3,15 @@ import { BasicDrawer } from '/@/components/Drawer/index';
import { Divider } from 'ant-design-vue';
import {
TypePicker,
ThemePicker,
ThemeColorPicker,
SettingFooter,
SwitchItem,
SelectItem,
InputNumberItem,
} from './components';
import { AppDarkModeToggle } from '/@/components/Application';
import { MenuTypeEnum, TriggerEnum } from '/@/enums/menuEnum';
import { useRootSetting } from '/@/hooks/setting/useRootSetting';
......@@ -52,6 +54,7 @@ export default defineComponent({
getColorWeak,
getGrayMode,
getLockTime,
getShowDarkModeToggle,
getThemeColor,
} = useRootSetting();
......@@ -116,7 +119,7 @@ export default defineComponent({
function renderHeaderTheme() {
return (
<ThemePicker
<ThemeColorPicker
colorList={HEADER_PRESET_BG_COLOR_LIST}
def={unref(getHeaderBgColor)}
event={HandlerEnum.HEADER_THEME}
......@@ -126,7 +129,7 @@ export default defineComponent({
function renderSiderTheme() {
return (
<ThemePicker
<ThemeColorPicker
colorList={SIDE_BAR_BG_COLOR_LIST}
def={unref(getMenuBgColor)}
event={HandlerEnum.MENU_THEME}
......@@ -136,7 +139,7 @@ export default defineComponent({
function renderMainTheme() {
return (
<ThemePicker
<ThemeColorPicker
colorList={APP_PRESET_COLOR_LIST}
def={unref(getThemeColor)}
event={HandlerEnum.CHANGE_THEME_COLOR}
......@@ -404,6 +407,8 @@ export default defineComponent({
width={330}
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>
{renderSidebar()}
<Divider>{() => t('layout.setting.sysTheme')}</Divider>
......
......@@ -26,7 +26,7 @@
import { HandlerEnum } from '../enum';
export default defineComponent({
name: 'ThemePicker',
name: 'ThemeColorPicker',
components: { CheckOutlined },
props: {
colorList: {
......
......@@ -74,7 +74,8 @@
content: '';
}
&--sidebar {
&--sidebar,
&--light {
&::before {
top: 0;
left: 0;
......@@ -124,6 +125,10 @@
}
}
&--dark {
background-color: #273352;
}
&--mix-sidebar {
&::before {
top: 0;
......@@ -152,17 +157,6 @@
}
}
// &::after {
// position: absolute;
// top: 50%;
// left: 50%;
// width: 0;
// height: 0;
// content: '';
// opacity: 0;
// transition: all 0.3s;
// }
&:hover,
&--active {
padding: 12px;
......
import { createAsyncComponent } from '/@/utils/factory/createAsyncComponent';
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 SwitchItem = createAsyncComponent(() => import('./SwitchItem.vue'));
export const SelectItem = createAsyncComponent(() => import('./SelectItem.vue'));
......
......@@ -14,6 +14,7 @@ const { t } = useI18n();
export enum HandlerEnum {
CHANGE_LAYOUT,
CHANGE_THEME_COLOR,
CHANGE_THEME,
// menu
MENU_HAS_DRAG,
MENU_ACCORDION,
......
......@@ -6,15 +6,20 @@ import { updateGrayMode } from '/@/logics/theme/updateGrayMode';
import { appStore } from '/@/store/modules/app';
import { ProjectConfig } from '/#/config';
import { changeTheme } from '/@/logics/theme';
import { updateDarkTheme } from '/@/logics/theme/dark';
import { useRootSetting } from '/@/hooks/setting/useRootSetting';
export function baseHandler(event: HandlerEnum, value: any) {
const config = handler(event, value);
appStore.commitProjectConfigState(config);
if (event === HandlerEnum.CHANGE_THEME) {
updateHeaderBgColor();
updateSidebarBgColor();
}
}
export function handler(event: HandlerEnum, value: any): DeepPartial<ProjectConfig> {
const { getThemeColor } = useRootSetting();
const { getThemeColor, getDarkMode } = useRootSetting();
switch (event) {
case HandlerEnum.CHANGE_LAYOUT:
const { mode, type, split } = value;
......@@ -36,8 +41,17 @@ export function handler(event: HandlerEnum, value: any): DeepPartial<ProjectConf
return {};
}
changeTheme(value);
return { themeColor: value };
case HandlerEnum.CHANGE_THEME:
if (getDarkMode.value === value) {
return {};
}
updateDarkTheme(value);
return { darkMode: value };
case HandlerEnum.MENU_HAS_DRAG:
return { menuSetting: { canDrag: value } };
......
......@@ -403,7 +403,7 @@
}
}
}
@border-color: @sider-dark-lighten-1-bg-color;
@border-color: @sider-dark-lighten-bg-color;
&.dark {
&.open {
......
@prefix-cls: ~'@{namespace}-multiple-tabs';
html[data-theme='dark'] {
.@{prefix-cls} {
.ant-tabs-tab {
border-bottom: 1px solid @border-color-base;
}
}
}
.@{prefix-cls} {
z-index: 10;
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);
.ant-tabs-small {
......@@ -15,7 +24,7 @@
.ant-tabs-card-bar {
height: @multiple-height;
margin: 0;
background: @white;
background: @component-background;
border: 0;
box-shadow: none;
......@@ -28,35 +37,14 @@
height: calc(@multiple-height - 2px);
padding-right: 12px;
line-height: calc(@multiple-height - 2px);
color: @text-color-call-out;
background: @white;
border-bottom: 1px solid @header-light-bottom-border-color;
color: @text-color-base;
background: @component-background;
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 {
.ant-tabs-close-x {
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 {
......@@ -85,26 +73,20 @@
}
}
.ant-tabs-tab:not(.ant-tabs-tab-active) {
&:hover {
color: @primary-color;
}
}
.ant-tabs-tab-active {
position: relative;
padding-left: 26px;
padding-left: 18px;
color: @white;
background: fade(@primary-color, 100%);
background: @primary-color;
border: 0;
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 {
opacity: 1;
}
......@@ -158,10 +140,10 @@
width: 36px;
height: @multiple-height;
line-height: @multiple-height;
color: #666;
color: @text-color-secondary;
text-align: center;
cursor: pointer;
border-left: 1px solid #eee;
border-left: 1px solid @border-color-base;
&:hover {
color: @text-color-base;
......
......@@ -14,4 +14,7 @@ export default {
redo: 'Refresh',
back: 'Back',
light: 'Light',
dark: 'Dark',
};
......@@ -30,6 +30,7 @@ export default {
drawerTitle: 'Configuration',
darkMode: 'Dark mode',
navMode: 'Navigation mode',
interfaceFunction: 'Interface function',
interfaceDisplay: 'Interface display',
......
......@@ -6,5 +6,4 @@ export default {
map: 'Map',
line: 'Line',
pie: 'Pie',
apexChart: 'ApexChart',
};
......@@ -14,4 +14,7 @@ export default {
redo: '刷新',
back: '返回',
light: '亮色主题',
dark: '黑暗主题',
};
......@@ -29,6 +29,7 @@ export default {
drawerTitle: '项目配置',
darkMode: '主题',
navMode: '导航栏模式',
interfaceFunction: '界面功能',
interfaceDisplay: '界面显示',
......
......@@ -6,5 +6,4 @@ export default {
map: '地图',
line: '折线图',
pie: '饼图',
apexChart: 'ApexChart',
};
......@@ -9,6 +9,7 @@ import projectSetting from '/@/settings/projectSetting';
import { updateHeaderBgColor, updateSidebarBgColor } from '/@/logics/theme/updateBackground';
import { updateColorWeak } from '/@/logics/theme/updateColorWeak';
import { updateGrayMode } from '/@/logics/theme/updateGrayMode';
import { updateDarkTheme } from '/@/logics/theme/dark';
import { changeTheme } from '/@/logics/theme';
import { appStore } from '/@/store/modules/app';
......@@ -19,30 +20,43 @@ import { getCommonStoragePrefix, getStorageShortName } from '/@/utils/env';
import { primaryColor } from '../../build/config/themeConfig';
import { Persistent } from '/@/utils/cache/persistent';
import { deepMerge } from '/@/utils';
import { ThemeEnum } from '../enums/appEnum';
// Initial project configuration
export function initAppConfigStore() {
let projCfg: ProjectConfig = Persistent.getLocal(PROJ_CFG_KEY) as ProjectConfig;
projCfg = deepMerge(projectSetting, projCfg || {});
const darkMode = appStore.getDarkMode;
const {
colorWeak,
grayMode,
themeColor,
headerSetting: { bgColor: headerBgColor } = {},
menuSetting: { bgColor } = {},
} = projCfg;
try {
const {
colorWeak,
grayMode,
themeColor,
headerSetting: { bgColor: headerBgColor } = {},
menuSetting: { bgColor } = {},
} = projCfg;
if (themeColor && themeColor !== primaryColor) {
changeTheme(themeColor);
}
headerBgColor && updateHeaderBgColor(headerBgColor);
bgColor && updateSidebarBgColor(bgColor);
grayMode && updateGrayMode(grayMode);
colorWeak && updateColorWeak(colorWeak);
} catch (error) {
console.log(error);
}
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();
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 { 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({
mixDarken,
mixLighten,
......@@ -12,6 +12,6 @@ export async function changeTheme(color: string, theme?: ThemeMode) {
});
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 { ThemeEnum } from '/@/enums/appEnum';
import { setCssVar } from './util';
......@@ -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_DARKEN_BG_COLOR = '--sider-dark-darken-bg-color';
const SIDER_LIGHTEN_1_BG_COLOR = '--sider-dark-lighten-1-bg-color';
const SIDER_LIGHTEN_2_BG_COLOR = '--sider-dark-lighten-2-bg-color';
const SIDER_LIGHTEN_BG_COLOR = '--sider-dark-lighten-bg-color';
/**
* Change the background color of the top header
* @param color
*/
export function updateHeaderBgColor(color: string) {
if (!isHexColor(color)) return;
export function updateHeaderBgColor(color?: string) {
const darkMode = appStore.getDarkMode === ThemeEnum.DARK;
if (!color) {
if (darkMode) {
color = '#151515';
} else {
color = appStore.getProjectConfig.headerSetting.bgColor;
}
}
// bg color
setCssVar(HEADER_BG_COLOR_VAR, color);
// hover color
const hoverColor = lighten(color, 6);
const hoverColor = lighten(color!, 6);
setCssVar(HEADER_BG_HOVER_COLOR_VAR, hoverColor);
setCssVar(HEADER_MENU_ACTIVE_BG_COLOR_VAR, hoverColor);
// Determine the depth of the color value and automatically switch the theme
const isDark = colorIsDark(color);
const isDark = colorIsDark(color!);
appStore.commitProjectConfigState({
headerSetting: {
theme: isDark ? ThemeEnum.DARK : ThemeEnum.LIGHT,
theme: isDark || darkMode ? ThemeEnum.DARK : ThemeEnum.LIGHT,
},
});
}
......@@ -40,21 +46,27 @@ export function updateHeaderBgColor(color: string) {
* Change the background color of the left menu
* @param color bg color
*/
export function updateSidebarBgColor(color: string) {
if (!isHexColor(color)) return;
export function updateSidebarBgColor(color?: string) {
// 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_DARKEN_BG_COLOR, darken(color, 6));
setCssVar(SIDER_LIGHTEN_1_BG_COLOR, lighten(color, 5));
setCssVar(SIDER_LIGHTEN_2_BG_COLOR, lighten(color, 8));
setCssVar(SIDER_DARK_DARKEN_BG_COLOR, darken(color!, 6));
setCssVar(SIDER_LIGHTEN_BG_COLOR, lighten(color!, 5));
// only #ffffff is 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({
menuSetting: {
theme: isLight ? ThemeEnum.LIGHT : ThemeEnum.DARK,
theme: isLight && !darkMode ? ThemeEnum.LIGHT : ThemeEnum.DARK,
},
});
}
......@@ -21,11 +21,6 @@ const menu: MenuModule = {
path: 'googleMap',
name: t('routes.demo.charts.googleMap'),
},
{
path: 'apexChart',
name: t('routes.demo.charts.apexChart'),
},
{
path: 'echarts',
name: 'Echarts',
......
......@@ -38,14 +38,6 @@ const charts: AppRouteModule = {
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',
name: 'Echarts',
......
import { ThemeEnum } from '../enums/appEnum';
export default {
prefixCls: 'vben',
};
export const darkMode = ThemeEnum.LIGHT;
// app theme preset color
export const APP_PRESET_COLOR_LIST: string[] = [
'#0960bd',
......@@ -18,6 +21,7 @@ export const APP_PRESET_COLOR_LIST: string[] = [
// header preset color
export const HEADER_PRESET_BG_COLOR_LIST: string[] = [
'#ffffff',
'#151515',
'#009688',
'#5172DC',
'#018ffb',
......@@ -32,6 +36,7 @@ export const HEADER_PRESET_BG_COLOR_LIST: string[] = [
// sider preset color
export const SIDE_BAR_BG_COLOR_LIST: string[] = [
'#001529',
'#212121',
'#273352',
'#ffffff',
'#191b24',
......
......@@ -9,13 +9,16 @@ import {
SettingButtonPositionEnum,
} from '/@/enums/appEnum';
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
const setting: ProjectConfig = {
// Whether to show the configuration button
showSettingButton: true,
// Whether to show the theme switch button
showDarkModeToggle: true,
// `Settings` button position
settingButtonPosition: SettingButtonPositionEnum.AUTO,
......@@ -28,9 +31,6 @@ const setting: ProjectConfig = {
// color
themeColor: primaryColor,
// TODO dark theme
themeMode: themeMode,
// Website gray mode, open for possible mourning dates
grayMode: false,
......
......@@ -4,13 +4,16 @@ import type { BeforeMiniState } from '../types';
import { VuexModule, getModule, Module, Mutation, Action } from 'vuex-module-decorators';
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 { Persistent } from '/@/utils/cache/persistent';
import { deepMerge } from '/@/utils';
import { resetRouter } from '/@/router';
import { ThemeEnum } from '../../enums/appEnum';
import { darkMode } from '/@/settings/designSetting';
export interface LockInfo {
pwd: string | undefined;
......@@ -22,6 +25,8 @@ const NAME = 'app';
hotModuleUnregisterModule(NAME);
@Module({ dynamic: true, namespaced: true, store, name: NAME })
export default class App extends VuexModule {
private darkMode;
// Page loading status
private pageLoadingState = false;
......@@ -38,6 +43,10 @@ export default class App extends VuexModule {
return this.pageLoadingState;
}
get getDarkMode() {
return this.darkMode || localStorage.getItem(APP_DARK_MODE_KEY_) || darkMode;
}
get getBeforeMiniState() {
return this.beforeMiniState;
}
......@@ -55,6 +64,12 @@ export default class App extends VuexModule {
this.pageLoadingState = loading;
}
@Mutation
commitDarkMode(mode: ThemeEnum): void {
this.darkMode = mode;
localStorage.setItem(APP_DARK_MODE_KEY_, mode);
}
@Mutation
commitBeforeMiniState(state: BeforeMiniState): void {
this.beforeMiniState = state;
......
......@@ -32,7 +32,6 @@
return;
}
setOptions({
backgroundColor: '#fff',
legend: {
bottom: 0,
data: ['访问', '购买'],
......
......@@ -32,7 +32,6 @@
return;
}
setOptions({
backgroundColor: '#fff',
legend: {
bottom: 0,
data: ['Visits', 'Sales'],
......
......@@ -32,7 +32,6 @@
return;
}
setOptions({
backgroundColor: '#fff',
legend: {
bottom: 0,
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 @@
height: 2000px;
margin: 20px auto;
text-align: center;
background: #fff;
background: @component-background;
justify-content: center;
flex-direction: column;
align-items: center;
......
......@@ -33,7 +33,7 @@
height: 2000px;
margin: 20px auto;
text-align: center;
background: #fff;
background: @component-background;
justify-content: center;
flex-direction: column;
align-items: center;
......
......@@ -54,6 +54,6 @@
.scroll-wrap {
width: 50%;
height: 300px;
background: #fff;
background: @component-background;
}
</style>
......@@ -50,7 +50,7 @@
&-wrap {
display: flex;
margin: 0 30%;
background: #fff;
background: @component-background;
justify-content: center;
}
......@@ -58,7 +58,7 @@
height: 40px;
padding: 0 20px;
line-height: 40px;
border-bottom: 1px solid #ddd;
border-bottom: 1px solid @border-color-base;
}
}
</style>
......@@ -26,6 +26,6 @@
.scroll-wrap {
width: 50%;
height: 300px;
background: #fff;
background: @component-background;
}
</style>
......@@ -26,7 +26,7 @@
<style lang="less" scoped>
.demo-wrap {
width: 50%;
background: #fff;
background: @component-background;
border-radius: 10px;
}
</style>
......@@ -3,17 +3,18 @@
Current Param : {{ params }}
<br />
Keep Alive
<input />
<Input />
</PageWrapper>
</template>
<script lang="ts">
import { computed, defineComponent, unref } from 'vue';
import { useRouter } from 'vue-router';
import { PageWrapper } from '/@/components/Page';
import { Input } from 'ant-design-vue';
export default defineComponent({
name: 'TestTab',
components: { PageWrapper },
components: { PageWrapper, Input },
setup() {
const { currentRoute } = useRouter();
return {
......
......@@ -2,10 +2,11 @@
<div class="p-5">
多层级缓存-页面1-1-1
<br />
<input />
<Input />
</div>
</template>
<script lang="ts">
import { defineComponent } from 'vue';
export default defineComponent({ name: 'Menu111Demo' });
import { Input } from 'ant-design-vue';
export default defineComponent({ name: 'Menu111Demo', components: { Input } });
</script>
......@@ -2,10 +2,11 @@
<div class="p-5">
多层级缓存-页面1-2
<br />
<input />
<Input />
</div>
</template>
<script lang="ts">
import { defineComponent } from 'vue';
export default defineComponent({ name: 'Menu12Demo' });
import { Input } from 'ant-design-vue';
export default defineComponent({ name: 'Menu12Demo', components: { Input } });
</script>
......@@ -2,12 +2,14 @@
<div class="p-5">
多层级缓存-页面2
<br />
<input />
<Input />
</div>
</template>
<script lang="ts">
import { defineComponent } from 'vue';
import { Input } from 'ant-design-vue';
export default defineComponent({
name: 'Menu2Demo',
components: { Input },
});
</script>
......@@ -64,7 +64,6 @@
margin-bottom: 5px;
font-size: 16px;
font-weight: 500;
color: rgba(0, 0, 0, 0.85);
.icon {
margin-top: -5px;
......@@ -75,19 +74,18 @@
&-num {
margin-left: 24px;
line-height: 36px;
color: #7d7a7a;
color: @text-color-secondary;
span {
margin-left: 5px;
font-size: 18px;
color: #000;
}
}
&-download {
float: right;
font-size: 20px !important;
color: #1890ff;
color: @primary-color;
}
}
}
......
......@@ -102,7 +102,7 @@
&-top {
padding: 10px;
margin: 16px 16px 12px 16px;
background: #fff;
background: @component-background;
border-radius: 3px;
&__avatar {
......@@ -144,7 +144,7 @@
&-bottom {
padding: 10px;
margin: 0 16px 16px 16px;
background: #fff;
background: @component-background;
border-radius: 3px;
}
}
......
......@@ -48,14 +48,14 @@
<style lang="less">
.account-setting {
margin: 12px;
background: #fff;
background: @component-background;
.base-title {
padding-left: 0;
}
.ant-tabs-tab-active {
background-color: #e6f7ff;
background-color: @item-active-bg;
}
}
</style>
......@@ -93,6 +93,6 @@
<style lang="less" scoped>
.desc-wrap {
padding: 16px;
background: #fff;
background: @component-background;
}
</style>
......@@ -62,6 +62,6 @@
<style lang="less" scoped>
.form-wrap {
padding: 24px;
background: #fff;
background: @component-background;
}
</style>
......@@ -78,18 +78,18 @@
margin: 0 0 12px;
font-size: 16px;
line-height: 32px;
color: rgba(0, 0, 0, 0.45);
color: @text-color;
}
h4 {
margin: 0 0 4px;
font-size: 14px;
line-height: 22px;
color: rgba(0, 0, 0, 0.45);
color: @text-color;
}
p {
color: rgba(0, 0, 0, 0.45);
color: @text-color;
}
}
......
......@@ -44,6 +44,6 @@
.desc-wrap {
padding: 24px 40px;
margin-top: 24px;
background: #fafafa;
background: @background-color-light;
}
</style>
......@@ -85,7 +85,7 @@
<style lang="less" scoped>
.step-form-content {
padding: 24px;
background: #fff;
background: @component-background;
}
.step-form-form {
......
......@@ -86,25 +86,25 @@
&__top {
padding: 24px;
text-align: center;
background: #fff;
background: @component-background;
&-col {
&:not(:last-child) {
border-right: 1px dashed rgba(206, 206, 206, 0.4);
border-right: 1px dashed @border-color-base;
}
div {
margin-bottom: 12px;
font-size: 14px;
line-height: 22px;
color: rgba(0, 0, 0, 0.45);
color: @text-color;
}
p {
margin: 0;
font-size: 24px;
line-height: 32px;
color: rgba(0, 0, 0, 0.85);
color: @text-color;
}
}
}
......@@ -112,7 +112,7 @@
&__content {
padding: 24px;
margin-top: 12px;
background: #fff;
background: @component-background;
.list {
position: relative;
......@@ -127,7 +127,7 @@
top: 20px;
right: 15px;
font-weight: normal;
color: #1890ff;
color: @primary-color;
cursor: pointer;
}
......
......@@ -84,7 +84,7 @@
margin-bottom: 5px;
font-size: 16px;
font-weight: 500;
color: rgba(0, 0, 0, 0.85);
color: @text-color;
.icon {
margin-top: -5px;
......@@ -97,7 +97,7 @@
padding-top: 10px;
padding-left: 30px;
font-size: 14px;
color: rgba(0, 0, 0, 0.5);
color: @text-color-secondary;
}
}
}
......
......@@ -91,7 +91,7 @@
&__container {
padding: 12px;
background: #fff;
background: @component-background;
}
&__title {
......@@ -100,7 +100,7 @@
}
&__content {
color: rgba(0, 0, 0, 0.65);
color: @text-color-secondary;
}
&__action {
......@@ -109,7 +109,7 @@
&-item {
display: inline-block;
padding: 0 16px;
color: rgba(0, 0, 0, 0.45);
color: @text-color-secondary;
&:nth-child(1) {
padding-left: 0;
......@@ -117,7 +117,7 @@
&:nth-child(1),
&:nth-child(2) {
border-right: 1px solid rgba(206, 206, 206, 0.4);
border-right: 1px solid @border-color-base;
}
}
......
......@@ -34,17 +34,16 @@
<style lang="less" scoped>
.result-error {
padding: 48px 32px;
background: #fff;
background: @component-background;
&__content {
padding: 24px 40px;
background: #fafafa;
background: @background-color-light;
&-title {
margin-bottom: 16px;
font-size: 16px;
font-weight: 500;
color: rgba(0, 0, 0, 0.85);
}
&-icon {
......
......@@ -48,11 +48,11 @@
<style lang="less" scoped>
.result-success {
padding: 48px 32px;
background: #fff;
background: @component-background;
&__content {
padding: 24px 40px;
background: #fafafa;
background: @background-color-light;
}
}
</style>
......@@ -83,6 +83,6 @@
</script>
<style lang="less" scoped>
.demo {
background: #fff;
background: @component-background;
}
</style>
......@@ -38,6 +38,6 @@
</script>
<style lang="less" scoped>
.demo {
background: #fff;
background: @component-background;
}
</style>
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册