工程化與框架系列(25)--低代碼平臺開發

低代碼平臺開發 🔧

引言

低代碼開發平臺是一種通過可視化配置和少量代碼實現應用開發的技術方案。本文將深入探討低代碼平臺的設計與實現,包括可視化編輯器、組件系統、數據流管理等關鍵主題,幫助開發者構建高效的低代碼開發平臺。

低代碼平臺概述

低代碼平臺主要包括以下核心功能:

  • 可視化編輯器:拖拽式界面設計
  • 組件系統:可配置的組件庫
  • 數據管理:數據源配置和狀態管理
  • 業務邏輯:可視化邏輯編排
  • 部署發布:應用打包和發布

可視化編輯器實現

編輯器核心架構

// 編輯器核心類
class VisualEditor {private container: HTMLElement;private components: Map<string, Component>;private selectedComponent: Component | null;private draggedComponent: Component | null;constructor(container: HTMLElement) {this.container = container;this.components = new Map();this.selectedComponent = null;this.draggedComponent = null;this.initializeEditor();}// 初始化編輯器private initializeEditor(): void {// 設置編輯器容器樣式this.container.style.position = 'relative';this.container.style.minHeight = '600px';this.container.style.border = '1px solid #ccc';// 注冊事件處理器this.registerEventHandlers();}// 注冊事件處理器private registerEventHandlers(): void {// 處理拖拽事件this.container.addEventListener('dragover', (e) => {e.preventDefault();e.dataTransfer!.dropEffect = 'copy';});this.container.addEventListener('drop', (e) => {e.preventDefault();const componentType = e.dataTransfer!.getData('componentType');const { clientX, clientY } = e;this.createComponent(componentType, {x: clientX - this.container.offsetLeft,y: clientY - this.container.offsetTop});});// 處理選擇事件this.container.addEventListener('click', (e) => {const target = e.target as HTMLElement;const componentId = target.dataset.componentId;if (componentId) {this.selectComponent(componentId);} else {this.clearSelection();}});}// 創建組件createComponent(type: string,position: { x: number; y: number }): Component {const component = new Component(type, position);this.components.set(component.id, component);const element = component.render();this.container.appendChild(element);return component;}// 選擇組件selectComponent(componentId: string): void {this.clearSelection();const component = this.components.get(componentId);if (component) {this.selectedComponent = component;component.select();}}// 清除選擇clearSelection(): void {if (this.selectedComponent) {this.selectedComponent.deselect();this.selectedComponent = null;}}// 更新組件屬性updateComponentProps(componentId: string,props: Record<string, any>): void {const component = this.components.get(componentId);if (component) {component.updateProps(props);}}// 導出頁面配置exportConfig(): Record<string, any> {const config: Record<string, any> = {components: []};this.components.forEach(component => {config.components.push(component.toJSON());});return config;}// 導入頁面配置importConfig(config: Record<string, any>): void {this.clear();config.components.forEach((componentConfig: any) => {const component = this.createComponent(componentConfig.type,componentConfig.position);component.updateProps(componentConfig.props);});}// 清空編輯器clear(): void {this.components.clear();this.container.innerHTML = '';}
}// 組件類
class Component {readonly id: string;private type: string;private position: { x: number; y: number };private props: Record<string, any>;private element: HTMLElement;constructor(type: string,position: { x: number; y: number }) {this.id = `component_${Date.now()}_${Math.random().toString(36).slice(2)}`;this.type = type;this.position = position;this.props = {};this.element = document.createElement('div');this.initialize();}// 初始化組件private initialize(): void {this.element.dataset.componentId = this.id;this.element.style.position = 'absolute';this.element.style.left = `${this.position.x}px`;this.element.style.top = `${this.position.y}px`;this.setupDraggable();}// 設置可拖拽private setupDraggable(): void {this.element.draggable = true;this.element.addEventListener('dragstart', (e) => {e.dataTransfer!.setData('componentId', this.id);});}// 渲染組件render(): HTMLElement {return this.element;}// 選中組件select(): void {this.element.style.outline = '2px solid #1890ff';}// 取消選中deselect(): void {this.element.style.outline = 'none';}// 更新屬性updateProps(props: Record<string, any>): void {this.props = { ...this.props, ...props };this.updateView();}// 更新視圖private updateView(): void {// 根據組件類型和屬性更新視圖switch (this.type) {case 'button':this.element.innerHTML = `<button style="padding: ${this.props.padding || '8px 16px'};background: ${this.props.background || '#1890ff'};color: ${this.props.color || '#fff'};border: none;border-radius: 4px;cursor: pointer;">${this.props.text || 'Button'}</button>`;break;case 'input':this.element.innerHTML = `<input type="text"style="padding: ${this.props.padding || '8px'};border: 1px solid #d9d9d9;border-radius: 4px;width: ${this.props.width || '200px'};"placeholder="${this.props.placeholder || ''}"/>`;break;default:this.element.innerHTML = `<div style="padding: 16px;background: #f0f0f0;border-radius: 4px;">${this.type}</div>`;}}// 轉換為JSONtoJSON(): Record<string, any> {return {id: this.id,type: this.type,position: this.position,props: this.props};}
}

屬性面板實現

// 屬性面板管理器
class PropertyPanel {private container: HTMLElement;private currentComponent: Component | null;private propertyConfigs: Map<string, PropertyConfig[]>;constructor(container: HTMLElement) {this.container = container;this.currentComponent = null;this.propertyConfigs = new Map();this.initializePropertyConfigs();}// 初始化屬性配置private initializePropertyConfigs(): void {// 按鈕組件屬性配置this.propertyConfigs.set('button', [{name: 'text',label: '按鈕文本',type: 'string',default: 'Button'},{name: 'background',label: '背景顏色',type: 'color',default: '#1890ff'},{name: 'color',label: '文字顏色',type: 'color',default: '#fff'},{name: 'padding',label: '內邊距',type: 'string',default: '8px 16px'}]);// 輸入框組件屬性配置this.propertyConfigs.set('input', [{name: 'placeholder',label: '占位文本',type: 'string',default: ''},{name: 'width',label: '寬度',type: 'string',default: '200px'},{name: 'padding',label: '內邊距',type: 'string',default: '8px'}]);}// 顯示組件屬性showProperties(component: Component): void {this.currentComponent = component;this.render();}// 清空屬性面板clear(): void {this.currentComponent = null;this.container.innerHTML = '';}// 渲染屬性面板private render(): void {if (!this.currentComponent) {this.clear();return;}const componentConfig = this.currentComponent.toJSON();const propertyConfigs = this.propertyConfigs.get(componentConfig.type) || [];this.container.innerHTML = `<div class="property-panel"><h3>${componentConfig.type} 屬性</h3><div class="property-list">${propertyConfigs.map(config => this.renderPropertyField(config)).join('')}</div></div>`;this.setupEventHandlers();}// 渲染屬性字段private renderPropertyField(config: PropertyConfig): string {const value = this.currentComponent?.toJSON().props[config.name] || config.default;switch (config.type) {case 'string':return `<div class="property-field"><label>${config.label}</label><input type="text"name="${config.name}"value="${value}"class="property-input"/></div>`;case 'color':return `<div class="property-field"><label>${config.label}</label><input type="color"name="${config.name}"value="${value}"class="property-color"/></div>`;default:return '';}}// 設置事件處理器private setupEventHandlers(): void {const inputs = this.container.querySelectorAll('input');inputs.forEach(input => {input.addEventListener('change', (e) => {const target = e.target as HTMLInputElement;const name = target.name;const value = target.value;if (this.currentComponent) {const props = { [name]: value };this.currentComponent.updateProps(props);}});});}
}// 屬性配置接口
interface PropertyConfig {name: string;label: string;type: 'string' | 'color' | 'number';default: any;
}

組件系統實現

組件注冊機制

// 組件注冊管理器
class ComponentRegistry {private static instance: ComponentRegistry;private components: Map<string, ComponentDefinition>;private constructor() {this.components = new Map();}static getInstance(): ComponentRegistry {if (!ComponentRegistry.instance) {ComponentRegistry.instance = new ComponentRegistry();}return ComponentRegistry.instance;}// 注冊組件registerComponent(type: string,definition: ComponentDefinition): void {this.components.set(type, definition);}// 獲取組件定義getComponentDefinition(type: string): ComponentDefinition | undefined {return this.components.get(type);}// 獲取所有組件getAllComponents(): ComponentDefinition[] {return Array.from(this.components.values());}
}// 組件定義接口
interface ComponentDefinition {type: string;title: string;icon?: string;props: PropertyConfig[];render: (props: any) => string;
}// 使用示例
const registry = ComponentRegistry.getInstance();// 注冊按鈕組件
registry.registerComponent('button', {type: 'button',title: '按鈕',icon: 'button-icon.svg',props: [{name: 'text',label: '按鈕文本',type: 'string',default: 'Button'},{name: 'background',label: '背景顏色',type: 'color',default: '#1890ff'}],render: (props) => `<button style="background: ${props.background};color: ${props.color};padding: ${props.padding};">${props.text}</button>`
});

組件拖拽實現

// 組件拖拽管理器
class DragDropManager {private container: HTMLElement;private dropTarget: HTMLElement | null;private draggedComponent: any;constructor(container: HTMLElement) {this.container = container;this.dropTarget = null;this.draggedComponent = null;this.initialize();}// 初始化拖拽功能private initialize(): void {this.setupDragEvents();this.setupDropZone();}// 設置拖拽事件private setupDragEvents(): void {// 組件列表拖拽const componentList = document.querySelectorAll('.component-item');componentList.forEach(item => {item.addEventListener('dragstart', (e) => {const target = e.target as HTMLElement;e.dataTransfer!.setData('componentType', target.dataset.type!);this.draggedComponent = {type: target.dataset.type,title: target.dataset.title};});});}// 設置放置區域private setupDropZone(): void {this.container.addEventListener('dragover', (e) => {e.preventDefault();e.dataTransfer!.dropEffect = 'copy';// 顯示放置預覽this.showDropPreview(e.clientX, e.clientY);});this.container.addEventListener('dragleave', () => {this.hideDropPreview();});this.container.addEventListener('drop', (e) => {e.preventDefault();const componentType = e.dataTransfer!.getData('componentType');if (componentType) {this.handleDrop(e.clientX, e.clientY, componentType);}this.hideDropPreview();});}// 顯示放置預覽private showDropPreview(x: number, y: number): void {if (!this.dropTarget) {this.dropTarget = document.createElement('div');this.dropTarget.className = 'drop-preview';document.body.appendChild(this.dropTarget);}const rect = this.container.getBoundingClientRect();const left = x - rect.left;const top = y - rect.top;this.dropTarget.style.left = `${left}px`;this.dropTarget.style.top = `${top}px`;}// 隱藏放置預覽private hideDropPreview(): void {if (this.dropTarget) {this.dropTarget.remove();this.dropTarget = null;}}// 處理組件放置private handleDrop(x: number, y: number, componentType: string): void {const rect = this.container.getBoundingClientRect();const position = {x: x - rect.left,y: y - rect.top};// 創建組件const registry = ComponentRegistry.getInstance();const definition = registry.getComponentDefinition(componentType);if (definition) {const component = new Component(componentType, position);component.updateProps(this.getDefaultProps(definition.props));const element = component.render();this.container.appendChild(element);}}// 獲取默認屬性值private getDefaultProps(propConfigs: PropertyConfig[]): Record<string, any> {const props: Record<string, any> = {};propConfigs.forEach(config => {props[config.name] = config.default;});return props;}
}

數據流管理

數據源配置

// 數據源管理器
class DataSourceManager {private static instance: DataSourceManager;private dataSources: Map<string, DataSource>;private constructor() {this.dataSources = new Map();}static getInstance(): DataSourceManager {if (!DataSourceManager.instance) {DataSourceManager.instance = new DataSourceManager();}return DataSourceManager.instance;}// 注冊數據源registerDataSource(name: string,config: DataSourceConfig): void {const dataSource = new DataSource(name, config);this.dataSources.set(name, dataSource);}// 獲取數據源getDataSource(name: string): DataSource | undefined {return this.dataSources.get(name);}// 執行數據源查詢async queryDataSource(name: string,params?: Record<string, any>): Promise<any> {const dataSource = this.dataSources.get(name);if (!dataSource) {throw new Error(`Data source ${name} not found`);}return dataSource.execute(params);}
}// 數據源類
class DataSource {private name: string;private config: DataSourceConfig;constructor(name: string, config: DataSourceConfig) {this.name = name;this.config = config;}// 執行數據源async execute(params?: Record<string, any>): Promise<any> {try {switch (this.config.type) {case 'api':return this.executeApi(params);case 'static':return this.executeStatic(params);default:throw new Error(`Unsupported data source type: ${this.config.type}`);}} catch (error) {console.error(`Data source ${this.name} execution failed:`, error);throw error;}}// 執行API數據源private async executeApi(params?: Record<string, any>): Promise<any> {const { url, method, headers } = this.config as ApiDataSourceConfig;const response = await fetch(url, {method: method || 'GET',headers: {'Content-Type': 'application/json',...headers},body: method !== 'GET' ? JSON.stringify(params) : undefined});if (!response.ok) {throw new Error(`API request failed: ${response.statusText}`);}return response.json();}// 執行靜態數據源private executeStatic(params?: Record<string, any>): any {const { data } = this.config as StaticDataSourceConfig;if (typeof data === 'function') {return data(params);}return data;}
}// 數據源配置接口
interface DataSourceConfig {type: 'api' | 'static';[key: string]: any;
}interface ApiDataSourceConfig extends DataSourceConfig {type: 'api';url: string;method?: string;headers?: Record<string, string>;
}interface StaticDataSourceConfig extends DataSourceConfig {type: 'static';data: any | ((params?: Record<string, any>) => any);
}// 使用示例
const dataSourceManager = DataSourceManager.getInstance();// 注冊API數據源
dataSourceManager.registerDataSource('userList', {type: 'api',url: '/api/users',method: 'GET',headers: {'Authorization': 'Bearer token'}
});// 注冊靜態數據源
dataSourceManager.registerDataSource('statusOptions', {type: 'static',data: [{ label: '啟用', value: 1 },{ label: '禁用', value: 0 }]
});

數據綁定實現

// 數據綁定管理器
class DataBindingManager {private bindings: Map<string, DataBinding[]>;constructor() {this.bindings = new Map();}// 添加數據綁定addBinding(targetId: string,binding: DataBinding): void {const bindings = this.bindings.get(targetId) || [];bindings.push(binding);this.bindings.set(targetId, bindings);}// 移除數據綁定removeBinding(targetId: string): void {this.bindings.delete(targetId);}// 執行數據綁定async executeBindings(targetId: string,context: Record<string, any>): Promise<void> {const bindings = this.bindings.get(targetId);if (!bindings) return;for (const binding of bindings) {await this.executeBinding(binding, context);}}// 執行單個綁定private async executeBinding(binding: DataBinding,context: Record<string, any>): Promise<void> {const { source, property, transform } = binding;// 獲取數據源值let value = await this.resolveSourceValue(source, context);// 應用轉換函數if (transform) {value = transform(value, context);}// 更新目標屬性this.updateTargetProperty(binding.target, property, value);}// 解析數據源值private async resolveSourceValue(source: string | DataSource,context: Record<string, any>): Promise<any> {if (typeof source === 'string') {// 從上下文中獲取值return this.getValueFromPath(context, source);} else {// 執行數據源return source.execute(context);}}// 從對象路徑獲取值private getValueFromPath(obj: any,path: string): any {return path.split('.').reduce((value, key) => {return value?.[key];}, obj);}// 更新目標屬性private updateTargetProperty(target: HTMLElement,property: string,value: any): void {switch (property) {case 'text':target.textContent = value;break;case 'value':(target as HTMLInputElement).value = value;break;case 'html':target.innerHTML = value;break;default:target.setAttribute(property, value);}}
}// 數據綁定接口
interface DataBinding {target: HTMLElement;property: string;source: string | DataSource;transform?: (value: any, context: Record<string, any>) => any;
}// 使用示例
const bindingManager = new DataBindingManager();// 添加數據綁定
const userNameInput = document.getElementById('userName')!;
bindingManager.addBinding('userForm', {target: userNameInput,property: 'value',source: 'user.name'
});// 執行數據綁定
const context = {user: {name: 'John Doe',age: 30}
};bindingManager.executeBindings('userForm', context);

最佳實踐與建議

  1. 架構設計

    • 采用模塊化設計
    • 實現插件化架構
    • 保持代碼可擴展性
    • 注重性能優化
  2. 組件開發

    • 組件粒度適中
    • 提供完整配置項
    • 實現組件聯動
    • 支持自定義擴展
  3. 數據處理

    • 統一數據流管理
    • 支持多種數據源
    • 實現數據緩存
    • 處理異常情況
  4. 用戶體驗

    • 直觀的操作方式
    • 及時的操作反饋
    • 完善的錯誤提示
    • 支持操作撤銷

總結

低代碼平臺開發是一個復雜的系統工程,需要考慮以下方面:

  1. 可視化編輯器實現
  2. 組件系統設計
  3. 數據流管理
  4. 部署與發布
  5. 擴展與集成

通過合理的架構設計和功能實現,可以構建一個高效、易用的低代碼開發平臺。

學習資源

  1. 低代碼平臺設計指南
  2. 組件化開發最佳實踐
  3. 數據流管理方案
  4. 可視化編輯器實現
  5. 前端架構設計模式

如果你覺得這篇文章有幫助,歡迎點贊收藏,也期待在評論區看到你的想法和建議!👇

終身學習,共同成長。

咱們下一期見

💻

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

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

相關文章

Redis系列之慢查詢分析與調優

Redis 慢查詢分析與優化&#xff1a;提升性能的實戰指南 Redis 作為一款高性能的內存數據庫&#xff0c;因其快速的數據讀寫能力和靈活的數據結構&#xff0c;被廣泛應用于緩存、消息隊列、排行榜等多種業務場景。然而&#xff0c;隨著業務規模的擴大和數據量的增加&#xff0…

Git系列之git tag和ReleaseMilestone

以下是關于 Git Tag、Release 和 Milestone 的深度融合內容&#xff0c;并補充了關于 Git Tag 的所有命令、詳細解釋和指令實例&#xff0c;條理清晰&#xff0c;結合實際使用場景和案例。 1. Git Tag 1.1 定義 ? Tag 是 Git 中用于標記特定提交&#xff08;commit&#xf…

開源項目介紹:Native-LLM-for-Android

項目地址&#xff1a;Native-LLM-for-Android 創作活動時間&#xff1a;2025年 支持在 Android 設備上運行大型語言模型 &#xff08;LLM&#xff09; &#xff0c;具體支持的模型包括&#xff1a; DeepSeek-R1-Distill-Qwen: 1.5B Qwen2.5-Instruct: 0.5B, 1.5B Qwen2/2.5VL:…

深入理解 Java 虛擬機內存區域

Java 虛擬機&#xff08;JVM&#xff09;是 Java 程序運行的核心環境&#xff0c;它通過內存管理為程序提供高效的執行支持。JVM 在運行時將內存劃分為多個區域&#xff0c;每個區域都有特定的作用和生命周期。本文將詳細介紹 JVM 的運行時數據區域及其功能&#xff0c;并探討與…

PDF轉JPG(并去除多余的白邊)

首先&#xff0c;手動下載一個軟件&#xff08;poppler for Windows&#xff09;&#xff0c;下載地址&#xff1a;https://github.com/oschwartz10612/poppler-windows/releases/tag/v24.08.0-0 否則會出現以下錯誤&#xff1a; PDFInfoNotInstalledError: Unable to get pag…

深入剖析MyBatis緩存機制:原理、源碼與實戰指南

引言 MyBatis作為一款優秀的ORM框架,其緩存機制能顯著提升數據庫查詢性能。但許多開發者僅停留在“知道有緩存”的層面,對其實現原理和細節知之甚少。本文將結合可運行的代碼示例和源碼分析,手把手帶您徹底掌握MyBatis緩存機制。 一、MyBatis緩存分類 MyBatis提供兩級緩存…

Vue 使用 vue-router 時,多級嵌套路由緩存問題處理

Vue 使用 vue-router 時&#xff0c;多級嵌套路由緩存問題處理 對于三級菜單&#xff08;或多級嵌套路由&#xff09;&#xff0c;vue 都是 通過 keep-alive 組件來實現路由組件的緩存。 有時候三級或者多級路由時&#xff0c;會出現失效情況。以下是三級菜單緩存的例子。 最…

QSplitter保存和讀取

官方文檔提供的方案 保存 connect(ui->splitter, &QSplitter::splitterMoved, [](){settings.setValue("splitterSizes", ui->splitter->saveState()); });讀取 ui->splitter->restoreState(settings.value("splitterSizes").toByteA…

VanillaVueSvelteReactSolidAngularPreact前端框架/庫的簡要介紹及其優勢

VanillaVueSvelteReactSolidAngularPreact前端框架/庫的簡要介紹及其優勢。以下是這些前端框架/庫的簡要介紹及其優勢&#xff1a; 1. Vanilla 定義&#xff1a;Vanilla 并不是一個框架&#xff0c;而是指 原生 JavaScript&#xff08;即不使用任何框架或庫&#xff09;。優勢…

Java多線程與高并發專題——關于CopyOnWrite 容器特點

引入 在 CopyOnWriteArrayList 出現之前&#xff0c;我們已經有了 ArrayList 和 LinkedList 作為 List 的數組和鏈表的實現&#xff0c;而且也有了線程安全的 Vector 和Collections.synchronizedList() 可以使用。 首先我們來看看Vector是如何實現線程安全的 &#xff0c;還是…

Jmeter接口測試詳解

今天筆者呢&#xff0c;想給大家聊聊Jmeter接口測試流程詳解&#xff0c;廢話不多說直接進入正題。 一、jmeter簡介 Jmeter是由Apache公司開發的java開源項目&#xff0c;所以想要使用它必須基于java環境才可以&#xff1b; Jmeter采用多線程&#xff0c;允許通過多個線程并…

DeepSeek開啟AI辦公新模式,WPS/Office集成DeepSeek-R1本地大模型!

從央視到地方媒體&#xff0c;已有多家媒體機構推出AI主播&#xff0c;最近杭州文化廣播電視集團的《杭州新聞聯播》節目&#xff0c;使用AI主持人進行新聞播報&#xff0c;且做到了0失誤率&#xff0c;可見AI正在逐漸取代部分行業和一些重復性的工作&#xff0c;這一現象引發很…

通過Golang的container/list實現LRU緩存算法

文章目錄 力扣&#xff1a;146. LRU 緩存主要結構 List 和 Element常用方法1. 初始化鏈表2. 插入元素3. 刪除元素4. 遍歷鏈表5. 獲取鏈表長度使用場景注意事項 源代碼閱讀 在 Go 語言中&#xff0c;container/list 包提供了一個雙向鏈表的實現。鏈表是一種常見的數據結構&#…

【大學生體質】智能 AI 旅游推薦平臺(Vue+SpringBoot3)-完整部署教程

智能 AI 旅游推薦平臺開源文檔 項目前端地址 ??項目介紹 智能 AI 旅游推薦平臺&#xff08;Intelligent AI Travel Recommendation Platform&#xff09;是一個利用 AI 模型和數據分析為用戶提供個性化旅游路線推薦、景點評分、旅游攻略分享等功能的綜合性系統。該系統融合…

【滲透測試】基于時間的盲注(Time-Based Blind SQL Injection)

發生ERROR日志告警 查看系統日志如下&#xff1a; java.lang.IllegalArgumentException: Illegal character in query at index 203: https://api.weixin.qq.com/sns/jscode2session?access_token90_Vap5zo5UTJS4jbuvneMkyS1LHwHAgrofaX8bnIfW8EHXA71IRZwsqzJam9bo1m3zRcSrb…

redis數據類型以及底層數據結構

redis數據類型以及底層數據結構 String&#xff1a;字符串類型&#xff0c;底層就是動態字符串&#xff0c;使用sds數據結構 Map:有兩種數據結構&#xff1a;1.壓縮列表&#xff1a;當hash結構中存儲的元素個數小于了512個。并且元 …

DeepSeek R1-32B醫療大模型的完整微調實戰分析(全碼版)

DeepSeek R1-32B微調實戰指南 ├── 1. 環境準備 │ ├── 1.1 硬件配置 │ │ ├─ 全參數微調:4*A100 80GB │ │ └─ LoRA微調:單卡24GB │ ├── 1.2 軟件依賴 │ │ ├─ PyTorch 2.1.2+CUDA │ │ └─ Unsloth/ColossalAI │ └── 1.3 模…

window下的docker內使用gpu

Windows 上使用 Docker GPU需要進行一系列的配置和步驟。這是因為 Docker 在 Windows 上的運行環境與 Linux 有所不同,需要借助 WSL 2(Windows Subsystem for Linux 2)和 NVIDIA Container Toolkit 來實現 GPU 的支持。以下是詳細的流程: 一、環境準備 1.系統要求 Window…

Ubuntu 下 nginx-1.24.0 源碼分析 - cycle->modules[i]->type

Nginx 中主要有以下幾種模塊類型 類型 含義 NGX_CORE_MODULE 核心模塊&#xff08;如進程管理、錯誤日志、配置解析&#xff09;。 NGX_EVENT_MODULE 事件模塊&#xff08;如 epoll、kqueue 等 IO 多路復用機制的實現&#xff09;。 NGX_HTTP_MODULE HTTP 模塊&#xf…

八、排序算法

一些簡單的排序算法 8.1 冒泡排序 void Bubble_sort(int a[] , int len){int i,j,flag,tmp;for(i=0 ; i < len-1 ; i++){flag = 1;for(j=0 ; j < len-1-i ; j++){if(a[j] > a[j+1]){tmp = a[j];a[j] = a[j+1];a[j+1] = tmp;flag = 0;}}if(flag == 1){break;}}…