index.vue 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174
  1. <script setup lang="ts">
  2. import { useI18n } from "vue-i18n";
  3. import { emitter } from "@/utils/mitt";
  4. import { onClickOutside } from "@vueuse/core";
  5. import { ref, computed, onMounted, onBeforeUnmount } from "vue";
  6. import { useDataThemeChange } from "@/layout/hooks/useDataThemeChange";
  7. import CloseIcon from "~icons/ep/close";
  8. const target = ref(null);
  9. const show = ref<Boolean>(false);
  10. const iconClass = computed(() => {
  11. return [
  12. "w-[22px]",
  13. "h-[22px]",
  14. "flex",
  15. "justify-center",
  16. "items-center",
  17. "outline-hidden",
  18. "rounded-[4px]",
  19. "cursor-pointer",
  20. "transition-colors",
  21. "hover:bg-[#0000000f]",
  22. "dark:hover:bg-[#ffffff1f]",
  23. "dark:hover:text-[#ffffffd9]"
  24. ];
  25. });
  26. const { t } = useI18n();
  27. const { onReset } = useDataThemeChange();
  28. onClickOutside(target, (event: any) => {
  29. if (event.clientX > target.value.offsetLeft) return;
  30. show.value = false;
  31. });
  32. onMounted(() => {
  33. emitter.on("openPanel", () => {
  34. show.value = true;
  35. });
  36. });
  37. onBeforeUnmount(() => {
  38. // 解绑`openPanel`公共事件,防止多次触发
  39. emitter.off("openPanel");
  40. });
  41. </script>
  42. <template>
  43. <div :class="{ show }">
  44. <div class="right-panel-background" />
  45. <div ref="target" class="right-panel">
  46. <div
  47. class="project-configuration border-0 border-b-[1px] border-solid border-[var(--pure-border-color)]"
  48. >
  49. <h4 class="dark:text-white">
  50. {{ t("panel.pureSystemSet") }}
  51. </h4>
  52. <span
  53. v-tippy="{
  54. content: t('panel.pureCloseSystemSet'),
  55. placement: 'bottom-start',
  56. zIndex: 41000
  57. }"
  58. :class="iconClass"
  59. >
  60. <IconifyIconOffline
  61. class="dark:text-white"
  62. width="18px"
  63. height="18px"
  64. :icon="CloseIcon"
  65. @click="show = !show"
  66. />
  67. </span>
  68. </div>
  69. <el-scrollbar>
  70. <slot />
  71. </el-scrollbar>
  72. <div
  73. class="flex justify-end p-3 border-0 border-t-[1px] border-solid border-[var(--pure-border-color)]"
  74. >
  75. <el-button
  76. v-tippy="{
  77. content: t('panel.pureClearCacheAndToLogin'),
  78. placement: 'left-start',
  79. zIndex: 41000
  80. }"
  81. type="danger"
  82. text
  83. bg
  84. @click="onReset"
  85. >
  86. {{ t("panel.pureClearCache") }}
  87. </el-button>
  88. </div>
  89. </div>
  90. </div>
  91. </template>
  92. <style lang="scss" scoped>
  93. :deep(.el-scrollbar) {
  94. height: calc(100vh - 110px);
  95. }
  96. // 用 ::v-deep 穿透 scoped,确保全局 .dark 类能影响变量
  97. :deep(:root) {
  98. --panel-bg-color: #ffffff; // 浅色模式背景
  99. }
  100. :deep(:root.dark) {
  101. --panel-bg-color: #1e1e1e; // 深色模式背景
  102. }
  103. .right-panel-background {
  104. position: fixed;
  105. top: 0;
  106. left: 0;
  107. z-index: -1;
  108. background: rgb(0 0 0 / 20%);
  109. opacity: 0;
  110. transition: opacity 0.3s cubic-bezier(0.7, 0.3, 0.1, 1);
  111. }
  112. .right-panel {
  113. position: fixed;
  114. top: 0;
  115. right: 0;
  116. z-index: 40000;
  117. width: 100%;
  118. max-width: 280px;
  119. box-shadow: 0 0 15px 0 rgb(0 0 0 / 5%);
  120. transform: translate(100%);
  121. transition: all 0.25s cubic-bezier(0.7, 0.3, 0.1, 1);
  122. // 强制应用背景色变量(核心修复)
  123. background-color: var(--el-color-white) !important;
  124. }
  125. .dark .right-panel {
  126. position: fixed;
  127. top: 0;
  128. right: 0;
  129. z-index: 40000;
  130. width: 100%;
  131. max-width: 280px;
  132. box-shadow: 0 0 15px 0 rgb(0 0 0 / 5%);
  133. transform: translate(100%);
  134. transition: all 0.25s cubic-bezier(0.7, 0.3, 0.1, 1);
  135. // 强制应用背景色变量(核心修复)
  136. background-color: var(--el-color-black) !important;
  137. }
  138. .show {
  139. transition: all 0.3s cubic-bezier(0.7, 0.3, 0.1, 1);
  140. .right-panel-background {
  141. z-index: 20000;
  142. width: 100%;
  143. height: 100%;
  144. opacity: 1;
  145. }
  146. .right-panel {
  147. transform: translate(0);
  148. }
  149. }
  150. .project-configuration {
  151. display: flex;
  152. align-items: center;
  153. justify-content: space-between;
  154. padding: 14px 20px;
  155. }
  156. </style>