mirror of
https://gitee.com/JavaLionLi/plus-ui.git
synced 2026-09-15 16:28:33 +08:00
Pre Merge pull request !280 from Lau/6.X-Vue
This commit is contained in:
commit
d398b1b9dc
@ -189,6 +189,7 @@ html.dark {
|
|||||||
// --- tags-view 与 app 壳变量(暗色) ---
|
// --- tags-view 与 app 壳变量(暗色) ---
|
||||||
--tags-view-active-bg: var(--el-color-primary-dark-6);
|
--tags-view-active-bg: var(--el-color-primary-dark-6);
|
||||||
--tags-view-active-border-color: var(--el-color-primary-light-2);
|
--tags-view-active-border-color: var(--el-color-primary-light-2);
|
||||||
|
--tags-view-chrome-tab-hover-bg: color-mix(in srgb, var(--el-color-primary) 14%, var(--app-surface-bg));
|
||||||
|
|
||||||
--app-shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.28);
|
--app-shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.28);
|
||||||
--app-shadow-md: 0 12px 28px rgba(0, 0, 0, 0.28);
|
--app-shadow-md: 0 12px 28px rgba(0, 0, 0, 0.28);
|
||||||
|
|||||||
@ -24,6 +24,7 @@
|
|||||||
|
|
||||||
--tags-view-active-bg: var(--el-color-primary);
|
--tags-view-active-bg: var(--el-color-primary);
|
||||||
--tags-view-active-border-color: var(--el-color-primary);
|
--tags-view-active-border-color: var(--el-color-primary);
|
||||||
|
--tags-view-chrome-tab-hover-bg: var(--el-color-primary-light-9);
|
||||||
|
|
||||||
// --- 应用壳:圆角、阴影、表面、导航、强调色与文案色 ---
|
// --- 应用壳:圆角、阴影、表面、导航、强调色与文案色 ---
|
||||||
--app-radius-sm: calc(var(--app-radius-base) - 8px);
|
--app-radius-sm: calc(var(--app-radius-base) - 8px);
|
||||||
|
|||||||
13
src/enums/TagsStyleEnum.ts
Normal file
13
src/enums/TagsStyleEnum.ts
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
/**
|
||||||
|
* 标签页样式枚举
|
||||||
|
*/
|
||||||
|
export enum TagsStyleEnum {
|
||||||
|
/**
|
||||||
|
* 按钮风格
|
||||||
|
*/
|
||||||
|
BUTTON = 'button',
|
||||||
|
/**
|
||||||
|
* 谷歌浏览器风格
|
||||||
|
*/
|
||||||
|
CHROME = 'chrome'
|
||||||
|
}
|
||||||
@ -133,6 +133,36 @@
|
|||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="drawer-item tags-style-item">
|
||||||
|
<span>标签页风格</span>
|
||||||
|
</div>
|
||||||
|
<div class="tags-style-wrap" :class="{ 'is-disabled': !settingsStore.tagsView }">
|
||||||
|
<el-tooltip content="按钮风格" placement="bottom">
|
||||||
|
<div
|
||||||
|
class="item button"
|
||||||
|
:style="{ '--theme': theme }"
|
||||||
|
:class="{ activeItem: tagsStyle === TagsStyleEnum.BUTTON }"
|
||||||
|
@click="handleTagsStyle(TagsStyleEnum.BUTTON)"
|
||||||
|
>
|
||||||
|
<b></b>
|
||||||
|
<b></b>
|
||||||
|
<b></b>
|
||||||
|
</div>
|
||||||
|
</el-tooltip>
|
||||||
|
<el-tooltip content="谷歌风格" placement="bottom">
|
||||||
|
<div
|
||||||
|
class="item chrome"
|
||||||
|
:style="{ '--theme': theme }"
|
||||||
|
:class="{ activeItem: tagsStyle === TagsStyleEnum.CHROME }"
|
||||||
|
@click="handleTagsStyle(TagsStyleEnum.CHROME)"
|
||||||
|
>
|
||||||
|
<b></b>
|
||||||
|
<b></b>
|
||||||
|
<b></b>
|
||||||
|
</div>
|
||||||
|
</el-tooltip>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="drawer-item">
|
<div class="drawer-item">
|
||||||
<span>固定 Header</span>
|
<span>固定 Header</span>
|
||||||
<span class="comp-style">
|
<span class="comp-style">
|
||||||
@ -171,6 +201,7 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { NavTypeEnum } from '@/enums/NavTypeEnum';
|
import { NavTypeEnum } from '@/enums/NavTypeEnum';
|
||||||
import { SideThemeEnum } from '@/enums/SideThemeEnum';
|
import { SideThemeEnum } from '@/enums/SideThemeEnum';
|
||||||
|
import { TagsStyleEnum } from '@/enums/TagsStyleEnum';
|
||||||
import modal from '@/plugins/modal';
|
import modal from '@/plugins/modal';
|
||||||
import defaultSettings from '@/settings';
|
import defaultSettings from '@/settings';
|
||||||
import { useAppStore } from '@/store/modules/app';
|
import { useAppStore } from '@/store/modules/app';
|
||||||
@ -189,6 +220,7 @@ const sideTheme = ref(settingsStore.sideTheme);
|
|||||||
const storeSettings = computed(() => settingsStore);
|
const storeSettings = computed(() => settingsStore);
|
||||||
const predefineColors = ref(['#409EFF', '#ff4500', '#ff8c00', '#ffd700', '#90ee90', '#00ced1', '#1e90ff', '#c71585']);
|
const predefineColors = ref(['#409EFF', '#ff4500', '#ff8c00', '#ffd700', '#90ee90', '#00ced1', '#1e90ff', '#c71585']);
|
||||||
const navType = ref(settingsStore.navType);
|
const navType = ref(settingsStore.navType);
|
||||||
|
const tagsStyle = ref(settingsStore.tagsStyle);
|
||||||
const radiusBase = ref(settingsStore.radiusBase);
|
const radiusBase = ref(settingsStore.radiusBase);
|
||||||
// 是否暗黑模式
|
// 是否暗黑模式
|
||||||
const isDark = useDark({
|
const isDark = useDark({
|
||||||
@ -228,6 +260,14 @@ const handleNavType = (val: NavTypeEnum) => {
|
|||||||
navType.value = val;
|
navType.value = val;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const handleTagsStyle = (val: TagsStyleEnum) => {
|
||||||
|
if (!settingsStore.tagsView) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
settingsStore.tagsStyle = val;
|
||||||
|
tagsStyle.value = val;
|
||||||
|
};
|
||||||
|
|
||||||
const dynamicTitleChange = () => {
|
const dynamicTitleChange = () => {
|
||||||
// 动态设置网页标题
|
// 动态设置网页标题
|
||||||
useDynamicTitle();
|
useDynamicTitle();
|
||||||
@ -260,6 +300,7 @@ const saveSetting = () => {
|
|||||||
settings.value.tagsView = storeSettings.value.tagsView;
|
settings.value.tagsView = storeSettings.value.tagsView;
|
||||||
settings.value.tagsViewPersist = storeSettings.value.tagsViewPersist;
|
settings.value.tagsViewPersist = storeSettings.value.tagsViewPersist;
|
||||||
settings.value.tagsIcon = storeSettings.value.tagsIcon;
|
settings.value.tagsIcon = storeSettings.value.tagsIcon;
|
||||||
|
settings.value.tagsStyle = storeSettings.value.tagsStyle;
|
||||||
settings.value.fixedHeader = storeSettings.value.fixedHeader;
|
settings.value.fixedHeader = storeSettings.value.fixedHeader;
|
||||||
settings.value.sidebarLogo = storeSettings.value.sidebarLogo;
|
settings.value.sidebarLogo = storeSettings.value.sidebarLogo;
|
||||||
settings.value.dynamicTitle = storeSettings.value.dynamicTitle;
|
settings.value.dynamicTitle = storeSettings.value.dynamicTitle;
|
||||||
@ -448,4 +489,105 @@ defineExpose({
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.tags-style-item {
|
||||||
|
padding-bottom: 0;
|
||||||
|
border-bottom: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tags-style-wrap {
|
||||||
|
display: flex;
|
||||||
|
justify-content: flex-start;
|
||||||
|
align-items: center;
|
||||||
|
margin-top: 4px;
|
||||||
|
margin-bottom: 12px;
|
||||||
|
padding-bottom: 12px;
|
||||||
|
border-bottom: 1px solid var(--app-surface-border);
|
||||||
|
|
||||||
|
&.is-disabled {
|
||||||
|
opacity: 0.5;
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.activeItem {
|
||||||
|
border: 2px solid #{'var(--theme)'} !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.item {
|
||||||
|
position: relative;
|
||||||
|
margin-right: 16px;
|
||||||
|
cursor: pointer;
|
||||||
|
width: 56px;
|
||||||
|
height: 36px;
|
||||||
|
border-radius: 8px;
|
||||||
|
background: var(--app-elevated-soft-bg);
|
||||||
|
border: 2px solid transparent;
|
||||||
|
overflow: hidden;
|
||||||
|
transition:
|
||||||
|
transform 0.2s ease,
|
||||||
|
border-color 0.2s ease;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
transform: translateY(-1px);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.button {
|
||||||
|
b {
|
||||||
|
position: absolute;
|
||||||
|
top: 14px;
|
||||||
|
width: 12px;
|
||||||
|
height: 14px;
|
||||||
|
border-radius: 4px;
|
||||||
|
background: var(--app-surface-bg);
|
||||||
|
border: 1px solid var(--app-surface-border);
|
||||||
|
}
|
||||||
|
|
||||||
|
b:nth-child(1) {
|
||||||
|
left: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
b:nth-child(2) {
|
||||||
|
left: 22px;
|
||||||
|
background: var(--theme, #409eff);
|
||||||
|
border-color: var(--theme, #409eff);
|
||||||
|
}
|
||||||
|
|
||||||
|
b:nth-child(3) {
|
||||||
|
left: 36px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.chrome {
|
||||||
|
background: var(--app-surface-bg);
|
||||||
|
border: 1px solid var(--app-surface-border);
|
||||||
|
|
||||||
|
b {
|
||||||
|
position: absolute;
|
||||||
|
bottom: 4px;
|
||||||
|
width: 14px;
|
||||||
|
height: 16px;
|
||||||
|
background: transparent;
|
||||||
|
border: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
b:nth-child(1) {
|
||||||
|
left: 6px;
|
||||||
|
border-right: 1px solid var(--app-surface-border);
|
||||||
|
}
|
||||||
|
|
||||||
|
b:nth-child(2) {
|
||||||
|
left: 18px;
|
||||||
|
width: 20px;
|
||||||
|
height: 18px;
|
||||||
|
background: var(--theme, #409eff);
|
||||||
|
border-radius: 4px 4px 2px 2px;
|
||||||
|
z-index: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
b:nth-child(3) {
|
||||||
|
left: 32px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<div id="tags-view-container" class="tags-view-container">
|
<div id="tags-view-container" class="tags-view-container" :class="`tags-style-${tagsStyle}`">
|
||||||
<span v-if="canScrollLeft" class="tags-nav-btn tags-nav-btn--left" @click="scrollLeft">
|
<span v-if="canScrollLeft" class="tags-nav-btn tags-nav-btn--left" @click="scrollLeft">
|
||||||
<el-icon><ArrowLeft /></el-icon>
|
<el-icon><ArrowLeft /></el-icon>
|
||||||
</span>
|
</span>
|
||||||
@ -16,10 +16,12 @@
|
|||||||
@click.middle="!isAffix(tag) ? closeSelectedTag(tag) : undefined"
|
@click.middle="!isAffix(tag) ? closeSelectedTag(tag) : undefined"
|
||||||
@contextmenu.prevent="openMenu(tag, $event)"
|
@contextmenu.prevent="openMenu(tag, $event)"
|
||||||
>
|
>
|
||||||
<svg-icon v-if="tagsIcon && tag.meta && tag.meta.icon && tag.meta.icon !== '#'" :icon-class="tag.meta.icon" />
|
<span class="tags-view-item-inner">
|
||||||
<span class="tags-view-item-title">{{ tag.title || tag.meta?.title }}</span>
|
<svg-icon v-if="tagsIcon && tag.meta && tag.meta.icon && tag.meta.icon !== '#'" :icon-class="tag.meta.icon" />
|
||||||
<span v-if="!isAffix(tag)" @click.prevent.stop="closeSelectedTag(tag)">
|
<span class="tags-view-item-title">{{ tag.title || tag.meta?.title }}</span>
|
||||||
<Close class="el-icon-close" style="width: 1em; height: 1em; vertical-align: middle" />
|
<span v-if="!isAffix(tag)" @click.prevent.stop="closeSelectedTag(tag)">
|
||||||
|
<Close class="el-icon-close" style="width: 1em; height: 1em; vertical-align: middle" />
|
||||||
|
</span>
|
||||||
</span>
|
</span>
|
||||||
</router-link>
|
</router-link>
|
||||||
</scroll-pane>
|
</scroll-pane>
|
||||||
@ -102,6 +104,7 @@ import {
|
|||||||
Right
|
Right
|
||||||
} from '@element-plus/icons-vue';
|
} from '@element-plus/icons-vue';
|
||||||
import tab from '@/plugins/tab';
|
import tab from '@/plugins/tab';
|
||||||
|
import { TagsStyleEnum } from '@/enums/TagsStyleEnum';
|
||||||
import { usePermissionStore } from '@/store/modules/permission';
|
import { usePermissionStore } from '@/store/modules/permission';
|
||||||
import { useSettingsStore } from '@/store/modules/settings';
|
import { useSettingsStore } from '@/store/modules/settings';
|
||||||
import { useTagsViewStore } from '@/store/modules/tagsView';
|
import { useTagsViewStore } from '@/store/modules/tagsView';
|
||||||
@ -128,6 +131,7 @@ const tagsViewStore = useTagsViewStore();
|
|||||||
const visitedViews = computed(() => tagsViewStore.getVisitedViews());
|
const visitedViews = computed(() => tagsViewStore.getVisitedViews());
|
||||||
const routes = computed(() => permissionStore.getRoutes());
|
const routes = computed(() => permissionStore.getRoutes());
|
||||||
const tagsIcon = computed(() => settingsStore.tagsIcon);
|
const tagsIcon = computed(() => settingsStore.tagsIcon);
|
||||||
|
const tagsStyle = computed(() => settingsStore.tagsStyle);
|
||||||
const selectedDropdownTag = computed<RouteLocationNormalized | undefined>(() => {
|
const selectedDropdownTag = computed<RouteLocationNormalized | undefined>(() => {
|
||||||
return visitedViews.value.find(tag => isActive(tag)) || selectedTag.value;
|
return visitedViews.value.find(tag => isActive(tag)) || selectedTag.value;
|
||||||
});
|
});
|
||||||
@ -161,6 +165,9 @@ const isActive = (currentRoute: RouteLocationNormalized): boolean => {
|
|||||||
|
|
||||||
const activeStyle = (tag: RouteLocationNormalized) => {
|
const activeStyle = (tag: RouteLocationNormalized) => {
|
||||||
if (!isActive(tag)) return {};
|
if (!isActive(tag)) return {};
|
||||||
|
if (tagsStyle.value === TagsStyleEnum.CHROME) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
return {
|
return {
|
||||||
backgroundColor: 'var(--tags-view-active-bg)',
|
backgroundColor: 'var(--tags-view-active-bg)',
|
||||||
borderColor: 'var(--tags-view-active-border-color)'
|
borderColor: 'var(--tags-view-active-border-color)'
|
||||||
@ -480,54 +487,22 @@ onBeforeUnmount(() => {
|
|||||||
.tags-view-container {
|
.tags-view-container {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: flex-start;
|
align-items: flex-start;
|
||||||
height: 38px;
|
|
||||||
width: 100%;
|
width: 100%;
|
||||||
background-color: var(--app-surface-bg);
|
|
||||||
border: 1px solid var(--app-surface-border);
|
|
||||||
border-radius: var(--app-radius-md);
|
|
||||||
box-shadow: var(--app-shadow-sm);
|
|
||||||
|
|
||||||
$btn-width: 26px;
|
|
||||||
$btn-hover-bg: var(--el-fill-color-light);
|
|
||||||
$btn-hover-color: var(--el-text-color-primary);
|
|
||||||
|
|
||||||
.tags-nav-btn {
|
.tags-nav-btn {
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
display: inline-flex;
|
display: inline-flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
width: $btn-width;
|
width: 26px;
|
||||||
height: 26px;
|
|
||||||
margin-top: 4px;
|
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
color: var(--app-text-muted);
|
color: var(--app-text-muted);
|
||||||
user-select: none;
|
user-select: none;
|
||||||
background-color: var(--app-surface-bg);
|
|
||||||
border: 1px solid var(--app-surface-border);
|
|
||||||
border-radius: var(--app-radius-md);
|
|
||||||
transition:
|
transition:
|
||||||
box-shadow 0.2s ease,
|
box-shadow 0.2s ease,
|
||||||
transform 0.2s ease,
|
transform 0.2s ease,
|
||||||
border-color 0.2s ease,
|
border-color 0.2s ease,
|
||||||
color 0.2s ease;
|
color 0.2s ease;
|
||||||
|
|
||||||
&:hover:not(.disabled) {
|
|
||||||
background: $btn-hover-bg;
|
|
||||||
color: $btn-hover-color;
|
|
||||||
border-color: var(--el-color-primary-light-5);
|
|
||||||
box-shadow: var(--app-shadow-sm);
|
|
||||||
transform: translateY(-1px);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.tags-nav-btn--left {
|
|
||||||
margin-left: 8px;
|
|
||||||
margin-right: 4px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.tags-nav-btn--right {
|
|
||||||
margin-left: 4px;
|
|
||||||
margin-right: 4px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.tags-view-wrapper {
|
.tags-view-wrapper {
|
||||||
@ -539,21 +514,133 @@ onBeforeUnmount(() => {
|
|||||||
align-items: center;
|
align-items: center;
|
||||||
position: relative;
|
position: relative;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
height: 26px;
|
|
||||||
line-height: 25px;
|
line-height: 25px;
|
||||||
background-color: var(--app-surface-bg);
|
|
||||||
border: 1px solid var(--app-surface-border);
|
|
||||||
color: var(--el-text-color-regular);
|
color: var(--el-text-color-regular);
|
||||||
padding: 0 8px;
|
padding: 0 8px;
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
margin-left: 5px;
|
|
||||||
margin-top: 4px;
|
|
||||||
border-radius: var(--app-radius-md);
|
|
||||||
transition:
|
transition:
|
||||||
box-shadow 0.2s ease,
|
box-shadow 0.2s ease,
|
||||||
transform 0.2s ease,
|
transform 0.2s ease,
|
||||||
border-color 0.2s ease,
|
border-color 0.2s ease,
|
||||||
color 0.2s ease;
|
color 0.2s ease;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.tags-view-item-title {
|
||||||
|
margin-left: 4px;
|
||||||
|
margin-right: 3px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tags-view-item-inner {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tags-action-dropdown {
|
||||||
|
flex-shrink: 0;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tags-action-btn {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
gap: 4px;
|
||||||
|
min-width: 26px;
|
||||||
|
cursor: pointer;
|
||||||
|
color: var(--app-text-muted);
|
||||||
|
user-select: none;
|
||||||
|
transition:
|
||||||
|
box-shadow 0.2s ease,
|
||||||
|
transform 0.2s ease,
|
||||||
|
border-color 0.2s ease,
|
||||||
|
color 0.2s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.contextmenu {
|
||||||
|
margin: 0;
|
||||||
|
background: var(--app-surface-bg);
|
||||||
|
z-index: 3000;
|
||||||
|
position: fixed;
|
||||||
|
list-style-type: none;
|
||||||
|
padding: 5px 0;
|
||||||
|
border-radius: var(--app-radius-md);
|
||||||
|
font-size: 12px;
|
||||||
|
font-weight: 400;
|
||||||
|
box-shadow: var(--app-shadow-md);
|
||||||
|
|
||||||
|
li {
|
||||||
|
margin: 0;
|
||||||
|
padding: 7px 16px;
|
||||||
|
cursor: pointer;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background: var(--el-fill-color-light);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.tags-style-button,
|
||||||
|
&.tags-style-chrome {
|
||||||
|
height: 38px;
|
||||||
|
align-items: center;
|
||||||
|
background-color: var(--app-surface-bg);
|
||||||
|
border: 1px solid var(--app-surface-border);
|
||||||
|
border-radius: var(--app-radius-md);
|
||||||
|
box-shadow: var(--app-shadow-sm);
|
||||||
|
|
||||||
|
.tags-nav-btn--left {
|
||||||
|
margin-left: 8px;
|
||||||
|
margin-right: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tags-nav-btn--right {
|
||||||
|
margin-left: 4px;
|
||||||
|
margin-right: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tags-nav-btn,
|
||||||
|
.tags-action-btn {
|
||||||
|
height: 26px;
|
||||||
|
background-color: var(--app-surface-bg);
|
||||||
|
border: 1px solid var(--app-surface-border);
|
||||||
|
border-radius: var(--app-radius-md);
|
||||||
|
|
||||||
|
&:hover:not(.disabled),
|
||||||
|
&:hover {
|
||||||
|
background: var(--el-fill-color-light);
|
||||||
|
color: var(--el-text-color-primary);
|
||||||
|
border-color: var(--el-color-primary-light-5);
|
||||||
|
box-shadow: var(--app-shadow-sm);
|
||||||
|
transform: translateY(-1px);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.tags-action-btn {
|
||||||
|
padding: 0 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tags-action-dropdown {
|
||||||
|
margin-left: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tags-refresh-btn {
|
||||||
|
width: auto;
|
||||||
|
font-size: 12px;
|
||||||
|
margin-left: 8px;
|
||||||
|
margin-right: 8px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.tags-style-button {
|
||||||
|
.tags-view-wrapper .tags-view-item {
|
||||||
|
height: 26px;
|
||||||
|
background-color: var(--app-surface-bg);
|
||||||
|
border: 1px solid var(--app-surface-border);
|
||||||
|
margin-left: 5px;
|
||||||
|
margin-top: 4px;
|
||||||
|
border-radius: var(--app-radius-md);
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
color: var(--el-color-primary);
|
color: var(--el-color-primary);
|
||||||
@ -586,82 +673,101 @@ onBeforeUnmount(() => {
|
|||||||
margin-right: 5px;
|
margin-right: 5px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&.active.has-icon::before {
|
||||||
|
content: none !important;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.tags-view-item.active.has-icon::before {
|
&.tags-style-chrome {
|
||||||
content: none !important;
|
.tags-view-wrapper {
|
||||||
}
|
align-self: stretch;
|
||||||
|
|
||||||
.tags-view-item-title {
|
:deep(.el-scrollbar__wrap) {
|
||||||
margin-left: 4px;
|
height: 34px;
|
||||||
margin-right: 3px;
|
align-items: flex-end;
|
||||||
}
|
}
|
||||||
|
|
||||||
.tags-action-dropdown {
|
.tags-view-item {
|
||||||
flex-shrink: 0;
|
height: 30px;
|
||||||
display: flex;
|
padding: 0 15px;
|
||||||
align-items: center;
|
background: transparent;
|
||||||
margin-top: 4px;
|
border: none;
|
||||||
margin-left: 4px;
|
border-radius: 12px 12px 0 0;
|
||||||
}
|
|
||||||
|
|
||||||
.tags-action-btn {
|
&:first-of-type {
|
||||||
display: inline-flex;
|
margin-left: 10px;
|
||||||
align-items: center;
|
}
|
||||||
justify-content: center;
|
|
||||||
gap: 4px;
|
|
||||||
min-width: $btn-width;
|
|
||||||
height: 26px;
|
|
||||||
padding: 0 8px;
|
|
||||||
cursor: pointer;
|
|
||||||
color: var(--app-text-muted);
|
|
||||||
user-select: none;
|
|
||||||
background-color: var(--app-surface-bg);
|
|
||||||
border: 1px solid var(--app-surface-border);
|
|
||||||
border-radius: var(--app-radius-md);
|
|
||||||
transition:
|
|
||||||
box-shadow 0.2s ease,
|
|
||||||
transform 0.2s ease,
|
|
||||||
border-color 0.2s ease,
|
|
||||||
color 0.2s ease;
|
|
||||||
|
|
||||||
&:hover {
|
&:last-of-type {
|
||||||
background: $btn-hover-bg;
|
margin-right: 10px;
|
||||||
color: $btn-hover-color;
|
}
|
||||||
border-color: var(--el-color-primary-light-5);
|
|
||||||
box-shadow: var(--app-shadow-sm);
|
|
||||||
transform: translateY(-1px);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.tags-refresh-btn {
|
&::before,
|
||||||
width: auto;
|
&::after {
|
||||||
font-size: 12px;
|
position: absolute;
|
||||||
margin-top: 4px;
|
bottom: 0;
|
||||||
margin-left: 8px;
|
content: '';
|
||||||
margin-right: 8px;
|
width: 20px;
|
||||||
}
|
height: 20px;
|
||||||
|
border-radius: 100%;
|
||||||
|
box-shadow: 0 0 0 30px transparent;
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
|
||||||
.contextmenu {
|
&::before {
|
||||||
margin: 0;
|
left: -20px;
|
||||||
background: var(--app-surface-bg);
|
clip-path: inset(50% -10px 0 50%);
|
||||||
z-index: 3000;
|
}
|
||||||
position: fixed;
|
|
||||||
list-style-type: none;
|
|
||||||
padding: 5px 0;
|
|
||||||
border-radius: var(--app-radius-md);
|
|
||||||
font-size: 12px;
|
|
||||||
font-weight: 400;
|
|
||||||
box-shadow: var(--app-shadow-md);
|
|
||||||
|
|
||||||
li {
|
&::after {
|
||||||
margin: 0;
|
right: -20px;
|
||||||
padding: 7px 16px;
|
clip-path: inset(50% 50% 0 -10px);
|
||||||
cursor: pointer;
|
}
|
||||||
|
|
||||||
&:hover {
|
.tags-view-item-inner {
|
||||||
background: var(--el-fill-color-light);
|
position: relative;
|
||||||
|
z-index: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:not(.active):not(:hover):not(:has(+ .tags-view-item.active)) {
|
||||||
|
background-image: linear-gradient(
|
||||||
|
to bottom,
|
||||||
|
transparent calc(50% - 8px),
|
||||||
|
var(--app-surface-border) calc(50% - 8px),
|
||||||
|
var(--app-surface-border) calc(50% + 8px),
|
||||||
|
transparent calc(50% + 8px)
|
||||||
|
);
|
||||||
|
background-size: 1px 100%;
|
||||||
|
background-position: right center;
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:hover:not(.active) {
|
||||||
|
z-index: 1;
|
||||||
|
color: var(--el-color-primary);
|
||||||
|
background-color: var(--tags-view-chrome-tab-hover-bg);
|
||||||
|
background-image: none;
|
||||||
|
|
||||||
|
&::before,
|
||||||
|
&::after {
|
||||||
|
box-shadow: 0 0 0 30px var(--tags-view-chrome-tab-hover-bg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.active {
|
||||||
|
z-index: 2;
|
||||||
|
font-weight: 500;
|
||||||
|
color: var(--el-color-white);
|
||||||
|
background-color: var(--tags-view-active-bg);
|
||||||
|
background-image: none;
|
||||||
|
|
||||||
|
&::before,
|
||||||
|
&::after {
|
||||||
|
box-shadow: 0 0 0 30px var(--tags-view-active-bg);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -696,6 +802,18 @@ onBeforeUnmount(() => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.tags-style-chrome .tags-view-item {
|
||||||
|
.el-icon-close:hover {
|
||||||
|
background-color: var(--app-elevated-close-hover-bg);
|
||||||
|
color: var(--app-text-title);
|
||||||
|
}
|
||||||
|
|
||||||
|
&.active .el-icon-close:hover {
|
||||||
|
background-color: rgba(255, 255, 255, 0.22);
|
||||||
|
color: var(--el-color-white);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
body.tags-fullscreen-mode {
|
body.tags-fullscreen-mode {
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
import { LanguageEnum } from '@/enums/LanguageEnum';
|
import { LanguageEnum } from '@/enums/LanguageEnum';
|
||||||
import { NavTypeEnum } from '@/enums/NavTypeEnum';
|
import { NavTypeEnum } from '@/enums/NavTypeEnum';
|
||||||
|
import { TagsStyleEnum } from '@/enums/TagsStyleEnum';
|
||||||
|
|
||||||
const setting: DefaultSettings = {
|
const setting: DefaultSettings = {
|
||||||
/**
|
/**
|
||||||
@ -38,6 +39,11 @@ const setting: DefaultSettings = {
|
|||||||
*/
|
*/
|
||||||
tagsIcon: true,
|
tagsIcon: true,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 标签页样式
|
||||||
|
*/
|
||||||
|
tagsStyle: TagsStyleEnum.BUTTON,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 是否固定头部
|
* 是否固定头部
|
||||||
*/
|
*/
|
||||||
|
|||||||
@ -2,6 +2,7 @@ import { useStorage } from '@vueuse/core';
|
|||||||
import { defineStore } from 'pinia';
|
import { defineStore } from 'pinia';
|
||||||
import { ref } from 'vue';
|
import { ref } from 'vue';
|
||||||
import { NavTypeEnum } from '@/enums/NavTypeEnum';
|
import { NavTypeEnum } from '@/enums/NavTypeEnum';
|
||||||
|
import { TagsStyleEnum } from '@/enums/TagsStyleEnum';
|
||||||
import defaultSettings from '@/settings';
|
import defaultSettings from '@/settings';
|
||||||
import { useDynamicTitle } from '@/utils/dynamicTitle';
|
import { useDynamicTitle } from '@/utils/dynamicTitle';
|
||||||
|
|
||||||
@ -10,6 +11,7 @@ export const useSettingsStore = defineStore('setting', () => {
|
|||||||
tagsView: defaultSettings.tagsView,
|
tagsView: defaultSettings.tagsView,
|
||||||
tagsViewPersist: defaultSettings.tagsViewPersist,
|
tagsViewPersist: defaultSettings.tagsViewPersist,
|
||||||
tagsIcon: defaultSettings.tagsIcon,
|
tagsIcon: defaultSettings.tagsIcon,
|
||||||
|
tagsStyle: defaultSettings.tagsStyle,
|
||||||
fixedHeader: defaultSettings.fixedHeader,
|
fixedHeader: defaultSettings.fixedHeader,
|
||||||
sidebarLogo: defaultSettings.sidebarLogo,
|
sidebarLogo: defaultSettings.sidebarLogo,
|
||||||
dynamicTitle: defaultSettings.dynamicTitle,
|
dynamicTitle: defaultSettings.dynamicTitle,
|
||||||
@ -26,6 +28,7 @@ export const useSettingsStore = defineStore('setting', () => {
|
|||||||
const tagsView = ref<boolean>(storageSetting.value.tagsView);
|
const tagsView = ref<boolean>(storageSetting.value.tagsView);
|
||||||
const tagsViewPersist = ref<boolean>(storageSetting.value.tagsViewPersist);
|
const tagsViewPersist = ref<boolean>(storageSetting.value.tagsViewPersist);
|
||||||
const tagsIcon = ref<boolean>(storageSetting.value.tagsIcon);
|
const tagsIcon = ref<boolean>(storageSetting.value.tagsIcon);
|
||||||
|
const tagsStyle = ref<TagsStyleEnum>(storageSetting.value.tagsStyle || TagsStyleEnum.BUTTON);
|
||||||
const fixedHeader = ref<boolean>(storageSetting.value.fixedHeader);
|
const fixedHeader = ref<boolean>(storageSetting.value.fixedHeader);
|
||||||
const sidebarLogo = ref<boolean>(storageSetting.value.sidebarLogo);
|
const sidebarLogo = ref<boolean>(storageSetting.value.sidebarLogo);
|
||||||
const dynamicTitle = ref<boolean>(storageSetting.value.dynamicTitle);
|
const dynamicTitle = ref<boolean>(storageSetting.value.dynamicTitle);
|
||||||
@ -47,6 +50,7 @@ export const useSettingsStore = defineStore('setting', () => {
|
|||||||
tagsView,
|
tagsView,
|
||||||
tagsViewPersist,
|
tagsViewPersist,
|
||||||
tagsIcon,
|
tagsIcon,
|
||||||
|
tagsStyle,
|
||||||
fixedHeader,
|
fixedHeader,
|
||||||
sidebarLogo,
|
sidebarLogo,
|
||||||
dynamicTitle,
|
dynamicTitle,
|
||||||
|
|||||||
5
src/types/global.d.ts
vendored
5
src/types/global.d.ts
vendored
@ -1,6 +1,7 @@
|
|||||||
import type { ComponentInternalInstance as ComponentInstance } from 'vue';
|
import type { ComponentInternalInstance as ComponentInstance } from 'vue';
|
||||||
import { LanguageEnum } from '@/enums/LanguageEnum';
|
import { LanguageEnum } from '@/enums/LanguageEnum';
|
||||||
import { NavTypeEnum } from '@/enums/NavTypeEnum';
|
import { NavTypeEnum } from '@/enums/NavTypeEnum';
|
||||||
|
import { TagsStyleEnum } from '@/enums/TagsStyleEnum';
|
||||||
|
|
||||||
declare global {
|
declare global {
|
||||||
/** vue Instance */
|
/** vue Instance */
|
||||||
@ -107,6 +108,10 @@ declare global {
|
|||||||
* 显示页签图标
|
* 显示页签图标
|
||||||
*/
|
*/
|
||||||
tagsIcon: boolean;
|
tagsIcon: boolean;
|
||||||
|
/**
|
||||||
|
* 标签页样式
|
||||||
|
*/
|
||||||
|
tagsStyle: TagsStyleEnum;
|
||||||
/**
|
/**
|
||||||
* 是否固定头部
|
* 是否固定头部
|
||||||
*/
|
*/
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user