深度优先

这个家伙好懒,除了文章什么都没留下

0%

借鉴自:使用JavaScript把页面上的表格导出为Excel文件

地址:https://www.cnblogs.com/zhuxinghan/p/6063193.html

JavaScript版的:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title></title>
<meta charset="utf-8" />
<style>
/* 此样式仅用于浏览器页面效果,Excel不会分离表格边框,不需要此样式 */
table {
border-collapse: collapse;
}
</style>
</head>
<body>
<!-- 设置border="1"以显示表格框线 -->
<table border="1">
<!-- caption元素可以生成表标题,其单元格列跨度为表格的列数 -->
<caption>学生成绩表</caption>
<tr>
<!-- 可以使用rowspan和colspan来合并单元格 -->
<th rowspan="2">编号</th>
<th rowspan="2">学号</th>
<th rowspan="2">姓名</th>
<th rowspan="2">性别</th>
<th rowspan="2">年龄</th>
<th colspan="3">成绩</th>
</tr>
<tr>
<th>语文</th>
<th>数学</th>
<th>英语</th>
</tr>
<tr>
<td>1</td>
<td>2016001</td>
<td>张三</td>
<td>男</td>
<td>13</td>
<td>85</td>
<td>94</td>
<td>77</td>
</tr>
<tr>
<td>2</td>
<td>2016002</td>
<td>李四</td>
<td>女</td>
<td>12</td>
<td>96</td>
<td>84</td>
<td>89</td>
</tr>
</table>

<a>导出表格</a>

<script>
// 使用outerHTML属性获取整个table元素的HTML代码(包括<table>标签),然后包装成一个完整的HTML文档,设置charset为urf-8以防止中文乱码
var html = "<html><head><meta charset='utf-8' /></head><body>" + document.getElementsByTagName("table")[0].outerHTML + "</body></html>";
// 实例化一个Blob对象,其构造函数的第一个参数是包含文件内容的数组,第二个参数是包含文件类型属性的对象
var blob = new Blob([html], { type: "application/vnd.ms-excel" });
var a = document.getElementsByTagName("a")[0];
// 利用URL.createObjectURL()方法为a元素生成blob URL
a.href = URL.createObjectURL(blob);
// 设置文件名
a.download = "学生成绩表.xls";
</script>
</body>
</html>

Angular版的,其实也差不多,只是构建一个table:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
exportCSV(value, columns, exportFilename) {
const data = value;
let table = '<table><tr>';
// headers
for (let i = 0; i < columns.length; i++) {
table += `<td>${columns[i]}</td>`
}
table += '</tr>'
data.forEach((record) => {
table += '<tr>';
for (let i_1 = 0; i_1 < columns.length; i_1++) {
table += `<td>${record[columns[i_1]]}</td>`;
}
table += '</tr>'
});
table += '</table>'

// 使用outerHTML属性获取整个table元素的HTML代码(包括<table>标签),然后包装成一个完整的HTML文档,设置charset为urf-8以防止中文乱码
var html = "<html><head><meta charset='utf-8' /></head><body>" + table + "</body></html>";
console.log(html);
// 实例化一个Blob对象,其构造函数的第一个参数是包含文件内容的数组,第二个参数是包含文件类型属性的对象
var blob = new Blob([html], { type: "application/vnd.ms-excel" });

if (window.navigator.msSaveOrOpenBlob) {
navigator.msSaveOrOpenBlob(blob, 'Sheet1.xls');
} else {
const link = document.createElement('a');
link.style.display = 'none';
document.body.appendChild(link);
if (link.download !== undefined) {
link.setAttribute('href', URL.createObjectURL(blob));
link.setAttribute('download','Sheet1.xls');
link.click();
}
document.body.removeChild(link);
}
}

导出CSV,其实个导出Excel差不多,只是改下属性,数据类型:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
analysisExportCSV(value, columns, exportFilename) {
const data = value;
let csv = '\ufeff';
// headers
const columnsData = [
'XXXX表头XXXX',
'XXXX表头XXXX',
'XXXX表头XXXX',
'XXXX表头XXXX',
];
for (let i = 0; i < columnsData.length; i++) {
const column = columnsData[i];
csv += '"' + column + '"';
if (i < (columns.length)) {
csv += this.csvSeparator;
}
}
// body
data.forEach((record) => {
csv += '\n';
for (let i_1 = 0; i_1 < columns.length; i_1++) {
const column = columns[i_1];
csv += '"' + this.resolveFieldData(record, column) + '"';
if (i_1 < (columns.length)) {
csv += this.csvSeparator;
}
}
});
const blob = new Blob([csv], {
type: 'text/csv;charset=utf-8;'
});
if (window.navigator.msSaveOrOpenBlob) {
navigator.msSaveOrOpenBlob(blob, exportFilename + '.csv');
} else {
const link = document.createElement('a');
link.style.display = 'none';
document.body.appendChild(link);
if (link.download !== undefined) {
link.setAttribute('href', URL.createObjectURL(blob));
link.setAttribute('download', exportFilename + '.csv');
link.click();
} else {
csv = 'data:text/csv;charset=utf-8,' + csv;
window.open(encodeURI(csv));
}
document.body.removeChild(link);
}
}

和导出CSV很相似嘛

最近的项目都是前后端分离的,后端都是提供Api接口的。

有时调试起来很不方便,给前端的wpi文档也需要经常变更很不方便。

如是网上搜了下,发现SwaggerUI还挺强大的,调试接口也比较方便,在此记录下:

1、引入Swashbuckle

第一个就是,我装的版本是5.6.0

设置xml文件输出路径:

在 App_Start 会生成 SwaggerConfig.cs,需要修改里面的内容:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public static void Register()
{
var thisAssembly = typeof(SwaggerConfig).Assembly;

GlobalConfiguration.Configuration
.EnableSwagger(c =>
{
c.SingleApiVersion("v1", "WebApiSwagger");
c.IncludeXmlComments(GetXmlCommentsPath());
//token认证
//c.OperationFilter<HttpHeaderFilter>();
})
.EnableSwaggerUi(c => {
//汉化
//c.InjectJavaScript(Assembly.GetExecutingAssembly(), "WebApiSwagger.SwaggerUi.scripts.swagger.js");
});
}
private static string GetXmlCommentsPath()
{

return System.String.Format(@"{0}/App_Data/WebApiSwagger.xml", System.AppDomain.CurrentDomain.BaseDirectory);
}

修改访问的起始页:

偷个懒,只需在home控制器里做个跳转

1
2
3
4
5
6
7
8
9
public class HomeController : Controller
{
public ActionResult Index()
{
ViewBag.Title = "Home Page";
Response.Redirect("/swagger/ui/index/");
return View();
}
}

在App_Start 中添加一个类 IOperationFilter.cs :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
using Swashbuckle.Swagger;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Http;
using System.Web.Http.Description;
using System.Web.Http.Filters;

namespace WebApiSwagger.App_Start
{
/// <summary>
///
/// </summary>
public class HttpHeaderFilter : IOperationFilter
{
/// <summary>
///
/// </summary>
/// <param name="operation"></param>
/// <param name="schemaRegistry"></param>
/// <param name="apiDescription"></param>
public void Apply(Operation operation, SchemaRegistry schemaRegistry, ApiDescription apiDescription)

{
if (operation.parameters == null)
operation.parameters = new List<Parameter>();
var filterPipeline = apiDescription.ActionDescriptor.GetFilterPipeline(); //判断是否添加权限过滤器
var isAuthorized = filterPipeline.Select(filterInfo => filterInfo.Instance).Any(filter => filter is IAuthorizationFilter); //判断是否允许匿名方法
var allowAnonymous = apiDescription.ActionDescriptor.GetCustomAttributes<AllowAnonymousAttribute>().Any();
if (isAuthorized && !allowAnonymous)
{
operation.parameters.Add(new Parameter { name = "Authorization", @in = "header", description = "Token", required = false, type = "string" });
}
}
}
}

修改:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public static void Register()
{
var thisAssembly = typeof(SwaggerConfig).Assembly;

GlobalConfiguration.Configuration
.EnableSwagger(c =>
{
c.SingleApiVersion("v1", "WebApiSwagger");
c.IncludeXmlComments(GetXmlCommentsPath());
c.OperationFilter<HttpHeaderFilter>();
})
.EnableSwaggerUi(c=> {
c.InjectJavaScript(Assembly.GetExecutingAssembly(), "WebApiSwagger.SwaggerUi.scripts.swagger.js");
//c.InjectStylesheet();
});
}

汉化:

js内容:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
 'use strict';
/**
* Translator for documentation pages.
*
* To enable translation you should include one of language-files in your index.html
* after <script src='lang/translator.js' type='text/javascript'></script>.
* For example - <script src='lang/ru.js' type='text/javascript'></script>
*
* If you wish to translate some new texsts you should do two things:
* 1. Add a new phrase pair ("New Phrase": "New Translation") into your language file (for example lang/ru.js). It will be great if you add it in other language files too.
* 2. Mark that text it templates this way <anyHtmlTag data-sw-translate>New Phrase</anyHtmlTag> or <anyHtmlTag data-sw-translate value='New Phrase'/>.
* The main thing here is attribute data-sw-translate. Only inner html, title-attribute and value-attribute are going to translate.
*
*/
window.SwaggerTranslator = {
_words: [],

translate: function () {
var $this = this;
$('[data-sw-translate]').each(function () {
$(this).html($this._tryTranslate($(this).html()));
$(this).val($this._tryTranslate($(this).val()));
$(this).attr('title', $this._tryTranslate($(this).attr('title')));
});
},

_tryTranslate: function (word) {
return this._words[$.trim(word)] !== undefined ? this._words[$.trim(word)] : word;
},

learn: function (wordsMap) {
this._words = wordsMap;
}
};

/* jshint quotmark: double */
window.SwaggerTranslator.learn({
"Warning: Deprecated": "警告:已过时",
"Implementation Notes": "实现备注",
"Response Class": "响应类",
"Status": "状态",
"Parameters": "参数",
"Parameter": "参数",
"Value": "值",
"Description": "描述",
"Parameter Type": "参数类型",
"Data Type": "数据类型",
"Response Messages": "响应消息",
"HTTP Status Code": "HTTP状态码",
"Reason": "原因",
"Response Model": "响应模型",
"Request URL": "请求URL",
"Response Body": "响应体",
"Response Code": "响应码",
"Response Headers": "响应头",
"Hide Response": "隐藏响应",
"Headers": "头",
"Try it out!": "试一下!",
"Show/Hide": "显示/隐藏",
"List Operations": "显示操作",
"Expand Operations": "展开操作",
"Raw": "原始",
"can't parse JSON. Raw result": "无法解析JSON. 原始结果",
"Model Schema": "模型架构",
"Model": "模型",
"apply": "应用",
"Username": "用户名",
"Password": "密码",
"Terms of service": "服务条款",
"Created by": "创建者",
"See more at": "查看更多:",
"Contact the developer": "联系开发者",
"api version": "api版本",
"Response Content Type": "响应Content Type",
"fetching resource": "正在获取资源",
"fetching resource list": "正在获取资源列表",
"Explore": "浏览",
"Show Swagger Petstore Example Apis": "显示 Swagger Petstore 示例 Apis",
"Can't read from server. It may not have the appropriate access-control-origin settings.": "无法从服务器读取。可能没有正确设置access-control-origin。",
"Please specify the protocol for": "请指定协议:",
"Can't read swagger JSON from": "无法读取swagger JSON于",
"Finished Loading Resource Information. Rendering Swagger UI": "已加载资源信息。正在渲染Swagger UI",
"Unable to read api": "无法读取api",
"from path": "从路径",
"server returned": "服务器返回"
});


$(function () {
window.SwaggerTranslator.translate();
});

效果图:

自动获取token,在swagger.js添加:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
$(function () {
window.SwaggerTranslator.translate();
//自动获取Token
$.ajax({
type: "POST",
url: "/token",
data: "grant_type=password&username=admin&password=admin",
success: function (res) {
var token = res['access_token'];
$("input[name='Authorization']").val('Bearer ' + token);
},
dataType: 'Json',
});
});

以下为打包方式:

通过命令行

1
ng build --prod --aot

会生成dist文件夹,将dist文件夹中的文件,直接上传到服务器IIS站点下。

然后发现可以正常访问,但是刷新页面就会报400错误,这时需要进行如下配置:

1.安装URL rewrite组件:

网址:https://www.microsoft.com/en-us/download/details.aspx?id=47337

2.在该网站目录下添加一个配置文件web.config,复制下边的内容到web.config

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<system.webServer>
<rewrite>
<rules>
<rule name="AngularJS" stopProcessing="true">
<match url=".*" />
<conditions logicalGrouping="MatchAll">
<add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" />
<add input="{REQUEST_FILENAME}" matchType="IsDirectory" negate="true" />
</conditions>
<action type="Rewrite" url="/" />
</rule>
</rules>
</rewrite>
</system.webServer>
</configuration>

然后就能正常的访问了!

参考:https://angular.io/guide/deployment#server-configuration