Merge branch 'client_sync'
# Conflicts: # web/.env # web/.env.development # web/.env.production # web/.eslintrc.js # web/README.md # web/index.html # web/package.json # web/public/favicon.ico # web/src/App.vue # web/src/api/login/index.ts # web/src/api/menu/index.ts # web/src/assets/logo-mini.svg # web/src/components/auth/auth.vue # web/src/components/auth/authAll.vue # web/src/components/auth/auths.vue # web/src/components/cropper/index.vue # web/src/components/editor/index.vue # web/src/components/iconSelector/index.vue # web/src/components/noticeBar/index.vue # web/src/components/svgIcon/index.vue # web/src/i18n/index.ts # web/src/i18n/lang/en.ts # web/src/i18n/lang/zh-cn.ts # web/src/i18n/lang/zh-tw.ts # web/src/layout/component/aside.vue # web/src/layout/component/columnsAside.vue # web/src/layout/component/header.vue # web/src/layout/component/main.vue # web/src/layout/footer/index.vue # web/src/layout/index.vue # web/src/layout/lockScreen/index.vue # web/src/layout/logo/index.vue # web/src/layout/main/classic.vue # web/src/layout/main/columns.vue # web/src/layout/main/defaults.vue # web/src/layout/main/transverse.vue # web/src/layout/navBars/breadcrumb/breadcrumb.vue # web/src/layout/navBars/breadcrumb/closeFull.vue # web/src/layout/navBars/breadcrumb/index.vue # web/src/layout/navBars/breadcrumb/search.vue # web/src/layout/navBars/breadcrumb/setings.vue # web/src/layout/navBars/breadcrumb/user.vue # web/src/layout/navBars/breadcrumb/userNews.vue # web/src/layout/navBars/index.vue # web/src/layout/navBars/tagsView/contextmenu.vue # web/src/layout/navBars/tagsView/tagsView.vue # web/src/layout/navMenu/horizontal.vue # web/src/layout/navMenu/subItem.vue # web/src/layout/navMenu/vertical.vue # web/src/layout/routerView/iframes.vue # web/src/layout/routerView/link.vue # web/src/layout/routerView/parent.vue # web/src/main.ts # web/src/router/backEnd.ts # web/src/router/frontEnd.ts # web/src/router/index.ts # web/src/router/route.ts # web/src/stores/keepAliveNames.ts # web/src/stores/requestOldRoutes.ts # web/src/stores/routesList.ts # web/src/stores/tagsViewRoutes.ts # web/src/stores/themeConfig.ts # web/src/stores/userInfo.ts # web/src/theme/app.scss # web/src/theme/common/transition.scss # web/src/theme/dark.scss # web/src/theme/element.scss # web/src/theme/iconSelector.scss # web/src/theme/index.scss # web/src/theme/media/form.scss # web/src/theme/media/layout.scss # web/src/theme/media/login.scss # web/src/theme/media/pagination.scss # web/src/theme/other.scss # web/src/utils/arrayOperation.ts # web/src/utils/commonFunction.ts # web/src/utils/loading.ts # web/src/utils/other.ts # web/src/utils/request.ts # web/src/utils/setIconfont.ts # web/src/utils/storage.ts # web/src/utils/theme.ts # web/src/utils/wartermark.ts # web/src/views/system/dept/index.vue # web/src/views/system/dic/index.vue # web/src/views/system/menu/index.vue # web/src/views/system/role/index.vue # web/src/views/system/user/index.vue # web/tsconfig.json # web/vite.config.ts
This commit is contained in:
@@ -23,7 +23,7 @@ export function judementSameArr(newArr: unknown[] | string[], oldArr: string[]):
|
||||
* @param b 要比较的对象二
|
||||
* @returns 相同返回 true,反之则反
|
||||
*/
|
||||
export function isObjectValueEqual(a: { [key: string]: any }, b: { [key: string]: any }) {
|
||||
export function isObjectValueEqual<T>(a: T, b: T): boolean {
|
||||
if (!a || !b) return false;
|
||||
let aProps = Object.getOwnPropertyNames(a);
|
||||
let bProps = Object.getOwnPropertyNames(b);
|
||||
@@ -48,19 +48,18 @@ export function isObjectValueEqual(a: { [key: string]: any }, b: { [key: string]
|
||||
* @param attr 需要去重的键值(数组对象)
|
||||
* @returns
|
||||
*/
|
||||
export function removeDuplicate(arr: any, attr?: string) {
|
||||
if (!arr && !arr.length) {
|
||||
export function removeDuplicate(arr: EmptyArrayType, attr?: string) {
|
||||
if (!Object.keys(arr).length) {
|
||||
return arr;
|
||||
} else {
|
||||
if (attr) {
|
||||
const obj: any = {};
|
||||
const newArr = arr.reduce((cur: any, item: any) => {
|
||||
const obj: EmptyObjectType = {};
|
||||
return arr.reduce((cur: EmptyArrayType[], item: EmptyArrayType) => {
|
||||
obj[item[attr]] ? '' : (obj[item[attr]] = true && item[attr] && cur.push(item));
|
||||
return cur;
|
||||
}, []);
|
||||
return newArr;
|
||||
} else {
|
||||
return Array.from(new Set([...arr]));
|
||||
return [...new Set(arr)];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,22 +7,23 @@ import { useI18n } from 'vue-i18n';
|
||||
export default function () {
|
||||
const { t } = useI18n();
|
||||
const { toClipboard } = useClipboard();
|
||||
//百分比格式化
|
||||
const percentFormat = (row: any, column: number, cellValue: any) => {
|
||||
|
||||
// 百分比格式化
|
||||
const percentFormat = (row: EmptyArrayType, column: number, cellValue: string) => {
|
||||
return cellValue ? `${cellValue}%` : '-';
|
||||
};
|
||||
//列表日期时间格式化
|
||||
const dateFormatYMD = (row: any, column: number, cellValue: any) => {
|
||||
// 列表日期时间格式化
|
||||
const dateFormatYMD = (row: EmptyArrayType, column: number, cellValue: string) => {
|
||||
if (!cellValue) return '-';
|
||||
return formatDate(new Date(cellValue), 'YYYY-mm-dd');
|
||||
};
|
||||
//列表日期时间格式化
|
||||
const dateFormatYMDHMS = (row: any, column: number, cellValue: any) => {
|
||||
// 列表日期时间格式化
|
||||
const dateFormatYMDHMS = (row: EmptyArrayType, column: number, cellValue: string) => {
|
||||
if (!cellValue) return '-';
|
||||
return formatDate(new Date(cellValue), 'YYYY-mm-dd HH:MM:SS');
|
||||
};
|
||||
//列表日期时间格式化
|
||||
const dateFormatHMS = (row: any, column: number, cellValue: any) => {
|
||||
// 列表日期时间格式化
|
||||
const dateFormatHMS = (row: EmptyArrayType, column: number, cellValue: string) => {
|
||||
if (!cellValue) return '-';
|
||||
let time = 0;
|
||||
if (typeof row === 'number') time = row;
|
||||
@@ -30,11 +31,11 @@ export default function () {
|
||||
return formatDate(new Date(time * 1000), 'HH:MM:SS');
|
||||
};
|
||||
// 小数格式化
|
||||
const scaleFormat = (value: any = 0, scale: number = 4) => {
|
||||
const scaleFormat = (value: string = '0', scale: number = 4) => {
|
||||
return Number.parseFloat(value).toFixed(scale);
|
||||
};
|
||||
// 小数格式化
|
||||
const scale2Format = (value: any = 0) => {
|
||||
const scale2Format = (value: string = '0') => {
|
||||
return Number.parseFloat(value).toFixed(2);
|
||||
};
|
||||
// 点击复制文本
|
||||
|
||||
@@ -32,11 +32,13 @@ export const NextLoading = {
|
||||
window.nextLoading = true;
|
||||
},
|
||||
// 移除 loading
|
||||
done: () => {
|
||||
done: (time: number = 0) => {
|
||||
nextTick(() => {
|
||||
window.nextLoading = false;
|
||||
const el = <HTMLElement>document.querySelector('.loading-next');
|
||||
el?.parentNode?.removeChild(el);
|
||||
setTimeout(() => {
|
||||
window.nextLoading = false;
|
||||
const el = <HTMLElement>document.querySelector('.loading-next');
|
||||
el?.parentNode?.removeChild(el);
|
||||
}, time);
|
||||
});
|
||||
},
|
||||
};
|
||||
|
||||
8
web/src/utils/mitt.ts
Normal file
8
web/src/utils/mitt.ts
Normal file
@@ -0,0 +1,8 @@
|
||||
// https://www.npmjs.com/package/mitt
|
||||
import mitt, { Emitter } from 'mitt';
|
||||
|
||||
// 类型
|
||||
const emitter: Emitter<MittType> = mitt<MittType>();
|
||||
|
||||
// 导出
|
||||
export default emitter;
|
||||
@@ -1,4 +1,4 @@
|
||||
import { nextTick } from 'vue';
|
||||
import { nextTick, defineAsyncComponent } from 'vue';
|
||||
import type { App } from 'vue';
|
||||
import * as svg from '@element-plus/icons-vue';
|
||||
import router from '/@/router/index';
|
||||
@@ -7,7 +7,10 @@ import { storeToRefs } from 'pinia';
|
||||
import { useThemeConfig } from '/@/stores/themeConfig';
|
||||
import { i18n } from '/@/i18n/index';
|
||||
import { Local } from '/@/utils/storage';
|
||||
import SvgIcon from '/@/components/svgIcon/index.vue';
|
||||
import { verifyUrl } from '/@/utils/toolsValidate';
|
||||
|
||||
// 引入组件
|
||||
const SvgIcon = defineAsyncComponent(() => import('/@/components/svgIcon/index.vue'));
|
||||
|
||||
/**
|
||||
* 导出全局注册 element plus svg 图标
|
||||
@@ -34,7 +37,7 @@ export function useTitle() {
|
||||
let globalTitle: string = themeConfig.value.globalTitle;
|
||||
const { path, meta } = router.currentRoute.value;
|
||||
if (path === '/login') {
|
||||
webTitle = <any>meta.title;
|
||||
webTitle = <string>meta.title;
|
||||
} else {
|
||||
webTitle = setTagsViewNameI18n(router.currentRoute.value);
|
||||
}
|
||||
@@ -48,20 +51,20 @@ export function useTitle() {
|
||||
* @returns 返回当前 tagsViewName 名称
|
||||
*/
|
||||
export function setTagsViewNameI18n(item: any) {
|
||||
let tagsViewName: any = '';
|
||||
let tagsViewName: string = '';
|
||||
const { query, params, meta } = item;
|
||||
if (query?.tagsViewName || params?.tagsViewName) {
|
||||
if (/\/zh-cn|en|zh-tw\//.test(query?.tagsViewName) || /\/(zh-cn|en|zh-tw)\//.test(params?.tagsViewName)) {
|
||||
if (/\/zh-cn|en|zh-tw\//.test(query?.tagsViewName) || /\/zh-cn|en|zh-tw\//.test(params?.tagsViewName)) {
|
||||
// 国际化
|
||||
const urlTagsParams = (query?.tagsViewName && JSON.parse(query?.tagsViewName)) || (params?.tagsViewName && JSON.parse(params?.tagsViewName));
|
||||
tagsViewName = urlTagsParams[i18n.global.locale];
|
||||
tagsViewName = urlTagsParams[i18n.global.locale.value];
|
||||
} else {
|
||||
// 非国际化
|
||||
tagsViewName = query?.tagsViewName || params?.tagsViewName;
|
||||
}
|
||||
} else {
|
||||
// 非自定义 tagsView 名称
|
||||
tagsViewName = i18n.global.t(<any>meta.title);
|
||||
tagsViewName = i18n.global.t(meta.title);
|
||||
}
|
||||
return tagsViewName;
|
||||
}
|
||||
@@ -72,7 +75,7 @@ export function setTagsViewNameI18n(item: any) {
|
||||
* @param arr 列表数据
|
||||
* @description data-xxx 属性用于存储页面或应用程序的私有自定义数据
|
||||
*/
|
||||
export const lazyImg = (el: any, arr: any) => {
|
||||
export const lazyImg = (el: string, arr: EmptyArrayType) => {
|
||||
const io = new IntersectionObserver((res) => {
|
||||
res.forEach((v: any) => {
|
||||
if (v.isIntersecting) {
|
||||
@@ -105,8 +108,8 @@ export const globalComponentSize = (): string => {
|
||||
* @param obj 源对象
|
||||
* @returns 克隆后的对象
|
||||
*/
|
||||
export function deepClone(obj: any) {
|
||||
let newObj: any;
|
||||
export function deepClone(obj: EmptyObjectType) {
|
||||
let newObj: EmptyObjectType;
|
||||
try {
|
||||
newObj = obj.push ? [] : {};
|
||||
} catch (error) {
|
||||
@@ -143,7 +146,7 @@ export function isMobile() {
|
||||
* @param list 数组对象
|
||||
* @returns 删除空值后的数组对象
|
||||
*/
|
||||
export function handleEmpty(list: any) {
|
||||
export function handleEmpty(list: EmptyArrayType) {
|
||||
const arr = [];
|
||||
for (const i in list) {
|
||||
const d = [];
|
||||
@@ -158,6 +161,17 @@ export function handleEmpty(list: any) {
|
||||
return arr;
|
||||
}
|
||||
|
||||
/**
|
||||
* 打开外部链接
|
||||
* @param val 当前点击项菜单
|
||||
*/
|
||||
export function handleOpenLink(val: RouteItem) {
|
||||
const { origin, pathname } = window.location;
|
||||
router.push(val.path);
|
||||
if (verifyUrl(<string>val.meta?.isLink)) window.open(val.meta?.isLink);
|
||||
else window.open(`${origin}${pathname}#${val.meta?.isLink}`);
|
||||
}
|
||||
|
||||
/**
|
||||
* 统一批量导出
|
||||
* @method elSvg 导出全局注册 element plus svg 图标
|
||||
@@ -168,6 +182,7 @@ export function handleEmpty(list: any) {
|
||||
* @method deepClone 对象深克隆
|
||||
* @method isMobile 判断是否是移动端
|
||||
* @method handleEmpty 判断数组对象中所有属性是否为空,为空则删除当前行对象
|
||||
* @method handleOpenLink 打开外部链接
|
||||
*/
|
||||
const other = {
|
||||
elSvg: (app: App) => {
|
||||
@@ -176,24 +191,27 @@ const other = {
|
||||
useTitle: () => {
|
||||
useTitle();
|
||||
},
|
||||
setTagsViewNameI18n(route: any) {
|
||||
setTagsViewNameI18n(route: RouteToFrom) {
|
||||
return setTagsViewNameI18n(route);
|
||||
},
|
||||
lazyImg: (el: any, arr: any) => {
|
||||
lazyImg: (el: string, arr: EmptyArrayType) => {
|
||||
lazyImg(el, arr);
|
||||
},
|
||||
globalComponentSize: () => {
|
||||
return globalComponentSize();
|
||||
},
|
||||
deepClone: (obj: any) => {
|
||||
deepClone: (obj: EmptyObjectType) => {
|
||||
return deepClone(obj);
|
||||
},
|
||||
isMobile: () => {
|
||||
return isMobile();
|
||||
},
|
||||
handleEmpty: (list: any) => {
|
||||
handleEmpty: (list: EmptyArrayType) => {
|
||||
return handleEmpty(list);
|
||||
},
|
||||
handleOpenLink: (val: RouteItem) => {
|
||||
handleOpenLink(val);
|
||||
},
|
||||
};
|
||||
|
||||
// 统一批量导出
|
||||
|
||||
@@ -1,20 +1,26 @@
|
||||
import axios from 'axios';
|
||||
import axios, { AxiosInstance, AxiosRequestConfig } from 'axios';
|
||||
import { ElMessage, ElMessageBox } from 'element-plus';
|
||||
import { Session } from '/@/utils/storage';
|
||||
import qs from 'qs';
|
||||
|
||||
// 配置新建一个 axios 实例
|
||||
const service = axios.create({
|
||||
baseURL: import.meta.env.VITE_API_URL as any,
|
||||
const service: AxiosInstance = axios.create({
|
||||
baseURL: import.meta.env.VITE_API_URL,
|
||||
timeout: 50000,
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
paramsSerializer: {
|
||||
serialize(params) {
|
||||
return qs.stringify(params, { allowDots: true });
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
// 添加请求拦截器
|
||||
service.interceptors.request.use(
|
||||
(config) => {
|
||||
(config: AxiosRequestConfig) => {
|
||||
// 在发送请求之前做些什么 token
|
||||
if (Session.get('token')) {
|
||||
(<any>config.headers).common['Authorization'] = `${Session.get('token')}`;
|
||||
config.headers!['Authorization'] = `${Session.get('token')}`;
|
||||
}
|
||||
return config;
|
||||
},
|
||||
|
||||
@@ -14,7 +14,7 @@ export const Local = {
|
||||
},
|
||||
// 获取永久缓存
|
||||
get(key: string) {
|
||||
let json: any = window.localStorage.getItem(key);
|
||||
let json = <string>window.localStorage.getItem(key);
|
||||
return JSON.parse(json);
|
||||
},
|
||||
// 移除永久缓存
|
||||
@@ -43,7 +43,7 @@ export const Session = {
|
||||
// 获取临时缓存
|
||||
get(key: string) {
|
||||
if (key === 'token') return Cookies.get(key);
|
||||
let json: any = window.sessionStorage.getItem(key);
|
||||
let json = <string>window.sessionStorage.getItem(key);
|
||||
return JSON.parse(json);
|
||||
},
|
||||
// 移除临时缓存
|
||||
|
||||
@@ -1,59 +1,63 @@
|
||||
import { ElMessage } from 'element-plus';
|
||||
|
||||
/**
|
||||
* hex颜色转rgb颜色
|
||||
* @param str 颜色值字符串
|
||||
* @returns 返回处理后的颜色值
|
||||
* 颜色转换函数
|
||||
* @method hexToRgb hex 颜色转 rgb 颜色
|
||||
* @method rgbToHex rgb 颜色转 Hex 颜色
|
||||
* @method getDarkColor 加深颜色值
|
||||
* @method getLightColor 变浅颜色值
|
||||
*/
|
||||
export function hexToRgb(str: any) {
|
||||
let hexs: any = '';
|
||||
let reg = /^\#?[0-9A-Fa-f]{6}$/;
|
||||
if (!reg.test(str)) return ElMessage.warning('输入错误的hex');
|
||||
str = str.replace('#', '');
|
||||
hexs = str.match(/../g);
|
||||
for (let i = 0; i < 3; i++) hexs[i] = parseInt(hexs[i], 16);
|
||||
return hexs;
|
||||
}
|
||||
|
||||
/**
|
||||
* rgb颜色转Hex颜色
|
||||
* @param r 代表红色
|
||||
* @param g 代表绿色
|
||||
* @param b 代表蓝色
|
||||
* @returns 返回处理后的颜色值
|
||||
*/
|
||||
export function rgbToHex(r: any, g: any, b: any) {
|
||||
let reg = /^\d{1,3}$/;
|
||||
if (!reg.test(r) || !reg.test(g) || !reg.test(b)) return ElMessage.warning('输入错误的rgb颜色值');
|
||||
let hexs = [r.toString(16), g.toString(16), b.toString(16)];
|
||||
for (let i = 0; i < 3; i++) if (hexs[i].length == 1) hexs[i] = `0${hexs[i]}`;
|
||||
return `#${hexs.join('')}`;
|
||||
}
|
||||
|
||||
/**
|
||||
* 加深颜色值
|
||||
* @param color 颜色值字符串
|
||||
* @param level 加深的程度,限0-1之间
|
||||
* @returns 返回处理后的颜色值
|
||||
*/
|
||||
export function getDarkColor(color: string, level: number) {
|
||||
let reg = /^\#?[0-9A-Fa-f]{6}$/;
|
||||
if (!reg.test(color)) return ElMessage.warning('输入错误的hex颜色值');
|
||||
let rgb = hexToRgb(color);
|
||||
for (let i = 0; i < 3; i++) rgb[i] = Math.floor(rgb[i] * (1 - level));
|
||||
return rgbToHex(rgb[0], rgb[1], rgb[2]);
|
||||
}
|
||||
|
||||
/**
|
||||
* 变浅颜色值
|
||||
* @param color 颜色值字符串
|
||||
* @param level 加深的程度,限0-1之间
|
||||
* @returns 返回处理后的颜色值
|
||||
*/
|
||||
export function getLightColor(color: string, level: number) {
|
||||
let reg = /^\#?[0-9A-Fa-f]{6}$/;
|
||||
if (!reg.test(color)) return ElMessage.warning('输入错误的hex颜色值');
|
||||
let rgb = hexToRgb(color);
|
||||
for (let i = 0; i < 3; i++) rgb[i] = Math.floor((255 - rgb[i]) * level + rgb[i]);
|
||||
return rgbToHex(rgb[0], rgb[1], rgb[2]);
|
||||
export function useChangeColor() {
|
||||
// str 颜色值字符串
|
||||
const hexToRgb = (str: string): any => {
|
||||
let hexs: any = '';
|
||||
let reg = /^\#?[0-9A-Fa-f]{6}$/;
|
||||
if (!reg.test(str)) {
|
||||
ElMessage.warning('输入错误的hex');
|
||||
return '';
|
||||
}
|
||||
str = str.replace('#', '');
|
||||
hexs = str.match(/../g);
|
||||
for (let i = 0; i < 3; i++) hexs[i] = parseInt(hexs[i], 16);
|
||||
return hexs;
|
||||
};
|
||||
// r 代表红色 | g 代表绿色 | b 代表蓝色
|
||||
const rgbToHex = (r: any, g: any, b: any): string => {
|
||||
let reg = /^\d{1,3}$/;
|
||||
if (!reg.test(r) || !reg.test(g) || !reg.test(b)) {
|
||||
ElMessage.warning('输入错误的rgb颜色值');
|
||||
return '';
|
||||
}
|
||||
let hexs = [r.toString(16), g.toString(16), b.toString(16)];
|
||||
for (let i = 0; i < 3; i++) if (hexs[i].length == 1) hexs[i] = `0${hexs[i]}`;
|
||||
return `#${hexs.join('')}`;
|
||||
};
|
||||
// color 颜色值字符串 | level 变浅的程度,限0-1之间
|
||||
const getDarkColor = (color: string, level: number): string => {
|
||||
let reg = /^\#?[0-9A-Fa-f]{6}$/;
|
||||
if (!reg.test(color)) {
|
||||
ElMessage.warning('输入错误的hex颜色值');
|
||||
return '';
|
||||
}
|
||||
let rgb = useChangeColor().hexToRgb(color);
|
||||
for (let i = 0; i < 3; i++) rgb[i] = Math.floor(rgb[i] * (1 - level));
|
||||
return useChangeColor().rgbToHex(rgb[0], rgb[1], rgb[2]);
|
||||
};
|
||||
// color 颜色值字符串 | level 加深的程度,限0-1之间
|
||||
const getLightColor = (color: string, level: number): string => {
|
||||
let reg = /^\#?[0-9A-Fa-f]{6}$/;
|
||||
if (!reg.test(color)) {
|
||||
ElMessage.warning('输入错误的hex颜色值');
|
||||
return '';
|
||||
}
|
||||
let rgb = useChangeColor().hexToRgb(color);
|
||||
for (let i = 0; i < 3; i++) rgb[i] = Math.floor((255 - rgb[i]) * level + rgb[i]);
|
||||
return useChangeColor().rgbToHex(rgb[0], rgb[1], rgb[2]);
|
||||
};
|
||||
return {
|
||||
hexToRgb,
|
||||
rgbToHex,
|
||||
getDarkColor,
|
||||
getLightColor,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -5,16 +5,16 @@ const setWatermark = (str: string) => {
|
||||
const can = document.createElement('canvas');
|
||||
can.width = 200;
|
||||
can.height = 130;
|
||||
const cans: any = can.getContext('2d');
|
||||
const cans = <CanvasRenderingContext2D>can.getContext('2d');
|
||||
cans.rotate((-20 * Math.PI) / 180);
|
||||
cans.font = '12px Vedana';
|
||||
cans.fillStyle = 'rgba(200, 200, 200, 0.30)';
|
||||
cans.textBaseline = 'Middle';
|
||||
cans.textBaseline = 'middle';
|
||||
cans.fillText(str, can.width / 10, can.height / 2);
|
||||
const div = document.createElement('div');
|
||||
div.id = id;
|
||||
div.style.pointerEvents = 'none';
|
||||
div.style.top = '15px';
|
||||
div.style.top = '0px';
|
||||
div.style.left = '0px';
|
||||
div.style.position = 'fixed';
|
||||
div.style.zIndex = '10000000';
|
||||
|
||||
Reference in New Issue
Block a user