修改报表展示方式,采用手风琴样式,增加面包屑导航

This commit is contained in:
falcon 2020-06-12 14:56:13 +08:00
parent 9f9eb79638
commit e61bc19123
10 changed files with 594 additions and 16 deletions

View File

@ -6,6 +6,7 @@ using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore.Internal; using Microsoft.EntityFrameworkCore.Internal;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using ReportService.Database; using ReportService.Database;
using ReportService.Models;
namespace ReportService.Controllers.api namespace ReportService.Controllers.api
{ {
@ -22,7 +23,7 @@ namespace ReportService.Controllers.api
/// </summary> /// </summary>
public string ReportPath { public string ReportPath {
get { get {
return Path.Combine(this.Env.ContentRootPath,"wwwroot/report"); return Path.Combine(this.Env.ContentRootPath,"wwwroot\\report");
} }
} }
@ -50,6 +51,37 @@ namespace ReportService.Controllers.api
return result; return result;
} }
/// <summary> /// <summary>
/// 获取树状架构的报表列表
/// </summary>
/// <returns>报表结构</returns>
public ReportListModel GetReportList(string rootPath = null) {
var result = new ReportListModel();
var cPath = Path.Combine(this.ReportPath,rootPath ?? "");
var dirs = Directory.GetDirectories(cPath);
foreach(var d in dirs) {
var sd = new ReportItem {
Name = d.Substring(d.LastIndexOf('\\') + 1),
Path = rootPath ?? "",
Type = ItemType.group,
};
result.Sub.Add(sd);
sd.Sub.AddRange(GetReportList(Path.Combine(sd.Path,sd.Name)).Sub);
}
var files = Directory.GetFiles(cPath,"*.html");
foreach(var f in files) {
var file = new System.IO.FileInfo(f);
if(file.Name.ToLower().EndsWith(".rpt.html")) {
continue;
}
result.Sub.Add(new ReportItem {
Name = file.Name.Substring(0,file.Name.IndexOf('.')),
Path = rootPath,
Type = ItemType.file,
});
}
return result;
}
/// <summary>
/// 获取模板内容显示模板页面 /// 获取模板内容显示模板页面
/// </summary> /// </summary>
/// <param name="fileName">模板文件名</param> /// <param name="fileName">模板文件名</param>

View File

@ -0,0 +1,53 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System.Text;
using System.Text.Json.Serialization;
namespace ReportService.Models
{
public class ReportListModel
{
[JsonPropertyName("s")]
public List<ReportItem> Sub { get; set; } = new List<ReportItem>();
}
/// <summary>
/// 报表项
/// </summary>
public class ReportItem
{
/// <summary>
/// 项类型
/// </summary>
[JsonPropertyName("t")]
public ItemType Type{ get; set; }
/// <summary>
/// 项名称
/// </summary>
[JsonPropertyName("n")]
public string Name { get; set; }
/// <summary>
/// 项路径
/// </summary>
[JsonPropertyName("p")]
public string Path { get; set; }
[JsonPropertyName("s")]
public List<ReportItem> Sub { get; set; } = new List<ReportItem>();
}
/// <summary>
/// 项目类型
/// </summary>
public enum ItemType
{
/// <summary>
/// 一个报表分组
/// </summary>
group = 1,
/// <summary>
/// 报表文件
/// </summary>
file = 2,
}
}

View File

@ -5,36 +5,60 @@
} }
</style> </style>
<div id="reportMain"> <div id="reportMain" class="row">
<ul class="menu-v reportForm" v-if="showReportList"> <div id="accd" class="col-3">
<li class="menu-item-v reportItem" v-for="m in reportList"> <div class="card" v-for="g in reportList.s" v-if="g.t==1">
<a class="nav-link" href="#" v-on:click="cli(m)">{{m}}</a> <div class="card-header">
<a class="card-link" data-toggle="collapse" :href="'#id'+g.n">{{g.n}}</a>
</div>
<div :id="'id'+g.n" class="collapse" data-parent="#accd">
<div class="card-body">
<ul class="list-group" v-for="f in g.s">
<li class="list-group-item list-group-item-action" v-if="f.t==2">
<a href="#" v-on:click="cli(g.n,f.p,f.n)">{{f.n}}</a>
</li> </li>
</ul> </ul>
<div id="rpPage" v-show="showPage"></div> </div>
</div>
</div>
</div>
<div class="col" v-show="showPage">
<ol class="breadcrumb">
<li class="breadcrumb-item">{{bread.p}}</li>
<li class="breadcrumb-item">{{bread.n}}</li>
</ol>
<div id="rpPage"></div>
</div>
</div> </div>
<script type="text/javascript"> <script type="text/javascript">
var vm = new Vue({ var vm = new Vue({
el: "#reportMain", el: "#reportMain",
data: { data: {
reportList: [], reportList: [],
url: myjs.urls.files, url: myjs.urls.reportList,
fileContentUrl: myjs.urls.fileContentUrl, fileContentUrl: myjs.urls.fileContentUrl,
showReportList: true, showReportList: true,
showPage: false, showPage: false,
bread: {
p: "",
n: "",
},
}, },
created() { created() {
$.get(this.url, function (d) { $.get(this.url, function (d) {
vm.reportList = d; vm.reportList = d;
var initReport = $.cookie("_initReport"); //var initReport = $.cookie("_initReport");
if (vm.reportList.indexOf(initReport) >= 0) { //if (vm.reportList.indexOf(initReport) >= 0) {
vm.cli(initReport); // vm.cli(initReport);
vm.showReportList = false; // vm.showReportList = false;
} //}
}); });
}, },
methods: { methods: {
cli(m) { cli(g, p, n) {
var m = p + "\\" + n;
this.bread.p = g;
this.bread.n = n;
$.get(this.fileContentUrl, { fileName: m }, function (h) { $.get(this.fileContentUrl, { fileName: m }, function (h) {
vm.showPage = true; vm.showPage = true;
$("#rpPage").html(h); $("#rpPage").html(h);

View File

@ -8,6 +8,7 @@
<link rel="stylesheet" href="~/css/site.css" /> <link rel="stylesheet" href="~/css/site.css" />
<script src="~/lib/jquery/dist/jquery.min.js"></script> <script src="~/lib/jquery/dist/jquery.min.js"></script>
<script src="~/lib/bootstrap/dist/js/bootstrap.bundle.min.js"></script> <script src="~/lib/bootstrap/dist/js/bootstrap.bundle.min.js"></script>
<script src="~/lib/bootstrap-collapse/bootstrap-collapse.js"></script>
<script src="~/lib/jquery.cookie/jquery.cookie.min.js"></script> <script src="~/lib/jquery.cookie/jquery.cookie.min.js"></script>
<script src="~/lib/vue/vue.min.js"></script> <script src="~/lib/vue/vue.min.js"></script>
<script src="~/js/site.js" asp-append-version="true"></script> <script src="~/js/site.js" asp-append-version="true"></script>

View File

@ -2,6 +2,7 @@
var myjs = { var myjs = {
urls: { urls: {
files: "/api/ReportApi/getreportfiles", files: "/api/ReportApi/getreportfiles",
reportList: "/api/ReportApi/GetReportList",
fileContentUrl: "/api/ReportApi/GetHtml", fileContentUrl: "/api/ReportApi/GetHtml",
reportUrl: "/api/ReportApi/GetPrint", reportUrl: "/api/ReportApi/GetPrint",
getresult: "/api/ReportApi/GetResult", getresult: "/api/ReportApi/GetResult",

View File

@ -0,0 +1,136 @@
/* =============================================================
* bootstrap-collapse.js v2.0.1
* http://twitter.github.com/bootstrap/javascript.html#collapse
* =============================================================
* Copyright 2012 Twitter, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ============================================================ */
!function ($) {
"use strict"
var Collapse = function (element, options) {
this.$element = $(element)
this.options = $.extend({}, $.fn.collapse.defaults, options)
if (this.options["parent"]) {
this.$parent = $(this.options["parent"])
}
this.options.toggle && this.toggle()
}
Collapse.prototype = {
constructor: Collapse
, dimension: function () {
var hasWidth = this.$element.hasClass('width')
return hasWidth ? 'width' : 'height'
}
, show: function () {
var dimension = this.dimension()
, scroll = $.camelCase(['scroll', dimension].join('-'))
, actives = this.$parent && this.$parent.find('.in')
, hasData
if (actives && actives.length) {
hasData = actives.data('collapse')
actives.collapse('hide')
hasData || actives.data('collapse', null)
}
this.$element[dimension](0)
this.transition('addClass', 'show', 'shown')
this.$element[dimension](this.$element[0][scroll])
}
, hide: function () {
var dimension = this.dimension()
this.reset(this.$element[dimension]())
this.transition('removeClass', 'hide', 'hidden')
this.$element[dimension](0)
}
, reset: function (size) {
var dimension = this.dimension()
this.$element
.removeClass('collapse')
[dimension](size || 'auto')
[0].offsetWidth
this.$element.addClass('collapse')
}
, transition: function (method, startEvent, completeEvent) {
var that = this
, complete = function () {
if (startEvent == 'show') that.reset()
that.$element.trigger(completeEvent)
}
this.$element
.trigger(startEvent)
[method]('in')
$.support.transition && this.$element.hasClass('collapse') ?
this.$element.one($.support.transition.end, complete) :
complete()
}
, toggle: function () {
this[this.$element.hasClass('in') ? 'hide' : 'show']()
}
}
/* COLLAPSIBLE PLUGIN DEFINITION
* ============================== */
$.fn.collapse = function (option) {
return this.each(function () {
var $this = $(this)
, data = $this.data('collapse')
, options = typeof option == 'object' && option
if (!data) $this.data('collapse', (data = new Collapse(this, options)))
if (typeof option == 'string') data[option]()
})
}
$.fn.collapse.defaults = {
toggle: true
}
$.fn.collapse.Constructor = Collapse
/* COLLAPSIBLE DATA-API
* ==================== */
$(function () {
$('body').on('click.collapse.data-api', '[data-toggle=collapse]', function (e) {
var $this = $(this), href
, target = $this.attr('data-target')
|| e.preventDefault()
|| (href = $this.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '') //strip for ie7
, option = $(target).data('collapse') ? 'toggle' : $this.data()
$(target).collapse(option)
})
})
}(window.jQuery);

View File

@ -0,0 +1,85 @@
<div id="findPerson">
<div id="para" class="reportFilter">
<input type="hidden" name="ProcedureName" v-model="ProcedureName" />
<input type="hidden" name="reportName" v-model="reportName" />
<input type="hidden" name="sqlStr" v-model="sqlStr" />
<input type="hidden" name="uid" v-model="uid" />
<input type="hidden" name="uName" v-model="uName" />
<!--以下部分为查询条件,根据实际需要修改-->
<label>姓名:<input name="name" value="" placeholder="输入姓名或留空" /></label>
<label>地址:<input name="address" value="" placeholder="输入地址数据" /></label>
<label>地址:<input name="marry" value="" placeholder="是否结婚" /></label>
<div class="btn-group">
<button class="btn btn-primary" v-on:click="find">查询</button>
<button class="btn btn-primary" v-on:click="print">打印</button>
<button class="btn btn-primary" v-on:click="down" v-if="result.length > 0">下载EXCEL</button>
</div>
<!--可修改部分结束-->
</div>
<div id="result" v-if="result.length > 0">
<!--以下部分为存储过程返回数据,根据实际需要修改-->
<table class="table reportTable" id="resultTable">
<thead>
<tr>
<th>姓名</th>
<th>年龄</th>
<th>性别</th>
<th>登录用户编号</th>
<th>登录用户名</th>
</tr>
</thead>
<tbody>
<tr v-for="i in result">
<td>{{i.name}}</td>
<td>{{i.age}}</td>
<td>{{i.sex}}</td>
<td>{{i.uid}}</td>
<td>{{i.Uname}}</td>
</tr>
</tbody>
</table>
<!--可修改部分结束-->
</div>
</div>
<script type="text/javascript">
var findPerson = new Vue({
el: "#findPerson",
data: {
//存储过程名称
ProcedureName: "example",
//报表名称
reportName: "报表1",
//除非你知道以下数据含义,否则不要修改
sqlStr: "",
url: myjs.urls.getresult,
result: [],
uid: "",
uName: "",
},
created() {
this.uid = myjs.getUId();
this.uName = myjs.getUName();
},
methods: {
find() {
var sql = myjs.createSql("#para");
this.sqlStr = sql;
console.log(sql);
myjs.post(this.url, { sql: sql }, function (d) {
findPerson.result = d;
});
},
print() {
var sql = myjs.createSql("#para");
this.sqlStr = sql;
myjs.print();
},
down() {
myjs.toExcel.tableToExcel("resultTable", this.reportName);
},
}
});
</script>

View File

@ -0,0 +1,82 @@
<div id="findPerson">
<div id="para" class="reportFilter">
<input type="hidden" name="ProcedureName" v-model="ProcedureName" />
<input type="hidden" name="reportName" v-model="reportName" />
<input type="hidden" name="sqlStr" v-model="sqlStr" />
<input type="hidden" name="uid" v-model="uid" />
<input type="hidden" name="uName" v-model="uName" />
<!--以下部分为查询条件,根据实际需要修改-->
<label>姓名:<input name="name" value="" placeholder="输入姓名或留空" /></label>
<label>地址:<input name="address" value="" placeholder="输入地址数据" /></label>
<label>地址:<input name="marry" value="" placeholder="是否结婚" /></label>
<button class="btn btn-primary" v-on:click="find">查询</button>
<button class="btn btn-primary" v-on:click="print">打印</button>
<button class="btn btn-primary" v-on:click="down" v-if="result.length > 0">下载EXCEL</button>
<!--可修改部分结束-->
</div>
<div id="result" v-if="result.length > 0">
<!--以下部分为存储过程返回数据,根据实际需要修改-->
<table class="table reportTable" id="resultTable">
<thead>
<tr>
<th>姓名</th>
<th>年龄</th>
<th>性别</th>
<th>登录用户编号</th>
<th>登录用户名</th>
</tr>
</thead>
<tbody>
<tr v-for="i in result">
<td>{{i.name}}</td>
<td>{{i.age}}</td>
<td>{{i.sex}}</td>
<td>{{i.uid}}</td>
<td>{{i.Uname}}</td>
</tr>
</tbody>
</table>
<!--可修改部分结束-->
</div>
</div>
<script type="text/javascript">
var findPerson = new Vue({
el: "#findPerson",
data: {
//存储过程名称
ProcedureName: "example",
//报表名称
reportName: "报表1",
//除非你知道以下数据含义,否则不要修改
sqlStr: "",
url: myjs.urls.getresult,
result: [],
uid: "",
uName: "",
},
created() {
this.uid = myjs.getUId();
this.uName = myjs.getUName();
},
methods: {
find() {
var sql = myjs.createSql("#para");
this.sqlStr = sql;
console.log(sql);
myjs.post(this.url, { sql: sql }, function (d) {
findPerson.result = d;
});
},
print() {
var sql = myjs.createSql("#para");
this.sqlStr = sql;
myjs.print();
},
down() {
myjs.toExcel.tableToExcel("resultTable", this.reportName);
},
}
});
</script>

View File

@ -0,0 +1,82 @@
<div id="findPerson">
<div id="para" class="reportFilter">
<input type="hidden" name="ProcedureName" v-model="ProcedureName" />
<input type="hidden" name="reportName" v-model="reportName" />
<input type="hidden" name="sqlStr" v-model="sqlStr" />
<input type="hidden" name="uid" v-model="uid" />
<input type="hidden" name="uName" v-model="uName" />
<!--以下部分为查询条件,根据实际需要修改-->
<label>姓名:<input name="name" value="" placeholder="输入姓名或留空" /></label>
<label>地址:<input name="address" value="" placeholder="输入地址数据" /></label>
<label>地址:<input name="marry" value="" placeholder="是否结婚" /></label>
<button class="btn btn-primary" v-on:click="find">查询</button>
<button class="btn btn-primary" v-on:click="print">打印</button>
<button class="btn btn-primary" v-on:click="down" v-if="result.length > 0">下载EXCEL</button>
<!--可修改部分结束-->
</div>
<div id="result" v-if="result.length > 0">
<!--以下部分为存储过程返回数据,根据实际需要修改-->
<table class="table reportTable" id="resultTable">
<thead>
<tr>
<th>姓名</th>
<th>年龄</th>
<th>性别</th>
<th>登录用户编号</th>
<th>登录用户名</th>
</tr>
</thead>
<tbody>
<tr v-for="i in result">
<td>{{i.name}}</td>
<td>{{i.age}}</td>
<td>{{i.sex}}</td>
<td>{{i.uid}}</td>
<td>{{i.Uname}}</td>
</tr>
</tbody>
</table>
<!--可修改部分结束-->
</div>
</div>
<script type="text/javascript">
var findPerson = new Vue({
el: "#findPerson",
data: {
//存储过程名称
ProcedureName: "example",
//报表名称
reportName: "报表1",
//除非你知道以下数据含义,否则不要修改
sqlStr: "",
url: myjs.urls.getresult,
result: [],
uid: "",
uName: "",
},
created() {
this.uid = myjs.getUId();
this.uName = myjs.getUName();
},
methods: {
find() {
var sql = myjs.createSql("#para");
this.sqlStr = sql;
console.log(sql);
myjs.post(this.url, { sql: sql }, function (d) {
findPerson.result = d;
});
},
print() {
var sql = myjs.createSql("#para");
this.sqlStr = sql;
myjs.print();
},
down() {
myjs.toExcel.tableToExcel("resultTable", this.reportName);
},
}
});
</script>

View File

@ -0,0 +1,82 @@
<div id="findPerson">
<div id="para" class="reportFilter">
<input type="hidden" name="ProcedureName" v-model="ProcedureName" />
<input type="hidden" name="reportName" v-model="reportName" />
<input type="hidden" name="sqlStr" v-model="sqlStr" />
<input type="hidden" name="uid" v-model="uid" />
<input type="hidden" name="uName" v-model="uName" />
<!--以下部分为查询条件,根据实际需要修改-->
<label>姓名:<input name="name" value="" placeholder="输入姓名或留空" /></label>
<label>地址:<input name="address" value="" placeholder="输入地址数据" /></label>
<label>地址:<input name="marry" value="" placeholder="是否结婚" /></label>
<button class="btn btn-primary" v-on:click="find">查询</button>
<button class="btn btn-primary" v-on:click="print">打印</button>
<button class="btn btn-primary" v-on:click="down" v-if="result.length > 0">下载EXCEL</button>
<!--可修改部分结束-->
</div>
<div id="result" v-if="result.length > 0">
<!--以下部分为存储过程返回数据,根据实际需要修改-->
<table class="table reportTable" id="resultTable">
<thead>
<tr>
<th>姓名</th>
<th>年龄</th>
<th>性别</th>
<th>登录用户编号</th>
<th>登录用户名</th>
</tr>
</thead>
<tbody>
<tr v-for="i in result">
<td>{{i.name}}</td>
<td>{{i.age}}</td>
<td>{{i.sex}}</td>
<td>{{i.uid}}</td>
<td>{{i.Uname}}</td>
</tr>
</tbody>
</table>
<!--可修改部分结束-->
</div>
</div>
<script type="text/javascript">
var findPerson = new Vue({
el: "#findPerson",
data: {
//存储过程名称
ProcedureName: "example",
//报表名称
reportName: "报表1",
//除非你知道以下数据含义,否则不要修改
sqlStr: "",
url: myjs.urls.getresult,
result: [],
uid: "",
uName: "",
},
created() {
this.uid = myjs.getUId();
this.uName = myjs.getUName();
},
methods: {
find() {
var sql = myjs.createSql("#para");
this.sqlStr = sql;
console.log(sql);
myjs.post(this.url, { sql: sql }, function (d) {
findPerson.result = d;
});
},
print() {
var sql = myjs.createSql("#para");
this.sqlStr = sql;
myjs.print();
},
down() {
myjs.toExcel.tableToExcel("resultTable", this.reportName);
},
}
});
</script>