Backstage v1.30.0 版本升级指南:Url Reader 迁移、Multiton 服务与新前端扩展体系
2026/9/13 9:54:46 网站建设 项目流程

Backstage v1.30.0 版本升级指南:Url Reader 迁移、Multiton 服务与新前端扩展体系

【免费下载链接】backstageBackstage is an open framework for building developer portals项目地址: https://gitcode.com/GitHub_Trending/ba/backstage

本文基于 Backstage 官方 v1.30.0 版本发布说明,系统梳理该版本的核心破坏性变更、新能力与升级路径。v1.30.0 是 Backstage 向"新后端系统 + 新前端系统"演进过程中的关键版本:它删除了大量遗留的UrlReader弃用导出、引入createServiceRef的 multiton 能力与createBackendFeatureLoader动态加载机制,并以前端 Blueprint 体系取代旧的扩展创建器。读完本文,你将掌握 v1.30.0 所有需要关注的破坏性变更、可用的新 API 及其在仓库中的落地实现,从而安全、平滑地完成升级。

版本概览:一次围绕服务注册与扩展体系的重构

v1.30.0 涉及 100+ 个 npm 包的同时发版,其中最核心的几条主线是:

  • 后端系统收紧@backstage/backend-plugin-api@0.8.0删除了一批弃用类型与导出,@backstage/backend-common@0.24.0@backstage/backend-app-api@0.9.0移除全部UrlReader相关工厂导出,统一收敛到@backstage/backend-defaults
  • 服务可组合性提升createServiceRef新增multiton选项,允许同一服务引用安装多个实现(典型落地即 Url Reader 工厂扩展点);
  • 后端功能动态加载:新增createBackendFeatureLoader,支持按配置动态安装后端特性;
  • 前端扩展体系换代@backstage/frontend-plugin-api@0.7.0全面切换到 Blueprint 模式与 v2 扩展格式,createExtensionBlueprintIconBundleBlueprintplugin.withOverrides成为新主力 API;
  • CLI 去 Yarn 化@backstage/cli@0.27.0移除所有基于 lockfile 的依赖分析与变更逻辑;
  • 后端任务包进入弃用倒计时@backstage/backend-tasks@0.6.0明确标记为 deprecated。

下文按主题逐项展开,并给出仓库源码佐证。

破坏性变更一:Url Reader 全面迁移到 backend-defaults

这是 v1.30.0 中影响面最广的破坏性变更。@backstage/backend-app-api@0.9.0移除了若干弃用的服务工厂(含urlReaderServiceFactory),@backstage/backend-common@0.24.0则一次性删除了全部 Url Reader 相关导出,包括:

  • 类型:UrlReader(改用UrlReaderService)、ReadUrlOptions/ReadUrlResponse(改用UrlReaderServiceReadUrlOptions/UrlReaderServiceReadUrlResponse)、ReadTreeOptions/ReadTreeResponse系列、SearchOptions/SearchResponse系列;
  • 具体实现类:AzureUrlReaderBitbucketUrlReaderBitbucketCloudUrlReaderBitbucketServerUrlReaderGithubUrlReaderGitlabUrlReaderGerritUrlReaderGiteaUrlReaderHarnessUrlReaderAwsS3UrlReaderFetchUrlReader
  • 组装工具:UrlReadersUrlReadersOptionsUrlReaderPredicateTupleReaderFactoryReadUrlResponseFactoryReadTreeResponseFactory及各类FromStreamOptions

迁移方式:以上全部改从@backstage/backend-defaults/urlReader子路径导入,接口类型则使用@backstage/backend-plugin-api中对应的UrlReaderService*类型。若你的代码仍直接依赖@backstage/backend-common中的旧导出,升级时必然出现编译错误,请按上述对照表逐一替换。

仓库源码中的实际落地可佐证这一收敛方向:在 urlReaderServiceFactory.ts 中,urlReaderServiceFactory通过createServiceFactory声明对coreServices.urlReader的注册,并依赖configlogger以及下文将要介绍的urlReaderFactoriesServiceRef组装出UrlReaders.default(...)实例。

新能力一:createServiceRef 的 multiton 选项与服务多实现注册

@backstage/backend-plugin-api@0.8.0中,createServiceRef新增布尔选项multiple(最终命名为multiton,默认false)。当设置为true时,同一服务引用可安装多个实现;依赖方拿到的是所有已注册实例组成的数组。设计动机在变更说明中写得很直白:希望在不整体替换服务的前提下增强服务能力——典型场景就是为UrlReader增加新的外部目标支持,而不必重写服务本身。

从源码看,multiton 是ServiceRef的第三类型参数:见 types.ts 中TInstances extends 'singleton' | 'multiton'的定义,以及createServiceRef实现中multiton = false的默认值与toJSON序列化(types.ts)。依赖解析时,multiton 引用会被注入为数组(见ServiceRefsToInstances工具类型)。

官方示例:为 UrlReader 注册自定义工厂

// @backstage/backend-defaults + export const urlReaderFactoriesServiceRef = createServiceRef<ReaderFactory>({ + id: 'core.urlReader.factories', + scope: 'plugin', + multiton: true, + }); export const urlReaderServiceFactory = createServiceFactory({ service: coreServices.urlReader, deps: { config: coreServices.rootConfig, logger: coreServices.logger, + factories: urlReaderFactoriesServiceRef, }, - async factory({ config, logger }) { + async factory({ config, logger, factories }) { return UrlReaders.default({ config, logger, + factories, }); }, });

这段代码就是仓库中 urlReaderServiceFactory.ts 的真实实现——urlReaderFactoriesServiceRefmultiton: true声明,urlReaderServiceFactory将它作为依赖注入,从而收集全部已安装的工厂实现。

随后你可以在后端实例中追加自定义 Url Reader 工厂:

// packages/backend/index.ts import { createServiceFactory } from '@backstage/backend-plugin-api'; import { urlReaderFactoriesServiceRef } from '@backstage/backend-defaults'; backend.add(createServiceFactory({ service: urlReaderFactoriesServiceRef, deps: {}, async factory() { return CustomUrlReader.factory; }, }));

除此之外,v1.30.0 还同步为ServiceRegister增加了"同一服务引用注册多个实现"的能力(@backstage/backend-app-api@0.9.0),并修复了 multiton 服务的类型问题(plugin/module 依赖 multiton 服务时能获得正确类型)。

新能力二:createBackendFeatureLoader 动态加载后端特性

@backstage/backend-plugin-api@0.8.0新增createBackendFeatureLoader,用于以编程方式选择并安装后端特性。其核心语义:

  • loader 可以返回一个可迭代的特性列表(Array或其他 iterable),因此天然支持写成 generator 函数;
  • 同步与异步 loader 均受支持,可yield import(...)动态加载 ES Module 形式的BackendFeature
  • loader 可以依赖服务,但只能依赖 root 作用域的服务,且不得覆盖已被实例化的服务。

仓库实现见 createBackendFeatureLoader.ts:它返回一个featureType: 'loader'BackendFeature,内部用for await消费迭代器,将其中合法的特性($$type === '@backstage/BackendFeature')或{ default }模块形态统一规整为特性数组。

官方示例——按自定义配置开关启用搜索相关后端插件:

const searchLoader = createBackendFeatureLoader({ deps: { config: coreServices.rootConfig, }, *loader({ config }) { // Example of a custom config flag to enable search if (config.getOptionalString('customFeatureToggle.search')) { yield import('@backstage/plugin-search-backend/alpha'); yield import('@backstage/plugin-search-backend-module-catalog/alpha'); yield import('@backstage/plugin-search-backend-module-explore/alpha'); yield import('@backstage/plugin-search-backend-module-techdocs/alpha'); } }, });

新能力三:SchedulerService 支持手动触发任务

@backstage/backend-plugin-api@0.8.0@backstage/backend-tasks@0.6.0同步支持了frequency: { trigger: 'manual' }的任务定义:任务不会被自动调度,只在调用SchedulerService.triggerTask(id)(或旧接口PluginTaskScheduler.triggerTask)时运行。

仓库中的类型定义可验证此语义:在 SchedulerService.ts 中,trigger: 'manual'被明确注释为"仅通过triggerTask手动触发,不做自动调度;适用于需要对全局任务加锁、避免并发执行"的场景,且triggerTask(id)是公开接口(SchedulerService.ts)。这为"按需执行的后台任务"提供了标准化的新后端系统写法。

破坏性变更二:backend-tasks 弃用与迁移对照

@backstage/backend-tasks@0.6.0被标记为 deprecated,将在近期删除。官方给出的迁移对照如下:

旧导出(backend-tasks)新导出(backend-plugin-api / backend-defaults / types)
TaskSchedulercoreServices.scheduler(新后端系统)或DefaultSchedulerService(backend-defaults)
TaskRunnerSchedulerServiceTaskRunner
TaskFunctionSchedulerServiceTaskFunction
TaskDescriptorSchedulerServiceTaskDescriptor
TaskInvocationDefinitionSchedulerServiceTaskInvocationDefinition
TaskScheduleDefinitionSchedulerServiceTaskScheduleDefinition(原文笔误为 Function,以类型语义为准)
TaskScheduleDefinitionConfigSchedulerServiceTaskScheduleDefinitionConfig
PluginTaskSchedulerSchedulerService(通常经coreServices.scheduler
readTaskScheduleDefinitionFromConfigreadSchedulerServiceTaskScheduleDefinitionFromConfig
HumanDurationTypesHumanDuration(来自@backstage/types

受此影响,v1.30.0 中几乎所有目录类后端插件(catalog-backend、scaffolder-backend、search-backend-node、kubernetes-backend、events 系列模块等)都同步执行了"停用 backend-tasks"的内部改造(对应fc24d9e提交),并在依赖清单中移除该包。如果你的自定义后端模块直接依赖@backstage/backend-tasks,请在升级时一并完成上述迁移。

其他后端破坏性变更与兼容性修复

  • @backstage/backend-plugin-api@0.8.0删除弃用类型ServiceRefConfigServiceRefOptionsRootServiceFactoryConfigRootServiceFactoryOptionsPluginServiceFactoryConfigPluginServiceFactoryOptions,以及一组UrlReader旧类型(ReadUrlOptionsReadTreeResponseFileSearchResponse等,均改用UrlReaderService*前缀)。
  • @backstage/backend-common@0.24.0剩余导出弃用cacheToPluginCacheManagercreateLegacyAuthAdaptersLegacyCreateRouterlegacyPluginloggerToWinstonLoggermakeLegacyPlugin全部标记弃用,官方建议完整迁移到新后端系统;createConfigSecretEnumeratorbackend-app-api改由backend-common导出。
  • @backstage/backend-defaults@0.4.2多项修复createHealthRouter改为经@backstage/backend-defaults/rootHttpRouter导出;健康检查端点固定为/.backstage/health/v1/readiness/.backstage/health/v1/liveness;JWKS 外部访问方法配置增加访问限制;morgan中间件改用自定义日志格式以避免记录 PII;SQL 查询改用格式化占位符防注入;SchedulerService支持 manual 触发;GitlabUrlReader.readUrl/readTree支持调用方传入 token(bearer 或 private token)。
  • @backstage/backend-test-utils@0.5.0:移除setupRequestMockHandlers(改用registerMswTestHooks)、MockDirectoryOptions(改用CreateMockDirectoryOptions)、isDockerDisabledForTestsServiceFactoryTester.get(改用getSubject);startTestBackendServiceFactoryTester默认服务现在包含 Root Health Service。
  • AWS 可观测性backend-commoncatalog-backend-module-aws为 AWS SDK 客户端设置了 user agent 头,方便通过 CloudTrail 等工具追踪 Backstage 发起的 AWS API 调用。
  • @backstage/catalog-model@1.6.0:Domain 与 System 实体类型新增可选的spec.type属性。

前端系统演进:Extension v2 格式与 Blueprint 体系

@backstage/frontend-plugin-api@0.7.0是 v1.30.0 前端的核心版本,它完成了一次扩展声明模型的换代,主要变化如下。

扩展输入/输出改为数组声明

扩展从"命名数据引用的 map"改为"数据引用的数组",以降低输入/输出命名带来的困惑,并支持更强大的覆盖(override)能力。旧写法:

const exampleExtension = createExtension({ name: 'example', inputs: { items: createExtensionInput({ element: coreExtensionData.reactElement, }), }, output: { element: coreExtensionData.reactElement, }, factory({ inputs }) { return { element: ( <div> Example {inputs.items.map(item => { return <div>{item.output.element}</div>; })} </div> ), }; }, });

迁移后:

const exampleExtension = createExtension({ name: 'example', inputs: { items: createExtensionInput([coreExtensionData.reactElement]), }, output: [coreExtensionData.reactElement], factory({ inputs }) { return [ coreExtensionData.reactElement( <div> Example {inputs.items.map(item => { return <div>{item.get(coreExtensionData.reactElement)}</div>; })} </div>, ), ]; }, });

createExtensionBlueprint 取代扩展创建器

4e53ad6提交引入createExtensionBlueprint,用于封装"扩展种类"并取代旧create*Extension创建器模式(7bd27e1c7603e8等提交在 catalog、search、org、user-settings、api-docs 等多个插件中同步弃用了旧模式)。仓库中可见packages/frontend-plugin-api/src/blueprints/目录下已落地PageBlueprintApiBlueprintAppRootElementBlueprintPluginWrapperBlueprintAnalyticsImplementationBlueprint等一批官方 Blueprint 实现。

创建与使用 Blueprint 实例的标准写法:

// 创建扩展蓝图,用于创建实例 const EntityCardBlueprint = createExtensionBlueprint({ kind: 'entity-card', attachTo: { id: 'test', input: 'default' }, output: [coreExtensionData.reactElement], factory(params: { text: string }) { return [coreExtensionData.reactElement(<h1>{params.text}</h1>)]; }, }); // 用参数创建蓝图实例 const testExtension = EntityCardBlueprint.make({ name: 'foo', params: { text: 'Hello World', }, });

Blueprint 还支持在实例上直接.override(...)(覆盖挂载点、扩展配置 schema 与工厂,工厂以 generator 形式组合原始输出),并对inputs做合并、对output停止合并(34f1b2a)。

IconBundleBlueprint 与 plugin.withOverrides

  • IconBundleBlueprint7777b5f):创建图标包扩展,安装在 App 中用于覆盖或新增应用图标:
import { IconBundleBlueprint } from '@backstage/frontend-plugin-api'; const exampleIconBundle = IconBundleBlueprint.make({ name: 'example-bundle', params: { icons: { user: MyOwnUserIcon, }, }, });
  • plugin.withOverrides99abb6b):支持在插件层覆盖其扩展:
import homePlugin from '@backstage/plugin-home'; export default homePlugin.withOverrides({ extensions: [ homePage.getExtension('page:home').override({ *factory(originalFactory) { yield* originalFactory(); yield coreExtensionData.reactElement(<h1>My custom home page</h1>); }, }), ], });

配套能力还有:plugin.getExtension(...)获取插件扩展定义(要求 v2 格式)、ExtensionBoundary.lazy创建支持懒加载的包裹元素(页面 Blueprint 已自动使用)、Blueprint 支持zodconfig schema 及 schema 自动合并(3fb421d)、扩展数据引用改为createExtensionDataRef<MyType>().with({ id: '...' })的封装 ID 写法(31bfc44,旧写法弃用)、createFrontendPlugin更名为createPlugin(旧符号保留但弃用)。

破坏性变更:useRouteRef 始终可空

72754db是前端唯一的显式破坏性变更:所有类型路由引用经useRouteRef使用时始终被视为可选,调用方必须处理潜在的undefined返回值;同时createExternalRouteRefoptional选项被移除(不再需要)。官方判断该影响面极小,因为支持新系统的插件仍通过@backstage/core-plugin-apiuseRouteRef搭配convertLegacyRouteRef使用。

前端其他值得注意的变化

  • @backstage/frontend-app-api@0.8.0:支持IconBundleBlueprint、支持 v2 扩展、为扩展增加 config 输入类型,并将createExtensionv1 用法迁移到 v2。
  • @backstage/core-compat-api@0.2.8compatWrapperconvertLegacyRouteRef现在支持从新系统向旧系统转换;新增convertLegacyPluginconvertLegacyPageExtension工具,用于把遗留插件/页面扩展转换到新系统。
  • @backstage/frontend-test-utils@0.1.12:新增扩展测试 API;createExtensionTester.render方法弃用,改由renderInTestApp直接渲染;Blueprint 的.make拆分为.make(简单实例化)与.makeWithOverrides(底层覆盖)。
  • @backstage/plugin-kubernetes@0.11.13:开始通过/alpha子路径支持新前端系统。

CLI 与构建链:移除 lockfile 分析与模块联邦增强

@backstage/cli@0.27.0的破坏性变更集中在移除与 Yarn lockfile 的耦合:

  • versions:bump不再修改 lockfile 做依赖升级与去重,只更新package.json
  • versions:check命令被整体移除(其唯一职责就是 lockfile 校验与变更),官方推荐改用yarn dedupe(Yarn 2+)或yarn-deduplicate包(Yarn classic);
  • 内置于package start的 lockfile 一致性告警被移除。

官方解释:Backstage 生态对包重复问题的容忍度已大幅改善,这些特性的必要性下降;移除后可显著减少 CLI 与 Yarn 的集成面,为未来支持更多包管理器铺路。此外,e53074f将默认后端插件模板从Config切换到RootConfigService;模块联邦构建新增FORCE_REACT_DEVELOPMENT环境变量强制使用 react/react-dom 开发版,并支持通过EXPERIMENTAL_MODULE_FEDERATION环境变量在yarn start时启用动态插件;新命令支持设置包许可证(adabb40)。

@backstage/config-loader@1.9.0为 File/RemoteConfigSource增加了可配置的解析逻辑(不再局限于 YAML,可解析 JSON 等格式),并为ConfigSources.default/defaultForTargets增加allowMissingDefaultConfig选项,允许在默认app-config.yaml缺失时省略对应 ConfigSource。

认证相关变更

  • @backstage/plugin-auth-node@0.5.0(破坏性):通过.signIn.resolvers配置的登录解析器现在优先于传给createOAuthProviderFactorysignInResolver选项。后者由此降级为"默认解析器",可被配置覆盖。
  • @backstage/plugin-auth-backend-module-cloudflare-access-provider@0.2.0:支持 Cloudflare 自定义请求头与自定义 Cookie 认证名。
  • 所有 auth provider 模块统一为配置 schema 增加signIn字段(c8f1cae)。
  • @backstage/plugin-auth-backend-module-aws-alb-provider:新增signer配置项,用于校验 token 的 claims,官方强烈建议设置为 ALB 实例的 ARN(形如arn:aws:elasticloadbalancing:us-east-2:...:loadbalancer/app/my-load-balancer/...),确保 provider 能安全校验入站 token 的真实性。完整配置示例:
auth: providers: awsalb: issuer: 'https://example.okta.com/oauth2/default' signer: 'arn:aws:elasticloadbalancing:us-east-2:123456789012:loadbalancer/app/my-load-balancer/1234567890123456' region: 'us-west-2' signIn: resolvers: - resolver: emailMatchingUserEntityProfileEmail - resolver: emailLocalPartMatchingUserEntityName
  • @backstage/core-app-api@1.14.2:受保护模式下删除 session cookie 的请求改用原生fetch(而非FetchApi),修复登出时应用立即重新登录的问题。

Catalog、Scaffolder 与 TechDocs 功能更新

Catalog

  • @backstage/plugin-catalog@1.22.0新增HasSubdomainsCard组件,展示指定 Domain 的子域;RelatedEntitiesCard预置组件开放复用;实体关系卡片(新前端系统/alpha)的默认过滤器更精细;所有表格新增tableOptions,API 表格新增title
  • @backstage/plugin-catalog-backend@1.25.0:弃用RouterOptionsCatalogBuilderCatalogEnvironment(强烈建议升级到新后端系统);新增CatalogLocationsExtensionPoint扩展点与setAllowedLocationTypes(不调用时保留默认allowedLocationTypes);ProcessorOutputCollector在收到metadata.annotations格式非法的延迟实体时直接报错,避免后续误导性的"缺少 location 注解"报错。
  • GitLab catalog provider 新增可选excludeRepos配置(c7b14ed);GitHub 模块修复repository事件支持(改用$.organization.login$.repository.html_url);Azure Entra ID 模块支持按组成员身份摄取群组(58dff4d)。

Scaffolder

  • @backstage/plugin-scaffolder@1.24.0MyGroupsPicker改用entityPresentationApi展示实体;新增支持 Bitbucket 自动补全的字段扩展RepoBranchPickerRepoUrlPicker修复切换主机时凭据不刷新的问题;Scaffolder 前端新增 i18n。
  • @backstage/plugin-scaffolder-backend@1.24.0:新增 OpenTelemetry 指标支持;scaffolder tasks 端点支持按状态过滤(c544f81);修复catalog:write向不存在的目录写入的问题。
  • @backstage/plugin-scaffolder-react@1.11.0:评审页支持对象条目分行展示;通过FormProps暴露uiSchemaformContext以自定义表单字段 UI;支持ajv-errors自定义校验错误信息。
  • 各 scaffolder 后端模块集中补充了大量 action 示例与测试用例(publish:azurepublish:bitbucketServerpublish:giteagithub:environment:creategithub:repo:creategithub:pagesfetch:cookiecutterfetch:railsgitlab:issues:create等),GitLab 模块新增gitlab:mergeRequest:auto自定义 action(自动在 create/update 之间选择提交动作),并允许createGitlabProjectVariableAction使用 OAuth token。
  • @backstage/plugin-scaffolder-backend-module-bitbucket-cloud:新增listBranchesByRepository方法,为branches资源提供自动补全。

TechDocs 与其他

  • 新增@backstage/plugin-techdocs-common@0.1.0包,统一注解常量;@backstage/plugin-techdocs@1.10.8支持mkdocs-redirects插件(外部跳转不支持,遇到外部 URL 时回到文档站点首页,跳转前弹通知提示);TechDocsReaderPage 的样式可独立于全局主题做细粒度覆盖;@backstage/plugin-techdocs-node@1.12.9修复嵌套文档的 Edit URL、独立处理repo_urledit_uri
  • 通知@backstage/plugin-notifications@0.3.0默认在打开 snackbar 或 Web 通知链接时将通知标记为已读,并修复页面切换导致通知重载的问题;@backstage/plugin-notifications-backend-module-email@0.2.0NotificationTemplateRenderer.getSubject/getText/getHtml改为返回 Promise 且必须await(破坏性),并支持流式传输调试、按邮件地址允许/拒绝接收通知。
  • 权限MetadataResponseMetadataResponseSerializedRule类型从plugin-permission-node迁至plugin-permission-common(旧位置保留 re-export 并标记弃用)。
  • 集成@backstage/integration@1.14.0GitlabUrlReader.readUrl/readTree支持调用方传入 token;Harness URL 工具函数支持 account/org 级 URL。
  • @backstage/create-app@0.5.18:默认应用新增 Kubernetes 插件、默认启用权限配置(bfeba46),并调整 Dockerfile 与app-config.production.yaml便于用示例数据快速上手。

升级建议与验证

  1. 优先处理 Url Reader 与 backend-tasks 迁移:二者均为破坏性/弃用性质,直接决定能否编译通过。可全局搜索@backstage/backend-common中的*UrlReaderUrlReaders以及@backstage/backend-tasks引用,按上文对照表替换。
  2. 锁定后端服务依赖@backstage/backend-plugin-api已升至 0.8.0,若你的服务工厂依赖旧类型(ServiceRefConfig等),需同步更新类型名;考虑将可增强的服务(如 UrlReader)改造为 multiton 依赖,便于后续扩展。
  3. 前端扩展迁移到 Blueprint/v2 格式createExtensionv1 与旧create*Extension创建器虽仍可用但已弃用,建议新代码直接使用createExtensionBlueprint、v2 数组式输入输出,并处理useRouteRef的可空返回值。
  4. CLI 流程调整:移除对versions:checkversions:bumplockfile 行为的依赖,改用yarn dedupe维护依赖去重。
  5. 回归验证:可用官方 Upgrade Helper 按to=1.30.0生成逐包升级清单;重点回归健康检查端点(/.backstage/health/v1/*)、GitLab/Harness 集成、通知邮件模板(await 化)以及 Scaffolder 各 Git 发布 action。

小结

v1.30.0 是 Backstage 双系统演进路线图上的一个"收敛型"版本:后端通过删除backend-common遗留导出、引入 multiton 与 feature loader,把服务注册和动态能力安装推向更统一的模型;前端则以 Blueprint 与 v2 扩展格式为后续 API 稳定化铺路。对于仍在维护自定义插件/模块的团队,本版本最值得投入的迁移工作是 Url Reader 收敛与backend-tasks弃用清理——它们都有清晰、可机械执行的替换路径,尽早完成可显著降低后续升级成本。

【免费下载链接】backstageBackstage is an open framework for building developer portals项目地址: https://gitcode.com/GitHub_Trending/ba/backstage

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询