636 lines
20 KiB
JavaScript
636 lines
20 KiB
JavaScript
import appConfig from '@/config'
|
||
/**
|
||
* 时间戳
|
||
* @param {*} timestamp 时间戳
|
||
*/
|
||
const timestampToTime = (timestamp) => {
|
||
let date = new Date(timestamp) //时间戳为10位需*1000,时间戳为13位的话不需乘1000
|
||
let Y = date.getFullYear() + '-'
|
||
let M =
|
||
(date.getMonth() + 1 < 10 ?
|
||
'0' + (date.getMonth() + 1) :
|
||
date.getMonth() + 1) + '-'
|
||
let D =
|
||
(date.getDate() < 10 ? '0' + date.getDate() : date.getDate()) + ' '
|
||
let h =
|
||
(date.getHours() < 10 ? '0' + date.getHours() : date.getHours()) + ':'
|
||
let m =
|
||
(date.getMinutes() < 10 ? '0' + date.getMinutes() : date.getMinutes()) +
|
||
':'
|
||
let s =
|
||
date.getSeconds() < 10 ? '0' + date.getSeconds() : date.getSeconds()
|
||
return Y + M + D + h + m + s
|
||
};
|
||
|
||
/**
|
||
* 时间日期格式化
|
||
* @param dateObj 如果为字符串 则原样返回,如果为date时间对象则返回格式化后的结果
|
||
* @param format
|
||
* @returns {*}
|
||
*/
|
||
const dateFormats = (dateObj, format) => {
|
||
if(typeof(dateObj) =='string'){
|
||
return dateObj
|
||
}
|
||
let date = {
|
||
'M+': dateObj.getMonth() + 1,
|
||
'd+': dateObj.getDate(),
|
||
'h+': dateObj.getHours(),
|
||
'm+': dateObj.getMinutes(),
|
||
's+': dateObj.getSeconds(),
|
||
'q+': Math.floor((dateObj.getMonth() + 3) / 3),
|
||
'S+': dateObj.getMilliseconds()
|
||
};
|
||
if (/(y+)/i.test(format)) {
|
||
format = format.replace(RegExp.$1, (dateObj.getFullYear() + '').substr(4 - RegExp.$1.length))
|
||
}
|
||
for (let k in date) {
|
||
if (new RegExp('(' + k + ')').test(format)) {
|
||
format = format.replace(RegExp.$1, RegExp.$1.length === 1
|
||
? date[k] : ('00' + date[k]).substr(('' + date[k]).length))
|
||
}
|
||
}
|
||
return format
|
||
}
|
||
|
||
/**
|
||
* 存储localStorage
|
||
*/
|
||
const setStore = (name, content) => {
|
||
if (!name) return;
|
||
if (typeof content !== 'string') {
|
||
content = JSON.stringify(content);
|
||
}
|
||
window.localStorage.setItem(name, content);
|
||
}
|
||
|
||
/**
|
||
* 获取localStorage
|
||
*/
|
||
const getStore = name => {
|
||
if (!name) return;
|
||
return window.localStorage.getItem(name);
|
||
}
|
||
|
||
/**
|
||
* 删除localStorage
|
||
*/
|
||
const removeStorage = name => {
|
||
if (!name) return;
|
||
window.localStorage.removeItem(name);
|
||
}
|
||
|
||
/**
|
||
* 设置cookie
|
||
**/
|
||
function setCookie(name, value, day) {
|
||
let date = new Date();
|
||
date.setDate(date.getDate() + day);
|
||
document.cookie = name + '=' + value + ';expires=' + date + ';SameSite=None';
|
||
}
|
||
|
||
/**
|
||
* 获取cookie
|
||
**/
|
||
function getCookie(name) {
|
||
let reg = RegExp(name + '=([^;]+)');
|
||
let arr = document.cookie.match(reg);
|
||
if (arr) {
|
||
return arr[1];
|
||
} else {
|
||
return '';
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 删除cookie
|
||
**/
|
||
function delCookie(name) {
|
||
setCookie(name, null, -1);
|
||
}
|
||
|
||
//只能输入正整数和0
|
||
function limitNumInt(value) {
|
||
value = value.replace(/\D/g, '');
|
||
return value
|
||
}
|
||
|
||
//金额
|
||
function limitPriceType(value){
|
||
var t = value.charAt(0);
|
||
value = value.replace(/[^\d\.]/g, '');
|
||
value = value.replace(/\.{2,}/g, '.');
|
||
value = value.replace('.', '$#$').replace(/\./g, '').replace('$#$', '.');
|
||
value = value.replace(/^\./g, '');
|
||
value = value.replace(/^(\-)*(\d+)\.(\d\d).*$/,'$1$2.$3');
|
||
return value
|
||
}
|
||
//通过a标签转换url为blob下载文件
|
||
function downloadFileURLByA(url) {
|
||
let a = document.createElement('a')
|
||
// 这里是将url转成blob地址,
|
||
fetch(url).then(res => res.blob()).then(blob => { // 将链接地址字符内容转变成blob地址
|
||
a.href = URL.createObjectURL(blob)
|
||
console.log(a.href)
|
||
a.download = '' // 下载文件的名字
|
||
// a.download = url.split('/')[url.split('/').length -1] // // 下载文件的名字
|
||
document.body.appendChild(a)
|
||
a.click()
|
||
})
|
||
}
|
||
//通过iframe标签下载文件
|
||
function downloadFileURLByIframe(url) {
|
||
var iframe =document.createElement("iframe")
|
||
iframe.style.display ="none";
|
||
iframe.src = url;
|
||
document.body.appendChild(iframe);
|
||
}
|
||
|
||
|
||
function formatUnitSize (bytes, is_unit, fixed, end_unit) //字节转换,到指定单位结束 is_unit:是否显示单位 fixed:小数点位置 end_unit:结束单位
|
||
{
|
||
if (bytes == undefined) return 0;
|
||
|
||
if (is_unit == undefined) is_unit = true;
|
||
if (fixed == undefined) fixed = 2;
|
||
if (end_unit == undefined) end_unit = '';
|
||
|
||
if (typeof bytes == 'string') bytes = parseInt(bytes);
|
||
var unit = [' B', ' KB', ' MB', ' GB', 'TB'];
|
||
var c = 1024;
|
||
for (var i = 0; i < unit.length; i++) {
|
||
var cUnit = unit[i];
|
||
if (end_unit) {
|
||
if (cUnit.trim() == end_unit.trim()) {
|
||
var val = i == 0 ? bytes : fixed == 0 ? bytes : bytes.toFixed(fixed)
|
||
if (is_unit) {
|
||
return val + cUnit;
|
||
} else {
|
||
val = parseFloat(val);
|
||
return val;
|
||
}
|
||
}
|
||
} else {
|
||
if (bytes < c) {
|
||
var val = i == 0 ? bytes : fixed == 0 ? bytes : bytes.toFixed(fixed)
|
||
if (is_unit) {
|
||
return val + cUnit;
|
||
} else {
|
||
val = parseFloat(val);
|
||
return val;
|
||
}
|
||
}
|
||
}
|
||
|
||
bytes /= c;
|
||
}
|
||
}
|
||
const handleDate = (date) => {
|
||
let month = date.getMonth() + 1 < 10 ? `0${date.getMonth() + 1}` : date.getMonth() + 1
|
||
let day = date.getDate() < 10 ? `0${date.getDate()}` : date.getDate()
|
||
let hours = date.getHours() < 10 ? `0${date.getHours()}` : date.getHours()
|
||
let minutes = date.getMinutes() < 10 ? `0${date.getMinutes()}` : date.getMinutes()
|
||
let seconds = date.getSeconds() < 10 ? `0${date.getSeconds()}` : date.getSeconds()
|
||
return `${date.getFullYear()}-${month}-${day}`
|
||
}
|
||
|
||
// 时间处理
|
||
const handleTime = (date) => {
|
||
let month = date.getMonth() + 1 < 10 ? `0${date.getMonth() + 1}` : date.getMonth() + 1
|
||
let day = date.getDate() < 10 ? `0${date.getDate()}` : date.getDate()
|
||
let hours = date.getHours() < 10 ? `0${date.getHours()}` : date.getHours()
|
||
let minutes = date.getMinutes() < 10 ? `0${date.getMinutes()}` : date.getMinutes()
|
||
let seconds = date.getSeconds() < 10 ? `0${date.getSeconds()}` : date.getSeconds()
|
||
return `${date.getFullYear()}-${month}-${day} ${hours}:${minutes}:${seconds}`
|
||
}
|
||
const commonVal = {
|
||
isPhone: /^[1][3-9]\d{9}$/, // 手机号码
|
||
isPrice: /^(^[1-9](\d+)?(\.\d{1,2})?$)|(^0$)|(^\d\.\d{1,2}$)$/, //money
|
||
isTel: /^((0\d{2,3}-\d{7,8})|(1[3456789]\d{9}))$/, // 手机号码,座机
|
||
isAgentAccount:/^[a-zA-Z0-9]+$/, //agentAccount
|
||
isEmail: /^([a-zA-Z0-9]+[|_|.]?)*[a-zA-Z0-9]+@([a-zA-Z0-9]+[|_|.]?)*[a-zA-Z0-9]+.[a-zA-Z]{2,3}$/
|
||
}
|
||
function setStorage(key,data){
|
||
appConfig.STORAGE_METHOD === "localStorage" ? localStorage.setItem(key,data):sessionStorage.setItem(key,data)
|
||
}
|
||
function getStorage(key){
|
||
const result = appConfig.STORAGE_METHOD === "localStorage" ? localStorage.getItem(key):sessionStorage.getItem(key)
|
||
return result
|
||
}
|
||
function getToken() {
|
||
return getStorage('logintoken')
|
||
}
|
||
function isShowBtn(url,moduleName, btnName) {
|
||
let btnArr = getStorage('menuList')?JSON.parse(getStorage('menuList')):[];
|
||
let isshow = false;
|
||
for (var i = 0; i < btnArr.length; i++) {
|
||
let item = btnArr[i];
|
||
if (item.url == url && item.moduleName == moduleName && item.menuPermission && item.menuPermission.includes(btnName) ) {
|
||
isshow = true;
|
||
break;
|
||
}
|
||
}
|
||
return isshow
|
||
}
|
||
|
||
function hasPermission(url,btnName) {
|
||
let btnArr = getStorage('menuList')?JSON.parse(getStorage('menuList')):[];
|
||
let isshow = false;
|
||
for (var i = 0; i < btnArr.length; i++) {
|
||
let item = btnArr[i];
|
||
if (item.url == url && item.menuPermission && item.menuPermission.includes(btnName) ) {
|
||
isshow = true;
|
||
break;
|
||
}
|
||
}
|
||
return isshow
|
||
}
|
||
|
||
function getTableHeight(tableSelectHeight,allowPage=true){
|
||
var pagination_height = allowPage?176:0;
|
||
let height = (window.innerHeight || document.documentElement.clientHeight || document.body.clientHeight) - tableSelectHeight;
|
||
var ua = navigator.userAgent;
|
||
//获取当前设备类型(安卓或苹果)
|
||
if (ua && /Android/.test(ua)) {
|
||
return 700
|
||
}
|
||
else if (ua && /iPhone|ipad|ipod|ios/.test(ua)){
|
||
return 700
|
||
}
|
||
else {
|
||
return height - pagination_height
|
||
}
|
||
}
|
||
|
||
//菜单数组转换为树结构
|
||
function transArrayMenuToTree(dataList) {
|
||
//定义父id字段为指定字段名
|
||
const pid = "parent"
|
||
// 最终要产出的树状数据的数组
|
||
let treeList = []
|
||
// 所有项都使用对象存储起来
|
||
let map = {}
|
||
// 建立一个映射关系:通过id快速找到对应的元素
|
||
let newDataList = []
|
||
dataList.forEach(item => {
|
||
if(item.visible == 1){
|
||
let newItem = {
|
||
text:item.name,
|
||
id:item.id,
|
||
attributes:{
|
||
url:item.web_path,
|
||
icon:item.icon
|
||
},
|
||
hasChildren: false,
|
||
hasParent:false,
|
||
parent:item.parent,
|
||
children:[],
|
||
}
|
||
newDataList.push(newItem)
|
||
map[item.id] = newItem
|
||
}
|
||
})
|
||
newDataList.forEach(item => {
|
||
// 对于每一个元素来说,先找它的上级
|
||
// 如果能找到,说明它有上级,则要把它添加到上级的children中去
|
||
// 如果找不到,说明它没有上级,直接添加到 treeList
|
||
let parent = map[item[pid]]
|
||
// 如果存在上级则表示item不是最顶层的数据
|
||
if (!!parent) {
|
||
item.hasChildren = item.children.length>0
|
||
item.hasParent = true
|
||
parent.children.push(item)
|
||
parent.hasChildren = true
|
||
} else {
|
||
// 如果不存在上级 则是顶层数据,直接添加
|
||
treeList.push(item)
|
||
}
|
||
})
|
||
return treeList
|
||
}
|
||
|
||
function randomId(){
|
||
return Math.floor(Math.random() * 100000 + Math.random() * 20000 + Math.random() * 5000 + Math.random() * 100);
|
||
}
|
||
|
||
function deepClone(str) {
|
||
if (str === undefined) {
|
||
return undefined
|
||
}
|
||
return JSON.parse(JSON.stringify(str))
|
||
}
|
||
|
||
function getDefaultFormConfig() {
|
||
return {
|
||
modelName: 'formData',//前端表单名
|
||
refName: 'lyFormBuilder',
|
||
rulesName: 'rules',
|
||
modelDbTable:"",//后端自动生成Model表名(英文名)
|
||
modelClassName:"",//后端自动生成Model的class名
|
||
modelVerboseName:"",//后端自动生成Model使用此字段作为表的verbose_name和菜单名称
|
||
other_config:{
|
||
create_datetime_filter:false,
|
||
mutiple_delete:false,
|
||
},//通用配置
|
||
labelWidth: 'auto',
|
||
labelPosition: 'left',
|
||
size: '',
|
||
disabled: false,//全局禁用表单
|
||
cssCode: '',
|
||
customClass: '',
|
||
functions: '', //全局函数
|
||
jsonVersion: 1,
|
||
onFormMounted: '',
|
||
}
|
||
}
|
||
function buildDefaultFormJson() {
|
||
return {
|
||
widgetList: [],
|
||
formConfig: deepClone(getDefaultFormConfig())
|
||
}
|
||
}
|
||
function isNull(value) {
|
||
return (value === null) || (value === undefined);
|
||
}
|
||
function insertCustomCssToHead (cssCode, formId = '') {
|
||
let head = document.getElementsByTagName('head')[0]
|
||
let oldStyle = document.getElementById('lyform-custom-css')
|
||
if (!!oldStyle) {
|
||
head.removeChild(oldStyle) //先清除后插入!!
|
||
}
|
||
if (!!formId) {
|
||
oldStyle = document.getElementById('lyform-custom-css' + '-' + formId)
|
||
!!oldStyle && head.removeChild(oldStyle) //先清除后插入!!
|
||
}
|
||
|
||
let newStyle = document.createElement('style')
|
||
newStyle.type = 'text/css'
|
||
newStyle.rel = 'stylesheet'
|
||
newStyle.id = !!formId ? 'lyform-custom-css' + '-' + formId : 'lyform-custom-css'
|
||
try {
|
||
newStyle.appendChild(document.createTextNode(cssCode))
|
||
} catch(ex) {
|
||
newStyle.styleSheet.cssText = cssCode
|
||
}
|
||
|
||
head.appendChild(newStyle)
|
||
}
|
||
|
||
function insertGlobalFunctionsToHtml (functionsCode, formId = '') {
|
||
let bodyElement = document.getElementsByTagName('body')[0]
|
||
let oldScriptEle = document.getElementById('ly_form_global_functions')
|
||
!!oldScriptEle && bodyElement.removeChild(oldScriptEle) //先清除后插入!!
|
||
if (!!formId) {
|
||
oldScriptEle = document.getElementById('ly_form_global_functions' + '-' + formId)
|
||
!!oldScriptEle && bodyElement.removeChild(oldScriptEle) //先清除后插入!!
|
||
}
|
||
|
||
let newScriptElelement = document.createElement('script')
|
||
newScriptElelement.id = !!formId ? 'ly_form_global_functions' + '-' + formId : 'ly_form_global_functions'
|
||
newScriptElelement.type = 'text/javascript'
|
||
newScriptElelement.innerHTML = functionsCode
|
||
bodyElement.appendChild(newScriptElelement)
|
||
}
|
||
|
||
function getDefaultWorkflowConfig() {
|
||
return {
|
||
name:"",//流程名称
|
||
jsonVersion: 1,//版本
|
||
nodeConfig:{
|
||
nodeName: '发起人',
|
||
type: 0,
|
||
setType:1,
|
||
nodeRoleList: [],
|
||
nodeUserList:[],
|
||
childNode:{}
|
||
},
|
||
}
|
||
}
|
||
|
||
// 图片上传根据名称排序
|
||
const sortName = (v1, v2) => {
|
||
let a = "" + v1;
|
||
let b = "" + v2;
|
||
let reg = /[0-9]+/g;
|
||
let lista = a.match(reg);
|
||
let listb = b.match(reg);
|
||
if (!lista || !listb) {
|
||
return a.localeCompare(b); }
|
||
for (let i = 0, minLen = Math.min(lista.length, listb.length) ; i < minLen; i++) {
|
||
//数字所在位置序号
|
||
let indexa = a.indexOf(lista[i]);
|
||
let indexb = b.indexOf(listb[i]);
|
||
//数字前面的前缀
|
||
let prefixa = a.substring(0, indexa);
|
||
let prefixb = b.substring(0, indexb);
|
||
//数字的string
|
||
let stra = lista[i];
|
||
let strb = listb[i];
|
||
//数字的值
|
||
let numa = parseInt(stra);
|
||
let numb = parseInt(strb);
|
||
//如果数字的序号不等或前缀不等,属于前缀不同的情况,直接比较
|
||
if (indexa != indexb || prefixa != prefixb) {
|
||
return a.localeCompare(b);
|
||
}
|
||
else {
|
||
//数字的string全等
|
||
if (stra === strb) {
|
||
//如果是最后一个数字,比较数字的后缀
|
||
if (i == minLen - 1) {
|
||
return a.substring(indexa).localeCompare(b.substring(indexb));
|
||
}
|
||
//如果不是最后一个数字,则循环跳转到下一个数字,并去掉前面相同的部分
|
||
else {
|
||
a = a.substring(indexa + stra.length);
|
||
b = b.substring(indexa + stra.length);
|
||
}
|
||
}
|
||
//如果数字的string不全等,但值相等
|
||
else if (numa == numb) {
|
||
//直接比较数字前缀0的个数,多的更小
|
||
return strb.lastIndexOf(numb + '') - stra.lastIndexOf(numa + '');
|
||
}
|
||
else {
|
||
return numa - numb;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
//根据变量类型判断是否为空
|
||
function isEmpty(nstr){
|
||
if (typeof nstr === 'string') {
|
||
return !!nstr;
|
||
} else if (Array.isArray(nstr)) {
|
||
return nstr.length === 0;
|
||
} else if (typeof nstr === 'object' && nstr !== null) {
|
||
return Object.keys(nstr).length === 0;
|
||
} else if(nstr === null || nstr === undefined || nstr === ""){
|
||
return true
|
||
} else {
|
||
return false; //默认非空
|
||
}
|
||
}
|
||
|
||
const getFileExt = function (fileName) {
|
||
// 从文件名中获取扩展名
|
||
const lastDotIndex = fileName.lastIndexOf('.');
|
||
if (lastDotIndex === -1) {
|
||
// 如果没有找到点,返回空字符串或其他默认值
|
||
return '';
|
||
} else {
|
||
// 使用 substring 方法获取最后一个点之后的部分作为扩展名
|
||
return fileName.substring(lastDotIndex + 1).toLowerCase();
|
||
}
|
||
}
|
||
|
||
const getFileTypeDesc = function (fileName) {
|
||
const ext = getFileExt(fileName);
|
||
switch (ext) {
|
||
case 'py':
|
||
return [ext,'Python源文件'];
|
||
case 'php':
|
||
return [ext,'Php源文件'];
|
||
case 'java':
|
||
return [ext,'Java源文件'];
|
||
case 'go':
|
||
return [ext,'Go源文件'];
|
||
case 'js':
|
||
return [ext,'JavaScript源文件'];
|
||
case 'ts':
|
||
return [ext,'TypeScript源文件'];
|
||
case 'vue':
|
||
return [ext,'Vue源文件'];
|
||
case 'json':
|
||
return [ext,'Json源文件'];
|
||
case 'css':
|
||
return [ext,'CSS样式表'];
|
||
case 'html':
|
||
case 'htm':
|
||
return [ext,'HTML文件'];
|
||
case 'pdf':
|
||
return [ext,'PDF文件'];
|
||
case 'jpg':
|
||
case 'jpeg':
|
||
case 'png':
|
||
case 'gif':
|
||
return [ext,'Image图片'];
|
||
case 'mp4':
|
||
case 'flv':
|
||
case 'm4a':
|
||
case 'avi':
|
||
return [ext,'Video视频文件'];
|
||
case 'sql':
|
||
return [ext,'SQL脚本文件'];
|
||
case 'txt':
|
||
return [ext,'文本格式'];
|
||
default:
|
||
return [ext,'未知文件'];
|
||
}
|
||
}
|
||
|
||
const canEditOnline = function (fileName) {
|
||
let ext = getFileExt(fileName);
|
||
let black_list = ['msi','psd','dll','sys','gz', 'zip', 'rar','7z', 'bz2', 'exe', 'db','sqlite','sqlite3','.mdb', 'pdf', 'doc', 'xls', 'docx', 'xlsx', 'ppt','pptx','mp4','flv','avi', 'png', 'gif', 'jpg', 'jpeg', 'bmp', 'icon', 'ico', 'pyc','class', 'so', 'pyd']
|
||
if (black_list.includes(ext)) {
|
||
return false
|
||
}
|
||
return true
|
||
}
|
||
|
||
// 生成指定长度随机字符串
|
||
const generateRandomString = function (length) {
|
||
const characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
|
||
let result = '';
|
||
for (let i = 0; i < length; i++) {
|
||
const randomIndex = Math.floor(Math.random() * characters.length);
|
||
result += characters.charAt(randomIndex);
|
||
}
|
||
return result;
|
||
}
|
||
|
||
// 获取路径中的文件名,如果为目录则获取目录名
|
||
const getFileNameFromPath = function(path) {
|
||
const isWindowsPath = /^[A-Za-z]:\//.test(path);
|
||
if(isWindowsPath){
|
||
if(path.length>3){
|
||
path = path.replace(/\/$/, '');
|
||
}else{
|
||
return ""
|
||
}
|
||
}else{
|
||
if(path.length>1){
|
||
path = path.replace(/\/$/, '');
|
||
}
|
||
if(path === "/"){
|
||
return ""
|
||
}
|
||
}
|
||
// 使用 split('/') 将路径按照斜杠分割成数组,并取最后一个元素作为文件名
|
||
const parts = path.split('/');
|
||
return parts[parts.length - 1];
|
||
}
|
||
|
||
const downloadFileContent = function (content, fileName) {
|
||
const downloadUrl = window.URL.createObjectURL(new Blob([content]));
|
||
const a = document.createElement('a');
|
||
a.style.display = 'none';
|
||
a.href = downloadUrl;
|
||
a.download = fileName;
|
||
const event = new MouseEvent('click');
|
||
a.dispatchEvent(event);
|
||
}
|
||
|
||
const addCopySuffix = function (name) {
|
||
const parts = name.split('.');
|
||
if (parts.length > 1) {
|
||
// 如果有扩展名,则在扩展名之前加上'-副本'
|
||
return parts.slice(0, -1).join('.') + '-副本.' + parts[parts.length - 1];
|
||
} else {
|
||
// 如果没有扩展名,则在最后加上'-副本'
|
||
return name + '-副本';
|
||
}
|
||
}
|
||
|
||
export{
|
||
timestampToTime,
|
||
dateFormats,
|
||
setStore,
|
||
getStore,
|
||
setCookie,
|
||
getCookie,
|
||
delCookie,
|
||
limitNumInt,
|
||
limitPriceType,
|
||
handleDate,
|
||
handleTime,
|
||
commonVal,
|
||
isShowBtn,
|
||
hasPermission,
|
||
getTableHeight,
|
||
transArrayMenuToTree,
|
||
sortName,
|
||
formatUnitSize,
|
||
downloadFileURLByA,
|
||
downloadFileURLByIframe,
|
||
randomId,
|
||
deepClone,
|
||
getDefaultFormConfig,
|
||
buildDefaultFormJson,
|
||
isNull,
|
||
insertCustomCssToHead,
|
||
insertGlobalFunctionsToHtml,
|
||
setStorage,
|
||
getStorage,
|
||
removeStorage,
|
||
getToken,
|
||
getDefaultWorkflowConfig,
|
||
isEmpty,
|
||
getFileNameFromPath,
|
||
canEditOnline,
|
||
getFileTypeDesc,
|
||
generateRandomString,
|
||
downloadFileContent,
|
||
addCopySuffix
|
||
} |