HarmonyOS 5.0 PC应用开发实战:构建跨设备协同的桌面生产力工具

文章目录

    • 每日一句正能量
    • 前言
    • [一、HarmonyOS PC应用开发背景与机遇](#一、HarmonyOS PC应用开发背景与机遇)
      • [1.1 生态发展现状](#1.1 生态发展现状)
      • [1.2 技术架构特点](#1.2 技术架构特点)
    • 二、实战项目:跨设备Markdown编辑器
      • [2.1 项目需求分析](#2.1 项目需求分析)
      • [2.2 技术选型](#2.2 技术选型)
    • 三、核心代码实现
      • [3.1 工程架构搭建](#3.1 工程架构搭建)
      • [3.2 PC端响应式布局](#3.2 PC端响应式布局)
      • [3.3 分布式数据同步实现](#3.3 分布式数据同步实现)
      • [3.4 PC端多窗口管理](#3.4 PC端多窗口管理)
      • [3.5 键盘快捷键系统](#3.5 键盘快捷键系统)
    • 四、跨设备协同场景实战
      • [4.1 手机拍照插入PC文档](#4.1 手机拍照插入PC文档)
      • [4.2 平板手绘同步到PC](#4.2 平板手绘同步到PC)
    • 五、性能优化与最佳实践
      • [5.1 大文件处理优化](#5.1 大文件处理优化)
      • [5.2 内存管理](#5.2 内存管理)
    • 六、调试与发布
      • [6.1 PC端调试技巧](#6.1 PC端调试技巧)
      • [6.2 发布配置](#6.2 发布配置)
    • 七、总结与展望

每日一句正能量

当你感到压力大,觉得不顺心的时候,就去逛逛菜市场......当看到年迈的老人,严寒酷暑,一小堆菜,一小堆水果,只为挣那几块几十块钱的家用,你所有的矫情和懒惰都会掉在地上碎成渣!

前言

摘要: 本文基于HarmonyOS 5.0.0版本,详细介绍如何开发一款具备跨设备协同能力的PC端生产力应用。通过实战案例,深入讲解ArkUI-X在PC端的适配、分布式软总线技术、以及多窗口管理等核心能力,为开发者提供完整的PC应用开发解决方案。


一、HarmonyOS PC应用开发背景与机遇

1.1 生态发展现状

随着HarmonyOS NEXT的正式发布,鸿蒙生态正式进入"纯血"时代。华为在2024年开发者大会上宣布,HarmonyOS PC版将于2025年全面商用,这意味着PC端将成为鸿蒙生态的重要拼图。对于开发者而言,这是一个巨大的蓝海市场------目前Windows桌面应用市场饱和,而鸿蒙PC应用尚处于起步阶段,先发优势明显。

1.2 技术架构特点

HarmonyOS PC应用并非简单的移动端移植,而是基于统一生态的重新设计:

  • 统一内核:采用与移动端相同的OpenHarmony内核,确保API一致性
  • 多窗口架构:支持自由窗口、分屏、多开等PC典型交互模式
  • 键鼠优化:原生支持键盘快捷键、鼠标右键菜单、滚轮缩放等操作
  • 跨端协同:通过分布式技术实现手机、平板、PC间的无缝流转

二、实战项目:跨设备Markdown编辑器

2.1 项目需求分析

我们将开发一款名为**"HarmonyMark"**的Markdown编辑器,核心功能包括:

  1. 基础编辑:支持Markdown语法高亮、实时预览、文件管理
  2. PC特性:多标签页、快捷键支持、拖拽打开文件
  3. 跨端协同:手机拍照→PC插入、平板手绘→PC同步、文件跨设备流转

2.2 技术选型

模块 技术方案 说明
UI框架 ArkUI-X 支持PC端响应式布局
状态管理 AppStorage + LocalStorage 跨Ability数据共享
分布式能力 DistributedObject + 软总线 跨设备数据同步
文件处理 @ohos.file.fs PC端文件系统访问
窗口管理 @ohos.window 多窗口生命周期管理

三、核心代码实现

3.1 工程架构搭建

首先创建Stage模型工程,配置PC设备支持:

typescript 复制代码
// entry/src/main/module.json5
{
  "module": {
    "name": "entry",
    "type": "entry",
    "deviceTypes": [
      "default",
      "tablet",
      "2in1"  // 支持PC/二合一设备
    ],
    "abilities": [
      {
        "name": "EntryAbility",
        "srcEntry": "./ets/entryability/EntryAbility.ets",
        "description": "$string:EntryAbility_desc",
        "icon": "$media:layered_image",
        "label": "$string:EntryAbility_label",
        "startWindowIcon": "$media:startIcon",
        "startWindowBackground": "$color:start_window_background",
        "exported": true,
        "skills": [
          {
            "entities": [
              "entity.system.home"
            ],
            "actions": [
              "action.system.home"
            ]
          }
        ],
        // PC端多窗口配置
        "windowMode": "multi_window",
        "maxWindowRatio": "4:3",
        "minWindowRatio": "1:2"
      }
    ]
  }
}

3.2 PC端响应式布局

HarmonyOS PC应用需要适配多种窗口尺寸,采用栅格系统实现响应式:

typescript 复制代码
// MainPage.ets
import { BreakpointSystem, BreakpointType } from '../utils/BreakpointSystem'

@Entry
@Component
struct MainPage {
  @StorageProp('currentBreakpoint') currentBreakpoint: string = 'sm'
  private breakpointSystem: BreakpointSystem = new BreakpointSystem()
  
  // 编辑器状态
  @State currentFile: FileItem | null = null
  @State isPreviewMode: boolean = false
  @State editorContent: string = ''

  aboutToAppear() {
    // 注册断点监听
    this.breakpointSystem.register()
    // 初始化分布式数据
    this.initDistributedData()
  }

  aboutToDisappear() {
    this.breakpointSystem.unregister()
  }

  build() {
    GridRow({
      columns: { sm: 4, md: 8, lg: 12 },  // 响应式列数
      gutter: { x: 12, y: 12 },
      breakpoints: {
        value: ['320vp', '600vp', '840vp'],
        reference: BreakpointsReference.WindowSize
      }
    }) {
      // 左侧文件栏:lg显示,sm/md隐藏
      GridCol({
        span: { sm: 0, md: 2, lg: 3 },
        offset: { sm: 0, md: 0, lg: 0 }
      }) {
        FileSidebar({
          onFileSelect: (file: FileItem) => this.handleFileSelect(file)
        })
      }
      .backgroundColor('#f5f5f5')
      .height('100%')

      // 中间编辑区
      GridCol({
        span: { sm: 4, md: 6, lg: this.isPreviewMode ? 5 : 9 }
      }) {
        EditorPanel({
          content: $editorContent,
          onContentChange: (val: string) => this.handleContentChange(val)
        })
      }
      .padding(16)

      // 右侧预览区:仅lg且预览模式显示
      GridCol({
        span: { sm: 0, md: 0, lg: 4 }
      }) {
        if (this.currentBreakpoint === 'lg' && this.isPreviewMode) {
          PreviewPanel({ markdown: this.editorContent })
        }
      }
      .backgroundColor('#fafafa')
    }
    .width('100%')
    .height('100%')
    .onBreakpointChange((breakpoint) => {
      AppStorage.setOrCreate('currentBreakpoint', breakpoint)
    })
  }

  // 处理文件选择
  private handleFileSelect(file: FileItem) {
    this.currentFile = file
    // 读取文件内容
    fs.readText(file.uri).then((content) => {
      this.editorContent = content
      // 同步到分布式数据
      this.syncToDistributed(file.uri, content)
    })
  }

  // 内容变更自动保存
  private handleContentChange(content: string) {
    this.editorContent = content
    if (this.currentFile) {
      this.autoSave(this.currentFile.uri, content)
    }
  }
}

3.3 分布式数据同步实现

核心功能:实现PC与手机间的实时内容同步:

typescript 复制代码
// DistributedEditorManager.ets
import distributedObject from '@ohos.data.distributedDataObject'
import distributedDeviceManager from '@ohos.distributedDeviceManager'

class EditorData {
  uri: string = ''
  content: string = ''
  lastModified: number = 0
  deviceId: string = ''
}

export class DistributedEditorManager {
  private distributedObject: distributedObject.DistributedObject | null = null
  private sessionId: string = 'harmonymark_editor_session'
  private deviceManager: distributedDeviceManager.DeviceManager | null = null
  
  // 创建分布式数据对象
  async createDistributedObject(initialData: EditorData) {
    try {
      this.distributedObject = distributedObject.create(
        getContext(this),
        this.sessionId,
        initialData
      )
      
      // 监听数据变更
      this.distributedObject.on('change', (sessionId, fields) => {
        console.info(`Data changed from ${sessionId}: ${JSON.stringify(fields)}`)
        this.handleRemoteChange(fields)
      })
      
      // 绑定到本地
      await this.distributedObject.setSessionId(this.sessionId)
      console.info('Distributed object created successfully')
    } catch (err) {
      console.error('Failed to create distributed object:', err)
    }
  }

  // 同步数据到所有设备
  async syncContent(uri: string, content: string) {
    if (!this.distributedObject) return
    
    const updateData: EditorData = {
      uri: uri,
      content: content,
      lastModified: Date.now(),
      deviceId: this.getLocalDeviceId()
    }
    
    // 更新分布式对象
    this.distributedObject.uri = updateData.uri
    this.distributedObject.content = updateData.content
    this.distributedObject.lastModified = updateData.lastModified
    this.distributedObject.deviceId = updateData.deviceId
    
    console.info('Content synced to distributed object')
  }

  // 处理远程数据变更
  private handleRemoteChange(fields: Array<string>) {
    if (!this.distributedObject) return
    
    // 检查是否是其他设备的更新
    if (fields.includes('content') && 
        this.distributedObject.deviceId !== this.getLocalDeviceId()) {
      
      const remoteContent = this.distributedObject.content
      const remoteUri = this.distributedObject.uri
      
      // 触发UI更新
      AppStorage.setOrCreate('remoteContent', remoteContent)
      AppStorage.setOrCreate('remoteUri', remoteUri)
      
      // 显示协同提示
      this.showCollaborationNotification(remoteContent)
    }
  }

  // 获取在线设备列表
  async getAvailableDevices(): Promise<Array<distributedDeviceManager.DeviceBasicInfo>> {
    try {
      this.deviceManager = distributedDeviceManager.createDeviceManager(getContext(this).bundleName)
      return this.deviceManager.getAvailableDeviceListSync()
    } catch (err) {
      console.error('Failed to get devices:', err)
      return []
    }
  }

  private getLocalDeviceId(): string {
    return this.deviceManager?.getLocalDeviceNetworkId() || ''
  }

  private showCollaborationNotification(content: string) {
    // 实现协同提示UI
    promptAction.showToast({
      message: '其他设备已更新内容',
      duration: 2000
    })
  }
}

3.4 PC端多窗口管理

实现类似VS Code的多窗口编辑体验:

typescript 复制代码
// MultiWindowManager.ets
import window from '@ohos.window'

export class MultiWindowManager {
  private static instance: MultiWindowManager
  private windowMap: Map<string, window.Window> = new Map()
  private mainWindow: window.Window | null = null

  static getInstance(): MultiWindowManager {
    if (!MultiWindowManager.instance) {
      MultiWindowManager.instance = new MultiWindowManager()
    }
    return MultiWindowManager.instance
  }

  // 初始化主窗口
  async initMainWindow() {
    this.mainWindow = await window.getLastWindow(getContext(this))
    await this.setupWindowConfig(this.mainWindow, 'main')
  }

  // 创建新窗口打开文件
  async openNewWindow(fileUri: string, fileName: string): Promise<void> {
    try {
      // 创建子窗口
      const subWindow = await window.createSubWindow(getContext(this), `editor_${Date.now()}`)
      const windowId = subWindow.getWindowProperties().id.toString()
      
      // 配置窗口属性
      await this.setupWindowConfig(subWindow, 'sub')
      
      // 设置窗口内容
      await subWindow.setUIContent('pages/EditorWindow', (data) => {
        // 传递参数
        AppStorage.setOrCreate('windowFileUri', fileUri)
        AppStorage.setOrCreate('windowFileName', fileName)
      })
      
      // 显示窗口
      await subWindow.showWindow()
      
      // 移动到合适位置(级联窗口效果)
      await this.cascadeWindow(subWindow)
      
      // 保存引用
      this.windowMap.set(windowId, subWindow)
      
      // 监听窗口关闭
      subWindow.on('windowStageDestroy', () => {
        this.windowMap.delete(windowId)
      })
      
    } catch (err) {
      console.error('Failed to create sub window:', err)
    }
  }

  // 配置窗口属性
  private async setupWindowConfig(win: window.Window, type: 'main' | 'sub') {
    // 设置窗口大小范围
    await win.setWindowLimits({
      minWidth: type === 'main' ? 800 : 600,
      minHeight: type === 'main' ? 600 : 400,
      maxWidth: 3840,
      maxHeight: 2160
    })

    if (type === 'sub') {
      // 子窗口默认大小
      await win.resize(1000, 700)
      
      // 启用窗口拖拽调整大小
      await win.setWindowTouchable(true)
    }

    // PC端特定优化
    await win.setWindowDecorVisible(true)  // 显示系统标题栏
    await win.setWindowBackgroundColor('#ffffff')
  }

  // 级联窗口布局
  private async cascadeWindow(win: window.Window) {
    const offset = this.windowMap.size * 30
    const display = await window.getLastWindow(getContext(this)).getWindowProperties().displayId
    // 基于主窗口位置偏移
    await win.moveWindowTo(100 + offset, 100 + offset)
  }

  // 分屏模式支持
  async enterSplitScreenMode() {
    if (!this.mainWindow) return
    await this.mainWindow.setWindowMode(window.WindowMode.SPLIT_PRIMARY)
  }

  // 获取所有打开的窗口
  getAllWindows(): Array<window.Window> {
    return Array.from(this.windowMap.values())
  }

  // 关闭所有子窗口
  async closeAllSubWindows() {
    for (const [id, win] of this.windowMap) {
      await win.destroyWindow()
    }
    this.windowMap.clear()
  }
}

3.5 键盘快捷键系统

PC应用的核心体验,实现专业编辑器级快捷键:

typescript 复制代码
// KeyboardShortcutManager.ets
import { KeyCode } from '@kit.InputKit'

interface ShortcutConfig {
  key: KeyCode
  modifiers: Array<'ctrl' | 'shift' | 'alt'>
  action: () => void
  description: string
}

export class KeyboardShortcutManager {
  private shortcuts: Map<string, ShortcutConfig> = new Map()
  private isListening: boolean = false

  // 注册默认快捷键
  registerDefaultShortcuts() {
    this.register({
      key: KeyCode.KEY_S,
      modifiers: ['ctrl'],
      action: () => this.saveFile(),
      description: '保存文件'
    })
    
    this.register({
      key: KeyCode.KEY_N,
      modifiers: ['ctrl'],
      action: () => this.newFile(),
      description: '新建文件'
    })
    
    this.register({
      key: KeyCode.KEY_O,
      modifiers: ['ctrl'],
      action: () => this.openFile(),
      description: '打开文件'
    })
    
    this.register({
      key: KeyCode.KEY_Z,
      modifiers: ['ctrl'],
      action: () => this.undo(),
      description: '撤销'
    })
    
    this.register({
      key: KeyCode.KEY_Z,
      modifiers: ['ctrl', 'shift'],
      action: () => this.redo(),
      description: '重做'
    })
    
    this.register({
      key: KeyCode.KEY_B,
      modifiers: ['ctrl'],
      action: () => this.insertBold(),
      description: '粗体'
    })
    
    this.register({
      key: KeyCode.KEY_P,
      modifiers: ['ctrl', 'shift'],
      action: () => this.togglePreview(),
      description: '切换预览'
    })

    // 开始监听
    this.startListening()
  }

  register(config: ShortcutConfig) {
    const key = this.getShortcutKey(config)
    this.shortcuts.set(key, config)
  }

  private startListening() {
    if (this.isListening) return
    
    // 使用InputKit监听键盘事件
    inputMonitor.on('key', (event) => {
      if (event.type !== 'keyDown') return
      
      const pressedKey = this.getShortcutKey({
        key: event.keyCode,
        modifiers: this.getActiveModifiers(event)
      } as ShortcutConfig)
      
      const shortcut = this.shortcuts.get(pressedKey)
      if (shortcut) {
        event.stopPropagation()
        shortcut.action()
        console.info(`Shortcut triggered: ${shortcut.description}`)
      }
    })
    
    this.isListening = true
  }

  private getShortcutKey(config: ShortcutConfig): string {
    const mods = config.modifiers.sort().join('+')
    return `${mods}+${config.key}`
  }

  private getActiveModifiers(event: KeyEvent): Array<string> {
    const mods: Array<string> = []
    if (event.ctrlKey) mods.push('ctrl')
    if (event.shiftKey) mods.push('shift')
    if (event.altKey) mods.push('alt')
    return mods
  }

  // 快捷键动作实现
  private saveFile() {
    const content = AppStorage.get<string>('currentContent') || ''
    const uri = AppStorage.get<string>('currentUri')
    if (uri) {
      fs.writeText(uri, content)
      promptAction.showToast({ message: '保存成功' })
    }
  }

  private newFile() {
    // 创建新文件逻辑
    router.pushUrl({ url: 'pages/Editor', params: { newFile: true } })
  }

  private openFile() {
    // 打开文件选择器
    let documentPicker = new picker.DocumentViewPicker(getContext(this))
    documentPicker.select().then((result) => {
      if (result.length > 0) {
        AppStorage.setOrCreate('selectedFileUri', result[0])
      }
    })
  }

  private undo() {
    // 调用编辑器撤销
    AppStorage.setOrCreate('editorAction', 'undo')
  }

  private redo() {
    AppStorage.setOrCreate('editorAction', 'redo')
  }

  private insertBold() {
    AppStorage.setOrCreate('editorInsert', '****')
  }

  private togglePreview() {
    const current = AppStorage.get<boolean>('isPreviewMode') || false
    AppStorage.setOrCreate('isPreviewMode', !current)
  }
}

四、跨设备协同场景实战

4.1 手机拍照插入PC文档

利用分布式文件系统实现:

typescript 复制代码
// PhotoTransferManager.ets
import distributedFile from '@ohos.file.distributedFile'

export class PhotoTransferManager {
  // 发起拍照请求到手机
  async requestPhotoFromPhone(): Promise<string> {
    // 查找在线手机设备
    const devices = await this.getPhoneDevices()
    if (devices.length === 0) {
      throw new Error('No phone device found')
    }

    const targetDevice = devices[0]
    
    // 通过分布式软总线发送拍照指令
    const session = await this.createSession(targetDevice.networkId)
    await session.sendMessage({ action: 'TAKE_PHOTO' })
    
    // 等待照片传输完成
    return new Promise((resolve, reject) => {
      session.onMessage((msg) => {
        if (msg.type === 'PHOTO_READY') {
          // 获取分布式文件路径
          const distributedPath = msg.data.path
          // 复制到本地
          this.copyToLocal(distributedPath).then(resolve).catch(reject)
        }
      })
      
      setTimeout(() => reject(new Error('Photo transfer timeout')), 30000)
    })
  }

  private async copyToLocal(distributedPath: string): Promise<string> {
    const fileName = `photo_${Date.now()}.jpg`
    const localPath = getContext(this).filesDir + '/' + fileName
    
    // 使用分布式文件API复制
    await distributedFile.copyFile(distributedPath, localPath)
    
    return localPath
  }
}

4.2 平板手绘同步到PC

利用分布式数据对象实时同步手绘数据:

typescript 复制代码
// DrawingSyncManager.ets
interface DrawingPoint {
  x: number
  y: number
  pressure: number
  timestamp: number
}

interface DrawingStroke {
  points: Array<DrawingPoint>
  color: string
  width: number
}

export class DrawingSyncManager {
  private distributedObj: any = null
  
  async init() {
    this.distributedObj = distributedObject.create(
      getContext(this),
      'drawing_session',
      { strokes: [] as Array<DrawingStroke> }
    )
    
    // 监听笔画数据
    this.distributedObj.on('change', (sessionId, fields) => {
      if (fields.includes('strokes')) {
        const strokes = this.distributedObj.strokes
        this.renderStrokes(strokes)
      }
    })
  }

  // 平板端调用:添加笔画
  async addStroke(stroke: DrawingStroke) {
    const currentStrokes = this.distributedObj.strokes || []
    currentStrokes.push(stroke)
    this.distributedObj.strokes = currentStrokes
  }

  // PC端调用:渲染笔画到Canvas
  private renderStrokes(strokes: Array<DrawingStroke>) {
    const canvas = AppStorage.get<CanvasRenderingContext2D>('drawingCanvas')
    if (!canvas) return
    
    canvas.clearRect(0, 0, canvas.width, canvas.height)
    
    strokes.forEach(stroke => {
      canvas.beginPath()
      canvas.strokeStyle = stroke.color
      canvas.lineWidth = stroke.width
      canvas.lineCap = 'round'
      canvas.lineJoin = 'round'
      
      stroke.points.forEach((point, index) => {
        if (index === 0) {
          canvas.moveTo(point.x, point.y)
        } else {
          canvas.lineTo(point.x, point.y)
        }
      })
      
      canvas.stroke()
    })
  }
}

五、性能优化与最佳实践

5.1 大文件处理优化

Markdown文件可能很大,需要虚拟列表优化:

typescript 复制代码
// VirtualListController.ets
class VirtualListController {
  private itemHeight: number = 40
  private visibleCount: number = 50
  private bufferCount: number = 10
  
  // 计算可见区域
  getVisibleRange(scrollOffset: number): { start: number, end: number } {
    const start = Math.floor(scrollOffset / this.itemHeight) - this.bufferCount
    const end = start + this.visibleCount + this.bufferCount * 2
    
    return {
      start: Math.max(0, start),
      end: Math.min(this.totalItems, end)
    }
  }
  
  // 渲染优化
  buildVirtualList(items: Array<string>) {
    List({ space: 0 }) {
      LazyForEach(this.dataSource, (item: string, index: number) => {
        ListItem() {
          MarkdownLine({ content: item, lineNumber: index + 1 })
        }
        .height(this.itemHeight)
        .recycle(true)  // 启用回收复用
      }, (item: string, index: number) => index.toString())
    }
    .cachedCount(this.bufferCount)  // 缓存缓冲区
    .onScroll((scrollOffset) => {
      this.updateVisibleRange(scrollOffset)
    })
  }
}

5.2 内存管理

PC应用可能长时间运行,需要注意内存泄漏:

typescript 复制代码
// MemoryManager.ets
export class MemoryManager {
  private static intervals: Array<number> = []
  private static listeners: Array<() => void> = []

  // 安全设置定时器
  static setSafeInterval(callback: () => void, delay: number): number {
    const id = setInterval(callback, delay)
    this.intervals.push(id)
    return id
  }

  // 安全注册事件
  static addSafeListener(event: string, handler: () => void) {
    emitter.on(event, handler)
    this.listeners.push(() => emitter.off(event, handler))
  }

  // 页面销毁时清理
  static cleanup() {
    this.intervals.forEach(id => clearInterval(id))
    this.intervals = []
    
    this.listeners.forEach(off => off())
    this.listeners = []
    
    // 释放大对象
    AppStorage.delete('largeDataCache')
  }
}

六、调试与发布

6.1 PC端调试技巧

bash 复制代码
# 连接PC设备(需开启开发者模式)
hdc list targets
hdc shell

# 实时查看日志
hdc hilog | grep HarmonyMark

# 性能分析
hdc shell hiprofiler -c /data/local/tmp/config.json

6.2 发布配置

json 复制代码
// 配置PC应用图标和分类
{
  "app": {
    "icon": "$media:pc_icon",
    "label": "HarmonyMark",
    "category": "productivity",
    "pcConfig": {
      "supportWindowMode": ["fullscreen", "split", "float"],
      "defaultWindowSize": [1200, 800],
      "minWindowSize": [800, 600]
    }
  }
}

七、总结与展望

本文完整演示了HarmonyOS 5.0 PC应用的核心开发流程,涵盖:

  1. 响应式布局:通过GridRow/GridCol实现PC端自适应
  2. 分布式能力:利用DistributedObject实现跨设备协同
  3. 多窗口管理:支持专业级多文档编辑体验
  4. 键鼠交互:完整的快捷键系统提升效率

未来优化方向:

  • 接入AI能力实现智能Markdown补全
  • 支持插件系统扩展编辑器功能
  • 实现WebDAV云同步

HarmonyOS PC生态正处于快速发展期,开发者应抓住窗口期,提前布局PC应用市场。随着2025年鸿蒙PC的全面商用,早期投入将获得显著的先发优势。


参考资源:


转载自:https://blog.csdn.net/u014727709/article/details/158931841

欢迎 👍点赞✍评论⭐收藏,欢迎指正

相关推荐
科技快报2 小时前
华为发布AI数据平台,重塑数据基座,加速企业AI应用落地
大数据·人工智能·华为
希赛网3 小时前
2026年华为HCIE数通认证考试,可以在哪里看课程?
网络·华为·华为认证数通学习答疑·hcie数通疑问·hcie-datacom·2026ie数通学习·hcie考试内容
毕设源码-郭学长3 小时前
【开题答辩全过程】以 华为产品销售的数据爬虫与可视化分析为例,包含答辩的问题和答案
华为
Lancker3 小时前
参与华为天工计划 冲刺75w激励
华为
木斯佳10 小时前
HarmonyOS 6实战:从爆款vlog探究鸿蒙智能体提取关键帧算法
算法·华为·harmonyos
天意__10 小时前
鸿蒙(ArkTS)与Flutter(Dart)开发语法全面对比
flutter·华为·harmonyos·arkts·dart·arkui
vistaup10 小时前
DevEco Studio 鸿蒙 HAR本地引入相互依赖问题解决
android·华为·harmonyos
fei_sun11 小时前
【鸿蒙智能硬件】(二)Windows开发环境
华为·harmonyos
前端不太难11 小时前
AI 时代,鸿蒙 App 还需要传统导航结构吗?
人工智能·状态模式·harmonyos