编写 LuCI CBI 模型

news2024/11/16 22:56:00

编写 LuCI CBI 模型

CBI模型是描述UCI配置文件结构的Lua文件,并且CBI解析器将lua文件转为HTML呈现给用户 。

所有 CBI 模型文件都必须返回类型为luci.cbi.Map的对象。

CBI 模型文件的范围由 luci.cbi 模块的内容和 luci.i18n 的转换函数自动扩展。

CBI控件类型汇总

名称描述继承自模板
NamedSectionA fixed configuration section defined by its nameNamedSection = class(AbstractSection)cbi/nsection
TypedSectionA (set of) configuration section(s) defined by the typeTypedSection = class(AbstractSection)cbi/tsection
NodeNode pseudo abstract classNode = class()cbi/node
TemplateA simple template elementTemplate = class(Node)
MapA map describing a configuration fileMap = class(Node)cbi/map
CompoundContainerCompound = class(Node)cbi/compound
DelegatorNode controllerDelegator = class(Node)cbi/delegator
SimpleFormA Simple non-UCI formSimpleForm = class(Node)cbi/simpleform
FormForm = class(SimpleForm)
AbstractSectionAbstractSection = class(Node)
SimpleSectionSimpleSection = class(AbstractSection)cbi/nullsection
TableTable = class(AbstractSection)cbi/tblsection
AbstractValueAn abstract Value TypeAbstractValue = class(Node)
ValueA one-line valueValue = class(AbstractValue)cbi/value
DummyValueThis does nothing except being thereDummyValue = class(AbstractValue)cbi/dvalue
FlagA flag being enabled or disabledFlag = class(AbstractValue)cbi/fvalue
ListValueA one-line value predefined in a listListValue = class(AbstractValue)cbi/lvalue
MultiValueMultiple delimited valuesMultiValue = class(AbstractValue)cbi/mvalue
StaticListStaticList = class(MultiValue)
DynamicListDynamicList = class(AbstractValue)cbi/dynlist
TextValueA multi-line valueTextValue = class(AbstractValue)cbi/tvalue
ButtonButton = class(AbstractValue)cbi/button
FileUploadFileUpload = class(AbstractValue)cbi/upload
FileBrowserFileBrowser = class(AbstractValue)cbi/browser
PageA simple nodePage = class(Node)

CBI常用控件用法详解

class Map (config, title, description)

这是模型的根对象。

  • config: 映射的配置文件名,请参阅UCI 文档和中的文件/etc/config
  • title:UI中显示的标题
  • description:UI中显示的描述

function :section(sectionclass, …)

创建一个新的 section。

  • sectionclass:section 对应的类对象
  • 传递给section类的构造函数的附加参数
section(TypedSection, type, title, description)
section(NamedSection, name, type, title, description)

section 对象有一些属性如下:

template: html 模板, 默认为"cbi/tsection"
addremove: 是否可以增加和删除, 默认为 false
anonymous: 是否为匿名 section, 默认为 false

Hooks

可用于在Map的生命周期中触发其他操作

  • on_cancel:用户在多步骤委托人或 SimpleForm 实例中按下取消
  • on_init: CBI 即将渲染 Map 对象
  • on_parse:CBI 即将读取接收到的 HTTP 表单值
  • on_save, on_before_save: CBI即将保存修改后的UCI配置文件
  • on_after_save: 修改后的 UCI 配置文件刚刚得到 sav
  • on_before_commit:CBI 即将提交更改
  • on_commit, on_after_commit, on_before_apply: 修改后的配置已提交,CBI 即将重启相关服务
  • on_apply, on_after_apply: 完全应用的所有更改(仅适用于具有 apply_on_parse 属性集的 Map 实例)

示例:

map = Map("config", "Title Text")

function map.on_commit(self)
    -- do something if the UCI configuration got committed
end

Sortable Tables

使用cbi/tblsection模板的 TypedSection 实例现在可以使用新属性sortable来允许用户重新排序表行,列表中会有up,down按钮。

sct = map:section(TypedSection, "name", "type", "Title Text")
sct.template = "cbi/tblsection"
sct.sortable = true

class NamedSection (name, type, title, description)

通过UCI section 的 name 选择 一个 section 对象。
实例化使用:Map:section(NamedSection, "name", "type", "title", "description")

  • name:UCI section 名称
  • type:UCI section 类型: Value、 DynamicList、 Flag、 ListValue、TextValue、MultiValue、DummyValue、StaticList、Button …
  • title:UI 中显示的标题
  • description:UI中显示的描述

function :option(optionclass, …)

创建一个新option

  • optionclass: section 对应的类对象
  • 传递给 option 类的构造函数的附加参数

function :tab(name, title, description)

将 CBI sections 分成多个tabs,以更好地组织更长的表格。

声明一个新选项卡并最多接受三个参数:

  • name: tab 的内部名称,在该 section 内必须是唯一的
  • title: tab 的标题
  • description: tab 的描述

function :taboption(tabname, type, name, title, description)

将 CBI sections 分成多个tabs,以更好地组织更长的表格。

taboption()函数包装option()选项对象并将其分配给给定的选项卡。它最多需要五个参数:

  • tabname: 分配给option的tab的名称
  • type: option类型,例如 Value 或 DynamicList
  • name: option名称
  • title: option的标题
  • description: option的描述

如果在特定section中使用tabs,则option()不得使用该功能,否则会导致未定义的行为。

示例:

sct = map:section(TypedSection, "name", "type", "Title Text")

sct:tab("general", "General Tab Title", "General Tab Description")
sct:tab("advanced", "Advanced Tab Title", "Advanced Tab Description")

opt = sct:taboption("general", Value, "optname", "Title Text")

property.addremove = false

允许用户删除和重新创建配置section。

property.dynamic = false

将此section标记为动态。动态section可以包含未定义数量的完全用户定义的option。

property.optional = true

解析可选option


class TypedSection (type, title, description)

描述一组按类型选择的 UCI sections 的对象。
实例化使用:Map:section(TypedSection, "type", "title", "description")

  • type:UCI section类型: Value、 DynamicList、 Flag、 ListValue、TextValue、MultiValue、DummyValue、StaticList、Button …
  • title:UI 中显示的标题
  • description:UI中显示的描述

function :option(optionclass, …)

创建一个新option

  • optionclass: section 对应的类对象
  • 传递给 option 类的构造函数的附加参数

function :depends(key, value)

只有在同一 section 中另一个option 的 key 设置为 value,才显示此 option 字段。 如果多次调用此函数,则这些依赖项为或的关系。

function.filter(self, section) -abstract-

可以重写此函数以过滤某些不需要被解析的sections。每个sections都会调用filter函数,要过滤掉不解析的section返回nil。其他sections需要返回第二个参数中给定的section name。

例如:

s = m:section(TypedSection, "interface", "Interfaces")
function s:filter(value)
   return value ~= "loopback" and value
end 

function :tab(name, title, description)

将 CBI sections 分成多个tabs,以更好地组织更长的表格。

声明一个新选项卡并最多接受三个参数:

  • name: tab 的内部名称,在该 section 内必须是唯一的
  • title: tab 的标题
  • description: tab 的描述

function :taboption(tabname, type, name, title, description)

将 CBI sections 分成多个tabs,以更好地组织更长的表格。

taboption()函数包装option()选项对象并将其分配给给定的选项卡。它最多需要五个参数:

  • tabname: 分配给option的tab的名称
  • type: option类型,例如 Value 或 DynamicList
  • name: option名称
  • title: option的标题
  • description: option的描述

如果在特定section中使用tabs,则option()不得使用该功能,否则会导致未定义的行为。

示例:

sct = map:section(TypedSection, "name", "type", "Title Text")

sct:tab("general", "General Tab Title", "General Tab Description")
sct:tab("advanced", "Advanced Tab Title", "Advanced Tab Description")

opt = sct:taboption("general", Value, "optname", "Title Text")

property.addremove = false

允许用户删除和重新创建配置section

property.dynamic = false

将此section标记为动态。动态section可以包含未定义数量的完全用户定义的option。

property.optional = true

解析可选option

property.anonymous = false

不显示 UCI section 名称


class Value (option, title, description)

描述 UCI 文件中某个section的 option 对象。在公式中创建标准文本字段(单行文本框)。
实例化使用:NamedSection:option(Value, "option", "title", "description")
TypedSection:option(Value, "option", "title", "description")

  • option:UCI option名称
  • title:UI 中显示的标题
  • description:UI中显示的描述

function :depends(key, value)

只有在同一 section 中另一个option 的 key 设置为 value,才显示此 option 字段。 如果多次调用此函数,则这些依赖项为或的关系。

function :value(key, value)

如果可能,将此文本字段转换为组合框并添加一个可选的option。

property.default = nil

默认值

property.maxlength = nil

值的最大输入长度(字符)

property.optional = false

将此option标记为可选,暗示.rmempty = true

property.rmempty = true

当用户输入空值时从配置文件中删除此option

property.size = nil

表单域显示的最大字符数

property.password = false

密码输入框


class ListValue (option, title, description)

描述 UCI 文件中某个section的 option 对象
在公式中创建一个列表框或单选列表(用于选择多个option之一)。
实例化使用:NamedSection:option(ListValue, "option", "title", "description")
TypedSection:option(ListValue, "option", "title", "description")

  • option:UCI option名称
  • title:UI 中显示的标题
  • description:UI中显示的描述

function :depends(key, value)

只有在同一 section 中另一个option 的 key 设置为 value,才显示此 option 字段。 如果多次调用此函数,则这些依赖项为或的关系。

function :value(key, value)

将条目添加到选择列表

property .widget =“select”

select显示选择列表,radio显示表单内的单选按钮列表

property.default = nil

默认值

property.optional = false

将此option标记为可选,暗示.rmempty = true

property.rmempty = true

当用户输入空值时从配置文件中删除此option

property.size = nil

表单域的大小


class Flag(option, title, description)

描述 UCI 文件section中具有两个可能值的option的对象。
在公式中创建一个复选框字段。
实例化使用:NamedSection:option(Flag, "option", "title", "description")
TypedSection:option(Flag, "option", "title", "description")

  • option:UCI option名称
  • title:UI 中显示的标题
  • description:UI中显示的描述

function :depends (key, value)

只有在同一 section 中另一个option 的 key 设置为 value,才显示此 option 字段。 如果多次调用此函数,则这些依赖项为或的关系。

property.default = nil

默认值

property.disabled = 0

如果未选中该复选框,则应设置的值

property.enabled = 1

复选框被选中时应设置的值

property.optional = false

将此option标记为可选,暗示.rmempty = true

property.rmempty = true

当用户输入空值时从配置文件中删除此option


class MultiValue (option, title, description)

描述 UCI 文件中某个section的 option 对象。
创建一个复选框列表或一个多选列表作为表单字段。
实例化使用:NamedSection:option(MultiValue, "option", "title", "description")
TypedSection:option(MultiValue, "option", "title", "description")

  • option:UCI option名称
  • title:UI 中显示的标题
  • description:UI中显示的描述

function :depends (key, value)

只有在同一 section 中另一个option 的 key 设置为 value,才显示此 option 字段。 如果多次调用此函数,则这些依赖项为或的关系。

function :value(key, value)

向列表中添加条目。

property .widget =“checkbox”

select显示选择列表,checkbox显示表单内的复选框列表

property.delimiter = " "

将用于分隔存储option中的值的字符串

property.default = nil

默认值

property.optional = false

将此option标记为可选,暗示.rmempty = true

property.rmempty = true

当用户输入空值时从配置文件中删除此option

property.size = nil

表单字段的大小(仅在 property 时使用.widget = "select"


class StaticList (option, title, description)

类似于MultiValue,但将选定的值存储到 UCI 列表中而不是字符分隔的option中。

config timeserver 'ntp'
    list server '0.openwrt.pool.ntp.org'
    list server '1.openwrt.pool.ntp.org'
    list server '2.openwrt.pool.ntp.org'
    list server '3.openwrt.pool.ntp.org'
  	option MultiValue '0 1 2 3' 

class DynamicList (option, title, description)

用户定义值的可扩展列表。将值存储到 UCI 列表中。
UI页面点击添加可向对应list增加条目。


class DummyValue (option, title, description)

在表单中创建一个只读文本。注意它不会向 UCI 写入数据!
实例化使用:NamedSection:option(DummyValue, "option", "title", "description")
TypedSection:option(DummyValue, "option", "title", "description")

  • option:UCI option名称
  • title:UI 中显示的标题
  • description:UI中显示的描述

function :depends (key, value)

只有在同一 section 中另一个option 的 key 设置为 value,才显示此 option 字段。 如果多次调用此函数,则这些依赖项为或的关系。


class TextValue (option, title, description)

描述非 UCI 形式的section中的多行文本框的对象。


class Button (option, title, description)

继承自Value。在非 UCI 形式的section中描述 Button 的对象。

property.inputstyle = nil

按钮样式 apply, reset,button,remove,save,find,link,reload等。

定义在对应主题的 cascade.css中:

.cbi-button-positive,
.cbi-button-fieldadd,
.cbi-button-add,
.cbi-button-save {
	border-color: #4a4;
	color: #4a4;
}

.cbi-button-neutral,
.cbi-button-download,
.cbi-button-find,
.cbi-button-link,
.cbi-button-up,
.cbi-button-down {
	color: #444;
}

.cbi-button-action,
.cbi-button-apply,
.cbi-button-reload,
.cbi-button-edit {
	border-color: #0069d6;
	color: #0069d6;
}

.cbi-button-negative,
.cbi-button-reset,
.cbi-button-remove {
	border-color: #c44;
	color: #c44;
}

其他属性:

onclick

inputtitle

CBI控件汇总示例

lua 文件中CBI控件代码

m = Map("test_file","map title" ,translate("map descrption")) -- cbi_file is the config file in /etc/config

a = m:section(TypedSection, "typedsection1_title", "typedsection1 description")  -- info is the section called info in cbi_file

a1 = a:option(Value, "Value_option_name","Value option title", translate("Value option description"));

a2 = a:option(TextValue, "TextValue_option_name","TextValue option title", "TextValue option description");

a3 = a:option(MultiValue , "MultiValue_option_name","MultiValue  option title", "MultiValue  option description");
a3:value("0", translate("value0"));
a3:value("1", translate("value1"));
a3:value("2", translate("value2"));
a3:value("3", translate("value3"));

a4 = a:option(DummyValue , "DummyValue_option_name","DummyValue option title", "DummyValue option description");

a5 = a:option(ListValue, "Listvalue_option_name","ListValue option title", "ListValue option description");
a5:value("0", translate("value0"));
a5:value("1", translate("value1"));
a5:value("2", translate("value2"));
a5:value("3", translate("value3"));

a6 = a:option(DynamicList, "DynamicList_option_name","Dynamiclist option title", "DynamicList option description");

a7 = a:option(StaticList, "StaticList_option_name","StaticList option title", "StaticList option description");
a7:value("0", translate("value0"));
a7:value("1", translate("value1"));
a7:value("2", translate("value2"));
a7:value("3", translate("value3"));

a8 = a:option(Flag, "Flag_option_name","Flag option title", "Flag option description");

a9 = a:option(Button, "Button_option_name","Button option title", "Button option description");
 
b = m:section(TypedSection, "typedsection2_title", "typedsection2 description")
b:tab("tab1", "Tab1");
b:tab("tab2", "Tab2");
b1=b:taboption("tab1", Value, "tab1_option1", "tab1 Option1");
b2=b:taboption("tab2", Value, "tab2_option2", "tab2 Option2");

return m	

UCI配置文件

config typedsection1_title 'typedsection1'
        option Value_option_name 'Value'
        option TextValue_option_name 'TextValue'
        option DummyValue_option_name 'DummyValue'
        option Listvalue_option_name '1'
        list DynamicList_option_name 'DynamicList'
        list DynamicList_option_name '123123'
        option Flag_option_name '1'
        option MultiValue_option_name '0 1 2 3'
        list StaticList_option_name '0'
        list StaticList_option_name '1'
        list StaticList_option_name '2'
        list StaticList_option_name '3'

config typedsection2_title 'typedsection2'
        option tab1_option1 '1'
        option tab2_option2 '2'

显示效果

在这里插入图片描述

数据类型验证

Datatypes

验证

服务器端验证器函数现在可以返回自定义错误消息,以便对无效输入提供更好的反馈。

opt = section:option(Value, "optname", "Title Text")

function opt.validate(self, value, section)
    if input_is_valid(value) then
        return value
    else
        return nil, "The value is invalid because ..."
    end
end

或者自定义不包含冒号的 maclist 验证

maclist = s:taboption("filter", DynamicList, "special_maclist", "MacList")
maclist.optional = true
maclist.rmempty = true
maclist.cast = "table"
maclist.placeholder = "eg. AABBCCDDEEFF"
maclist.validate = function (self, value)
    for i, val in pairs(value) do
        if val ~= "" then
            if not val:match("^[%x]+$") or #val ~= 12 then
                return nil, "The"..val.." format error!"
            end
        end
    end
    return value
end

JavaScript

LuCI 0.10 分支引入了一个新的 JavaScript 文件xhr.js,它为操作提供支持例程XMLHttpRequest<head>每个主题都必须在文档区域中包含此文件,以便表单正常工作。

它应该像这样包含:

<script type="text/javascript" src="<%=resource%>/xhr.js"></script>

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

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

相关文章

如何使用ESP32-CAM构建一个人脸识别系统

有许多人识别系统使用签名、指纹、语音、手部几何、人脸识别等来识别人&#xff0c;但除了人脸识别系统。 人脸识别系统不仅可以用于安全目的来识别公共场所的人员&#xff0c;还可以用于办公室和学校的考勤目的。 在这个项目中&#xff0c;我们将使用 ESP32-CAM 构建一个人脸识…

eclipse for abap下载及配置安装

一&#xff0c;下载eclipse &#xff0c;地址 https://www.eclipse.org/downloads/download.php?file/oomph/epp/2023-03/R/eclipse-inst-jre-win64.exe 可以选择(大连东软信息学院)端口下载&#xff0c;这样开一些&#xff0c; 二&#xff1a;双击安装&#xff0c;安装FOR…

放弃手动测试,快来了解JMeter压测神器的安装和使用吧~~

目录&#xff1a;导读 引言 jmeter的安装 JMeter是干什么的 JMeter都可以做那些测试 JMeter的使用和组件介绍 下面我们进行XML格式的实战练习 jmeter与postman的区别 JSON的插件 另附视频教程资源 引言 你是否曾经为手动测试而苦恼&#xff1f;是不是觉得手动测试太费…

Windows Java JavaFX Idea 开发环境搭建

博文目录 文章目录 JavaFX 简单说明JavaFX 版本说明JavaFX 与 JDK 的关系JavaFX 与 JDK Modular (JDK 9 模块化系统)JavaFX 模块说明 (JavaFX 20)JavaFX Scene Builder构建 JavaFX 应用程序的两种选择 环境搭建 建议先阅读下方引用的官方文档, 与本章节做相互印证与理解版本选…

Vue 3组件传值 、组件通信

本文采用<script setup />的写法&#xff0c;比options API更自由。那么我们就来说说以下七种组件通信方式&#xff1a; props emit v-model refs provide/inject eventBus vuex/pinia 举个例子 本文将使用下面的演示&#xff0c;如下图所示&#xff1a; 上图中…

【社区图书馆】《新程序员005:开源深度指南 新金融背后的科技力量》

各位CSDN的uu们你们好呀&#xff0c;今天&#xff0c;小雅兰来给大家推荐一本书&#xff0c;此书的书名为新程序员005&#xff1a;开源深度指南 & 新金融背后的科技力量&#xff0c;为什么小雅兰今天要给大家推荐这样一本书呢&#xff1f;好啦&#xff0c;现在&#xff0c;…

[python][pcl]python-pcl案例之兔子显示

兔子pcd文件下载&#xff1a;firc.lanzoux.com/iLfSgg749ab# -*- coding: utf-8 -*- # Point cloud library import pcl import pcl.pcl_visualization# Opencv # import opencv import cv2def main():# These are track bar initial settings adjusted to the given pointclou…

牛客网Verilog刷题——VL12

牛客网Verilog刷题——VL12 题目答案 题目 4bit超前进位加法器的逻辑表达式如下&#xff1a; G i G_i Gi​ A i A_i Ai​ B i B_i Bi​&#xff0c; P i P_i Pi​ A i A_i Ai​ ⊕ \oplus ⊕ B i B_i Bi​   和&#xff1a; S i S_i Si​ P i P_i Pi​ ⊕ \oplus ⊕ C i − 1…

DHCP协议详解

DHCP是什么 1.1 DHCP定义 DHCP&#xff08; Dynamic Host Configuration Protocol&#xff0c; 动态主机配置协议&#xff09;定义&#xff1a; 存在于应用层&#xff08;OSI&#xff09; 前身是BOOTP&#xff08;Bootstrap Protocol&#xff09;协议 是一个使用UDP&#xff08…

如何正确选择集体渲染(云渲染)和gpu离线渲染

在数字娱乐领域&#xff0c;渲染是制作高质量影像的关键步骤之一。随着技术的不断发展和应用的广泛普及&#xff0c;渲染方式也在不断演进。目前&#xff0c;集体渲染&#xff08;云渲染&#xff09;和GPU离线渲染是两种比较流行的渲染方式。那么&#xff0c;哪种方式会更快呢&…

一文了解什么是5G

5G是第五代移动网络。它是继1G、2G、3G、4G网络之后的新的全球无线标准。5G 支持一种新型网络&#xff0c;旨在将几乎所有人和所有事物连接在一起&#xff0c;包括机器、物体和设备。 一、前几代移动网络和5G有什么区别 第一代 – 1G 1980 年代&#xff1a;1G 传送模拟语音。…

软件测试标准升级|新版25000标准解读

广电计量 目录 收起 一、覆盖软件产品八大特性的测试依据及准则 二、信息安全测试的关键要点 三、兼容性测试的关键要点 四、功能测试的关键要点 五、性能效率测试的关键要点 六、易用性测试的关键要点 七、可靠性测试的关键要点 八、维护性测试的关键要点 九、可移植…

Linux各文件权限

参考:https://blog.csdn.net/weixin_45423515/article/details/126652740 一、切换root权限 既然root是最大的权限&#xff0c;那么这里就来了解一下如果切换到root用户。 su - //切换成root 这就是切换人的权限&#xff0c;但是大多数情况是root权限不会轻易的分给普通用户…

NIS服务

NIS 文章目录 NIS一、NIS二、简介2.1 NIS的产生2.2 什么是NIS&#xff1f; 三、NIS的相关组件3.1 服务端3.1.1 配置文件3.1.2 主要服务3.1.3 数据库相关指令 3.2 客户端3.2.1 配置文件3.2.2 主要指令 四、NIS环境4.1 NIS所需的软件包4.2 NIS Server (Master/Slave)4.3 NIS Clie…

unity3d---物体加点击事件

目录 1.给需要点击点物体加collider 2.层级面板加EventSystem 3. 相机加Physics Raycaster 4.物体单独响应点击事件 5.控制脚本实现各物体的点击事件 6.点击ui时屏蔽 物体点击事件 1.给需要点击点物体加collider 2.层级面板加EventSystem 3. 相机加Physics Raycaster 2d…

机器学习 Rider数据集分析和预测

介绍数据集 ride_id&#xff1a;乘车ID rideable_type&#xff1a;乘车类型 started_at&#xff1a;开始日期 ended_at &#xff1a;结束日期 start_station_name&#xff1a;开始站的名字 start_station_id&#xff1a;开始站的ID end_station_name&#xff1a;结束站的名字 …

魔百和UNT403G 国科芯片2+8 安卓9.0 免拆机纯净线刷包

固件特点&#xff1a; 1、本固件在UNT403G 盒子上测试可用&#xff0c; 其它盒子请慎 重使用&#xff1b; 2、支持原装遥控器&#xff0c;语音蓝牙遥控器&#xff1b; 3、固件压缩包有刷机教程&#xff0c;请一定仔细阅读。 4、刷机后三网通用&#xff0c;可自由安装应用&#…

NewBing 边栏快捷插件没有了!如何解决?如何脱离浏览器使用 New Bing?

作者&#xff1a;明明如月学长&#xff0c; CSDN 博客专家&#xff0c;蚂蚁集团高级 Java 工程师&#xff0c;《性能优化方法论》作者、《解锁大厂思维&#xff1a;剖析《阿里巴巴Java开发手册》》、《再学经典&#xff1a;《EffectiveJava》独家解析》专栏作者。 热门文章推荐…

【移动端网页布局】流式布局 ① ( 流式布局简介 | 百分比布局 / 非固定像素布局 | 根据屏幕尺寸 / 设备类型自动调整网页布局 )

文章目录 一、流式布局简介二、流式布局代码示例 一、流式布局简介 流式布局 又称为 百分比布局 / 非固定像素布局 ; 为 流式布局 中 盒子模型 设置 百分比宽度 , 其大小可以根据屏幕宽度自适应伸缩 , 该盒子没有像素限制 , 内容自动向左右两边填充 ; 流式布局 可以 根据 设备…

蓝库云|究竟什么是ERP?它对企业有什么重要性作用呢

一、什么是ERP ERP全称为Enterprise Resource Planning&#xff0c;即企业资源计划&#xff0c;是一种运用信息技术手段来集成管理企业内部所有资源&#xff0c;协调各项业务、机构、流程和人员&#xff0c;实现高效、协同、合规经营的商业管理软件。ERP系统包括销售、采购、物…