HarmonyOS开发:强制更新策略

举报
Jack20 发表于 2026/06/25 20:42:35 2026/06/25
【摘要】 HarmonyOS开发:强制更新策略📌 核心要点:强制更新不是你想用就能用的——它直接阻断用户的使用流程。只有在严重安全漏洞、核心功能不可用、数据不兼容等极端场景下才该启用,而且弹窗设计必须给用户足够的尊重。 背景与动机你打开一个App,还没看清首页长什么样,一个弹窗就糊脸上了:“发现新版本,请立即更新”。没有"稍后"按钮,没有"跳过"选项,只有"立即更新"。你什么感觉?被绑架了。强制更...

HarmonyOS开发:强制更新策略

📌 核心要点:强制更新不是你想用就能用的——它直接阻断用户的使用流程。只有在严重安全漏洞、核心功能不可用、数据不兼容等极端场景下才该启用,而且弹窗设计必须给用户足够的尊重。

背景与动机

你打开一个App,还没看清首页长什么样,一个弹窗就糊脸上了:“发现新版本,请立即更新”。没有"稍后"按钮,没有"跳过"选项,只有"立即更新"。

你什么感觉?被绑架了。

强制更新是最粗暴的版本控制手段。它直接告诉用户:不更新就别用。这种体验放在平时,用户骂你两句就算了;但如果你的理由不充分,用户可能直接卸载。

但强制更新不是不能用,而是要慎用。有些场景不用强制更新,后果比强制更新更严重——比如你的旧版本存在安全漏洞,用户数据可能被窃取;比如你的服务端API已经升级,旧版本完全无法工作。

这篇文章,把强制更新的适用场景、策略设计、弹窗实现、用户体验优化全部讲清楚。

核心原理

强制更新决策流程

graph TD
    A[应用启动] --> B[检查更新]
    B --> C{有新版本?}
    C -->|| D[正常使用]
    C -->|| E{当前版本 < 最低支持版本?}
    E -->|| F[可选更新提示]
    E -->|| G[强制更新弹窗]
    F --> H{用户选择}
    H -->|更新| I[跳转AppGallery]
    H -->|跳过| D
    G --> J{用户点击更新}
    J -->|| I
    J -->|关闭弹窗| K[阻止使用]
    K --> G

    classDef startStyle fill:#FF6B35,stroke:#D4551F,color:#fff,font-weight:bold
    classDef processStyle fill:#4ECDC4,stroke:#3BA99C,color:#fff
    classDef decisionStyle fill:#FFE66D,stroke:#D4B93C,color:#333,font-weight:bold
    classDef dangerStyle fill:#FF6B6B,stroke:#CC5555,color:#fff
    classDef successStyle fill:#96CEB4,stroke:#6DAF8E,color:#fff,font-weight:bold
    
    class A,B startStyle
    class D,F,I processStyle
    class C,E,H,J decisionStyle
    class G,K dangerStyle

什么时候该用强制更新?

强制更新的触发条件必须严格限定。不是你觉得"用户应该更新"就强制,而是"不更新就出事"才强制。

场景 是否强制更新 理由
严重安全漏洞 ✅ 是 不更新可能导致用户数据泄露
服务端API不兼容 ✅ 是 旧版本完全无法工作
数据库结构变更 ✅ 是 旧版本会导致数据错乱
新功能上线 ❌ 否 用户有权选择不使用新功能
UI优化 ❌ 否 不影响功能使用
Bug修复 ❌ 否 除非是导致核心功能不可用的Bug
性能优化 ❌ 否 旧版本性能差但不影响使用

版本最低限制机制

强制更新的核心是"版本最低限制"(minSupportVersion)。你在服务端配置一个最低版本号,低于这个版本的客户端必须更新。

服务端配置:
  latestVersion: 1.5.0 (versionCode: 10500)
  minSupportVersion: 1.3.0 (versionCode: 10300)

客户端逻辑:
  当前版本 >= minSupportVersion → 可选更新
  当前版本 < minSupportVersion → 强制更新

代码实战

基础用法:版本检查与强制更新判断

// entry/src/main/ets/utils/ForceUpdateManager.ets
// 强制更新管理器——判断是否需要强制更新

import { hilog } from '@kit.PerformanceAnalysisKit';
import { bundleManager } from '@kit.AbilityKit';
import { preferences } from '@kit.ArkData';
import { common } from '@kit.AbilityKit';

// 服务端返回的版本信息
interface ServerVersionInfo {
  latestVersionName: string;     // 最新版本名
  latestVersionCode: number;     // 最新版本号
  minSupportVersionCode: number; // 最低支持版本号
  updateLog: string;             // 更新日志
  downloadUrl: string;           // 下载链接
  isForceUpdate: boolean;        // 是否强制更新
  forceUpdateReason: string;     // 强制更新原因
}

// 更新检查结果
interface UpdateCheckResult {
  hasUpdate: boolean;            // 是否有更新
  isForce: boolean;              // 是否强制更新
  currentVersionCode: number;    // 当前版本号
  latestVersionCode: number;     // 最新版本号
  minSupportVersionCode: number; // 最低支持版本号
  updateLog: string;             // 更新日志
  forceReason: string;           // 强制更新原因
}

export class ForceUpdateManager {
  private static instance: ForceUpdateManager;
  private context: common.Context | null = null;
  private currentVersionCode: number = 0;

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

  // 初始化
  async init(context: common.Context): Promise<void> {
    this.context = context;
    
    // 获取当前版本号
    try {
      const bundleInfo = await bundleManager.getBundleInfoForSelf(
        bundleManager.BundleFlag.GET_BUNDLE_INFO_DEFAULT
      );
      this.currentVersionCode = bundleInfo.versionCode;
      hilog.info(0x0000, 'ForceUpdate', `当前版本号: ${this.currentVersionCode}`);
    } catch (error) {
      hilog.error(0x0000, 'ForceUpdate', `获取版本号失败: ${JSON.stringify(error)}`);
    }
  }

  // 检查更新
  async checkUpdate(): Promise<UpdateCheckResult> {
    // 从服务端获取版本信息
    const serverInfo = await this.fetchServerVersionInfo();
    
    if (!serverInfo) {
      return {
        hasUpdate: false,
        isForce: false,
        currentVersionCode: this.currentVersionCode,
        latestVersionCode: this.currentVersionCode,
        minSupportVersionCode: 0,
        updateLog: '',
        forceReason: ''
      };
    }

    // 判断是否有更新
    const hasUpdate = serverInfo.latestVersionCode > this.currentVersionCode;
    
    // 判断是否强制更新
    // 两个条件满足其一即强制:
    // 1. 服务端标记了强制更新
    // 2. 当前版本低于最低支持版本
    const isForce = serverInfo.isForceUpdate || 
                    this.currentVersionCode < serverInfo.minSupportVersionCode;

    return {
      hasUpdate,
      isForce,
      currentVersionCode: this.currentVersionCode,
      latestVersionCode: serverInfo.latestVersionCode,
      minSupportVersionCode: serverInfo.minSupportVersionCode,
      updateLog: serverInfo.updateLog,
      forceReason: isForce ? serverInfo.forceUpdateReason : ''
    };
  }

  // 从服务端获取版本信息
  private async fetchServerVersionInfo(): Promise<ServerVersionInfo | null> {
    // 实际项目中通过HTTP请求获取
    // 这里用模拟数据演示
    try {
      // const response = await http.request('https://api.example.com/version/check');
      // return response.result as ServerVersionInfo;
      
      // 模拟服务端返回数据
      return {
        latestVersionName: '1.5.0',
        latestVersionCode: 10500,
        minSupportVersionCode: 10300,
        updateLog: '1. 修复了数据同步异常的问题\n2. 优化了页面加载速度\n3. 新增了深色模式支持',
        downloadUrl: 'appgallery://com.example.myapp',
        isForceUpdate: false,
        forceUpdateReason: '为了保护您的数据安全,请更新到最新版本'
      };
    } catch (error) {
      hilog.error(0x0000, 'ForceUpdate', `获取版本信息失败: ${JSON.stringify(error)}`);
      return null;
    }
  }

  // 跳转到AppGallery更新
  async goToAppGallery(): Promise<void> {
    if (!this.context) return;
    
    try {
      // 使用应用市场链接跳转
      // HarmonyOS通过隐式Want跳转到AppGallery
      hilog.info(0x0000, 'ForceUpdate', '跳转到AppGallery更新页面');
      // 实际跳转逻辑需要根据AppGallery的URI scheme配置
    } catch (error) {
      hilog.error(0x0000, 'ForceUpdate', `跳转AppGallery失败: ${JSON.stringify(error)}`);
    }
  }
}

进阶用法:强制更新弹窗设计

强制更新弹窗的设计直接决定用户体验。做得好,用户理解你的苦衷;做得差,用户觉得你在绑架他。

// entry/src/main/ets/components/ForceUpdateDialog.ets
// 强制更新弹窗——给用户尊重,也给自己留余地

import { common } from '@kit.AbilityKit';

@CustomDialog
export struct ForceUpdateDialog {
  controller: CustomDialogController;
  private context: common.Context = getContext(this) as common.Context;
  
  // 弹窗配置
  isForce: boolean = false;           // 是否强制更新
  updateLog: string = '';              // 更新日志
  forceReason: string = '';            // 强制更新原因
  currentVersion: string = '';         // 当前版本
  latestVersion: string = '';          // 最新版本
  
  // 回调
  onUpdateClick?: () => void;          // 点击更新回调
  onLaterClick?: () => void;           // 点击稍后回调(仅非强制时有效)

  // 更新按钮点击
  handleUpdate(): void {
    this.controller.close();
    this.onUpdateClick?.();
    
    // 跳转到AppGallery
    this.goToAppGallery();
  }

  // 稍后按钮点击
  handleLater(): void {
    this.controller.close();
    this.onLaterClick?.();
  }

  // 跳转到AppGallery
  private goToAppGallery(): void {
    try {
      hilog.info(0x0000, 'ForceUpdate', '正在跳转到AppGallery...');
      // 实际跳转逻辑
    } catch (error) {
      hilog.error(0x0000, 'ForceUpdate', `跳转失败: ${JSON.stringify(error)}`);
    }
  }

  build() {
    Column({ space: 0 }) {
      // 标题区域
      Column({ space: 8 }) {
        Text(this.isForce ? '需要更新' : '发现新版本')
          .fontSize(20)
          .fontWeight(FontWeight.Bold)
          .fontColor('#333333')

        // 版本号
        Text(`${this.currentVersion}${this.latestVersion}`)
          .fontSize(13)
          .fontColor('#999999')
      }
      .width('100%')
      .padding({ left: 24, right: 24, top: 24, bottom: 12 })

      // 强制更新原因(仅强制时显示)
      if (this.isForce && this.forceReason) {
        Row({ space: 8 }) {
          Text('⚠️')
            .fontSize(16)
          Text(this.forceReason)
            .fontSize(14)
            .fontColor('#FF6B35')
            .layoutWeight(1)
        }
        .width('100%')
        .padding({ left: 24, right: 24, top: 4, bottom: 8 })
        .alignItems(VerticalAlign.Top)
      }

      // 更新日志
      Scroll() {
        Text(this.updateLog || '暂无更新说明')
          .fontSize(14)
          .fontColor('#666666')
          .lineHeight(22)
      }
      .width('100%')
      .constraintSize({ maxHeight: 200 })
      .padding({ left: 24, right: 24, top: 8, bottom: 16 })

      // 分割线
      Divider()
        .color('#F0F0F0')

      // 按钮区域
      Row() {
        // 非强制更新时显示"稍后"按钮
        if (!this.isForce) {
          Button('稍后再说')
            .width('50%')
            .height(48)
            .backgroundColor(Color.Transparent)
            .fontColor('#999999')
            .fontSize(16)
            .onClick(() => this.handleLater())
        }

        Button(this.isForce ? '立即更新' : '立即更新')
          .width(this.isForce ? '100%' : '50%')
          .height(48)
          .backgroundColor('#007DFF')
          .fontColor(Color.White)
          .fontSize(16)
          .borderRadius(0)
          .onClick(() => this.handleUpdate())
      }
      .width('100%')
    }
    .backgroundColor(Color.White)
    .borderRadius(16)
    .width('85%')
    .clip(true)
  }
}

// 需要导入hilog
import { hilog } from '@kit.PerformanceAnalysisKit';

完整示例:强制更新全流程

把版本检查、弹窗展示、跳转更新整合在一起,实现完整的强制更新流程。

// entry/src/main/ets/utils/UpdateController.ets
// 更新控制器——管理可选更新和强制更新的完整流程

import { hilog } from '@kit.PerformanceAnalysisKit';
import { common } from '@kit.AbilityKit';
import { preferences } from '@kit.ArkData';
import { bundleManager } from '@kit.AbilityKit';

// 更新策略
interface UpdatePolicy {
  checkOnLaunch: boolean;         // 启动时检查
  checkIntervalHours: number;     // 检查间隔(小时)
  remindIntervalDays: number;     // 提醒间隔(天,仅非强制更新)
  maxRemindCount: number;         // 最大提醒次数(仅非强制更新)
  forceBlockApp: boolean;         // 强制更新时是否阻止使用
}

// 更新状态
interface UpdateState {
  lastCheckTime: number;          // 上次检查时间
  lastRemindTime: number;         // 上次提醒时间
  remindCount: number;            // 已提醒次数
  skippedVersionCode: number;     // 用户跳过的版本号
}

export class UpdateController {
  private static instance: UpdateController;
  private context: common.Context | null = null;
  private policy: UpdatePolicy = {
    checkOnLaunch: true,
    checkIntervalHours: 24,
    remindIntervalDays: 3,
    maxRemindCount: 5,
    forceBlockApp: true
  };
  private state: UpdateState = {
    lastCheckTime: 0,
    lastRemindTime: 0,
    remindCount: 0,
    skippedVersionCode: 0
  };

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

  // 初始化
  async init(context: common.Context): Promise<void> {
    this.context = context;
    await this.loadState();
    hilog.info(0x0000, 'UpdateController', '更新控制器初始化完成');
  }

  // 检查是否需要展示更新提示
  async shouldShowUpdate(): Promise<{
    show: boolean;
    isForce: boolean;
    reason: string;
  }> {
    // 检查是否在检查间隔内
    const now = Date.now();
    const intervalMs = this.policy.checkIntervalHours * 3600 * 1000;
    if (now - this.state.lastCheckTime < intervalMs) {
      // 还没到检查时间,但如果是强制更新,仍然要检查
      // 这里简化处理,每次都检查
    }

    // 从服务端获取版本信息
    const serverInfo = await this.fetchVersionInfo();
    if (!serverInfo) {
      return { show: false, isForce: false, reason: '' };
    }

    // 获取当前版本
    const currentVersionCode = await this.getCurrentVersionCode();
    const hasUpdate = serverInfo.latestVersionCode > currentVersionCode;
    
    if (!hasUpdate) {
      return { show: false, isForce: false, reason: '' };
    }

    // 判断是否强制更新
    const isForce = currentVersionCode < serverInfo.minSupportVersionCode;

    if (isForce) {
      // 强制更新,必须展示
      return {
        show: true,
        isForce: true,
        reason: serverInfo.forceUpdateReason
      };
    }

    // 非强制更新,检查是否需要提醒
    // 用户跳过了这个版本
    if (this.state.skippedVersionCode >= serverInfo.latestVersionCode) {
      return { show: false, isForce: false, reason: '' };
    }

    // 提醒次数已达上限
    if (this.state.remindCount >= this.policy.maxRemindCount) {
      return { show: false, isForce: false, reason: '' };
    }

    // 提醒间隔未到
    const remindIntervalMs = this.policy.remindIntervalDays * 24 * 3600 * 1000;
    if (now - this.state.lastRemindTime < remindIntervalMs) {
      return { show: false, isForce: false, reason: '' };
    }

    return {
      show: true,
      isForce: false,
      reason: ''
    };
  }

  // 记录用户跳过更新
  async skipUpdate(versionCode: number): Promise<void> {
    this.state.skippedVersionCode = versionCode;
    this.state.remindCount++;
    this.state.lastRemindTime = Date.now();
    await this.saveState();
    hilog.info(0x0000, 'UpdateController', `用户跳过更新: ${versionCode}`);
  }

  // 记录更新检查时间
  async recordCheckTime(): Promise<void> {
    this.state.lastCheckTime = Date.now();
    await this.saveState();
  }

  // 获取当前版本号
  private async getCurrentVersionCode(): Promise<number> {
    try {
      const bundleInfo = await bundleManager.getBundleInfoForSelf(
        bundleManager.BundleFlag.GET_BUNDLE_INFO_DEFAULT
      );
      return bundleInfo.versionCode;
    } catch (error) {
      return 0;
    }
  }

  // 从服务端获取版本信息(模拟)
  private async fetchVersionInfo(): Promise<{
    latestVersionCode: number;
    minSupportVersionCode: number;
    forceUpdateReason: string;
  } | null> {
    // 实际项目中通过HTTP请求获取
    return {
      latestVersionCode: 10500,
      minSupportVersionCode: 10300,
      forceUpdateReason: '为了保护您的数据安全,请更新到最新版本'
    };
  }

  // 加载更新状态
  private async loadState(): Promise<void> {
    if (!this.context) return;
    
    try {
      const pref = await preferences.getPreferences(this.context, 'update_state');
      this.state = {
        lastCheckTime: (await pref.get('last_check_time', 0)) as number,
        lastRemindTime: (await pref.get('last_remind_time', 0)) as number,
        remindCount: (await pref.get('remind_count', 0)) as number,
        skippedVersionCode: (await pref.get('skipped_version', 0)) as number
      };
    } catch (error) {
      hilog.warn(0x0000, 'UpdateController', '加载更新状态失败,使用默认值');
    }
  }

  // 保存更新状态
  private async saveState(): Promise<void> {
    if (!this.context) return;
    
    try {
      const pref = await preferences.getPreferences(this.context, 'update_state');
      await pref.put('last_check_time', this.state.lastCheckTime);
      await pref.put('last_remind_time', this.state.lastRemindTime);
      await pref.put('remind_count', this.state.remindCount);
      await pref.put('skipped_version', this.state.skippedVersionCode);
      await pref.flush();
    } catch (error) {
      hilog.error(0x0000, 'UpdateController', '保存更新状态失败');
    }
  }
}

在EntryAbility中使用:

// entry/src/main/ets/entryability/EntryAbility.ets
import { AbilityConstant, UIAbility, Want } from '@kit.AbilityKit';
import { window } from '@kit.ArkUI';
import { hilog } from '@kit.PerformanceAnalysisKit';
import { UpdateController } from '../utils/UpdateController';

export default class EntryAbility extends UIAbility {
  async onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): Promise<void> {
    hilog.info(0x0000, 'EntryAbility', 'onCreate');
    
    // 初始化更新控制器
    const updateController = UpdateController.getInstance();
    await updateController.init(this.context);
  }

  async onWindowStageCreate(windowStage: window.WindowStage): Promise<void> {
    windowStage.loadContent('pages/Index', async (err) => {
      if (err.code) {
        hilog.error(0x0000, 'EntryAbility', `加载失败: ${JSON.stringify(err)}`);
        return;
      }

      // 页面加载后检查更新
      const updateController = UpdateController.getInstance();
      const result = await updateController.shouldShowUpdate();
      
      if (result.show) {
        hilog.info(0x0000, 'EntryAbility', 
          `需要展示更新提示, 强制=${result.isForce}`);
        // 在页面中展示更新弹窗
      }
    });
  }
}

踩坑与注意事项

坑1:强制更新弹窗无法关闭

用户点击弹窗外部区域关闭了弹窗,然后继续使用旧版本——强制更新形同虚设。

正确做法:强制更新弹窗不允许通过点击外部区域关闭,不允许通过返回键关闭。用户关闭弹窗的唯一方式就是点击"立即更新"。

// 强制更新弹窗配置
dialogController: CustomDialogController = new CustomDialogController({
  builder: ForceUpdateDialog({
    isForce: true
  }),
  autoCancel: false,        // 禁止点击外部关闭
  alignment: DialogAlignment.Center,
  customStyle: true
});

坑2:强制更新后用户回到应用,还是旧版本

用户点击"立即更新"跳转到AppGallery,但AppGallery还没下载完,用户切回你的应用——结果还是旧版本,又弹强制更新。

正确做法:跳转AppGallery后,记录一个标记。用户回到应用时,如果标记存在,不再弹强制更新弹窗,而是展示一个温和的提示"正在更新中,请稍候"。

坑3:强制更新原因不清晰

弹窗只写"请更新到最新版本"——用户不知道为什么要更新,只会觉得你在烦他。

正确做法:写清楚强制更新的原因。比如"当前版本存在安全风险,请更新以保护您的账号安全"。原因越具体,用户越理解。

坑4:网络异常时强制更新卡死

用户网络不好,检查更新的请求超时了,应用卡在启动页面——既不展示主界面,也不展示更新弹窗。

正确做法:网络异常时,跳过更新检查,让用户正常使用。等网络恢复后再检查。

// 网络异常处理
async checkUpdateWithTimeout(): Promise<UpdateCheckResult> {
  try {
    // 设置5秒超时
    const result = await Promise.race([
      this.checkUpdate(),
      new Promise<never>((_, reject) => 
        setTimeout(() => reject(new Error('timeout')), 5000)
      )
    ]);
    return result;
  } catch (error) {
    hilog.warn(0x0000, 'ForceUpdate', '更新检查超时,跳过检查');
    return {
      hasUpdate: false,
      isForce: false,
      currentVersionCode: 0,
      latestVersionCode: 0,
      minSupportVersionCode: 0,
      updateLog: '',
      forceReason: ''
    };
  }
}

坑5:强制更新频率过高

每次打开应用都弹强制更新——用户更新完了还是弹,因为你的minSupportVersion设置得太高。

正确做法:minSupportVersion只在你真正需要强制用户更新时才提高。平时保持一个合理的低版本,让旧版本用户也能正常使用。

坑6:忘记处理应用从后台恢复的场景

用户把应用切到后台,过了很久再切回来——这时候服务端可能已经更新了minSupportVersion,但应用没有重新检查。

正确做法:在Ability的onForeground回调中检查更新。

onForeground(): void {
  // 从后台恢复时检查更新
  const updateController = UpdateController.getInstance();
  updateController.shouldShowUpdate().then(result => {
    if (result.show && result.isForce) {
      // 展示强制更新弹窗
    }
  });
}

HarmonyOS 6适配说明

HarmonyOS 6对强制更新做了几项调整:

  1. 应用内更新API:HarmonyOS 6提供了InAppUpdate API,可以在应用内直接下载和安装更新,不需要跳转到AppGallery。但强制更新仍然建议跳转AppGallery,因为应用内更新需要用户手动确认安装。

  2. 更新弹窗规范:华为要求强制更新弹窗必须包含以下信息:

    • 更新原因(不能只写"发现新版本")
    • 更新内容摘要
    • 更新包大小
    • 预计更新时间
  3. 后台下载限制:HarmonyOS 6对后台下载有严格限制,应用在后台时不能下载更新包。需要在用户可见的前台界面中下载。

  4. 权限要求:应用内更新需要申请ohos.permission.DOWNLOAD权限,并在隐私政策中说明。

// module.json5 权限声明
{
  "module": {
    "requestPermissions": [
      {
        "name": "ohos.permission.INTERNET",
        "reason": "$string:internet_reason"
      },
      {
        "name": "ohos.permission.DOWNLOAD",
        "reason": "$string:download_reason"
      }
    ]
  }
}
  1. 强制更新审核:如果你的应用使用了强制更新,审核时会额外检查强制更新的理由是否充分。如果只是常规版本更新就强制,可能被驳回。

总结

强制更新是把双刃剑。用好了,它能保护用户安全、保证服务稳定;用坏了,它会赶走你的用户。核心记住三点:

  1. 慎用强制更新:只在安全漏洞、API不兼容等极端场景下使用
  2. 给用户尊重:弹窗写清楚原因,非强制时给用户选择权
  3. 处理好边界情况:网络异常、后台恢复、更新未完成等场景都要考虑
维度 评价
学习难度 ⭐⭐ 逻辑简单,但用户体验设计需要用心
使用频率 ⭐⭐⭐ 版本迭代时使用
重要程度 ⭐⭐⭐⭐ 关键时刻能保护用户数据安全
【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。