

基于Admin.NET框架的前端的一些改进和代码生成处理(2)
source link: https://www.cnblogs.com/wuhuacong/p/17267815.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

在上篇随笔《基于Admin.NET框架的前端的一些改进和代码生成处理(1)》中大致介绍了一些关于对Admin.NET框架的前端的改造工作,主要目的就是希望能够增加前端代码的简洁性和可读性,以及利用代码生成工具来快速生成相关的代码,从而减少开发过程中的繁琐问题。本篇随笔继续探讨一下,对其中一些模块功能进行一些修改调整,涉及前后端的一起修改调整。
Admin.NET框架的后端基于基于Furion/.NET 6实现,底层集成SqlSugar;前端则是采用Vue-Next-Admin的前端框架,整体是一套非常不错的框架。
1、增加批量添加字典项目
Admin.NET框架的字典管理项目界面如下所示。

它通过列出字典大类,然后在右边入口进行字典项目的管理,以前我倾向于使用左右视图分拆的方式,从而实现字典大类和字典项目的快捷管理。
如在随笔《在Vue&Element前端项目中,对于字典列表的显示处理 》中介绍到的字典综合展示方式如下所示。

我们这里暂且不修改这个页面,继续查看其字典项目管理的界面如下所示。
其列表里面只有一个新增的操作,如果对于初始化字典,则是一份苦差事,反复的打开录入是比较费时间的。我们可以使用惯用的方式,来批量录入字典项目,来提高字典项目初始化处理的效率。
我们在原有界面上增加一个批量录入,和批量删除的操作,如下界面所示。

批量新增字典项目的界面,如下所示。

如果字典值和编码内容不一致,可以使用如下效果进行批量新增
批量添加字典项目的页面,我们是作为一个组件页面的方式添加,然后在页面中应用组件即可,如下代码所示。

对应的批量添加页面里面,提交的时候,调用对应的API接口就可以了,如下代码所示。
// 保存数据处理 async function submitData() { var formEl = editRef.value; if (!formEl) return; await formEl.validate(async (valid) => { if (valid) { //验证成功,执行下面方法 var result = await dictdata.BatchAdd(editForm); //编辑保存 if (result) { $u.message.success('批量添加字典成功!'); // 提示信息 emit('submit'); // 提示刷新数据 closeDialog(); // 重置窗口状态 } else { $u.message.error('批量添加失败'); } } }); }
对应的业务API类里面,定义对应的接口函数。
/** * 系统字典值表 管理Api */ class SysDictDataApi extends BaseApi<SysDictData, AddDictDataInput, UpdateDictDataInput> { ............ /** 批量添加字典项目 */ BatchAdd = async (data: object) => { const url = this.baseUrl + `/BatchAdd`; return await this.axiosInstance.post<UnifyResult<void>>(url, data) } } export default new SysDictDataApi('/api/sysDictData');
后端增加对应的处理接口,实现数据的批量添加即可。

至此,批量添加字典项目的操作,配合前端后端一起,就可以完成该操作了。

2、显示/隐藏开发测试菜单
在Vue-Next-Admin的前端框架演示项目里面,本身提供了很多Demo案例的页面展示,不过Admin.NET应该为了简化框架的效果,从而把这些演示的案例菜单移除了,不过视图文件依旧保存在项目里面,我们开发测试过程中,有时候需要参考这些页面效果,以便了解一些插件的功能和特点,因此可能偶尔需要使用了解下的。而在部署的时候,肯定是需要隐藏起来,不让客户使用这些Demo,否则增加烦恼。
为了更好的管控这些演示菜单连接的入口,我们在原有菜单的表里面增加一个Tag标签,用来标识相关的菜单功能,例如我们把测试页面的Tag标注为 dev, 而菜单表里面本身有是否隐藏和是否启用的设置,隐藏相对于菜单而已不显示(但包含路由),是否启用相对于路由而言(禁用也就无法访问菜单的路由了)。
我们通过这些设置信息,可以对特定的标签,启用或者禁用,从而实现我们对开发测试的菜单页面的显示和隐藏操作。

这个修改处理,必须结合后端进行相关数据表结构调整,以及相关的代码属性调整,在数据库增加一个Tag属性字段,然后修改实体对象定义。
/// <summary> /// 系统菜单表 /// </summary> [SugarTable(null, "系统菜单表")] [SystemTable] public class SysMenu : EntityBase { .................... /// <summary> /// 标签 /// </summary> [SugarColumn(ColumnDescription = "标签", Length = 256)] [MaxLength(256)] public string? Tag { get; set; } }
以及在相关的Dto对象上增加相关的属性。
public class MenuInput { /// <summary> /// 标题 /// </summary> public string Title { get; set; } /// <summary> /// 标签 /// </summary> public string? Tag { get; set; } /// <summary> /// 菜单类型(1目录 2菜单 3按钮) /// </summary> public MenuTypeEnum? Type { get; set; } }
为了隐藏或者显示菜单,我们需要在后端增加一个接口函数,接口函数会通过代理注入的方式提供相关的控制器接口入口,从而给前端访问处理的。
/// <summary> /// 隐藏/启用开发测试页面菜单(对标记tag为dev的,进行隐藏或者启用) /// </summary> /// <returns></returns> [DisplayName("隐藏/启用开发测试页面菜单")] public async Task HideOrShowDevMenu() { var tagFlag = "dev"; var hideState = await _sysMenuRep.IsAnyAsync(u => u.Tag == tagFlag && u.IsHide); var newHide = !hideState; var newState = hideState ? StatusEnum.Enable : StatusEnum.Disable; //更新特定字段(同时隐藏和禁用) await _sysMenuRep.UpdateAsync( u => new SysMenu { IsHide = newHide, Status = newState }, u => u.Tag == tagFlag); }
我们通过判断当前记录的隐藏状态和启用状态,从而给他一个反转值,然后根据条件更新相关的记录即可。
前端开发的时候,我们除了也是相应增加对应的Tag属性,也需要配合后端,手工添加一个对应的方法调用,如下代码所示。
import { BaseApi } from './base-api'; import { SysMenu, UpdateMenuInput, AddMenuInput, MenuOutput } from '/@/api/models'; /** 菜单管理Api */ class SysMenuApi extends BaseApi<SysMenu, AddMenuInput, UpdateMenuInput> { /**隐藏/启用开发测试页面菜单(对标记tag为dev的,进行隐藏或者启用) */ HideOrShowDevMenu = async () => { const url = this.baseUrl + `/HideOrShowDevMenu`; return await this.axiosInstance.post<UnifyResult<void>>(url, null) } } export default new SysMenuApi('/api/sysMenu');
这里只需要注意前端的调用api路径,以及返回结果即可。
根据Vue-Next-Admin的前端的测试菜单的页面信息,我们添加了相关的测试案例菜单,并给它们统一打上dev的标签,添加后的菜单列表界面如下所示。

然后在界面上增加一个操作入口,如下所示。
来操作测试案例菜单的启用或者禁用处理即可。
const hideOrShowDevMenu = () => { var tips = '您确认要隐藏/启用开发测试页面?'; //(对记录标记tag为dev的,进行隐藏或者启用) $u.message.confirm(tips).then(async () => { await menuApi.HideOrShowDevMenu(); $u.message.success('操作成功,请刷新菜单页面,查看变化。'); setTimeout(() => { window.location.reload(); }, 1000); }); }
其中 $u.message 是我们注入的一个全局对象的调用方式,具体操作方式,请参考随笔《在基于vue-next-admin的Vue3+TypeScript前端项目中,为了使用方便全局挂载对象接口》进行了解。
这样显示/禁用测试案例的菜单,就可以正常的随意处理了。

3、文件管理增加分组ID
Admin.NET框架的文件表结构如下所示。
我在以前使用文件的时候,倾向于添加一个附件组,这样在实际业务处理的时候,不用记录多个附件ID的记录,只需要引用一个附件组的ID即可,因此我也希望保留这个方式来绑定多个附件的展示处理。
因此在原有表的基础上增加一个GroupId的字段,如下所示。

调整前后端的代码,让它和其他字段一样能够生效。
例如后端进行分页查询的时候,我们增加对分组ID的判别,如下代码所示。
/// <summary> /// 获取文件分页列表 /// </summary> /// <param name="input"></param> /// <returns></returns> [DisplayName("获取文件分页列表")] public async Task<SqlSugarPagedList<SysFile>> GetPage([FromQuery] PageFileInput input) { return await _sysFileRep.AsQueryable() .WhereIF(!string.IsNullOrWhiteSpace(input.FileName), u => u.FileName.Contains(input.FileName.Trim())) //增加分组ID查询 .WhereIF(!string.IsNullOrWhiteSpace(input.GroupId), u => u.GroupId.Equals(input.GroupId.Trim(), StringComparison.OrdinalIgnoreCase)) .WhereIF(!string.IsNullOrWhiteSpace(input.StartTime.ToString()) && !string.IsNullOrWhiteSpace(input.EndTime.ToString()), u => u.CreateTime >= input.StartTime && u.CreateTime <= input.EndTime) .OrderBy(u => u.CreateTime, OrderByType.Desc) .ToPagedListAsync(input.Page, input.PageSize); }
另外我们增加一个根据分组ID进行查询列表的操作,便于我们在前端根据分组获得对应的文件列表。
/// <summary> /// 获取指定附件组GUID的附件列表 /// </summary> /// <param name="groupId">附件组GUID</param> /// <returns></returns> [DisplayName("获取指定附件组GUID的附件列表")] public async Task<List<SysFile>> GetFilesByGroupId(string groupId) { var list = new List<SysFile>(); if(!string.IsNullOrWhiteSpace(groupId)) { list = await _sysFileRep.GetListAsync(u => u.GroupId == groupId); } return list; }
其他地方进行适当的调整,以便能够使得分组ID真正的好用,便利即可。
在前端代码里面,我们增加对应分组ID查询文件的接口,如下代码所示。
import { BaseNormal } from './base-api'; import { FileInput, FileOutput, SysFile } from '/@/api/models'; /** * 系统文件 管理Api */ class SysFileApi extends BaseNormal { .............
/**获取指定附件组ID的附件列表 */ GetFilesByGroupId = async (groupId: string) => { const url = this.baseUrl + `/FilesByGroupId/${groupId}`; return await this.axiosInstance.get<UnifyResult<Array<SysFile>>>(url, { params: null }) } } export default new SysFileApi('/api/sysFile');
在查看附件或者上传附件的时候,我们指定对应的groupId就可以了,由于为了方便展示附件列表,我们通过自定义组件的方式,绑定它的分组ID进行处理。
<div> <my-upload v-model="attachGroupId" :data="{ groupId: attachGroupId, path: '' }" :is-avatar-upload="false" :show-file-list="true" :is-show-tip="true" /> </div> <div> <my-attachment v-model="attachGroupId"></my-attachment> </div>
例如附件列表,我们在请求数据的时候,如下代码所示。
getData() { // console.log(this.modelValue); if (!isEmpty(this.modelValue)) { fileApi.GetFilesByGroupId(this.modelValue).then(data => { this.attachFiles = data.data.result!; // 生成并添加预览图片列表 this.imageList = []; this.attachFiles.map(item => { if (item.url && this.isImage(item)) { this.imageList.push(item.url!); } }); }); }
附件列表的界面效果如下所示,可以通过绑定GroupId的方式,展示多个附件列表了。
如果需要上传,那么使用封装的上传附件的控件展示,并绑定对应的GroupId就可以展示多个文件列表了

Recommend
-
57
-
12
一些前端框架的比较(下)——Ember.js 和 React 这是前端框架比较和吐槽的第二篇。 Ember.js
-
6
一些前端框架的比较(上)——GWT、AngularJS 和 Backbone.js 和一些前端框架打过交道,想起来这也是技...
-
11
在一般系统开发中,我们一般要借助于高度定制化的代码生成工具,用于统一代码风,节省开发时间,提高开发效率。不同的项目,它的项目不同分层的基类定义不同,我们需要在框架基类的基础上扩展我们的业务类代码,尽量根据已有数据库设计的信息,完整、详细的重现...
-
6
最近有几个其他项目组的童鞋给我之前的 转表工具链-xresloader 提了几个需求。然后我也根据我们近期一些需求点对转表工具链一起给这套工具做了点功能增强和细节上的一些改进。 这篇blog差不多是这些东西的 CHAN...
-
3
我们在做某件事情的时候,一般需要详细了解它的特点,以及内在的逻辑关系,一旦我们详细了解了整个事物后,就可以通过一些辅助手段来提高我们的做事情的效率了。本篇随笔介绍ABP VNext框架各分层项目的规则,以及结合代码生成工具Database2Sharp来实现项目类代...
-
8
在上一篇 kratos quickstart 文章中,我们直接用 kratos new 命令生成了一个项目。 这一篇来看看 kratos API 的定义和使用。 一、krat...
-
10
前端框架ElementUI使用sass离线生成自定义主题 大概是人员离...
-
5
Admin.NET 是一套基于Furion/.NET 6实现的通用管理平台,模块插件式开发,框架包含了常规的权限管理、字典等管理模块,以及一些Vue3的Demo案例,框架前后端分离。后端基于基于Furion/.NET 6实现,底层集成SqlSugar;前端则是采用Vue-Next-Admin的前端框架,整体是一...
-
8
编码数据集生成框架 UnitGen 0.4.0:代码文档生成、测试代码生成 Posted by: Phodal Huang Jan. 7, 2024, 11:34 a.m. UnitGen 是我...
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK