diff --git a/src/components/ReCropper/src/circled.css b/src/components/ReCropper/src/circled.css index 41b0d9931..d9216c4f1 100644 --- a/src/components/ReCropper/src/circled.css +++ b/src/components/ReCropper/src/circled.css @@ -1,7 +1,5 @@ -@import "cropperjs/dist/cropper.css"; -@import "tippy.js/dist/tippy.css"; @import "tippy.js/themes/light.css"; -@import "tippy.js/animations/perspective.css"; +@import "cropperjs/dist/cropper.css"; .re-circled { .cropper-view-box, diff --git a/src/components/ReCropper/src/index.tsx b/src/components/ReCropper/src/index.tsx index 5a487abd1..bd57e142c 100644 --- a/src/components/ReCropper/src/index.tsx +++ b/src/components/ReCropper/src/index.tsx @@ -1,10 +1,10 @@ import "./circled.css"; import Cropper from "cropperjs"; +import { useTippy } from "vue-tippy"; import { ElUpload } from "element-plus"; import type { CSSProperties } from "vue"; import { useResizeObserver } from "@vueuse/core"; import { longpress } from "@/directives/longpress"; -import { useTippy, directive as tippy } from "vue-tippy"; import { delay, debounce, isArray, downloadByBase64 } from "@pureadmin/utils"; import { ref, @@ -233,7 +233,6 @@ export default defineComponent({ const menuContent = defineComponent({ directives: { - tippy, longpress }, setup() { diff --git a/src/components/ReIcon/src/hooks.ts b/src/components/ReIcon/src/hooks.ts index 675d303d1..6fc355b9d 100644 --- a/src/components/ReIcon/src/hooks.ts +++ b/src/components/ReIcon/src/hooks.ts @@ -33,7 +33,7 @@ export function useRenderIcon(icon: any, attrs?: iconType): Component { }); } else if (typeof icon === "function" || typeof icon?.render === "function") { // svg - return icon; + return h(icon, { ...attrs }); } else if (typeof icon === "object") { return defineComponent({ name: "OfflineIcon", diff --git a/src/components/ReIcon/src/types.ts b/src/components/ReIcon/src/types.ts index 8ae8a543c..000bdc594 100644 --- a/src/components/ReIcon/src/types.ts +++ b/src/components/ReIcon/src/types.ts @@ -13,7 +13,8 @@ export interface iconType { align?: string; onLoad?: Function; includes?: Function; - - // all icon + // svg 需要什么SVG属性自行添加 + fill?: string; + // all icon style?: object; } diff --git a/src/components/ReSegmented/src/index.css b/src/components/ReSegmented/src/index.css index 53eeba83e..22acb2b9f 100644 --- a/src/components/ReSegmented/src/index.css +++ b/src/components/ReSegmented/src/index.css @@ -6,7 +6,6 @@ color: rgba(0, 0, 0, 0.65); background-color: rgb(0 0 0 / 4%); border-radius: 2px; - transition: all 0.2s cubic-bezier(0.645, 0.045, 0.355, 1); } .pure-segmented-group { @@ -43,7 +42,7 @@ text-align: center; cursor: pointer; border-radius: 4px; - transition: all 0.2s cubic-bezier(0.645, 0.045, 0.355, 1); + transition: all 0.1s cubic-bezier(0.645, 0.045, 0.355, 1); } .pure-segmented-item > div { diff --git a/src/components/ReSegmented/src/index.tsx b/src/components/ReSegmented/src/index.tsx index 8378f4ad6..41c08af18 100644 --- a/src/components/ReSegmented/src/index.tsx +++ b/src/components/ReSegmented/src/index.tsx @@ -121,7 +121,11 @@ export default defineComponent({ class="pure-segmented-item-icon" style={{ marginRight: option.label ? "6px" : 0 }} > - {h(useRenderIcon(option.icon))} + {h( + useRenderIcon(option.icon, { + ...option?.iconAttrs + }) + )} ) : null} {option.label ? ( diff --git a/src/components/ReSegmented/src/type.ts b/src/components/ReSegmented/src/type.ts index e96d8166c..0b6f5d432 100644 --- a/src/components/ReSegmented/src/type.ts +++ b/src/components/ReSegmented/src/type.ts @@ -1,4 +1,5 @@ import type { VNode, Component } from "vue"; +import type { iconType } from "@/components/ReIcon/src/types.ts"; export interface OptionsType { /** 文字 */ @@ -8,6 +9,8 @@ export interface OptionsType { * @see {@link 用法参考 https://yiming_chang.gitee.io/pure-admin-doc/pages/icon/#%E9%80%9A%E7%94%A8%E5%9B%BE%E6%A0%87-userendericon-hooks } */ icon?: string | Component; + /** 图标属性、样式配置 */ + iconAttrs?: iconType; /** 值 */ value?: string | number; /** 是否禁用 */ diff --git a/src/layout/components/panel/index.vue b/src/layout/components/panel/index.vue index 59001f08c..efbc04cdc 100644 --- a/src/layout/components/panel/index.vue +++ b/src/layout/components/panel/index.vue @@ -2,6 +2,7 @@ import { emitter } from "@/utils/mitt"; import { onClickOutside } from "@vueuse/core"; import { ref, computed, onMounted, onBeforeUnmount } from "vue"; +import { useDataThemeChange } from "@/layout/hooks/useDataThemeChange"; import Close from "@iconify-icons/ep/close"; const target = ref(null); @@ -9,7 +10,6 @@ const show = ref(false); const iconClass = computed(() => { return [ - "mr-[20px]", "outline-none", "width-[20px]", "height-[20px]", @@ -22,6 +22,8 @@ const iconClass = computed(() => { ]; }); +const { onReset } = useDataThemeChange(); + onClickOutside(target, (event: any) => { if (event.clientX > target.value.offsetLeft) return; show.value = false; @@ -43,23 +45,47 @@ onBeforeUnmount(() => {
-
-
-

项目配置

- - - -
-
+
+

项目配置

+ + + +
+ + + +
+ + 清空缓存 +
@@ -74,6 +100,10 @@ onBeforeUnmount(() => { diff --git a/src/layout/components/setting/index.vue b/src/layout/components/setting/index.vue index 8b3f8621d..1fc880f16 100644 --- a/src/layout/components/setting/index.vue +++ b/src/layout/components/setting/index.vue @@ -8,28 +8,22 @@ import { nextTick, onBeforeMount } from "vue"; -import { getConfig } from "@/config"; -import { useRouter } from "vue-router"; import panel from "../panel/index.vue"; import { emitter } from "@/utils/mitt"; -import { resetRouter } from "@/router"; -import { removeToken } from "@/utils/auth"; -import { routerArrays } from "@/layout/types"; import { useNav } from "@/layout/hooks/useNav"; import { useAppStoreHook } from "@/store/modules/app"; +import { useDark, debounce, useGlobal } from "@pureadmin/utils"; import { toggleTheme } from "@pureadmin/theme/dist/browser-utils"; import { useMultiTagsStoreHook } from "@/store/modules/multiTags"; +import Segmented, { type OptionsType } from "@/components/ReSegmented"; import { useDataThemeChange } from "@/layout/hooks/useDataThemeChange"; -import { useDark, debounce, useGlobal, storageLocal } from "@pureadmin/utils"; +import Check from "@iconify-icons/ep/check"; import dayIcon from "@/assets/svg/day.svg?component"; import darkIcon from "@/assets/svg/dark.svg?component"; -import Check from "@iconify-icons/ep/check"; -import Logout from "@iconify-icons/ri/logout-circle-r-line"; -const router = useRouter(); +const { device } = useNav(); const { isDark } = useDark(); -const { device, tooltipEffect } = useNav(); const { $storage } = useGlobal(); const mixRef = ref(); @@ -40,8 +34,8 @@ const { dataTheme, layoutTheme, themeColors, + toggleClass, dataThemeChange, - setEpThemeColor, setLayoutThemeColor } = useDataThemeChange(); @@ -89,13 +83,6 @@ function storageConfigureChange(key: string, val: T): void { $storage.configure = storageConfigure; } -function toggleClass(flag: boolean, clsName: string, target?: HTMLElement) { - const targetEl = target || document.body; - let { className } = targetEl; - className = className.replace(clsName, "").trim(); - targetEl.className = flag ? `${className} ${clsName} ` : className; -} - /** 灰色模式设置 */ const greyChange = (value): void => { toggleClass(settings.greyVal, "html-grey", document.querySelector("html")); @@ -132,24 +119,11 @@ const multiTagsCacheChange = () => { useMultiTagsStoreHook().multiTagsCacheChange(multiTagsCache); }; -/** 清空缓存并返回登录页 */ -function onReset() { - removeToken(); - storageLocal().clear(); - const { Grey, Weak, MultiTagsCache, EpThemeColor, Layout } = getConfig(); - useAppStoreHook().setLayout(Layout); - setEpThemeColor(EpThemeColor); - useMultiTagsStoreHook().multiTagsCacheChange(MultiTagsCache); - toggleClass(Grey, "html-grey", document.querySelector("html")); - toggleClass(Weak, "html-weakness", document.querySelector("html")); - router.push("/login"); - useMultiTagsStoreHook().handleTags("equal", [...routerArrays]); - resetRouter(); -} - -function onChange(label) { - storageConfigureChange("showModel", label); - emitter.emit("tagViewsShowModel", label); +function onChange({ option }) { + const { value } = option; + markValue.value = value; + storageConfigureChange("showModel", value); + emitter.emit("tagViewsShowModel", value); } /** 侧边栏Logo */ @@ -185,6 +159,32 @@ const getThemeColor = computed(() => { }; }); +const themeOptions = computed>(() => { + return [ + { + label: "亮色", + icon: dayIcon, + iconAttrs: { fill: isDark.value ? "#fff" : "#000" } + }, + { + label: "暗色", + icon: darkIcon, + iconAttrs: { fill: isDark.value ? "#fff" : "#000" } + } + ]; +}); + +const markOptions: Array = [ + { + label: "灵动", + value: "smart" + }, + { + label: "卡片", + value: "card" + } +]; + /** 设置导航模式 */ function setLayoutModel(layout: string) { layoutTheme.value.layout = layout; @@ -234,185 +234,153 @@ onBeforeMount(() => { @@ -422,41 +390,41 @@ onBeforeMount(() => { font-weight: 700; } -.is-select { - border: 2px solid var(--el-color-primary); +:deep(.el-switch__core) { + --el-switch-off-color: var(--pure-switch-off-color); + + min-width: 36px; + height: 18px; } -.setting { - width: 100%; +:deep(.el-switch__core .el-switch__action) { + height: 14px; +} + +.theme-color { + height: 20px; li { - display: flex; - align-items: center; - justify-content: space-between; - margin: 25px; - } -} + float: left; + height: 20px; + margin-right: 8px; + cursor: pointer; + border-radius: 4px; -.pure-datatheme { - display: block; - width: 100%; - height: 50px; - padding-top: 25px; - text-align: center; + &:nth-child(2) { + border: 1px solid #ddd; + } + } } .pure-theme { display: flex; - flex-wrap: wrap; - justify-content: space-around; - width: 100%; - height: 50px; - margin-top: 25px; + gap: 12px; li { position: relative; - width: 18%; - height: 45px; + width: 46px; + height: 36px; overflow: hidden; cursor: pointer; background: #f0f2f5; @@ -517,27 +485,17 @@ onBeforeMount(() => { } } -.theme-color { - display: flex; - justify-content: center; - width: 100%; - height: 40px; - margin-top: 20px; +.is-select { + border: 2px solid var(--el-color-primary); +} +.setting { li { - float: left; - width: 20px; - height: 20px; - margin-top: 8px; - margin-right: 8px; - font-weight: 700; - text-align: center; - cursor: pointer; - border-radius: 2px; - - &:nth-child(2) { - border: 1px solid #ddd; - } + display: flex; + align-items: center; + justify-content: space-between; + padding: 4px 0; + font-size: 14px; } } diff --git a/src/layout/hooks/useDataThemeChange.ts b/src/layout/hooks/useDataThemeChange.ts index c0d3f6e93..e92d8d57d 100644 --- a/src/layout/hooks/useDataThemeChange.ts +++ b/src/layout/hooks/useDataThemeChange.ts @@ -1,9 +1,14 @@ import { ref } from "vue"; import { getConfig } from "@/config"; import { useLayout } from "./useLayout"; -import { useGlobal } from "@pureadmin/utils"; +import { removeToken } from "@/utils/auth"; +import { routerArrays } from "@/layout/types"; +import { router, resetRouter } from "@/router"; import type { themeColorsType } from "../types"; +import { useAppStoreHook } from "@/store/modules/app"; +import { useGlobal, storageLocal } from "@pureadmin/utils"; import { useEpThemeStoreHook } from "@/store/modules/epTheme"; +import { useMultiTagsStoreHook } from "@/store/modules/multiTags"; import { darken, lighten, @@ -37,6 +42,13 @@ export function useDataThemeChange() { const dataTheme = ref($storage?.layout?.darkMode); const body = document.documentElement as HTMLElement; + function toggleClass(flag: boolean, clsName: string, target?: HTMLElement) { + const targetEl = target || document.body; + let { className } = targetEl; + className = className.replace(clsName, "").trim(); + targetEl.className = flag ? `${className} ${clsName} ` : className; + } + /** 设置导航主题色 */ function setLayoutThemeColor(theme = getConfig().Theme ?? "default") { layoutTheme.value.theme = theme; @@ -78,9 +90,8 @@ export function useDataThemeChange() { } }; - /** 日间、夜间主题切换 */ + /** 亮色、暗色整体风格切换 */ function dataThemeChange() { - /* 如果当前是light夜间主题,默认切换到default主题 */ if (useEpThemeStoreHook().epTheme === "light" && dataTheme.value) { setLayoutThemeColor("default"); } else { @@ -94,11 +105,28 @@ export function useDataThemeChange() { } } + /** 清空缓存并返回登录页 */ + function onReset() { + removeToken(); + storageLocal().clear(); + const { Grey, Weak, MultiTagsCache, EpThemeColor, Layout } = getConfig(); + useAppStoreHook().setLayout(Layout); + setEpThemeColor(EpThemeColor); + useMultiTagsStoreHook().multiTagsCacheChange(MultiTagsCache); + toggleClass(Grey, "html-grey", document.querySelector("html")); + toggleClass(Weak, "html-weakness", document.querySelector("html")); + router.push("/login"); + useMultiTagsStoreHook().handleTags("equal", [...routerArrays]); + resetRouter(); + } + return { body, dataTheme, layoutTheme, themeColors, + onReset, + toggleClass, dataThemeChange, setEpThemeColor, setLayoutThemeColor diff --git a/src/main.ts b/src/main.ts index 31446af9f..55865c7b2 100644 --- a/src/main.ts +++ b/src/main.ts @@ -45,6 +45,14 @@ app.component("FontIcon", FontIcon); import { Auth } from "@/components/ReAuth"; app.component("Auth", Auth); +// 全局注册`vue-tippy` +import "tippy.js/dist/tippy.css"; +import "tippy.js/animations/perspective.css"; +import VueTippy from "vue-tippy"; +app.use(VueTippy, { + defaultProps: { animation: "perspective" } +}); + getPlatformConfig(app).then(async config => { setupStore(app); app.use(router); diff --git a/src/style/dark.scss b/src/style/dark.scss index 43f9da6be..77568ac27 100644 --- a/src/style/dark.scss +++ b/src/style/dark.scss @@ -2,11 +2,18 @@ /* 暗黑模式适配 */ html.dark { - /* 自定义深色背景颜色 */ - // --el-bg-color: #020409; $border-style: #303030; $color-white: #fff; + /* 自定义深色背景颜色 */ + // --el-bg-color: #020409; + + /* 常用border-color 需要时可取用 */ + --pure-border-color: rgb(253 253 253 / 12%); + + /* switch关闭状态下的color 需要时可取用 */ + --pure-switch-off-color: #ffffff3f; + .navbar, .tags-view, .contextmenu, diff --git a/src/style/element-plus.scss b/src/style/element-plus.scss index 460f0d9f9..3fea90802 100644 --- a/src/style/element-plus.scss +++ b/src/style/element-plus.scss @@ -50,12 +50,6 @@ padding: 0 !important; } -/* 自定义 tooltip 的类名 */ -.pure-tooltip { - // 右侧操作面板right-panel类名的z-index为40000,tooltip需要大于它才能显示 - z-index: 41000 !important; -} - /* nprogress 适配 element-plus 的主题色 */ #nprogress { & .bar { diff --git a/src/style/index.scss b/src/style/index.scss index b6ffa29a8..d267d389c 100644 --- a/src/style/index.scss +++ b/src/style/index.scss @@ -7,6 +7,12 @@ :root { /* 左侧菜单展开、收起动画时长 */ --pure-transition-duration: 0.3s; + + /* 常用border-color 需要时可取用 */ + --pure-border-color: rgb(5 5 5 / 6%); + + /* switch关闭状态下的color 需要时可取用 */ + --pure-switch-off-color: #a6a6a6; } /* 灰色模式 */ diff --git a/src/views/able/wavesurfer/index.vue b/src/views/able/wavesurfer/index.vue index 299c1adb1..06a403d36 100644 --- a/src/views/able/wavesurfer/index.vue +++ b/src/views/able/wavesurfer/index.vue @@ -4,15 +4,10 @@ import { getTime } from "@pureadmin/utils"; import { Play, Pause, Forward, Rewind } from "./svg"; import { ref, onMounted, onBeforeUnmount } from "vue"; -import "tippy.js/dist/tippy.css"; -import "tippy.js/animations/scale.css"; -import { directive as tippy } from "vue-tippy"; - defineOptions({ name: "Wavesurfer" }); -const vTippy = tippy; const loading = ref(true); const wavesurfer = ref(null); const wavesurferRef = ref(); @@ -114,8 +109,7 @@ onBeforeUnmount(() => { {
{