本地部署Scratch在線編輯器

1、說明

由于在GitHub上沒有找到Scratch源碼,所以只能編寫腳本下載官網相關資源,然后在本地部署。
如果你找到了Scratch源碼,請自行編譯部署,可忽略以下操作。
項目結構:scratch.mit.edu
|-- chunks
|   |-- fetch-worker.7a0adc94df277ffeb963.js
|   `-- static
|       `-- extension-assets
|           `-- scratch3_music
|               `-- 420991e0d6d99292c6d736963842536a.wav
|-- common.css
|-- css
|   `-- lib
|       `-- normalize.min.css
|-- favicon.ico
|-- http-server.go
|-- index.html
|-- internalapi
|   `-- asset
|       |-- 圖片/音頻文件
|-- js
|   |-- common.bundle.js
|   |-- polyfill.min.js
|   |-- projects.bundle-bak.js
|   |-- projects.bundle.js
|   |-- projects.intl.js
|   |-- splash.bundle.js
|   `-- splash.intl.js
|-- main-v1.go
|-- main-v2.go
|-- main-v3.go
|-- projects
|   `-- editor
|       `-- index.html
|-- projects.css
|-- session
|-- splash.css
`-- static|-- assets|   |-- 圖片文件`-- blocks-media|-- default|   |-- dropdown-arrow.svg|   |-- green-flag.svg|   |-- repeat.svg|   |-- rotate-left.svg|   |-- rotate-right.svg|   |-- zoom-in.svg|   |-- zoom-out.svg|   `-- zoom-reset.svg`-- high-contrast|-- dropdown-arrow.svg|-- green-flag.svg|-- repeat.svg|-- rotate-left.svg|-- rotate-right.svg|-- zoom-in.svg|-- zoom-out.svg`-- zoom-reset.svg
go版本:go1.22.2執行go腳本命令:go run xxx.gogo腳本使用了代理來下載文件,如果不需要代理,直接使用go的http.Get來下載

2、下載index.html

手動下載以下文件,地址如下所示:https://scratch.mit.edu/projects/editor/index.htmlhttps://scratch.mit.edu/favicon.icohttps://scratch.mit.edu/css/lib/normalize.min.css
https://scratch.mit.edu/common.css
https://scratch.mit.edu/splash.csshttps://scratch.mit.edu/js/polyfill.min.js
https://scratch.mit.edu/js/common.bundle.js
https://scratch.mit.edu/js/splash.intl.js
https://scratch.mit.edu/js/splash.bundle.js如果需要其他資源,請手動繼續下載

3、下載projects/editor/index.html

手動下載以下文件,地址如下所示:// 將index.html文件保存到projects/editor目錄
https://scratch.mit.edu/projects/editor/index.html如果需要其他資源,請手動繼續下載

main-v1.go文件

根據projects/editor/index.html文件內容,提取圖片/音頻鏈接,然后下載

package mainimport ("fmt""io""net/http""net/url""os""regexp""strings"
)func main() {// https://scratch.mit.edu/projects/editor/// 1、解析html文件fmt.Println("parse html start...")urls, err := parseHtml()if err != nil {fmt.Println("parse html err: ", err)return}if len(urls) == 0 {fmt.Println("none")return}fmt.Println("parse html end...")// 2、創建目錄fmt.Println("create dir start...")createDir(urls)fmt.Println("create dir end...")// 3、下載fmt.Println("download start...")download(urls)fmt.Println("download end...")
}// 解析html
func parseHtml() ([]string, error) {filename := "projects/editor/index.html"f, err := os.Open(filename)if err != nil {return nil, err}defer f.Close()b, _ := io.ReadAll(f)s := string(b)hrefRule := `href="[^http](.*)"`srcRule := `src="[^http](.*)"`urlRes := make([]string, 0)hrefReg := regexp.MustCompile(hrefRule)hrefRes := hrefReg.FindAllStringSubmatch(s, -1)for _, v := range hrefRes {urlRes = append(urlRes, v[1])}srcReg := regexp.MustCompile(srcRule)srcRes := srcReg.FindAllStringSubmatch(s, -1)for _, v := range srcRes {urlRes = append(urlRes, v[1])}// fmt.Println(hrefRes)// fmt.Println(srcRes)// fmt.Println(urlRes)return urlRes, nil
}// 創建目錄
func createDir(data []string) {m := make(map[string]bool)for _, v := range data {if _, ok := m[v]; !ok {arr := strings.Split(v, "/")s := strings.Join(arr[:len(arr)-1], "/")if len(s) == 0 {continue}if err := os.MkdirAll(s, 0666); err == nil {m[v] = true} else {fmt.Println("create dir err: ", err)}}}
}// 下載
func download(data []string) {for _, v := range data {s := fmt.Sprintf("%s%s", "https://scratch.mit.edu/", v)// resp, err := http.Get(s)req, _ := http.NewRequest(http.MethodGet, s, nil)req.Header.Add("user-agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/134.0.0.0 Safari/537.36")// 設置代理tr := &http.Transport{Proxy: http.ProxyURL(&url.URL{Scheme: "http",Host:   "127.0.0.1:7890",}),}client := &http.Client{Transport: tr,}// 發起http的get請求resp, err := client.Do(req)if err != nil {fmt.Println("http request err: ", err)continue}defer resp.Body.Close()// 讀取內容b, err := io.ReadAll(resp.Body)if err != nil {fmt.Println("read body err: ", err)continue}// 寫入文件err = os.WriteFile(v, b, 0666)if err != nil {fmt.Println("write file err: ", err)}}
}

main-v2.go文件

運行項目,發現部分資源缺失導致頁面顯示異常,需要下載缺失資源

package mainimport ("fmt""io""net/http""net/url""os""regexp""strings"
)// 啟動項目后,發現部分資源缺失導致頁面顯示異常,需要下載以下資源
var links = []string{"chunks/fetch-worker.7a0adc94df277ffeb963.js",// "https://api.scratch.mit.edu/projects/undefined","static/blocks-media/default/zoom-out.svg","static/blocks-media/default/zoom-in.svg","static/blocks-media/default/zoom-reset.svg","static/blocks-media/default/dropdown-arrow.svg","static/blocks-media/default/green-flag.svg","static/blocks-media/default/repeat.svg","static/blocks-media/default/rotate-right.svg","static/blocks-media/default/rotate-left.svg","chunks/static/extension-assets/scratch3_music/420991e0d6d99292c6d736963842536a.wav","static/blocks-media/high-contrast/zoom-out.svg","static/blocks-media/high-contrast/zoom-in.svg","static/blocks-media/high-contrast/zoom-reset.svg","static/blocks-media/high-contrast/dropdown-arrow.svg","static/blocks-media/high-contrast/green-flag.svg","static/blocks-media/high-contrast/repeat.svg","static/blocks-media/high-contrast/rotate-right.svg","static/blocks-media/high-contrast/rotate-left.svg",
}func main() {// https://scratch.mit.edu/projects/editor/// 1、解析html文件// fmt.Println("parse html start...")// urls, err := parseHtml()// if err != nil {// 	fmt.Println("parse html err: ", err)// 	return// }// if len(urls) == 0 {// 	fmt.Println("none")// 	return// }// fmt.Println("parse js end...")// 2、創建目錄fmt.Println("create dir start...")createDir(links)fmt.Println("create dir end...")// 3、下載fmt.Println("download start...")download(links)fmt.Println("download end...")
}// 解析html
func parseHtml() ([]string, error) {filename := "projects/editor/index.html"f, err := os.Open(filename)if err != nil {return nil, err}defer f.Close()b, _ := io.ReadAll(f)s := string(b)hrefRule := `href="[^http](.*)"`srcRule := `src="[^http](.*)"`urlRes := make([]string, 0)hrefReg := regexp.MustCompile(hrefRule)hrefRes := hrefReg.FindAllStringSubmatch(s, -1)for _, v := range hrefRes {urlRes = append(urlRes, v[1])}srcReg := regexp.MustCompile(srcRule)srcRes := srcReg.FindAllStringSubmatch(s, -1)for _, v := range srcRes {urlRes = append(urlRes, v[1])}// fmt.Println(hrefRes)// fmt.Println(srcRes)// fmt.Println(urlRes)return urlRes, nil
}// 創建目錄
func createDir(data []string) {m := make(map[string]bool)for _, v := range data {if _, ok := m[v]; !ok {arr := strings.Split(v, "/")s := strings.Join(arr[:len(arr)-1], "/")if len(s) == 0 {continue}if err := os.MkdirAll(s, 0666); err == nil {m[v] = true} else {fmt.Println("create dir err: ", err)}}}
}// 下載
func download(data []string) {for _, v := range data {s := fmt.Sprintf("%s%s", "https://scratch.mit.edu/", v)// resp, err := http.Get(s)req, _ := http.NewRequest(http.MethodGet, s, nil)req.Header.Add("user-agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/134.0.0.0 Safari/537.36")// 設置代理tr := &http.Transport{Proxy: http.ProxyURL(&url.URL{Scheme: "http",Host:   "127.0.0.1:7890",}),}client := &http.Client{Transport: tr,}// 發起http的get請求resp, err := client.Do(req)if err != nil {fmt.Println("http request err: ", err)continue}defer resp.Body.Close()// 讀取內容b, err := io.ReadAll(resp.Body)if err != nil {fmt.Println("read body err: ", err)continue}// 寫入文件err = os.WriteFile(v, b, 0666)if err != nil {fmt.Println("write file err: ", err)}}
}

main-v3.go文件

根據js/projects.bundle.js文件內容,提取圖片/音頻鏈接,然后下載

package mainimport ("fmt""io""net/http""net/url""os""regexp""strings""sync"
)var ch chan string
var wg sync.WaitGroupvar defaultAssetPath = "static/assets" // 默認資源路徑
var cdnAssetPath = "internalapi/asset" // cdn資源路徑// 目錄
var dirPaths = []string{defaultAssetPath,cdnAssetPath,
}// 域名
var domains = map[string]string{"default": "https://scratch.mit.edu/","cdn":     "https://cdn.assets.scratch.mit.edu/",
}func main() {// 1、解析js文件fmt.Println("parse js start...")data, err := parseJs()if err != nil {fmt.Println("parse js err: ", err)return}if len(data) == 0 {fmt.Println("none")return}fmt.Println("parse js end...")// 2、創建目錄fmt.Println("create dir start...")createDir(dirPaths)fmt.Println("create dir end...")// 3、下載fmt.Println("download start...")download(data)fmt.Println("download end...")
}// 解析js文件中的圖片/音頻等資源鏈接
func parseJs() ([]string, error) {filename := "js/projects.bundle.js"f, err := os.Open(filename)if err != nil {fmt.Println("file open err: ", err)return nil, err}defer f.Close()b, _ := io.ReadAll(f)s := string(b)// static/assets/talking-3-say-something.en.8e5a33f8b13b50ff97fd.pngruleAssets := `(static\/assets\/[a-zA-Z0-9\.\-_]+\.[a-z]+)`regAssets := regexp.MustCompile(ruleAssets)resAssets := regAssets.FindAllStringSubmatch(s, -1)// md5ext:"cd21514d0531fdffb22204e0ec5ed84a.svg"ruleMd5 := `"md5ext":"([a-z0-9]+\.[a-z0-9]+)"`regMd5 := regexp.MustCompile(ruleMd5)resMd5 := regMd5.FindAllStringSubmatch(s, -1)m := make(map[string]bool) // 去重data := make([]string, 0)  // url鏈接for _, v := range resAssets {if _, ok := m[v[1]]; !ok {m[v[1]] = truedata = append(data, v[1])}}for _, v := range resMd5 {if _, ok := m[v[1]]; !ok {m[v[1]] = truedata = append(data, fmt.Sprintf("%s/%s", cdnAssetPath, v[1]))}}// fmt.Println(data)// fmt.Println(len(m))// fmt.Println(len(data)) // 未去重2661;去重1331m = nilresAssets = nilresMd5 = nilreturn data, nil
}// 創建目錄
func createDir(data []string) {for _, v := range data {err := os.MkdirAll(v, 0666)if err != nil {panic(fmt.Sprintln("create dir err: ", err))}}
}// 下載
func download(data []string) {taskNum := 20ch = make(chan string, 5)for i := 0; i < taskNum; i++ {go task(ch)}for _, v := range data {ch <- vwg.Add(1)}wg.Wait()
}// 任務
func task(data chan string) {for {select {case msg := <-data:work(msg)wg.Done()}}
}// 下載文件
func work(filename string) {// 設置代理tr := &http.Transport{Proxy: http.ProxyURL(&url.URL{Scheme: "http",Host:   "127.0.0.1:7890",}),}client := &http.Client{Transport: tr,}// 發起http的get請求link := ""if strings.HasPrefix(filename, cdnAssetPath) {link = fmt.Sprintf("%s%s/get", domains["cdn"], filename)} else {link = fmt.Sprintf("%s%s", domains["default"], filename)}resp, err := client.Get(link)if err != nil {fmt.Println("http request err: ", err)return}defer resp.Body.Close()// 讀取內容b, err := io.ReadAll(resp.Body)if err != nil {fmt.Println("read body err: ", err)return}// 寫入文件err = os.WriteFile(filename, b, 0666)if err != nil {fmt.Println("write file err: ", err)}
}

4、編寫http服務

如果不想編寫http服務,也可以使用Nginx、OpenResty等Web服務器部署項目

js/projects.bundle.js文件

# 使用Linux的sed命令# 將 https://cdn.assets.scratch.mit.edu 替換為 http://127.0.0.1:8000(即替換為ip或域名)
sed -i 's/https:\/\/cdn.assets.scratch.mit.edu/http:\/\/127.0.0.1:8000/g' js/projects.bundle.js# 將 https://assets.scratch.mit.edu 替換為 http://127.0.0.1:8000(即替換為ip或域名)
sed -i 's/https:\/\/assets.scratch.mit.edu/http:\/\/127.0.0.1:8000/g' js/projects.bundle.js

http-server.go文件

package mainimport ("io""net/http""os""strings"
)/**
1、修改index.html文件(忽略這步操作)
window.location.pathname = '/projects/editor/';2、修改js/projects.bundle.js文件
# 使用Linux的sed命令# 將 https://cdn.assets.scratch.mit.edu 替換為 http://127.0.0.1:8000(即替換為ip或域名)
sed -i 's/https:\/\/cdn.assets.scratch.mit.edu/http:\/\/127.0.0.1:8000/g' js/projects.bundle.js# 將 https://assets.scratch.mit.edu 替換為 http://127.0.0.1:8000(即替換為ip或域名)
sed -i 's/https:\/\/assets.scratch.mit.edu/http:\/\/127.0.0.1:8000/g' js/projects.bundle.js
*/func main() {// http.Handle("/", http.FileServer(http.Dir("."))) // 文件服務器http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {p := r.URL.Path// fmt.Println(p)filename := strings.Trim(p, "/")if strings.HasPrefix(p, "/internalapi/asset") && (strings.HasSuffix(p, "/get/") || strings.HasSuffix(p, "/get")) {filename = strings.Trim(strings.TrimRight(filename, "get"), "/")p = filename}typ := "text/html"if p == "/" {filename = "index.html"} else if p == "/projects/editor/" || p == "/projects/editor" {filename += "/index.html"} else if p == "/session/" || p == "/session" {typ = "application/json"} else if strings.HasSuffix(p, ".ico") {typ = "image/x-icon"} else if strings.HasSuffix(p, ".js") {typ = "application/javascript"} else if strings.HasSuffix(p, ".css") {typ = "text/css"} else if strings.HasSuffix(p, ".svg") {typ = "image/svg+xml"} else if strings.HasSuffix(p, ".wav") {typ = "audio/x-wav"} else if strings.HasSuffix(p, ".png") {typ = "image/png"} else if strings.HasSuffix(p, ".jpg") {typ = "image/jpeg"}w.Header().Add("Content-Type", typ)f, err := os.Open(filename)if err != nil {w.WriteHeader(http.StatusBadRequest)w.Write(nil)return}b, _ := io.ReadAll(f)w.Write(b)})http.ListenAndServe(":8000", nil)
}

Nginx配置文件

# 如果使用Nginx服務器部署項目,nginx.conf配置文件增加下面這段server,內容如下:server {listen 80;server_name 域名; location / {# scratch項目路徑root html/scratch.mit.edu;index index.html index.htm;}# 重寫urllocation /internalapi/asset/ {root html/scratch.mit.edu;rewrite ^/internalapi/asset/(.*)/get[\/]* /internalapi/asset/$1 break;}
}

5、運行項目

# 運行項目
go run http-server.go

效果如下:

1)瀏覽器訪問http://127.0.0.1:8000

2)點擊創建,頁面跳轉到http://127.0.0.1:8000/projects/editor/?tutorial=getStarted

6、代碼

https://gitcode.com/janthinasnail/scratch.mit.edu

7、詳見

https://scratch.mit.edu/

https://scratch.mit.edu/projects/editor/?tutorial=getStarted

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

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

相關文章

Gmsh 讀取自定義輪廓并劃分網格:深入解析與實踐指南

一、Gmsh 簡介 (一)Gmsh 是什么 Gmsh 是一款功能強大的開源有限元網格生成器,廣泛應用于工程仿真、數值模擬以及計算機圖形學等領域。它為用戶提供了從幾何建模到網格劃分的一整套解決方案,能夠有效處理復雜幾何形狀,生成高質量的二維和三維網格,滿足多種數值方法的需求…

Elabscience 精準識別 CD4+ T 細胞|大鼠源單克隆抗體 GK1.5,適配小鼠樣本的流式優選方案

內容概要 CD4 T細胞在免疫調節、自身免疫疾病及腫瘤免疫治療中發揮關鍵作用。Elabscience推出的APC Anti-Mouse CD4 Antibody (GK1.5)&#xff08;貨號&#xff1a;E-AB-F1097E&#xff09;是一款高特異性、低背景的流式抗體&#xff0c;專為小鼠CD4 T細胞亞群檢測優化設計。該…

【RabbitMQ】應用問題、仲裁隊列(Raft算法)和HAProxy負載均衡

&#x1f525;個人主頁&#xff1a; 中草藥 &#x1f525;專欄&#xff1a;【中間件】企業級中間件剖析 一、冪等性保障 什么是冪等性&#xff1f; 冪等性是指對一個系統進行重復調用&#xff08;相同參數&#xff09;&#xff0c;無論同一操作執行多少次&#xff0c;這些請求…

51 單片機頭文件 reg51.h 和 reg52.h 詳解

51 單片機頭文件詳解 51 單片機的頭文件reg51.h和reg52.h是開發中非常重要的文件,它們定義了單片機的特殊功能寄存器 (SFR) 和位地址。以下是對這兩個頭文件的詳細解析: 1. 頭文件概述 reg51.h:針對標準 8051 單片機(4KB ROM, 128B RAM) reg52.h:針對增強型 8052 單片…

前端的面試筆記——JavaScript篇(二)

一、instanceof 在 JavaScript 里&#xff0c;instanceof 是一個相當實用的運算符&#xff0c;它的主要功能是檢查某個對象是否屬于特定構造函數的實例。這里需要明確的是&#xff0c;判斷的依據并非對象的類型&#xff0c;而是其原型鏈。下面為你詳細介紹它的用法和特點&…

”一維前綴和“算法原理及模板

前綴和&#xff0c;就是通過一種方法來求出數組中某個連續區間的元素的和的辦法。我們通常先預處理出來一個前綴和數組&#xff0c;然后把數組中進行元素填充后再進行后續使用。 我們通過一道模板題或許能更加理解其意思。 現在的問題就是&#xff1a;如果我們用暴力枚舉來記錄…

5.13/14 linux安裝centos及一些操作命令隨記

一、環境準備 VMware Workstation版本選擇建議 CentOS 7 ISO鏡像下載指引 虛擬機硬件配置建議&#xff08;內存/處理器/磁盤空間&#xff09; 二、系統基礎命令 一、環境準備 1.VMware Workstation版本選擇建議 版本選擇依據 選擇VMware Workstation的版本時&#xff0c…

spring學習->sprintboot

spring IoC(控制翻轉): 控制:資源的控制權(資源的創建&#xff0c;獲取&#xff0c;銷毀等) 反轉:和傳統方式不一樣(用上面new什么)&#xff0c;不用new讓ioc來發現你用什么&#xff0c;然后我來給什么 DI:(依賴注入) 依賴:組件的依賴關系。如newsController依賴NewsServi…

iOS 閱后即焚功能的實現

iOS閱后即焚功能實現步驟 一、功能設計要點 消息類型支持&#xff1a;文本、圖片、視頻、音頻等。銷毀觸發條件&#xff1a; 接收方首次打開消息后啟動倒計時。消息存活時間可配置&#xff08;如5秒、1分鐘&#xff09;。 安全要求&#xff1a; 端到端加密&#xff08;E2EE&a…

OpenHarmony 開源鴻蒙南向開發——linux下使用make交叉編譯第三方庫——mqtt庫

準備工作 請依照這篇文章搭建環境 OpenHarmony 開源鴻蒙南向開發——linux下使用make交叉編譯第三方庫——環境配置_openharmony交叉編譯-CSDN博客 下載 wget ftp://ftp.gnutls.org/gcrypt/gnutls/v3.5/gnutls-3.5.9.tar.xz 解壓 tar -xf mkdir ./out cd ./out Cmake命…

武漢SMT貼片工藝優化與生產效能提升路徑

內容概要 隨著華中地區電子制造產業集群的快速發展&#xff0c;武漢SMT貼片行業面臨工藝升級與效能提升的雙重挑戰。本文聚焦SMT生產全流程中的關鍵環節&#xff0c;從鋼網印刷精度控制、回流焊溫度曲線優化、AOI檢測系統迭代三大核心工藝出發&#xff0c;結合區域產業鏈特點提…

線程池(ThreadPoolExecutor)實現原理和源碼細節是Java高并發面試和實戰開發的重點

一、線程池核心流程圖 ----------------- | 提交任務 | submit/execute -----------------|v ----------------- | 判斷核心線程數 | < corePoolSize&#xff1f; -----------------|Yes |Nov v [創建新線程] -----------------| 隊列是否滿&a…

學習海康VisionMaster之直方圖工具

一&#xff1a;進一步學習了 今天學習下VisionMaster中的直方圖工具&#xff1a;就是統計在ROI范圍內進行灰度級分布的統計 二&#xff1a;開始學習 1&#xff1a;什么是直方圖工具&#xff1f; 直方圖工具針對輸入灰度圖像的指定ROI區域&#xff0c;輸出該區域的圖像灰度直方…

計算機網絡 : Socket編程

計算機網絡 &#xff1a; Socket編程 目錄 計算機網絡 &#xff1a; Socket編程引言1.UDP網絡編程1.1 網絡地址與端口轉換函數1.2 本地環回1.3 EchoServer1.4 DictServer1.5 DictServer封裝版1.6 簡單聊天室 2.TCP網絡編程2.1 TCP Socket API詳解2.2 Echo Server2.3 Echo Serve…

Elasticsearch/OpenSearch 中doc_values的作用

目錄 1. 核心作用 2. 適用場景 3. 與 index 參數的對比 4. 典型配置示例 場景 1&#xff1a;僅用于聚合&#xff0c;禁止搜索 場景 2&#xff1a;優化大字段存儲 5. 性能調優建議 6. 底層原理 doc_values 是 Elasticsearch/OpenSearch 中用于優化查詢和聚合的列式存儲結…

使用mermaid 語言繪畫時序圖和鏈路圖

給大家展示一下效果&#xff0c; 官方地址&#xff1a;https://mermaid.nodejs.cn/ 官方開發地&#xff1a;https://mermaid.nodejs.cn/intro/#google_vignette graph LR%% 樣式定義&#xff08;完全保留&#xff09; classDef user fill:#E1F5FE,stroke:#0288D1;classDef …

C++ Kafka客戶端(cppkafka)安裝與問題解決指南

一、cppkafka簡介 cppkafka是一個現代C的Apache Kafka客戶端庫&#xff0c;它是對librdkafka的高級封裝&#xff0c;旨在簡化使用librdkafka的過程&#xff0c;同時保持最小的性能開銷。 #mermaid-svg-qDUFSYLBf8cKkvdw {font-family:"trebuchet ms",verdana,arial,…

STM32的ADC模塊中,**采樣時機(Sampling Time)**和**轉換時機(Conversion Time),獲取數據的時機詳解

在STM32的ADC模塊中&#xff0c;**采樣時機&#xff08;Sampling Time&#xff09;和轉換時機&#xff08;Conversion Time&#xff09;**是ADC工作流程中的兩個關鍵階段&#xff0c;直接影響采樣精度和系統實時性。以下是詳細解析&#xff1a; 1. 采樣時機&#xff08;Samplin…

Pageassist安裝(ollama+deepseek-r1)

page-assist網站&#xff1a;https://github.com/n4ze3m/page-assist 首先電腦配置node.js&#xff0c;管理員打開命令窗口輸入下面命令下載bun npm install -g buncd 到你想要安裝page-assist的地方&#xff08;推薦桌面&#xff09; 輸入下列命令 git clone https://gith…

APC 熒光通道專用!Elabscience? CD11b 抗體激發 / 發射光譜精準匹配流式檢測

內容概要 Elabscience APC Anti-Mouse/Human CD11b Antibody [M1/70]&#xff08;貨號&#xff1a;E-AB-F1081E&#xff09;是一款高特異性熒光標記抗體&#xff0c;適用于流式細胞術&#xff08;FCM&#xff09;&#xff0c;可精準檢測小鼠和人類樣本中的 CD11b 髓系細胞&…