mirror of
https://github.com/pure-admin/pure-admin-thin.git
synced 2025-04-24 23:47:17 +08:00
release: update 5.7.0
This commit is contained in:
parent
0a57ad7920
commit
7640f97a36
1
.vscode/extensions.json
vendored
1
.vscode/extensions.json
vendored
@ -1,6 +1,7 @@
|
||||
{
|
||||
"recommendations": [
|
||||
"christian-kohler.path-intellisense",
|
||||
"warmthsea.vscode-custom-code-color",
|
||||
"vscode-icons-team.vscode-icons",
|
||||
"davidanson.vscode-markdownlint",
|
||||
"ms-azuretools.vscode-docker",
|
||||
|
13
.vscode/settings.json
vendored
13
.vscode/settings.json
vendored
@ -27,5 +27,16 @@
|
||||
"editor.codeActionsOnSave": {
|
||||
"source.fixAll.eslint": "explicit"
|
||||
},
|
||||
"iconify.excludes": ["el"]
|
||||
"iconify.excludes": [
|
||||
"el"
|
||||
],
|
||||
"vscodeCustomCodeColor.highlightValue": [
|
||||
"v-loading",
|
||||
"v-auth",
|
||||
"v-copy",
|
||||
"v-longpress",
|
||||
"v-optimize",
|
||||
"v-ripple"
|
||||
],
|
||||
"vscodeCustomCodeColor.highlightValueColor": "#b392f0",
|
||||
}
|
@ -4,6 +4,7 @@ import { viteBuildInfo } from "./info";
|
||||
import svgLoader from "vite-svg-loader";
|
||||
import type { PluginOption } from "vite";
|
||||
import vueJsx from "@vitejs/plugin-vue-jsx";
|
||||
import Inspector from "vite-plugin-vue-inspector";
|
||||
import { configCompressPlugin } from "./compress";
|
||||
import removeNoMatch from "vite-plugin-router-warn";
|
||||
import { visualizer } from "rollup-plugin-visualizer";
|
||||
@ -21,6 +22,8 @@ export function getPluginsList(
|
||||
vue(),
|
||||
// jsx、tsx语法支持
|
||||
vueJsx(),
|
||||
// 按下Command(⌘)+Shift(⇧),然后点击页面元素会自动打开本地IDE并跳转到对应的代码位置
|
||||
Inspector(),
|
||||
viteBuildInfo(),
|
||||
/**
|
||||
* 开发环境下移除非必要的vue-router动态路由警告No match found for location with path
|
||||
|
45
package.json
45
package.json
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "pure-admin-thin",
|
||||
"version": "5.6.0",
|
||||
"version": "5.7.0",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
@ -52,19 +52,19 @@
|
||||
"@pureadmin/table": "^3.1.2",
|
||||
"@pureadmin/utils": "^2.4.7",
|
||||
"@vueuse/core": "^10.10.0",
|
||||
"@vueuse/motion": "^2.1.0",
|
||||
"@vueuse/motion": "^2.2.3",
|
||||
"animate.css": "^4.1.1",
|
||||
"axios": "^1.7.2",
|
||||
"dayjs": "^1.11.11",
|
||||
"echarts": "^5.5.0",
|
||||
"element-plus": "^2.7.3",
|
||||
"element-plus": "^2.7.4",
|
||||
"js-cookie": "^3.0.5",
|
||||
"localforage": "^1.10.0",
|
||||
"mitt": "^3.0.1",
|
||||
"nprogress": "^0.2.0",
|
||||
"path": "^0.12.7",
|
||||
"pinia": "^2.1.7",
|
||||
"pinyin-pro": "^3.21.0",
|
||||
"pinyin-pro": "^3.21.1",
|
||||
"qs": "^6.12.1",
|
||||
"responsive-storage": "^2.2.0",
|
||||
"sortablejs": "^1.15.2",
|
||||
@ -77,7 +77,7 @@
|
||||
"@commitlint/cli": "^19.3.0",
|
||||
"@commitlint/config-conventional": "^19.2.2",
|
||||
"@commitlint/types": "^19.0.3",
|
||||
"@eslint/js": "^9.3.0",
|
||||
"@eslint/js": "^9.4.0",
|
||||
"@faker-js/faker": "^8.4.1",
|
||||
"@iconify-icons/ep": "^1.2.12",
|
||||
"@iconify-icons/ri": "^1.2.10",
|
||||
@ -85,18 +85,18 @@
|
||||
"@pureadmin/theme": "^3.2.0",
|
||||
"@types/gradient-string": "^1.1.6",
|
||||
"@types/js-cookie": "^3.0.6",
|
||||
"@types/node": "^20.12.12",
|
||||
"@types/node": "^20.14.2",
|
||||
"@types/nprogress": "^0.2.3",
|
||||
"@types/qs": "^6.9.15",
|
||||
"@types/sortablejs": "^1.15.8",
|
||||
"@typescript-eslint/eslint-plugin": "^7.11.0",
|
||||
"@typescript-eslint/parser": "^7.11.0",
|
||||
"@vitejs/plugin-vue": "^5.0.4",
|
||||
"@vitejs/plugin-vue-jsx": "^3.1.0",
|
||||
"@typescript-eslint/eslint-plugin": "^7.12.0",
|
||||
"@typescript-eslint/parser": "^7.12.0",
|
||||
"@vitejs/plugin-vue": "^5.0.5",
|
||||
"@vitejs/plugin-vue-jsx": "^4.0.0",
|
||||
"autoprefixer": "^10.4.19",
|
||||
"boxen": "^7.1.1",
|
||||
"cssnano": "^7.0.1",
|
||||
"eslint": "^9.3.0",
|
||||
"cssnano": "^7.0.2",
|
||||
"eslint": "^9.4.0",
|
||||
"eslint-config-prettier": "^9.1.0",
|
||||
"eslint-define-config": "^2.1.0",
|
||||
"eslint-plugin-prettier": "^5.1.3",
|
||||
@ -108,26 +108,27 @@
|
||||
"postcss-html": "^1.7.0",
|
||||
"postcss-import": "^16.1.0",
|
||||
"postcss-scss": "^4.0.9",
|
||||
"prettier": "^3.2.5",
|
||||
"prettier": "^3.3.1",
|
||||
"rimraf": "^5.0.7",
|
||||
"rollup-plugin-visualizer": "^5.12.0",
|
||||
"sass": "^1.77.2",
|
||||
"stylelint": "^16.6.0",
|
||||
"sass": "^1.77.4",
|
||||
"stylelint": "^16.6.1",
|
||||
"stylelint-config-recess-order": "^5.0.1",
|
||||
"stylelint-config-recommended-vue": "^1.5.0",
|
||||
"stylelint-config-standard-scss": "^13.1.0",
|
||||
"stylelint-prettier": "^5.0.0",
|
||||
"svgo": "^3.3.2",
|
||||
"tailwindcss": "^3.4.3",
|
||||
"tailwindcss": "^3.4.4",
|
||||
"typescript": "^5.4.5",
|
||||
"vite": "^5.2.11",
|
||||
"vite": "^5.2.12",
|
||||
"vite-plugin-cdn-import": "^1.0.1",
|
||||
"vite-plugin-compression": "^0.5.1",
|
||||
"vite-plugin-fake-server": "^2.1.1",
|
||||
"vite-plugin-remove-console": "^2.2.0",
|
||||
"vite-plugin-router-warn": "^1.0.0",
|
||||
"vite-plugin-vue-inspector": "^5.1.2",
|
||||
"vite-svg-loader": "^5.1.0",
|
||||
"vue-eslint-parser": "^9.4.2",
|
||||
"vue-eslint-parser": "^9.4.3",
|
||||
"vue-tsc": "^1.8.27"
|
||||
},
|
||||
"engines": {
|
||||
@ -136,11 +137,17 @@
|
||||
},
|
||||
"pnpm": {
|
||||
"allowedDeprecatedVersions": {
|
||||
"are-we-there-yet": "*",
|
||||
"sourcemap-codec": "*",
|
||||
"domexception": "*",
|
||||
"w3c-hr-time": "*",
|
||||
"inflight": "*",
|
||||
"npmlog": "*",
|
||||
"rimraf": "*",
|
||||
"stable": "*",
|
||||
"abab": "*"
|
||||
"gauge": "*",
|
||||
"abab": "*",
|
||||
"glob": "*"
|
||||
},
|
||||
"peerDependencyRules": {
|
||||
"allowedVersions": {
|
||||
|
1168
pnpm-lock.yaml
generated
1168
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
@ -1,5 +1,5 @@
|
||||
{
|
||||
"Version": "5.6.0",
|
||||
"Version": "5.7.0",
|
||||
"Title": "PureAdmin",
|
||||
"FixedHeader": true,
|
||||
"HiddenSideBar": false,
|
||||
|
@ -2,7 +2,7 @@ import { hasAuth } from "@/router/utils";
|
||||
import type { Directive, DirectiveBinding } from "vue";
|
||||
|
||||
export const auth: Directive = {
|
||||
mounted(el: HTMLElement, binding: DirectiveBinding) {
|
||||
mounted(el: HTMLElement, binding: DirectiveBinding<string | Array<string>>) {
|
||||
const { value } = binding;
|
||||
if (value) {
|
||||
!hasAuth(value) && el.parentNode?.removeChild(el);
|
||||
|
@ -3,13 +3,13 @@ import { useEventListener } from "@vueuse/core";
|
||||
import { copyTextToClipboard } from "@pureadmin/utils";
|
||||
import type { Directive, DirectiveBinding } from "vue";
|
||||
|
||||
interface CopyEl extends HTMLElement {
|
||||
export interface CopyEl extends HTMLElement {
|
||||
copyValue: string;
|
||||
}
|
||||
|
||||
/** 文本复制指令(默认双击复制) */
|
||||
export const copy: Directive = {
|
||||
mounted(el: CopyEl, binding: DirectiveBinding) {
|
||||
mounted(el: CopyEl, binding: DirectiveBinding<string>) {
|
||||
const { value } = binding;
|
||||
if (value) {
|
||||
el.copyValue = value;
|
||||
|
@ -3,7 +3,7 @@ import type { Directive, DirectiveBinding } from "vue";
|
||||
import { subBefore, subAfter, isFunction } from "@pureadmin/utils";
|
||||
|
||||
export const longpress: Directive = {
|
||||
mounted(el: HTMLElement, binding: DirectiveBinding) {
|
||||
mounted(el: HTMLElement, binding: DirectiveBinding<Function>) {
|
||||
const cb = binding.value;
|
||||
if (cb && isFunction(cb)) {
|
||||
let timer = null;
|
||||
|
@ -8,9 +8,22 @@ import {
|
||||
import { useEventListener } from "@vueuse/core";
|
||||
import type { Directive, DirectiveBinding } from "vue";
|
||||
|
||||
export interface OptimizeOptions {
|
||||
/** 事件名 */
|
||||
event: string;
|
||||
/** 事件触发的方法 */
|
||||
fn: (...params: any) => any;
|
||||
/** 是否立即执行 */
|
||||
immediate?: boolean;
|
||||
/** 防抖或节流的延迟时间(防抖默认:`200`毫秒、节流默认:`1000`毫秒) */
|
||||
timeout?: number;
|
||||
/** 传递的参数 */
|
||||
params?: any;
|
||||
}
|
||||
|
||||
/** 防抖(v-optimize或v-optimize:debounce)、节流(v-optimize:throttle)指令 */
|
||||
export const optimize: Directive = {
|
||||
mounted(el: HTMLElement, binding: DirectiveBinding) {
|
||||
mounted(el: HTMLElement, binding: DirectiveBinding<OptimizeOptions>) {
|
||||
const { value } = binding;
|
||||
const optimizeType = binding.arg ?? "debounce";
|
||||
const type = ["debounce", "throttle"].find(t => t === optimizeType);
|
||||
|
@ -2,8 +2,10 @@ import "./index.scss";
|
||||
import { isObject } from "@pureadmin/utils";
|
||||
import type { Directive, DirectiveBinding } from "vue";
|
||||
|
||||
interface RippleOptions {
|
||||
export interface RippleOptions {
|
||||
/** 自定义`ripple`颜色,支持`tailwindcss` */
|
||||
class?: string;
|
||||
/** 是否从中心扩散 */
|
||||
center?: boolean;
|
||||
circle?: boolean;
|
||||
}
|
||||
@ -220,13 +222,6 @@ function updated(el: HTMLElement, binding: RippleDirectiveBinding) {
|
||||
updateRipple(el, binding, wasEnabled);
|
||||
}
|
||||
|
||||
/**
|
||||
* @description 指令 v-ripple
|
||||
* @use 用法如下
|
||||
* 1. v-ripple 代表启用基本的 ripple 功能
|
||||
* 2. v-ripple="{ class: 'text-red' }" 代表自定义 ripple 颜色,支持 tailwindcss,生效样式是 color
|
||||
* 3. v-ripple.center 代表从中心扩散
|
||||
*/
|
||||
export const Ripple: Directive = {
|
||||
mounted,
|
||||
unmounted,
|
||||
|
@ -1,6 +1,7 @@
|
||||
<script setup lang="ts">
|
||||
import LayFrame from "../lay-frame/index.vue";
|
||||
import LayFooter from "../lay-footer/index.vue";
|
||||
import { useTags } from "@/layout/hooks/useTag";
|
||||
import { useGlobal, isNumber } from "@pureadmin/utils";
|
||||
import BackTopIcon from "@/assets/svg/back_top.svg?component";
|
||||
import { h, computed, Transition, defineComponent } from "vue";
|
||||
@ -10,6 +11,7 @@ const props = defineProps({
|
||||
fixedHeader: Boolean
|
||||
});
|
||||
|
||||
const { showModel } = useTags();
|
||||
const { $storage, $config } = useGlobal<GlobalPropertiesApi>();
|
||||
|
||||
const isKeepAlive = computed(() => {
|
||||
@ -49,9 +51,17 @@ const getMainWidth = computed(() => {
|
||||
const getSectionStyle = computed(() => {
|
||||
return [
|
||||
hideTabs.value && layout ? "padding-top: 48px;" : "",
|
||||
!hideTabs.value && layout ? "padding-top: 81px;" : "",
|
||||
!hideTabs.value && layout
|
||||
? showModel.value == "chrome"
|
||||
? "padding-top: 85px;"
|
||||
: "padding-top: 81px;"
|
||||
: "",
|
||||
hideTabs.value && !layout.value ? "padding-top: 48px;" : "",
|
||||
!hideTabs.value && !layout.value ? "padding-top: 81px;" : "",
|
||||
!hideTabs.value && !layout.value
|
||||
? showModel.value == "chrome"
|
||||
? "padding-top: 85px;"
|
||||
: "padding-top: 81px;"
|
||||
: "",
|
||||
props.fixedHeader
|
||||
? ""
|
||||
: `padding-top: 0;${
|
||||
|
@ -230,6 +230,11 @@ const markOptions = computed<Array<OptionsType>>(() => {
|
||||
label: "卡片",
|
||||
tip: "卡片标签,高效浏览",
|
||||
value: "card"
|
||||
},
|
||||
{
|
||||
label: "谷歌",
|
||||
tip: "谷歌风格,经典美观",
|
||||
value: "chrome"
|
||||
}
|
||||
];
|
||||
});
|
||||
@ -440,7 +445,7 @@ onUnmounted(() => removeMatchMedia);
|
||||
<Segmented
|
||||
resize
|
||||
class="select-none"
|
||||
:modelValue="markValue === 'smart' ? 0 : 1"
|
||||
:modelValue="markValue === 'smart' ? 0 : markValue === 'card' ? 1 : 2"
|
||||
:options="markOptions"
|
||||
@change="onChange"
|
||||
/>
|
||||
|
33
src/layout/components/lay-tag/components/TagChrome.vue
Normal file
33
src/layout/components/lay-tag/components/TagChrome.vue
Normal file
@ -0,0 +1,33 @@
|
||||
<template>
|
||||
<svg class="w-full h-full">
|
||||
<defs>
|
||||
<symbol id="geometry-left" viewBox="0 0 214 36">
|
||||
<path d="M17 0h197v36H0v-2c4.5 0 9-3.5 9-8V8c0-4.5 3.5-8 8-8z" />
|
||||
</symbol>
|
||||
<symbol id="geometry-right" viewBox="0 0 214 36">
|
||||
<use xlink:href="#geometry-left" />
|
||||
</symbol>
|
||||
<clipPath>
|
||||
<rect width="100%" height="100%" x="0" />
|
||||
</clipPath>
|
||||
</defs>
|
||||
<svg width="51%" height="100%">
|
||||
<use
|
||||
xlink:href="#geometry-left"
|
||||
width="214"
|
||||
height="36"
|
||||
fill="currentColor"
|
||||
/>
|
||||
</svg>
|
||||
<g transform="scale(-1, 1)">
|
||||
<svg width="51%" height="100%" x="-100%" y="0">
|
||||
<use
|
||||
xlink:href="#geometry-right"
|
||||
width="214"
|
||||
height="36"
|
||||
fill="currentColor"
|
||||
/>
|
||||
</svg>
|
||||
</g>
|
||||
</svg>
|
||||
</template>
|
@ -41,6 +41,13 @@
|
||||
padding-right: 24px;
|
||||
}
|
||||
|
||||
&.chrome-item {
|
||||
padding-right: 0;
|
||||
padding-left: 0;
|
||||
margin-right: -18px;
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
.el-icon-close {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
@ -76,6 +83,14 @@
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
|
||||
&.chrome-scroll-container {
|
||||
padding-top: 4px;
|
||||
|
||||
.fixed-tag {
|
||||
padding: 0 !important;
|
||||
}
|
||||
}
|
||||
|
||||
.tab {
|
||||
position: relative;
|
||||
float: left;
|
||||
@ -89,6 +104,12 @@
|
||||
&:nth-child(1) {
|
||||
padding: 0 12px;
|
||||
}
|
||||
|
||||
&.chrome-item {
|
||||
&:nth-child(1) {
|
||||
padding: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.fixed-tag {
|
||||
@ -173,9 +194,29 @@
|
||||
color: #fff;
|
||||
box-shadow: 0 0 0.7px #888;
|
||||
|
||||
.chrome-tab {
|
||||
z-index: 10;
|
||||
}
|
||||
|
||||
.chrome-tab__bg {
|
||||
color: var(--el-color-primary-light-9) !important;
|
||||
}
|
||||
|
||||
.tag-title {
|
||||
color: var(--el-color-primary) !important;
|
||||
}
|
||||
|
||||
.chrome-close-btn {
|
||||
color: var(--el-color-primary);
|
||||
|
||||
&:hover {
|
||||
background-color: var(--el-color-primary);
|
||||
}
|
||||
}
|
||||
|
||||
.chrome-tab-divider {
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.arrow-left,
|
||||
@ -262,3 +303,69 @@
|
||||
background: var(--el-color-primary);
|
||||
animation: schedule-out-width 200ms ease-in;
|
||||
}
|
||||
|
||||
/* 谷歌风格的页签 */
|
||||
.chrome-tab {
|
||||
position: relative;
|
||||
display: inline-flex;
|
||||
gap: 16px;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 0 24px;
|
||||
white-space: nowrap;
|
||||
cursor: pointer;
|
||||
|
||||
.tag-title {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.chrome-tab-divider {
|
||||
position: absolute;
|
||||
right: 7px;
|
||||
width: 1px;
|
||||
height: 14px;
|
||||
background-color: #2b2d2f;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
z-index: 10;
|
||||
|
||||
.chrome-tab__bg {
|
||||
color: #dee1e6;
|
||||
}
|
||||
|
||||
.tag-title {
|
||||
color: #1f1f1f;
|
||||
}
|
||||
|
||||
.chrome-tab-divider {
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.chrome-tab__bg {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
z-index: -10;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
color: transparent;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.chrome-close-btn {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
color: #666;
|
||||
border-radius: 50%;
|
||||
|
||||
&:hover {
|
||||
color: white;
|
||||
background-color: #b1b3b8;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -4,6 +4,7 @@ import { RouteConfigs } from "../../types";
|
||||
import { useTags } from "../../hooks/useTag";
|
||||
import { routerArrays } from "@/layout/types";
|
||||
import { onClickOutside } from "@vueuse/core";
|
||||
import TagChrome from "./components/TagChrome.vue";
|
||||
import { handleAliveRoute, getTopMenu } from "@/router/utils";
|
||||
import { useSettingStoreHook } from "@/store/modules/settings";
|
||||
import { useMultiTagsStoreHook } from "@/store/modules/multiTags";
|
||||
@ -563,6 +564,7 @@ onBeforeUnmount(() => {
|
||||
<div
|
||||
ref="scrollbarDom"
|
||||
class="scroll-container"
|
||||
:class="showModel === 'chrome' && 'chrome-scroll-container'"
|
||||
@wheel.prevent="handleWheel"
|
||||
>
|
||||
<div ref="tabDom" class="tab select-none" :style="getTabStyle">
|
||||
@ -573,6 +575,7 @@ onBeforeUnmount(() => {
|
||||
:class="[
|
||||
'scroll-item is-closable',
|
||||
linkIsActive(item),
|
||||
showModel === 'chrome' && 'chrome-item',
|
||||
!isAllEmpty(item?.meta?.fixedTag) && 'fixed-tag'
|
||||
]"
|
||||
@contextmenu.prevent="openMenu(item, $event)"
|
||||
@ -580,28 +583,46 @@ onBeforeUnmount(() => {
|
||||
@mouseleave.prevent="onMouseleave(index)"
|
||||
@click="tagOnClick(item)"
|
||||
>
|
||||
<span
|
||||
class="tag-title dark:!text-text_color_primary dark:hover:!text-primary"
|
||||
>
|
||||
{{ item.meta.title }}
|
||||
</span>
|
||||
<span
|
||||
v-if="
|
||||
isAllEmpty(item?.meta?.fixedTag)
|
||||
? iconIsActive(item, index) ||
|
||||
(index === activeIndex && index !== 0)
|
||||
: false
|
||||
"
|
||||
class="el-icon-close"
|
||||
@click.stop="deleteMenu(item)"
|
||||
>
|
||||
<IconifyIconOffline :icon="Close" />
|
||||
</span>
|
||||
<span
|
||||
v-if="showModel !== 'card'"
|
||||
:ref="'schedule' + index"
|
||||
:class="[scheduleIsActive(item)]"
|
||||
/>
|
||||
<template v-if="showModel !== 'chrome'">
|
||||
<span
|
||||
class="tag-title dark:!text-text_color_primary dark:hover:!text-primary"
|
||||
>
|
||||
{{ item.meta.title }}
|
||||
</span>
|
||||
<span
|
||||
v-if="
|
||||
isAllEmpty(item?.meta?.fixedTag)
|
||||
? iconIsActive(item, index) ||
|
||||
(index === activeIndex && index !== 0)
|
||||
: false
|
||||
"
|
||||
class="el-icon-close"
|
||||
@click.stop="deleteMenu(item)"
|
||||
>
|
||||
<IconifyIconOffline :icon="Close" />
|
||||
</span>
|
||||
<span
|
||||
v-if="showModel !== 'card'"
|
||||
:ref="'schedule' + index"
|
||||
:class="[scheduleIsActive(item)]"
|
||||
/>
|
||||
</template>
|
||||
<div v-else class="chrome-tab">
|
||||
<div class="chrome-tab__bg">
|
||||
<TagChrome />
|
||||
</div>
|
||||
<span class="tag-title">
|
||||
{{ item.meta.title }}
|
||||
</span>
|
||||
<span
|
||||
v-if="isAllEmpty(item?.meta?.fixedTag) ? index !== 0 : false"
|
||||
class="chrome-close-btn"
|
||||
@click.stop="deleteMenu(item)"
|
||||
>
|
||||
<IconifyIconOffline :icon="Close" />
|
||||
</span>
|
||||
<span class="chrome-tab-divider" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -49,6 +49,22 @@ html.dark {
|
||||
background-color: rgb(255 255 255 / 12%);
|
||||
}
|
||||
}
|
||||
|
||||
.chrome-tab {
|
||||
.tag-title {
|
||||
color: #666;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
.chrome-tab__bg {
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.tag-title {
|
||||
color: #adadad;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
26
types/directives.d.ts
vendored
Normal file
26
types/directives.d.ts
vendored
Normal file
@ -0,0 +1,26 @@
|
||||
import type { Directive } from "vue";
|
||||
import type { CopyEl, OptimizeOptions, RippleOptions } from "@/directives";
|
||||
|
||||
declare module "vue" {
|
||||
export interface ComponentCustomProperties {
|
||||
/** `Loading` 动画加载指令,具体看:https://element-plus.org/zh-CN/component/loading.html#%E6%8C%87%E4%BB%A4 */
|
||||
vLoading: Directive<Element, boolean>;
|
||||
/** 按钮权限指令 */
|
||||
vAuth: Directive<HTMLElement, string | Array<string>>;
|
||||
/** 文本复制指令(默认双击复制) */
|
||||
vCopy: Directive<CopyEl, string>;
|
||||
/** 长按指令 */
|
||||
vLongpress: Directive<HTMLElement, Function>;
|
||||
/** 防抖、节流指令 */
|
||||
vOptimize: Directive<HTMLElement, OptimizeOptions>;
|
||||
/**
|
||||
* `v-ripple`指令,用法如下:
|
||||
* 1. `v-ripple`代表启用基本的`ripple`功能
|
||||
* 2. `v-ripple="{ class: 'text-red' }"`代表自定义`ripple`颜色,支持`tailwindcss`,生效样式是`color`
|
||||
* 3. `v-ripple.center`代表从中心扩散
|
||||
*/
|
||||
vRipple: Directive<HTMLElement, RippleOptions>;
|
||||
}
|
||||
}
|
||||
|
||||
export {};
|
Loading…
x
Reference in New Issue
Block a user