PasteForm最佳CRUD实践,实际案例PasteTemplate详解(一)

news/2024/9/24 22:07:28/文章来源:https://www.cnblogs.com/pastespider/p/18430156

本文将介绍soft.pastecode.cn出品的PasteForm,PasteForm是贴代码使用Dto思想实现的CRUD的一个组件,或者说输出一个思想!
为啥我觉得是最佳的CRUD呢?先结合你的实际项目解答下以下问题:

1.如果有一个系统,有100个表,你的管理端需要多少页面?别和我说100个表很多,需求复杂点的随随便便上100个数据库表的!

2.新的需求下来了,说XX表要新增一个字段,默认为100,新增的时候输入,不支持修改,作为你目前的管理端你需要几个步骤来实现?关键点你如何做版本过渡的问题?

3.做开发的都是到,表和表之间一般是有关系的,虽然不一定会建立外表链,比如BindUserGrade的表中的UserId一般就是表示UserInfo表的Id,这就牵扯到录入,更新,和显示的问题了,其实我们希望看到的是显示UserInfo中的UserName而不是干巴巴的一个UserId对吧!

4.一个表我们在管理端的时候一般会涉及到数据的列表显示,比较常用的就是table表格对吧,对应的有新增,编辑,查看,删除,那作为管理端你如何控制他们的权限?权限往往涉及2大块,a.前端页面的显示否,b.后端接口中的权限判定

... .. .

让我们一起来看下PasteForm的案例项目PasteTemplate是如何处理以上问题的!

案例代码 https://gitee.com/pastecode/paste-template/tree/master/example/PasteTemplate
从上面下载代码后,直接启动,然后,应该是localhost:22222端口 http://localhost:22222/page/index.html

登陆页面

image
登陆页面没什么好说的,因为不涉及找回密码,注册等,只有图形验证码和登陆

管理端

image
登陆后,看到如上图
左侧菜单采用动态的模式,菜单由权限读取,系统在首次启动的时候会把默认的菜单写入到数据库,如果当前账号有root-root的权限,则会返回所有的菜单,也就是root-root表示超级权限的意思,拥有系统的所有权限!
由于其他表的信息比较简单,我就从测试表的数据来举例子
image

页面组成

PasteForm的整个体系其实只有4个页面,
1.上图的index.html页面,作为管理端的菜单页面
2.右侧区域的数据表格table显示和他上方的搜索区域组成的pasteform/index.html页面
3.对应的表的编辑和新增页面,新增和编辑是同一个页面,这里命名为pasteform/view.html,也就是form表单页面
4.有些时候表的数据多大,我们不希望在table中全部显示,比如博文的正文,这就需要有一个页面查看详细的,pasteform/detail.html

index.html

管理端的主页面,大概是左右布局,100%绝对定位,是为了满足右侧子页面的flex布局,主要点是左侧的tree,内容是从API读取的,也就是不同账号登陆后看到的菜单是不一样的,具体的看角色对应的菜单(权限)

pasteform/index.html

image
如上图,你看到的内容,可以说整个页面都是后端的Dto控制的
1.比如搜索区域有多少个搜索项,搜索项的交互(daterange,date,outer,select,selects,word等)
2.中间区域的表格,包含了新增,编辑,删除,详情的基本4个菜单,然后就是自定义的一些按钮,比如上图的 添加子集!
3.然后是表格区域内的排序,注意看表格header中的ID 排序 层级 其实哪些字段支持排序,在后端的Dto中也就一行代码的事情!
4.表格中的一些交互,比如上图的switch,点击后是可以直接修改的,操作后会和后端API进行交互,如果返回非200则会重置状态
5.按钮区域的提交按钮,有些时候表格的按钮需要条件判断,那也是支持的,比如age>18的显示按钮1,age<12的显示按钮2等!
6.表格的自定义显示,有时候我们希望一个表格显示多个字段,比如换行啥的,也是可以实现的

pasteform/view.html

表单主页面,作为新增或者编辑的页面,支持几乎常见的录入
1.基础录入包括默认值等,比如text,number,switch,select等
image

2.也支持特殊的格式,比如daterange,richtext,textarea,selects,image,file等
image

3.高级支持,外表输入,比如选择其他表的一个对象作为这个表单的一个录入
image
点击父级后面的输入框,是弹出一个页面,选择一个对象,作为这个输入框的值,值一般包含2个,一个是id,一个是显示的
image

4.高级支持,参数输入,比如权限列表中的添加子集,那么打开的应该是添加页面,这个时候父级是不要输入的,由url参数传递过去
image

还有更多的功能等你发觉,上面说得一大堆功能,其实都是Dto中配置的
啥叫Dto?
接触过ABPvNext的应该比较数据,其实就是不同的Model,比如UserInfo这个表,一般会创建对应的4个Dto
UserInfoAddDto:作为UserInfo新增的数据模型
UserInfoUpdateDto:作为UserInfo的编辑的数据模型
UserInfoDto:一般作为详细显示的数据模型
UserInfoListDto:一般作为表格,列表的数据展示用
这几个模型可以配置互转,就是使用AutoMapper!

为了实现更加灵活的CRUD,我们只需要在对应的Dto中的字段上添加对应的属性即可,由于需求比较特殊,我定义了一个属性

    /// <summary>/// 前端用数据类型 /// </summary>[AttributeUsage(AttributeTargets.Property | AttributeTargets.Class, AllowMultiple = true)]public class ColumnDataTypeAttribute : Attribute{/// <summary>/// image region navigator select selects dateplan datetime等/// </summary>public string Name { get; set; } = "";/// <summary>/// /// </summary>public string Args1 { get; set; } = "";/// <summary>/// /// </summary>public string Args2 { get; set; } = "";/// <summary>/// 参数3/// </summary>public string Args3 { get; set; } = "";/// <summary>/// 参数4/// </summary>public string Args4 { get; set; } = "";/// <summary>/// /// </summary>public string ErrorMessage { get; set; } = "";/// <summary>/// 按照要求文档填写参数/// </summary>/// <param name="name"></param>/// <param name="args1"></param>/// <param name="args2"></param>/// <param name="args3"></param>/// <param name="args4"></param>/// <param name="ErrorMessage"></param>public ColumnDataTypeAttribute(string name = "", string args1 = "", string args2 = "", string args3 = "", string args4 = "", string ErrorMessage = ""){this.Name = name;this.Args3 = args3;this.Args1 = args1;this.Args2 = args2;this.Args4 = args4;this.ErrorMessage = ErrorMessage;}/// <summary>/// /// </summary>/// <returns></returns>public override string ToString(){return string.Format("{0}-{1}-{2}-{3}-{4}", Name, Args1, Args2, Args3, Args4);}}

然后是在需要限定的字段添加这个或者多个这个属性,比如

    ///<summary>///测试表 用于测试CURD的表///</summary>public class TestTableAddDto{///<summary>///姓名 模拟短文本输入///</summary>[MaxLength(32)][Required][PasteMark("test", "name")]public string Name { get; set; }///<summary>///头像 模拟图片上传///</summary>[MaxLength(128)][PasteMark("test", "head")][ColumnDataType("image", "1", "head", "60*60")]public string Head { get; set; }///<summary>///年龄 模拟输入number///</summary>[Range(5, 90, ErrorMessage = "年龄必须限定在5~90之间!")]public int Age { get; set; }///<summary>///文本区域 模拟文本区域的输入///</summary>[MaxLength(128)]public string Desc { get; set; }///<summary>///富文本 模拟富文本,前端HTML的是使用wangEditv5///</summary>public string Blog { get; set; }///<summary>///加入日期 模拟必填时间的输入///</summary>public DateTime JoinDate { get; set; }/// <summary>/// 文件/// </summary>[ColumnDataType("file", "/api/app/Upload/UpImage?type=file")]public string Fpath { get; set; } = "";///<summary>///单选 一般表示状态,内定的,有点像Enum,关于Enum后续会支持///</summary>[ColumnDataType("mark", "test", "datetype")][ColumnDataType("select", "[{\"name\":\"日类型\",\"value\":0},{\"name\":\"月类型\",\"value\":1},{\"name\":\"年类型\",\"value\":2}]")]public int DateType { get; set; }/// <summary>/// 复选 多个之间用逗号隔开/// </summary>[ColumnDataType("selects", "[{\"name\":\"日类型\",\"value\":\"day\"},{\"name\":\"月类型\",\"value\":\"month\"},{\"name\":\"年类型\",\"value\":\"year\"}]", ",")]public string TypeStrs { get; set; }/// <summary>/// 复选数组/// </summary>[ColumnDataType("selects", "[{\"name\":\"日类型\",\"value\":\"day\"},{\"name\":\"月类型\",\"value\":\"month\"},{\"name\":\"年类型\",\"value\":\"year\"}]")]public string[] Types { get; set; }///<summary>///角色ID 这里一般用于外表,就是选择其他表的一个数据作为输入内容///</summary>[ColumnDataType("outer", "gradeInfo", "", "id", "name")]public int GradeId { get; set; }///<summary>///成绩 模拟前端限定2位小数///</summary>public double Score { get; set; }/// <summary>/// 字符串多图/// </summary>[ColumnDataType("image", "3", "img", "60*60")]public string Img2 { get; set; }/// <summary>/// 数组图片/// </summary>[ColumnDataType("image", "3", "img", "60*60")]public string[] Img3 { get; set; }/// <summary>/// 会员周期 会员生效区间/// </summary>[ColumnDataType("daterange", "dateStart", "dateEnd")]public DateTime DateStart { get; set; } = DateTime.Parse("2024-09-01 00:00:00");/// <summary>/// 会员周期 会员生效区间/// </summary>[ColumnDataType("hidden")]public DateTime DateEnd { get; set; } = DateTime.Parse("2024-10-01 00:00:00");}

看上面的是测试表的Dto的属性的写法,由于配置ColumnDataType属性有多个参数,为了防止写错,你也可以自定义,然后继承于ColumnDataType就行了,比如我的

 /// <summary>/// /// </summary>public class PasteMarkAttribute : ColumnDataTypeAttribute{/// <summary>/// 书签属性/// </summary>/// <param name="_model">书签模块,示例product</param>/// <param name="_value">书签项,示例code</param>public PasteMarkAttribute(string _model, string _value){base.Name = "mark";base.Args1 = _model;base.Args2 = _value;}}/// <summary>/// 日期区间/// </summary>public class PasteDaterangeAttribute : ColumnDataTypeAttribute{/// <summary>/// 日期区间/// </summary>/// <param name="_sdate">开始日期字段</param>/// <param name="_edate">结束日期字段</param>public PasteDaterangeAttribute(string _sdate="sdate",string _edate="edate"){base.Name = "daterange";base.Args1 = _sdate;base.Args2 = _edate;}}/// <summary>/// /// </summary>public class PasteLeftAttribute : ColumnDataTypeAttribute{/// <summary>/// /// </summary>public PasteLeftAttribute(){base.Name = "class";base.Args1 = "fleft";}}/// <summary>/// /// </summary>public class PasteSwitchAttribute : ColumnDataTypeAttribute{/// <summary>/// /// </summary>public PasteSwitchAttribute(){base.Name = "switch";}}/// <summary>/// 同hidden 表示在UI中隐藏这个对象/// </summary>public class PasteHiddenAttribute : ColumnDataTypeAttribute{/// <summary>/// /// </summary>public PasteHiddenAttribute(){base.Name = "hidden";}}/// <summary>/// 配置菜单或者是条件菜单/// </summary>public class PasteMenuAttribute : ColumnDataTypeAttribute{/// <summary>/// /// </summary>/// <param name="_name"></param>/// <param name="_script"></param>/// <param name="_iconfont"></param>/// <param name="_box"></param>public PasteMenuAttribute(string _name, string _script, string _iconfont = "", bool _box = false){base.Name = "menu";base.Args1 = _name;base.Args2 = _script;base.Args3 = _iconfont;if (_box){base.Args4 = "box";}}}/// <summary>/// 配置菜单或者是条件菜单/// </summary>public class PasteIfMenuAttribute : ColumnDataTypeAttribute{//[ColumnDataType("ifmenu", "item.isReady", "<a href=\"javascript:;\" title=\"如果之前创建失败,修改信息后,可以重置,重置后可以重新创建\" onclick=\"global_store_reset_state({{:=item.id}});\"><i class=\"Hui-iconfont Hui-iconfont-xiangpicha\">重置状态</i></a>", "", "")]/// <summary>/// 条件按钮/// </summary>/// <param name="_expresion"></param>/// <param name="_insertHtml"></param>/// <param name="_box">是否在按钮盒子中</param>public PasteIfMenuAttribute(string _expresion, string _insertHtml, bool _box = false){base.Name = "ifmenu";base.Args1 = _expresion;base.Args2 = _insertHtml;//base.Args3 = _iconfont;if (_box){base.Args3 = "box";}}}/// <summary>/// 用于表格中,显示另外一个字段的某一个值的表达式/// </summary>public class PasteOuterDisplayAttribute : ColumnDataTypeAttribute{/// <summary>/// 表格中用于显示某一个字段/// </summary>/// <param name="_expression">示例extendService?.name || ''</param>public PasteOuterDisplayAttribute(string _expression){base.Name = "outerdisplay";//base.Args1 = _cloumnName;base.Args2 = _expression;}}/// <summary>/// /// </summary>public class PasteDisableAttribute : ColumnDataTypeAttribute{/// <summary>/// /// </summary>/// <param name="_unadd">禁用新增</param>/// <param name="_unedit">禁用编辑</param>/// <param name="_undel">禁用删除</param>public PasteDisableAttribute(bool _unadd = false, bool _unedit = false, bool _undel = false){base.Name = "disable";if (_unadd){base.Args1 = "add";}if (_unedit){base.Args2 = "edit";}if (_undel){base.Args3 = "del";}}}/// <summary>/// 单位属性 为计量添加单位/// </summary>public class PasteUnitAttribute : ColumnDataTypeAttribute{/// <summary>/// Unit的属性/// </summary>/// <param name="_unit">示例元</param>public PasteUnitAttribute(string _unit){base.Name = "unit";base.Args1 = _unit;}}/// <summary>/// Select的属性/// </summary>public class PasteSelectAttribute : ColumnDataTypeAttribute{/// <summary>/// Select的属性/// </summary>/// <param name="_selectvalues">示例[{name,value,selected}]</param>public PasteSelectAttribute(string _selectvalues){base.Name = "select";base.Args1 = _selectvalues;}}/// <summary>/// Selects的属性 可以多选的/// </summary>public class PasteSelectsAttribute : ColumnDataTypeAttribute{/// <summary>/// Selects的属性/// </summary>/// <param name="_selectvalues">示例[{name,value,selected}]</param>public PasteSelectsAttribute(string _selectvalues){base.Name = "selects";base.Args1 = _selectvalues;}}/// <summary>/// Image的属性/// </summary>public class PasteImageAttribute : ColumnDataTypeAttribute{/// <summary>/// Image的属性/// </summary>/// <param name="_num">可以传多少张</param>/// <param name="_path">存放的路径</param>/// <param name="_size">转化的大小,示例60*60,1920*0</param>public PasteImageAttribute(int _num = 1, string _path = "", string _size = ""){base.Name = "image";base.Args1 = _num.ToString();base.Args2 = _path;base.Args3 = _size;}}/// <summary>/// /// </summary>public class PasteOuterAttribute : ColumnDataTypeAttribute{/// <summary>/// 链接外表显示和输入用/// </summary>/// <param name="className">外表名称,示例serviceInfo</param>/// <param name="extendName">显示的时候的表达式,示例extendService.name || ''</param>/// <param name="_keyColumn">回传的列的名称,示例id</param>/// <param name="_showColumn">显示的列表的名称,示例name</param>public PasteOuterAttribute(string className, string extendName = "", string _keyColumn = "id", string _showColumn = "name"){base.Name = "outer";base.Args1 = className;base.Args2 = extendName;base.Args3 = _keyColumn;base.Args4 = _showColumn;}}

案例有了,那么每个name是干嘛用的?

ColumnDataTypeAttribute

ColumnDataType的配置说明

image

相对于后面的 head 来说,这里是大图模式,在ListDto中表示使用图片的模式渲染

字段 类型 示例 说明
args1 数字 1 图片数量
args2 字符 cate 存放在什么位置,上传图片的时候会附带到参数type中
args3 字符 60*60 图片是否需要压缩,压缩的宽高,不压缩的设置为0,比如60*0
args4 字符 small small,normal,big表示图片的大小三个规格,默认normal,如果要返回格式,则由dataFrom决定

head 弃用,使用image

使用方式同 image 这里表示的是小图标模式

字段 类型 示例 说明
args1 数字 1 图片数量
args2 字符 cate 存放在什么位置,上传图片的时候会附带到参数type中
args3 字符 60*60 图片是否需要压缩,压缩的宽高,不压缩的设置为0,比如60*0
args4 字符 arr或str 默认值str对应字段的类型,是array类型还是string类型,如果是string类型多个之间用,隔开

file

其实可以使用image的接口,他们2个的返回格式都是一样的,wangEditor的返回格式,主要是UI上不一样,毕竟文件没法预览

字段 类型 示例 说明
args1 字符 /api/app/Upload/UpImage 表示上传的路径,默认是/api/app/Upload/UpFile,你也可以自己修改他

region

小程序中的地区选择,可以配置精确度,到区还是到县

字段 类型 示例 说明
args1 字符 region 表示地址选择的层级,可选region和sub-district
args2 字符 str 可用值str或者arr 表示返回的数据类型,str的时候用,隔开

outer

表示一个值需要从外表获取,编辑的时候如何显示? 比如fatherId,extendRole

字段 类型 示例 说明
args1 字符 cateInfo 外表的名称,对应模板的path,或者路径,路径一定附带了/字符示例./abc.html
args2 字符 extendCates 表示显示的数据,需要和下面2个配合,是一个当前的扩展,目标数组要配置hidden
args3 字符 id 获取返回对象的属性,一般为id
args4 字符 name id的友好名称显示,这里指的是外表,比如cateId,需要打开catelist页面,选择后,返回cate,则name作为友好显示,id作为实际值

outers

outer的复数版本,表示可以从外部列表中选择多个,比如在创建账号的时候给他绑定多个角色,就用这个!

字段 类型 示例 说明
args1 字符 cateInfo 外表的名称,对应模板的path,或者路径,路径一定附带了/字符示例./abc.html
args2 字符 extendCates 表示显示的数据,需要和下面2个配合,是一个数组,目标数组要配置hidden
args3 字符 id 获取返回对象的属性,一般为id
args4 字符 name id的友好名称显示,这里指的是外表,比如cateId,需要打开catelist页面,选择后,返回cate,则name作为友好显示,id作为实际值

outerdisplay

ListDto中用于外表的显示,比如有字段cateInfoId,对应的ExtendCateInfo要标记为outerdisplay,args2配置为extendCateInfo?.name || '',否则会显示为[object object]

字段 类型 示例 说明
args1 字符 cateInfoId 表示这个字段的值,一般不显示
args2 字符 extendCateInfo?.name || '' 表示显示的名称,友好名称,需要后端支持,在前端会处理成.display

表示这个值需要使用页面从另外一个列表中获取,这里表示小程序端的,建议使用outer outerdisplay

字段 类型 示例 说明
args1 字符 cate.name || '' 表示显示cate.name或者空这个一般用于ListDto中
args2 字符 cateInfo 外表的名称,对应模板的path,可以为空
args3 字符 /pages/cate/index/?model=select 如果对应的表不用模板,则直接表示路径

datetime

默认的yyyy-MM-dd HH:mm:ss的格式

字段 类型 示例 说明
args1 字符 yyyy-MM-dd HH:mm:ss 表示时间使用的格式

hidden

表示隐藏这个字段,一般是主键ID,或者外表链接过来的会这配置,比如需要给cate添加子项,则添加由cate那边过来
这个也适用于ListDto

字段 类型 示例 说明
args1 字符 bind 如果不填表示隐藏,如果填写了表示页面的query中model=xxx的时候不隐藏,表示非xxx的时候隐藏,xxx的时候不隐藏

password

密码框模式

query

如果从query中获取到了数据,则对应的字段隐藏,注意不要配置hidden,因为查询的时候是从表单读取数据的,hidden的话是不写入到form中的,那样查询就没法获取query来的值了

字段 类型 示例 说明
args1 字符 cateid 表示使用url中的哪个参数读取值

readyonly

表示这个字段是只读的,一般是编辑的时候生效

richtext

如果是字符串,没有设置maxlength,默认就会变更成richtext,也可以手动强制配置

textarea

如果是字符串,设置maxlength,且设置的值大于128,默认就会变更成textarea,也可以手动强制配置

text

对于一些长度过长的,会被判定为textarea,或者richtext的可以使用这个强制换行成text

fentoyuan

这个是指后台单位为分,又需要前端进行元输入的,注意小数位数为2位小数,也就是分的格式为int

select

表示单选,比如权限类型,一般是指固定类型的,一般不修改的那种情况,也可以表示状态等

字段 类型 示例 说明
args1 字符 [{"name":"大","value":"1"},{"name":"小","value":"2"}] 表示单选的可选值,name是显示 value是值
args2 字符 表示值得类型,这里是单个,跟随主类型走

selects

表示多选,这个表示的是页面上的多选,需要列表显示,然后是可以多选!关键在于最后读取数据的时候,需要判断是什么格式的!

字段 类型 示例 说明
args1 字符 [{"name":"大","value":"1"},{"name":"小","value":"2"}] 表示单选的可选值,name是显示 value是值
args2 字符 , 如果值类型不是数组,则返回字符串,用这个字符拼接,也就是分割字符

sort

表示排序,表示字段的顺序,一般表格比较会使用这个

字段 类型 示例 说明
args1 数字 0 小的排在前面,默认为0

这个用于表格显示,一般表示用于显示外表的数据,这个将弃用,使用outerdisplay替换

字段 类型 示例 说明
args1 字符 extendCate.name 显示的外表链接,示例extendCate?.name || ''表示显示cate.name或者空这个一般用于ListDto中

width

表示这个字段在表格得宽度,可以为*或者对应得数字,是表格得列的宽度的权重,这个适用于ListDto

字段 类型 示例 说明
args1 字符 60 表示这个列的宽度,可以为数字也可以是*比如3*这样

orderby

表示基于哪个字段进行排序,这个一般是ListDto表示表格中,可以基于哪个字段进行排序查询

字段 类型 示例 说明
args1 字符 id 表示使用id正序排序
args2 字符 id desc 表示使用倒叙排序

datalist

前端表示使用datalist作为选择数据源,前端需要把datalist的id赋值给datalistid,默认为字段name,这个规则适用于表单和QueryDto

字段 类型 示例 说明
args1 字符 [{"name":"正常","value":"1","selected":true}] JSON的字符串,也可以为空
args2 字符 data_pro 表示调用哪个datalist数据,表示datalist的id,和args1互斥
args3 字符 read_pro_datalist() 表示需要使用eval执行哪个函数,一般和args2配合使用,和args1互斥

daterange

主字段需要设置为daterange,其他字段需要设置hidden,在最后组合数据的时候,会基于参数生成对应的,应该要设置为可null格式

字段 类型 示例 说明
args1 字符 sdate 表示开始时间,最后会传送yyyy-MM-dd 00:00:00的格式数据
args2 字符 edate 表示结束时间,如果你选择2024-08-31,最后上送的会是2024-08-31 00:00:00
args3 字符 yyyy-MM-dd 00:00:00 表示时间的格式化,默认使用yyyy-MM-dd 00:00:00

disable

特殊限定,限定于class的,表示禁用这个模型的哪些功能,这个一般用于ListDto,因为这些功能都在列表页面

字段 类型 示例 说明
args1 字符 add 表示忽略新增,也就是不显示新增按钮
args2 字符 edit 表示忽略编辑,表示列表中没有编辑的这个选项,有些数据只能看,不需要新增和编辑
args3 字符 del 表示这个表没有删除,页面UI中不需要删除按钮

用于列表后面的菜单 比如<a href="javascript:;" onclick="args2"><i class="Hui-iconfont args3">\args1

字段 类型 示例 说明
args1 字符 编辑 按钮的名称
args2 字符 open_view(<%:=item.id%>); onclick事件的代码
args3 字符 Hui-iconfont-menu 样式名称
args4 字符 box 默认不写,如果写box表示要方入到menubox中

ifmenu

基于条件模式的菜单,使用于Listdto中
示例: [ColumnDataType("ifmenu", "item.age==8", "<a href="javascript:;" onclick="open_window(222,./index.html?path=userInfo&goid={{:=item.id}})">条件2", "box")]
数据对象就是item表示当前这行数据

字段 类型 示例 说明
args1 字符 isReady == true if的表达式中()内的内容
args2 字符 <a hreaf="javascript:;" onclick="open({{:=id}})"> 这里填写条件后的菜单代码,注意引用需要使用{
args3 字符 box 默认不写,如果写box表示要方入到menubox中

htmltemplate

已抛弃,使用下方的html替代,如果要显示自定义的表格,则使用这个,表示直接显示信息模板注意里面的带参使用{{:=item.name}}这样的形式

字段 类型 示例 说明
args1 字符
{{:=item.name}}{{:=item.desc}}
需要在td中显示的html代码,支持模板的写法

html

如果要显示自定义的表格,则使用这个,表示直接显示信息模板注意里面的带参使用{{:=item.name}}这样的形式

字段 类型 示例 说明
args1 字符
{{:=item.name}}{{:=item.desc}}
需要在td中显示的html代码,支持模板的写法

linkquery

表示把某些参数穿透给子页面,比如服务->文件,则可以在服务A页的时候查看文件列表B页,在文件列表中可以直接新增文件C页,这个时候我们希望对应的服务ID直接由参数传入
也就是在打开C的时候,希望把B的参数传递给C,注意这个linkquery是放在ListDto中的Class上的,也就是和disable一样

字段 类型 示例 说明
args1 字符 需要传递的参数 多个之间用,隔开,比如serviceid,ftype

object

适用于表单页面,表示从另外一个表单新增数据,比如用户的收货地址,在表单的时候,打开一个新的表单,进行信息填写后,返回一个obj,这个时候是没有写入数据库的,所以在返回的时候需要显示
和outer有点像,不过回传的是一个object类型!如果是编辑的时候?需不需要上传到API表示编辑了?打开表单的时候会传递model=object这个参数过去,表示叫子表单不要做API入库操作
注意这个子模型也是需要建立对应的API的,不过不需要建立新增和编辑的接口,因为被上一级涵盖了!

字段 类型 示例 说明
args1 字符 roleInfo 一般使用path也可以使用页面的路径
args2 字符 id 新增的时候无用,主要是编辑的时候,基于这个id和path去数据库查询新的数据
args3 字符 name 表示显示的是这个object的哪个字段,一般在编辑的时候可见

objects

object的复数版本,表示一个集合,比如一个会员有多个爱好,新增的时候,打开子表单,填写多个爱好的object信息体返回,在显示的时候,如果一个字段不足以显示???是否支持多个字段联动显示?

字段 类型 示例 说明
args1 字符 roleInfo 一般使用path也可以使用页面的路径
args2 字符 id 新增的时候无效,编辑的时候表示从数据库查询信息,也作为删除的key使用
args3 字符 name 表示显示的是这个object的哪个字段,一般在编辑的时候可见

mark

字段详细说明,或者是文档,这里是做一个描点,需要使用公共函数自己实现具体的要求,一般的是项目下面的模块的某一个字段的说明,一个项目往往这个是一样的,然后就是哪个模块的哪个字段,所以有2个字段
会在title后面生成一个span class="tapmark" onclick="global_tap_mark(_modek,_code)";

字段 类型 示例 说明
args1 字符 product 一般作为模块使用,比如商品的这个模块
args2 字符 code 模块下的一个字段的说明,比如code这个字段的用法,案例说明等

template

作为有些表的特殊布局,就是自定义布局表格部分的内容,包括表头和表身2个部分,注意需要实现选择的功能,除非这个表用不到选择这个功能
文件存放于pasteform/template.html,就只有一个template.html页面,里面的都是模板代码

字段 类型 示例 说明
args1 字符 template_user_head 表格的表头部分的script的id
args2 字符 template_user_body 表格的表身部分的模板的script的id

style

针对一些特殊的设定,比如textarea,有些地方我们要设置高一些

字段 类型 示例 说明
args1 字符 height:500px; 就是style里面的内容

class

针对一些自定义的class,可以通过这个来配置

字段 类型 示例 说明
args1 字符 btngo 表示这个对象要添加的class

button

用于表单中,的按钮,用意是让用户点击后触发函数,global_form_button_click(this,className,name);
注意按钮的value为当前字段的value,比如当前页面的path=nginxRoute

        /// <summary>/// Http模板 表示使用Http模式的模板的内容/// </summary>[ColumnDataType("button")]public string Temp1 { get; set; } = "点击导入";

则上面会生成的页面内容为

Http模板:点击导入

点击导入点击后,会调用global_form_button_click(this,'nginxRoute','temp1');
注意由于返回的首单次会小写,所以是temp1而不是Temp1

unit

用于显示单位,比如MB,KG,个等,一般在Int Long Double等Number地方后显示,也可以作为表格中显示?

字段 类型 示例 说明
args1 字符 MB 表示这个对象的单位

待处理

1.列表中可编辑的对象 比如switch?
handler_switch_change(elc){
// className columnName id state
}

2.外表选择的时候,是否支持多选模式?
多选模式的时候,如何加载已经选中的,已经选中的如何删除?难不成要搞一个选定区域?

3.Int32[] Int64[] String[]
这种数据的显示和最后更新

4.表单数据的提交前的数据格式的校验!

5.daterange如何设定
单个变成多个!

6.有些数据不需要新增,和编辑 ,虽然可以使用API控制,但是在前端有这么个按钮存在,也是很突兀的,所以得处理

7.管理员拥有多个角色,这个多个角色的显示和编辑问题!
selects 可以设定返回多个
list设定显示的方式 关键在于如何每次编辑的时候不是覆盖!还是写一个单个删除的接口?

8.enum类型的显示问题?其实就是enmu变种到attribute的select!!!

9.从角色绑定权限来说,角色列表,点击权限(给这个角色绑定权限),打开的权限列表是所有的,需要绑定的勾选,不要的取消勾选
model=bind 则有一些字段这个模式下才显示
hidden.args1表示某一个模式,如果为空表示都隐藏

待确认问题

1.必填,如果是int的类型的,是不是只能非0,还是不生效?

2.对于menu的支持,参数因该是{{}}控制的,而不是<%%>

3.enum类型的返回,是返回值,还是对应的名称?是否支持enum转select?

4.有时候表单只是为了新增一个数据,不入库那种!outform model=outform 返回组合的 ...待定

5.比如查看某一个列表--子项列表--子项添加
linkquery cateid,abcid

6.单位转化,比如后台是分,前端需要输入元 那么就是在输入的时候是元,显示是元 提交的时候是分!!!
fentoyuan 分转元 默认2位小数点

7.关于是否需要显示详情页面的问题,因为有时候表格数据是显示不全的,比如richtext,这个时候可能需要一个detail.html页面
如果要呈现,则需要对应的模型Dto的属性,生成器默认是去除的,则需要自己在Domain中添加/template/dto.html作为生成模型替换生成器默认的模型!
页面的呈现上和表单类型,把输入框等渲染成直接显示的即可!
然后再由ListDto中,添加菜单detail的支持!

8.在列表页面中,如果一个对象被标记为query,如果从参数中获取到了值,则这个查询项进行隐藏操作

9.如果列表页面的当前状态为model,则上方的搜索区域默认隐藏

10.关于引入字段说明的事情,比如一个表单100个字段,各个字段表示什么意思,一般的做法是点击对应的?然后弹出或者是跳转到某一个站点,显示这个介绍
mark由此而来

11.是否加入自模型,就是表格数据展示的样式,是否引入自定义的模板???
默认是使用内置的二次模板,如果是引用外部的化,则需要整个,也就是表头和表身都需要!
需要外部写一个html的template页面,然后使用Jquery的load加载进去!
在ListDto中,使用template进行标注,标注args1为表头样式的模板 args2为表身部分的内容

12.添加对自定义样式的支持 style class

13.添加对menubox的支持,针对很多按钮的情况

14.表单中需要特意操作的,添加函数支持 把表单的数据传递过去 由自定义函数决定执行结果!global_form_action(elc,className,name,location.search);
项目路由中的 载入模板 模板测试等!

15.搞一个占位的?有时候的排版等,需要空开一个位置

16.可以搞一个属性继承于基础属性,这样在输入的时候会好些,比如PasteMarkAttribute:ColumnDataTypeAttribute;

17.窗口的弹出大小问题,有些情况需要大的 有些情况小的 有些情况要动态的!

18.查询的select和表格的select冲突的问题!!!

19.表格的不同模式下,不同字段的显示问题!

篇幅有限,下章讲接收后端的API如何编写,然后是如何使用代码生成器实现这个CRUD

有问题的,欢迎评论区提问,我会一一回答

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

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

相关文章

RTE大会报名丨 重塑语音交互:音频技术和 Voice AI,RTE2024 技术专场第一弹!

Voice AI 实现 human-like 的最后一步是什么?AI 视频爆炸增长,新一代编解码技术将面临何种挑战?当大模型进化到实时多模态,又将诞生什么样的新场景和玩法?所有 AI Infra 都在探寻规格和性能的最佳平衡,如何构建高可用的云边端协同架构?AI 加持下,空间计算和新硬件也迎来…

彻底搞懂回溯算法

1.回溯算法的核心思想 回溯算法的核心思想是:尝试+记录+回退。 先尝试一种选项,在选择该选项的前提下继续寻解,如果最后寻解成功,则记录这个解,否则不用记录,然后再回退到选择该选项前的状态,改为尝试其它选项再继续寻解,判断其它选项是不是解。 2.回溯算法的关键点 回溯…

9.23 ~ 9.29

集训9.23 集训第一天。 早晨因为太多人没拿早读资料被老登 D 了。 不是哥们你不早说 现在我上哪给你找资料去 😅 上午模拟赛。 发现 T1 的图挂了,于是看形式化题意;初始有一张 \(n\) 个点的完全图,接着删除 \(m\) 条边。 询问有多少长度为 \(13\) 的序列 \(p_1,...,p_{13}…

CSP 集训记录

用来整理模拟赛等9.23 csp-3【noip23 ZR二十连测 DAY10】 保龄. A.奇观 狗市题目描述。不是这题意太大歧义了吧,我讨厌的第二种出题人——题意描述相当不清。CTH:13 座城市又不代表是 13 座不同的城市。直接看形式化题目的话(如果能看懂要干什么)那这题确实不难。 解: 容易…

判断系统大小端字节序的方法

1、字节序 1.1、大端字节序(big-endian) 数据低位存储在高地址位,数据高位存储在低地址位。 假设定义一个变量并赋予初值: int a = 0x12345678; 对于这个整型数据,一共有四个字节,假设为其分配的地址空间为0x1001~0x1004,则从低位到高位,每个字节依次是:12、34、56、78。…

第二十四讲:MySQL是怎么保证高可用的?

为了让各位更好的了解文章,我归纳了下面几点最重要的: 1、MySQL 高可用系统的可用性,是依赖于主备延迟的。延迟的时间越小,主库故障的时候,服务恢复需要的时间就越短,可用性就越高。 2、主备延迟原因:备库用的机子不行(IOPS是和主库相同的,不要轻视备库)、备库压力太…

redis内容记录

redis的基本数据类型String:是最基本的数据类型,它可以存储任何二进制安全的数据。 不仅能存放文本数据,还能保存图片、音频、视频、压缩文件等二进制数据。它们通常用于缓存。 Hash:哈希类型,其中键值对中的值本身又是一个键值对结构,hash 特别适合用于存储对象。 List:…

人工智能教育技术学第四周

1.用亿图图示制作黄山奇石语文课文的思维导图2.CAJViewer9.2(CAJ全文浏览器)是中国知网的专用全文格式阅读器,CAJ浏览器支持中国期刊网的CAJ、PDF、KDH等多种格式文件阅读。并且它的打印效果与原版的效果一致。可实现页面设置、浏览页面、查找文字、切换显示语言、文本摘录、…

项目实战:Qt+OSG爆破动力学仿真三维引擎测试工具v1.1.0(加载.K模型,子弹轨迹模拟动画,支持windows、linux、国产麒麟系统)

需求1.使用osg三维引擎进行动力学模型仿真性能测试;  2.打开动力学仿真模型文件,.k后缀的模型文件,测试加载解析过程;  3.解决第三方company的opengl制作的三维引擎,绘制面较多与弹丸路径模拟较卡顿的问题;  4.测试时,使用的模型为公开模型,基础面数量达到160多万…

【入门岛第1关】linux 基础知识

目录闯关任务 完成SSH连接与端口映射并运行hello_world.py 闯关任务 完成SSH连接与端口映射并运行hello_world.py 1 在远程主机上建立hello_python.py程序并运行,查看程序运行的端口: import socket import re import gradio as gr# 获取主机名 def get_hostname():hostname …

DOTS计算Voronoi图形生成,根据点自动划分区域生成多边形

如图,生成Voronoi图形,代码如下。// web* src = https://gist.github.com/andrew-raphael-lukasik/cc9d61edbbb44ecb4956c6cb69363a8e using UnityEngine; using Unity.Mathematics; using Unity.Jobs; using Unity.Collections; using Unity.Profiling;[ExecuteInEditMode] …

Vue2+3基础

。第一个Vue程序 使用script进行Vue全局设置: 指定Vue实例挂载的位置 , Vue和js一样,都需要在script里写 第一步创建vue实例 1.为什么要new vue(),直接调用Vue不行吗?不行,因为如果直接调用Vue()会报如下错误: 2.关于vue构造函数:optionsoptions翻译为多个选项 Vue…