Files
Situation-Awareness-Platfor…/src/utils/index.ts

463 lines
13 KiB
TypeScript
Raw Normal View History

2025-03-12 18:41:20 +08:00
/* 工具函数 */
import router from '@/router';
import * as CryptoJS from 'crypto-js';
import pick from 'lodash/pick';
import pickBy from 'lodash/pickBy';
import type { createIssueReqType } from '@/api/issue/types';
import type { RepoItemResData } from '@/utils/types';
import DOMPurify from 'dompurify';
import { Message } from 'vue-devui/message';
import qs from 'qs';
/**
* axios data, obj data
*/
export const escapeResData = (obj: object) => {
if (!obj) return obj;
if (!Object.prototype.hasOwnProperty.call(obj, 'data')) return obj;
if (obj?.headers?.constructor?.name === 'AxiosHeaders') { return obj?.data; };
return escapeResData(obj?.data);
};
export function getRepoName(): string {
//
return router.currentRoute.value.params.repoName;
};
/**
* Parse the time to string
* @param {(Object|string|number)} time
* @param {string} cFormat
* @returns {string | null}
*/
function parseTime(time: string | number | Date, cFormat?: string) {
if (!time) {
return null;
}
const format = cFormat || '{y}-{m}-{d} {h}:{i}:{s}';
let date;
if (typeof time === 'object') {
date = time;
} else {
if ((typeof time === 'string')) {
if ((/^[0-9]+$/.test(time))) {
time = parseInt(time);
} else {
// support safari
time = time.replace(new RegExp(/-/gm), '/');
}
}
if ((typeof time === 'number') && (time.toString().length === 10)) {
time = time * 1000;
}
date = new Date(time);
}
const formatObj = {
y: date.getFullYear(),
m: date.getMonth() + 1,
d: date.getDate(),
h: date.getHours(),
i: date.getMinutes(),
s: date.getSeconds(),
a: date.getDay()
};
const time_str = format.replace(/{([ymdhisa])+}/g, (result, key) => {
const value = formatObj[key];
// Note: getDay() returns 0 on Sunday
if (key === 'a') { return ['日', '一', '二', '三', '四', '五', '六'][value]; }
return value.toString().padStart(2, '0');
});
return time_str;
}
export function fileToBlob(file: any) {
// 创建 FileReader 对象
const reader = new FileReader();
return new Promise(resolve => {
// FileReader 添加 load 事件
reader.addEventListener('load', (e) => {
let blob;
if (typeof e.target.result === 'object') {
blob = new Blob([e.target.result]);
} else {
blob = e.target.result;
}
resolve(blob);
});
// FileReader 以 ArrayBuffer 格式 读取 File 对象中数据
reader.readAsArrayBuffer(file);
});
}
// 图片转 base64
export function imageToBase64(file: File) {
return new Promise((resolve, reject) => {
const reader = new FileReader();
reader.readAsDataURL(file);
reader.onload = () => resolve(reader.result);
reader.onerror = error => reject(error);
});
}
export function generateHash(userName: string, salt: string): string {
const hashBytes = CryptoJS.SHA256(userName + salt);
return hashBytes.toString(CryptoJS.enc.Hex);
}
export function getFilePath(hash: string, filetype: string): string {
const chars: string[] = hash.split('');
const sb: string[] = [];
for (const c of chars) {
if (isNaN(Number(c))) {
sb.push(c);
}
}
return `${sb.slice(0, 2).join('')}/${sb.slice(2, 4).join('')}/${hash}.${filetype}`;
}
export function getImageUrl(iam_id?: string, fileType: string = 'png', isAvatar: boolean = true) {
if (!iam_id) {
const accountInfo = JSON.parse(localStorage.getItem('opUserInfo') || '{}');
2025-03-12 18:41:20 +08:00
iam_id = accountInfo.iam_id;
}
if (isAvatar) {
const host = 'https://gitcode-img.obs.cn-south-1.myhuaweicloud.com:443/';
const salt = 'avatar';
const hash = generateHash(iam_id || '', salt);
const path = getFilePath(hash, fileType || 'png');
return host + path + '?time=' + new Date().getTime();
}
}
/**
* issue put
*/
export function formatIssuePutData(data: createIssueReqType) {
const params = pick(data, ['title', 'description', 'confidential', 'discussions', 'assignee', 'assignee_id', 'assignee_ids', 'project_id', 'issue_iid', 'labels', 'milestone_id', 'discussion_locked', 'state_event']);
let { labels } = params;
if (typeof labels === 'object') {
labels = labels.map(item => {
if (typeof item === 'string') {
return item;
} else if (typeof item.name === 'string') {
return item.name;
} else {
return null;
}
});
}
return ({
...params,
labels,
issue_category: '-',
issue_stage: '-',
issue_severity: '-'
});
}
/**
*
*/
export const pickNickName = (author?: any): string => {
return author?.nick_name || author?.nickname || author?.name_cn || author?.name || author?.username || '';
};
/**
*
*/
export function removeEmptyValue(params: object): object {
return pickBy(params, (e) => (e !== undefined && e !== '' && e !== null));
}
/**
* null为 undefined
*/
export function replaceNull(obj: {[name:string]: any}): any {
for (const k in obj) {
if (obj[k] === null) {
obj[k] = undefined;
}
}
return obj;
}
/**
* 1. select 2. 3.
*/
export function formatSelectedData(current: string | object | undefined | null, selectedList: any[], judge: (a: { [name: string]: unknown }, b: { [name: string]: unknown } | unknown) => boolean): object[] {
if (!current) return [];
const index = selectedList.findIndex((item) => {
if (typeof item === 'string') {
return item === current;
} else {
return judge && judge(item, current);
}
});
if (index > -1) {
selectedList.splice(index, 1);
} else {
selectedList.push(current);
}
return selectedList;
}
/**
*
*/
export const formatQuoteReply = (str: string) => {
str = str.trim();
if (!str) return '';
str = str.split('\n').map(e => '>' + e).join('\n') + '\n\n';
return str;
};
/**
*
*/
export function hasClassInParent(target: Element, classNameList: string[]): boolean {
if (target?.parentElement) {
if (classNameList.every(name => target?.classList?.contains(name))) {
return true;
} else {
return hasClassInParent(target?.parentElement, classNameList);
}
} else {
return target ? classNameList.every(name => target?.classList?.contains(name)) : false;
}
}
/**
*
*/
export const sortList = (list: Object[] = [], select: Object[] = []):Object[] => {
list = list.slice(0);
select = select.slice(0);
if (select[0]) {
const sList:any[] = [];
for (let i = 0; i < select.length; i++) {
const index = list.findIndex(e => e.value === select[i]?.value);
if (index > -1) {
const one = list.splice(index, 1)[0];
sList.push(one);
}
}
return sList.concat(list);
} else {
return list;
}
};
/**
* repo数据便于使用repoItem组件
*/
export const repoDataHandler = (data: RepoItemResData[]) => {
return data.filter((item) => {
return !!item && (item.id || item.resource_id);
}).map((item) => {
const langs = (item.main_repository_language || []).filter((lang) => {
return !!lang;
});
return {
id: item.id || item.resource_id || '',
imgSrc: '',
title: item.name || '-',
desc: item.description || '-',
isStar: item.starred || false,
tag: item.visibility || '',
to: `/${item.namespace}`,
web_url: item.web_url,
iconHandleList: [
{ icon: 'icon-dot-status', value: langs.join(',') || '-', type: 'language', iconColor: 'red', label: '', to: '' },
{ icon: 'gt-star', value: item.star_count, label: '', to: '' },
{ icon: 'gt-fork', value: item.forks_count, label: '', to: '' },
{ icon: 'gt-date', value: item.last_activity_at, label: '', to: '' }
]
};
});
};
/**
*
*/
export const highlightWords = (Word: string, title?: string) => {
if (!Word) return xssPurify(title || '');
title = title ? xssPurify(title) : '';
const regexPattern = new RegExp(`(${Word})`, 'gi');
const str = title?.replace(regexPattern, (_, match) => `<span style="color:red">${match}</span>`);
return str;
};
/*
* @param obj
* @returns
*/
export function filterEmptyObj(obj: object) {
const newObj = obj;
for (const key in newObj) { // 删除空属性值
if (Object.prototype.hasOwnProperty.call(newObj, key)) {
if (!newObj[key]) {
delete newObj[key];
}
}
}
return newObj;
}
export const fullscreen = (id: string): void => {
if (document.fullscreenElement || document.webkitCurrentFullScreenElement) {
if (document.exitFullscreen) {
document.exitFullscreen();
} else if (document.mozCancelFullScreen) {
// 兼容Firefox
document.mozCancelFullScreen();
} else if (document.webkitExitFullscreen) {
// 兼容Chrome, Safari and Opera等
document.webkitExitFullscreen();
} else if (document.msExitFullscreen) {
// 兼容IE/Edge
document.msExitFullscreen();
}
} else {
const dom = document.getElementById(id);
if (dom?.requestFullscreen) {
dom.requestFullscreen();
} else if (dom?.mozRequestFullScreen) {
// 兼容Firefox
dom.mozRequestFullScreen();
} else if (dom?.webkitRequestFullScreen) {
// 兼容Chrome, Safari and Opera等
dom.webkitRequestFullScreen();
} else if (dom?.msRequestFullscreen) {
// 兼容IE/Edge
dom.msRequestFullscreen();
}
}
};
// 对象深层递归合并
export const deepMerge = function(target: object, source: object) {
for (const key in source) {
if (Object.prototype.hasOwnProperty.call(source, key)) {
if (source[key] instanceof Object && key in target && target[key] instanceof Object) {
deepMerge(target[key], source[key]);
} else {
target[key] = source[key];
}
}
}
return target;
};
// 最长公共子序列(模糊匹配)
export const longestCommonSubsequence = function(str1: string, str2: string) {
const m = str1.length;
const n = str2.length;
const dp = new Array(m + 1);
for (let i = 0; i <= m; i++) {
dp[i] = new Array(n + 1).fill(0);
}
for (let i = 1; i <= m; i++) {
for (let j = 1; j <= n; j++) {
if (str1[i - 1] === str2[j - 1]) {
dp[i][j] = dp[i - 1][j - 1] + 1;
} else {
dp[i][j] = Math.max(dp[i - 1][j], dp[i][j - 1]);
}
}
}
let lcs = '';
let i = m; let j = n;
while (i > 0 && j > 0) {
if (str1[i - 1] === str2[j - 1]) {
lcs = str1[i - 1] + lcs;
i--;
j--;
} else if (dp[i - 1][j] > dp[i][j - 1]) {
i--;
} else {
j--;
}
}
return lcs;
};
export const blurMatch = function(target: string, keywords: string) {
const m = target.length;
const n = keywords.length;
const dp = new Array(m + 1);
for (let i = 0; i <= m; i++) {
dp[i] = new Array(n + 1).fill('');
}
const match = [];
for (let i = 1; i <= m; i++) {
for (let j = 1; j <= n; j++) {
if (target[i - 1] === keywords[j - 1]) {
dp[i][j] = dp[i - 1][j - 1] + keywords[j - 1];
if (typeof match[j - 1] === 'undefined') match[j - 1] = i - 1;
} else {
dp[i][j] = dp[i - 1][j].length > dp[i][j - 1].length ? dp[i - 1][j] : dp[i][j - 1];
}
}
}
return match;
};
/**
* xss
* purify https://github.com/cure53/DOMPurify#control-our-allow-lists-and-block-lists
*/
const purifyConfig = { FORBID_TAGS: ['img'] };
export const xssPurify = (str: string) => DOMPurify.sanitize(str, purifyConfig);
export const messageError = ({ error_message, message }) => Message.error(error_message || message);
export const savePageRef = (fullPath:string) => {
const BASE_URL = (import.meta as any).env.VITE_HOST;
const beforeRef = sessionStorage.getItem('ref');
const ref = beforeRef || document.referrer || '';
window.page_ref = ref;
sessionStorage.setItem('ref', BASE_URL + fullPath);
};
/**
* header中的地址 header size 431
* @param href string访问地址
* @returns {string} 访
*/
export const cutParamsInUrl = (href: string) => {
if (!href) return '';
try {
const location = new URL(href);
const query = qs.parse(location.search, { ignoreQueryPrefix: true });
for (const k in query) {
if (typeof query[k] === 'string') {
query[k] = query[k]?.substring(0, 100);
}
}
location.search = qs.stringify(query);
return location.href;
} catch (error) {
console.log(error);
return href;
};
};
/**
* utm_source()
* @returns {string} utm_source
*/
export const getSignUtmSource = () => {
const utm_source_sign = localStorage.getItem('utm_source_sign');
if (utm_source_sign) {
const intervalTime = 1000 * 60 * 60;
const currentTime = Date.now();
const utm_source_sign_time = Number(localStorage.getItem('utm_source_sign_time'));
if (utm_source_sign_time + intervalTime < currentTime) {
// 超过一小时清除utm_source
localStorage.removeItem('utm_source_sign');
localStorage.removeItem('utm_source_sign_time');
return '';
} else {
return JSON.parse(utm_source_sign);
}
}
return '';
};