ace-component
Version:
ace-components for ewms
819 lines (713 loc) • 22.7 kB
text/typescript
import { Component, OnInit, ViewEncapsulation, Input, Output, ElementRef,
NgZone, EventEmitter, ChangeDetectorRef,OnChanges,ContentChild,TemplateRef} from '@angular/core';
import { AjaxSetting, AceTableService, CBparams } from './ace-table.service'
import * as $ from 'jquery'
interface DataInfo {
page: number;
totalPage?: number;
total?: number;
startId?: number;
endId?: number;
}
interface ModalState {
show: boolean;
text?: string;
}
interface ShowTr {
el: any;
show: boolean;
}
export class AceTableComponent implements OnInit {
template;
DEGUGGER:boolean = false;
tbTitle; //表格标题
_dataSource: Array<object> = [];//遍历的数据
set dataSource(val: Array<object>) {
this._dataSource = val;
this.init();
}
get dataSource() {
return this._dataSource
}
theadSource: Array<object> //表头数据
widths: Array<number> = []; //默认宽度100;
minWidth: number = 100;//最小宽度
_tableHeight:number;
get tableHeight():number{
return this._tableHeight
}
set tableHeight(val){
this._tableHeight = val;
if(this.tableEle){
this.styInit()
}
}
// @Input() rowNumber: number = 10; //一页的函数,默认10
multipleChoice: boolean = true; //是否可以多选
loading: boolean = false; //加载动画
dataInf: DataInfo = { //数据的相关信息
page: 1,
totalPage: 1,
total: 1,
startId: 0,
endId: 0
};
modalState: ModalState = { //modal框的设置
show: false,
text: "初次打开页面不加载数据,请组合条件进行搜索数据..."
};
operateState: boolean = false; //控制开关状态
changeState: boolean = false; //操作状态
paginNum: number = 5; //翻页器显示的数量
onSelect = new EventEmitter(); //选中了某一行触发的事件
onChangeRows = new EventEmitter(); //改变了每页行数的事件
onChangePage = new EventEmitter(); //翻页
onReflresh = new EventEmitter(); //刷新单项
onChangeInfomation = new EventEmitter();
onDelInfomation = new EventEmitter();
onAjaxOver = new EventEmitter();
private wrapEle: any; //容器
private tableEle: any; //表格区
private theadEle: any; //头部
public theadSty: any; //头部的样式
public thOffsetLeft: number = 0; //头部偏移量
private contentEle: any; //内容区
private moveBlock: any; //拖动的模型
private lineEle: any; //标志线
public wrapWidth: number; //容器宽度
private tableWidth: number; //表格区宽度
private colsWidth: Array<number> = []; //每一列的实际宽度
private movedCol: number | null; //可以移动的列的下标
private moveStarX: number | null = null; //初始位置
private moveCurrX: number | null = null; //最新的位置
private colSetVals: Array<number> = []; //用户设置的固定宽度,包括拖动,固定宽度
private setColsTotal: number; //设置的值的固定宽度
private tdpadding: number; //td,td padding值
private closeStatus: boolean = false; //收起
private checkRow: object = {}; //选中的行
private selectAll: boolean = false; //选中的行
private windowResize: any; //window.onresize 绑定的函数
private mouseUpFunction: any; //window.mouseup 绑定的函数
private inPutEle: any; //底部页数输入框
public inputValue: any = 1; //底部页数输入框 输入的值
public inputTextSty: object = { //输入框样式
"z-index": 5
};
private operaRefresh: Array<boolean>; //正在刷新的行的集合
private operaShowDetail: Array<ShowTr> = []; //正在展开的行的集合
rowNumber: number = 30; //一页的函数,默认30
_selectOption:Array<number>=[
10,20,30,50,100
];
set selectOption(arr:Array<number>){
this._selectOption = arr;
}
get selectOption(){
return this._selectOption
}
constructor(
private el: ElementRef,
private zone: NgZone,
public service: AceTableService,
public cd: ChangeDetectorRef
) {
this.cd.detach();
}
ngOnChanges() {
this.do();
setTimeout(() => {
this.tableResize();
});
this.inputValue = this.dataInf.page;
}
ngOnInit() {
if (!this.theadSource) {
throw new Error('theadSource is undefined.theadSource is required.')
};
this.colsWidth = [];
Promise.resolve().then(() => {
this.init();
this.getElementWidth();
if ("colsWidth" in this) {
this.setUserSettingWidth() ? this.styInit() : "";
} else {
this.styInit()
}
}).then(() => {
//绑定事件
let timeout;
this.windowResize = function () {
clearTimeout(timeout);
setTimeout(() => {
this.zone.run(() => {
this.tableResize();
});
}, 200)
};
this.windowResize = this.windowResize.bind(this);
window.addEventListener('resize', this.windowResize);
}).then(() => {
this.mouseUpFunction = this.mouseUp.bind(this);
document.body.addEventListener('mouseup', this.mouseUpFunction);
}).then(() => {
if (this.ajaxUrl) {
if (typeof this.setParamsFn != 'function') {
throw 'settingParams must be function , it is used to setting http params';
}
this.modalState.show = true;
}
});
}
ngOnDestroy() {
document.body.removeEventListener('mouseup', this.mouseUpFunction);
window.removeEventListener('resize', this.windowResize);
}
do() {
this.cd.detectChanges();
}
//获取关键节点
init() {
this.wrapEle = (<any>$(this.el.nativeElement)).find('.ace-wrap');
this.tableEle = $(this.wrapEle).find('.ace-table-content');
this.theadEle = (<any>$(this.el.nativeElement)).find('.ace-table-thead');
this.contentEle = (<any>$(this.el.nativeElement)).find('.ace-table-list');
this.moveBlock = (<any>$(this.el.nativeElement)).find('.ace-move-block');
this.lineEle = (<any>$(this.el.nativeElement)).find('.ace-move-line');
this.inPutEle = (<any>$(this.el.nativeElement)).find('.text-area-view').find('input');
if (this.operateState) {
this.operaRefresh = [];
for (let i = 0; i < this.dataSource.length; i++) {
this.operaRefresh.push(false);
}
};
}
//计算没设置固定宽度td的宽度
styInit() {
if ('tableHeight' in this) {
//设置默认高度:
$(this.tableEle).css({ height: this.tableHeight + 'px', overflow: "hidden" });
}
this.setColsTotal = this.colsWidth.reduce((total, next) => {
return total + next;
}, 0);
//默认值minWidth不足以填满table
var val;
if (this.tableWidth > (this.setColsTotal + this.minWidth * (this.theadSource.length - this.colsWidth.length))) {
//平均分配
val = Math.floor((this.tableWidth - this.setColsTotal) / (this.theadSource.length - this.colsWidth.length));
} else {
//统一设置为this.minWidth
val = this.minWidth
}
for (let i = this.colsWidth.length; i < this.theadSource.length; i++) {
this.colsWidth[i] = val;
}
}
//获取宽度,wrap 跟table,如果table大于wrap,需要添加滚动属性给wrap
getElementWidth() {
this.wrapWidth = $(this.wrapEle).width();
this.tableWidth = $(this.tableEle).width() - 17;
this.theadSty = { width: this.wrapWidth + "px" };
}
//设置用户自定义的宽度
setUserSettingWidth() {
//widths不够
if (this.widths.length < this.theadSource.length) {
this.widths.forEach((val, idx) => {
this.colSetVals[idx] = val;
this.colsWidth.push(val);
})
return true
} else {
//widths过多,不需要计算默认值
this.widths.forEach((val, idx) => {
if (idx > this.colsWidth.length) return
val > this.minWidth ? this.colsWidth[idx] = val : this.colsWidth[idx] = this.minWidth;
});
return false
}
}
//resize table
tableResize() {
if (!this.wrapEle) return
this.getElementWidth();
//没设置宽度的td计算
var nosetArr = [];
this.theadSource.forEach((val, idx) => {
if (!this.colSetVals[idx]) {
nosetArr.push(idx)
}
});
let x = Math.floor((this.tableWidth - this.setColsTotal - (this.multipleChoice ? 50 : 0) - (this.operateState ? 200 : 0) - (this.changeState ? 200 : 0)) / nosetArr.length);
x = x > this.minWidth ? x : this.minWidth;
nosetArr.forEach((val) => {
this.colsWidth[val] = x;
});
this.checkScroll();
}
//判断是否需要 横向滚动条 或者纵向滚动条
checkScroll() {
//纵向
var scrollY = 'hidden', scrollX = 'hidden';
if ('tableHeight' in this) {
var h = $(this.contentEle).height();
var contentH = $(this.theadEle).height() + h;
if (contentH > this.tableHeight || h < 10) {
scrollY = 'scroll'
this.theadSty = { width: this.wrapWidth - 17 + "px" }
$(this.contentEle).css('padding-right', 0);
} else {
$(this.contentEle).css('padding-right',0);
this.theadSty = { width: this.wrapWidth + "px" }
}
}
var total = this.colsWidth.reduce((pre, next) => {
return pre + next;
}, ((this.multipleChoice ? 50 : 0) + (this.operateState ? 200 : 0) + (this.changeState ? 200 : 0)));
if (total > this.tableWidth) {
scrollX = 'scroll';
}
$(this.tableEle).css({ overflowX: scrollX, overflowY: scrollY });
this.do();
}
//计算th宽度
getThSty(idx) {
return "colsWidth" in this ? { width: this.colsWidth[idx] + "px" } : '';
}
// 收起表单
close() {
this.closeStatus = !this.closeStatus;
if (this.closeStatus) {
(<any>$(this.wrapEle)).slideUp();
} else {
(<any>$(this.wrapEle)).slideDown();
}
this.do();
}
//关闭表单时候的按钮动画
closeIconSty() {
// return this.closeStatus?{display:'none'}:{display:'block'};
if (this.closeStatus) {
return { transform: "rotate(180deg)" };
} else {
return { transform: "rotate(0)" };
}
}
//获取key值
getKeys(data: any) {
var arr = [];
this.theadSource.forEach((val: any, idx: number)=>{
var tdData: any = {};
if (typeof data[val.name] == 'object'&&data[val.name]!==null) {
data[val.name].rowspan ? tdData.rowspan = data[val.name].rowspan : 1;
data[val.name].slot ? tdData.slot = data[val.name].slot :false;
if('value' in data[val.name]){
tdData.text = data[val.name].value;
}
if('position' in data[val.name]){
tdData.position = data[val.name].position;
}
arr.push(tdData);
} else if (val.name in data) {
tdData.text = data[val.name];
arr.push(tdData);
}else{
if(this.DEGUGGER){
arr.push("");
}
}
});
return arr;
}
//拖动横向滚动条
tableScroll(e: any) {
if (e.target.scrollLeft != -this.thOffsetLeft) {
this.thOffsetLeft = -e.target.scrollLeft;
this.do();
}
}
//th拖动事件
//1.只能在右边拖动
//2.20px是触发的条件
//3.鼠标变形
//4.点击之后,隐藏标签出现,获取offsetX
//5.隐藏标签有mouseon事件,竖条跟着走。
//6.松开鼠标结束
//7.判断能否移动到该位置(过小的问题)
thMoving(e: any, idx) {
if (this.colsWidth[idx] - e.offsetX < 20) {
if($(e.target).css('cursor')!='e-resize'){
$(e.target).css({ cursor: 'e-resize' });
}
} else {
if($(e.target).css('cursor')!='default'){
$(e.target).css({ cursor: 'default' });
}
}
}
//记录下移动的th的下标
tdisClilked(e: any, idx) {
if (this.colsWidth[idx] - e.offsetX < 20) {
this.movedCol = idx;
$(this.moveBlock).css('z-index', 10);
}
}
mySetTimeout = null;
//坐标线位置, 移动中
moveBlockEvent(e: any) {
var css:any = {
transform:'translateX(' + e.offsetX + 'px)'
}
if($(this.lineEle).css('opacity') as any==0){
css.opacity = 1;
this.moveStarX = e.clientX;
}
this.moveCurrX = e.clientX;
$(this.lineEle).css(css);
}
mouseUpSet=null;
//松开鼠标
mouseUp(e) {
if(this.mouseUpSet) clearTimeout(this.mouseUpSet);
this.mouseUpSet = setTimeout(()=>{
if (this.lineEle[0].style.opacity == 1) {
if (this.movedCol == null) return
$(this.lineEle).css('opacity', 0);
$(this.moveBlock).css('z-index', -1);
//计算移动的距离
let moveSize = this.moveCurrX - this.moveStarX;
if (this.colsWidth[this.movedCol] + moveSize < this.minWidth) {
this.colsWidth[this.movedCol] = this.minWidth;
} else {
this.colsWidth[this.movedCol] = this.colsWidth[this.movedCol] + moveSize;
}
this.colSetVals[this.movedCol] = this.colsWidth[this.movedCol];
this.setColsTotal = this.colSetVals.reduce((pre, next) => {
if (next) {
return pre + next;
} else {
return pre;
}
})
this.tableResize();
this.moveCurrX = null;
this.moveStarX = null;
this.movedCol = null;
this.do();
}
},30)
}
//选中一行
onCheckRow(idx: number) {
setTimeout(() => {
var num = 0;
for (var i in this.checkRow) {
if (this.checkRow[i] == false) break;
num++
};
this.emitSelect()
this.selectAll = num == this.dataSource.length;
this.do();
})
}
//全选
onSelectedAll() {
setTimeout(() => {
this.dataSource.forEach((val, idx) => {
this.checkRow[idx] = this.selectAll
})
this.emitSelect();
this.do();
}, 30)
}
//选中删除指定行
delRow(): void {
for (var key in this.checkRow) {
this.dataSource.splice((<any>key), 1)
};
this.checkRow = {};
this.do();
}
//重置选中
initCheckRow() {
var arr = []
for (var i in this.checkRow) {
arr.push(i);
}
arr.forEach((val) => {
delete this.checkRow[val]
})
this.selectAll = false;
this.do();
}
//output 返回选中的数据
emitSelect() {
var arr = [];
for (var i in this.checkRow) {
if (this.checkRow[i]) {
arr.push(this.dataSource[i])
}
}
this.onSelect.emit(arr);
}
//改变每页行数
onPageNumerChanged(e: any) {
this.rowNumber = e.target.value;
if (this.ajaxUrl) {
this.sendAjax(1);
}
this.onChangeRows.emit(e.target.value);
this.do();
}
//翻页
onToPage(page: any) {
if (page == 1) {
if (this.dataInf.page != 1) {
if (this.ajaxUrl) {
this.sendAjax(page);
}
this.onChangePage.emit(page);
}
} else if (page == this.dataInf.totalPage) {
if (this.dataInf.page != this.dataInf.totalPage) {
if (this.ajaxUrl) {
this.sendAjax(page);
}
this.onChangePage.emit(page);
}
} else if (page > 1 && page < this.dataInf.totalPage) {
if (this.ajaxUrl) {
this.sendAjax(page);
}
this.onChangePage.emit(page)
}
this.do();
}
//计算显示的页数
computPagination() {
var paginNum = this.paginNum;
var cPage = this.dataInf.page;
var total = this.dataInf.totalPage;
var result = [];
if (total <= paginNum) {
for (var i = 1; i <= total; i++) {
result.push(i)
}
} else if (cPage <= (paginNum - 1) / 2) {
for (var i = 1; i <= paginNum; i++) {
result.push(i)
};
} else if (cPage + ((paginNum - 1) / 2) >= total) {
for (var i = total; i > total - paginNum; i--) {
result.unshift(i)
}
} else {
for (var i = cPage - (paginNum - 1) / 2; i <= cPage + (paginNum - 1) / 2; i++) {
result.push(i)
}
}
return result;
}
//键盘输入 页数
onInputPageNum() {
this.inputTextSty["z-index"] = -1;
Promise.resolve().then(() => {
this.inPutEle.focus();
})
}
//检查输入的值
onCheckInputValue(e: any) {
if (this.modalState.show) {
e.preventDefault();
return
}
var value = e.target.value;
var pro = new Promise(function (resolve, reject) {
resolve();
});
pro.then(() => {
if (/^[0-9]+$/.test(value) == false) {
throw new Error('输入的值无效')
}
}).then(() => {
if (value >= 1 && value <= this.dataInf.totalPage) {
this.inPutEle.blur();
this.onToPage(value);
this.inputTextSty["z-index"] = 5;
} else {
throw new Error('超出了页数范围')
}
}).catch(err => {
this.modalState.show = true;
this.modalState.text = err;
setTimeout(() => {
this.inputValue = this.dataInf.page;
this.modalState.show = false
}, 1500)
})
}
//输入框失去焦点
onInputBlur() {
this.inputTextSty["z-index"] = 5;
}
//鼠标变形
onCheckChangePageAU(order: string | any) {
//首页
switch (order) {
case "first":
if (this.dataInf.page == 1) {
return { disable: true }
}
break;
case "pre":
if (this.dataInf.page - 1 <= 0) {
return { disable: true }
};
break;
case "last":
if (this.dataInf.page >= this.dataInf.totalPage) {
return { disable: true }
}; break;
case "next": if (this.dataInf.page - 0 + 1 > this.dataInf.totalPage) {
return { disable: true }
}; break;
}
}
//设置刷新动画
getReflreshSty(idx: number): string {
if (!this.operaRefresh) return ""
return this.operaRefresh[idx] ? "fa-spin" : ""
}
//改变刷新动画的状态
onChangeReflreshState(idx: number): void {
this.operaRefresh[idx] = !this.operaRefresh[idx];
this.onReflresh.emit({
state: this.operaRefresh[idx],
data: this.dataSource[idx]
});
this.do();
};
//修改属性
onChangeInfo(idx: number): void {
this.onChangeInfomation.emit(this.dataSource[idx]);
this.do();
};
//删除选中行
onDelInfo(idx: number): void {
this.onDelInfomation.emit(this.dataSource[idx]);
this.do();
};
//展示detail
onShowDetail(e: any, idx: number): void {
if (this.operaShowDetail[idx] && this.operaShowDetail[idx].show) { //删除
$(this.operaShowDetail[idx].el).remove();
this.operaShowDetail[idx].show = false;
} else {
var curTr = $(e.target).closest('tr');
var ele = $(`
<tr>
<td class='ace-tb-detail' colspan="${this.computeNotDataColspan()}">
${(<any>this.dataSource[idx]).detail}
</td>
</tr>
`);
this.operaShowDetail[idx] = {
el: ele[0],
show: true
};
ele.insertAfter(curTr);
}
this.do();
};
// 全新功能
ajaxUrl: string; //请求的地址
setParamsFn; // 设置请求参数的函数
cbParams: CBparams; //设置响应时候的各个字段的名称
//启动第一次请求
firstAjax() {
this.sendAjax(1);
};
sendAjaxPage: number; //请求的page
//发送ajax
sendAjax(page: number) {
if (!this.cbParams) {
throw new Error('ace-table cbParams undefined')
}
this.modalState.show = false;
this.loading = true;
this.sendAjaxPage = page;
this.do();
this.service.toAjax({
url: this.ajaxUrl,
setParams: this.setParamsFn,
cb: this.ajaxCB,
page,
limit: this.rowNumber,
cbParams: this.cbParams
});
}
//请求成功
ajaxCB = ({
code,
items,
page,
total,
msg,
data
}) => {
//根据code判断
setTimeout(() => {
this.checkScroll();
setTimeout(() => {
this.tableResize();
})
this.loading = false;
this.do();
}, 30)
$(this.el.nativeElement).find('.ace-tb-detail').closest('tr').remove();
this.initCheckRow();
if (code == 200) {
this.modalState.show = false;
this.dataSource = items;
this.dataInf.page = page;
this.dataInf.total = total;
this.dataInf.startId = ((page - 1) * this.rowNumber + 1)>0?((page - 1) * this.rowNumber + 1):0;
this.dataInf.endId =( (page-1) * this.rowNumber)+this.dataSource.length;
this.dataInf.totalPage = Math.ceil(total / this.rowNumber);
} else {
this.modalState.show = true;
if (typeof msg == 'string') {
this.modalState.text = msg;
} else {
this.modalState.text = '请求失败 错误码:' + code;
}
}
this.onAjaxOver.emit(data);
}
//无数据时候的展示
computeNotDataColspan() {
var result = this.theadSource.length;
if (this.multipleChoice) result++;
if (this.changeState) result++;
if (this.operateState) result++;
return result;
};
//判断是否展示
computeNotDataRow() {
return this.dataSource.length == 0 && this.modalState.show == false && this.loading == false;
}
computedRowData(item) {
if (typeof item == 'string' && item.indexOf("</") > -1) {
return true
} else {
return false
}
}
}