还是最近在搞的财务模块,由于WEB项目中是用datatables配合modal来实现凭证录入和管理的,看起来不够直观,所以尝试写了一个分部视图用来预览记账凭证。
页面上的凭证列表是这个样子的,和纸质的凭证有很大区别
纸质凭证通常是这样的
实现效果图如下(按照公司财务妹子给的模板做的,和上面的图片有点区别):
cshtml代码如下:
@model List
@{
string m = "千百十万千百十元角分 千百十万千百十元角分";
decimal jfze = 0;
decimal dfze = 0;
}
@DictionaryUtil.GetContentByCode("凭证类别",Model[0].Pzlb)
凭证日期:@DateTime.Now.ToShortDateString()
@Model[0].Pzlb 字: @Model[0].Pzxh 号
摘 要
科 目
借 方 金 额
贷 方 金 额
科 目 代 码
会 计 科 目
@VouRow(m)
@{
for (int i = 0; i < Model.Count; i++)
{
jfze += Model[i].Jfje;
dfze += Model[i].Dfje;
@Model[i].Zy
@Model[i].Kjkmdm
@Model[i].Kjkmmc
@VouRow(Model[i].Jfje, Model[i].Dfje)
}
}
合计:@NumtoChinese(jfze)
@VouRow(jfze, dfze)
经办人:@Model[0].Jbr
记账人:@Model[0].Jzr
审核人:@Model[0].Shr
@helper VouRow(string m)
{
for (int j = 1; j <= 21; j++)
{
if (j == 2 || j == 5 || j == 13 || j == 16)
{
@m[j - 1]
}
else if (j == 8 || j == 19)
{
@m[j - 1]
}
else if (j == 11)
{
}
else
{
@m[j - 1]
}
}
}
@helper VouRow(decimal k, decimal d)
{
string m = (k == 0 ? "".PadLeft(10) : k.ToString().Replace(".", "").PadLeft(10)) + " " + (d == 0 ? "".PadLeft(10) : d.ToString().Replace(".", "").PadLeft(10));
@VouRow(m)
}
@helper NumtoChinese(decimal s)
{
s = Math.Round(s, 2);//四舍五入到两位小数,即分
string[] n = { "零", "壹", "贰", "叁", "肆", "伍", "陆", "柒", "捌", "玖" };
//数字转大写
string[] d = { "", "分", "角", "元", "拾", "佰", "仟", "万", "拾", "佰", "仟", "亿" };
//不同位置的数字要加单位
List needReplace = new List { "零拾", "零佰", "零仟", "零万", "零亿", "亿万", "零元", "零零", "零角", "零分" };
List afterReplace = new List { "零", "零", "零", "万", "亿", "亿", "元", "零", "", "" };//特殊情况用replace剔除
string b = "人民币";//开头
string e = s % 1 == 0 ? "整" : "";//金额是整数要加一个“整”结尾
string re = "";
Int64 a = (Int64)(s * 100);
int k = 1;
while (a != 0)
{//初步转换为大写+单位
re = n[a % 10] + d[k] + re;
a = a / 10;
k = k < 11 ? k + 1 : 4;
}
string need = needReplace.Where(tb => re.Contains(tb)).FirstOrDefault();
while (need != null)
{
int i = needReplace.IndexOf(need);
re = re.Replace(needReplace[i], afterReplace[i]);
need = needReplace.Where(tb => re.Contains(tb)).FirstOrDefault();
}//循环排除特殊情况
re = re == "" ? "" : b + re + e;
@re;
}
主要原理是后台返回PartialView的时候把该凭证的所有记录查询为List作为model返回,cshtml中用内联css控制表格的样式,用razer代码遍历model动态生成整张table。
@model List
是Nhibernate中的表model,用到的字段页面上都有,不再贴代码了。
@helper VouRow(string m)
用来生成金额的列标题(因为数量太多所以直接用循环来生成,有几个单元格有特殊样式需要动态判断下)
@helper VouRow(decimal k, decimal d)
是上个方法的重载,把两个金额拼成一个字符串,然后调用上一个方法生成table行。
@helper NumtoChinese(decimal s)
详情见上篇博客,把循环中累加的金额之和转换为大写放到“合计”中。
@DictionaryUtil.GetContentByCode("凭证类别",Model[0].Pzlb)
是项目中通用的方法,作用是从数据字典中根据凭证代码获取凭证名称(即页面上显示的“付款凭证”标题),引用关系比较复杂,就不贴代码了。
一开始的时候视图的布局是用bootstrap的栅格系统做的,但调试的时候发现在分部视图中引用css会和父页面的引用冲突导致报错,没有发现好的解决方式,所以改用两个table嵌套(调整大小的方式也改为自己写js)。
本来打算直接用这个页面进行凭证录入,但做的时候发现动态增删数据行比较麻烦,每个单元格一个input在保存的时候也很难控制(两个金额字段对应20个input,而且页面上要预置几个空行,就是一百多个input,这样保存的时候为了获取数据要写一大堆代码),所以放弃了,有兴趣的同学可以自己改下看看。