mirror of
https://gitee.com/orangeform/orange-admin.git
synced 2026-01-18 11:06:36 +08:00
commit:升级到vue3,更新最近工作流技术栈,支持sa-token
This commit is contained in:
73
OrangeFormsOpen-VUE3/src/common/hooks/useCommon.ts
Normal file
73
OrangeFormsOpen-VUE3/src/common/hooks/useCommon.ts
Normal file
@@ -0,0 +1,73 @@
|
||||
import { Delete, Search, Edit, Plus, Refresh, Picture } from '@element-plus/icons-vue';
|
||||
import { EpPropMergeType } from 'element-plus/es/utils';
|
||||
import { useDate } from '@/common/hooks/useDate';
|
||||
import { usePermissions } from '@/common/hooks/usePermission';
|
||||
import { Dialog } from '@/components/Dialog';
|
||||
import { useDropdown } from '@/common/hooks/useDropdown';
|
||||
import { useTable } from '@/common/hooks/useTable';
|
||||
|
||||
/**
|
||||
* 大部分管理页面需要的组件及公共属性和方法
|
||||
*
|
||||
* @returns 图标(Plus、Delete、Edit、Search)、对话框组件(Dialog)、defaultFormItemSize、mainContextHeight、checkPermCodeExist、下拉数据勾子(useDropdown)、表格数据勾子(useTable)
|
||||
*/
|
||||
export const useCommon = () => {
|
||||
const mainContextHeight = inject('mainContextHeight', ref(200));
|
||||
const clientHeight = inject('documentClientHeight', ref(200));
|
||||
|
||||
const { checkPermCodeExist } = usePermissions();
|
||||
const { formatDateByStatsType, getDateRangeFilter } = useDate();
|
||||
|
||||
/**
|
||||
* 将输入的值转换成指定的类型
|
||||
* @param {Any} value
|
||||
* @param {String} type 要转换的类型(integer、float、boolean、string)
|
||||
*/
|
||||
function parseParams(value: number | string | boolean | undefined, type = 'string') {
|
||||
if (value == null) return value;
|
||||
switch (type) {
|
||||
case 'integer':
|
||||
return Number.parseInt(value as string);
|
||||
case 'float':
|
||||
return Number.parseFloat(value as string);
|
||||
case 'boolean':
|
||||
return value === 'true' || value;
|
||||
default:
|
||||
return String(value);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 将输入值转换为执行的类型数组
|
||||
* @param {Array} value 输入数组
|
||||
* @param {String} type 要转换的类型(integer、float、boolean、string)
|
||||
*/
|
||||
function parseArrayParams(value: Array<number | string | boolean>, type = 'string') {
|
||||
if (Array.isArray(value)) {
|
||||
return value.map(item => {
|
||||
return parseParams(item, type);
|
||||
});
|
||||
} else {
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
Delete,
|
||||
Search,
|
||||
Edit,
|
||||
Plus,
|
||||
Refresh,
|
||||
Picture,
|
||||
Dialog,
|
||||
mainContextHeight,
|
||||
clientHeight,
|
||||
checkPermCodeExist,
|
||||
formatDateByStatsType,
|
||||
getDateRangeFilter,
|
||||
useDropdown,
|
||||
useTable,
|
||||
parseParams,
|
||||
parseArrayParams,
|
||||
};
|
||||
};
|
||||
92
OrangeFormsOpen-VUE3/src/common/hooks/useDate.ts
Normal file
92
OrangeFormsOpen-VUE3/src/common/hooks/useDate.ts
Normal file
@@ -0,0 +1,92 @@
|
||||
import { formatDate, parseDate } from '../utils';
|
||||
|
||||
const allowStatsType = ['time', 'datetime', 'day', 'month', 'year'];
|
||||
|
||||
export const useDate = () => {
|
||||
/**
|
||||
* 格式化日期
|
||||
* @param {Date|String} date 要格式化的日期
|
||||
* @param {String} statsType 输出日期类型
|
||||
* @param {String} format 输入日期的格式
|
||||
*/
|
||||
const formatDateByStatsType = (
|
||||
date: string | number | Date,
|
||||
statsType = 'day',
|
||||
format = 'YYYY-MM-DD',
|
||||
) => {
|
||||
if (date == null) return undefined;
|
||||
if (statsType == null) return date;
|
||||
statsType = allowStatsType.indexOf(statsType) === -1 ? 'day' : statsType;
|
||||
if (statsType === 'datetime') format = 'YYYY-MM-DD HH:mm:ss';
|
||||
|
||||
//console.log('date', statsType, format, date);
|
||||
|
||||
const tempDate = date instanceof Date ? date : parseDate(date, format);
|
||||
//console.log('tempDate', tempDate);
|
||||
if (!tempDate) return undefined;
|
||||
switch (statsType) {
|
||||
case 'time':
|
||||
return formatDate(tempDate, 'HH:mm:ss');
|
||||
case 'datetime':
|
||||
return formatDate(tempDate, 'YYYY-MM-DD HH:mm:ss');
|
||||
case 'day':
|
||||
return formatDate(tempDate, 'YYYY-MM-DD');
|
||||
case 'month':
|
||||
return formatDate(tempDate, 'YYYY-MM');
|
||||
case 'year':
|
||||
return formatDate(tempDate, 'YYYY');
|
||||
default:
|
||||
return formatDate(tempDate, 'YYYY-MM-DD');
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* 根据输入的日期获得日期范围(例如:输入2019-12-12,输出['2019-12-12 00:00:00', '2019-12-12 23:59:59'])
|
||||
* @param {Date|String} date 要转换的日期
|
||||
* @param {String} statsType 转换类型(day, month, year)
|
||||
* @param {String} format 输出格式
|
||||
*/
|
||||
const getDateRangeFilter = (date: string, statsType = 'day', format = 'YYYY-MM-dd HH:mm:ss') => {
|
||||
if (date == null) return [];
|
||||
|
||||
statsType = allowStatsType.indexOf(statsType) === -1 ? 'day' : statsType;
|
||||
date = date.substring(0, date.indexOf(' '));
|
||||
const tempList = date.split('-');
|
||||
const year = Number.parseInt(tempList[0]);
|
||||
const month = Number.parseInt(tempList[1]);
|
||||
const day = Number.parseInt(tempList[2]);
|
||||
if (isNaN(year) || isNaN(month) || isNaN(day)) {
|
||||
return [];
|
||||
}
|
||||
const tempDate = new Date(year, month - 1, day);
|
||||
// 判断是否正确的日期
|
||||
if (isNaN(tempDate.getTime())) return [];
|
||||
|
||||
tempDate.setHours(0, 0, 0, 0);
|
||||
let retDate: Date[] = [];
|
||||
// TODO 如果类型为'time', 'datetime'会出错
|
||||
switch (statsType) {
|
||||
case 'day':
|
||||
retDate = [new Date(tempDate), new Date(tempDate.setDate(tempDate.getDate() + 1))];
|
||||
break;
|
||||
case 'month':
|
||||
tempDate.setDate(1);
|
||||
retDate = [new Date(tempDate), new Date(tempDate.setMonth(tempDate.getMonth() + 1))];
|
||||
break;
|
||||
case 'year':
|
||||
tempDate.setDate(1);
|
||||
tempDate.setMonth(0);
|
||||
retDate = [new Date(tempDate), new Date(tempDate.setFullYear(tempDate.getFullYear() + 1))];
|
||||
break;
|
||||
}
|
||||
|
||||
retDate[1] = new Date(retDate[1].getTime() - 1);
|
||||
|
||||
return [formatDate(retDate[0], format), formatDate(retDate[1], format)];
|
||||
};
|
||||
|
||||
return {
|
||||
formatDateByStatsType,
|
||||
getDateRangeFilter,
|
||||
};
|
||||
};
|
||||
60
OrangeFormsOpen-VUE3/src/common/hooks/useDownload.ts
Normal file
60
OrangeFormsOpen-VUE3/src/common/hooks/useDownload.ts
Normal file
@@ -0,0 +1,60 @@
|
||||
import { ElMessage } from 'element-plus';
|
||||
import { get } from '../http/request';
|
||||
|
||||
/**
|
||||
* 文件下载Hooks
|
||||
*
|
||||
* @returns downloadFile
|
||||
*/
|
||||
export const useDownload = () => {
|
||||
/**
|
||||
* 下载上传的文件
|
||||
* @param {*} url 下载文件的url
|
||||
* @param {*} fileName 下载文件名
|
||||
*/
|
||||
const downloadFile = (url: string, fileName: string) => {
|
||||
get<Blob>(
|
||||
url,
|
||||
{},
|
||||
{},
|
||||
{
|
||||
responseType: 'blob',
|
||||
transformResponse: function (data) {
|
||||
return data;
|
||||
},
|
||||
},
|
||||
)
|
||||
.then(res => {
|
||||
console.log('============= download', res);
|
||||
const data = res instanceof Blob ? res : res.data;
|
||||
if (data instanceof Blob) {
|
||||
const url = window.URL.createObjectURL(data);
|
||||
const link = document.createElement('a');
|
||||
link.style.display = 'none';
|
||||
link.href = url;
|
||||
link.setAttribute('download', fileName);
|
||||
document.body.appendChild(link);
|
||||
link.click();
|
||||
document.body.removeChild(link);
|
||||
} else {
|
||||
ElMessage.error('下载文件失败');
|
||||
}
|
||||
})
|
||||
.catch(e => {
|
||||
console.error('============= download', e);
|
||||
if (e instanceof Blob) {
|
||||
const reader = new FileReader();
|
||||
reader.onload = function () {
|
||||
ElMessage.error(
|
||||
reader.result ? JSON.parse(reader.result.toString()).errorMessage : '下载文件失败',
|
||||
);
|
||||
};
|
||||
reader.readAsText(e);
|
||||
} else {
|
||||
ElMessage.error('下载文件失败');
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
return { downloadFile };
|
||||
};
|
||||
85
OrangeFormsOpen-VUE3/src/common/hooks/useDropdown.ts
Normal file
85
OrangeFormsOpen-VUE3/src/common/hooks/useDropdown.ts
Normal file
@@ -0,0 +1,85 @@
|
||||
import { DropdownOptions } from '../types/list';
|
||||
import { treeDataTranslate } from '../utils';
|
||||
|
||||
const defaultOptions = {
|
||||
isTree: false,
|
||||
idKey: 'id',
|
||||
parentIdKey: 'parentId',
|
||||
};
|
||||
|
||||
export const useDropdown = <T>(options: DropdownOptions<T>) => {
|
||||
const loading = ref(false);
|
||||
let loaded = false;
|
||||
const dropdownList: Ref<T[]> = ref([]);
|
||||
|
||||
const finalOptions = { ...defaultOptions, ...options };
|
||||
|
||||
const { loadData, isTree, idKey, parentIdKey } = finalOptions;
|
||||
|
||||
//console.log('dropdown', loadData, isTree, idKey, parentIdKey);
|
||||
|
||||
const loadDropdownData = (): Promise<T[]> => {
|
||||
return new Promise((resolve, reject) => {
|
||||
if (!loaded && !loading.value) {
|
||||
loadData()
|
||||
.then(res => {
|
||||
console.log(`loadDropdownData 加载了${res.dataList.length}条数据`);
|
||||
loaded = true;
|
||||
dropdownList.value = isTree
|
||||
? treeDataTranslate(res.dataList, idKey, parentIdKey)
|
||||
: res.dataList;
|
||||
resolve(dropdownList.value);
|
||||
})
|
||||
.catch(e => {
|
||||
reject(e);
|
||||
})
|
||||
.finally(() => {
|
||||
loading.value = false;
|
||||
});
|
||||
} else {
|
||||
resolve(dropdownList.value);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* 下拉框显示或隐藏时调用
|
||||
* @param {Boolean} isShow 正在显示或者隐藏
|
||||
*/
|
||||
const onVisibleChange = (isShow: boolean): Promise<T[]> => {
|
||||
return new Promise((resolve, reject) => {
|
||||
if (isShow && !loaded && !loading.value) {
|
||||
loadDropdownData()
|
||||
.then(res => {
|
||||
resolve(res);
|
||||
})
|
||||
.catch(e => {
|
||||
reject(e);
|
||||
});
|
||||
} else {
|
||||
resolve(dropdownList.value);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* 刷新列表
|
||||
* @param immediate 是否立即刷新,默认为true
|
||||
* @return Promise<T[] | void> 立即执行时返回最新数据
|
||||
*/
|
||||
const refresh = (immediate = true): Promise<T[] | void> => {
|
||||
loaded = false;
|
||||
if (immediate) {
|
||||
return loadDropdownData();
|
||||
}
|
||||
dropdownList.value = [];
|
||||
return Promise.resolve();
|
||||
};
|
||||
|
||||
return {
|
||||
loading,
|
||||
dropdownList,
|
||||
onVisibleChange,
|
||||
refresh,
|
||||
};
|
||||
};
|
||||
25
OrangeFormsOpen-VUE3/src/common/hooks/usePermission.ts
Normal file
25
OrangeFormsOpen-VUE3/src/common/hooks/usePermission.ts
Normal file
@@ -0,0 +1,25 @@
|
||||
import { useLoginStore } from '@/store';
|
||||
import { getAppId } from '../utils';
|
||||
|
||||
export const usePermissions = () => {
|
||||
const loginStorage = useLoginStore();
|
||||
|
||||
const checkPermCodeExist = (permCode: string) => {
|
||||
//console.log(permCode);
|
||||
if (getAppId() != null && getAppId() !== '') return true;
|
||||
|
||||
if (loginStorage.userInfo == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (loginStorage.userInfo.permCodeList != null) {
|
||||
return loginStorage.userInfo.permCodeList.indexOf(permCode) != -1;
|
||||
} else {
|
||||
return loginStorage.userInfo.isAdmin;
|
||||
}
|
||||
};
|
||||
|
||||
return {
|
||||
checkPermCodeExist,
|
||||
};
|
||||
};
|
||||
197
OrangeFormsOpen-VUE3/src/common/hooks/useTable.ts
Normal file
197
OrangeFormsOpen-VUE3/src/common/hooks/useTable.ts
Normal file
@@ -0,0 +1,197 @@
|
||||
/*
|
||||
* 表格数据(分页)钩子
|
||||
* 提供表格数据查询、分页基础数据和回调方法
|
||||
*/
|
||||
import { ElMessage } from 'element-plus';
|
||||
import { OrderInfo, RequestParam, TableOptions } from '../types/pagination';
|
||||
import { SortInfo } from '../types/sortinfo';
|
||||
|
||||
// 默认分页大小
|
||||
const DEFAULT_PAGE_SIZE = 10;
|
||||
|
||||
export const useTable = <T>(options: TableOptions<T>) => {
|
||||
const orderInfo: OrderInfo = {
|
||||
fieldName: options.orderFieldName,
|
||||
asc: options.ascending || false,
|
||||
dateAggregateBy: options.dateAggregateBy,
|
||||
};
|
||||
const loading = ref(false);
|
||||
const currentPage = ref(1);
|
||||
const totalCount = ref(0);
|
||||
const dataList: Ref<T[]> = ref([]);
|
||||
const pageSize: Ref<number> = ref(options.pageSize || DEFAULT_PAGE_SIZE);
|
||||
if (!options.verifyTableParameter) {
|
||||
options.verifyTableParameter = () => true;
|
||||
}
|
||||
const { loadTableData, paged, verifyTableParameter } = options;
|
||||
|
||||
let oldPage = 0;
|
||||
let oldPageSize: number = options.pageSize || DEFAULT_PAGE_SIZE;
|
||||
|
||||
if (pageSize.value <= 0) {
|
||||
console.warn(`pagesize的值不能小于等于0,被设置为默认值:${DEFAULT_PAGE_SIZE}`);
|
||||
pageSize.value = DEFAULT_PAGE_SIZE;
|
||||
}
|
||||
|
||||
// 监听pageSize变化
|
||||
watch(pageSize, (newVal, oldVal) => {
|
||||
//console.log('pageSize change', newVal, oldVal);
|
||||
if (newVal != oldVal) {
|
||||
loadData(1, newVal)
|
||||
.then(() => {
|
||||
oldPage = 1;
|
||||
oldPageSize = newVal;
|
||||
currentPage.value = 1;
|
||||
})
|
||||
.catch(() => {
|
||||
currentPage.value = oldPage;
|
||||
pageSize.value = oldVal;
|
||||
});
|
||||
}
|
||||
});
|
||||
// 监听currentPage变化
|
||||
watch(currentPage, (newVal, oldVal) => {
|
||||
if (newVal != oldVal) {
|
||||
loadData(newVal, pageSize.value)
|
||||
.then(() => {
|
||||
oldPage = newVal;
|
||||
})
|
||||
.catch(() => {
|
||||
currentPage.value = oldVal;
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* 获取表格数据
|
||||
* @param pageNum 当前分页
|
||||
* @param pageSize 每页数量
|
||||
* @param reload 是否重新获取数据
|
||||
*/
|
||||
const loadData = (pageNum: number, pageSize: number, reload = false): Promise<void> => {
|
||||
if (paged && !reload && oldPage == pageNum && oldPageSize == pageSize) {
|
||||
console.log('数据已加载,无须重复执行');
|
||||
return Promise.resolve();
|
||||
}
|
||||
if (paged) {
|
||||
console.log(`开始加载数据, 第${pageNum}页,每页${pageSize}, 强制加载:${reload}`);
|
||||
} else {
|
||||
console.log(`开始加载数据, 无分页, 强制加载:${reload}`);
|
||||
}
|
||||
|
||||
const params = {} as RequestParam;
|
||||
if (orderInfo.fieldName != null) params.orderParam = [orderInfo];
|
||||
if (paged) {
|
||||
params.pageParam = {
|
||||
pageNum,
|
||||
pageSize,
|
||||
};
|
||||
}
|
||||
return new Promise((resolve, reject) => {
|
||||
loading.value = true;
|
||||
loadTableData(params)
|
||||
.then(res => {
|
||||
//console.log(res.dataList, res.totalCount);
|
||||
// vxetable需要用到对象的hasOwnerProperty方法,因此需要重新构造对象
|
||||
dataList.value = res.dataList.map((item: T) => {
|
||||
return { ...item };
|
||||
});
|
||||
totalCount.value = res.totalCount;
|
||||
console.log(`本次加载${res.dataList.length}条数据,共有${res.totalCount}条数据`);
|
||||
resolve();
|
||||
})
|
||||
.catch(e => {
|
||||
reject(e);
|
||||
})
|
||||
.finally(() => {
|
||||
loading.value = false;
|
||||
//console.log('加载数据完毕');
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
const onPageSizeChange = (size: number) => {
|
||||
pageSize.value = size;
|
||||
};
|
||||
|
||||
const onCurrentPageChange = (newVal: number) => {
|
||||
currentPage.value = newVal;
|
||||
};
|
||||
|
||||
/**
|
||||
* 表格排序字段变化
|
||||
* @param {String} prop 排序字段的字段名
|
||||
* @param {string} field 排序字段的字段名
|
||||
* @param {String} order 正序还是倒序
|
||||
*/
|
||||
const onSortChange = ({ prop, field, order }: SortInfo) => {
|
||||
//console.log(prop, field, order);
|
||||
orderInfo.fieldName = prop || field;
|
||||
orderInfo.asc = order == 'ascending' || order == 'asc';
|
||||
refreshTable();
|
||||
};
|
||||
/**
|
||||
* 刷新表格数据
|
||||
* @param {Boolean} research 是否按照新的查询条件重新查询(调用verify函数)
|
||||
* @param {Integer} pageNum 当前页面
|
||||
* @param showMsg 是否显示查询结果成功与否消息
|
||||
*/
|
||||
const refreshTable = (research = false, pageNum = 0, showMsg = false) => {
|
||||
//console.log(research, pageNum, showMsg);
|
||||
let reload = false;
|
||||
if (research) {
|
||||
if (!verifyTableParameter()) return;
|
||||
reload = true;
|
||||
}
|
||||
|
||||
if (pageNum && pageNum != currentPage.value) {
|
||||
loadData(pageNum, pageSize.value, reload)
|
||||
.then(() => {
|
||||
oldPage = currentPage.value = pageNum;
|
||||
if (showMsg) ElMessage.success('查询成功');
|
||||
})
|
||||
.catch((e: Error) => {
|
||||
console.warn('获取表格数据出错了', e);
|
||||
currentPage.value = oldPage;
|
||||
if (showMsg) ElMessage.error('查询失败' + e.message);
|
||||
});
|
||||
} else {
|
||||
loadData(currentPage.value, pageSize.value, true)
|
||||
.then(() => {
|
||||
if (showMsg) ElMessage.success('查询成功');
|
||||
})
|
||||
.catch((e: Error) => {
|
||||
console.warn('获取表格数据出错了', e);
|
||||
if (showMsg) ElMessage.error('查询失败' + e.message);
|
||||
});
|
||||
}
|
||||
};
|
||||
/**
|
||||
* 获取每一行的index信息
|
||||
* @param {Integer} index 表格在本页位置
|
||||
*/
|
||||
const getTableIndex = (index: number) => {
|
||||
return paged ? (currentPage.value - 1) * pageSize.value + (index + 1) : index + 1;
|
||||
};
|
||||
|
||||
const clearTable = () => {
|
||||
oldPage = 0;
|
||||
currentPage.value = 1;
|
||||
totalCount.value = 0;
|
||||
dataList.value = [];
|
||||
};
|
||||
|
||||
return {
|
||||
loading,
|
||||
currentPage,
|
||||
totalCount,
|
||||
pageSize,
|
||||
dataList,
|
||||
clearTable,
|
||||
getTableIndex,
|
||||
onPageSizeChange,
|
||||
onCurrentPageChange,
|
||||
onSortChange,
|
||||
refreshTable,
|
||||
};
|
||||
};
|
||||
160
OrangeFormsOpen-VUE3/src/common/hooks/useUpload.ts
Normal file
160
OrangeFormsOpen-VUE3/src/common/hooks/useUpload.ts
Normal file
@@ -0,0 +1,160 @@
|
||||
import { useLayoutStore } from '@/store';
|
||||
import { ANY_OBJECT } from '@/types/generic';
|
||||
import { getAppId, getToken } from '../utils';
|
||||
import { post } from '../http/request';
|
||||
import { useUrlBuilder } from './useUrl';
|
||||
|
||||
export const useUpload = () => {
|
||||
const { buildGetUrl, requestUrl } = useUrlBuilder();
|
||||
/**
|
||||
* 解析返回的上传文件数据
|
||||
* @param {String} jsonData 上传文件数据,[{name, downloadUri, filename}]
|
||||
* @param {Object} params 上传文件的参数
|
||||
* @returns {Array} 上传文件信息,[{name, downloadUri, filename, url}]
|
||||
*/
|
||||
const parseUploadData = (jsonData: string, params: ANY_OBJECT) => {
|
||||
let pathList = [];
|
||||
if (jsonData != null) {
|
||||
try {
|
||||
pathList = JSON.parse(jsonData);
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
}
|
||||
}
|
||||
|
||||
return Array.isArray(pathList)
|
||||
? pathList.map(item => {
|
||||
const downloadParams = { ...params };
|
||||
downloadParams.filename = item.filename;
|
||||
return {
|
||||
...item,
|
||||
url: getUploadFileUrl(item, downloadParams),
|
||||
};
|
||||
})
|
||||
: [];
|
||||
};
|
||||
|
||||
/**
|
||||
* 获得上传文件url
|
||||
* @param {*} item 上传文件
|
||||
* @param {*} params 上传文件的参数
|
||||
*/
|
||||
const getUploadFileUrl = (item: { downloadUri: string }, params?: ANY_OBJECT) => {
|
||||
if (item == null || item.downloadUri == null) {
|
||||
return null;
|
||||
} else {
|
||||
const currentMenuId = useLayoutStore().currentMenuId;
|
||||
const query = { ...params };
|
||||
query.Authorization = getToken();
|
||||
query.MenuId = currentMenuId;
|
||||
query.AppCode = getAppId();
|
||||
return buildGetUrl(item.downloadUri, query);
|
||||
}
|
||||
};
|
||||
|
||||
const getUploadHeaders = computed(() => {
|
||||
const token = getToken();
|
||||
const appId = getAppId();
|
||||
const currentMenuId = useLayoutStore().currentMenuId;
|
||||
const header: ANY_OBJECT = {
|
||||
Authorization: token,
|
||||
MenuId: currentMenuId,
|
||||
};
|
||||
if (appId) header.AppCode = appId;
|
||||
|
||||
return header;
|
||||
});
|
||||
|
||||
/**
|
||||
* 获得上传接口
|
||||
* @param {*} url 上传路径
|
||||
*/
|
||||
const getUploadActionUrl = (url: string) => {
|
||||
return buildGetUrl(url, null);
|
||||
};
|
||||
|
||||
/**
|
||||
* 上传文件
|
||||
* @param {*} url 请求的url
|
||||
* @param {*} params 请求参数
|
||||
*/
|
||||
const fetchUpload = (url: string, params: ANY_OBJECT) => {
|
||||
return new Promise<ANY_OBJECT>((resolve, reject) => {
|
||||
post(
|
||||
requestUrl(url),
|
||||
{},
|
||||
{ showError: true },
|
||||
{
|
||||
data: params,
|
||||
headers: {
|
||||
'Content-Type': 'multipart/form-data',
|
||||
},
|
||||
transformRequest: [
|
||||
function (data: ANY_OBJECT) {
|
||||
const formData = new FormData();
|
||||
Object.keys(data).map(key => {
|
||||
formData.append(key, data[key]);
|
||||
});
|
||||
return formData;
|
||||
},
|
||||
],
|
||||
},
|
||||
)
|
||||
.then((res: ANY_OBJECT) => {
|
||||
console.log('uploaded file fetchUpload', res);
|
||||
if (res.data && res.success) {
|
||||
resolve(res.data);
|
||||
}
|
||||
})
|
||||
.catch(e => {
|
||||
reject(e);
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* 获得上传文件url列表
|
||||
* @param {*} jsonData 上传文件数据,[{name, downloadUri, filename}]
|
||||
* @param {*} params 上传文件的参数
|
||||
* @returns {Array} 文件url列表
|
||||
*/
|
||||
const getPictureList = (jsonData: string, params: ANY_OBJECT) => {
|
||||
const tempList = parseUploadData(jsonData, params);
|
||||
if (Array.isArray(tempList)) {
|
||||
return tempList.map(item => item.url);
|
||||
} else {
|
||||
return [];
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* 将选中文件信息格式化成json信息
|
||||
* @param {Array} fileList 上传文件列表,[{name, fileUrl, data}]
|
||||
*/
|
||||
const fileListToJson = (fileList: ANY_OBJECT[]) => {
|
||||
if (Array.isArray(fileList)) {
|
||||
return JSON.stringify(
|
||||
fileList.map(item => {
|
||||
return {
|
||||
name: item.name,
|
||||
downloadUri: item.downloadUri || item.response.data.downloadUri,
|
||||
filename: item.filename || item.response.data.filename,
|
||||
uploadPath: item.uploadPath || item.response.data.uploadPath,
|
||||
};
|
||||
}),
|
||||
);
|
||||
} else {
|
||||
return undefined;
|
||||
}
|
||||
};
|
||||
|
||||
return {
|
||||
getUploadFileUrl,
|
||||
parseUploadData,
|
||||
getUploadHeaders,
|
||||
getUploadActionUrl,
|
||||
fetchUpload,
|
||||
getPictureList,
|
||||
fileListToJson,
|
||||
};
|
||||
};
|
||||
25
OrangeFormsOpen-VUE3/src/common/hooks/useUploadWidget.ts
Normal file
25
OrangeFormsOpen-VUE3/src/common/hooks/useUploadWidget.ts
Normal file
@@ -0,0 +1,25 @@
|
||||
import { UploadFile } from 'element-plus';
|
||||
|
||||
export const useUploadWidget = (maxFileCount = 1) => {
|
||||
const fileList = ref<UploadFile[]>([]);
|
||||
const maxCount = ref(maxFileCount);
|
||||
|
||||
/**
|
||||
* 上传文件列表改变
|
||||
* @param {Object} uploadFile 改变的文件
|
||||
* @param {Array} uploadFiles 改变后的文件列表
|
||||
*/
|
||||
const onFileChange = (uploadFile: UploadFile | null, uploadFiles: UploadFile[] | null) => {
|
||||
if (uploadFiles && uploadFiles.length > 0) {
|
||||
if (maxFileCount == 1) {
|
||||
fileList.value = [uploadFiles[uploadFiles.length - 1]];
|
||||
} else {
|
||||
fileList.value = uploadFiles;
|
||||
}
|
||||
} else {
|
||||
fileList.value = [];
|
||||
}
|
||||
};
|
||||
|
||||
return { fileList, onFileChange, maxCount };
|
||||
};
|
||||
40
OrangeFormsOpen-VUE3/src/common/hooks/useUrl.ts
Normal file
40
OrangeFormsOpen-VUE3/src/common/hooks/useUrl.ts
Normal file
@@ -0,0 +1,40 @@
|
||||
import { ANY_OBJECT } from '@/types/generic';
|
||||
import { objectToQueryString } from '../utils';
|
||||
|
||||
export const useUrlBuilder = () => {
|
||||
/**
|
||||
* 请求地址统一处理/组装
|
||||
* @param actionName 方法名称
|
||||
* @param params 请求参数
|
||||
* @returns 请求全路径(含参数)
|
||||
*/
|
||||
const buildGetUrl = (actionName: string, params: ANY_OBJECT | null = null) => {
|
||||
console.log('getUrl', actionName);
|
||||
const queryString = objectToQueryString(params);
|
||||
if (actionName != null && actionName !== '') {
|
||||
if (actionName.substring(0, 1) === '/') actionName = actionName.substring(1);
|
||||
}
|
||||
|
||||
return (
|
||||
import.meta.env.VITE_SERVER_HOST + actionName + (queryString == null ? '' : '?' + queryString)
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* 请求地址统一处理/组装
|
||||
* @param actionName action方法名称
|
||||
*/
|
||||
const requestUrl = (actionName: string) => {
|
||||
console.log('requestUrl', actionName);
|
||||
if (actionName) {
|
||||
if (actionName.substring(0, 1) === '/') actionName = actionName.substring(1);
|
||||
}
|
||||
if (actionName.indexOf('http://') === 0 || actionName.indexOf('https://') === 0) {
|
||||
return actionName;
|
||||
} else {
|
||||
return import.meta.env.VITE_SERVER_HOST + actionName;
|
||||
}
|
||||
};
|
||||
|
||||
return { buildGetUrl, requestUrl };
|
||||
};
|
||||
50
OrangeFormsOpen-VUE3/src/common/hooks/useWindowResize.ts
Normal file
50
OrangeFormsOpen-VUE3/src/common/hooks/useWindowResize.ts
Normal file
@@ -0,0 +1,50 @@
|
||||
import { onMounted, onUnmounted, provide, ref } from 'vue';
|
||||
import { useLayoutStore } from '@/store';
|
||||
import { getAppId } from '../utils';
|
||||
|
||||
// 屏幕宽度分界值,影响整体样式
|
||||
const WIDTH = 1900;
|
||||
|
||||
const documentClientHeight = ref(0);
|
||||
|
||||
/**
|
||||
* 在最顶层使用该hook,一方面监听窗口大小变化,同时向下面提供一个计算属性
|
||||
*/
|
||||
export const useWindowResize = () => {
|
||||
const windowResize = () => {
|
||||
//console.log('窗口尺寸发生变化');
|
||||
documentClientHeight.value = document.documentElement.clientHeight;
|
||||
if (window.innerWidth <= WIDTH) {
|
||||
layoutStore.defaultFormItemSize = 'default';
|
||||
document.body.className = 'orange-project container-default';
|
||||
} else {
|
||||
layoutStore.defaultFormItemSize = 'large';
|
||||
document.body.className = 'orange-project container-large';
|
||||
}
|
||||
|
||||
layoutStore.documentClientHeight = document.documentElement.clientHeight;
|
||||
layoutStore.mainContextHeight = mainContextHeight.value;
|
||||
};
|
||||
|
||||
const layoutStore = useLayoutStore();
|
||||
const mainContextHeight = computed(() => {
|
||||
const appId = getAppId();
|
||||
if (appId == null) {
|
||||
return documentClientHeight.value - (layoutStore.supportTags ? 110 : 60);
|
||||
} else {
|
||||
return documentClientHeight.value;
|
||||
}
|
||||
});
|
||||
|
||||
provide('documentClientHeight', documentClientHeight);
|
||||
provide('mainContextHeight', mainContextHeight);
|
||||
|
||||
onMounted(() => {
|
||||
windowResize();
|
||||
window.addEventListener('resize', windowResize);
|
||||
});
|
||||
|
||||
onUnmounted(() => {
|
||||
window.removeEventListener('resize', windowResize);
|
||||
});
|
||||
};
|
||||
147
OrangeFormsOpen-VUE3/src/common/http/axios.ts
Normal file
147
OrangeFormsOpen-VUE3/src/common/http/axios.ts
Normal file
@@ -0,0 +1,147 @@
|
||||
import axios, { AxiosInstance, AxiosPromise, AxiosResponse } from 'axios';
|
||||
import JSONbig from 'json-bigint';
|
||||
import { router } from '@/router';
|
||||
import { getToken, setToken, getAppId } from '@/common/utils/index';
|
||||
import { useLayoutStore } from '@/store';
|
||||
import { Dialog } from '@/components/Dialog';
|
||||
import { serverDefaultCfg } from './config';
|
||||
import { ResponseDataType } from './types';
|
||||
|
||||
// 创建 axios 请求实例
|
||||
const axiosInstance: AxiosInstance = axios.create({
|
||||
baseURL: serverDefaultCfg.baseURL, // 基础请求地址
|
||||
timeout: 30000, // 请求超时设置
|
||||
withCredentials: true, // 跨域请求是否需要携带 cookie
|
||||
headers: {
|
||||
//Accept: 'application/json, text/plain, */*',
|
||||
//'X-Requested-With': 'XMLHttpRequest',
|
||||
'Content-Type': 'application/json; charset=utf-8',
|
||||
deviceType: '4',
|
||||
},
|
||||
validateStatus: status => {
|
||||
return status === 200 || status === 401; // 放行哪些状态的请求
|
||||
},
|
||||
transformResponse: [
|
||||
function (data) {
|
||||
//console.log('transformResponse', data);
|
||||
if (typeof data === 'string') {
|
||||
return JSONbig({ storeAsString: true }).parse(data);
|
||||
} else {
|
||||
return data;
|
||||
}
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
// 创建请求拦截
|
||||
axiosInstance.interceptors.request.use(
|
||||
config => {
|
||||
const token = getToken();
|
||||
const appId = getAppId();
|
||||
const currentMenuId = useLayoutStore().currentMenuId;
|
||||
if (token != null) config.headers['Authorization'] = token;
|
||||
if (appId != null && appId !== '') config.headers['AppCode'] = appId;
|
||||
if (currentMenuId != null) config.headers['MenuId'] = currentMenuId;
|
||||
return config;
|
||||
},
|
||||
error => {
|
||||
Promise.reject(error);
|
||||
},
|
||||
);
|
||||
|
||||
const loginInvalid = () => {
|
||||
setToken(null);
|
||||
Dialog.closeAll();
|
||||
router.push({ name: 'login' });
|
||||
};
|
||||
|
||||
// 创建响应拦截
|
||||
axiosInstance.interceptors.response.use(
|
||||
<T>(response: AxiosResponse): AxiosPromise<ResponseDataType<T>> => {
|
||||
//console.log('axios response => ', response);
|
||||
const { data, status } = response;
|
||||
// 如果401响应放行至此,执行此逻辑
|
||||
if (status === 401) {
|
||||
const appId = getAppId();
|
||||
if (appId == null) {
|
||||
loginInvalid();
|
||||
}
|
||||
return Promise.reject(new Error('您未登录,或者登录已经超时,请先登录!'));
|
||||
}
|
||||
if (response.data && response.data.errorCode === 'UNAUTHORIZED_LOGIN') {
|
||||
// 401, token失效
|
||||
const appId = getAppId();
|
||||
if (appId == null) {
|
||||
loginInvalid();
|
||||
} else {
|
||||
return Promise.reject(new Error(response.data.errorMessage));
|
||||
}
|
||||
} else {
|
||||
if (response.headers['refreshedtoken'] != null) {
|
||||
setToken(response.headers['refreshedtoken']);
|
||||
}
|
||||
//console.log('response', response, 'blob', response.data instanceof Blob);
|
||||
// 判断请求是否成功
|
||||
if (!(response.data instanceof Blob) && !response.data.success) {
|
||||
return Promise.reject(new Error(response.data.errorMessage || 'error'));
|
||||
}
|
||||
}
|
||||
return data;
|
||||
},
|
||||
error => {
|
||||
//console.warn(error);
|
||||
let message = '';
|
||||
if (error && error.response) {
|
||||
switch (error.response.status) {
|
||||
case 302:
|
||||
message = '接口重定向了!';
|
||||
break;
|
||||
case 400:
|
||||
message = '参数不正确!';
|
||||
break;
|
||||
case 401:
|
||||
message = '您未登录,或者登录已经超时,请先登录!';
|
||||
break;
|
||||
case 403:
|
||||
message = '您没有权限操作!';
|
||||
break;
|
||||
case 404:
|
||||
message = `请求地址出错: ${error.response.config.url}`;
|
||||
break;
|
||||
case 408:
|
||||
message = '请求超时!';
|
||||
break;
|
||||
case 409:
|
||||
message = '系统已存在相同数据!';
|
||||
break;
|
||||
case 500:
|
||||
message = '服务器内部错误!';
|
||||
break;
|
||||
case 501:
|
||||
message = '服务未实现!';
|
||||
break;
|
||||
case 502:
|
||||
message = '网关错误!';
|
||||
break;
|
||||
case 503:
|
||||
message = '服务不可用!';
|
||||
break;
|
||||
case 504:
|
||||
message = '服务暂时无法访问,请稍后再试!';
|
||||
break;
|
||||
case 505:
|
||||
message = 'HTTP 版本不受支持!';
|
||||
break;
|
||||
default:
|
||||
message = '异常问题,请联系管理员!';
|
||||
break;
|
||||
}
|
||||
console.log('请求异常 ==>', message);
|
||||
return Promise.reject(new Error(message));
|
||||
} else {
|
||||
return Promise.reject(new Error(error.message));
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
export default axiosInstance;
|
||||
4
OrangeFormsOpen-VUE3/src/common/http/config.ts
Normal file
4
OrangeFormsOpen-VUE3/src/common/http/config.ts
Normal file
@@ -0,0 +1,4 @@
|
||||
export const serverDefaultCfg = {
|
||||
baseURL: import.meta.env.VITE_SERVER_HOST, // 请求基础地址,可根据环境自定义
|
||||
mockURL: '',
|
||||
};
|
||||
384
OrangeFormsOpen-VUE3/src/common/http/request.ts
Normal file
384
OrangeFormsOpen-VUE3/src/common/http/request.ts
Normal file
@@ -0,0 +1,384 @@
|
||||
import { ElMessage, ElLoading } from 'element-plus';
|
||||
import { AxiosRequestConfig } from 'axios';
|
||||
import { getAppId } from '@/common/utils/index';
|
||||
import { ANY_OBJECT } from '@/types/generic';
|
||||
import { useUrlBuilder } from '../hooks/useUrl';
|
||||
import axiosInstance from './axios';
|
||||
import { serverDefaultCfg } from './config';
|
||||
import { RequestMethods, RequestOption, ResponseDataType } from './types';
|
||||
|
||||
const { requestUrl } = useUrlBuilder();
|
||||
const globalConfig = {
|
||||
requestOption: {
|
||||
mock: false,
|
||||
// 调用的时候是否显示蒙版
|
||||
showMask: true,
|
||||
// 是否显示公共的错误提示
|
||||
showError: true,
|
||||
// 是否开启节流功能,同一个url不能频繁重复调用
|
||||
throttleFlag: false,
|
||||
// 节流间隔
|
||||
throttleTimeout: 50,
|
||||
} as RequestOption,
|
||||
axiosOption: {
|
||||
responseType: 'json',
|
||||
} as AxiosRequestConfig,
|
||||
};
|
||||
|
||||
function showErrorMessage(message: string | { showClose: boolean; message: string }) {
|
||||
const appId = getAppId();
|
||||
if (appId != null && appId !== '') {
|
||||
if (window.parent) {
|
||||
window.parent.postMessage(
|
||||
{
|
||||
type: 'message',
|
||||
data: {
|
||||
type: 'error',
|
||||
text: message,
|
||||
},
|
||||
},
|
||||
'*',
|
||||
);
|
||||
}
|
||||
} else {
|
||||
ElMessage.error(message);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 遮罩管理,多次调用支持引用计数
|
||||
*/
|
||||
class LoadingManager {
|
||||
private options: ANY_OBJECT;
|
||||
private refCount: number;
|
||||
private loading: ReturnType<typeof ElLoading.service> | null;
|
||||
|
||||
constructor(options: ANY_OBJECT) {
|
||||
this.options = options;
|
||||
this.refCount = 0;
|
||||
this.loading = null;
|
||||
}
|
||||
|
||||
showMask() {
|
||||
this.refCount++;
|
||||
//console.log('loading >>>', this.refCount);
|
||||
if (this.refCount <= 1 && this.loading == null) {
|
||||
//console.log('loading do create serice');
|
||||
this.loading = ElLoading.service(this.options);
|
||||
}
|
||||
}
|
||||
|
||||
hideMask() {
|
||||
//console.log('loading hideMask', this.refCount);
|
||||
if (this.refCount <= 1 && this.loading != null) {
|
||||
this.loading.close();
|
||||
this.loading = null;
|
||||
//console.log('loading hideMask do close');
|
||||
}
|
||||
this.refCount--;
|
||||
this.refCount = Math.max(0, this.refCount);
|
||||
}
|
||||
}
|
||||
|
||||
//console.log('new LoadingManager');
|
||||
const loadingManager = new LoadingManager({
|
||||
fullscreen: true,
|
||||
background: 'rgba(0, 0, 0, 0.1)',
|
||||
});
|
||||
|
||||
// url调用节流Set
|
||||
const ajaxThrottleSet = new Set();
|
||||
|
||||
/**
|
||||
* 核心函数,可通过它处理一切请求数据,并做横向扩展
|
||||
* @param url 请求地址
|
||||
* @param params 请求参数
|
||||
* @param method 请求方法,只接受"get" | "delete" | "head" | "post" | "put" | "patch"
|
||||
* @param requestOption 请求配置(针对当前本次请求)
|
||||
* @param axiosOption axios配置(针对当前本次请求)
|
||||
*/
|
||||
export async function commonRequest<D>(
|
||||
url: string,
|
||||
params: ANY_OBJECT,
|
||||
method: RequestMethods,
|
||||
requestOption?: RequestOption,
|
||||
axiosOption?: AxiosRequestConfig,
|
||||
): Promise<ResponseDataType<D>> {
|
||||
const finalOption = {
|
||||
...globalConfig.requestOption,
|
||||
...requestOption,
|
||||
};
|
||||
const { showMask, showError, throttleFlag, throttleTimeout } = finalOption;
|
||||
|
||||
let finalUrl = url;
|
||||
// 通过mock平台可对局部接口进行mock设置
|
||||
if (finalOption.mock) finalUrl = serverDefaultCfg.mockURL;
|
||||
|
||||
if (ajaxThrottleSet.has(finalUrl) && throttleFlag) {
|
||||
return Promise.reject();
|
||||
} else {
|
||||
if (throttleFlag) {
|
||||
ajaxThrottleSet.add(url);
|
||||
setTimeout(() => {
|
||||
ajaxThrottleSet.delete(url);
|
||||
}, throttleTimeout || 50);
|
||||
}
|
||||
|
||||
const finalAxiosOption = {
|
||||
...globalConfig.axiosOption,
|
||||
...axiosOption,
|
||||
};
|
||||
|
||||
// get请求使用params字段
|
||||
let data: ANY_OBJECT = { params };
|
||||
// 非get请求使用data字段
|
||||
if (method !== 'get') data = { data: params };
|
||||
|
||||
if (showMask) loadingManager.showMask();
|
||||
try {
|
||||
const result: ResponseDataType<D> = await axiosInstance({
|
||||
url: finalUrl,
|
||||
method,
|
||||
...data,
|
||||
...finalAxiosOption,
|
||||
});
|
||||
//console.log('result:', result);
|
||||
if (result instanceof Blob || result.success) {
|
||||
return Promise.resolve(result);
|
||||
} else {
|
||||
if (showError) {
|
||||
showErrorMessage({
|
||||
showClose: true,
|
||||
message: result.errorMessage ? result.errorMessage : '数据请求失败',
|
||||
});
|
||||
}
|
||||
return Promise.reject(result);
|
||||
}
|
||||
} catch (error) {
|
||||
console.warn('请求异常', error);
|
||||
if (showError) {
|
||||
const err = error as Error;
|
||||
showErrorMessage({
|
||||
showClose: true,
|
||||
message: err ? err.message : '网络请求错误',
|
||||
});
|
||||
}
|
||||
return Promise.reject(error);
|
||||
} finally {
|
||||
loadingManager.hideMask();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/***
|
||||
* @param url 请求地址
|
||||
* @param params 请求参数
|
||||
* @param options 请求设置(showMask-是否显示Loading层,默认为true;showError-是否显示错误信息,默认为true;throttleFlag-是否开户节流,默认为false;throttleTimeout-节流时效,默认为50毫秒)
|
||||
* @param axiosOption
|
||||
*/
|
||||
export const get = async <D>(
|
||||
url: string,
|
||||
params: ANY_OBJECT,
|
||||
options?: RequestOption,
|
||||
axiosOption?: AxiosRequestConfig,
|
||||
) => {
|
||||
return await commonRequest<D>(url, params, 'get', options, axiosOption);
|
||||
};
|
||||
/***
|
||||
* @param url 请求地址
|
||||
* @param params 请求参数
|
||||
* @param options 请求设置(showMask-是否显示Loading层,默认为true;showError-是否显示错误信息,默认为true;throttleFlag-是否开户节流,默认为false;throttleTimeout-节流时效,默认为50毫秒)
|
||||
* @param axiosOption
|
||||
*/
|
||||
export const post = async <D>(
|
||||
url: string,
|
||||
params: ANY_OBJECT,
|
||||
options?: RequestOption,
|
||||
axiosOption?: AxiosRequestConfig,
|
||||
) => {
|
||||
return await commonRequest<D>(url, params, 'post', options, axiosOption);
|
||||
};
|
||||
/***
|
||||
* @param url 请求地址
|
||||
* @param params 请求参数
|
||||
* @param options 请求设置(showMask-是否显示Loading层,默认为true;showError-是否显示错误信息,默认为true;throttleFlag-是否开户节流,默认为false;throttleTimeout-节流时效,默认为50毫秒)
|
||||
* @param axiosOption
|
||||
*/
|
||||
export const put = async <D>(
|
||||
url: string,
|
||||
params: ANY_OBJECT,
|
||||
options?: RequestOption,
|
||||
axiosOption?: AxiosRequestConfig,
|
||||
) => {
|
||||
return await commonRequest<D>(url, params, 'put', options, axiosOption);
|
||||
};
|
||||
/***
|
||||
* @param url 请求地址
|
||||
* @param params 请求参数
|
||||
* @param options 请求设置(showMask-是否显示Loading层,默认为true;showError-是否显示错误信息,默认为true;throttleFlag-是否开户节流,默认为false;throttleTimeout-节流时效,默认为50毫秒)
|
||||
* @param axiosOption
|
||||
*/
|
||||
export const patch = async <D>(
|
||||
url: string,
|
||||
params: ANY_OBJECT,
|
||||
options?: RequestOption,
|
||||
axiosOption?: AxiosRequestConfig,
|
||||
) => {
|
||||
return await commonRequest<D>(url, params, 'patch', options, axiosOption);
|
||||
};
|
||||
/***
|
||||
* @param url 请求地址
|
||||
* @param params 请求参数
|
||||
* @param options 请求设置(showMask-是否显示Loading层,默认为true;showError-是否显示错误信息,默认为true;throttleFlag-是否开户节流,默认为false;throttleTimeout-节流时效,默认为50毫秒)
|
||||
* @param axiosOption
|
||||
*/
|
||||
export const del = async <D>(
|
||||
url: string,
|
||||
params: ANY_OBJECT,
|
||||
options?: RequestOption,
|
||||
axiosOption?: AxiosRequestConfig,
|
||||
) => {
|
||||
return await commonRequest<D>(url, params, 'delete', options, axiosOption);
|
||||
};
|
||||
/**
|
||||
*
|
||||
* @param url 请求地址
|
||||
* @param params 请求参数
|
||||
* @param filename 文件名
|
||||
* @param options 请求设置(showMask-是否显示Loading层,默认为true;showError-是否显示错误信息,默认为true;throttleFlag-是否开户节流,默认为false;throttleTimeout-节流时效,默认为50毫秒)
|
||||
*/
|
||||
export const download = async (
|
||||
url: string,
|
||||
params: ANY_OBJECT,
|
||||
filename: string,
|
||||
method?: RequestMethods,
|
||||
options?: RequestOption,
|
||||
) => {
|
||||
// console.log(
|
||||
// 'download file url=%s, params:%s, filename:%s, options:%s',
|
||||
// url,
|
||||
// params,
|
||||
// filename,
|
||||
// options,
|
||||
// );
|
||||
return new Promise((resolve, reject) => {
|
||||
downloadBlob(url, params, method, options)
|
||||
.then(blobData => {
|
||||
const blobUrl = window.URL.createObjectURL(blobData);
|
||||
const linkDom = document.createElement('a');
|
||||
linkDom.style.display = 'none';
|
||||
linkDom.href = blobUrl;
|
||||
linkDom.setAttribute('download', filename);
|
||||
if (typeof linkDom.download === 'undefined') {
|
||||
linkDom.setAttribute('target', '_blank');
|
||||
}
|
||||
document.body.appendChild(linkDom);
|
||||
linkDom.click();
|
||||
document.body.removeChild(linkDom);
|
||||
window.URL.revokeObjectURL(blobUrl);
|
||||
resolve(true);
|
||||
})
|
||||
.catch(e => {
|
||||
reject(e);
|
||||
});
|
||||
});
|
||||
};
|
||||
/**
|
||||
* 下载文件,返回blob
|
||||
* @param {String} url 请求的url
|
||||
* @param {Object} params 请求参数
|
||||
* @param {RequestMethods} method 请求方法
|
||||
* @returns {Promise}
|
||||
*/
|
||||
export const downloadBlob = (
|
||||
url: string,
|
||||
params: ANY_OBJECT,
|
||||
method: RequestMethods = 'post',
|
||||
options?: RequestOption,
|
||||
) => {
|
||||
return new Promise<Blob>((resolve, reject) => {
|
||||
const axiosOption: AxiosRequestConfig = {
|
||||
responseType: 'blob',
|
||||
transformResponse: function (data) {
|
||||
//console.log(data);
|
||||
return data instanceof Blob && data.size > 0 ? data : undefined;
|
||||
},
|
||||
};
|
||||
commonRequest<Blob>(requestUrl(url), params, method, options, axiosOption)
|
||||
.then(res => {
|
||||
//console.log('download blob response >>>', res);
|
||||
if (res instanceof Blob) {
|
||||
const blobData = new Blob([res.data], { type: 'application/octet-stream' });
|
||||
resolve(blobData);
|
||||
} else {
|
||||
console.warn('下载文件失败', res);
|
||||
reject(new Error('下载文件失败'));
|
||||
}
|
||||
})
|
||||
.catch(e => {
|
||||
if (e instanceof Blob) {
|
||||
const reader = new FileReader();
|
||||
reader.onload = () => {
|
||||
reject(
|
||||
reader.result ? JSON.parse(reader.result.toString()).errorMessage : '下载文件失败',
|
||||
);
|
||||
};
|
||||
reader.readAsText(e);
|
||||
} else {
|
||||
reject('下载文件失败');
|
||||
}
|
||||
});
|
||||
});
|
||||
};
|
||||
/**
|
||||
* 上传
|
||||
* @param url 请求地址
|
||||
* @param params 请求参数
|
||||
* @param options 请求设置(showMask-是否显示Loading层,默认为true;showError-是否显示错误信息,默认为true;throttleFlag-是否开户节流,默认为false;throttleTimeout-节流时效,默认为50毫秒)
|
||||
*/
|
||||
export const upload = async (url: string, params: ANY_OBJECT, options?: RequestOption) => {
|
||||
//console.log('upload file url=%s, params:%s, options:%s', url, params, options);
|
||||
const axiosOption: AxiosRequestConfig = {
|
||||
headers: {
|
||||
'Content-Type': 'multipart/form-data',
|
||||
},
|
||||
transformRequest: [
|
||||
function (data) {
|
||||
const formData = new FormData();
|
||||
Object.keys(data).forEach(key => {
|
||||
formData.append(key, data[key]);
|
||||
});
|
||||
return formData;
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
const finalOption = {
|
||||
...globalConfig.requestOption,
|
||||
...options,
|
||||
};
|
||||
const { showError } = finalOption;
|
||||
return new Promise((resolve, reject) => {
|
||||
commonRequest<ANY_OBJECT>(requestUrl(url), params, 'post', options, axiosOption)
|
||||
.then(res => {
|
||||
if (res?.success) {
|
||||
resolve(res);
|
||||
} else {
|
||||
if (showError)
|
||||
showErrorMessage({
|
||||
showClose: true,
|
||||
message: res.data.errorMessage ? res.data.errorMessage : '数据请求失败',
|
||||
});
|
||||
reject('数据请求失败');
|
||||
}
|
||||
})
|
||||
.catch(e => {
|
||||
if (showError)
|
||||
showErrorMessage({
|
||||
showClose: true,
|
||||
message: e.errorMessage ? e.errorMessage : '网络请求错误',
|
||||
});
|
||||
reject(e);
|
||||
});
|
||||
});
|
||||
};
|
||||
39
OrangeFormsOpen-VUE3/src/common/http/types.d.ts
vendored
Normal file
39
OrangeFormsOpen-VUE3/src/common/http/types.d.ts
vendored
Normal file
@@ -0,0 +1,39 @@
|
||||
import { Method } from 'axios';
|
||||
import { ANY_OBJECT } from '@/types/generic';
|
||||
|
||||
export type RequestMethods = Extract<
|
||||
Method,
|
||||
'get' | 'post' | 'put' | 'delete' | 'patch' | 'option' | 'head'
|
||||
>;
|
||||
|
||||
/**
|
||||
* @param showMask 是否显示Loading层
|
||||
* @param showError 是否显示错误消息
|
||||
* @param throttleFlag 是否节流
|
||||
* @param throttleTimeout 节流限制时长
|
||||
*/
|
||||
export type RequestOption = {
|
||||
/** 是否使用Mock请求 */
|
||||
mock?: boolean;
|
||||
showMask?: boolean;
|
||||
showError?: boolean;
|
||||
throttleFlag?: boolean;
|
||||
throttleTimeout?: number;
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
[key: string]: any;
|
||||
};
|
||||
|
||||
// 定义返回数据的类型
|
||||
export type ResponseDataType<T> = {
|
||||
errorCode: string | null;
|
||||
data: T;
|
||||
errorMessage: string | null;
|
||||
success: boolean;
|
||||
};
|
||||
|
||||
export type TableData<T> = {
|
||||
dataList: T[];
|
||||
totalCount: number;
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
[key: string]: any;
|
||||
};
|
||||
5
OrangeFormsOpen-VUE3/src/common/staticDict/combined.ts
Normal file
5
OrangeFormsOpen-VUE3/src/common/staticDict/combined.ts
Normal file
@@ -0,0 +1,5 @@
|
||||
import * as baseDict from './index';
|
||||
|
||||
export default {
|
||||
...baseDict,
|
||||
};
|
||||
331
OrangeFormsOpen-VUE3/src/common/staticDict/flow.ts
Normal file
331
OrangeFormsOpen-VUE3/src/common/staticDict/flow.ts
Normal file
@@ -0,0 +1,331 @@
|
||||
/**
|
||||
* 流程表单常量字典
|
||||
*/
|
||||
import { DictionaryBase } from './types';
|
||||
|
||||
const SysFlowEntryBindFormType = new DictionaryBase('流程绑定表单类型', [
|
||||
{
|
||||
id: 0,
|
||||
name: '动态表单',
|
||||
symbol: 'ONLINE_FORM',
|
||||
},
|
||||
{
|
||||
id: 1,
|
||||
name: '路由表单',
|
||||
symbol: 'ROUTER_FORM',
|
||||
},
|
||||
]);
|
||||
|
||||
const SysFlowEntryPublishedStatus = new DictionaryBase('流程设计发布状态', [
|
||||
{
|
||||
id: 0,
|
||||
name: '未发布',
|
||||
symbol: 'UNPUBLISHED',
|
||||
},
|
||||
{
|
||||
id: 1,
|
||||
name: '已发布',
|
||||
symbol: 'PUBLISHED',
|
||||
},
|
||||
]);
|
||||
|
||||
const SysFlowEntryStep = new DictionaryBase('流程设计步骤', [
|
||||
{
|
||||
id: 0,
|
||||
name: '编辑基础信息',
|
||||
symbol: 'BASIC',
|
||||
},
|
||||
{
|
||||
id: 1,
|
||||
name: '流程变量设置',
|
||||
symbol: 'PROCESS_VARIABLE',
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
name: '设计流程',
|
||||
symbol: 'PROCESS_DESIGN',
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
name: '流程状态设置',
|
||||
symbol: 'PROCESS_STATUS',
|
||||
},
|
||||
]);
|
||||
|
||||
const SysFlowTaskOperationType = new DictionaryBase('任务操作类型', [
|
||||
{
|
||||
id: 'agree',
|
||||
name: '同意',
|
||||
symbol: 'AGREE',
|
||||
},
|
||||
{
|
||||
id: 'refuse',
|
||||
name: '拒绝',
|
||||
symbol: 'REFUSE',
|
||||
},
|
||||
{
|
||||
id: 'reject',
|
||||
name: '驳回',
|
||||
symbol: 'REJECT',
|
||||
},
|
||||
{
|
||||
id: 'rejectToStart',
|
||||
name: '驳回到起点',
|
||||
symbol: 'REJECT_TO_START',
|
||||
},
|
||||
{
|
||||
id: 'revoke',
|
||||
name: '撤销',
|
||||
symbol: 'REVOKE',
|
||||
},
|
||||
{
|
||||
id: 'transfer',
|
||||
name: '转办',
|
||||
symbol: 'TRANSFER',
|
||||
},
|
||||
{
|
||||
id: 'multi_consign',
|
||||
name: '加签',
|
||||
symbol: 'CO_SIGN',
|
||||
},
|
||||
{
|
||||
id: 'multi_minus_sign',
|
||||
name: '减签',
|
||||
symbol: 'SIGN_REDUCTION',
|
||||
},
|
||||
{
|
||||
id: 'save',
|
||||
name: '保存',
|
||||
symbol: 'SAVE',
|
||||
},
|
||||
{
|
||||
id: 'stop',
|
||||
name: '终止',
|
||||
symbol: 'STOP',
|
||||
},
|
||||
{
|
||||
id: 'multi_sign',
|
||||
name: '会签',
|
||||
symbol: 'MULTI_SIGN',
|
||||
},
|
||||
{
|
||||
id: 'multi_agree',
|
||||
name: '同意(会签)',
|
||||
symbol: 'MULTI_AGREE',
|
||||
},
|
||||
{
|
||||
id: 'multi_refuse',
|
||||
name: '拒绝(会签)',
|
||||
symbol: 'MULTI_REFUSE',
|
||||
},
|
||||
{
|
||||
id: 'multi_abstain',
|
||||
name: '弃权(会签)',
|
||||
symbol: 'MULTI_ABSTAIN',
|
||||
},
|
||||
{
|
||||
id: 'set_assignee',
|
||||
name: '指定审批人',
|
||||
symbol: 'SET_ASSIGNEE',
|
||||
},
|
||||
]);
|
||||
|
||||
const SysFlowTaskType = new DictionaryBase('工作流任务类型', [
|
||||
{
|
||||
id: 0,
|
||||
name: '其他任务',
|
||||
symbol: 'OTHER_TASK',
|
||||
},
|
||||
{
|
||||
id: 1,
|
||||
name: '用户任务',
|
||||
symbol: 'USER_TASK',
|
||||
},
|
||||
]);
|
||||
|
||||
const SysFlowVariableType = new DictionaryBase('工作流变量类型', [
|
||||
{
|
||||
id: 0,
|
||||
name: '流程变量',
|
||||
symbol: 'INSTANCE',
|
||||
},
|
||||
{
|
||||
id: 1,
|
||||
name: '任务变量',
|
||||
symbol: 'TASK',
|
||||
},
|
||||
]);
|
||||
|
||||
const SysFlowWorkOrderStatus = new DictionaryBase('工单状态', [
|
||||
{
|
||||
id: 0,
|
||||
name: '已提交',
|
||||
symbol: 'SUBMITED',
|
||||
},
|
||||
{
|
||||
id: 1,
|
||||
name: '审批中',
|
||||
symbol: 'APPROVING',
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
name: '已拒绝',
|
||||
symbol: 'REFUSED',
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
name: '已完成',
|
||||
symbol: 'FINISHED',
|
||||
},
|
||||
{
|
||||
id: 4,
|
||||
name: '终止',
|
||||
symbol: 'STOPPED',
|
||||
},
|
||||
{
|
||||
id: 5,
|
||||
name: '撤销',
|
||||
symbol: 'CANCEL',
|
||||
},
|
||||
{
|
||||
id: 6,
|
||||
name: '草稿',
|
||||
symbol: 'DRAFT',
|
||||
},
|
||||
]);
|
||||
|
||||
const SysFlowCopyForType = new DictionaryBase('抄送类型', [
|
||||
{
|
||||
id: 'user',
|
||||
name: '抄送人',
|
||||
symbol: 'USER',
|
||||
},
|
||||
{
|
||||
id: 'dept',
|
||||
name: '抄送部门',
|
||||
symbol: 'DEPT',
|
||||
},
|
||||
{
|
||||
id: 'role',
|
||||
name: '抄送角色',
|
||||
symbol: 'ROLE',
|
||||
},
|
||||
{
|
||||
id: 'deptPostLeader',
|
||||
name: '审批人部门领导',
|
||||
symbol: 'SELF_DEPT_LEADER',
|
||||
},
|
||||
{
|
||||
id: 'upDeptPostLeader',
|
||||
name: '审批人上级部门领导',
|
||||
symbol: 'UP_DEPT_LEADER',
|
||||
},
|
||||
{
|
||||
id: 'allDeptPost',
|
||||
name: '抄送岗位',
|
||||
symbol: 'POST',
|
||||
},
|
||||
{
|
||||
id: 'selfDeptPost',
|
||||
name: '审批人部门岗位',
|
||||
symbol: 'SELF_DEPT_POST',
|
||||
},
|
||||
{
|
||||
id: 'siblingDeptPost',
|
||||
name: '审批人同级部门岗位',
|
||||
symbol: 'SLIBING_DEPT_POST',
|
||||
},
|
||||
{
|
||||
id: 'upDeptPost',
|
||||
name: '审批人上级部门岗位',
|
||||
symbol: 'UP_DEPT_POST',
|
||||
},
|
||||
{
|
||||
id: 'deptPost',
|
||||
name: '指定部门岗位',
|
||||
symbol: 'DEPT_POST',
|
||||
},
|
||||
]);
|
||||
|
||||
const FlowNodeType = new DictionaryBase('钉钉节点类型', [
|
||||
{
|
||||
id: 0,
|
||||
name: '发起人',
|
||||
symbol: 'ORIGINATOR',
|
||||
},
|
||||
{
|
||||
id: 1,
|
||||
name: '审批人',
|
||||
symbol: 'APPROVED_BY',
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
name: '抄送人',
|
||||
symbol: 'CC_TO',
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
name: '连接线',
|
||||
symbol: 'CONNECTING_LINE',
|
||||
},
|
||||
{
|
||||
id: 4,
|
||||
name: '条件分支',
|
||||
symbol: 'CONDITIONAL_BRANCH',
|
||||
},
|
||||
{
|
||||
id: 5,
|
||||
name: '并行分支',
|
||||
symbol: 'PARALLEL_BRANCH',
|
||||
},
|
||||
]);
|
||||
|
||||
const DiagramType = new DictionaryBase('', [
|
||||
{
|
||||
id: 0,
|
||||
name: '普通流程图',
|
||||
symbol: 'ORDINARY',
|
||||
},
|
||||
{
|
||||
id: 1,
|
||||
name: '钉钉风格流程图',
|
||||
symbol: 'DINGDING',
|
||||
},
|
||||
]);
|
||||
|
||||
const SysAutoCodeType = new DictionaryBase('自动编码类型', [
|
||||
{
|
||||
id: 'DAYS',
|
||||
name: '精确到日',
|
||||
symbol: 'DAYS',
|
||||
},
|
||||
{
|
||||
id: 'HOURS',
|
||||
name: '精确到时',
|
||||
symbol: 'HOURS',
|
||||
},
|
||||
{
|
||||
id: 'MINUTES',
|
||||
name: '精确到分',
|
||||
symbol: 'MINUTES',
|
||||
},
|
||||
{
|
||||
id: 'SECONDS',
|
||||
name: '精确到秒',
|
||||
symbol: 'SECONDS',
|
||||
},
|
||||
]);
|
||||
|
||||
export {
|
||||
SysFlowEntryPublishedStatus,
|
||||
SysFlowEntryBindFormType,
|
||||
SysFlowEntryStep,
|
||||
SysFlowTaskOperationType,
|
||||
SysFlowTaskType,
|
||||
SysFlowVariableType,
|
||||
SysFlowWorkOrderStatus,
|
||||
SysFlowCopyForType,
|
||||
DiagramType,
|
||||
FlowNodeType,
|
||||
SysAutoCodeType,
|
||||
};
|
||||
946
OrangeFormsOpen-VUE3/src/common/staticDict/index.ts
Normal file
946
OrangeFormsOpen-VUE3/src/common/staticDict/index.ts
Normal file
@@ -0,0 +1,946 @@
|
||||
import { DictionaryBase } from './types';
|
||||
|
||||
const SysUserStatus = new DictionaryBase('用户状态', [
|
||||
{
|
||||
id: 0,
|
||||
name: '正常状态',
|
||||
symbol: 'NORMAL',
|
||||
},
|
||||
{
|
||||
id: 1,
|
||||
name: '锁定状态',
|
||||
symbol: 'LOCKED',
|
||||
},
|
||||
]);
|
||||
|
||||
const SysUserType = new DictionaryBase('用户类型', [
|
||||
{
|
||||
id: 0,
|
||||
name: '管理员',
|
||||
symbol: 'ADMIN',
|
||||
},
|
||||
{
|
||||
id: 1,
|
||||
name: '系统操作员',
|
||||
symbol: 'SYSTEM',
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
name: '普通操作员',
|
||||
symbol: 'OPERATOR',
|
||||
},
|
||||
]);
|
||||
|
||||
const SysOperationType = new DictionaryBase('操作日志操作类型', [
|
||||
{
|
||||
id: 0,
|
||||
name: '登录',
|
||||
symbol: 'LOGIN',
|
||||
},
|
||||
{
|
||||
id: 1,
|
||||
name: '手机登录',
|
||||
symbol: 'MOBILE_LOGIN',
|
||||
},
|
||||
{
|
||||
id: 5,
|
||||
name: '登出',
|
||||
symbol: 'LOGOUT',
|
||||
},
|
||||
{
|
||||
id: 10,
|
||||
name: '新增',
|
||||
symbol: 'ADD',
|
||||
},
|
||||
{
|
||||
id: 15,
|
||||
name: '修改',
|
||||
symbol: 'UPDATE',
|
||||
},
|
||||
{
|
||||
id: 20,
|
||||
name: '删除',
|
||||
symbol: 'DELETE',
|
||||
},
|
||||
{
|
||||
id: 35,
|
||||
name: '查询',
|
||||
symbol: 'LIST',
|
||||
},
|
||||
{
|
||||
id: 40,
|
||||
name: '分组查询',
|
||||
symbol: 'LIST_WITH_GROUP',
|
||||
},
|
||||
{
|
||||
id: 45,
|
||||
name: '导出',
|
||||
symbol: 'EXPORT',
|
||||
},
|
||||
{
|
||||
id: 25,
|
||||
name: '新增多对多关联',
|
||||
symbol: 'ADD_M2M',
|
||||
},
|
||||
{
|
||||
id: 30,
|
||||
name: '移除多对多关联',
|
||||
symbol: 'DELETE_M2M',
|
||||
},
|
||||
{
|
||||
id: 50,
|
||||
name: '上传',
|
||||
symbol: 'UPLOAD',
|
||||
},
|
||||
{
|
||||
id: 55,
|
||||
name: '下载',
|
||||
symbol: 'DOWNLOAD',
|
||||
},
|
||||
{
|
||||
id: 60,
|
||||
name: '重置缓存',
|
||||
symbol: 'RELOAD_CACHE',
|
||||
},
|
||||
{
|
||||
id: 65,
|
||||
name: '发布',
|
||||
symbol: 'PUBLISH',
|
||||
},
|
||||
{
|
||||
id: 70,
|
||||
name: '取消发布',
|
||||
symbol: 'UNPUBLISH',
|
||||
},
|
||||
{
|
||||
id: 75,
|
||||
name: '流程挂起',
|
||||
symbol: 'SUSPEND',
|
||||
},
|
||||
{
|
||||
id: 80,
|
||||
name: '流程恢复',
|
||||
symbol: 'RESUME',
|
||||
},
|
||||
{
|
||||
id: 100,
|
||||
name: '启动流程',
|
||||
symbol: 'START_FLOW',
|
||||
},
|
||||
{
|
||||
id: 105,
|
||||
name: '终止流程',
|
||||
symbol: 'STOP_FLOW',
|
||||
},
|
||||
{
|
||||
id: 110,
|
||||
name: '删除流程',
|
||||
symbol: 'DELETE_FLOW',
|
||||
},
|
||||
{
|
||||
id: 115,
|
||||
name: '撤销流程',
|
||||
symbol: 'CANCEL_FLOW',
|
||||
},
|
||||
{
|
||||
id: 120,
|
||||
name: '提交流程任务',
|
||||
symbol: 'SUBMIT_TASK',
|
||||
},
|
||||
{
|
||||
id: 125,
|
||||
name: '催办流程',
|
||||
symbol: 'REMIND_TASK',
|
||||
},
|
||||
{
|
||||
id: 126,
|
||||
name: '流程干预',
|
||||
symbol: 'INTERVENE_FLOW',
|
||||
},
|
||||
{
|
||||
id: 127,
|
||||
name: '流程数据补偿',
|
||||
symbol: 'FIX_FLOW_BUSINESS_DATA',
|
||||
},
|
||||
]);
|
||||
|
||||
const SysPermModuleType = new DictionaryBase('权限分组类型', [
|
||||
{
|
||||
id: 0,
|
||||
name: '分组模块',
|
||||
symbol: 'GROUP',
|
||||
},
|
||||
{
|
||||
id: 1,
|
||||
name: '接口模块',
|
||||
symbol: 'CONTROLLER',
|
||||
},
|
||||
]);
|
||||
|
||||
const SysPermCodeType = new DictionaryBase('权限字类型', [
|
||||
{
|
||||
id: 0,
|
||||
name: '表单',
|
||||
symbol: 'FORM',
|
||||
},
|
||||
{
|
||||
id: 1,
|
||||
name: '片段',
|
||||
symbol: 'FRAGMENT',
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
name: '操作',
|
||||
symbol: 'OPERATION',
|
||||
},
|
||||
]);
|
||||
|
||||
/**
|
||||
* 菜单类型
|
||||
*
|
||||
* DIRECTORY(0: 目录)
|
||||
* MENU(1: 表单)
|
||||
* FRAGMENT(2: 片段)
|
||||
* BUTTON(3: 按钮)
|
||||
*/
|
||||
const SysMenuType = new DictionaryBase('菜单类型', [
|
||||
{
|
||||
id: 0,
|
||||
name: '目录',
|
||||
symbol: 'DIRECTORY',
|
||||
},
|
||||
{
|
||||
id: 1,
|
||||
name: '表单',
|
||||
symbol: 'MENU',
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
name: '片段',
|
||||
symbol: 'FRAGMENT',
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
name: '按钮',
|
||||
symbol: 'BUTTON',
|
||||
},
|
||||
]);
|
||||
|
||||
const MobileEntryType = new DictionaryBase('移动端首页配置项类型', [
|
||||
{
|
||||
id: 0,
|
||||
name: '轮播图',
|
||||
symbol: 'BANNER',
|
||||
},
|
||||
{
|
||||
id: 1,
|
||||
name: '九宫格',
|
||||
symbol: 'SUDOKU',
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
name: '分组',
|
||||
symbol: 'GROUP',
|
||||
},
|
||||
]);
|
||||
|
||||
/**
|
||||
* 菜单绑定类型
|
||||
*
|
||||
* ROUTER(0: 路由菜单)
|
||||
* ONLINE_FORM(1: 在线表单)
|
||||
* WORK_ORDER(2: 工单列表)
|
||||
* REPORT(3: 报表页面)
|
||||
* THRID_URL(4: 外部链接)
|
||||
*/
|
||||
const SysMenuBindType = new DictionaryBase('菜单绑定类型', [
|
||||
{
|
||||
id: 0,
|
||||
name: '路由菜单',
|
||||
symbol: 'ROUTER',
|
||||
},
|
||||
{
|
||||
id: 1,
|
||||
name: '在线表单',
|
||||
symbol: 'ONLINE_FORM',
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
name: '工单列表',
|
||||
symbol: 'WORK_ORDER',
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
name: '报表页面',
|
||||
symbol: 'REPORT',
|
||||
},
|
||||
{
|
||||
id: 4,
|
||||
name: '外部链接',
|
||||
symbol: 'THRID_URL',
|
||||
},
|
||||
]);
|
||||
|
||||
const SysDataPermType = new DictionaryBase('数据权限类型', [
|
||||
{
|
||||
id: 0,
|
||||
name: '查看全部',
|
||||
symbol: 'ALL',
|
||||
},
|
||||
{
|
||||
id: 1,
|
||||
name: '仅看自己',
|
||||
symbol: 'ONLY_USER',
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
name: '仅看所在部门',
|
||||
symbol: 'ONLY_DEPT',
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
name: '仅看所在部门及子部门',
|
||||
symbol: 'ONLY_DEPT_AND_CHILD',
|
||||
},
|
||||
{
|
||||
id: 4,
|
||||
name: '自选部门及子部门',
|
||||
symbol: 'CUSTOM_DEPT_AND_CHILD',
|
||||
},
|
||||
{
|
||||
id: 5,
|
||||
name: '仅自选部门',
|
||||
symbol: 'CUSTOM_DEPT',
|
||||
},
|
||||
{
|
||||
id: 6,
|
||||
name: '本部门用户',
|
||||
symbol: 'DEPT_USER',
|
||||
},
|
||||
{
|
||||
id: 7,
|
||||
name: '本部门及子部门用户',
|
||||
symbol: 'DEPT_AND_CHILD_USER',
|
||||
},
|
||||
]);
|
||||
|
||||
const ScatterSymbolType = new DictionaryBase('纵轴位置', [
|
||||
{
|
||||
id: 0,
|
||||
name: '固定大小',
|
||||
symbol: 'FIXED',
|
||||
},
|
||||
{
|
||||
id: 1,
|
||||
name: '值大小',
|
||||
symbol: 'VALUE',
|
||||
},
|
||||
]);
|
||||
|
||||
const SysCustomWidgetType = new DictionaryBase('组件类型', [
|
||||
{
|
||||
id: 0,
|
||||
name: '文本显示',
|
||||
symbol: 'Label',
|
||||
},
|
||||
{
|
||||
id: 1,
|
||||
name: '文本输入框',
|
||||
symbol: 'Input',
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
name: '数字输入框',
|
||||
symbol: 'NumberInput',
|
||||
},
|
||||
{
|
||||
id: 4,
|
||||
name: '数字范围输入框',
|
||||
symbol: 'NumberRange',
|
||||
},
|
||||
{
|
||||
id: 5,
|
||||
name: '开关组件',
|
||||
symbol: 'Switch',
|
||||
},
|
||||
{
|
||||
id: 6,
|
||||
name: '滑块组件',
|
||||
symbol: 'Slider',
|
||||
},
|
||||
{
|
||||
id: 7,
|
||||
name: '单选组件',
|
||||
symbol: 'Radio',
|
||||
},
|
||||
{
|
||||
id: 8,
|
||||
name: '复选框',
|
||||
symbol: 'CheckBox',
|
||||
},
|
||||
{
|
||||
id: 10,
|
||||
name: '下拉选择框',
|
||||
symbol: 'Select',
|
||||
},
|
||||
{
|
||||
id: 12,
|
||||
name: '级联选择框',
|
||||
symbol: 'Cascader',
|
||||
},
|
||||
{
|
||||
id: 13,
|
||||
name: '树形选择组件',
|
||||
symbol: 'Tree',
|
||||
},
|
||||
{
|
||||
id: 14,
|
||||
name: '评分组件',
|
||||
symbol: 'Rate',
|
||||
},
|
||||
{
|
||||
id: 15,
|
||||
name: '进步器',
|
||||
symbol: 'Stepper',
|
||||
},
|
||||
{
|
||||
id: 16,
|
||||
name: '日历组件',
|
||||
symbol: 'Calendar',
|
||||
},
|
||||
{
|
||||
id: 20,
|
||||
name: '日期选择框',
|
||||
symbol: 'Date',
|
||||
},
|
||||
{
|
||||
id: 21,
|
||||
name: '日期范围选择框',
|
||||
symbol: 'DateRange',
|
||||
},
|
||||
{
|
||||
id: 30,
|
||||
name: '颜色选择框',
|
||||
symbol: 'ColorPicker',
|
||||
},
|
||||
{
|
||||
id: 31,
|
||||
name: '上传组件',
|
||||
symbol: 'Upload',
|
||||
},
|
||||
{
|
||||
id: 32,
|
||||
name: '富文本编辑',
|
||||
symbol: 'RichEditor',
|
||||
},
|
||||
{
|
||||
id: 40,
|
||||
name: '分割线',
|
||||
symbol: 'Divider',
|
||||
},
|
||||
{
|
||||
id: 41,
|
||||
name: '文本',
|
||||
symbol: 'Text',
|
||||
},
|
||||
{
|
||||
id: 42,
|
||||
name: '图片',
|
||||
symbol: 'Image',
|
||||
},
|
||||
{
|
||||
id: 43,
|
||||
name: '超链接',
|
||||
symbol: 'Link',
|
||||
},
|
||||
{
|
||||
id: 100,
|
||||
name: '表格组件',
|
||||
symbol: 'Table',
|
||||
},
|
||||
{
|
||||
id: 101,
|
||||
name: '透视表',
|
||||
symbol: 'PivotTable',
|
||||
},
|
||||
{
|
||||
id: 102,
|
||||
name: '数据列表',
|
||||
symbol: 'List',
|
||||
},
|
||||
{
|
||||
id: 103,
|
||||
name: '查询列表',
|
||||
symbol: 'QueryList',
|
||||
},
|
||||
{
|
||||
id: 104,
|
||||
name: '工单列表',
|
||||
symbol: 'WorkOrderList',
|
||||
},
|
||||
{
|
||||
id: 200,
|
||||
name: '折线图',
|
||||
symbol: 'LineChart',
|
||||
},
|
||||
{
|
||||
id: 201,
|
||||
name: '柱状图',
|
||||
symbol: 'BarChart',
|
||||
},
|
||||
{
|
||||
id: 202,
|
||||
name: '饼图',
|
||||
symbol: 'PieChart',
|
||||
},
|
||||
{
|
||||
id: 203,
|
||||
name: '散点图',
|
||||
symbol: 'ScatterChart',
|
||||
},
|
||||
{
|
||||
id: 204,
|
||||
name: '普通表格',
|
||||
symbol: 'DataViewTable',
|
||||
},
|
||||
{
|
||||
id: 205,
|
||||
name: '轮播图',
|
||||
symbol: 'Carousel',
|
||||
},
|
||||
{
|
||||
id: 206,
|
||||
name: '富文本',
|
||||
symbol: 'RichText',
|
||||
},
|
||||
{
|
||||
id: 207,
|
||||
name: '仪表盘',
|
||||
symbol: 'GaugeChart',
|
||||
},
|
||||
{
|
||||
id: 208,
|
||||
name: '漏斗图',
|
||||
symbol: 'FunnelChart',
|
||||
},
|
||||
{
|
||||
id: 209,
|
||||
name: '雷达图',
|
||||
symbol: 'RadarChart',
|
||||
},
|
||||
{
|
||||
id: 210,
|
||||
name: '普通进度条',
|
||||
symbol: 'ProgressBar',
|
||||
},
|
||||
{
|
||||
id: 211,
|
||||
name: '环形进度条',
|
||||
symbol: 'ProgressCircle',
|
||||
},
|
||||
{
|
||||
id: 212,
|
||||
name: '通用卡片',
|
||||
symbol: 'DataCard',
|
||||
},
|
||||
{
|
||||
id: 213,
|
||||
name: '通用列表',
|
||||
symbol: 'CommonList',
|
||||
},
|
||||
{
|
||||
id: 214,
|
||||
name: '进度条卡片',
|
||||
symbol: 'DataProgressCard',
|
||||
},
|
||||
{
|
||||
id: 300,
|
||||
name: '基础块',
|
||||
symbol: 'Block',
|
||||
},
|
||||
{
|
||||
id: 301,
|
||||
name: '卡片组件',
|
||||
symbol: 'Card',
|
||||
},
|
||||
{
|
||||
id: 302,
|
||||
name: 'Tabs 组件',
|
||||
symbol: 'Tabs',
|
||||
},
|
||||
{
|
||||
id: 303,
|
||||
name: '图片卡片',
|
||||
symbol: 'ImageCard',
|
||||
},
|
||||
{
|
||||
id: 304,
|
||||
name: '分组容器',
|
||||
symbol: 'CellGroup',
|
||||
},
|
||||
{
|
||||
id: 400,
|
||||
name: '用户选择',
|
||||
symbol: 'UserSelect',
|
||||
},
|
||||
{
|
||||
id: 401,
|
||||
name: '部门选择',
|
||||
symbol: 'DeptSelect',
|
||||
},
|
||||
{
|
||||
id: 402,
|
||||
name: '关联选择',
|
||||
symbol: 'DataSelect',
|
||||
},
|
||||
{
|
||||
id: 403,
|
||||
name: '表格容器',
|
||||
symbol: 'TableContainer',
|
||||
},
|
||||
{
|
||||
id: 500,
|
||||
name: '单选过滤',
|
||||
symbol: 'MobileRadioFilter',
|
||||
},
|
||||
{
|
||||
id: 501,
|
||||
name: '多选过滤',
|
||||
symbol: 'MobileCheckBoxFilter',
|
||||
},
|
||||
{
|
||||
id: 502,
|
||||
name: '文本过滤',
|
||||
symbol: 'MobileInputFilter',
|
||||
},
|
||||
{
|
||||
id: 503,
|
||||
name: '开关过滤',
|
||||
symbol: 'MobileSwitchFilter',
|
||||
},
|
||||
{
|
||||
id: 504,
|
||||
name: '日期过滤',
|
||||
symbol: 'MobileDateRangeFilter',
|
||||
},
|
||||
{
|
||||
id: 505,
|
||||
name: '数字范围过滤',
|
||||
symbol: 'MobileNumberRangeFilter',
|
||||
},
|
||||
]);
|
||||
|
||||
const OnlineFormEventType = new DictionaryBase('在线表单事件类型', [
|
||||
{
|
||||
id: 'change',
|
||||
name: '数据改变',
|
||||
symbol: 'CHANGE',
|
||||
},
|
||||
{
|
||||
id: 'disable',
|
||||
name: '是否禁用',
|
||||
symbol: 'DISABLE',
|
||||
},
|
||||
{
|
||||
id: 'visible',
|
||||
name: '是否可见',
|
||||
symbol: 'VISIBLE',
|
||||
},
|
||||
{
|
||||
id: 'dropdownChange',
|
||||
name: '下拉数据改变',
|
||||
symbol: 'DROPDOWN_CHANGE',
|
||||
},
|
||||
{
|
||||
id: 'linkHerf',
|
||||
name: '链接地址',
|
||||
symbol: 'LINK_HERF',
|
||||
},
|
||||
{
|
||||
id: 'disabledDate',
|
||||
name: '日期是否可用',
|
||||
symbol: 'DISABLED_DATE',
|
||||
},
|
||||
{
|
||||
id: 'afterLoadTableData',
|
||||
name: '表格加载数据后',
|
||||
symbol: 'AFTER_LOAD_TABLE_DATA',
|
||||
},
|
||||
{
|
||||
id: 'beforeLoadTableData',
|
||||
name: '表格加载数据前',
|
||||
symbol: 'BEFORE_LOAD_TABLE_DATA',
|
||||
},
|
||||
{
|
||||
id: 'afterLoadFormData',
|
||||
name: '页面加载数据后',
|
||||
symbol: 'AFTER_LOAD_FORM_DATA',
|
||||
},
|
||||
{
|
||||
id: 'beforeLoadFormData',
|
||||
name: '页面加载数据前',
|
||||
symbol: 'BEFORE_LOAD_FORM_DATA',
|
||||
},
|
||||
{
|
||||
id: 'beforeCommitFormData',
|
||||
name: '页面数据提交前',
|
||||
symbol: 'BEFORE_COMMIT_FORM_DATA',
|
||||
},
|
||||
{
|
||||
id: 'formCreated',
|
||||
name: '页面创建完毕',
|
||||
symbol: 'AFTER_CREATE_FORM',
|
||||
},
|
||||
{
|
||||
id: 'tableOperationVisible',
|
||||
name: '操作是否可见',
|
||||
symbol: 'OPERATION_VISIBLE',
|
||||
},
|
||||
{
|
||||
id: 'tableOperationDisbled',
|
||||
name: '操作是否禁用',
|
||||
symbol: 'OPERATION_DISABLED',
|
||||
},
|
||||
]);
|
||||
|
||||
/**
|
||||
* 表单类型
|
||||
*
|
||||
* QUERY(1: 查询表单)
|
||||
* ADVANCE_QUERY(2: 左树右表查询)
|
||||
* ONE_TO_ONE_QUERY(3: 一对一查询)
|
||||
* FORM(5: 编辑表单)
|
||||
* FLOW(10: 流程表单)
|
||||
* WORK_ORDER(11: 工单列表)
|
||||
* REPORT(50: 报表页面)
|
||||
*/
|
||||
const SysOnlineFormType = new DictionaryBase('表单类型', [
|
||||
{
|
||||
id: 1,
|
||||
name: '查询表单',
|
||||
symbol: 'QUERY',
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
name: '左树右表查询',
|
||||
symbol: 'ADVANCE_QUERY',
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
name: '一对一查询',
|
||||
symbol: 'ONE_TO_ONE_QUERY',
|
||||
},
|
||||
{
|
||||
id: 5,
|
||||
name: '编辑表单',
|
||||
symbol: 'FORM',
|
||||
},
|
||||
{
|
||||
id: 10,
|
||||
name: '流程表单',
|
||||
symbol: 'FLOW',
|
||||
},
|
||||
{
|
||||
id: 11,
|
||||
name: '工单列表',
|
||||
symbol: 'WORK_ORDER',
|
||||
},
|
||||
{
|
||||
id: 50,
|
||||
name: '报表页面',
|
||||
symbol: 'REPORT',
|
||||
},
|
||||
]);
|
||||
|
||||
const SysCustomWidgetOperationType = new DictionaryBase('操作类型', [
|
||||
{
|
||||
id: 0,
|
||||
name: '新建',
|
||||
symbol: 'ADD',
|
||||
},
|
||||
{
|
||||
id: 1,
|
||||
name: '编辑',
|
||||
symbol: 'EDIT',
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
name: '删除',
|
||||
symbol: 'DELETE',
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
name: '导出',
|
||||
symbol: 'EXPORT',
|
||||
},
|
||||
{
|
||||
id: 10,
|
||||
name: '批量删除',
|
||||
symbol: 'BATCH_DELETE',
|
||||
},
|
||||
{
|
||||
id: 20,
|
||||
name: '表单操作',
|
||||
symbol: 'FORM',
|
||||
},
|
||||
{
|
||||
id: 22,
|
||||
name: '复制',
|
||||
symbol: 'COPY',
|
||||
},
|
||||
{
|
||||
id: 30,
|
||||
name: '保存',
|
||||
symbol: 'SAVE',
|
||||
},
|
||||
{
|
||||
id: 31,
|
||||
name: '取消',
|
||||
symbol: 'CANCEL',
|
||||
},
|
||||
{
|
||||
id: 50,
|
||||
name: '脚本操作',
|
||||
symbol: 'SCRIPT',
|
||||
},
|
||||
{
|
||||
id: 51,
|
||||
name: '下钻事件',
|
||||
symbol: 'DRILL',
|
||||
},
|
||||
{
|
||||
id: 52,
|
||||
name: '路由跳转',
|
||||
symbol: 'ROUTE',
|
||||
},
|
||||
]);
|
||||
|
||||
const OnlineSystemVariableType = new DictionaryBase('系统变量类型', [
|
||||
{
|
||||
id: 0,
|
||||
name: '登录用户',
|
||||
symbol: 'CURRENT_USER',
|
||||
},
|
||||
{
|
||||
id: 1,
|
||||
name: '所属部门',
|
||||
symbol: 'CURRENT_DEPT',
|
||||
},
|
||||
{
|
||||
id: 10,
|
||||
name: '当前日期',
|
||||
symbol: 'CURRENT_DATE',
|
||||
},
|
||||
{
|
||||
id: 11,
|
||||
name: '当前时间',
|
||||
symbol: 'CURRENT_TIME',
|
||||
},
|
||||
{
|
||||
id: 20,
|
||||
name: '流程发起人',
|
||||
symbol: 'FLOW_CREATE_USER',
|
||||
},
|
||||
]);
|
||||
|
||||
const SysCustomWidgetBindDataType = new DictionaryBase('组件绑定数据类型', [
|
||||
{
|
||||
id: 0,
|
||||
name: '字段',
|
||||
symbol: 'Column',
|
||||
},
|
||||
{
|
||||
id: 5,
|
||||
name: '系统变量',
|
||||
symbol: 'SYSTEM_VARIABLE',
|
||||
},
|
||||
{
|
||||
id: 10,
|
||||
name: '自定义字段',
|
||||
symbol: 'Custom',
|
||||
},
|
||||
{
|
||||
id: 20,
|
||||
name: '固定值',
|
||||
symbol: 'Fixed',
|
||||
},
|
||||
]);
|
||||
|
||||
const DirectionType = new DictionaryBase('方向', [
|
||||
{
|
||||
id: 0,
|
||||
name: '横轴',
|
||||
symbol: 'HORIZONTAL',
|
||||
},
|
||||
{
|
||||
id: 1,
|
||||
name: '纵轴',
|
||||
symbol: 'VERTICAL',
|
||||
},
|
||||
]);
|
||||
|
||||
const DblinkType = new DictionaryBase('数据库连接类型', [
|
||||
{
|
||||
id: 0,
|
||||
name: 'MySQL',
|
||||
symbol: 'MYSQL',
|
||||
},
|
||||
/*
|
||||
{
|
||||
id: 1,
|
||||
name: 'PostgreSQL',
|
||||
symbol: 'POSTGRESQL',
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
name: 'Oracle',
|
||||
symbol: 'ORACLE',
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
name: '达梦数据库',
|
||||
symbol: 'DM_DB',
|
||||
},
|
||||
{
|
||||
id: 4,
|
||||
name: '人大金仓',
|
||||
symbol: 'KINGBASE',
|
||||
},
|
||||
{
|
||||
id: 5,
|
||||
name: '华为高斯',
|
||||
symbol: 'OPENGAUSS',
|
||||
},
|
||||
{
|
||||
id: 10,
|
||||
name: 'ClickHouse',
|
||||
symbol: 'CLICK_HOUSE',
|
||||
},
|
||||
{
|
||||
id: 11,
|
||||
name: 'Doris',
|
||||
symbol: 'DORIS',
|
||||
},
|
||||
*/
|
||||
]);
|
||||
|
||||
export {
|
||||
SysUserStatus,
|
||||
SysUserType,
|
||||
SysDataPermType,
|
||||
SysOperationType,
|
||||
SysPermModuleType,
|
||||
SysPermCodeType,
|
||||
SysMenuBindType,
|
||||
MobileEntryType,
|
||||
SysMenuType,
|
||||
ScatterSymbolType,
|
||||
SysCustomWidgetType,
|
||||
OnlineFormEventType,
|
||||
SysOnlineFormType,
|
||||
SysCustomWidgetOperationType,
|
||||
OnlineSystemVariableType,
|
||||
SysCustomWidgetBindDataType,
|
||||
DirectionType,
|
||||
DblinkType,
|
||||
};
|
||||
411
OrangeFormsOpen-VUE3/src/common/staticDict/online.ts
Normal file
411
OrangeFormsOpen-VUE3/src/common/staticDict/online.ts
Normal file
@@ -0,0 +1,411 @@
|
||||
/**
|
||||
* 在线表单常量字典
|
||||
*/
|
||||
import { DictionaryBase } from './types';
|
||||
|
||||
const SysOnlineFieldKind = new DictionaryBase('字段类型', [
|
||||
{
|
||||
id: 1,
|
||||
name: '文件上传字段',
|
||||
symbol: 'UPLOAD',
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
name: '图片上传字段',
|
||||
symbol: 'UPLOAD_IMAGE',
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
name: '富文本字段',
|
||||
symbol: 'RICH_TEXT',
|
||||
},
|
||||
{
|
||||
id: 4,
|
||||
name: '多选字段',
|
||||
symbol: 'MULTI_SELECT',
|
||||
},
|
||||
{
|
||||
id: 19,
|
||||
name: '创建人部门',
|
||||
symbol: 'CREATE_USER_DEPT_ID',
|
||||
},
|
||||
{
|
||||
id: 20,
|
||||
name: '创建时间字段',
|
||||
symbol: 'CREATE_TIME',
|
||||
},
|
||||
{
|
||||
id: 21,
|
||||
name: '创建人字段',
|
||||
symbol: 'CREATE_USER_ID',
|
||||
},
|
||||
{
|
||||
id: 22,
|
||||
name: '更新时间字段',
|
||||
symbol: 'UPDATE_TIME',
|
||||
},
|
||||
{
|
||||
id: 23,
|
||||
name: '更新人字段',
|
||||
symbol: 'UPDATE_USER_ID',
|
||||
},
|
||||
{
|
||||
id: 25,
|
||||
name: '流程审批状态',
|
||||
symbol: 'FLOW_APPROVAL_STATUS',
|
||||
},
|
||||
{
|
||||
id: 26,
|
||||
name: '流程状态',
|
||||
symbol: 'FLOW_FINISHED_STATUS',
|
||||
},
|
||||
{
|
||||
id: 31,
|
||||
name: '逻辑删除字段',
|
||||
symbol: 'LOGIC_DELETE',
|
||||
},
|
||||
]);
|
||||
|
||||
const SysOnlineDataPermFilterType = new DictionaryBase('数据权限过滤类型', [
|
||||
{
|
||||
id: 1,
|
||||
name: '用户过滤字段',
|
||||
symbol: 'USER_FILTER',
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
name: '部门过滤字段',
|
||||
symbol: 'DEPT_FILTER',
|
||||
},
|
||||
]);
|
||||
|
||||
const SysOnlineRelationType = new DictionaryBase('关联类型', [
|
||||
{
|
||||
id: 0,
|
||||
name: '一对一关联',
|
||||
symbol: 'ONE_TO_ONE',
|
||||
},
|
||||
{
|
||||
id: 1,
|
||||
name: '一对多关联',
|
||||
symbol: 'ONE_TO_MANY',
|
||||
},
|
||||
]);
|
||||
|
||||
const SysOnlineFormKind = new DictionaryBase('表单类别', [
|
||||
{
|
||||
id: 1,
|
||||
name: '弹出窗口',
|
||||
symbol: 'DIALOG',
|
||||
},
|
||||
{
|
||||
id: 5,
|
||||
name: '跳转页面',
|
||||
symbol: 'PAGE',
|
||||
},
|
||||
]);
|
||||
|
||||
const SysOnlinePageType = new DictionaryBase('页面类型', [
|
||||
{
|
||||
id: 1,
|
||||
name: '业务页面',
|
||||
symbol: 'BIZ',
|
||||
},
|
||||
{
|
||||
id: 10,
|
||||
name: '流程页面',
|
||||
symbol: 'FLOW',
|
||||
},
|
||||
]);
|
||||
|
||||
const SysOnlinePageStatus = new DictionaryBase('页面状态', [
|
||||
{
|
||||
id: 0,
|
||||
name: '基础信息录入',
|
||||
symbol: 'BASIC',
|
||||
},
|
||||
{
|
||||
id: 1,
|
||||
name: '数据模型录入',
|
||||
symbol: 'DATASOURCE',
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
name: '表单设计',
|
||||
symbol: 'DESIGNING',
|
||||
},
|
||||
]);
|
||||
|
||||
const SysOnlineDictType = new DictionaryBase('字典类型', [
|
||||
{
|
||||
id: 1,
|
||||
name: '数据表字典',
|
||||
symbol: 'TABLE',
|
||||
},
|
||||
{
|
||||
id: 5,
|
||||
name: 'URL字典',
|
||||
symbol: 'URL',
|
||||
},
|
||||
{
|
||||
id: 10,
|
||||
name: '静态字典',
|
||||
symbol: 'STATIC',
|
||||
},
|
||||
{
|
||||
id: 20,
|
||||
name: '编码字典',
|
||||
symbol: 'CODE',
|
||||
},
|
||||
{
|
||||
id: 15,
|
||||
name: '自定义字典',
|
||||
symbol: 'CUSTOM',
|
||||
},
|
||||
]);
|
||||
|
||||
const SysOnlineRuleType = new DictionaryBase('验证规则类型', [
|
||||
{
|
||||
id: 1,
|
||||
name: '只允许整数',
|
||||
symbol: 'INTEGER_ONLY',
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
name: '只允许数字',
|
||||
symbol: 'DIGITAL_ONLY',
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
name: '只允许英文字符',
|
||||
symbol: 'LETTER_ONLY',
|
||||
},
|
||||
{
|
||||
id: 4,
|
||||
name: '范围验证',
|
||||
symbol: 'RANGE',
|
||||
},
|
||||
{
|
||||
id: 5,
|
||||
name: '邮箱格式验证',
|
||||
symbol: 'EMAIL',
|
||||
},
|
||||
{
|
||||
id: 6,
|
||||
name: '手机格式验证',
|
||||
symbol: 'MOBILE',
|
||||
},
|
||||
{
|
||||
id: 100,
|
||||
name: '自定义验证',
|
||||
symbol: 'CUSTOM',
|
||||
},
|
||||
]);
|
||||
|
||||
const SysCustomWidgetBindValueType = new DictionaryBase('组件绑定值类型', [
|
||||
{
|
||||
id: 1,
|
||||
name: '字典数据',
|
||||
symbol: 'DICT_DATA',
|
||||
},
|
||||
{
|
||||
id: 10,
|
||||
name: '系统变量',
|
||||
symbol: 'SYSTEM_VARIABLE',
|
||||
},
|
||||
{
|
||||
id: 20,
|
||||
name: '自定义',
|
||||
symbol: 'INPUT_DATA',
|
||||
},
|
||||
]);
|
||||
|
||||
const SysOnlineColumnFilterType = new DictionaryBase('过滤类型', [
|
||||
{
|
||||
id: 0,
|
||||
name: '无过滤',
|
||||
symbol: 'NONE',
|
||||
},
|
||||
{
|
||||
id: 1,
|
||||
name: '普通过滤',
|
||||
symbol: 'EQUAL_FILTER',
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
name: '范围过滤',
|
||||
symbol: 'RANFGE_FILTER',
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
name: '模糊过滤',
|
||||
symbol: 'LIKE_FILTER',
|
||||
},
|
||||
{
|
||||
id: 4,
|
||||
name: '多选过滤',
|
||||
symbol: 'MULTI_SELECT_FILTER',
|
||||
},
|
||||
]);
|
||||
|
||||
const SysOnlinePageDatasourceFieldStatus = new DictionaryBase('数据表状态', [
|
||||
{
|
||||
id: 0,
|
||||
name: '已删除',
|
||||
symbol: 'DELETED',
|
||||
},
|
||||
{
|
||||
id: 1,
|
||||
name: '已使用',
|
||||
symbol: 'USED',
|
||||
},
|
||||
{
|
||||
id: 0,
|
||||
name: '未使用',
|
||||
symbol: 'UNUSED',
|
||||
},
|
||||
]);
|
||||
|
||||
const SysOnlinePageSettingStep = new DictionaryBase('在线表单编辑步骤', [
|
||||
{
|
||||
id: 0,
|
||||
name: '编辑基础信息',
|
||||
symbol: 'BASIC',
|
||||
},
|
||||
{
|
||||
id: 1,
|
||||
name: '编辑数据模型',
|
||||
symbol: 'DATASOURCE',
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
name: '设计表单',
|
||||
symbol: 'FORM_DESIGN',
|
||||
},
|
||||
]);
|
||||
|
||||
const SysOnlineParamValueType = new DictionaryBase('参数值类型', [
|
||||
{
|
||||
id: 1,
|
||||
name: '数据字段',
|
||||
symbol: 'TABLE_COLUMN',
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
name: '静态字典',
|
||||
symbol: 'STATIC_DICT',
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
name: '直接输入',
|
||||
symbol: 'INPUT_VALUE',
|
||||
},
|
||||
]);
|
||||
|
||||
const SysOnlineAggregationType = new DictionaryBase('字段聚合类型', [
|
||||
{
|
||||
id: 0,
|
||||
name: '总数',
|
||||
symbol: 'SUM',
|
||||
},
|
||||
{
|
||||
id: 1,
|
||||
name: '个数',
|
||||
symbol: 'COUNT',
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
name: '平均数',
|
||||
symbol: 'AVG',
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
name: '最小值',
|
||||
symbol: 'MIN',
|
||||
},
|
||||
{
|
||||
id: 4,
|
||||
name: '最大值',
|
||||
symbol: 'MAX',
|
||||
},
|
||||
]);
|
||||
|
||||
const SysOnlineFilterOperationType = new DictionaryBase('过滤条件操作类型', [
|
||||
{
|
||||
id: 0,
|
||||
name: ' = ',
|
||||
symbol: 'EQUAL',
|
||||
},
|
||||
{
|
||||
id: 1,
|
||||
name: ' != ',
|
||||
symbol: 'NOT_EQUAL',
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
name: ' >= ',
|
||||
symbol: 'GREATER_THAN_OR_EQUAL',
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
name: ' > ',
|
||||
symbol: 'GREATER_THAN',
|
||||
},
|
||||
{
|
||||
id: 4,
|
||||
name: ' <= ',
|
||||
symbol: 'LESS_THAN_OR_EQUAL',
|
||||
},
|
||||
{
|
||||
id: 5,
|
||||
name: ' < ',
|
||||
symbol: 'LESS_THAN',
|
||||
},
|
||||
{
|
||||
id: 6,
|
||||
name: ' like ',
|
||||
symbol: 'LIKE',
|
||||
},
|
||||
{
|
||||
id: 7,
|
||||
name: ' not null ',
|
||||
symbol: 'NOT_NULL',
|
||||
},
|
||||
{
|
||||
id: 8,
|
||||
name: ' is null ',
|
||||
symbol: 'IS_NULL',
|
||||
},
|
||||
]);
|
||||
|
||||
const SysOnlineVirtualColumnFilterValueType = new DictionaryBase('虚拟字段过滤值类型', [
|
||||
{
|
||||
id: 0,
|
||||
name: '输入值',
|
||||
symbol: 'CUSTOM_INPUT',
|
||||
},
|
||||
{
|
||||
id: 1,
|
||||
name: '静态字典',
|
||||
symbol: 'STATIC_DICT',
|
||||
},
|
||||
]);
|
||||
|
||||
export {
|
||||
SysOnlineFieldKind,
|
||||
SysOnlineDataPermFilterType,
|
||||
SysOnlineRelationType,
|
||||
SysOnlineFormKind,
|
||||
SysOnlinePageType,
|
||||
SysOnlinePageStatus,
|
||||
SysOnlineDictType,
|
||||
SysOnlineRuleType,
|
||||
SysCustomWidgetBindValueType,
|
||||
SysOnlineColumnFilterType,
|
||||
SysOnlinePageSettingStep,
|
||||
SysOnlinePageDatasourceFieldStatus,
|
||||
SysOnlineParamValueType,
|
||||
SysOnlineAggregationType,
|
||||
SysOnlineFilterOperationType,
|
||||
SysOnlineVirtualColumnFilterValueType,
|
||||
};
|
||||
78
OrangeFormsOpen-VUE3/src/common/staticDict/types.ts
Normal file
78
OrangeFormsOpen-VUE3/src/common/staticDict/types.ts
Normal file
@@ -0,0 +1,78 @@
|
||||
/**
|
||||
* 字典数据类型
|
||||
*/
|
||||
export type DictDataIdType = string | number;
|
||||
export type DictDataPropertyType = string | number | undefined | boolean;
|
||||
|
||||
export type DictData = {
|
||||
id: DictDataIdType;
|
||||
name: string;
|
||||
symbol?: string;
|
||||
[key: string]: DictDataPropertyType;
|
||||
};
|
||||
/**
|
||||
* 常量字典数据
|
||||
*/
|
||||
export class DictionaryBase extends Map<DictDataIdType, DictData> {
|
||||
public showName: string;
|
||||
// 动态属性
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
[name: string]: any;
|
||||
|
||||
constructor(name: string, dataList: DictData[], keyId = 'id', symbolId = 'symbol') {
|
||||
super();
|
||||
this.showName = name;
|
||||
this.setList(dataList, keyId, symbolId);
|
||||
}
|
||||
|
||||
setList(dataList: DictData[], keyId = 'id', symbolId = 'symbol') {
|
||||
this.clear();
|
||||
if (Array.isArray(dataList)) {
|
||||
dataList.forEach(item => {
|
||||
this.set(item[keyId] as DictDataIdType, item);
|
||||
if (item[symbolId] != null) {
|
||||
Object.defineProperty(this, item[symbolId] as PropertyKey, {
|
||||
get: function () {
|
||||
return item[keyId];
|
||||
},
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
getList(
|
||||
valueId = 'name',
|
||||
parentIdKey = 'parentId',
|
||||
filter?: (o: DictData) => DictData,
|
||||
): DictData[] {
|
||||
const temp: DictData[] = [];
|
||||
this.forEach((value, key: DictDataPropertyType) => {
|
||||
let obj: DictData = {
|
||||
id: key as string | number,
|
||||
name: typeof value === 'string' ? value : String(value[valueId]),
|
||||
parentId: value[parentIdKey],
|
||||
};
|
||||
if (typeof value !== 'string') {
|
||||
obj = {
|
||||
...value,
|
||||
...obj,
|
||||
};
|
||||
}
|
||||
if (typeof filter !== 'function' || filter(obj)) {
|
||||
temp.push(obj);
|
||||
}
|
||||
});
|
||||
|
||||
return temp;
|
||||
}
|
||||
|
||||
getValue(id: DictDataIdType, valueId = 'name'): string {
|
||||
// 如果id为boolean类型,则自动转换为0和1
|
||||
if (typeof id === 'boolean') {
|
||||
id = id ? 1 : 0;
|
||||
}
|
||||
const obj = this.get(id);
|
||||
return obj == null ? '' : (obj[valueId] as string);
|
||||
}
|
||||
}
|
||||
21
OrangeFormsOpen-VUE3/src/common/types/list.d.ts
vendored
Normal file
21
OrangeFormsOpen-VUE3/src/common/types/list.d.ts
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
/**
|
||||
* 列表数据
|
||||
*
|
||||
* @param dataList 数据集合
|
||||
*/
|
||||
export interface ListData<T> {
|
||||
dataList: T[];
|
||||
}
|
||||
/**
|
||||
* 下拉列表初始化参数
|
||||
* @param loadData 加载数据函数
|
||||
* @param isTree 是否树型数据
|
||||
* @param idKey ID字段名,默认:id
|
||||
* @param parentIdKey 父ID字段名,默认:parentId
|
||||
*/
|
||||
export interface DropdownOptions<T> {
|
||||
loadData: () => Promise<ListData<T>>;
|
||||
isTree?: boolean;
|
||||
idKey?: string;
|
||||
parentIdKey?: string;
|
||||
}
|
||||
53
OrangeFormsOpen-VUE3/src/common/types/pagination.d.ts
vendored
Normal file
53
OrangeFormsOpen-VUE3/src/common/types/pagination.d.ts
vendored
Normal file
@@ -0,0 +1,53 @@
|
||||
/**
|
||||
* 分页参数
|
||||
* @param pageNum 查询页
|
||||
* @param pagesize 分页大小
|
||||
*/
|
||||
export interface PageParam {
|
||||
pageNum: number;
|
||||
pageSize: number;
|
||||
}
|
||||
/**
|
||||
* 排序参数
|
||||
* @param fieldName 排序字段名
|
||||
* @param asc 是否正序
|
||||
* @param dateAggregateBy 默认排序字段的日期统计类型
|
||||
*/
|
||||
export interface OrderInfo {
|
||||
fieldName?: string;
|
||||
asc?: boolean;
|
||||
dateAggregateBy?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* 分页查询请求参数
|
||||
* @param pageParam 分页参数
|
||||
* @param orderParam 排序参数
|
||||
*/
|
||||
export interface RequestParam {
|
||||
pageParam?: PageParam;
|
||||
orderParam?: OrderInfo[];
|
||||
}
|
||||
|
||||
/**
|
||||
* 表格初始化参数
|
||||
*
|
||||
* @param loadTableData 表数据获取函数,返回Promise
|
||||
* @param verifyTableParameter 表数据获取检验函数
|
||||
* @param paged 是否支持分页
|
||||
* @param rowSelection 是否支持行选择
|
||||
* @param orderFieldName 默认排序字段
|
||||
* @param ascending 默认排序方式(true为正序,false为倒序),默认值:true
|
||||
* @param dateAggregateBy 默认排序字段的日期统计类型
|
||||
* @param pageSize 分页大小,默认值:10
|
||||
*/
|
||||
export type TableOptions<T> = {
|
||||
loadTableData: (params: RequestParam) => Promise<TableData<T>>;
|
||||
verifyTableParameter?: () => boolean;
|
||||
paged?: boolean;
|
||||
rowSelection?: boolean;
|
||||
orderFieldName?: string;
|
||||
ascending?: boolean;
|
||||
dateAggregateBy?: string;
|
||||
pageSize?: number;
|
||||
};
|
||||
5
OrangeFormsOpen-VUE3/src/common/types/sortinfo.d.ts
vendored
Normal file
5
OrangeFormsOpen-VUE3/src/common/types/sortinfo.d.ts
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
export interface SortInfo {
|
||||
prop?: string;
|
||||
field?: string;
|
||||
order: string;
|
||||
}
|
||||
11
OrangeFormsOpen-VUE3/src/common/types/table.d.ts
vendored
Normal file
11
OrangeFormsOpen-VUE3/src/common/types/table.d.ts
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
import { ListData } from './list';
|
||||
|
||||
/**
|
||||
* 表格数据
|
||||
*
|
||||
* @param dataList 数据集合
|
||||
* @param totalCount 数据集合总数
|
||||
*/
|
||||
export interface TableData<T> extends ListData<T> {
|
||||
totalCount: number;
|
||||
}
|
||||
664
OrangeFormsOpen-VUE3/src/common/utils/index.ts
Normal file
664
OrangeFormsOpen-VUE3/src/common/utils/index.ts
Normal file
@@ -0,0 +1,664 @@
|
||||
import { JSEncrypt } from 'jsencrypt';
|
||||
import dayjs from 'dayjs';
|
||||
import { ANY_OBJECT } from '@/types/generic';
|
||||
|
||||
/**
|
||||
* 列表数据转换树形数据
|
||||
* @param {Array} data 要转换的列表
|
||||
* @param {String} id 主键字段字段名
|
||||
* @param {String} pid 父字段字段名
|
||||
* @returns {Array} 转换后的树数据
|
||||
*/
|
||||
export function treeDataTranslate<D>(data: Array<D>, id = 'id', pid = 'parentId'): D[] {
|
||||
const res: D[] = [];
|
||||
const temp: ANY_OBJECT = {};
|
||||
const dataList: ANY_OBJECT[] = data.map(item => {
|
||||
return { ...item } as ANY_OBJECT;
|
||||
});
|
||||
for (let i = 0; i < dataList.length; i++) {
|
||||
const d = dataList[i];
|
||||
if (d) {
|
||||
temp[d[id]] = dataList[i];
|
||||
}
|
||||
}
|
||||
for (let k = 0; k < dataList.length; k++) {
|
||||
const d = dataList[k];
|
||||
if (d) {
|
||||
if (temp[d[pid]] && d[id] !== d[pid]) {
|
||||
if (!temp[d[pid]]['children']) {
|
||||
temp[d[pid]]['children'] = [];
|
||||
}
|
||||
if (!temp[d[pid]]['_level']) {
|
||||
temp[d[pid]]['_level'] = 1;
|
||||
}
|
||||
d['_level'] = temp[d[pid]]._level + 1;
|
||||
d['_parent'] = d[pid];
|
||||
temp[d[pid]]['children'].push(d);
|
||||
} else {
|
||||
res.push(d as D);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
/**
|
||||
* 获取字符串字节长度(中文算2个字符)
|
||||
* @param {String} str 要获取长度的字符串
|
||||
*/
|
||||
export function getStringLength(str: string) {
|
||||
return str.replace(/[\u4e00-\u9fa5\uff00-\uffff]/g, '**').length;
|
||||
}
|
||||
/**
|
||||
* 获取uuid
|
||||
*/
|
||||
export function getUUID(): string {
|
||||
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, c => {
|
||||
const random: number = Math.random() * 16;
|
||||
return (c === 'x' ? random : (random & 0x3) | 0x8).toString(16);
|
||||
});
|
||||
}
|
||||
|
||||
export function stringCase(str: string, type: number) {
|
||||
if (str == null || str === '') return str;
|
||||
if (type === 0) {
|
||||
// 首字母小写
|
||||
return str.slice(0, 1).toLowerCase() + str.slice(1);
|
||||
} else {
|
||||
// 首字母大写
|
||||
return str.slice(0, 1).toUpperCase() + str.slice(1);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 大小驼峰变换函数
|
||||
* @param name 要转换的字符串
|
||||
* @param type 转换的类型0:转换成小驼峰,1:转换成大驼峰
|
||||
*/
|
||||
export function nameTranslate(name: string, type: 0 | 1) {
|
||||
name = name.toLowerCase();
|
||||
let nameArray = name.split('_');
|
||||
nameArray.forEach((item, index) => {
|
||||
if (index === 0) {
|
||||
name = type === 1 ? item.slice(0, 1).toUpperCase() + item.slice(1) : item;
|
||||
} else {
|
||||
name = name + item.slice(0, 1).toUpperCase() + item.slice(1);
|
||||
}
|
||||
});
|
||||
|
||||
nameArray = name.split('-');
|
||||
nameArray.forEach((item, index) => {
|
||||
if (index === 0) {
|
||||
name = type === 1 ? item.slice(0, 1).toUpperCase() + item.slice(1) : item;
|
||||
} else {
|
||||
name = name + item.slice(0, 1).toUpperCase() + item.slice(1);
|
||||
}
|
||||
});
|
||||
return name;
|
||||
}
|
||||
/**
|
||||
* 通过id从树中获取指定的节点
|
||||
* @param {Object} node 根节点
|
||||
* @param {String|Nubmer} id 键值
|
||||
* @param {Array} list 保存查询路径
|
||||
* @param {String} idKey 主键字段名
|
||||
* @param {String} childKey 子节点字段名
|
||||
*/
|
||||
function findNode(
|
||||
node: ANY_OBJECT,
|
||||
id: string | number | undefined,
|
||||
list?: Array<ANY_OBJECT> | undefined,
|
||||
idKey = 'id',
|
||||
childKey = 'children',
|
||||
): ANY_OBJECT | undefined {
|
||||
if (Array.isArray(list)) list.push(node);
|
||||
if (node[idKey] === id) {
|
||||
return node;
|
||||
}
|
||||
|
||||
if (node[childKey] != null && Array.isArray(node[childKey])) {
|
||||
for (let i = 0; i < node[childKey].length; i++) {
|
||||
const tempNode: ANY_OBJECT | undefined = findNode(
|
||||
node[childKey][i],
|
||||
id,
|
||||
list,
|
||||
idKey,
|
||||
childKey,
|
||||
);
|
||||
if (tempNode) return tempNode;
|
||||
}
|
||||
}
|
||||
|
||||
if (Array.isArray(list)) list.pop();
|
||||
}
|
||||
/**
|
||||
* 通过id返回从根节点到指定节点的路径
|
||||
* @param {Array} treeRoot 树根节点数组
|
||||
* @param {*} id 要查询的节点的id
|
||||
* @param {*} idKey 主键字段名
|
||||
* @param {*} childKey 子节点字段名
|
||||
*/
|
||||
export function findTreeNodeObjectPath(
|
||||
treeRoot: ANY_OBJECT,
|
||||
id: string | number | undefined,
|
||||
idKey = 'id',
|
||||
childKey = 'children',
|
||||
) {
|
||||
const tempList: ANY_OBJECT[] = [];
|
||||
for (let i = 0; i < treeRoot.length; i++) {
|
||||
if (findNode(treeRoot[i], id, tempList, idKey, childKey)) {
|
||||
return tempList;
|
||||
}
|
||||
}
|
||||
|
||||
return [];
|
||||
}
|
||||
|
||||
export function findTreeNodePath<D>(
|
||||
treeRoot: Array<D>,
|
||||
id: string | number | undefined,
|
||||
idKey = 'id',
|
||||
childKey = 'children',
|
||||
): Array<string | number> {
|
||||
return (findTreeNodeObjectPath(treeRoot, id, idKey, childKey) || []).map(item => item[idKey]);
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过id从树中查找节点
|
||||
* @param {Array} treeRoot 根节点数组
|
||||
* @param {*} id 要查找的节点的id
|
||||
* @param {*} idKey 主键字段名
|
||||
* @param {*} childKey 子节点字段名
|
||||
*/
|
||||
export function findTreeNode(
|
||||
treeRoot: ANY_OBJECT,
|
||||
id: string,
|
||||
idKey = 'id',
|
||||
childKey = 'children',
|
||||
) {
|
||||
for (let i = 0; i < treeRoot.length; i++) {
|
||||
const tempNode = findNode(treeRoot[i], id, undefined, idKey, childKey);
|
||||
if (tempNode) return tempNode;
|
||||
}
|
||||
}
|
||||
|
||||
export function traverseTree(
|
||||
root: ANY_OBJECT,
|
||||
callback: (node: ANY_OBJECT) => void,
|
||||
childKey = 'children',
|
||||
) {
|
||||
function traverseNode(node: ANY_OBJECT) {
|
||||
if (typeof callback === 'function') callback(node);
|
||||
if (Array.isArray(node[childKey])) {
|
||||
node[childKey].forEach((suNode: ANY_OBJECT) => {
|
||||
traverseNode(suNode);
|
||||
});
|
||||
}
|
||||
}
|
||||
if (Array.isArray(root)) {
|
||||
root.forEach(node => {
|
||||
traverseNode(node);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 把Object转换成query字符串
|
||||
* @param {Object} params 要转换的Object
|
||||
*/
|
||||
export function objectToQueryString(params: ANY_OBJECT | null) {
|
||||
if (params == null) {
|
||||
return null;
|
||||
} else {
|
||||
return Object.keys(params)
|
||||
.map(key => {
|
||||
if (params[key] !== undefined) {
|
||||
return `${key}=${params[key]}`;
|
||||
} else {
|
||||
return undefined;
|
||||
}
|
||||
})
|
||||
.filter(item => item != null)
|
||||
.join('&');
|
||||
}
|
||||
}
|
||||
/**
|
||||
* 从数组中查找某一项
|
||||
* @param {Array} list 要查找的数组
|
||||
* @param {String} id 要查找的节点id
|
||||
* @param {String} idKey 主键字段名(如果为null则直接比较)
|
||||
* @param {Boolean} removeItem 是否从数组中移除查找到的节点
|
||||
* @returns {Object} 找到返回节点,没找到返回undefined
|
||||
*/
|
||||
export function findItemFromList(
|
||||
list: ANY_OBJECT[],
|
||||
id: string | number | undefined | null,
|
||||
idKey: string | null = null,
|
||||
removeItem = false,
|
||||
) {
|
||||
if (Array.isArray(list) && list.length > 0 && id != null) {
|
||||
for (let i = 0; i < list.length; i++) {
|
||||
const item = list[i];
|
||||
if (
|
||||
((idKey == null || idKey === '') && item.toString() === id) ||
|
||||
(idKey != null && item[idKey] === id)
|
||||
) {
|
||||
if (removeItem) list.splice(i, 1);
|
||||
return item;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
/**
|
||||
* 将数据保存到sessionStorage
|
||||
* @param {*} key sessionStorage的键值
|
||||
* @param {*} value 要保存的数据
|
||||
*/
|
||||
export function setObjectToSessionStorage(key: string, value: ANY_OBJECT) {
|
||||
if (key == null || key === '') return false;
|
||||
if (value == null) {
|
||||
window.sessionStorage.removeItem(key);
|
||||
return true;
|
||||
} else {
|
||||
const jsonObj = {
|
||||
data: value,
|
||||
};
|
||||
window.sessionStorage.setItem(key, JSON.stringify(jsonObj));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* 从sessionStorage里面获取数据
|
||||
* @param {String} key 键值
|
||||
* @param {*} defaultValue 默认值
|
||||
*/
|
||||
export function getObjectFromSessionStorage(key: string, defaultValue: ANY_OBJECT): ANY_OBJECT {
|
||||
let jsonObj = null;
|
||||
try {
|
||||
const val: string | null = sessionStorage.getItem(key);
|
||||
if (val == null) return defaultValue;
|
||||
jsonObj = JSON.parse(val);
|
||||
jsonObj = (jsonObj || {}).data;
|
||||
} catch (e) {
|
||||
jsonObj = defaultValue;
|
||||
}
|
||||
return jsonObj != null ? jsonObj : defaultValue;
|
||||
}
|
||||
/**
|
||||
* 判读字符串是否一个数字
|
||||
* @param {String} str 要判断的字符串
|
||||
*/
|
||||
export function isNumber(str: string) {
|
||||
const num = Number.parseFloat(str);
|
||||
if (Number.isNaN(num)) return false;
|
||||
return num.toString() === str;
|
||||
}
|
||||
/**
|
||||
* 生成随机数
|
||||
* @param {Integer} min 随机数最小值
|
||||
* @param {Integer} max 随机数最大值
|
||||
*/
|
||||
export function random(min: number, max: number) {
|
||||
const base = Math.random();
|
||||
return min + base * (max - min);
|
||||
}
|
||||
/**
|
||||
* 加密
|
||||
* @param {*} value 要加密的字符串
|
||||
*/
|
||||
const publicKey =
|
||||
'MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCpC4QMnbTrQOFriJJCCFFWhlruBJThAEBfRk7pRx1jsAhyNVL3CqJb0tRvpnbCnJhrRAEPdgFHXv5A0RrvFp+5Cw7QoFH6O9rKB8+0H7+aVQeKITMUHf/XMXioymw6Iq4QfWd8RhdtM1KM6eGTy8aU7SO2s69Mc1LXefg/x3yw6wIDAQAB';
|
||||
export function encrypt(value: string): string | null {
|
||||
if (value == null || value === '') return null;
|
||||
const encrypt = new JSEncrypt();
|
||||
encrypt.setPublicKey(publicKey);
|
||||
return encodeURIComponent(encrypt.encrypt(value));
|
||||
}
|
||||
|
||||
export function getToken() {
|
||||
return sessionStorage.getItem('token');
|
||||
}
|
||||
|
||||
export function setToken(token: string | null | undefined) {
|
||||
if (token == null || token === '') {
|
||||
sessionStorage.removeItem('token');
|
||||
} else {
|
||||
sessionStorage.setItem('token', token);
|
||||
}
|
||||
}
|
||||
|
||||
export function getAppId() {
|
||||
const appId = sessionStorage.getItem('appId');
|
||||
return appId != null ? appId : undefined;
|
||||
}
|
||||
|
||||
export function setAppId(appId: string | null | undefined) {
|
||||
if (appId == null || appId === '') {
|
||||
sessionStorage.removeItem('appId');
|
||||
} else {
|
||||
sessionStorage.setItem('appId', appId);
|
||||
}
|
||||
}
|
||||
|
||||
export function traversalTree(
|
||||
treeNode: ANY_OBJECT,
|
||||
callback: (treeNode: ANY_OBJECT) => void,
|
||||
childrenKey = 'children',
|
||||
) {
|
||||
if (
|
||||
treeNode != null &&
|
||||
Array.isArray(treeNode[childrenKey]) &&
|
||||
treeNode[childrenKey].length > 0
|
||||
) {
|
||||
treeNode[childrenKey].forEach((childNode: ANY_OBJECT) => {
|
||||
traversalTree(childNode, callback, childrenKey);
|
||||
});
|
||||
}
|
||||
return typeof callback === 'function' ? callback(treeNode) : undefined;
|
||||
}
|
||||
|
||||
export class TreeTableImpl {
|
||||
private options;
|
||||
private dataList;
|
||||
private dataMap;
|
||||
private checkedRows: Map<string, ANY_OBJECT> | undefined;
|
||||
|
||||
constructor(
|
||||
dataList: Array<ANY_OBJECT>,
|
||||
options: {
|
||||
idKey: string;
|
||||
nameKey: string;
|
||||
parentIdKey: string;
|
||||
isLefeCallback: (item: ANY_OBJECT) => boolean | undefined;
|
||||
checkStrictly: boolean;
|
||||
},
|
||||
) {
|
||||
this.options = {
|
||||
idKey: options ? options.idKey : 'id',
|
||||
nameKey: options ? options.nameKey : 'name',
|
||||
parentIdKey: options ? options.parentIdKey : 'parentId',
|
||||
isLefeCallback: options ? options.isLefeCallback : undefined,
|
||||
checkStrictly: options ? options.checkStrictly : false,
|
||||
};
|
||||
|
||||
this.dataList = Array.isArray(dataList) ? dataList : [];
|
||||
this.dataMap = new Map();
|
||||
this.dataList.forEach(item => {
|
||||
this.dataMap.set(item[this.options.idKey], item);
|
||||
});
|
||||
// 表格选中行
|
||||
this.checkedRows = undefined;
|
||||
this.onCheckedRowChange = this.onCheckedRowChange.bind(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* 过滤表格数据
|
||||
* @param {string} filterString 过滤条件字符串
|
||||
* @param {boolean} onlyChecked 是否只显示选中节点
|
||||
* @returns {array} 过滤后的表格数据列表
|
||||
*/
|
||||
getFilterTableData(filterString: string | null, onlyChecked = false) {
|
||||
const { idKey, nameKey, parentIdKey, isLefeCallback } = this.options;
|
||||
const tempMap = new Map();
|
||||
const parentIdList: ANY_OBJECT[] = [];
|
||||
this.dataList.forEach(item => {
|
||||
if (
|
||||
(filterString == null ||
|
||||
filterString === '' ||
|
||||
item[nameKey].indexOf(filterString) !== -1) &&
|
||||
(!onlyChecked || (this.checkedRows != null && this.checkedRows.get(item[idKey])))
|
||||
) {
|
||||
if (!isLefeCallback || !isLefeCallback(item)) {
|
||||
parentIdList.push(item[idKey]);
|
||||
}
|
||||
// 将命中节点以及它的父节点都设置为命中
|
||||
let tempItem = item;
|
||||
do {
|
||||
tempMap.set(tempItem[idKey], tempItem);
|
||||
tempItem = this.dataMap.get(tempItem[parentIdKey]);
|
||||
} while (tempItem != null);
|
||||
}
|
||||
});
|
||||
|
||||
return this.dataList.map(item => {
|
||||
let disabled = true;
|
||||
|
||||
if (parentIdList.indexOf(item[parentIdKey]) !== -1 || tempMap.get(item[idKey]) != null) {
|
||||
if (
|
||||
parentIdList.indexOf(item[parentIdKey]) !== -1 &&
|
||||
(isLefeCallback == null || !isLefeCallback(item))
|
||||
) {
|
||||
parentIdList.push(item[idKey]);
|
||||
}
|
||||
disabled = false;
|
||||
}
|
||||
|
||||
return {
|
||||
...item,
|
||||
__disabled: disabled,
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取表格树数据,计算选中状态
|
||||
* @param {array} dataList 表格列表数据
|
||||
*/
|
||||
getTableTreeData(dataList: ANY_OBJECT[], checkedRows: Map<string, ANY_OBJECT>) {
|
||||
const { idKey, parentIdKey, checkStrictly } = this.options;
|
||||
let treeData: ANY_OBJECT[] = [];
|
||||
function calcPermCodeTreeAttribute(treeNode: ANY_OBJECT, checkedRows: Map<string, ANY_OBJECT>) {
|
||||
const checkedItem = checkedRows == null ? null : checkedRows.get(treeNode[idKey]);
|
||||
treeNode.__checked = checkedItem != null;
|
||||
// 是否所有子权限字都被选中
|
||||
let allChildChecked = true;
|
||||
// 是否任意子权限字被选中
|
||||
let hasChildChecked = false;
|
||||
// 如果存在子权限字
|
||||
if (Array.isArray(treeNode.children) && treeNode.children.length > 0) {
|
||||
treeNode.children.forEach((item: ANY_OBJECT) => {
|
||||
const isChecked = calcPermCodeTreeAttribute(item, checkedRows);
|
||||
hasChildChecked = hasChildChecked || isChecked;
|
||||
allChildChecked = allChildChecked && isChecked;
|
||||
});
|
||||
} else {
|
||||
allChildChecked = false;
|
||||
}
|
||||
treeNode.__indeterminate = !checkStrictly && hasChildChecked && !allChildChecked;
|
||||
treeNode.__checked = treeNode.__checked || (allChildChecked && !checkStrictly);
|
||||
return treeNode.__checked || treeNode.__indeterminate;
|
||||
}
|
||||
|
||||
if (Array.isArray(dataList)) {
|
||||
treeData = treeDataTranslate(
|
||||
dataList.map(item => {
|
||||
return { ...item };
|
||||
}),
|
||||
idKey,
|
||||
parentIdKey,
|
||||
);
|
||||
treeData.forEach(item => {
|
||||
calcPermCodeTreeAttribute(item, checkedRows);
|
||||
});
|
||||
}
|
||||
|
||||
return treeData;
|
||||
}
|
||||
|
||||
/**
|
||||
* 树表格行选中状态改变
|
||||
* @param {object} row 选中状态改变行数据
|
||||
*/
|
||||
onCheckedRowChange(row: ANY_OBJECT) {
|
||||
if (this.checkedRows == null) {
|
||||
this.checkedRows = new Map();
|
||||
} else {
|
||||
const temp = new Map();
|
||||
this.checkedRows.forEach((item, key) => {
|
||||
temp.set(key, item);
|
||||
});
|
||||
this.checkedRows = temp;
|
||||
}
|
||||
const { idKey } = this.options;
|
||||
if (!row.__checked || row.__indeterminate) {
|
||||
// 节点之前未被选中或者之前为半选状态,修改当前节点以及子节点为选中状态
|
||||
this.checkedRows.set(row[idKey], row);
|
||||
if (Array.isArray(row.children) && !this.options.checkStrictly) {
|
||||
row.children.forEach((childNode: ANY_OBJECT) => {
|
||||
traversalTree(childNode, node => {
|
||||
this.checkedRows?.set(node[idKey], node);
|
||||
});
|
||||
});
|
||||
}
|
||||
} else {
|
||||
// 节点之前为选中状态,修改节点以及子节点为未选中状态
|
||||
this.checkedRows.delete(row[idKey]);
|
||||
if (Array.isArray(row.children) && !this.options.checkStrictly) {
|
||||
row.children.forEach((childNode: ANY_OBJECT) => {
|
||||
traversalTree(childNode, node => {
|
||||
this.checkedRows?.delete(node[idKey]);
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取所有选中的权限字节点
|
||||
* @param {array} treeData 树数据
|
||||
* @param {boolean} includeHalfChecked 是否包含半选节点,默认为false
|
||||
* @returns {array} 选中节点列表
|
||||
*/
|
||||
getCheckedRows(treeData: ANY_OBJECT, includeHalfChecked = false) {
|
||||
const checkedRows: ANY_OBJECT[] = [];
|
||||
|
||||
function traversalCallback(node: ANY_OBJECT) {
|
||||
if (node == null) return;
|
||||
if (node.__checked || (includeHalfChecked && node.__indeterminate)) {
|
||||
checkedRows.push(node);
|
||||
}
|
||||
}
|
||||
|
||||
if (Array.isArray(treeData) && treeData.length > 0) {
|
||||
treeData.forEach(permCode => {
|
||||
traversalTree(permCode, traversalCallback, 'children');
|
||||
});
|
||||
}
|
||||
|
||||
return checkedRows;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置选中节点
|
||||
* @param {array} checkedRows
|
||||
*/
|
||||
setCheckedRows(checkedRows: ANY_OBJECT[]) {
|
||||
this.checkedRows = new Map();
|
||||
if (Array.isArray(checkedRows)) {
|
||||
checkedRows.forEach(item => {
|
||||
const node = this.dataMap.get(item[this.options.idKey]);
|
||||
if (node != null) {
|
||||
this.checkedRows?.set(node[this.options.idKey], node);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
/**
|
||||
* 根据id获取表格行
|
||||
* @param {*} id
|
||||
*/
|
||||
getTableRow(id: string) {
|
||||
return this.dataMap.get(id);
|
||||
}
|
||||
}
|
||||
|
||||
export function formatDate(
|
||||
date: string | number | Date | dayjs.Dayjs | null | undefined,
|
||||
formatString: string | undefined,
|
||||
) {
|
||||
return dayjs(date).format(formatString);
|
||||
}
|
||||
|
||||
export function parseDate(date: string | number | Date, formatString: string | undefined) {
|
||||
return dayjs(date, formatString);
|
||||
}
|
||||
|
||||
export function fileToBase64(file: File) {
|
||||
return new Promise<string | undefined>((resolve, reject) => {
|
||||
if (file == null) return reject();
|
||||
const reader = new FileReader();
|
||||
reader.readAsDataURL(file);
|
||||
reader.onload = e => {
|
||||
console.log('file loaded', e);
|
||||
resolve(e.target?.result as string);
|
||||
};
|
||||
reader.onerror = e => {
|
||||
console.warn('file load', e);
|
||||
reject(e);
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
export function getObjectValue(data: ANY_OBJECT, fieldName: string) {
|
||||
if (data == null) return undefined;
|
||||
if (fieldName == null || fieldName === '') return data;
|
||||
const fieldPath = fieldName.split('.');
|
||||
let tempValue = data;
|
||||
if (Array.isArray(fieldPath)) {
|
||||
fieldPath.forEach(key => {
|
||||
if (tempValue != null) {
|
||||
tempValue = tempValue[key];
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return tempValue;
|
||||
}
|
||||
|
||||
// 判断输入值是否一个Object
|
||||
export function isObject(obj: ANY_OBJECT) {
|
||||
return obj != null && typeof obj === 'object' && obj.toString() === '[object Object]';
|
||||
}
|
||||
|
||||
function copyObject(obj: ANY_OBJECT): ANY_OBJECT {
|
||||
if (obj == null) return obj;
|
||||
return JSON.parse(JSON.stringify(obj));
|
||||
}
|
||||
|
||||
export function deepMerge(obj1: ANY_OBJECT, obj2: ANY_OBJECT) {
|
||||
const tempObj = copyObject(obj1);
|
||||
if (obj2 != null) {
|
||||
Object.keys(obj2).forEach(key => {
|
||||
const val2 = obj2[key];
|
||||
const val1 = tempObj[key];
|
||||
if (isObject(val2)) {
|
||||
// 如果两个值都是对象,则递归合并
|
||||
if (isObject(val1)) {
|
||||
tempObj[key] = deepMerge(val1, val2);
|
||||
} else {
|
||||
tempObj[key] = copyObject(val2);
|
||||
}
|
||||
} else if (Array.isArray(val2)) {
|
||||
//console.log('......deepMerge.......', val1, val2, obj1, obj2);
|
||||
// 如果两个值都是数组,则合并数组
|
||||
if (Array.isArray(val1)) {
|
||||
tempObj[key] = val2.map((arrVal2, index) => {
|
||||
const arrVal1 = val1[index];
|
||||
if (isObject(arrVal1)) {
|
||||
return deepMerge(arrVal1, arrVal2);
|
||||
} else {
|
||||
return arrVal2;
|
||||
}
|
||||
});
|
||||
} else {
|
||||
tempObj[key] = copyObject(val2);
|
||||
}
|
||||
} else {
|
||||
// 直接覆盖
|
||||
tempObj[key] = val2;
|
||||
}
|
||||
});
|
||||
}
|
||||
return tempObj;
|
||||
}
|
||||
30
OrangeFormsOpen-VUE3/src/common/utils/validate.ts
Normal file
30
OrangeFormsOpen-VUE3/src/common/utils/validate.ts
Normal file
@@ -0,0 +1,30 @@
|
||||
export const pattern = {
|
||||
mobie:
|
||||
/^((\+?86)|(\(\+86\)))?(13[012356789][0-9]{8}|15[012356789][0-9]{8}|17[012356789][0-9]{8}|19[012356789][0-9]{8}|18[02356789][0-9]{8}|147[0-9]{8}|1349[0-9]{7})$/,
|
||||
english: /^[a-zA-Z]+$/,
|
||||
englishAndNumber: /^[a-zA-Z0-9]+$/,
|
||||
};
|
||||
|
||||
/**
|
||||
* 邮箱
|
||||
* @param str
|
||||
*/
|
||||
export function isEmail(str: string) {
|
||||
return /^([a-zA-Z0-9_-])+@([a-zA-Z0-9_-])+((.[a-zA-Z0-9_-]{2,3}){1,2})$/.test(str);
|
||||
}
|
||||
|
||||
/**
|
||||
* 手机号码
|
||||
* @param str
|
||||
*/
|
||||
export function isMobile(str: string) {
|
||||
return pattern.mobie.test(str);
|
||||
}
|
||||
|
||||
/**
|
||||
* 电话号码
|
||||
* @param str
|
||||
*/
|
||||
export function isPhone(str: string) {
|
||||
return /^([0-9]{3,4}-)?[0-9]{7,8}$/.test(str);
|
||||
}
|
||||
Reference in New Issue
Block a user