一、数据字典
就是将各种表里面的代表属性的字段抽取成一张类型表
比如产品的名字,单位,重量,地区等等
id一般不会加入业务模块,使用编码sn代表唯一
字典详细数据
就是将每张表代表类型明细的数据抽取出来,比如产品的计量方式,各个产地等等
二、产品模块实体类的 关联
产品表
@Entity
@Table(name="product")
public class Product extends BaseDomain {
private String name;
private String color;
private String pic;
private String smallpic;
private Double costprice;
private Double saleprice;
//产品类型 多对一
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "types_id")
private Producttype producttype;
//单位
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "unit_id")
private Systemdictionarydetail systemdictionarydetail;
//品牌
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "brand_id")
private Systemdictionarydetail brandName;
省略getset
}
产品类型表
@Entity
@Table(name="producttype")
public class Producttype extends BaseDomain {
private String name;
private String descs;
//配置类型的父类型,每一个类型都有对应的父类型
@ManyToOne(fetch=FetchType.LAZY)
@JoinColumn(name="parent_id")
private Producttype parent;
//用于下拉框的父子层级关系
public String getGroup(){
if(parent!=null){
return parent.getName();
}
return "";
}
。。。。
}
字典明细表
@Entity
@Table(name="systemdictionarydetail")
public class Systemdictionarydetail extends BaseDomain {
private String name;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "types_id")
private Systemdictionarytype type;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
字典表
@Entity
@Table(name="systemdictionarytype")
public class Systemdictionarytype extends BaseDomain {
public static final String PRODUCT_BRAND="productBrand";//品牌sn
public static final String PRODUCT_UNIT="productUnit";//单位sn
private String sn;
private String name;
}
三、数据查询展示
product.jsp页面
<table id="productGrid" class="easyui-datagrid" enableHeaderClickMenu="true"
data-options="url:'/product/page',fitColumns:true,onRowContextMenu:showMenu,singleSelect:true,pagination:true,fit:true,toolbar:'#gridTools',onLoadSuccess:loadSuccess">
<thead>
<tr>
<th width="20" field="name" sortable="true">产品名称</th>
<th width="20" field="color" sortable="true" data-options="formatter:colorFormatter">产品颜色</th>
<th width="20" field="pic" sortable="true" data-options="formatter:picFormatter">产品图片</th>
<%--<th width="20" field="smallpic" sortable="true">smallpic</th>--%>
<th width="20" field="costprice" sortable="true">成本价</th>
<th width="20" field="saleprice" sortable="true">产品售价</th>
<th width="20" field="producttype" sortable="true" data-options="formatter:protype">产品类型</th>
<th width="20" field="systemdictionarydetail" sortable="true" data-options="formatter:unitFormatter">单位</th>
<th width="20" field="brandName" sortable="true" data-options="formatter:brandFormatter">品牌</th>
</tr>
</thead>
</table>
实体类字段显示为object,显示为正确形式
product.js代码
function protype(value,row,index) {
if (value){
return value.name;
}
}
function unitFormatter(value,row,index) {
if (value){
return value.name;
}
}
function brandFormatter(value,row,index) {
if (value){
return value.name;
}
}
/*返回图片*/
function picFormatter(value,row,index) {
console.debug(value)
return value?`<img src="${value}" width="50px" `:'';
}
测试效果
鼠标移到图片上展示大图片
easyUI引入【jeasyui.extensions.base.tooltip.js】
在上面数据表的组件属性加入onLoadSuccess:loadSuccess
表示页面加载完成后执行方法
<table id="productGrid" class="easyui-datagrid" enableHeaderClickMenu="true"
data-options="url:'/product/page',fitColumns:true,onRowContextMenu:showMenu,singleSelect:true,pagination:true,fit:true,toolbar:'#gridTools',onLoadSuccess:loadSuccess">
。。。。。。。
。。。。。。。
- js代码
主要功能完成是通过js
//成功后进行加载
function loadSuccess(data) {
alert(123333333)
//传入的是所有的行数据
console.debug(data)
var rows = data.rows;
for(var i=0;i<rows.length;i++){
var result = rows[i];
$.easyui.tooltip.init($("img[src='"+result.pic+"']"), {
position: "rigth",
content: "<div style=\"width:400px;height:300px;\"><img style='width: 400px' src='"+result.pic+"' /></div>"
});
}
}
增删改的方法添加
<div id="gridTools" style="padding:5px;height:auto">
<%--功能条--%>
<div style="margin-bottom:5px">
<a href="#" data-method="add" class="easyui-linkbutton" iconCls="icon-add" plain="true">添加</a>
<a href="#" data-method="update" class="easyui-linkbutton" iconCls="icon-edit" plain="true">修改</a>
<a href="#" data-method="del" class="easyui-linkbutton" iconCls="icon-remove" plain="true">删除</a>
</div>
</div>
模态框
<%--添加和修改的弹出模态框--%>
<div id="editDialog" class="easyui-dialog" title="功能编辑" style="width:400px;"
data-options="iconCls:'icon-save',resizable:true,modal:true,closed:true">
<form id="editForm" method="post" enctype="multipart/form-data">
<input id="productId" type="hidden" name="id">
<table cellpadding="5">
<tr>
<td>产品名称:</td>
<td><input class="easyui-validatebox" type="text" name="name"data-options="required:true,validType:'checkName'"></input></td>
</tr>
<tr>
<td>产品颜色:</td>
<td><input class="easyui-validatebox" type="color" name="color"></input></td>
</tr>
<tr>
<td>产品图片:</td>
<td><input class="easyui-filebox" name="fileImage" value="选择" data-options="prompt:'选择一个图片...'"
style="width:200px"></td>
</tr>
<%-- <tr>
<td>smallpic:</td>
<td><input class="easyui-validatebox" type="text" name="smallpic"></input></td>
</tr>--%>
<tr>
<td>成本价:</td>
<td><input class="easyui-validatebox" type="text" name="costprice"></input></td>
</tr>
<tr>
<td>产品售价:</td>
<td><input class="easyui-validatebox" type="text" name="saleprice"></input></td>
</tr>
<tr>
<td>产品类型:</td>
<td>
<input name="producttype.id" class="easyui-combobox" panelHeight="auto"
data-options=" groupField:'group',valueField:'id',textField:'name',url:'/util/productType',required:true" />
</td>
</tr>
<tr>
<td>单位:</td>
<td>
<input name="systemdictionarydetail.id" class="easyui-combobox" panelHeight="auto"
data-options="valueField:'id',textField:'name',url:'/util/productUnit',required:true" />
</td>
</tr>
<tr>
<td>品牌:</td>
<td>
<input name="brandName.id" class="easyui-combobox" panelHeight="auto"
data-options="valueField:'id',textField:'name',url:'/util/productBrand',required:true" />
</td>
</tr>
</table>
</form>
<div style="text-align:center;padding:5px">
<a href="javascript:void(0)" class="easyui-linkbutton" data-method="save">提交</a>
<a href="javascript:void(0)" class="easyui-linkbutton" data-method="closeDialog">关闭</a>
</div>
<%-- 右键支持增删改--%>
<div id="gridMenu" class="easyui-menu" style="width:120px;">
<div data-options="iconCls:'icon-add'" data-method="add">添加</div>
<div data-options="iconCls:'icon-edit'" data-method="update">修改</div>
<div data-options="iconCls:'icon-remove'" data-method="del">删除</div>
</div>
</div>
四、产品类型,单位,品牌的
- 添加功能完成
产品的颜色选择,可以找颜色控件,也可以使用input标签的自带选择,只需要将type改为color - 产品类型,单位,品牌的组合框展示
层级效果展示,子菜单
想要分组展示
先添加属性groupField:‘group’
<td>产品类型:</td>
<td>
<input name="producttype.id" class="easyui-combobox" panelHeight="auto"
data-options=" groupField:'group',valueField:'id',textField:'name',url:'/util/productType',required:true" />
</td>
根据路径查询到子菜单
//拿到所有菜单
@RequestMapping("/productType")
@ResponseBody
public List<Producttype> productType(){
List<Producttype> producttypes = iProducttypeService.findChildren();
return producttypes;
}
ProducttypeRepository
public interface ProducttypeRepository extends BaseRepository<Producttype,Long> {
//拿到所有子类型
@Query("select o from Producttype o where o.parent.id is not null")
List<Producttype> findChildren();
}
ProducttypeServiceImpl
@Override
public List<Producttype> findChildren() {
List<Producttype> childrens = producttypeRepository.findChildren();
return childrens;
}
将所有的子菜单就返回给了前台,现在获取父菜单
Producttype类中提供get方法
jsp页面自动通过儿子,找到父菜单,通过父菜单的组名
public String getGroup(){
if(parent!=null){
return parent.getName();
}
return "";
}
完成组合框展示
五、单位,品牌的展示
SystemdictionarydetailRepository
根据产品类型来查询
public interface SystemdictionarydetailRepository extends BaseRepository<Systemdictionarydetail,Long> {
@Query("select o from Systemdictionarydetail o where o.type.sn = ?1")
List<Systemdictionarydetail> findByProductType(String sn);
}
SystemdictionarydetailServiceImpl
使用产品数据字典类型中的静态字段,根据类型来区分单位和品牌
查询不同数据
@Override
public List<Systemdictionarydetail> findBrand() {
List<Systemdictionarydetail> brands = systemdictionarydetailRepository.findByProductType(Systemdictionarytype.PRODUCT_BRAND);
return brands;
}
@Override
public List<Systemdictionarydetail> findUnit() {
List<Systemdictionarydetail> units = systemdictionarydetailRepository.findByProductType(Systemdictionarytype.PRODUCT_UNIT);
return units;
}
controller层调用,返回数据
//拿到当前单位
@RequestMapping("/productUnit")
@ResponseBody
public List<Systemdictionarydetail> productUnit(){
List<Systemdictionarydetail> units = iSystemdictionarydetailService.findUnit();
return units;
}
//拿到当前品牌
@RequestMapping("/productBrand")
@ResponseBody
public List<Systemdictionarydetail> productBrand(){
List<Systemdictionarydetail> brands = iSystemdictionarydetailService.findBrand();
return brands;
}
在模态框中展示数据producttype.id
对象.属性,才可以被正确展示
六、保存方法
//点击a标签的时候,获取到函数名称 动态调用方法
//加*匹配所有的a标签
$("*[data-method]").on("click",function(){
var methodName = $(this).data("method");
window.comlr[methodName]();
})
//添加方法
comlr={
add(){
//让密码框显示出来
$("*[data-edit]").show();
$("*[data-edit] input").validatebox("enable");
/* 每次打开会又上次的缓存 。。方法 clear 清除表单中的内容*/
editForm.form("clear");
/*点击添加弹出模态框 并且每次都居中*/
editDialog.dialog("center").dialog("open");
},
update(){ },
save(){
/*如果有id则是提交表单到修改的controller*/
var productId = $("#productId").val();
url="/product/save";
if(productId){
//如果是修改,跳转修改controller
url="/product/update?cmd=_update";
}
/*easyui的表单提交 在form中找的方法。。*/
editForm.form('submit', {
url:url,
onSubmit: function(){
var isValid = $(this).form('validate');
return isValid; // 返回false终止表单提交
},
/* 成功,后台返回结果*/
success: function(data){
var result = JSON.parse(data);
if(result.success){
productGrid.datagrid("reload")
}
else {
$.messager.alert('失败',`操作失败了可能是因为:${result.msg}`,"warning");
}
//关闭弹出框
itsource.closeDialog();
}
});
},
del(){},
search(){
//serializeObject:拿到一个form中的所有数据,封装成json对象
var params = querySearch.serializeObject();
console.debug(params)
productGrid.datagrid("load",params);
},
closeDialog(){
/*点击关闭按钮的事件,关闭模态框*/
editDialog.dialog("center").dialog("close");
}
}
//快捷键的绑定
$(document).bind('keydown', 'del', itsource.del);
$(document).bind('keydown', 'Shift+1', itsource.add);
$(document).bind('keydown', 'Shift+2', itsource.update);
})
保存之前将关联对象设置为空,不然报n-to-n的错
@ModelAttribute("editProduct")
//每一次传id的方法都会先执行这个方法,很浪费性能,解决方法 js 提交请求的时候传一个String过来 判断是否有才继续执行
public Product beforEdit(Long id,String cmd){
if (id!=null&&"_update".equals(cmd)){
Product one = iProductService.findOne(id);
//解决n-to-n 把关联对象设置为null
one.setBrandName(null);
one.setProducttype(null);
one.setSystemdictionarydetail(null);
return one;
}
return null;
}
七、修改,回显
-
点击修改
-
取消验证
-
数据回显
js代码
添加属性,传入后台封装的时候是封装的值,对象字段,应该是字段点属性
update(){
var rows = productGrid.datagrid("getSelected");
if(!rows){
$.messager.alert('注意','请选中再操作');
return;
}
/*先清空再回显*/
editForm.form("clear")
console.debug(rows.color+"00000000000000000000000000000000000000000000")
/* 如果有部门,添加属性为department.id,和表单的department属性对应*/
if(rows.producttype){
/*添加属性*/
rows["producttype.id"]=rows.producttype.id;
}
if(rows.systemdictionarydetail){
/*添加属性*/
rows["systemdictionarydetail.id"]=rows.systemdictionarydetail.id;
}
if(rows.producttype){
/*添加属性*/
rows["brandName.id"]=rows.brandName.id;
}
/*显示rows选择的数据*/
editForm.form("load",rows)
/*将密码框组件禁用 验证禁用 */
$("*[data-edit] input").validatebox("disable");
/*将密码框的表单隐藏*/
$("*[data-edit]").hide();
editDialog.dialog("center").dialog("open");
}
数据回显完成,点击提交,传入后台
八、图片的上传下载
mvc.xml中配置
<!-- 错误:提示告诉开发者你没有配置文件上传解析器。 -->
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<!-- 设置上传文件的最大尺寸为1MB -->
<property name="maxUploadSize">
<value>1048576</value>
</property>
</bean>
将修改添加 的弹出模态框更改提交方式和文件上传
enctype=“multipart/form-data”
<form id="editForm" method="post" enctype="multipart/form-data">
。。。
。。。
模态框的图片上传input标签
<tr>
<td>产品图片:</td>
<td><input class="easyui-filebox" name="fileImage" value="选择" data-options="prompt:'选择一个图片...'"
style="width:200px"></td>
</tr>
点击提交form表单,数据全部提交到后台
注意
input的图片name属性和实体类的图片不能一样,不然后台会将传入的图片文件封装到product对象中,一直报错
文件上传的controller层代码
添加和修改都变成了有文件的情况
九、图片的上传下载controller
//图片上传功能
private static final SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd-HHmmssS");
//图片上传功能
public void uploadImage(Product product, MultipartFile fileImage, HttpServletRequest req){
if(fileImage!=null) {
String webapp = req.getServletContext().getRealPath("/");
//图片存在就把它给删除掉
/*
if (product.getId() != null && StringUtils.isNotBlank(product.getPic())) {
File deleteFile = new File(webapp, product.getPic());
if (deleteFile.exists()) {
deleteFile.delete();
}
File deleteFile2 = new File(webapp, product.getSmallPic());
if (deleteFile2.exists()) {
deleteFile2.delete();
}
}
*/
try {
// 上传文件命名,拷贝到webapp的位置,设置pic到product
Date date = new Date();
// 大小图的路径+文件名称
String fileName = "/upload/" + sdf.format(date) + ".png";
String smallFileName = "/upload/" + sdf.format(date) + "_small.png";
// 大小图的在服务器上面的物理路径
File destFile = new File(webapp, fileName);
File smallDestFile = new File(webapp, smallFileName);
// 生成upload目录
File parentFile = destFile.getParentFile();
if (!parentFile.exists()) {
parentFile.mkdirs();// 自动生成upload目录
}
// 把上传的临时图片,复制到当前项目的webapp路径
//FileUtils.copyFile(upload, destFile);
FileCopyUtils.copy(fileImage.getInputStream(), new FileOutputStream(destFile));
// 处理缩略图
//Thumbnails.of(upload).scale(0.1F).toFile(smallDestFile);
Thumbnails.of(fileImage.getInputStream()).scale(0.1F).toFile(smallDestFile);
// 把大小图的相对webapp的路径设置到数据库产品表里面
product.setPic(fileName);
product.setSmallpic(smallFileName);
} catch (Exception e) {
e.printStackTrace();
}
}
}
//添加或者修改
private SuccessBoolean saveOrUpdate(Product product, HttpServletRequest req){
//下面是解决上传文件为空报错的问题
MultipartFile fileImage = null;
boolean isMultipart = ServletFileUpload.isMultipartContent(req);
if (isMultipart){
MultipartHttpServletRequest multipartRequest = WebUtils.getNativeRequest(req, MultipartHttpServletRequest.class);
fileImage = multipartRequest.getFile("fileImage");
}
uploadImage(product, fileImage, req);
try {
iProductService.save(product);
return new SuccessBoolean();
} catch (Exception e) {
e.printStackTrace();
return new SuccessBoolean(false,e.getMessage());
}
}
//保存的controller
@RequestMapping("/save")
@ResponseBody
public SuccessBoolean save(Product product, HttpServletRequest req){
return saveOrUpdate(product,req);
}
@ModelAttribute("editProduct")
//每一次传id的方法都会先执行这个方法,很浪费性能,解决方法 js 提交请求的时候传一个String过来 判断是否有才继续执行
public Product beforEdit(Long id,String cmd){
if (id!=null&&"_update".equals(cmd)){
Product one = iProductService.findOne(id);
//解决n-to-n 把关联对象设置为null
one.setBrandName(null);
one.setProducttype(null);
one.setSystemdictionarydetail(null);
return one;
}
return null;
}
//修改
@RequestMapping("/update")
@ResponseBody
public SuccessBoolean update(@ModelAttribute("editProduct")Product product,HttpServletRequest req){
return saveOrUpdate(product,req);
}