提交 8cffb4df 编写于 作者: Q qq_32624153

Tue Sep 12 17:30:00 CST 2023 inscode

上级 f7260135
文件已添加
文件已添加
文件已添加
...@@ -7,8 +7,13 @@ ...@@ -7,8 +7,13 @@
"preview": "vite preview --port 4173" "preview": "vite preview --port 4173"
}, },
"dependencies": { "dependencies": {
"bk-magic-vue": "^2.5.7",
"bkui-vue": "^0.0.2-beta.36",
"element-ui": "^2.15.14",
"fabric": "^5.3.0",
"guess": "^1.0.2", "guess": "^1.0.2",
"vue": "^3.2.37" "vue": "^3.2.37",
"vuedraggable": "^2.24.3"
}, },
"devDependencies": { "devDependencies": {
"@vitejs/plugin-vue": "^3.0.1", "@vitejs/plugin-vue": "^3.0.1",
......
<template>
<section class="bk-layout-custom-component-wrapper container-fdpfkocb">
<div class="bk-free-layout-fdpfkocb free-layout-c8466">
<div style="position: absolute; top: 16px; left: 42px; width: 88px;">
<bk-button
title="hello world"
size="normal"
theme="primary"
:disabled="true"
:loading="false"
class="bk-layout-component-fdpfkocb buttonD1d89">
应用</bk-button>
</div>
<div style="position: absolute; top: 71px; left: 42px;">
<bk-button
title="hello world"
size="normal"
theme="primary"
:disabled="false"
:loading="false"
class="bk-layout-component-fdpfkocb buttonC90ac">
资产记录</bk-button>
</div>
<div style="position: absolute; top: 0px; left: 418px; width: 386px;">
<bk-input
value="请输入节点名称搜索"
type="text"
font-size="normal"
:disabled="false"
:readonly="false"
:clearable="true"
:show-controls="true"
class="bk-layout-component-fdpfkocb input52f12"></bk-input>
</div>
<div style="position: absolute; top: 89px; left: 262px;">
<bk-breadcrumb separator=">" separator-class="" class="bk-layout-component-fdpfkocb">
<bk-breadcrumb-item
v-for="(item, index) in breadCrumb83a41Slotdefault"
:key="index"
:to="item.to">{{ item.label }}</bk-breadcrumb-item>
</bk-breadcrumb>
</div>
<div style="position: absolute; top: 34px; left: 212px; width: 1016px;">
<bk-image
src="https://bkrepo.ce.bktencent.com/generic/bksaas-addons/public-bkapp-bk_les-5/914/file-lib/abd2230e4e0526eaa9e0198888e13dee.png"
alt=""
class="bk-layout-component-fdpfkocb image7cedd"></bk-image>
</div>
<div style="position: absolute; top: 150px; left: 5px; width: 188px;">
<el-cascader
:value="elCascaderFcd8cvalue"
:options="elCascaderFcd8coptions"
:props="elCascaderFcd8cprops"
size=""
:disabled="false"
:clearable="false"
:show-all-levels="true"
:filterable="false"
separator="/"
v-model="elCascaderFcd8cvalue"
class="bk-layout-component-fdpfkocb elCascaderFcd8c"></el-cascader>
</div>
<div style="position: absolute; top: 5px; left: 215px;">
<bk-breadcrumb separator=">" separator-class="" class="bk-layout-component-fdpfkocb">
<bk-breadcrumb-item
v-for="(item, index) in breadCrumb0424dSlotdefault"
:key="index"
:to="item.to">{{ item.label }}</bk-breadcrumb-item>
</bk-breadcrumb>
</div>
</div>
<div class="bk-free-layout-fdpfkocb free-layout-0bb40">
<div style="position: absolute; top: 54px; left: 9px;">
<bk-switcher
theme="success"
:value="false"
:disabled="false"
:is-outline="false"
:is-square="false"
:show-text="false"
on-text="ON"
off-text="OFF"
class="bk-layout-component-fdpfkocb switcher98fae"></bk-switcher>
</div>
</div>
<div class="bk-layout-component-fdpfkocb block8476f">
<widget-bk-table
table-name="scvirtualmachine"
:data="table0e9e9data"
:stripe="false"
:border="false"
:outer-border="false"
:row-border="true"
:col-border="false"
size="medium"
:fit="true"
:row-auto-height="false"
:show-header="true"
empty-text="暂无数据"
:header-border="false"
:auto-scroll-to-top="false"
:highlight-current-row="false"
class="bk-layout-component-fdpfkocb">
<template v-for="(item, index) in table0e9e9Slotdefault">
<bk-table-column
v-if="item.type === 'customCol'"
:label="item.label"
:prop="item.prop"
:sortable="item.sortable"
:type="item.type"
:width="item.width"
:key="item.templateCol">
<template slot-scope="props">
<render-html
:html="item.templateCol"
:render-options="item"
:props="props"
:parent-id="_uid"></render-html>
</template>
</bk-table-column>
<widget-table-column v-else type="bk-table-column" :key="index" :item="item"></widget-table-column>
</template>
</widget-bk-table>
</div>
</section>
</template>
<script>
/**
* 请先安装 bk-magic-vue 组件库、bkui-vue-complex 复合组件库以及 element-ui 组件库
* bk-magic-vue 组件库: https://magicbox.bk.tencent.com/static_api/v3/components_vue/2.0/example/index.html#/install
* bkui-vue-complex 复合组件库: https://github.com/TencentBlueKing/lesscode-comp
* element-ui 组件库: https://element.eleme.cn/#/zh-CN/component/installation
*
* 如果页面使用了远程函数,单独使用本页面,需要确保项目 store 下有相应的方法,后端有相应的转发接口
*/
<!--引入 bk-magic-vue 组件库-->
<link rel="stylesheet" href="//magicbox.bk.tencent.com/static_api/v3/components_vue/2.0.2-beta.7/theme-chalk/index.css">
<script src="//magicbox.bk.tencent.com/static_api/v3/components_vue/2.0.2-beta.7/components.min.js"></script>
<!--引入 bkui-vue-complex 复合组件库-->
<link rel="stylesheet" href="//cdn.bkstatic.com/comp/lesscode-vue/latest/lesscode-vue.min.css">
<script src="//cdn.bkstatic.com/comp/lesscode-vue/v3.1.1/lesscode-vue.min.js"></script>
<!--引入 element-ui 组件库-->
<link rel="stylesheet" href="//unpkg.com/element-ui/lib/theme-chalk/index.css">
<script src="//unpkg.com/element-ui/lib/index.js"></script>
export default {
data () {
return {
breadCrumb83a41Slotdefault: [
{ label: '首页', to: '/' },
{ label: '使用指引', to: '/help' },
{ label: '面包屑', to: null }
],
elCascaderFcd8cvalue: [],
elCascaderFcd8coptions: [
{
value: 'ziyuanjiedian',
label: '资源节点',
children: [
{
value: 'IP',
label: 'IP',
children: [
{ value: '10.0.218.13', label: '10.0.218.13' },
{ value: '10.0.218.12', label: '10.0.218.12' },
{ value: '10.0.218.11', label: '10.0.218.11' },
{ value: '10.2.232.113', label: '10.2.232.113' }
]
},
{
value: 'VM',
label: 'VM',
children: [
{ value: 'SCVirtualMachine', label: 'SCVirtualMachine' },
{ value: 'VDI', label: 'vdi' }
]
}
]
},
{
value: 'wangluo',
label: '网络',
children: [
{ value: 'Internet', label: '互联网线路' },
{ value: 'behaviour', label: '上网行为管理器' },
{ value: 'jiaohuanji', label: '交换机' },
{ value: 'fanghuoqiang', label: '防火墙' },
{ value: 'navigation', label: '负载均衡' },
{ value: 'others', label: '无线设备' }
]
},
{
value: 'zhongjianjian',
label: '中间件',
children: [
{ value: 'axure', label: 'IIS' },
{ value: 'sketch', label: 'Nginx' },
{ value: 'jiaohu', label: 'Kubernates' }
]
}
],
elCascaderFcd8cprops: { multiple: false, expandTrigger: 'click', checkStrictly: false },
breadCrumb0424dSlotdefault: [
{ label: '资产', to: '/complex-nav/horizontal-nav2' },
{ label: '应用拓扑', to: '/horizontal-nav/horizontal-nav1' }
],
table0e9e9data: [],
table0e9e9Slotdefault: [
{ label: '业务', prop: 'hyper_project', sortable: false, type: '' },
{ label: '集群', prop: 'hyper_cluster', sortable: false, type: '' },
{ label: '模块', prop: 'hyper_host_service', sortable: false, type: '' },
{ label: 'IP', prop: 'hyper_ips', sortable: false, type: '' }
]
}
},
created () {
this.initRemoteData()
},
methods: {
async initRemoteData () {
try {
const table0e9e9dataSourcedafc = await this.$http.get(
'/data-source/user/projectId/914/tableName/scvirtualmachine'
)
this.table0e9e9data = table0e9e9dataSourcedafc.data.list || []
} catch (error) {
console.error(error)
}
}
}
}
</script>
<style lang="css" scoped>
.container-fdpfkocb {
padding-left: 24px;
padding-right: 24px;
padding-top: 20px;
padding-bottom: 0px;
height: 100%;
}
.bk-layout-row-fdpfkocb {
display: flex;
}
.bk-layout-row-fdpfkocb:after {
display: block;
clear: both;
content: '';
font-size: 0;
height: 0;
visibility: hidden;
}
.bk-layout-col-fdpfkocb {
float: left;
position: relative;
min-height: 1px;
}
.bk-free-layout-fdpfkocb {
height: 500px;
width: 100%;
display: inline-block;
position: relative;
}
.bk-free-layout-item-inner-fdpfkocb {
height: 100%;
position: relative;
}
.bk-form-radio {
margin-right: 20px;
}
.bk-form-checkbox {
margin-right: 20px;
}
.echarts {
width: 100%;
height: 100%;
}
/* 设置 bk-exception 组件宽度为 100% */
.bk-exception-img {
width: 100%;
}
.bk-form-item {
margin: 10px;
}
.bk-sideslider {
margin: 0;
}
/* 设置 .bk-form-control 组件宽度为 auto */
.bk-form-control {
width: auto;
}
.bk-form-control .bk-input-text {
font-size: 12px;
}
[align-horizontal-left] > *,
[align-horizontal-center] > *,
[align-horizontal-right] > *,
[align-horizontal-space-between] > *,
[align-vertical-top] > *,
[align-vertical-center] > *,
[align-vertical-bottom] > * {
flex-shrink: 0;
}
[align-horizontal-left],
[align-horizontal-center],
[align-horizontal-right],
[align-horizontal-space-between] {
display: flex !important;
align-items: flex-start;
flex-wrap: wrap;
}
[align-horizontal-left] {
justify-content: flex-start;
}
[align-horizontal-center] {
justify-content: center;
}
[align-horizontal-right] {
justify-content: flex-end;
}
[align-horizontal-space-between] {
justify-content: space-between;
}
[align-vertical-top],
[align-vertical-center],
[align-vertical-bottom] {
display: flex !important;
flex-wrap: wrap;
}
[align-vertical-top] {
align-items: flex-start;
}
[align-vertical-center] {
align-items: center;
}
[align-vertical-bottom] {
align-items: flex-end;
}
[absolute-align-horizontal-left] {
left: 0 !important;
}
[absolute-align-horizontal-center] {
left: 50% !important;
transform: translateX(-50%) !important;
}
[absolute-align-horizontal-right] {
left: unset !important;
right: 0 !important;
}
[absolute-align-vertical-top] {
top: 0 !important;
}
[absolute-align-vertical-center] {
top: 50% !important;
transform: translateY(-50%) !important;
}
[absolute-align-vertical-bottom] {
top: unset !important;
bottom: 0 !important;
}
[absolute-align-horizontal-center][absolute-align-vertical-center] {
transform: translate(-50%, -50%) !important;
}
.free-layout-c8466 {
height: 655px;
margin-left: 0;
width: 1231px;
margin-top: -1px;
}
.bk-layout-component-fdpfkocb.buttonD1d89 {
display: inline-block;
vertical-align: middle;
width: 88px;
}
.bk-layout-component-fdpfkocb.buttonC90ac {
display: inline-block;
vertical-align: middle;
}
.bk-layout-component-fdpfkocb.input52f12 {
display: inline-block;
vertical-align: middle;
width: 386px;
}
.bk-layout-component-fdpfkocb.image7cedd {
display: inline-block;
width: 1016px;
vertical-align: middle;
height: 598px;
}
.bk-layout-component-fdpfkocb.elCascaderFcd8c {
width: 188px;
}
.free-layout-0bb40 {
height: 84px;
margin-top: 8px;
width: 696px;
}
.bk-layout-component-fdpfkocb.switcher98fae {
display: inline-block;
}
.bk-layout-component-fdpfkocb.block8476f {
display: block;
width: 100%;
margin-top: 8px;
}
</style>
<template> <template>
<div class="canvas" @mousedown="handleMouseDown" @mousemove="handleMouseMove" @mouseup="handleMouseUp"> <div class="canvas-container" ref="canvasContainer">
<div v-for="(component, index) in components" :key="index" class="component" :style="{ left: component.x + 'px', top: component.y + 'px' }" :draggable="true" @dragstart="handleDragStart(component, $event)" @dragend="handleDragEnd(component, $event)">{{ component.text }}</div> <canvas ref="canvas"></canvas>
<svg> <div class="element"
<path v-for="(line, index) in lines" :key="index" :d="line.path" stroke="black" fill="transparent" /> v-for="(element, index) in elements"
</svg> :key="index"
:style="{ left: element.left + 'px', top: element.top + 'px', width: element.width + 'px', height: element.height + 'px' }"
v-draggable="{ onDrag: handleDrag, onDragEnd: handleDragEnd }">
</div>
</div> </div>
</template> </template>
<script> <script>
import VueDraggable from 'vuedraggable'
import { fabric } from 'fabric'
export default { export default {
components: {
VueDraggable
},
data() { data() {
return { return {
components: [ elements: [
{ text: 'Component 1', x: 50, y: 50 }, { type: 'rect', left: 50, top: 50, width: 100, height: 100 },
{ text: 'Component 2', x: 150, y: 50 }, { type: 'rect', left: 200, top: 200, width: 150, height: 75 },
{ text: 'Component 3', x: 100, y: 150 }
], ],
lines: [] canvas: null
}; }
},
methods: {
handleMouseDown(event) {
// Handle mouse down event
},
handleMouseMove(event) {
// Handle mouse move event
}, },
handleMouseUp(event) { mounted() {
// Handle mouse up event this.canvas = new fabric.Canvas(this.$refs.canvas)
this.canvas.setWidth(this.$refs.canvasContainer.offsetWidth)
this.canvas.setHeight(this.$refs.canvasContainer.offsetHeight)
this.canvas.backgroundColor = 'grey';
this.elements.forEach(element => {
if (element.type === 'image') {
fabric.Image.fromURL(element.src, img => {
img.set({ left: element.left, top: element.top, width: element.width, height: element.height, angle: 0 })
this.canvas.add(img)
element.object = img
})
} else {
const rect = new fabric.Rect({
left: element.left,
top: element.top,
width: element.width,
height: element.height,
fill: 'transparent',
stroke: 'red'
})
this.canvas.add(rect)
element.object = rect
}
})
}, },
handleDragStart(component, event) { methods: {
// Handle drag start event handleDrag(event) {
const element = this.elements[event.elementIndex]
element.left = event.position.left
element.top = event.position.top
if (element.type === 'image') {
element.object.set({ left: element.left, top: element.top, angle: 0 })
} else {
element.object.set({ left: element.left, top: element.top })
}
this.canvas.renderAll()
}, },
handleDragEnd(component, event) { handleDragEnd() {
// Handle drag end event this.canvas.renderAll()
} }
} }
};
</script>
<style>
.canvas {
position: relative;
} }
</script>
.component {
position: absolute;
background-color: #ccc;
padding: 10px;
}
svg {
position: absolute;
top: 0;
left: 0;
pointer-events: none;
}
</style>
import { createApp } from 'vue' import { createApp } from 'vue'
import App from './canvas.vue' import App from './bklesscode-page-demo.vue'
import './assets/main.css' import './assets/main.css'
// 全量引入 bkui-vue
import bkui from 'bkui-vue'
// 全量引入 bkui-vue 样式
import 'bkui-vue/dist/style.css'
createApp(App)
.use(store)
.use(router)
.use(bkui)
.mount('#app')
createApp(App).mount('#app') createApp(App).mount('#app')
<template>
<div>
<h1>Drag and Scale Elements</h1>
<div class="canvas-container" ref="canvasContainer">
<canvas ref="canvas"></canvas>
<div class="element" v-for="(element, index) in elements" :key="index"
:style="{ left: element.left + 'px', top: element.top + 'px', width: element.width + 'px', height: element.height + 'px' }"
v-draggable="{ onDrag: handleDrag, onDragEnd: handleDragEnd, onResize: handleResize, onResizeEnd: handleResizeEnd }">
</div>
</div>
<button @click="generateCanvas">Generate Canvas</button>
</div>
</template>
<script>
import VueDraggable from 'vuedraggable'
import { fabric } from 'fabric'
export default {
components: {
VueDraggable
},
data() {
return {
elements: [
{ left: 50, top: 50, width: 100, height: 100 },
{ left: 200, top: 200, width: 150, height: 75 }
],
canvas: null
}
},
mounted() {
this.canvas = new fabric.Canvas(this.$refs.canvas)
this.canvas.setWidth(this.$refs.canvasContainer.offsetWidth)
this.canvas.setHeight(this.$refs.canvasContainer.offsetHeight)
},
methods: {
handleDrag(event) {
const element = this.elements[event.elementIndex]
element.left = event.position.left
element.top = event.position.top
},
handleDragEnd() {
this.updateCanvas()
},
handleResize(event) {
const element = this.elements[event.elementIndex]
element.width = event.size.width
element.height = event.size.height
},
handleResizeEnd() {
this.updateCanvas()
},
updateCanvas() {
this.canvas.clear()
this.elements.forEach(element => {
const rect = new fabric.Rect({
left: element.left,
top: element.top,
width: element.width,
height: element.height,
fill: 'transparent',
stroke: 'black'
})
this.canvas.add(rect)
})
},
generateCanvas() {
const dataURL = this.canvas.toDataURL('image/png')
const link = document.createElement('a')
link.href = dataURL
link.download = 'canvas.png'
link.click()
}
}
}
</script>
\ No newline at end of file
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册