发布代码生成、更新20+表单组件,优化数据字典,gf版本更新到2.3.1

This commit is contained in:
孟帅
2023-01-18 16:23:39 +08:00
parent 50207ded90
commit 87c27a17a3
386 changed files with 27926 additions and 44297 deletions

View File

@@ -121,13 +121,6 @@ export function encodeParams(obj) {
return arr.join('&');
}
/**
* 去重追加
* @param array
* @param son
*/
export function onlyPush(array: any, son: any) {}
/**
* 对象拷贝
* @param obj2

74
web/src/utils/charset.ts Normal file
View File

@@ -0,0 +1,74 @@
/**
* 随机生成字符串
*/
export function getRandomString(len = 12, isSmall = false) {
const _charStr = 'abacdefghjklmnopqrstuvwxyzABCDEFGHJKLMNOPQRSTUVWXYZ0123456789';
const _smallCharStr = 'abacdefghjklmnopqrstuvwxyz0123456789';
const charStr = isSmall ? _smallCharStr : _charStr;
const min = 0;
const max = charStr.length - 1;
let _str = '';
//循环生成字符串
for (let i = 0, index; i < len; i++) {
index = (function (randomIndexFunc, i) {
return randomIndexFunc(min, max, i, randomIndexFunc);
})(function (min, max, i, _self) {
const numStart = _charStr.length - 10;
let indexTemp = Math.floor(Math.random() * (max - min + 1) + min);
if (i == 0 && indexTemp >= numStart) {
indexTemp = _self(min, max, i, _self);
}
return indexTemp;
}, i);
_str += _charStr[index];
}
return _str;
}
/**
* 隐藏中间几位字符
*/
export function structure(array) {
// 将字符串转化成数组
const arrBox = [...array];
const count = arrBox.length;
if (count == 1) {
return '*';
}
let min = 1;
let max = count;
// 两位姓名
if (count == 2) {
min = 0;
max = count;
}
// 三位姓名
if (count == 3) {
min = 0;
max = count - 1;
}
// if (count >= 2 && count <= 8) {
// min = 1;
// }
// 手机号
if (count == 11) {
min = 3;
max = 7;
}
// 身份证号码
if (count >= 15) {
min = 9;
max = count - 4;
}
// 2.将数组中的4-7位变成*
let str = '';
arrBox.map((res, index) => {
if (index > min && index < max) {
str += '*';
} else {
str += res;
}
});
return str;
}

View File

@@ -1,21 +1,38 @@
import { format } from 'date-fns';
import {
endOfMonth,
endOfToday,
endOfWeek,
endOfYesterday,
format,
startOfMonth,
startOfToday,
startOfTomorrow,
startOfWeek,
startOfYesterday,
subMonths,
} from 'date-fns';
const DATE_TIME_FORMAT = 'YYYY-MM-DD HH:mm';
const DATE_FORMAT = 'YYYY-MM-DD ';
const DATE_TIME_FORMAT = 'yyyy-MM-dd HH:mm:ss';
const DATE_FORMAT = 'yyyy-MM-dd';
export function formatToDateTime(date: Date, formatStr = DATE_TIME_FORMAT): string {
const date2 = new Date(date);
return format(date2, formatStr);
export function formatToDateTime(date: string, formatStr = DATE_TIME_FORMAT): string {
if (date === null || date === undefined || date === '') {
return ``;
}
return format(new Date(Date.parse(date)), formatStr);
}
export function formatToDate(date: Date, formatStr = DATE_FORMAT): string {
return format(date, formatStr);
export function formatToDate(date: string, formatStr = DATE_FORMAT): string {
if (date === null || date === undefined || date === '') {
return ``;
}
return format(new Date(Date.parse(date)), formatStr);
}
export function timestampToTime(timestamp) {
const date = new Date(timestamp * 1000);
const Y = date.getFullYear() + '-';
const M = (date.getMonth() + 1 <= 10 ? '0' + (date.getMonth() + 1) : date.getMonth() + 1) + '-';
const M = (date.getMonth() + 1 < 10 ? '0' + (date.getMonth() + 1) : date.getMonth() + 1) + '-';
const D = (date.getDate() + 1 <= 10 ? '0' + date.getDate() : date.getDate()) + ' ';
const h = (date.getHours() + 1 <= 10 ? '0' + date.getHours() : date.getHours()) + ':';
const m = (date.getMinutes() + 1 <= 10 ? '0' + date.getMinutes() : date.getMinutes()) + ':';
@@ -26,7 +43,7 @@ export function timestampToTime(timestamp) {
export function timestampToTimeNF(timestamp) {
const date = new Date(timestamp);
const Y = date.getFullYear();
const M = date.getMonth() + 1 <= 10 ? '0' + (date.getMonth() + 1) : date.getMonth() + 1;
const M = date.getMonth() + 1 < 10 ? '0' + (date.getMonth() + 1) : date.getMonth() + 1;
const D = date.getDate() + 1 <= 10 ? '0' + date.getDate() : date.getDate();
const h = date.getHours() + 1 <= 10 ? '0' + date.getHours() : date.getHours();
const m = date.getMinutes() + 1 <= 10 ? '0' + date.getMinutes() : date.getMinutes();
@@ -34,6 +51,13 @@ export function timestampToTimeNF(timestamp) {
return Y.toString() + M.toString() + D.toString() + h.toString() + m.toString() + s.toString();
}
export function dateToTimestamp(date: string) {
if (date === null || date === undefined || date === '') {
return 0;
}
return new Date(date).getTime();
}
export function timestampToDate(timestamp) {
const date = new Date(timestamp);
const Y = date.getFullYear() + '-';
@@ -44,23 +68,16 @@ export function timestampToDate(timestamp) {
export function getTime() {
const myDate = new Date();
const hour = myDate.getHours().toString().padStart(2, '0');
const minutes = myDate.getMinutes().toString().padStart(2, '0');
const seconed = myDate.getSeconds().toString().padStart(2, '0');
return hour + ':' + minutes + ':' + seconed;
}
export function getDate() {
const myDate = new Date();
const month = (myDate.getMonth() + 1).toString().padStart(2, '0');
const day = myDate.getDate().toString().padStart(2, '0');
return myDate.getFullYear() + '-' + month + '-' + day;
}
@@ -129,15 +146,11 @@ export function formatAfter(end): string {
if (end.getTime() - start.getTime() > 0) {
sjc = end.getTime() - start.getTime(); //时间差的毫秒数
}
const days = Math.floor(sjc / (24 * 3600 * 1000)); //计算出相差天数
const leave1 = sjc % (24 * 3600 * 1000); //计算天数后剩余的毫秒数
const hours = Math.floor(leave1 / (3600 * 1000)); //计算出小时数
const leave2 = leave1 % (3600 * 1000); //计算小时数后剩余的毫秒数
const minutes = Math.floor(leave2 / (60 * 1000)); //计算相差分钟数
const leave3 = leave2 % (60 * 1000); //计算分钟数后剩余的毫秒数
const seconds = Math.round(leave3 / 1000); //计算相差秒数
if (days > 0) {
@@ -152,6 +165,38 @@ export function formatAfter(end): string {
if (seconds > 0) {
return seconds + '秒后';
}
return '刚刚';
}
export function defShortcuts() {
return {
今天: startOfToday().getTime(),
昨天: startOfYesterday().getTime(),
明天: startOfTomorrow().getTime(),
};
}
export function defRangeShortcuts() {
const nowDate = new Date();
return {
: [startOfToday().getTime(), endOfToday().getTime()] as const,
: () => {
return [startOfYesterday().getTime(), endOfYesterday().getTime()] as const;
},
: () => {
return [
startOfWeek(nowDate, { weekStartsOn: 1 }).getTime(),
endOfWeek(nowDate, { weekStartsOn: 1 }).getTime(),
] as const;
},
: () => {
return [startOfMonth(nowDate).getTime(), endOfMonth(nowDate).getTime()] as const;
},
: () => {
return [
startOfMonth(subMonths(nowDate, 1)).getTime(),
endOfMonth(subMonths(nowDate, 1)).getTime(),
] as const;
},
};
}

View File

@@ -62,6 +62,7 @@ export function downloadByUrl({
// saveAs(imageDataUrl, '附件');
canvas.toBlob((blob) => {
const link = document.createElement('a');
// @ts-ignore
link.href = window.URL.createObjectURL(blob);
link.download = getFileName(url);
link.click();

53
web/src/utils/hotgo.ts Normal file
View File

@@ -0,0 +1,53 @@
import { Ref, UnwrapRef } from '@vue/reactivity';
export interface Option {
label: string;
value: string;
key: string;
type: string;
listClass: 'default' | 'error' | 'primary' | 'info' | 'success' | 'warning';
}
export interface Options {
[name: string]: Option[];
}
// 获取选项名称
export function getOptionLabel(options: Option[], value) {
if (options === undefined || options?.length === 0) {
return `unknown`;
}
for (const item of options) {
if (item.value == value) {
return item.label;
}
}
return `unknown`;
}
// 获取选项标签
export function getOptionTag(options: Option[], value) {
if (options === undefined || options?.length === 0) {
return 'default';
}
for (const item of options) {
if (item.value == value) {
return item.listClass;
}
}
return 'default';
}
// 自适应模板宽度
export function adaModalWidth(dialogWidth: Ref<UnwrapRef<string>>) {
const val = document.body.clientWidth;
const def = 840; // 默认宽度
if (val <= def) {
dialogWidth.value = '100%';
} else {
dialogWidth.value = def + 'px';
}
return dialogWidth.value;
}

View File

@@ -1,10 +1,8 @@
import type { AxiosRequestConfig, AxiosInstance, AxiosResponse } from 'axios';
import axios from 'axios';
import { AxiosCanceler } from './axiosCancel';
import { isFunction } from '@/utils/is';
import { cloneDeep } from 'lodash-es';
import type { RequestOptions, CreateAxiosOptions, Result, UploadFileParams } from './types';
import { ContentTypeEnum } from '@/enums/httpEnum';

View File

@@ -18,6 +18,7 @@ import { CreateAxiosOptions, RequestOptions, Result } from './types';
import { useUserStoreWidthOut } from '@/store/modules/user';
import router from '@/router';
import { storage } from '@/utils/Storage';
import { encodeParams } from '@/utils/urlUtils';
const globSetting = useGlobSetting();
const urlPrefix = globSetting.urlPrefix || '';
@@ -60,7 +61,7 @@ const transform: AxiosTransform = {
}
// 这里 coderesultmessage为 后台统一的字段,需要修改为项目自己的接口返回格式
let { code, data, message } = response;
const { code, data, message } = response;
// 请求成功
const hasSuccess = response && Reflect.has(response, 'code') && code === ResultEnum.SUCCESS;
@@ -118,8 +119,11 @@ const transform: AxiosTransform = {
onNegativeClick: () => {},
});
break;
default:
console.log('unknown status code:' + code);
$message.error(errorMsg);
}
$message.error(errorMsg);
throw new Error(errorMsg);
},
@@ -277,6 +281,15 @@ function createAxios(opt?: Partial<CreateAxiosOptions>) {
export const http = createAxios();
// 导出
export const jumpExport = function (url, params) {
window.location.href =
urlPrefix +
url +
'?' +
encodeParams({ ...params, ...{ authorization: useUserStoreWidthOut().token } });
};
// 项目,多个不同 api 地址,直接在这里导出多个
// src/api ts 里面接口,就可以单独使用这个请求,
// import { httpTwo } from '@/utils/http/axios'

View File

@@ -158,6 +158,7 @@ export function filterRouter(routerMap: Array<any>) {
export const withInstall = <T>(component: T, alias?: string) => {
const comp = component as any;
comp.install = (app: App) => {
// @ts-ignore
app.component(comp.name || comp.displayName, component);
if (alias) {
app.config.globalProperties[alias] = component;
@@ -203,6 +204,7 @@ export function getTreeAll(data: any[]): any[] {
export function getDynamicProps<T, U>(props: T): Partial<U> {
const ret: Recordable = {};
// @ts-ignore
Object.keys(props).map((key) => {
ret[key] = unref((props as Recordable)[key]);
});

View File

@@ -80,6 +80,23 @@ export function isArray(val: any): val is Array<any> {
return val && Array.isArray(val);
}
/**
* @description: 是否为转为string的json
*/
export function isJsonString(value: any) {
try {
const toObj = JSON.parse(value);
if (toObj && typeof toObj === 'object') {
return true;
}
} catch {}
return false;
}
export function isNullObject(value: object) {
return isNullOrUnDef(value) || JSON.stringify(value) === '{}' || JSON.stringify(value) === '[]';
}
/**
* @description: 是否客户端
*/
@@ -116,3 +133,8 @@ export function isNullAndUnDef(val: unknown): val is null | undefined {
export function isNullOrUnDef(val: unknown): val is null | undefined {
return isUnDef(val) || isNull(val);
}
// 判断字串符是否以字母开头
export function isLetterBegin(str) {
return /^[A-z]/.test(str);
}

View File

@@ -22,3 +22,22 @@ export function setObjToUrlParams(baseUrl: string, obj: object): string {
}
return url;
}
export function encodeParams(obj) {
const arr = [];
for (const p in obj) {
// @ts-ignore
arr.push(encodeURIComponent(p) + '=' + encodeURIComponent(obj[p]));
}
return arr.join('&');
}
/**
* 获取文件后缀
*/
export function getFileExt(fileName: string) {
if (fileName === undefined || fileName === '') {
return ``;
}
return fileName.substring(fileName.lastIndexOf('.') + 1);
}

View File

@@ -0,0 +1,212 @@
import { FormItemRule } from 'naive-ui';
/**
* @description 表单验证封装
*/
export const validate = {
ip(rule: FormItemRule, value: any, callback: Function) {
// 支持通配符的ipv4正则
const ipv4Regex =
/^(?:[1-9]?[0-9]|1[0-9]{2}|2(?:[0-4][0-9]|5[0-5]))(?!.*?\.\*\.[*\d])(?:\.(?:(?:[1-9]?[0-9]|1[0-9]{2}|2(?:[0-4][0-9]|5[0-5]))|\*)){1,3}$/;
// Ipv6:
const ipv6Regex =
/^\s*((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){5}(((:[0-9A-Fa-f]{1,4}){1,2})|:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){4}(((:[0-9A-Fa-f]{1,4}){1,3})|((:[0-9A-Fa-f]{1,4})?:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){3}(((:[0-9A-Fa-f]{1,4}){1,4})|((:[0-9A-Fa-f]{1,4}){0,2}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){2}(((:[0-9A-Fa-f]{1,4}){1,5})|((:[0-9A-Fa-f]{1,4}){0,3}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){1}(((:[0-9A-Fa-f]{1,4}){1,6})|((:[0-9A-Fa-f]{1,4}){0,4}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(:(((:[0-9A-Fa-f]{1,4}){1,7})|((:[0-9A-Fa-f]{1,4}){0,5}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:)))(%.+)?\s*$/;
if (!value && !rule.required) {
callback();
}
if (!value) {
callback(new Error('请输入IP'));
} else if (!ipv4Regex.test(value) && !ipv6Regex.test(value)) {
callback(new Error('请输入正确的IP'));
} else {
callback();
}
},
//0-100百分比验证
percentage(rule: FormItemRule, value: any, callback: Function) {
const reg = /^([1-9]{1,2}$)|(^[0-9]{1,2}\.[0-9]{1,2}$)|100$/;
if (!value && !rule.required) {
callback(new Error('请输入比例'));
} else if (!reg.test(value)) {
callback(new Error('请输入0-100的数字'));
} else {
callback();
}
},
// 手机号 eg:138********,159********
phone(rule: FormItemRule, value: any, callback: Function) {
const regPhone = /^1([38][0-9]|4[579]|5[0-3,5-9]|6[6]|7[0135678]|9[89])\d{8}$/;
if (!value && !rule.required) {
callback();
} else if (!value) {
callback(new Error('请输入手机号码'));
} else if (!regPhone.test(value)) {
callback(new Error('手机号格式错误'));
} else {
callback();
}
},
// 用户名 eg:a123456
userName(rule: FormItemRule, value: any, callback: Function) {
const regUserName = /^[0-9a-zA-Z]{6,16}$/;
if (!value && !rule.required) {
callback(new Error('请输入登录账号'));
} else if (!regUserName.test(value)) {
callback(new Error('请输入6-16位由字母和数字组成的登录账号'));
} else {
callback();
}
},
// 账号
account(rule: FormItemRule, value: any, callback: Function) {
const regex = /^[\w_\d]{6,16}$/;
if (!value && !rule.required) {
callback();
} else if (!value) {
callback(new Error('请输入账号'));
} else if (!regex.test(value)) {
callback(new Error('请输入6-16位由字母、数字或下划线组成的账号'));
} else {
callback();
}
},
// 密码
password(rule: FormItemRule, value: any, callback: Function) {
const regPassword = /^(?![0-9]+$)(?![a-zA-Z]+$)[0-9A-Za-z]{6,18}$/;
if (!value && !rule.required) {
callback(new Error('请输入密码'));
} else if (!regPassword.test(value)) {
callback(new Error('密码格式错误必须包含6-18为字母和数字'));
} else {
callback();
}
},
// 邮箱
email(rule: FormItemRule, value: any, callback: Function) {
const regEmails = /^([A-Za-z0-9_\-\.])+\@([A-Za-z0-9_\-\.])+\.([A-Za-z]{2,4})$/;
// console.log('isRequired is: ', JSON.stringify(isRequired))
if (!value && !rule.required) {
callback();
} else if (!value) {
callback(new Error('请输入邮箱'));
} else if (!regEmails.test(value)) {
callback(new Error('邮箱格式错误'));
} else {
callback();
}
},
// 金额验证
amount(rule: FormItemRule, value: any, callback: Function) {
const regAmount = /(^[0-9]{1,10}$)|(^[0-9]{1,10}[\.]{1}[0-9]{1,2}$)/;
if (!value && !rule.required) {
callback();
} else if (!value) {
callback(new Error('请输入金额'));
} else if (!regAmount.test(value)) {
callback(new Error('金额格式错误最多允许输入10位整数及2位小数'));
} else {
callback();
}
},
// 身份证验证
idCard(rule: FormItemRule, value: any, callback: Function, isEnabled = true) {
const regIdCard =
/^[1-9]\d{7}((0\d)|(1[0-2]))(([0|1|2]\d)|3[0-1])\d{3}$|^[1-9]\d{5}[1-9]\d{3}((0\d)|(1[0-2]))(([0|1|2]\d)|3[0-1])\d{3}([0-9]|X|x)$/;
if (!isEnabled) {
callback();
} else if (!value && !rule.required) {
callback();
} else if (!value) {
callback(new Error('请输入身份证号'));
} else if (!regIdCard.test(value)) {
callback(new Error('身份证号码格式错误'));
} else {
callback();
}
},
// 银行卡验证
bank(rule: FormItemRule, value: any, callback: Function) {
const regBank = /^([1-9]{1})(\d{15}|\d{16}|\d{18})$/;
if (!value && !rule.required) {
callback();
} else if (!value) {
callback();
} else if (!regBank.test(value)) {
callback(new Error('银行卡号码格式错误'));
} else {
callback();
}
},
// 非零正整数验证
num(rule: FormItemRule, value: any, callback: Function) {
const reg = /^\+?[1-9][0-9]*$/;
if (!value && !rule.required) {
callback(new Error('请填写非零正整数'));
} else {
if (!reg.test(value)) {
callback(new Error('请输入非零的正整数'));
} else {
callback();
}
}
},
// 银行卡
bankCard(rule: FormItemRule, value: any, callback: Function) {
const regBankCard = /^(\d{16}|\d{19})$/;
if (value == '' && !rule.required) {
callback(new Error('请输入银行卡号'));
} else {
if (!regBankCard.test(value)) {
callback(new Error('银行卡号格式错误'));
} else {
callback();
}
}
},
// 固话格式
tel(rule: FormItemRule, value: any, callback: Function) {
const regTel = /^(0\d{2,3}-?)?\d{7,8}$/;
if (value == '' && !rule.required) {
callback(new Error('请输入座机号码'));
} else {
if (!regTel.test(value)) {
callback(new Error('座机号码格式错误'));
} else {
callback();
}
}
},
// QQ号码
qq(rule: FormItemRule, value: any, callback: Function) {
const regex = /^[1-9][0-9]{4,}$/;
if (!value && !rule.required) {
callback();
} else if (!value) {
callback(new Error('请输入QQ号码'));
} else {
if (!regex.test(value)) {
callback(new Error('QQ号码格式错误'));
} else {
callback();
}
}
},
// weibo号
weibo(rule: FormItemRule, value: any, callback: Function) {
const regex = /^[0-9a-zA-Z\u4e00-\u9fa5_-]*$/;
if (!value && !rule.required) {
callback();
} else if (!value) {
callback(new Error('请输入微博账号'));
} else {
if (!regex.test(value)) {
callback(new Error('微博号码格式错误'));
} else {
callback();
}
}
},
// 不验证
none(_rule: FormItemRule, _value: any, callback: Function) {
callback();
},
};

View File

@@ -7,7 +7,6 @@ let socket: WebSocket;
let isActive: boolean;
export function getSocket(): WebSocket {
console.log('socket:', socket);
if (socket === undefined) {
location.reload();
}
@@ -15,7 +14,6 @@ export function getSocket(): WebSocket {
}
export function getActive(): boolean {
console.log('isActive:', isActive);
return isActive;
}
@@ -85,7 +83,6 @@ export default (onMessage: Function) => {
event: SocketEnum.EventPing,
})
);
console.log('ping');
self.serverTimeoutObj = setTimeout(function () {
console.log('关闭服务');
socket.close();
@@ -133,7 +130,7 @@ export default (onMessage: Function) => {
socket.onmessage = function (event) {
isActive = true;
console.log('WebSocket:收到一条消息', event.data);
// console.log('WebSocket:收到一条消息', event.data);
let isHeart = false;
const message = JSON.parse(event.data);