一、16进制颜色随机值生成
getRandomColorValue(){
let str: string = '#';
const arr: Array<string> = ['0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'];
for(let i = 0; i < 6; i++){
const num = parseInt((Math.random()*16).toString());
str += arr[num]
}
return str;
}
二、angular请求拦截器
1.生成新的ts文件
import { Injectable } from '@angular/core';
import { HttpInterceptor, HttpEvent, HttpHandler, HttpRequest, HTTP_INTERCEPTORS } from '@angular/common/http';
import { Observable } from 'rxjs';
import {environment} from '../../../../environments/environment'
/**
* 拦截器
*/
@Injectable()
class InterceptorService implements HttpInterceptor {
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
let reqInterception: any;
const loginUrl: any = environment.baseUrl + 'user/login'
if (req.url !== loginUrl) {
if (localStorage.getItem('access_token')) { // 判断是否存在token
const token: any = localStorage.getItem('access_token') || ''; // 一定存在token
reqInterception = req.clone({setHeaders:{token: token}}) // 写入token
next.handle(reqInterception)
} else throw new Error('没登录成功哈!')
//else this.router.navigate(['/login']);
}
reqInterception = req.clone({setHeaders:{}})
return next.handle(reqInterception);
}
}
/**
* 拦截器收集
*/
export const httpInterceptorProviders = [
{ provide: HTTP_INTERCEPTORS, useClass: InterceptorService, multi: true }
]
2.app.model.ts中注入
import { httpInterceptorProviders } from './shared/services/http/httpIntercept' // 请求拦截器
providers: [
httpInterceptorProviders // 请求拦截器注入
],
三、word生成
1,公共方法
/**
* word文档生成
* @param exportWordFormParams 参数
* @param exportWordUrl 地址
* @param pagesType 页面类型
* @returns Promise<any> = true
*/
public async exportWordDocument(exportWordFormParams: object, exportWordUrl: string, pagesType: string): Promise<any>{
const exportWordFormUrl = environment.baseUrl + exportWordUrl;
const exportWordFormOptions:any = { // 请求option参数
headers: new HttpHeaders().set("Content-type", 'application/json;charset=UTF-8').set("access-control-allow-origin", '*'),
responseType: 'blob',
observe:'response'
}
let loading = parent.window.document.querySelector('.loading-box') as HTMLElement;
if(loading == null) return;
loading.style.display = 'block';
let response: any = await this.HttpClient.post<any>(exportWordFormUrl, JSON.stringify(exportWordFormParams), exportWordFormOptions).toPromise()
if (response.status != 200) {
this.message.error(response.statusText)
return
}
let blob = new Blob([response.body], { type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=UTF-8' });
let link = document.createElement('a');
let worldUploadUrl = URL.createObjectURL(blob);
link.setAttribute("href", worldUploadUrl);
link.setAttribute("download", pagesType + '.docx');
link.click();
window.URL.revokeObjectURL(link.href); //释放内存
loading.style.display = 'none';
return response.ok;
}
2,调用方法
import{ publicFunctions } from'src/app/shared/model/product-making/publicMethods'
publicFunctions: any = null; // 公共方法
/**
* 初始化 公共方法库
*/
initPublicFunctions(){
this.publicFunctions = new publicFunctions(this.httpService,this.message,this.HttpClient)
// 获取期数
this.publicFunctions.getWordNumberNames(this.pagesType).then(res => {this.shortTermAreaRainfallForecast.number = res})
// 获取审核人集合
this.publicFunctions.getAuditOption(this.unitId).then(res => {this.shortTermAreaRainfallForecast.audit = res.audit,this.shortTermAreaRainfallForecast.auditOption = res.auditOption})
}
// 生成word文档
async onWeaterReportFormClick(e: any) {
const exportWordFormUrl = 'productMake/shortTermAreaRainForecastReport';
let exportWordFormParams: any = { // 文档所需参数内容
number: this.shortTermAreaRainfallForecast.number, // 期数
time: moment(this.shortTermAreaRainfallForecast.time).format('YYYY-MM-DD HH:00:00'), // 时间(发布时间)
author: this.shortTermAreaRainfallForecast.author, // 制作人
audit: this.shortTermAreaRainfallForecast.audit, // 审核人
phone: this.shortTermAreaRainfallForecast.phone, // 电话
picture: this.imageUpload.imgFiles.map((item: any) => {return item.thumbUrl}) == null ? [] : this.imageUpload.imgFiles.map((item: any) => {return item.thumbUrl}), // 淮河流域雨量图
pictureExplain: this.shortTermAreaRainfallForecast.pictureExplain, // 图片说明
hhForecast: this.shortTermAreaRainfallForecast.hhForecast,//淮河流域未来三天面雨量预报
ahForecast: this.shortTermAreaRainfallForecast.ahForecast,//安徽流域未来三天面雨量预报
}
//生成word文档
this.publicFunctions.exportWordDocument(exportWordFormParams,exportWordFormUrl,this.pagesType).then(res => {
if(res == true) this.restFormData(); // 清空表单
});
}
注:异步方法async的return 值为Promise<any>,需要.then,.catch进行取值
四、base64转blob
/**
* 编码转blob文件流
* @param base64 编码
* @returns blob
*/
public base64ToBlob(base64: any): any{
const arr = base64.split(',')
let mime = arr[0].match(/:(.*?);/)[1]
let encodeStr = atob(arr[1])
let n = encodeStr.length
let u8Arr = new Uint8Array(n)
while (n--) {
u8Arr[n] = encodeStr.charCodeAt(n)
}
return new Blob([u8Arr], {type: mime})
}
/**
* blob 转 file
* @param blob 文件流
* @returns file
*/
public blobToFile(blob: any): any{
return new File([blob], `${new Date().getTime()}.png`, { type: blob.type })
}
五、图片转base64
1、方法
/**
* 图片转base64编码
* @param imgUrl 图片地址url 例:assets/images/logo.png
* @returns Promise
* @time 2023-6-16
* @writer wy
*/
private async imgToBase64(imgUrl: string) {
return new Promise((resolve, reject) => {
const image = new Image()
image.src = imgUrl
image.onload = () => {
const canvas = document.createElement('canvas')
canvas.width = image.naturalWidth // 使用 naturalWidth 为了保证图片的清晰度
canvas.height = image.naturalHeight
canvas.style.width = `${canvas.width / window.devicePixelRatio}px`
canvas.style.height = `${canvas.height / window.devicePixelRatio}px`
const ctx = canvas.getContext('2d')
if (!ctx) {
return null
}
ctx.drawImage(image, 0, 0)
const base64 = canvas.toDataURL('image/png')
return resolve(base64)
}
image.onerror = (err) => {
return reject(err);
}
})
}
2、调用
this.imgToBase64(iamgeUrl).then(res => {
console.log(res) // base64
}).catch(err => {console.log(err)})
六、excel生成导出
npm install xlsx
// npm install file-saver
// npm install script-loader
import * as XLSX from 'xlsx';
onExportExcelClick() { // 普通导出 Excel
let excelTable: any = []
this.tableListData.forEach((item: any) => {
let excelRow: any = {};
excelRow['产品'] = item.titleName;
excelRow['时效'] = item.time;
excelRow['站点'] = item.region;
if (this.arealRainfallChecked.indexOf('abs') !== -1) excelRow['绝对误差'] = item.abs == -999 ? '暂无数据' : item.abs;
if (this.arealRainfallChecked.indexOf('rel') !== -1) excelRow['相对误差'] = item.rel == -999 ? '暂无数据' : item.rel;
if (this.arealRainfallChecked.indexOf('ts') !== -1) excelRow['TS评分'] = item.ts == -999 ? '暂无数据' : item.ts;
if (this.arealRainfallChecked.indexOf('blur_score') !== -1) excelRow['模糊评分'] = item.blur_score == -999 ? '暂无数据' : item.abs;
excelTable.push(excelRow)
});
this.jsonToSheet(excelTable, '面雨量评分表格导出.xls');
}
onCorrelationExportExcelClick() { // 对比导出 Excel(2023-5-24)
let CorrelationTable: any = []
for (let i = 0; i < this.CorrelationData.length; i++) {
this.CorrelationData[i].correlationData.forEach((item: any) => {
let excelRow: any = {};
excelRow['产品'] = item.modelName;
excelRow['时效'] = item.agingTime;
excelRow['站点'] = item.siteName;
excelRow['实况数据'] = item.liveValue;
excelRow['预报数据'] = item.forecastValue;
CorrelationTable.push(excelRow)
});
}
this.jsonToSheet(CorrelationTable, '预报和实况对比数据表格导出.xls');
}
jsonToSheet(json: any[], filename: string): void { // JSON 转 Excel
//生成工作表
const worksheet: XLSX.WorkSheet = XLSX.utils.json_to_sheet(json);
//生成工作页
const workbook: XLSX.WorkBook = XLSX.utils.book_new();
// 融合页表
XLSX.utils.book_append_sheet(workbook, worksheet, 'Sheet1');
// 保存 文件
XLSX.writeFile(workbook, filename);
}
文献地址:https://www.npmjs.com/package/xlsx
七、数据合并(表格合并)
sortAndMerge(rawDataList): any[] { // 处理合并数据
const rowspan = this.rowspan, mergeColumns = this.mergeColumns;
if (rawDataList.length > 1) {//长度大于1才有资格进一步处理
const sortColumn = Object.keys(rawDataList[0]), // 字段名称 ['region', 'time', 'rel', 'abs', 'ts', 'blur_score']
keySort = raw => {
for (let i = raw.length - 1; i > 0; i--) {
let newObj = {}, tmpObj = raw[i]; // raw[i]是单条数据
sortColumn.forEach(s => {
// s 为 ['region', 'time', 'rel', 'abs', 'ts', 'blur_score'] 中的每一项
newObj[s] = tmpObj[s]
});
raw[i] = newObj;
}
return raw;
},
compare = (a, b, c = sortColumn[0], i = 0) => {
if (a[c] === b[c]) { //等于的话进行判断是否还有后续字段需要排序,没有则返回0;有则递归进行后续字段排序处理。
if (i === sortColumn.length - 1) {//没有后续字段
return i = 0;
}
i++;
return compare(a, b, sortColumn[i], i);//递归排序后续字段
} else if (a[c] > b[c]) { //大于返回1
return 1;
} else { //小于返回-1
return -1;
}
},
arr = keySort(JSON.parse(JSON.stringify(rawDataList))),
aLen = arr.length;
for (let i = mergeColumns.length - 1; i >= 0; i--) {//先迭代待合并列
let index = 0;
let title = mergeColumns[i];
let span = 1;//合并列属性默认为1
for (let j = 0; j < aLen; j++) {
let comp = arr[index][title];
let compRegion = arr[index]['region']; // 拿到名称
// if (arr[j][title] === comp) {
if (arr[j][title] === comp && arr[j]['region'] === compRegion) {
j !== index && (delete arr[j][title], span++);
j === aLen - 1 && (arr[index][rowspan + title] = span);
} else {
span > 1 && (arr[index][rowspan + title] = span, span = 1);
index = j;
}
}
}
return arr;
}
return rawDataList;
}
disposeTableData(dataOrigin: any) { // 处理合并数据源
let data: any = [];
let transferData: any = [];
dataOrigin.forEach((item: any) => {
if (transferData.length === 0) {
transferData[0] = []
transferData[0].push(item)
} else {
let flag: any = -1;
for (let i = 0; i < transferData.length;i++ ) {
if(transferData[i][0].region === item.region) {
transferData[i].push(item)
break
}
if ((i + 1) === transferData.length) {
flag = transferData.length;
}
}
if (flag !== -1) {
transferData[flag] = []
transferData[flag].push(item)
flag = -1
}
}
})
for (let i = 0; i < transferData.length; i++) {
this.sortAndMerge(transferData[i]).forEach((item) => {
data.push(item)
})
// data.push(this.sortAndMerge(transferData[i]))
}
return data
}
八、滚动条插件
npm install smooth-scrollbar --save
import Scrollbar from 'smooth-scrollbar';
/**
* Scrollbar初始化
*/
getPagesScrollbarInit() {
let element = document.querySelector('#right-model-weather') as HTMLElement; // 获取需要添加滚动条的元素
Scrollbar.init(element);
}
文献地址:https://www.npmjs.com/package/smooth-scrollbar
九、object.keys(object)用法,作用于遍历对象(返回对象可枚举属性),return 枚举Array
// 天气公报-word生成数据
weatherReport: any = {
number: null, // 期数
time: new Date(), // 时间(发布时间)
formatDate:'yyyy-MM-dd HH:00:00',
author: '', // 制作人
audit: null, // 审核人
auditOption: [], // 审核人集合
phone: '62290367', // 电话
overview: '', // 概述(水文气象监测)
rain: '', // 雨情
water: '', // 水情
// rainPicture: '', // 图片
weatherForecast: '', // 预报(未来三天天气预报)
// waterTime: null, // 水文数据时间
}
/**
* 清空表单
*/
Object.keys(this.weatherReport).forEach((key) => {
key == 'time' ? this.weatherReport[key] = new Date()
: key == 'number' ? this.weatherReport[key] = null
: key == 'formatDate' ? this.weatherReport[key] = 'yyyy-MM-dd HH:00:00'
: key == 'phone' ? this.weatherReport[key] = '62290367'
: key == 'author' ? this.weatherReport[key] = this.weatherReport[key]
: key == 'audit' ? this.weatherReport[key] = this.weatherReport[key]
: key == 'auditOption' ? this.weatherReport[key] = this.weatherReport[key]
: this.weatherReport[key] = '';
})
十、moment().format()用法
npm install moment --save
import * as moment from 'moment';
moment(需要格式化的时间,需要格式化的数据时间格式)add(需要增加的时间长度,增加的时间类型【年月日时分秒】).format(时间需要格式化的格式)
例1):moment('202202121515','YYYYMMDDHH0000').add(10, 'h').add( -5, 'h').format('YYYY年MM月DD日 HH时')
例2):[moment(moment().add(-1, 'day').format('YYYY-MM-DD 08:00:00')).toDate(), moment(new Date()).format('YYYY-MM-DD 08:00:00')] // 时间段
文献地址:https://www.npmjs.com/package/vue-moment
十一、音频播放器(进入页面自动播放)
属性参考文献:(HTML DOM Audio对象的方法、属性和事件)
HTML代码:
<audio id="audioPlayMp3" [src]="audioPalySrc"></audio>
<button (click)="audioPlayAndPauseClick(false)" title="停止播放">停止播放</button>
TS代码:(注:页面销毁时要销毁自动播放)
audioPalySrc: string = '../../assets/videos/Alarmtone.mp3'; // 音频地址
/*
* 页面初始化时 调用 this.audioPlayAndPauseClick()
*/
/*
* 页面销毁时 调用 this.audioPlayAndPauseClick(false)
*/
audioPlayAndPauseClick(type: boolean = true){
const audioElement: any = document.getElementsByTagName('audio'); // 获取audio元素
audioElement['audioPlayMp3'].load(); // 加载
// audioElement['audioPlayMp3'].play(); // 播放
audioElement['audioPlayMp3'].autoplay = type; // 自动播放
audioElement['audioPlayMp3'].loop = type; // 循环播放
if(!type) audioElement['audioPlayMp3'].pause() // 暂停
}