antvX6 - Vue自定義節點,并實現多種畫布操作,拖拽、縮放、連線、雙擊、檢索等等

一、 首先?antv x6 分為兩個版本? 低版本和高版本

? 我這里是使用的2.0版本 并且搭配了相關插件 例如:畫布的圖形變換、地圖等

? 個人推薦 2.0版本,高版本配置多,可使用相關插件多,但是文檔描述小,仍在更新, 低版本文檔描述清晰,但是相關插件少

二、antv x6 支持自定義節點!?

? ? ? ? ? 這里要特別注意? 雖然支持自定義節點,但是連線,連線樁也自然只能節點之間互連,所以你看我的例子中,想要列表里的子節點也可以實現 互相連接,但是這是自定義節點無法做到的。
? ? ? ? ? 因為此時這一整個盒子就是 一個節點!

三、事件集合

    // 事件集合loadEvents(containerRef) {// 節點雙擊this.graph.on('node:dblclick', ({ node }) => {const data = node.store.data;console.log(data);this.$router.push({path: '/modeling/homeModeling',query: {id: data.modelingId,name: data.name,layerTypeId: data.layerTypeId,tableType: data.modelingType,},});});// 連線雙擊this.graph.on('edge:dblclick', ({ edge }) => {// const data = edge.store.data;// const { type, id } = data;// alert('連線雙擊');// console.log('edge:dbclick', edge);// if (type === 'taskNode') {//   this.nodeId = id;//   this.showRight = true;// } else {//   this.nodeId = '';//   this.showRight = false;// }});// 節點鼠標移入this.graph.on('node:mouseenter',FunctionExt.debounce(({ node }) => {// 添加刪除// const x = node.store.data.size.width - 10;// node.addTools({//   name: 'button-remove',//   args: {//     x: 0,//     y: 0,//     offset: { x, y: 15 },//   },// });}),500,);this.graph.on('node:port-contextmenu', ({ e }) => {// console.log(//   'ports',//   e,//   e.currentTarget.parentElement.getAttribute('port'),// );});// 連接線鼠標移入this.graph.on('edge:mouseenter', ({ edge }) => {// edge.addTools([//   'source-arrowhead',//   'target-arrowhead',//   {//     name: 'button-remove',//     args: {//       distance: '50%',//     },//   },// ]);});// 節點鼠標移出this.graph.on('node:mouseleave', ({ node }) => {// // 移除刪除// node.removeTools();});this.graph.on('edge:mouseleave', ({ edge }) => {// edge.removeTools();});this.graph.on('edge:connected', ({ isNew, edge }) => {// console.log('connected', edge.source, edge.target);// if (isNew) {//   // 對新創建的邊進行插入數據庫等持久化操作// }});},

四、畫布初始化

    graphInit() {// 容器生成圖表const containerRef = this.$refs.containerRef;const graph = new Graph({container: containerRef,background: {color: '#F1F6F9',},grid: {size: 10, // 網格大小 10pxvisible: true, // 繪制網格,默認繪制 dot 類型網格type: 'fixedDot',args: {color: '#AFB0B1', // 網點顏色thickness: 1, // 網點大小},},panning: true, // 畫布拖拽history: true, // 啟動歷史記錄selecting: {// 選擇與框選enabled: true,rubberband: true,movable: true,strict: true,showNodeSelectionBox: true, // 顯示節點的選擇框(才能進行移動)modifiers: ['alt'],},// Scroller 使畫布具備滾動、平移、居中、縮放等能力scroller: {enabled: true,pageVisible: true,pageBreak: true,pannable: true,},// 鼠標滾輪的默認行為是滾動頁面 使用ctrl+滾輪 實現縮放mousewheel: {enabled: true,modifiers: ['ctrl', 'meta'], // +按鍵為縮放minScale: 0.5,maxScale: 2,},snapline: true, // 對齊線// 節點連接connecting: {router: {name: 'er',args: {offset: 25,direction: 'H',},},snap: true, // 自動吸附allowBlank: false, // 是否允許連接到畫布空白位置的點allowLoop: false, // 是否允許創建循環連線,即邊的起始節點和終止節點為同一節點allowNode: false, // 是否允許邊鏈接到節點(非節點上的鏈接樁)createEdge() {return new Shape.Edge({attrs: {line: {stroke: '#1684FC',strokeWidth: 2,},},});},},// 連接樁樣式 -- 高亮highlighting: {magnetAvailable: {name: 'stroke',args: {padding: 4,attrs: {strokeWidth: 4,stroke: '#1684FC',},},},},});// 小地圖const minimapContainer = this.$refs.minimapContainer;graph.use(new MiniMap({container: minimapContainer,width: '250',height: '150',scalable: true, // 是否可縮放minScale: 0.01,maxScale: 16,}),);// 圖形graph.use(new Transform({enabled: true,resizing: map,}),);// 縮放畫布內容,使畫布內容充滿視口graph.zoomToFit({ padding: 10, maxScale: 1 });// 賦值生成this.graph = graph;// 事件集合this.loadEvents(containerRef);},

五、創建Vue自定義節點

<template><divref="node_dom"class="node_warp":style="{width: node.size.width + 'px',height: node.size.height + 'px',borderTopColor: color,}"><div class="head_top" :style="{ backgroundColor }"><svg-icon :icon-class="icon" :style="{ color }"></svg-icon><div class="code_warp"><span class="code ellipsis_text">{{ node.code }}</span><span class="name ellipsis_text">{{ node.name }}</span></div><el-popoverref="popoverDom"placement="bottom-end"width="60":value="popShow"trigger="click"popper-class="filter_column_popover"@hide="popShow = false"@show="popShow = true"><svg-iconslot="reference"class="icon"type="primary"size="mini"style="opacity: 0.5;"icon-class="table_column_settings"></svg-icon><p class="header_wrap_filter_column"><el-checkboxv-model="checkAll":indeterminate="isIndeterminate"@change="handleCheckAllChange">全選</el-checkbox><!-- --><!-- <el-button size="mini" type="text" @click="resetColumn">重置</el-button> --></p><el-checkbox-groupv-model="checkList"@change="handleCheckedCitiesChange"><el-checkbox v-for="item in checkData" :key="item" :label="item">{{ item }}</el-checkbox></el-checkbox-group><div v-if="!checkData.length" class="empy">暫無數據</div></el-popover></div><div class="main"><divv-for="(item, index) in node.columnVersions":key="index"class="text "><svg-icon v-if="item.isPrimaryKey" icon-class="key"></svg-icon><span v-show="checkList.includes('英文名稱')" class="ellipsis_text">{{ item.code }}</span><div v-show="checkList.includes('字段類型')" class="type ellipsis_text">{{ item.dataType }}</div><span v-show="checkList.includes('中文名稱')" class="ellipsis_text">{{ item.name }}</span></div><divv-if="!node.columnVersions || !node.columnVersions.length"class="empy flex">暫無數據</div></div><div class="footer">{{ `共${node.columnSize || 0}個字段` }}</div></div>
</template><script>
import { manage } from './config';
const cityOptions = ['英文名稱', '字段類型', '中文名稱'];
export default {name: 'Node',inject: ['getNode'],data() {return {num: 0,icon: '',color: '',node: {},popShow: false,checkAll: false,checkList: ['英文名稱', '字段類型'],checkData: cityOptions,isIndeterminate: true,backgroundColor: null,typeMap: manage.typeMap,};},watch: {checkList(val) {console.log(val);},},created() {const node = this.getNode();const typeMap = this.typeMap;this.node = node.store.data;const type = this.node.modelingType;this.icon = typeMap[type].icon;this.color = typeMap[type].color;this.backgroundColor = typeMap[type].backgroundColor;},methods: {handleCheckAllChange(val) {this.checkList = val ? cityOptions : [];this.isIndeterminate = false;},handleCheckedCitiesChange(value) {const checkedCount = value.length;this.checkAll = checkedCount === this.checkData.length;this.isIndeterminate =checkedCount > 0 && checkedCount < this.checkData.length;},resetColumn() {this.checkList = ['英文名稱', '字段類型'];},},
};
</script><style lang="scss" scoped>
.node_warp {display: flex;border-radius: 4px;flex-direction: column;border: 1px solid #d9dae2;border-top: 5px solid #d9dae2;position: relative;user-select: none;transition: all 0.4s ease-in 0.2s;transition: width 0.25s;-webkit-transition: width 0.25s;-moz-transition: width 0.25s;-webkit-transition: width 0.25s;-o-transition: width 0.25s;.head_top {width: 100%;height: 48px;display: flex;padding-left: 10px;align-items: center;position: relative;border-bottom: 1px solid #d9dae2;.code_warp {width: 85%;font-size: 12px;margin-left: 8px;display: flex;flex-direction: column;.code {color: black;font-weight: 700;}.name {color: #b3b2bf;font-weight: 600;}}.icon {position: absolute;right: 5px;bottom: 5px;}}.main {flex: 1;width: 100%;overflow: auto;padding-right: 2px;background: #fff;.text {height: 32px;display: flex;gap: 1px;font-size: 13px;position: relative;padding-left: 20px;align-items: center;svg {position: absolute;left: 4px;top: 10px;}.type {flex: 1;height: 24px;font-size: 12px;line-height: 24px;text-align: center;border-radius: 4px;margin-right: 5px;display: inline-block;background-color: #f7f7f9;}span {flex: 1;text-align: center;}&:hover {background: #f8f8fa;}}}.footer {height: 20px;font-size: 12px;line-height: 20px;padding-left: 10px;color: rgb(156, 160, 184);border-top: 1px solid #d9dae2;background: rgb(247, 247, 249);}.ellipsis_text {white-space: nowrap;overflow: hidden;text-overflow: ellipsis;word-break: break-all;line-height: 18px;}.empy {color: #ccc;font-size: 14px;margin: 10px auto;width: fit-content;}.flex {display: flex;height: calc(100% - 30px);align-items: center;}
}
</style>

六、注冊引入Vue自定義節點

1、安裝依賴

? ? ??"@antv/x6-vue-shape": "2.0.6",

? ? ? yarn add?antv/x6-vue-shape@2.0.6

2、引入 Vue 自定義組件

? ? ??import CustomNode from '../node';

3、引入插件的方法

? ? ??import { register } from '@antv/x6-vue-shape'; // vue節點

4、注冊節點

????????

register({

? shape: 'custom-vue-node',

? component: CustomNode,

});


import CustomNode from '../node';
import { register } from '@antv/x6-vue-shape'; // vue節點// 注冊 Vue component
register({shape: 'custom-vue-node',component: CustomNode,
});

七、創建節點、創建連線、渲染節點

// 連接線  
const lineNewData = newData.map((item, index) => {return {id: String(new Date().getTime() + index),shape: 'edge',// 連接源source: {cell: item.sourceTableId,},// 連接目標target: {cell: item.targetTableId,},attrs: {line: {stroke: '#1684FC',strokeWidth: 2,},},// 名字labels: [{attrs: {label: {text: item.name || '',},},},],zIndex: 0,};});// 節點const nodeData = result.map(item => {return {...item,id: item.modelingVersionId,width: Number(item.width || 300),height: Number(item.heigh || 270),// 節點類型shape: item.shape || 'custom-vue-node',position: {x: Number(item.posX || this.getRandomInt()),y: Number(item.posY || this.getRandomInt()),},};});this.erData = [...nodeData, ...lineNewData];

? 通過數據 渲染節點

  watch: {data(val) {const cells = [];this.data.forEach(item => {console.log(item, item.shape);if (item.shape === 'edge') {cells.push(this.graph.createEdge(item)); // 創建連線} else {cells.push(this.graph.createNode(item)); // 創建節點}});// 清空畫布并添加用指定的節點/邊this.graph.resetCells(cells);},},

八、canvas主頁面 全部代碼

<template><div id="container" class="antv-x6"><div ref="minimapContainer" class="app-mini"></div><div ref="containerRef" class="app-content"></div><div class="operating"><el-selectv-model="value"clearablefilterableplaceholder="請選擇"size="mini":popper-append-to-body="false":class="isShow ? 'showSelect' : 'hideSelect'"@change="valChange"><el-optionv-for="item in data.filter(i => i.modelingType)":key="item.id":label="item.code":value="item.id"><div class="head_top"><svg-icon:icon-class="typeMap[item.modelingType].icon":style="{ color: typeMap[item.modelingType].color }"/><div class="code_warp"><span class="code ellipsis_text">{{ item.code }}</span><span class="name ellipsis_text">{{ item.name }}</span></div></div></el-option></el-select><div class="icon_oper"><el-tooltipclass="item"effect="dark"content="搜索"placement="bottom"><svg-icon icon-class="search_canvas" @click="search" /></el-tooltip><el-tooltipclass="item"effect="dark"content="放大"placement="bottom"><svg-icon icon-class="amplify_canvas" @click="zoomInFn" /></el-tooltip><el-tooltipclass="item"effect="dark"content="縮小"placement="bottom"><svg-icon icon-class="reduce_canvas" @click="zoomOutFn" /></el-tooltip><el-tooltipclass="item"effect="dark"content="還原"placement="bottom"><svg-icon icon-class="1_1_canvas" @click="resetFn" /></el-tooltip><el-tooltipclass="item"effect="dark"content="保存"placement="bottom"><svg-icon icon-class="saveModel" @click="submit" /></el-tooltip><el-tooltipclass="item"effect="dark":content="isFullScreen ? '退出全屏' : '全屏'"placement="bottom"><svg-icon icon-class="screen" @click="fullScreen" /></el-tooltip><el-tooltipclass="item"effect="dark"content="刷新"placement="bottom"><svg-icon icon-class="refresh" @click="redoFn" /></el-tooltip></div></div></div>
</template><script>
import { manage } from '../config';
import CustomNode from '../node';
import { Graph, Shape, FunctionExt } from '@antv/x6';
import { register } from '@antv/x6-vue-shape'; // vue節點
import { MiniMap } from '@antv/x6-plugin-minimap'; // 地圖
import { Transform } from '@antv/x6-plugin-transform'; // 圖形變換
// import { Scroller } from '@antv/x6-plugin-scroller'; // 滾動畫布const map = {enabled: true,minWidth: 200,maxWidth: 700,minHeight: 100,maxHeight: 500,orthogonal: false,restrict: false,preserveAspectRatio: false,
};// 注冊 Vue component
register({shape: 'custom-vue-node',component: CustomNode,
});export default {name: 'Er',props: {data: {type: Array,default: () => [],},},data() {return {value: '',graph: null,isShow: false,showRight: false,isFullScreen: false,typeMap: manage.typeMap,};},watch: {data(val) {const cells = [];this.data.forEach(item => {console.log(item, item.shape);if (item.shape === 'edge') {cells.push(this.graph.createEdge(item)); // 創建連線} else {cells.push(this.graph.createNode(item)); // 創建節點}});// 清空畫布并添加用指定的節點/邊this.graph.resetCells(cells);},},mounted() {this.graphInit();},methods: {graphInit() {// 容器生成圖表const containerRef = this.$refs.containerRef;const graph = new Graph({container: containerRef,background: {color: '#F1F6F9',},grid: {size: 10, // 網格大小 10pxvisible: true, // 繪制網格,默認繪制 dot 類型網格type: 'fixedDot',args: {color: '#AFB0B1', // 網點顏色thickness: 1, // 網點大小},},panning: true, // 畫布拖拽history: true, // 啟動歷史記錄selecting: {// 選擇與框選enabled: true,rubberband: true,movable: true,strict: true,showNodeSelectionBox: true, // 顯示節點的選擇框(才能進行移動)modifiers: ['alt'],},// Scroller 使畫布具備滾動、平移、居中、縮放等能力scroller: {enabled: true,pageVisible: true,pageBreak: true,pannable: true,},// 鼠標滾輪的默認行為是滾動頁面 使用ctrl+滾輪 實現縮放mousewheel: {enabled: true,modifiers: ['ctrl', 'meta'], // +按鍵為縮放minScale: 0.5,maxScale: 2,},snapline: true, // 對齊線// 節點連接connecting: {router: {name: 'er',args: {offset: 25,direction: 'H',},},snap: true, // 自動吸附allowBlank: false, // 是否允許連接到畫布空白位置的點allowLoop: false, // 是否允許創建循環連線,即邊的起始節點和終止節點為同一節點allowNode: false, // 是否允許邊鏈接到節點(非節點上的鏈接樁)createEdge() {return new Shape.Edge({attrs: {line: {stroke: '#1684FC',strokeWidth: 2,},},});},},// 連接樁樣式 -- 高亮highlighting: {magnetAvailable: {name: 'stroke',args: {padding: 4,attrs: {strokeWidth: 4,stroke: '#1684FC',},},},},});// 小地圖const minimapContainer = this.$refs.minimapContainer;graph.use(new MiniMap({container: minimapContainer,width: '250',height: '150',scalable: true, // 是否可縮放minScale: 0.01,maxScale: 16,}),);// 圖形graph.use(new Transform({enabled: true,resizing: map,}),);// 縮放畫布內容,使畫布內容充滿視口graph.zoomToFit({ padding: 10, maxScale: 1 });// 賦值生成this.graph = graph;// 事件集合this.loadEvents(containerRef);},// 事件集合loadEvents(containerRef) {// 節點雙擊this.graph.on('node:dblclick', ({ node }) => {const data = node.store.data;console.log(data);this.$router.push({path: '/modeling/homeModeling',query: {id: data.modelingId,name: data.name,layerTypeId: data.layerTypeId,tableType: data.modelingType,},});});// 連線雙擊this.graph.on('edge:dblclick', ({ edge }) => {// const data = edge.store.data;// const { type, id } = data;// alert('連線雙擊');// console.log('edge:dbclick', edge);// if (type === 'taskNode') {//   this.nodeId = id;//   this.showRight = true;// } else {//   this.nodeId = '';//   this.showRight = false;// }});// 節點鼠標移入this.graph.on('node:mouseenter',FunctionExt.debounce(({ node }) => {// 添加刪除// const x = node.store.data.size.width - 10;// node.addTools({//   name: 'button-remove',//   args: {//     x: 0,//     y: 0,//     offset: { x, y: 15 },//   },// });}),500,);this.graph.on('node:port-contextmenu', ({ e }) => {// console.log(//   'ports',//   e,//   e.currentTarget.parentElement.getAttribute('port'),// );});// 連接線鼠標移入this.graph.on('edge:mouseenter', ({ edge }) => {// edge.addTools([//   'source-arrowhead',//   'target-arrowhead',//   {//     name: 'button-remove',//     args: {//       distance: '50%',//     },//   },// ]);});// 節點鼠標移出this.graph.on('node:mouseleave', ({ node }) => {// // 移除刪除// node.removeTools();});this.graph.on('edge:mouseleave', ({ edge }) => {// edge.removeTools();});this.graph.on('edge:connected', ({ isNew, edge }) => {// console.log('connected', edge.source, edge.target);// if (isNew) {//   // 對新創建的邊進行插入數據庫等持久化操作// }});},// 放大zoomInFn() {this.graph.zoom(0.1);},// 縮小zoomOutFn() {const Num = Number(this.graph.zoom().toFixed(1));if (Num > 0.1) {this.graph.zoom(-0.1);}},// 重置1:1resetFn() {this.graph.centerContent();this.graph.zoomTo(1); // 縮放畫布到指定的比例},// 刷新redoFn() {this.$emit('detailsEr');},// 全屏fullScreen() {// const element = document.documentElement;const element = document.getElementById('container');// 判斷是否已經是全屏if (this.isFullScreen) {// 退出全屏if (document.exitFullscreen) {document.exitFullscreen();} else if (document.webkitCancelFullScreen) {document.webkitCancelFullScreen();} else if (document.mozCancelFullScreen) {document.mozCancelFullScreen();} else if (document.msExitFullscreen) {document.msExitFullscreen();}} else {// 全屏if (element.requestFullscreen) {element.requestFullscreen();} else if (element.webkitRequestFullScreen) {element.webkitRequestFullScreen();} else if (element.mozRequestFullScreen) {element.mozRequestFullScreen();} else if (element.msRequestFullscreen) {// IE11element.msRequestFullscreen();}}this.isFullScreen = !this.isFullScreen;},// 搜索search() {this.isShow = !this.isShow;},// 保存submit() {const data = this.graph.getNodes();this.$emit('submitEr', data);},// 檢索valChange(val) {if (val) {// false - 清空const nodes = this.graph.getNodes() || [];const node = nodes.filter(item => item.id === val)[0] || {};this.graph.centerCell(node); // 將節點/邊的中心與視口中心對齊} else {this.resetFn();}},},
};
</script><style lang="scss" scoped>
.antv-x6 {width: 100%;height: 100%;padding: 0;display: flex;position: relative;box-sizing: border-box;-moz-box-sizing: border-box;-webkit-box-sizing: border-box;::v-deep body {min-width: auto;}.node-c {width: 200px;border-right: 1px solid #eee;padding: 20px;dl {margin-bottom: 20px;line-height: 30px;display: flex;cursor: move;dt {&.circle {width: 30px;height: 30px;border-radius: 50%;&.start {border: 1px solid green;background: greenyellow;}&.end {border: 1px solid salmon;background: red;}}&.rect {width: 30px;height: 30px;border: 1px solid #ccc;}}dd {font-size: bold;font-size: 14px;padding: 0 0 0 10px;overflow: hidden;text-overflow: ellipsis;white-space: nowrap;}}}.template-c {padding: 10px 0;li {line-height: 40px;font-size: 14px;border-bottom: 1px solid #dcdfe6;cursor: pointer;display: flex;justify-content: space-between;span {flex: 1;padding-right: 10px;overflow: hidden;text-overflow: ellipsis;white-space: nowrap;}i {font-size: 14px;color: #2d8cf0;width: 20px;line-height: 40px;}}}.container {flex: 1;}.operating {position: absolute;z-index: 999;right: 20px;top: 10px;padding: 5px 10px;border-radius: 6px;background-color: #ffffff;border: 1px solid rgb(187, 187, 187);box-shadow: 1px 1px 4px 0 #0a0a0a2e;display: flex;height: 34px;align-items: center;.el-select {transition: width 0.6s ease-in-out;::v-deep .el-input__inner {height: 26px;line-height: 26px;}::v-deep .el-input--mini .el-input__icon {line-height: 26px;}::v-deep .el-select-dropdown__item {height: 48px;max-width: 410px;line-height: 48px;}&.hideSelect {width: 0px;::v-deep .el-input__inner {display: none;}::v-deep .el-input__suffix {display: none;}}&.showSelect {width: 180px;::v-deep .el-input__inner {display: block;}::v-deep .el-input__suffix {display: block;}}}.icon_oper {svg {font-size: 18px;cursor: pointer;margin: 0 5px;&:hover {color: #2d8cf0;}&.opacity {opacity: 0.5;}}}}
}
.app-mini {position: fixed;z-index: 999;bottom: 10px;right: 20px;border-radius: 6px;box-shadow: 0 0 10px rgba(0, 0, 0, 0.5);
}
.app-content {flex: 1;height: 100% !important;
}
::v-deep .x6-graph-scroller {border: 1px solid #f0f0f0;margin-left: -1px;width: 100% !important;height: 100% !important;
}.head_top {width: 100%;height: 48px;display: flex;align-items: center;.code_warp {width: 90%;height: 100%;font-size: 12px;margin-left: 8px;display: flex;gap: 4px;flex-direction: column;justify-content: center;.code {color: black;font-weight: 700;line-height: normal;white-space: nowrap;overflow: hidden;text-overflow: ellipsis;word-break: break-all;}.name {color: #b3b2bf;font-weight: 600;line-height: normal;white-space: nowrap;overflow: hidden;text-overflow: ellipsis;word-break: break-all;}}
}
::v-deep .text {height: 32px;display: flex;gap: 1px;font-size: 13px;position: relative;padding-left: 20px;align-items: center;svg {position: absolute;left: 4px;top: 10px;}.type {width: 25%;height: 24px;font-size: 12px;line-height: 24px;text-align: center;border-radius: 4px;margin-right: 5px;display: inline-block;background-color: #f7f7f9;}span {flex: 1;white-space: nowrap;overflow: hidden;text-overflow: ellipsis;word-break: break-all;line-height: 18px;}&:hover {background: #f8f8fa;}
}
</style>

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/714164.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/714164.shtml
英文地址,請注明出處:http://en.pswp.cn/news/714164.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

小d和圖片壓縮

題目描述 小ddd和她對象小紅去海洋館玩了&#xff0c;但是由于小ddd拍照技術不好&#xff0c;他對象說把她拍的像嘎子&#xff01; 小ddd看了看&#xff0c;發現是小紅最近長痘痘了&#xff0c;于是他為了討小紅開心&#xff0c;讓痘痘看不見&#xff0c;自學了圖像壓縮這個技…

裝飾器模式 詳解 設計模式

裝飾器模式 它允許你在不改變對象結構的情況下&#xff0c;動態地將新功能附加到對象上。 結構&#xff1a; 抽象組件&#xff08;Component&#xff09;&#xff1a;定義了原始對象和裝飾器對象的公共接口或抽象類&#xff0c;可以是具體組件類的父類或接口。具體組件&…

固定排班計劃

目錄 1.按發車時間排序。 2.排班日期默認當天時間。 3.編輯不可修改線路和排班日期。 4.線路、車號、司機是否匹配&#xff0c;不匹配不可入庫&#xff08;和其他表比&#xff09;&#xff0c;線路、發車時間、司機、車號、日期、上下行相同不可入庫&#xff08;和自己表比…

GO語言學習筆記(與Java的比較學習)(一)

GO的優缺點&#xff1a; 此處引用華為云開發者聯盟的一篇文章&#xff1a; GO語言的亮點很明顯&#xff1a; GoDoc。 GoDoc的靜態語言分析能力很強大&#xff0c;可以直接從代碼和注釋生成漂亮的文檔。這一點區別于其他的類似工具如JavaDoc, PHPDoc或者JSDoc。這些工具需要添加…

如何在群暉Docker運行本地聊天機器人并結合內網穿透發布到公網訪問

文章目錄 1. 拉取相關的Docker鏡像2. 運行Ollama 鏡像3. 運行Chatbot Ollama鏡像4. 本地訪問5. 群暉安裝Cpolar6. 配置公網地址7. 公網訪問8. 固定公網地址 隨著ChatGPT 和open Sora 的熱度劇增,大語言模型時代,開啟了AI新篇章,大語言模型的應用非常廣泛&#xff0c;包括聊天機…

C# Socket通信從入門到精通(21)——TCP發送文件與接收文件 C#代碼實現

1、前言 我們在開發上位機軟件的過程中經常需要發送文件,本文就是介紹如何利用tcp客戶端發送文件、tcp服務器端接收文件,而且本文介紹的方法可以自動發送一個文件夾下的所有子目錄以及所有文件,經驗來自于實際項目,具備非常有價值的參考意義! 2、發送文件以及C#代碼 被發…

LeetCode第48天 買賣股票的最佳時機 買賣股票的最佳時機II 動態規劃

121. 買賣股票的最佳時機 class Solution { public:int maxProfit(vector<int>& prices) {// int res 0 ;// int low INT_MAX;// for (int i 0; i < prices.size(); i) {// low min(low, prices[i]);// res max(res, prices[i]-low);// }// return r…

低密度奇偶校驗碼LDPC(八)——QC-LDPC譯碼器FPGA設計概要

往期博文 低密度奇偶校驗碼LDPC&#xff08;一&#xff09;——概述_什么是gallager構造-CSDN博客 低密度奇偶校驗碼LDPC&#xff08;二&#xff09;——LDPC編碼方法-CSDN博客 低密度奇偶校驗碼LDPC&#xff08;三&#xff09;——QC-LDPC碼概述-CSDN博客 低密度奇偶校驗碼…

Linux系統--------內核參數調優、一鍵安裝nginx、tomcat調優

一、內核參數調優 默認的Linux內核參數考慮的是最通用場景&#xff0c;不符合用于支持高并發訪問的Web服務器的定義&#xff0c;根據業務特點來進行調整&#xff0c;當Nginx作為靜態web內容服務器、反向代理或者提供壓縮服務器的服務器時&#xff0c;內核參數的調整都是不同的…

Spring面試系列-02

1. Spring 中自動裝配有那些局限性? 自動裝配的局限性 重寫:仍需用<constructor-arg>和<property>配置來定義依賴,意味著總要重寫自動裝配。 基本數據類型:不能自動裝配簡單的屬性,例如基本數據類型、String字符串、和類。 模糊特性:自動裝配不如顯式裝配…

Vue點擊復制到剪切板

一、Vue2寫法 安裝 &#xff08;官網地址&#xff09; npm install --save vue-clipboard2 使用 //main.js import VueClipboard from vue-clipboard2 Vue.use(VueClipboard)//頁面使用 <button type"button"v-clipboard:copy"message"v-clipboard:su…

Mac電腦軟件開發的優缺點

Mac電腦軟件開發的優缺點 在軟件開發領域&#xff0c;Mac電腦一直以其獨特的優勢占有一席之地。然而&#xff0c;就像任何工具或平臺一樣&#xff0c;Mac電腦在軟件開發方面也存在其優點和缺點。本文將探討在Mac上進行軟件開發的利弊&#xff0c;幫助您了解是否應將Mac作為您的…

node.js 用 xml2js.Parser 讀 Freeplane.mm文件,生成測試用例.csv文件

Freeplane 是一款基于 Java 的開源軟件&#xff0c;繼承 Freemind 的思維導圖工具軟件&#xff0c;它擴展了知識管理功能&#xff0c;在 Freemind 上增加了一些額外的功能&#xff0c;比如數學公式、節點屬性面板等。 編寫 mm_xml2js_csv.js 如下 // 用 xml2js.Parser 讀 F…

Android 通過Intent打開第三方App

Android 使用 Intent 打開第三方應用或調用制定 Activity Intent intent new Intent(); intent.setClassName("package name", "activity name"); // 內部調用 intent.setComponent(new ComponentName("package name", "activity name&qu…

javaWebssh票據管理系統myeclipse開發mysql數據庫MVC模式java編程計算機網頁設計

一、源碼特點 java ssh票據管理系統是一套完善的web設計系統&#xff08;系統采用ssh框架進行設計開發&#xff09;&#xff0c;對理解JSP java編程開發語言有幫助&#xff0c;系統具有完整的源代碼和數據庫&#xff0c;系統主要采用B/S模 式開發。開發環境為TOMCAT7.0,My…

C++ 快速排序快速選擇

目錄 1、75. 顏色分類 2、912. 排序數組 3、 215. 數組中的第K個最大元素 4、LCR 159. 庫存管理 III 1、75. 顏色分類 思路&#xff1a;利用快速排序思路&#xff0c;使用三指針分塊進行優化。 [0,left]——小于key[left1,right-1]——等于key[right,nums.size()]——大于k…

博途PLC 面向對象系列之“輸送帶控制功能塊“(SCL代碼)

這篇是面向對象系列之"輸送帶功能塊"的封裝,面向對象是系列文章,相關鏈接如下: 1、面向對象系列之找"對象" https://rxxw-control.blog.csdn.net/article/details/136150027https://rxxw-control.blog.csdn.net/article/details/1361500272、面向對象…

LeetCode 刷題 [C++] 第215題.數組中的第K個最大元素

題目描述 給定整數數組 nums 和整數 k&#xff0c;請返回數組中第 k 個最大的元素。 請注意&#xff0c;你需要找的是數組排序后的第 k 個最大的元素&#xff0c;而不是第 k 個不同的元素。 你必須設計并實現時間復雜度為 O(n) 的算法解決此問題。 題目分析 根據題意分析&…

MYSQL 刪除命令 delete、truncate 、drop

目錄 一、delete 二、truncate 三、drop 四、delete&#xff0c;drop&#xff0c;truncate的區別 一、delete 作用&#xff1a;僅僅刪除表數據&#xff0c;表結構保留&#xff0c;數據能回滾 命令格式 #刪除全部數據 delete from 表名;#刪除表中id為1的數據&#xff0c;…

CleanMyMac X2024一款專為Mac用戶設計的優化工具

親愛的用戶們&#xff0c;我們都知道電腦在長時間使用后會變得越來越慢&#xff0c;垃圾文件和無用的應用程序會占用我們的硬盤空間&#xff0c;讓我們的電腦變得像蝸牛一樣慢。但是&#xff0c;現在有一個解決方案可以讓你的電腦重獲新生&#xff0c;那就是CleanMyMac X&#…