CRUD的最佳实践,联动前后端,包含微信小程序,API,HTML等(三)
关说不练假把式,在上一,二篇中介绍了我心目中的CRUD的样子
基于之前的理念,我开发了一个命名为PasteTemplate的项目,这个项目呢后续会转化成项目模板,转化成项目模板后,后续需要开发新的项目就可以基于这个模板创建,这样就不要copy一个旧的项目,然后删删删,改改改,重命名等操作了
强迫症,一个项目的名字就得统一,心里才舒服
那么本次作者就带来了实物,本次主要介绍管理端的内容,我们一起来看看
这个是后台,目前使用的是HTML原生写的,如果说使用VUE的话,会更简单,这个后续看情况推出!
先用原生的原因呢,一是顺手,二是前期是规划期,改动比较多,这个项目开发过程我是录制了视频的,后续会和项目模板一并放出来!
这个管理端有多少代码?
可能说代码量不太合适,我就列出下各个文件的大概情况(文件采用松散编辑模式,就是一个花括号就一行的写法,所以不存在刻意压缩代码行的问题哈!)
文件 | 大小 | 行数 | 说明 |
---|---|---|---|
login/index.html | 8KB | 177 | 登陆页面,账号密码验证码登陆 |
login.less | 9KB | 381 | 登陆页面的样式文件 |
pasteform/index.html | 12KB | 212 | 表格列表页面的主UI页面 |
pasteform/index.js | 22KB | 682 | 表格页面的主逻辑JS页面 |
pasteform/index.less | 14KB | 656 | 表格页面的样式文件 |
pasteform/view.html | 12KB | 184 | 表单新增编辑页面的UI文件 |
pasteform/view.js | 27KB | 820 | 表单新增编辑页面的逻辑JS代码 |
pasteform/view.less | 10KB | 499 | 表单编辑新增页的样式文件 |
index.html | 11KB | 225 | 首页,也就是菜单页面,上图的这个主页面,菜单采用API获取的动态方式 |
index.less | 5KB | 311 | 首页的样式文件 |
lib/api.js | 18KB | 598 | ajax请求,一些基础函数的转化等,相当于帮助类 |
还有一些其他的三方组件,比如jquery.js,layer.js,daterange.js,pagenum.js,datepicker.js,template.js,wangedit.js等
为啥才这么几个文件?
看上图至少有4个表为啥才这么几个文件?
文件复用了
比如权限的列表页面为pasteform/index.html?path=roleInfo,而用户的列表页面为pasteform/index.html?path=userInfo
对应的表单页面为pasteform/view.html?path=roleInfo和pasteform/view.html?path=userInfo
实现原理
在执行UI之前,获取对应的模型的模型内容,比如新增的时候,获取对应的AddDto模型的模型属性,包括不限于,包含了哪些属性(是否禁用add,edit,del等),有哪些字段,字段的特性是哪些,还有就是字段的默认值!
同理在编辑的时候,会把要编辑的主键带入API中,先查询这个UpdateDto的模型数据,然后基于ID获取这个模型的值,组合后返回给前端
至于表格,请求的时候要读取ListDto和对应的搜索InputQueryDto的内容!
表格页面功能介绍
从上图中可以看到大概几个要点!
1.左侧的菜单是采用动态模式的,看图的中间部分的菜单类型可以看到和左侧的一一对应!
2.右侧区域的功能都是动态的,貌似除了关键字输入和搜索按钮是固定的,其他都是动态控制的
3.搜索区域的内容和类型由后端的InputQueryXXX的模型来控制
4.新增,编辑和删除按钮由对应模型的ListDto控制
5.列表中支持排序,比如上图的ID,排序,层级等
6.列表中支持直接显示外表的对应字段,比如父级ID那一列,直接显示了父级ID对应的权限的名称
7.支持状态快编,也就如上图的switch,这个是可以交互的!
外表输入
支持外表输入,比如要查询某一个角色有多少用户,那么用户列表中,角色ID作为筛选,那角色ID不能自己手动输入吧
点击后,会弹出角色列表页面,选择要查询的,然后点击确定,就会把对应的值输入到输入框中(显示的是友好名)
在Model中是这样配置外表选择的
时间区间
有些时候需要查询时间区间,比如本月新增的用户有多少
在Model中,时间区间其实是由2个字段表示的,开始字段和结束字段,当然了结束字段需要配置隐藏,如下图
单选
有时候查询需要选择某一个状态,比如查询禁用的用户有多少,查询状态正常的用户有多少(也就是一个select的选项)
在Model中体现为:
表单页面功能介绍
表单页面也就是新增数据,或者编辑,如下
基本输入
一些比如文本,文本域,数字,开关等的输入,和基本的一致,约定输入框的名称为Model对应字段的注释部分的前部分,后部分则为placeholder,前后部分使用空格隔开!
头像图片
不单单支持单图,还支持多图模式!
富文本模式
系统采用的是wangEdit v5的版本
时间模式
时间上支持单时间和时间区间模式
单选模式
单选有一个问题,就是选项是固定的,也就是要预先写好,如果是动态的,则使用外表的模式
外表单选
点击和表格那边的操作模式是一样的
要实现这些功能,只需要在对应的Model做属性的标记即可,如下
///<summary>
///测试表 用于测试CURD的表
///</summary>
public class TestTableAddDto
{
///<summary>
///姓名 模拟短文本输入
///</summary>
[MaxLength(32)]
[Required]
public string Name { get; set; }
///<summary>
///头像 模拟图片上传
///</summary>
[MaxLength(128)]
[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>
///单选 一般表示状态,内定的,有点像Enum,关于Enum后续会支持
///</summary>
[ColumnDataType("select", "[{\"name\":\"日类型\",\"value\":0},{\"name\":\"月类型\",\"value\":1},{\"name\":\"年类型\",\"value\":2}]")]
public int DateType { 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("daterange","dateStart","dateEnd")]
public DateTime DateStart { get; set; }
/// <summary>
/// 会员周期 会员生效区间
/// </summary>
[ColumnDataType("hidden")]
public DateTime DateEnd { get; set; }
}
至于编辑模式,其实编辑模式和新增模式的字段属性标记同样适用!
在编辑模式中有一个特别的,就是外表显示,比如上面的外表选择中的选择父级,则在编辑中是这样的
补充
对于上面其实比较纠结的地方应该就是字段的特性ColumnDataType
image
相对于后面的 head 来说,这里是大图模式,在ListDto中表示使用图片的模式渲染
字段 | 类型 | 示例 | 说明 |
---|---|---|---|
args1 | 数字 | 1 | 图片数量 |
args2 | 字符 | cate | 存放在什么位置,上传图片的时候会附带到参数type中 |
args3 | 字符 | 60*60 | 图片是否需要压缩,压缩的宽高,不压缩的设置为0,比如60*0 |
args4 | 字符 | arr或str | 默认值str对应字段的类型,是array类型还是string类型,如果是string类型多个之间用,隔开 |
head
使用方式同 image 这里表示的是小图标模式
字段 | 类型 | 示例 | 说明 |
---|---|---|---|
args1 | 数字 | 1 | 图片数量 |
args2 | 字符 | cate | 存放在什么位置,上传图片的时候会附带到参数type中 |
args3 | 字符 | 60*60 | 图片是否需要压缩,压缩的宽高,不压缩的设置为0,比如60*0 |
args4 | 字符 | arr或str | 默认值str对应字段的类型,是array类型还是string类型,如果是string类型多个之间用,隔开 |
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 |
navigator
表示这个值需要使用页面从另外一个列表中获取,这里表示小程序端的,建议使用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
需要和 hidden 配合使用一般,表示在表单的时候使用哪个参数作为数据
字段 | 类型 | 示例 | 说明 |
---|---|---|---|
args1 | 字符 | cateid | 表示使用url中的哪个参数读取值 |
readyonly
表示这个字段是只读的,一般是编辑的时候生效
richtext
如果是字符串,没有设置maxlength,默认就会变更成richtext,也可以手动强制配置
textarea
如果是字符串,设置maxlength,且设置的值大于128,默认就会变更成textarea,也可以手动强制配置
select
字段 | 类型 | 示例 | 说明 |
---|---|---|---|
args1 | 字符 | [{“name”:“大”,“value”:“1”},{“name”:“小”,“value”:“2”}] | 表示单选的可选值,name是显示 value是值 |
args2 | 字符 | 表示值得类型,这里是单个,跟随主类型走 |
selects
表示多选,这个表示的是页面上的多选
字段 | 类型 | 示例 | 说明 |
---|---|---|---|
args1 | 字符 | [{“name”:“大”,“value”:“1”},{“name”:“小”,“value”:“2”}] | 表示单选的可选值,name是显示 value是值 |
args2 | 字符 | str | 表示值得类型是一个数组,还是字符串,如果是字符串则使用逗号隔开 |
sort
表示排序,表示字段的顺序,一般表格比较会使用这个
字段 | 类型 | 示例 | 说明 |
---|---|---|---|
args1 | 数字 | 0 | 小的排在前面,默认为0 |
link
这个用于表格显示,一般表示用于显示外表的数据,这个将弃用,使用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中不需要删除按钮 |
目前还在思考有哪些常用的需要添加进来,
目前还是缺少很多东西的
1.index.js和view.js有很多重复的函数,可以考虑把他们2个综合一下,后续好维护
2.一些特殊的常用的功能的实现,比如作者的PasteSpider中大量的使用了datalist
3.如何在小程序上接入,毕竟这个项目的初衷就是为了解决小程序上大量表单输入和编辑的问题而提出的方案
4.后续大家如何使用,如何按照自己的需求修改规则等
后续将放出案例项目和项目模板
我们下期见