feat: first commit

This commit is contained in:
2025-01-24 00:49:17 +08:00
commit c2cbc1b1d6
88 changed files with 12831 additions and 0 deletions
+142
View File
@@ -0,0 +1,142 @@
<template>
<!-- <el-watermark :font="font" :content="['加零', '+0']" :gap="[20,20]"> -->
<div :ref="drop" class="target-box" :class="$style['a4']">
<!-- {{ isActive ? 'Release to drop' : 'Drag item here' }} -->
<!-- <Card v-for="(card, index) in cards" :id="card.id" :key="card.id" :text="card.text" :index="index"
:move-card="moveCard" /> -->
<auto-responsive v-bind="options" :itemMargin="itemMargin" :gridWidth="gridWidth" >
<div class="column" v-for="(card, index) in cardList" :style="{height:card.getOffsetHeight()+'px',width:card.getOffsetWidth()+'px'}">
<component :is="switchCom(card)" v-bind="card" :index="index"
:moveCard="moveCard"></component>
</div>
</auto-responsive>
</div>
<!-- </el-watermark> -->
</template>
<script lang="ts" setup>
import { computed, ref, unref, h, reactive } from 'vue'
import Card from './Box1.vue'
import { useDrop } from 'vue3-dnd'
import { toRefs } from '@vueuse/core'
import Box2 from './Box2.vue';
import AutoResponsive from "../../components/autoresponsive.vue";
import { Box } from './boxType';
import Box3 from './Box3.vue';
import Box4 from './Box4.vue';
const options = {
itemMargin: 1,
containerWidth: 793.7,
itemClassName: 'column',
gridWidth: 1,
transitionDuration: '.5'
};
const font = reactive({
color: 'rgba(0, 0, 0, .45)',
})
const props = withDefaults(defineProps<{
itemMargin: number
gridWidth: number
}>(), {
itemMargin:1,
gridWidth: 1
})
defineExpose({
addLastNode:(data)=>{
const box=new Box(data.width,data.height,data.padding,data.type);
box.fontSize=data.fontSize;
box.fontColor=data.fontColor;
cardList.value.push(box);
},
removeLastNode:()=>{
cardList.value.splice(cardList.value.length-1);
},
clearNode:()=>{
cardList.value.splice(0);
}
});
const cards = ref<Item[]>()
const cardList = ref<IBox[]>([]);
const [collect, drop] = useDrop(() => ({
accept: 'card',
collect: (monitor) => {
return { isActive: monitor.canDrop() && monitor.isOver() }
},
drop: (item: any, monitor) => {
// console.log(monitor.canDrop(), monitor.didDrop(), monitor.getDropResult(), monitor.getItem(), item, monitor.isOver({ shallow: true }));
const boxItem:IBox=monitor.getItem() as IBox;
if (monitor.canDrop() && !monitor.didDrop() && monitor.isOver({ shallow: true })) {
const box=new Box(boxItem.width.toString(),boxItem.height.toString(),boxItem.padding.toString(),boxItem.type);
box.fontSize=boxItem.fontSize;
box.fontColor=boxItem.fontColor;
cardList.value.push(box);
console.log('add', cardList.value);
}
}
}))
const { isActive } = toRefs(collect)
interface Item {
id: number
text: string
}
const switchCom = (item) => {
switch (item.type) {
case "Box1":
return Box2;
case "Box2":
return Box3;
case "Box3":
return Box4;
default:
return;
}
}
const moveCard = (dragIndex: number, hoverIndex: number) => {
const item = cards.value[dragIndex]
cards.value.splice(dragIndex, 1)
cards.value.splice(hoverIndex, 0, item)
}
</script>
<style module lang="scss">
:global {
:local(.device-list) {
padding: 20px;
background-color: #FFF;
}
:local(.img-preview-dialog) {
:local(.footer) {
margin-top: 20px;
display: flex;
flex-direction: row;
>div {
margin-left: 40px;
}
}
}
:local(.a4) {
width: 793.7px;
// height: 1122.5px;
border: 1px solid black;
.column {}
}
}
</style>
+118
View File
@@ -0,0 +1,118 @@
<script lang="ts" setup>
import { computed, ref, unref } from 'vue'
import { useDrag, useDrop } from 'vue3-dnd'
// import { ItemTypes } from './ItemTypes'
import type { XYCoord, Identifier } from 'dnd-core'
import { toRefs } from '@vueuse/core'
const props = defineProps<{
id: any
text: string
index: number
moveCard: (dragIndex: number, hoverIndex: number) => void
}>()
interface DragItem {
index: number
id: string
type: string
}
const card = ref<HTMLDivElement>()
const [dropCollect, drop] = useDrop<
DragItem,
void,
{ handlerId: Identifier | null }
>({
accept: 'card',
collect(monitor) {
return {
handlerId: monitor.getHandlerId(),
}
},
hover(item: DragItem, monitor) {
if (!card.value) {
return
}
const dragIndex = item.index
const hoverIndex = props.index
// Don't replace items with themselves
if (dragIndex === hoverIndex) {
return
}
// Determine rectangle on screen
const hoverBoundingRect = card.value?.getBoundingClientRect()
// Get vertical middle
const hoverMiddleY = (hoverBoundingRect.bottom - hoverBoundingRect.top) / 2
// Determine mouse position
const clientOffset = monitor.getClientOffset()
// Get pixels to the top
const hoverClientY = (clientOffset as XYCoord).y - hoverBoundingRect.top
// Only perform the move when the mouse has crossed half of the items height
// When dragging downwards, only move when the cursor is below 50%
// When dragging upwards, only move when the cursor is above 50%
// Dragging downwards
if (dragIndex < hoverIndex && hoverClientY < hoverMiddleY) {
return
}
// Dragging upwards
if (dragIndex > hoverIndex && hoverClientY > hoverMiddleY) {
return
}
// Time to actually perform the action
props.moveCard(dragIndex, hoverIndex)
// Note: we're mutating the monitor item here!
// Generally it's better to avoid mutations,
// but it's good here for the sake of performance
// to avoid expensive index searches.
item.index = hoverIndex
},
})
const dragId = ref();
const [collect, drag] = useDrag({
type: 'card',
item: () => {
return { id: props.id, index: props.index, dragId: dragId.value }
},
collect: (monitor: any) => {
return ({
isDragging: monitor.isDragging(),
})
}
})
const { handlerId } = toRefs(dropCollect)
const { isDragging } = toRefs(collect)
const opacity = computed(() => (unref(isDragging) ? 0 : 1))
const setRef = (el: HTMLDivElement) => {
card.value = drag(drop(el)) as HTMLDivElement
}
</script>
<template>
<div :ref="setRef" class="card" :style="{ opacity }" :data-handler-id="handlerId">
{{ text }}
</div>
</template>
<style lang="scss" scoped>
.card {
margin-bottom: 0.5rem;
padding: 0.5rem 1rem;
background-color: white;
border: 1px dashed gray;
cursor: move;
}
</style>
+166
View File
@@ -0,0 +1,166 @@
<template>
<div :ref="setRef" class="card" :style="{ opacity }" :data-handler-id="handlerId">
<div>i5 10</div>
<div>16g 256g</div>
<div>显卡:2060</div>
<div>加零租赁</div>
</div>
</template>
<script lang="ts" setup>
import { computed, ref, unref, useCssVars } from 'vue'
import { useDrag, useDrop } from 'vue3-dnd'
// import { ItemTypes } from './ItemTypes'
import type { XYCoord, Identifier } from 'dnd-core'
import { toRefs } from '@vueuse/core'
import {Box} from "./boxType";
const props = withDefaults(defineProps<{
id: any
index: number
width: number
height: number
padding:number
fontSize:number
fontColor:string
moveCard?: (dragIndex: number, hoverIndex: number) => void
}>(), {
width: 100,
height: 100,
padding:10,
fontSize:18,
fontColor:"black"
})
interface DragItem {
index: number
id: string
type: string
}
const BOXTYPE:TBoxType = "Box1"
const card = ref<HTMLDivElement>()
const [dropCollect, drop] = useDrop<
DragItem,
void,
{ handlerId: Identifier | null }
>({
accept: 'card',
collect(monitor) {
return {
handlerId: monitor.getHandlerId(),
}
},
hover(item: DragItem, monitor) {
if (!card.value) {
return
}
const dragIndex = item.index
const hoverIndex = props.index
// Don't replace items with themselves
if (dragIndex === hoverIndex) {
return
}
// Determine rectangle on screen
const hoverBoundingRect = card.value?.getBoundingClientRect()
// Get vertical middle
const hoverMiddleY = (hoverBoundingRect.bottom - hoverBoundingRect.top) / 2
// Determine mouse position
const clientOffset = monitor.getClientOffset()
// Get pixels to the top
const hoverClientY = (clientOffset as XYCoord).y - hoverBoundingRect.top
// Only perform the move when the mouse has crossed half of the items height
// When dragging downwards, only move when the cursor is below 50%
// When dragging upwards, only move when the cursor is above 50%
// Dragging downwards
if (dragIndex < hoverIndex && hoverClientY < hoverMiddleY) {
return
}
// Dragging upwards
if (dragIndex > hoverIndex && hoverClientY > hoverMiddleY) {
return
}
// Time to actually perform the action
props.moveCard(dragIndex, hoverIndex)
// Note: we're mutating the monitor item here!
// Generally it's better to avoid mutations,
// but it's good here for the sake of performance
// to avoid expensive index searches.
item.index = hoverIndex
},
})
const dragId = ref();
const [collect, drag] = useDrag({
type: 'card',
item: ():IBox => {
const {width,height,padding,index,fontColor,fontSize}=props;
const box=new Box(width,height,padding,BOXTYPE);
box.fontSize=fontSize;
box.fontColor=fontColor;
box.index=index;
return box;
},
collect: (monitor: any) => {
return ({
isDragging: monitor.isDragging(),
})
}
})
const { handlerId } = toRefs(dropCollect)
const { isDragging } = toRefs(collect)
const opacity = computed(() => (unref(isDragging) ? 0 : 1))
const setRef = (el: HTMLDivElement) => {
// card.value = drag(drop(el)) as HTMLDivElement
card.value = drag(el) as HTMLDivElement
}
const widthValue = computed(() => {
return props.width + "px";
})
const heightValue = computed(() => {
return props.height + "px";
})
const paddingValue=computed(()=>{
console.log("padding:",props.padding)
return props.padding+"px";
})
const fontSizeValue=computed(()=>{
console.log("padding:",props.padding)
return props.fontSize+"px";
})
const fontColorValue=computed(()=>{
console.log("padding:",props.padding)
return props.fontColor;
})
</script>
<style lang="scss" scoped>
.card {
width: v-bind(widthValue);
height:v-bind(heightValue);
// margin-bottom: 8px;
padding: v-bind(paddingValue);
font-size: v-bind(fontSizeValue);
color:v-bind(fontColorValue);
background-color: white;
border: 1px dashed gray;
cursor: move;
}
</style>
+163
View File
@@ -0,0 +1,163 @@
<template>
<div :ref="setRef" class="card" :style="{ opacity }" :data-handler-id="handlerId">
加零租赁
</div>
</template>
<script lang="ts" setup>
import { computed, ref, unref, useCssVars } from 'vue'
import { useDrag, useDrop } from 'vue3-dnd'
// import { ItemTypes } from './ItemTypes'
import type { XYCoord, Identifier } from 'dnd-core'
import { toRefs } from '@vueuse/core'
import {Box} from "./boxType";
const props = withDefaults(defineProps<{
id: any
index: number
width: number
height: number
padding:number
fontSize:number
fontColor:string
moveCard?: (dragIndex: number, hoverIndex: number) => void
}>(), {
width: 60,
height: 40,
padding:2,
fontSize:12,
fontColor:"black"
})
interface DragItem {
index: number
id: string
type: string
}
const BOXTYPE:TBoxType = "Box2"
const card = ref<HTMLDivElement>()
const [dropCollect, drop] = useDrop<
DragItem,
void,
{ handlerId: Identifier | null }
>({
accept: 'card',
collect(monitor) {
return {
handlerId: monitor.getHandlerId(),
}
},
hover(item: DragItem, monitor) {
if (!card.value) {
return
}
const dragIndex = item.index
const hoverIndex = props.index
// Don't replace items with themselves
if (dragIndex === hoverIndex) {
return
}
// Determine rectangle on screen
const hoverBoundingRect = card.value?.getBoundingClientRect()
// Get vertical middle
const hoverMiddleY = (hoverBoundingRect.bottom - hoverBoundingRect.top) / 2
// Determine mouse position
const clientOffset = monitor.getClientOffset()
// Get pixels to the top
const hoverClientY = (clientOffset as XYCoord).y - hoverBoundingRect.top
// Only perform the move when the mouse has crossed half of the items height
// When dragging downwards, only move when the cursor is below 50%
// When dragging upwards, only move when the cursor is above 50%
// Dragging downwards
if (dragIndex < hoverIndex && hoverClientY < hoverMiddleY) {
return
}
// Dragging upwards
if (dragIndex > hoverIndex && hoverClientY > hoverMiddleY) {
return
}
// Time to actually perform the action
props.moveCard(dragIndex, hoverIndex)
// Note: we're mutating the monitor item here!
// Generally it's better to avoid mutations,
// but it's good here for the sake of performance
// to avoid expensive index searches.
item.index = hoverIndex
},
})
const dragId = ref();
const [collect, drag] = useDrag({
type: 'card',
item: ():IBox => {
const {width,height,padding,index,fontColor,fontSize}=props;
const box=new Box(width,height,padding,BOXTYPE);
box.fontSize=fontSize;
box.fontColor=fontColor;
box.index=index;
return box;
},
collect: (monitor: any) => {
return ({
isDragging: monitor.isDragging(),
})
}
})
const { handlerId } = toRefs(dropCollect)
const { isDragging } = toRefs(collect)
const opacity = computed(() => (unref(isDragging) ? 0 : 1))
const setRef = (el: HTMLDivElement) => {
// card.value = drag(drop(el)) as HTMLDivElement
card.value = drag(el) as HTMLDivElement
}
const widthValue = computed(() => {
return props.width + "px";
})
const heightValue = computed(() => {
return props.height + "px";
})
const paddingValue=computed(()=>{
console.log("padding:",props.padding)
return props.padding+"px";
})
const fontSizeValue=computed(()=>{
console.log("padding:",props.padding)
return props.fontSize+"px";
})
const fontColorValue=computed(()=>{
console.log("padding:",props.padding)
return props.fontColor;
})
</script>
<style lang="scss" scoped>
.card {
width: v-bind(widthValue);
height:v-bind(heightValue);
// margin-bottom: 8px;
padding: v-bind(paddingValue);
font-size: v-bind(fontSizeValue);
color:v-bind(fontColorValue);
background-color: white;
border: 1px dashed gray;
cursor: move;
}
</style>
+166
View File
@@ -0,0 +1,166 @@
<template>
<div :ref="setRef" class="card" :style="{ opacity }" :data-handler-id="handlerId">
<span></span><span></span><span></span><span></span>
</div>
</template>
<script lang="ts" setup>
import { computed, ref, unref, useCssVars } from 'vue'
import { useDrag, useDrop } from 'vue3-dnd'
// import { ItemTypes } from './ItemTypes'
import type { XYCoord, Identifier } from 'dnd-core'
import { toRefs } from '@vueuse/core'
import {Box} from "./boxType";
const props = withDefaults(defineProps<{
id: any
index: number
width: number
height: number
padding:number
fontSize:number
fontColor:string
moveCard?: (dragIndex: number, hoverIndex: number) => void
}>(), {
width: 60,
height: 40,
padding:2,
fontSize:12,
fontColor:"black"
})
interface DragItem {
index: number
id: string
type: string
}
const BOXTYPE:TBoxType = "Box3"
const card = ref<HTMLDivElement>()
const [dropCollect, drop] = useDrop<
DragItem,
void,
{ handlerId: Identifier | null }
>({
accept: 'card',
collect(monitor) {
return {
handlerId: monitor.getHandlerId(),
}
},
hover(item: DragItem, monitor) {
if (!card.value) {
return
}
const dragIndex = item.index
const hoverIndex = props.index
// Don't replace items with themselves
if (dragIndex === hoverIndex) {
return
}
// Determine rectangle on screen
const hoverBoundingRect = card.value?.getBoundingClientRect()
// Get vertical middle
const hoverMiddleY = (hoverBoundingRect.bottom - hoverBoundingRect.top) / 2
// Determine mouse position
const clientOffset = monitor.getClientOffset()
// Get pixels to the top
const hoverClientY = (clientOffset as XYCoord).y - hoverBoundingRect.top
// Only perform the move when the mouse has crossed half of the items height
// When dragging downwards, only move when the cursor is below 50%
// When dragging upwards, only move when the cursor is above 50%
// Dragging downwards
if (dragIndex < hoverIndex && hoverClientY < hoverMiddleY) {
return
}
// Dragging upwards
if (dragIndex > hoverIndex && hoverClientY > hoverMiddleY) {
return
}
// Time to actually perform the action
props.moveCard(dragIndex, hoverIndex)
// Note: we're mutating the monitor item here!
// Generally it's better to avoid mutations,
// but it's good here for the sake of performance
// to avoid expensive index searches.
item.index = hoverIndex
},
})
const dragId = ref();
const [collect, drag] = useDrag({
type: 'card',
item: ():IBox => {
const {width,height,padding,index,fontColor,fontSize}=props;
const box=new Box(width,height,padding,BOXTYPE);
box.fontSize=fontSize;
box.fontColor=fontColor;
box.index=index;
return box;
},
collect: (monitor: any) => {
return ({
isDragging: monitor.isDragging(),
})
}
})
const { handlerId } = toRefs(dropCollect)
const { isDragging } = toRefs(collect)
const opacity = computed(() => (unref(isDragging) ? 0 : 1))
const setRef = (el: HTMLDivElement) => {
// card.value = drag(drop(el)) as HTMLDivElement
card.value = drag(el) as HTMLDivElement
}
const widthValue = computed(() => {
return props.width + "px";
})
const heightValue = computed(() => {
return props.height + "px";
})
const paddingValue=computed(()=>{
console.log("padding:",props.padding)
return props.padding+"px";
})
const fontSizeValue=computed(()=>{
console.log("padding:",props.padding)
return props.fontSize+"px";
})
const fontColorValue=computed(()=>{
console.log("padding:",props.padding)
return props.fontColor;
})
</script>
<style lang="scss" scoped>
.card {
width: v-bind(widthValue);
height:v-bind(heightValue);
// margin-bottom: 8px;
padding: v-bind(paddingValue);
font-size: v-bind(fontSizeValue);
color:v-bind(fontColorValue);
background-color: white;
border: 1px dashed gray;
cursor: move;
display: flex;
flex-direction: column;
}
</style>
+81
View File
@@ -0,0 +1,81 @@
<template>
<div ref="watermarkContainer" class="watermark-container"></div>
</template>
<script>
import { onMounted,onUnmounted,ref } from 'vue';
export default{
name:'Watermark',
setup(){
const watermarkContainer=ref(null);
const createWatermark=()=>{
if(!watermarkContainer.value)return;
const canvas=document.createElement('canvas');
const ctx=canvas.getContext('2d');
const text='Your watermark'
const fontSize=4;
ctx.font=`${fontSize}px sans-serif`;
ctx.fillStyle='rgba(128,128,128,0.3)';
ctx.textAlign='center';
ctx.textBaseline='middle';
const width=watermarkContainer.value.clientWidth;
const heigth=watermarkContainer.value.clientHeight;
const padding=20;
const lineHeight=fontSize+padding;
const columns=Math.ceil(width/lineHeight);
const rows=Math.ceil(height/lineHeight);
canvas.width=width;
canvas.height=height;
for(let i=0;i<rows;i++){
for(let j=0;j<columns;j++){
ctx.fillText(text,j*lineHeight+lineHeight/2,i*lineHeight+lineHeight/2);
}
}
const watermarkImage=new Image();
watermarkImage.src=canvas.toDataURL();
watermarkImage.onload=()=>{
const watermarkDiv=document.createElement('div');
watermarkDiv.style.backgroundImage=`url(${watermarkImage.src})`;
watermarkDiv.style.backgroundRepeat='repeat';
watermarkDiv.style.position='absolute';
watermarkDiv.style.top=0;
watermarkDiv.style.left=0;
watermarkDiv.style.width='100%';
watermarkDiv.style.height='100%';
watermarkContainer.value.appendChild(watermarkDiv);
}
}
onMounted(()=>{
createWatermark();
window.addEventListener('resize',createWatermark);
})
onUnmounted(()=>{
window.removeEventListener('resize',createWatermark)
})
return {
watermarkContainer
}
}
}
</script>
<style scoped>
.watermark-container{
position:relative;
}
</style>
+36
View File
@@ -0,0 +1,36 @@
export class Box implements IBox {
type: TBoxType = "Box1";
width: number = 0;
height: number = 0;
padding: number = 10;
borderWidth: number = 1;
fontSize:number=18;
fontColor:string="black";
sort: number = 1;
index: number = 1
constructor(_width: string, _height: string, _padding: string | number = 10, type: TBoxType = "Box1") {
this.type = type;
this.width = parseFloat(_width);
this.height = parseFloat(_height);
this.padding = parseFloat(_padding.toString());
}
getOffsetWidth() {
return this.width + this.padding * 2 + this.borderWidth * 2;
}
getOffsetHeight() {
return this.height + this.padding * 2 + this.borderWidth * 2;
}
}
export class Template implements ITemplate {
id: string = "";
width: number = 100;
height: number = 100;
padding: number = 10;
fontSize: number = 18;
fontColor: string = "#000000";
}
+23
View File
@@ -0,0 +1,23 @@
declare type TBoxType = "Box1" | "Box2" | "Box3" | "Box4";
declare interface IBox {
type: TBoxType;
width: number;
height: number;
padding: number;
fontSize:number;
fontColor:string;
sort: number;
index: number;
getOffsetWidth: () => number;
getOffsetHeight: () => number;
}
declare interface ITemplate {
type:TBoxType;
width: number;
height: number;
padding: number;
fontSize: number;
fontColor: string;
}