巡检报告导出方案
# 导出pdf
# 方案比较
HTML2PDF的方式又分为两种:
- [客户端] PDFKit; 只使用一个PDF的库;
- [客户端] 基于canvas的客户端生成方案;使用一个DOM的屏幕快照;
- [服务端] 基于nodejs + puppeteer的服务端生成方案;相比客户端生成方式,使用puppeteer生成的pdf质量比较高,可满足生产要求。
# 详细比较
# chrome浏览器自带
缺点:
- 需要用户自己点击
- 用户需要使用chrome等支持的浏览器
- 打印默认是全局打印
# html2canvas + jsPdf
缺点:
- html2canvas插件在IE的兼容性问题
- 清晰度问题
- 分页问题
- 文字图片截断问题
# node服务端转换
- phantomjs (opens new window) 基于webkit的无头浏览器,社区使用的不多,很久没更新了,可以深度了解下
- Puppeteer (opens new window) + Headless Chrome 社区里使用该方案的也比较多
# 简单导出 jspdf
# jspdf/html2canvas
- html2canvas (opens new window),从DOM中实现一个屏幕快照
- jsPDF (opens new window),一个生成PDF的库
/*
* @Author: samy
* @email: samyzhg#qq.com
* @time: 2020-09-18 15:25:55
* @modAuthor: samy
* @modTime: 2022-04-02 10:39:54
* @desc: pdf导出工具类
* @Copyright © 2020 BDP FE
*/
// import html2Canvas from 'html2canvas';
import { Html2Canvas as html2Canvas } from '@autorun/components';
import JsPDF from 'jspdf';
/**
* @param {*} domId 操作的dom
* @param {*} fileName 导出的文件名
* @param {*} type 0 图片; 1 pdf a4大小分页导出 2 pdf 不A4分页;
* @param {*} isA4Page
*/
export function htmlToPdf(domId, fileName, type) {
// const target = $(domId); target[0]
const target = document.querySelector(`${domId}`);
const opts = {
// useCORS: true,
// allowTaint: true,
// dpi: 96, // option from 192 to 96
scale: 2, // window.devicePixelRatio
width: target.clientWidth,
height: target.clientHeight,
// logging: true,
};
return html2Canvas(target, opts).then(canvasN => {
const pageData = canvasN.toDataURL('image/jpeg', 1.0);
if (type === 0) {
const objectUrl = pageData.replace('image/jpeg', 'image/octet-stream');
const a = document.createElement('a');
document.body.appendChild(a);
a.setAttribute('style', 'display:none');
a.setAttribute('href', objectUrl);
a.setAttribute('download', `${fileName}.jpeg`);
a.click();
URL.revokeObjectURL(objectUrl);
return;
}
const contentWidth = canvasN.width;
const contentHeight = canvasN.height;
let pdf;
if (type == 1) {
// a4纸的尺寸[595.28,841.89],html页面生成的canvas在pdf中图片的宽高
const a4Width = 595.28;
const a4Hight = 841.89;
let leftHeight = contentHeight;
let position = 0; // 页面偏移
const pageHeight = (contentWidth / a4Width) * a4Hight;
const imgHeight = (a4Width / contentWidth) * contentHeight;
pdf = new JsPDF('', 'pt', 'a4');
// const pdf = new JsPDF('p', 'pt', 'a4', true);
const leftPos = 16;
const topPos = 15;
// 有两个高度需要区分,一个是html页面的实际高度,和生成pdf的页面高度(841.89)
// 当内容未超过pdf一页显示的范围,无需分页
if (leftHeight < pageHeight) {
pdf.addImage(pageData, 'JPEG', leftPos, topPos, a4Width, imgHeight);
} else {
while (leftHeight > 0) {
pdf.addImage(pageData, 'JPEG', leftPos, position + topPos, a4Width, imgHeight);
leftHeight -= pageHeight;
position -= 841.89;
if (leftHeight > 0) {
pdf.addPage();// 避免添加空白页
}
}
}
} else {
// // jspdf.js 插件对单页面的最大宽高限制 为 14400
// const limit = 14400
// if (contentHeight > limit) {
// const contentScale = limit / contentHeight
// contentHeight = limit
// // eslint-disable-next-line operator-assignment
// contentWidth = contentScale * contentWidth
// }
// let orientation = 'p'
// // 在 jspdf 源码里,如果是 orientation = 'p' 且 width > height 时, 会把 width 和 height 值交换,
// // 类似于 把 orientation 的值修改为 'l' , 反之亦同。
// if (contentWidth > contentHeight) {
// orientation = 'l'
// }
// // orientation Possible values are "portrait" or "landscape" (or shortcuts "p" or "l")
// pdf = new JsPDF(orientation, 'pt', [contentWidth, contentHeight]) // 下载尺寸 a4 纸 比例
const pdfWidth = ((contentWidth + 10) / 2) * 0.75;
const pdfHeight = ((contentHeight + 200) / 2) * 0.75; // 500为底部留白
const imgWidth = pdfWidth;
const imgHeight = (contentHeight / 2) * 0.75; // 内容图片这里不需要留白的距离
pdf = new JsPDF('', 'pt', [pdfWidth, pdfHeight]);
pdf.addImage(pageData, 'jpeg', 0, 0, imgWidth, imgHeight);
}
return pdf.save(`${fileName}.pdf`);
});
}
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
92
93
94
95
96
97
98
99
100
101
102
其他初始化的相关参数:
let contentWidth = html.clientWidth // 获得该容器的宽
let contentHeight = html.clientHeight // 获得该容器的高
let canvas = document.createElement('canvas')
let scale = 2 // 解决清晰度问题,先放大 2倍
canvas.width = contentWidth * scale // 将画布宽&&高放大两倍
canvas.height = contentHeight * scale
canvas.getContext('2d').scale(scale, scale)
let opts = {
scale: scale,
canvas: canvas,
width: contentWidth,
height: contentHeight,
useCORS: true
}
return html2Canvas(target, opts).then(canvasN => {})
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
可以帮助你再获取照片前,便利的获取屏幕快照和操作DOM。我们可以看到需要使用这个工具的例子。不幸的是,这其中并没有我们想要的。我们需要再后端处理PDF的生成。
# PDF库
在NPM上有许多库可以实现这样的要求,例如jsPDF或者PDFKit (opens new window),随之而来的问题就是如果你想要使用这些库,你不得不再一次生成页面的架子。你还需要把后续的所有改变应用到PDF模板和React页面中。 看到上面得代码,我们需要自己创建一个PDF文档。现在你可以通过DOM找到如何去转换每一个元素变成PDF,但这是一个沉闷的工作。肯定有一些更简单的方法
const doc = new PDFDocument()
doc.pipe(fs.createWriteStream(resolve('./test.pdf')));
doc.font(resolve('./font.ttf'))
.fontSize(30)
.text('测试添加自定义字体!', 100, 100)
doc.image(resolve('./image.jpg'), {
fit: [250, 300],
align: 'center',
valign: 'center'
})
doc.addPage()
.fontSize(25)
.text('Here is some vector graphics...', 100, 100)
doc.pipe(res);
doc.end();
2
3
4
5
6
7
8
9
10
11
12
13
14
15
这个片段是根据PDFKit的文档写的,如果不需要在已有的HTML页面进行转变,它可以有效的帮助你快速的直接生产PDF文件。
# 配合服务导出Puppeteer
【推荐】
- 可以直接服务器生成pdf,再放回pdf路径给前端;
- 也可以直接返回文件流给前端,让前端自行下载;【推荐这种方案】,不用服务器维护pdf文件;
具体处理方法可以参考;【puppeteer实践及分析】和【vue中pdf下载及预览】
# 简介
puppeteer是google推出的headless浏览器,即没有图形界面的浏览器,但又可以实现普通浏览器HTML/JS/CSS的渲染,以及其他基本浏览器功能。你可以理解为一个没有界面的Chrome浏览器。主要有以下几种使用场景:
- 生成页面的截图和PDF
- 抓取SPA并生成预先呈现的内容(即“SSR”)
- 爬虫,从网站抓取你需要的内容
- 自动化测试,自动表单提交,UI测试,键盘输入等
- 创建一个最新的自动化测试环境。使用最新的JavaScript和浏览器功能,直接在最新版本的Chrome中运行测试 通过理解puppeteer的功能,我们可以开启一个实例去渲染HTML报告,然后再利用其提供的转换PDF功能进行PDF的生成。
两个重要的API:
- page.goto(url, [options]) - 打开指定url的文件,可以是本地文件(file://)也可以是网络文件(http://)
- page.pdf([options]) - 转换页面成PDF文件
# pdf静态模版处理
确保静态文件的根路径和服务基本端口一致,方便用ngx统一代理出去;
目前采用方案是,使用vue写的多页处理方案做前端模版;
# docker环境配置库及字体
# chrome相关库
# 安装依赖库 60M左右
#apt-get install -y google-chrome-stable
RUN yum install -y kde-l10n-Chinese pango.x86_64 libXcomposite.x86_64 libXcursor.x86_64 libXdamage.x86_64 libXext.x86_64 libXi.x86_64 libXtst.x86_64 cups-libs.x86_64 libXScrnSaver.x86_64 libXrandr.x86_64 GConf2.x86_64 alsa-lib.x86_64 atk.x86_64 gtk3.x86_64 \
#字体库相关;注意最后面两个字体库;
&& yum install -y ipa-gothic-fonts xorg-x11-fonts-100dpi xorg-x11-fonts-75dpi xorg-x11-utils xorg-x11-fonts-cyrillic xorg-x11-fonts-Type1 xorg-x11-fonts-misc wqy-unibit-fonts.noarch wqy-zenhei-fonts.noarch
2
3
4
5
# ubuntu中安装字体的处理
RUN apt-get -y install fontconfig xfonts-utils
RUN fc-list :lang=zh
2
# 人为手动安装字体
安装fontconfig yum -y install fontconfig
这个命令执行完成之后,就可以在/usr/share
文件夹里面看到fonts和fontconfig 二、添加中文字体库
- 从window的
C:\Windows\Fonts
里面字体拷贝一份,或者只选择你需要的 - 在CentOS的
/usr/share/fonts
新建一个叫chinese的文件夹 - 然后把刚刚拷贝字体放到CentOS的
/usr/share/fonts/chinese
里面 - 修改chinese目录的权限。
chmod -R 775 /usr/share/fonts/chinese
- 接下来需要安装
ttmkfdir
来搜索目录中所有的字体信息,并汇总生成fonts.scale文件,输入命令yum -y install ttmkfdir
- 执行ttmkfdir命令,
ttmkfdir -e /usr/share/X11/fonts/encodings/encodings.dir
- 打开字体配置文件,
vi /etc/fonts/fonts.conf
,添加下面这一段
<!-- Font directory list -->
<dir>/usr/share/fonts</dir>
<dir>/usr/share/X11/fonts/Type1</dir>
<dir>/usr/share/X11/fonts/TTF</dir>
<dir>/usr/local/share/fonts</dir>
<dir>/usr/local/share/fonts/chinese</dir>
<dir>~/.fonts</dir>
2
3
4
5
6
7
- 刷新内存中的字体缓存,fc-cache
- 看一下现在机器上已经有了刚才添加的字体。fc-list :lang=zh
nodejs环境
#wget https://nodejs.org/dist/v10.24.0/node-v10.24.0-linux-x64.tar.gz
wget http://10.45.xxx.116:58888/files/autorun/pro/soft/nodejs/node-v10.24.0-linux-x64.tar.gz
tar xvf node-v10.24.0-linux-x64.tar.gz
mv node-v10.24.0-linux-x64 nodejs
mv nodejs /usr/local/nodejs
#方式一:环境变量方式
#vi /ect/profile source /etc/profile
vi .bashrc
export NODE_HOME=/usr/local/nodejs/bin
export NODE_PATH=/usr/local/nodejs/lib/node_modules
export PATH=$PATH:$NODE_HOME/bin:$NODE_PATH
source .bashrc
#方式二:软链接方式(推荐)
ln -s /usr/local/nodejs/bin/npm /usr/local/bin/
ln -s /usr/local/nodejs/bin/node /usr/local/bin/
ln -s /usr/local/nodejs/bin/npx /usr/local/bin/
ln -s /usr/local/nodejs/bin/pm2 /usr/local/bin/
#查看nodejs是否安装成功
node -v
npm -v
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
项目启动相关
npm config set registry https://registry.npm.taobao.org/
npm install -g pm2
#wget http://10.45.xxx.116:58888/files/autorun/tmp/pdf-render-puppeteer.tar.gz
#mkdir pdf-render-puppeteer
#tar zxvf pdf-render-puppeteer.tar.gz -C pdf-render-puppeteer
wget http://10.45.xxx.116:58888/files/autorun/pro/pdf-server/pdf-render-puppeteer.tar.gz
tar zxvf pdf-render-puppeteer.tar.gz
npm config set puppeteer_download_host=https://npm.taobao.org/mirrors
npm install --unsafe-perm=true --allow-root
2
3
4
5
6
7
8
9
10
11
安装pm2及启动
npm i -g pm2
ln -s /usr/local/nodejs/bin/pm2 /usr/local/bin/
#npm start
sh start.sh
2
3
4
最后优化为:
# install nodejs
&& cd $WORKDIR/soft/nodejs \
&& tar xvf node-v10.24.0-linux-x64.tar.gz \
&& mv node-v10.24.0-linux-x64 nodejs \
&& mv nodejs /usr/local/nodejs \
&& ln -s /usr/local/nodejs/bin/npm /usr/local/bin/ \
&& ln -s /usr/local/nodejs/bin/node /usr/local/bin/ \
&& ln -s /usr/local/nodejs/bin/npx /usr/local/bin/ \
&& ln -s /usr/local/nodejs/bin/pm2 /usr/local/bin/ \
&& npm config set registry https://registry.npm.taobao.org/ \
&& npm install -g pm2 \
&& rm -rf *.gz \
# pro
&& cd $WORKDIR/portal \
&& tar -zxvf eureka.tar.gz\
&& tar -zxvf GSMAppService.tar.gz\
&& tar -zxvf AAWeb.tar.gz\
&& mv dist AAWeb \
&& rm -rf *.gz \
&& cd $WORKDIR/autorun \
&& tar -zxvf zookeeper-3.4.8.tar.gz \
&& tar -zxvf autorun.tar.gz \
&& rm -rf *.gz \
&& cd $WORKDIR/pdf-server \
# && mkdir pdf-render-puppeteer && tar zxvf pdf-render-puppeteer.tar.gz -C pdf-render-puppeteer \
# && cd pdf-render-puppeteer && npm install --unsafe-perm=true --allow-root \
&& tar zxvf pdf-render-puppeteer.tar.gz \
&& npm install --unsafe-perm=true --allow-root \
&& rm -rf *.gz
echo "启动pdf-server..."
cd /srv/app/pdf-server && sh start.sh
sleep 5
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
# nginx配置
使用相同的ip和端口,使nginx转发到nodejs服务器上;
location /pdfServer {
proxy_pass http://127.0.0.1:8084/pdfServer;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header REMOTE-HOST $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
# 巡检 production; pdfServer统一一样,方便统一部署到ngx上代理;
VUE_APP_API_PREFIX=/pdfServer
PUBLIC_PATH='/pdfServer/'
app.use(express.static('public'))
2
3
4
5
6
7
8
9
10
11
12
13
# pdf-server
deploy.json
{
"apps": [
{
"name": "pdf-server",
"script": "./app.js",
"exec_mode": "cluster",
"instances": -1,
"log_date_format": "YYYY-MM-DD HH:mm:ss",
"max_memory_restart": "5G",
"max_restarts": 4,
"min_uptime": 400,
"env": {
"COMMON_VARIABLE": "true",
"PORT": 8084
},
"env_production": {
"NODE_ENV": "production",
"PORT": 8084
},
"args": ["--max_old_space_size=4096"]
}
]
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
start.sh
pm2 startOrRestart deploy.json --env production
# 访问示范
http://10.45.xxx.116:9527?url=http://10.45.46.xxxx:9001/report.html&type=pdf
#模版页面
http://10.45.xxx.xx:8444/pdfServer/autorun/clusterReport.html?id=2211
#生产pdf接口
http://10.45.xxx.xx:8444/pdfServer/getPdf?url=http://10.45.xxx.xx:8444/pdfServer/autorun/clusterReport.html&&id=2211&&type=pdf
http://localhost:9800/pdfServer/getPdf?url=http:%2F%2Flocalhost:9800%2Fautorun%2FclusterReport.html&id=2210&type=pd
// window.open(`http://localhost:9527/?url=http://localhost:9800/autorun/clusterReport.html&type=pdf`)
2
3
4
5
6
7
8
# 处理大数据5k条优化【核心】
# 核心思想:要处理客户端请求超时,及打印转换pdf时超时设置;
统计:pdf大小:目前是11M左右;接口数据:2M左右;目前单进程处理的话3min左右;
客户端配置
const request = axios.create({
baseURL: process.env.VUE_APP_API_PREFIX, // API 请求的默认前缀,
timeout: 1000 * 60 * 6 // 6min请求超时时间
// timeout: 0 // 无限请求超时时间
})
2
3
4
5
服务端配置
核心设置
const renderdoneHandle = await page.waitForFunction('window.renderReportFlag', { polling: 120, timeout: defaultTime })
await page.goto(url, { timeout: timeout || 0, waitUntil })
return await page.pdf({ ...pdfOptions, timeout: defaultTime })
主要这里的异常处理方式;
async pdf(url, options = {}) {
let page = null
try {
const { timeout, waitUntil, credentials, headers, emulateMediaType, ...extraOptions } = options
page = await this.createPage(url, {
timeout,
waitUntil,
credentials,
headers,
emulateMediaType: emulateMediaType || 'print',
})
const pdfOptions = await pdfSchema.validate(extraOptions)
console.info("----begin---page.pdf-----", new Date(), url);
return await page.pdf({ ...pdfOptions, timeout: defaultTime })
} catch (error) {
console.error('---pdf---',error);
throw new Error(error)
} finally {
this.closePage(page)
}
}
async createPage(url, options = {}) {
try {
const { timeout, waitUntil, credentials, emulateMediaType, headers, waitForFunction } = await pageSchema.validate(options)
const page = await this.browser.newPage()
if (headers) {
await page.setExtraHTTPHeaders(JSON.parse(headers))
}
await page.setCacheEnabled(false)
await page.setDefaultNavigationTimeout(0); //这个配置跟下面的goto中的设置冲突;
// await page.setDefaultTimeout(defaultTime);
page.on('error', async error => {
await this.closePage(page)
throw new Error(error)
})
if (emulateMediaType) {
await page.emulateMediaType(emulateMediaType)
}
if (credentials) {
await page.authenticate(credentials)
}
console.log("-----begin--page.goto-----", new Date(), url);
await page.goto(url, { waitUntil })
const renderdoneHandle = await page.waitForFunction('window.renderReportFlag', { polling: 120, timeout: defaultTime })
const renderdone = await renderdoneHandle.jsonValue();
if (renderdone) {
console.info('页面请求接口加载成功!', new Date(),url)
} else {
console.info('页面请求加载中...')
}
return page
} catch (error) {
console.error('---createPage---',error);
throw new Error(error)
}
}
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
可能出现的问题:
[Puppeteer TimeoutError: Navigation timeout of 30000 ms exceeded](https://stackoverflow.com/questions/60051954/puppeteer-timeouterror-navigation-timeout-of-30000-ms-exceeded)
Before await browser.goto try await page.setDefaultNavigationTimeout(0)
or put { waitUntil: 'load', timeout: 0 }
inside .goto options. 最后考虑直接设置setDefaultNavigationTimeout(0)
;
# 再优化部分
渲染页面可以做成SSR页面可以加快处理;抓取SPA并生成预先呈现的内容(即“SSR”)
# 临时替换新版本脚本备用
docker exec -it autorun-new bash
cd /srv/app/portal/
wget http://10.45.xx.116:58888/files/autorun/pro/portal/AAWeb-new.tar.gz
tar zxvf AAWeb-new.tar.gz && rm -rf AAWeb && mv dist AAWeb
mkdir -p pdf-render-puppeteer && cd pdf-render-puppeteer
wget http://10.45.xx.116:58888/files/autorun/pro/pdf-server/pdf-render-puppeteer.tar.gz
tar zxvf pdf-render-puppeteer.tar.gz
npm install --unsafe-perm=true --allow-root && sh start.sh
2
3
4
5
6
7
8
9
10
# 导出离线Html freemarker
目前的话,只做了部分调研功能;
# 介绍
# 实践
单页面模拟数据;要冻结请求数据;
# 后端处理
main.java
/*
* @Author: samy
* @email: yessz#foxmail.com
* @time: 2020-12-29 10:16:33
* @modAuthor: samy
* @modTime: 2020-12-29 10:16:33
* @desc:
* @Copyright © 2015~2020 BDP FE
*/
public class ExportReport {
public static void main(String[] args) throws IOException, TemplateException {
ReportPreviewDto reportPreviewDto;
String reportFilePath = "/Users/samy/Downloads/freemaker-demo/src/main/resources/report-2055.json";
String reportString = FileReaderUtil.getString(reportFilePath);
JSONObject reportJson = JSONObject.parseObject(reportString);
reportPreviewDto = JSON.toJavaObject(reportJson.getJSONObject("resultObject"), ReportPreviewDto.class);
Map reportMap = new HashMap();
// reportMap.put("data", JSON.toJSONString(reportPreviewDto));
// reportMap.put("data", JSON.toJSONString("{'objList':'objList'}"));
reportMap.put("clusterName", JSON.toJSONString(reportPreviewDto.getClusterName()));
reportMap.put("report", JSON.toJSONString(reportPreviewDto.getReport()));
reportMap.put("componentReport", JSON.toJSONString(reportPreviewDto.getSceneDetail().getComponentReport()));
reportMap.put("indexReport", JSON.toJSONString(reportPreviewDto.getSceneDetail().getIndexReport()));
reportMap.put("applicationReport", JSON.toJSONString(reportPreviewDto.getSceneDetail().getApplicationReport()));
reportMap.put("exceptionSite", reportPreviewDto.getSceneDetail().getExceptionSite());
reportMap.put("repairAdvice", JSON.toJSONString(reportPreviewDto.getSceneDetail().getRepairAdvice()));
String path = "/Users/samy/Downloads/freemaker-demo/src/main/resources/template";
// 第一步:创建一个Configuration对象,直接new一个对象。构造方法的参数就是FreeMarker对于的版本号。
Configuration configuration = new Configuration(Configuration.getVersion());
// 第二步:设置模板文件所在的路径。
configuration.setDirectoryForTemplateLoading(new File(path + "/ftl"));
// 第三步:设置模板文件使用的字符集。一般就是utf-8.
configuration.setDefaultEncoding("utf-8");
// 第四步:加载一个模板,创建一个模板对象。
// Template template = configuration.getTemplate("hello.ftl");
Template template = configuration.getTemplate("report.ftl");
// 第五步:创建一个模板使用的数据集,可以是pojo也可以是map。一般是Map。
// Map dataModel = new HashMap<>();
//向数据集中添加数据
// dataModel.put("hello", "this is my first FreeMarker test.");
// 第六步:创建一个Writer对象,一般创建一FileWriter对象,指定生成的文件名。
// Writer out = new FileWriter(new File(path + "/html/hello.html"));
Writer out = new FileWriter(new File(path + "/html/report.html"));
// 第七步:调用模板对象的process方法输出文件。
template.process(reportMap, out);
// 第八步:关闭流。
out.close();
}
}
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
common.ftl
<!--
* @Author: samy
* @email: yessz#foxmail.com
* @time: 2020-12-16 16:18:49
* @modAuthor: samy
* @modTime: 2020-12-18 16:38:05
* @desc: 基础类
* @Copyright © 2015~2020 BDP FE
-->
<!DOCTYPE html>
<html lang="en">
<head>
<title>ftp-vue</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<#-- <script src="https://unpkg.com/vue@2.6.12/dist/vue.min.js"></script>-->
<#-- <script src="https://unpkg.com/ant-design-vue@1.7.2/dist/antd.min.js"></script>-->
<#-- <script src="https://unpkg.com/moment@2.29.1/min/moment.min.js"></script>-->
<#-- <link rel="stylesheet" href="https://unpkg.com/ant-design-vue@1.7.2/dist/antd.min.css"></link> -->
<#-- -->
<script src="./asset/js/vue.min.js"></script>
<script src="./asset/js/antd.min.js"></script>
<script src="./asset/js/moment.min.js"></script>
<link rel="stylesheet" href="./asset/css/antd.min.css"></link>
</head>
</html>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
hello.ftl
<#ftl attributes={"content_type":"text/html; charset=UTF-8"}>
<?xml version="1.0" encoding="utf-8"?>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
<#include "./common/common.ftl"/>
</head>
<body>
<div id="app">
<h2>{{clusterName}}</h2>
<h2>{{report}}</h2>
<h2>{{list}}</h2>
</div>
</body>
<script>
var clusterName =""
var report =""
// window.onload=function(){}
<#--$(function () {-->
<#-- clusterName = '${clusterName}' || ''-->
<#-- report = JSON.parse('${report}') || {}-->
<#-- console.log(clusterName)-->
<#-- console.log(report)-->
<#-- vm.getData(clusterName,report);-->
<#--});-->
var vm = new Vue({
el: "#app",
data: {
<#--data: JSON.parse('${data}') || {},-->
clusterName: Object.freeze(JSON.parse('${clusterName}') || ''),
report: Object.freeze(JSON.parse('${report}') || {}),
list: Object.freeze(JSON.parse('${componentReport}') || []),
},
methods: {
// getData: function (clusterName,report) {
// var self=this;
// self.clusterName= clusterName;
// self.report =report;
// },
}
});
console.log(vm.clusterName)
console.log(vm.report)
console.log(vm.list)
</script>
</html>
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
report.ftl
<!--<!--
* @Author: samy
* @email: yessz#foxmail.com
* @time: 2020-12-16 17:03:55
* @modAuthor: samy
* @modTime: 2020-12-24 14:27:16
* @desc: 功能首页
* @Copyright © 2015~2020 BDP FE
-->
<!DOCTYPE html>
<html lang="en">
<head>
<!-- <link rel="stylesheet" type="text/css" href="../src/css/index.css"> -->
<#include "./common/common.ftl"/>
<style>
* {
box-sizing: border-box;
}
html,
body,
#app {
color: rgba(0, 0, 0, 0.65);
font-family: Arial, Helvetica, "STHeiti STXihei", "Microsoft YaHei",
Tohoma, sans-serif;
background-color: #fff;
width: 100%;
height: 100%;
font-size: 16px;
box-sizing: border-box;
padding: 16px;
}
html,
body,
p,
ul,
li {
margin: 0;
padding: 0;
}
a {
color: #1d8af2;
}
.flex {
display: flex;
}
.flex-cc {
display: flex;
align-items: center;
}
.flex-sc {
display: flex;
justify-content: center;
}
.flex-sb {
display: flex;
justify-content: space-between;
}
.flex-ccb {
display: flex;
align-items: center;
justify-content: space-between;
}
.flex-ccc {
display: flex;
align-items: center;
justify-content: center;
}
.full-page {
width: 100%;
height: 100%;
}
.relative {
position: relative;
}
.ml10 {
margin-left: 10px;
}
.mr10 {
margin-right: 10px;
}
.mt10 {
margin-top: 10px;
}
.m10 {
margin: 10px;
}
.mb10 {
margin-bottom: 10px;
}
.m16 {
margin: 16px;
}
.mt16 {
margin-top: 16px;
}
.mb16 {
margin-bottom: 16px;
}
.ml16 {
margin-left: 16px;
}
.mr16 {
margin-right: 16px;
}
.ml50 {
margin-left: 50px;
}
.mr50 {
margin-right: 50px;
}
.pt16 {
padding-top: 16px;
}
.pb16 {
padding-bottom: 16px;
}
.mt0 {
margin-top: 0 !important;
}
.mb0 {
margin-bottom: 0 !important;
}
.topInfo {
border-bottom: 1px solid #eff1f4;
}
.descTitle {
padding-bottom: 5px;
font-size: 12px;
font-weight: bold;
}
.descTitle:before {
content: "";
display: inline-block;
width: 2px;
height: 14px;
margin-right: 10px;
position: relative;
background-color: #00c1de;
top: 2px;
}
.textArea {
padding: 5px 16px;
border: 1px solid rgba(0, 0, 0, 0.09);
}
.fixSuggest {
padding-top: 10px;
}
.fontBlk {
color: #000;
}
.scores {
font-size: 20px;
color: #00c1de;
}
.ant-collapse > .ant-collapse-item > .ant-collapse-header {
padding: 6px 16px 6px 40px;
}
.ant-table-column-title {
font-size: 12px;
}
.ant-list-item:first-child {
padding: 0 0 12px 0;
}
.ant-list-item:last-child {
padding: 12px 0 0 0;
}
/* .ant-table-small {
border: none !important;
} */
.table_bg_red{
background-color: #ffc0cb
}
</style>
</head>
<body>
<div id="app">
<h2 class="flex-ccc mt16">{{ report.reportName }}</h2>
<div class="flex-ccc topInfo">
<span>
<span>得分:</span>
<span class="fontBlk">{{ Number(report.scores).toFixed(2) }}</span>
<span>分</span>
</span>
<span class="ml50">
<span>操作人:</span>
<span class="fontBlk">{{report.staffId }}</span>
</span>
<span class="ml50">
<span>生成时间:</span>
<span class="fontBlk">{{ report.updateDate | formatDate }}</span>
</span>
</div>
<div class="flex-ccb ml16 mr16 mt10 mb10">
<span>
<span>总体得分:</span>
<span class="scores">{{ Number(report.scores).toFixed(2) }}</span>
<span>分</span>
</span>
<span>
<span>异常数量:</span>
<span>{{ report.alertIndexCount || 0 }}</span>
</span>
<span>
<span>告警数量:</span>
<span>{{ report.alertIndexCount || 0 }}</span>
</span>
<span>
<span>报告编码:</span>
<span>{{ report.reportInstId }}</span>
</span>
</div>
<a-collapse v-model="activeKey">
<a-collapse-panel key="1" header="组件健康状态分析报告">
<a-list item-layout="horizontal" :data-source="componentReport">
<a-list-item slot="renderItem" slot-scope="item, index">
<div :key="item.componentName">
<div class="descTitle">{{ item.componentName }}</div>
<a-table
:columns="itemColumns"
:data-source="item.subComponentList"
:pagination="false"
size="small"
rowKey="subComponentName"
>
<span slot="hostNum" slot-scope="text">{{ text || 0 }}</span>
<span slot="normalHostNum" slot-scope="text">{{
text || 0
}}</span>
<span slot="affectHostNum" slot-scope="text">{{
text || 0
}}</span>
<span slot="exceptionHostNum" slot-scope="text">{{
text || 0
}}</span>
</a-table>
</div>
</a-list-item>
</a-list>
</a-collapse-panel>
<a-collapse-panel key="2" header="巡检指标分析报告" :disabled="false">
<!-- :scroll="{ y: 500 }" -->
<a-table
:columns="columns"
:data-source="indexReport"
:pagination="false"
size="small"
rowKey="indexId"
:rowClassName="setRowClassName"
>
<span slot="referenceVDown" slot-scope="text, record"
>{{ record.referenceVDown || "0" }} ~
{{ record.referenceVUp || "0" }}
</span>
<span slot="effectHostNum" slot-scope="text">{{ text }}台</span>
<span slot="indexValue" slot-scope="text, record">{{ text }}
<a-icon v-if= "text > record.referenceVUp" type="arrow-up" style="color:'#f00'" />
<a-icon v-else-if="text < record.referenceVDown" type="arrow-down" style="color:'#58bc58'" />
</span>
<span slot="riskRank" slot-scope="text">
<a-tag
:color="text === '1001' ? 'red' : text=== '1002' ? 'orange' : 'green'"
>
{{ text === '高风险' ? 'red' : text=== '1002' ? '中风险' : '低风险' }}
</a-tag>
</span>
</a-table>
</a-collapse-panel>
<a-collapse-panel key="3" header="大数据作业任务">
<a-table
:columns="columnsTask"
:data-source="applicationReport"
:pagination="false"
size="small"
rowKey="taskId"
>
<span slot="riskRank" slot-scope="text">
<a-tag
:color="text === '1001' ? 'red' : text=== '1002' ? 'orange' : 'green'"
>
{{ text === '高风险' ? 'red' : text=== '1002' ? '中风险' : '低风险' }}
</a-tag>
</span>
</a-table>
</a-collapse-panel>
<a-collapse-panel key="4" header="异常点总结">
<div>
<div class="descTitle">异常点描述</div>
<div class="textArea">
<pre>{{exceptionSite}}</pre>
<#--<div v-html="exceptionSite"></div>-->
</div>
</div>
<div>
<div class="descTitle fixSuggest">修复建议</div>
<div class="textArea">
<pre> {{repairAdvice}} </pre>
</div>
</div>
</a-collapse-panel>
</a-collapse>
</div>
</body>
</html>
<script>
const itemColumns = [
{
title: "子组件名称",
key: "subComponentName",
dataIndex: "subComponentName",
width: "12%",
},
{
title: "子组件节点数量",
key: "hostNum",
dataIndex: "hostNum",
ellipsis: true,
width: "10%",
scopedSlots: { customRender: "hostNum" },
},
{
title: "正常状态数量",
key: "normalHostNum",
dataIndex: "normalHostNum",
ellipsis: true,
width: "10%",
scopedSlots: { customRender: "normalHostNum" },
},
{
title: "隐患状态数量",
key: "affectHostNum",
dataIndex: "affectHostNum",
ellipsis: true,
width: "10%",
scopedSlots: { customRender: "affectHostNum" },
},
{
title: "异常状态数量",
key: "exceptionHostNum",
dataIndex: "exceptionHostNum",
ellipsis: true,
width: "10%",
scopedSlots: { customRender: "exceptionHostNum" },
},
{
title: "异常占比",
key: "exceptionHostPercent",
dataIndex: "exceptionHostPercent",
ellipsis: true,
width: "10%",
},
{
title: "影响分析",
key: "effect",
dataIndex: "effect",
ellipsis: true,
width: "30%",
},
];
const columns = [
{
title: "指标大项",
key: "indexItemCode",
dataIndex: "indexItemCode",
width: "20%",
},
{
title: "指标子项",
dataIndex: "indexSubItemCode",
key: "indexSubItemCode",
width: "20%",
},
{
title: "指标名称",
dataIndex: "indexName",
width: "20%",
key: "indexName",
},
{
title: "指标值",
dataIndex: "indexValue",
key: "indexValue",
width: "10%",
ellipsis: true,
scopedSlots: { customRender: "indexValue" },
},
{
title: "单位",
dataIndex: "valueUnit",
key: "valueUnit",
width: "8%",
ellipsis: true,
},
{
title: "参考范围",
key: "referenceVDown",
ellipsis: true,
width: "10%",
scopedSlots: { customRender: "referenceVDown" },
},
{
title: "风险级别",
dataIndex: "riskRank",
key: "riskRank",
ellipsis: true,
width: 80,
scopedSlots: { customRender: "riskRank" },
},
{
title: "是否告警",
dataIndex: "isNotice",
key: "isNotice",
width: 80,
ellipsis: true,
},
{
title: "影响主机数",
dataIndex: "effectHostNum",
key: "effectHostNum",
ellipsis: true,
width: 120,
scopedSlots: { customRender: "effectHostNum" },
},
{
title: "备注",
dataIndex: "comments",
key: "comments",
ellipsis: true,
width: 80,
},
];
const columnsTask = [
{
title: "任务类型",
key: "appType",
dataIndex: "appType",
ellipsis: true,
},
{
title: "任务名称",
dataIndex: "appName",
key: "appName",
},
{
title: "StageID",
dataIndex: "stageId",
key: "stageId",
},
{
title: "taskId",
dataIndex: "taskId",
key: "taskId",
},
{
title: "exceptionType",
dataIndex: "exceptionType",
key: "exceptionType",
},
{
title: "风险级别",
dataIndex: "riskRank",
key: "riskRank",
scopedSlots: { customRender: "riskRank" },
},
];
var vm = new Vue({
el: "#app",
data: {
itemColumns,
columns,
columnsTask,
activeKey: ["1"],
report: Object.freeze(JSON.parse('${report}') || {}),
componentReport: Object.freeze(JSON.parse('${componentReport}') || []),
indexReport: Object.freeze(JSON.parse('${indexReport}') || []),
applicationReport: Object.freeze(JSON.parse('${applicationReport}') || []),
repairAdvice: JSON.parse('${repairAdvice}') || '',
exceptionSite: `${exceptionSite}`, //特殊字符不能用json处理;
},
filters: {
formatDate(value, format) {
return moment(value || new Date()).format(format ||'YYYY-MM-DD HH:mm:ss')
}
},
methods: {
setRowClassName: function (record) {
return record.indexValue > record.referenceVUp || record.indexValue < record.referenceVDown ? "table_bg_red" : "";
}
},
});
</script>
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
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
# 最后生成后的模版
把生成的离线html做成压缩包,再返回文件流改前端,下载即可以;
report.html
<!--
* @Author: samy
* @email: yessz#foxmail.com
* @time: 2020-12-16 17:03:55
* @modAuthor: samy
* @modTime: 2020-12-18 16:29:45
* @desc: 功能首页
* @Copyright © 2015~2020 BDP FE
-->
<!DOCTYPE html>
<html lang="en">
<head>
<!-- <link rel="stylesheet" type="text/css" href="../src/css/index.css"> -->
<!DOCTYPE html>
<html lang="en">
<head>
<title>ftp-vue</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<script src="https://unpkg.com/jquery@3.5.1/dist/jquery.min.js"></script>
<script src="https://unpkg.com/vue@2.6.12/dist/vue.min.js"></script>
<script src="https://unpkg.com/vue-router@3.4.9/dist/vue-router.min.js"></script>
<script src="https://unpkg.com/axios@0.21.0/dist/axios.min.js"></script>
<script src="https://unpkg.com/ant-design-vue@1.7.2/dist/antd.min.js"></script>
<link rel="stylesheet" href="https://unpkg.com/ant-design-vue@1.7.2/dist/antd.min.css"></link>
<!-- <link rel="stylesheet" href="./global.css"></link> -->
</head>
</html> <style>
* {
box-sizing: border-box;
}
html,
body,
#app {
color: #969696;
font-family: Arial, Helvetica, "STHeiti STXihei", "Microsoft YaHei",
Tohoma, sans-serif;
background-color: #fff;
width: 100%;
height: 100%;
font-size: 14px;
box-sizing: border-box;
/* padding: 16px; */
}
html,
body,
p,
ul,
li {
margin: 0;
padding: 0;
}
a {
color: #1d8af2;
}
.flex {
display: flex;
}
.flex-cc {
display: flex;
align-items: center;
}
.flex-sc {
display: flex;
justify-content: center;
}
.flex-sb {
display: flex;
justify-content: space-between;
}
.flex-ccb {
display: flex;
align-items: center;
justify-content: space-between;
}
.flex-ccc {
display: flex;
align-items: center;
justify-content: center;
}
.full-page {
width: 100%;
height: 100%;
}
.relative {
position: relative;
}
.mr10 {
margin-right: 10px;
}
.mb10 {
margin-bottom: 10px;
}
.m16 {
margin: 16px;
}
.mt16 {
margin-top: 16px;
}
.mb16 {
margin-bottom: 16px;
}
.ml16 {
margin-left: 16px;
}
.mr16 {
margin-right: 16px;
}
.pt16 {
padding-top: 16px;
}
.pb16 {
padding-bottom: 16px;
}
.mt0 {
margin-top: 0 !important;
}
.mb0 {
margin-bottom: 0 !important;
}
.topInfo {
border-bottom: 1px solid #eff1f4;
}
.descTitle {
padding-bottom: 5px;
font-size: 12px;
font-weight: bold;
}
.descTitle:before {
content: "";
display: inline-block;
width: 2px;
height: 14px;
margin-right: 10px;
position: relative;
background-color: #00c1de;
top: 2px;
}
.textArea {
padding: 5px 16px;
border: 1px solid rgba(0, 0, 0, 0.09);
}
.fixSuggest {
padding-top: 10px;
}
</style>
</head>
<body>
<div id="app">
<h2 class="flex-ccc">{{report.reportName}}</h2>
<div class="flex-ccc topInfo">
<span>
<span>得分:</span>
<span>{{ Number(report.scores).toFixed(2) }}分</span>
</span>
<span class="ml16">
<span>操作人:</span>
<span>{{report.staffId }}</span>
</span>
<span class="ml16">
<span>生成时间:</span>
<span>{{ report.updateDate }}</span>
</span>
</div>
<div class="flex-ccb m16">
<span>
<span>总体得分:</span>
<span>{{ Number(report.scores).toFixed(2) }}分</span>
</span>
<span>
<span>异常数量:</span>
<span>{{ report.alertIndexCount || 0 }}</span>
</span>
<span>
<span>告警数量:</span>
<span>{{ report.alertIndexCount || 0 }}</span>
</span>
<span>
<span>报告编码:</span>
<span>{{ report.reportInstId }}</span>
</span>
</div>
<a-collapse v-model="activeKey">
<a-collapse-panel key="1" header="组件健康状态分析报告">
<a-list item-layout="horizontal" :data-source="componentReport">
<a-list-item slot="renderItem" slot-scope="item, index">
<div :key="item.componentName">
<div class="descTitle">{{ item.componentName }}</div>
<a-table
:columns="itemColumns"
:data-source="item.subComponentList"
:pagination="false"
>
<a slot="name" slot-scope="text">{{ text }}</a>
</a-table>
</div>
</a-list-item>
</a-list>
</a-collapse-panel>
<a-collapse-panel key="2" header="巡检指标分析报告" :disabled="false">
<a-table :columns="columns" :data-source="indexReport" :pagination="false">
<a slot="name" slot-scope="text">{{ text }}</a>
</a-table>
</a-collapse-panel>
<a-collapse-panel key="3" header="大数据作业任务">
<a-table
:columns="columnsTask"
:data-source="applicationReport"
:pagination="false"
>
<a slot="name" slot-scope="text">{{ text }}</a>
</a-table>
</a-collapse-panel>
<a-collapse-panel key="4" header="异常点总结">
<div>
<div class="descTitle">异常点描述</div>
<div class="textArea">
<pre>{{exceptionSite}}</pre>
</div>
</div>
<div>
<div class="descTitle fixSuggest">修复建议</div>
<div class="textArea">
<pre> {{repairAdvice}} </pre>
</div>
</div>
</a-collapse-panel>
</a-collapse>
</div>
</body>
</html>
<script>
var itemColumns = [
{
title: "子组件名称",
key: "subComponentName",
dataIndex: "subComponentName",
width: "12%",
},
{
title: "子组件节点数量",
key: "hostNum",
dataIndex: "hostNum",
ellipsis: true,
width: "10%",
},
{
title: "正常状态数量",
key: "normalHostNum",
dataIndex: "normalHostNum",
ellipsis: true,
width: "10%",
},
{
title: "隐患状态数量",
key: "affectHostNum",
dataIndex: "affectHostNum",
ellipsis: true,
width: "10%",
},
{
title: "异常状态数量",
key: "exceptionHostNum",
dataIndex: "exceptionHostNum",
ellipsis: true,
width: "10%",
},
{
title: "异常占比",
key: "exceptionHostPercent",
dataIndex: "exceptionHostPercent",
ellipsis: true,
width: "10%",
},
{
title: "影响分析",
key: "effect",
dataIndex: "effect",
ellipsis: true,
width: "30%",
},
];
var columns = [
{
title: "指标大项",
key: "indexItemCode",
dataIndex: "indexItemCode",
width: "20%",
},
{
title: "指标子项",
dataIndex: "indexSubItemCode",
key: "indexSubItemCode",
width: "20%",
},
{
title: "指标名称",
dataIndex: "indexName",
width: "20%",
key: "indexName",
},
{
title: "指标值",
dataIndex: "indexValue",
key: "indexValue",
width: "10%",
ellipsis: true,
},
{
title: "单位",
dataIndex: "valueUnit",
key: "valueUnit",
width: "8%",
ellipsis: true,
},
{
title: "参考范围",
key: "referenceVDown",
ellipsis: true,
width: "10%",
},
{
title: "风险级别",
dataIndex: "riskRank",
key: "riskRank",
ellipsis: true,
width: 80,
},
{
title: "是否告警",
dataIndex: "isNotice",
key: "isNotice",
width: 80,
ellipsis: true,
},
{
title: "影响主机数",
dataIndex: "effectHostNum",
key: "effectHostNum",
ellipsis: true,
width: 80,
},
{
title: "备注",
dataIndex: "comments",
key: "comments",
ellipsis: true,
width: "5%",
},
];
var columnsTask = [
{
title: "任务类型",
key: "appType",
dataIndex: "appType",
ellipsis: true,
},
{
title: "任务名称",
dataIndex: "appName",
key: "appName",
},
{
title: "StageID",
dataIndex: "stageId",
key: "stageId",
},
{
title: "taskId",
dataIndex: "taskId",
key: "taskId",
},
{
title: "exceptionType",
dataIndex: "exceptionType",
key: "exceptionType",
},
{
title: "风险级别",
dataIndex: "riskRank",
key: "riskRank",
},
];
var vm = new Vue({
el: "#app",
data: {
itemColumns,
columns,
columnsTask,
activeKey: ["1", "2", "3", "4"],
report: Object.freeze(JSON.parse('{"beginTime":1607529600000,"clusterId":26,"endTime":1607529600000,"reportInstId":2055,"reportName":"hdp生产集群","scores":90.625,"staffId":"autorun","updateDate":1607589666000}') || {}),
componentReport: Object.freeze(JSON.parse('[{"componentName":"HIVE","subComponentList":[{"affectHostNum":0,"effect":"","exceptionHostNum":0,"exceptionHostPercent":"0%","hostNum":1,"normalHostNum":1,"subComponentName":"HiveMetaStore"}]},{"componentName":"HDFS","subComponentList":[{"affectHostNum":0,"effect":"","exceptionHostNum":0,"exceptionHostPercent":"0%","hostNum":1,"normalHostNum":1,"subComponentName":"NameNode"},{"affectHostNum":0,"effect":"主机host166异常;","exceptionHostNum":1,"exceptionHostPercent":"50.00%","hostNum":2,"normalHostNum":1,"subComponentName":"DataNode"}]},{"componentName":"HBASE","subComponentList":[{"affectHostNum":0,"effect":"","exceptionHostNum":0,"exceptionHostPercent":"0%","hostNum":1,"normalHostNum":1,"subComponentName":"HMaster"},{"affectHostNum":0,"effect":"","exceptionHostNum":0,"exceptionHostPercent":"0%","hostNum":2,"normalHostNum":2,"subComponentName":"HRegionServer"}]},{"componentName":"YARN","subComponentList":[{"affectHostNum":0,"effect":"主机host166异常;主机host167异常;","exceptionHostNum":2,"exceptionHostPercent":"100.00%","hostNum":2,"normalHostNum":0,"subComponentName":"NodeManager"},{"affectHostNum":0,"effect":"","exceptionHostNum":0,"exceptionHostPercent":"0%","hostNum":1,"normalHostNum":1,"subComponentName":"ResourceManager"}]}]') || []),
indexReport: Object.freeze(JSON.parse('[{"createTime":1607589588000,"effectHostNum":0,"indexCode":"hive_meta_store_delete_total_count_partitions","indexId":512,"indexItemCode":"HIVE","indexName":"hiveMetaStore删除的分区总数","indexSubItemCode":"HiveMetaStore","indexType":"1001","indexValue":4166.0,"referenceVDown":0.0,"referenceVUp":1000000.0,"riskRank":"1003","valueType":"int","valueUnit":"个数"},{"createTime":1607589588000,"effectHostNum":0,"indexCode":"hive_meta_store_jvm_pause_extra_sleep_time","indexId":513,"indexItemCode":"HIVE","indexName":"hiveMetaStore中jvm暂停使用的额外时间","indexSubItemCode":"HiveMetaStore","indexType":"1001","indexValue":950.0,"referenceVDown":0.0,"referenceVUp":1000.0,"riskRank":"1003","valueType":"int","valueUnit":"毫秒/秒"},{"createTime":1607589588000,"effectHostNum":0,"indexCode":"hive_meta_store_memory_heap_usage","indexId":514,"indexItemCode":"HIVE","indexName":"hiveMetaStore内存使用率","indexSubItemCode":"HiveMetaStore","indexType":"1001","indexValue":0.0542118,"referenceVDown":0.0,"referenceVUp":0.8,"riskRank":"1003","valueType":"float","valueUnit":"使用率"},{"createTime":1607589588000,"effectHostNum":0,"indexCode":"hive_meta_store_threads_count","indexId":515,"indexItemCode":"HIVE","indexName":"hiveMetaStore线程总数","indexSubItemCode":"HiveMetaStore","indexType":"1001","indexValue":216.0,"referenceVDown":0.0,"referenceVUp":1000000.0,"riskRank":"1003","valueType":"int","valueUnit":"个数"},{"createTime":1607589588000,"effectHostNum":0,"indexCode":"hive_meta_store_threads_waiting_count","indexId":516,"indexItemCode":"HIVE","indexName":"hiveMetaStore等待的线程数","indexSubItemCode":"HiveMetaStore","indexType":"1001","indexValue":183.0,"referenceVDown":0.0,"referenceVUp":1000000.0,"riskRank":"1003","valueType":"int","valueUnit":"个数"},{"createTime":1607589588000,"effectHostNum":0,"indexCode":"hive_server_2_open_connections","indexId":517,"indexItemCode":"HIVE","indexName":"hiveServer2连接数","indexSubItemCode":"HiveServer2","indexType":"1001","indexValue":4.0,"referenceVDown":0.0,"referenceVUp":1000000.0,"riskRank":"1003","valueType":"int","valueUnit":"个数"},{"createTime":1607589588000,"effectHostNum":1,"indexCode":"hive_server_2_jvm_pause_extra_sleep_time","indexId":518,"indexItemCode":"HIVE","indexName":"hiveServer2中jvm暂停使用的额外时间","indexSubItemCode":"HiveServer2","indexType":"1001","indexValue":1701.0,"referenceVDown":0.0,"referenceVUp":1000.0,"riskRank":"1003","valueType":"int","valueUnit":"毫秒/秒"},{"createTime":1607589588000,"effectHostNum":0,"indexCode":"hive_server_2_memory_heap_usage","indexId":519,"indexItemCode":"HIVE","indexName":"hiveServer2内存使用率","indexSubItemCode":"HiveServer2","indexType":"1001","indexValue":0.214575,"referenceVDown":0.0,"referenceVUp":0.8,"riskRank":"1003","valueType":"float","valueUnit":"使用率"},{"createTime":1607589588000,"effectHostNum":0,"indexCode":"hive_server_2_threads_count","indexId":520,"indexItemCode":"HIVE","indexName":"hiveServer2线程总数","indexSubItemCode":"HiveServer2","indexType":"1001","indexValue":54.0,"referenceVDown":0.0,"referenceVUp":1000.0,"riskRank":"1003","valueType":"int","valueUnit":"毫秒/秒"},{"createTime":1607589588000,"effectHostNum":0,"indexCode":"hive_server_2_threads_waiting_count","indexId":521,"indexItemCode":"HIVE","indexName":"hiveServer2等待线程总数","indexSubItemCode":"HiveServer2","indexType":"1001","indexValue":10.0,"referenceVDown":0.0,"referenceVUp":1000.0,"riskRank":"1003","valueType":"int","valueUnit":"毫秒/秒"},{"createTime":1607589588000,"effectHostNum":0,"indexCode":"datanode_heartbeats_num_ops","indexId":527,"indexItemCode":"HDFS","indexName":"datanode心跳总数","indexSubItemCode":"DataNode","indexType":"1001","indexValue":209298.0,"referenceVDown":0.0,"referenceVUp":1000000.0,"riskRank":"1003","valueType":"int","valueUnit":"个数"},{"createTime":1607589588000,"effectHostNum":0,"indexCode":"datanode_heartbeats_avg_time","indexId":528,"indexItemCode":"HDFS","indexName":"datanode心跳平均时间","indexSubItemCode":"DataNode","indexType":"1001","indexValue":2.93506,"referenceVDown":0.0,"referenceVUp":100.0,"riskRank":"1003","valueType":"float","valueUnit":"秒"},{"createTime":1607589588000,"effectHostNum":0,"indexCode":"datanode_dfs_used","indexId":529,"indexItemCode":"HDFS","indexName":"datanode中dfs使用的内存","indexSubItemCode":"DataNode","indexType":"1001","indexValue":883008.0,"referenceVDown":0.0,"referenceVUp":1.0E7,"riskRank":"1003","valueType":"int","valueUnit":"MB"},{"createTime":1607589588000,"effectHostNum":0,"indexCode":"datanode_capacity","indexId":530,"indexItemCode":"HDFS","indexName":"datanode总内存","indexSubItemCode":"DataNode","indexType":"1001","indexValue":1013260.0,"referenceVDown":0.0,"referenceVUp":1.0E8,"riskRank":"1003","valueType":"int","valueUnit":"MB"},{"createTime":1607589588000,"effectHostNum":0,"indexCode":"datanode_remaining","indexId":531,"indexItemCode":"HDFS","indexName":"datanode剩余内存","indexSubItemCode":"DataNode","indexType":"1001","indexValue":99767.0,"referenceVDown":0.0,"referenceVUp":1.0E8,"riskRank":"1003","valueType":"int","valueUnit":"个数"},{"createTime":1607589588000,"effectHostNum":0,"indexCode":"nodemanager_containers_running","indexId":532,"indexItemCode":"YARN","indexName":"nodeManager中处于running状态的container数量","indexSubItemCode":"NodeManager","indexType":"1001","indexValue":8.0,"referenceVDown":0.0,"referenceVUp":10000.0,"riskRank":"1003","valueType":"int","valueUnit":"个数"},{"createTime":1607589588000,"effectHostNum":0,"indexCode":"nodemanager_allocated_memory","indexId":533,"indexItemCode":"YARN","indexName":"nodeManager已分配的内存","indexSubItemCode":"NodeManager","indexType":"1001","indexValue":16.5,"referenceVDown":0.0,"referenceVUp":1000.0,"riskRank":"1003","valueType":"int","valueUnit":"GB"},{"createTime":1607589588000,"effectHostNum":0,"indexCode":"nodemanager_allocated_containers","indexId":534,"indexItemCode":"YARN","indexName":"nodeManager已分配的container数量","indexSubItemCode":"NodeManager","indexType":"1001","indexValue":8.0,"referenceVDown":0.0,"referenceVUp":1000.0,"riskRank":"1003","valueType":"int","valueUnit":"个数"},{"createTime":1607589588000,"effectHostNum":0,"indexCode":"nodemanager_available_memory","indexId":535,"indexItemCode":"YARN","indexName":"nodeManager可用的内存","indexSubItemCode":"NodeManager","indexType":"1001","indexValue":37.5,"referenceVDown":0.0,"referenceVUp":1000.0,"riskRank":"1003","valueType":"int","valueUnit":"GB"},{"createTime":1607589588000,"effectHostNum":0,"indexCode":"nodemanager_allocated_v_cores","indexId":536,"indexItemCode":"YARN","indexName":"nodeManager已分配的CPU核心数","indexSubItemCode":"NodeManager","indexType":"1001","indexValue":11.0,"referenceVDown":0.0,"referenceVUp":100.0,"riskRank":"1003","valueType":"int","valueUnit":"个数"},{"createTime":1607589588000,"effectHostNum":0,"indexCode":"nodemanager_available_v_cores","indexId":537,"indexItemCode":"YARN","indexName":"nodeManager可用的CPU核心数","indexSubItemCode":"NodeManager","indexType":"1001","indexValue":21.0,"referenceVDown":0.0,"referenceVUp":1000.0,"riskRank":"1003","valueType":"int","valueUnit":"个数"},{"createTime":1607589588000,"effectHostNum":0,"indexCode":"nodemanager_container_launch_duration_avg_time","indexId":538,"indexItemCode":"YARN","indexName":"nodeManager平均调用container的时间","indexSubItemCode":"NodeManager","indexType":"1001","indexValue":25.0625,"referenceVDown":0.0,"referenceVUp":1000.0,"riskRank":"1003","valueType":"float","valueUnit":"毫秒"},{"createTime":1607589588000,"effectHostNum":0,"indexCode":"nodemanager_mem_non_heap_used","indexId":539,"indexItemCode":"YARN","indexName":"nodeManager非堆内存使用情况","indexSubItemCode":"NodeManager","indexType":"1001","indexValue":58.316,"referenceVDown":0.0,"referenceVUp":10000.0,"riskRank":"1003","valueType":"float","valueUnit":"MB"},{"createTime":1607589588000,"effectHostNum":0,"indexCode":"nodemanager_mem_non_heap_committed","indexId":540,"indexItemCode":"YARN","indexName":"nodeManager中committed的非堆内存","indexSubItemCode":"NodeManager","indexType":"1001","indexValue":74.125,"referenceVDown":0.0,"referenceVUp":10000.0,"riskRank":"1003","valueType":"float","valueUnit":"MB"},{"createTime":1607589588000,"effectHostNum":0,"indexCode":"nodemanager_mem_non_heap_max","indexId":541,"indexItemCode":"YARN","indexName":"nodeManager最大可使用的非堆内存","indexSubItemCode":"NodeManager","indexType":"1001","indexValue":130.0,"referenceVDown":0.0,"referenceVUp":10000.0,"riskRank":"1003","valueType":"float","valueUnit":"MB"},{"createTime":1607589588000,"effectHostNum":0,"indexCode":"nodemanager_mem_heap_used","indexId":542,"indexItemCode":"YARN","indexName":"nodeManager堆内存使用情况","indexSubItemCode":"NodeManager","indexType":"1001","indexValue":394.6115,"referenceVDown":0.0,"referenceVUp":10000.0,"riskRank":"1003","valueType":"float","valueUnit":"MB"},{"createTime":1607589588000,"effectHostNum":0,"indexCode":"nodemanager_mem_heap_committed","indexId":543,"indexItemCode":"YARN","indexName":"nodeManager中committed的堆内存","indexSubItemCode":"NodeManager","indexType":"1001","indexValue":989.875,"referenceVDown":0.0,"referenceVUp":10000.0,"riskRank":"1003","valueType":"float","valueUnit":"MB"},{"createTime":1607589588000,"effectHostNum":0,"indexCode":"nodemanager_mem_heap_max","indexId":544,"indexItemCode":"YARN","indexName":"nodeManager中最大可使用的堆内存","indexSubItemCode":"NodeManager","indexType":"1001","indexValue":989.875,"referenceVDown":0.0,"referenceVUp":10000.0,"riskRank":"1003","valueType":"float","valueUnit":"MB"},{"createTime":1607589588000,"effectHostNum":0,"indexCode":"nodemanager_mem_max","indexId":545,"indexItemCode":"YARN","indexName":"nodeManager中最大可使用的内存","indexSubItemCode":"NodeManager","indexType":"1001","indexValue":989.875,"referenceVDown":0.0,"referenceVUp":10000.0,"riskRank":"1003","valueType":"float","valueUnit":"MB"},{"createTime":1607589588000,"effectHostNum":1,"indexCode":"nodemanager_gc_count_par_new","indexId":546,"indexItemCode":"YARN","indexName":"nodeManager中新生代GC次数","indexSubItemCode":"NodeManager","indexType":"1001","indexValue":79473.0,"referenceVDown":0.0,"referenceVUp":100000.0,"riskRank":"1003","valueType":"int","valueUnit":"次"},{"createTime":1607589588000,"effectHostNum":1,"indexCode":"nodemanager_gc_time_millis_par_new","indexId":547,"indexItemCode":"YARN","indexName":"nodeManager中新生代GC消耗的时间","indexSubItemCode":"NodeManager","indexType":"1001","indexValue":1347686.5,"referenceVDown":0.0,"referenceVUp":1000000.0,"riskRank":"1003","valueType":"int","valueUnit":"毫秒"},{"createTime":1607589588000,"effectHostNum":0,"indexCode":"resourcemanager_mem_non_heap_used","indexId":548,"indexItemCode":"YARN","indexName":"rm已使用的非堆内存","indexSubItemCode":"ResourceManager","indexType":"1001","indexValue":69.2743,"referenceVDown":0.0,"referenceVUp":500.0,"riskRank":"1003","valueType":"float","valueUnit":"MB"},{"createTime":1607589588000,"effectHostNum":0,"indexCode":"resourcemanager_mem_non_heap_committed","indexId":549,"indexItemCode":"YARN","indexName":"rm中committed的非堆内存","indexSubItemCode":"ResourceManager","indexType":"1001","indexValue":95.0625,"referenceVDown":0.0,"referenceVUp":500.0,"riskRank":"1003","valueType":"float","valueUnit":"MB"},{"createTime":1607589588000,"effectHostNum":0,"indexCode":"resourcemanager_mem_non_heap_max","indexId":550,"indexItemCode":"YARN","indexName":"rm中可使用的最大非堆内存","indexSubItemCode":"ResourceManager","indexType":"1001","indexValue":130.0,"referenceVDown":0.0,"referenceVUp":500.0,"riskRank":"1003","valueType":"float","valueUnit":"MB"},{"createTime":1607589588000,"effectHostNum":1,"indexCode":"resourcemanager_mem_heap_used","indexId":551,"indexItemCode":"YARN","indexName":"rm中已使用的堆内存","indexSubItemCode":"ResourceManager","indexType":"1001","indexValue":630.492,"referenceVDown":0.0,"referenceVUp":500.0,"riskRank":"1003","valueType":"float","valueUnit":"MB"},{"createTime":1607589588000,"effectHostNum":0,"indexCode":"resourcemanager_mem_heap_committed","indexId":552,"indexItemCode":"YARN","indexName":"rm中committed的非堆内存","indexSubItemCode":"ResourceManager","indexType":"1001","indexValue":989.875,"referenceVDown":0.0,"referenceVUp":2000.0,"riskRank":"1003","valueType":"float","valueUnit":"MB"},{"createTime":1607589588000,"effectHostNum":0,"indexCode":"resourcemanager_mem_heap_max","indexId":553,"indexItemCode":"YARN","indexName":"rm中可使用的最大堆内存","indexSubItemCode":"ResourceManager","indexType":"1001","indexValue":989.875,"referenceVDown":0.0,"referenceVUp":2000.0,"riskRank":"1003","valueType":"float","valueUnit":"MB"},{"createTime":1607589588000,"effectHostNum":0,"indexCode":"resourcemanager_mem_max","indexId":554,"indexItemCode":"YARN","indexName":"rm中分配的最大内存","indexSubItemCode":"ResourceManager","indexType":"1001","indexValue":989.875,"referenceVDown":0.0,"referenceVUp":2000.0,"riskRank":"1003","valueType":"float","valueUnit":"MB"},{"createTime":1607589588000,"effectHostNum":0,"indexCode":"resourcemanager_gc_count_par_new","indexId":555,"indexItemCode":"YARN","indexName":"rm中新生代GC次数","indexSubItemCode":"ResourceManager","indexType":"1001","indexValue":64652.0,"referenceVDown":0.0,"referenceVUp":1000000.0,"riskRank":"1003","valueType":"int","valueUnit":"次"},{"createTime":1607589588000,"effectHostNum":0,"indexCode":"resourcemanager_gc_time_millis_par_new","indexId":556,"indexItemCode":"YARN","indexName":"rm中新生代gc时间","indexSubItemCode":"ResourceManager","indexType":"1001","indexValue":923638.0,"referenceVDown":0.0,"referenceVUp":1000000.0,"riskRank":"1003","valueType":"int","valueUnit":"毫秒"},{"createTime":1607589588000,"effectHostNum":0,"indexCode":"namenode_under_replicated_blocks","indexId":563,"indexItemCode":"HDFS","indexName":"总的待复制的区块","indexSubItemCode":"NameNode","indexType":"1001","indexValue":86832.0,"referenceVDown":0.0,"referenceVUp":1000000.0,"riskRank":"1003","valueType":"int","valueUnit":"个数"},{"createTime":1607589588000,"effectHostNum":0,"indexCode":"namenode_corrupt_blocks","indexId":564,"indexItemCode":"HDFS","indexName":"损坏的区块数","indexSubItemCode":"NameNode","indexType":"1001","indexValue":66.0,"referenceVDown":0.0,"referenceVUp":1000000.0,"riskRank":"1003","valueType":"int","valueUnit":"个数"},{"createTime":1607589588000,"effectHostNum":0,"indexCode":"namenode_total_dirs","indexId":566,"indexItemCode":"HDFS","indexName":"总的目录数","indexSubItemCode":"NameNode","indexType":"1001","indexValue":84409.0,"referenceVDown":0.0,"referenceVUp":1.0E8,"riskRank":"1003","valueType":"int","valueUnit":"个数"},{"createTime":1607589588000,"effectHostNum":0,"formula":"","indexCode":"namenode_total_files","indexId":567,"indexItemCode":"HDFS","indexName":"总的文件数","indexSubItemCode":"NameNode","indexType":"1001","indexValue":121231.0,"referenceVDown":0.0,"referenceVUp":1.0E8,"riskRank":"1003","valueType":"int","valueUnit":"个数"},{"createTime":1607589588000,"effectHostNum":1,"indexCode":"exceeding_max_num_subtexts_dirs_num","indexId":589,"indexItemCode":"HDFS","indexName":"超过限定子文件数量的文件目录的数量","indexSubItemCode":"NameNode","indexType":"1001","indexValue":40.0,"referenceVDown":0.0,"referenceVUp":0.0,"riskRank":"1003","valueType":"int","valueUnit":"个"},{"createTime":1607589588000,"effectHostNum":0,"indexCode":"hmaster_num_open_connections","indexId":486,"indexItemCode":"HBASE","indexName":"HMaster连接数检测","indexSubItemCode":"HMaster","indexType":"1001","indexValue":2.0,"referenceVDown":0.0,"referenceVUp":100.0,"riskRank":"1003","valueType":"int","valueUnit":"个数"},{"createTime":1607589588000,"effectHostNum":0,"indexCode":"hmaster_gc_count_par_new","indexId":487,"indexItemCode":"HBASE","indexName":"HMaster新生代GC次数","indexSubItemCode":"HMaster","indexType":"1001","indexValue":1664.0,"referenceVDown":0.0,"referenceVUp":2000.0,"riskRank":"1003","valueType":"int","valueUnit":"次数"},{"createTime":1607589588000,"effectHostNum":1,"indexCode":"hmaster_gc_time_millis_par_new","indexId":488,"indexItemCode":"HBASE","indexName":"HMaster新生代GC耗时","indexSubItemCode":"HMaster","indexType":"1001","indexValue":12481.0,"referenceVDown":0.0,"referenceVUp":10000.0,"riskRank":"1003","valueType":"int","valueUnit":"毫秒"},{"createTime":1607589588000,"effectHostNum":0,"indexCode":"hmaster_gc_count_concurrent_mark_sweep","indexId":489,"indexItemCode":"HBASE","indexName":"HMaster老年代GC次数","indexSubItemCode":"HMaster","indexType":"1001","indexValue":0.0,"referenceVDown":0.0,"referenceVUp":100.0,"riskRank":"1003","valueType":"int","valueUnit":"次数"},{"createTime":1607589588000,"effectHostNum":0,"indexCode":"hmaster_gc_time_millis_concurrent_mark_sweep","indexId":490,"indexItemCode":"HBASE","indexName":"HMaster老年代GC耗时","indexSubItemCode":"HMaster","indexType":"1001","indexValue":0.0,"referenceVDown":0.0,"referenceVUp":10000.0,"riskRank":"1003","valueType":"int","valueUnit":"毫秒"},{"createTime":1607589588000,"effectHostNum":0,"indexCode":"region_server_num_open_connections","indexId":492,"indexItemCode":"HBASE","indexName":"当前regionServer的连接数","indexSubItemCode":"HRegionServer","indexType":"1001","indexValue":1.0,"referenceVDown":0.0,"referenceVUp":100.0,"riskRank":"1003","valueType":"int","valueUnit":"个数"},{"createTime":1607589588000,"effectHostNum":0,"indexCode":"region_server_read_request_count","indexId":493,"indexItemCode":"HBASE","indexName":"regionServer的读请求数","indexSubItemCode":"HRegionServer","indexType":"1001","indexValue":3.39328E8,"referenceVDown":0.0,"referenceVUp":1.0E12,"riskRank":"1003","valueType":"int","valueUnit":"个数"},{"createTime":1607589588000,"effectHostNum":0,"indexCode":"region_server_write_request_count","indexId":494,"indexItemCode":"HBASE","indexName":"regionServer的写请求数","indexSubItemCode":"HRegionServer","indexType":"1001","indexValue":490688.0,"referenceVDown":0.0,"referenceVUp":1000000.0,"riskRank":"1003","valueType":"int","valueUnit":"个数"},{"createTime":1607589588000,"effectHostNum":0,"indexCode":"region_server_regions","indexId":495,"indexItemCode":"HBASE","indexName":"regionServer的region数量","indexSubItemCode":"HRegionServer","indexType":"1001","indexValue":483.0,"referenceVDown":0.0,"referenceVUp":1000000.0,"riskRank":"1003","valueType":"int","valueUnit":"个数"},{"createTime":1607589588000,"effectHostNum":0,"indexCode":"region_server_gc_count_par_new","indexId":496,"indexItemCode":"HBASE","indexName":"regionServer新生代GC次数","indexSubItemCode":"HRegionServer","indexType":"1001","indexValue":2775.0,"referenceVDown":0.0,"referenceVUp":1000000.0,"riskRank":"1003","valueType":"int","valueUnit":"次"},{"createTime":1607589588000,"effectHostNum":0,"indexCode":"region_server_gc_time_millis_par_new","indexId":497,"indexItemCode":"HBASE","indexName":"regionServer新生代GC耗时","indexSubItemCode":"HRegionServer","indexType":"1001","indexValue":239203.0,"referenceVDown":0.0,"referenceVUp":1000000.0,"riskRank":"1003","valueType":"int","valueUnit":"毫秒"},{"createTime":1607589588000,"effectHostNum":0,"indexCode":"region_server_gc_count_concurrent_mark_sweep","indexId":498,"indexItemCode":"HBASE","indexName":"regionServer老年代GC次数","indexSubItemCode":"HRegionServer","indexType":"1001","indexValue":51.0,"referenceVDown":0.0,"referenceVUp":1000000.0,"riskRank":"1003","valueType":"int","valueUnit":"次"},{"createTime":1607589588000,"effectHostNum":0,"indexCode":"region_server_gc_time_millis_concurrent_mark_sweep","indexId":499,"indexItemCode":"HBASE","indexName":"regionServer老年代GC耗时","indexSubItemCode":"HRegionServer","indexType":"1001","indexValue":8106.0,"referenceVDown":0.0,"referenceVUp":1000000.0,"riskRank":"1003","valueType":"int","valueUnit":"毫秒"},{"createTime":1607589588000,"effectHostNum":0,"indexCode":"region_server_slow_get_count","indexId":500,"indexItemCode":"HBASE","indexName":"regionServer的get操作完成时间超过1000ms的次数","indexSubItemCode":"HRegionServer","indexType":"1001","indexValue":0.0,"referenceVDown":0.0,"referenceVUp":1000000.0,"riskRank":"1003","valueType":"int","valueUnit":"次"},{"createTime":1607589588000,"effectHostNum":0,"indexCode":"region_server_slow_put_count","indexId":501,"indexItemCode":"HBASE","indexName":"regionServer的put操作完成时间超过1000ms的次数","indexSubItemCode":"HRegionServer","indexType":"1001","indexValue":2.0,"referenceVDown":0.0,"referenceVUp":1000000.0,"riskRank":"1003","valueType":"int","valueUnit":"次"},{"createTime":1607589588000,"effectHostNum":0,"indexCode":"region_server_slow_append_count","indexId":502,"indexItemCode":"HBASE","indexName":"regionServer的append操作完成时间超过1000ms的次数","indexSubItemCode":"HRegionServer","indexType":"1001","indexValue":0.0,"referenceVDown":0.0,"referenceVUp":1000000.0,"riskRank":"1003","valueType":"int","valueUnit":"次"},{"createTime":1607589588000,"effectHostNum":0,"indexCode":"region_server_slow_delete_count","indexId":503,"indexItemCode":"HBASE","indexName":"regionServer的delete操作完成时间超过1000ms的次数","indexSubItemCode":"HRegionServer","indexType":"1001","indexValue":0.0,"referenceVDown":0.0,"referenceVUp":1000000.0,"riskRank":"1003","valueType":"int","valueUnit":"次"},{"createTime":1607589588000,"effectHostNum":0,"indexCode":"region_server_slow_increment_count","indexId":504,"indexItemCode":"HBASE","indexName":"regionServer的increment操作完成时间超过1000ms的次数","indexSubItemCode":"HRegionServer","indexType":"1001","indexValue":0.0,"referenceVDown":0.0,"referenceVUp":1000000.0,"riskRank":"1003","valueType":"int","valueUnit":"次"},{"createTime":1607589588000,"effectHostNum":0,"indexCode":"hive_meta_store_open_connections","indexId":506,"indexItemCode":"HIVE","indexName":"hiveMetaStore的连接数","indexSubItemCode":"HiveMetaStore","indexType":"1001","indexValue":24.0,"referenceVDown":0.0,"referenceVUp":1000000.0,"riskRank":"1003","valueType":"int","valueUnit":"个数"},{"createTime":1607589588000,"effectHostNum":0,"indexCode":"hive_meta_store_create_total_count_dbs","indexId":507,"indexItemCode":"HIVE","indexName":"hiveMetaStore创建的数据库总数","indexSubItemCode":"HiveMetaStore","indexType":"1001","indexValue":2075.0,"referenceVDown":0.0,"referenceVUp":1000000.0,"riskRank":"1003","valueType":"int","valueUnit":"个数"},{"createTime":1607589588000,"effectHostNum":0,"indexCode":"hive_meta_store_create_total_count_tables","indexId":508,"indexItemCode":"HIVE","indexName":"hiveMetaStore创建的表总数","indexSubItemCode":"HiveMetaStore","indexType":"1001","indexValue":2443.0,"referenceVDown":0.0,"referenceVUp":1000000.0,"riskRank":"1003","valueType":"int","valueUnit":"个数"},{"createTime":1607589588000,"effectHostNum":0,"indexCode":"hive_meta_store_create_total_count_partitions","indexId":509,"indexItemCode":"HIVE","indexName":"hiveMetaStore创建的分区总数","indexSubItemCode":"HiveMetaStore","indexType":"1001","indexValue":4229.0,"referenceVDown":0.0,"referenceVUp":1000000.0,"riskRank":"1003","valueType":"int","valueUnit":"个数"},{"createTime":1607589588000,"effectHostNum":0,"indexCode":"hive_meta_store_delete_total_count_dbs","indexId":510,"indexItemCode":"HIVE","indexName":"hiveMetaStore删除的数据库总数","indexSubItemCode":"HiveMetaStore","indexType":"1001","indexValue":2075.0,"referenceVDown":0.0,"referenceVUp":1000000.0,"riskRank":"1003","valueType":"int","valueUnit":"个数"},{"createTime":1607589588000,"effectHostNum":0,"indexCode":"hive_meta_store_delete_total_count_tables","indexId":511,"indexItemCode":"HIVE","indexName":"hiveMetaStore删除的表总数","indexSubItemCode":"HiveMetaStore","indexType":"1001","indexValue":2436.0,"referenceVDown":0.0,"referenceVUp":1000000.0,"riskRank":"1003","valueType":"int","valueUnit":"个数"}]') || []),
applicationReport: Object.freeze(JSON.parse('null') || []),
repairAdvice: JSON.parse('"请人工咨询"') || '',
exceptionSite: `DataNode:主机host166异常;
NodeManager:主机host166异常、主机host167异常;
以下目录的子文件夹数量超过500个
/user/hive/zfetch 该目录下的子文件数量为:2428
`, //特殊字符不能用json处理;
// exceptionSite: `DataNode:主机host166异常;
// NodeManager:主机host166异常、主机host167异常;
// `,
},
});
</script>
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
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
# 在线预览PDF
# PDFjs介绍
PDF.js (opens new window)是使用 HTML5 构建的可移植文档格式 (PDF) 查看器。 PDF.js 由社区驱动并受 Mozilla 支持。我们的目标是创建一个通用的、基于 Web 标准的平台来解析和呈现 PDF。官方案例详细说明 (opens new window)
# 实践
- 官网给出的使用方法是将PDF.js下载到项目静态资源目录中,在html文件中引入pdf.js去使用,但这样会导致最后项目编译打包后的资源包比较大。
- pdfjs-dist这一node库这好可以解决我们的问题。pdfjs-dist是pdf.js源代码的预构建版本,我们直接在项目中引入该库即可使用,接下来我们介绍如何使用。
- 需要预览的PDF一般是后台接口返回的base64编码数据或者是本地上传获取到文件,接下来我们在vue工程上实现本地上传PDF文件,获取文件的base64编码,利用pdf.js实现预览效果。
//npm install pdfjs-dist
previewPDF() {
// 引入pdf.js的字体
let CMAP_URL = 'https://unpkg.com/pdfjs-dist@2.0.943/cmaps/'
//读取base64的pdf流文件
let loadingTask = pdfJS.getDocument({
data: this.pdfData, // PDF base64编码
cMapUrl: CMAP_URL,
cMapPacked: true
})
loadingTask.promise.then((pdf) => {
console.log('PDF loaded');
this.loadFinished = true
let numPages = pdf.numPages
let pageNumber = 1 // 获取第一页
this.getPage(pdf, pageNumber, numPages)
})
},
getPage(pdf, pageNumber, numPages) {
let _this = this
pdf.getPage(pageNumber)
.then((page) => {
// 准备画布使用PDF页面尺寸
// var canvas = document.getElementById('the-canvas');
let canvas = this.$refs.myCanvas
let ctx = canvas.getContext('2d')
//var scale = 1.5;
//var viewport = page.getViewport({scale: scale});
let viewport = page.getViewport(_this.scale)
canvas.height = viewport.height
canvas.width = viewport.width
// 渲染PDF页到画布上下文
let renderContext = {
canvasContext: ctx,
viewport: viewport
}
page.render(renderContext).then(() => {
console.log('Page rendered');
pageNumber += 1
if (pageNumber <= numPages) {
_this.getPage(pdf, pageNumber, numPages)
}
})
})
}
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
# 参考链接
- https://segmentfault.com/a/1190000009211079