记PasteSpider部署工具的Windows.IIS版本开发过程之草稿-动态表单(2)

news2025/1/8 10:02:57

接1的内容,那么有这么一个需求!

需求分析

需要修改某一个配置的时候
1.从对应的api中读取消息,消息内容为Json格式的
2.基于当前的Json渲染成表单提供给管理端的客户呈现
3.管理端的用户可以基于这个表单的内容进行修改,然后提交
4.服务端基于用户提交的信息,提交给IIS Administration以便更新到IIS的网站中!
所以我们需要一个东西,可以动态编辑Json内容的东西!!!
关键点在于这个编辑非开发也能玩,当然我们也可以提供2个版本,一个表单版本,一个字符串版本

方案一

由上面的步骤可知,1获取到的数据是变动的,或者你可以说可以把几种的格式都创建成表然后入库
只入库表的结构,获取到数据后和表的结构相互结合,然后使用PasteForm提供给用户进行更新!
不要在意CRUD的规范一个表一个API,在这个需求中完全可以使用动态Route进行单API处理!

    {
        "title":"标题",
        "desc":"描述信息",
        "value":97.5
    }

以上的方案你会可见的发现,将会有非常多的工作量,可能增加的表不下100个!!!

方案二

结合现有的PasteForm框架知识,是否也可以搞一个动态的表单,理想的状态有
1.无论来的Json数据是咋样的,都给他在表单中显示
2.可以针对性质的一些字段进行配置,也就是结合方案一的内容做一个表结构的信息
3.区别于方案一的是,方案一比如有100个结构表,你得先创建100个表及对应得CRUD,而这里得动态是可以不出创建的
比如有

    {
        "title":"标题",
        "desc":"描述信息",
        "value":97.5
    }

其实在文章1中还有一个隐藏的知识点就是Json不是单层级的,比如

{
    "name": "iis_temp",
    "id": "UYZcrUKt9eaMiolk-rH_GA",
    "status": "started",
    "auto_start": "true",
    "pipeline_mode": "integrated",
    "managed_runtime_version": "",
    "enable_32bit_win64": "false",
    "queue_length": "1000",
    "start_mode": "OnDemand",
    "cpu": {
        "limit": "0",
        "limit_interval": "5",
        "action": "NoAction",
        "processor_affinity_enabled": "false",
        "processor_affinity_mask32": "0xFFFFFFFF",
        "processor_affinity_mask64": "0xFFFFFFFF"
    },
    "process_model": {
        "idle_timeout": "20",
        "max_processes": "1",
        "pinging_enabled": "true",
        "ping_interval": "30",
        "ping_response_time": "90",
        "shutdown_time_limit": "90",
        "startup_time_limit": "90",
        "idle_timeout_action": "Terminate"
    },
    "identity": {
        "identity_type": "ApplicationPoolIdentity",
        "username": "",
        "load_user_profile": "true"
    },
    "recycling": {
        "disable_overlapped_recycle": "false",
        "disable_recycle_on_config_change": "false",
        "log_events": {
            "time": "true",
            "requests": "true",
            "schedule": "true",
            "memory": "true",
            "isapi_unhealthy": "true",
            "on_demand": "true",
            "config_change": "true",
            "private_memory": "true"
        },
        "periodic_restart": {
            "time_interval": "1740",
            "private_memory": "0",
            "request_limit": "0",
            "virtual_memory": "0",
            "schedule": []
        }
    },
    "rapid_fail_protection": {
        "enabled": "true",
        "load_balancer_capabilities": "HttpLevel",
        "interval": "5",
        "max_crashes": "5",
        "auto_shutdown_exe": "",
        "auto_shutdown_params": ""
    },
    "process_orphaning": {
        "enabled": "false",
        "orphan_action_exe": "",
        "orphan_action_params": ""
    }
}

上面只是二级的,还有一些是Array格式的,更加负责了,还可能有多级,不止二级!

结合上面的消息,所以选择的是方案二

实现单元

结合上面的内容,我的习惯是搞一个测试项目,然后做单元测试,在一个现有的项目中要添加比较大的模块的时候,
我的步骤就是先梳理大脉络,大需求,大方向
然后拆分成小的功能点
整理下有难点的,不太确定的功能点
搞一个案例项目,实现后进行单元测试下

结合以上的内容,由于也用到了贴代码PasteForm框架的内容,所以我打算在PasteTemplate案例项目上实现这个功能!

动态分析

按照方案二的说明,比如有以下内容

        {
            "va":"aabbcc",
            "score":98,
            "avg":67.5
        }

按照默认的显示应该是这样的
在这里插入图片描述
如果是一些简单的单词还好,有一些单词就不是这么好识别了,比如如下的

{
        "title":"这个是标题",
        "desc":"描述信息",
        "value":97.5
    }

我们希望他的显示是如下的,比如title这个字段
在这里插入图片描述
结合以上的内容,所以我们知道了这个动态的意思,就是如果我配置中有这个比如title字段的信息,则在表单中对应的显示
如果没有则使用JSON的字段直接显示(一般为英文字母)

以上是单元的内容的需求分析,那么还有一个需求,就是多层级的JSON,比如

{
    "name":"abc",
    "age":19,
    "actions":[
        {
            "va":"aabbcc",
            "score":98,
            "avg":67.5
        }
    ],
    "info":{
        "title":"标题",
        "desc":"描述信息",
        "value":97.5
    }
}

这个时候的显示,我希望他能分组,否则会有一大堆,
有一个关键点在于名称重复,比如name和info.name最终显示都是name,如果全显示可能非常长!
对于用户来说很容易搞混,实现后大概是这样的
在这里插入图片描述
注意看上图,按照JSON的内容,做了分组,上面的info或者actions是可以收缩的,如下
在这里插入图片描述
结合以上的需求,我设定添加2个表,一个动态表,一个动态字段!

动态表

直接上代码,创建CodeFirst

using System.ComponentModel.DataAnnotations;
using Microsoft.EntityFrameworkCore;
using Volo.Abp.Domain.Entities;

namespace PasteTemplate.dynamicmodels
{
    /// <summary>
    /// 动态表
    /// </summary>
    [Index(nameof(Code), IsUnique = true)]
    public class DynamicTable : Entity<int>
    {
        /// <summary>
        /// 代码 示例:userInfo
        /// </summary>
        [MaxLength(32)]
        public string Code { get; set; }

        /// <summary>
        /// 名称 示例:用户信息
        /// </summary>
        [MaxLength(16)]
        public string Name { get; set; }

        /// <summary>
        /// 说明 示例:修改用户基本信息
        /// </summary>
        [MaxLength(128)]
        public string Desc { get; set; }

        /// <summary>
        /// 状态
        /// </summary>
        public bool IsEnable { get; set; } = true;

        /// <summary>
        /// 空字符 空字符串移除对象
        /// </summary>
        public bool RemoveEmptyStr { get; set; }

        /// <summary>
        /// 数值0 数值为0移除对象
        /// </summary>
        public bool RemoveZeroNumber { get; set; }

        /// <summary>
        /// 特性
        /// </summary>
        public string AttributeJson { get; set; }

        / <summary>
        / 数据提交地址
        / </summary>
        //[MaxLength(256)]
        //public string PostUrl { get; set; }
    }
}

注意上面的特性是使用贴代码PasteForm的特性的JSON内容
其他的字段信息就没啥可说的了!

动态字段

一个动态表可以包含很多个字段,每个字段有不一样的信息,比如标题,说明,是否必填,长度,特性规则等!

using System.ComponentModel.DataAnnotations;
using Volo.Abp.Domain.Entities;

namespace PasteTemplate.dynamicmodels
{
    /// <summary>
    /// 动态字段信息
    /// </summary>
    public class DynamicField : Entity<int>
    {

        /// <summary>
        /// 动态表
        /// </summary>
        public int TableId { get; set; }

        /// <summary>
        /// 字段名称 CreateDate
        /// </summary>
        [MaxLength(64)]
        public string Name { get; set; } = "";

        /// <summary>
        /// 字段类型 System.DateTime
        /// </summary>
        [MaxLength(64)]
        public string DataType { get; set; } = "";

        /// <summary>
        /// 默认值
        /// </summary>
        public string DefaultValue { get; set; }

        /// <summary>
        /// 字段中文 创建日期
        /// </summary>
        [MaxLength(16)]
        public string Title { get; set; } = "";

        /// <summary>
        /// 描述
        /// </summary>
        [MaxLength(128)]
        public string Placeholder { get; set; } = "";

        /// <summary>
        /// 限定 最大长度
        /// </summary>
        public int Maxlength { get; set; } = 0;


        /// <summary>
        /// 必填
        /// </summary>
        public bool Required { get; set; } = false;

        / <summary>
        / 排序
        / </summary>
        //public int Sort { get; set; } = 0;

        /// <summary>
        /// 特性串
        /// </summary>
        public string AttributesJson { get; set; }

        /// <summary>
        /// 状态
        /// </summary>
        public bool IsEnable { get; set; } = true;


    }
}

以上两个cs创建后,我们使用贴代码提供的代码生成器PasteBuilder执行下
在这里插入图片描述
然后就会创建对应的Dto AppService等文件,由于我新弄了一个模块,所以要把没引入的namespace处理下,重新生成!
然后稍微改造下对应的Dto,比如DynamicTable
在这里插入图片描述
主要是上面的,给他搞一个菜单
然后是字段信息中的表ID,给搞一个从url的参数中获取
在这里插入图片描述
以上信息处理后,记得add-migration一下,然后启动项目,到管理页面后,新建一个权限,如下
在这里插入图片描述
然后刷新下页面,可以打开对应的菜单
在这里插入图片描述
一开始打开,表格内时空白的,没有数据,你可以去创建下!
到此对于动态表的添加就算完成,或者说是对JSON的字段的附加说明的内容!

逻辑代码实现

结合上的内容,那么流程应该是这样的,用户打开一个页面,然后这个页面载入要修改的JSON的数据,以表单的形式呈现,如果有配置字段的附加信息,则把附加信息也展示(就是附加信息结合JSON的值显示)
1.你没办法post一大串数据到一个页面吧!
2.JSON本身数据是动态的,所以数据提供的时候,得给他一个定义,这就是table_code的由来

实现API

按照上面的分析,我们先实现几个接口,一个是读取JSON内容的,一个是测试的,如下

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text.Json;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using PasteFormHelper;
using PasteTemplate.Application.Contracts;
using PasteTemplate.Handler;

namespace PasteTemplate.dynamicmodels
{
    /// <summary>
    ///
    ///</summary>
    //[TypeFilter(typeof(RoleAttribute), Arguments = new object[] { "data", "view" })]
    public class DynamicHelperAppService : PasteTemplateAppService
    {

        private IAppCache _appCache => LazyServiceProvider.LazyGetRequiredService<IAppCache>();

        /// <summary>
        ///
        ///</summary>
        public DynamicHelperAppService() : base()
        {

        }

        /// <summary>
        /// 基于datakey读取对应的模型数据和对象数据
        /// </summary>
        /// <returns></returns>
        [HttpGet]
        public async Task<DynamicModel> Read(string datakey)
        {
            if (String.IsNullOrEmpty(datakey))
            {
                throw new PasteCodeException("传递有效的参数datakey");
            }

            var _modelStr = await _appCache.GetAsync(datakey);
            if (String.IsNullOrEmpty(_modelStr))
            {
                throw new PasteCodeException("缓存数据有误,无法继续执行!");
            }

            var _model = JsonSerializer.Deserialize<DynamicModel>(_modelStr);
            //从数据库读取对应的信息
            if (!String.IsNullOrEmpty(_model.Code) || _model.TableId != 0)
            {
                var _table = await _dbContext.DynamicTable
                    .WhereIf(_model.TableId != 0, x => x.Id == _model.TableId)
                    .WhereIf(!String.IsNullOrEmpty(_model.Code), x => x.Code == _model.Code)
                    .AsNoTracking()
                    .FirstOrDefaultAsync();

                if (_table != null && _table != default)
                {
                    _model.Table = ObjectMapper.Map<DynamicTable, DynamicTableModel>(_table);
                    //二次加工

                    _model.Title = _table.Name;

                    if (!String.IsNullOrEmpty(_table.AttributeJson))
                    {
                        _model.Attributes = JsonSerializer.Deserialize<List<VoloModelAttribute>>(_table.AttributeJson);
                    }

                    var _fields = await _dbContext.DynamicField
                        .Where(x => x.TableId == _table.Id && x.IsEnable)
                        .OrderBy(x => x.Id)
                        .AsNoTracking()
                        .ToListAsync();

                    if (_fields != null && _fields.Count > 0)
                    {
                        _model.Properties = ObjectMapper.Map<List<DynamicField>, List<DynamicFieldModel>>(_fields);
                        //二次加工
                        foreach (var _field in _model.Properties)
                        {
                            if (!String.IsNullOrEmpty(_field.DefaultValue))
                            {
                                switch (_field.DataType)
                                {
                                    case "Int32":
                                        {
                                            if (int.TryParse(_field.DefaultValue, out var _val))
                                            {
                                                _field.Value = _val;
                                            }
                                        }
                                        break;
                                    case "Int64":
                                        {
                                            if (long.TryParse(_field.DefaultValue, out var _val))
                                            {
                                                _field.Value = _val;
                                            }
                                        }
                                        break;
                                    case "Double":
                                        {
                                            if (double.TryParse(_field.DefaultValue, out var _val))
                                            {
                                                _field.Value = _val;
                                            }
                                        }
                                        break;
                                    case "DateTime":
                                        {
                                            if (_field.DefaultValue == "now")
                                            {
                                                _field.Value = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
                                            }
                                            else if (_field.DefaultValue == "today")
                                            {
                                                _field.Value = DateTime.Now.ToString("yyyy-MM-dd 00:00:00");
                                            }
                                            else if (_field.DefaultValue == "month")
                                            {
                                                _field.Value = DateTime.Now.ToString("yyyy-MM-01 00:00:00");
                                            }
                                            else
                                            {
                                                if (DateTime.TryParse(_field.DefaultValue, out var _val))
                                                {
                                                    _field.Value = _val;
                                                }
                                            }
                                        }
                                        break;
                                    default:
                                        {
                                            _field.Value = _field.DefaultValue;
                                        }
                                        break;
                                }
                            }
                            if (!String.IsNullOrEmpty(_field.AttributesJson))
                            {
                                _field.Attributes = JsonSerializer.Deserialize<List<VoloModelAttribute>>(_field.AttributesJson);
                            }
                        }
                    }
                }
            }
            return _model;
        }

        /// <summary>
        /// 提交修改后的JsonString
        /// </summary>
        /// <returns></returns>
        [HttpPost]
        public async Task<string> Update(string datakey)
        {
            if (_httpContext.Request.Body != null)
            {
                using var reader = new StreamReader(_httpContext.Request.Body);
                var bodystr = await reader.ReadToEndAsync();
                reader.Close();
                reader.Dispose();
                return bodystr;
            }
            else
            {
                throw new PasteCodeException("提交数据有误,无法输出");
            }
        }


        /// <summary>
        /// 上传一个json对象,获取datakey
        /// </summary>
        /// <returns></returns>
        [HttpPost]
        public async Task<string> Test(string code = "", int tableid = 0)
        {
            var _key = Guid.NewGuid().ToString().Replace("-", "");

            var _model = new DynamicModel { };

            _model.DataKey = _key;
            _model.Code = code;
            _model.TableId = tableid;

            var _httpContext = base._httpContext;

            if (_httpContext.Request.Body != null)
            {
                using var reader = new StreamReader(_httpContext.Request.Body);
                var bodystr = await reader.ReadToEndAsync();
                reader.Close();
                reader.Dispose();
                if (!String.IsNullOrEmpty(bodystr))
                {
                    var _jobj = System.Text.Json.JsonSerializer.Deserialize<JsonElement>(bodystr);
                    _model.Data = _jobj;
                }
            }
            var _modelStr = JsonSerializer.Serialize(_model);
            await _appCache.SetAsync(_key, _modelStr, 3600 * 4);
            return _key;
        }

    }
}

上面的数据中的DynamicModel内容如下

    /// <summary>
    /// 
    /// </summary>
    public class DynamicModel
    {
        /// <summary>
        /// 数据key 必填
        /// </summary>
        public string DataKey { get; set; }

        /// <summary>
        /// Table.Code 二选一,如果有模型数据的话
        /// </summary>
        public string Code { get; set; }

        /// <summary>
        /// Table.Id 二选一,如果有模型数据的话
        /// </summary>
        public int TableId { get; set; }

        /// <summary>
        /// 名称
        /// </summary>
        public string Title { get; set; }

        /// <summary>
        /// 模型自己的属性规则列表
        /// </summary>
        public List<VoloModelAttribute> Attributes { get; set; }

        /// <summary>
        /// 表信息 可能为null
        /// </summary>
        public DynamicTableModel Table { get; set; }

        /// <summary>
        /// 字段信息 字段格式信息,可能为null
        /// </summary>
        public List<DynamicFieldModel> Properties { get; set; }

        /// <summary>
        /// System.Text.Json 必填表示Json的数据
        /// </summary>
        public JsonElement Data { get; set; }

    }

主要的意思就是,提交JSON信息的生产者需要知道当前的JSON是哪个的信息(table_id/table_code),然后是数据本身(Data)
这里要注意,由于Data是动态的,这里涉及到JSON的序列化和反序列化,这个和AppService的默认处理方式有关!
就是在AppService中,如果你写的返回值为Object,返回到前端往往是一个JSONString,其实这里是有一个中间件在转格式输出的,目前有System.Text.Json和Newtonsoft的方式,2边需要一致,否则会造成数据丢失的可能!
比如你提交的数据为

{
    "info":{
        "title":"标题",
        "desc":"描述信息",
        "value":97.5
    }
}

前端接收到的为

{
    "info":{
        "title":[],
        "desc":[],
        "value":[]
    }
}

惊不惊喜!!!

到此,完成了大概动态表单的API部分,实现的内容有
1.搞一个动态表,动态字段,用于承载配置,针对JSON的某一些字段做补充,或者说是所有字段
2.实现JSON数据的暂存,生产者获得JSON数据后,加工下存储在一个key中,给前端,前端基于这个key进行对应的数据的读取!
这个数据是经过加工的,比如说添加了table_code,对应的1中的模型数据,也可能没有配置,所以这里有一个很好的解耦动作!

下一章将介绍动态表单的UI部分的内容,和这章中的动态字段中的Name的关键说法!

下期见… … .

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

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

相关文章

pycharm-pyspark 环境安装

1、环境准备&#xff1a;java、scala、pyspark、python-anaconda、pycharm vi ~/.bash_profile export SCALA_HOME/Users/xunyongsun/Documents/scala-2.13.0 export PATH P A T H : PATH: PATH:SCALA_HOME/bin export SPARK_HOME/Users/xunyongsun/Documents/spark-3.5.4-bin…

Clisoft SOS设置Workarea

Clisoft SOS设置Workarea 本人也是刚刚接触这个软件&#xff0c;可能有些方面不够完善&#xff0c;欢迎大佬指点。 这里就不演示创建创建Server和Project&#xff0c;可以参考Clisoft SOS设置Server和Project 创建Workarea 创建好目录并设置好权限 # 创建组 [bhlumaster ~]$…

数据结构:LinkedList与链表—无头双向链表(二)

目录 一、什么是LinkedList&#xff1f; 二、LinkedList的模拟实现 1、display()方法 2、addFirst(int data)方法 3、addLast(int data)方法 4、addIndex(int index,int data)方法 5、contains(int key)方法 6、remove(int key)方法 7、removeAllKey(int key)方法 8、…

基于SpringBoot实现的保障性住房管理系统

&#x1f942;(❁◡❁)您的点赞&#x1f44d;➕评论&#x1f4dd;➕收藏⭐是作者创作的最大动力&#x1f91e; &#x1f496;&#x1f4d5;&#x1f389;&#x1f525; 支持我&#xff1a;点赞&#x1f44d;收藏⭐️留言&#x1f4dd;欢迎留言讨论 &#x1f525;&#x1f525;&…

【Linux】硬链接和软连接(符号连接)

目录 硬链接 软连接 硬链接和软连接的区别 硬链接 ln根据linux系统分配给文件inode(ls -li)进行建立&#xff0c;没办法跨越文件系统 格式&#xff1a;ln 被链接的文件(源文件) 生成的链接文件(目标文件) 1) 硬链接的属性 - 相当于生成一个副本 起别名 2) 修改内容都变化…

多目标优化算法——基于聚类的不规则Pareto前沿多目标优化自适应进化算法(CA-MOEA)

基于聚类的不规则Pareto前沿多目标优化自适应进化算法&#xff08;CA-MOEA&#xff09; 一、算法简介 简介&#xff1a; 现有的多目标进化算法&#xff08;moea&#xff09;在具有规则Pareto前沿且Pareto最优解在目标空间上连续分布的多目标优化问题&#xff08;MOPs&#xff…

基于SpringBoot的乐器商城购物推荐系统

作者&#xff1a;计算机学姐 开发技术&#xff1a;SpringBoot、SSM、Vue、MySQL、JSP、ElementUI、Python、小程序等&#xff0c;“文末源码”。 专栏推荐&#xff1a;前后端分离项目源码、SpringBoot项目源码、Vue项目源码、SSM项目源码、微信小程序源码 精品专栏&#xff1a;…

【vba源码】自动获取汇率

Hi&#xff0c;大家好&#xff01; 没有想到今天居然是腊八&#xff0c;过了腊八就是年&#xff0c;离过年越来越近了&#xff0c;那在这里给大家就拜个年&#xff0c;希望大家在新的一年都有好事发生。 最近在弄点小项目&#xff0c;在项目遇到了一个汇率计算的问题&#xff…

JavaEE初阶——计算机工作原理

一、什么是JavaEE JavaEE&#xff08;Java Platform&#xff0c;Enterprise Edition&#xff09;是sun公司&#xff08;2009年4月20日甲骨文将其收购&#xff09;推出的企业级应用程序版本。这个版本以前称为 J2EE。能够帮助我们开发和部署可移植、健壮、可伸缩且安全的服务器…

【Unity3D】AB包加密(AssetBundle加密)

加密前&#xff1a; 加密后&#xff0c;直接无法加载ab&#xff0c;所以无法正常看到ab内容。 using UnityEngine; using UnityEditor; using System.IO; public static class AssetBundleDemoTest {[MenuItem("Tools/打包!")]public static void Build(){//注意:St…

数据库语句学习

WHERE AND: 请编写 SQL 语句&#xff0c;从 courses 表中&#xff0c;选取课程名为 Web 或者 Big Data 的课程信息&#xff0c;如果这两门课程存在&#xff0c;请将这两门课程的信息全部返回。 SELECT * FROM courses where name in (Web,Big Data) -- 等同于 -- WHERE name …

“AI智慧语言训练系统:让语言学习变得更简单有趣

大家好&#xff0c;我是你们的老朋友&#xff0c;一个热衷于探讨科技与教育结合的产品经理。今天&#xff0c;我想和大家聊聊一个让语言学习变得不再头疼的话题——AI智慧语言训练系统。这个系统可是我们语言学习者的福音&#xff0c;让我们一起来揭开它的神秘面纱吧&#xff0…

Postman接口测试05|实战项目笔记

目录 一、项目接口概况 二、单接口测试-登录接口&#xff1a;POST 1、正例 2、反例 ①姓名未注册 ②密码错误 ③姓名为空 ④多参 ⑤少参 ⑥无参 三、批量运行测试用例 四、生成测试报告 1、Postman界面生成 2、Newman命令行生成 五、token鉴权&#xff08;“…

使用Locust对MongoDB进行负载测试

1.安装环境 pip install pymongo locust 2.设置测试环境 开启MongoDB服务 打开Navicat&#xff0c;新建MongoDB连接 新建test数据库和sample集合 3.编写脚本 load_mongo.py # codingutf-8 from locust import User, task, between, events from pymongo import MongoClie…

【微服务】3、配置管理

微服务配置管理 已掌握的微服务组件及配置管理问题引出 已掌握注册中心、Openfan、远程调用、负载均衡、网关等组件&#xff0c;具备微服务开发能力&#xff0c;但仍存在其他问题待解决。微服务和网关存在大量配置文件&#xff0c;其中包含很多重复配置&#xff0c;如数据库、日…

【Notepad++】Notepad++如何删除包含某个字符串所在的行

Notepad如何删除包含某个字符串所在的行 一&#xff0c;简介二&#xff0c;操作方法三&#xff0c;总结 一&#xff0c;简介 在使用beyoundcompare软件进行对比的时候&#xff0c;常常会出现一些无关紧要的地方&#xff0c;且所在行的内容是变化的&#xff0c;不方便进行比较&…

计算机网络——期末复习(7)期末试卷样例3

一、辨析题&#xff08;共4小题&#xff0c;每小题5分&#xff0c;共20分&#xff09; 1.差错检测是保障网络正常通信的一项重要措施&#xff0c;有多种差错检测算法&#xff08;技术&#xff09;&#xff0c; &#xff08;1&#xff09;以太网和IP协议各自采用的差错校验算法…

STM32-笔记34-4G遥控灯

4G接线 一、项目需求 服务器通过4G模块远程遥控开关灯。 二、项目实现 复制项目文件夹38-wifi控制风扇项目 重命名为39-4G遥控点灯 打开项目文件 加载文件 main.c #include "sys.h" #include "delay.h" #include "led.h" #include "ua…

游戏引擎学习第77天

仓库: https://gitee.com/mrxiao_com/2d_game 回顾昨天的 bug 今天我们继续开发进度&#xff0c;进行调试昨天代码的问题&#xff0c;主要是关于如何跟踪玩家和敌人在世界中的高度位置。虽然我们做的是一款 2D 游戏&#xff0c;但我们希望能够处理多层的房间&#xff0c;玩家…

STM32完全学习——使用定时器1精确延时

一、定时器的相关配置 首先一定要是递减定时器&#xff0c;递增的不太行&#xff0c;控制的不够准确&#xff0c;其次在大于10微秒的延时是非常准确的&#xff0c;小于的话&#xff0c;就没有那没准&#xff0c;但是凑合能用。误差都在一个微秒以内。使用高级定时器也就是时钟…