devexpress 22.1.3 PivotGrid 结合.net6 MVC 做统计页面
效果图
主页面zyjkDetection.cshtml
@using Health.Model @using Health.Repository; @* For more information on enabling MVC for empty projects, visit https://go.microsoft.com/fwlink/?LinkID=397860 *@ @inject HealthDataContext db @{ ViewData["Title"] = "统计"; } <style type="text/css"> #sales { max-height: 570px; } .options { padding: 20px; margin-top: 20px; background-color: rgba(191, 191, 191, 0.15); } .caption { font-size: 18px; font-weight: 500; } .option { width: 24%; display: inline-block; margin-top: 10px; } .options-container { display: flex; align-items: center; } .demo-tabs > .el-tabs__content { padding: 5px; color: #6b778c; font-size: 32px; font-weight: 600; } .el-main { --el-main-padding: 20px 20px 0px 20px; display: block; flex: 1; flex-basis: auto; overflow: auto; box-sizing: border-box; padding: var(--el-main-padding); } </style> <div id="app" class="app-main" style="height:100%"> </div> <script type="text/x-template" id="appTemplate"> <el-container style="height:100%"> <el-aside width="300px"> <el-tree style="padding: 15px 0px 3px 5px" :data="treeData" :props="defaultProps" v-on:node-click="handleNodeClick" node-key="title" :default-expanded-keys="['全部']" highlight-current="true"/> </el-aside> <el-container> <el-main> <el-form :inline="true" :model="formFilter" class="demo-form-inline"> <el-form-item label="年份:"> <el-select v-model="formFilter.year" placeholder="请选择" style="width:80px"> <el-option v-for="item in yearList" :value="item" :key='item' >{{ item }}</el-option> </el-select> </el-form-item> <el-form-item label="行政区:"> <el-select v-model="formFilter.region" placeholder="请选择" style="width:100px"> <el-option v-for="item in regionList" :value="item.RegionName" :key='item.RegionName' >{{ item.RegionName }}</el-option> </el-select> </el-form-item> <el-form-item label="企业规模:"> <el-select v-model="formFilter.enterpriseScale" placeholder="请选择" style="width:80px"> <el-option v-for="item in enterpriseScalerList" :value="item.name" :key='item.name' >{{ item.name }}</el-option> </el-select> </el-form-item> <el-form-item label="体检类别:"> <el-select v-model="formFilter.category" placeholder="请选择" style="width:120px"> <el-option v-for="item in categoryList" :value="item.id" :key='item.id' :label="item.name"/> </el-select> </el-form-item> <el-form-item label="危害因素类别:"> <el-select v-model="formFilter.zybwhysType" placeholder="请选择" style="width:120px"> <el-option v-for="item in zybwhysTypeList" :value="item.name" :key='item.name' >{{ item.name }}</el-option> </el-select> </el-form-item> <el-form-item label="统计参数:"> <el-select v-model="formFilter.parameter" placeholder="请选择" style="width:180px" multiple collapse-tags collapse-tags-tooltip> <el-option v-for="item in parameterList " :value="item" :key='item' >{{ item }}</el-option> </el-select> </el-form-item> <el-form-item> <el-button type="primary" v-on:click="onSubmit">查询</el-button> </el-form-item> </el-form> <el-tabs v-model="activeName" class="demo-tabs" v-on:tab-click="handleClick"> <el-tab-pane label="统计表格" name="first"> <div v-loading="loading"> <iframe ref='iframe' frameborder='0' width='100%' :height='gvHeight' scrolling='none' v-bind:src='plantAreaUrl'></iframe> </div> </el-tab-pane> <el-tab-pane label="统计图" name="second"> <el-form-item label=""> <el-select v-model="parameter2" placeholder="请选择" style="width:180px" > <el-option v-for="item in formFilter.parameter " :value="item" :key='item' >{{ item }}</el-option> </el-select> </el-form-item> <div v-loading="loading2"> <div v-bind:style="bindStyle" id="chartStatisticsPlantArea"></div> </div> </el-tab-pane> </el-tabs> </el-main> </el-container> </el-container> </script> <script> const App = { template: "#appTemplate", data: function () { return { loading:true, loading2:true, formFilter: { year:2021, enterpriseScale:'全部', region:'全市', zybwhysType:'全部', parameter:['应检','实检'], category:0, }, parameter2:'应检', zybwhysTypeList:[], parameterList:['应检','实检','未见异常','应复查','实际复查'], activeName:'first', regionList:[], yearList:[2020,2021], enterpriseScalerList:[{id:1,name:'全部'},{id:1,name:'大型'},{id:2,name:'中型'},{id:31,name:'小型'},{id:4,name:'微型'},{id:5,name:'不详'},{id:6,name:'空白'}], defaultProps : { children: 'children', label: 'title', }, selectedItem:null, treeData:[], chart: null, plantAreaUrl:'', gvHeight:600, categoryList:[{id:0,name:'全部'},{id:1,name:'上岗体检'},{id:2,name:'岗中体检'},{id:3,name:'离岗体检'}] }; }, computed: { plantAreaUrl2 () { //let url = util.baseHost() + 'Farm/Statistics/PlantArea?token=' + Cookies.get('token'); //let url ='/Health/Occupational/jhtjPivotGrid?'; let url = '@Url.Action("zyjkDetectionPivotGrid")?' if (this.formFilter.year) { url += '&year=' + this.formFilter.year; } if (this.formFilter.enterpriseScale) { url += '&enterpriseScale=' + this.formFilter.enterpriseScale; } if (this.formFilter.region) { url += '®ion=' + this.formFilter.region; } if (this.formFilter.zybwhysType) { url += '&zybwhysType=' + this.formFilter.zybwhysType; } if (this.formFilter.parameter) { url += '¶meter=' + this.formFilter.parameter.toString(); } if (this.selectedItem) { url += '&classCode=' + this.selectedItem.id; } if (this.formFilter.category) { url += '&category=' + this.formFilter.category; } //console.log('url',url); return url; }, bindStyle: function () { var that = this; return { 'height': '' + (that.gvHeight-50) + 'px', 'width':'100%' //'overflowY': 'auto', //'loverflowX': 'hidden' } } }, watch: { 'formFilter.parameter' (value) { console.log('formFilter.parameter',value) this.parameter2=value[0]; }, 'parameter2' (value) { console.log('parameter2',value) this.loadChart(); } }, created:function(){ this.getTree(); this.getYearList(); this.getRegionList(); this.getZybwhysTypeList(); this.onSubmit(); }, mounted:function () { var that=this; let iframe = that.$refs.iframe; //console.log("iframe",iframe) if (iframe) { if (iframe.attachEvent) { iframe.attachEvent('onload', function () { that.loading=false; }); } else { iframe.onload = function () { that.loading=false; }; } } that.gvHeight= window.innerHeight - 288; if(window.innerWidth<1800){ that.gvHeight= window.innerHeight - 288-50; } that.$nextTick(function () { window.addEventListener('resize', function () { //1539*1033 //console.log(window.innerHeight,window.innerWidth); that.gvHeight= window.innerHeight - 288; var width=window.innerWidth; if(width<1800){ that.gvHeight= window.innerHeight - 288-50; } let chart = that.chart; if (chart) { chart.resize(); } }); }); //that.gvHeight= window.innerHeight - 335; // let chart = that.chart; // if (chart) { // chart.resize(); // } // window.onresize = function temp() { // that.gvHeight= window.innerHeight - 335; // let chart = that.chart; // if (chart) { // chart.resize(); // } //} }, methods: { onSubmit(){ this.plantAreaUrl= this.plantAreaUrl2; this.loadChart(); }, handleClick(clickData){ //console.log('clickData',clickData) var that = this; that.loadChart(); }, handleNodeClick(clickData) { this.selectedItem = clickData; this.onSubmit(); //console.log('clickData',clickData) //console.log('selectedItem',this.selectedItem) }, getRegionList() { var that = this; var pms={} var arr=[] var url = '@Url.Action("RegionAllList", "Region")'; $http({ url: url, method: 'get', params: pms }).then(function (response) { //console.log('RegionAllList', response) if (response.data.data) { that.regionList = response.data.data; that.regionList.unshift({RegionName:'全市',RegionId:0}) }else{ that.regionList=[] } }) }, getYearList() { var that = this; var pms={} var arr=[] var url = '@Url.Action("ZybwhysContactNumberYearList", "Occupational")'; $http({ url: url, method: 'get', params: pms }).then(function (response) { //console.log('YearList', response) if (response.data.data) { that.yearList = response.data.data; }else{ that.yearList=[] } }) }, getZybwhysTypeList() { var that = this; var pms={} var arr=[] var url = '@Url.Action("ZybwhysTypeList", "Occupational")'; $http({ url: url, method: 'get', params: pms }).then(function (response) { //console.log('zybwhysTypeList', response) if (response.data.data) { that.zybwhysTypeList = response.data.data; that.zybwhysTypeList.unshift({name: "全部",code:0 }) that.zybwhysTypeList.push({name: "其他",code:'JCQT' }) }else{ that.zybwhysTypeList=[] } }) }, getTree() { var that = this; var pms={} var arr=[] var url = '@Url.Action("Tree", "Occupational")'; $http({ url: url, method: 'get', params: pms }).then(function (response) { //console.log('Tree', response) if (response.data) { that.treeData = response.data; }else{ that.treeData=[] } }) }, loadChart () { this.loading2=true; if (this.chart) { this.chart.dispose(); } let params = { }; if (this.formFilter.year) { params.year=this.formFilter.year; } if (this.formFilter.enterpriseScale) { params.enterpriseScale=this.formFilter.enterpriseScale; } if (this.formFilter.region) { params.region=this.formFilter.region; } if (this.formFilter.zybwhysType) { params.zybwhysType=this.formFilter.zybwhysType; } if (this.formFilter.parameter) { params.parameter=this.formFilter.parameter.toString(); } if (this.selectedItem) { params.classCode=this.selectedItem.id; } if (this.formFilter.category) { params.category=this.formFilter.category; } console.log('params',params); var url = '@Url.Action("zyjkDetectionList2", "Occupational")'; var that=this; $http({ url:url, method: 'get', params: params }).then(function (response){ console.log('zyjkDetectionList2',response) let data = response.data; // $("#" + 'chartStatisticsPlantArea').height(600); let chart = echarts.init(document.getElementById('chartStatisticsPlantArea'), 'light'); var namePms="Code2Name"; if(that.formFilter.zybwhysType=="全部"){ namePms="Code1Name" } var regionPms="TownName"; if(that.formFilter.region=="全市"){ regionPms="RegionName" } let nameList = []; let regionList = []; for (let i in data) { let name = data[i][namePms]; let regionName = data[i][regionPms]; if (nameList.indexOf(name) === -1) { nameList.push(name); } if (regionList.indexOf(regionName) === -1) { regionList.push(regionName); } } //let labelOption = { // normal: { // show: true, // position: 'insideBottom', // distance: 15, // align: 'left', // verticalAlign: 'middle', // rotate: 90, // formatter: '{c} {name|{a}}', // fontSize: 16, // rich: { // name: { // textBorderColor: '#fff' // } // } // } //}; var parameterPms=""; parameterPms= GetParameterName(that.parameter2); let series = []; for (let i in nameList) { let sItem = { name: nameList[i], type: 'bar', stack: '叠加', //barGap: 0, //label: labelOption, data: [] }; for (let j in regionList) { let area = 0; for (let k in data) { let name = data[k][namePms]; let regionName = data[k][regionPms]; if (regionList[j] === regionName&& nameList[i] === name ) { area += formatTwoDecimalPlaces(data[k][parameterPms]); } } sItem.data.push(area); } series.push(sItem); } console.log('series',series); let yAxisName=""; const option = { tooltip: { trigger: 'axis', formatter: function (data) { return TooltipFormatter(data); } //axisPointer: { // type: 'shadow' //} }, legend: { type: 'scroll', left: 'center', data: nameList }, grid: { top:'5%', left: '3%', right: '4%', bottom: '40px', containLabel: true, }, toolbox: { show: false, left: 'right', top: 'top', feature: { // mark: {show: true}, // dataView: {show: true, readOnly: false}, // magicType: {show: true, type: ['line', 'bar', 'stack', 'tiled']}, // restore: {show: true}, //saveAsImage: {show: true} } }, calculable: true, xAxis: [ { type: 'category', axisLabel: { interval: 0, rotate: 40 }, axisTick: {show: false}, data: regionList } ], yAxis: [ { name: yAxisName, type: 'value' } ], series: series }; chart.setOption(option,true); //console.log('option',option); that.chart = chart; that.loading2=false; }); }, } } function GetParameterName(value){ var englishName=''; switch(value) { case '应检': englishName='PlanNumber'; break; case '实检': englishName='RealNumber'; break; case '未见异常': englishName='NormalNumber';break; case '应复查': englishName='PlanReviewNumber'; break; case '实际复查': englishName='RealReviewNumber'; break; } return englishName; } function TooltipFormatter(data) { console.log('TooltipFormatter',data); // var seriesNames = []; var formateStrings = []; var formateString = ""; if (data.length > 0) { formateStrings.push(data[0].axisValue + "<br/>"); var j = 1; for (i in data) { var item = data[i]; //seriesNames.push(item.seriesName); if (item.value) { if (j % 3 == 0) { formateStrings.push(item.marker + item.seriesName + ": " + item.value + "<br/>"); j++; } else if(j % 3 == 1) { formateStrings.push(item.marker + item.seriesName + ": " + item.value ); j++; }else if(j % 3 ==2) { formateStrings.push(item.marker + item.seriesName + ": " + item.value); j++; } } } formateString = formateStrings.join(" "); return formateString; } } function ToolboxDataView(opt) { var axisData = opt.xAxis[0].data; //坐标数据 var series = opt.series; //折线图数据 var tdHeads = '<td style="padding: 0 10px">年份</td>'; //表头第一列 var tdBodys = ''; //表数据 //组装表头 for (var i = 0; i < series.length; i++) { tdHeads += '<td style="padding: 0 10px">' + series[i].name + '</td>'; } var table = '<table border="1" class="table-bordered table-striped" style="width:100%;text-align:center" ><tbody><tr>' + tdHeads + ' </tr>'; //组装表数据 //行数 for (var i = 0; i < axisData.length; i++) { //列数 for (var j = 0; j < series.length ; j++) { var temp = series[j].data[i]; if (temp != null && temp != undefined) { tdBodys += '<td>' + formatTwoDecimalPlaces(temp) + '</td>'; } else { tdBodys += '<td></td>'; } } table += '<tr><td style="padding: 0 10px">' + axisData[i] + '</td>' + tdBodys + '</tr>'; tdBodys = ''; } table += '</tbody></table>'; return table; } const app = Vue.createApp(App); </script>
部分页:zyjkDetectionPivotGrid.cshtml
@using Health.Model @using Health.Repository; @* For more information on enabling MVC for empty projects, visit https://go.microsoft.com/fwlink/?LinkID=397860 *@ @inject HealthDataContext db @{ Layout = "_DevExtremeLayout"; //string region = ViewBag.region; //var showRegion = false; //if (region=="全市") //{ // showRegion = true; //} } <style type="text/css"> #sales { max-height: 570px; } .options { padding: 20px; margin-top: 20px; background-color: rgba(191, 191, 191, 0.15); } .caption { font-size: 18px; font-weight: 500; } .option { width: 24%; display: inline-block; margin-top: 10px; } .options-container { display: flex; align-items: center; } </style> @(Html.DevExtreme().PivotGrid() .ID("pivotgrid") .AllowFiltering(true) .AllowSorting(true) .AllowSortingBySummary(true) .Height(600) .ShowBorders(true) .HeaderFilter(h => h .AllowSearch(true) .ShowRelevantValues(true) .Width(300) .Height(400) ) @* .FieldChooser(f => f.AllowSearch(true))*@ .FieldChooser(f=>f.Enabled(false)) .FieldPanel(f => f .ShowFilterFields(false) .AllowFieldDragging(false) .Visible(true) ) .DataSource(d => d .Store(s => s.Mvc().Controller("Occupational").LoadAction("zyjkDetectionList2").LoadParams(new{year=ViewBag.year, enterpriseScale=ViewBag.enterpriseScale,region=ViewBag.region,zybwhysType=ViewBag.zybwhysType,parameter=ViewBag.parameter, classCode=ViewBag.classCode,category=ViewBag.category})) .Fields(fields => { if(ViewBag.zybwhysType=="全部"){ fields.Add() .DataField("Code1Name") .Caption("职业病危害因素分类") .Area(PivotGridArea.Column) .SortOrder(SortOrder.Desc); }else{ fields.Add() .DataField("Code2Name") .Caption("职业病危害因素名称") .Area(PivotGridArea.Column) .SortOrder(SortOrder.Desc); } if( ViewBag.region=="全市"){ fields.Add() .DataField("RegionName") .Caption("区") .Area(PivotGridArea.Row) .SortOrder(SortOrder.Desc); } fields.Add() .DataField("TownName") .Caption("街镇") .Area(PivotGridArea.Row); if( Array.IndexOf(ViewBag.parameter.Split(','),"应检")>-1){ fields.Add() .DataField("PlanNumber") .Caption("应检") .Area(PivotGridArea.Data) .SummaryType(SummaryType.Sum); } if(Array.IndexOf(ViewBag.parameter.Split(','),"实检")>-1){ fields.Add() .DataField("RealNumber") .Caption("实检") .Area(PivotGridArea.Data) .SummaryType(SummaryType.Sum); } if(Array.IndexOf(ViewBag.parameter.Split(','),"未见异常")>-1){ fields.Add() .DataField("NormalNumber") .Caption("未见异常") .Area(PivotGridArea.Data) .SummaryType(SummaryType.Sum); } if(Array.IndexOf(ViewBag.parameter.Split(','),"应复查")>-1){ fields.Add() .DataField("PlanReviewNumber") .Caption("应复查") .Area(PivotGridArea.Data) .SummaryType(SummaryType.Sum); } if( Array.IndexOf(ViewBag.parameter.Split(','),"实际复查")>-1){ fields.Add() .DataField("RealReviewNumber") .Caption("实际复查") .Area(PivotGridArea.Data) .SummaryType(SummaryType.Sum); } }) ) ) <script> $(function(){ setHeight(); $(window).resize(function(){ setHeight() }) }) function setHeight(){ var containerHeight = window.innerHeight; //console.log('containerHeight',containerHeight); $("#pivotgrid").height(containerHeight); $("#pivotgrid").dxPivotGrid("updateDimensions"); } </script> @*<div class="options"> <div class="caption">Options</div> <div class="options-container"> <div class="option"> @(Html.DevExtreme().CheckBox() .Text("Allow Search") .Value(true) .OnValueChanged(@<text> function(data) { $("#pivotgrid").dxPivotGrid("instance").option("headerFilter.allowSearch", data.value); } </text>) ) </div> <div class="option"> @(Html.DevExtreme().CheckBox() .Text("Show Relevant Values") .Value(true) .OnValueChanged(@<text> function(data) { $("#pivotgrid").dxPivotGrid("instance").option("headerFilter.showRelevantValues", data.value); } </text>) ) </div> </div> </div>*@
DEV自动生成的布局页,做一些删减
<!DOCTYPE html> <html> <head> <meta name="viewport" content="width=device-width, initial-scale=1"> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="description" content=""> <meta name="author" content=""> @* <title>Health_Web</title>*@ <link href="~/favicon.ico" rel="shortcut icon" type="image/x-icon" /> @* Uncomment to use the HtmlEditor control *@ @* <script src="https://unpkg.com/devextreme-quill@21_2/dist/dx-quill.min.js"></script> *@ @* Uncomment to use the Gantt control *@ @*<link href="~/css/devextreme/dx-gantt.css" rel="stylesheet" />*@ @* Uncomment to use the Diagram control *@ @*<link href="~/css/devextreme/dx-diagram.css" rel="stylesheet" />*@ <link href="~/css/devextreme/bootstrap.css" rel="stylesheet" /> <link href="~/css/devextreme/dx.common.css" rel="stylesheet" /> @* Predefined themes: https://js.devexpress.com/DevExtreme/Guide/Themes_and_Styles/Predefined_Themes/ *@ <link href="~/css/devextreme/dx.light.css" rel="stylesheet" /> @* Uncomment to use the Gantt control *@ @*<script src="~/js/devextreme/dx-gantt.js"></script>*@ @* Uncomment to use the Diagram control *@ @*<script src="~/js/devextreme/dx-diagram.js"></script>*@ <script src="~/js/devextreme/jquery.js"></script> <script src="~/js/devextreme/bootstrap.js"></script> @* Uncomment to use Globalize for localization *@ @* Docs: https://docs.devexpress.com/AspNetCore/400577#globalize *@ @*<script src="~/js/devextreme/cldr.js"></script>*@ @*<script src="~/js/devextreme/cldr/event.js"></script>*@ @*<script src="~/js/devextreme/cldr/supplemental.js"></script>*@ @*<script src="~/js/devextreme/cldr/unresolved.js"></script>*@ @*<script src="~/js/devextreme/globalize.js"></script>*@ @*<script src="~/js/devextreme/globalize/message.js"></script>*@ @*<script src="~/js/devextreme/globalize/number.js"></script>*@ @*<script src="~/js/devextreme/globalize/currency.js"></script>*@ @*<script src="~/js/devextreme/globalize/date.js"></script>*@ @* Uncomment to enable client-side export *@ @*<script src="~/js/devextreme/jszip.js"></script>*@ <script src="~/js/devextreme/dx.all.js"></script> @* Uncomment to provide geo-data for the VectorMap control *@ @* Docs: https://js.devexpress.com/DevExtreme/Guide/Widgets/VectorMap/Providing_Data/#Data_for_Areas *@ @*<script src="~/js/devextreme/vectormap-data/world.js"></script>*@ <script src="~/js/devextreme/aspnet/dx.aspnet.mvc.js"></script> <script src="~/js/devextreme/aspnet/dx.aspnet.data.js"></script> <script src="~/js/devextreme/localization/dx.messages.zh.js"></script> </head> <script> DevExpress.localization.locale("zh"); </script> <body> @* <nav class="navbar navbar-dark bg-dark fixed-top navbar-expand-md"> <a class="navbar-brand" href="/">Health_Web</a> <button type="button" class="navbar-toggler" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar"> <span class="navbar-toggler-icon"></span> </button> <div id="navbar" class="collapse navbar-collapse"> <ul class="navbar-nav mr-auto"> <li class="active nav-item"><a href="#" class="nav-link">Home</a></li> <li class="nav-item"><a href="#about" class="nav-link">About</a></li> <li class="nav-item"><a href="#contact" class="nav-link">Contact</a></li> </ul> </div> </nav>*@ @* <main role="main" class="container"> </main>*@ @RenderBody() </body> </html>
后端部分:
public IActionResult zyjkDetection() { return View(); } public IActionResult zyjkDetectionPivotGrid(string? enterpriseScale, int? year = null, string? region = null, string? zybwhysType = null, string? parameter = null, string? classCode = null, int? category=null) { //string[] strArray = parameter.Split(','); ViewBag.year = year; ViewBag.enterpriseScale = enterpriseScale; ViewBag.region = region; ViewBag.zybwhysType = zybwhysType; ViewBag.parameter = parameter; ViewBag.classCode = classCode; ViewBag.category = category; return View(); } //职业健康监护情况 public async Task<IActionResult> zyjkDetectionList2(string? enterpriseScale, int? year = null, string? region = null, string? zybwhysType = null, string? parameter = null, string? classCode = null, int? category = null) { var query = from z in this.db.TZyjkDetections join c in this.db.TCompanies on z.SerialId equals c.SerialId join r in this.db.TRegions on c.RegionId equals r.RegionId where z.Code1Navigation != null && z.Code2Navigation != null select new { z.Id, z.SerialId, Code1Name = z.Code1Navigation == null ? "" : z.Code1Navigation.Name,//危害因素类别一级 Code2Name = z.Code2Navigation == null ? "" : z.Code2Navigation.Name, //z.Description, z.Category, z.PlanNumber, z.RealNumber, z.NormalNumber, z.ExceptionNumber, z.PlanReviewNumber, z.RealReviewNumber, z.OccupationalContraindication, z.SuspectedOccupationalDisease, r.RegionName, c.TownName, c.ReportYear, c.EnterpriseScale,//企业类型 c.IndustryCategory, r.Seq }; if (year != null) { query = query.Where(d => d.ReportYear == year); } if (enterpriseScale != "全部") { query = query.Where(d => d.EnterpriseScale == enterpriseScale); } if (region != null && region != "全市") { query = query.Where(d => d.RegionName == region); } if (zybwhysType != null && zybwhysType != "全部") { query = query.Where(d => d.Code1Name == zybwhysType); } if (classCode != null && classCode != "0") { query = query.Where(d => d.IndustryCategory == classCode); } if (category != null && category != 0) { query = query.Where(d => d.Category == category); } //var data= query.Skip(1).Take(1000).ToList(); //var data = await query.ToListAsync();//.OrderBy(d=>d.Seq) var outData = from d in query group d by new { d.RegionName, d.TownName, d.Code1Name, d.Code2Name } into g select new { g.Key.Code1Name, g.Key.TownName, g.Key.Code2Name, g.Key.RegionName, PlanNumber = g.Sum(d => d.PlanNumber), RealNumber = g.Sum(d => d.RealNumber), NormalNumber = g.Sum(d => d.NormalNumber), PlanReviewNumber = g.Sum(d => d.PlanReviewNumber), RealReviewNumber = g.Sum(d => d.RealReviewNumber), }; var outList = await outData.ToListAsync(); return Json(outList); }
注意数据大的时候要:
1后端数据统计,把数据减到最少,前端只做数据展示;
2配置响应压缩
https://www.cnblogs.com/hao-1234-1234/p/16627966.html
3添加(唯一或非唯一)索引
--------------------------------------------------------------------
官方文档:
新建DEV项目
https://docs.devexpress.com/AspNetCore/401026/devextreme-based-controls/get-started/configure-a-visual-studio-project#complete-the-project-configuration
简单案例
https://demos.devexpress.com/ASPNetCore/Demo/PivotGrid/LayoutCustomization/NetCore/Light/
PivotGrid 结合 js脚本,做一些动态变化
https://docs.devexpress.com/AspNetCore/401155/devextreme-based-controls/concepts/razor-syntax/call-methods
PivotGrid 属性、方法、事件文档
https://js.devexpress.com/DevExtreme/ApiReference/UI_Components/dxPivotGrid/
英文转中文
https://docs.devexpress.com/DevExtremeAspNetMvc/400706/concepts/localization
DevExpress.localization.locale("zh");