• [技术干货] Selenium WebDriver中的XPath:完整教程
    作者:姚旺时间:2021.6.1在Selenium 自动化中,如果id、name、classname等常规定位器没有找到元素,那么就需要使用XPath在web页面上查找元素。在本教程中,我们将学习用xpath表达式查找复杂或动态元素。在本教程中,您将学习:1.0 XPath是什么?2.0 Xpath类型    2.1 Absolute XPath    2.2 Relative Xpath3.0 在Selenium中使用XPath处理复杂和动态元素    3.1 XPath基础    3.2 Contains()    3.3 OR & AND    3.4 Starts-with function    3.5 Text()    3.6 XPath轴方法       3.6.1 Following       3.6.2 Ancestor       3.6.3 Child       3.6.4 Preceding       3.6.5 Following-sibling       3.6.6 Parent       3.6.7 Descendant1.0 XPath是什么?XPath被定义为XML路径。它是一种使用XML路径表达式查找web页面上的任意元素的语法。XPath用于在HTML DOM网页结构中查找任意元素的位置,下面的截图展示了XPath的基本格式。XPath的语法:XPath包含位于web页面的元素的路径。创建XPath的标准语法是:Xpath=//tagname[@attribute='value']•  // :选择当前节点•  Tagname:节点名/标签名•  @:选择属性•  Attribute:节点下的属性名•  Value:属性值 为了准确地找到网页上的元素,有不同类型的定位器:Xpath定位器在网页上找到不同的元素ID按元素的ID查找元素Classname按元素的类名查找元素Name按元素名称查找元素Link text按链接的文本查找元素XPath查找动态元素CSS pathCSS path也可以定位没有名称、类或ID的元素。2.0 Xpath类型XPath定位分为两种类型:  1)    Absolute XPath(绝对定位)  2)    Relative XPath(相对定位)2.1 Absolute XPath绝对定位是找到元素最直接方法,但是绝对定位的缺点是,如果该元素在HTML DOM结构中的路径做了任何更改,那么XPath定位就会失败。绝对定位的关键特征是它以单正斜杠(/)开始,这意味着您必须从根节点开始选择元素(在html中以/html开始)。下面截图是元素的绝对定位表达式的示例。以华为商城登录页面为例(https://id1.cloud.huawei.com/CAS/portal/loginAuth.html)Absolute xpath: /html/body/div[1]/div[2]/div/div/div[1]/div[3]/span[3]/div[1]/span/div[2]/div[2]/div/input★ 定位说明及建议:在Chrome中,按下F12启动控制台,点击控制台左侧的小箭头,选择需要定位的元素,选中元素后,控制台会自动滚动到该元素标签在当前html中的位置,且该标签会处于高亮状态,右键该标签-选择”Copy”—“Copy full Xpath”即可获取元素的绝对定位。此时在控制台中按下Ctrl+F,将我们获取到的绝对定位粘贴到输入栏,在这里我们可以验证Xpath定位是否准确,以及定位到的元素的个数。通常情况下,绝对定位的xpath路径较长,如果该元素所处的html结构发生变化,那么XPath定位就会失败。另外,程序在解析绝对定位是需要层层筛查,检索会比较慢。所以,一般情况下,不建议使用绝对定位。 2.2 Relative Xpath相对定位的路径从HTML DOM结构的中间开始。它以双斜杠(//)开始,这意味着它可以在网页的任何地方搜索该元素。您可以从HTML DOM结构的中间开始,不需要编写长段的xpath。下面截图是相同元素的相对XPath表达式的示例。这是通过相对定位查找元素时使用的常见格式。Relative xpath: //input[@class="hwid-input hwid-cover-input userAccount"]★ 定位说明及建议:相对定位需要手动编写xpath(属性和属性值可以双击控制台中元素的属性进行复制)。相对定位可以从需要定位的元素开始编写xpath,通常你可以通过标签名+属性+文本这三个维度去定位元素,如果该元素不止一个,可以继续向其父元素、祖先元素追加定位(也可以通过兄弟元素定位),或增加属性、文本。如案例中,如果上例xpath找到的元素不止一个,可以写成//div[@class="hwid-input-wrap"]//input[@class="hwid-input hwid-cover-input userAccount"]、//input[@class="hwid-input hwid-cover-input userAccount"][@placeholder="手机号/邮件地址/华为号"]或//input[@class="hwid-input hwid-cover-input userAccount" and @placeholder="手机号/邮件地址/华为号"] 3.0 在Selenium中使用XPath处理复杂和动态元素3.1 XPath基础XPath表达式根据ID、Name、Classname等属性从XML文档中选择节点或节点列表,如下所示。Xpath=//input[@name='uid']下面是访问页面的链接https://id1.cloud.huawei.com/CAS/portal/loginAuth.html(华为商城登录页面)一些基础的xpath表达式:Xpath=//input[@type="password"]Xpath= //*[@placeholder="密码"]Xpath= //i[@class="hwid-password-eye hwid-password-eyeoff-disable"]XPath= //img[@alt="Scan me!"] 3.2 Contains()Contains()是XPath表达式中常用的方法。它用于任何属性的值动态变化,可以通过包含特性找到带有部分文本的元素,如下面的示例所示。在本例中,我们尝试通过使用属性的部分文本值来定位元素。在下面的XPath表达式中,使用部分值“pass”代替“password”,可以看到元素被成功地找到了。“Type”的完整值是“password”,但只使用部分值“pass”。Xpath=//input[contains(@type,'pass')]'class'的完整值是'hwid-input hwid-input-pwd',但只使用部分值'hwid-input '。Xpath=//input[contains(@class,'hwid-input')]在上面的表达式中,我们使用'class'作为属性,'hwid-input'作为部分值,如下面的屏幕截图所示。这将找到三个元素,因为它们的“class”属性都含有“hwid-input”。类似地,在下面的表达式中,我们将“文本”作为属性,而“验证码”作为部分值,如下面的截图所示。Xpath=//span[contains(text(),'验证码')]3.3 OR & AND在OR表达式中,使用了两个条件,无论是第一个条件还是第二个条件都应该为真。它也适用于任何条件为真或两者皆为真。意味着任何一个条件都必须为真才能找到元素。在下面的XPath表达式中,它定位了单个条件或两个条件都为真的元素。Xpath=//*[@type="password" or contains(@class,"hwid-cover-input")]突出显示两个元素“type” 属性为“password”和“class”属性含有“hwid-cover-input”。在AND表达式中,使用了两个条件,两个条件都必须为真才能找到元素。如果任何一个条件为假,则无法找到元素。Xpath=//*[@type="text" and contains(@class,"hwid-cover-input")]在下面的表达式中,突出显示“input”元素,因为它同时具有“type”和“class”属性。3.4  Starts-with functionStart-with方法常用于查找在网页上动态变化的元素。在这个表达式中,通过匹配元素属性值的起始文本来查找属性动态变化的元素。您还可以找到其属性值为静态(而不是动态)的元素。假设特定元素的ID动态变化如下:Id=" message12"Id=" message345"Id=" message8769"等等;但是起始的字符是一样的。在本例中,我们使用start-with表达式。Xpath=//*[starts-with(@Id,'message')]XPath查找那些“ID”属性以“message”开头的元素。3.5 Text()在这个表达式中,通过text()方法,我们可以找到与精确文本匹配的元素,如下所示。在本例中,我们找到文本为“登录”的元素。Xpath= //span[text()='登录']3.6 XPath轴方法什么是XPath轴?轴表示与上下文节点的关系,XPath轴从当前上下文节点搜索XML文档中的不同节点。如果普通XPath方法没有ID、类名、名称等,则无法找到这些动态元素,而XPath轴是用于查找动态元素的方法。在Selenium Webdriver中常用的轴方法有:child、parent、ancestor、sibling、prior、self等。这些XPath轴方法用于查找复杂或动态的元素。下面我们将看到其中的一些方法。为了演示这些XPath轴方法,我们将使用华为商城登录页面作为演示站点。3.6.1 Followingfollowing选取文档中当前节点的结束标签之后的所有节点,包含同一文档中按文档顺序位于上下文节点之前的所有节点,除了祖先节点。如下面的屏幕所示。Xpath=//*[@type='text']//following::input从结果上我们可以知道“账号输入框”元素结束之后,页面中还有两个input标签。如果想要选择任何特定元素,可以使用下面的XPath方法:Xpath=//*[@class="hwid-input hwid-cover-input userAccount"]//following::input[1]您可以根据需求更改XPath,添加[1]、[2]、[@attribute=’value’]……等等。在输入为“1”的情况下,就会定位到“密码输入框”元素的特定节点。3.6.2 Ancestorancestor轴选择当前节点的所有祖先元素(祖父、父等),如下图所示。在下面的表达式中,我们正在查找当前节点(“input(密码输入框)”节点)的祖先元素。Xpath=//input[@type="password"]//ancestor::div 有11个“div”节点通过使用“祖先”轴匹配。如果您想关注任何特定的元素,那么您可以使用下面的XPath,其中根据您的需求更改数字1,2:Xpath=//*[text()='Enterprise Testing']//ancestor::div[1]您可以根据需求更改XPath,添加[1]、[2]、[@attribute=’value’]……等等 3.6.3 Child选择当前节点的所有子元素,如下面的截图所示。Xpath=//div[@class="hwid-pwdlogin-root"]//child::input使用“child”轴匹配3个“input”节点。如果您想关注任何特定的元素,那么可以使用下面的xpath:Xpath=//*[@id='java_technologies']/child::li[1]您可以根据需求更改xpath,添加[1]、[2] 、[@attribute=’value’]……等等 3.6.4  Preceding选择当前节点之前的所有节点,如下面的截图所示。在下面的表达式中,它标识了“短信验证码登录”标签之前的所有的input元素。//span[text()='短信验证码登录']//preceding::input使用“preceding”轴匹配2个“input”节点。如果您想定位任何特定的元素,那么可以使用下面的XPath:Xpath=//span[text()='短信验证码登录']//preceding::input[last()]----选中“密码输入框”。您可以根据需求更改xpath,添加[1]、[2] 、[@attribute=’value’]……等等。 3.6.5 Following-sibling选择该节点以下的上下文节点的兄弟节点。兄弟节点与当前节点处于同一级别,如下面的屏幕所示。它将在当前节点之后查找元素。xpath=//a[@id="foot_EULA"]//following-sibling::a使用“following-sibling”轴匹配2个“a”节点。如果您想定位任何特定的元素,那么可以使用下面的XPath:Xpath=//a[@id="foot_EULA"]//following-sibling::a [1]----选中“关于华为账号与云控件隐私声明”。您可以根据需求更改xpath,添加[1]、//tagName、[@attribute=’value’]……等等。 3.6.6 Parent选择当前节点的父节点,如下面的屏幕所示。Xpath=//a[@id="foot_EULA"]//parent::p★ 定位说明及建议:Parent轴方法通常用于根据子元素来定位父元素,获取父元素相关属性或文本。另外,上面的xpath定位Xpath=//a[@id="foot_EULA"]//parent::p等价于Xpath= (//a[@id="foot_EULA"])/..您可以根据需求更改XPath,添加//tagName……等等。 3.6.7  Descendant选择当前节点的后代节点,如下面的屏幕所示。在下面的表达式中,它标识了当前元素的所有后代元素,这意味着在节点的下面(子节点,孙子节点,等等)。Xpath=//*[@id='rt-feature']//descendant::a使用“descendant”轴匹配4个“a”节点。如果您想定位任何特定的元素,那么可以使用下面的XPath:Xpath=//div[@class="warrant-area"]//descendant::a[2]您可以根据需求更改XPath,添加[1]、//tagName、[@attribute=’value’]……等等。 在实际定位过程中,经常会碰到的问题及技巧:1.有时候我们用id去定位,但是运行依然找不到元素,可以观察id是否是变化的(通常id属性值含有一串无规律的数字即可怀疑是可变的),刷新页面,就能观察到id是否是变化的,对于动态的id,我们需要选择用其它属性去定位。2.需要定位的元素在下拉选择框中,我们在Chrome中可以用Ctrl+Shift+C,点击元素进行定位。点击需要定位的元素所在的下拉选择框,将鼠标悬浮于选择框中,按下“Ctrl+Shift+C”组合键,点击需要定位的元素,即可对元素进行定位。如下图:
  • [技术干货] 三极管在数字电路中的应用
    三极管在我们数字电路和模拟电路中都有大量的应用三极管是一种很常用的控制和驱动器件,常用的三极管根据材料分有硅管和锗管两种,原理相同,压降略有不同,硅管用的较普遍,而锗管应用较少。三极管有 2 种类型,分别是 PNP 型和 NPN 型      三极管一共有 3 个极,从图 3-6 来看,横向左侧的引脚叫做基极(base),中间有一个箭头,一头连接基极,另外一头连接的是发射极 e(emitter),那剩下的一个引脚就是集电极 c(collector)了。三极管有截止、放大、饱和三种工作状态。放大状态主要应用于模拟电路中,且用法和计算方法也比较复杂,我们暂时用不到。而数字电路主要使用的是三极管的开关特性,只用到了截止与饱和两种状态。      三极管的用法特点,关键点在于 b 极(基极)和 e 级(发射极)之间的电压情况,对于PNP 而言,e 极电压只要高于 b 级 0.7V 以上,这个三极管 e 级和 c 级之间就可以顺利导通。也就是说,控制端在 b 和 e 之间,被控制端是 e 和 c 之间。同理,NPN 型三极管的导通电压是 b 极比 e 极高 0.7V,总之是箭头的始端比末端高 0.7V 就可以导通三极管的 e 极和 c 极。如图三极管基极通过一个 10K 的电阻接到了单片机的一个 IO 口上,假定是 P1.0,发射极直接接到 5V 的电源上,集电极接了一个 LED 小灯,并且串联了 一个 1K 的限流电阻最终接到了电源负极 GND 上。 如果 P1.0 由我们的程序给一个高电平 1,那么基极 b 和发射极 e 都是 5V,也就是说 e 到 b 不会产生一个 0.7V 的压降,这个时候,发射极和集电极也就不会导通,那么竖着看这 个电路在三极管处是断开的,没有电流通过,LED2 小灯也就不会亮。如果程序给 P1.0 一个 低电平 0,这时 e 极还是 5V,于是 e 和 b 之间产生了压差,三极管 e 和 b 之间也就导通了, 三极管 e 和 b 之间大概有 0.7V 的压降,那还有(5-0.7)V 的电压会在电阻 R47 上。这个时候, e 和 c 之间也会导通了,那么 LED 小灯本身有 2V 的压降,三极管本身 e 和 c 之间大概有 0.2V 的压降,我们忽略不计。那么在 R41 上就会有大概 3V 的压降,可以计算出来,这条支路的 电流大概是 3mA,可以成功点亮 LED。 最后一个,电流控制。三极管有截止,放大,饱和三个状态,截止只要 e 和 b 之间不导通即可。让这个三极管处于饱和状态,就是开关特性,必须要满足一个条件。三极管都有一个放大倍数β,要想处于饱和状态,b 极电 流就必须大于 e 和 c 之间电流值除以β。这个β,对于常用的三极管大概可以认为是 100。 三极管在数字电路里的开关特性,最常见的应用有 2 个:一个是控制应用,一个是驱动应用。
  • [API集成编排] ADC相对于APPcube优势是什么,相对有其他业界的低代码平台差异在哪里?ADC比直接用HTML,js等开发优势是什么?
    在ADC伙伴伴飞过程中客户提的问题,请专家答复【功能模块】【操作步骤&问题现象】1、2、【截图信息】【日志信息】(可选,上传日志内容或者附件)
  • [openEuler] openEuler社区软件包引入提交流程
    1. 前言在这里,我们以软件cloc为例进行说明。在openEuler社区中,基本的“组织”单元是SIG组,也就是special interest group。软件本身必须是要属于某一个SIG的。很多人在写完程序以后,都总会执行一下cloc这个命令,看一下今天又新增了多少行代码,以期获得一下码农与生俱来的成就感。显然cloc是一个开发类的工具,帮助码农统计代码行,幸运的是,拥有同样兴趣的人并不在少数,他们建立了一个dev-utils的SIG组,我们可以将cloc这个软件归属于这个SIG组。openEuler所有的SIG组都在https://gitee.com/openeuler/community/tree/master/sig列出来,大家可以参考。一般来说,增加一个软件包到openEuler中,需要如下的几个大步骤:确认软件包生命周期正常,即软件包的上游社区(如github等)正常在维护,最近一次提交在两年之内。让系统为你的cloc软件包建立一个“仓”,也就是git仓。上传制作cloc软件包所需要的“零件”。将这个软件系统加入到openEuler的自动化编译系统中,由系统自动化构建出软件。2. 提交PR基本操作提交PR是对项目上一次合入申请,为保证合入的质量,这个动作是需要小心谨慎的。在您提交PR之前,请先完成本地验证,以便在一定程度上保证在提交PR后的持续集成测试的通过。Gitee上工作流的基本操作,请参考工作流。2.1  提交PR 2.1.1  提交PR请求为了更快的得到响应,您可以给PR添加标签,或提供更详细的信息,这里需要特别提示您的是:关联Issue:如果您提交的PR是针对某个Issue的,请您在提交的描述框内添加“#”字符,此时机器人会自动关联出当前存在的Issue,你可以通过此种方式快速的链接到关联的Issue。标注优先级:您可以在创建PR的时候,选择PR的优先级,或者在评论区通过/priority high给PR添加高优先级标签。标注是解决bug的合入:您可以在描述框通过输入/kind bug来标注该PR是合入解决问题的代码,以便于大家更快的回应您的PR请求。标注所属sig:为了方便查找,您也可以在描述框通过输入sig sig-name来标识该PR所属的sig。2.1.2  分配评审人您提交PR以后,社区机器人会自动给您分配评审人,您也可以指定评审人。制定评审人有两种方式,您可以在创建PR的时候,在右侧的下拉框中选择评审人;也可以在评论框中输入/assign @reviewer,从而把该PR分配给对应的人。如果您想把PR提交给项目的核心成员评审,以便于更快的获得批准,可以有两种方式获取到核心成员的信息:方式一:该Repository的owners文件(该文件通常在该repository的根目录下)中查看,此文件保存的是所有该Repository的评审人列表。方式二:可以到该项目所属的SIG的首页内查看md文件,此文件会列出该sig的负责人,所有项目以及项目的负责人。2.2  审核PR如果审核人通过您的审核,会在评论区添加/lgtm以及/approve,以表示对本次PR提交的认同审核人可以在评论区发表意见,也可以在审核文件的时候,在发现问题处添加审核意见。无论哪种方式,都会在评论区显示出来。区别是,后者的评论会显示出“代码评论”,您可以通过“详情”查看评论具体指向的出处。为了表示对评审人意见的尊重,如果对意见有异议,请您通过回复该意见来说明原因;如果接纳评审人意见,也请您做出简单的回应,便于确认后继的提交是否已按照所有接纳意见完成修改。您也可以点击“文件”,直接在文件区查看具体的代码评审意见和对比结果。在此处,您也可以直接回复评审意见。如果项目组的核心成员拒接了您的PR,会给出拒接意见。请不要气馁,您可以根据意见调整后继续和项目组成员沟通,相信在持之以恒的沟通调整后,您的能力和意见都会得到大家的认同。请注意,在使用/approve前至少要有一个/lgtm。3. 建仓3.1 SIG组相关openEuler社区按照不同的SIG来组织,以便于更好的管理和改善工作流程。SIG组是开放的,欢迎任何人加入并参与贡献。SIG都是针对特定的一个或多个技术主题而成立的。SIG内的成员推动交付成果输出,并争取让交付成果成为openEuler社区发行的一部分。SIG的核心成员主导SIG的治理,开发者可以在贡献的同时积累经验和提升影响力。每一个SIG在Gitee上都会拥有一个或多个项目,这些项目会拥有一个或多个Repository。SIG的交付成果会保存在这些Repository内。可以在SIG对应的Repository内提交Issue、针对特定问题参与讨论,提交和解决问题,参与评审等。也可以通过邮件列表、IRC或视频会议和SIG内的成员进行交流。引入软件包时,需要找到这个软件包所归属的SIG组,如果您知道感兴趣的项目名称,可以在openEuler的Repository列表下进行模糊搜索,从而快速定位到对应项目的首页地址。通常情况下,在该项目首页地址的README.md文件中,可以找到该项目所属的SIG信息、交流方式、成员和联系方式等。每个SIG内的项目使用的编码语言、开发环境、编码约定等都可能存在差异的。如果想了解并参与到编码类贡献,可以先找到该项目给开发者提供的贡献者指南——这个指南一般是在该SIG的首页地址内,以CONTRIBUTING.md文件的形式提供,或者就直接在该项目的README.md内。除了这些文件外,SIG可能还会提供其他指南信息。这些信息位于SIG或其项目的特定社区目录中。如果未找到相关信息,或者对相关信息有疑问,可以在该SIG内提交Issue,或者把问题或疑问发送到该项目所属SIG的邮件列表。如果您认为长时间没有得到回应,可以向community@openeuler.org求助。接下来建仓其实就是提交PR来修改三个文件。以当前软件包为例,其所在sig组为dev-utils, 需要修改的文件如下:README.md,sigs.yaml,src-openeuler.yaml。修改第一个文件README.md将你要加入的cloc软件的名字和地址放上去。修改sigs.yaml文件,将cloc软件增加到dev-utils这个SIG分组下面。修改src-openeuler.yaml将cloc增加到src-openeuler里。3.2 修改步骤通过修改gitee中的openeuler/community仓库实现新增软件包的具体操作步骤如下:Fork到自己的仓库点击进入community仓库,将其fork到自己的仓库。     b.clone到本地将fork完成的community仓库clone到本地。git clone https://gitee.com/"$username"/community.git     c. 修改community仓库以在gitee新增zip软件包,并且同步在openEuler:Factory工程项目下添加该包为例。cd community/sig;明确软件包所属的sig组,如zip属于Base-service组;修改所属sig文件夹下的内容,如项目清单等;修改sig/sigs.yaml,将要新增的软件包以"- src-openeuler/zip"的形式添加到对应的sig组列表下;以zip为例: openeuler.yaml;其他社区引入包: src-openeuler.yaml。提交PR(PR合入后将会在gitee建立同名仓库。当申请的结果被批准以后,你所需要的“仓”就会被系统自动建立起来,查看地址是src-openeuler。对于cloc来说,它的代码仓的位置在https://gitee.com/src-openeuler/cloc,这是PR被批准以后由系统自动为我建立的。同时在OBS上建立同名仓库,可在OBS网站查看(https://build.openeuler.org/project/show/openEuler:Factory); 剩下的时间,你就可以开始真正上传制作cloc软件的原材料了。4. 上传软件包一般来说,一个软件只需要上传两个“原材料”就足够制作一个软件包了。如下图所示:第一个材料:首先要上传这个软件包的SPEC文件,也就是告诉构建系统如何编译,制作cloc这个软件包。第二个材料:cloc的源代码压缩包。其它零件:如果SPEC中需要有Patch,那么也需要把相关的Patch文件上传到仓中。上传完毕一个软件包所需要的原材料, 这里我们需要在OBS上的Factory工程中确认软件包是否构建成功。在Factory工程下软件包,会分别显示在aarch64与x86环境中的构建结果。以软件cloc为例,如图所示即为构建成功:如果构建不成功,则状态为failed,unresolveable,broken等状态, 需要查看编译日志中的具体错误信息,定位出错原因。 5. 加入构建系统当我们在Factory工程上面确认好了软件包已经构建成功,当前的构建工程还是在Factory上面,我们需要将它移动到最终归属的构建工程。openEuler现在使用OBS作为构建工具系统,因此,引入的软件包需要加入到OBS构建系统中 。加入到构建系统中,就意味着你的软件可以被系统自动编译,自动生成RPM包,继而在后续的openEuler发行版本中出现。OBS使用源服务获取源码,使用源服务,就需要_service文件。新增软件包时,openEuler自动使用了tar_scm_kernel_repo插件拉取代码。可通过修改src-openeuler/obs_meta仓库下对应软件包的_service文件实现自定义更改,具体步骤如下:点击进入obs_meta仓库,将其fork到自己的仓库。将fork完成的obs_meta仓库clone到本地。git clone https://gitee.com/"$username"/obs_meta.git     3. 修改obs_meta仓库。cd obs_meta/master/openEuler:Factory/vim "package_name"/_service根据自己的需求修改_service 文件。(package_name是需要自定义_service文件的软件包名称)提交PR,PR合入后将会把修改后的_service文件同步到该仓库。_service文件是一个xml格式的文件,主要功能是拉取代码库上的代码,对代码库的代码再组织打包进行编译前的源码准备。以软件包cloc为例: 这行指定插件名称为tar_scm_kernel_repo。repo 这行指定插件操作的代码管理工具为repo。next/openEuler/cloc这行指定repo源码的地址。在本次赛题中,我们需要将代码提交到openEuler:20.03:LTS:SP1:HDC工程下,因此需要在obs_meta/ openEuler-20.03-LTS-SP1/openEuler:20.03:LTS:SP1:HDC目录下新建软件包目录,将obs_meta/master/openEuler:Factory/下面的_service文件复制到HDC下的软件包目录里,然后提交PR,这样,构建工程就从Factory添加到HDC工程下面了。6. 新建分支如果我们需要为软件包新建分支,和新建仓库类似也需要去community仓库提pr来进行操作。具体步骤如下:Fork community到自己的仓库点击进入community仓库,将其fork到自己的仓库。     b.clone到本地将fork完成的community仓库clone到本地。git clone https://gitee.com/"$username"/community.git     c. 修改community仓库cd community/repository;修改src-openeuler.yaml,搜索该软件包名,并为其添加新分支的名字、类型(protected)以及继承自哪个分支。以zip软件包新增openEuler-20.03-LTS-Next分支为例。注意类型均为protected, Next分支继承自master分支。之后就可以提pr等maintainer合入了,合入后会自动在该包的src-openeuler仓库下新建一个openEuler-20.03-LTS-Next分支。
  • [技术干货] html学习(下)
    表格标签练习(绘出求职简历表)123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172<!DOCTYPE html><html>    <head>        <meta charset="utf-8">        <title>表格文件作业</title>    </head>    <body>        <table border="green" cellpadding="10" cellspacing="">            <tr>                <th colspan="2" width="100px">基本信息</th>                <td colspan="8" width="400px"></td>                             </tr>            <tr>                <th colspan="2">姓名</th>                <td colspan="2" width="100px"></td>                <th colspan="2" width="100px">性别</th>                <td colspan="2" width="100px"></td>                <td rowspan="7"  colspan="2" width="200px"></td>             </tr>            <tr>                <th colspan="2">民族</th>                <td colspan="2"></td>                <th colspan="2">出生年月</th>                <td colspan="2"></td>             </tr>            <tr>                <th colspan="2">政治面貌</th>                <td colspan="2"></td>                 <th colspan="2">健康状况</th>                <td colspan="2"></td>             </tr>            <tr>                <th colspan="2">籍贯</th>                <td colspan="2"></td>                 <th colspan="2">学历</th>                <td colspan="2"></td>             </tr>            <tr>                <th colspan="2">电子信箱</th>                <td colspan="2"></td>                 <th colspan="2">联系电话</th>                <td colspan="2"></td>              </tr>            <tr>                <th colspan="2">专业</th>                <td colspan="6"></td>                              </tr>            <tr>                <th colspan="2" >毕业院校</th>                <td colspan="6"></td>              </tr>            <tr>                <th colspan="2">求职意向</th>                <td colspan="8"></td>            </tr>        </table>    </body></html> 内嵌标签的学习iframe参数:​ src:要显示的网页资源路径;可以是本地(相对路径)也可以是网络资源(URL )注:默认当前页面打开及加载src指向的资源​ width:设置显示区域的宽度 height :设置显示区域的高度作用:在当前网页中加载其他网页的资源,达到不同网页资源之间不相互干扰,并能在同一个页面中展现给用户的目的。1234567891011121314<!DOCTYPE html><html>    <head>        <meta charset="utf-8">        <title></title>    </head>    <body>        <a href="https://www.csdn.net/" rel="external nofollow"  target="ifcsdn">csdn</a>        <a href="http://www.baidu.com" rel="external nofollow"  rel="external nofollow"  target="_ifbaidu">baidu</a>        <br>        <iframe src="" width="48%" height="500px" name="ifcsdn"></iframe>        <iframe src="" width="48%" height="500px" name="_ifbaidu"></iframe>    </body></html> 框架标签的学习 1.删除body标签frameset参数rows :按照行进行切分页面cols :按照列进行切分页面子标签:frame :进行切分区域的占位,一个frame可以单独加载网页资源。src :资源路径(本地或者网络)name :区域名, 结合超链接使用12345678910111213141516<!DOCTYPE html><html>    <head>        <meta charset="utf-8">        <title>框架标签学习</title>    </head>    <frameset cols=" 20% ,*,50%">        <frame src="frame/left.html" >        <frameset rows="70% ,*">            <frame src="frame/top.html" >            <frame src="frame/bottom.html" >        </frameset>        <frame src="frame/right.html" name="_right" >             </frameset></html> form表单标签的学习作用:收集并提交用户数据给指定服务器属性:action :收集的数据提交地址也就是URLmethod :收集的数据的提交方式get :适合小量数据 ,表单数据以?隔开拼接在URL后面,不同的键值对使用&符号隔开,不安全。post:适合大量数据,安全,隐式提交注:表单数据的提交,要提交的表单项必须拥有name属性值,否则不会提交。提交的表单项数据为键值对,键为name属性的值,值为用户书写的数据form标签会收集其标签内部的数据form表单的数据提交需要依赖于submit提交按钮. from表单域标签学习作用:给用户提供可以进行数据书写或者选择的标签。使用:(1)文本框:text 收集少量的文本数据,用户可见password收集用户密码数据 name :数据提交的键,也会被js使用value:默认值(2)单选框:radio ​ name : name属性值相同的单选框只能选择一项数据​ value :要提交的数据​ checked:checked使用此属性的单选默认是选择状态(3)多选框checkbox name:一个多选组需要使用相同的name属性值value:要提交的数据checked:checked 使用此属性的多选框默认选择状态(4)单选下拉框select name :数据提交的键名,必须声明子标签option:一个option标签表示一个下拉选项value :要提交的数据(5)文本域textarea:声明一个可以书写大量文字的文本区域 name :数据提交的键名, js和CSS也会使用rows :声明文本域的行数cols :声明文本域的列数(6)普通按钮<input type="button" name="" id="" value="普通按钮" />(7)隐藏标签隐藏标签<input type="hidden" name="hidden" id="" value="啦啦" />1234567891011121314151617181920212223242526272829303132333435363738<!DOCTYPE html><html>    <head>        <meta charset="utf-8">        <title>form表单标签的学习</title>    </head>    <body>        <h3>form表单标签的学习</h3>        <hr >        <form action="#" method="get">            Login:<input type="text" id="" name="user" value=""  /><br>            Password:<input type="password" name="password" value="" /><br>            sex:男<input type="radio" name="sex" value="n" checked="checked" />女<input type="radio" name="sex" value="w"/><br>            爱好:吃饭<input type="checkbox" name="fav" value="1"/>             睡觉<input type="checkbox" name="fav" value="2"/>             打豆豆<input type="checkbox" name="fav" value="3"/> <br>                         籍贯:<select name="address">                <option value="北京">北京</option>                <option value="上海">上海</option>                <option value="广州" selected="selected">广州</option>            </select><br>                         文本域:<br>            <textarea rows="10" cols="30" name="intro">                             </textarea>            <br>            <input type="button" name="" id="" value="普通按钮" />            <br>            <hr >            隐藏标签<input type="hidden" name="hidden" id="" value="啦啦" />            <hr >            <input type="submit" id="" name=""  value="登录"/>                     </form>    </body></html>
  • [技术干货] html各种学习(中)
    超链接标签学习 a标签href :要跳转的网页资源路径本地资源:相对路径网络资源:网络资源(网页)的URLtarget :指明要跳转的网页资源的显示位置_self 在当前页中刷新显示_blank 在新的标签页中显示_top 在顶层页面中显示_parent 在父级页面中显示 锚点学习作用:在一张网页中进行资源跳转使用:先使用超链接标签在指定的网页位置增加锚点.格式为:<a name="锚点名”></a>使用a标签可以跳转指定的锚点,达到网页内部资源跳转的目的,格式:<a href="#锚点名" rel="external nofollow" >访问方式/a>代码粘贴123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263#超链接<!DOCTYPE html><html>    <head>        <meta charset="utf-8">        <title>超链接</title>    </head>    <body>        <h3>超链接标签</h3>        <hr >        <a href="图片标签 .html" rel="external nofollow"  target="_blank">图片标签</a>        <hr >        <a href="body标签(列表标签).html" rel="external nofollow"  target="_parent"><img src="img/1.jpg" height="200px" ></a>        <hr >        <a href="http://www.baidu.com" rel="external nofollow"  rel="external nofollow" >baidu</a>        <h3>锚点学习</h3>        <a href="锚点学习.html" rel="external nofollow" >锚点学习</a>    </body></html>  #锚点学习<!DOCTYPE html><html>    <head>        <meta charset="utf-8">        <title>锚点学习</title>    </head>    <body>        <a href="#first" rel="external nofollow" >第一章</a><br>        <a href="#second" rel="external nofollow" >第二章</a><br>                          <h5>第一章</h5>        <a name="first"></a>                 <p>            啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦        </p>        <p>            啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦        </p>        <p>            啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦        </p>        <p>            啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦        </p>                 <h5>第二章</h5>        <a name="second"></a>        <p>            哈哈哈哈哈哈哈哈哈哈或或或或或或或或或或或或或或或或或或或或或或或或或        </p>        <p>            哈哈哈哈哈哈哈哈哈哈或或或或或或或或或或或或或或或或或或或或或或或或或        </p>        <p>            哈哈哈哈哈哈哈哈哈哈或或或或或或或或或或或或或或或或或或或或或或或或或        </p>        <a href="#" rel="external nofollow" >回到顶部</a>    </body></html> 表格标签的学习table :声明一个表格​ tr:声明一行,设置行高及改行所有单元格的高度。​ th:声明一个单元格,表头格.默认居中加黑显示​ td:声明一个单元格,默认居左显示原始数据属性:border :给表格添加边框width:设置表格的宽度height:设置表格的高度cellpadding:设置内容居边框的距离cellspacing:设置边框的大小特点:默认根据数据的多少进行表格的大小显示1234567891011121314151617181920<table border="1px" bordercolor="red" cellpadding="10" cellspacing="0">            <tr height="50px">                <th width="100px">科目</th>                <th>分数</th>                <th>姓名</th>                <th>性别</th>            </tr>            <tr>                <td>英语</td>                <td>100</td>                <td>张三水电费水电费</td>                <td>男</td>            </tr>            <tr>                <td>汉语</td>                <td>10</td>                <td>李四</td>                <td>男</td>            </tr>        </table> 表格的合并步骤:1.首先确保表格是一个规整的表格2.根据要合并的单元格,找到其所在的源码位置3.合并行合并:在要合并的单元格中的第一个单元格 上使用属性rowspan= “要合并的单元格的个数” ,并删除其他单元格完成合并列合并:在要合并的单元格中的任意一个上使用属性colspan=“要合并的单元格的个数” ,并删除其他单元格123456789101112131415161718192021222324252627<h4>表格合并的学习</h4>        <hr >        <table border="2" cellpadding="10" cellspacing="0" bordercolor="red">            <tr height="35px">                <td width="100px"></td>                <td width="100px"></td>                <td width="100px"></td>                <td width="200px"colspan="2" rowspan="2"></td>            </tr>            <tr height="35px">                <td colspan="2"></td>                <td></td>            </tr>            <tr height="35px">                <td></td>                <td></td>                <td></td>                <td rowspan="2" ></td>                <td></td>            </tr>            <tr height="35px">                <td></td>                <td></td>                <td></td>                <td></td>            </tr>        </table> 代码粘贴123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960<!DOCTYPE html><html>    <head>        <meta charset="utf-8" />        <meta name="viewport" content="width=device-width, initial-scale=1">        <title>表格标签</title>    </head>    <body>        <h3>表格标签的学习</h3>        <hr >        <table border="1px" bordercolor="red" cellpadding="10" cellspacing="0">            <tr height="50px">                <th width="100px">科目</th>                <th>分数</th>                <th>姓名</th>                <th>性别</th>            </tr>            <tr>                <td>英语</td>                <td>100</td>                <td>张三水电费水电费</td>                <td>男</td>            </tr>            <tr>                <td>汉语</td>                <td>10</td>                <td>李四</td>                <td>男</td>            </tr>        </table>                 <h4>表格合并的学习</h4>        <hr >        <table border="2" cellpadding="10" cellspacing="0" bordercolor="red">            <tr height="35px">                <td width="100px"></td>                <td width="100px"></td>                <td width="100px"></td>                <td width="200px"colspan="2" rowspan="2"></td>            </tr>            <tr height="35px">                <td colspan="2"></td>                <td></td>            </tr>            <tr height="35px">                <td></td>                <td></td>                <td></td>                <td rowspan="2" ></td>                <td></td>            </tr>            <tr height="35px">                <td></td>                <td></td>                <td></td>                <td></td>            </tr>        </table>    </body></html>
  • [技术干货] 仙女本仙教你在线学习html各种标签(上)
    head标签学习网页标题标签12<title>HTML学习</title> <!-- 告诉浏览器我们需要什么标题来显示页 -->编码格式标签12<meta charset="utf-8" /> <!-- H5网页解析编码标签 --><meta http-equiv="content-type" content="text/html; charset=utf-8"><!-- H4网页解析编码标签 -->网页搜索优化标签1234<title>HTML学习</title> <!-- 告诉浏览器我们需要什么标题来显示页 -->    <meta name="Description" content="本网页是关于HTML的head的学习,666,哈哈哈"/> <!-- 网页描述 -->    <meta name="Keywords" content="azb,lll,xxx"/> <!-- 网页关键字 -->    <meta name="author" content="安老师"/> <!-- 网页作者 -->网页指定跳转标签1<meta http-equiv="refresh" content="5;url = https://www.baidu.com"/><!-- 表示五秒后跳转指定URL -->其他标签CSS或js引入的标签 body标签学习body文本标签 1.标题标签h1到h6:会将其中的数据加粗显示,并且显示依次减弱,标题标签自带换行功能(块级标签)属性:12align : center right left<h1 align="center">我是标题</h1><br><h2 align="center">我是标题</h2><br><h3 align="middle">我是标题</h3><br><h4 align="right">我是标题</h4><br><h5>我是标题</h5><br><h6>我是标题</h6> 2.水平线标签hr:会在页面中显示一条水平线,默认居中显示属性:width="宽度”设置水平线的宽度size=“高度”设置水平线的高度color="颜色”设置水平线的颜色12345<hr width="200px"size="20px" color="red"align="left"><hr width="40%"> 3.段落标签p:会将一段数据作为整体进行显示,主要是进行css和js操作时比较方便.会自动换行(块级元素)特点:段间距比较大 4.换行符标签br:告诉浏览器需要在此位置换行 5.空格符标签&nbsp:告诉浏览器在此位置增加空格 6.权重标签b:会将内容加黑显示i :会将内容斜体显示u:会将内容增加下划线del :增加中划线权重标签可以随意叠加注:1标签的属性是对标签的功能进一步的补充 ,可以由开发人员自由指定标签的属性值,来达到想要的显示效果。2像素单位占据的是电脑屏幕的大小,百分比占据的是浏览器窗口的大小。1234567<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<u>东方网·演兵场4月6日报道</u>:<br>多家央媒近日集中报道了入列一年多的首艘国产航母山东舰,披露了其社区化生活、官兵伙食和近防装备等诸多细节。演兵场注意到</p><p><b>东方网</b>·演兵场<i>4月6日</i>报道:多家央媒近日集中报道了入列一年多的首艘国产航母山东舰,<del>披露了其社区化生活、官兵伙食和近防装备等诸多细节。演兵场注意到</del></p><b><i><u><del>今天适合学习d</del></u></i></b>文本标签全部代码12345678910111213141516171819<html><head><meta charset="utf-8"/><title>body标签学习</title></head><body><h1 align="center">我是标题</h1><h2 align="center">我是标题</h2><h3 align="middle">我是标题</h3><h4 align="right">我是标题</h4><h5>我是标题</h5><h6>我是标题</h6><hr width="200px" size="20px" color="red" align="left"><hr idth="40%"><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<u>东方网·演兵场4月6日报道</u>:<br>多家央媒近日集中报道了入列一年多的首艘国产航母山东舰,披露了其社区化生活、官兵伙食和近防装备等诸多细节。演兵场注意到</p><p><b>东方网</b>·演兵场<i>4月6日</i>报道:多家央媒近日集中报道了入列一年多的首艘国产航母山东舰,<del>披露了其社区化生活、官兵伙食和近防装备等诸多细节。演兵场注意到</del></p><b><i><u><del>今天适合学习d</del></u></i></b></body></html> body列表标签 1.无序列表ulli :该标签中书写列表内容,一个1i标签代表列表中的一行数据特点:默认数据前有一个黑圆圈符号. 2.有序列表olli :该标签中书写列表内容,一个1i标签代表列表中的一行数据特点:会自动的给列表进行顺序编码,格式从小到大并且是连续的。属性:type:可以改变顺序编码的值,可以是1 a A I, ,默认使用阿拉伯数字进行顺序编码 3.自定义列表dldt :数据的标题dd:数据的具体内容,一个dd表示一 条数据、 列表标签全部代码1234567891011121314151617181920212223242526<!DOCTYPE html><html><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1"><title>body标签(列表标签)</title></head><body><h3>列表的学习</h3><hr ><h3>无序列表</h3><ul><li>北京</li><li>广州</li><li>上海</li><li>西安</li></ul><h3>有序列表</h3><ol type="A"><li>xx</li><li>hh</li><li>ll</li><li>qq</li></ol><dl><dt>java</dt><dd>python</dd><dd>go</dd><dd>shell</dd><dt>hh</dt><dd>aa</dd><dd>xx</dd><dd>ll</dd></dl></body></html> 图片标签学习img src :图片路径本地资源路径:一般本地图片资源使用相对路径即可网络资源路径:图片资源的URL地址属性width:设置图片的宽度,如果是单独设置,则再图片保证不失真的情况下自动缩小或者放大;单位可以是px也可以是百分比height :设置图片的高度,如果是单独设置,则再图片保证不失真的情况下自动缩小或者放大;单位可以是px也可以是百分比title:图片标题,鼠标放在图片上的时候会显示alt:图片加载失败后的提示语注意:图片是不会自动换行的(行内元素) 代码粘贴1234567891011121314151617<html>    <head>        <meta charset="utf-8"/>        <title>图片标签学习</title>             </head>    <body>        <h3>图片标签学习</h3>        <hr >        <img src="D:/" title="hanpi" alt="shabi">        <img src="./img/1.jpg" height="200px" title="shabi" alt="hanpi">        <img src="img/2.jpg" width="200px" >        <hr >        <img src="https://ss1.bdstatic.com/70cFuXSh_Q1YnxGkpoWK1HF6hhy/it/u=3767793794,672931879&fm=26&gp=0.jpg" >             </body></html>
  • [技术干货] https://bbs.huaweicloud.com/forum/thread-13735-1-1.html
    https://www.huawei.com/minisite/ascend/cn/filedetail_1.html
  • [技术干货] HTML 拖拉功能的实现代码(下)
    12345678910111213141516171819202122232425262728293031323334353637383940<!-- 父组件代码片段 vue 文件版 --> <template>  <div    ref="father"    style"width: 100%, height: 100%"  >    <ChildComponents      v-for="(item, index) in playList"      :key="index"      :ref="index"      :visible="true"      :z-index="index"      :back-value="backValue"      :info="item"      :close="close"      :width="600"      :height="400"    />  </div></template><script>export default {  components: {    VideoPlayerModal  },  props: {    playList: {      type: Array,      required: true    }  },  methods: {    backValue (left, top, zIndex) {      this.$refs[zIndex][0].$el.style.top = `${top}px`      this.$refs[zIndex][0].$el.style.left = `${left}px`    }  }}</script>设置子组件的围栏范围这个功能只需要在 onmousemove 事件中进行判断 子容器的 top 和 left 是否超出浏览器的可视范围12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061/** 1. this.width 数据为父组件传递进来的 width 值,或者子组件本身设置的默认值* 2. this.height 数据为父组件传递进来的 height 值,或者子组件本身设置的默认值*/ move (e) {  // 判断 flag 是否允许移动  if (!this.moveFlag) return   // 判断是否超出左边视图      if (this.$refs.fatherBox.offsetLeft < this.width / 2) {        // 禁止弹框移动        this.moveFlag = false        // 设置弹框左边位置        this.left = this.width / 2 + 10        // 调用回调函数把偏移量暴露给父组件        this.backValue(this.left, this.top, this.zIndex)        return      }       // 判断是否超出右边视图      if (this.$refs.fatherBox.offsetLeft > document.body.clientWidth - this.width / 2) {        // 禁止弹框移动        this.moveFlag = false        // 设置弹框右边位置        this.left = document.body.clientWidth - this.width / 2 - 10        // 调用回调函数把偏移量暴露给父组件        this.backValue(this.left, this.top, this.zIndex)        return      }       // 判断是否超出顶部视图      if (this.$refs.fatherBox.offsetTop < this.height / 2 + 70) {        // 禁止弹框移动        this.moveFlag = false        // 设置弹框顶部位置        this.top = this.height / 2 + 70 + 10        // 调用回调函数把偏移量暴露给父组件        this.backValue(this.left, this.top, this.zIndex)        return      }       // 判断是否超出底部视图      if (this.$refs.fatherBox.offsetTop > document.body.clientHeight - this.height / 2 - 50) {        // 禁止弹框移动        this.moveFlag = false        // 设置弹框底部位置        this.top = document.body.clientHeight - this.height / 2 - 50 - 10        // 调用回调函数把偏移量暴露给父组件        this.backValue(this.left, this.top, this.zIndex)        return      }       // 设置弹框左边位置      this.left = e.clientX - this.startLeft      // 设置弹框右边位置      this.top = e.clientY - this.startTop       // 调用回调函数把偏移量暴露给父组件      this.backValue(this.left, this.top, this.zIndex)}子组件还要设置一个当鼠标超出子容器时的 onmouseout 事件,用来防止不可预期的 bug 问题123mouseOut (e) {  this.moveFlag = false}
  • [技术干货] HTML 拖拉功能的实现代码(上)
    基于 vue此功能核心思想就是通过 JavaScript 代码控制 node 在页面上的左边距与顶边距,不同的的样式定位方式有不同的解决方案本方案采用position: absolute定位方式的解决方案css 样式的核心代码1234// 父容器核心样式   width: 100%;  height: 100%;12345// 子容器核心样式  position: absolute;  top: 50%;  left: 50%;  transform: translate(-50%,-50%);父容器通过width && height字段占满整个浏览器的可视范围,子容器通过position: absolute属性开启在父容器内的绝对定位,在通过top && left && transform: translate(-50%, -50%)属性控制子容器在父容器内的绝对位置JavaScript 逻辑控制的核心代码首先分解下,要实现 node 的移动需要哪些步骤和对应的 event 事件子容器创建时,在父容器内的绝对位置鼠标按键按下时,onmousedown 事件鼠标移动时,onmousemove 事件鼠标按键弹起时,onmouseup 事件只要使用 onMousedown、onMousemove和onMouseup 这三个事件,就可以实现最简单的移动12345678/** 在子容器创建的时候获取子容器相对于父容器的 top 和 left 位置*/ mounted () {  this.left = this.$refs.fatherBox.offsetLeft  this.top = this.$refs.fatherBox.offsetTop}12345678910111213/** 鼠标按下时* 1. 开启允许子容器移动的 flag* 2. 记录鼠标点击时的位置信息*/ mouseDown (e) {  // 设置允许弹窗移动的 flag  this.moveFlag = true  // 保存鼠标开始位置  this.startLeft = e.clientX - this.left  this.startTop = e.clientY - this.top}1234567891011121314151617/** 鼠标移动时* 1. 判断 flag 是否允许子容器移动* 2. 设置弹框左边位置* 3. 设置弹框右边位置*/ move (e) {  // 判断 flag 是否允许移动  if (!this.moveFlag) return   // 设置弹框左边位置  this.left = e.clientX - this.startLeft  // 设置弹框右边位置  this.top = e.clientY - this.startTop }12345678/** 鼠标按键弹起时* 1. 关闭允许子容器移动的 flag*/ mouseUp (e) {  this.flag = false}通过这几个方法就可以获取鼠标按下移动时,鼠标的top 和 left 的偏移量,通过把这偏移量暴露出去给父组件,父组件实时设置子组件的 top 和 left 值,来使得子容器跟随鼠标的移动父组件部分代码父组件通过设置子组件的 ref、zIndex 值,而且父组件的 backValue 方法会从子组件接收 zIndex 值,通过 zIndex 来识别具体的子组件实例12345678910111213141516171819202122232425262728293031323334353637383940/** 父组件代码片段 jsx 版*/ export default {  props: {    playList: {      type: Array,      required: true    }  },  render () {    return (      <div style={{width: '100%', height: '100%'}} ref={'father'}>        {          this.playList && this.playList.map((item, index) => {            return (              <ChildComponents                key={index}                ref={index}                zIndex={index}                visible={true}                backValue={this.backValue}                info={item}                width={600}                height={400}              />            )          })        }      </div>    )  },  methods: {    backValue (left, top, zIndex) {      this.$refs[zIndex].$el.style.top = `${top}px`      this.$refs[zIndex].$el.style.left = `${left}px`    }  }}
  • [技术干货] django中显示字符串的实例方法
    1、quicktool/view.py文件修改视图函数index(),渲染一个home.html模板,在视图中传递一个字符串名称是 string 到模板 home.html123def index(request):  string = u'这是一个由Django2.1.7版本写出的视图内容!'  return render(request, 'home.html',{'string':string})2、quicktool(应用app)下创建一个templates文件夹(模板),在templates下创建一个home.html1234567891011<!DOCTYPE html><html><head>  <title>学习Django</title></head><body>  {{ string }}  </body></html>知识点扩展:在django中,带有HTML标签的字符串,如str = "aa a",我们通过template展示在html页面中时,django会自动转义为可显示的html字符串,即将html标签的尖括号等字符转义。如字符串中的空格会显示为  ,尖括号会显示为 <、 >等等。当我们不需要此自动转换,如上述str在html页面直接显示为aa a时,可通过多种方法禁止django进行自动转义。1. 对于单个变量,可以在其后面加上safe过滤器,告诉Django这个字符串不用进行HTML转义。比如:12This will be escaped: {{ data }}This will not be escaped: {{ data|safe }}2.对于一段模板内容可以使用autoescape标签,比如:123{% autoescape off %}Hello {{ name }}{% endautoescape %}
  • [问题求助] 【软件定义相机 D2120-10-SIU 产品】【实现在浏览器中自定义HTML页面上播放相机实况监控功能】
    【功能模块】最近有个项目需要做类似安全生产监控平台这么个系统,其中有一项需求就是做一个网页播放摄像头的实时监控功能,这个的功能该如何实现呢,有没有知道的大哥给个思路或者示例,感激不尽!!!
  • [其他] 【故障】列存表并发更新时时出现锁等待问题
    【案例描述】现场在做业务测试,开启transaction,执行updata的语句执行成功,不执行commit或rollback;再开启另一个窗口,执行upadate语句,有时失败(报错:锁等待超时),有时成功,但是如果对于上一个窗口执行rollback,此窗口update可以执行成功。【案例根因】现场测试使用的是列存表,在事务中执行update操作时,是以CU为单位进行加锁的,所以在事务未提交时并发更新同一CU的其他数据时会出现锁等待的情况,等待超时时会出现报错【机制原理】1. CU为压缩单元(Compress Unit),列存储的最小单位,导入数据时生成,生成后数据固定不可更改,单个CU最多存储1列60000行数据。同一列的CU连续存储在一个文件中,当大于1G时,切换到新文件中。其中的Ctid字段标识列存表的一行,由cu_id和CU内行号(cu_id, offset)组成;一次性写入的多条的数据位于同一CU。2.  为了防止页面同一个元组被两个事务同时更新,在进行update时,都会加上行级锁,对于行存来说是对一行数据加锁,对于列存来说就是对一个CU加锁,当一个事务update未提交时,其他事务是无法同时去更新同一CU的数据的。3. 进行update操作后,旧元组被标记为deleted,新元组会写到一个新的CU中【案例分析】1.根据现场的报错信息,可以确定是并发更新报错;进行update时,会申请行级锁,在申请行级锁之前会申请transactionid锁,等待超时后报错信息为:waiting for ShareLock on transaction xxx after ..ms2. 客户反应更新的并不是同一条数据,id不同,询问客户后得知出现问题的是列存表,查询更新的数据是否处于同一CU。查询后发现处于同一CU,符合预期。3. 本地复现场景后向客户解释:起事务执行update操作:事务未提交并发更新数据出现等待:查询后发现两条数据位于同一cu:【相关问题】1.一线咨询为什么update成功一次之后,下一次update就不会互相等锁了  这是因为update成功之后,旧数据被标记为deleted,新数据写入新的CU,这两条数据不再是同一个CU了,也就不存在这种锁冲突2.客户反馈有两条数据不是同一批次入库的,也出现了锁等待现象通过查出这两条数据的ctid和xmin,可以确认是同一批入库,在同一CU,客户反馈有误。【处理方案】列存表不适合频繁的update场景,列存频繁的update容易触发并发更新等锁超时,并且会导致小CU过多,而每个CU都会扩展至8192字节进行对齐,从而导致磁盘空间迅速膨胀;频繁的点查或频繁update场景建议使用行存表
  • [技术干货] Django URL和View的关系说明
    URL和View的关系1、每次用户发来一个HttpRequest请求,Django会用URL_pattern与请求进行匹配,匹配到第一个URL_pattern就会把请求转向对应的view2、view用来响应request,并返回response,response里可以包含网页文件呀,图片等等。所以项目中绝大部分代码均在此编写。view 可以引入通用模板来减少代码量,具体查看文档1Use generic views3、view引入HTML文件的方法:在一个app下建立一个templates文件夹,将html文件放进去该文件夹这里其实不一定要把HTML文件放在这个templates里,可以随意定义不过,需要在setting.py里,找到templates,修改DIRS:[ os.path.join (BASE_DIR,'你定义的html存放的文件夹')]在app下 view.py 文件,在里面写好view函数def 函数名(request):1return render(request,'index.html')render(渲染)需要三个变量, 第一个变量是request请求,第二个是模版所在目录,第三个是一个字典(可选),字典用于对应模板里设计的变量,可以用locals()将函数里设计的变量自动转换为字典4、在对于app下创建一个urls.py ,写入如下内容12345from django.urls import pathfrom . import viewsurlpatterns = [  path('', views.index, name='index'),]5、在项目文件夹里找到 urls.py 加入如下内容123456from django.urls import include, pathurlpatterns = [ path('polls/', include('polls.urls')), path('admin/', admin.site.urls),]对于<a>标签里的 href 可以用 {% url 'url名' %}来代替,url名指的是 urls.py 里的path('login.html/', views.my_login, name='url名'),Django 中通常使用 get_object_or_404()来捕捉 404 错误,而不用自己写 try...except123def detail(request, question_id): question = get_object_or_404(Question, pk=question_id) return render(request, 'polls/detail.html', {'question': question})补充:django中url与view配置方法django中url与view配置方法(一)url.py12345from django.conf.urls import urlfrom . import viewsurlpatterns = [ url(r'^$', views.showAssets, name='show_assets'),]views.py12345# -*- coding: utf-8 -*-from django.shortcuts import render_to_response# Create your views here.def showAssets(request): return render_to_response('assets_index.html', {})django中url与view配置方法(二)url.py123456# -*- coding: utf-8 -*-from django.conf.urls import urlfrom app001.views import IndexViewurlpatterns = [ url(r'^admin/', admin.site.urls), url(r'^$', IndexView.as_view(), name="index"), ]views.py1234567# -*- coding: utf-8 -*-from django.views.generic.base import Viewfrom django.shortcuts import render# Create your views here.class IndexView(View): def get(self, request):  return render(request, 'index.html', {})
  • 项目实战案例解析:B样条曲线问题
    【案例】我们今天就以B样条曲线问题,作为今天的测试样例。B样条(B-Spline)曲线是最重要的自由曲线曲面类型之一。我们可以在在二维平面内,根据指定的控制点坐标,在指定的精度下,按照指定幂次,绘制与这组控制点对应的B样条曲线的函数。代码如下:          void drawBSpline( GLint order, GLfloat v[][2], GLint ptsNum, GLint numofU, GLint node[] )          {              glColor3f(0.0,1.0,0.0); // 设置B样条曲线绘制颜色为绿色              glLineWidth(3.0); // 设置绘制线宽              for(int i=0; i<ptsNum-order; i++){// 对每段曲线,有numofU个点                  glBegin(GL_LINE_STRIP); // 开始绘制的标志                  GLfloat tempU=node[0]; // 对tempU赋初值for(int k=0; k<numofU; k++)  {// 对每个点,有Bj, k(u)*Vj个取值,j=i-k, i-k+1, ..., i                      GLfloat tempx = 0.0, tempy = 0.0;                      GLint jj = i;                      for(int j=-order; j<1; j++){// 计算对应B样条基函数的值,即Bi, k(u)                          GLfloat tempB = calcBaseFunc( j, order, tempU, node );                          tempx += v[jj][0] * tempB;                          tempy += v[jj][1] * tempB;                          jj++; // 顶点是不断变化的,但B样条基函数其实是不变的                      }                      glVertex2f(tempx, tempy); // 不记录曲线点,直接绘制B-spline曲线上的点                      tempU+=1.0/(numofU-1); // 更新tempU,作为下次循环的初值                  }                  glEnd(); // 结束绘制的标志}          }  【解析】我们可以将每层循环涉及的循环变量、初值、终值和循环累加量的情况,做一个简单的罗列。 ptsNum、oder、numofU均为取值不确定的变量,并满足如下的约束条件:(1)order≥0,曲线幂次不应小于零;(2)ptsNum≥2,控制点的个数至少应能生成一条直线段;(3)numofU≥2,绘制B样条曲线的点数应保证至少包含起点和终点。 针对这样的边界条件,我们应结合循环次数的边界组合,来进行测试设计。这样,我们就可以得到内容:①9个(21.4%)是永远测不到的情况;②18个(42.9%)是不符合约束条件的情况。这种情况,我们只需要选择其中几个进行测试即可;③剩下的15个(35.7%)测试用例中,只有3个是可以得到光滑曲线的,其他均对应测试的是特殊的曲线形式或特殊的显示效果。因此,如果仅根据循环的类型(串联、嵌套等),B样条曲线如何随着幂次的变化而变化,曲线形状如何随着绘制精度的变化而变化,以及B样条控制多边形的形状和绘制精度对得到的B样条曲线形状具有怎样的影响?通过上述分析,我们不难看出,实际上,B样条曲线的绘制函数是一种特殊情况,它所涉及的数值在计算上较为复杂。如果我们要检验函数计算的正确性,就必须根据B样条曲线点的计算公式,通过手动方式来计算其正确结果。这样做其实非常烦琐。所以,我们一般地处理方法是,通过直观观察的方式,对程序计算结果进行初步检验。如果曲线生成符合一般规律,则初步认为计算过程是正确的。