vmf
Version:
vue micro service frame
1,768 lines (1,749 loc) • 78.5 kB
JavaScript
import Vue from 'vue';
export { default as Vue } from 'vue';
import Moment from 'dayjs';
import Md5 from 'md5';
import Router from 'vue-router';
import Vuex from 'vuex';
import VueMeta from 'vue-meta';
import Axios from 'axios';
export { default as Axios } from 'axios';
import Qs from 'qs';
import { MessageBox, Message, Loading } from 'element-ui';
async function getQRCode() {
const { default: qrcode } = await import(/* webpackChunkName: "qrcode" */ 'qrcode');
return qrcode;
}
async function toDataURL(...arg) {
const qrcode = await getQRCode();
if (arg.length <= 1) {
arg.push({
margin: 2,
scale: 30,
errorCorrectionLevel: 'H',
});
}
return qrcode.toDataURL.apply(null, arg);
}
var QRCode = {
getQRCode,
toDataURL,
};
/**
* Created by henian.xu on 2019/2/28.
* 字符串解码
*/
/* eslint-disable*/
const t = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
const a = [
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
62,
-1,
-1,
-1,
63,
52,
53,
54,
55,
56,
57,
58,
59,
60,
61,
-1,
-1,
-1,
-1,
-1,
-1,
-1,
0,
1,
2,
3,
4,
5,
6,
7,
8,
9,
10,
11,
12,
13,
14,
15,
16,
17,
18,
19,
20,
21,
22,
23,
24,
25,
-1,
-1,
-1,
-1,
-1,
-1,
26,
27,
28,
29,
30,
31,
32,
33,
34,
35,
36,
37,
38,
39,
40,
41,
42,
43,
44,
45,
46,
47,
48,
49,
50,
51,
-1,
-1,
-1,
-1,
-1,
];
function uniEncode(t) {
const e = [];
for (let n = 0; n < t.length; n++)
e[n] = (`00${t.charCodeAt(n).toString(16)}`).slice(-4);
return `\\u${e.join('\\u')}`;
}
function uniDecode(t) {
t = t = t.replace(/(\\)?\\u/gi, '%u').replace('%u0025', '%25');
const e = (t = unescape(t.toString().replace(/%2B/g, '+'))).match(/(%u00([0-9A-F]{2}))/gi);
if (e) {
for (let n = 0; n < e.length; n++) {
const a = e[n].substring(1, 3);
Number(`0x${a}`) >= 128 && (t = t.replace(e[n], a));
}
}
return (t = unescape(t.toString().replace(/%2B/g, '+')));
}
function base64Encode(e) {
let n;
let a;
let i;
let r;
let s;
let o;
for (i = e.length, a = 0, n = ''; a < i;) {
if (((r = 255 & e.charCodeAt(a++)), a == i)) {
(n += t.charAt(r >> 2)), (n += t.charAt((3 & r) << 4)), (n += '==');
break;
}
if (((s = e.charCodeAt(a++)), a == i)) {
(n += t.charAt(r >> 2)),
(n += t.charAt(((3 & r) << 4) | ((240 & s) >> 4))),
(n += t.charAt((15 & s) << 2)),
(n += '=');
break;
}
(o = e.charCodeAt(a++)),
(n += t.charAt(r >> 2)),
(n += t.charAt(((3 & r) << 4) | ((240 & s) >> 4))),
(n += t.charAt(((15 & s) << 2) | ((192 & o) >> 6))),
(n += t.charAt(63 & o));
}
return n;
}
function base64Decode(t) {
let e;
let n;
let i;
let r;
let s;
let o;
let l;
for (o = t.length, s = 0, l = ''; s < o;) {
do {
e = a[255 & t.charCodeAt(s++)];
} while (s < o && e == -1);
if (e == -1)
break;
do {
n = a[255 & t.charCodeAt(s++)];
} while (s < o && n == -1);
if (n == -1)
break;
l += String.fromCharCode((e << 2) | ((48 & n) >> 4));
do {
if ((i = 255 & t.charCodeAt(s++)) == 61)
return l;
i = a[i];
} while (s < o && i == -1);
if (i == -1)
break;
l += String.fromCharCode(((15 & n) << 4) | ((60 & i) >> 2));
do {
if ((r = 255 & t.charCodeAt(s++)) == 61)
return l;
r = a[r];
} while (s < o && r == -1);
if (r == -1)
break;
l += String.fromCharCode(((3 & i) << 6) | r);
}
return l;
}
function utf8Encode(t) {
let e;
let n;
let a;
let i;
for (e = '', a = t.length, n = 0; n < a; n++) {
(i = t.charCodeAt(n)) >= 1 && i <= 127
? (e += t.charAt(n))
: i > 2047
? ((e += String.fromCharCode(224 | ((i >> 12) & 15))),
(e += String.fromCharCode(128 | ((i >> 6) & 63))),
(e += String.fromCharCode(128 | ((i >> 0) & 63))))
: ((e += String.fromCharCode(192 | ((i >> 6) & 31))),
(e += String.fromCharCode(128 | ((i >> 0) & 63))));
}
return e;
}
function utf8Decode(t) {
let e;
let n;
let a;
let i;
let r;
let s;
for (e = '', a = t.length, n = 0; n < a;) {
switch ((i = t.charCodeAt(n++)) >> 4) {
case 0:
case 1:
case 2:
case 3:
case 4:
case 5:
case 6:
case 7:
e += t.charAt(n - 1);
break;
case 12:
case 13:
(r = t.charCodeAt(n++)), (e += String.fromCharCode(((31 & i) << 6) | (63 & r)));
break;
case 14:
(r = t.charCodeAt(n++)),
(s = t.charCodeAt(n++)),
(e += String.fromCharCode(((15 & i) << 12) | ((63 & r) << 6) | ((63 & s) << 0)));
}
}
return e;
}
function utf16to8(t) {
return t.replace(/\\x/g, '%');
}
function utf8to16(t) {
return t.replace(/%/g, '\\x');
}
var Decode = {
uniEncode,
uniDecode,
base64Encode,
base64Decode,
utf8Encode,
utf8Decode,
utf16to8,
utf8to16,
};
/**
* Created by henian.xu on 2019/11/1.
*
*/
function sortAtOrderNum(list) {
list.sort((prev, next) => prev.orderNum - next.orderNum || prev.id - next.id);
}
function sortTreeData(list) {
if (!Array.isArray(list) && typeof list !== 'object')
return;
list.forEach(item => {
if (item.children && item.children.length) {
sortTreeData(item.children);
}
});
sortAtOrderNum(list);
}
function listToTree(list, lv) {
// console.log('convertListToTree');
const res = [];
const parentNodeMap = {};
let minLv = 9999999;
list.forEach(item => {
// item.id 有值时才可能是父节点 (这个有数据问题 id 不应该不存在)
if (item.id) {
parentNodeMap[item.id] = item;
minLv = lv || (item.lv < minLv ? item.lv : minLv);
}
});
list.forEach(item => {
// item.lv = minLv 时是根节点
if (item.lv === minLv) {
res.push(item);
}
else {
const parentNode = parentNodeMap[item.parentId];
if (parentNode) {
parentNode.children = parentNode.children || [];
parentNode.children.push(item);
}
else {
console.error('此节点数据有问题', item);
}
}
});
// console.log(res);
sortTreeData(res);
// console.log(res);
return res;
}
var Convert = {
listToTree,
sortAtOrderNum,
sortTreeData,
};
const pickerOptions = {
shortcuts: [
{
text: '今天',
onClick(picker) {
const now = new Date();
picker.$emit('pick', [now, now]);
},
},
{
text: '昨天',
onClick(picker) {
const now = new Date();
now.setTime(now.getTime() - 3600 * 1000 * 24);
picker.$emit('pick', [now, now]);
},
},
{
text: '近一周',
onClick(picker) {
const end = new Date();
const start = new Date();
start.setTime(start.getTime() - 3600 * 1000 * 24 * 7);
picker.$emit('pick', [start, end]);
},
},
{
text: '近一个月',
onClick(picker) {
const end = new Date();
const start = new Date();
start.setTime(start.getTime() - 3600 * 1000 * 24 * 30);
picker.$emit('pick', [start, end]);
},
},
{
text: '近三个月',
onClick(picker) {
const end = new Date();
const start = new Date();
start.setTime(start.getTime() - 3600 * 1000 * 24 * 90);
picker.$emit('pick', [start, end]);
},
},
],
};
var CommonConfig = {
pickerOptions,
};
/**
* Created by henian.xu on 2019/3/19.
*
*/
const Device = (function Device() {
const { platform } = window.navigator;
const ua = window.navigator.userAgent;
const device = {
ua,
ios: false,
android: false,
androidChrome: false,
desktop: false,
windowsPhone: false,
iphone: false,
iphoneX: false,
ipod: false,
ipad: false,
edge: false,
ie: false,
firefox: false,
macos: false,
windows: false,
cordova: !!(window.cordova || window.phonegap),
phonegap: !!(window.cordova || window.phonegap),
electron: false,
webview: false,
standalone: false,
statusbar: false,
weixin: false,
pixelRatio: 1,
os: '',
osVersion: null,
needsStatusbarOverlay: () => false,
};
const screenWidth = window.screen.width;
const screenHeight = window.screen.height;
const windowsPhone = ua.match(/(Windows Phone);?[\s\/]+([\d.]+)?/); // eslint-disable-line
const android = ua.match(/(Android);?[\s\/]+([\d.]+)?/); // eslint-disable-line
const ipad = ua.match(/(iPad).*OS\s([\d_]+)/);
const ipod = ua.match(/(iPod)(.*OS\s([\d_]+))?/);
const iphone = !ipad && ua.match(/(iPhone\sOS|iOS)\s([\d_]+)/);
const iphoneX = iphone &&
((screenWidth === 375 && screenHeight === 812) || // X/XS
(screenWidth === 414 && screenHeight === 896)); // XR / XS Max
const ie = ua.indexOf('MSIE ') >= 0 || ua.indexOf('Trident/') >= 0;
const edge = ua.indexOf('Edge/') >= 0;
const firefox = ua.indexOf('Gecko/') >= 0 && ua.indexOf('Firefox/') >= 0;
const macos = platform === 'MacIntel';
const windows = platform === 'Win32';
const electron = ua.toLowerCase().indexOf('electron') >= 0;
const weixin = !!ua.match(/MicroMessenger/);
device.ie = ie;
device.edge = edge;
device.firefox = firefox;
device.weixin = weixin;
/* eslint-disable prefer-destructuring */
// Windows
if (windowsPhone) {
device.os = 'windowsPhone';
device.osVersion = windowsPhone[2];
device.windowsPhone = true;
}
// Android
if (android && !windows) {
device.os = 'android';
device.osVersion = android[2];
device.android = true;
device.androidChrome = ua.toLowerCase().indexOf('chrome') >= 0;
}
if (ipad || iphone || ipod) {
device.os = 'ios';
device.ios = true;
}
// iOS
if (iphone && !ipod) {
device.osVersion = iphone[2].replace(/_/g, '.');
device.iphone = true;
device.iphoneX = !!iphoneX;
}
if (ipad) {
device.osVersion = ipad[2].replace(/_/g, '.');
device.ipad = true;
}
if (ipod) {
device.osVersion = ipod[3] ? ipod[3].replace(/_/g, '.') : null;
device.iphone = true;
}
// iOS 8+ changed UA
if (device.ios && device.osVersion && ua.indexOf('Version/') >= 0) {
if (device.osVersion.split('.')[0] === '10') {
device.osVersion = ua
.toLowerCase()
.split('version/')[1]
.split(' ')[0];
}
}
// Webview
const webView = !!((iphone || ipad || ipod) && (ua.match(/.*AppleWebKit(?!.*Safari)/i) || window.navigator.standalone)) ||
(window.matchMedia && window.matchMedia('(display-mode: standalone)').matches);
device.webview = webView;
device.standalone = webView;
// Desktop
device.desktop = !(device.ios || device.android || device.windowsPhone) || electron;
if (device.desktop) {
device.electron = electron;
device.macos = macos;
device.windows = windows;
}
// Meta statusbar
const metaStatusbar = document.querySelector('meta[name="apple-mobile-web-app-status-bar-style"]');
// Check for status bar and fullscreen app mode
device.needsStatusbarOverlay = function needsStatusbarOverlay() {
if (device.desktop)
return false;
if (device.standalone && device.ios && metaStatusbar && metaStatusbar.content === 'black-translucent') {
return true;
}
if ((webView || (device.android && device.cordova)) &&
window.innerWidth * window.innerHeight === window.screen.width * window.screen.height) {
if (device.iphoneX && (window.orientation === 90 || window.orientation === -90)) {
return false;
}
return true;
}
return false;
};
device.statusbar = device.needsStatusbarOverlay();
// Pixel Ratio
device.pixelRatio = window.devicePixelRatio || 1;
// Export object
return device;
})();
/**
* Created by henian.xu on 2020/5/22.
*
*/
const NOOP = () => { };
const getType = (obj) => Object.prototype.toString.call(obj).slice(8, -1);
const { isArray } = Array;
const isFunction = (val) => typeof val === 'function';
const isString = (val) => typeof val === 'string';
const isBoolean = (val) => typeof val === 'boolean';
const isObject = (val) => val !== null && typeof val === 'object';
// const urlReg = new RegExp(/[a-zA-z]+:\/\/[^\s]*/);
const isUrl = (url) => /[a-zA-z]+:\/\/[^\s]*/.test(url);
function assert(condition, msg, module = 'vmf') {
if (!condition)
throw new Error(`[${module}] ${msg}`);
}
const isDef = (val) => val !== undefined;
const getUniqueId = (() => {
let autoIncrement = 0;
return (prefix = '') => {
autoIncrement += 1;
const cDate = new Date().getTime();
const offDate = new Date(2010, 1, 1).getTime();
const offset = cDate - offDate;
return prefix + parseFloat(`${offset}`).toString(16) + autoIncrement;
};
})();
function getKey() {
// const t = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'
const t = 'xxxxxxxx';
return t.replace(/[xy]/g, c => {
const r = (Math.random() * 16) | 0;
const v = c === 'x' ? r : (r & 0x3) | 0x8;
return v.toString(16);
});
}
/**
* 检查对象是否具有该属性。
*/
const hasOwn = (() => {
const { hasOwnProperty } = Object.prototype;
return (obj, key) => hasOwnProperty.call(obj, key);
})();
/**
* 是否 VNode
* @param node
*/
const isVNode = (node) => node !== null && typeof node === 'object' && hasOwn(node, 'componentOptions');
/**
* 防抖
* (与underscore 不同的是 immediate 为 true 时仅仅只是第一次触发会立即调用,
* 而 underscore immediate 为 true 时会把调用前置,既:触发会立即调用且在 delay 内再触发触发的不调用。
* 与 underscore 的不同导致不会严格按照 delay 时间间隔调用,因为正好在 delay 调用后触发会立即调用)
* @param func
* @param delay
* @param immediate
*/
function debounce(func, delay = 200, immediate = false) {
let timeout = null;
function debounced(...args) {
let callback;
const promise = new Promise(resolve => {
callback = resolve;
});
if (timeout)
clearTimeout(timeout);
if (immediate) {
const callNow = !timeout;
// 如果 timeout 为 false 立即调用,侧 setTimeout 就无需重复调用,否侧相反
timeout = setTimeout((now) => {
timeout = null;
if (now)
callback(func.apply(this, args));
}, delay, !callNow);
if (callNow)
callback(func.apply(this, args));
}
else {
timeout = setTimeout(() => callback(func.apply(this, args)), delay);
}
return promise;
}
debounced.cancel = () => {
clearTimeout(timeout);
timeout = null;
};
return debounced;
}
/**
* 节流
* underscore的实现
* @param func
* @param delay
* @param options
*/
function throttle(func, delay = 200, options = { leading: true, trailing: true }) {
let timeout;
let context;
let _args;
let previous = 0;
if (!options)
options = {};
const later = (resolve) => {
previous = options.leading === false ? 0 : new Date().getTime();
timeout = null;
resolve(func.apply(context, _args));
if (!timeout) {
context = null;
_args = null;
}
};
function throttled(...args) {
let callback;
const promise = new Promise(resolve => {
callback = resolve;
});
const now = new Date().getTime();
if (!previous && options.leading === false)
previous = now;
const remaining = delay - (now - previous);
context = this;
_args = args;
if (remaining <= 0 || remaining > delay) {
if (timeout) {
clearTimeout(timeout);
timeout = null;
}
previous = now;
callback(func.apply(context, _args));
if (!timeout) {
context = null;
_args = null;
}
}
else if (!timeout && options.trailing !== false) {
timeout = setTimeout(later, remaining, callback);
}
return promise;
}
throttled.cancel = () => {
clearTimeout(timeout);
previous = 0;
timeout = null;
context = null;
_args = null;
};
return throttled;
}
/**
* 整合异步
* @param func
*/
function integrateAsync(func) {
const promisesMap = {};
return async function integrate(...args) {
let options = [...Array.from(args)].pop();
if (!isObject(options))
options = {};
const groupKey = `${options.groupKey || 'default'}`;
const promises = promisesMap[groupKey];
if (promises) {
return new Promise((resolve, reject) => {
promises.push({ resolve, reject });
});
}
promisesMap[groupKey] = [];
let res = null;
try {
res = await func.apply(this, args);
}
catch (e) {
res = Promise.reject(e);
}
promisesMap[groupKey].forEach(({ resolve, reject }) => {
if (res instanceof Promise) {
res.then(r => {
resolve(r);
}).catch(e => {
reject(e);
});
}
else {
resolve(res);
}
});
delete promisesMap[groupKey];
return res;
};
}
function delayRun(func, delay, ...args) {
return setTimeout(() => func.apply(this, args), delay);
}
// 加载图片
function loadImg(src) {
return new Promise((resolve, reject) => {
const img = new Image();
// 当为线上图片时,需要设置 crossOrigin 属性;
if (src.indexOf('http') === 0)
img.crossOrigin = '*';
img.onload = () => {
resolve(img);
};
img.onerror = () => {
reject(img);
};
img.src = src;
});
}
function loadImgs(srcs) {
const lng = srcs.length;
let count = 0;
const imgs = [];
return new Promise((resolve, reject) => {
srcs.forEach((item, index) => {
loadImg(item)
.then(img => {
count += 1;
imgs[index] = img;
if (count >= lng) {
resolve(imgs);
}
})
.catch(_err => {
reject(_err);
});
});
});
}
// 合并表单项
function formModelMerge(formModel, obj) {
Object.keys(formModel).forEach(key => {
let item = obj[key];
if (typeof item === 'string') {
item = item.trim();
}
const isBooleanAndNumber = typeof item === 'boolean' || typeof item === 'number';
if (!(!isBooleanAndNumber &&
(item === undefined || (Array.isArray(item) && !item.length) || JSON.stringify(item) === '{}'))) {
formModel[key] = item;
}
});
}
/**
* 数值格式化
* @param value
* @param length
* @param strict
*/
function filterNumber(value = 0, length = 2, strict = false) {
if (value === null)
return '';
let numberList = [];
if (Number.isNaN(+value)) {
numberList = `${value}`.split('-');
}
else {
numberList = [`${value}`];
}
return numberList
.reduce((pre, cur) => {
let item = '';
if (!Number.isNaN(+cur) && cur !== '') {
item = (+cur).toFixed(length);
if (!strict) {
item = `${+item}`;
}
}
pre.push(item);
return pre;
}, [])
.join('-');
}
// 获取当前月份第一天
function getSysMonthFirstDayDate() {
const date = new Date();
return `${date.getFullYear()}-${(Array(2).join('0') + (date.getMonth() + 1)).slice(-2)}-01`;
}
// 获取当前年月日
function getSysDayDate() {
const date = new Date();
return `${date.getFullYear()}-${(Array(2).join('0') + (date.getMonth() + 1)).slice(-2)}-${(Array(2).join('0') + date.getDate()).slice(-2)}`;
}
// 获取当年第一个月
function getSysYearFirstMonthDate() {
const date = new Date();
return `${date.getFullYear()}-01`;
}
// 获取当前年月
function getSysMonthDate() {
const date = new Date();
return `${date.getFullYear()}-${(Array(2).join('0') + (date.getMonth() + 1)).slice(-2)}`;
}
// 表单校验
function validateForm(forms, showFirstErrorField = true) {
forms = forms.filter(form => form._isVue && form.validate);
let callback;
let count = 0;
const len = forms.length;
const invalidFields = [];
const formsMap = {};
let resultValid = true;
if (!forms.length)
return Promise.resolve(true);
const promise = new Promise((resolve, reject) => {
callback = (valid, invalidFieldMap, _uid) => {
if (!valid)
resultValid = false;
Object.keys(invalidFieldMap || {}).forEach(field => {
invalidFields.push(formsMap[_uid].fieldsMap[field]);
});
count += 1;
if (count !== len)
return;
if (!resultValid) {
if (showFirstErrorField && invalidFields.length) {
invalidFields[0].scrollIntoView(true);
}
// eslint-disable-next-line prefer-promise-reject-errors
reject({ errorField: invalidFields });
}
else {
resolve(true);
}
};
});
forms.forEach(form => {
formsMap[form._uid] = {
fieldsMap: form.fields.reduce((prev, curr) => {
prev[curr.prop] = curr.$el;
return prev;
}, {}),
};
form.validate((valid, invalidFieldMap) => callback(valid, invalidFieldMap, form._uid));
});
return promise;
}
// 取出对象中的深层属性
function pluckDeep(path, data, isCreate = false) {
const pathArr = `${path}`.split('.');
const lng = pathArr.length;
return pathArr.reduce((prev, next, index) => {
const now = prev[next];
if (now !== null && typeof now === 'object' && !Array.isArray(now)) {
return now;
}
if (!isCreate) {
if (index + 1 === lng) {
return now;
}
throw new Error(`${path}超出对像范围`);
}
prev[next] = {};
return prev[next];
}, data);
}
/* 转换 css 的值 */
function transformCssValue(val, unit = 'px') {
const int = parseFloat(val);
if (!int)
return '';
if (!+val)
return val;
return int + unit;
}
function makeEnum(obj) {
if (!isObject(obj))
throw new Error(`构建枚举的对象必须是 array 或 object`);
let list = obj;
if (!isArray(list)) {
list = Object.entries(obj).reduce((pre, cur) => {
const [code, key] = cur;
pre.push({ key, code });
return pre;
}, []);
}
const result = {};
Object.defineProperty(result, '_rawList', {
get() {
return list;
},
});
return list.reduce((pre, cur) => {
const { key, code, name } = cur;
if (!key || (!code && !name)) {
throw new Error(`构建枚举的数组项必须包含{key,[code|name]}`);
}
if (code) {
if (hasOwn(pre, code))
throw new Error(`有重复 code:${code} 值`);
Object.defineProperty(pre, code, { get: () => key });
}
else if (name) {
if (hasOwn(pre, name))
throw new Error(`有重复 name:${name} 值`);
Object.defineProperty(pre, name, { get: () => key });
}
if (hasOwn(pre, key))
throw new Error(`有重复 key:${key} 值`);
Object.defineProperty(pre, key, {
get() {
const res = { ...cur };
if (code)
res.code = code;
if (name || code)
res.name = name || code;
return res;
},
enumerable: true,
});
return pre;
}, result);
}
function dataURLtoBlob(dataurl, fileName = '') {
const arr = dataurl.split(',');
const mime = (arr[0].match(/:(.*?);/) || [])[1];
const bstr = atob(arr[1]);
let n = bstr.length;
const u8arr = new Uint8Array(n);
while (n) {
n -= 1;
u8arr[n] = bstr.charCodeAt(n);
}
const blob = new Blob([u8arr], { type: mime });
if (fileName) {
// ios 某些版本不支持 new File
// return new File([u8arr], fileName, { type: mime });
blob.name = fileName;
blob.lastModifiedDate = new Date();
}
return blob;
}
const createObjectURL = (() => {
const { createObjectURL: createUrl } = (window || {}).URL || {};
return (obj) => createUrl && createUrl(obj);
})();
function formatDuration(ms) {
if (ms < 0)
ms = -ms;
const time = {
day: Math.floor(ms / 86400000),
hour: Math.floor(ms / 3600000) % 24,
minute: Math.floor(ms / 60000) % 60,
second: Math.floor(ms / 1000) % 60,
};
const splitMap = {
day: ' ',
hour: ':',
minute: ':',
second: '',
};
return Object.entries(time)
.filter(val => val[1] !== 0 || val[0] === 'second' || val[0] === 'minute')
.map(([key, val]) => `${`${val}`.padStart(2, '0')}${splitMap[key]}`)
.join('');
}
const startCountdown = (() => {
let heartbeatId = null;
const timestampMap = {};
function heartbeat() {
heartbeatId = setInterval(() => {
const timestampList = Object.values(timestampMap);
if (heartbeatId && (!timestampList || !timestampList.length)) {
clearInterval(heartbeatId);
heartbeatId = null;
return;
}
timestampList.forEach(item => {
const { uid, active, callBack, finish } = item;
if (!active) {
delete timestampMap[uid];
return;
}
item.timestamp -= 1000;
if (item.timestamp > 0) {
callBack(formatDuration(item.timestamp), item.timestamp);
}
else {
item.active = false;
callBack(formatDuration(0), 0);
finish(0);
}
});
}, 1000);
}
function stop(uid) {
const item = timestampMap[uid];
if (!item)
return;
item.active = false;
}
return function handler(timestamp, callBack = NOOP, finish = NOOP) {
const uid = getUniqueId('countdown-');
timestampMap[uid] = {
uid,
active: true,
timestamp,
callBack,
finish,
};
if (!heartbeatId)
heartbeat();
return () => stop(uid);
};
})();
function addScript(src) {
if (!src)
return null;
const script = document.createElement('script');
script.type = 'text/javascript';
script.src = src;
document.body.appendChild(script);
return () => {
document.body.removeChild(script);
};
}
async function loadExternalScript(src, check, delay = 500) {
if (!src)
return Promise.reject(new Error('src 不能为空'));
if (isFunction(check)) {
const res = check();
if (res)
return res;
}
let checkCount = 0;
return new Promise((resolve, reject) => {
const unload = addScript(src);
if (!unload) {
reject(new Error('加载脚本失败'));
return;
}
if (isFunction(check)) {
const timerId = setInterval(() => {
const res = check();
if (res) {
resolve(res);
clearInterval(timerId);
}
else if (checkCount > 5) {
clearInterval(timerId);
unload();
reject(new Error(`已检查 5遍了,脚本未加载成功!`));
}
checkCount += 1;
}, delay);
}
});
}
const sizeMap = { b: 0, kb: 1, mb: 2, gb: 3 };
function fileSize(value = 0, format, isUpperCase = false) {
let val = +value || 0;
let unit = `${format || ''}`.toLocaleLowerCase();
if (val) {
if (unit) {
val = Array(sizeMap[unit] || 0)
.fill(null)
.reduce(pre => {
pre /= 1024;
return pre;
}, val);
}
else if (~~(val / 1024 ** 3)) {
val /= 1024 ** 3;
unit = 'gb';
}
else if (~~(val / 1024 ** 2)) {
val /= 1024 ** 2;
unit = 'mb';
}
else if (~~(val / 1024 ** 1)) {
val /= 1024 ** 1;
unit = 'kb';
}
else {
unit = 'b';
}
}
if (isUpperCase)
unit = unit.toLocaleUpperCase();
return `${+val.toFixed(2)}${unit}`;
}
/**
* Created by henian.xu on 2018/7/24.
* 常用校验类
*/
const emailReg = /[\w!#$%&'*+/=?^_`{|}~-]+(?:\.[\w!#$%&'*+/=?^_`{|}~-]+)*@(?:[\w](?:[\w-]*[\w])?\.)+[\w](?:[\w-]*[\w])?/;
// const mobileReg = /(^((166|198|199)|(15[^4])|(14[5-9])|17[0-3]|(17[5-8])|((13|18)[0-9]))\d{8}$)|(^(1749)\d{7}$)/;
const mobileReg = /^1\d{10}$/;
/**
* 确认密码验证
* @param rule
* @param value
* @param callback
*/
function againPassword(rule, value, callback /* , source, options */) {
if (value !== this.formModel.password) {
callback(new Error(rule.message));
}
else {
callback();
}
}
/**
* 邮箱验证
* @param rule
* @param value
* @param callback
* @param source
* @param options
*/
function email(rule, value, callback /* , source, options */) {
if (!emailReg.test(value)) {
callback(new Error(rule.message));
}
else {
callback();
}
}
/**
* 手机验证
* @param rule
* @param value
* @param callback
* @param source
* @param options
*/
function mobile(rule, value, callback /* , source, options */) {
if (!mobileReg.test(value)) {
callback(new Error(rule.message));
}
else {
callback();
}
}
/**
* 账号验证(手机号与邮箱)
* @param rule
* @param value
* @param callback
*/
function account(rule, value, callback) {
if (!emailReg.test(value) && !mobileReg.test(value)) {
callback(new Error(rule.message));
}
else {
callback();
}
}
function strictRequired(rule, value, callback) {
const { key = 'id', message } = rule;
let val = value;
if (isArray(value)) {
val = value.length;
}
else if (isObject(value)) {
val = value[key];
}
else if (isBoolean(value)) {
val = true;
}
if (val) {
callback();
}
else {
callback(new Error(message));
}
}
var Valid = {
againPassword,
email,
mobile,
account,
strictRequired,
};
/**
* Created by henian.xu on 2019/11/24.
*
*/
const $bus = new Vue();
let _router;
function setRouter(router) {
_router = router;
}
function getRouter() {
return _router;
}
var Runtime = {
setRouter,
getRouter,
};
/**
* Created by henian.xu on 2019/10/12.
*
*/
const GlobalVar = window.__GLOBAL_VAR__ || {};
GlobalVar.docTitle = document.title; // 默认页面标题
GlobalVar.isDev = process.env.NODE_ENV === 'development';
function mergeConfig(config) {
// TODO 写一个配置合并方法
GlobalVar.appConfig = {
...GlobalVar.appConfig,
...config,
};
}
const requireConfig = require.context('@', true, /\.(\/.[^/]*)?\/(config|config\/index)\.js$/);
requireConfig.keys().forEach((fileName) => {
const config = requireConfig(fileName);
if (!config)
return;
mergeConfig(config);
// console.log(config);
});
// console.log('config', requireConfig.keys());
var GlobalVar$1 = Vue.observable(GlobalVar);
/**
* Created by henian.xu on 2019/11/18.
*
*/
var Utils = /*#__PURE__*/Object.freeze({
__proto__: null,
QRCode: QRCode,
Decode: Decode,
Convert: Convert,
CommonConfig: CommonConfig,
Device: Device,
Valid: Valid,
Runtime: Runtime,
$bus: $bus,
GlobalVar: GlobalVar$1,
Md5: Md5,
NOOP: NOOP,
getType: getType,
isArray: isArray,
isFunction: isFunction,
isString: isString,
isBoolean: isBoolean,
isObject: isObject,
isUrl: isUrl,
assert: assert,
isDef: isDef,
getUniqueId: getUniqueId,
getKey: getKey,
hasOwn: hasOwn,
isVNode: isVNode,
debounce: debounce,
throttle: throttle,
integrateAsync: integrateAsync,
delayRun: delayRun,
loadImg: loadImg,
loadImgs: loadImgs,
formModelMerge: formModelMerge,
filterNumber: filterNumber,
getSysMonthFirstDayDate: getSysMonthFirstDayDate,
getSysDayDate: getSysDayDate,
getSysYearFirstMonthDate: getSysYearFirstMonthDate,
getSysMonthDate: getSysMonthDate,
validateForm: validateForm,
pluckDeep: pluckDeep,
transformCssValue: transformCssValue,
makeEnum: makeEnum,
dataURLtoBlob: dataURLtoBlob,
createObjectURL: createObjectURL,
formatDuration: formatDuration,
startCountdown: startCountdown,
addScript: addScript,
loadExternalScript: loadExternalScript,
fileSize: fileSize
});
Moment.extend(require('dayjs/plugin/duration'));
var Filter = (vue) => {
vue.filter('moment', (value, format = 'YYYY-MM-DD') => {
if (!value)
return '';
return Moment(value).format(format);
});
vue.filter('number', (value = 0, length = 2, strict = true) => {
const res = filterNumber(value, length, strict);
return strict ? res : +res;
});
vue.filter('price', (value = 0, length = 0, strict) => {
const amountFormat = `${GlobalVar$1.moduleConfig.amountFormat}`;
const signStrict = amountFormat.charAt(0) !== '+';
const arr = amountFormat.split('.');
const len = arr.length < 2 ? 0 : arr[1].length;
return filterNumber(value, length || len, isDef(strict) ? strict : signStrict);
});
/**
* imgCropping
* mini: 100
* small: 200
* little: 375
* normal: 750
* big: 900
* more: 1200
* super: 1920
*/
vue.filter('imgCropping', (value, params) => {
value += '';
const { moduleConfig: { imgCropping } = {} } = GlobalVar$1;
if (!value || !imgCropping || !params)
return value;
const imgCroppingList = isArray(imgCropping) ? imgCropping : [imgCropping];
const available = imgCroppingList.some(val => isString(val) && value.indexOf(val) === 0);
// console.log(available, params);
if (!available)
return value;
if (params && isString(params))
return `${value}_${params}`;
if (params && isObject(params)) {
// doc: https://help.aliyun.com/document_detail/44688.html?spm=a2c4g.11186623.6.1372.11313168wqiX8s
const keyMap = {
mode: 'm',
width: 'w',
height: 'h',
long: 'l',
short: 's',
limit: 'limit',
color: 'color',
};
const query = Object.entries(params)
.reduce((pre, [key, val]) => {
const k = keyMap[key];
if (k)
pre.push(`${k}_${val}`);
return pre;
}, ['image/resize'])
.join(',');
const fn = '?x-oss-process=';
return `${value}${fn}${query}`;
}
return `${value}_normal`;
});
vue.filter('fileSize', (value = 0, format, isUpperCase = false) => {
return fileSize(value, format, isUpperCase);
});
vue.filter('moneyFormat', (value = 0) => {
let val = value;
if (val === 0)
val = '0';
return `${val || ''}`.replace(/(?<!\.\d*)(\d)(?=(\d{3})+($|\.))/g, '$1,');
});
};
/**
* Created by henian.xu on 2023/6/12.
*
*/
function create$$t(vue) {
const old$t = vue.prototype.$t;
const { $i18n } = vue.prototype;
return function func(key, defaultValue, ...values) {
let res = '';
if (old$t) {
res = old$t.call(this, key, ...values);
}
else if ($i18n) {
res = $i18n._t(key, $i18n.locale, $i18n._getMessages(), this, ...values);
}
return res || defaultValue || '';
};
}
const $$t = create$$t(Vue);
var I18n = (vue) => {
vue.prototype.$$t = create$$t(vue);
};
let powerMap = null;
// 添加权限
function addPower(list = [], isClear = true) {
if (!powerMap || isClear) {
powerMap = {};
}
list.reduce((pre, cur) => {
pre[cur] = true;
return pre;
}, powerMap);
}
const hasPower = (value, bitAnd) => {
if (!powerMap || powerMap['*'])
return true;
let result = false;
// eslint-disable-next-line no-cond-assign
for (let i = 0, item; (item = value[i]); i += 1) {
result = powerMap[item];
if (!result) {
const itemArr = item.split(':');
const itemLen = itemArr.length - 1;
for (let n = 0; n < itemLen; n += 1) {
itemArr.length -= 1;
const key = `${itemArr.join(':')}*`;
result = powerMap[key];
if (result)
break;
}
}
// 处理关系
if (bitAnd) {
if (!result)
break;
}
else if (result)
break;
}
return result;
};
hasPower.addPower = addPower;
var Power = (vue) => {
Object.defineProperty(vue, '$power', {
get() {
return hasPower;
},
});
Object.defineProperty(vue.prototype, '$power', {
get() {
return hasPower;
},
});
};
/**
* Created by henian.xu on 2019/10/12.
*
*/
Vue.use(Router);
const initialMethodMap = {};
const routes = [];
async function initAppData(to) {
const { meta: { uniqueId }, } = to;
const initialMethod = initialMethodMap[uniqueId];
let res;
if (!initialMethod || initialMethod.isCalled)
return res;
res = await initialMethod();
console.log('初始路由数据完成', 222222);
initialMethod.isCalled = true;
return res;
}
const router = new Router({
mode: 'hash',
linkActiveClass: 'active',
linkExactActiveClass: 'exact-active',
...(GlobalVar$1.appConfig && GlobalVar$1.appConfig.ROUTER_DEFAULT_CONFIG),
});
router.beforeEach((to, from, next) => {
if (to.path === '/login') {
next();
return;
}
initAppData(to)
.then(() => {
next();
})
.catch(() => {
next();
})
.finally(() => {
// noop
});
});
// eslint-disable-next-line no-shadow
function markRoutes(routes, uniqueId) {
return routes.map(route => {
const res = {
...route,
meta: {
...route.meta,
uniqueId,
},
};
if (route.children && route.children.length)
res.children = markRoutes(route.children, uniqueId);
return res;
});
}
// TODO 检验重复的 route
function addRoutes(routesList, beforeEach) {
const uniqueId = getUniqueId('router-');
const routeList = markRoutes(routesList, uniqueId);
if (isFunction(beforeEach)) {
initialMethodMap[uniqueId] = beforeEach;
}
routes.splice(routes.length, 0, ...routeList);
router.addRoutes(routeList);
}
// 设置运行时 router
Runtime.setRouter(router);
/**
* Created by henian.xu on 2020/2/6.
* 该插件使 getters 中的方法 this 指向 {store,dispatch,commit}
* store: 当前根 store 实例
* dispatch: 当前模块 dispatch 方法
* commit: 当前模块 commit 方法
*/
function forEachModules(store, modules, path = []) {
Object.keys(modules).forEach(moduleKey => {
const module = modules[moduleKey];
const { namespaced, _rawModule: rawModule, _children: children, context, } = module;
const newPath = namespaced ? path.concat(moduleKey) : path;
const { getters = {} } = rawModule;
Object.keys(getters).forEach(key => {
const methodsKey = newPath.concat(key).join('/');
const { _vm: { _computedWatchers: computedWatchers = {} } = {} } = store;
if (computedWatchers[methodsKey]) {
computedWatchers[methodsKey].getter = () => {
return getters[key].call({
store,
dispatch: context.dispatch,
commit: context.commit,
}, // local context
context.state, // local state
context.getters, // local getters
store.state, // root state
store.getters);
};
}
});
forEachModules(store, children, newPath);
});
}
var gettersPlugin = (store) => forEachModules(store, store._modules);
/**
* Created by henian.xu on 2019/10/13.
*
*/
// import Global from './Global'; // 移到 vmf 模块下
Vue.use(Vuex);
function assertModule(store, path) {
const pathList = Array.isArray(path) ? path : [path];
for (let i = 0, len = pathList.length; i < len; i += 1) {
const key = pathList[i];
if (!hasOwn(store, key))
return;
store = store[key];
}
assert(false, `${pathList.join('.')} 模块/属性已经存在,所以不能注册!`, '@vmf/vuex');
}
const store = new Vuex.Store({
plugins: [gettersPlugin],
// 原始默认状态(是无法被 unregisterModule 注销的)
modules: {},
state: {},
getters: {},
mutations: {},
actions: {},
});
function registerModule(path, module, options) {
assertModule(store.state, path);
store.registerModule(path, module, options);
const rootModule = store._modules.root;
const { plugins } = rootModule._rawModule;
// apply plugins
plugins.forEach((plugin) => plugin(store));
}
function unregisterModule(path) {
store.unregisterModule(path);
}
/**
* Created by henian.xu on 2019/11/24.
*
*/
var Plugin = (vue) => {
const { appConfig = {} } = GlobalVar$1;
vue.prototype.$defaultImg = appConfig.DEFAULT_IMG;
vue.use(VueMeta, appConfig.VUE_META);
};
const recordRequestMap = {};
const recordLoadingMap = {};
let loadingInstance = null;
const vm = new Vue();
// 获取取消请求配置
function getExtendConfig(config) {
const { cancelToken } = config;
if (!cancelToken || !cancelToken.extendConfig)
return null;
return cancelToken.extendConfig;
}
// 记录请求用于处理重复请求
function recordRequest(config) {
const extendConfig = getExtendConfig(config);
if (!extendConfig)
return;
const { isRepeat, isCancelBefore, cancelSource } = extendConfig;
if (isRepeat)
return; // 可重复的请求不记录
const { url, baseURL } = config;
const recordKey = `${baseURL}${url}`;
const oldCancelSource = recordRequestMap[recordKey];
if (!oldCancelSource) {
// requestMap 无记录说明是新的请求
recordRequestMap[recordKey] = cancelSource;
}
else if (isCancelBefore) {
oldCancelSource.cancel(`因重复而取消之前的请求:${recordKey}`);
recordRequestMap[recordKey] = cancelSource; // 更新取消令牌
}
else {
cancelSource.cancel(`因重复而取消当前的请求:${recordKey}`);
}
}
// 删除已记录的请求
function removeRequestRecord(response) {
const { config } = response;
if (!config || !config.url)
return;
const { url, baseURL } = config;
const recordKey = new RegExp(`^${baseURL}`).test(url) ? url : `${baseURL}${url}`;
delete recordRequestMap[recordKey];
}
// 请求提示处理
function promptHandler(response) {
const { config, data: reslut } = response;
const extendConfig = getExtendConfig(config);
if (!extendConfig)
return Promise.resolve(response);
const { isHandleError, isSuccessTip } = extendConfig;
if (!reslut.success) {
if (isHandleError)
return Promise.resolve(response);
if (!isHandleError) {
// 统一处理失败请求提示
MessageBox.alert(reslut.msg || '', vm.$$t('vmf_friendly_reminder', '温馨提示'), {
type: 'error',
confirmButtonText: vm.$$t('vmf_confirm', '确定'),
});
}
return Promise.reject(response);
}
if (isSuccessTip) {
// 统一处理成功请求提示
Message.success({ message: reslut.msg || '', offset: 70 });
}
return Promise.resolve(response);
}
// loading处理
function recordRequestLoading(config) {
const extendConfig = getExtendConfig(config);
if (!extendConfig)
return;
const { isLoading } = extendConfig;
if (!isLoading)
return;
const { url, baseURL } = config;
const recordKey = `${baseURL}${url}`;
recordLoadingMap[recordKey] = true;
loadingInstance = Loading.service({
lock: true,
text: isString(isLoading) ? isLoading : vm.$$t('vmf_please_wait', '请稍候...'),
spinner: 'el-icon-loading',
background: 'rgba(0, 0, 0, 0.7)',
customClass: 'loading-show-ani',
});
// vm.$nprogress.start();
}
function removeRequestLoading(response) {
const { config } = response;
if (!config || !config.url)
return;
const { url, baseURL } = config;
const recordKey = new RegExp(`^${baseURL}`).test(url) ? url : `${baseURL}${url}`;
delete recordLoadingMap[recordKey];
const { length } = Object.keys(recordLoadingMap);
if (length || !loadingInstance)
return;
loadingInstance.close();
loadingInstance = null;
// vm.$nprogress.done();
}
const httpStatusHandler = {
isStatusProcessing: {
401: false,
},
401() {
console.log(401);
const router = Runtime.getRouter();
const { currentRoute } = router;
const query = {};
if (currentRoute.name === null && currentRoute.path === '/') {
const hash = (window.location.hash || '').replace(/^#/, '');
const [matchedComponent] = router.getMatchedComponents(hash);
if (matchedComponent.name !== 'ErrorPage') {
query.backUrl = hash;
}
}
if (this.isStatusProcessing[401] || currentRoute.name === 'login')
return;
this.isStatusProcessing[401] = true;
router
.replace({
path: '/login',
query,
})
.finally(() => {
this.isStatusProcessing[401] = false;
});
},
404( /* response */) {
/* console.log('404'); */
},
};
// http状态处理
function httpStatusCodeHandler(error) {
const { resp