feat: 优化部分代码
parent
95dfbc6cdb
commit
79e016fbd7
|
|
@ -1,22 +1,22 @@
|
|||
<!-- 修改自: https://github.com/zuley/vue-color-picker -->
|
||||
|
||||
<script setup lang="ts">
|
||||
import { computed, ref } from "vue";
|
||||
import { onClickOutside } from "@vueuse/core";
|
||||
import { computed, ref } from "vue";
|
||||
|
||||
const props = withDefaults(
|
||||
defineProps<{
|
||||
// 当前颜色
|
||||
modelValue: string;
|
||||
// 默认颜色
|
||||
defaultColor?: string;
|
||||
// 禁用状态
|
||||
disabled?: boolean;
|
||||
}>(),
|
||||
{
|
||||
defaultColor: "#000000",
|
||||
}
|
||||
);
|
||||
const props = defineProps({
|
||||
modelValue: {
|
||||
type: String,
|
||||
},
|
||||
defaultColor: {
|
||||
type: String,
|
||||
default: "#000000",
|
||||
},
|
||||
disabled: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
});
|
||||
|
||||
const emits = defineEmits<{
|
||||
(e: "update:modelValue", value: string): void;
|
||||
|
|
@ -112,7 +112,7 @@ const triggerHtml5Color = () => {
|
|||
html5ColorEl.value?.click();
|
||||
};
|
||||
// 更新组件的值
|
||||
const updataValue = (value: string) => {
|
||||
const updataValue = (value: string = "") => {
|
||||
emits("update:modelValue", value);
|
||||
emits("change", value);
|
||||
openStatus.value = false;
|
||||
|
|
@ -196,7 +196,7 @@ const gradient = (startColor: string, endColor: string, step: number) => {
|
|||
</div>
|
||||
</div>
|
||||
<div class="bd">
|
||||
<h3>主题颜色</h3>
|
||||
<h3 class="section-title">主题颜色</h3>
|
||||
<ul class="tColor">
|
||||
<li
|
||||
v-for="(color, index) of tColor"
|
||||
|
|
@ -221,7 +221,7 @@ const gradient = (startColor: string, endColor: string, step: number) => {
|
|||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
<h3>标准颜色</h3>
|
||||
<h3 class="section-title">标准颜色</h3>
|
||||
<ul class="tColor">
|
||||
<li
|
||||
v-for="(color, index) of bColor"
|
||||
|
|
@ -247,6 +247,7 @@ const gradient = (startColor: string, endColor: string, step: number) => {
|
|||
font-size: 14px;
|
||||
display: inline-block;
|
||||
outline: none;
|
||||
|
||||
ul,
|
||||
li,
|
||||
ol {
|
||||
|
|
@ -276,6 +277,7 @@ const gradient = (startColor: string, endColor: string, step: number) => {
|
|||
opacity: 0;
|
||||
transition: all 0.3s ease;
|
||||
box-sizing: content-box;
|
||||
z-index: 99999;
|
||||
h3 {
|
||||
margin: 0;
|
||||
font-size: 14px;
|
||||
|
|
@ -295,7 +297,6 @@ const gradient = (startColor: string, endColor: string, step: number) => {
|
|||
.box.open {
|
||||
visibility: visible;
|
||||
opacity: 1;
|
||||
z-index: 1;
|
||||
}
|
||||
.hd {
|
||||
overflow: hidden;
|
||||
|
|
@ -314,6 +315,9 @@ const gradient = (startColor: string, endColor: string, step: number) => {
|
|||
cursor: pointer;
|
||||
color: #333;
|
||||
}
|
||||
.section-title {
|
||||
color: #899;
|
||||
}
|
||||
}
|
||||
.tColor {
|
||||
li {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,907 @@
|
|||
<!-- 修改自:https://github.com/kirillmurashov/vue-drag-resize -->
|
||||
<template>
|
||||
<div
|
||||
class="vdr"
|
||||
:style="positionStyle"
|
||||
:class="`${active || isActive ? 'active' : 'inactive'} ${contentClass ? contentClass : ''}`"
|
||||
@mousedown="bodyDown($event)"
|
||||
@touchstart="bodyDown($event)"
|
||||
@touchend="up($event)"
|
||||
>
|
||||
<div :style="sizeStyle" class="content-container" ref="container">
|
||||
<slot></slot>
|
||||
</div>
|
||||
<div
|
||||
v-for="stick in sticks"
|
||||
class="vdr-stick"
|
||||
:class="['vdr-stick-' + stick, isResizable ? '' : 'not-resizable']"
|
||||
@mousedown.stop.prevent="stickDown(stick, $event)"
|
||||
@touchstart.stop.prevent="stickDown(stick, $event)"
|
||||
:style="vdrStick(stick)"
|
||||
></div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
const styleMapping = {
|
||||
y: {
|
||||
t: "top",
|
||||
m: "marginTop",
|
||||
b: "bottom",
|
||||
},
|
||||
x: {
|
||||
l: "left",
|
||||
m: "marginLeft",
|
||||
r: "right",
|
||||
},
|
||||
};
|
||||
|
||||
function addEvents(events) {
|
||||
events.forEach((cb, eventName) => {
|
||||
document.documentElement.addEventListener(eventName, cb);
|
||||
});
|
||||
}
|
||||
|
||||
function removeEvents(events) {
|
||||
events.forEach((cb, eventName) => {
|
||||
document.documentElement.removeEventListener(eventName, cb);
|
||||
});
|
||||
}
|
||||
|
||||
export default {
|
||||
name: "vue-drag-resize",
|
||||
|
||||
emits: ["clicked", "dragging", "dragstop", "resizing", "resizestop", "activated", "deactivated"],
|
||||
|
||||
props: {
|
||||
stickSize: {
|
||||
type: Number,
|
||||
default: 8,
|
||||
},
|
||||
parentScaleX: {
|
||||
type: Number,
|
||||
default: 1,
|
||||
},
|
||||
parentScaleY: {
|
||||
type: Number,
|
||||
default: 1,
|
||||
},
|
||||
isActive: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
preventActiveBehavior: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
isDraggable: {
|
||||
type: Boolean,
|
||||
default: true,
|
||||
},
|
||||
isResizable: {
|
||||
type: Boolean,
|
||||
default: true,
|
||||
},
|
||||
aspectRatio: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
parentLimitation: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
snapToGrid: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
gridX: {
|
||||
type: Number,
|
||||
default: 50,
|
||||
validator(val) {
|
||||
return val >= 0;
|
||||
},
|
||||
},
|
||||
gridY: {
|
||||
type: Number,
|
||||
default: 50,
|
||||
validator(val) {
|
||||
return val >= 0;
|
||||
},
|
||||
},
|
||||
parentW: {
|
||||
type: Number,
|
||||
default: 0,
|
||||
validator(val) {
|
||||
return val >= 0;
|
||||
},
|
||||
},
|
||||
parentH: {
|
||||
type: Number,
|
||||
default: 0,
|
||||
validator(val) {
|
||||
return val >= 0;
|
||||
},
|
||||
},
|
||||
w: {
|
||||
type: [String, Number],
|
||||
default: 200,
|
||||
validator(val) {
|
||||
return typeof val === "string" ? val === "auto" : val >= 0;
|
||||
},
|
||||
},
|
||||
h: {
|
||||
type: [String, Number],
|
||||
default: 200,
|
||||
validator(val) {
|
||||
return typeof val === "string" ? val === "auto" : val >= 0;
|
||||
},
|
||||
},
|
||||
minw: {
|
||||
type: Number,
|
||||
default: 50,
|
||||
validator(val) {
|
||||
return val >= 0;
|
||||
},
|
||||
},
|
||||
minh: {
|
||||
type: Number,
|
||||
default: 50,
|
||||
validator(val) {
|
||||
return val >= 0;
|
||||
},
|
||||
},
|
||||
x: {
|
||||
type: Number,
|
||||
default: 0,
|
||||
validator(val) {
|
||||
return typeof val === "number";
|
||||
},
|
||||
},
|
||||
y: {
|
||||
type: Number,
|
||||
default: 0,
|
||||
validator(val) {
|
||||
return typeof val === "number";
|
||||
},
|
||||
},
|
||||
z: {
|
||||
type: [String, Number],
|
||||
default: "auto",
|
||||
validator(val) {
|
||||
return typeof val === "string" ? val === "auto" : val >= 0;
|
||||
},
|
||||
},
|
||||
dragHandle: {
|
||||
type: String,
|
||||
default: null,
|
||||
},
|
||||
dragCancel: {
|
||||
type: String,
|
||||
default: null,
|
||||
},
|
||||
sticks: {
|
||||
type: Array,
|
||||
default() {
|
||||
return ["tl", "tm", "tr", "mr", "br", "bm", "bl", "ml"];
|
||||
},
|
||||
},
|
||||
axis: {
|
||||
type: String,
|
||||
default: "both",
|
||||
validator(val) {
|
||||
return ["x", "y", "both", "none"].indexOf(val) !== -1;
|
||||
},
|
||||
},
|
||||
contentClass: {
|
||||
type: String,
|
||||
required: false,
|
||||
default: "",
|
||||
},
|
||||
},
|
||||
|
||||
data() {
|
||||
return {
|
||||
fixAspectRatio: null,
|
||||
active: null,
|
||||
zIndex: null,
|
||||
parentWidth: null,
|
||||
parentHeight: null,
|
||||
left: null,
|
||||
top: null,
|
||||
right: null,
|
||||
bottom: null,
|
||||
minHeight: null,
|
||||
};
|
||||
},
|
||||
|
||||
beforeCreate() {
|
||||
this.stickDrag = false;
|
||||
this.bodyDrag = false;
|
||||
this.dimensionsBeforeMove = { pointerX: 0, pointerY: 0, x: 0, y: 0, w: 0, h: 0 };
|
||||
this.limits = {
|
||||
left: { min: null, max: null },
|
||||
right: { min: null, max: null },
|
||||
top: { min: null, max: null },
|
||||
bottom: { min: null, max: null },
|
||||
};
|
||||
|
||||
this.currentStick = null;
|
||||
},
|
||||
|
||||
mounted() {
|
||||
this.parentElement = this.$el.parentNode;
|
||||
this.parentWidth = this.parentW ? this.parentW : this.parentElement.clientWidth;
|
||||
this.parentHeight = this.parentH ? this.parentH : this.parentElement.clientHeight;
|
||||
|
||||
this.left = this.x;
|
||||
this.top = this.y;
|
||||
this.right = this.parentWidth - (this.w === "auto" ? this.$refs.container.scrollWidth : this.w) - this.left;
|
||||
this.bottom = this.parentHeight - (this.h === "auto" ? this.$refs.container.scrollHeight : this.h) - this.top;
|
||||
|
||||
this.domEvents = new Map([
|
||||
["mousemove", this.move],
|
||||
["mouseup", this.up],
|
||||
["mouseleave", this.up],
|
||||
["mousedown", this.deselect],
|
||||
["touchmove", this.move],
|
||||
["touchend", this.up],
|
||||
["touchcancel", this.up],
|
||||
["touchstart", this.up],
|
||||
]);
|
||||
|
||||
addEvents(this.domEvents);
|
||||
|
||||
if (this.dragHandle) {
|
||||
[...this.$el.querySelectorAll(this.dragHandle)].forEach((dragHandle) => {
|
||||
dragHandle.setAttribute("data-drag-handle", this._uid);
|
||||
});
|
||||
}
|
||||
|
||||
if (this.dragCancel) {
|
||||
[...this.$el.querySelectorAll(this.dragCancel)].forEach((cancelHandle) => {
|
||||
cancelHandle.setAttribute("data-drag-cancel", this._uid);
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
beforeDestroy() {
|
||||
removeEvents(this.domEvents);
|
||||
},
|
||||
|
||||
methods: {
|
||||
deselect() {
|
||||
if (this.preventActiveBehavior) {
|
||||
return;
|
||||
}
|
||||
this.active = false;
|
||||
},
|
||||
|
||||
move(ev) {
|
||||
if (!this.stickDrag && !this.bodyDrag) {
|
||||
return;
|
||||
}
|
||||
|
||||
ev.stopPropagation();
|
||||
|
||||
const pageX = typeof ev.pageX !== "undefined" ? ev.pageX : ev.touches[0].pageX;
|
||||
const pageY = typeof ev.pageY !== "undefined" ? ev.pageY : ev.touches[0].pageY;
|
||||
|
||||
const { dimensionsBeforeMove } = this;
|
||||
|
||||
const delta = {
|
||||
x: (dimensionsBeforeMove.pointerX - pageX) / this.parentScaleX,
|
||||
y: (dimensionsBeforeMove.pointerY - pageY) / this.parentScaleY,
|
||||
};
|
||||
|
||||
if (this.stickDrag) {
|
||||
this.stickMove(delta);
|
||||
}
|
||||
|
||||
if (this.bodyDrag) {
|
||||
if (this.axis === "x") {
|
||||
delta.y = 0;
|
||||
} else if (this.axis === "y") {
|
||||
delta.x = 0;
|
||||
} else if (this.axis === "none") {
|
||||
return;
|
||||
}
|
||||
this.bodyMove(delta);
|
||||
}
|
||||
},
|
||||
|
||||
up(ev) {
|
||||
if (this.stickDrag) {
|
||||
this.stickUp(ev);
|
||||
} else if (this.bodyDrag) {
|
||||
this.bodyUp(ev);
|
||||
}
|
||||
},
|
||||
|
||||
bodyDown(ev) {
|
||||
const { target, button } = ev;
|
||||
|
||||
if (!this.preventActiveBehavior) {
|
||||
this.active = true;
|
||||
}
|
||||
|
||||
if (button && button !== 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.$emit("clicked", ev);
|
||||
|
||||
if (!this.active) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.dragHandle && target.getAttribute("data-drag-handle") !== this._uid.toString()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.dragCancel && target.getAttribute("data-drag-cancel") === this._uid.toString()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (typeof ev.stopPropagation !== "undefined") {
|
||||
ev.stopPropagation();
|
||||
}
|
||||
|
||||
if (typeof ev.preventDefault !== "undefined") {
|
||||
ev.preventDefault();
|
||||
}
|
||||
|
||||
if (this.isDraggable) {
|
||||
this.bodyDrag = true;
|
||||
}
|
||||
|
||||
const pointerX = typeof ev.pageX !== "undefined" ? ev.pageX : ev.touches[0].pageX;
|
||||
const pointerY = typeof ev.pageY !== "undefined" ? ev.pageY : ev.touches[0].pageY;
|
||||
|
||||
this.saveDimensionsBeforeMove({ pointerX, pointerY });
|
||||
|
||||
if (this.parentLimitation) {
|
||||
this.limits = this.calcDragLimitation();
|
||||
}
|
||||
},
|
||||
|
||||
bodyMove(delta) {
|
||||
const { dimensionsBeforeMove, parentWidth, parentHeight, gridX, gridY, width, height } = this;
|
||||
|
||||
let newTop = dimensionsBeforeMove.top - delta.y;
|
||||
let newBottom = dimensionsBeforeMove.bottom + delta.y;
|
||||
let newLeft = dimensionsBeforeMove.left - delta.x;
|
||||
let newRight = dimensionsBeforeMove.right + delta.x;
|
||||
|
||||
if (this.snapToGrid) {
|
||||
let alignTop = true;
|
||||
let alignLeft = true;
|
||||
|
||||
let diffT = newTop - Math.floor(newTop / gridY) * gridY;
|
||||
let diffB = parentHeight - newBottom - Math.floor((parentHeight - newBottom) / gridY) * gridY;
|
||||
let diffL = newLeft - Math.floor(newLeft / gridX) * gridX;
|
||||
let diffR = parentWidth - newRight - Math.floor((parentWidth - newRight) / gridX) * gridX;
|
||||
|
||||
if (diffT > gridY / 2) {
|
||||
diffT -= gridY;
|
||||
}
|
||||
if (diffB > gridY / 2) {
|
||||
diffB -= gridY;
|
||||
}
|
||||
if (diffL > gridX / 2) {
|
||||
diffL -= gridX;
|
||||
}
|
||||
if (diffR > gridX / 2) {
|
||||
diffR -= gridX;
|
||||
}
|
||||
|
||||
if (Math.abs(diffB) < Math.abs(diffT)) {
|
||||
alignTop = false;
|
||||
}
|
||||
if (Math.abs(diffR) < Math.abs(diffL)) {
|
||||
alignLeft = false;
|
||||
}
|
||||
|
||||
newTop -= alignTop ? diffT : diffB;
|
||||
newBottom = parentHeight - height - newTop;
|
||||
newLeft -= alignLeft ? diffL : diffR;
|
||||
newRight = parentWidth - width - newLeft;
|
||||
}
|
||||
|
||||
({
|
||||
newLeft: this.left,
|
||||
newRight: this.right,
|
||||
newTop: this.top,
|
||||
newBottom: this.bottom,
|
||||
} = this.rectCorrectionByLimit({ newLeft, newRight, newTop, newBottom }));
|
||||
|
||||
this.$emit("dragging", this.rect);
|
||||
},
|
||||
|
||||
bodyUp() {
|
||||
this.bodyDrag = false;
|
||||
this.$emit("dragging", this.rect);
|
||||
this.$emit("dragstop", this.rect);
|
||||
|
||||
this.dimensionsBeforeMove = { pointerX: 0, pointerY: 0, x: 0, y: 0, w: 0, h: 0 };
|
||||
|
||||
this.limits = {
|
||||
left: { min: null, max: null },
|
||||
right: { min: null, max: null },
|
||||
top: { min: null, max: null },
|
||||
bottom: { min: null, max: null },
|
||||
};
|
||||
},
|
||||
|
||||
stickDown(stick, ev, force = false) {
|
||||
if ((!this.isResizable || !this.active) && !force) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.stickDrag = true;
|
||||
|
||||
const pointerX = typeof ev.pageX !== "undefined" ? ev.pageX : ev.touches[0].pageX;
|
||||
const pointerY = typeof ev.pageY !== "undefined" ? ev.pageY : ev.touches[0].pageY;
|
||||
|
||||
this.saveDimensionsBeforeMove({ pointerX, pointerY });
|
||||
|
||||
this.currentStick = stick;
|
||||
|
||||
this.limits = this.calcResizeLimits();
|
||||
},
|
||||
|
||||
saveDimensionsBeforeMove({ pointerX, pointerY }) {
|
||||
this.dimensionsBeforeMove.pointerX = pointerX;
|
||||
this.dimensionsBeforeMove.pointerY = pointerY;
|
||||
|
||||
this.dimensionsBeforeMove.left = this.left;
|
||||
this.dimensionsBeforeMove.right = this.right;
|
||||
this.dimensionsBeforeMove.top = this.top;
|
||||
this.dimensionsBeforeMove.bottom = this.bottom;
|
||||
|
||||
this.dimensionsBeforeMove.width = this.width;
|
||||
this.dimensionsBeforeMove.height = this.height;
|
||||
|
||||
this.aspectFactor = this.width / this.height;
|
||||
},
|
||||
|
||||
stickMove(delta) {
|
||||
const { currentStick, dimensionsBeforeMove, gridY, gridX, snapToGrid, parentHeight, parentWidth } = this;
|
||||
|
||||
let newTop = dimensionsBeforeMove.top;
|
||||
let newBottom = dimensionsBeforeMove.bottom;
|
||||
let newLeft = dimensionsBeforeMove.left;
|
||||
let newRight = dimensionsBeforeMove.right;
|
||||
switch (currentStick[0]) {
|
||||
case "b":
|
||||
newBottom = dimensionsBeforeMove.bottom + delta.y;
|
||||
|
||||
if (snapToGrid) {
|
||||
newBottom = parentHeight - Math.round((parentHeight - newBottom) / gridY) * gridY;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case "t":
|
||||
newTop = dimensionsBeforeMove.top - delta.y;
|
||||
|
||||
if (snapToGrid) {
|
||||
newTop = Math.round(newTop / gridY) * gridY;
|
||||
}
|
||||
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
switch (currentStick[1]) {
|
||||
case "r":
|
||||
newRight = dimensionsBeforeMove.right + delta.x;
|
||||
|
||||
if (snapToGrid) {
|
||||
newRight = parentWidth - Math.round((parentWidth - newRight) / gridX) * gridX;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case "l":
|
||||
newLeft = dimensionsBeforeMove.left - delta.x;
|
||||
|
||||
if (snapToGrid) {
|
||||
newLeft = Math.round(newLeft / gridX) * gridX;
|
||||
}
|
||||
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
({ newLeft, newRight, newTop, newBottom } = this.rectCorrectionByLimit({ newLeft, newRight, newTop, newBottom }));
|
||||
|
||||
if (this.aspectRatio) {
|
||||
({ newLeft, newRight, newTop, newBottom } = this.rectCorrectionByAspectRatio({
|
||||
newLeft,
|
||||
newRight,
|
||||
newTop,
|
||||
newBottom,
|
||||
}));
|
||||
}
|
||||
|
||||
this.left = newLeft;
|
||||
this.right = newRight;
|
||||
this.top = newTop;
|
||||
this.bottom = newBottom;
|
||||
|
||||
this.$emit("resizing", this.rect);
|
||||
},
|
||||
|
||||
stickUp() {
|
||||
this.stickDrag = false;
|
||||
this.dimensionsBeforeMove = {
|
||||
pointerX: 0,
|
||||
pointerY: 0,
|
||||
x: 0,
|
||||
y: 0,
|
||||
w: 0,
|
||||
h: 0,
|
||||
};
|
||||
this.limits = {
|
||||
left: { min: null, max: null },
|
||||
right: { min: null, max: null },
|
||||
top: { min: null, max: null },
|
||||
bottom: { min: null, max: null },
|
||||
};
|
||||
|
||||
this.$emit("resizing", this.rect);
|
||||
this.$emit("resizestop", this.rect);
|
||||
},
|
||||
|
||||
calcDragLimitation() {
|
||||
const { parentWidth, parentHeight } = this;
|
||||
|
||||
return {
|
||||
left: { min: 0, max: parentWidth - this.width },
|
||||
right: { min: 0, max: parentWidth - this.width },
|
||||
top: { min: 0, max: parentHeight - this.height },
|
||||
bottom: { min: 0, max: parentHeight - this.height },
|
||||
};
|
||||
},
|
||||
|
||||
calcResizeLimits() {
|
||||
const { aspectFactor, width, height, bottom, top, left, right } = this;
|
||||
let { minh: minHeight, minw: minWidth } = this;
|
||||
|
||||
const parentLim = this.parentLimitation ? 0 : null;
|
||||
|
||||
if (this.aspectRatio) {
|
||||
if (minWidth / minHeight > aspectFactor) {
|
||||
minHeight = minWidth / aspectFactor;
|
||||
} else {
|
||||
minWidth = aspectFactor * minHeight;
|
||||
}
|
||||
}
|
||||
|
||||
const limits = {
|
||||
left: { min: parentLim, max: left + (width - minWidth) },
|
||||
right: { min: parentLim, max: right + (width - minWidth) },
|
||||
top: { min: parentLim, max: top + (height - minHeight) },
|
||||
bottom: { min: parentLim, max: bottom + (height - minHeight) },
|
||||
};
|
||||
|
||||
if (this.aspectRatio) {
|
||||
const aspectLimits = {
|
||||
left: {
|
||||
min: left - Math.min(top, bottom) * aspectFactor * 2,
|
||||
max: left + ((height - minHeight) / 2) * aspectFactor * 2,
|
||||
},
|
||||
right: {
|
||||
min: right - Math.min(top, bottom) * aspectFactor * 2,
|
||||
max: right + ((height - minHeight) / 2) * aspectFactor * 2,
|
||||
},
|
||||
top: {
|
||||
min: top - (Math.min(left, right) / aspectFactor) * 2,
|
||||
max: top + ((width - minWidth) / 2 / aspectFactor) * 2,
|
||||
},
|
||||
bottom: {
|
||||
min: bottom - (Math.min(left, right) / aspectFactor) * 2,
|
||||
max: bottom + ((width - minWidth) / 2 / aspectFactor) * 2,
|
||||
},
|
||||
};
|
||||
|
||||
if (this.currentStick[0] === "m") {
|
||||
limits.left = {
|
||||
min: Math.max(limits.left.min, aspectLimits.left.min),
|
||||
max: Math.min(limits.left.max, aspectLimits.left.max),
|
||||
};
|
||||
limits.right = {
|
||||
min: Math.max(limits.right.min, aspectLimits.right.min),
|
||||
max: Math.min(limits.right.max, aspectLimits.right.max),
|
||||
};
|
||||
} else if (this.currentStick[1] === "m") {
|
||||
limits.top = {
|
||||
min: Math.max(limits.top.min, aspectLimits.top.min),
|
||||
max: Math.min(limits.top.max, aspectLimits.top.max),
|
||||
};
|
||||
limits.bottom = {
|
||||
min: Math.max(limits.bottom.min, aspectLimits.bottom.min),
|
||||
max: Math.min(limits.bottom.max, aspectLimits.bottom.max),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
return limits;
|
||||
},
|
||||
|
||||
sideCorrectionByLimit(limit, current) {
|
||||
let value = current;
|
||||
|
||||
if (limit.min !== null && current < limit.min) {
|
||||
value = limit.min;
|
||||
} else if (limit.max !== null && limit.max < current) {
|
||||
value = limit.max;
|
||||
}
|
||||
|
||||
return value;
|
||||
},
|
||||
|
||||
rectCorrectionByLimit(rect) {
|
||||
const { limits } = this;
|
||||
let { newRight, newLeft, newBottom, newTop } = rect;
|
||||
|
||||
newLeft = this.sideCorrectionByLimit(limits.left, newLeft);
|
||||
newRight = this.sideCorrectionByLimit(limits.right, newRight);
|
||||
newTop = this.sideCorrectionByLimit(limits.top, newTop);
|
||||
newBottom = this.sideCorrectionByLimit(limits.bottom, newBottom);
|
||||
|
||||
return {
|
||||
newLeft,
|
||||
newRight,
|
||||
newTop,
|
||||
newBottom,
|
||||
};
|
||||
},
|
||||
|
||||
rectCorrectionByAspectRatio(rect) {
|
||||
let { newLeft, newRight, newTop, newBottom } = rect;
|
||||
const { parentWidth, parentHeight, currentStick, aspectFactor, dimensionsBeforeMove } = this;
|
||||
|
||||
let newWidth = parentWidth - newLeft - newRight;
|
||||
let newHeight = parentHeight - newTop - newBottom;
|
||||
|
||||
if (currentStick[1] === "m") {
|
||||
const deltaHeight = newHeight - dimensionsBeforeMove.height;
|
||||
|
||||
newLeft -= (deltaHeight * aspectFactor) / 2;
|
||||
newRight -= (deltaHeight * aspectFactor) / 2;
|
||||
} else if (currentStick[0] === "m") {
|
||||
const deltaWidth = newWidth - dimensionsBeforeMove.width;
|
||||
|
||||
newTop -= deltaWidth / aspectFactor / 2;
|
||||
newBottom -= deltaWidth / aspectFactor / 2;
|
||||
} else if (newWidth / newHeight > aspectFactor) {
|
||||
newWidth = aspectFactor * newHeight;
|
||||
|
||||
if (currentStick[1] === "l") {
|
||||
newLeft = parentWidth - newRight - newWidth;
|
||||
} else {
|
||||
newRight = parentWidth - newLeft - newWidth;
|
||||
}
|
||||
} else {
|
||||
newHeight = newWidth / aspectFactor;
|
||||
|
||||
if (currentStick[0] === "t") {
|
||||
newTop = parentHeight - newBottom - newHeight;
|
||||
} else {
|
||||
newBottom = parentHeight - newTop - newHeight;
|
||||
}
|
||||
}
|
||||
|
||||
return { newLeft, newRight, newTop, newBottom };
|
||||
},
|
||||
},
|
||||
|
||||
computed: {
|
||||
positionStyle() {
|
||||
return {
|
||||
top: this.top + "px",
|
||||
left: this.left + "px",
|
||||
zIndex: this.zIndex,
|
||||
};
|
||||
},
|
||||
|
||||
sizeStyle() {
|
||||
return {
|
||||
width: this.w == "auto" ? "auto" : this.width + "px",
|
||||
height: this.h == "auto" ? "auto" : this.height + "px",
|
||||
};
|
||||
},
|
||||
|
||||
vdrStick() {
|
||||
return (stick) => {
|
||||
const stickStyle = {
|
||||
width: `${this.stickSize / this.parentScaleX}px`,
|
||||
height: `${this.stickSize / this.parentScaleY}px`,
|
||||
};
|
||||
stickStyle[styleMapping.y[stick[0]]] = `${this.stickSize / this.parentScaleX / -2}px`;
|
||||
stickStyle[styleMapping.x[stick[1]]] = `${this.stickSize / this.parentScaleX / -2}px`;
|
||||
return stickStyle;
|
||||
};
|
||||
},
|
||||
|
||||
width() {
|
||||
return this.parentWidth - this.left - this.right;
|
||||
},
|
||||
|
||||
height() {
|
||||
return this.parentHeight - this.top - this.bottom;
|
||||
},
|
||||
|
||||
rect() {
|
||||
return {
|
||||
left: Math.round(this.left),
|
||||
top: Math.round(this.top),
|
||||
width: Math.round(this.width),
|
||||
height: Math.round(this.height),
|
||||
};
|
||||
},
|
||||
},
|
||||
|
||||
watch: {
|
||||
active(isActive) {
|
||||
if (isActive) {
|
||||
this.$emit("activated");
|
||||
} else {
|
||||
this.$emit("deactivated");
|
||||
}
|
||||
},
|
||||
|
||||
isActive: {
|
||||
immediate: true,
|
||||
handler(val) {
|
||||
this.active = val;
|
||||
},
|
||||
},
|
||||
|
||||
z: {
|
||||
immediate: true,
|
||||
handler(val) {
|
||||
if (val >= 0 || val === "auto") {
|
||||
this.zIndex = val;
|
||||
}
|
||||
},
|
||||
},
|
||||
|
||||
x: {
|
||||
handler(newVal, oldVal) {
|
||||
if (this.stickDrag || this.bodyDrag || newVal === this.left) {
|
||||
return;
|
||||
}
|
||||
|
||||
const delta = oldVal - newVal;
|
||||
|
||||
this.bodyDown({ pageX: this.left, pageY: this.top });
|
||||
this.bodyMove({ x: delta, y: 0 });
|
||||
|
||||
this.$nextTick(() => {
|
||||
this.bodyUp();
|
||||
});
|
||||
},
|
||||
},
|
||||
|
||||
y: {
|
||||
handler(newVal, oldVal) {
|
||||
if (this.stickDrag || this.bodyDrag || newVal === this.top) {
|
||||
return;
|
||||
}
|
||||
|
||||
const delta = oldVal - newVal;
|
||||
|
||||
this.bodyDown({ pageX: this.left, pageY: this.top });
|
||||
this.bodyMove({ x: 0, y: delta });
|
||||
|
||||
this.$nextTick(() => {
|
||||
this.bodyUp();
|
||||
});
|
||||
},
|
||||
},
|
||||
|
||||
w: {
|
||||
handler(newVal, oldVal) {
|
||||
if (this.stickDrag || this.bodyDrag || newVal === this.width) {
|
||||
return;
|
||||
}
|
||||
|
||||
const stick = "mr";
|
||||
const delta = oldVal - newVal;
|
||||
|
||||
this.stickDown(stick, { pageX: this.right, pageY: this.top + this.height / 2 }, true);
|
||||
this.stickMove({ x: delta, y: 0 });
|
||||
|
||||
this.$nextTick(() => {
|
||||
this.stickUp();
|
||||
});
|
||||
},
|
||||
},
|
||||
|
||||
h: {
|
||||
handler(newVal, oldVal) {
|
||||
if (this.stickDrag || this.bodyDrag || newVal === this.height) {
|
||||
return;
|
||||
}
|
||||
|
||||
const stick = "bm";
|
||||
const delta = oldVal - newVal;
|
||||
|
||||
this.stickDown(stick, { pageX: this.left + this.width / 2, pageY: this.bottom }, true);
|
||||
this.stickMove({ x: 0, y: delta });
|
||||
|
||||
this.$nextTick(() => {
|
||||
this.stickUp();
|
||||
});
|
||||
},
|
||||
},
|
||||
|
||||
parentW(val) {
|
||||
this.right = val - this.width - this.left;
|
||||
this.parentWidth = val;
|
||||
},
|
||||
|
||||
parentH(val) {
|
||||
this.bottom = val - this.height - this.top;
|
||||
this.parentHeight = val;
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.vdr {
|
||||
position: absolute;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
.vdr.active:before {
|
||||
content: "";
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
box-sizing: border-box;
|
||||
outline: 1px dashed #d6d6d6;
|
||||
}
|
||||
.vdr-stick {
|
||||
box-sizing: border-box;
|
||||
position: absolute;
|
||||
font-size: 1px;
|
||||
background: #ffffff;
|
||||
border: 1px solid #6c6c6c;
|
||||
box-shadow: 0 0 2px #bbb;
|
||||
}
|
||||
.inactive .vdr-stick {
|
||||
display: none;
|
||||
}
|
||||
.vdr-stick-tl,
|
||||
.vdr-stick-br {
|
||||
cursor: nwse-resize;
|
||||
}
|
||||
.vdr-stick-tm,
|
||||
.vdr-stick-bm {
|
||||
left: 50%;
|
||||
cursor: ns-resize;
|
||||
}
|
||||
.vdr-stick-tr,
|
||||
.vdr-stick-bl {
|
||||
cursor: nesw-resize;
|
||||
}
|
||||
.vdr-stick-ml,
|
||||
.vdr-stick-mr {
|
||||
top: 50%;
|
||||
cursor: ew-resize;
|
||||
}
|
||||
.vdr-stick.not-resizable {
|
||||
display: none;
|
||||
}
|
||||
.content-container {
|
||||
display: block;
|
||||
position: relative;
|
||||
}
|
||||
</style>
|
||||
|
|
@ -0,0 +1 @@
|
|||
export const ContextKey = Symbol('ContextKey');
|
||||
|
|
@ -20,10 +20,20 @@
|
|||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ContextKey } from './config';
|
||||
import PanelHeader from "./panel-header/index.vue";
|
||||
import PanelLeft from "./panel-left/index.vue";
|
||||
import PanelMain from "./panel-main/index.vue";
|
||||
import PanelRight from "./panel-right/index.vue";
|
||||
import PanelHeader from "./panel-header/index.vue";
|
||||
|
||||
const context = reactive({
|
||||
current: {
|
||||
|
||||
}
|
||||
})
|
||||
|
||||
provide(ContextKey, {})
|
||||
|
||||
</script>
|
||||
|
||||
<style lang="less">
|
||||
|
|
@ -55,5 +65,9 @@ import PanelHeader from "./panel-header/index.vue";
|
|||
.arco-form-item-content-flex {
|
||||
display: block;
|
||||
}
|
||||
.arco-divider-text-left {
|
||||
left: 0;
|
||||
padding-left: 0;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -5,12 +5,29 @@ export interface Block<T = any> {
|
|||
y: number;
|
||||
w: number;
|
||||
h: number;
|
||||
xFixed: boolean;
|
||||
yFixed: boolean;
|
||||
bgImage?: string;
|
||||
bgColor?: string;
|
||||
data: T;
|
||||
meta: Record<string, any>;
|
||||
}
|
||||
|
||||
export const DefaultBlock: Block = {
|
||||
id: "",
|
||||
type: "",
|
||||
x: 0,
|
||||
y: 0,
|
||||
w: 50,
|
||||
h: 50,
|
||||
xFixed: false,
|
||||
yFixed: false,
|
||||
bgImage: "",
|
||||
bgColor: "",
|
||||
data: {},
|
||||
meta: {},
|
||||
}
|
||||
|
||||
export interface Container {
|
||||
id: string;
|
||||
type: string;
|
||||
|
|
|
|||
|
|
@ -1,87 +1,6 @@
|
|||
export interface Text {
|
||||
/**
|
||||
* 文字内容
|
||||
*/
|
||||
text: string;
|
||||
/**
|
||||
* 字体
|
||||
*/
|
||||
family: string;
|
||||
/**
|
||||
* 字号(px)
|
||||
*/
|
||||
size: number;
|
||||
/**
|
||||
* 颜色(16进制)
|
||||
*/
|
||||
color: string;
|
||||
/**
|
||||
* 是否加粗
|
||||
*/
|
||||
bold: boolean;
|
||||
/**
|
||||
* 是否斜体
|
||||
*/
|
||||
italic: boolean;
|
||||
/**
|
||||
* 是否下划线
|
||||
*/
|
||||
underline: boolean;
|
||||
/**
|
||||
* 对齐方式
|
||||
*/
|
||||
align: number;
|
||||
}
|
||||
import Option from './option.vue'
|
||||
import Render from './render.vue'
|
||||
export * from './interface'
|
||||
|
||||
export const DefaultText = {
|
||||
text: "双击编辑文字",
|
||||
family: "microsoft yahei",
|
||||
size: 14,
|
||||
color: "#000000",
|
||||
bold: false,
|
||||
italic: false,
|
||||
underline: false,
|
||||
align: 3,
|
||||
}
|
||||
export { Option, Render }
|
||||
|
||||
export const TextAlignOptions = [
|
||||
{
|
||||
label: "居上",
|
||||
value: 1,
|
||||
},
|
||||
{
|
||||
label: "居下",
|
||||
value: 2,
|
||||
},
|
||||
{
|
||||
label: "居中",
|
||||
value: 3,
|
||||
},
|
||||
{
|
||||
label: "居左",
|
||||
value: 4,
|
||||
},
|
||||
{
|
||||
label: "居右",
|
||||
value: 5,
|
||||
},
|
||||
];
|
||||
|
||||
export const TextFamilyOptions = [
|
||||
{
|
||||
label: "微软雅黑111111111",
|
||||
value: "microsoft yahei",
|
||||
},
|
||||
{
|
||||
label: "黑体",
|
||||
value: "gothic",
|
||||
},
|
||||
{
|
||||
label: "宋体",
|
||||
value: "simsun",
|
||||
},
|
||||
{
|
||||
label: "Arial",
|
||||
value: "arial",
|
||||
},
|
||||
];
|
||||
|
|
|
|||
|
|
@ -0,0 +1,87 @@
|
|||
export interface Text {
|
||||
/**
|
||||
* 文字内容
|
||||
*/
|
||||
text: string;
|
||||
/**
|
||||
* 字体
|
||||
*/
|
||||
family: string;
|
||||
/**
|
||||
* 字号(px)
|
||||
*/
|
||||
size: number;
|
||||
/**
|
||||
* 颜色(16进制)
|
||||
*/
|
||||
color: string;
|
||||
/**
|
||||
* 是否加粗
|
||||
*/
|
||||
bold: boolean;
|
||||
/**
|
||||
* 是否斜体
|
||||
*/
|
||||
italic: boolean;
|
||||
/**
|
||||
* 是否下划线
|
||||
*/
|
||||
underline: boolean;
|
||||
/**
|
||||
* 对齐方式
|
||||
*/
|
||||
align: number;
|
||||
}
|
||||
|
||||
export const DefaultText: Text = {
|
||||
text: "双击编辑文字",
|
||||
family: "microsoft yahei",
|
||||
size: 14,
|
||||
color: "#000000",
|
||||
bold: false,
|
||||
italic: false,
|
||||
underline: false,
|
||||
align: 3,
|
||||
}
|
||||
|
||||
export const TextAlignOptions = [
|
||||
{
|
||||
label: "居上",
|
||||
value: 1,
|
||||
},
|
||||
{
|
||||
label: "居下",
|
||||
value: 2,
|
||||
},
|
||||
{
|
||||
label: "居中",
|
||||
value: 3,
|
||||
},
|
||||
{
|
||||
label: "居左",
|
||||
value: 4,
|
||||
},
|
||||
{
|
||||
label: "居右",
|
||||
value: 5,
|
||||
},
|
||||
];
|
||||
|
||||
export const TextFamilyOptions = [
|
||||
{
|
||||
label: "微软雅黑111111111",
|
||||
value: "microsoft yahei",
|
||||
},
|
||||
{
|
||||
label: "黑体",
|
||||
value: "gothic",
|
||||
},
|
||||
{
|
||||
label: "宋体",
|
||||
value: "simsun",
|
||||
},
|
||||
{
|
||||
label: "Arial",
|
||||
value: "arial",
|
||||
},
|
||||
];
|
||||
|
|
@ -9,7 +9,8 @@
|
|||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { Text } from "./index.ts";
|
||||
import { PropType } from "vue";
|
||||
import { Text } from "./interface";
|
||||
|
||||
const props = defineProps({
|
||||
data: {
|
||||
|
|
@ -57,7 +58,7 @@ const style = computed(() => {
|
|||
color,
|
||||
textAlign,
|
||||
verticalAlign,
|
||||
};
|
||||
} as any;
|
||||
});
|
||||
</script>
|
||||
|
||||
|
|
|
|||
|
|
@ -1,10 +1,20 @@
|
|||
<template>
|
||||
<div class="h-full flex items-center justify-between px-4">
|
||||
<div class="text-base">前端编辑器</div>
|
||||
<div class="text-base group">
|
||||
<a-tag color="green" bordered class="mr-1.5"> 新增 </a-tag>前端编辑器
|
||||
<i class="icon-park-outline-edit text-gray-400 hover:text-gray-700 ml-1"></i>
|
||||
</div>
|
||||
<div class="flex gap-2">
|
||||
<a-button> 导出 </a-button>
|
||||
<a-button> 设置 </a-button>
|
||||
<a-button type="primary"> 立即保存 </a-button>
|
||||
<a-button>退出</a-button>
|
||||
<a-dropdown-button type="primary">
|
||||
保存
|
||||
<template #content>
|
||||
<a-doption>保存为JSON</a-doption>
|
||||
<a-doption>保存为图片</a-doption>
|
||||
</template>
|
||||
</a-dropdown-button>
|
||||
<a-button status="danger">退出</a-button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
<template>
|
||||
<div>
|
||||
<div class="border-r border-slate-200">
|
||||
<div class="h-full grid grid-cols-[auto_1fr]" :style="{ width: !collapsed ? '248px' : undefined }">
|
||||
<div class="h-full grid grid-rows-[1fr_auto] border-r border-slate-200">
|
||||
<a-menu :collapsed="true">
|
||||
<a-menu-item key="0_0">
|
||||
<template #icon>
|
||||
|
|
@ -27,11 +27,32 @@
|
|||
Menu 4
|
||||
</a-menu-item>
|
||||
</a-menu>
|
||||
<div class="w-full justify-center gap-1 grid text-center pb-4">
|
||||
<a-tooltip content="帮助" position="right">
|
||||
<a-button type="text">
|
||||
<template #icon>
|
||||
<i class="icon-park-outline-info text-lg text-gray-400 hover:text-gray-700"></i>
|
||||
</template>
|
||||
</a-button>
|
||||
</a-tooltip>
|
||||
<a-tooltip :content="collapsed ? '展开' : '折叠'" position="right">
|
||||
<a-button type="text" @click="collapsed = !collapsed">
|
||||
<template #icon>
|
||||
<i
|
||||
class="text-lg text-gray-400 hover:text-gray-700"
|
||||
:class="collapsed ? 'icon-park-outline-expand-left' : 'icon-park-outline-expand-right'"
|
||||
></i>
|
||||
</template>
|
||||
</a-button>
|
||||
</a-tooltip>
|
||||
</div>
|
||||
</div>
|
||||
<div></div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts"></script>
|
||||
<script setup lang="ts">
|
||||
const collapsed = ref(false);
|
||||
</script>
|
||||
|
||||
<style scoped></style>
|
||||
|
|
|
|||
|
|
@ -1,6 +1,54 @@
|
|||
<template>
|
||||
<div class="h-full grid grid-rows-[auto_1fr]">
|
||||
<div class="h-10 bg-white"></div>
|
||||
<div class="h-10 flex items-center justify-between gap-4 px-4 bg-white">
|
||||
<div>
|
||||
<span class="group">
|
||||
<span class="text-gray-400">描述: </span>
|
||||
国庆节上午9:00-10:00版式设计
|
||||
<i
|
||||
class="!hidden !group-hover:inline-block icon-park-outline-edit text-gray-400 hover:text-gray-700 ml-1"
|
||||
></i>
|
||||
</span>
|
||||
</div>
|
||||
<div class="flex items-center">
|
||||
<span class="text-gray-400 text-xs mr-2">
|
||||
尺寸:
|
||||
<span class="text-gray-700">1920 * 1080</span>
|
||||
</span>
|
||||
<span class="text-gray-400 text-xs mr-2">
|
||||
比例:
|
||||
<span class="text-gray-700">100%</span>
|
||||
</span>
|
||||
<span class="text-gray-400 text-xs mr-2">
|
||||
组件:
|
||||
<span class="text-gray-700">3 个</span>
|
||||
</span>
|
||||
<a-tooltip content="预览" position="bottom">
|
||||
<a-button type="text">
|
||||
<template #icon>
|
||||
<i class="icon-park-outline-play text-base !text-gray-600"></i>
|
||||
</template>
|
||||
</a-button>
|
||||
</a-tooltip>
|
||||
<a-popover position="br" trigger="click">
|
||||
<a-button type="text">
|
||||
<template #icon>
|
||||
<i class="icon-park-outline-config text-base !text-gray-600"></i>
|
||||
</template>
|
||||
</a-button>
|
||||
<template #content>
|
||||
<span>
|
||||
背景图片:
|
||||
<a-link>选择</a-link>
|
||||
</span>
|
||||
<span class="inline-flex items-center">
|
||||
背景颜色:
|
||||
<color-picker></color-picker>
|
||||
</span>
|
||||
</template>
|
||||
</a-popover>
|
||||
</div>
|
||||
</div>
|
||||
<div class="h-full p-5 px-6">
|
||||
<div class="bg-white h-full relative">
|
||||
<drag-resizer
|
||||
|
|
@ -21,7 +69,8 @@
|
|||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import DragResizer from "vue-drag-resize";
|
||||
import ColorPicker from "../components/ColorPicker.vue";
|
||||
import DragResizer from "../components/DragResizer.vue";
|
||||
import TextRender from "../items/text/render.vue";
|
||||
|
||||
const item = ref({
|
||||
|
|
@ -36,7 +85,7 @@ const item = ref({
|
|||
draggable: true,
|
||||
});
|
||||
|
||||
const onItemDragOrResize = (rect) => {
|
||||
const onItemDragOrResize = (rect: any) => {
|
||||
item.value.x = rect.left;
|
||||
item.value.y = rect.top;
|
||||
item.value.w = rect.width;
|
||||
|
|
@ -44,13 +93,13 @@ const onItemDragOrResize = (rect) => {
|
|||
};
|
||||
|
||||
const textCh = {
|
||||
text: "文本",
|
||||
family: "simsun",
|
||||
text: "进站前请准备好车票或乘车二维码。进站前请主动配合车站工作人员,接受安检,准备好自己的车票或乘车二维码。车站检票闸机会扫描并验证车票或乘车二维码,验证通过后方可进站。",
|
||||
family: "",
|
||||
bold: false,
|
||||
italic: false,
|
||||
underline: false,
|
||||
size: 14,
|
||||
color: "#33cc99",
|
||||
color: "#ffffff",
|
||||
align: 3,
|
||||
};
|
||||
</script>
|
||||
|
|
|
|||
|
|
@ -61,11 +61,11 @@
|
|||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { Block } from "../interface.ts";
|
||||
import { PropType } from "vue";
|
||||
|
||||
defineProps({
|
||||
block: {
|
||||
type: Object as PropType<Block>,
|
||||
type: Object as PropType<any>,
|
||||
required: true,
|
||||
},
|
||||
});
|
||||
|
|
|
|||
|
|
@ -6,9 +6,11 @@
|
|||
</a-radio-group>
|
||||
<a-form :model="block" layout="vertical">
|
||||
<div class="muti-form-item mt-2">
|
||||
<a-divider orientation="left">基本设置</a-divider>
|
||||
<block-attr :block="item"></block-attr>
|
||||
</div>
|
||||
<div class="muti-form-item">
|
||||
<a-divider orientation="left">中文设置</a-divider>
|
||||
<text-attr :block="block.textStyle"></text-attr>
|
||||
</div>
|
||||
</a-form>
|
||||
|
|
@ -19,7 +21,7 @@
|
|||
import BlockAttr from "./block-attr.vue";
|
||||
import TextAttr from "./text-attr.vue";
|
||||
|
||||
const item = ref({
|
||||
const item = ref<any>({
|
||||
x: 0,
|
||||
y: 0,
|
||||
w: 200,
|
||||
|
|
|
|||
|
|
@ -1,5 +1,9 @@
|
|||
<template>
|
||||
<div>
|
||||
<a-form-item label="内容">
|
||||
<a-textarea v-model="block.text" placeholder="输入内容..."></a-textarea>
|
||||
</a-form-item>
|
||||
|
||||
<a-form-item label="颜色">
|
||||
<a-input v-model="block.color">
|
||||
<template #prefix>
|
||||
|
|
@ -50,12 +54,16 @@
|
|||
<a-select v-model="block.align" :options="TextAlignOptions"></a-select>
|
||||
</a-form-item>
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { TextAlignOptions, TextFamilyOptions } from "../interface.ts";
|
||||
import { PropType } from "vue";
|
||||
import ColorPicker from "../components/ColorPicker.vue";
|
||||
import { TextAlignOptions, TextFamilyOptions } from "../interface";
|
||||
|
||||
defineProps({
|
||||
block: {
|
||||
type: Object as PropType<any>,
|
||||
|
|
|
|||
|
|
@ -0,0 +1,58 @@
|
|||
<template>
|
||||
<a-modal v-model:visible="modal.visible" title="上传文件" title-align="start" :footer="false">
|
||||
<a-upload :custom-request="upload" draggable action="/api/v1/upload"></a-upload>
|
||||
</a-modal>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { api } from "@/api";
|
||||
import { RequestOption } from "@arco-design/web-vue";
|
||||
import axios from "axios";
|
||||
import { reactive } from "vue";
|
||||
|
||||
const modal = reactive({
|
||||
visible: false,
|
||||
});
|
||||
|
||||
const upload = (option: RequestOption) => {
|
||||
const { fileItem, onError, onProgress, onSuccess } = option;
|
||||
const source = axios.CancelToken.source();
|
||||
if (fileItem.file) {
|
||||
api.upload
|
||||
.addFile(
|
||||
{
|
||||
file: fileItem.file,
|
||||
},
|
||||
{
|
||||
onUploadProgress(e) {
|
||||
let percent = 0;
|
||||
if (e.total && e.total > 0) {
|
||||
percent = e.loaded / e.total;
|
||||
}
|
||||
onProgress(percent, e as any);
|
||||
},
|
||||
cancelToken: source.token,
|
||||
}
|
||||
)
|
||||
.then((res) => {
|
||||
onSuccess(res);
|
||||
})
|
||||
.catch((e) => {
|
||||
onError(e);
|
||||
});
|
||||
}
|
||||
return {
|
||||
abort() {
|
||||
source.cancel();
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
defineExpose({
|
||||
open: () => {
|
||||
modal.visible = true;
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped></style>
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
|
||||
export const useModal = (modal: any) => {
|
||||
|
||||
}
|
||||
|
|
@ -7,62 +7,43 @@ export {}
|
|||
|
||||
declare module '@vue/runtime-core' {
|
||||
export interface GlobalComponents {
|
||||
AAlert: typeof import('@arco-design/web-vue')['Alert']
|
||||
AAvatar: typeof import('@arco-design/web-vue')['Avatar']
|
||||
ABreadcrumb: typeof import('@arco-design/web-vue')['Breadcrumb']
|
||||
ABreadcrumbItem: typeof import('@arco-design/web-vue')['BreadcrumbItem']
|
||||
AButton: typeof import('@arco-design/web-vue')['Button']
|
||||
ACard: typeof import('@arco-design/web-vue')['Card']
|
||||
ACheckbox: typeof import('@arco-design/web-vue')['Checkbox']
|
||||
ACheckboxGroup: typeof import('@arco-design/web-vue')['CheckboxGroup']
|
||||
AConfigProvider: typeof import('@arco-design/web-vue')['ConfigProvider']
|
||||
ADatePicker: typeof import('@arco-design/web-vue')['DatePicker']
|
||||
ADivider: typeof import('@arco-design/web-vue')['Divider']
|
||||
ADoption: typeof import('@arco-design/web-vue')['Doption']
|
||||
ADrawer: typeof import('@arco-design/web-vue')['Drawer']
|
||||
ADropdown: typeof import('@arco-design/web-vue')['Dropdown']
|
||||
ADropdownButton: typeof import('@arco-design/web-vue')['DropdownButton']
|
||||
AForm: typeof import('@arco-design/web-vue')['Form']
|
||||
AFormItem: typeof import('@arco-design/web-vue')['FormItem']
|
||||
AImage: typeof import('@arco-design/web-vue')['Image']
|
||||
AInput: typeof import('@arco-design/web-vue')['Input']
|
||||
AInputNumber: typeof import('@arco-design/web-vue')['InputNumber']
|
||||
AInputPassword: typeof import('@arco-design/web-vue')['InputPassword']
|
||||
AInputSearch: typeof import('@arco-design/web-vue')['InputSearch']
|
||||
ALayout: typeof import('@arco-design/web-vue')['Layout']
|
||||
ALayoutContent: typeof import('@arco-design/web-vue')['LayoutContent']
|
||||
ALayoutHeader: typeof import('@arco-design/web-vue')['LayoutHeader']
|
||||
ALayoutSider: typeof import('@arco-design/web-vue')['LayoutSider']
|
||||
ALink: typeof import('@arco-design/web-vue')['Link']
|
||||
AList: typeof import('@arco-design/web-vue')['List']
|
||||
AListItem: typeof import('@arco-design/web-vue')['ListItem']
|
||||
AListItemMeta: typeof import('@arco-design/web-vue')['ListItemMeta']
|
||||
AMenu: typeof import('@arco-design/web-vue')['Menu']
|
||||
AMenuItem: typeof import('@arco-design/web-vue')['MenuItem']
|
||||
AMenuItemGroup: typeof import('@arco-design/web-vue')['MenuItemGroup']
|
||||
AModal: typeof import('@arco-design/web-vue')['Modal']
|
||||
APagination: typeof import('@arco-design/web-vue')['Pagination']
|
||||
APopover: typeof import('@arco-design/web-vue')['Popover']
|
||||
ARadio: typeof import('@arco-design/web-vue')['Radio']
|
||||
ARadioGroup: typeof import('@arco-design/web-vue')['RadioGroup']
|
||||
AScrollbar: typeof import('@arco-design/web-vue')['Scrollbar']
|
||||
ASelect: typeof import('@arco-design/web-vue')['Select']
|
||||
ASlider: typeof import('@arco-design/web-vue')['Slider']
|
||||
ASpace: typeof import('@arco-design/web-vue')['Space']
|
||||
ASpin: typeof import('@arco-design/web-vue')['Spin']
|
||||
ASwitch: typeof import('@arco-design/web-vue')['Switch']
|
||||
ATabPane: typeof import('@arco-design/web-vue')['TabPane']
|
||||
ATabs: typeof import('@arco-design/web-vue')['Tabs']
|
||||
ATag: typeof import('@arco-design/web-vue')['Tag']
|
||||
ATextarea: typeof import('@arco-design/web-vue')['Textarea']
|
||||
ATooltip: typeof import('@arco-design/web-vue')['Tooltip']
|
||||
ATree: typeof import('@arco-design/web-vue')['Tree']
|
||||
AUpload: typeof import('@arco-design/web-vue')['Upload']
|
||||
BlockAttr: typeof import('./../components/editor/panel-right/block-attr.vue')['default']
|
||||
BreadCrumb: typeof import('./../components/breadcrumb/bread-crumb.vue')['default']
|
||||
BreadPage: typeof import('./../components/breadcrumb/bread-page.vue')['default']
|
||||
ColorPicker: typeof import('./../components/editor/components/ColorPicker.vue')['default']
|
||||
DragResizer: typeof import('./../components/editor/components/DragResizer.vue')['default']
|
||||
Editor: typeof import('./../components/editor/index.vue')['default']
|
||||
Option: typeof import('./../components/editor/items/text/option.vue')['default']
|
||||
Options: typeof import('./../components/editor/items/text/options.vue')['default']
|
||||
Page403: typeof import('./../components/error/page-403.vue')['default']
|
||||
PanelHeader: typeof import('./../components/editor/panel-header/index.vue')['default']
|
||||
PanelLeft: typeof import('./../components/editor/panel-left/index.vue')['default']
|
||||
|
|
|
|||
Loading…
Reference in New Issue