Ver Fonte

feat: 修改部分暗黑模式

zhouyuhao há 11 meses atrás
pai
commit
b36dc2e912

+ 4 - 1
src/components/VSliderVerification/src/VSliderVerification.vue

@@ -47,7 +47,7 @@ const addTipsNode = () => {
 
 const styleMap = {
   start: {
-    thumbColor: 'var(--color-neutral-1)',
+    thumbColor: 'var(--color-slider-thumb-start)',
     thumbIcon: 'icon-icon_drag__line_b',
     trackBackground: 'var(--color-success)'
   },
@@ -163,6 +163,9 @@ defineExpose({
   width: 400px;
   height: 373px;
   padding: 40px;
+  background-color: var(--color-slider-bg);
+  border-radius: 16px;
+  box-shadow: -2px 2px 12px 0 rgba(0, 0, 0, 0.5);
   .tips {
     margin-bottom: 16px;
     text-align: center;

+ 5 - 14
src/main.ts

@@ -24,12 +24,6 @@ const app = createApp(App)
 
 // 动态加载暗黑主题
 async function loadDarkTheme() {
-  // const linkEl = document.createElement('link')
-  // linkEl.rel = 'stylesheet'
-  // linkEl.href = 'https://unpkg.com/element-plus/theme-chalk/dark/css-vars.css' // 暗黑主题 CSS
-  // linkEl.id = 'dark-theme-style'
-  // document.head.appendChild(linkEl)
-
   await import('element-plus/theme-chalk/dark/css-vars.css') // 动态导入暗黑主题
 }
 // 动态移除暗黑主题
@@ -39,18 +33,15 @@ function unloadDarkTheme() {
     darkThemeStylesheet.remove()
   }
 }
-// 根据用户偏好或系统设置决定是否加载暗黑主题
-if (
-  (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) ||
-  localStorage.getItem('theme') === 'dark'
-) {
+// 根据用户偏好或系统设置决定是否加载暗黑主题 (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) ||
+if (localStorage.getItem('theme') === 'dark') {
   loadDarkTheme()
   document.documentElement.classList.add('dark')
 }
 // 根据用户偏好或系统设置决定是否添加暗黑模式类名
-if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) {
-  document.documentElement.classList.add('dark')
-}
+// if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) {
+//   document.documentElement.classList.add('dark')
+// }
 // 提供一个全局方法来切换主题
 app.config.globalProperties.$toggleDarkMode = () => {
   const html = document.documentElement

+ 38 - 0
src/stores/modules/theme.ts

@@ -0,0 +1,38 @@
+import { defineStore } from 'pinia'
+
+interface ThemeState {
+  theme: string
+}
+export const useThemeStore = defineStore('theme', {
+  state: (): ThemeState => ({
+    theme: localStorage.getItem('theme') || 'light'
+  }),
+  actions: {
+    toggleTheme() {
+      const html = document.documentElement
+      if (html.classList.contains('dark')) {
+        unloadDarkTheme()
+        html.classList.remove('dark')
+        localStorage.setItem('theme', 'light')
+        this.theme = 'light'
+      } else {
+        loadDarkTheme()
+        html.classList.add('dark')
+        localStorage.setItem('theme', 'dark')
+        this.theme = 'dark'
+      }
+    }
+  }
+})
+
+// 动态加载暗黑主题
+async function loadDarkTheme() {
+  await import('element-plus/theme-chalk/dark/css-vars.css') // 动态导入暗黑主题
+}
+// 动态移除暗黑主题
+function unloadDarkTheme() {
+  const darkThemeStylesheet = document.getElementById('dark-theme-style')
+  if (darkThemeStylesheet) {
+    darkThemeStylesheet.remove()
+  }
+}

+ 10 - 3
src/styles/elementui.scss

@@ -418,8 +418,13 @@ div .el-checkbox.el-checkbox--large span.el-checkbox__inner::after {
 }
 div .el-popper__arrow,
 div .el-popper__arrow:before {
-  height: 0;
-  width: 0;
+  // height: 0;
+  // width: 0;
+}
+.el-popper.is-dark,
+div.el-popper.is-dark > .el-popper__arrow:before {
+  background-color: var(--color-el-popper-bg);
+  border: var(--color-el-popper-bg);
 }
 div .el-popper[data-popper-placement^='bottom'] > .el-popper__arrow {
   top: 0;
@@ -446,10 +451,12 @@ div .el-popper[data-popper-placement^='bottom'] .el-popper__arrow:before {
 div .el-popover.el-popper {
   padding: 0;
 }
-.el-popper.is-dark {
+div.el-popper.is-dark {
   span {
     color: #fff;
   }
+  background-color: var(--color-el-popper-bg);
+  border-color: var(--color-el-popper-bg);
 }
 div .el-collapse-item__arrow,
 .el-tabs__nav {

+ 20 - 0
src/styles/theme.scss

@@ -175,6 +175,7 @@
   );
   --scoring-smile-radio-color: #e0e2e6;
 
+  --color-el-popper-bg: #303133;
   // 滚动条
   --color-scrollbar-thumb: #d9dddf;
 
@@ -197,6 +198,13 @@
   --color-customize-column-tabs-header-border: #ebeef5;
 
   --color-shipment-status-label-bg: #ccd1db;
+
+  --color-slider-bg: #fff;
+  --color-slider-thumb-start: #2b2f36;
+
+  --color-public-tracking-bg-mask: rgba(255, 255, 255, 0.85);
+  --color-public-tracking-search-input-btn: #000;
+  --color-public-tracking-search-input-border: #2b2f36;
 }
 
 :root.dark {
@@ -226,6 +234,13 @@
   --color-shipment-status-label-bg: #656f7d;
   --color-shipment-status-detail-path-font-color: #b5b7ba;
   --color-shipment-status-label-font-color: #c6cad0;
+
+  --color-slider-bg: #3f434a;
+  --color-slider-thumb-start: #646a73;
+
+  --color-public-tracking-bg-mask: rgba(43, 47, 54, 0.75);
+  --color-public-tracking-search-input-btn: #ed6d00;
+  --color-public-tracking-search-input-border: #656f7d;
   // 滚动条
   --color-scrollbar-thumb: #656f7d;
 
@@ -261,6 +276,11 @@
   --el-input-focus: #2b2f36;
   --color-dialog-header-bg: #3e454f;
   --color-dialog-body-bg: #30353c;
+  div.el-card {
+    --el-card-bg-color: #30353c;
+  }
+  --color-el-popper-bg: #1a1c20;
+  --el-bg-color: var(--color-neutral-1);
 
   // vxe-table
   --vxe-ui-layout-background-color: #2b2f36;

+ 8 - 1
src/views/Layout/src/components/Header/HeaderView.vue

@@ -7,12 +7,19 @@ import { useUserStore } from '@/stores/modules/user'
 import { useHeaderSearch } from '@/stores/modules/headerSearch'
 import { onBeforeRouteUpdate } from 'vue-router'
 import { useLoadingState } from '@/stores/modules/loadingState'
+import { useThemeStore } from '@/stores/modules/theme'
 
+const themeStore = useThemeStore()
 const userStore = useUserStore()
 const route = useRoute()
 const router = useRouter()
 const headerSearch = useHeaderSearch()
 
+// 切换系统主题颜色
+const toggleThemeMode = () => {
+  themeStore.toggleTheme()
+}
+
 const searchValue = ref('')
 // 用于判断是否在搜索后跳转页面,跳转后清空搜索框的值
 const isJumpPageBySearch = ref(false)
@@ -142,7 +149,7 @@ const handleLogin = () => {
   <div class="layout-toolbar">
     <VBreadcrumb></VBreadcrumb>
     <div class="right-info">
-      <el-button @click="$toggleDarkMode">切换主题</el-button>
+      <el-button @click="toggleThemeMode">切换主题</el-button>
       <el-input
         v-model="searchValue"
         size="large"

+ 3 - 0
src/views/Layout/src/components/Header/components/ChangePasswordDialog.vue

@@ -210,7 +210,10 @@ defineExpose({
   .form-item {
     margin-bottom: 16px;
     .label {
+      display: inline-block;
+      margin-bottom: 4px;
       font-size: 12px;
+      color: var(--color-neutral-2);
     }
     .error {
       font-size: 12px;

+ 1 - 0
src/views/Layout/src/components/Menu/MenuView.vue

@@ -221,6 +221,7 @@ const jumpLink = (link: string) => {
   margin: 0 12px 2px;
   padding-left: 8px !important;
   border-radius: 6px;
+  color: var(--color-neutral-1);
   &:hover {
     background-color: var(--color-mune-active-bg);
   }

+ 27 - 1
src/views/Login/src/components/ChangePasswordCard.vue

@@ -1,7 +1,29 @@
 <script setup lang="ts">
 import { useRouter } from 'vue-router'
+import { useThemeStore } from '@/stores/modules/theme'
 
 const router = useRouter()
+
+const themeStore = useThemeStore()
+const changePasswordRef = ref()
+// 判断当前系统主题模式
+onMounted(() => {
+  watch(
+    () => themeStore.theme,
+    (newVal) => {
+      if (newVal === 'dark') {
+        changePasswordRef.value.classList.add('dark-bg')
+      } else {
+        changePasswordRef.value.classList.remove('dark-bg')
+      }
+    },
+    {
+      immediate: true,
+      deep: true
+    }
+  )
+})
+
 const loginForm = ref({
   username: '',
   oldPassword: '',
@@ -112,7 +134,7 @@ const checkPassword = () => {
 </script>
 
 <template>
-  <div class="login">
+  <div class="login" ref="changePasswordRef">
     <el-card class="login-card">
       <div class="title">
         <span class="welcome">Change Password</span>
@@ -229,6 +251,10 @@ const checkPassword = () => {
   width: 100%;
   background: url(../image/bg.png) no-repeat center center;
   background-size: cover;
+  &.dark-bg {
+    background: url(../image/bg-dark.png) no-repeat center center;
+    background-size: cover;
+  }
 }
 
 .login-card {

+ 26 - 1
src/views/Login/src/loginView.vue

@@ -2,12 +2,33 @@
 import { useRouter, useRoute } from 'vue-router'
 import ErrorTips from './components/ErrorTips.vue'
 import { useUserStore } from '@/stores/modules/user'
+import { useThemeStore } from '@/stores/modules/theme'
 import ScoringSystem from '@/views/Dashboard/src/components/ScoringSystem.vue'
 import CryptoJS from 'crypto-js'
 import dayjs from 'dayjs'
 
 const router = useRouter()
 const route = useRoute()
+const themeStore = useThemeStore()
+
+const loginRef = ref()
+// 判断当前系统主题模式
+onMounted(() => {
+  watch(
+    () => themeStore.theme,
+    (newVal) => {
+      if (newVal === 'dark') {
+        loginRef.value.classList.add('dark-bg')
+      } else {
+        loginRef.value.classList.remove('dark-bg')
+      }
+    },
+    {
+      immediate: true,
+      deep: true
+    }
+  )
+})
 
 // 手动获取url中的参数,直接获取route.query的参数时如果有+号会被转义成空格
 const getQueryParams = (url: string) => {
@@ -340,7 +361,7 @@ const errorTipsRef = ref()
 </script>
 
 <template>
-  <div class="login">
+  <div class="login" ref="loginRef">
     <ScoringSystem class="scoring-system"></ScoringSystem>
     <el-card class="login-card" v-if="status === 'login'">
       <div class="card-title">
@@ -485,6 +506,10 @@ const errorTipsRef = ref()
   width: 100%;
   background: url(../src/image/bg.png) no-repeat center center;
   background-size: cover;
+  &.dark-bg {
+    background: url(../src/image/bg-dark.png) no-repeat center center;
+    background-size: cover;
+  }
   .scoring-system {
     position: absolute;
     top: 0;

+ 30 - 5
src/views/Tracking/src/components/PublicTracking/src/PublicTrackingSearch.vue

@@ -4,6 +4,27 @@ import { useHeaderSearch } from '@/stores/modules/headerSearch'
 import SlideVerify from './components/SlideVerify.vue'
 import CryptoJS from 'crypto-js'
 import dayjs from 'dayjs'
+import { useThemeStore } from '@/stores/modules/theme'
+
+const themeStore = useThemeStore()
+const publicTrackingRef = ref()
+// 判断当前系统主题模式
+onMounted(() => {
+  watch(
+    () => themeStore.theme,
+    (newVal) => {
+      if (newVal === 'dark') {
+        publicTrackingRef.value.classList.add('dark-bg')
+      } else {
+        publicTrackingRef.value.classList.remove('dark-bg')
+      }
+    },
+    {
+      immediate: true,
+      deep: true
+    }
+  )
+})
 
 const router = useRouter()
 
@@ -91,7 +112,7 @@ const encryptPassword = (password) => {
 </script>
 
 <template>
-  <div class="public-tracking-search" v-vloading="loading">
+  <div class="public-tracking-search" ref="publicTrackingRef" v-vloading="loading">
     <div class="search-info">
       <div class="title">Tracking</div>
       <el-input
@@ -155,6 +176,10 @@ const encryptPassword = (password) => {
   background-size: cover;
   z-index: 1;
   height: 100%;
+  &.dark-bg {
+    background: url(../../../../../Login/src/image/bg-dark.png) no-repeat center center;
+    background-size: cover;
+  }
 }
 
 .public-tracking-search::before {
@@ -164,7 +189,7 @@ const encryptPassword = (password) => {
   left: 0;
   right: 0;
   bottom: 0;
-  background-color: rgba(255, 255, 255, 0.85); /* 半透明白色背景层 */
+  background-color: var(--color-public-tracking-bg-mask); /* 半透明白色背景层 */
   z-index: -1; /* 将伪元素放置在背景图片的下方 */
 }
 
@@ -187,8 +212,8 @@ const encryptPassword = (password) => {
     }
     :deep(.el-input-group__append) {
       padding: 0;
-      background-color: black;
-      border: 1px solid black;
+      background-color: var(--color-public-tracking-search-input-btn);
+      border: 1px solid var(--color-public-tracking-search-input-btn);
       border-radius: 0 6px 6px 0;
       box-shadow: 0 0 10px 0 rgba(0, 0, 0, 0.1);
       span {
@@ -217,7 +242,7 @@ const encryptPassword = (password) => {
 }
 .public-tracking-search-input {
   :deep(.el-input__wrapper) {
-    box-shadow: 0 0 0 1px #2b2f36 inset;
+    box-shadow: 0 0 0 1px var(--color-public-tracking-search-input-border) inset;
   }
 }
 </style>

+ 14 - 6
src/views/Tracking/src/components/TrackingDetail/src/TrackingDetail.vue

@@ -301,13 +301,21 @@ const { isOverflow: isDestinationOverflow } = useOverflow(destinationRef, allDat
   padding-bottom: 16px;
   & > .header {
     background: linear-gradient(
-      251deg,
-      rgba(255, 255, 255, 0.3),
-      rgba(255, 244, 235, 0.5) 22.66%,
-      rgba(240, 243, 255, 0.5) 44.57%,
-      rgba(224, 247, 249, 0.6) 80.46%,
-      rgba(255, 255, 255, 0.3)
+      270deg,
+      rgba(43, 47, 54, 0.05) 1.88%,
+      rgba(255, 182, 121, 0.05) 15.6%,
+      rgba(118, 145, 255, 0.05) 49.92%,
+      rgba(96, 242, 255, 0.05) 81.78%,
+      rgba(43, 47, 54, 0.05) 97.95%
     );
+    // background: linear-gradient(
+    //   251deg,
+    //   rgba(255, 255, 255, 0.3),
+    //   rgba(255, 244, 235, 0.5) 22.66%,
+    //   rgba(240, 243, 255, 0.5) 44.57%,
+    //   rgba(224, 247, 249, 0.6) 80.46%,
+    //   rgba(255, 255, 255, 0.3)
+    // );
 
     .detail-status {
       position: relative;