vue3使用mermaid生成圖表,并可編輯

效果圖

實際代碼


<template><div class="mermaid-container" style="z-index: 99999" ref="wrapperRef"><!-- 控制欄 --><div class="control-bar"><div class="control-bar-flex control-bar-tab-wrap"><div :class="['control-bar-tab-item', showCode ? '' : 'control-bar-tab-item-active']" @click="toggleCode">圖表</div><div :class="['control-bar-tab-item', showCode ? 'control-bar-tab-item-active' : '']" @click="toggleCode">代碼</div></div><div class="control-bar-flex"><div v-if="showCode"><div class="control-bar-dropdown" style="margin-right: 8px" @click="onCopy"><icon-park type="copy" size="16" theme="outline" fill="rgba(82,82,82)" style="margin-right: 4px"></icon-park><span>復制</span></div></div><template v-else><el-tooltip class="box-item" effect="dark" content="縮小" placement="top"><icon-park type="zoom-out" size="16" theme="outline" fill="rgba(82,82,82)" @click="zoomOut" style="margin-right: 16px; cursor: pointer"></icon-park></el-tooltip><el-tooltip class="box-item" effect="dark" content="放大" placement="top"><icon-park type="zoom-in" size="16" theme="outline" fill="rgba(82,82,82)" @click="zoomIn" style="margin-right: 16px; cursor: pointer"></icon-park></el-tooltip><div class="control-bar-line"></div><div class="control-bar-dropdown" @click="editHandle" style="margin-right: 4px"><icon-park type="edit" size="16" theme="outline" fill="rgba(82,82,82)" style="margin-right: 4px"></icon-park><span>編輯</span></div></template><el-dropdown trigger="click"><div class="control-bar-dropdown"><icon-park type="download" size="16" theme="outline" fill="rgba(82,82,82)" style="margin-right: 4px"></icon-park><span>下載</span></div><template #dropdown><el-dropdown-menu><el-dropdown-item @click="downloadSVG">下載 SVG</el-dropdown-item><el-dropdown-item @click="downloadPNG">下載 PNG</el-dropdown-item><el-dropdown-item @click="downloadCode">下載代碼</el-dropdown-item></el-dropdown-menu></template></el-dropdown></div></div><!-- 代碼/圖表切換 --><pre class="mermaid-code" v-if="showCode"><code class="hljs code-block-body">{{ code }}</code></pre><div v-else id="graphContainer" class="mermaid-chart" @mousedown="startDrag" @mouseup="stopDrag" @mouseleave="stopDrag" @mousemove="dragFlowchart"><div id="custom-output" class="mermaid-chart-container" ref="mermaidContainer" :style="{ transform: `translate3d(0, ${offsetY}px, 0) scale(${scale})`, maxWidth: `${maxWidth}px` }"><!-- {{ code }} --></div></div><div id="diagram" class="mermaid-container" style="float: left; width: 1px; height: 1px; overflow: hidden"><svg xmlns="http://www.w3.org/2000/svg" id="abc" width="200" height="200"><g transform="translate(50,50)"></g></svg></div><el-dialog v-model="showEditDialog" title="編輯" width="98%" @close="closeEditDialog" modal-class="drawioFrame-dialog" :close-on-click-modal="false"><iframe ref="drawioFrame" :src="iframeSrc" style="width: calc(100% - 4px); height: calc(100% - 4px); border: 0"></iframe><template #footer><!-- <el-button @click="showEditDialog = false">關閉編輯器</el-button> --></template></el-dialog></div>
</template><script setup lang="ts" name="MermaidDiagram">
import { ref, onMounted, nextTick, watch, inject } from 'vue'
import hljs from 'highlight.js'const props = defineProps({code: {type: String,required: true},dialogVisible: {type: Boolean,default: false}
})const onceMessage = inject('$onceMessage')
const showCode = ref(false)
const scale = ref(1)
const mermaidContainer = ref(null)
const maxWidth = ref(0)
const wrapperRef = ref(null)
const svgHeight = ref(0)
const svgWidth = ref(0)
const isDragging = ref(false)
const offsetY = ref(0) // 縱向偏移量
const startY = ref(0) // 鼠標按下時的初始Y坐標
const showEditDialog = ref(false)
const drawioFrame = ref(null)
const iframeSrc = ref('https://embed.diagrams.net/?embed=1&ui=atlas&spin=1&proto=json')
const baseXml = ref(``)
const isDrawioReady = ref(false)// 合并初始化監聽(優化邏輯)
const initMessageHandler = () => {// 確保每次對話框打開時重新監聽window.addEventListener('message', handleDrawioMessage)
}// 初始化Mermaid
onMounted(() => {refreshMermaid()initMermaid()calculateMaxWidth()window.addEventListener('resize', calculateMaxWidth)initMessageHandler()
})const calculateMaxWidth = () => {if (wrapperRef.value) {maxWidth.value = wrapperRef.value.clientWidth}
}// 監聽顯示狀態變化
watch(() => showCode.value,newVal => {if (newVal) {nextTick(() => {// 具體高亮方式選其一// 方式1:全局重新高亮hljs.highlightAll()// 方式2:定向高亮(推薦)const codeBlocks = document.querySelectorAll('.mermaid-code code')codeBlocks.forEach(block => {hljs.highlightElement(block)})})}}
)// 監聽顯示狀態變化
// watch(
// ? ? () => [props.code,props.dialogVisible],
// ? ? newVal => {
// ? ? ? ? if (newVal[0] && newVal[1]) {
// ? ? ? ? ? ? refreshMermaid()
// ? ? ? ? ? ? initMermaid()
// ? ? ? ? }
// ? ? }
// )const initMermaid = () => {mermaid.initialize({startOnLoad: false,theme: 'default',flowchart: {useMaxWidth: false,htmlLabels: true,curve: 'basis'},securityLevel: 'loose' // 允許SVG操作})renderDiagram()
}const renderDiagram = async () => {await nextTick()if (mermaidContainer.value) {try {// 使用 mermaid.init 生成流程圖,并傳入回調函數// mermaid.init(undefined, mermaidContainer.value, () => {// ? ? // 在回調函數中獲取高度// ? ? const svgElement = mermaidContainer.value.querySelector('svg')// ? ? if (svgElement) {// ? ? ? ? // 獲取 viewBox 高度,這是 Mermaid 渲染后的實際高度// ? ? ? ? const viewBox = svgElement.viewBox?.baseVal// ? ? ? ? const height = viewBox?.height || svgElement.getBoundingClientRect().height// ? ? ? ? const width = viewBox?.width || svgElement.getBoundingClientRect().width// ? ? ? ? console.log('Mermaid渲染后高度:', height)// ? ? ? ? console.log('Mermaid渲染后width:', width)// ? ? ? ? svgHeight.value = height// ? ? ? ? svgWidth.value = width// ? ? ? ? // 計算縮放比例// ? ? ? ? if (height > 546) {// ? ? ? ? ? ? const targetScale = 546 / height// ? ? ? ? ? ? scale.value = Math.min(targetScale, 1)// ? ? ? ? ? ? console.log(`自動縮放: 原始高度${height}px, 縮放比例${targetScale.toFixed(2)}`)// ? ? ? ? } else {// ? ? ? ? ? ? scale.value = 1// ? ? ? ? }// ? ? }// })const input = props.codeconst outputId = 'mermaid-' + Math.random().toString(36).substr(2, 9)// 使用render方法渲染圖表mermaid.render(outputId, input).then(result => {mermaidContainer.value.innerHTML = result.svgsetTimeout(() => {// 在回調函數中獲取高度const svgElement = mermaidContainer.value.querySelector('svg')if (svgElement) {// 獲取 viewBox 高度,這是 Mermaid 渲染后的實際高度const viewBox = svgElement.viewBox?.baseValconst height = viewBox?.height || svgElement.getBoundingClientRect().heightconst width = viewBox?.width || svgElement.getBoundingClientRect().widthconsole.log('Mermaid渲染后高度:', height)console.log('Mermaid渲染后width:', width)svgHeight.value = heightsvgWidth.value = width// ? ? // 計算縮放比例if (height > 546) {const targetScale = 546 / heightscale.value = Math.min(targetScale, 1)console.log(`自動縮放: 原始高度${height}px, 縮放比例${targetScale.toFixed(2)}`)} else {scale.value = 1}}}, 0)}).catch(error => {console.error('渲染錯誤:', error)mermaidContainer.value.innerHTML = '<div style="color: red; padding: 10px; background-color: #ffe6e6;">渲染錯誤: ' + error.message + '</div>'})} catch (err) {console.error('Mermaid渲染錯誤:', err)}}
}// 控制方法
const toggleCode = () => {showCode.value = !showCode.valuesetTimeout(() => {if (!showCode.value) {refreshMermaid()initMermaid()}}, 0)
}const refreshMermaid = () => {scale.value = 1isDragging.value = falseoffsetY.value = 0startY.value = 0showCode.value = false
}const draw = async (diag: any) => {let conf5 = mermaid.getConfig2()if (diag.db.getData) {const data4Layout = diag.db.getData()const direction = diag.db.getDirection()data4Layout.type = diag.typedata4Layout.layoutAlgorithm = 'dagre'data4Layout.direction = directiondata4Layout.nodeSpacing = conf5?.nodeSpacing || 50data4Layout.rankSpacing = conf5?.rankSpacing || 50data4Layout.markers = ['point', 'circle', 'cross']data4Layout.diagramId = 'id-111'return data4Layout}return null
}const svgToImage = (svgString: any, format = 'png') => {return new Promise((resolve, reject) => {try {// 創建SVG圖像const svgBlob = new Blob([svgString], { type: 'image/svg+xml;charset=utf-8' })const svgUrl = URL.createObjectURL(svgBlob)// 加載圖像const img = new Image()img.onload = function () {try {// 創建canvasconst canvas = document.createElement('canvas')const ctx = canvas.getContext('2d')canvas.width = img.widthcanvas.height = img.heightctx.drawImage(img, 0, 0)const imageData = canvas.toDataURL(`image/${format}`, 0.9)URL.revokeObjectURL(svgUrl)resolve({data: imageData,width: img.width,height: img.height})} catch (err) {reject(`轉換canvas時出錯: ${err.message}`)}}img.onerror = function () {URL.revokeObjectURL(svgUrl)reject('SVG加載失敗')}img.src = svgUrl} catch (err) {reject(`SVG解析錯誤: ${err.message}`)}})
}const svgToBase64 = (svgContent: any) => {// 處理Unicode字符const bytes = new TextEncoder().encode(svgContent)const binString = Array.from(bytes, byte => String.fromCharCode(byte)).join('')const base64 = btoa(binString)return `shape=image;noLabel=1;verticalAlign=top;imageAspect=1;image=data:image/svg+xml,${base64}`
}const createDrawIoXml = (imageData: any, width: any, height: any, text: any) => {const uuid = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {const r = (Math.random() * 16) | 0const v = c === 'x' ? r : (r & 0x3) | 0x8return v.toString(16)})// 創建draw.io XML文件內容let xml = ''xml += '<mxGraphModel dx="0" dy="0" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="' + width + '" pageHeight="' + height + '">\n'xml += ' ?<root>\n'xml += ' ? ?<mxCell id="0" />\n'xml += ' ? ?<mxCell id="1" parent="0" />\n'xml += ' ? ?<UserObject label="" mermaidData="' + text + '" id="' + uuid + '">\n'xml += ' ? ? ?<mxCell style="' + imageData + ';" vertex="1" parent="1">\n'xml += ' ? ? ? ? <mxGeometry x="0" y="0" width="' + width + '" height="' + height + '" as="geometry" />\n'xml += ' ? ? ?</mxCell>\n'xml += ' ? ?</UserObject>\n'xml += ' ?</root>\n'xml += '</mxGraphModel>\n'return xml
}const start = async () => {let mermaidText = props.codeconst diagram = await mermaid.mermaidAPI.getDiagramFromText(mermaidText)// console.log('完整的解析結果:', diagram)let data4Layout = await draw(diagram)if (data4Layout) {console.log('完整的解析結果:', data4Layout)console.log(mermaid.select_default2('#diagram'))const ss = mermaid.select_default2('#abc')let ddd = await mermaid.render3(data4Layout, ss)const drawio = mxMermaidToDrawio(ddd, data4Layout.type, {})// console.log('===========drawio', drawio)return drawio} else {console.log('沒有解析到數據')const result = await mermaid.render('diagram2', mermaidText)const imageResult = await svgToImage(result.svg)const data = svgToBase64(result.svg)console.log(imageResult)let d = { data: mermaidText }const jsonString = JSON.stringify(d)const escapedJson = jsonString.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>').replace(/"/g, '"')console.log(escapedJson)const drawioXml = createDrawIoXml(data, svgWidth.value, svgHeight.value, escapedJson)console.log('=========drawioXml', drawioXml)return drawioXml}
}const editHandle = async () => {baseXml.value = await start()showEditDialog.value = trueawait nextTick()
}// 2. 監聽 draw.io 的初始化完成事件
const handleDrawioMessage = event => {if (event.data === '{"event":"init"}') {isDrawioReady.value = truetryLoadDiagram()}
}// 3. 只有 iframe 和 draw.io 都就緒時,才發送 XML
const tryLoadDiagram = () => {if (isDrawioReady.value) {loadDiagram()}
}// 調整對話框關閉事件處理
const closeEditDialog = () => {showEditDialog.value = falseisDrawioReady.value = false // 重置狀態initMessageHandler() // 重新綁定監聽以便下次使用
}const loadDiagram = () => {const frame = drawioFrame.valueif (frame) {frame.contentWindow.postMessage(JSON.stringify({action: 'load',xml: baseXml.value}),'*')}
}const zoomIn = () => {// scale.value = Math.min(scale.value + 0.1, 2)const newScale = scale.value + 0.1const scaledWidth = (mermaidContainer.value?.scrollWidth || 0) * newScale// 只有當縮放后寬度小于容器寬度時才允許放大if (scaledWidth <= maxWidth.value) {scale.value = newScale} else {// 自動調整到最大允許比例scale.value = maxWidth.value / (mermaidContainer.value?.scrollWidth || maxWidth.value)}
}const zoomOut = () => {scale.value = Math.max(scale.value - 0.1, 0.5)
}const downloadSVG = () => {const svg = mermaidContainer.value?.querySelector('svg')if (!svg) returnconst serializer = new XMLSerializer()const source = serializer.serializeToString(svg)const svgBlob = new Blob([source], { type: 'image/svg+xml' })downloadFile(svgBlob, 'diagram.svg')
}const downloadPNG = async () => {const svg = mermaidContainer.value?.querySelector('svg')if (!svg) returnconst canvas = document.createElement('canvas')const ctx = canvas.getContext('2d')const data = new XMLSerializer().serializeToString(svg)const img = new Image()img.onload = () => {canvas.width = svgWidth.valuecanvas.height = svgHeight.valuectx.drawImage(img, 0, 0)canvas.toBlob(blob => {downloadFile(blob, 'diagram.png')}, 'image/png')}img.src = 'data:image/svg+xml;base64,' + btoa(unescape(encodeURIComponent(data)))
}const downloadCode = async () => {// 創建 Blob 對象const blob = new Blob([props.code], { type: 'text/plain' })downloadFile(blob, 'diagram.mermaid')
}const downloadFile = (blob, filename) => {const link = document.createElement('a')link.href = URL.createObjectURL(blob)link.download = filenamedocument.body.appendChild(link)link.click()document.body.removeChild(link)
}const onCopy = () => {const textarea = document.createElement('textarea') // 直接構建textareatextarea.value = `${props.code}` // 設置內容document.body.appendChild(textarea) // 添加臨時實例textarea.select() // 選擇實例內容document.execCommand('Copy') // 執行復制document.body.removeChild(textarea) // 刪除臨時實例onceMessage.success('復制成功')
}// 開始拖動
const startDrag = e => {isDragging.value = truestartY.value = e.clientYdocument.body.style.cursor = 'grab' // 五指抓取手勢document.body.style.userSelect = 'none' // 禁用文本選擇
}// 停止拖動
const stopDrag = () => {if (!isDragging.value) returnisDragging.value = falsedocument.body.style.cursor = '' // 恢復默認光標document.body.style.userSelect = '' // 恢復文本選擇
}// 拖動中計算位置
const dragFlowchart = e => {if (!isDragging.value) returnconst deltaY = e.clientY - startY.valueoffsetY.value += deltaYstartY.value = e.clientY // 更新當前鼠標位置// 根據縮放比例動態計算最大偏移量const containerHeight = 546 // 容器固定高度const scaledHeight = svgHeight.value * scale.value // 縮放后的實際高度const maxOffset = Math.max(0, scaledHeight - containerHeight) // 計算最大可偏移量// 限制拖動邊界offsetY.value = Math.max(-maxOffset, Math.min(maxOffset, offsetY.value))
}
</script><style lang="scss">
.drawioFrame-dialog {max-height: calc(100vh) !important;.ep-dialog {padding: 4px;height: calc(96vh) !important;}.ep-dialog__header {margin-bottom: 2px;}.ep-dialog__headerbtn {top: -4px;}.ep-dialog__body {padding: 0 !important;margin: 0 !important;max-height: 100% !important;height: calc(96vh - 24px - 8px) !important;}.ep-dialog__footer {display: none;}
}
</style>
<style lang="scss" scoped>
.mermaid-container {// border: 1px solid #eee;border-radius: 12px;// padding: 10px;// margin: 20px 0;background-color: #fafafa;color: #494949;.control-bar {display: flex;border-radius: 12px 12px 0 0;justify-content: space-between;display: flex;padding: 6px 14px 6px 6px;background-color: #f5f5f5;.control-bar-flex {display: flex;justify-content: center;align-items: center;color: rgba(82, 82, 82);}.control-bar-tab-wrap {background-color: rgba(0, 0, 0, 0.03);border-radius: 8px;}.control-bar-tab-item {height: 26px;font-size: 12px;white-space: nowrap;cursor: pointer;border-radius: 8px;flex: 1;justify-content: center;align-items: center;padding: 0 14px;font-weight: 400;display: flex;position: relative;}.control-bar-tab-item-active {display: flex;background-color: #fff;font-weight: 600;box-shadow: 0 0 4px 0 rgba(0, 0, 0, 0.02), 0 6px 10px 0 rgba(0, 0, 0, 0.04);}.control-bar-line {width: 1px;height: 14px;margin-right: 12px;background-color: rgba(187, 187, 187, 1);}.control-bar-dropdown {cursor: pointer;display: flex;align-items: center;cursor: pointer;padding: 0px 4px;height: 28px;font-size: 12px;color: rgba(82, 82, 82);border-radius: 12px;&:hover {background-color: rgba(0, 0, 0, 0.04);}}}
}.mermaid-chart {overflow: auto;background-color: #fafafa;border-radius: 0 0 12px 12px;overflow: hidden;max-height: 546px;display: flex;justify-content: center;align-items: center;user-select: none; // 禁用文本選擇will-change: transform; // 提示瀏覽器優化渲染.mermaid-chart-container {will-change: transform; // 提示瀏覽器優化渲染user-select: none; // 禁用文本選擇}/* 鼠標按下時切換為激活手勢 */.mermaid-flowchart:active {cursor: grabbing;}
}.mermaid-chart > div {display: flex;justify-content: center;align-items: center;width: 100%;height: 100%;
}.mermaid-code {background-color: #fafafa;padding: calc(9.144px) calc(13.716px) calc(9.144px) calc(13.716px);white-space: pre-wrap;overflow: auto;text-align: left;border-radius: 0 0 12px 12px;font-size: 12px;
}.icon {font-style: normal;
}
</style>

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

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

相關文章

tcp/quic 的滑動窗口

一、滑動窗口 rwnd&#xff1a; 接收端窗口&#xff0c;接收方在每次發送ACK確認報文時&#xff0c;會包含一個 rwnd (Receive Window Size) 字段&#xff0c;指明自己當前剩余的接收緩沖區大小&#xff08;即可用窗口&#xff09;&#xff0c;這里是否是socket的接收緩沖區&am…

JVM監控及診斷工具-命令行篇

18.1. 概述 性能診斷是軟件工程師在日常工作中需要經常面對和解決的問題&#xff0c;在用戶體驗至上的今天&#xff0c;解決好應用的性能問題能帶來非常大的收益。 Java 作為最流行的編程語言之一&#xff0c;其應用性能診斷一直受到業界廣泛關注。可能造成 Java 應用出現性能…

Jenkins 版本升級與插件問題深度復盤:從 2.443 到 2.504.3 及功能恢復全解析

前言&#xff1a;問題溯源與升級必要性 在 Jenkins 持續集成體系中&#xff0c;插件生態是其強大功能的核心驅動力。然而&#xff0c;某次例行維護中&#xff0c;團隊對 Jenkins 2.443 環境的插件進行批量升級后&#xff0c;意外觸發連鎖反應 &#xff1a; SSH Server 插件功能…

Ribbon實戰

一、前置知識 1.1 負載均衡定義 負載均衡指的是將網絡請求通過不同的算法分配到不同的服務器上的技術&#xff0c;從而提升系統的性能。 1.2 負載均衡工具 負載均衡工具可以分分為客戶端負載均衡工具和服務端負載均衡工具&#xff0c;它們的區別如下。 表1-1 負載均衡工具…

cs285學習筆記(一):課程總覽

根據 Fall 2023 學期的官方課程日程&#xff0c;這里是 CS?285 全課程的 Lecture 大綱及內容摘要&#xff0c;詳細對應周次和主題&#xff0c;方便你快速定位每節課要點、相關作業與視頻資源 &#x1f3af; 官方課程地址 YouTobe 視頻地址 blibli視頻(帶中文字幕) &#x…

OkHttp SSE 完整總結(最終版)

1. SSE 基礎概念 什么是 SSE&#xff1f; SSE&#xff08;Server-Sent Events&#xff09;是一種 Web 標準&#xff0c;允許服務器向客戶端推送實時數據。 核心特點 單向通信&#xff1a;服務器 → 客戶端 基于 HTTP 協議&#xff1a;使用 GET 請求 長連接&#xff1a;連…

聚寬sql數據庫傳遞

自建數據庫從聚寬到Q-MT自動化交易實戰 從接觸聚寬以來一直都是手動跟單&#xff0c;在網上看到許多大佬的自動交易文章&#xff0c;心里也不禁十分癢癢。百說不如一練&#xff0c;千講不如實干。經過一番努力&#xff0c;終于成功實盤了&#xff0c;效果還可以&#xff0c;幾…

es里為什么node和shard不是一對一的關系

提問&#xff1a; 既然多個shard會被分配到同一個node上&#xff0c;那么為什么不把多個shard合并成一個然后存在當前node上呢&#xff0c;簡而言之也就是讓node和shard形成一對一的關系呢 &#xff1f;非常好的問題&#xff0c;這正是理解Elasticsearch分片&#xff08;shard…

淺談npm,cnpm,pnpm,npx,nvm,yarn之間的區別

首先做一個基本的分類 名稱描述npm,cnpm,yarn,pnpm都是Javascript包管理器nvm是Node.js版本控制器npx命令行工具 I.npm,cnpm,yarn,pnpm npm (Node Package Manager) npm是Node.js默認的包管理器&#xff0c;隨Node.js的安裝會一起安裝。使用npm可以安裝&#xff0c;發布&…

滑動窗口-76.最小覆蓋子串-力扣(LeetCode)

一、題目解析1.不符合要求則返回空串("")2.子串中重復字符的數量要不少于t中該字符的數量二、算法原理解法1&#xff1a;暴力枚舉哈希表這里的暴力枚舉也可以優化&#xff0c;即在包含t中元素處枚舉&#xff0c;如在A、B和C處開始枚舉&#xff0c;減少不必要的枚舉 解…

從零構建搜索引擎 build demo search engine from scratch

從零構建搜索引擎 build demo search engine from scratch 我們每天都會使用搜索引擎&#xff1a;打開google等搜索引擎&#xff0c;輸入關鍵詞&#xff0c;檢索出結果&#xff0c;這是一次搜索&#xff1b;當打開歷史記錄旁邊的&#x1f50d;按鈕&#xff0c;輸入關鍵詞&#…

pytorch小記(二十九):深入解析 PyTorch 中的 `torch.clip`(及其別名 `torch.clamp`)

pytorch小記&#xff08;二十九&#xff09;&#xff1a;深入解析 PyTorch 中的 torch.clip&#xff08;及其別名 torch.clamp&#xff09;深入解析 PyTorch 中的 torch.clip&#xff08;及其別名 torch.clamp&#xff09;一、函數簽名二、簡單示例三、廣播支持四、與 Autograd…

快速分頁wpf

/*沒有在xaml設置上下文window.context是因為 命名空間一直對應不上 所以在xaml.cs 里面綁定*/ <Window x:Class"DataGrid.views.MainWindow"xmlns"http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x"http://schemas.microsoft…

如何徹底禁用 Chrome 自動更新

如何徹底禁用 Chrome 自動更新 隨著谷歌將 Chrome 瀏覽器版本升級至 138&#xff0c;它即將徹底拋棄對 Manifest V2 擴展的支持。許多用戶希望將瀏覽器版本鎖定在 138&#xff0c;以繼續使用 uBlock Origin、Tampermonkey 等常用擴展。 本文總結了四種有效方法&#xff0c;幫助…

流批一體的“奧卡姆剃刀”:Apache Cloudberry 增量物化視圖應用解析

引言&#xff1a;流批一體&#xff0c;理想與現實的鴻溝 在數據驅動的今天&#xff0c;“實時”二字仿佛擁有魔力&#xff0c;驅使著無數企業投身于流批一體架構的建設浪潮中。我們渴望實時洞察業務變化&#xff0c;實時響應用戶需求。以 Apache Flink 為代表的流處理引擎&…

C# 入門教程(三):詳解字段、屬性、索引器及各類參數與擴展方法

文章目錄一、字段、屬性、索引器、常量1.字段2.屬性2.1 什么是屬性2.2 屬性的聲明2.3 屬性與字段的關系3 索引器4. 常量二、傳值 輸出 引用 數組 具名 可選參數&#xff0c;擴展方法2.1 傳值參數2.1.1 值類型 傳參2.1.2 引用類型 傳參2.2 引用參數2.2.1 引用參數-值類型 傳參2.…

《美術教育研究》是什么級別的期刊?是正規期刊嗎?能評職稱嗎?

?問題解答&#xff1a;問&#xff1a;《美術教育研究》是不是核心期刊&#xff1f;答&#xff1a;不是&#xff0c;是知網收錄的第一批認定學術期刊。問&#xff1a;《美術教育研究》級別&#xff1f;答&#xff1a;省級。主管單位&#xff1a; 安徽出版集團有限責任公司 主辦…

每日算法刷題Day47:7.13:leetcode 復習完滑動窗口一章,用時2h30min

思考: 遇到子數組/子字符串可以考慮能不能用滑動窗口&#xff0c; 定長:逆向思維,答案不定 最大長度/最小長度:一般求長度 越長越合法/越短越合法/恰好:一般求數量 主要思考窗口條件成立&#xff0c; 判斷條件是符合窗口條件(最小長度/越長越合法還是不符合(最大長度/越短越合法…

電流驅動和電壓驅動的區別

理解電流驅動和電壓驅動的區別對電路設計至關重要&#xff0c;尤其在高速、高抗噪要求的場景&#xff08;如LVDS&#xff09;。以下是兩者的核心對比&#xff1a;一、電壓驅動 (Voltage Drive) 核心原理&#xff1a; 驅動器輸出一個受控的電壓&#xff08;與負載阻抗無關&#…

宿舍電費查詢——以ZUA為例

宿舍電費查詢——以ZUA為例0. 安裝抓包環境手機端桌面端1. 登錄1.1 開啟抓包后進入繳費頁面&#xff1a;1.2 分析請求1.3 編寫登錄代碼2. 獲取樓棟及房間ID2.1 獲取樓棟ID2.2 編寫獲取樓棟ID代碼2.3 獲取房間ID2.4 編寫獲取房間ID代碼3. 獲取剩余電費&#xff1a;3.1 選擇房間號…