mirror of
https://github.com/pure-admin/vue-pure-admin.git
synced 2025-06-06 00:18:51 +08:00
parent
6971ba6c53
commit
d43316f7c9
@ -41,7 +41,7 @@ const permissionRouter = {
|
||||
title: "menus.permission",
|
||||
icon: "lollipop",
|
||||
i18n: true,
|
||||
rank: 3
|
||||
rank: 7
|
||||
},
|
||||
children: [
|
||||
{
|
||||
@ -72,7 +72,7 @@ const tabsRouter = {
|
||||
icon: "IF-team-icontabs",
|
||||
title: "menus.hstabs",
|
||||
i18n: true,
|
||||
rank: 8
|
||||
rank: 10
|
||||
},
|
||||
children: [
|
||||
{
|
||||
|
@ -52,10 +52,12 @@ import arrowRightSLine from "@iconify-icons/ri/arrow-right-s-line";
|
||||
import arrowLeftSLine from "@iconify-icons/ri/arrow-left-s-line";
|
||||
import logoutCircleRLine from "@iconify-icons/ri/logout-circle-r-line";
|
||||
import nodeTree from "@iconify-icons/ri/node-tree";
|
||||
import ubuntuFill from "@iconify-icons/ri/ubuntu-fill";
|
||||
addIcon("arrow-right-s-line", arrowRightSLine);
|
||||
addIcon("arrow-left-s-line", arrowLeftSLine);
|
||||
addIcon("logout-circle-r-line", logoutCircleRLine);
|
||||
addIcon("node-tree", nodeTree);
|
||||
addIcon("ubuntu-fill", ubuntuFill);
|
||||
|
||||
// Font Awesome 4
|
||||
import faUser from "@iconify-icons/fa/user";
|
||||
|
@ -5,6 +5,7 @@ import { routeMetaType } from "../types";
|
||||
import { transformI18n } from "/@/plugins/i18n";
|
||||
import { storageSession } from "/@/utils/storage";
|
||||
import { useAppStoreHook } from "/@/store/modules/app";
|
||||
import { remainingPaths } from "/@/router/modules/index";
|
||||
import { Title } from "../../../public/serverConfig.json";
|
||||
import { useEpThemeStoreHook } from "/@/store/modules/epTheme";
|
||||
import { remainingPaths } from "/@/router/modules/index";
|
||||
|
@ -32,7 +32,9 @@ export default {
|
||||
permissionPage: "Page Permission",
|
||||
permissionButton: "Button Permission",
|
||||
hstabs: "Tabs Operate",
|
||||
hsMenuTree: "Menu Tree",
|
||||
hsguide: "Guide",
|
||||
externalLink: "External Link"
|
||||
externalLink: "External Link",
|
||||
hsAble: "Able",
|
||||
hsMenuTree: "Menu Tree",
|
||||
hsWatermark: "Water Mark"
|
||||
};
|
||||
|
@ -32,7 +32,9 @@ export default {
|
||||
permissionPage: "页面权限",
|
||||
permissionButton: "按钮权限",
|
||||
hstabs: "标签页操作",
|
||||
hsMenuTree: "菜单树结构",
|
||||
hsguide: "引导页",
|
||||
externalLink: "外链"
|
||||
externalLink: "外链",
|
||||
hsAble: "功能",
|
||||
hsMenuTree: "菜单树结构",
|
||||
hsWatermark: "水印"
|
||||
};
|
||||
|
37
src/router/modules/able.ts
Normal file
37
src/router/modules/able.ts
Normal file
@ -0,0 +1,37 @@
|
||||
import { $t } from "/@/plugins/i18n";
|
||||
const Layout = () => import("/@/layout/index.vue");
|
||||
|
||||
const ableRouter = {
|
||||
path: "/able",
|
||||
name: "components",
|
||||
component: Layout,
|
||||
redirect: "/able/menuTree",
|
||||
meta: {
|
||||
icon: "ubuntu-fill",
|
||||
title: $t("menus.hsAble"),
|
||||
i18n: true,
|
||||
rank: 3
|
||||
},
|
||||
children: [
|
||||
{
|
||||
path: "/able/menuTree",
|
||||
name: "reMenuTree",
|
||||
component: () => import("/@/views/able/menu-tree.vue"),
|
||||
meta: {
|
||||
title: $t("menus.hsMenuTree"),
|
||||
i18n: true
|
||||
}
|
||||
},
|
||||
{
|
||||
path: "/able/watermark",
|
||||
name: "reWatermark",
|
||||
component: () => import("/@/views/able/watermark.vue"),
|
||||
meta: {
|
||||
title: $t("menus.hsWatermark"),
|
||||
i18n: true
|
||||
}
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
export default ableRouter;
|
@ -1,5 +1,5 @@
|
||||
import { $t } from "/@/plugins/i18n";
|
||||
import Layout from "/@/layout/index.vue";
|
||||
const Layout = () => import("/@/layout/index.vue");
|
||||
|
||||
const componentsRouter = {
|
||||
path: "/components",
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { $t } from "/@/plugins/i18n";
|
||||
import Layout from "/@/layout/index.vue";
|
||||
const Layout = () => import("/@/layout/index.vue");
|
||||
|
||||
const editorRouter = {
|
||||
path: "/editor",
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { $t } from "/@/plugins/i18n";
|
||||
import Layout from "/@/layout/index.vue";
|
||||
const Layout = () => import("/@/layout/index.vue");
|
||||
|
||||
const errorRouter = {
|
||||
path: "/error",
|
||||
@ -10,7 +10,7 @@ const errorRouter = {
|
||||
icon: "position",
|
||||
title: $t("menus.hserror"),
|
||||
i18n: true,
|
||||
rank: 7
|
||||
rank: 9
|
||||
},
|
||||
children: [
|
||||
{
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { $t } from "/@/plugins/i18n";
|
||||
import Layout from "/@/layout/index.vue";
|
||||
const Layout = () => import("/@/layout/index.vue");
|
||||
|
||||
const externalLink = {
|
||||
path: "/external",
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { $t } from "/@/plugins/i18n";
|
||||
import Layout from "/@/layout/index.vue";
|
||||
const Layout = () => import("/@/layout/index.vue");
|
||||
|
||||
const flowChartRouter = {
|
||||
path: "/flowChart",
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { $t } from "/@/plugins/i18n";
|
||||
import Layout from "/@/layout/index.vue";
|
||||
const Layout = () => import("/@/layout/index.vue");
|
||||
|
||||
const guideRouter = {
|
||||
path: "/guide",
|
||||
@ -10,7 +10,7 @@ const guideRouter = {
|
||||
icon: "guide",
|
||||
title: $t("menus.hsguide"),
|
||||
i18n: true,
|
||||
rank: 10
|
||||
rank: 11
|
||||
},
|
||||
children: [
|
||||
{
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { $t } from "/@/plugins/i18n";
|
||||
import Layout from "/@/layout/index.vue";
|
||||
const Layout = () => import("/@/layout/index.vue");
|
||||
|
||||
const homeRouter = {
|
||||
path: "/",
|
||||
|
@ -1,10 +1,10 @@
|
||||
// 静态路由
|
||||
import homeRouter from "./home";
|
||||
import ableRouter from "./able";
|
||||
import errorRouter from "./error";
|
||||
import guideRouter from "./guide";
|
||||
import editorRouter from "./editor";
|
||||
import nestedRouter from "./nested";
|
||||
import menuTreeRouter from "./menuTree";
|
||||
import externalLink from "./externalLink";
|
||||
import flowChartRouter from "./flowchart";
|
||||
import remainingRouter from "./remaining";
|
||||
@ -21,12 +21,12 @@ import { buildHierarchyTree } from "/@/utils/tree";
|
||||
// 原始静态路由(未做任何处理)
|
||||
const routes = [
|
||||
homeRouter,
|
||||
ableRouter,
|
||||
errorRouter,
|
||||
guideRouter,
|
||||
nestedRouter,
|
||||
externalLink,
|
||||
editorRouter,
|
||||
menuTreeRouter,
|
||||
flowChartRouter,
|
||||
componentsRouter
|
||||
];
|
||||
|
@ -1,28 +0,0 @@
|
||||
import { $t } from "/@/plugins/i18n";
|
||||
import Layout from "/@/layout/index.vue";
|
||||
|
||||
const menuTreeRouter = {
|
||||
path: "/menuTree",
|
||||
name: "reMenuTree",
|
||||
component: Layout,
|
||||
redirect: "/menuTree/index",
|
||||
meta: {
|
||||
icon: "node-tree",
|
||||
title: $t("menus.hsMenuTree"),
|
||||
i18n: true,
|
||||
rank: 9
|
||||
},
|
||||
children: [
|
||||
{
|
||||
path: "/menuTree/index",
|
||||
name: "reMenuTree",
|
||||
component: () => import("/@/views/menu-tree/index.vue"),
|
||||
meta: {
|
||||
title: $t("menus.hsMenuTree"),
|
||||
i18n: true
|
||||
}
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
export default menuTreeRouter;
|
@ -1,5 +1,5 @@
|
||||
import { $t } from "/@/plugins/i18n";
|
||||
import Layout from "/@/layout/index.vue";
|
||||
const Layout = () => import("/@/layout/index.vue");
|
||||
|
||||
const nestedRouter = {
|
||||
path: "/nested",
|
||||
@ -10,7 +10,7 @@ const nestedRouter = {
|
||||
title: $t("menus.hsmenus"),
|
||||
icon: "histogram",
|
||||
i18n: true,
|
||||
rank: 5
|
||||
rank: 8
|
||||
},
|
||||
children: [
|
||||
{
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { $t } from "/@/plugins/i18n";
|
||||
import Layout from "/@/layout/index.vue";
|
||||
const Layout = () => import("/@/layout/index.vue");
|
||||
|
||||
const remainingRouter = [
|
||||
{
|
||||
|
@ -8,11 +8,11 @@ import {
|
||||
} from "vue-router";
|
||||
import { router } from "./index";
|
||||
import { loadEnv } from "../../build";
|
||||
import Layout from "/@/layout/index.vue";
|
||||
import { useTimeoutFn } from "@vueuse/core";
|
||||
import { RouteConfigs } from "/@/layout/types";
|
||||
import { buildHierarchyTree } from "/@/utils/tree";
|
||||
import { usePermissionStoreHook } from "/@/store/modules/permission";
|
||||
const Layout = () => import("/@/layout/index.vue");
|
||||
// https://cn.vitejs.dev/guide/features.html#glob-import
|
||||
const modulesRoutes = import.meta.glob("/src/views/**/*.{vue,tsx}");
|
||||
|
||||
|
@ -1,3 +1,5 @@
|
||||
import type { FunctionArgs } from "@vueuse/core";
|
||||
|
||||
export const hasClass = (ele: RefType<any>, cls: string): any => {
|
||||
return !!ele.className.match(new RegExp("(\\s|^)" + cls + "(\\s|$)"));
|
||||
};
|
||||
@ -40,3 +42,16 @@ export const toggleClass = (
|
||||
className = className.replace(clsName, "");
|
||||
targetEl.className = flag ? `${className} ${clsName} ` : className;
|
||||
};
|
||||
|
||||
export function useRafThrottle<T extends FunctionArgs>(fn: T): T {
|
||||
let locked = false;
|
||||
// @ts-ignore
|
||||
return function (...args) {
|
||||
if (locked) return;
|
||||
locked = true;
|
||||
window.requestAnimationFrame(() => {
|
||||
fn.apply(this, args);
|
||||
locked = false;
|
||||
});
|
||||
};
|
||||
}
|
||||
|
116
src/utils/watermark.ts
Normal file
116
src/utils/watermark.ts
Normal file
@ -0,0 +1,116 @@
|
||||
import {
|
||||
ref,
|
||||
Ref,
|
||||
unref,
|
||||
shallowRef,
|
||||
onBeforeUnmount,
|
||||
getCurrentInstance
|
||||
} from "vue";
|
||||
import { isDef } from "/@/utils/is";
|
||||
import { useRafThrottle } from "/@/utils/operate";
|
||||
import { addResizeListener, removeResizeListener } from "/@/utils/resize";
|
||||
|
||||
const domSymbol = Symbol("watermark-dom");
|
||||
|
||||
type attr = {
|
||||
font?: string;
|
||||
fillStyle?: string;
|
||||
};
|
||||
|
||||
export function useWatermark(
|
||||
appendEl: Ref<HTMLElement | null> = ref(document.body) as Ref<HTMLElement>
|
||||
) {
|
||||
const func = useRafThrottle(function () {
|
||||
const el = unref(appendEl);
|
||||
if (!el) return;
|
||||
const { clientHeight: height, clientWidth: width } = el;
|
||||
updateWatermark({ height, width });
|
||||
});
|
||||
const id = domSymbol.toString();
|
||||
const watermarkEl = shallowRef<HTMLElement>();
|
||||
|
||||
const clear = () => {
|
||||
const domId = unref(watermarkEl);
|
||||
watermarkEl.value = undefined;
|
||||
const el = unref(appendEl);
|
||||
if (!el) return;
|
||||
domId && el.removeChild(domId);
|
||||
removeResizeListener(el, func);
|
||||
};
|
||||
|
||||
function createBase64(str: string, attr?: attr) {
|
||||
const can = document.createElement("canvas");
|
||||
const width = 300;
|
||||
const height = 240;
|
||||
Object.assign(can, { width, height });
|
||||
|
||||
const cans = can.getContext("2d");
|
||||
if (cans) {
|
||||
cans.rotate((-20 * Math.PI) / 120);
|
||||
cans.font = attr?.font ?? "15px Reggae One";
|
||||
cans.fillStyle = attr?.fillStyle ?? "rgba(0, 0, 0, 0.15)";
|
||||
cans.textAlign = "left";
|
||||
cans.textBaseline = "middle";
|
||||
cans.fillText(str, width / 20, height);
|
||||
}
|
||||
return can.toDataURL("image/png");
|
||||
}
|
||||
|
||||
function updateWatermark(
|
||||
options: {
|
||||
width?: number;
|
||||
height?: number;
|
||||
str?: string;
|
||||
attr?: attr;
|
||||
} = {}
|
||||
) {
|
||||
const el = unref(watermarkEl);
|
||||
if (!el) return;
|
||||
if (isDef(options.width)) {
|
||||
el.style.width = `${options.width}px`;
|
||||
}
|
||||
if (isDef(options.height)) {
|
||||
el.style.height = `${options.height}px`;
|
||||
}
|
||||
if (isDef(options.str)) {
|
||||
el.style.background = `url(${createBase64(
|
||||
options.str,
|
||||
options.attr
|
||||
)}) left top repeat`;
|
||||
}
|
||||
}
|
||||
|
||||
const createWatermark = (str: string, attr?: attr) => {
|
||||
if (unref(watermarkEl)) {
|
||||
updateWatermark({ str, attr });
|
||||
return id;
|
||||
}
|
||||
const div = document.createElement("div");
|
||||
watermarkEl.value = div;
|
||||
div.id = id;
|
||||
div.style.pointerEvents = "none";
|
||||
div.style.top = "0px";
|
||||
div.style.left = "0px";
|
||||
div.style.position = "absolute";
|
||||
div.style.zIndex = "100000";
|
||||
const el = unref(appendEl);
|
||||
if (!el) return id;
|
||||
const { clientHeight: height, clientWidth: width } = el;
|
||||
updateWatermark({ str, width, height, attr });
|
||||
el.appendChild(div);
|
||||
return id;
|
||||
};
|
||||
|
||||
function setWatermark(str: string, attr?: attr) {
|
||||
createWatermark(str, attr);
|
||||
addResizeListener(document.documentElement, func);
|
||||
const instance = getCurrentInstance();
|
||||
if (instance) {
|
||||
onBeforeUnmount(() => {
|
||||
clear();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return { setWatermark, clear };
|
||||
}
|
13
src/views/able/watermark.vue
Normal file
13
src/views/able/watermark.vue
Normal file
@ -0,0 +1,13 @@
|
||||
<script setup lang="ts">
|
||||
import { useWatermark } from "/@/utils/watermark";
|
||||
const { setWatermark, clear } = useWatermark();
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div>
|
||||
<el-button @click="setWatermark('vue-pure-admin')">创建</el-button>
|
||||
<el-button @click="clear">清除</el-button>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped></style>
|
Loading…
x
Reference in New Issue
Block a user