提交代码
10
src/App.vue
Normal file
@@ -0,0 +1,10 @@
|
||||
<script setup lang="ts">
|
||||
import loadSvg from '@/utils/loadSvg'
|
||||
loadSvg()
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<router-view></router-view>
|
||||
</template>
|
||||
|
||||
<style scoped></style>
|
||||
87
src/api/index.ts
Normal file
@@ -0,0 +1,87 @@
|
||||
import http from '@/utils/request'
|
||||
|
||||
//查询图元
|
||||
export function find() {
|
||||
return http.request({
|
||||
url: '/cs-system-boot/csElement/find',
|
||||
method: 'POST'
|
||||
})
|
||||
}
|
||||
// 获取svg文件
|
||||
export function download(params: any) {
|
||||
return http.request({
|
||||
url: '/system-boot/file/download',
|
||||
method: 'get',
|
||||
params
|
||||
})
|
||||
}
|
||||
|
||||
// 新增图元
|
||||
export function addElement(params: any) {
|
||||
return http.request({
|
||||
url: '/cs-system-boot/csElement/add',
|
||||
method: 'post',
|
||||
data: params
|
||||
})
|
||||
}
|
||||
|
||||
// 删除图元
|
||||
export function deleteElement(params: any) {
|
||||
return http.request({
|
||||
url: '/cs-system-boot/csElement/delete',
|
||||
method: 'post',
|
||||
params: params
|
||||
})
|
||||
}
|
||||
|
||||
// 查询左侧图纸列表
|
||||
export function queryPage(params: any) {
|
||||
return http.request({
|
||||
url: '/cs-harmonic-boot/cspage/queryPage',
|
||||
method: 'post',
|
||||
data: params
|
||||
})
|
||||
}
|
||||
|
||||
// 总的画布的保存
|
||||
export function addCanvas(params: any) {
|
||||
return http.request({
|
||||
url: '/cs-harmonic-boot/cspage/add',
|
||||
method: 'post',
|
||||
data: params
|
||||
})
|
||||
}
|
||||
|
||||
// 截图
|
||||
export function audit(params: any) {
|
||||
return http.request({
|
||||
url: '/cs-harmonic-boot/csconfiguration/audit',
|
||||
method: 'post',
|
||||
data: params
|
||||
})
|
||||
}
|
||||
|
||||
// 监测点列表
|
||||
export function lineTree(params: any) {
|
||||
return http.request({
|
||||
url: '/cs-device-boot/csLedger/lineTree',
|
||||
method: 'post',
|
||||
data: params
|
||||
})
|
||||
}
|
||||
|
||||
// 指标列表
|
||||
export function targetList(params: any) {
|
||||
return http.request({
|
||||
url: '/cs-harmonic-boot/lineTarget/target',
|
||||
method: 'post',
|
||||
params: params
|
||||
})
|
||||
}
|
||||
// 无锡指标列表
|
||||
export function eleEpdChooseTree_wx() {
|
||||
return http.request({
|
||||
url: '/csDictData/eleEpdChooseTree',
|
||||
method: 'get'
|
||||
})
|
||||
}
|
||||
10
src/api/index_wx.ts
Normal file
@@ -0,0 +1,10 @@
|
||||
import http from '@/utils/request'
|
||||
|
||||
// 监测点树
|
||||
export function lineTree_wx(params: any) {
|
||||
return http.request({
|
||||
url: '/terminalTree/tree',
|
||||
method: 'get',
|
||||
params: params
|
||||
})
|
||||
}
|
||||
91
src/assets/css-vars.css
Normal file
@@ -0,0 +1,91 @@
|
||||
#mt-edit.dark {
|
||||
color-scheme: dark;
|
||||
--el-color-primary: #409eff;
|
||||
--el-color-primary-light-3: #3375b9;
|
||||
--el-color-primary-light-5: #2a598a;
|
||||
--el-color-primary-light-7: #213d5b;
|
||||
--el-color-primary-light-8: #1d3043;
|
||||
--el-color-primary-light-9: #18222c;
|
||||
--el-color-primary-dark-2: #66b1ff;
|
||||
--el-color-success: #67c23a;
|
||||
--el-color-success-light-3: #4e8e2f;
|
||||
--el-color-success-light-5: #3e6b27;
|
||||
--el-color-success-light-7: #2d481f;
|
||||
--el-color-success-light-8: #25371c;
|
||||
--el-color-success-light-9: #1c2518;
|
||||
--el-color-success-dark-2: #85ce61;
|
||||
--el-color-warning: #e6a23c;
|
||||
--el-color-warning-light-3: #a77730;
|
||||
--el-color-warning-light-5: #7d5b28;
|
||||
--el-color-warning-light-7: #533f20;
|
||||
--el-color-warning-light-8: #3e301c;
|
||||
--el-color-warning-light-9: #292218;
|
||||
--el-color-warning-dark-2: #ebb563;
|
||||
--el-color-danger: #f56c6c;
|
||||
--el-color-danger-light-3: #b25252;
|
||||
--el-color-danger-light-5: #854040;
|
||||
--el-color-danger-light-7: #582e2e;
|
||||
--el-color-danger-light-8: #412626;
|
||||
--el-color-danger-light-9: #2b1d1d;
|
||||
--el-color-danger-dark-2: #f78989;
|
||||
--el-color-error: #f56c6c;
|
||||
--el-color-error-light-3: #b25252;
|
||||
--el-color-error-light-5: #854040;
|
||||
--el-color-error-light-7: #582e2e;
|
||||
--el-color-error-light-8: #412626;
|
||||
--el-color-error-light-9: #2b1d1d;
|
||||
--el-color-error-dark-2: #f78989;
|
||||
--el-color-info: #909399;
|
||||
--el-color-info-light-3: #6b6d71;
|
||||
--el-color-info-light-5: #525457;
|
||||
--el-color-info-light-7: #393a3c;
|
||||
--el-color-info-light-8: #2d2d2f;
|
||||
--el-color-info-light-9: #202121;
|
||||
--el-color-info-dark-2: #a6a9ad;
|
||||
--el-box-shadow: 0px 12px 32px 4px rgba(0, 0, 0, 0.36), 0px 8px 20px rgba(0, 0, 0, 0.72);
|
||||
--el-box-shadow-light: 0px 0px 12px rgba(0, 0, 0, 0.72);
|
||||
--el-box-shadow-lighter: 0px 0px 6px rgba(0, 0, 0, 0.72);
|
||||
--el-box-shadow-dark: 0px 16px 48px 16px rgba(0, 0, 0, 0.72), 0px 12px 32px #000000, 0px 8px 16px -8px #000000;
|
||||
--el-bg-color-page: #0a0a0a;
|
||||
--el-bg-color: #141414;
|
||||
--el-bg-color-overlay: #1d1e1f;
|
||||
--el-text-color-primary: #e5eaf3;
|
||||
--el-text-color-regular: #cfd3dc;
|
||||
--el-text-color-secondary: #a3a6ad;
|
||||
--el-text-color-placeholder: #8d9095;
|
||||
--el-text-color-disabled: #6c6e72;
|
||||
--el-border-color-darker: #636466;
|
||||
--el-border-color-dark: #58585b;
|
||||
--el-border-color: #4c4d4f;
|
||||
--el-border-color-light: #414243;
|
||||
--el-border-color-lighter: #363637;
|
||||
--el-border-color-extra-light: #2b2b2c;
|
||||
--el-fill-color-darker: #424243;
|
||||
--el-fill-color-dark: #39393a;
|
||||
--el-fill-color: #303030;
|
||||
--el-fill-color-light: #262727;
|
||||
--el-fill-color-lighter: #1d1d1d;
|
||||
--el-fill-color-extra-light: #191919;
|
||||
--el-fill-color-blank: transparent;
|
||||
--el-mask-color: rgba(0, 0, 0, 0.8);
|
||||
--el-mask-color-extra-light: rgba(0, 0, 0, 0.3);
|
||||
transition: all 5s;
|
||||
}
|
||||
#mt-edit.dark .el-button {
|
||||
--el-button-disabled-text-color: rgba(255, 255, 255, 0.5);
|
||||
}
|
||||
#mt-edit.dark .el-card {
|
||||
--el-card-bg-color: var(--el-bg-color-overlay);
|
||||
}
|
||||
#mt-edit.dark .el-empty {
|
||||
--el-empty-fill-color-0: var(--el-color-black);
|
||||
--el-empty-fill-color-1: #4b4b52;
|
||||
--el-empty-fill-color-2: #36383d;
|
||||
--el-empty-fill-color-3: #1e1e20;
|
||||
--el-empty-fill-color-4: #262629;
|
||||
--el-empty-fill-color-5: #202124;
|
||||
--el-empty-fill-color-6: #212224;
|
||||
--el-empty-fill-color-7: #1b1c1f;
|
||||
--el-empty-fill-color-8: #1c1d1f;
|
||||
--el-empty-fill-color-9: #18181a;
|
||||
}
|
||||
6
src/assets/icons/add.svg
Normal file
@@ -0,0 +1,6 @@
|
||||
<svg class="icon" viewBox="0 0 1024 1024" version="1.1"
|
||||
xmlns="http://www.w3.org/2000/svg" width="200" height="200">
|
||||
<path
|
||||
d="M801.171 483.589H544V226.418c0-17.673-14.327-32-32-32s-32 14.327-32 32v257.171H222.83c-17.673 0-32 14.327-32 32s14.327 32 32 32H480v257.17c0 17.673 14.327 32 32 32s32-14.327 32-32v-257.17h257.171c17.673 0 32-14.327 32-32s-14.327-32-32-32z"
|
||||
fill=""></path>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 412 B |
1
src/assets/icons/align-bottom.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 256 256"><path fill="currentColor" d="M228 216a12 12 0 0 1-12 12H40a12 12 0 0 1 0-24h176a12 12 0 0 1 12 12m-92-48V80a20 20 0 0 1 20-20h36a20 20 0 0 1 20 20v88a20 20 0 0 1-20 20h-36a20 20 0 0 1-20-20m24-4h28V84h-28Zm-116 4V40a20 20 0 0 1 20-20h36a20 20 0 0 1 20 20v128a20 20 0 0 1-20 20H64a20 20 0 0 1-20-20m24-4h28V44H68Z"/></svg>
|
||||
|
After Width: | Height: | Size: 408 B |
1
src/assets/icons/align-horizontally.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 256 256"><path fill="currentColor" d="M208 136h-68v-16h44a20 20 0 0 0 20-20V60a20 20 0 0 0-20-20h-44v-8a12 12 0 0 0-24 0v8H72a20 20 0 0 0-20 20v40a20 20 0 0 0 20 20h44v16H48a20 20 0 0 0-20 20v40a20 20 0 0 0 20 20h68v8a12 12 0 0 0 24 0v-8h68a20 20 0 0 0 20-20v-40a20 20 0 0 0-20-20M76 64h104v32H76Zm128 128H52v-32h152Z"/></svg>
|
||||
|
After Width: | Height: | Size: 404 B |
1
src/assets/icons/align-left.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 256 256"><path fill="currentColor" d="M52 40v176a12 12 0 0 1-24 0V40a12 12 0 0 1 24 0m16 60V64a20 20 0 0 1 20-20h88a20 20 0 0 1 20 20v36a20 20 0 0 1-20 20H88a20 20 0 0 1-20-20m24-4h80V68H92Zm144 60v36a20 20 0 0 1-20 20H88a20 20 0 0 1-20-20v-36a20 20 0 0 1 20-20h128a20 20 0 0 1 20 20m-24 4H92v28h120Z"/></svg>
|
||||
|
After Width: | Height: | Size: 387 B |
1
src/assets/icons/align-right.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 256 256"><path fill="currentColor" d="M228 40v176a12 12 0 0 1-24 0V40a12 12 0 0 1 24 0m-40 24v36a20 20 0 0 1-20 20H80a20 20 0 0 1-20-20V64a20 20 0 0 1 20-20h88a20 20 0 0 1 20 20m-24 4H84v28h80Zm24 88v36a20 20 0 0 1-20 20H40a20 20 0 0 1-20-20v-36a20 20 0 0 1 20-20h128a20 20 0 0 1 20 20m-24 4H44v28h120Z"/></svg>
|
||||
|
After Width: | Height: | Size: 389 B |
1
src/assets/icons/align-top.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 256 256"><path fill="currentColor" d="M228 40a12 12 0 0 1-12 12H40a12 12 0 0 1 0-24h176a12 12 0 0 1 12 12m-16 48v88a20 20 0 0 1-20 20h-36a20 20 0 0 1-20-20V88a20 20 0 0 1 20-20h36a20 20 0 0 1 20 20m-24 4h-28v80h28Zm-68-4v128a20 20 0 0 1-20 20H64a20 20 0 0 1-20-20V88a20 20 0 0 1 20-20h36a20 20 0 0 1 20 20m-24 4H68v120h28Z"/></svg>
|
||||
|
After Width: | Height: | Size: 409 B |
1
src/assets/icons/align-vertical.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 256 256"><path fill="currentColor" d="M224 116h-8V72a20 20 0 0 0-20-20h-40a20 20 0 0 0-20 20v44h-16V48a20 20 0 0 0-20-20H60a20 20 0 0 0-20 20v68h-8a12 12 0 0 0 0 24h8v68a20 20 0 0 0 20 20h40a20 20 0 0 0 20-20v-68h16v44a20 20 0 0 0 20 20h40a20 20 0 0 0 20-20v-44h8a12 12 0 0 0 0-24M96 204H64V52h32Zm96-24h-32V76h32Z"/></svg>
|
||||
|
After Width: | Height: | Size: 401 B |
5
src/assets/icons/align.svg
Normal file
@@ -0,0 +1,5 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 15 15">
|
||||
<path fill="currentColor" fill-rule="evenodd"
|
||||
d="M3.5 14.9a.4.4 0 0 0 .4-.4v-4.034l1.317 1.317a.4.4 0 0 0 .565-.566l-2-2a.4.4 0 0 0-.565 0l-2 2a.4.4 0 0 0 .565.566L3.1 10.466V14.5c0 .22.18.4.4.4ZM8 10.5a.5.5 0 0 0 .5.5h6a.5.5 0 1 0 0-1h-6a.5.5 0 0 0-.5.5Zm0-3a.5.5 0 0 0 .5.5h6a.5.5 0 0 0 0-1h-6a.5.5 0 0 0-.5.5ZM8.5 5a.5.5 0 1 1 0-1h6a.5.5 0 0 1 0 1h-6ZM3.9.5a.4.4 0 0 0-.8 0v4.034L1.781 3.217a.4.4 0 0 0-.565.566l2 2a.4.4 0 0 0 .565 0l2-2a.4.4 0 0 0-.565-.566L3.899 4.534V.5Z"
|
||||
clip-rule="evenodd" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 614 B |
6
src/assets/icons/dark.svg
Normal file
@@ -0,0 +1,6 @@
|
||||
<svg viewBox="0 0 1024 1024" version="1.1"
|
||||
xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
width="200" height="200">
|
||||
<path
|
||||
d="M513.173333 128A255.061333 255.061333 0 0 0 448 298.666667c0 141.376 114.624 256 256 256a255.36 255.36 0 0 0 189.802667-84.202667c1.450667 13.653333 2.197333 27.498667 2.197333 41.536 0 212.074667-171.925333 384-384 384S128 724.074667 128 512c0-209.706667 168.106667-380.16 376.96-383.936L513.152 128z m-117.824 85.930667l-3.52 1.408C274.645333 262.826667 192 377.770667 192 512c0 176.725333 143.274667 320 320 320 145.408 0 268.16-96.981333 307.114667-229.802667l1.536-5.504-1.6 0.64a319.509333 319.509333 0 0 1-106.496 21.226667L704 618.666667c-176.725333 0-320-143.274667-320-320 0-28.48 3.754667-56.405333 10.944-83.2l0.405333-1.536z"></path>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 829 B |
1
src/assets/icons/delete.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24"><path fill="currentColor" d="M7.5 1h9v3H22v2h-2.029l-.5 17H4.529l-.5-17H2V4h5.5V1Zm2 3h5V3h-5v1ZM6.03 6l.441 15h11.058l.441-15H6.03ZM13 8v11h-2V8h2Z"/></svg>
|
||||
|
After Width: | Height: | Size: 242 B |
5
src/assets/icons/exit-full-screen.svg
Normal file
@@ -0,0 +1,5 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 15 15">
|
||||
<path fill="currentColor" fill-rule="evenodd"
|
||||
d="M5.5 2a.5.5 0 0 1 .5.5v3a.5.5 0 0 1-.5.5h-3a.5.5 0 0 1 0-1H5V2.5a.5.5 0 0 1 .5-.5Zm4 0a.5.5 0 0 1 .5.5V5h2.5a.5.5 0 0 1 0 1h-3a.5.5 0 0 1-.5-.5v-3a.5.5 0 0 1 .5-.5ZM2 9.5a.5.5 0 0 1 .5-.5h3a.5.5 0 0 1 .5.5v3a.5.5 0 0 1-1 0V10H2.5a.5.5 0 0 1-.5-.5Zm7 0a.5.5 0 0 1 .5-.5h3a.5.5 0 0 1 0 1H10v2.5a.5.5 0 0 1-1 0v-3Z"
|
||||
clip-rule="evenodd" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 497 B |
1
src/assets/icons/export-json.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24"><path fill="currentColor" d="M3 1h12.414L21 6.586V12h-2V9h-6V3H5v18h6v2H3V1Zm12 2.414V7h3.586L15 3.414Zm4.05 10.674l4.858 4.914l-4.858 4.914l-1.422-1.406l2.48-2.508h-7.11v-2h7.11l-2.48-2.508l1.422-1.406Z"/></svg>
|
||||
|
After Width: | Height: | Size: 297 B |
4
src/assets/icons/full-screen.svg
Normal file
@@ -0,0 +1,4 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 2048 2048">
|
||||
<path fill="currentColor"
|
||||
d="M1664 1664v-384h128v512h-512v-128h384zM1280 256h512v512h-128V384h-384V256zM256 768V256h512v128H384v384H256zm128 512v384h384v128H256v-512h128z" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 283 B |
1
src/assets/icons/group.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 1024 1024"><path fill="currentColor" d="M912 820.1V203.9c28-9.9 48-36.6 48-67.9c0-39.8-32.2-72-72-72c-31.3 0-58 20-67.9 48H203.9C194 84 167.3 64 136 64c-39.8 0-72 32.2-72 72c0 31.3 20 58 48 67.9v616.2C84 830 64 856.7 64 888c0 39.8 32.2 72 72 72c31.3 0 58-20 67.9-48h616.2c9.9 28 36.6 48 67.9 48c39.8 0 72-32.2 72-72c0-31.3-20-58-48-67.9zM888 112c13.3 0 24 10.7 24 24s-10.7 24-24 24s-24-10.7-24-24s10.7-24 24-24zM136 912c-13.3 0-24-10.7-24-24s10.7-24 24-24s24 10.7 24 24s-10.7 24-24 24zm0-752c-13.3 0-24-10.7-24-24s10.7-24 24-24s24 10.7 24 24s-10.7 24-24 24zm704 680H184V184h656v656zm48 72c-13.3 0-24-10.7-24-24s10.7-24 24-24s24 10.7 24 24s-10.7 24-24 24z"/><path fill="currentColor" d="M288 474h448c8.8 0 16-7.2 16-16V282c0-8.8-7.2-16-16-16H288c-8.8 0-16 7.2-16 16v176c0 8.8 7.2 16 16 16zm56-136h336v64H344v-64zm-56 420h448c8.8 0 16-7.2 16-16V566c0-8.8-7.2-16-16-16H288c-8.8 0-16 7.2-16 16v176c0 8.8 7.2 16 16 16zm56-136h336v64H344v-64z"/></svg>
|
||||
|
After Width: | Height: | Size: 1023 B |
1
src/assets/icons/help.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24"><path fill="currentColor" d="M12 21a9 9 0 1 0 0-18a9 9 0 0 0 0 18m11-9c0 6.075-4.925 11-11 11S1 18.075 1 12S5.925 1 12 1s11 4.925 11 11m-9.996 6.254H11V16.25h2.004zM11 15.25V14c0-.867.39-1.573.826-2.11c.432-.53.974-.974 1.41-1.318a2 2 0 1 0-3.123-2.24l-.333.944l-1.885-.666l.333-.943a4.001 4.001 0 1 1 6.246 4.476c-.431.34-.817.666-1.096 1.009c-.274.338-.378.61-.378.848v1.25z"/></svg>
|
||||
|
After Width: | Height: | Size: 470 B |
1
src/assets/icons/horizontal-distribution.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 20 20"><path fill="currentColor" d="M3.5 18a.5.5 0 0 1-.5-.5v-15a.5.5 0 0 1 1 0v15a.5.5 0 0 1-.5.5m12.5-.5a.5.5 0 0 0 1 0v-15a.5.5 0 0 0-1 0zM9 4a2 2 0 0 0-2 2v8a2 2 0 0 0 2 2h2a2 2 0 0 0 2-2V6a2 2 0 0 0-2-2z"/></svg>
|
||||
|
After Width: | Height: | Size: 295 B |
1
src/assets/icons/import-json.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24"><path fill="currentColor" d="M3 1h12.414L21 6.586V23h-9v-2h7V9h-6V3H5v10H3V1Zm12 2.414V7h3.586L15 3.414ZM7.05 14.088l4.858 4.914l-4.858 4.914l-1.422-1.406l2.48-2.508H.997v-2h7.11l-2.48-2.508l1.422-1.406Z"/></svg>
|
||||
|
After Width: | Height: | Size: 297 B |
7
src/assets/icons/light.svg
Normal file
@@ -0,0 +1,7 @@
|
||||
<svg viewBox="0 0 1024 1024" version="1.1"
|
||||
xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
width="200" height="200">
|
||||
<path
|
||||
d="M522.88 874.666667a21.333333 21.333333 0 0 1 21.333333 21.333333v85.333333a21.333333 21.333333 0 0 1-21.333333 21.333334h-21.333333a21.333333 21.333333 0 0 1-21.333334-21.333334v-85.333333a21.333333 21.333333 0 0 1 21.333334-21.333333h21.333333z m268.416-107.52l60.352 60.352a21.333333 21.333333 0 0 1 0 30.165333l-15.082667 15.082667a21.333333 21.333333 0 0 1-30.186666 0l-60.330667-60.352a21.333333 21.333333 0 0 1 0-30.165334l15.082667-15.082666a21.333333 21.333333 0 0 1 30.165333 0z m-527.957333 0l15.082666 15.082666a21.333333 21.333333 0 0 1 0 30.165334l-60.352 60.352a21.333333 21.333333 0 0 1-30.165333 0l-15.082667-15.082667a21.333333 21.333333 0 0 1 0-30.165333l60.330667-60.352a21.333333 21.333333 0 0 1 30.186667 0zM512 277.333333c141.376 0 256 114.624 256 256s-114.624 256-256 256-256-114.624-256-256 114.624-256 256-256z m0 64a192 192 0 1 0 0 384 192 192 0 0 0 0-384z m448.213333 160a21.333333 21.333333 0 0 1 21.333334 21.333334v21.333333a21.333333 21.333333 0 0 1-21.333334 21.333333h-85.333333a21.333333 21.333333 0 0 1-21.333333-21.333333v-21.333333a21.333333 21.333333 0 0 1 21.333333-21.333334h85.333333z m-810.666666 0a21.333333 21.333333 0 0 1 21.333333 21.333334v21.333333a21.333333 21.333333 0 0 1-21.333333 21.333333h-85.333334a21.333333 21.333333 0 0 1-21.333333-21.333333v-21.333333a21.333333 21.333333 0 0 1 21.333333-21.333334h85.333334zM836.586667 193.92l15.082666 15.082667a21.333333 21.333333 0 0 1 0 30.165333l-60.352 60.352a21.333333 21.333333 0 0 1-30.165333 0l-15.082667-15.082667a21.333333 21.333333 0 0 1 0-30.165333l60.330667-60.352a21.333333 21.333333 0 0 1 30.186667 0z m-618.496 0l60.352 60.352a21.333333 21.333333 0 0 1 0 30.165333l-15.082667 15.082667a21.333333 21.333333 0 0 1-30.186667 0L172.821333 239.146667a21.333333 21.333333 0 0 1 0-30.165334l15.082667-15.082666a21.333333 21.333333 0 0 1 30.165333 0zM522.901333 64a21.333333 21.333333 0 0 1 21.333334 21.333333v85.333334a21.333333 21.333333 0 0 1-21.333334 21.333333h-21.333333a21.333333 21.333333 0 0 1-21.333333-21.333333V85.333333a21.333333 21.333333 0 0 1 21.333333-21.333333h21.333333z"
|
||||
></path>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 2.2 KiB |
1
src/assets/icons/line.svg
Normal file
@@ -0,0 +1 @@
|
||||
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1676518938084" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2193" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="M893.60324 384c-54.7 1-101.1 36.4-118.4 85.4-2.2 6.4-8.3 10.6-15 10.6H263.80324c-6.7 0-12.8-4.2-15-10.6-17.3-49.1-63.6-84.4-118.4-85.4C59.90324 382.7 0.50324 440.6 0.00324 511.1-0.49676 582.2 57.00324 640 128.00324 640c55.7 0 103.1-35.6 120.7-85.3 2.3-6.4 8.3-10.7 15.1-10.7h496.4c6.8 0 12.8 4.3 15.1 10.7 17.6 49.7 65 85.3 120.7 85.3 71 0 128.5-57.8 128-128.9-0.5-70.5-59.9-128.4-130.4-127.1zM128.00324 576c-35.3 0-64-28.7-64-64s28.7-64 64-64 64 28.7 64 64-28.7 64-64 64z m768 0c-35.3 0-64-28.7-64-64s28.7-64 64-64 64 28.7 64 64-28.7 64-64 64z" p-id="2194"></path></svg>
|
||||
|
After Width: | Height: | Size: 904 B |
1
src/assets/icons/lock.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 36 36"><path fill="currentColor" d="M18.09 20.59A2.41 2.41 0 0 0 17 25.14V28h2v-2.77a2.41 2.41 0 0 0-.91-4.64" class="clr-i-outline clr-i-outline-path-1"/><path fill="currentColor" d="M26 15v-4.28a8.2 8.2 0 0 0-8-8.36a8.2 8.2 0 0 0-8 8.36V15H7v17a2 2 0 0 0 2 2h18a2 2 0 0 0 2-2V15Zm-14-4.28a6.2 6.2 0 0 1 6-6.36a6.2 6.2 0 0 1 6 6.36V15H12ZM9 32V17h18v15Z" class="clr-i-outline clr-i-outline-path-2"/><path fill="none" d="M0 0h36v36H0z"/></svg>
|
||||
|
After Width: | Height: | Size: 521 B |
1
src/assets/icons/menu-fold.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24"><path fill="currentColor" d="M2 4h20v2H2V4Zm20 5.57v4.86L18.113 12L22 9.57ZM2 13v-2h15v2H2Zm0 7v-2h20v2H2Z"/></svg>
|
||||
|
After Width: | Height: | Size: 200 B |
1
src/assets/icons/menu-unfold.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24"><path fill="currentColor" d="M2 4h20v2H2V4Zm0 5.57L5.887 12L2 14.43V9.57ZM7 11h15v2H7v-2Zm-5 7h20v2H2v-2Z"/></svg>
|
||||
|
After Width: | Height: | Size: 199 B |
6
src/assets/icons/pen-line.svg
Normal file
@@ -0,0 +1,6 @@
|
||||
<svg width="256" height="256" xmlns="http://www.w3.org/2000/svg">
|
||||
<g>
|
||||
<path d="m227.32,73.37l-44.69,-44.68a16,16 0 0 0 -22.63,0l-123.31,123.31a15.86,15.86 0 0 0 -4.69,11.31l0,44.69a16,16 0 0 0 16,16l44.69,0a15.86,15.86 0 0 0 11.31,-4.69l83.67,-83.66l3.48,13.9l-36.8,36.79a8,8 0 0 0 11.31,11.32l40,-40a8,8 0 0 0 2.11,-7.6l-6.9,-27.61l26.45,-26.45a16,16 0 0 0 0,-22.63m-179.32,105.94l28.69,28.69l-28.69,0l0,-28.69zm48,25.38l-44.69,-44.69l84.69,-84.69l44.69,44.69l-84.69,84.69zm96,-96l-44.68,-44.69l24,-24l44.68,44.69l-24,24z" fill="currentColor"/>
|
||||
<line stroke-width="10" y2="234" x2="245" y1="234" x1="47" stroke="#000" fill="none"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 650 B |
1
src/assets/icons/preview.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24"><path fill="currentColor" d="M12 3a9 9 0 1 0 0 18a9 9 0 0 0 0-18ZM1 12C1 5.925 5.925 1 12 1s11 4.925 11 11s-4.925 11-11 11S1 18.075 1 12Zm7.5-5.63L18.25 12L8.5 17.63V6.37Zm2 3.465v4.33L14.25 12L10.5 9.835Z"/></svg>
|
||||
|
After Width: | Height: | Size: 299 B |
10
src/assets/icons/question.svg
Normal file
@@ -0,0 +1,10 @@
|
||||
<svg viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" width="200"
|
||||
height="200">
|
||||
<path
|
||||
d="M512 65.984C266.08 65.984 65.984 266.08 65.984 512c0 245.952 200.064 446.016 446.016 446.016 245.952 0 446.016-200.064 446.016-446.016C958.016 266.08 757.952 65.984 512 65.984zM512 894.016C301.344 894.016 129.984 722.624 129.984 512 129.984 301.344 301.344 129.984 512 129.984c210.624 0 382.016 171.36 382.016 382.016C894.016 722.624 722.624 894.016 512 894.016z"
|
||||
fill="#5C636E"></path>
|
||||
<path
|
||||
d="M512 255.2c-77.216 0-140.032 62.272-140.032 138.816 0 17.664 14.336 32 32 32s32-14.336 32-32c0-41.952 33.376-74.816 76.032-74.816 41.952 0 76.032 34.368 76.032 76.64 0 15.968-22.848 38.784-43.008 58.944C514.56 485.216 480 519.744 480 566.016l0 45.696c0 17.696 14.336 32 32 32s32-14.304 32-32l0-45.696c0-19.744 23.52-43.264 46.272-65.984 28.928-28.928 61.76-61.728 61.76-104.192C652.032 318.272 589.216 255.2 512 255.2z"
|
||||
fill="#5C636E"></path>
|
||||
<path d="M512 753.92m-48 0a1.5 1.5 0 1 0 96 0 1.5 1.5 0 1 0-96 0Z" fill="#5C636E"></path>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.1 KiB |
1
src/assets/icons/redo.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="-1 -2 24 24"><path fill="currentColor" d="m19.347 7.24l.847-1.266a.984.984 0 0 1 1.375-.259c.456.31.58.93.277 1.383L19.65 10.38a.984.984 0 0 1-1.375.259L14.97 8.393a1.002 1.002 0 0 1-.277-1.382a.984.984 0 0 1 1.375-.26l1.344.915C16.428 4.386 13.42 2 9.863 2c-4.357 0-7.89 3.582-7.89 8s3.533 8 7.89 8c.545 0 .987.448.987 1s-.442 1-.987 1C4.416 20 0 15.523 0 10S4.416 0 9.863 0c4.504 0 8.302 3.06 9.484 7.24z"/></svg>
|
||||
|
After Width: | Height: | Size: 489 B |
1
src/assets/icons/return.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 2048 2048"><path fill="currentColor" d="M1792 1152H475l466 467l-90 90l-621-621l621-621l90 90l-466 467h1189V384h128v768z"/></svg>
|
||||
|
After Width: | Height: | Size: 206 B |
1
src/assets/icons/rotate.svg
Normal file
@@ -0,0 +1 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?><svg width="24" height="24" viewBox="0 0 48 48" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M44 24C44 12.9543 35.0457 4 24 4C12.9543 4 4 12.9543 4 24C4 35.0457 12.9543 44 24 44C30.9566 44 37.0836 40.4483 40.6667 35.0593" stroke="#333" stroke-width="4" stroke-linecap="round"/><path d="M44 24H30" stroke="#333" stroke-width="4" stroke-linecap="round"/><circle cx="24" cy="24" r="6" fill="#333" stroke="#333" stroke-width="4"/></svg>
|
||||
|
After Width: | Height: | Size: 481 B |
1
src/assets/icons/save.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 2048 2048"><path fill="currentColor" d="M1792 128q27 0 50 10t40 27t28 41t10 50v1664H357l-229-230V256q0-27 10-50t27-40t41-28t50-10h1536zM512 896h1024V256H512v640zm768 512H640v384h128v-256h128v256h384v-384zm512-1152h-128v768H384V256H256v1381l154 155h102v-512h896v512h384V256z"/></svg>
|
||||
|
After Width: | Height: | Size: 360 B |
1
src/assets/icons/search.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 1024 1024"><path fill="currentColor" d="M909.6 854.5L649.9 594.8C690.2 542.7 712 479 712 412c0-80.2-31.3-155.4-87.9-212.1c-56.6-56.7-132-87.9-212.1-87.9s-155.5 31.3-212.1 87.9C143.2 256.5 112 331.8 112 412c0 80.1 31.3 155.5 87.9 212.1C256.5 680.8 331.8 712 412 712c67 0 130.6-21.8 182.7-62l259.7 259.6a8.2 8.2 0 0 0 11.6 0l43.6-43.5a8.2 8.2 0 0 0 0-11.6zM570.4 570.4C528 612.7 471.8 636 412 636s-116-23.3-158.4-65.6C211.3 528 188 471.8 188 412s23.3-116.1 65.6-158.4C296 211.3 352.2 188 412 188s116.1 23.2 158.4 65.6S636 352.2 636 412s-23.3 116.1-65.6 158.4z"/></svg>
|
||||
|
After Width: | Height: | Size: 644 B |
6
src/assets/icons/setting.svg
Normal file
@@ -0,0 +1,6 @@
|
||||
<svg viewBox="0 0 1024 1024" version="1.1"
|
||||
xmlns="http://www.w3.org/2000/svg" width="200" height="200">
|
||||
<path
|
||||
d="M919.6 405.6l-57.2-8c-12.7-1.8-23-10.4-28-22.1-11.3-26.7-25.7-51.7-42.9-74.5-7.7-10.2-10-23.5-5.2-35.3l21.7-53.5c6.7-16.4 0.2-35.3-15.2-44.1L669.1 96.6c-15.4-8.9-34.9-5.1-45.8 8.9l-35.4 45.3c-7.9 10.2-20.7 14.9-33.5 13.3-14-1.8-28.3-2.8-42.8-2.8-14.5 0-28.8 1-42.8 2.8-12.8 1.6-25.6-3.1-33.5-13.3l-35.4-45.3c-10.9-14-30.4-17.8-45.8-8.9L230.4 168c-15.4 8.9-21.8 27.7-15.2 44.1l21.7 53.5c4.8 11.9 2.5 25.1-5.2 35.3-17.2 22.8-31.7 47.8-42.9 74.5-5 11.8-15.3 20.4-28 22.1l-57.2 8C86 408 72.9 423 72.9 440.8v142.9c0 17.7 13.1 32.7 30.6 35.2l57.2 8c12.7 1.8 23 10.4 28 22.1 11.3 26.7 25.7 51.7 42.9 74.5 7.7 10.2 10 23.5 5.2 35.3l-21.7 53.5c-6.7 16.4-0.2 35.3 15.2 44.1L354 927.8c15.4 8.9 34.9 5.1 45.8-8.9l35.4-45.3c7.9-10.2 20.7-14.9 33.5-13.3 14 1.8 28.3 2.8 42.8 2.8 14.5 0 28.8-1 42.8-2.8 12.8-1.6 25.6 3.1 33.5 13.3l35.4 45.3c10.9 14 30.4 17.8 45.8 8.9l123.7-71.4c15.4-8.9 21.8-27.7 15.2-44.1l-21.7-53.5c-4.8-11.8-2.5-25.1 5.2-35.3 17.2-22.8 31.7-47.8 42.9-74.5 5-11.8 15.3-20.4 28-22.1l57.2-8c17.6-2.5 30.6-17.5 30.6-35.2V440.8c0.2-17.8-12.9-32.8-30.5-35.2z m-408 245.5c-76.7 0-138.9-62.2-138.9-138.9s62.2-138.9 138.9-138.9 138.9 62.2 138.9 138.9-62.2 138.9-138.9 138.9z"
|
||||
></path>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.3 KiB |
1
src/assets/icons/thumbnail.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 20 20"><path fill="currentColor" d="M3 2a2 2 0 0 0-2 2v12a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2V4a2 2 0 0 0-2-2zm0 15a1 1 0 0 1-1-1V4a1 1 0 0 1 1-1h14a1 1 0 0 1 1 1v12a1 1 0 0 1-1 1z"/><path fill="currentColor" d="M17 4H3v10h14zM5 12l2.5-3l2 2L12 8l3 4zm-1 3h12v1H4z"/></svg>
|
||||
|
After Width: | Height: | Size: 346 B |
1
src/assets/icons/tree-list.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24"><path fill="currentColor" d="M6 22a4 4 0 0 1-1-7.874V9.874A4.002 4.002 0 0 1 6 2a4 4 0 0 1 1 7.874v4.252A4.002 4.002 0 0 1 6 22Zm-2-4a2 2 0 1 0 4 0a2 2 0 0 0-4 0ZM4 6a2 2 0 1 0 4 0a2 2 0 0 0-4 0Zm8 12h7v2h-7v-2Zm0-7h10v2H12v-2Zm0-7h7v2h-7V4Z"/></svg>
|
||||
|
After Width: | Height: | Size: 335 B |
1
src/assets/icons/undo.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="-0.5 -2 24 24"><path fill="currentColor" d="m5.308 7.612l1.352-.923a.981.981 0 0 1 1.372.27a1.008 1.008 0 0 1-.266 1.388l-3.277 2.237a.981.981 0 0 1-1.372-.27L.907 6.998a1.007 1.007 0 0 1 .266-1.389a.981.981 0 0 1 1.372.27l.839 1.259C4.6 3.01 8.38 0 12.855 0c5.458 0 9.882 4.477 9.882 10s-4.424 10-9.882 10a.994.994 0 0 1-.988-1c0-.552.443-1 .988-1c4.366 0 7.906-3.582 7.906-8s-3.54-8-7.906-8C9.311 2 6.312 4.36 5.308 7.612z"/></svg>
|
||||
|
After Width: | Height: | Size: 507 B |
1
src/assets/icons/ungroup.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 1024 1024"><path fill="currentColor" d="M736 550H288c-8.8 0-16 7.2-16 16v176c0 8.8 7.2 16 16 16h448c8.8 0 16-7.2 16-16V566c0-8.8-7.2-16-16-16zm-56 136H344v-64h336v64zm208 130c-39.8 0-72 32.2-72 72s32.2 72 72 72s72-32.2 72-72s-32.2-72-72-72zm0 96c-13.3 0-24-10.7-24-24s10.7-24 24-24s24 10.7 24 24s-10.7 24-24 24zM736 266H288c-8.8 0-16 7.2-16 16v176c0 8.8 7.2 16 16 16h448c8.8 0 16-7.2 16-16V282c0-8.8-7.2-16-16-16zm-56 136H344v-64h336v64zm208-194c39.8 0 72-32.2 72-72s-32.2-72-72-72s-72 32.2-72 72s32.2 72 72 72zm0-96c13.3 0 24 10.7 24 24s-10.7 24-24 24s-24-10.7-24-24s10.7-24 24-24zM136 64c-39.8 0-72 32.2-72 72s32.2 72 72 72s72-32.2 72-72s-32.2-72-72-72zm0 96c-13.3 0-24-10.7-24-24s10.7-24 24-24s24 10.7 24 24s-10.7 24-24 24zm0 656c-39.8 0-72 32.2-72 72s32.2 72 72 72s72-32.2 72-72s-32.2-72-72-72zm0 96c-13.3 0-24-10.7-24-24s10.7-24 24-24s24 10.7 24 24s-10.7 24-24 24z"/></svg>
|
||||
|
After Width: | Height: | Size: 956 B |
1
src/assets/icons/unlock.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 36 36"><path fill="currentColor" d="M12 25.14V28h2v-2.77a2.42 2.42 0 1 0-2-.09" class="clr-i-outline clr-i-outline-path-1"/><path fill="currentColor" d="M26 2a8.2 8.2 0 0 0-8 8.36V15H2v17a2 2 0 0 0 2 2h18a2 2 0 0 0 2-2V15h-4v-4.64A6.2 6.2 0 0 1 26 4a6.2 6.2 0 0 1 6 6.36v6.83a1 1 0 0 0 2 0v-6.83A8.2 8.2 0 0 0 26 2m-4 15v15H4V17Z" class="clr-i-outline clr-i-outline-path-2"/><path fill="none" d="M0 0h36v36H0z"/></svg>
|
||||
|
After Width: | Height: | Size: 496 B |
1
src/assets/icons/upload.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24"><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 17v2a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2v-2M7 9l5-5l5 5m-5-5v12"/></svg>
|
||||
|
After Width: | Height: | Size: 262 B |
1
src/assets/icons/vertical-distribution.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 20 20"><path fill="currentColor" d="M2.5 3a.5.5 0 0 0 0 1h15a.5.5 0 0 0 0-1zM2 16.5a.5.5 0 0 1 .5-.5h15a.5.5 0 0 1 0 1h-15a.5.5 0 0 1-.5-.5M6 7a2 2 0 0 0-2 2v2a2 2 0 0 0 2 2h8a2 2 0 0 0 2-2V9a2 2 0 0 0-2-2z"/></svg>
|
||||
|
After Width: | Height: | Size: 293 B |
1
src/assets/icons/view-hide.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 20 20"><path fill="currentColor" d="m12.81 4.36l-1.77 1.78a4 4 0 0 0-4.9 4.9l-2.76 2.75C2.06 12.79.96 11.49.2 10a11 11 0 0 1 12.6-5.64zm3.8 1.85c1.33 1 2.43 2.3 3.2 3.79a11 11 0 0 1-12.62 5.64l1.77-1.78a4 4 0 0 0 4.9-4.9l2.76-2.75zm-.25-3.99l1.42 1.42L3.64 17.78l-1.42-1.42z"/></svg>
|
||||
|
After Width: | Height: | Size: 361 B |
1
src/assets/icons/view-show.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 20 20"><path fill="currentColor" d="M.2 10a11 11 0 0 1 19.6 0A11 11 0 0 1 .2 10m9.8 4a4 4 0 1 0 0-8a4 4 0 0 0 0 8m0-2a2 2 0 1 1 0-4a2 2 0 0 1 0 4"/></svg>
|
||||
|
After Width: | Height: | Size: 232 B |
BIN
src/assets/imgs/test/my-img.png
Normal file
|
After Width: | Height: | Size: 29 KiB |
BIN
src/assets/logo.png
Normal file
|
After Width: | Height: | Size: 41 KiB |
4
src/assets/main.css
Normal file
@@ -0,0 +1,4 @@
|
||||
body {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
5
src/assets/svgs/electrical/face/三绕组变压器.svg
Normal file
@@ -0,0 +1,5 @@
|
||||
<svg id="_图层_1" data-name="图层 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 454 488.5">
|
||||
<path d="m134.5,20c30.58,0,59.34,11.91,80.96,33.54,21.63,21.63,33.54,50.38,33.54,80.96s-11.91,59.34-33.54,80.96c-21.63,21.63-50.38,33.54-80.96,33.54s-59.34-11.91-80.96-33.54c-21.63-21.63-33.54-50.38-33.54-80.96s11.91-59.34,33.54-80.96c21.63-21.63,50.38-33.54,80.96-33.54m0-20C60.22,0,0,60.22,0,134.5s60.22,134.5,134.5,134.5,134.5-60.22,134.5-134.5S208.78,0,134.5,0h0Z"/>
|
||||
<path d="m134.5,240c30.58,0,59.34,11.91,80.96,33.54,21.63,21.63,33.54,50.38,33.54,80.96s-11.91,59.34-33.54,80.96c-21.63,21.63-50.38,33.54-80.96,33.54s-59.34-11.91-80.96-33.54c-21.63-21.63-33.54-50.38-33.54-80.96s11.91-59.34,33.54-80.96c21.63-21.63,50.38-33.54,80.96-33.54m0-20C60.22,220,0,280.22,0,354.5s60.22,134.5,134.5,134.5,134.5-60.22,134.5-134.5-60.22-134.5-134.5-134.5h0Z"/>
|
||||
<path d="m319.5,129.75c30.58,0,59.34,11.91,80.96,33.54,21.63,21.63,33.54,50.38,33.54,80.96s-11.91,59.34-33.54,80.96c-21.63,21.63-50.38,33.54-80.96,33.54s-59.34-11.91-80.96-33.54c-21.63-21.63-33.54-50.38-33.54-80.96s11.91-59.34,33.54-80.96c21.63-21.63,50.38-33.54,80.96-33.54m0-20c-74.28,0-134.5,60.22-134.5,134.5s60.22,134.5,134.5,134.5,134.5-60.22,134.5-134.5-60.22-134.5-134.5-134.5h0Z"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.2 KiB |
6
src/assets/svgs/electrical/face/交流发电机.svg
Normal file
@@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg id="_图层_1" data-name="图层 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 500 500">
|
||||
<path d="m250,20c31.06,0,61.18,6.08,89.52,18.07,27.39,11.58,51.99,28.17,73.11,49.3,21.13,21.13,37.72,45.73,49.3,73.11,11.99,28.34,18.07,58.46,18.07,89.52s-6.08,61.18-18.07,89.52c-11.58,27.39-28.17,51.99-49.3,73.11s-45.73,37.72-73.11,49.3c-28.34,11.99-58.46,18.07-89.52,18.07s-61.18-6.08-89.52-18.07c-27.39-11.58-51.99-28.17-73.11-49.3-21.13-21.13-37.72-45.73-49.3-73.11-11.99-28.34-18.07-58.46-18.07-89.52s6.08-61.18,18.07-89.52c11.58-27.39,28.17-51.99,49.3-73.11,21.13-21.13,45.73-37.72,73.11-49.3,28.34-11.99,58.46-18.07,89.52-18.07m0-20C111.93,0,0,111.93,0,250s111.93,250,250,250,250-111.93,250-250S388.07,0,250,0h0Z"/>
|
||||
<text transform="translate(193.93 213.75) scale(1.35 1)" style="font-family: SimHei, SimHei; font-size: 161.58px;"><tspan x="0" y="0">G</tspan></text>
|
||||
<text transform="translate(145.34 570.94) scale(1.24 1)" style="font-family: SimHei, SimHei; font-size: 327.63px;"><tspan x="0" y="0">~</tspan></text>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.0 KiB |
5
src/assets/svgs/electrical/face/双绕组变压器.svg
Normal file
@@ -0,0 +1,5 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg id="_图层_1" data-name="图层 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 278 500">
|
||||
<path d="m139,21c31.79,0,61.67,12.38,84.15,34.85,22.48,22.48,34.85,52.36,34.85,84.15s-12.38,61.67-34.85,84.15c-22.48,22.48-52.36,34.85-84.15,34.85s-61.67-12.38-84.15-34.85c-22.48-22.48-34.85-52.36-34.85-84.15s12.38-61.67,34.85-84.15c22.48-22.48,52.36-34.85,84.15-34.85m0-20C62.23,1,0,63.23,0,140s62.23,139,139,139,139-62.23,139-139S215.77,1,139,1h0Z"/>
|
||||
<path d="m139,242c31.79,0,61.67,12.38,84.15,34.85,22.48,22.48,34.85,52.36,34.85,84.15s-12.38,61.67-34.85,84.15c-22.48,22.48-52.36,34.85-84.15,34.85s-61.67-12.38-84.15-34.85c-22.48-22.48-34.85-52.36-34.85-84.15s12.38-61.67,34.85-84.15c22.48-22.48,52.36-34.85,84.15-34.85m0-20C62.23,222,0,284.23,0,361s62.23,139,139,139,139-62.23,139-139-62.23-139-139-139h0Z"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 861 B |
16
src/assets/svgs/electrical/face/告警.svg
Normal file
@@ -0,0 +1,16 @@
|
||||
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<svg
|
||||
id="_图层_12" data-name="图层 12"
|
||||
viewBox="0 0 1024 1024"
|
||||
version="1.1"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
p-id="2803"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
width="200"
|
||||
height="200"
|
||||
>
|
||||
<path
|
||||
d="M959.800889 318.762667a30.364444 30.364444 0 0 1-11.377778 41.543111l-98.133333 56.632889-30.222222-52.864 94.435555-56.632889a47.872 47.872 0 0 1 22.641778-3.783111 34.688 34.688 0 0 1 22.656 15.104z m-898.844445 0c4.48-6.968889 11.107556-12.273778 18.887112-15.104a24.974222 24.974222 0 0 1 22.656 3.783111l94.435555 56.632889-30.222222 52.864-94.421333-56.632889a30.364444 30.364444 0 0 1-11.377778-41.543111h0.042666zM249.799111 129.962667a47.900444 47.900444 0 0 1 22.656-3.783111 37.688889 37.688889 0 0 1 18.887111 15.104l56.661334 94.407111-52.878223 30.208-56.647111-94.407111a30.364444 30.364444 0 0 1 11.377778-41.528889h-0.056889zM513.848889 56.888889a37.105778 37.105778 0 0 1 36.636444 31.530667v109.511111h-70.570666v-109.511111C476.131556 73.315556 494.961778 56.888889 513.848889 56.888889z m253.383111 73.073778a30.364444 30.364444 0 0 1 11.377778 41.528889l-56.647111 94.407111-52.878223-30.208 56.647112-94.407111a66.304 66.304 0 0 1 18.887111-15.104c7.552 0 18.887111 0 22.656 3.783111h-0.042667zM533.020444 409.329778L378.168889 665.614222h124.629333l-30.222222 181.902222 162.247111-252.387555h-132.024889l30.222222-185.799111z m-271.928888 483.100444h-64.782223V594.360889c1.521778-172.103111 141.952-310.556444 314.055111-309.632A308.48 308.48 0 0 1 819.868444 594.346667v298.069333H261.091556z m-169.955556 0H933.404444a37.12 37.12 0 0 1 33.991112 37.603556 33.877333 33.877333 0 0 1-33.991112 33.991111H91.164444a33.848889 33.848889 0 0 1-33.991111-33.991111 37.12 37.12 0 0 1 33.991111-37.603556"
|
||||
|
||||
></path>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.9 KiB |
4
src/assets/svgs/electrical/face/手车02.svg
Normal file
@@ -0,0 +1,4 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg id="_图层_1" data-name="图层 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 180 180">
|
||||
<rect y="0" width="180" height="180" rx="18.7" ry="18.7"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 205 B |
22
src/assets/svgs/electrical/face/测试.svg
Normal file
@@ -0,0 +1,22 @@
|
||||
<?xml version="1.0" standalone="no"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<svg
|
||||
t="1689212544735"
|
||||
class="icon"
|
||||
viewBox="0 0 1024 1024"
|
||||
version="1.1"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
p-id="2636"
|
||||
width="48"
|
||||
height="48"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
>
|
||||
<path
|
||||
d="M866.816 588.8c17.92 11.264 45.056 11.264 61.44 0 16.384-12.288 16.384-31.232 0-41.984l-379.904-322.56c-9.728-5.632-20.992-8.704-33.792-7.68-12.8-1.024-24.064 1.024-33.792 7.68l-382.464 322.56c-16.384 12.288-16.384 31.232 0 41.984 17.92 11.264 45.056 11.264 61.44 0l354.816-303.616 352.256 303.616z"
|
||||
p-id="2637"
|
||||
></path>
|
||||
<path
|
||||
d="M873.984 836.608c17.92 11.264 45.056 11.264 61.44 0 16.384-12.288 16.384-31.232 0-41.984l-379.904-322.56c-9.728-5.632-20.992-8.704-33.792-7.68-12.8-1.024-24.064 1.024-33.792 7.68l-382.464 322.56c-16.384 12.288-16.384 31.232 0 41.984 17.92 11.264 45.056 11.264 61.44 0l354.816-303.616 352.256 303.616z"
|
||||
p-id="2638"
|
||||
></path>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.1 KiB |
10
src/assets/svgs/electrical/fs/故障.svg
Normal file
@@ -0,0 +1,10 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg id="_图层_1" data-name="图层 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 218 364">
|
||||
<line x1="210.89" y1="6.61" x2="63.11" y2="154.39"
|
||||
style="fill: none; stroke: currentColor; stroke-miterlimit: 10; stroke-width: 20px;" />
|
||||
<line x1="56" y1="157" x2="201" y2="157"
|
||||
style="fill: none; stroke: currentColor; stroke-miterlimit: 10; stroke-width: 20px;" />
|
||||
<line x1="208.45" y1="154.2" x2="60.66" y2="301.98"
|
||||
style="fill: none; stroke: currentColor; stroke-miterlimit: 10; stroke-width: 20px;" />
|
||||
<polygon points="2.42 360.3 94.44 307.69 55.03 268.28 2.42 360.3" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 641 B |
7
src/assets/svgs/electrical/fs/火花间隙.svg
Normal file
@@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg id="_图层_1" data-name="图层 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 56 492">
|
||||
<polygon points="28.14 226 56 123.72 .27 123.72 28.14 226" stroke="none"/>
|
||||
<line x1="28.14" y1=".6" x2="28.14" y2="126.7" style="stroke: currentColor; stroke-miterlimit: 10; stroke-width: 16px;"/>
|
||||
<polygon points="28.38 266.54 .51 368.81 56.24 368.81 28.38 266.54" stroke="none"/>
|
||||
<line x1="28.38" y1="491.94" x2="28.38" y2="365.83" style="stroke: currentColor; stroke-miterlimit: 10; stroke-width: 16px;"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 559 B |
5
src/assets/svgs/electrical/fs/电阻(阻抗).svg
Normal file
@@ -0,0 +1,5 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg id="_图层_1" data-name="图层 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 259 158">
|
||||
<rect x="10" y="50" width="239" height="99" style="fill: none; stroke: currentColor; stroke-miterlimit: 10; stroke-width: 20px;"/>
|
||||
<text transform="translate(114.5 40.88)" style="font-size: 60px;">R</text>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 354 B |
15
src/assets/svgs/electrical/fs/避雷器.svg
Normal file
@@ -0,0 +1,15 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: $$$/GeneralStr/196=Adobe Illustrator 27.6.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="图层_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 134 337" style="enable-background:new 0 0 134 337;" xml:space="preserve">
|
||||
<style type="text/css">
|
||||
.st0{fill:none;stroke:currentColor;stroke-width:20;stroke-miterlimit:10;}
|
||||
.st1{fill:none;stroke:currentColor;stroke-width:4;stroke-miterlimit:10;}
|
||||
.st2{fill:none;stroke:currentColor;stroke-width:10;stroke-miterlimit:10;}
|
||||
.st3{fill:none;stroke:currentColor;stroke-width:16;stroke-miterlimit:10;}
|
||||
</style>
|
||||
<polygon points="67,227 92.72,124 41.28,124 " fill="none"/>
|
||||
<line class="st3" x1="67" y1="0" x2="67" y2="127"/>
|
||||
<line class="st3" x1="67" y1="243" x2="67" y2="337.05"/>
|
||||
<rect x="8" y="83" class="st3" width="118" height="163"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 935 B |
5
src/assets/svgs/electrical/stroke/三绕组自耦变压器.svg
Normal file
@@ -0,0 +1,5 @@
|
||||
<svg id="_图层_1" data-name="图层 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 258 499">
|
||||
<circle cx="129.5" cy="370" r="119" style="fill: none; stroke: currentColor; stroke-miterlimit: 10; stroke-width: 20px;"/>
|
||||
<circle cx="129.5" cy="179" r="119" style="fill: none; stroke: currentColor; stroke-miterlimit: 10; stroke-width: 20px;"/>
|
||||
<path d="m248.5,180c0-93.19-52.48-168.86-117.53-169.99-.69.68-2.08,1.07-2.77,1.75" style="fill: none; stroke: currentColor; stroke-miterlimit: 10; stroke-width: 20px;"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 527 B |
6
src/assets/svgs/electrical/stroke/手车01.svg
Normal file
@@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg id="_图层_1" data-name="图层 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 158 286">
|
||||
<polyline points="6.88 87 79 14.88 151.12 87" style="fill: none; stroke: currentColor; stroke-miterlimit: 10; stroke-width: 20px;"/>
|
||||
<polyline points="6.6 155.52 78.73 83.39 150.85 155.52" style="fill: none; stroke: currentColor; stroke-miterlimit: 10; stroke-width: 20px;"/>
|
||||
<line x1="79" y1="94" x2="79" y2="286" style="fill: none; stroke: currentColor; stroke-miterlimit: 10; stroke-width: 20px;"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 552 B |
7
src/assets/svgs/electrical/stroke/接地.svg
Normal file
@@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg id="_图层_1" data-name="图层 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 210 392">
|
||||
<line y1="284" x2="210" y2="284" style="fill: none; stroke: currentColor; stroke-miterlimit: 10; stroke-width: 20px;"/>
|
||||
<line x1="25" y1="333" x2="185" y2="333" style="fill: none; stroke: currentColor; stroke-miterlimit: 10; stroke-width: 20px;"/>
|
||||
<line x1="45" y1="382" x2="165" y2="382" style="fill: none; stroke: currentColor; stroke-miterlimit: 10; stroke-width: 20px;"/>
|
||||
<line x1="105" x2="105" y2="275" style="fill: none; stroke: currentColor; stroke-miterlimit: 10; stroke-width: 20px;"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 648 B |
16
src/assets/svgs/electrical/stroke/断路器-开关.svg
Normal file
@@ -0,0 +1,16 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: $$$/GeneralStr/196=Adobe Illustrator 27.6.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="图层_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 125.5 318" style="enable-background:new 0 0 125.5 318;" xml:space="preserve">
|
||||
<style type="text/css">
|
||||
.st0{fill:none;stroke:currentColor;stroke-width:20;stroke-miterlimit:10;}
|
||||
.st1{fill:none;stroke:currentColor;stroke-width:4;stroke-miterlimit:10;}
|
||||
.st2{fill:none;stroke:currentColor;stroke-width:10;stroke-miterlimit:10;}
|
||||
.st3{fill:none;stroke:currentColor;stroke-width:16;stroke-miterlimit:10;}
|
||||
</style>
|
||||
<line class="st0" x1="111" y1="0" x2="111" y2="76"/>
|
||||
<line class="st0" x1="111" y1="242" x2="111" y2="318"/>
|
||||
<line class="st1" x1="96" y1="74" x2="124" y2="102"/>
|
||||
<line class="st1" x1="96" y1="102" x2="124" y2="74"/>
|
||||
<line class="st0" x1="110.5" y1="251.47" x2="9.5" y2="76.53"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 992 B |
11
src/assets/svgs/electrical/stroke/消弧线圈.svg
Normal file
@@ -0,0 +1,11 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg id="_图层_1" data-name="图层 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 146 648">
|
||||
<path d="m66,78c37,0,67,30,67,67s-30,67-67,67" style="fill: none; stroke: currentColor; stroke-miterlimit: 10; stroke-width: 16px;"/>
|
||||
<path d="m65.91,211.53c37,0,67,30,67,67s-30,67-67,67" style="fill: none; stroke: currentColor; stroke-miterlimit: 10; stroke-width: 16px;"/>
|
||||
<path d="m65.91,345.53c37,0,67,30,67,67s-30,67-67,67" style="fill: none; stroke: currentColor; stroke-miterlimit: 10; stroke-width: 16px;"/>
|
||||
<line x1="62" y1=".5" x2="62" y2="86.5" style="fill: none; stroke: currentColor; stroke-miterlimit: 10; stroke-width: 16px;"/>
|
||||
<line x1="74" y1="474" x2="74" y2="560" style="fill: none; stroke: currentColor; stroke-miterlimit: 10; stroke-width: 16px;"/>
|
||||
<line x1=".14" y1="570" x2="145.86" y2="570" style="fill: none; stroke: currentColor; stroke-miterlimit: 10; stroke-width: 20px;"/>
|
||||
<line x1="17.49" y1="604" x2="128.51" y2="604" style="fill: none; stroke: currentColor; stroke-miterlimit: 10; stroke-width: 20px;"/>
|
||||
<line x1="33" y1="638" x2="113" y2="638" style="fill: none; stroke: currentColor; stroke-miterlimit: 10; stroke-width: 20px;"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.2 KiB |
17
src/assets/svgs/electrical/stroke/熔断器.svg
Normal file
@@ -0,0 +1,17 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg id="_图层_1" data-name="图层 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 190 469">
|
||||
<rect
|
||||
x="10"
|
||||
y="98.5"
|
||||
width="170"
|
||||
height="272"
|
||||
style="fill: none; stroke: currentColor; stroke-miterlimit: 10; stroke-width: 20px"
|
||||
/>
|
||||
<line
|
||||
x1="95"
|
||||
y1="1"
|
||||
x2="95"
|
||||
y2="469"
|
||||
style="fill: none; stroke: currentColor; stroke-miterlimit: 10; stroke-width: 20px"
|
||||
/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 452 B |
4
src/assets/svgs/electrical/stroke/电动机.svg
Normal file
@@ -0,0 +1,4 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg id="_图层_1" data-name="图层 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 465.5 465">
|
||||
<circle cx="233" cy="233" r="222" stroke="currentColor" style="fill: none; stroke-miterlimit: 10; stroke-width: 20px;"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 269 B |
7
src/assets/svgs/electrical/stroke/电容器.svg
Normal file
@@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg id="_图层_1" data-name="图层 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 345 151">
|
||||
<line y1="74" x2="129" y2="74" style="fill: none; stroke: currentColor; stroke-miterlimit: 10; stroke-width: 20px;"/>
|
||||
<line x1="135" x2="135" y2="151" style="fill: none; stroke: currentColor; stroke-miterlimit: 10; stroke-width: 20px;"/>
|
||||
<line x1="345" y1="77" x2="216" y2="77" style="fill: none; stroke: currentColor; stroke-miterlimit: 10; stroke-width: 20px;"/>
|
||||
<line x1="210" y1="151" x2="210" y2="0" style="fill: none; stroke: currentColor; stroke-miterlimit: 10; stroke-width: 20px;"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 644 B |
15
src/assets/svgs/electrical/stroke/电抗器.svg
Normal file
@@ -0,0 +1,15 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: $$$/GeneralStr/196=Adobe Illustrator 27.6.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="图层_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 120 282" style="enable-background:new 0 0 120 282;" xml:space="preserve">
|
||||
<style type="text/css">
|
||||
.st0{fill:none;stroke:currentColor;stroke-width:20;stroke-miterlimit:10;}
|
||||
.st1{fill:none;stroke:currentColor;stroke-width:4;stroke-miterlimit:10;}
|
||||
.st2{fill:none;stroke-width:10;stroke-miterlimit:10;}
|
||||
.st3{fill:none;stroke-width:16;stroke-miterlimit:10;}
|
||||
</style>
|
||||
<path class="st0" d="M60,215c-28.17,0-51-22.83-51-51s22.83-51,51-51s51,22.83,51,51"/>
|
||||
<line class="st0" x1="60" y1="0" x2="60" y2="159"/>
|
||||
<line class="st0" x1="60" y1="205" x2="60" y2="283"/>
|
||||
<line class="st0" x1="120" y1="163" x2="50" y2="163"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 915 B |
13
src/assets/svgs/electrical/stroke/电缆终端头.svg
Normal file
@@ -0,0 +1,13 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: $$$/GeneralStr/196=Adobe Illustrator 27.6.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="图层_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 222 336" style="enable-background:new 0 0 222 336;" xml:space="preserve">
|
||||
<style type="text/css">
|
||||
.st0{fill:none;stroke:currentColor;stroke-width:20;stroke-miterlimit:10;}
|
||||
.st1{fill:none;stroke:currentColor;stroke-width:4;stroke-miterlimit:10;}
|
||||
.st2{fill:none;stroke:currentColor;stroke-width:10;stroke-miterlimit:10;}
|
||||
.st3{fill:none;stroke:currentColor;stroke-width:16;stroke-miterlimit:10;}
|
||||
</style>
|
||||
<line class="st0" x1="111" y1="0" x2="111" y2="336"/>
|
||||
<polygon class="st0" points="111,269 204.92,106.33 17.08,106.33 "/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 830 B |
15
src/assets/svgs/electrical/stroke/自动空气断路器.svg
Normal file
@@ -0,0 +1,15 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: $$$/GeneralStr/196=Adobe Illustrator 27.6.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="图层_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 160 318" style="enable-background:new 0 0 160 318;" xml:space="preserve">
|
||||
<style type="text/css">
|
||||
.st0{fill:none;stroke:currentColor;stroke-width:20;stroke-miterlimit:10;}
|
||||
.st1{fill:none;stroke:currentColor;stroke-width:4;stroke-miterlimit:10;}
|
||||
.st2{fill:none;stroke:currentColor;stroke-width:10;stroke-miterlimit:10;}
|
||||
.st3{fill:none;stroke:currentColor;stroke-width:16;stroke-miterlimit:10;}
|
||||
</style>
|
||||
<line class="st0" x1="149.81" y1="-0.48" x2="149.81" y2="75.52"/>
|
||||
<line class="st0" x1="149.81" y1="241.52" x2="149.81" y2="317.52"/>
|
||||
<line class="st0" x1="149.31" y1="250.99" x2="48.31" y2="76.05"/>
|
||||
<line class="st2" x1="50" y1="185" x2="108" y2="185"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 963 B |
16
src/assets/svgs/electrical/stroke/跌落式熔断器.svg
Normal file
@@ -0,0 +1,16 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: $$$/GeneralStr/196=Adobe Illustrator 27.6.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="图层_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 179 319" style="enable-background:new 0 0 179 319;" xml:space="preserve">
|
||||
<style type="text/css">
|
||||
.st0{fill:none;stroke:currentColor;stroke-width:20;stroke-miterlimit:10;}
|
||||
.st1{fill:none;stroke:currentColor;stroke-width:4;stroke-miterlimit:10;}
|
||||
.st2{fill:none;stroke:currentColor;stroke-width:10;stroke-miterlimit:10;}
|
||||
.st3{fill:none;stroke:currentColor;stroke-width:16;stroke-miterlimit:10;}
|
||||
</style>
|
||||
<line class="st0" x1="168.6" y1="0.58" x2="168.6" y2="76.58"/>
|
||||
<line class="st0" x1="168.6" y1="242.58" x2="168.6" y2="318.58"/>
|
||||
<line class="st0" x1="168.1" y1="252.05" x2="67.1" y2="77.11"/>
|
||||
<rect x="82" y="107" transform="matrix(0.866 -0.5 0.5 0.866 -64.4769 78.3689)" class="st3" width="64" height="105"/>
|
||||
<line class="st2" x1="45.05" y1="190.18" x2="87" y2="169"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.1 KiB |
15
src/assets/svgs/electrical/stroke/隔离开关-刀闸.svg
Normal file
@@ -0,0 +1,15 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: $$$/GeneralStr/196=Adobe Illustrator 27.6.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="图层_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 133 318" style="enable-background:new 0 0 133 318;" xml:space="preserve">
|
||||
<style type="text/css">
|
||||
.st0{fill:none;stroke:currentColor;stroke-width:20;stroke-miterlimit:10;}
|
||||
.st1{fill:none;stroke:currentColor;stroke-width:4;stroke-miterlimit:10;}
|
||||
.st2{fill:none;stroke:currentColor;stroke-width:10;stroke-miterlimit:10;}
|
||||
.st3{fill:none;stroke:currentColor;stroke-width:16;stroke-miterlimit:10;}
|
||||
</style>
|
||||
<line class="st0" x1="109.27" y1="0.58" x2="109.27" y2="76.58"/>
|
||||
<line class="st0" x1="109.27" y1="242.58" x2="109.27" y2="318.58"/>
|
||||
<line class="st0" x1="108.77" y1="252.05" x2="7.77" y2="77.11"/>
|
||||
<line class="st0" x1="82" y1="79" x2="133" y2="79"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 959 B |
39
src/components/custom-components/bind-dot-vue/index.vue
Normal file
@@ -0,0 +1,39 @@
|
||||
<template>
|
||||
<p
|
||||
class="break-words w-1/1 h-1/1"
|
||||
:class="props.vertical ? 'text-vertical' : ''"
|
||||
:style="{ fontFamily: props.fontFamily, fontSize: props.fontSize + 'px', color: props.fill }"
|
||||
>
|
||||
{{ props.text }}
|
||||
</p>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
const props = defineProps({
|
||||
fontFamily: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
fontSize: {
|
||||
type: Number,
|
||||
default: 15
|
||||
},
|
||||
text: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
fill: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
vertical: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
})
|
||||
</script>
|
||||
<style scoped>
|
||||
.text-vertical {
|
||||
writing-mode: tb;
|
||||
letter-spacing: 5px;
|
||||
}
|
||||
</style>
|
||||
39
src/components/custom-components/bind-index-vue/index.vue
Normal file
@@ -0,0 +1,39 @@
|
||||
<template>
|
||||
<p
|
||||
class="break-words w-1/1 h-1/1"
|
||||
:class="props.vertical ? 'text-vertical' : ''"
|
||||
:style="{ fontFamily: props.fontFamily, fontSize: props.fontSize + 'px', color: props.fill }"
|
||||
>
|
||||
{{ props.text }}
|
||||
</p>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
const props = defineProps({
|
||||
fontFamily: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
fontSize: {
|
||||
type: Number,
|
||||
default: 15
|
||||
},
|
||||
text: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
fill: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
vertical: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
})
|
||||
</script>
|
||||
<style scoped>
|
||||
.text-vertical {
|
||||
writing-mode: tb;
|
||||
letter-spacing: 5px;
|
||||
}
|
||||
</style>
|
||||
39
src/components/custom-components/card-vue/index.vue
Normal file
@@ -0,0 +1,39 @@
|
||||
<!-- eslint-disable vue/html-indent -->
|
||||
<template>
|
||||
<div class="w-1/1 h-1/1 flex justify-center items-center custom-card">
|
||||
<el-card
|
||||
class="w-95/100 h-95/100"
|
||||
:shadow="props.shadow as any"
|
||||
:style="{
|
||||
'background-color': props.backGroundColor
|
||||
}"
|
||||
></el-card>
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { ElCard } from 'element-plus'
|
||||
const props = defineProps({
|
||||
shadow: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
backGroundColor: {
|
||||
type: String,
|
||||
default: '#ffffff'
|
||||
},
|
||||
boxShadow: {
|
||||
type: String,
|
||||
default: '#ffffff'
|
||||
}
|
||||
})
|
||||
</script>
|
||||
<style lang="less">
|
||||
.custom-card {
|
||||
.el-card.is-always-shadow {
|
||||
box-shadow: v-bind('`0px 0px 12px ${$props.boxShadow}`') !important;
|
||||
}
|
||||
.el-card.is-hover-shadow:hover {
|
||||
box-shadow: v-bind('`0px 0px 12px ${$props.boxShadow}`') !important;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
71
src/components/custom-components/kv-vue/index.vue
Normal file
@@ -0,0 +1,71 @@
|
||||
<template>
|
||||
<table class="w-1/1 h-1/1 kvTable">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td class="kvKey kvKeyValue" colspan="1">{{ props.label }}</td>
|
||||
<td class="kvValue kvKeyValue" colspan="1">{{ props.value }}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { ElDescriptions, ElDescriptionsItem } from 'element-plus'
|
||||
import type { PropType } from 'vue'
|
||||
const props = defineProps({
|
||||
fontFamily: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
fontSize: {
|
||||
type: Number,
|
||||
default: 15
|
||||
},
|
||||
label: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
labelWidth: {
|
||||
type: Number,
|
||||
default: 50
|
||||
},
|
||||
value: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
valueWidth: {
|
||||
type: Number,
|
||||
default: 50
|
||||
},
|
||||
color: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
border: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
borderColor: {
|
||||
type: String,
|
||||
default: ''
|
||||
}
|
||||
})
|
||||
</script>
|
||||
<style scroped>
|
||||
.kvTable {
|
||||
border: v-bind('`${props.border?1:0}px solid ${props.borderColor}`');
|
||||
}
|
||||
.kvKeyValue {
|
||||
font-size: v-bind('`${props.fontSize}px`');
|
||||
font-family: v-bind('`${props.fontFamily}`');
|
||||
color: v-bind('`${props.color}`');
|
||||
}
|
||||
.kvKey {
|
||||
width: v-bind('`${props.labelWidth}px`');
|
||||
border-right-width: v-bind('`${props.border?1:0}px`');
|
||||
border-right-style: solid;
|
||||
border-right-color: v-bind('`${props.borderColor}`') !important;
|
||||
}
|
||||
.kvValue {
|
||||
width: v-bind('`${props.valueWidth}px`');
|
||||
}
|
||||
</style>
|
||||
72
src/components/custom-components/now-time-vue/index.vue
Normal file
@@ -0,0 +1,72 @@
|
||||
<!-- eslint-disable vue/html-indent -->
|
||||
<template>
|
||||
<div>
|
||||
<div class="flex">
|
||||
<div class="font-bold" :style="{ color: props.fontColor, fontSize: `${props.dateSize}px` }">
|
||||
{{ date }}
|
||||
</div>
|
||||
<div class="font-bold ml-5px" :style="{ color: props.fontColor, fontSize: `${props.weekSize}px ` }">
|
||||
{{ week }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="font-bold mt-5px ml-5px" :style="{ color: props.fontColor, fontSize: `${props.timeSize}px ` }">
|
||||
{{ time }}
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { computed, onMounted, ref, onUnmounted } from 'vue'
|
||||
const props = defineProps({
|
||||
fontColor: {
|
||||
type: String,
|
||||
default: '#000000'
|
||||
},
|
||||
dateSize: {
|
||||
type: Number,
|
||||
default: 12
|
||||
},
|
||||
weekSize: {
|
||||
type: Number,
|
||||
default: 12
|
||||
},
|
||||
timeSize: {
|
||||
type: Number,
|
||||
default: 24
|
||||
}
|
||||
})
|
||||
const now_date = ref(new Date())
|
||||
const timer = ref()
|
||||
const date = computed(() => {
|
||||
const year = now_date.value.getFullYear()
|
||||
const month = now_date.value.getMonth() + 1
|
||||
const day = now_date.value.getDate()
|
||||
const time = year.toString() + '年' + month.toString() + '月' + day.toString() + '日'
|
||||
return time
|
||||
})
|
||||
const week = computed(() => {
|
||||
const d = now_date.value.getDay()
|
||||
const weekday = ['星期日', '星期一', '星期二', '星期三', '星期四', '星期五', '星期六']
|
||||
const time = weekday[d]
|
||||
return time
|
||||
})
|
||||
const time = computed(() => {
|
||||
const hour = now_date.value.getHours()
|
||||
const minute = now_date.value.getMinutes()
|
||||
const second = now_date.value.getSeconds()
|
||||
const time =
|
||||
(hour < 10 ? '0' + hour.toString() : hour.toString()) +
|
||||
':' +
|
||||
(minute < 10 ? '0' + minute.toString() : minute.toString()) +
|
||||
':' +
|
||||
(second < 10 ? '0' + second.toString() : second.toString())
|
||||
return time
|
||||
})
|
||||
onMounted(() => {
|
||||
timer.value = setInterval(() => {
|
||||
now_date.value = new Date() // 修改数据date
|
||||
}, 500)
|
||||
})
|
||||
onUnmounted(() => {
|
||||
clearInterval(timer.value)
|
||||
})
|
||||
</script>
|
||||
48
src/components/custom-components/sys-button-vue/index.vue
Normal file
@@ -0,0 +1,48 @@
|
||||
<template>
|
||||
<div style="width: 100%; height: 100%">
|
||||
<button class="w-1/1 h-1/1" :style="getStyle(props.type, props.round)">
|
||||
<el-text>{{ props.text }}</el-text>
|
||||
</button>
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { ElText } from 'element-plus'
|
||||
import type { PropType } from 'vue'
|
||||
type ButtonType = '' | 'default' | 'success' | 'warning' | 'info' | 'primary' | 'danger'
|
||||
const props = defineProps({
|
||||
text: {
|
||||
type: String,
|
||||
default: '按钮文本'
|
||||
},
|
||||
type: {
|
||||
type: String as PropType<ButtonType>,
|
||||
default: ''
|
||||
},
|
||||
round: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
})
|
||||
const getStyle = (type: ButtonType, round: boolean) => {
|
||||
let bg_color = ''
|
||||
let border_radius = '4px'
|
||||
if (type == 'primary') {
|
||||
bg_color = '#409eff'
|
||||
} else if (type == 'success') {
|
||||
bg_color = '#67c23a'
|
||||
} else if (type == 'warning') {
|
||||
bg_color = '#e6a23c'
|
||||
} else if (type == 'danger') {
|
||||
bg_color = '#f56c6c'
|
||||
} else if (type == 'info') {
|
||||
bg_color = '#909399'
|
||||
}
|
||||
if (round) {
|
||||
border_radius = '20px'
|
||||
}
|
||||
return {
|
||||
backgroundColor: bg_color,
|
||||
borderRadius: border_radius
|
||||
}
|
||||
}
|
||||
</script>
|
||||
39
src/components/custom-components/text-vue/index.vue
Normal file
@@ -0,0 +1,39 @@
|
||||
<template>
|
||||
<p
|
||||
class="break-words w-1/1 h-1/1"
|
||||
:class="props.vertical ? 'text-vertical' : ''"
|
||||
:style="{ fontFamily: props.fontFamily, fontSize: props.fontSize + 'px', color: props.fill }"
|
||||
>
|
||||
{{ props.text }}
|
||||
</p>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
const props = defineProps({
|
||||
fontFamily: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
fontSize: {
|
||||
type: Number,
|
||||
default: 15
|
||||
},
|
||||
text: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
fill: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
vertical: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
})
|
||||
</script>
|
||||
<style scoped>
|
||||
.text-vertical {
|
||||
writing-mode: tb;
|
||||
letter-spacing: 5px;
|
||||
}
|
||||
</style>
|
||||
11
src/components/mt-dzr/__tests__/mt-dzr.spec.ts
Normal file
@@ -0,0 +1,11 @@
|
||||
import { describe, it, expect } from 'vitest'
|
||||
|
||||
import { mount } from '@vue/test-utils'
|
||||
import HelloWorld from '../index.vue'
|
||||
|
||||
describe('HelloWorld', () => {
|
||||
it('renders properly', () => {
|
||||
const wrapper = mount(HelloWorld, { props: { msg: 'Hello Vitest' } })
|
||||
expect(wrapper.text()).toContain('Hello Vitest')
|
||||
})
|
||||
})
|
||||
5
src/components/mt-dzr/components/render-item.vue
Normal file
@@ -0,0 +1,5 @@
|
||||
<template>
|
||||
<div class="w-1/1 h-1/1 select-none">
|
||||
<slot></slot>
|
||||
</div>
|
||||
</template>
|
||||
190
src/components/mt-dzr/components/resize-handle.vue
Normal file
@@ -0,0 +1,190 @@
|
||||
<template>
|
||||
<div>
|
||||
<div
|
||||
v-for="(item, key) in points"
|
||||
:key="key"
|
||||
:id="`resize_${key}`"
|
||||
:style="item"
|
||||
class="mt-dzr-resize mt-dzr-resize-point touch-none"
|
||||
@mousedown="e => onMouseDown(e, key)"
|
||||
@touchstart.passive="e => onMouseDown(e, key)"
|
||||
></div>
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { computed, ref } from 'vue'
|
||||
import type { IDzrPropsModelValue } from '../types'
|
||||
import { dzrStore } from '../store'
|
||||
import {
|
||||
autoDestroyMouseMove,
|
||||
calcGrid,
|
||||
centerToTL,
|
||||
degToRadian,
|
||||
formatData,
|
||||
getLength,
|
||||
getNewStyle,
|
||||
getXY
|
||||
} from '../utils'
|
||||
import type { MouseTouchEvent } from '../utils/types'
|
||||
type ResizeProps = {
|
||||
itemInfo: IDzrPropsModelValue
|
||||
targetDom: HTMLElement | null
|
||||
scaleRatio: number
|
||||
gridAlignSize: number
|
||||
genId: string
|
||||
useProportionalScaling?: boolean
|
||||
}
|
||||
const resizeProps = withDefaults(defineProps<ResizeProps>(), {
|
||||
scaleRatio: 1,
|
||||
gridAlignSize: 1,
|
||||
useProportionalScaling: false
|
||||
})
|
||||
const points = computed(() => {
|
||||
return {
|
||||
tl: {
|
||||
left: '0px',
|
||||
top: '0px',
|
||||
cursor: getCursor(0)
|
||||
},
|
||||
tc: {
|
||||
left: resizeProps.itemInfo.width / 2 + 'px',
|
||||
top: '0px',
|
||||
cursor: getCursor(45)
|
||||
},
|
||||
tr: {
|
||||
left: resizeProps.itemInfo.width + 'px',
|
||||
top: '0px',
|
||||
cursor: getCursor(90)
|
||||
},
|
||||
l: {
|
||||
left: '0px',
|
||||
top: resizeProps.itemInfo.height / 2 + 'px',
|
||||
cursor: getCursor(315)
|
||||
},
|
||||
r: {
|
||||
left: resizeProps.itemInfo.width + 'px',
|
||||
top: resizeProps.itemInfo.height / 2 + 'px',
|
||||
cursor: getCursor(135)
|
||||
},
|
||||
bl: {
|
||||
left: '0px',
|
||||
top: resizeProps.itemInfo.height + 'px',
|
||||
cursor: getCursor(270)
|
||||
},
|
||||
bc: {
|
||||
left: resizeProps.itemInfo.width / 2 + 'px',
|
||||
top: resizeProps.itemInfo.height + 'px',
|
||||
cursor: getCursor(225)
|
||||
},
|
||||
br: {
|
||||
left: resizeProps.itemInfo.width + 'px',
|
||||
top: resizeProps.itemInfo.height + 'px',
|
||||
cursor: getCursor(180)
|
||||
}
|
||||
}
|
||||
})
|
||||
const angle_to_cursor = [
|
||||
{ start: 338, end: 23, cursor: 'nw' },
|
||||
{ start: 23, end: 68, cursor: 'n' },
|
||||
{ start: 68, end: 113, cursor: 'ne' },
|
||||
{ start: 293, end: 338, cursor: 'w' },
|
||||
{ start: 113, end: 158, cursor: 'e' },
|
||||
{ start: 248, end: 293, cursor: 'sw' },
|
||||
{ start: 203, end: 248, cursor: 's' },
|
||||
{ start: 158, end: 203, cursor: 'se' }
|
||||
]
|
||||
/**
|
||||
* 获取旋转之后的光标样式
|
||||
* @param init_angle 初始角度 360/8=45
|
||||
*/
|
||||
const getCursor = (init_angle: number) => {
|
||||
const now_init_angle = (init_angle + resizeProps.itemInfo.angle) % 360
|
||||
const find_cursor = angle_to_cursor.find(f => f.start <= now_init_angle && f.end > now_init_angle)
|
||||
if (!find_cursor) {
|
||||
return 'nw-resize'
|
||||
}
|
||||
return find_cursor.cursor + '-resize'
|
||||
}
|
||||
const emits = defineEmits(['update:itemInfo', 'onResizeDone', 'onResizeMove'])
|
||||
//记录原始位置
|
||||
const dzr_copy_info_value = ref({ ...resizeProps.itemInfo })
|
||||
const onMouseDown = (de: MouseTouchEvent, type: 'tl' | 'tc' | 'tr' | 'l' | 'r' | 'bl' | 'bc' | 'br') => {
|
||||
de.stopPropagation()
|
||||
dzr_copy_info_value.value = { ...resizeProps.itemInfo }
|
||||
const { clientX: de_client_x, clientY: de_client_y } = getXY(de)
|
||||
//计算组件中心点
|
||||
const { width, height, left, top } = resizeProps.itemInfo
|
||||
const centerX = left + width / 2
|
||||
const centerY = top + height / 2
|
||||
//记录原始信息和中心点
|
||||
const rect = {
|
||||
width,
|
||||
height,
|
||||
centerX,
|
||||
centerY,
|
||||
rotateAngle: resizeProps.itemInfo.angle
|
||||
}
|
||||
const onMouseMove = (me: MouseTouchEvent) => {
|
||||
me.preventDefault()
|
||||
dzrStore.showDzrCopy({ ...dzr_copy_info_value.value }, resizeProps.genId)
|
||||
const { clientX: me_client_x, clientY: me_client_y } = getXY(me)
|
||||
// 距离 网格对齐
|
||||
const delta_x = (me_client_x - de_client_x) / resizeProps.scaleRatio
|
||||
const delta_y = (me_client_y - de_client_y) / resizeProps.scaleRatio
|
||||
const alpha = Math.atan2(delta_y, delta_x)
|
||||
const delta_l = getLength(delta_x, delta_y)
|
||||
const beta = alpha - degToRadian(rect.rotateAngle)
|
||||
const deltaW = delta_l * Math.cos(beta)
|
||||
const deltaH = delta_l * Math.sin(beta)
|
||||
// 如果按shift键则等比缩放
|
||||
const ratio = resizeProps.useProportionalScaling || me.shiftKey ? rect.width / rect.height : undefined
|
||||
const {
|
||||
position: { centerX, centerY },
|
||||
size: { width, height }
|
||||
} = getNewStyle(type, { ...rect, rotateAngle: rect.rotateAngle }, deltaW, deltaH, ratio, 1, 1)
|
||||
const pData = centerToTL({
|
||||
centerX,
|
||||
centerY,
|
||||
width,
|
||||
height,
|
||||
angle: resizeProps.itemInfo.angle
|
||||
})
|
||||
const format_data = formatData(pData, centerX, centerY)
|
||||
const new_width = calcGrid(format_data.width, resizeProps.gridAlignSize)
|
||||
const new_height = calcGrid(format_data.height, resizeProps.gridAlignSize)
|
||||
emits('update:itemInfo', {
|
||||
...resizeProps.itemInfo,
|
||||
...format_data,
|
||||
left: calcGrid(format_data.left, resizeProps.gridAlignSize),
|
||||
top: calcGrid(format_data.top, resizeProps.gridAlignSize),
|
||||
width: new_width,
|
||||
height: new_height
|
||||
})
|
||||
emits('onResizeMove', {
|
||||
width: new_width,
|
||||
height: new_height
|
||||
})
|
||||
}
|
||||
autoDestroyMouseMove(onMouseMove, () => {
|
||||
dzrStore.hideDzrCopy()
|
||||
emits('onResizeDone')
|
||||
})
|
||||
}
|
||||
</script>
|
||||
<style scoped lang="less">
|
||||
.mt-dzr-resize {
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
.mt-dzr-resize-point {
|
||||
position: absolute;
|
||||
background: #fff;
|
||||
border: 1px solid #59c7f9;
|
||||
width: 8px;
|
||||
height: 8px;
|
||||
margin-left: -4px;
|
||||
margin-top: -4px;
|
||||
border-radius: 50%;
|
||||
z-index: 1;
|
||||
}
|
||||
</style>
|
||||
86
src/components/mt-dzr/components/rotate-handle.vue
Normal file
@@ -0,0 +1,86 @@
|
||||
<template>
|
||||
<div class="mt-dzr-rotate touch-none" @mousedown="onMouseDown" @touchstart.passive="onMouseDown">
|
||||
<svg viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg">
|
||||
<path
|
||||
d="M929 849a30 30 0 0 1-30-30v-83.137a447.514 447.514 0 0 1-70.921 92.209C722.935 933.225 578.442 975.008 442 953.482a444.917 444.917 0 0 1-241.139-120.591 30 30 0 1 1 37.258-47.01l0.231-0.231A385.175 385.175 0 0 0 442 892.625v-0.006c120.855 22.123 250.206-13.519 343.656-106.975a386.646 386.646 0 0 0 70.6-96.653h-87.247a30 30 0 0 1 0-60H929a30 30 0 0 1 30 30V819a30 30 0 0 1-30 30zM512 392a120 120 0 1 1-120 120 120 120 0 0 1 120-120z m293.005-147.025a29.87 29.87 0 0 1-19.117-6.882l-0.232 0.231A386.5 386.5 0 0 0 689.478 168h-0.011c-145.646-75.182-329.021-51.747-451.117 70.35a386.615 386.615 0 0 0-70.6 96.65H255a30 30 0 0 1 0 60H95a30 30 0 0 1-30-30V205a30 30 0 0 1 60 0v83.129a447.534 447.534 0 0 1 70.923-92.206C317.981 73.866 493.048 37.2 647 85.836v-0.045a444.883 444.883 0 0 1 176.143 105.291 30 30 0 0 1-18.138 53.893z"
|
||||
fill="#06B7FF"
|
||||
></path>
|
||||
</svg>
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { ref } from 'vue'
|
||||
import { dzrStore } from '../store'
|
||||
import type { IDzrPropsModelValue } from '../types'
|
||||
import { alignToGrid, autoDestroyMouseMove, getXY } from '../utils'
|
||||
import type { MouseTouchEvent } from '../utils/types'
|
||||
type RotateProps = {
|
||||
itemInfo: IDzrPropsModelValue
|
||||
targetDom: HTMLElement | null
|
||||
genId: string
|
||||
}
|
||||
const rotateProps = withDefaults(defineProps<RotateProps>(), {})
|
||||
const emits = defineEmits(['update:itemInfo', 'onRotateDone', 'onRotateMove'])
|
||||
//记录原始位置
|
||||
const dzr_copy_info_value = ref({ ...rotateProps.itemInfo })
|
||||
const is_mouse_down = ref(false)
|
||||
const onMouseDown = (de: MouseTouchEvent) => {
|
||||
de.stopPropagation()
|
||||
if (!rotateProps.targetDom) {
|
||||
console.error('target_dom is null')
|
||||
return
|
||||
}
|
||||
const target_dom_rect = rotateProps.targetDom.getBoundingClientRect()
|
||||
if (!target_dom_rect) {
|
||||
console.error('boundingClientRect is null')
|
||||
return
|
||||
}
|
||||
const { clientX: de_client_x, clientY: de_client_y } = getXY(de)
|
||||
dzr_copy_info_value.value = { ...rotateProps.itemInfo }
|
||||
dzrStore.hideDzrCopy()
|
||||
//记录旋转前的初始值
|
||||
const init_angle = rotateProps.itemInfo.angle
|
||||
//计算组件中心点位置
|
||||
const center_x = target_dom_rect.left + target_dom_rect.width / 2
|
||||
const center_y = target_dom_rect.top + target_dom_rect.height / 2
|
||||
is_mouse_down.value = true
|
||||
const onMouseMove = (me: MouseTouchEvent) => {
|
||||
if (!is_mouse_down.value) {
|
||||
return
|
||||
}
|
||||
const { clientX: me_client_x, clientY: me_client_y } = getXY(me)
|
||||
dzrStore.showDzrCopy({ ...dzr_copy_info_value.value }, rotateProps.genId)
|
||||
// 旋转前的角度
|
||||
const rotate_before = Math.atan2(de_client_y - center_y, de_client_x - center_x) / (Math.PI / 180)
|
||||
// 旋转后的角度
|
||||
const rotate_after = Math.atan2(me_client_y - center_y, me_client_x - center_x) / (Math.PI / 180)
|
||||
const new_angle = alignToGrid(init_angle + rotate_after - rotate_before)
|
||||
emits('update:itemInfo', {
|
||||
...rotateProps.itemInfo,
|
||||
left: alignToGrid(rotateProps.itemInfo.left),
|
||||
top: alignToGrid(rotateProps.itemInfo.top),
|
||||
angle: new_angle
|
||||
})
|
||||
emits('onRotateMove', {
|
||||
angle: new_angle
|
||||
})
|
||||
}
|
||||
autoDestroyMouseMove(onMouseMove, () => {
|
||||
dzrStore.hideDzrCopy()
|
||||
is_mouse_down.value = false
|
||||
emits('onRotateDone')
|
||||
})
|
||||
}
|
||||
</script>
|
||||
<style scoped lang="less">
|
||||
.mt-dzr-rotate {
|
||||
position: absolute;
|
||||
cursor: grab;
|
||||
left: 50%;
|
||||
top: 0;
|
||||
transform: translate(-50%, -160%);
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
font-size: 20px;
|
||||
}
|
||||
</style>
|
||||
0
src/components/mt-dzr/composables/mouse.ts
Normal file
3
src/components/mt-dzr/index.ts
Normal file
@@ -0,0 +1,3 @@
|
||||
import MtDzr from './index.vue'
|
||||
|
||||
export default MtDzr
|
||||
276
src/components/mt-dzr/index.vue
Normal file
@@ -0,0 +1,276 @@
|
||||
<template>
|
||||
<div
|
||||
class="absolute select-none opacity-30"
|
||||
v-if="dzrStore.dzr_copy_info.show && dzrStore.dzr_copy_info.gen_id == gen_id && MtDzrProps.showGhostDom"
|
||||
style="outline: 1px solid #06b7ff"
|
||||
:style="getStyle(dzrStore.dzr_copy_info.value)"
|
||||
>
|
||||
<render-item>
|
||||
<slot></slot>
|
||||
</render-item>
|
||||
</div>
|
||||
<div
|
||||
v-if="!MtDzrProps.hide"
|
||||
:id="MtDzrProps.id"
|
||||
ref="dzrRef"
|
||||
:class="`${MtDzrProps.class} absolute select-none touch-none ${MtDzrProps.lock ? 'opacity-50' : ''} ${
|
||||
MtDzrProps.active && MtDzrProps.modelValue.width != 0 && MtDzrProps.modelValue.height != 0
|
||||
? 'dzr-active'
|
||||
: ''
|
||||
}`"
|
||||
@mousedown="onMouseDown"
|
||||
@touchstart.passive="onMouseDown"
|
||||
@mouseenter="onMouseEnter"
|
||||
@mouseleave="onMouseLeave"
|
||||
@click.right.prevent="onRightClick"
|
||||
:style="getStyle(drag_data_info)"
|
||||
>
|
||||
<render-item>
|
||||
<slot></slot>
|
||||
</render-item>
|
||||
<div v-if="MtDzrProps.resize && !MtDzrProps.lock && MtDzrProps.active && !MtDzrProps.disabled">
|
||||
<resize-handle
|
||||
v-model:item-info="mt_dzr_vmodel"
|
||||
:target-dom="dzrRef"
|
||||
:scale-ratio="MtDzrProps.scaleRatio"
|
||||
:grid-align-size="grid_align_size"
|
||||
:gen-id="gen_id"
|
||||
:use-proportional-scaling="MtDzrProps.useProportionalScaling"
|
||||
@on-resize-done="onResizeDone"
|
||||
@on-resize-move="val => onResizeMove(val)"
|
||||
></resize-handle>
|
||||
</div>
|
||||
<rotate-handle
|
||||
v-if="MtDzrProps.rotate && !MtDzrProps.lock && MtDzrProps.active && !MtDzrProps.disabled"
|
||||
v-model:item-info="mt_dzr_vmodel"
|
||||
:target-dom="dzrRef"
|
||||
:gen-id="gen_id"
|
||||
@on-rotate-done="onRotateDone"
|
||||
@on-rotate-move="val => onRotateMove(val)"
|
||||
></rotate-handle>
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { computed, nextTick, ref, watch } from 'vue'
|
||||
import { type IDzrProps, type IDzrPropsModelValue } from './types'
|
||||
import { alignToGrid, autoDestroyMouseMove, getXY, randomString } from './utils/index'
|
||||
import ResizeHandle from './components/resize-handle.vue'
|
||||
import RotateHandle from './components/rotate-handle.vue'
|
||||
import renderItem from './components/render-item.vue'
|
||||
import { dzrStore } from './store/index'
|
||||
import type { MouseTouchEvent } from './utils/types'
|
||||
const MtDzrProps = withDefaults(defineProps<IDzrProps>(), {
|
||||
id: randomString(16),
|
||||
modelValue: () => {
|
||||
return {
|
||||
left: 0,
|
||||
top: 0,
|
||||
width: 0,
|
||||
height: 0,
|
||||
angle: 0
|
||||
}
|
||||
},
|
||||
scaleRatio: 1,
|
||||
grid: () => {
|
||||
return {
|
||||
enabled: false,
|
||||
align: false,
|
||||
size: 10
|
||||
}
|
||||
},
|
||||
resize: true,
|
||||
rotate: true,
|
||||
lock: false,
|
||||
active: false,
|
||||
useProportionalScaling: false,
|
||||
showGhostDom: true,
|
||||
hide: false,
|
||||
disabled: false,
|
||||
adsorp_diff: () => {
|
||||
return {
|
||||
x: 0,
|
||||
y: 0
|
||||
}
|
||||
}
|
||||
})
|
||||
const MtDzrEmits = defineEmits([
|
||||
'update:modelValue',
|
||||
'mousedown',
|
||||
'onItemMove',
|
||||
'moveMouseUp',
|
||||
'onMouseEnter',
|
||||
'onMouseLeave',
|
||||
'onResizeMove',
|
||||
'onResizeDone',
|
||||
'onRotateDone',
|
||||
'onRightClick',
|
||||
'onRotateMove'
|
||||
])
|
||||
const dzrRef = ref()
|
||||
//
|
||||
const gen_id = randomString(16)
|
||||
|
||||
//记录原始位置
|
||||
const dzr_copy_info_value = ref({ ...MtDzrProps.modelValue })
|
||||
// 拖拽数据
|
||||
const drag_data_info = ref({
|
||||
...MtDzrProps.modelValue
|
||||
})
|
||||
const getStyle = (data: IDzrPropsModelValue) => {
|
||||
const { width, height, left, top, angle } = data
|
||||
return {
|
||||
width: width + 'px',
|
||||
height: height + 'px',
|
||||
left: left + 'px',
|
||||
top: top + 'px',
|
||||
transform: `rotate(${angle}deg)`
|
||||
}
|
||||
}
|
||||
|
||||
//如果网格关闭或者没有开启网格对齐,网格大小为1
|
||||
const grid_align_size = computed(() => (!MtDzrProps.grid.align || !MtDzrProps.grid.enabled ? 1 : MtDzrProps.grid.size))
|
||||
const mt_dzr_vmodel = computed({
|
||||
get: () => drag_data_info.value,
|
||||
set: value => {
|
||||
drag_data_info.value = value
|
||||
MtDzrEmits('update:modelValue', value)
|
||||
}
|
||||
})
|
||||
const onMouseDown = (de: MouseTouchEvent) => {
|
||||
MtDzrEmits('mousedown', de)
|
||||
if (MtDzrProps.lock || MtDzrProps.disabled) {
|
||||
return
|
||||
}
|
||||
//记录最开始点击时鼠标位置和组件的位置
|
||||
const { clientX: de_client_x, clientY: de_client_y } = getXY(de)
|
||||
dzr_copy_info_value.value = { ...MtDzrProps.modelValue }
|
||||
drag_data_info.value = {
|
||||
...MtDzrProps.modelValue
|
||||
}
|
||||
dzrStore.hideDzrCopy()
|
||||
const { left: init_x, top: init_y } = MtDzrProps.modelValue
|
||||
//计算xy轴最小坐标和最大坐标,不要超出父元素
|
||||
const { clientWidth, clientHeight } = dzrRef.value.parentElement
|
||||
const min_left = 0
|
||||
const min_top = 0
|
||||
const max_left = clientWidth - MtDzrProps.modelValue.width
|
||||
const max_top = clientHeight - MtDzrProps.modelValue.height
|
||||
let set_new_left = init_x
|
||||
let set_new_top = init_y
|
||||
const onMouseMove = (me: MouseTouchEvent) => {
|
||||
dzrStore.showDzrCopy({ ...dzr_copy_info_value.value }, gen_id)
|
||||
const { clientX: me_client_x, clientY: me_client_y } = getXY(me)
|
||||
const move_x = (me_client_x - de_client_x) / MtDzrProps.scaleRatio
|
||||
const move_y = (me_client_y - de_client_y) / MtDzrProps.scaleRatio
|
||||
|
||||
const new_left = alignToGrid(init_x + move_x, grid_align_size.value)
|
||||
const new_top = alignToGrid(init_y + move_y, grid_align_size.value)
|
||||
set_new_left = new_left < min_left ? min_left : new_left > max_left ? max_left : new_left
|
||||
set_new_top = new_top < min_top ? min_top : new_top > max_top ? max_top : new_top
|
||||
drag_data_info.value = {
|
||||
...drag_data_info.value,
|
||||
left: set_new_left,
|
||||
top: set_new_top
|
||||
}
|
||||
MtDzrEmits('onItemMove', {
|
||||
move_length: {
|
||||
x: new_left - init_x,
|
||||
y: new_top - init_y
|
||||
},
|
||||
new_lt: {
|
||||
left: set_new_left,
|
||||
top: set_new_top
|
||||
},
|
||||
// 因为是鼠标松开的时候才更新组件数据,所以这里需要把组件的实时binfo返回回去
|
||||
move_binfo: {
|
||||
id: MtDzrProps.id,
|
||||
left: set_new_left,
|
||||
top: set_new_top,
|
||||
width: drag_data_info.value.width,
|
||||
height: drag_data_info.value.height,
|
||||
angle: drag_data_info.value.angle
|
||||
}
|
||||
})
|
||||
nextTick(() => {
|
||||
const adsorp_diff_x = MtDzrProps.adsorp_diff?.x ?? 0
|
||||
const adsorp_diff_y = MtDzrProps.adsorp_diff?.y ?? 0
|
||||
// 当视图渲染之后 根据需要吸附的距离更新数据
|
||||
if (adsorp_diff_x == 0 && adsorp_diff_y == 0) {
|
||||
return
|
||||
}
|
||||
set_new_left += adsorp_diff_x
|
||||
set_new_top += adsorp_diff_y
|
||||
drag_data_info.value = {
|
||||
...drag_data_info.value,
|
||||
left: set_new_left,
|
||||
top: set_new_top
|
||||
}
|
||||
MtDzrEmits('onItemMove', {
|
||||
new_lt: {
|
||||
left: set_new_left,
|
||||
top: set_new_top
|
||||
},
|
||||
// 因为是鼠标松开的时候才更新组件数据,所以这里需要把组件的实时binfo返回回去
|
||||
move_binfo: {
|
||||
id: MtDzrProps.id,
|
||||
left: set_new_left,
|
||||
top: set_new_top,
|
||||
width: drag_data_info.value.width,
|
||||
height: drag_data_info.value.height,
|
||||
angle: drag_data_info.value.angle
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
autoDestroyMouseMove(onMouseMove, () => {
|
||||
nextTick(() => {
|
||||
dzrStore.hideDzrCopy()
|
||||
MtDzrEmits('moveMouseUp')
|
||||
MtDzrEmits('update:modelValue', {
|
||||
...MtDzrProps.modelValue,
|
||||
left: set_new_left,
|
||||
top: set_new_top
|
||||
})
|
||||
})
|
||||
})
|
||||
}
|
||||
const onMouseEnter = (e: MouseEvent) => {
|
||||
MtDzrEmits('onMouseEnter', e)
|
||||
}
|
||||
const onMouseLeave = (e: MouseEvent) => {
|
||||
MtDzrEmits('onMouseLeave', e)
|
||||
}
|
||||
const onResizeMove = (val: any) => {
|
||||
MtDzrEmits('onResizeMove', val)
|
||||
}
|
||||
const onResizeDone = () => {
|
||||
MtDzrEmits('onResizeDone')
|
||||
}
|
||||
const onRotateDone = () => {
|
||||
MtDzrEmits('onRotateDone')
|
||||
}
|
||||
const onRotateMove = (val: any) => {
|
||||
MtDzrEmits('onRotateMove', val)
|
||||
}
|
||||
const onRightClick = (e: MouseEvent) => {
|
||||
MtDzrEmits('onRightClick', e)
|
||||
}
|
||||
watch(
|
||||
() => MtDzrProps.modelValue,
|
||||
value => {
|
||||
drag_data_info.value = value
|
||||
},
|
||||
{
|
||||
deep: true
|
||||
}
|
||||
)
|
||||
</script>
|
||||
<style scoped>
|
||||
.dzr {
|
||||
position: absolute;
|
||||
user-select: none;
|
||||
}
|
||||
.dzr-active {
|
||||
outline: 1px solid #06b7ff;
|
||||
}
|
||||
</style>
|
||||
34
src/components/mt-dzr/store/index.ts
Normal file
@@ -0,0 +1,34 @@
|
||||
import { reactive } from 'vue'
|
||||
import type { IDzrCopyInfo, IDzrStore } from './types'
|
||||
import type { IDzrPropsModelValue } from '../types'
|
||||
|
||||
export const dzrStore: IDzrStore = reactive({
|
||||
dzr_copy_info: {
|
||||
gen_id: '',
|
||||
show: false,
|
||||
value: {
|
||||
left: 0,
|
||||
top: 0,
|
||||
width: 0,
|
||||
height: 0,
|
||||
angle: 0
|
||||
}
|
||||
},
|
||||
setDzrCopyInfo: (value: IDzrCopyInfo) => {
|
||||
dzrStore.dzr_copy_info = value
|
||||
},
|
||||
showDzrCopy: (value: IDzrPropsModelValue, gen_id: string) => {
|
||||
dzrStore.setDzrCopyInfo({
|
||||
...dzrStore.dzr_copy_info,
|
||||
show: true,
|
||||
value,
|
||||
gen_id
|
||||
})
|
||||
},
|
||||
hideDzrCopy: () => {
|
||||
dzrStore.setDzrCopyInfo({
|
||||
...dzrStore.dzr_copy_info,
|
||||
show: false
|
||||
})
|
||||
}
|
||||
})
|
||||
13
src/components/mt-dzr/store/types.ts
Normal file
@@ -0,0 +1,13 @@
|
||||
import type { IDzrPropsModelValue } from '../types'
|
||||
|
||||
export interface IDzrStore {
|
||||
dzr_copy_info: IDzrCopyInfo
|
||||
setDzrCopyInfo: (value: IDzrCopyInfo) => void
|
||||
showDzrCopy: (value: IDzrPropsModelValue, gen_id: string) => void
|
||||
hideDzrCopy: () => void
|
||||
}
|
||||
export interface IDzrCopyInfo {
|
||||
gen_id: string
|
||||
show: boolean
|
||||
value: IDzrPropsModelValue
|
||||
}
|
||||
31
src/components/mt-dzr/types.ts
Normal file
@@ -0,0 +1,31 @@
|
||||
export interface IDzrProps {
|
||||
id: string
|
||||
modelValue: IDzrPropsModelValue //位置和大小
|
||||
scaleRatio?: number //画布缩放倍数
|
||||
hide: boolean //隐藏
|
||||
grid?: IDzrPropsGrid //网格配置
|
||||
resize?: boolean //开启缩放
|
||||
rotate?: boolean //开启旋转
|
||||
lock?: boolean //锁定
|
||||
active?: boolean //激活
|
||||
useProportionalScaling?: boolean //开启等比例缩放
|
||||
showGhostDom?: boolean //是否显示幽灵dom
|
||||
class?: string //
|
||||
disabled: boolean //是否禁用
|
||||
adsorp_diff?: {
|
||||
x: number
|
||||
y: number
|
||||
}
|
||||
}
|
||||
export interface IDzrPropsModelValue {
|
||||
left: number
|
||||
top: number
|
||||
width: number
|
||||
height: number
|
||||
angle: number
|
||||
}
|
||||
export interface IDzrPropsGrid {
|
||||
enabled: boolean //开启网格
|
||||
align: boolean //对齐到网格
|
||||
size: number //网格大小
|
||||
}
|
||||
349
src/components/mt-dzr/utils/index.ts
Normal file
@@ -0,0 +1,349 @@
|
||||
import type { IDzrPropsModelValue } from '../types'
|
||||
import type { MouseTouchEvent } from './types'
|
||||
|
||||
/**
|
||||
* 会自动销毁的鼠标移动事件
|
||||
* @param onMousemove
|
||||
*/
|
||||
export const autoDestroyMouseMove = (onMousemove: (e: MouseTouchEvent) => void, mouseUpCallBack?: () => void) => {
|
||||
const onMouseup = () => {
|
||||
document.removeEventListener('mousemove', onMousemove)
|
||||
document.removeEventListener('touchmove', onMousemove)
|
||||
document.removeEventListener('mouseup', onMouseup)
|
||||
document.removeEventListener('touchend', onMouseup)
|
||||
document.removeEventListener('mouseleave', onMouseup)
|
||||
if (mouseUpCallBack) {
|
||||
mouseUpCallBack()
|
||||
}
|
||||
}
|
||||
document.addEventListener('mousemove', onMousemove)
|
||||
document.addEventListener('touchmove', onMousemove)
|
||||
document.addEventListener('mouseup', onMouseup)
|
||||
document.addEventListener('touchend', onMouseup)
|
||||
document.addEventListener('mouseleave', onMouseup)
|
||||
}
|
||||
/**
|
||||
* 根据坐标对齐到网格
|
||||
* @param position 当前坐标
|
||||
* @param grid 网格大小
|
||||
* @returns 对应网格的坐标
|
||||
*/
|
||||
export const alignToGrid = (position: number, grid = 1) => {
|
||||
const integerPart = Math.floor(position / grid)
|
||||
const fractionalPart = position % grid
|
||||
|
||||
if (fractionalPart >= grid / 2) {
|
||||
return (integerPart + 1) * grid
|
||||
} else {
|
||||
return integerPart * grid
|
||||
}
|
||||
}
|
||||
/** 根据移动的距离对齐到网格
|
||||
* @param diff 移动的距离
|
||||
* @param grid 网格大小
|
||||
*/
|
||||
export const calcGrid = (diff: number, grid = 1) => {
|
||||
// 得到每次缩放的余数
|
||||
const r = Math.abs(diff) % grid
|
||||
|
||||
// 正负grid
|
||||
const mulGrid = diff > 0 ? grid : -grid
|
||||
let result = 0
|
||||
// 余数大于grid的1/2
|
||||
if (r > grid / 2) {
|
||||
result = mulGrid * Math.ceil(Math.abs(diff) / grid)
|
||||
} else {
|
||||
result = mulGrid * Math.floor(Math.abs(diff) / grid)
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
/**
|
||||
* 获取当前点击坐标 根据pc端和移动端获取
|
||||
* @param e
|
||||
* @returns
|
||||
*/
|
||||
export function getXY(e: MouseTouchEvent) {
|
||||
let clientX = 0,
|
||||
clientY = 0
|
||||
if (isTouchEvent(e)) {
|
||||
const touch = e.targetTouches[0]
|
||||
clientX = touch.pageX
|
||||
clientY = touch.pageY
|
||||
} else {
|
||||
clientX = e.clientX
|
||||
clientY = e.clientY
|
||||
}
|
||||
|
||||
return { clientX, clientY }
|
||||
}
|
||||
|
||||
function isTouchEvent(val: unknown): val is TouchEvent {
|
||||
const typeStr = Object.prototype.toString.call(val)
|
||||
return typeStr.substring(8, typeStr.length - 1) === 'TouchEvent'
|
||||
}
|
||||
|
||||
export const getLength = (x: number, y: number) => Math.sqrt(x * x + y * y)
|
||||
|
||||
export const degToRadian = (deg: number) => (deg * Math.PI) / 180
|
||||
const cos = (deg: number) => Math.cos(degToRadian(deg))
|
||||
const sin = (deg: number) => Math.sin(degToRadian(deg))
|
||||
/**
|
||||
* 计算并返回给定类型变换的新样式。
|
||||
*
|
||||
* @param {string} type - 变换的类型。
|
||||
* @param {any} rect - 矩形对象。
|
||||
* @param {number} deltaW - 宽度变化。
|
||||
* @param {number} deltaH - 高度变化。
|
||||
* @param {number | undefined} ratio - 比例。
|
||||
* @param {number} minWidth - 最小宽度。
|
||||
* @param {number} minHeight - 最小高度。
|
||||
* @returns {Object} 矩形的新位置和大小。
|
||||
*/
|
||||
export const getNewStyle = (
|
||||
type: string,
|
||||
rect: any,
|
||||
deltaW: number,
|
||||
deltaH: number,
|
||||
ratio: number | undefined,
|
||||
minWidth: number,
|
||||
minHeight: number
|
||||
) => {
|
||||
// eslint-disable-next-line prefer-const
|
||||
let { width, height, centerX, centerY, rotateAngle } = rect
|
||||
const widthFlag = width < 0 ? -1 : 1
|
||||
const heightFlag = height < 0 ? -1 : 1
|
||||
width = Math.abs(width)
|
||||
height = Math.abs(height)
|
||||
switch (type) {
|
||||
case 'r': {
|
||||
const widthAndDeltaW = setWidthAndDeltaW(width, deltaW, minWidth)
|
||||
width = widthAndDeltaW.width
|
||||
deltaW = widthAndDeltaW.deltaW
|
||||
if (ratio) {
|
||||
deltaH = deltaW / ratio
|
||||
height = width / ratio
|
||||
// 左上角固定
|
||||
centerX += (deltaW / 2) * cos(rotateAngle) - (deltaH / 2) * sin(rotateAngle)
|
||||
centerY += (deltaW / 2) * sin(rotateAngle) + (deltaH / 2) * cos(rotateAngle)
|
||||
} else {
|
||||
// 左边固定
|
||||
centerX += (deltaW / 2) * cos(rotateAngle)
|
||||
centerY += (deltaW / 2) * sin(rotateAngle)
|
||||
}
|
||||
break
|
||||
}
|
||||
case 'tr': {
|
||||
deltaH = -deltaH
|
||||
const widthAndDeltaW = setWidthAndDeltaW(width, deltaW, minWidth)
|
||||
width = widthAndDeltaW.width
|
||||
deltaW = widthAndDeltaW.deltaW
|
||||
const heightAndDeltaH = setHeightAndDeltaH(height, deltaH, minHeight)
|
||||
height = heightAndDeltaH.height
|
||||
deltaH = heightAndDeltaH.deltaH
|
||||
if (ratio) {
|
||||
deltaW = deltaH * ratio
|
||||
width = height * ratio
|
||||
}
|
||||
centerX += (deltaW / 2) * cos(rotateAngle) + (deltaH / 2) * sin(rotateAngle)
|
||||
centerY += (deltaW / 2) * sin(rotateAngle) - (deltaH / 2) * cos(rotateAngle)
|
||||
break
|
||||
}
|
||||
case 'br': {
|
||||
const widthAndDeltaW = setWidthAndDeltaW(width, deltaW, minWidth)
|
||||
width = widthAndDeltaW.width
|
||||
deltaW = widthAndDeltaW.deltaW
|
||||
const heightAndDeltaH = setHeightAndDeltaH(height, deltaH, minHeight)
|
||||
height = heightAndDeltaH.height
|
||||
deltaH = heightAndDeltaH.deltaH
|
||||
if (ratio) {
|
||||
deltaW = deltaH * ratio
|
||||
width = height * ratio
|
||||
}
|
||||
centerX += (deltaW / 2) * cos(rotateAngle) - (deltaH / 2) * sin(rotateAngle)
|
||||
centerY += (deltaW / 2) * sin(rotateAngle) + (deltaH / 2) * cos(rotateAngle)
|
||||
break
|
||||
}
|
||||
case 'bc': {
|
||||
const heightAndDeltaH = setHeightAndDeltaH(height, deltaH, minHeight)
|
||||
height = heightAndDeltaH.height
|
||||
deltaH = heightAndDeltaH.deltaH
|
||||
if (ratio) {
|
||||
deltaW = deltaH * ratio
|
||||
width = height * ratio
|
||||
// 左上角固定
|
||||
centerX += (deltaW / 2) * cos(rotateAngle) - (deltaH / 2) * sin(rotateAngle)
|
||||
centerY += (deltaW / 2) * sin(rotateAngle) + (deltaH / 2) * cos(rotateAngle)
|
||||
} else {
|
||||
// 上边固定
|
||||
centerX -= (deltaH / 2) * sin(rotateAngle)
|
||||
centerY += (deltaH / 2) * cos(rotateAngle)
|
||||
}
|
||||
break
|
||||
}
|
||||
case 'bl': {
|
||||
deltaW = -deltaW
|
||||
const widthAndDeltaW = setWidthAndDeltaW(width, deltaW, minWidth)
|
||||
width = widthAndDeltaW.width
|
||||
deltaW = widthAndDeltaW.deltaW
|
||||
const heightAndDeltaH = setHeightAndDeltaH(height, deltaH, minHeight)
|
||||
height = heightAndDeltaH.height
|
||||
deltaH = heightAndDeltaH.deltaH
|
||||
if (ratio) {
|
||||
height = width / ratio
|
||||
deltaH = deltaW / ratio
|
||||
}
|
||||
centerX -= (deltaW / 2) * cos(rotateAngle) + (deltaH / 2) * sin(rotateAngle)
|
||||
centerY -= (deltaW / 2) * sin(rotateAngle) - (deltaH / 2) * cos(rotateAngle)
|
||||
break
|
||||
}
|
||||
case 'l': {
|
||||
deltaW = -deltaW
|
||||
const widthAndDeltaW = setWidthAndDeltaW(width, deltaW, minWidth)
|
||||
width = widthAndDeltaW.width
|
||||
deltaW = widthAndDeltaW.deltaW
|
||||
if (ratio) {
|
||||
height = width / ratio
|
||||
deltaH = deltaW / ratio
|
||||
// 右上角固定
|
||||
centerX -= (deltaW / 2) * cos(rotateAngle) + (deltaH / 2) * sin(rotateAngle)
|
||||
centerY -= (deltaW / 2) * sin(rotateAngle) - (deltaH / 2) * cos(rotateAngle)
|
||||
} else {
|
||||
// 右边固定
|
||||
centerX -= (deltaW / 2) * cos(rotateAngle)
|
||||
centerY -= (deltaW / 2) * sin(rotateAngle)
|
||||
}
|
||||
break
|
||||
}
|
||||
case 'tl': {
|
||||
deltaW = -deltaW
|
||||
deltaH = -deltaH
|
||||
const widthAndDeltaW = setWidthAndDeltaW(width, deltaW, minWidth)
|
||||
width = widthAndDeltaW.width
|
||||
deltaW = widthAndDeltaW.deltaW
|
||||
const heightAndDeltaH = setHeightAndDeltaH(height, deltaH, minHeight)
|
||||
height = heightAndDeltaH.height
|
||||
deltaH = heightAndDeltaH.deltaH
|
||||
if (ratio) {
|
||||
width = height * ratio
|
||||
deltaW = deltaH * ratio
|
||||
}
|
||||
centerX -= (deltaW / 2) * cos(rotateAngle) - (deltaH / 2) * sin(rotateAngle)
|
||||
centerY -= (deltaW / 2) * sin(rotateAngle) + (deltaH / 2) * cos(rotateAngle)
|
||||
break
|
||||
}
|
||||
case 'tc': {
|
||||
deltaH = -deltaH
|
||||
const heightAndDeltaH = setHeightAndDeltaH(height, deltaH, minHeight)
|
||||
height = heightAndDeltaH.height
|
||||
deltaH = heightAndDeltaH.deltaH
|
||||
if (ratio) {
|
||||
width = height * ratio
|
||||
deltaW = deltaH * ratio
|
||||
// 左下角固定
|
||||
centerX += (deltaW / 2) * cos(rotateAngle) + (deltaH / 2) * sin(rotateAngle)
|
||||
centerY += (deltaW / 2) * sin(rotateAngle) - (deltaH / 2) * cos(rotateAngle)
|
||||
} else {
|
||||
centerX += (deltaH / 2) * sin(rotateAngle)
|
||||
centerY -= (deltaH / 2) * cos(rotateAngle)
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
position: {
|
||||
centerX,
|
||||
centerY
|
||||
},
|
||||
size: {
|
||||
width: width * widthFlag,
|
||||
height: height * heightFlag
|
||||
}
|
||||
}
|
||||
}
|
||||
/**
|
||||
* 根据给定的参数设置高度和 deltaH 值。
|
||||
*
|
||||
* @param {number} height - 当前的高度值。
|
||||
* @param {number} deltaH - 高度变化值。
|
||||
* @param {number} minHeight - 最小高度值。
|
||||
* @return {object} - 包含更新后的高度和 deltaH 值的对象。
|
||||
*/
|
||||
const setHeightAndDeltaH = (height: number, deltaH: number, minHeight: number) => {
|
||||
const expectedHeight = height + deltaH
|
||||
if (expectedHeight > minHeight) {
|
||||
height = expectedHeight
|
||||
} else {
|
||||
deltaH = minHeight - height
|
||||
height = minHeight
|
||||
}
|
||||
return { height, deltaH }
|
||||
}
|
||||
/**
|
||||
* 设置元素的宽度和deltaW值。
|
||||
*
|
||||
* @param {number} width - 元素的当前宽度。
|
||||
* @param {number} deltaW - 元素宽度的变化量。
|
||||
* @param {number} minWidth - 元素的最小宽度。
|
||||
* @return {Object} - 包含更新后的宽度和deltaW值的对象。
|
||||
*/
|
||||
const setWidthAndDeltaW = (width: number, deltaW: number, minWidth: number) => {
|
||||
const expectedWidth = width + deltaW
|
||||
if (expectedWidth > minWidth) {
|
||||
width = expectedWidth
|
||||
} else {
|
||||
deltaW = minWidth - width
|
||||
width = minWidth
|
||||
}
|
||||
return { width, deltaW }
|
||||
}
|
||||
/**
|
||||
* 根据矩形的中心坐标、尺寸和角度计算左上角的位置。
|
||||
*
|
||||
* @param {object} params - 计算的参数。
|
||||
* @param {number} params.centerX - 矩形的中心点的 x 坐标。
|
||||
* @param {number} params.centerY - 矩形的中心点的 y 坐标。
|
||||
* @param {number} params.width - 矩形的宽度。
|
||||
* @param {number} params.height - 矩形的高度。
|
||||
* @param {number} params.angle - 矩形的旋转角度。
|
||||
* @return {object} - 矩形的左上角位置。
|
||||
*/
|
||||
export const centerToTL = ({ centerX, centerY, width, height, angle }: any): IDzrPropsModelValue => ({
|
||||
top: centerY - height / 2,
|
||||
left: centerX - width / 2,
|
||||
width,
|
||||
height,
|
||||
angle
|
||||
})
|
||||
/**
|
||||
* 格式化数据并返回一个包含更新后尺寸和位置的对象。
|
||||
*
|
||||
* @param {IDzrPropsModelValue} data - 包含宽度和高度的数据。
|
||||
* @param {number} centerX - 中心点的x坐标。
|
||||
* @param {number} centerY - 中心点的y坐标。
|
||||
* @return {object} - 一个包含更新后尺寸和位置的对象。
|
||||
*/
|
||||
export const formatData = (data: IDzrPropsModelValue, centerX: number, centerY: number) => {
|
||||
const { width, height } = data
|
||||
return {
|
||||
width: Math.abs(width),
|
||||
height: Math.abs(height),
|
||||
left: centerX - Math.abs(width) / 2,
|
||||
top: centerY - Math.abs(height) / 2
|
||||
}
|
||||
}
|
||||
/**
|
||||
* 生成随机字符串
|
||||
* @param len 生成个数
|
||||
*/
|
||||
export const randomString = (len?: number) => {
|
||||
len = len || 10
|
||||
const str = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'
|
||||
const maxPos = str.length
|
||||
let random_str = ''
|
||||
for (let i = 0; i < len; i++) {
|
||||
random_str += str.charAt(Math.floor(Math.random() * maxPos))
|
||||
}
|
||||
return random_str
|
||||
}
|
||||
1
src/components/mt-dzr/utils/types.ts
Normal file
@@ -0,0 +1 @@
|
||||
export type MouseTouchEvent = MouseEvent | TouchEvent
|
||||
78
src/components/mt-edit/ace-edit.ts
Normal file
@@ -0,0 +1,78 @@
|
||||
import ace from 'ace-builds'
|
||||
|
||||
import themeMonokaiUrl from 'ace-builds/src-noconflict/theme-monokai?url'
|
||||
ace.config.setModuleUrl('ace/theme/monokai', themeMonokaiUrl)
|
||||
|
||||
import workerBaseUrl from 'ace-builds/src-noconflict/worker-base?url'
|
||||
ace.config.setModuleUrl('ace/mode/base', workerBaseUrl)
|
||||
|
||||
import modeJsonUrl from 'ace-builds/src-noconflict/mode-json?url'
|
||||
ace.config.setModuleUrl('ace/mode/json', modeJsonUrl)
|
||||
import workerJsonUrl from 'ace-builds/src-noconflict/worker-json?url'
|
||||
ace.config.setModuleUrl('ace/mode/json_worker', workerJsonUrl)
|
||||
import snippetsJsonUrl from 'ace-builds/src-noconflict/snippets/json?url'
|
||||
ace.config.setModuleUrl('ace/snippets/json', snippetsJsonUrl)
|
||||
|
||||
import modeJavascriptUrl from 'ace-builds/src-noconflict/mode-javascript?url'
|
||||
ace.config.setModuleUrl('ace/mode/javascript', modeJavascriptUrl)
|
||||
import workerJavascriptUrl from 'ace-builds/src-noconflict/worker-javascript?url'
|
||||
ace.config.setModuleUrl('ace/mode/javascript_worker', workerJavascriptUrl)
|
||||
import snippetsJavascriptUrl from 'ace-builds/src-noconflict/snippets/javascript?url'
|
||||
ace.config.setModuleUrl('ace/snippets/javascript', snippetsJavascriptUrl)
|
||||
|
||||
import 'ace-builds/src-noconflict/ext-language_tools'
|
||||
// ace.require('ace/ext/language_tools');
|
||||
const langTools = ace.require('ace/ext/language_tools')
|
||||
langTools.addCompleter({
|
||||
getCompletions: function (
|
||||
_editor: any,
|
||||
_session: any,
|
||||
_pos: any,
|
||||
prefix: string | any[],
|
||||
callback: (
|
||||
arg0: null,
|
||||
arg1: {
|
||||
name: string //显示的名称
|
||||
value: string //插入的值,
|
||||
score: number //分数
|
||||
meta: string //描述
|
||||
}[]
|
||||
) => void
|
||||
) {
|
||||
if (prefix.length === 0) {
|
||||
callback(null, [])
|
||||
return
|
||||
}
|
||||
callback(null, [
|
||||
{
|
||||
name: '$mtEventCallBack',
|
||||
value: '$mtEventCallBack(type,$item_info.id)',
|
||||
score: 1000,
|
||||
meta: '执行订阅回调函数'
|
||||
},
|
||||
{
|
||||
name: '$mtElMessage',
|
||||
value: '$mtElMessage.success("成功")',
|
||||
score: 1000,
|
||||
meta: '消息提示'
|
||||
},
|
||||
{
|
||||
name: '$mtElMessageBox',
|
||||
value: `$mtElMessageBox.alert('This is a message', 'Title', {
|
||||
confirmButtonText: 'OK',
|
||||
callback: (action) => {
|
||||
console.log(action)
|
||||
},
|
||||
})`,
|
||||
score: 1000,
|
||||
meta: '消息弹出框'
|
||||
},
|
||||
{
|
||||
name: '$item_info',
|
||||
value: '$item_info',
|
||||
score: 1000,
|
||||
meta: '回调函数中获取当前触发事件图形的信息'
|
||||
}
|
||||
])
|
||||
}
|
||||
})
|
||||
37
src/components/mt-edit/assets/css/custom_ani.css
Normal file
@@ -0,0 +1,37 @@
|
||||
@-webkit-keyframes rotate360 {
|
||||
0% {
|
||||
-webkit-transform: rotate3d(0, 0, 1, 0deg);
|
||||
transform: rotate3d(0, 0, 1, 0deg);
|
||||
}
|
||||
50% {
|
||||
-webkit-transform: rotate3d(0, 0, 1, 180deg);
|
||||
transform: rotate3d(0, 0, 1, 180deg);
|
||||
}
|
||||
to {
|
||||
-webkit-transform: rotate3d(0, 0, 1, 360deg);
|
||||
transform: rotate3d(0, 0, 1, 360deg);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes rotate360 {
|
||||
0% {
|
||||
-webkit-transform: rotate3d(0, 0, 1, 0deg);
|
||||
transform: rotate3d(0, 0, 1, 0deg);
|
||||
}
|
||||
50% {
|
||||
-webkit-transform: rotate3d(0, 0, 1, 180deg);
|
||||
transform: rotate3d(0, 0, 1, 180deg);
|
||||
}
|
||||
to {
|
||||
-webkit-transform: rotate3d(0, 0, 1, 360deg);
|
||||
transform: rotate3d(0, 0, 1, 360deg);
|
||||
}
|
||||
}
|
||||
|
||||
.animate__rotate360 {
|
||||
-webkit-animation-name: rotate360;
|
||||
animation-name: rotate360;
|
||||
animation-timing-function: linear;
|
||||
-webkit-transform-origin: center;
|
||||
transform-origin: center;
|
||||
}
|
||||
280
src/components/mt-edit/components/add-element/index.vue
Normal file
@@ -0,0 +1,280 @@
|
||||
<template>
|
||||
<div class="add-element">
|
||||
<el-dialog v-model="open" title="新增图元" width="500px" destroy-on-close @close="closeDialog">
|
||||
<el-form :model="element" ref="ruleFormRef" :rules="rules" label-width="120px">
|
||||
<el-form-item label="图元分类:" prop="elementSonType">
|
||||
<el-select v-model="element.elementSonType" placeholder="请选择图元分类" style="width: 100%">
|
||||
<el-option v-for="item in options" :key="item.value" :label="item.label" :value="item.value" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<!-- <el-form-item label="组件子类型:" prop="elementSonType">
|
||||
<el-select
|
||||
v-model="element.elementSonType"
|
||||
placeholder="请选择组件子类型"
|
||||
style="width: 100%"
|
||||
>
|
||||
<el-option
|
||||
v-for="item in options1.filter(
|
||||
(item) => item.key == element.elementType
|
||||
)"
|
||||
:key="item.value"
|
||||
:label="item.label"
|
||||
:value="item.value"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item> -->
|
||||
<!-- <el-form-item label="图元状态:" prop="elementForm">
|
||||
<el-select
|
||||
v-if="element.elementSonType == '电力状态图元'"
|
||||
v-model="element.elementForm"
|
||||
placeholder="请选择图元状态"
|
||||
style="width: 100%"
|
||||
@change="
|
||||
(val) => {
|
||||
changeEvent(val, args);
|
||||
}
|
||||
"
|
||||
>
|
||||
<el-option
|
||||
v-for="item in StatusList1"
|
||||
:key="item.value"
|
||||
:label="item.label"
|
||||
:value="item.value"
|
||||
/>
|
||||
</el-select>
|
||||
<el-select
|
||||
v-else="
|
||||
element.elementSonType == '电力系统基础图元' ||
|
||||
element.elementSonType == '自定义图元'
|
||||
"
|
||||
v-model="element.elementForm"
|
||||
placeholder="请选择图元状态"
|
||||
style="width: 100%"
|
||||
@change="
|
||||
(val) => {
|
||||
changeEvent(val, args);
|
||||
}
|
||||
"
|
||||
>
|
||||
<el-option
|
||||
v-for="item in StatusList"
|
||||
:key="item.value"
|
||||
:label="item.label"
|
||||
:value="item.value"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item> -->
|
||||
<!-- <el-form-item label="组件编码:" prop="elementCode">
|
||||
<el-input
|
||||
v-model="element.elementCode"
|
||||
placeholder="请选择组件编码"
|
||||
style="width: 100%"
|
||||
/>
|
||||
</el-form-item> -->
|
||||
<el-form-item label="图元名称:" prop="elementName">
|
||||
<el-input v-model="element.elementName" placeholder="请选择组件名称" style="width: 100%" />
|
||||
</el-form-item>
|
||||
<!-- <el-form-item label="组件标识:" prop="elementMark">
|
||||
<el-input v-model="element.elementMark" placeholder="请选择组件标识" style="width: 100%" />
|
||||
</el-form-item> -->
|
||||
<el-form-item label="上传svg:">
|
||||
<el-upload
|
||||
ref="upload"
|
||||
v-model="fileList"
|
||||
style="width: 415px"
|
||||
action="#"
|
||||
multiple
|
||||
accept="image/svg+xml"
|
||||
:http-request="UploadSvg"
|
||||
:on-remove="handleRemove"
|
||||
:before-upload="beforeAvatarUpload"
|
||||
:limit="1"
|
||||
:on-exceed="handleExceed"
|
||||
>
|
||||
<el-button type="primary">上传</el-button>
|
||||
</el-upload>
|
||||
<el-dialog v-model="dialogVisible">
|
||||
<img w-full :src="dialogImageUrl" alt="Preview Image" />
|
||||
</el-dialog>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button @click="addNewComponent(ruleFormRef)" type="primary">保存</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { defineProps, getCurrentInstance, onMounted, ref, watch, reactive } from 'vue'
|
||||
import { ElInput, ElFormItem, ElForm, ElDialog, ElUpload, ElMessage, ElButton, ElSelect, ElOption } from 'element-plus'
|
||||
import type { UploadInstance, UploadProps, FormInstance, FormRules, UploadFile, UploadUserFile } from 'element-plus'
|
||||
|
||||
import { addElement, download } from '@/api/index'
|
||||
import { leftAsideStore } from '@/export'
|
||||
|
||||
const instance = getCurrentInstance() // 获取当前组件实例
|
||||
|
||||
const open = ref(false)
|
||||
|
||||
const props = defineProps({
|
||||
show: Boolean
|
||||
})
|
||||
|
||||
const element: any = ref({
|
||||
elementCode: '', //组件编码
|
||||
elementForm: '', // 图元状态
|
||||
elementMark: '', //组件标识
|
||||
elementName: '', //图元名称
|
||||
elementSonType: '', //组件子类型 图元分类
|
||||
elementType: '', //组件分类
|
||||
multipartFile: '' // 图元文件
|
||||
})
|
||||
|
||||
interface RuleForm {
|
||||
elementCode: string
|
||||
elementForm: string
|
||||
elementMark: string
|
||||
elementName: string
|
||||
elementSonType: string
|
||||
elementType: string
|
||||
}
|
||||
|
||||
const options = [
|
||||
{
|
||||
value: '电力基础图元',
|
||||
label: '电力基础图元'
|
||||
},
|
||||
{
|
||||
value: '自定义',
|
||||
label: '自定义'
|
||||
}
|
||||
]
|
||||
|
||||
const fileList = ref<UploadFile[]>([]) // 上传文件列表
|
||||
const dialogImageUrl = ref('')
|
||||
const dialogVisible = ref(false) // 上传图片预览
|
||||
|
||||
const handleRemove = (file: UploadFile) => {
|
||||
fileList.value = []
|
||||
}
|
||||
// 文件校验
|
||||
const beforeAvatarUpload: UploadProps['beforeUpload'] = rawFile => {
|
||||
if (rawFile.type !== 'image/svg+xml') {
|
||||
ElMessage.error('只能上传svg格式文件!')
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
const handleExceed: UploadProps['onExceed'] = files => {
|
||||
return ElMessage.error('只能上传1个svg文件!')
|
||||
}
|
||||
// 上传svg
|
||||
// const UploadSvg = (params:any) => {
|
||||
// fileList.value.push(params.file);
|
||||
// };
|
||||
|
||||
const UploadSvg = (params: any) => {
|
||||
return new Promise<void>(resolve => {
|
||||
fileList.value.push(params.file)
|
||||
resolve()
|
||||
})
|
||||
}
|
||||
|
||||
const handlePictureCardPreview = (file: UploadFile) => {
|
||||
dialogImageUrl.value = file.url!
|
||||
dialogVisible.value = true
|
||||
}
|
||||
|
||||
const ruleFormRef = ref<FormInstance>()
|
||||
const rules = reactive<FormRules<RuleForm>>({
|
||||
elementCode: [{ required: true, message: '请输入组件编码', trigger: 'blur' }],
|
||||
elementForm: [{ required: true, message: '请选择图元状态', trigger: 'change' }],
|
||||
elementMark: [{ required: true, message: '请输入组件标识', trigger: 'blur' }],
|
||||
elementName: [{ required: true, message: '请输入图元名称', trigger: 'blur' }],
|
||||
elementSonType: [{ required: true, message: '请选择父类型', trigger: 'change' }],
|
||||
elementType: [{ required: true, message: '请选择组件分类', trigger: 'change' }]
|
||||
})
|
||||
|
||||
const closeDialog = () => {
|
||||
open.value = false
|
||||
if (instance) {
|
||||
const emit = instance.emit
|
||||
emit('update:show', false) // 向父组件发送更新后的状态
|
||||
}
|
||||
}
|
||||
|
||||
watch(
|
||||
() => props.show,
|
||||
val => {
|
||||
if (val === true) {
|
||||
open.value = true
|
||||
element.value = {}
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
// 新增保存
|
||||
|
||||
const addNewComponent = async (formEl: FormInstance | undefined) => {
|
||||
if (!formEl) return
|
||||
await formEl.validate(valid => {
|
||||
if (valid) {
|
||||
if (fileList.value.length == 0) {
|
||||
ElMessage({
|
||||
message: '请上传svg文件!',
|
||||
type: 'warning'
|
||||
})
|
||||
return Promise.resolve() // 显式返回 Promise<void>
|
||||
}
|
||||
let form = new FormData()
|
||||
|
||||
form.append('elementCode', element.value.elementName)
|
||||
form.append('elementForm', '普通图元')
|
||||
form.append('elementMark', element.value.elementName)
|
||||
form.append('elementName', element.value.elementName)
|
||||
form.append('elementSonType', element.value.elementSonType)
|
||||
form.append('elementType', 'svg文件')
|
||||
form.append('multipartFile', fileList.value[0])
|
||||
|
||||
addElement(form).then((res: any) => {
|
||||
if (res.code == 'A0000') {
|
||||
ElMessage({
|
||||
message: '新增成功',
|
||||
type: 'success'
|
||||
})
|
||||
closeDialog()
|
||||
// 左侧列表渲染新增的图元
|
||||
download({ filePath: res.data.path }).then((Svg: any) => {
|
||||
// 动态添加svg
|
||||
leftAsideStore.svgPush(res.data.elementSonType, [
|
||||
{
|
||||
id: res.data.id,
|
||||
title: res.data.elementName,
|
||||
type: 'svg',
|
||||
thumbnail:
|
||||
'data:image/svg+xml;utf8,' +
|
||||
encodeURIComponent(Svg.replace(/(\sfill=(["']))[^"']*(\2)/g, '$1#000000$3')),
|
||||
svg: Svg.replace(/\sfill=(["'])[^"']*\1/g, ''),
|
||||
props: {
|
||||
fill: {
|
||||
type: 'color',
|
||||
val: '#FF0000',
|
||||
title: '填充色'
|
||||
}
|
||||
}
|
||||
}
|
||||
])
|
||||
})
|
||||
} else {
|
||||
ElMessage({
|
||||
message: res.message,
|
||||
type: 'info'
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
return Promise.resolve() // 确保所有分支都返回 Promise<void>
|
||||
})
|
||||
}
|
||||
</script>
|
||||
86
src/components/mt-edit/components/context-menu/index.vue
Normal file
@@ -0,0 +1,86 @@
|
||||
<template>
|
||||
<ul ref="contextMenuRef" class="contextMenu" v-show="show">
|
||||
<li
|
||||
v-for="(item, key) in contextMenuProps.menuInfo.info"
|
||||
:key="item.title"
|
||||
@click="onItemClick(key, item, $event)"
|
||||
>
|
||||
<p :class="item.enable ? '' : 'disabled'">
|
||||
{{ item.title }}
|
||||
<span class="shortcut">{{ item.hot_key }}</span>
|
||||
</p>
|
||||
</li>
|
||||
</ul>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import type { ContextMenuInfoType, IContextMenuDetail, IContextMenuInfo } from '../../store/types'
|
||||
|
||||
type ContextMenuProps = {
|
||||
menuInfo: IContextMenuDetail
|
||||
show: boolean
|
||||
}
|
||||
const contextMenuProps = withDefaults(defineProps<ContextMenuProps>(), {})
|
||||
const emits = defineEmits(['onContextMenuClick'])
|
||||
const onItemClick = (key: ContextMenuInfoType, item: IContextMenuInfo, e: MouseEvent) => {
|
||||
if (!item.enable) {
|
||||
return
|
||||
}
|
||||
emits('onContextMenuClick', key, e)
|
||||
}
|
||||
</script>
|
||||
<style scoped lang="less">
|
||||
.contextMenu {
|
||||
position: fixed;
|
||||
z-index: 99999;
|
||||
background: #ffffff;
|
||||
padding: 5px 0;
|
||||
margin: 0px;
|
||||
display: block;
|
||||
border-radius: 5px;
|
||||
box-shadow: 2px 5px 10px rgba(0, 0, 0, 0.3);
|
||||
left: v-bind('contextMenuProps.menuInfo.left + "px"');
|
||||
top: v-bind('contextMenuProps.menuInfo.top + "px"');
|
||||
|
||||
li {
|
||||
list-style: none;
|
||||
padding: 0px;
|
||||
margin: 0px;
|
||||
}
|
||||
|
||||
.shortcut {
|
||||
width: 115px;
|
||||
text-align: right;
|
||||
float: right;
|
||||
}
|
||||
|
||||
p {
|
||||
text-decoration: none;
|
||||
display: block;
|
||||
padding: 0px 15px 1px 20px;
|
||||
margin: 0;
|
||||
user-select: none;
|
||||
-webkit-user-select: none;
|
||||
}
|
||||
|
||||
p:hover {
|
||||
background-color: #0cf;
|
||||
color: #ffffff;
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
.disabled {
|
||||
color: #999;
|
||||
}
|
||||
|
||||
.disabled:hover {
|
||||
color: #999;
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
li.separator {
|
||||
border-top: solid 1px #e3e3e3;
|
||||
padding-top: 5px;
|
||||
margin-top: 5px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,26 @@
|
||||
<template>
|
||||
<img draggable="false" class="w-1/1 h-1/1" :src="img_url" />
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
// @ts-nocheck
|
||||
import { onMounted, ref, useSlots, watch } from 'vue'
|
||||
import { renderToString } from 'vue/server-renderer'
|
||||
import { svgToImgSrc } from '../../utils'
|
||||
const img_url = ref('')
|
||||
const slots = useSlots()
|
||||
const setImgUrl = async () => {
|
||||
const slotNodes = slots.default ? slots.default() : []
|
||||
const slotStrings = await renderToString(slotNodes[0])
|
||||
img_url.value = svgToImgSrc(slotStrings)
|
||||
}
|
||||
onMounted(async () => {
|
||||
await setImgUrl()
|
||||
})
|
||||
watch(
|
||||
() => slots.default(),
|
||||
async () => {
|
||||
await setImgUrl()
|
||||
},
|
||||
{ deep: true }
|
||||
)
|
||||
</script>
|
||||
51
src/components/mt-edit/components/done-tree/index.vue
Normal file
@@ -0,0 +1,51 @@
|
||||
<template>
|
||||
<el-tree
|
||||
:data="doneTreeProps.doneJson"
|
||||
:props="defaultProps"
|
||||
@node-click="handleNodeClick"
|
||||
:default-expand-all="true"
|
||||
:expand-on-click-node="false"
|
||||
:highlight-current="true"
|
||||
node-key="id"
|
||||
:current-node-key="current_node_key"
|
||||
>
|
||||
<template #default="{ node, data }">
|
||||
<div class="flex justify-between w-8/10">
|
||||
<div>{{ node.label }}</div>
|
||||
<el-button text circle size="small" class="mr-10px">
|
||||
<el-icon :title="data.hide ? '隐藏' : '显示'" :size="20" @click.stop="changeHide(data)">
|
||||
<svg-analysis :name="data.hide ? 'view-hide' : 'view-show'"></svg-analysis>
|
||||
</el-icon>
|
||||
</el-button>
|
||||
</div>
|
||||
</template>
|
||||
</el-tree>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { ElTree, ElButton, ElIcon } from 'element-plus'
|
||||
import { computed } from 'vue'
|
||||
import type { IDoneJson } from '@/components/mt-edit/store/types'
|
||||
import SvgAnalysis from '@/components/mt-edit/components/svg-analysis/index.vue'
|
||||
type DoneTree = {
|
||||
doneJson: IDoneJson[]
|
||||
selectedItemsId: string[] //已选中组件的id
|
||||
}
|
||||
const doneTreeProps = withDefaults(defineProps<DoneTree>(), {})
|
||||
|
||||
const emits = defineEmits(['updateSelectedItemsId', 'updateSelectedIdHide'])
|
||||
|
||||
const current_node_key = computed(() => {
|
||||
return doneTreeProps.selectedItemsId.length == 1 ? doneTreeProps.selectedItemsId[0] : ''
|
||||
})
|
||||
const handleNodeClick = (data: IDoneJson) => {
|
||||
emits('updateSelectedItemsId', data.id)
|
||||
}
|
||||
const changeHide = (data: IDoneJson) => {
|
||||
emits('updateSelectedIdHide', data.id)
|
||||
}
|
||||
const defaultProps = {
|
||||
children: 'nochildren',
|
||||
label: 'title'
|
||||
}
|
||||
</script>
|
||||
49
src/components/mt-edit/components/drag-canvas/index.vue
Normal file
@@ -0,0 +1,49 @@
|
||||
<template>
|
||||
<div class="hidden"></div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import type { MouseTouchEvent } from '../types'
|
||||
type DragCanvasProps = {
|
||||
scaleRatio: number
|
||||
}
|
||||
const dragCanvasProps = withDefaults(defineProps<DragCanvasProps>(), {
|
||||
scaleRatio: 1
|
||||
})
|
||||
const emits = defineEmits(['dragCanvasMouseDown', 'dragCanvasMouseMove', 'dragCanvasMouseUp'])
|
||||
|
||||
const onMouseDown = (de: MouseTouchEvent) => {
|
||||
let move_x = 0
|
||||
let move_y = 0
|
||||
// 记录最开始点击时鼠标位置
|
||||
const d_x = de instanceof MouseEvent ? de.clientX : de.touches[0].pageX
|
||||
const d_y = de instanceof MouseEvent ? de.clientY : de.touches[0].pageY
|
||||
emits('dragCanvasMouseDown', d_x, d_y)
|
||||
const onMouseMove = (e: MouseTouchEvent) => {
|
||||
// 记录鼠标移动的位置
|
||||
const m_x = e instanceof MouseEvent ? e.clientX : e.touches[0].pageX
|
||||
const m_y = e instanceof MouseEvent ? e.clientY : e.touches[0].pageY
|
||||
// 移动的距离
|
||||
move_x = (m_x - d_x) / 1
|
||||
move_y = (m_y - d_y) / 1
|
||||
emits('dragCanvasMouseMove', move_x, move_y)
|
||||
}
|
||||
|
||||
const onMouseUp = () => {
|
||||
document.removeEventListener('mousemove', onMouseMove)
|
||||
document.removeEventListener('mouseup', onMouseUp)
|
||||
document.removeEventListener('touchmove', onMouseMove)
|
||||
document.removeEventListener('touchend', onMouseUp)
|
||||
emits('dragCanvasMouseUp', move_x, move_y)
|
||||
}
|
||||
document.addEventListener('mousemove', onMouseMove)
|
||||
document.addEventListener('mouseup', onMouseUp)
|
||||
document.addEventListener('touchmove', onMouseMove)
|
||||
document.addEventListener('touchend', onMouseUp)
|
||||
}
|
||||
|
||||
defineExpose({
|
||||
onMouseDown
|
||||
})
|
||||
</script>
|
||||
<style scoped></style>
|
||||
196
src/components/mt-edit/components/draw-line-render/index.vue
Normal file
@@ -0,0 +1,196 @@
|
||||
<template>
|
||||
<svg
|
||||
:id="lineRenderProps.itemJson.id"
|
||||
class="mt-line-render"
|
||||
:style="{
|
||||
position: 'absolute',
|
||||
left: `${-offset}px`,
|
||||
top: `${-offset}px`,
|
||||
width: `${lineRenderProps.canvasCfg.width + offset}px`,
|
||||
height: `${lineRenderProps.canvasCfg.height + offset}px`
|
||||
}"
|
||||
version="1.1"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
pointer-events="none"
|
||||
>
|
||||
<g>
|
||||
<defs>
|
||||
<marker
|
||||
:id="'markerArrowStart' + lineRenderProps.itemJson.id"
|
||||
viewBox="0 0 10 10"
|
||||
refX="8"
|
||||
refY="5"
|
||||
markerWidth="6"
|
||||
markerHeight="6"
|
||||
orient="auto-start-reverse"
|
||||
>
|
||||
<path d="M 0 0 L 10 5 L 0 10 z" :fill="lineRenderProps.itemJson.props.stroke.val" />
|
||||
</marker>
|
||||
<marker
|
||||
:id="'markerArrowEnd' + lineRenderProps.itemJson.id"
|
||||
viewBox="0 0 10 10"
|
||||
refX="8"
|
||||
refY="5"
|
||||
markerWidth="6"
|
||||
markerHeight="6"
|
||||
orient="auto"
|
||||
>
|
||||
<path d="M 0 0 L 10 5 L 0 10 z" :fill="lineRenderProps.itemJson.props.stroke.val" />
|
||||
</marker>
|
||||
</defs>
|
||||
<path
|
||||
:d="
|
||||
positionArrarToPath(
|
||||
lineRenderProps.itemJson.props.point_position.val,
|
||||
lineRenderProps.itemJson.binfo.left + offset,
|
||||
lineRenderProps.itemJson.binfo.top + offset
|
||||
)
|
||||
"
|
||||
pointer-events="visibleStroke"
|
||||
fill="none"
|
||||
:stroke="
|
||||
lineRenderProps.itemJson.props.ani_type.val === 'electricity'
|
||||
? lineRenderProps.itemJson.props.ani_color.val
|
||||
: lineRenderProps.itemJson.props.stroke.val
|
||||
"
|
||||
:stroke-width="lineRenderProps.itemJson.props['stroke-width'].val"
|
||||
style="cursor: move"
|
||||
stroke-dashoffset="0"
|
||||
:stroke-dasharray="
|
||||
lineRenderProps.itemJson.props.ani_type.val === 'electricity'
|
||||
? lineRenderProps.itemJson.props['stroke-width'].val * 3
|
||||
: 0
|
||||
"
|
||||
:marker-start="
|
||||
lineRenderProps.itemJson.props?.['marker-start']?.val
|
||||
? `url(#markerArrowStart${lineRenderProps.itemJson.id})`
|
||||
: ''
|
||||
"
|
||||
:marker-end="
|
||||
lineRenderProps.itemJson.props?.['marker-end']?.val
|
||||
? `url(#markerArrowEnd${lineRenderProps.itemJson.id})`
|
||||
: ''
|
||||
"
|
||||
class="real"
|
||||
>
|
||||
<animate
|
||||
v-if="lineRenderProps.itemJson.props.ani_type.val === 'electricity'"
|
||||
attributeName="stroke-dashoffset"
|
||||
:from="lineRenderProps.itemJson.props.ani_reverse.val ? 0 : 1000"
|
||||
:to="
|
||||
lineRenderProps.itemJson.props.ani_reverse.val
|
||||
? lineRenderProps.itemJson.props.ani_play.val
|
||||
? 1000
|
||||
: 0
|
||||
: lineRenderProps.itemJson.props.ani_play.val
|
||||
? 0
|
||||
: 1000
|
||||
"
|
||||
:dur="`${
|
||||
lineRenderProps.itemJson.props.ani_dur.val < 1 ? 1 : lineRenderProps.itemJson.props.ani_dur.val
|
||||
}s`"
|
||||
repeatCount="indefinite"
|
||||
/>
|
||||
</path>
|
||||
</g>
|
||||
</svg>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import type { MouseTouchEvent } from '@/components/mt-dzr/utils/types'
|
||||
import type { IDoneJson, IGlobalStoreCanvasCfg, IGlobalStoreGridCfg } from '../../store/types'
|
||||
import { alignToGrid, positionArrarToPath } from '@/components/mt-edit/utils'
|
||||
import { computed } from 'vue'
|
||||
import { configStore } from '../../store/config'
|
||||
type LineRenderProps = {
|
||||
itemJson: IDoneJson
|
||||
canvasCfg: IGlobalStoreCanvasCfg
|
||||
grid: IGlobalStoreGridCfg
|
||||
canvasDom: HTMLElement | null
|
||||
mode: 'pen' | 'pencil'
|
||||
}
|
||||
const lineRenderProps = withDefaults(defineProps<LineRenderProps>(), {
|
||||
mode: 'pen'
|
||||
})
|
||||
const lineRenderEmits = defineEmits(['drawLineEnd'])
|
||||
const offset = configStore.lineRenderOffset
|
||||
//如果网格关闭或者没有开启网格对齐,网格大小为1
|
||||
const grid_align_size = computed(() =>
|
||||
!lineRenderProps.grid.align || !lineRenderProps.grid.enabled ? 1 : lineRenderProps.grid.size
|
||||
)
|
||||
const onMouseDown = (de: MouseTouchEvent, point_index: number, item: { x: number; y: number }) => {
|
||||
de.stopPropagation()
|
||||
// 记录鼠标按下时实际点的坐标
|
||||
const { x: realityX, y: realityY } = item
|
||||
// 记录最开始点击时鼠标位置
|
||||
const d_x = de instanceof MouseEvent ? de.clientX : de.touches[0].pageX
|
||||
const d_y = de instanceof MouseEvent ? de.clientY : de.touches[0].pageY
|
||||
let new_x = 0
|
||||
let new_y = 0
|
||||
const onMouseMove = (e: MouseTouchEvent) => {
|
||||
// 记录鼠标移动的位置
|
||||
const m_x = e instanceof MouseEvent ? e.clientX : e.touches[0].pageX
|
||||
const m_y = e instanceof MouseEvent ? e.clientY : e.touches[0].pageY
|
||||
// 移动的距离
|
||||
const move_x = de.ctrlKey ? 0 : alignToGrid((m_x - d_x) / lineRenderProps.canvasCfg.scale, 1) //感觉对齐网格有点体验不好 所以固定为一了
|
||||
const move_y = de.shiftKey ? 0 : alignToGrid((m_y - d_y) / lineRenderProps.canvasCfg.scale, 1)
|
||||
new_x = realityX + move_x
|
||||
new_y = realityY + move_y
|
||||
if (lineRenderProps.mode == 'pencil') {
|
||||
const new_point_position = lineRenderProps.itemJson.props.point_position.val
|
||||
new_point_position.push({
|
||||
x: new_x,
|
||||
y: new_y
|
||||
})
|
||||
return
|
||||
} else {
|
||||
const new_point_position = lineRenderProps.itemJson.props.point_position.val
|
||||
new_point_position[point_index].x = new_x
|
||||
new_point_position[point_index].y = new_y
|
||||
}
|
||||
}
|
||||
|
||||
const onMouseUp = () => {
|
||||
document.removeEventListener('mousemove', onMouseMove)
|
||||
document.removeEventListener('mouseup', onMouseUp)
|
||||
document.removeEventListener('touchmove', onMouseMove)
|
||||
document.removeEventListener('touchend', onMouseUp)
|
||||
const itemRect = document.querySelector(`#${lineRenderProps.itemJson.id} g .real`)!.getBoundingClientRect()
|
||||
const canvas_area_bounding_info = lineRenderProps.canvasDom!.getBoundingClientRect()
|
||||
const new_left = (itemRect?.left - canvas_area_bounding_info?.left) / lineRenderProps.canvasCfg.scale
|
||||
const new_top = (itemRect?.top - canvas_area_bounding_info?.top) / lineRenderProps.canvasCfg.scale
|
||||
const move_x = new_left - lineRenderProps.itemJson.binfo.left
|
||||
const move_y = new_top - lineRenderProps.itemJson.binfo.top
|
||||
const new_item_json = {
|
||||
...lineRenderProps.itemJson,
|
||||
binfo: {
|
||||
...lineRenderProps.itemJson.binfo,
|
||||
left: new_left,
|
||||
top: new_top,
|
||||
width: itemRect?.width / lineRenderProps.canvasCfg.scale,
|
||||
height: itemRect?.height / lineRenderProps.canvasCfg.scale
|
||||
},
|
||||
props: {
|
||||
...lineRenderProps.itemJson.props,
|
||||
point_position: {
|
||||
...lineRenderProps.itemJson.props.point_position,
|
||||
val: lineRenderProps.itemJson.props.point_position.val.map((m: { x: number; y: number }) => {
|
||||
return {
|
||||
x: m.x - move_x,
|
||||
y: m.y - move_y
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
lineRenderEmits('drawLineEnd', new_item_json)
|
||||
}
|
||||
document.addEventListener('mousemove', onMouseMove)
|
||||
document.addEventListener('mouseup', onMouseUp)
|
||||
document.addEventListener('touchmove', onMouseMove)
|
||||
document.addEventListener('touchend', onMouseUp)
|
||||
}
|
||||
defineExpose({
|
||||
onMouseDown
|
||||
})
|
||||
</script>
|
||||
<style scoped></style>
|
||||
35
src/components/mt-edit/components/export-json/index.vue
Normal file
@@ -0,0 +1,35 @@
|
||||
<template>
|
||||
<div>
|
||||
<v-ace-editor
|
||||
v-model:value="export_json"
|
||||
lang="json"
|
||||
theme="monokai"
|
||||
style="height: 400px"
|
||||
:options="{
|
||||
useWorker: true,
|
||||
enableBasicAutocompletion: true,
|
||||
enableSnippets: true,
|
||||
enableLiveAutocompletion: true
|
||||
}"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { VAceEditor } from 'vue3-ace-editor'
|
||||
import type { IDoneJson, IGlobalStoreCanvasCfg, IGlobalStoreGridCfg } from '../../store/types'
|
||||
import { computed } from 'vue'
|
||||
import { genExportJson } from '../../composables'
|
||||
type ExportProps = {
|
||||
doneJson: IDoneJson[]
|
||||
canvasCfg: IGlobalStoreCanvasCfg
|
||||
gridCfg: IGlobalStoreGridCfg
|
||||
}
|
||||
const exportProps = withDefaults(defineProps<ExportProps>(), {})
|
||||
const export_json = computed({
|
||||
get: () => {
|
||||
const { exportJson } = genExportJson(exportProps.canvasCfg, exportProps.gridCfg, exportProps.doneJson)
|
||||
return JSON.stringify(exportJson, null, 2)
|
||||
},
|
||||
set: () => {}
|
||||
})
|
||||
</script>
|
||||
44
src/components/mt-edit/components/group-render/index.vue
Normal file
@@ -0,0 +1,44 @@
|
||||
<template>
|
||||
<div class="mt-group">
|
||||
<div
|
||||
class="absolute"
|
||||
v-for="item in groupRender.itemJson.children"
|
||||
:key="item.id"
|
||||
:id="item.id"
|
||||
:style="{
|
||||
left: item.binfo.left + '%',
|
||||
top: item.binfo.top + '%',
|
||||
width: item.binfo.width + '%',
|
||||
height: item.binfo.height + '%',
|
||||
transform: `rotate(${item.binfo.angle}deg)`
|
||||
}"
|
||||
>
|
||||
<render-item
|
||||
:item-json="item"
|
||||
:grid="groupRender.grid"
|
||||
:canvas-cfg="groupRender.canvasCfg"
|
||||
:canvas-dom="groupRender.canvasDom"
|
||||
:lock-state="false"
|
||||
></render-item>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import RenderItem from '@/components/mt-edit/components/render-item/index.vue'
|
||||
import type { IDoneJson, IGlobalStoreCanvasCfg, IGlobalStoreGridCfg } from '@/components/mt-edit/store/types'
|
||||
type GroupRender = {
|
||||
itemJson: IDoneJson
|
||||
grid: IGlobalStoreGridCfg
|
||||
canvasCfg: IGlobalStoreCanvasCfg
|
||||
canvasDom: HTMLElement | null
|
||||
}
|
||||
const groupRender = withDefaults(defineProps<GroupRender>(), {})
|
||||
</script>
|
||||
<style scoped>
|
||||
.mt-group {
|
||||
left: v-bind('groupRender.itemJson.binfo.left+"px"');
|
||||
top: v-bind('groupRender.itemJson.binfo.top+"px"');
|
||||
width: v-bind('groupRender.itemJson.binfo.width+"px"');
|
||||
height: v-bind('groupRender.itemJson.binfo.height+"px"');
|
||||
}
|
||||
</style>
|
||||
44
src/components/mt-edit/components/import-json/index.vue
Normal file
@@ -0,0 +1,44 @@
|
||||
<template>
|
||||
<div>
|
||||
<v-ace-editor
|
||||
v-model:value="import_json"
|
||||
lang="json"
|
||||
theme="monokai"
|
||||
style="height: 400px"
|
||||
:options="{
|
||||
useWorker: true,
|
||||
enableBasicAutocompletion: true,
|
||||
enableSnippets: true,
|
||||
enableLiveAutocompletion: true
|
||||
}"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { VAceEditor } from 'vue3-ace-editor'
|
||||
import { ref } from 'vue'
|
||||
import type { IExportJson } from '../types'
|
||||
import { globalStore } from '../../store/global'
|
||||
import { useExportJsonToDoneJson } from '../../composables'
|
||||
const import_json = ref('')
|
||||
const onImport = () => {
|
||||
return new Promise((resolve, reject) => {
|
||||
try {
|
||||
const json: IExportJson = JSON.parse(import_json.value)
|
||||
console.log('🚀 ~ onImport ~ json:', json)
|
||||
|
||||
const { canvasCfg, gridCfg, importDoneJson } = useExportJsonToDoneJson(json)
|
||||
|
||||
globalStore.canvasCfg = canvasCfg
|
||||
globalStore.gridCfg = gridCfg
|
||||
globalStore.setGlobalStoreDoneJson(importDoneJson)
|
||||
resolve(true)
|
||||
} catch (error) {
|
||||
resolve(false)
|
||||
}
|
||||
})
|
||||
}
|
||||
defineExpose({
|
||||
onImport
|
||||
})
|
||||
</script>
|
||||