plus-base-on-baosight
Version:
Expansion based on the Baosight methods.
371 lines (357 loc) • 11.2 kB
text/typescript
const os = require('os');
export * from '../ag-grid/index.ts';
/**
* 根据Object生成sql
* @param data Object类型数据
* @param opts.type sql类型:新增(add) 删除(del) 修改(modify)
* @param opts.table sql表名
* @param opts.key sql中的判断主键字段名:... WHERE key=value
* @param opts.exclude 需要从data中排除的字段
* @param opts.fun 回调函数
* @returns 生成的sql字符串
*/
export function createSqlByObject(
data: { [key: string]: any }[],
opts: {
type: 'add' | 'del' | 'modify';
table: string;
key?: string;
exclude?: string[];
fun?: (
row: { [key: string]: any },
index: number,
opts_: {
type: 'add' | 'del' | 'modify';
p1: string[];
p2: any[];
}
) => void | string;
}
) {
return data.reduce((pre: string, row: { [key: string]: any }, rowIndex) => {
const part1: any[] = []; // field 数组
const part2: any[] = []; // value 数组
// 处理单行数据
if (opts.type !== 'del') {
Object.entries(row).map(([field, value]) => {
value = value.toString().trim();
if (!value) return;
if (opts?.exclude?.includes(field)) {
// 除特殊字符外 直接跳过
} else {
// 新增 or 自定义
if (opts.type === 'add') {
part1.push(field);
part2.push(`'${value}'`);
}
// 修改
if (opts.type === 'modify') {
part1.push(`${field} = ${value}`);
}
}
});
}
// 回调
opts.fun?.apply(window, [row, rowIndex, { type: opts.type, p1: part1, p2: part2 }]);
// 新增
if (opts.type === 'add') {
pre += `INSERT INTO ${opts.table} (${part1.join(',')}) values (${part2.join(',')});`;
}
// 修改
if (opts.type === 'modify') {
if (opts.key) {
pre += `UPDATA ${opts.table} SET ${part1.join(',')} WHEREW ${opts.key} = '${row[opts.key]};'`;
} else {
throw Error('[modify]时,[opts.key]不能为空');
}
}
// 删除
if (opts.type === 'del') {
if (opts.key) {
pre += `DELETE FROM ${opts.table} WHEREW ${opts.key} = '${row[opts.key]}';`;
} else {
throw Error('[del]时,[opts.key]不能为空');
}
}
return pre;
}, '');
}
/**
* 指定数组中某段范围的数据移动到指定位置之后
* @param arr 需要处理的数组
* @param index_from 指定范围开始位置
* @param index_to 指定范围结束位置
* @param index_end 指定移动到的目标位置
* @returns 返回重排序后的结果数组
*/
export function arrayMoveRangeToEnd(arr: { [key: string]: any }[], index_from: number, index_to: number, index_end: number) {
// 判断是往前插入 还是 往后插入
let res: any[] = [];
if (index_end < index_from) {
// 往前插入 需从尾部删除目标区域数据个数
// 拆分为5个部分
const top = arr.slice(0, index_end);
const target = arr.slice(index_end, index_end + 1);
const mid = arr.slice(index_end + 1, index_from);
const range_data = arr.slice(index_from, index_to + 1);
const btm = arr.slice(index_to + 1);
// 重新组合5部分
res = top.concat(target).concat(range_data).concat(mid).concat(btm);
} else {
// 往后插入
// 拆分为5个部分
const top = arr.slice(0, index_from);
const range_data = arr.slice(index_from, index_to + 1);
const mid = arr.slice(index_to + 1, index_end);
const target = arr.slice(index_end, index_end + 1);
const btm = arr.slice(index_end + 1);
// 重新组合5部分
res = top.concat(mid).concat(target).concat(range_data).concat(btm);
}
return res;
}
/**
* 指定对象数组中某个成员对象的key-value,将对应成员移动到另一个成员value值的前面
* @param arr 需要处理的数组
* @param key 指定对象key
* @param val_from 移动的key对应的value
* @param val_to 移动的key对应的value
* @returns 返回重排序后的结果数组
*/
export function arrayObjMoveToForward(arr: { [key: string]: any }[], key: string, val_from: string, val_to: string) {
const i = arr.reduce(
(pre: { index_from: number; index_to: number }, row, i) => {
if (row[key] === val_from) {
pre.index_from = i;
}
if (row[key] === val_to) {
pre.index_to = i;
}
return pre;
},
{
index_from: -1,
index_to: -1,
}
);
// plan_no_from plan_no_to 将数据分为3段
let part1: any[] = [];
let part2: any[] = [];
let part3: any[] = [];
let resGridData: { [key: string]: any }[] = [];
if (i.index_from < i.index_to) {
// 从上往下移
part1 = arr.slice(0, i.index_from);
part2 = arr.slice(i.index_from, i.index_to);
part3 = arr.slice(i.index_to);
part3.unshift(part2[0]);
part2.splice(0, 1);
resGridData = part1.concat(part2).concat(part3);
}
if (i.index_from > i.index_to) {
// 从下往上移
part1 = arr.slice(0, i.index_to);
part2 = arr.slice(i.index_to, i.index_from);
part3 = arr.slice(i.index_from);
part1.push(part3[0]);
part3.splice(0, 1);
resGridData = part1.concat(part2).concat(part3);
}
return resGridData;
}
/**
* 防抖函数
* @param func 需要防抖的函数
* @param wait 延迟时间
* @param immediate 是否立即执行一次
*/
export function debounce(func: Function, wait = 0, immediate: boolean = false) {
let timeout: NodeJS.Timeout | null;
return function executedFunction(...args: any[]) {
const later = function () {
timeout = null;
if (!immediate) func.apply(window, args);
};
const callNow = immediate && !timeout;
timeout && clearTimeout(timeout);
timeout = setTimeout(later, wait);
if (callNow) func.apply(window, args);
};
}
/**
* 获取当前网络IP和MAC,vue中需挂载在vite.config.ts中运行,可通过全局变量/消息通信发送到页面
*/
export function getNetworkMacAndIp() {
let IP = '127.0.0.1';
let MAC = '';
const networkInterfaces = os.networkInterfaces();
for (const iface of Object.values(networkInterfaces)) {
for (const details of iface as any) {
if (details.family === 'IPv4' && details.mac !== '00:00:00:00:00:00' && details.address !== '127.0.0.1') {
MAC = details.mac;
IP = details.address;
return { MAC, IP };
}
}
}
return { MAC, IP };
}
/**
* 复制文本到剪切板,已过滤了兼容性
* @param 需要复制的文本
*/
export function copyTextToClipboard(str: string) {
if (navigator.clipboard) {
// 框架对非安全模式浏览器做了限制
navigator.clipboard.writeText(str);
} else {
// 这里做兼容性处理
const dom = document.createElement('input');
dom.value = str;
document.body.appendChild(dom);
dom.select();
document.execCommand('copy');
document.body.removeChild(dom);
dom.remove();
}
}
/**
* 锚点缩放
* @param topDomClassName 顶部锚点元素className
* @param bottomDomClassName 底部锚点元素className
* @param aim_rate 正确的锚点缩放比例
* @param move_val 偏移值
* @returns 相对于aim_rate的缩放比例
*/
export function getZoomByDoms(topDomClassName: string, bottomDomClassName: string, aim_rate: number, move_val: number = 0) {
// 获取锚点的最顶部元素(锚点顶部)
const mid_top_el = document.getElementsByClassName(topDomClassName)[0];
// 获取锚点的最底部元素(锚点底部)
const mid_bottom_el = document.getElementsByClassName(bottomDomClassName)[0];
// 都获取到了
if (mid_top_el && mid_bottom_el) {
// 取锚点元素的高(锚点高度)
const mid_height = getElClientRects(mid_bottom_el)?.leftTopPoint[1]! - getElClientRects(mid_top_el)?.leftTopPoint[1]! + move_val;
// 当前计算出的相对于锚点-整个屏幕高度的比例
const now_rate = mid_height / document.documentElement.clientHeight;
// console.log('理论比:', aim_rate, '当前比:', now_rate);
// console.log('相差缩放比:', aim_rate / now_rate, '约算结果:', Number((aim_rate / now_rate).toFixed(3)));
// 计算出实际比与理论比的相对比 即最终结果
return Number((aim_rate / now_rate).toFixed(3));
}
// 默认不缩放 即 1
return 1;
}
/**
* 获取元素尺寸信息
* @param el 需要获取尺寸信息的元素
*/
export function getElClientRects(el: Element | HTMLElement) {
if (el) {
const el1_client_rects = el.getClientRects()[0];
return {
// 储存原始数据
_client_rects: el1_client_rects,
// 计算数据
leftTopPoint: [el1_client_rects.x, el1_client_rects.y],
leftBottomPoint: [el1_client_rects.x, el1_client_rects.y - el1_client_rects.height],
rightTopPoint: [el1_client_rects.x + el1_client_rects.width, el1_client_rects.y],
rightBottomPoint: [el1_client_rects.x + el1_client_rects.width, el1_client_rects.y - el1_client_rects.height],
};
}
return null;
}
/**
* 获取系统缩放比例
*/
export function reSetSysZoom() {
let ratio = 0;
let screen = window.screen as any;
let ua = navigator.userAgent.toLowerCase();
if (window.devicePixelRatio !== undefined) {
ratio = window.devicePixelRatio;
} else if (~ua.indexOf('msie')) {
if (screen.deviceXDPI && screen.logicalXDPI) {
ratio = screen.deviceXDPI / screen.logicalXDPI;
}
} else if (window.outerWidth !== undefined && window.innerWidth !== undefined) {
ratio = window.outerWidth / window.innerWidth;
}
if (ratio) {
ratio = Math.round(ratio * 100);
}
return 100 / Number(ratio);
}
/**
* 下载文件
* @param url 需要下载的文件url
* @param success 下载成功后的回调函数
*/
export function downByUrl(url: string, success?: () => void) {
const a = document.createElement('a');
a.href = url;
a.click();
a.remove();
success && success();
}
/**
* Object深度合并
* @param obj1 对象1
* @param obj2 对象2,可选;为空时,程序等同于深拷贝
* @returns 合并后的对象
*/
export function deepMerge(obj1: { [key: string]: any }, obj2?: { [key: string]: any }) {
if (obj2) {
const result = deepClone(obj1);
for (const key in obj2) {
const value = obj2[key];
const isNorObj = typeof obj2[key] === 'object' && obj2[key] !== null;
const isArr = Array.isArray(value);
const isData = value instanceof Date;
if (value && isNorObj && !isArr && !isData) {
result[key] = deepMerge(result[key] || {}, obj2[key]);
} else {
result[key] = value;
}
}
return result;
} else {
return deepClone(obj1);
}
}
/**
* 深拷贝
* @param obj 对象
* @param hash 通常无需传值
* @returns 深拷贝后的对象
*/
export function deepClone(obj: { [key: string]: any }, hash = new WeakMap()) {
if (obj === null) return null;
if (obj instanceof Date) return new Date(obj);
if (obj instanceof RegExp) return new RegExp(obj);
if (typeof obj !== 'object') return obj;
if (hash.has(obj)) return hash.get(obj);
const cloneObj: { [key: string]: any } = Array.isArray(obj) ? [] : {};
hash.set(obj, cloneObj);
for (const key in obj) {
if (obj.hasOwnProperty(key)) {
cloneObj[key] = deepClone(obj[key], hash);
}
}
return cloneObj;
}
/**
* 将Map类型转换为eBFR字符串参数
* @param map
* @param addTimeStampOnEnd
* @returns
*/
export function mapToeBFRParams(map: Map<string, string>, addTimeStampOnEnd = true) {
const res = Array.from(map).map(([field, value]) => {
return `@${field}@$$${value};;`;
});
if (addTimeStampOnEnd) {
return res.join('') + new Date().getTime();
}
return res.join('');
}