Merge branch 'main' of github.com:pure-admin/vue-pure-admin into gitee

This commit is contained in:
xiaoxian521 2023-06-12 21:13:23 +08:00
commit 4e62edc78e
8 changed files with 221 additions and 1 deletions

View File

@ -68,6 +68,7 @@ menus:
hsguide: Guide
hsAble: Able
hsMenuTree: Menu Tree
hsOptimize: Debounce、Throttle、Copy Directives
hsWatermark: Water Mark
hsPrint: Print
hsDownload: Download

View File

@ -68,6 +68,7 @@ menus:
hsguide: 引导页
hsAble: 功能
hsMenuTree: 菜单树结构
hsOptimize: 防抖、截流、复制指令
hsWatermark: 水印
hsPrint: 打印
hsDownload: 下载

View File

@ -7,7 +7,9 @@ export const auth: Directive = {
if (value) {
!hasAuth(value) && el.parentNode?.removeChild(el);
} else {
throw new Error("need auths! Like v-auth=\"['btn.add','btn.edit']\"");
throw new Error(
"[Directive: auth]: need auths! Like v-auth=\"['btn.add','btn.edit']\""
);
}
}
};

View File

@ -0,0 +1,33 @@
import { message } from "@/utils/message";
import { useEventListener } from "@vueuse/core";
import { copyTextToClipboard } from "@pureadmin/utils";
import { Directive, type DirectiveBinding } from "vue";
interface CopyEl extends HTMLElement {
copyValue: string;
}
/** 文本复制指令(默认双击复制) */
export const copy: Directive = {
mounted(el: CopyEl, binding: DirectiveBinding) {
const { value } = binding;
if (value) {
el.copyValue = value;
const arg = binding.arg ?? "dblclick";
// Register using addEventListener on mounted, and removeEventListener automatically on unmounted
useEventListener(el, arg, () => {
const success = copyTextToClipboard(el.copyValue);
success
? message("复制成功", { type: "success" })
: message("复制失败", { type: "error" });
});
} else {
throw new Error(
'[Directive: copy]: need value! Like v-copy="modelValue"'
);
}
},
updated(el: CopyEl, binding: DirectiveBinding) {
el.copyValue = binding.value;
}
};

View File

@ -1 +1,3 @@
export * from "./auth";
export * from "./copy";
export * from "./optimize";

View File

@ -0,0 +1,55 @@
import {
isFunction,
isObject,
isArray,
debounce,
throttle
} from "@pureadmin/utils";
import { useEventListener } from "@vueuse/core";
import { Directive, type DirectiveBinding } from "vue";
/** 防抖v-optimize或v-optimize:debounce、节流v-optimize:throttle指令 */
export const optimize: Directive = {
mounted(el: HTMLElement, binding: DirectiveBinding) {
const { value } = binding;
const optimizeType = binding.arg ?? "debounce";
const type = ["debounce", "throttle"].find(t => t === optimizeType);
if (type) {
if (value && value.event && isFunction(value.fn)) {
let params = value?.params;
if (params) {
if (isArray(params) || isObject(params)) {
params = isObject(params) ? Array.of(params) : params;
} else {
throw new Error(
"[Directive: optimize]: `params` must be an array or object"
);
}
}
// Register using addEventListener on mounted, and removeEventListener automatically on unmounted
useEventListener(
el,
value.event,
type === "debounce"
? debounce(
params ? () => value.fn(...params) : value.fn,
value?.timeout ?? 200,
value?.immediate ?? false
)
: throttle(
params ? () => value.fn(...params) : value.fn,
value?.timeout ?? 1000
)
);
} else {
throw new Error(
"[Directive: optimize]: `event` and `fn` are required, and `fn` must be a function"
);
}
} else {
throw new Error(
"[Directive: optimize]: only `debounce` and `throttle` are supported"
);
}
}
};

View File

@ -10,6 +10,15 @@ export default {
rank: able
},
children: [
{
path: "/able/directives",
name: "Directives",
component: () => import("@/views/able/directives.vue"),
meta: {
title: $t("menus.hsOptimize"),
extraIcon: "IF-pure-iconfont-new svg"
}
},
{
path: "/able/watermark",
name: "WaterMark",

View File

@ -0,0 +1,117 @@
<script setup lang="ts">
import { ref } from "vue";
import { message } from "@/utils/message";
defineOptions({
name: "Directives"
});
const search = ref("");
const searchTwo = ref("");
const searchThree = ref("");
const searchFour = ref("");
const searchFive = ref("");
const searchSix = ref("copy");
const text = ref("可复制的文本");
function onInput() {
message(search.value);
}
function onInputTwo() {
message(searchTwo.value);
}
function onInputThree({ name, sex }) {
message(`${name}${sex}${searchThree.value}`);
}
function onInputFour() {
message(searchFour.value);
}
function onInputFive({ name, sex }) {
message(`${name}${sex}${searchFive.value}`);
}
</script>
<template>
<el-card shadow="never">
<template #header>
<div class="card-header">
<span class="font-medium">自定义防抖截流文本复制指令</span>
</div>
</template>
<div class="mb-2">
防抖指令连续输入只会执行第一次点击事件立即执行
<el-input
v-optimize="{
event: 'input',
fn: onInput,
immediate: true,
timeout: 1000
}"
v-model="search"
class="!w-[200px]"
clearable
@clear="onInput"
/>
</div>
<div class="mb-2">
防抖指令连续输入只会执行最后一次事件延后执行
<el-input
v-optimize="{ event: 'input', fn: onInputTwo, timeout: 400 }"
v-model="searchTwo"
class="!w-[200px]"
clearable
/>
</div>
<div>
防抖指令连续输入只会执行最后一次事件延后执行传参用法
<el-input
v-optimize="{
event: 'input',
fn: onInputThree,
timeout: 400,
params: { name: '小明', sex: '男' }
}"
v-model="searchThree"
class="!w-[200px]"
clearable
/>
</div>
<el-divider />
<div class="mb-2">
节流指令连续输入每一秒只会执行一次事件
<el-input
v-optimize:throttle="{ event: 'input', fn: onInputFour, timeout: 1000 }"
v-model="searchFour"
class="!w-[200px]"
clearable
/>
</div>
<div>
节流指令连续输入每一秒只会执行一次事件传参用法
<el-input
v-optimize:throttle="{
event: 'input',
fn: onInputFive,
params: { name: '小明', sex: '男' }
}"
v-model="searchFive"
class="!w-[200px]"
clearable
/>
</div>
<el-divider />
<div class="mb-2">
文本复制指令双击输入框内容即可复制
<el-input v-copy="searchSix" v-model="searchSix" class="!w-[200px]" />
</div>
<div>
文本复制指令自定义触发事件单击复制
<span v-copy:click="text" class="text-sky-500">{{ text }}</span>
</div>
</el-card>
</template>