完整教程:Coze源码分析-资源库-编辑插件-后端源码-IDL/API/应用服务层

news/2025/10/1 21:07:09/文章来源:https://www.cnblogs.com/tlnshuju/p/19122869

完整教程:Coze源码分析-资源库-编辑插件-后端源码-IDL/API/应用服务层

2025-10-01 21:04  tlnshuju  阅读(0)  评论(0)    收藏  举报

前言

本文将深入分析Coze Studio项目中用户编辑插件功能的后端实现。当用户登录Coze平台后,点击"资源库" → 接着在表格中点击要编辑的插件行,触发的是一个完整的插件资源编辑流程。插件作为AI应用开发的核心组件,其编辑操作涉及权限验证、编辑锁定、数据更新和多个后端服务层的协同工作。通过源码解读,我们将深入理解插件编辑功能在整个Coze Studio后端架构中的设计思路和技术实现细节。

项目架构概览

插件编辑功能架构设计

Coze Studio的插件编辑功能采用了经典的分层架构模式,专门针对插件资源的安全编辑进行了优化设计。整个架构围绕插件的权限验证、编辑锁定、数据更新和版本管理展开:

┌─────────────────────────────────────────────────────────────┐
│                    IDL接口定义层                             │
│  ┌─────────────┐  ┌─────────────┐    ┌─────────────┐        │
│  │ base.thrift │  │plugin_      │    │ api.thrift  │        │
│  │             │  │develop.     │    │             │        │
│  │             │  │thrift       │    │             │        │
│  └─────────────┘  └─────────────┘    └─────────────┘        │
└─────────────────────────────────────────────────────────────┘↓
┌─────────────────────────────────────────────────────────────┐
│                    API网关层                                 │
│  ┌─────────────┐  ┌─────────────┐  ┌─────────────┐          │
│  │   Handler   │  │   Router    │  │ Middleware  │          │
│  │   处理器     │  │   路由      │  │   中间件     │          │
│  └─────────────┘  └─────────────┘  └─────────────┘          │
└─────────────────────────────────────────────────────────────┘↓
┌─────────────────────────────────────────────────────────────┐
│                   应用服务层                                 │
│  ┌─────────────────────────────────────────────────────┐    │
│  │           PluginApplicationService                  │    │
│  │     CheckAndLockPluginEdit UpdatePluginMeta         │    │
│  └─────────────────────────────────────────────────────┘    │
└─────────────────────────────────────────────────────────────┘↓
┌─────────────────────────────────────────────────────────────┐
│                   领域服务层                                 │
│  ┌─────────────────────────────────────────────────────┐    │
│  │              pluginServiceImpl                      │    │
│  │                ┌─────────────────┐                  │    │
│  │                │UpdatePlugin     │                  │    │
│  │                │Meta             │                  │    │
│  │                └─────────────────┘                  │    │
│  └─────────────────────────────────────────────────────┘    │
└─────────────────────────────────────────────────────────────┘↓
┌─────────────────────────────────────────────────────────────┐
│                   数据访问层                                 │
│  ┌─────────────────────────────────────────────────────┐    │
│  │              PluginRepository                       │    │
│  │  ┌──── ─────── ──── ──┐  ┌─────────────────────────┐│    │
│  │  │PluginDAO           │  │plugin.gen.go            ││    │
│  │  │UpdatePlugin        │  │tool.gen.go              ││    │
│  │  │ToolDAO             │  │GORM Generated Code      ││    │
│  │  └──── ─────── ─── ───┘  └─────────────────────────┘│    │
│  └─────────────────────────────────────────────────────┘    │
└─────────────────────────────────────────────────────────────┘↓
┌─────────────────────────────────────────────────────────────┐
│                   基础设施层                                 │
│              ┌─ ─ ─── ─ ── ── ─ ─ ─┐                        │
│              │       gorm.DB       │                        │
│              │ es.Client redisImpl │                        │
│              └── ─ ── ── ─ ── ── ─ ┘                        │
└─────────────────────────────────────────────────────────────┘↓
┌─────────────────────────────────────────────────────────────┐
│                   存储服务层                                 │
│  ┌─────────────────────────────────────────────────────┐    │
│  │       MySQL数据库       Redis数据库                  │    │
│  │            ElasticSearch数据库                      │    │
│  └─────────────────────────────────────────────────────┘    │
└─────────────────────────────────────────────────────────────┘

插件编辑流程核心组件

API路由映射:

  • POST /api/plugin_api/check_and_lock_plugin_edit - 检查并锁定插件以进行编辑
  • POST /api/plugin_api/update_plugin_meta - 更新插件元数据
  • POST /api/plugin_api/unlock_plugin_edit - 解锁插件编辑

核心数据模型:

// 文件位置:backend/api/model/crossdomain/plugin/plugin.go
type PluginInfo struct {
ID           int64
PluginType   api.PluginType
SpaceID      int64
DeveloperID  int64
APPID        *int64
RefProductID *int64 // for product plugin
IconURI      *string
ServerURL    *string
Version      *string
VersionDesc  *string
CreatedAt    int64
UpdatedAt    int64
Manifest     *PluginManifest
OpenapiDoc   *Openapi3T
}
// 文件位置:backend/api/model/crossdomain/plugin/tool.go
type ToolInfo struct {
ID              int64
PluginID        int64
Name            string
Method          HTTPMethod
SubURL          string
ActivatedStatus ActivatedStatus
DebugStatus     DebugStatus
CreatedAt       int64
UpdatedAt       int64
RequestSchema   *openapi3.Schema
ResponseSchema  openapi3.Responses
}

1. IDL接口定义层

IDL基础类型定义(base.thrift)

文件位置:idl/base.thrift
核心代码:

namespace py base
namespace go base
namespace java com.bytedance.thrift.base
struct TrafficEnv {1: bool   Open = false,2: string Env  = ""   ,
}
struct Base {1:          string             LogID      = "",2:          string             Caller     = "",3:          string             Addr       = "",4:          string             Client     = "",5: optional TrafficEnv         TrafficEnv     ,6: optional map Extra          ,
}
struct BaseResp {1:          string             StatusMessage = "",2:          i32                StatusCode    = 0 ,3: optional map Extra             ,
}

文件作用:
定义了Coze Studio项目中所有接口的基础数据结构,作为其他IDL文件的依赖基础。

插件开发接口定义(plugin_develop.thrift)

文件位置:idl/plugin/plugin_develop.thrift

当Coze用户登录平台后点击"资源库" → 接着在表格中点击要编辑的插件行时,前端会调用插件编辑相关的接口。该文件定义了插件编辑的核心数据结构和接口。

检查并锁定插件编辑接口
struct CheckAndLockPluginEditRequest {1  : required i64    plugin_id (api.body = "plugin_id", api.js_conv = "str"),255: optional base.Base Base                                                   ,
}
struct CheckAndLockPluginEditResponse {1  : required i32                                              code   ,2  : required string                                           msg     ,3  :          plugin_develop_common.CheckAndLockPluginEditData data     ,255: optional base.BaseResp                                    BaseResp                   ,
}
更新插件元数据接口
struct UpdatePluginMetaRequest {1  : required i64                                                                                     plugin_id (api.js_conv = "str")     ,2  : optional string                                                                                     name           ,3  : optional string                                                                                     desc           ,4  : optional string                                                                                     url            , // plugin service url5  : optional plugin_develop_common.PluginIcon                                                           icon           ,6  : optional plugin_develop_common.AuthorizationType                                                    auth_type      ,7  : optional plugin_develop_common.AuthorizationServiceLocation                                         location       , // When the sub-authorization type is api/token, the token parameter position8  : optional string                                                                                     key            , // When the sub-authorization type is api/token, the token parameter key9  : optional string                                                                                     service_token  , // When the sub-authorization type is api/token, the token parameter value10 : optional string                                                                                     oauth_info     , // When the sub-authorization type is oauth, for oauth information, see GetOAuthSchema return value11 : optional map> common_params  , // JSON serialization12 : optional plugin_develop_common.CreationMethod                                                       creation_method, // ignore13 : optional i32                                                                                        edit_version   , // ignore14 : optional plugin_develop_common.PluginType                                                           plugin_type    ,15 : optional i32                                                                                        sub_auth_type  , // Level 2 authorization type16 : optional string                                                                                     auth_payload   , // ignore17 : optional bool                                                                                       fixed_export_ip, // ignore255: optional base.Base                                                                                  Base           ,
}
struct UpdatePluginMetaResponse {1  :          i64           code        ,2  :          string        msg         ,3  :          i32           edit_version,255: optional base.BaseResp BaseResp    ,
}
解锁插件编辑接口
struct UnlockPluginEditRequest {1  : required i64    plugin_id (api.body = "plugin_id", api.js_conv = "str"),255: optional base.Base Base                                                   ,
}
struct UnlockPluginEditResponse {1  : required i32           code       ,2  : required string        msg        ,3  : required bool          released ,255: optional base.BaseResp BaseResp                       ,
}

插件开发服务接口(plugin_develop.thrift)

文件位置:idl/plugin/plugin_develop.thrift

该文件定义了PluginDevelopService服务的核心接口,包括插件管理的服务接口定义。

PluginDevelopService服务定义
service PluginDevelopService {CheckAndLockPluginEditResponse CheckAndLockPluginEdit(1: CheckAndLockPluginEditRequest request)(api.post='/api/plugin_api/check_and_lock_plugin_edit', api.category="plugin", api.gen_path="plugin", )UnlockPluginEditResponse UnlockPluginEdit(1: UnlockPluginEditRequest request)(api.post='/api/plugin_api/unlock_plugin_edit', api.category="plugin", api.gen_path="plugin")UpdatePluginMetaResponse UpdatePluginMeta(1: UpdatePluginMetaRequest request) (api.post = '/api/plugin_api/update_plugin_meta', api.category = "plugin")// 其他服务接口...
}

插件接口路由映射说明:

  • CheckAndLockPluginEdit: POST /api/plugin_api/check_and_lock_plugin_edit - 检查并锁定插件以进行编辑
  • UpdatePluginMeta: POST /api/plugin_api/update_plugin_meta - 更新插件元数据
  • UnlockPluginEdit: POST /api/plugin_api/unlock_plugin_edit - 解锁插件编辑

接口功能说明:

  • 数据结构设计: CheckAndLockPluginEditRequest包含插件ID字段;UpdatePluginMetaRequest包含插件ID、名称、描述、URL等可更新字段;UnlockPluginEditRequest包含插件ID字段
  • 编辑操作: 支持通过UI界面编辑插件,包括基本信息更新、授权配置修改等

IDL主API服务聚合文件(api.thrift)

文件位置:idl/api.thrift

该文件是整个Coze项目的API服务聚合入口点,负责将所有业务模块的IDL服务定义统一聚合,为代码生成工具提供完整的服务接口定义。

核心代码:

include "./plugin/plugin_develop.thrift"
namespace go coze
// 插件开发核心服务聚合
service PluginDevelopService extends plugin_develop.PluginDevelopService {}
// 其他业务服务聚合

插件接口聚合说明:
通过 service PluginDevelopService extends plugin_develop.PluginDevelopService {} 聚合定义,api.thrift将plugin_develop.thrift中定义的所有插件相关接口统一暴露.

2. API网关层

接口定义-plugin_develop.go文件详细分析

文件位置:backend\api\model\plugin_develop\plugin_develop.go
核心代码:

type PluginDevelopService interface {
CheckAndLockPluginEdit(ctx context.Context, request *CheckAndLockPluginEditRequest) (r *CheckAndLockPluginEditResponse, err error)
UnlockPluginEdit(ctx context.Context, request *UnlockPluginEditRequest) (r *UnlockPluginEditResponse, err error)
UpdatePluginMeta(ctx context.Context, request *UpdatePluginMetaRequest) (r *UpdatePluginMetaResponse, err error)
}
插件相关接口模型定义

当Coze用户登录平台后点击"资源库" → 接着在表格中点击要编辑的插件行时,前端会调用插件编辑相关接口来编辑插件资源。

CheckAndLockPluginEditRequest 检查并锁定插件编辑请求结构体

type CheckAndLockPluginEditRequest struct {
// 插件ID
PluginID int64 `thrift:"plugin_id,1,required" form:"plugin_id,required" json:"plugin_id,required" query:"plugin_id,required"`
Base     *base.Base `thrift:"Base,255" form:"Base" json:"Base" query:"Base"`
}

UpdatePluginMetaRequest 更新插件元数据请求结构体

type UpdatePluginMetaRequest struct {
// 插件ID
PluginID int64 `thrift:"plugin_id,1,required" form:"plugin_id,required" json:"plugin_id,required" query:"plugin_id,required"`
// 插件名称
Name         *string `thrift:"name,2" form:"name" json:"name" query:"name"`
// 插件描述
Desc         *string `thrift:"desc,3" form:"desc" json:"desc" query:"desc"`
// 插件服务地址前缀
Url          *string `thrift:"url,4" form:"url" json:"url" query:"url"`
// 插件图标
Icon         *plugin_develop_common.PluginIcon `thrift:"icon,5" form:"icon" json:"icon" query:"icon"`
// 插件授权类型
AuthType     *plugin_develop_common.AuthorizationType `thrift:"auth_type,6" form:"auth_type" json:"auth_type" query:"auth_type"`
// 空间ID
Base         *base.Base `thrift:"Base,255" form:"Base" json:"Base" query:"Base"`
// 其他字段...
}

UnlockPluginEditRequest 解锁插件编辑请求结构体

type UnlockPluginEditRequest struct {
// 插件ID
PluginID int64 `thrift:"plugin_id,1,required" form:"plugin_id,required" json:"plugin_id,required" query:"plugin_id,required"`
Base     *base.Base `thrift:"Base,255" form:"Base" json:"Base" query:"Base"`
}
接口功能说明

业务功能

  • 插件编辑锁定:确保在同一时间只有一个用户可以编辑特定插件,防止冲突
  • 插件元数据更新:根据用户输入更新插件的基本信息、授权配置等
  • 编辑解锁:当用户完成编辑后,释放插件的编辑锁定,允许其他用户编辑
  • 权限验证:确保只有有权限的用户才能编辑插件
  • 数据存储:将更新后的插件信息持久化存储
  • 操作审计:记录编辑操作的日志和审计信息

技术特性

  • 类型安全:使用强类型定义确保插件数据的一致性
  • 多格式支持:支持thrift、form、json、query等多种序列化格式
  • 参数验证:通过required标记确保必要参数的完整性
  • 统一响应:遵循统一的响应格式规范

文件作用
由thriftgo自动生成的Go代码文件,基于plugin_develop.thrift IDL定义生成对应的Go结构体和接口,提供类型安全的插件API模型。该文件实现了完整的Thrift RPC通信机制,包括客户端调用、服务端处理、序列化/反序列化等功能,确保了插件服务间的可靠通信。

插件接口处理器实现

文件位置:backend/api/handler/coze/plugin_develop_service.go

该文件包含了用户登录后点击"资源库" → 接着在表格中点击要编辑的插件行功能的核心API接口处理器,主要负责处理插件资源的编辑功能。

检查并锁定插件编辑处理器
// CheckAndLockPluginEdit .
// @router /api/plugin_api/check_and_lock_plugin_edit [POST]
func CheckAndLockPluginEdit(ctx context.Context, c *app.RequestContext) {
var err error
var req plugin_develop.CheckAndLockPluginEditRequest
err = c.BindAndValidate(&req)
if err != nil {
invalidParamRequestResponse(c, err.Error())
return
}
if req.PluginID <= 0 {
invalidParamRequestResponse(c, "pluginID is invalid")
return
}
resp, err := plugin.PluginApplicationSVC.CheckAndLockPluginEdit(ctx, &req)
if err != nil {
internalServerErrorResponse(ctx, c, err)
return
}
c.JSON(consts.StatusOK, resp)
}
更新插件元数据处理器
// UpdatePluginMeta .
// @router /api/plugin_api/update_plugin_meta [POST]
func UpdatePluginMeta(ctx context.Context, c *app.RequestContext) {
var err error
var req plugin_develop.UpdatePluginMetaRequest
err = c.BindAndValidate(&req)
if err != nil {
invalidParamRequestResponse(c, err.Error())
return
}
if req.PluginID <= 0 {
invalidParamRequestResponse(c, "pluginID is invalid")
return
}
if req.Name != nil && *req.Name == "" {
invalidParamRequestResponse(c, "plugin name is invalid")
return
}
if req.Desc != nil && *req.Desc == "" {
invalidParamRequestResponse(c, "plugin desc is invalid")
return
}
if req.URL != nil && (*req.URL == "" || len(*req.URL) > 512) {
invalidParamRequestResponse(c, "plugin server url is invalid")
return
}
resp, err := plugin.PluginApplicationSVC.UpdatePluginMeta(ctx, &req)
if err != nil {
internalServerErrorResponse(ctx, c, err)
return
}
c.JSON(consts.StatusOK, resp)
}
解锁插件编辑处理器
// UnlockPluginEdit .
// @router /api/plugin_api/unlock_plugin_edit [POST]
func UnlockPluginEdit(ctx context.Context, c *app.RequestContext) {
var err error
var req plugin_develop.UnlockPluginEditRequest
err = c.BindAndValidate(&req)
if err != nil {
invalidParamRequestResponse(c, err.Error())
return
}
resp, err := plugin.PluginApplicationSVC.UnlockPluginEdit(ctx, &req)
if err != nil {
internalServerErrorResponse(ctx, c, err)
return
}
c.JSON(consts.StatusOK, resp)
}

实现功能

  1. 参数验证:验证插件ID、名称、描述、URL等参数的有效性
  2. 业务调用:调用PluginApplicationSVC应用服务层的相应方法处理插件编辑业务逻辑
  3. 错误处理:统一的错误处理机制,包括参数错误和内部服务错误
  4. 响应返回:返回标准化的操作响应结果

参数校验逻辑

  • 插件ID验证:确保插件ID大于0,防止无效的编辑操作
  • 插件名称验证:确保更新的插件名称不为空
  • 插件描述验证:确保更新的插件描述不为空
  • URL长度验证:确保插件服务URL长度不超过512字符

路由注册实现-api.go文件详细分析

文件位置:backend/api/router/coze/api.go

该文件是Coze Studio后端的核心路由注册文件,由hertz generator自动生成,负责将所有HTTP API接口路由与对应的处理函数进行绑定和注册。对于插件编辑功能,构建了专门的路由结构:

/api/plugin_api/check_and_lock_plugin_edit [POST]
├── rootMw() # 根级中间件
├── _apiMw() # API组中间件
├── _plugin_apiMw() # 插件API组中间件
├── _checkandlockplugineditMw() # 检查并锁定插件编辑接口专用中间件
└── coze.CheckAndLockPluginEdit # 检查并锁定插件编辑处理函数
/api/plugin_api/update_plugin_meta [POST]
├── rootMw() # 根级中间件
├── _apiMw() # API组中间件
├── _plugin_apiMw() # 插件API组中间件
├── _updatepluginmetaMw() # 更新插件元数据接口专用中间件
└── coze.UpdatePluginMeta # 更新插件元数据处理函数
/api/plugin_api/unlock_plugin_edit [POST]
├── rootMw() # 根级中间件
├── _apiMw() # API组中间件
├── _plugin_apiMw() # 插件API组中间件
├── _unlockplugineditMw() # 解锁插件编辑接口专用中间件
└── coze.UnlockPluginEdit # 解锁插件编辑处理函数

核心代码:

{
_plugin_api := _api.Group("/plugin_api", _plugin_apiMw()...)
_plugin_api.POST("/check_and_lock_plugin_edit", append(_checkandlockplugineditMw(), coze.CheckAndLockPluginEdit)...)
_plugin_api.POST("/update_plugin_meta", append(_updatepluginmetaMw(), coze.UpdatePluginMeta)...)
_plugin_api.POST("/unlock_plugin_edit", append(_unlockplugineditMw(), coze.UnlockPluginEdit)...)
// 其他插件相关路由...
}

3. 应用服务层

PluginApplicationService 应用服务层概述

PluginApplicationService是插件编辑功能的核心应用服务层组件,负责协调各个领域服务和数据访问层,处理插件编辑的业务逻辑。该服务实现了PluginDevelopService接口,为API网关层提供具体的业务处理能力。

检查并锁定插件编辑实现

检查并锁定插件编辑是用户开始编辑插件前的关键步骤,确保在同一时间只有一个用户可以编辑特定插件,防止数据冲突。

func (p *PluginApplicationService) CheckAndLockPluginEdit(ctx context.Context, req *pluginAPI.CheckAndLockPluginEditRequest) (resp *pluginAPI.CheckAndLockPluginEditResponse, err error) {
// 初始化响应结构体并设置锁定状态为已锁定
resp = &pluginAPI.CheckAndLockPluginEditResponse{
Code: 0,
Msg:  "",
Data: &plugin_develop_common.CheckAndLockPluginEditData{
Seized: true,
},
}
return resp, nil
}

更新插件元数据实现

更新插件元数据是插件编辑的核心操作,负责根据用户提交的信息更新插件的基本属性。

func (p *PluginApplicationService) UpdatePluginMeta(ctx context.Context, req *pluginAPI.UpdatePluginMetaRequest) (resp *pluginAPI.UpdatePluginMetaResponse, err error) {
// 初始化响应结构体
resp = &pluginAPI.UpdatePluginMetaResponse{}
// 验证用户权限和授权信息
authInfo, err := p.getUpdateAuthInfo(ctx, req)
if err != nil {
// 处理权限错误
return nil, err
}
// 构建更新请求
updateReq := &domain.UpdateDraftPluginRequest{
PluginID:      req.PluginID,
Name:          req.Name,
Desc:          req.Desc,
ServerURL:     req.URL,
Icon:          req.Icon,
AuthType:      req.AuthType,
AuthLocation:  req.Location,
AuthKey:       req.Key,
AuthValue:     req.ServiceToken,
OAuthInfo:     req.OAuthInfo,
CommonParams:  req.CommonParams,
PluginType:    req.PluginType,
SubAuthType:   req.SubAuthType,
FixedExportIP: req.FixedExportIP,
SpaceID:       authInfo.SpaceID,
DeveloperID:   authInfo.UserID,
}
// 调用领域服务更新插件
err = p.domainSVC.UpdateDraftPlugin(ctx, updateReq)
if err != nil {
// 处理更新错误
return nil, err
}
// 发布资源变更事件
p.publishResourceEvent(ctx, req.PluginID, authInfo)
// 设置响应信息
resp.Code = 0
resp.Msg = ""
resp.EditVersion = authInfo.EditVersion
return resp, nil
}

解锁插件编辑实现

解锁插件编辑是用户完成编辑后释放编辑锁的操作,允许其他用户对插件进行编辑。

func (p *PluginApplicationService) UnlockPluginEdit(ctx context.Context, req *pluginAPI.UnlockPluginEditRequest) (resp *pluginAPI.UnlockPluginEditResponse, err error) {
// 初始化响应结构体并设置释放状态为已释放
resp = &pluginAPI.UnlockPluginEditResponse{
Code:     0,
Msg:      "",
Released: true,
}
return resp, nil
}

应用服务层工作流程

插件编辑功能的完整工作流程如下:

  1. 编辑准备阶段

    • 用户点击要编辑的插件行
    • 前端调用CheckAndLockPluginEdit接口
    • 应用服务层验证权限并获取编辑锁
    • 返回插件当前信息给前端进行展示
  2. 编辑进行阶段

    • 用户在前端界面修改插件信息
    • 完成修改后点击保存
    • 前端调用UpdatePluginMeta接口
    • 应用服务层验证权限、检查锁定状态
    • 调用领域服务更新插件数据
    • 返回更新结果
  3. 编辑完成阶段

    • 用户完成所有编辑操作
    • 前端调用UnlockPluginEdit接口
    • 应用服务层释放编辑锁
    • 插件可以被其他用户编辑

核心业务逻辑与协作

应用服务层在插件编辑过程中主要负责以下核心业务逻辑:

  1. 权限验证:确保只有有权限的用户才能编辑特定插件
  2. 并发控制:通过编辑锁定机制防止并发编辑冲突
  3. 数据验证:验证用户提交的数据符合业务规则和约束
  4. 事务管理:确保插件数据更新的原子性和一致性
  5. 版本管理:维护插件的编辑版本号,用于冲突检测
  6. 领域协调:协调调用各个领域服务完成完整的编辑流程

应用服务层作为API网关层和领域服务层之间的桥梁,将复杂的业务流程分解为可管理的步骤,确保插件编辑功能的正确性和可靠性。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/924278.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

网站建设中文百wordpress 网站播放器插件

WX-CSQX12 随着空气污染问题的日益严重&#xff0c;大气环境监测设备成为了我们生活中不可或缺的一部分。而一体化的大气环境监测设备&#xff0c;更是为我们的环境保护工作带来了更多的便利和效益。 一体化大气环境监测设备是一种集成了多种功能于一体的环保设备&#xff0c;…

Linux 中awk命令如何统计每行指定字符出现的次数

001、[root@localhost test]# ls a.txt [root@localhost test]# cat a.txt ## 测试数据 0aa1 0AA2 03 04 05 06 07 08 09 10 1a1 12 [root@localhost test]# awk {a = gsub(&qu…

长安网站制作广告公司网站首页设计页面

引言 今天看题的时候&#xff0c;发现一道题看着挺简单&#xff0c;写了一下&#xff0c;输出正确。感觉解的挺好的&#xff0c;下面记录一下。 题目 给定一个排序数组和一个目标值&#xff0c;在数组中找到目标值&#xff0c;并返回其索引。如果目标值不存在于数组中&#…

实用指南:音频类AI工具扩展

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

什么就是云原生之CNCF

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

常系数齐次微分方程

常系数齐次微分方程 引子 线性相关/线性无关 设 \(y_1,y_2, \dots , y_n\) 为定义在 \(I\) 上的 \(n\) 个函数,如果存在 \(n\) 个不全为零的常数 \(k_1,k_2, \dots k_n\) 使得如下恒等式成立: \[k_1y_1 + k_2y_2 + \…

甘肃建设网站首页公司网站域名是什么意思

通过对网络爬虫的购物平台价格监测系统的业务流程进行梳理可知&#xff0c;网络爬虫的购物平台价格监测系统主要由前台买家模块、后台卖家模块以及管理员模块构成。前台功能包含登录功能、注册功能、系统首页功能、唯品会商品详情浏览、唯品会商品收藏、唯品会商品点赞、唯品会…

公司百度网站怎么做做外贸上阿里巴巴什么网站

网站的数据库怎么上传到服务器 内容精选换一换通常在将数据导入数据库前&#xff0c;即将入库的数据已经在相关主机上了。我们称这种保存着待入库数据的服务器为数据服务器。此时&#xff0c;只需检测以确认数据服务器和GaussDB(for openGauss)集群能够正常通信&#xff0c;并查…

东莞网站建设要注意什么网站备案链接

写在前面说的话 在这里&#xff0c;记录下来&#xff0c;是为了方便以后偶尔所制作所需和你们前来的浏览学习。 学会&#xff0c;玩弄一些视频和音频的软件&#xff0c;只有好处没有害处。同时&#xff0c;也不需很多时间&#xff0c;练练手罢了。也是方便自己所用吧&#xff0…

关于子集的枚举与高维前缀和

今天集训的题我已经写不动了,下周开始会复习 dp, 现在就提前把一些东西补一补,这个说不好会在之后状压里边用到。 枚举子集 如何遍历一个集合的子集 通常我们会采取递归的方式,是 \(O(2^n)\) 的,但是这个样子我们在…

北邻京网站茵建设wordpress网站根目录

1. 什么是IDS&#xff1f; IDS是入侵检测系统&#xff0c;一种对于网络传输进行及时监视&#xff0c;在发现可疑的传输时发出警报或者采取主动反应措施的网络安全设备。IDS是一种积极地主动的防御技术。 2. IDS和防火墙有什么不同&#xff1f; 防火墙是一种隔离并过滤非授权用…

HyperWorks 14.0 轮毂仿真全流程详细教程

HyperWorks 14.0 轮毂仿真全流程详细教程 一、前期准备 1.1 软件启动双击桌面 HyperWorks 14.0 图标 在启动界面选择 HyperMesh User Profile选择:OptiStruct 或 Radioss(根据求解器选择)1.2 设置工作目录菜单栏:F…

概率统计中的数学语言与术语1 - 实践

概率统计中的数学语言与术语1 - 实践pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monac…

网站的安全度wordpress圆角插件汉化

文章目录 1. `<a>` 标签属性详细说明示例2. `<iframe>` 标签属性详细说明示例注意事项总结链接标签在HTML中是实现网页导航的重要工具,允许用户从一个页面跳转到另一个页面或嵌入外部内容。主要的链接标签包括 <a> 标签和<iframe> 标签。本文将深入探…

科技设计公司网站模板青岛做网站建设的公司哪家好

本篇为西安交通大学本科课程《电气材料基础》的笔记。 本篇为这一单元的第四篇笔记&#xff0c;上一篇传送门。 复合电介质材料 是由多种成分共同组成&#xff0c;例如油纸复合绝缘、云母层压板、环氧浸渍玻璃纤维布等。即便是没有添加的材料&#xff0c;材料也会存在杂质和…

你访问的网站正在建设西部数码网站管理系统

1.简介 1.1 2D测量技术 基于单目相机的2D测量技术在许多领域中具有重要的背景和意义。 工业制造&#xff1a;在工业制造过程中&#xff0c;精确测量是确保产品质量和一致性的关键。基于单目相机的2D测量技术可以用于检测和测量零件尺寸、位置、形状等参数&#xff0c;进而实…

【Linux】库的链接与加载 - 详解

【Linux】库的链接与加载 - 详解pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco&qu…

CSP-S模拟26

\(T1:\)median 思路: 根据题目要求,我们不难发现题目要求的就是每个合法的数(即能够成为中位数)作为中位数的情况数该数,最后对所有情况进行求和。显然,我们要枚举每一个数作为中位数,那么在另外四组里一定有两…

网站建设专业搜狗搜索引擎推广

系统提供了 ValueNotifier 组件的实现数据监听&#xff0c;局部刷新&#xff1a; /// 声明可能变化的数据 ValueNotifier<int> valueNotifier ValueNotifier(0);监听数据&#xff1a; ValueListenableBuilder<int>(/// 建立与 _statusNotifier 的绑定关系valueL…