plus-base-on-baosight
Version:
Expansion based on the Baosight methods.
355 lines (346 loc) • 10.5 kB
text/typescript
import { CSSProperties } from 'vue';
import { MenuItemDef, DefaultMenuItem } from '../types/index';
export * from './GridCustomExportManager';
export type * from './GridCustomExportManager';
/**
* 在AG Grid右下角前方插入文本
* @param erFormHelper
* @param grid id
* @param template 模板:{type|field|formater}的格式。例:{count|MAT_NO}-统计MAT_NO的数量;{sum|SHEET_NUM|2}-统计SHEET_NUM的和并且保留2位小数;{fun|HEAT_TREAT_MODE|T}-自定义方法统计HEAT_TREAT_MODE字段并且传递参数T
* @param opts.fontStyle 显示的字体样式,同CSS
* @param opts.fun 自定义函数,当模板中type=fun时,会调用opts.fun方法;回调参数:字段名,行数据,格式化参数。返回值必须为数字!否则无效
*/
export function setGridStatusBar(
erFormHelper: any,
grid: string,
template: string,
opts?: {
fontStyle?: CSSProperties;
fun?: (field: string, row: { [key: string]: any }, format: string) => number;
}
) {
const bar_class_name = '--lxy-ag-grid-tj';
const api = erFormHelper.getGridApi(grid);
const bar_opts = erFormHelper.getGrid(grid).statusBar.statusPanels as any[];
const panel_name = bar_opts.at(-1).statusPanel;
const bar_instance = erFormHelper.getGridApi(grid)?.getStatusPanel(panel_name) as any;
const bar_el = (bar_instance.$el || bar_instance.eGui) as HTMLElement;
const outer_el = bar_el.parentElement?.parentElement;
const child_el = bar_el.parentElement;
let node = createNode(opts?.fontStyle);
const has = outer_el?.querySelector(`.${bar_class_name}`);
if (!has) {
node.apply();
// filter事件
api?.addEventListener('filterChanged', (e: any) => {
node.updataValue();
});
(window as any)['TJBAR'] = node;
} else {
(window as any)['TJBAR']?.updataValue?.();
}
// 创建Node
function createNode(css?: CSSProperties) {
const div = document.createElement('div');
div.innerText = template;
div.style.marginLeft = 'auto';
div.style.display = 'flex';
div.style.alignItems = 'center';
div.classList.add(bar_class_name);
for (const key in css) {
(div.style as any)[key] = String(css[key as any]);
}
return {
apply() {
this.updataValue();
outer_el?.insertBefore(div, child_el);
},
updataValue() {
div.innerText = updateTemplate(template);
},
remove() {
div.remove();
},
};
}
// 替换模板
interface Rules {
type: 'count' | 'sum' | 'fun';
field: string;
template: string;
rule: string;
format?: string;
value: number;
}
function updateTemplate(template: string) {
const regex = /(?<=\{)[^{}]+(?=\})/g;
const res_match = template.match(regex);
const rules: Rules[] = [];
if (res_match?.length) {
res_match.forEach((str, i) => {
// 去掉全部空格
const str_old = str;
const rule = str.replace(/\s/g, '');
const rule_type = rule.split('|')[0] as any;
const rule_field = rule.split('|')[1];
const rule_float = rule.split('|')[2];
rules.push({
type: rule_type,
field: rule_field,
template: str_old,
rule,
format: rule_float,
value: 0,
});
});
}
api?.forEachNodeAfterFilterAndSort((node_row, i) => {
const data_row = node_row.data.toJSON();
for (let j = 0; j < rules.length; j++) {
const item = rules[j];
if (!Reflect.has(data_row, item.field)) {
break;
}
if (item.type === 'sum') {
item.value += Number(data_row[item.field]);
}
if (item.type === 'count') {
item.value += data_row[item.field]?.toString() ? 1 : 0;
}
if (item.type === 'fun') {
item.value += opts?.fun?.(item.field, data_row, item?.format ?? '') || 0;
}
}
});
rules.forEach((item) => {
const float = Number.parseInt(item.format ?? '0');
let value = item.value.toString();
if (value.includes('.')) {
value = Number(value).toFixed(float);
}
template = template.replace(`{${item.template}}`, value);
});
return template;
}
}
/**
* 导出多个ag grid数据为Excel
* @param erFormHelper
* @param name_file 导出之后的文件名,不包括后缀
* @param opts.grid id
* @param opts.name_sheet sheet名称,默认从Sheet1开始
* @param opts.columns 需要导出的列,默认全部列
* @param opts.formatter 单元格格式化函数,返回值必须为字符串!
*/
export function exportGridByMulSheet(
erFormHelper: any,
name_file: string,
opts: {
grid: string;
name_sheet?: string;
columns?: string[];
formatter?: (params: { value: any; row: { [key: string]: any }; column: string }) => string;
}[]
) {
const data_export = opts.reduce((pre: string[], opt, i) => {
const gridApi = erFormHelper.getGridApi(opt.grid);
const { grid, name_sheet, columns, formatter } = opt;
if (gridApi) {
const _opt: { [key: string]: any } = {};
if (name_sheet) {
_opt['sheetName'] = name_sheet;
} else {
_opt['sheetName'] = `Sheet${i + 1}`;
}
if (columns) {
_opt['columnKeys'] = columns;
}
if (formatter) {
_opt['processCellCallback'] = (params: any) => {
const { value, node, column } = params;
const str = formatter.call(window, {
value,
row: node?.data,
column: column.getColId(),
});
return str;
};
}
const temp = gridApi.getSheetDataForExcel({
..._opt,
});
if (temp) {
pre.push(temp);
} else {
throw `[${grid} sheet data] is undefined.`;
}
} else {
throw `[${grid}] is undefined.`;
}
return pre;
}, []);
const api = erFormHelper.getGridApi(opts[0].grid);
api?.exportMultipleSheetsAsExcel({
data: data_export,
fileName: `${name_file}.xlsx`,
});
}
/**
* 获取grid配置的颜色
* @param erFormHelper
* @param grid id
*/
export function getGridColorConfig(erFormHelper: any, grid: string) {
const res: { color: string; desc: string; field: string; mark: string; rule: string; target: string; _data: any[] }[] = [];
const gridStyles = (erFormHelper.ConfigInfo.TSI00GRIDSTYLE.data as any[]).filter((item) => item.FUNCTION_ID === grid);
gridStyles.map((row) => {
const color = (row.FILL_COLOR as string).trim();
const desc = (row.REMARK as string).trim();
const field = (row.COL_NAME as string).trim();
const mark = (row.CONST_PARA as string).trim();
const rule = (row.REGULAR_EXPRESS as string).trim();
const target = (row.FUNCTION_ID as string).trim();
if (desc && !field.startsWith('_')) {
res.push({ desc, color, field, mark, rule, target, _data: row });
}
});
return res;
}
/**
* 设置grid内容右键菜单,详情可查看官网:https://www.ag-grid.com/react-data-grid/context-menu/#built-in-menu-items
* @param erFormHelper
* @param grid id
*/
export function setGridContentMenu(erFormHelper: any, grid: any, menus: (e: any) => (MenuItemDef | DefaultMenuItem)[]) {
let api = erFormHelper.getGridApi(grid);
api?.setGetContextMenuItems((params: any) => {
return menus.call(window, params);
});
}
/**
* 滚动grid到指定index行
* @param erFormHelper
* @param grid id
* @param targetValue 目标对象,建议尽量为数据中的唯一值字段
* @param opts.keepLine 保留行数,默认为5行
* @param opts.reMerge 是否重新给grid设置数据
* @returns
*/
export function scrollGridToData(erFormHelper: any, grid: any, targetValue: { [key: string]: any }, opts?: { keepLine?: number; reMerge?: boolean }) {
const keepLine = opts?.keepLine ?? 5;
const reMerge = opts?.reMerge ?? true;
let gridData = erFormHelper.getGridRows(grid, 'all', true);
let findIndex = gridData.findIndex((row: { [key: string]: any }, i: number) =>
Object.keys(targetValue).every((key) => row[key] === targetValue[key])
);
if (findIndex <= -1) return;
if (findIndex - keepLine > 0) {
findIndex -= keepLine;
}
const api = erFormHelper.getGridApi(grid);
if (reMerge) {
erFormHelper.mergeDataToGrid(gridData, grid);
}
api?.ensureIndexVisible(findIndex, 'top');
setTimeout(() => {
erFormHelper.setGridIndicator(grid, { [Object.keys(targetValue)[0]]: Object.values(targetValue)[0] });
}, 100);
}
/**
* 滚动指定grid指定px
* @param erFormHelper
* @param grid id
* @param px 滚动的像素
*/
export function scrollGridByPx(erFormHelper: any, grid: string, px: number) {
const api = erFormHelper.getGridApi(grid);
(api as any).gridBodyCtrl.scrollVertically(px);
}
/**
* AG Grid 筛选管理
* @constructor erFormHelper
* @constructor grid id
*/
export class AgGirdFilterManger {
private erFormHelper: any;
private recordOn = false;
private model_old = {};
private api: any = null;
constructor(erFormHelper: any, grid_id: string) {
this.erFormHelper = erFormHelper;
this.api = this.erFormHelper.getGridApi(grid_id);
if (!this.api) {
throw new Error(`[${grid_id} is not found]`);
}
// 添加 filterChanged 事件
this.api.addEventListener('filterChanged', () => {
if (this.recordOn) {
this.model_old = this.api!.getFilterModel();
}
});
}
// 记录 用于需要保留当前筛选设置的情况
record = {
on: () => {
this.recordOn = true;
},
off: (clearAll = false) => {
this.recordOn = false;
clearAll && (this.model_old = {});
},
set: () => {
this.api?.setFilterModel(this.model_old);
},
};
/**
* 设置列筛选
* @param filterOpts 对象格式:{列1英文名:筛选值1,列2英文名:筛选值2,列2英文名:筛选值2,...}
*/
filter(filterOpts: { [col_name: string]: string }) {
Object.entries(filterOpts).forEach(([col_name, col_filter_value]) => {
const col = this.api?.getColumnDef(col_name);
if (col_name === col?.field) {
this.api?.setFilterModel({
[col_name]: {
// 低代码列好像都用的 multi
filterType: 'multi',
filterModels: [
{
// 筛选类型
filterType: 'text',
// type: 筛选方式
type: 'startWidths',
// 筛选的值
filter: col_filter_value,
},
],
},
});
}
});
}
/**
* 清除当前筛选设置
*/
clear() {
this.api?.setFilterModel(null);
}
}
/**
* 获取Grid的Nodes数据
* @param erFormHelper
* @param grid id
* @param toJson 是否转化为json数据
*/
export function getGridDataByNodes(erFormHelper: any, grid: string, toJson?: boolean) {
const back: { [key: string]: any }[] = [];
const api = erFormHelper.getGridApi(grid) as any;
api.forEachNode((node: any, i: number) => {
if (toJson) {
back.push(node.data.toJSON());
} else {
back.push(node.data);
}
});
return back;
}