本篇通过完整示例介绍如何实现一对多关系表单的相应服务及视图。
一、准备数据结构
示例所采用的数据结构为“物资需求”一对多“物资清单”,通过IDE的实体设计器如下所示:
1. 物资(DonateItem)
2. 物资需求(Requirement)
3. 物资清单(RequireItem)
主键为Req(Requirement)+Item(DonateItem)
二、实现需求列表显示功能
1. 新建RequirementService服务实现加载列表数据
using System;
using System.Threading.Tasks;
namespace dns.ServiceLogic
{
public class RequirementService
{
///
/// 分页加载需求记录
///
public async Task
2. 新建RequireList视图
2.1 模版
新建
修改
删除
刷新
2.2 脚本
@Component
export default class RequireList extends Vue {
items = [] //需求列表
loading = false
pageIndex = 0
pageSize = 20
load() {
this.loading = true
dns.Services.RequirementService.Load(this.pageIndex, this.pageSize).then(res => {
this.$set(this, 'items', $runtime.parseEntity(res))
this.loading = false
}).catch(err => {
this.loading = false
this.$message.error('加载需求列表失败: ' + err)
})
}
mounted() {
this.load()
}
}
系统函数$runtime.parseEntity()用于将调用服务的结果内的数据对象如{ID:xxx,Name:xxx}转换为前端的Entity对象,另如果调用服务的结果只用作展示可以不用转换。
2.3 预览
三、实现新建需求功能
3.1 修改RequirementService实现保存方法
///
/// 保存需求
///
public async Task Save(Entities.Requirement req)
{
//TODO:验证
using var conn = await DataStore.Default.OpenConnectionAsync();
using var txn = conn.BeginTransaction();
//保存主记录
await DataStore.Default.SaveAsync(req, txn);
//保存子记录
foreach (var item in req.Items)
{
await DataStore.Default.SaveAsync(item, txn);
}
//处理已删除的物资
if (req.PersistentState != PersistentState.Detached)
{
foreach (var item in req.Items.DeletedItems)
{
await DataStore.Default.DeleteAsync(item, txn);
}
}
//递交事务
txn.Commit();
}
3.2 新建ItemService实现用于绑定的加载方法
using System;
using System.Threading.Tasks;
namespace dns.ServiceLogic
{
public class ItemService
{
///
/// 加载用于前端选择绑定
///
public async Task
3.3 新建RequireView编辑视图
3.3.1 模版
需求方:
时间:
联系人:
电话:
地址:
邮编:
添加
删除
保存
3.3.2 脚本
@Component
export default class RequireView extends Vue {
@Prop({ type: Object, default: {} }) req: dns.Entities.Requirement
optItems = [] //物资选择列表
/** 用于Table绑定,过滤已标为删除的 */
get items() {
if (this.req.Items) {
return this.req.Items.filter(t => !t.isDeleted())
}
return null
}
/** 加载用于绑定下拉选择的物资列表 */
loadItems() {
dns.Services.ItemService.LoadForSelect().then(res => {
this.$set(this, 'optItems', res)
}).catch(err => {
this.$message.error("加载物资列表失败: " + err)
})
}
/** 添加物资 */
onAddItem() {
if (!this.req.Items) { //仅测试
this.$set(this.req, 'Items', [])
}
this.req.Items.push(new dns.Entities.RequireItem())
}
/** 删除物资 */
onDeleteItem(index) {
//新建的直接删除,旧的标为删除
if (this.req.Items[index].isNew()) {
this.req.Items.splice(index, 1)
} else {
this.req.Items[index].markDeleted()
}
}
onSave() {
dns.Services.RequirementService.Save(this.req).then(res => {
this.req.acceptChanges()
this.$message.success("保存成功")
}).catch(err => {
this.$message.error("保存错误: " + err)
})
}
mounted() {
this.loadItems()
}
}
3.4 修改RequireList视图,实现新建功能
3.4.1 模版
新建
3.4.2 脚本
@Component({
components: { RequireView: dns.Views.RequireView }
})
export default class RequireList extends Vue {
//----省略----
dlgVisible = false
current = null
//----省略----
onCreate() {
this.current = new dns.Entities.Requirement()
this.dlgVisible = true
}
//----省略----
现在可以在预览内尝试添加些数据了!
四、实现需求列表Pop显示物资清单
主列表使用懒加载方式加载子表数据。
4.1 修改RequirementService服务实现加载子表数据方法
///
/// 加载需求物资列表
///
public async Task
4.2 修改RequireList视图
4.2.1 模版
{{index+1}}.
{{item.ItemName}}
{{item.ItemSpec}}
{{item.Quantity}}
物资清单
4.2.2 脚本
/** 加载需求物资清单 */
loadItems(row: dns.Entities.Requirement) {
if (row.Items) { return }
dns.Services.RequirementService.LoadItems(row.Id).then(res => {
this.$set(row, 'Items', $runtime.parseEntity(res))
}).catch(err => {
this.$message.error('加载物资列表失败: ' + err)
})
}
4.2.3 预览
五、实现修改与删除功能
5.1 修改RequirementService服务实现删除方法
public async Task Delete(Entities.Requirement req)
{
//TODO:判断状态,已发放物资的不能删除
using var conn = await DataStore.Default.OpenConnectionAsync();
using var txn = conn.BeginTransaction();
//先删除子表记录
var deleteItems = new SqlDeleteCommand();
deleteItems.Where(t => t.ReqId == req.Id);
await DataStore.Default.ExecCommandAsync(deleteItems, txn);
//再删除主表记录
await DataStore.Default.DeleteAsync(req, txn);
//递交事务
txn.Commit();
}
5.2 修改RequireList视图
5.2.1 模版
修改
删除
5.2.2 脚本
//----省略----
export default class RequireList extends Vue {
//----省略----
currentRow = null
//----省略----
onCurrentChanged(row) {
this.currentRow = row
}
onEdit() {
if (!this.currentRow) {
this.$message.warning("请先选择记录")
return
}
this.loadItems(this.currentRow)
this.current = this.currentRow
this.dlgVisible = true
}
onDelete() {
if (!this.currentRow) {
this.$message.warning("请先选择记录")
return
}
this.$confirm('确认删除选择的记录吗?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
dns.Services.RequirementService.Delete(this.currentRow).then(res => {
this.$message.success("删除成功");
}).catch(err => {
this.$message.error("删除失败: " + err)
})
}).catch(() => { })
}
//----省略----
5.2.3 预览
六、本篇小结
作者上篇提到实现独立的不依赖内置存储的版本,本篇示例即是基于此版本,下一步重点是针对此版本的测试与Bug修复。另一边码代码一边码文实属不易,作者需要您的支持请您多多点赞推荐!