dev #4

Merged
bunny merged 5 commits from dev into master 2024-05-10 16:30:34 +08:00
9 changed files with 257 additions and 7 deletions

19
src/directives/index.ts Normal file
View File

@ -0,0 +1,19 @@
import { App, Directive } from 'vue';
import copy from './modules/copy';
import existShow from './modules/existShow';
import vPrint from './modules/print';
import waterMarker from './modules/waterMarker';
const directivesList: { [key: string]: Directive } = { copy, waterMarker, existShow, vPrint };
/**
*
*/
const directives = {
install: function (app: App<Element>) {
Object.keys(directivesList).forEach(key => {
app.directive(key, directivesList[key]);
});
},
};
export default directives;

View File

@ -0,0 +1,51 @@
import type { DirectiveBinding } from 'vue';
import { Directive } from 'vue';
interface ElType extends HTMLElement {
copyData: string | number; // 定义一个属性,用于存储需要复制的数据
__handleClick__: any; // 定义一个属性,用于存储事件处理函数
}
/**
* * v-copy
*
* string类型/Ref<string>/Reactive<string>
*/
const copy: Directive = {
mounted(el: ElType, binding: DirectiveBinding) {
el.copyData = binding.value;
el.addEventListener('click', handelClick);
},
// 指令所在组件VNode 更新时触发
updated(el: ElType, binding: DirectiveBinding) {
el.copyData = binding.value; // 更新需要复制的数据
},
// 指令与元素绑定时触发
beforeMount(el: ElType) {
// 移除点击事件
el.removeEventListener('click', el.__handleClick__);
},
};
/**
* *
* @param this
*/
function handelClick(this: any) {
// 创建一个 input 元素
const input = document.createElement('input');
// 将需要复制的数据赋值给 input 的 value 属性
input.value = this.copyData.toLocaleString();
// 将 input 元素添加到 body 中
document.body.appendChild(input);
// 选中 input 元素中的文本
input.select();
// 执行复制操作
document.execCommand('Copy');
// 将 input 元素从 body 中移除
document.body.removeChild(input);
// TODO: 如需自定义请修改提示方式
alert('复制成功');
}
export default copy;

View File

@ -0,0 +1,66 @@
import type { Directive } from 'vue';
interface ELType extends HTMLElement {
parentNode: any;
}
/*
1absoluterelative
2(onmousedown) left top
3(onmousemove) left top
4(onmouseup)
使 Dom v-draggable
<div class="dialog-model" v-draggable></div>
*/
const draggable: Directive = {
mounted(el: ELType) {
// 将光标设置为“move”将位置设置为“absolute”
el.style.cursor = 'move';
el.style.position = 'absolute';
// 当元素被点击时
el.onmousedown = function (e) {
// 计算鼠标点击位置与元素左上角之间的距离
let disX = e.pageX - el.offsetLeft;
let disY = e.pageY - el.offsetTop;
// 当鼠标移动时
document.onmousemove = function (e) {
// 计算元素的新位置
let x = e.pageX - disX;
let y = e.pageY - disY;
// 计算元素可以移动到的最大位置
let maxX = el.parentNode.offsetWidth - el.offsetWidth;
let maxY = el.parentNode.offsetHeight - el.offsetHeight;
// 确保元素不会超出其父元素的边界
if (x < 0) {
x = 0;
} else if (x > maxX) {
x = maxX;
}
if (y < 0) {
y = 0;
} else if (y > maxY) {
y = maxY;
}
// 设置元素的新位置
el.style.left = x + 'px';
el.style.top = y + 'px';
};
// 当鼠标释放时
document.onmouseup = function () {
// 停止跟踪鼠标移动
document.onmousemove = document.onmouseup = null;
};
};
},
};
export default draggable;

View File

@ -0,0 +1,15 @@
import { Directive } from 'vue';
/**
* * 退
*/
const existShow: Directive = {
// 指令与元素绑定时触发
beforeMount() {
window.onbeforeunload = function (event) {
(event || window.event).returnValue = '确定离开此页吗?';
};
},
};
export default existShow;

View File

@ -0,0 +1,23 @@
import type { DirectiveBinding } from 'vue';
import { Directive } from 'vue';
interface ElType extends HTMLElement {
copyData: string | number; // 定义一个属性,用于存储需要复制的数据
__handleClick__: any; // 定义一个属性,用于存储事件处理函数
}
const vPrint: Directive = {
mounted(el: ElType, binding: DirectiveBinding) {
el.copyData = binding.value;
el.addEventListener('click', handelClick);
},
beforeMount(el: ElType) {
el.removeEventListener('click', el.__handleClick__);
},
};
function handelClick(this: any) {
print();
}
export default vPrint;

View File

@ -0,0 +1,46 @@
import type { Directive, DirectiveBinding } from 'vue';
/*
1使 canvas base64
2
使
<div v-waterMarker="{text:'版权所有',textColor:'rgba(180, 180, 180, 0.4)'}"></div>
*/
const addWaterMarker: Directive = (str: string, parentNode: any, font: any, textColor: string) => {
// 创建一个canvas元素
let can: HTMLCanvasElement = document.createElement('canvas');
// 将canvas元素添加到父元素中
parentNode.appendChild(can);
// 设置canvas元素的宽高
can.width = 205;
can.height = 140;
// 隐藏canvas元素
can.style.display = 'none';
// 获取canvas元素的2d上下文
let cans = can.getContext('2d') as CanvasRenderingContext2D;
// 旋转canvas元素
cans.rotate((-20 * Math.PI) / 180);
// 设置canvas元素的字体和文字颜色
cans.font = font || '16px Microsoft JhengHei';
cans.fillStyle = textColor || 'rgba(180, 180, 180, 0.3)';
// 设置canvas元素的文本对齐方式和基线
cans.textAlign = 'left';
cans.textBaseline = 'Middle' as CanvasTextBaseline;
// 在canvas元素上绘制文本
cans.fillText(str, can.width / 10, can.height / 2);
// 将父元素的背景图片设置为canvas元素的dataURL
parentNode.style.backgroundImage = `url("${can.toDataURL('image/png')}")`;
};
const waterMarker: Directive = {
mounted(el: DirectiveBinding, binding: DirectiveBinding) {
// 调用addWaterMarker函数给元素添加水印
addWaterMarker(binding.value.text, el, binding.value.font, binding.value.textColor);
},
};
export default waterMarker;

View File

@ -1,3 +1,4 @@
import directives from '@/directives';
import { createPinia } from 'pinia';
import { createApp } from 'vue';
import App from './App.vue';
@ -8,5 +9,5 @@ import router from './router';
const pinia = createPinia();
const app = createApp(App);
app.use(router).use(pinia)
app.use(router).use(pinia).use(directives);
app.mount('#app');

View File

@ -1,4 +1,24 @@
<template>sdasd</template>
<template>
<textarea type="text" v-model="myData.inputValue" />
<button v-copy="myData.copyValue" @click="handelClik">点击复制</button>
<button v-vPrint>点击打印</button>
</template>
<script setup lang="ts"></script>
<style scoped lang="scss"></style>
<script setup lang="ts">
import { reactive } from 'vue';
const myData = reactive({
inputValue: '我是被复制的内容 🍒🍇🍊2023-4-21 14:02:59',
copyValue: '',
});
const handelClik = () => {
myData.copyValue = myData.inputValue;
};
</script>
<style scoped lang="scss">
textarea {
width: 500px;
height: 300px;
outline: 1px solid #f4dde5;
}
</style>

View File

@ -1,6 +1,15 @@
<template>
<h1>bunny/default页面</h1>
<RouterView />
<div v-waterMarker="{ text: 'Bunny Admin', textColor: 'rgba(180, 180, 180, 0.6)' }" v-existShow>
<h1 @click="handelClik">bunny/default页面</h1>
<My />
<RouterView />
</div>
</template>
<script setup lang="ts"></script>
<script setup lang="ts">
import My from '@/views/bunny/default/My.vue';
const handelClik = () => {
print();
};
</script>