近期在开发的过程中遇到了两个难题,一个是目前的穿梭框不支持产品的要求,不能够上下拖拽,二是vben没有水印的api,需要我们自己来开发。
一、可拖拽穿梭框
做成功的效果如下:
思路:
- 将table放入transfer的slot里进行使用。
2、将table的拖拽事件写出来,让其中的值赋值正确
3、因为左边不能拖动,右边可以拖动,判断是否为right来绑定是否拖拽事件
代码展示
html代码
<!-- 新增编辑弹窗 -->
<AddEditModel
:addFormSchema="addFormSchema"
:title="'薪酬方案'"
@register="registerModal1"
@success="handleSuccess1"
@cancel="handleCancel1"
>
<template #itemIds="{ model, field }">
<Transfer
ref="transferRef"
:titles="['待选薪酬项目', '已选薪酬项目']"
v-model:target-keys="model[field]"
:data-source="mockData"
show-search
:list-style="{
width: '210px',
height: '300px',
}"
:render="(item) => `${item.title}`"
>
<template #notFoundContent>
<span>没数据</span>
</template>
<template
#children="{ direction, filteredItems, selectedKeys, onItemSelectAll, onItemSelect }"
>
<Table
:row-selection="
getRowSelection({
selectedKeys,
onItemSelectAll,
onItemSelect,
})
"
:columns="TransferColumns"
:data-source="filteredItems"
:pagination="false"
:scroll="{
y: 160,
}"
height="400"
size="small"
:customRow="direction === 'right' ? customRow.bind(list, filteredItems) : undefined"
/>
</template>
</Transfer>
</template>
</AddEditModel>
Js代码
// 拖动排序
function customRow(list, record) {
return {
props: {
draggable: 'true',
},
style: {
cursor: 'move',
},
// 鼠标移入
onMouseenter: (event) => {
// 兼容IE
var ev = event || window.event;
ev.target.draggable = true;
},
// 开始拖拽
onDragstart: (event) => {
var ev = event || window.event; // 兼容IE
ev.stopPropagation(); // 阻止冒泡
fistIndex.value = list.findIndex(function (event) {
return event.key === record.key;
});
},
// 拖动元素经过的元素
onDragover: (event) => {
var ev = event || window.event;
ev.preventDefault(); // 阻止默认行为
},
// 鼠标松开
onDrop: (event) => {
var ev = event || window.event;
ev.stopPropagation(); // 阻止冒泡
let tagIndex = list.findIndex(function (event) {
return event.key === record.key;
});
let temp = list[fistIndex.value];
set(list, fistIndex.value, list[tagIndex]);
set(list, tagIndex, temp);
sortList.value = list;
},
};
}
const getRowSelection = ({
disabled,
selectedKeys,
onItemSelectAll,
onItemSelect,
}: Record<string, any>) => {
return {
getCheckboxProps: (item: Record<string, string | boolean>) => ({
disabled: disabled || item.disabled,
}),
onSelectAll(selected: boolean, selectedRows: Record<string, string | boolean>[]) {
const treeSelectedKeys = selectedRows
.filter((item) => !item.disabled)
.map(({ key }) => key);
onItemSelectAll(treeSelectedKeys, selected);
},
onSelect({ key }: Record<string, string>, selected: boolean) {
onItemSelect(key, selected);
},
selectedRowKeys: selectedKeys,
};
};
二、水印问题
客户要求在table背后加上公司的水印,vben框架没有这个的api,我们自己开发完成。效果图如下:
需求:给整个页面添加背景水印。
思路:
1、使用 canvas 特性生成 base64 格式的图片文件,设置其字体大小,颜色等。
2、将其设置为背景图片,从而实现页面或组件水印效果
3、监听新旧父元素宽高,让水印填充满
使用:设置水印文案,颜色,字体大小即可
<div v-waterMarker="{text:'版权所有',textColor:'rgba(180, 180, 180, 0.4)'}"></div>
废话不多说,直接上代码:
import type { Directive, DirectiveBinding, App } from 'vue';
function createBase64(
str: string,
textSize: number,
textColor: string,
textXGap: number,
textYGap: number
) {
const can = document.createElement('canvas')
const width = textXGap || 300
const height = textYGap || width / 3
Object.assign(can, { width, height })
const cans = can.getContext('2d')
if (cans) {
cans.rotate((-20 * Math.PI) / 120)
cans.font = textSize + 'px Microsoft JhengHei' || '16px Microsoft JhengHei'
cans.fillStyle = textColor || 'rgba(0, 0, 0, 0.15)'
cans.textAlign = 'left'
cans.textBaseline = 'middle'
cans.fillText(str, width / 10, height)
}
return can.toDataURL('image/png')
}
const addWaterMarker = (
str: string,
parentNode: any,
textSize: number,
textColor: string,
textXGap: number,
textYGap: number
) => {
const el = parentNode
const waterMarkerlist = document.getElementsByClassName('waterMarker-box')
if (waterMarkerlist.length) {
for (let i = 0; i < waterMarkerlist.length; i++) {
el.removeChild(waterMarkerlist[i])
}
}
el.style.position = 'relative'
const { clientHeight: height, clientWidth: width } = el
const div = document.createElement('div')
div.style.pointerEvents = 'none'
div.className = 'waterMarker-box'
div.style.top = '0px'
div.style.left = '0px'
div.style.position = 'absolute'
div.style.height = height + 'px'
div.style.width = width + 'px'
div.style.zIndex = '100000'
div.style.background = `url(${createBase64(
str,
textSize,
textColor,
textXGap,
textYGap
)}) left top repeat`
el.appendChild(div)
}
const waterMarker = {
mounted(el: DirectiveBinding, binding: DirectiveBinding) {
let width = '',
height = '';
function isReize() {
const style = document.defaultView.getComputedStyle(el);
if (width !== style.width || height !== style.height) {
addWaterMarker(
binding.value.text,
el,
binding.value.textSize,
binding.value.textColor,
binding.value.textXGap,
binding.value.textYGap
)
}
width = style.width;
height = style.height;
}
el.__vueSetInterval__ = setInterval(isReize, 300);
},
};
export function setupWaterMarkerDirective(app: App) {
app.directive('waterMarker', waterMarker);
}
export default waterMarker;
以上就是拖拽穿梭框和背景水印的核心内容,如果使用的是vben框架的话,大家会更容易理解,有什么不同的问题,可以留言一起讨论哦。