<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@include file="/WEB-INF/views/head.jsp" %>
<html>
<head>
<title>Titletitle>
<%--引入EasyUI的datagrid-groupview扩展--%>
<script type="text/javascript" src="/easyui/plugins/datagrid-groupview.js">script>
<%--引入Highcharts支持的JS文件--%>
<script src="https://code.highcharts.com.cn/highcharts/highcharts.js">script>
<script src="https://code.highcharts.com.cn/highcharts/highcharts-3d.js">script>
<script src="https://code.highcharts.com.cn/highcharts/modules/exporting.js">script>
<script src="https://code.highcharts.com.cn/highcharts-plugins/highcharts-zh_CN.js">script>
<script src="https://code.highcharts.com.cn/highcharts/modules/oldie.js">script>
<script src="https://code.highcharts.com.cn/highcharts/modules/cylinder.js">script>
<script src="https://code.highcharts.com.cn/highcharts/themes/sand-signika.js">script>
<%--引入当前页面对应的js文件--%>
<script src="/js/model/purchasebillitem.js">script>
head>
<body>
<table id="purchasebillitemGrid">
table>
<%--grid顶部工具栏--%>
<div id="gridTools" style="padding:5px;height:auto">
<%--查询条--%>
<form id="searchForm">
日期: <input name="beginDate" class="easyui-datebox" style="width:150px">
- <input name="endDate" class="easyui-datebox" style="width:150px">
状态: <select class="easyui-combobox" name="status" panelHeight="auto" style="width:100px;">
<option value="">--所有--option>
<option value="0">待审option>
<option value="1">已审option>
<option value="-1">作废option>
select>
分组:<select class="easyui-combobox" name="groupBy" panelHeight="auto" style="width:100px;">
<option value="">--所有--option>
<option value="0">供应商option>
<option value="1">采购员option>
<option value="2">月份option>
select>
<a href="#" data-method="search" class="easyui-linkbutton" iconCls="icon-search">查询a>
<span style="color: darkblue;font-size: 16px"> 图表:span>
<a href="#" data-method="chart3d" class="easyui-linkbutton" iconCls="icon-3dpie">3D饼图a>
<a href="#" data-method="chart2d" class="easyui-linkbutton" iconCls="icon-2dpie">2D饼图a>
<a href="#" data-method="chartZhu3d" class="easyui-linkbutton" iconCls="icon-3dbar">3D柱状图a>
<a href="#" data-method="chartZhu2d" class="easyui-linkbutton" iconCls="icon-2dbar">2D柱状图a>
form>
div>
<%--饼状图--%>
<div id="chartDialog" class="easyui-dialog" title="采购订单明细" style="width:800px;"
data-options="iconCls:'icon-save',resizable:true,modal:true,closed:true">
<div id="container" style="height: 500px">div>
div>
<%--柱状图--%>
<div id="chartDialog2" class="easyui-dialog" title="采购订单明细" style="width:800px;"
data-options="iconCls:'icon-save',resizable:true,modal:true,closed:true">
<div id="container2" style="min-width: 310px; height: 400px; margin: 0 auto">div>
div>
body>
html>
//状态的格式化
function formatStatus(v) {
if (v == -1) {
return `作废`
} else if (v == 1) {
return `已审`
} else if (v == 0) {
return `待审`
}
}
$(function () {
var purchasebillitemGrid = $('#purchasebillitemGrid');
var searchForm = $('#searchForm');
var chartDialog = $('#chartDialog');
var chartDialog2 = $('#chartDialog2');
purchasebillitemGrid.datagrid({
rownumbers: true, // 行号
remoteSort: false, //远程排序
nowrap: false,
fit: true,
fitColumns: true,
toolbar: "#gridTools",
url: '/purchasebillitem/findItems', //获取数据的路径
//所有的列的字段 【需要修改成我们自己的数据:编号,采购员,供应商....】
columns: [[
{
field: 'id', title: '编号', width: 100},
{
field: 'supplierName', title: '供应商', width: 100},
{
field: 'buyerName', title: '采购员', width: 100},
{
field: 'productName', title: '产品', width: 100},
{
field: 'productTypeName', title: '产品类型', width: 100},
{
field: 'vdate', title: '日期', width: 100},
{
field: 'price', title: '单价', width: 100},
{
field: 'num', title: '数量', width: 100},
{
field: 'amount', title: '小计', width: 100},
{
field: 'status', title: '状态', formatter: formatStatus, width: 100}
]],
//分组字段
groupField: 'groupField',
view: groupview, //支持分组视图功能
//分组格式化
// value:就是当前groupField分组的值
// rows:当前这一组的所有行
groupFormatter: function (value, rows) {
var totalNum = 0;
var totalAmount = 0;
for (let r of rows) {
totalNum += r.num;
totalAmount += r.amount;
}
//成都供应商 - 10 条数据 共34商品 总金额:344
return `${
value} - ${
rows.length}条数据 共${
totalNum}个商品
总金额:${
totalAmount}`;
}
});
$("*[data-method]").on("click", function () {
var methodName = $(this).data("method");
window.itsource[methodName]();
})
itsource = {
//查询
search() {
//serializeObject:拿到一个form中的所有数据,封装成json对象
var params = searchForm.serializeObject();
purchasebillitemGrid.datagrid("load", params);
},
//查询3D图片
chart3d() {
//获取到表单中的所有值
var params = searchForm.serializeObject();
if (params.groupBy == "") {
$.messager.alert('提示', '请选择 分组 条件', 'info');
return;
}
//打开弹出框
chartDialog.dialog("center").dialog("open");
//请求的时候把值传到后台
$.post("/purchasebillitem/findCharts", params, function (result) {
//展示图表
Highcharts.chart('container', {
chart: {
type: 'pie',
options3d: {
enabled: true,
alpha: 45, //倾斜度
beta: 0
}
},
title: {
text: '采购订单总金额'
},
//鼠标移上去后显示的数据
tooltip: {
pointFormat: '{series.name}: {point.percentage:.1f}%'
},
plotOptions: {
pie: {
//是否自己可以选择
allowPointSelect: true,
//鼠标指上来后的样式
cursor: 'pointer',
depth: 35, //深度
dataLabels: {
enabled: true,
format: '{point.name}'
}
}
},
series: [{
type: 'pie',
name: '占比',
data: result
}]
});
})
},
//查询2D图片
chart2d() {
//获取到表单中的所有值
var params = searchForm.serializeObject();
if (params.groupBy == "") {
$.messager.alert('提示', '请选择 分组 条件', 'info');
return;
}
//打开弹出框
chartDialog.dialog("center").dialog("open");
//请求的时候把值传到后台
$.post("/purchasebillitem/findCharts", params, function (result) {
Highcharts.chart('container', {
chart: {
plotBackgroundColor: null,
plotBorderWidth: null,
plotShadow: false,
type: 'pie'
},
title: {
text: '采购订单总金额'
},
tooltip: {
pointFormat: '{series.name}: {point.percentage:.1f}%'
},
plotOptions: {
pie: {
allowPointSelect: true,
cursor: 'pointer',
dataLabels: {
enabled: true,
format: '{point.name}: {point.percentage:.1f} %',
style: {
color: (Highcharts.theme && Highcharts.theme.contrastTextColor) || 'black'
}
}
}
},
series: [{
name: '占比',
colorByPoint: true,
data: result
}]
});
})
},
chartZhu2d() {
//获取到表单中的所有值
var params = searchForm.serializeObject();
if (params.groupBy == "") {
$.messager.alert('提示', '请选择 分组 条件', 'info');
return;
}
//打开弹出框
chartDialog2.dialog("center").dialog("open");
//请求的时候把值传到后台
$.post("/purchasebillitem/findCharts", params, function (result) {
//展示图表
Highcharts.chart('container2', {
chart: {
type: 'column'
},
title: {
text: '采购订单总金额'
},
subtitle: {
text: '可切换分组查看'
},
xAxis: {
type: 'category'
},
yAxis: {
title: {
text: '采购订单总金额'
}
},
legend: {
enabled: false
},
plotOptions: {
series: {
borderWidth: 0,
dataLabels: {
enabled: true,
format: '{point.name}: {point.y:.1f}',
}
}
},
tooltip: {
headerFormat: '{series.name}
',
pointFormat: '{point.name}: {point.y:.1f}
'
},
series: [{
name: '总金额',
colorByPoint: true,
data: result
}]
});
})
},
chartZhu3d() {
//获取到表单中的所有值
var params = searchForm.serializeObject();
if (params.groupBy == "") {
$.messager.alert('提示', '请选择 分组 条件', 'info');
return;
}
//打开弹出框
chartDialog2.dialog("center").dialog("open");
//请求的时候把值传到后台
$.post("/purchasebillitem/findCharts", params, function (result) {
Highcharts.chart('container2', {
chart: {
type: 'cylinder',
options3d: {
enabled: true,
alpha: 15,
beta: 15,
depth: 50,
viewDistance: 25
}
},
title: {
text: '采购订单总金额'
},
plotOptions: {
series: {
depth: 25,
colorByPoint: true
}
},
series: [{
data: result,
name: '总金额',
showInLegend: false
}]
});
});
}
}
})
public class ItemChartVo {
private Object name;
private Object y;
public ItemChartVo() {
}
public ItemChartVo(Object name, Object y) {
this.name = name;
this.y = y;
}
public ItemChartVo(String name, Object y) {
this.name = name;
this.y = y;
}
//get set
}
package com.xuxusheng.aisell.domain.vo;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.xuxusheng.aisell.domain.Purchasebillitem;
import com.xuxusheng.aisell.query.PurchasebillitemQuery;
import java.math.BigDecimal;
import java.util.Calendar;
import java.util.Date;
//List -》 List
public class PurchaseBillItemVo {
private Long id; //编号
private String supplierName; //供应商
private String buyerName;//采购员
private String productName; //产品
private String productTypeName; //产品类型
private Date vdate;//日期
private BigDecimal price;//单价
private BigDecimal num;//数量
private BigDecimal amount;//小计
private Integer status; //状态
private String groupField; //分组字段
/**
* 把一个Purchasebillitem对象变成咱们的vo对象
* @param item
*/
public PurchaseBillItemVo(Purchasebillitem item, PurchasebillitemQuery query) {
this.id = item.getId();
this.supplierName = item.getBill().getSupplier().getName();
this.buyerName = item.getBill().getBuyer().getUsername();
this.productName = item.getProduct().getName();
this.productTypeName = item.getProduct().getTypes().getName();
this.vdate = item.getBill().getVdate();
this.price = item.getPrice();
this.num = item.getNum();
this.amount = item.getAmount();
this.status = item.getBill().getStatus();
Integer groupBy = query.getGroupBy();
if(groupBy==1){
//采购员分组
this.groupField = buyerName;
}else if(groupBy==2){
//月份
Calendar cal = Calendar.getInstance();
cal.setTime(vdate);
String month = (cal.get(Calendar.MONTH)+1) + "";
this.groupField = month;
}else{
//供应商分组
this.groupField = supplierName;
}
}
@JsonFormat(pattern = "yyyy-MM-dd",timezone = "GMT+8")
public Date getVdate() {
return vdate;
}
//get set
}
新增加两条自定义的查询
@NoRepositoryBean
public interface BaseRepository<T,ID extends Serializable> extends JpaRepository<T,ID>,JpaSpecificationExecutor<T> {
//根据Query拿到对应的所有数据(不分页)
List<T> findByQuery(BaseQuery baseQuery);
//根据jpql与对应的参数拿到数据
List findByJpql(String jpql,Object... values);
}
public class BaseRepositoryImpl<T,ID extends Serializable> extends SimpleJpaRepository<T,ID> implements BaseRepository<T,ID> {
private final EntityManager entityManager;
//必需要实现父类的这个构造器
public BaseRepositoryImpl(Class<T> domainClass, EntityManager em) {
super(domainClass, em);
this.entityManager = em;
}
@Override
public List<T> findByQuery(BaseQuery baseQuery) {
//第一步:拿到所有高级查询条件
Specification spec = baseQuery.createSpecification();
//第二步:拿到排序的值
Sort sort = baseQuery.createSort();
//第三步:拿到数据返回
return super.findAll(spec, sort);
}
//select ... where xxx =? and yy =? ...
@Override
public List findByJpql(String jpql, Object... values) {
//第一步:创建Query对象
Query query = entityManager.createQuery(jpql);
//第二步:把值设置到Query对象中去
if (values!=null) {
for (int i = 0; i < values.length; i++) {
query.setParameter(i + 1, values[i]);
}
}
//第三步:返回数据
return query.getResultList();
}
}
public class BaseRepositoryFactoryBean<T extends Repository<S, ID>, S, ID extends Serializable> extends JpaRepositoryFactoryBean<T,S,ID> {
@Override
protected RepositoryFactorySupport createRepositoryFactory(EntityManager entityManager) {
return new MyRepositoryFactory<T,ID>(entityManager); //注:这里创建是我们的自定义类
}
//继承JpaRepositoryFactory后,把返回的对象修改成我们自己的实现
private static class MyRepositoryFactory<T,ID extends Serializable> extends JpaRepositoryFactory {
private final EntityManager entityManager;
/**
* Creates a new {@link JpaRepositoryFactory}.
*
* @param entityManager must not be {@literal null}
*/
public MyRepositoryFactory(EntityManager entityManager) {
super(entityManager);
this.entityManager = entityManager;
}
//这里返回最后的功能对象
@Override
protected Object getTargetRepository(RepositoryInformation information) {
return new BaseRepositoryImpl<T,ID>((Class<T>)information.getDomainType(),entityManager);
}
//确定功能对象的类型
@Override
protected Class<?> getRepositoryBaseClass(RepositoryMetadata metadata) {
return BaseRepositoryImpl.class;
}
}
}
较之前新增加一个条factory-class
<tx:annotation-driven transaction-manager="transactionManager" />
<jpa:repositories base-package="com.xuxusheng.aisell.repository"
entity-manager-factory-ref="entityManagerFactory"
transaction-manager-ref="transactionManager"
factory-class="com.xuxusheng.aisell.repository.BaseRepositoryFactoryBean"
/>
public class PurchasebillitemQuery extends BaseQuery {
//开始时间
private Date beginDate;
//结束时间
private Date endDate;
//状态
private Integer status;
//分组条件(默认供应商分组)
private Integer groupBy = 1;
private Long isdelete;
@Override
public Specification createSpecification() {
Date tempDate = null;
if(endDate!=null) {
tempDate = DateUtils.addDays(endDate, 1);
}
Specification<Purchasebillitem> specification = Specifications.<Purchasebillitem>and()
.ge(beginDate!=null,"bill.vdate",beginDate)
//注意:这里设计成小于
.lt(tempDate!=null,"bill.vdate",tempDate)
.eq(status!=null,"bill.status",status)
.eq(true,"isdelete",1L)
.build();
return specification;
}
@Override
public Specification createSpecificationRe() {
Date tempDate = null;
if(endDate!=null) {
tempDate = DateUtils.addDays(endDate, 1);
}
Specification<Purchasebillitem> specification = Specifications.<Purchasebillitem>and()
.ge(beginDate!=null,"bill.vdate",beginDate)
//注意:这里设计成小于
.lt(tempDate!=null,"bill.vdate",tempDate)
.eq(status!=null,"bill.status",status)
.eq(true,"isdelete",2L)
.build();
return specification;
}
public Specification createSpecification2() {
Specification<Purchasebillitem> specification = Specifications.<Purchasebillitem>and().build();
return specification;
}
//查询的参数
private List<Object> params = new ArrayList<>();
//获取到where条件的JPQL
public String getWhereJpql(){
StringBuilder jpql = new StringBuilder();
if(beginDate!=null){
jpql.append(" and o.bill.vdate >= ? ");
params.add(beginDate);
}
if(endDate!=null){
//返回新的值,就是加一天的值
Date tempDate = DateUtils.addDays(endDate, 1);
jpql.append(" and o.bill.vdate < ? ");
params.add(tempDate);
}
if(status!=null){
jpql.append(" and o.bill.status =? ");
params.add(status);
}
return jpql.toString().replaceFirst("and","where");
}
//获取到分组的字符串
public String getGroupByStr(){
if(groupBy==1){
//根据采购员分组
return "o.bill.buyer.username";
}else if(groupBy==2){
//根据月份分组
return "MONTH(o.bill.vdate)";
}else{
//根据供应商分组
return "o.bill.supplier.name";
}
}
@DateTimeFormat(pattern = "yyyy-MM-dd")
public void setEndDate(Date endDate) {
this.endDate = endDate;
}
//get set
//根据Query拿到对应的所有数据(不分页)
List<T> findByQuery(BaseQuery baseQuery);
//根据jpql与对应的参数拿到数据
List findByJpql(String jpql,Object... values);
@Service
public class PurchasebillitemServiceImpl extends BaseServiceImpl<Purchasebillitem,Long> implements IPurchasebillitemService{
@Autowired
private PurchasebillitemRepository purchasebillitemRepository;
@Override
public List<PurchaseBillItemVo> findItems(PurchasebillitemQuery query) {
//获取到所有数据
List<Purchasebillitem> items = purchasebillitemRepository.findByQuery(query);
//准备vo集合,用到装数据
List<PurchaseBillItemVo> vos = new ArrayList<>();
for (Purchasebillitem item : items) {
//把item变成vo,放到vos里面
PurchaseBillItemVo vo = new PurchaseBillItemVo(item,query);
vos.add(vo);
}
return vos;
}
@Override
public List<ItemChartVo> findCharts(PurchasebillitemQuery query) {
//1.获取到分组的条件
String groupByStr = query.getGroupByStr();
//2.获取到相应的JPQL
String whereJpql = query.getWhereJpql();
//3.获取到JPQL中?对应的值
List<Object> params = query.getParams();
//注意;这里必需使用全限定名
String jpql = "select new com.xuxusheng.aisell.domain.vo.ItemChartVo("+groupByStr
+",sum(amount)) from Purchasebillitem o "+whereJpql+" group by "+groupByStr;
//如果我们获取单独的一些值,那么就会变成一个Object数组
List<ItemChartVo> vos = super.findByJpql(jpql,params.toArray());
return vos;
}
}
@Controller
@RequestMapping("/purchasebillitem")
public class PurchasebillitemController extends BaseController {
@Autowired
private IPurchasebillitemService purchasebillitemService;
@RequestMapping("/index")
public String index() {
return "purchasebillitem/index";
}
@RequestMapping("/findItems")
@ResponseBody
public List<PurchaseBillItemVo> page(PurchasebillitemQuery query) {
System.out.println(query);
return purchasebillitemService.findItems(query);
}
@RequestMapping("/findCharts")
@ResponseBody
public List<ItemChartVo> findChart(PurchasebillitemQuery itemQuery) {
return purchasebillitemService.findCharts(itemQuery);
}
}