|
@@ -13,7 +13,7 @@
|
|
|
<t-tooltip content="保存为我的组件" placement="bottom">
|
|
|
<a><t-icon name="layers" @click="save(SaveType.Save, true)" /></a>
|
|
|
</t-tooltip>
|
|
|
- <t-tooltip content="格式化" placement="bottom">
|
|
|
+ <t-tooltip content="格式化(双击可连续使用)" placement="bottom">
|
|
|
<a
|
|
|
@click="oneFormat"
|
|
|
@dblclick="alwaysFormat"
|
|
@@ -72,13 +72,15 @@
|
|
|
><t-icon name="slash"
|
|
|
/></a>
|
|
|
</t-tooltip>
|
|
|
- <!-- <t-tooltip content="连线" placement="top"> -->
|
|
|
- <t-dropdown
|
|
|
- :minColumnWidth="200"
|
|
|
- :maxHeight="560"
|
|
|
- :delay2="[10, 150]"
|
|
|
- overlayClassName="header-dropdown"
|
|
|
- >
|
|
|
+ <t-tooltip content="文字" placement="bottom">
|
|
|
+ <a
|
|
|
+ :draggable="true"
|
|
|
+ @dragstart="onAddShape($event, 'text')"
|
|
|
+ @click.stop="onAddShape($event, 'text')"
|
|
|
+ >T</a
|
|
|
+ >
|
|
|
+ </t-tooltip>
|
|
|
+ <t-tooltip content="连线(双击可连续使用)" placement="bottom">
|
|
|
<a
|
|
|
@click="oneDraw"
|
|
|
@dblclick="alwaysDraw"
|
|
@@ -98,24 +100,86 @@
|
|
|
></path>
|
|
|
</svg>
|
|
|
</a>
|
|
|
+ </t-tooltip>
|
|
|
+ <!-- <t-tooltip content="连线" placement="top"> -->
|
|
|
+ <t-dropdown
|
|
|
+ :minColumnWidth="200"
|
|
|
+ :maxHeight="560"
|
|
|
+ :delay2="[10, 150]"
|
|
|
+ overlayClassName="header-dropdown"
|
|
|
+ >
|
|
|
+ <a>
|
|
|
+ <svg class="l-icon" aria-hidden="true">
|
|
|
+ <use
|
|
|
+ :xlink:href="
|
|
|
+ lineTypes.find((item) => item.value === currentLineType)?.icon
|
|
|
+ "
|
|
|
+ ></use>
|
|
|
+ </svg>
|
|
|
+ </a>
|
|
|
<t-dropdown-menu>
|
|
|
<t-dropdown-item v-for="item in lineTypes">
|
|
|
<div class="flex middle" @click="changeLineType(item.value)">
|
|
|
{{ item.name }} <span class="flex-grow"></span>
|
|
|
- <t-icon v-show="item.value === currentLineType" name="check" />
|
|
|
+ <!-- <t-icon v-show="item.value === currentLineType" name="check" /> -->
|
|
|
+ <svg class="l-icon" aria-hidden="true">
|
|
|
+ <use :xlink:href="item.icon"></use>
|
|
|
+ </svg>
|
|
|
+ </div>
|
|
|
+ </t-dropdown-item>
|
|
|
+ </t-dropdown-menu>
|
|
|
+ </t-dropdown>
|
|
|
+ <t-dropdown
|
|
|
+ :minColumnWidth="200"
|
|
|
+ :maxHeight="560"
|
|
|
+ :delay2="[10, 150]"
|
|
|
+ overlayClassName="header-dropdown"
|
|
|
+ >
|
|
|
+ <a>
|
|
|
+ <svg class="l-icon" aria-hidden="true">
|
|
|
+ <use
|
|
|
+ :xlink:href="
|
|
|
+ fromArrows.find((item) => item.value === fromArrow)?.icon
|
|
|
+ "
|
|
|
+ ></use>
|
|
|
+ </svg>
|
|
|
+ </a>
|
|
|
+ <t-dropdown-menu>
|
|
|
+ <t-dropdown-item v-for="item in fromArrows">
|
|
|
+ <div class="flex middle" style="height: 30px;" @click="changeFromArrow(item.value)">
|
|
|
+ <svg class="l-icon" aria-hidden="true">
|
|
|
+ <use :xlink:href="item.icon"></use>
|
|
|
+ </svg>
|
|
|
+ </div>
|
|
|
+ </t-dropdown-item>
|
|
|
+ </t-dropdown-menu>
|
|
|
+ </t-dropdown>
|
|
|
+ <t-dropdown
|
|
|
+ :minColumnWidth="200"
|
|
|
+ :maxHeight="560"
|
|
|
+ :delay2="[10, 150]"
|
|
|
+ overlayClassName="header-dropdown"
|
|
|
+ >
|
|
|
+ <a>
|
|
|
+ <svg class="l-icon" aria-hidden="true">
|
|
|
+ <use
|
|
|
+ :xlink:href="
|
|
|
+ toArrows.find((item) => item.value === toArrow)?.icon
|
|
|
+ "
|
|
|
+ ></use>
|
|
|
+ </svg>
|
|
|
+ </a>
|
|
|
+ <t-dropdown-menu>
|
|
|
+ <t-dropdown-item v-for="item in toArrows">
|
|
|
+ <div class="flex middle" style="height: 30px;" @click="changeToArrow(item.value)">
|
|
|
+ <svg class="l-icon" aria-hidden="true">
|
|
|
+ <use :xlink:href="item.icon"></use>
|
|
|
+ </svg>
|
|
|
</div>
|
|
|
</t-dropdown-item>
|
|
|
</t-dropdown-menu>
|
|
|
</t-dropdown>
|
|
|
<!-- </t-tooltip> -->
|
|
|
- <t-tooltip content="文字" placement="bottom">
|
|
|
- <a
|
|
|
- :draggable="true"
|
|
|
- @dragstart="onAddShape($event, 'text')"
|
|
|
- @click.stop="onAddShape($event, 'text')"
|
|
|
- >T</a
|
|
|
- >
|
|
|
- </t-tooltip>
|
|
|
<t-tooltip content="视图大小" placement="bottom">
|
|
|
<div style="line-height: 40px; margin-left: 8px">{{ scale }}%</div>
|
|
|
</t-tooltip>
|
|
@@ -131,9 +195,6 @@
|
|
|
</t-tooltip>
|
|
|
|
|
|
<div class="flex-grow"></div>
|
|
|
- <t-tooltip content="预览" placement="bottom">
|
|
|
- <a @click="preview"><t-icon name="browse" /></a>
|
|
|
- </t-tooltip>
|
|
|
<t-tooltip
|
|
|
:content="isLock === 2 ? '锁定' : isLock === 1 ? '预览' : '编辑'"
|
|
|
placement="bottom"
|
|
@@ -161,6 +222,10 @@
|
|
|
</svg>
|
|
|
</a>
|
|
|
</t-tooltip>
|
|
|
+ <t-tooltip content="运行(在新页面全屏查看)" placement="bottom">
|
|
|
+ <a @click="preview"><t-icon name="caret-right" /></a>
|
|
|
+ </t-tooltip>
|
|
|
+
|
|
|
<t-tooltip content="手机查看" placement="bottom">
|
|
|
<a><t-icon name="qrcode" /></a>
|
|
|
</t-tooltip>
|
|
@@ -180,27 +245,35 @@
|
|
|
</template>
|
|
|
|
|
|
<script lang="ts" setup>
|
|
|
-import { Meta2d, Options, Pen, deepClone, LockState } from '@meta2d/core';
|
|
|
-import { onMounted, onUnmounted, watch, ref, reactive } from 'vue';
|
|
|
-import { registerBasicDiagram } from '@/services/register';
|
|
|
-import { useRouter, useRoute } from 'vue-router';
|
|
|
-import { useUser } from '@/services/user';
|
|
|
-import { getLe5le2d } from '@/services/api';
|
|
|
-import { useDot } from '@/services/common';
|
|
|
+import {
|
|
|
+ Meta2d,
|
|
|
+ Options,
|
|
|
+ Pen,
|
|
|
+ deepClone,
|
|
|
+ LockState,
|
|
|
+ PenType,
|
|
|
+} from "@meta2d/core";
|
|
|
+import { onMounted, onUnmounted, watch, ref, reactive } from "vue";
|
|
|
+import { registerBasicDiagram } from "@/services/register";
|
|
|
+import { useRouter, useRoute } from "vue-router";
|
|
|
+import { useUser } from "@/services/user";
|
|
|
+import { getLe5le2d } from "@/services/api";
|
|
|
+import { useDot } from "@/services/common";
|
|
|
import {
|
|
|
save,
|
|
|
newFile,
|
|
|
SaveType,
|
|
|
onScaleView,
|
|
|
onScaleWindow,
|
|
|
-} from '@/services/common';
|
|
|
-import { useSelection, SelectionMode } from '@/services/selections';
|
|
|
-import { defaultFormat } from '@/services/defaults';
|
|
|
-import { MessagePlugin } from 'tdesign-vue-next';
|
|
|
-import { localMeta2dDataName } from '@/services/utils';
|
|
|
-import localforage from 'localforage';
|
|
|
-import { checkData } from '@/services/utils';
|
|
|
-import { cdn } from '@/services/api';
|
|
|
+} from "@/services/common";
|
|
|
+import { useSelection, SelectionMode } from "@/services/selections";
|
|
|
+import { defaultFormat } from "@/services/defaults";
|
|
|
+import { MessagePlugin } from "tdesign-vue-next";
|
|
|
+import { localMeta2dDataName } from "@/services/utils";
|
|
|
+import localforage from "localforage";
|
|
|
+import { checkData, Meta2dBackData } from "@/services/utils";
|
|
|
+import { cdn } from "@/services/api";
|
|
|
+import dayjs from "dayjs";
|
|
|
|
|
|
const router = useRouter();
|
|
|
const route = useRoute();
|
|
@@ -216,7 +289,8 @@ const meta2dOptions: Options = {
|
|
|
y: 32,
|
|
|
width: 1920,
|
|
|
height: 1080,
|
|
|
- color: '#4583FF',
|
|
|
+ color: "#bdc7db",
|
|
|
+ disableAnchor:true,
|
|
|
defaultFormat: { ...defaultFormat },
|
|
|
};
|
|
|
onMounted(() => {
|
|
@@ -230,7 +304,17 @@ onMounted(() => {
|
|
|
// @ts-ignore
|
|
|
meta2d.on('scale', scaleListener);
|
|
|
// @ts-ignore
|
|
|
- meta2d.on('add', lineAdd);
|
|
|
+ meta2d.on("add", lineAdd);
|
|
|
+
|
|
|
+ meta2d.on("undo", autoSave);
|
|
|
+ meta2d.on("redo", autoSave);
|
|
|
+ meta2d.on("add", autoSave);
|
|
|
+ meta2d.on("delete", autoSave);
|
|
|
+ meta2d.on("rotatePens", autoSave);
|
|
|
+ meta2d.on("translatePens", autoSave);
|
|
|
+
|
|
|
+ //TODO所有编辑栏所做修改
|
|
|
+ meta2d.on("components-update-value", autoSave);
|
|
|
});
|
|
|
|
|
|
const watcher = watch(
|
|
@@ -261,11 +345,58 @@ onUnmounted(() => {
|
|
|
// @ts-ignore
|
|
|
meta2d.off('scale', scaleListener);
|
|
|
// @ts-ignore
|
|
|
- meta2d.off('add', lineAdd);
|
|
|
+ meta2d.off("add", lineAdd);
|
|
|
+
|
|
|
+ meta2d.off("undo", autoSave);
|
|
|
+ meta2d.off("redo", autoSave);
|
|
|
+ meta2d.off("add", autoSave);
|
|
|
+ meta2d.off("delete", autoSave);
|
|
|
+ meta2d.off("rotatePens", autoSave);
|
|
|
+ meta2d.off("translatePens", autoSave);
|
|
|
+ meta2d.off("components-update-value", autoSave);
|
|
|
meta2d.destroy();
|
|
|
}
|
|
|
});
|
|
|
|
|
|
+let localSaveTimer: any = 0;
|
|
|
+let saveTimer: any = 0;
|
|
|
+const autoSave = () => {
|
|
|
+ setDot(true);
|
|
|
+ localSaveTimer && clearTimeout(localSaveTimer);
|
|
|
+ localSaveTimer = setTimeout(() => {
|
|
|
+ const data: Meta2dBackData = meta2d.data();
|
|
|
+ let _localMeta2dDataName = data._id
|
|
|
+ ? localMeta2dDataName + "-" + data._id
|
|
|
+ : localMeta2dDataName;
|
|
|
+ (data as any).localSaveAt = dayjs().format();
|
|
|
+ localforage.setItem(_localMeta2dDataName, JSON.stringify(data));
|
|
|
+ localSaveTimer = undefined;
|
|
|
+ }, 3000);
|
|
|
+ autoSaveServer();
|
|
|
+};
|
|
|
+//运行 在新标签页查看
|
|
|
+function autoSaveServer() {
|
|
|
+ //会员享受自动保存
|
|
|
+ if (saveTimer) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ saveTimer = setTimeout(() => {
|
|
|
+ const data: Meta2dBackData = meta2d.data();
|
|
|
+ if (
|
|
|
+ user &&
|
|
|
+ user.id &&
|
|
|
+ user.vipExpired &&
|
|
|
+ data._id &&
|
|
|
+ !data.component &&
|
|
|
+ data.owner &&
|
|
|
+ data.owner?.id === user.id
|
|
|
+ ) {
|
|
|
+ save(SaveType.Save);
|
|
|
+ }
|
|
|
+ saveTimer = null;
|
|
|
+ }, 60000);
|
|
|
+}
|
|
|
+
|
|
|
const inactive = () => {
|
|
|
select();
|
|
|
};
|
|
@@ -318,10 +449,10 @@ const connectShow = () => {
|
|
|
|
|
|
const currentLineType = ref('curve');
|
|
|
const lineTypes = reactive([
|
|
|
- { name: '曲线', icon: 't-icon t-curve2', value: 'curve' },
|
|
|
- { name: '线段', icon: 't-icon t-polyline', value: 'polyline' },
|
|
|
- { name: '直线', icon: 't-icon t-line', value: 'line' },
|
|
|
- { name: '脑图曲线', icon: 't-icon t-mind', value: 'mind' },
|
|
|
+ { name: "曲线", icon: "#l-curve2", value: "curve" },
|
|
|
+ { name: "线段", icon: "#l-polyline", value: "polyline" },
|
|
|
+ { name: "直线", icon: "#l-line", value: "line" },
|
|
|
+ { name: "脑图曲线", icon: "#l-mind", value: "mind" },
|
|
|
]);
|
|
|
|
|
|
const changeLineType = (value: string) => {
|
|
@@ -335,24 +466,108 @@ const changeLineType = (value: string) => {
|
|
|
}
|
|
|
};
|
|
|
|
|
|
+const fromArrow = ref("");
|
|
|
+const fromArrows = [
|
|
|
+ { icon: "#l-line", value: "" },
|
|
|
+ { icon: "#l-from-triangle", value: "triangle" },
|
|
|
+ { icon: "#l-from-diamond", value: "diamond" },
|
|
|
+ { icon: "#l-from-circle", value: "circle" },
|
|
|
+ { icon: "#l-from-lineDown", value: "lineDown" },
|
|
|
+ { icon: "#l-from-lineUp", value: "lineUp" },
|
|
|
+ { icon: "#l-from-triangleSolid", value: "triangleSolid" },
|
|
|
+ { icon: "#l-from-diamondSolid", value: "diamondSolid" },
|
|
|
+ { icon: "#l-from-circleSolid", value: "circleSolid" },
|
|
|
+ { icon: "#l-from-line", value: "line" },
|
|
|
+];
|
|
|
+const toArrow = ref("");
|
|
|
+const toArrows = [
|
|
|
+ { icon: "#l-line", value: "" },
|
|
|
+ { icon: "#l-to-triangle", value: "triangle" },
|
|
|
+ { icon: "#l-to-diamond", value: "diamond" },
|
|
|
+ { icon: "#l-to-circle", value: "circle" },
|
|
|
+ { icon: "#l-to-lineDown", value: "lineDown" },
|
|
|
+ { icon: "#l-to-lineUp", value: "lineUp" },
|
|
|
+ { icon: "#l-to-triangleSolid", value: "triangleSolid" },
|
|
|
+ { icon: "#l-to-diamondSolid", value: "diamondSolid" },
|
|
|
+ { icon: "#l-to-circleSolid", value: "circleSolid" },
|
|
|
+ { icon: "#l-to-line", value: "line" },
|
|
|
+];
|
|
|
+
|
|
|
+const changeFromArrow = (value: string) => {
|
|
|
+ fromArrow.value = value;
|
|
|
+ // 画布默认值
|
|
|
+ meta2d.store.data.fromArrow = value;
|
|
|
+ // 活动层的箭头都变化
|
|
|
+ if (meta2d.store.active) {
|
|
|
+ meta2d.store.active.forEach((pen: Pen) => {
|
|
|
+ if (pen.type === PenType.Line) {
|
|
|
+ pen.fromArrow = value;
|
|
|
+ meta2d.setValue(
|
|
|
+ {
|
|
|
+ id: pen.id,
|
|
|
+ fromArrow: pen.fromArrow,
|
|
|
+ },
|
|
|
+ {
|
|
|
+ render: false,
|
|
|
+ }
|
|
|
+ );
|
|
|
+ }
|
|
|
+ });
|
|
|
+ meta2d.render();
|
|
|
+ }
|
|
|
+};
|
|
|
+
|
|
|
+const changeToArrow = (value: string) => {
|
|
|
+ toArrow.value = value;
|
|
|
+ // 画布默认值
|
|
|
+ meta2d.store.data.toArrow = value;
|
|
|
+ // 活动层的箭头都变化
|
|
|
+ if (meta2d.store.active) {
|
|
|
+ meta2d.store.active.forEach((pen: Pen) => {
|
|
|
+ if (pen.type === PenType.Line) {
|
|
|
+ pen.toArrow = value;
|
|
|
+ meta2d.setValue(
|
|
|
+ {
|
|
|
+ id: pen.id,
|
|
|
+ toArrow: pen.toArrow,
|
|
|
+ },
|
|
|
+ {
|
|
|
+ render: false,
|
|
|
+ }
|
|
|
+ );
|
|
|
+ }
|
|
|
+ });
|
|
|
+ meta2d.render();
|
|
|
+ }
|
|
|
+};
|
|
|
+
|
|
|
const oneD = ref<boolean>(false);
|
|
|
const alwaysD = ref<boolean>(false);
|
|
|
const oneDraw = () => {
|
|
|
if (oneD.value) {
|
|
|
oneD.value = false;
|
|
|
+ if (!alwaysD.value) {
|
|
|
+ meta2d.finishDrawLine();
|
|
|
+ meta2d.drawLine();
|
|
|
+ meta2d.store.options.disableAnchor =true;
|
|
|
+ }
|
|
|
} else {
|
|
|
oneD.value = true;
|
|
|
meta2d.drawLine(meta2d.store.options.drawingLineName);
|
|
|
+ meta2d.store.options.disableAnchor =false;
|
|
|
}
|
|
|
if (alwaysD.value) {
|
|
|
meta2d.finishDrawLine();
|
|
|
meta2d.drawLine();
|
|
|
oneD.value = false;
|
|
|
alwaysD.value = false;
|
|
|
+ meta2d.store.options.disableAnchor =true;
|
|
|
}
|
|
|
};
|
|
|
const alwaysDraw = () => {
|
|
|
alwaysD.value = true;
|
|
|
+ meta2d.drawLine(meta2d.store.options.drawingLineName);
|
|
|
+ meta2d.store.options.disableAnchor =false;
|
|
|
};
|
|
|
|
|
|
const lineAdd = (pens: Pen[]) => {
|
|
@@ -364,6 +579,7 @@ const lineAdd = (pens: Pen[]) => {
|
|
|
setTimeout(() => {
|
|
|
meta2d.finishDrawLine();
|
|
|
meta2d.drawLine();
|
|
|
+ meta2d.store.options.disableAnchor =true;
|
|
|
}, 100);
|
|
|
}
|
|
|
}
|
|
@@ -455,7 +671,10 @@ const preview = async () => {
|
|
|
padding: 0 10px;
|
|
|
color: var(--color);
|
|
|
text-decoration: none;
|
|
|
-
|
|
|
+ .l-icon {
|
|
|
+ width: 16px;
|
|
|
+ height: 16px;
|
|
|
+ }
|
|
|
&:hover {
|
|
|
color: var(--color-primary);
|
|
|
}
|