前端代码
This commit is contained in:
@@ -0,0 +1,153 @@
|
||||
import { getVmParentByName } from '@/utils/util'
|
||||
|
||||
const FormTypes = {
|
||||
normal: 'normal',
|
||||
input: 'input',
|
||||
inputNumber: 'inputNumber',
|
||||
checkbox: 'checkbox',
|
||||
select: 'select',
|
||||
date: 'date',
|
||||
datetime: 'datetime',
|
||||
upload: 'upload',
|
||||
file: 'file',
|
||||
image: 'image',
|
||||
popup: 'popup',
|
||||
list_multi: 'list_multi',
|
||||
sel_search: 'sel_search',
|
||||
sel_search_async: 'sel_search_async',
|
||||
radio: 'radio',
|
||||
checkbox_meta: 'checkbox_meta',
|
||||
input_pop: 'input_pop',
|
||||
sel_depart: 'sel_depart',
|
||||
sel_user: 'sel_user',
|
||||
slot: 'slot',
|
||||
hidden: 'hidden'
|
||||
}
|
||||
const VALIDATE_NO_PASSED = Symbol('')
|
||||
export { FormTypes, VALIDATE_NO_PASSED }
|
||||
|
||||
/**
|
||||
* 获取指定的 $refs 对象
|
||||
* 有时候可能会遇到组件未挂载到页面中的情况,导致无法获取 $refs 中的某个对象
|
||||
* 这个方法可以等待挂载完成之后再返回 $refs 的对象,避免报错
|
||||
* @author sunjianlei
|
||||
**/
|
||||
export function getRefPromise (vm, name) {
|
||||
return new Promise((resolve) => {
|
||||
(function next () {
|
||||
const ref = vm.$refs[name]
|
||||
if (ref) {
|
||||
resolve(ref)
|
||||
} else {
|
||||
setTimeout(() => {
|
||||
next()
|
||||
}, 10)
|
||||
}
|
||||
})()
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 一次性验证主表单和所有的次表单
|
||||
* @param form 主表单 form 对象
|
||||
* @param cases 接收一个数组,每项都是一个JEditableTable实例
|
||||
* @returns {Promise<any>}
|
||||
* @author sunjianlei
|
||||
*/
|
||||
export function validateFormAndTables (form, cases) {
|
||||
if (!(form && typeof form.validateFields === 'function')) {
|
||||
throw new Error(`form 参数需要的是一个form对象,而传入的却是${typeof form}`)
|
||||
}
|
||||
|
||||
const options = {}
|
||||
return new Promise((resolve, reject) => {
|
||||
// 验证主表表单
|
||||
form.validateFields((err, values) => {
|
||||
err ? reject({ error: VALIDATE_NO_PASSED }) : resolve(values)
|
||||
})
|
||||
}).then(values => {
|
||||
Object.assign(options, { formValue: values })
|
||||
// 验证所有子表的表单
|
||||
return validateTables(cases)
|
||||
}).then(all => {
|
||||
Object.assign(options, { tablesValue: all })
|
||||
return Promise.resolve(options)
|
||||
}).catch(error => {
|
||||
return Promise.reject(error)
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 一次性验证主表单和所有的次表单(新版本)
|
||||
* @param form 主表单 form 对象
|
||||
* @param values
|
||||
* @param cases 接收一个数组,每项都是一个JEditableTable实例
|
||||
* @returns {Promise<any>}
|
||||
* @author sunjianlei
|
||||
*/
|
||||
export function validateFormModelAndTables (form, values, cases) {
|
||||
if (!(form && typeof form.validate === 'function')) {
|
||||
throw new Error(`form 参数需要的是一个form对象,而传入的却是${typeof form}`)
|
||||
}
|
||||
const options = {}
|
||||
return new Promise((resolve, reject) => {
|
||||
// 验证主表表单
|
||||
form.validate((valid) => {
|
||||
valid ? resolve(values) : reject({ error: VALIDATE_NO_PASSED })
|
||||
})
|
||||
}).then(values => {
|
||||
Object.assign(options, { formValue: values })
|
||||
// 验证所有子表的表单
|
||||
return validateTables(cases)
|
||||
}).then(all => {
|
||||
Object.assign(options, { tablesValue: all })
|
||||
return Promise.resolve(options)
|
||||
}).catch(error => {
|
||||
return Promise.reject(error)
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 验证并获取一个或多个表格的所有值
|
||||
* @param cases 接收一个数组,每项都是一个JEditableTable实例
|
||||
* @param deleteTempId 是否删除临时ID,如果设为true,行编辑就不返回新增行的ID,ID需要后台生成
|
||||
* @author sunjianlei
|
||||
*/
|
||||
export function validateTables (cases, deleteTempId) {
|
||||
if (!(cases instanceof Array)) {
|
||||
throw new Error(`'validateTables'函数的'cases'参数需要的是一个数组,而传入的却是${typeof cases}`)
|
||||
}
|
||||
return new Promise((resolve, reject) => {
|
||||
const tables = []
|
||||
let index = 0
|
||||
if (!cases || cases.length === 0) {
|
||||
resolve()
|
||||
}
|
||||
(function next () {
|
||||
const vm = cases[index]
|
||||
vm.getAll(true, deleteTempId).then(all => {
|
||||
tables[index] = all
|
||||
// 判断校验是否全部完成,完成返回成功,否则继续进行下一步校验
|
||||
if (++index === cases.length) {
|
||||
resolve(tables)
|
||||
} else {
|
||||
(
|
||||
next()
|
||||
)
|
||||
}
|
||||
}, error => {
|
||||
// 出现未验证通过的表单,不再进行下一步校验,直接返回失败并跳转到该表格
|
||||
if (error === VALIDATE_NO_PASSED) {
|
||||
// 尝试获取tabKey,如果在ATab组件内即可获取
|
||||
let paneKey
|
||||
const tabPane = getVmParentByName(vm, 'ATabPane')
|
||||
if (tabPane) {
|
||||
paneKey = tabPane.$vnode.key
|
||||
}
|
||||
reject({ error: VALIDATE_NO_PASSED, index, paneKey })
|
||||
}
|
||||
reject(error)
|
||||
})
|
||||
})()
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,106 @@
|
||||
/**
|
||||
* LunarFullCalendar 公共 js
|
||||
*
|
||||
* @version 1.0.0
|
||||
* @author sunjianlei
|
||||
*
|
||||
* */
|
||||
|
||||
import { getRefPromise } from '@/utils/JEditableTableUtil'
|
||||
|
||||
/* 日历的视图类型 */
|
||||
const calendarViewType = {
|
||||
month: 'month', // 月视图
|
||||
basicWeek: 'basicWeek', // 基础周视图
|
||||
basicDay: 'basicDay', // 基础天视图
|
||||
agendaWeek: 'agendaWeek', // 议程周视图
|
||||
agendaDay: 'agendaDay' // 议程天视图
|
||||
}
|
||||
|
||||
/* 定义默认视图 */
|
||||
const defaultView = calendarViewType.month
|
||||
|
||||
/* 定义日历默认配置 */
|
||||
const defaultSettings = {
|
||||
locale: 'zh-cn',
|
||||
// 按钮文字
|
||||
buttonText: {
|
||||
today: '今天',
|
||||
month: '月',
|
||||
week: '周',
|
||||
day: '日'
|
||||
},
|
||||
// 头部排列方式
|
||||
header: {
|
||||
left: 'prev,next, today',
|
||||
center: 'title',
|
||||
right: 'hide, custom, month,agendaWeek,agendaDay'
|
||||
},
|
||||
// 点击今天日列表图
|
||||
eventLimitClick: 'day',
|
||||
// 隐藏超出的事件
|
||||
eventLimit: true,
|
||||
// 设置每周开始日期为周日
|
||||
firstDay: 0,
|
||||
// 默认显示视图
|
||||
defaultView,
|
||||
timeFormat: 'H:mm',
|
||||
axisFormat: 'H:mm',
|
||||
// agenda视图下是否显示all-day
|
||||
allDaySlot: true,
|
||||
// agenda视图下all-day的显示文本
|
||||
allDayText: '全天',
|
||||
// 时区默认本地的
|
||||
timezone: 'local',
|
||||
// 周视图和日视同的左侧时间显示
|
||||
slotLabelFormat: 'HH:mm',
|
||||
// 设置第二天阈值
|
||||
nextDayThreshold: '00:00:00'
|
||||
}
|
||||
|
||||
/** 提供了一些增强方法 */
|
||||
const CalendarMixins = {
|
||||
data () {
|
||||
return {
|
||||
calenderCurrentViewType: defaultView
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
|
||||
getCalendarConfigEventHandler () {
|
||||
return {
|
||||
// 处理 view changed 事件
|
||||
viewRender: (view, element) => {
|
||||
const { type } = view
|
||||
|
||||
const lastViewType = this.calenderCurrentViewType
|
||||
this.calenderCurrentViewType = type
|
||||
|
||||
if (typeof this.handleViewRender === 'function') {
|
||||
this.handleViewRender(type, view, element)
|
||||
}
|
||||
|
||||
if (lastViewType !== this.calenderCurrentViewType && typeof this.handleViewChanged === 'function') {
|
||||
this.handleViewChanged(type, view, element)
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
/** 获取 LunarFullCalendar 实例,ref = baseCalendar */
|
||||
getCalendar (fn) {
|
||||
return getRefPromise(this, 'baseCalendar').then(fn)
|
||||
},
|
||||
|
||||
calendarEmit (name, data) {
|
||||
this.getCalendar(ref => ref.$emit(name, data))
|
||||
},
|
||||
|
||||
/** 强制重新加载所有的事件(日程) */
|
||||
calendarReloadEvents () {
|
||||
this.calendarEmit('reload-events')
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export { defaultSettings, calendarViewType, CalendarMixins }
|
||||
@@ -0,0 +1,248 @@
|
||||
import { SYS_BUTTON_AUTH, USER_AUTH } from '@/store/mutation-types'
|
||||
|
||||
export function disabledAuthFilter (code, formData) {
|
||||
if (nodeDisabledAuth(code, formData)) {
|
||||
return true
|
||||
} else {
|
||||
return globalDisabledAuth(code)
|
||||
}
|
||||
}
|
||||
|
||||
function nodeDisabledAuth (code, formData) {
|
||||
let permissionList = []
|
||||
try {
|
||||
if (formData) {
|
||||
const bpmList = formData.permissionList
|
||||
permissionList = bpmList.filter(item => item.type + '' === '2')
|
||||
// for (let bpm of bpmList) {
|
||||
// if(bpm.type == '2') {
|
||||
// permissionList.push(bpm);
|
||||
// }
|
||||
// }
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
} catch (e) {
|
||||
// console.log("页面权限异常----", e);
|
||||
}
|
||||
if (permissionList.length === 0) {
|
||||
return false
|
||||
}
|
||||
|
||||
console.log('流程节点页面权限禁用--NODE--开始')
|
||||
const permissions = []
|
||||
for (const item of permissionList) {
|
||||
if (item.type + '' === '2') {
|
||||
permissions.push(item.action)
|
||||
}
|
||||
}
|
||||
// console.log("页面权限----"+code);
|
||||
if (!permissions.includes(code)) {
|
||||
return false
|
||||
} else {
|
||||
for (const item2 of permissionList) {
|
||||
if (code === item2.action) {
|
||||
console.log('流程节点页面权限禁用--NODE--生效')
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
function globalDisabledAuth (code) {
|
||||
const permissionList = []
|
||||
const allPermissionList = []
|
||||
|
||||
// let authList = Vue.ls.get(USER_AUTH);
|
||||
const authList = JSON.parse(sessionStorage.getItem(USER_AUTH) || '[]')
|
||||
for (const auth of authList) {
|
||||
if (auth.type + '' === '2') {
|
||||
permissionList.push(auth)
|
||||
}
|
||||
}
|
||||
// console.log("页面禁用权限--Global--",sessionStorage.getItem(SYS_BUTTON_AUTH));
|
||||
const allAuthList = JSON.parse(sessionStorage.getItem(SYS_BUTTON_AUTH) || '[]')
|
||||
for (const gauth of allAuthList) {
|
||||
if (gauth.type + '' === '2') {
|
||||
allPermissionList.push(gauth)
|
||||
}
|
||||
}
|
||||
// 设置全局配置是否有命中
|
||||
let gFlag = false// 禁用命中
|
||||
let invalidFlag = false// 无效命中
|
||||
if (allPermissionList && allPermissionList.length > 0) {
|
||||
for (const itemG of allPermissionList) {
|
||||
if (code === itemG.action) {
|
||||
if (itemG.status + '' === '0') {
|
||||
invalidFlag = true
|
||||
break
|
||||
} else {
|
||||
gFlag = true
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (invalidFlag) {
|
||||
return false
|
||||
}
|
||||
if (permissionList === null || permissionList === '' || permissionList === undefined || permissionList.length <= 0) {
|
||||
return gFlag
|
||||
}
|
||||
const permissions = []
|
||||
for (const item of permissionList) {
|
||||
if (item.type + '' === '2') {
|
||||
permissions.push(item.action)
|
||||
}
|
||||
}
|
||||
// console.log("页面禁用权限----"+code);
|
||||
if (!permissions.includes(code)) {
|
||||
return gFlag
|
||||
} else {
|
||||
for (const item2 of permissionList) {
|
||||
if (code === item2.action) {
|
||||
gFlag = false
|
||||
}
|
||||
}
|
||||
return gFlag
|
||||
}
|
||||
}
|
||||
|
||||
export function colAuthFilter (columns, pre) {
|
||||
const authList = getNoAuthCols(pre)
|
||||
return columns.filter(item => {
|
||||
return hasColoum(item, authList)
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 【子表行编辑】实现两个功能:
|
||||
* 1、隐藏JEditableTable无权限的字段
|
||||
* 2、禁用JEditableTable无权限的字段
|
||||
* @param columns
|
||||
* @param pre
|
||||
* @returns {*}
|
||||
*/
|
||||
export function colAuthFilterJEditableTable (columns, pre) {
|
||||
const authList = getAllShowAndDisabledAuthCols(pre)
|
||||
return columns.filter(item => {
|
||||
let oneAuth = authList.find(auth => {
|
||||
return auth.action === pre + item.key
|
||||
})
|
||||
if (!oneAuth) {
|
||||
return true
|
||||
}
|
||||
|
||||
// 代码严谨处理,防止一个授权标识,配置多次
|
||||
if (oneAuth instanceof Array) {
|
||||
oneAuth = oneAuth[0]
|
||||
}
|
||||
|
||||
// 禁用逻辑
|
||||
if (oneAuth.type + '' === '2' && !oneAuth.isAuth) {
|
||||
item.disabled = true
|
||||
return true
|
||||
}
|
||||
// 隐藏逻辑逻辑
|
||||
return !(oneAuth.type + '' === '1' && !oneAuth.isAuth)
|
||||
})
|
||||
}
|
||||
|
||||
function hasColoum (item, authList) {
|
||||
return !authList.includes(item.dataIndex)
|
||||
}
|
||||
|
||||
// 权限无效时不做控制,有效时控制,只能控制 显示不显示
|
||||
// 根据授权码前缀获取未授权的列信息
|
||||
export function getNoAuthCols (pre) {
|
||||
if (!pre || pre.length === 0) {
|
||||
return []
|
||||
}
|
||||
const permissionList = []
|
||||
const allPermissionList = []
|
||||
|
||||
// let authList = Vue.ls.get(USER_AUTH);
|
||||
const authList = JSON.parse(sessionStorage.getItem(USER_AUTH) || '[]')
|
||||
for (const auth of authList) {
|
||||
// 显示策略,有效状态
|
||||
if (auth.type + '' === '1' && startWith(auth.action, pre)) {
|
||||
permissionList.push(substrPre(auth.action, pre))
|
||||
}
|
||||
}
|
||||
// console.log("页面禁用权限--Global--",sessionStorage.getItem(SYS_BUTTON_AUTH));
|
||||
const allAuthList = JSON.parse(sessionStorage.getItem(SYS_BUTTON_AUTH) || '[]')
|
||||
for (const gauth of allAuthList) {
|
||||
// 显示策略,有效状态
|
||||
if (gauth.type + '' === '1' && gauth.status + '' === '1' && startWith(gauth.action, pre)) {
|
||||
allPermissionList.push(substrPre(gauth.action, pre))
|
||||
}
|
||||
}
|
||||
return allPermissionList.filter(item => {
|
||||
return !permissionList.includes(item)
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 将Online的行编辑按钮权限,添加至本地存储
|
||||
*/
|
||||
export function addOnlineBtAuth2Storage (pre, authList) {
|
||||
const allAuthList = JSON.parse(sessionStorage.getItem(SYS_BUTTON_AUTH) || '[]')
|
||||
const newAuthList = allAuthList.filter(item => {
|
||||
if (!item.action) {
|
||||
return true
|
||||
}
|
||||
return item.action.indexOf(pre) < 0
|
||||
})
|
||||
if (authList && authList.length > 0) {
|
||||
for (const item of authList) {
|
||||
newAuthList.push({
|
||||
action: pre + item,
|
||||
type: 1,
|
||||
status: 1
|
||||
})
|
||||
}
|
||||
const temp = JSON.parse(sessionStorage.getItem(USER_AUTH) || '[]')
|
||||
const newArr = temp.filter(item => {
|
||||
if (!item.action) {
|
||||
return true
|
||||
}
|
||||
return item.action.indexOf(pre) < 0 || authList.indexOf(item.action.replace(pre, '')) < 0
|
||||
})
|
||||
sessionStorage.setItem(USER_AUTH, JSON.stringify(newArr))
|
||||
}
|
||||
sessionStorage.setItem(SYS_BUTTON_AUTH, JSON.stringify(newAuthList))
|
||||
}
|
||||
|
||||
/**
|
||||
* 额外增加方法【用于行编辑组件】
|
||||
* date: 2020-04-05
|
||||
* author: scott
|
||||
* @param pre
|
||||
* @returns {*[]}
|
||||
*/
|
||||
function getAllShowAndDisabledAuthCols (pre) {
|
||||
// 用户拥有的权限
|
||||
const userAuthList = JSON.parse(sessionStorage.getItem(USER_AUTH) || '[]')
|
||||
// 全部权限配置
|
||||
const allAuthList = JSON.parse(sessionStorage.getItem(SYS_BUTTON_AUTH) || '[]')
|
||||
|
||||
return allAuthList.map(function (item) {
|
||||
const hasAuthArray = userAuthList.filter(u => u.action === item.action)
|
||||
if (hasAuthArray && hasAuthArray.length > 0) {
|
||||
item.isAuth = true
|
||||
}
|
||||
return item
|
||||
})
|
||||
}
|
||||
|
||||
function startWith (str, pre) {
|
||||
if (pre == null || pre + '' === '' || str == null || str + '' === '' || str.length === 0 || pre.length > str.length) {
|
||||
return false
|
||||
}
|
||||
return str.substr(0, pre.length) + '' === pre + ''
|
||||
}
|
||||
|
||||
function substrPre (str, pre) {
|
||||
return str.substr(pre.length)
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
const VueAxios = {
|
||||
vm: {},
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
install (Vue, router = {}, instance) {
|
||||
if (this.installed) {
|
||||
return
|
||||
}
|
||||
this.installed = true
|
||||
|
||||
if (!instance) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.error('You have to install axios')
|
||||
return
|
||||
}
|
||||
|
||||
Vue.axios = instance
|
||||
|
||||
Object.defineProperties(Vue.prototype, {
|
||||
axios: {
|
||||
get: function get () {
|
||||
return instance
|
||||
}
|
||||
},
|
||||
$http: {
|
||||
get: function get () {
|
||||
return instance
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
export {
|
||||
VueAxios
|
||||
// eslint-disable-next-line no-undef
|
||||
// instance as axios
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
// 判断是否IE<11浏览器
|
||||
export function isIE () {
|
||||
return navigator.userAgent.indexOf('compatible') > -1 && navigator.userAgent.indexOf('MSIE') > -1
|
||||
}
|
||||
|
||||
export function isIE11 () {
|
||||
return navigator.userAgent.indexOf('Trident') > -1 && navigator.userAgent.indexOf('rv:11.0') > -1
|
||||
}
|
||||
|
||||
// 判断是否IE的Edge浏览器
|
||||
export function isEdge () {
|
||||
return navigator.userAgent.indexOf('Edge') > -1 && !isIE()
|
||||
}
|
||||
|
||||
export function getIEVersion () {
|
||||
const userAgent = navigator.userAgent // 取得浏览器的userAgent字符串
|
||||
const isIEFlag = isIE()
|
||||
const isIE11Flag = isIE11()
|
||||
const isEdgeFlag = isEdge()
|
||||
|
||||
if (isIEFlag) {
|
||||
const reIE = new RegExp('MSIE (\\d+\\.\\d+);')
|
||||
reIE.test(userAgent)
|
||||
const fIEVersion = parseFloat(RegExp.$1)
|
||||
if (fIEVersion === 7 || fIEVersion === 8 || fIEVersion === 9 || fIEVersion === 10) {
|
||||
return fIEVersion
|
||||
} else {
|
||||
return 6// IE版本<7
|
||||
}
|
||||
} else if (isEdgeFlag) {
|
||||
return 'edge'
|
||||
} else if (isIE11Flag) {
|
||||
return 11
|
||||
} else {
|
||||
return -1
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
import { getFileAccessHttpUrl } from '@/api/manage'
|
||||
const getFileName = (path) => {
|
||||
if (path.lastIndexOf('\\') >= 0) {
|
||||
const reg = new RegExp('\\\\', 'g')
|
||||
path = path.replace(reg, '/')
|
||||
}
|
||||
return path.substring(path.lastIndexOf('/') + 1)
|
||||
}
|
||||
|
||||
const uidGenerator = () => {
|
||||
return '-' + parseInt(Math.random() * 10000 + 1, 10)
|
||||
}
|
||||
|
||||
const getFilePaths = (uploadFiles) => {
|
||||
const arr = []
|
||||
if (!uploadFiles) {
|
||||
return ''
|
||||
}
|
||||
for (let a = 0; a < uploadFiles.length; a++) {
|
||||
arr.push(uploadFiles[a].response.message)
|
||||
}
|
||||
if (arr && arr.length > 0) {
|
||||
return arr.join(',')
|
||||
}
|
||||
return ''
|
||||
}
|
||||
|
||||
const getUploadFileList = (paths) => {
|
||||
if (!paths) {
|
||||
return []
|
||||
}
|
||||
const fileList = []
|
||||
const arr = paths.split(',')
|
||||
for (let a = 0; a < arr.length; a++) {
|
||||
if (!arr[a]) {
|
||||
continue
|
||||
} else {
|
||||
fileList.push({
|
||||
uid: uidGenerator(),
|
||||
name: getFileName(arr[a]),
|
||||
status: 'done',
|
||||
url: getFileAccessHttpUrl(arr[a]),
|
||||
response: {
|
||||
status: 'history',
|
||||
message: arr[a]
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
return fileList
|
||||
}
|
||||
export { getFilePaths, getUploadFileList }
|
||||
@@ -0,0 +1,22 @@
|
||||
/*
|
||||
*
|
||||
* 这里填写用户自定义的表达式
|
||||
* 可用在Online表单的默认值表达式中使用
|
||||
* 需要外部使用的变量或方法一定要 export,否则无法识别
|
||||
* 示例:
|
||||
* export const name = '张三'; // const 是常量
|
||||
* export let age = 17; // 看情况 export const 还是 let ,两者都可正常使用
|
||||
* export function content(arg) { // export 方法,可传参数,使用时要加括号,值一定要return回去,可以返回Promise
|
||||
* return 'content' + arg;
|
||||
* }
|
||||
* export const address = (arg) => content(arg) + ' | 北京市'; // export 箭头函数也可以
|
||||
*
|
||||
*/
|
||||
|
||||
/** 字段默认值官方示例:获取地址 */
|
||||
export function demoFieldDefValGetAddress (arg) {
|
||||
if (!arg) {
|
||||
arg = '朝阳区'
|
||||
}
|
||||
return `北京市 ${arg}`
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
import enquireJs from 'enquire.js'
|
||||
|
||||
const enquireScreen = function (call) {
|
||||
// tablet
|
||||
const handler = {
|
||||
match: function () {
|
||||
call && call(0)
|
||||
},
|
||||
unmatch: function () {
|
||||
call && call(-1)
|
||||
}
|
||||
}
|
||||
// mobile
|
||||
const handler2 = {
|
||||
match: () => {
|
||||
call && call(1)
|
||||
}
|
||||
}
|
||||
enquireJs.register('screen and (max-width: 1087.99px)', handler)
|
||||
enquireJs.register('screen and (max-width: 767.99px)', handler2)
|
||||
}
|
||||
|
||||
export default enquireScreen
|
||||
@@ -0,0 +1,16 @@
|
||||
import { axios } from '@/utils/request'
|
||||
|
||||
/**
|
||||
* 获取RSA公钥
|
||||
* @returns {*}
|
||||
*/
|
||||
export function getRSAPublicKey () {
|
||||
return axios({
|
||||
url: `/sys/getRSAPublicKey`,
|
||||
method: 'get',
|
||||
timeout: 5000,
|
||||
headers: {
|
||||
'Content-Type': 'application/json;charset=UTF-8'
|
||||
}
|
||||
})
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,128 @@
|
||||
import md5 from 'md5'
|
||||
// 签名密钥串(前后端要一致,正式发布请自行修改)
|
||||
const signatureSecret = 'dd05f1c54d63749eda95f9fa6d49v442a'
|
||||
|
||||
export default class signMd5Utils {
|
||||
/**
|
||||
* json参数升序
|
||||
* @param jsonObj 发送参数
|
||||
*/
|
||||
|
||||
static sortAsc (jsonObj) {
|
||||
const arr = []
|
||||
let num = 0
|
||||
for (const i in jsonObj) {
|
||||
arr[num] = i
|
||||
num++
|
||||
}
|
||||
const sortArr = arr.sort()
|
||||
const sortObj = {}
|
||||
for (const i in sortArr) {
|
||||
sortObj[sortArr[i]] = jsonObj[sortArr[i]]
|
||||
}
|
||||
return sortObj
|
||||
}
|
||||
|
||||
/**
|
||||
* @param url 请求的url,应该包含请求参数(url的?后面的参数)
|
||||
* @param requestParams 请求参数(POST的JSON参数)
|
||||
* @returns {string} 获取签名
|
||||
*/
|
||||
static getSign (url, requestParams) {
|
||||
const urlParams = this.parseQueryString(url)
|
||||
const jsonObj = this.mergeObject(urlParams, requestParams)
|
||||
// console.log("sign jsonObj: ",jsonObj)
|
||||
const requestBody = this.sortAsc(jsonObj)
|
||||
console.log('sign requestBody: ', requestBody)
|
||||
return md5(JSON.stringify(requestBody) + signatureSecret).toUpperCase()
|
||||
}
|
||||
|
||||
/**
|
||||
* @param url 请求的url
|
||||
* @returns {{}} 将url中请求参数组装成json对象(url的?后面的参数)
|
||||
*/
|
||||
static parseQueryString (url) {
|
||||
const urlReg = /^[^\?]+\?([\w\W]+)$/
|
||||
const paramReg = /([^&=]+)=([\w\W]*?)(&|$|#)/g
|
||||
const urlArray = urlReg.exec(url)
|
||||
const result = {}
|
||||
|
||||
// 获取URL上最后带逗号的参数变量 sys/dict/getDictItems/sys_user,realname,username
|
||||
// 【这边条件没有encode】带条件参数例子:/sys/dict/getDictItems/sys_user,realname,id,username!='admin'%20order%20by%20create_time
|
||||
let lastpathVariable = url.substring(url.lastIndexOf('/') + 1)
|
||||
if (lastpathVariable.includes(',')) {
|
||||
if (lastpathVariable.includes('?')) {
|
||||
lastpathVariable = lastpathVariable.substring(0, lastpathVariable.indexOf('?'))
|
||||
}
|
||||
// 解决Sign 签名校验失败 #2728
|
||||
result['x-path-variable'] = decodeURIComponent(lastpathVariable)
|
||||
}
|
||||
if (urlArray && urlArray[1]) {
|
||||
const paramString = urlArray[1]; let paramResult
|
||||
while ((paramResult = paramReg.exec(paramString)) != null) {
|
||||
// 数字值转为string类型,前后端加密规则保持一致
|
||||
if (this.myIsNaN(paramResult[2])) {
|
||||
paramResult[2] = paramResult[2].toString()
|
||||
}
|
||||
result[paramResult[1]] = paramResult[2]
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
/**
|
||||
* @returns {*} 将两个对象合并成一个
|
||||
*/
|
||||
static mergeObject (objectOne, objectTwo) {
|
||||
if (objectTwo && Object.keys(objectTwo).length > 0) {
|
||||
for (const key in objectTwo) {
|
||||
if (Object.prototype.hasOwnProperty.call(objectTwo, key) === true) {
|
||||
// 数字值转为string类型,前后端加密规则保持一致
|
||||
if (this.myIsNaN(objectTwo[key])) {
|
||||
objectTwo[key] = objectTwo[key].toString()
|
||||
}
|
||||
objectOne[key] = objectTwo[key]
|
||||
}
|
||||
}
|
||||
}
|
||||
return objectOne
|
||||
}
|
||||
|
||||
static urlEncode (param, key, encode) {
|
||||
if (param == null) return ''
|
||||
let paramStr = ''
|
||||
const t = typeof (param)
|
||||
if (t === 'string' || t === 'number' || t === 'boolean') {
|
||||
paramStr += '&' + key + '=' + ((encode == null || encode) ? encodeURIComponent(param) : param)
|
||||
} else {
|
||||
for (const i in param) {
|
||||
const k = key == null ? i : key + (param instanceof Array ? '[' + i + ']' : '.' + i)
|
||||
paramStr += this.urlEncode(param[i], k, encode)
|
||||
}
|
||||
}
|
||||
return paramStr
|
||||
};
|
||||
|
||||
static getDateTimeToString () {
|
||||
const date_ = new Date()
|
||||
const year = date_.getFullYear()
|
||||
let month = date_.getMonth() + 1
|
||||
let day = date_.getDate()
|
||||
if (month < 10) month = '0' + month
|
||||
if (day < 10) day = '0' + day
|
||||
let hours = date_.getHours()
|
||||
let mins = date_.getMinutes()
|
||||
let secs = date_.getSeconds()
|
||||
const msecs = date_.getMilliseconds()
|
||||
if (hours < 10) hours = '0' + hours
|
||||
if (mins < 10) mins = '0' + mins
|
||||
if (secs < 10) secs = '0' + secs
|
||||
if (msecs < 10) secs = '0' + msecs
|
||||
return year + '' + month + '' + day + '' + hours + '' + mins + '' + secs
|
||||
}
|
||||
|
||||
// true:数值型的,false:非数值型
|
||||
static myIsNaN (value) {
|
||||
return typeof value === 'number' && !isNaN(value)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
import Vue from 'vue'
|
||||
import * as dayjs from 'dayjs'
|
||||
|
||||
Vue.filter('NumberFormat', function (value) {
|
||||
if (!value) {
|
||||
return '0'
|
||||
}
|
||||
// 将整数部分逢三一断
|
||||
return value.toString().replace(/(\d)(?=(?:\d{3})+$)/g, '$1,')
|
||||
})
|
||||
|
||||
Vue.filter('dayjs', function (dataStr, pattern = 'YYYY-MM-DD HH:mm:ss') {
|
||||
return dayjs(dataStr).format(pattern)
|
||||
})
|
||||
|
||||
Vue.filter('moment', function (dataStr, pattern = 'YYYY-MM-DD HH:mm:ss') {
|
||||
return dayjs(dataStr).format(pattern)
|
||||
})
|
||||
|
||||
/** 字符串超长截取省略号显示 */
|
||||
Vue.filter('ellipsis', function (value, vlength = 25) {
|
||||
if (!value) {
|
||||
return ''
|
||||
}
|
||||
if (value.length > vlength) {
|
||||
return value.slice(0, vlength) + '...'
|
||||
}
|
||||
return value
|
||||
})
|
||||
@@ -0,0 +1,196 @@
|
||||
import { USER_AUTH, SYS_BUTTON_AUTH } from '@/store/mutation-types'
|
||||
|
||||
const hasPermission = {
|
||||
install (Vue) {
|
||||
Vue.directive('has', {
|
||||
inserted: (el, binding, vnode) => {
|
||||
// console.time()
|
||||
// 节点权限处理,如果命中则不进行全局权限处理
|
||||
if (!filterNodePermission(el, binding, vnode)) {
|
||||
filterGlobalPermission(el, binding, vnode)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 流程节点权限控制
|
||||
*/
|
||||
export function filterNodePermission (el, binding, vnode) {
|
||||
const permissionList = []
|
||||
try {
|
||||
const obj = vnode.context.$props.formData
|
||||
if (obj) {
|
||||
const bpmList = obj.permissionList
|
||||
for (const bpm of bpmList) {
|
||||
if (bpm.type + '' !== '2') {
|
||||
permissionList.push(bpm)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
} catch (e) {
|
||||
// console.log("页面权限异常----", e);
|
||||
}
|
||||
if (permissionList === null || permissionList === '' || permissionList === undefined || permissionList.length <= 0) {
|
||||
// el.parentNode.removeChild(el)
|
||||
return false
|
||||
}
|
||||
|
||||
console.log('流程节点页面权限--NODE--')
|
||||
const permissions = []
|
||||
for (const item of permissionList) {
|
||||
if (item.type + '' !== '2') {
|
||||
permissions.push(item.action)
|
||||
}
|
||||
}
|
||||
// console.log("页面权限----"+permissions);
|
||||
// console.log("页面权限----"+binding.value);
|
||||
if (!permissions.includes(binding.value)) {
|
||||
// el.parentNode.removeChild(el)
|
||||
return false
|
||||
} else {
|
||||
for (const item2 of permissionList) {
|
||||
if (binding.value === item2.action) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
/**
|
||||
* 全局权限控制
|
||||
*/
|
||||
export function filterGlobalPermission (el, binding) {
|
||||
const permissionList = []
|
||||
const allPermissionList = []
|
||||
|
||||
// let authList = Vue.ls.get(USER_AUTH);
|
||||
const authList = JSON.parse(sessionStorage.getItem(USER_AUTH) || '[]')
|
||||
for (const auth of authList) {
|
||||
if (auth.type + '' !== '2') {
|
||||
permissionList.push(auth)
|
||||
}
|
||||
}
|
||||
// console.log("页面权限--Global--",sessionStorage.getItem(SYS_BUTTON_AUTH));
|
||||
const allAuthList = JSON.parse(sessionStorage.getItem(SYS_BUTTON_AUTH) || '[]')
|
||||
for (const gauth of allAuthList) {
|
||||
if (gauth.type + '' !== '2') {
|
||||
allPermissionList.push(gauth)
|
||||
}
|
||||
}
|
||||
// 设置全局配置是否有命中
|
||||
let invalidFlag = false// 无效命中
|
||||
if (allPermissionList && allPermissionList.length > 0) {
|
||||
for (const itemG of allPermissionList) {
|
||||
if (binding.value === itemG.action) {
|
||||
if (itemG.status + '' === '0') {
|
||||
invalidFlag = true
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (invalidFlag) {
|
||||
return
|
||||
}
|
||||
if (permissionList === null || permissionList === '' || permissionList === undefined || permissionList.length <= 0) {
|
||||
el.parentNode.removeChild(el)
|
||||
return
|
||||
}
|
||||
const permissions = []
|
||||
for (const item of permissionList) {
|
||||
// 权限策略1显示2禁用
|
||||
if (item.type + '' !== '2') {
|
||||
// update--begin--autor:wangshuai-----date:20200729------for:按钮权限,授权标识的提示信息是多个用逗号分隔逻辑处理 gitee#I1OUGU-------
|
||||
if (item.action) {
|
||||
if (item.action.includes(',')) {
|
||||
const split = item.action.split(',')
|
||||
for (let i = 0; i < split.length; i++) {
|
||||
if (!split[i] || split[i].length === 0) {
|
||||
continue
|
||||
}
|
||||
permissions.push(split[i])
|
||||
}
|
||||
} else {
|
||||
permissions.push(item.action)
|
||||
}
|
||||
}
|
||||
// update--end--autor:wangshuai-----date:20200729------for:按钮权限,授权标识的提示信息是多个用逗号分隔逻辑处理 gitee#I1OUGU------
|
||||
}
|
||||
}
|
||||
if (!permissions.includes(binding.value)) {
|
||||
el.parentNode.removeChild(el)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据授权标识是否拥有该权限,用于tab页签的权限
|
||||
*/
|
||||
export function isHasPermission (permissionIdentifier) {
|
||||
const permissionList = []
|
||||
const allPermissionList = []
|
||||
|
||||
// let authList = Vue.ls.get(USER_AUTH);
|
||||
const authList = JSON.parse(sessionStorage.getItem(USER_AUTH) || '[]')
|
||||
for (const auth of authList) {
|
||||
if (auth.type + '' !== '2') {
|
||||
permissionList.push(auth)
|
||||
}
|
||||
}
|
||||
// console.log("页面权限--Global--",sessionStorage.getItem(SYS_BUTTON_AUTH));
|
||||
const allAuthList = JSON.parse(sessionStorage.getItem(SYS_BUTTON_AUTH) || '[]')
|
||||
for (const gauth of allAuthList) {
|
||||
if (gauth.type + '' !== '2') {
|
||||
allPermissionList.push(gauth)
|
||||
}
|
||||
}
|
||||
// 设置全局配置是否有命中
|
||||
let invalidFlag = false// 无效命中
|
||||
if (allPermissionList && allPermissionList.length > 0) {
|
||||
for (const itemG of allPermissionList) {
|
||||
if (permissionIdentifier === itemG.action) {
|
||||
if (itemG.status + '' === '0') {
|
||||
invalidFlag = true
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (invalidFlag) {
|
||||
return
|
||||
}
|
||||
if (permissionList === null || permissionList === '' || permissionList === undefined || permissionList.length <= 0) {
|
||||
return false
|
||||
}
|
||||
const permissions = []
|
||||
for (const item of permissionList) {
|
||||
// 权限策略1显示2禁用
|
||||
if (item.type + '' !== '2') {
|
||||
// update--begin--autor:wangshuai-----date:20200729------for:按钮权限,授权标识的提示信息是多个用逗号分隔逻辑处理 gitee#I1OUGU-------
|
||||
if (item.action) {
|
||||
if (item.action.includes(',')) {
|
||||
const split = item.action.split(',')
|
||||
for (let i = 0; i < split.length; i++) {
|
||||
if (!split[i] || split[i].length === 0) {
|
||||
continue
|
||||
}
|
||||
permissions.push(split[i])
|
||||
}
|
||||
} else {
|
||||
permissions.push(item.action)
|
||||
}
|
||||
}
|
||||
// update--end--autor:wangshuai-----date:20200729------for:按钮权限,授权标识的提示信息是多个用逗号分隔逻辑处理 gitee#I1OUGU------
|
||||
}
|
||||
}
|
||||
if (!permissions.includes(permissionIdentifier)) {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
export default hasPermission
|
||||
@@ -0,0 +1,40 @@
|
||||
import Vue from 'vue'
|
||||
import { USER_INFO } from '../store/mutation-types'
|
||||
import { Base64 } from 'js-base64'
|
||||
import md5 from 'md5'
|
||||
|
||||
function fillZero (str) {
|
||||
let realNum
|
||||
if (str < 10) {
|
||||
realNum = '0' + str
|
||||
} else {
|
||||
realNum = str
|
||||
}
|
||||
return realNum
|
||||
}
|
||||
|
||||
export function dealUrl (fileUrl) {
|
||||
const userInfo = Vue.ls.get(USER_INFO)
|
||||
// 获取当前时间
|
||||
const date = new Date()
|
||||
const year = date.getFullYear()
|
||||
const month = date.getMonth() + 1
|
||||
const day = date.getDate()
|
||||
const hour = date.getHours()
|
||||
const minute = date.getMinutes()
|
||||
const second = date.getSeconds()
|
||||
const time = `${year}${fillZero(month)}${fillZero(day)}${fillZero(hour)}${fillZero(minute)}${fillZero(second)}`
|
||||
// 水印内容
|
||||
const watermarkTxt = `${userInfo.username} ${userInfo.realname} ${time}`
|
||||
// 客户环境预览需要加的加密参数
|
||||
const watermarkSign = md5(watermarkTxt + 'cnhtc')
|
||||
return `${window._CONFIG.onlinePreviewDomainURL}?url=${encodeURIComponent(Base64.encode(fileUrl))}&watermarkTxt=${encodeURIComponent(watermarkTxt)}&watermarkSign=${watermarkSign}`
|
||||
}
|
||||
|
||||
/**
|
||||
* kkFile预览文件并添加水印
|
||||
* @param fileUrl
|
||||
*/
|
||||
export const kkFilePreview = (fileUrl) => {
|
||||
window.open(dealUrl(fileUrl))
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
// import Vue from 'vue'
|
||||
import { mapState } from 'vuex'
|
||||
|
||||
// const mixinsComputed = Vue.config.optionMergeStrategies.computed
|
||||
// const mixinsMethods = Vue.config.optionMergeStrategies.methods
|
||||
|
||||
const mixin = {
|
||||
computed: {
|
||||
...mapState({
|
||||
layoutMode: state => state.app.layout,
|
||||
navTheme: state => state.app.theme,
|
||||
primaryColor: state => state.app.color,
|
||||
colorWeak: state => state.app.weak,
|
||||
multipage: state => state.app.multipage, // 多页签设置
|
||||
fixedHeader: state => state.app.fixedHeader,
|
||||
fixSiderbar: state => state.app.fixSiderbar,
|
||||
contentWidth: state => state.app.contentWidth,
|
||||
autoHideHeader: state => state.app.autoHideHeader,
|
||||
sidebarOpened: state => state.app.sidebar.opened
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
const mixinDevice = {
|
||||
computed: {
|
||||
...mapState({
|
||||
device: state => state.app.device
|
||||
})
|
||||
},
|
||||
methods: {
|
||||
isMobile () {
|
||||
return this.device === 'mobile'
|
||||
},
|
||||
isDesktop () {
|
||||
return this.device === 'desktop'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export { mixin, mixinDevice }
|
||||
@@ -0,0 +1,82 @@
|
||||
import { generateEmptyFileTemplate, queryFileInfoByEditId } from '../api/workCenter'
|
||||
import { USER_INFO } from '../store/mutation-types'
|
||||
import Vue from 'vue'
|
||||
|
||||
/**
|
||||
* 获取文件信息
|
||||
* @param fileId
|
||||
* @returns {Promise<unknown>}
|
||||
*/
|
||||
const queryFileInfo = (fileId) => {
|
||||
return new Promise(resolve => {
|
||||
let fileInfo
|
||||
queryFileInfoByEditId({ id: fileId }).then(res => {
|
||||
if (res.success) {
|
||||
fileInfo = res.result
|
||||
}
|
||||
}).finally(() => {
|
||||
resolve(fileInfo)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成空白模板并获取模板路径
|
||||
* @returns {Promise<unknown>}
|
||||
*/
|
||||
const getEmptyFileTemplate = (params) => {
|
||||
return new Promise(resolve => {
|
||||
let fileInfo
|
||||
generateEmptyFileTemplate(params).then(res => {
|
||||
if (res.success) {
|
||||
fileInfo = res.result
|
||||
}
|
||||
}).finally(() => {
|
||||
resolve(fileInfo)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 跳转在线编辑
|
||||
* @param params Object {
|
||||
* standard_number: 标准编号,
|
||||
* substitute_standard_number: 代替标准号,
|
||||
* implementation_date: 实施日期,
|
||||
* release_date: 发布日期,
|
||||
* standard_name: 标准名称
|
||||
* }
|
||||
* @param fileId 文件id,有的话是编辑,没有是新增
|
||||
*/
|
||||
export const onlineEditor = async (params, fileId) => {
|
||||
let fileInfo
|
||||
if (fileId) {
|
||||
fileInfo = await queryFileInfo(fileId)
|
||||
} else {
|
||||
const param = {
|
||||
model: `${params.standard_number} ${params.standard_name}` // 处理文件名
|
||||
}
|
||||
fileInfo = await getEmptyFileTemplate(param)
|
||||
}
|
||||
if (!fileInfo) {
|
||||
return false
|
||||
}
|
||||
// 获取用户信息
|
||||
const userInfo = Vue.ls.get(USER_INFO)
|
||||
// 截取文件后缀名
|
||||
const fileSuffix = (fileInfo.fileName ? fileInfo.fileName.split('.')[fileInfo.fileName.split('.').length - 1] : '').toLowerCase()
|
||||
// Q/ZZ 部分截取
|
||||
const standardNumberPrefix = params.standard_number ? params.standard_number.split(' ')[0] : null
|
||||
const businessParams = {
|
||||
standCode: params.standard_number,
|
||||
dtqbbhbuss: params.substitute_standard_number,
|
||||
standName: params.standard_name,
|
||||
standEnName: params.standard_english_name,
|
||||
issueTime: params.release_date,
|
||||
putTime: params.implementation_date,
|
||||
standardNumberPrefix: standardNumberPrefix
|
||||
}
|
||||
const url = `${window._CONFIG.onlyOfficeUrl}/editorPage?filePath=${fileInfo.editFilePath}&fileName=${fileInfo.fileName}&fileType=${fileSuffix}&fileId=${fileInfo.id}&key=${fileInfo.id}&userId=${userInfo.id}&userName=${userInfo.realname}&business=${JSON.stringify(businessParams)}`
|
||||
window.open(url, '_blank')
|
||||
return fileInfo.id
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
export function actionToObject (json) {
|
||||
try {
|
||||
return JSON.parse(json)
|
||||
} catch (e) {
|
||||
console.log('err', e.message)
|
||||
}
|
||||
return []
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
import { ACCESS_TOKEN } from '@/store/mutation-types'
|
||||
import Vue from 'vue'
|
||||
|
||||
const getToken = () => Vue.ls.get(ACCESS_TOKEN)
|
||||
|
||||
// 预览pdf
|
||||
const previewPdf = (id) => {
|
||||
const url = `${window._CONFIG.domianURL}/sys/common/view/${id}?type=view&at=${getToken()}`
|
||||
return `${process.env.BASE_URL}pdfjs/web/viewer.html?file=` + encodeURIComponent(url) + '&.pdf'
|
||||
}
|
||||
|
||||
export {
|
||||
previewPdf
|
||||
}
|
||||
@@ -0,0 +1,112 @@
|
||||
/**
|
||||
* 该文件截取自 "ant-design-vue/es/_util/props-util.js" 文件,并对其做出特殊修改
|
||||
*/
|
||||
function classNames () {
|
||||
const classes = []
|
||||
|
||||
for (let i = 0; i < arguments.length; i++) {
|
||||
const arg = arguments[i]
|
||||
if (!arg) continue
|
||||
|
||||
const argType = typeof arg
|
||||
|
||||
if (argType === 'string' || argType === 'number') {
|
||||
classes.push(arg)
|
||||
} else if (Array.isArray(arg) && arg.length) {
|
||||
const inner = classNames.apply(null, arg)
|
||||
if (inner) {
|
||||
classes.push(inner)
|
||||
}
|
||||
} else if (argType === 'object') {
|
||||
for (const key in arg) {
|
||||
if (Object.prototype.hasOwnProperty.call(arg, key) && arg[key]) {
|
||||
classes.push(key)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return classes.join(' ')
|
||||
}
|
||||
|
||||
const camelizeRE = /-(\w)/g
|
||||
|
||||
function camelize (str) {
|
||||
return str.replace(camelizeRE, (_, c) => (c ? c.toUpperCase() : ''))
|
||||
}
|
||||
|
||||
function objectCamelize (obj) {
|
||||
const res = {}
|
||||
Object.keys(obj).forEach(k => (res[camelize(k)] = obj[k]))
|
||||
return res
|
||||
}
|
||||
|
||||
function parseStyleText (cssText = '', camel) {
|
||||
const res = {}
|
||||
const listDelimiter = /;(?![^(]*\))/g
|
||||
const propertyDelimiter = /:(.+)/
|
||||
cssText.split(listDelimiter).forEach(function (item) {
|
||||
if (item) {
|
||||
const tmp = item.split(propertyDelimiter)
|
||||
if (tmp.length > 1) {
|
||||
const k = camel ? camelize(tmp[0].trim()) : tmp[0].trim()
|
||||
res[k] = tmp[1].trim()
|
||||
}
|
||||
}
|
||||
})
|
||||
return res
|
||||
}
|
||||
|
||||
export function getClass (ele) {
|
||||
let data = {}
|
||||
if (ele.data) {
|
||||
data = ele.data
|
||||
} else if (ele.$vnode && ele.$vnode.data) {
|
||||
data = ele.$vnode.data
|
||||
}
|
||||
const tempCls = data.class || {}
|
||||
const staticClass = data.staticClass
|
||||
let cls = {}
|
||||
staticClass &&
|
||||
staticClass.split(' ').forEach(c => {
|
||||
cls[c.trim()] = true
|
||||
})
|
||||
if (typeof tempCls === 'string') {
|
||||
tempCls.split(' ').forEach(c => {
|
||||
cls[c.trim()] = true
|
||||
})
|
||||
} else if (Array.isArray(tempCls)) {
|
||||
classNames(tempCls)
|
||||
.split(' ')
|
||||
.forEach(c => {
|
||||
cls[c.trim()] = true
|
||||
})
|
||||
} else {
|
||||
cls = { ...cls, ...tempCls }
|
||||
}
|
||||
return cls
|
||||
}
|
||||
|
||||
export function getStyle (ele, camel) {
|
||||
getClass(ele)
|
||||
|
||||
let data = {}
|
||||
if (ele.data) {
|
||||
data = ele.data
|
||||
} else if (ele.$vnode && ele.$vnode.data) {
|
||||
data = ele.$vnode.data
|
||||
}
|
||||
|
||||
// update-begin-author:sunjianlei date:20200303 for: style 和 staticStyle 可以共存
|
||||
let style = data.style || {}
|
||||
let staticStyle = data.staticStyle
|
||||
staticStyle = staticStyle ? objectCamelize(data.staticStyle) : {}
|
||||
// update-end-author:sunjianlei date:20200303 for: style 和 staticStyle 可以共存
|
||||
|
||||
if (typeof style === 'string') {
|
||||
style = parseStyleText(style, camel)
|
||||
} else if (camel && style) {
|
||||
// 驼峰化
|
||||
style = objectCamelize(style)
|
||||
}
|
||||
return { ...staticStyle, ...style }
|
||||
}
|
||||
@@ -0,0 +1,184 @@
|
||||
import Vue from 'vue'
|
||||
import axios from 'axios'
|
||||
import store from '@/store'
|
||||
import { VueAxios } from './axios'
|
||||
import router from '@/router/index'
|
||||
import { ACCESS_TOKEN, TENANT_ID } from '@/store/mutation-types'
|
||||
import { Modal } from 'ant-design-vue'
|
||||
|
||||
/**
|
||||
* 【指定 axios的 baseURL】
|
||||
* 如果手工指定 baseURL: '/laws-sinotruk'
|
||||
* 则映射后端域名,通过 vue.config.js
|
||||
* @type {*|string}
|
||||
*/
|
||||
const apiBaseUrl = window._CONFIG.domianURL || '/laws-sinotruk'
|
||||
// console.log("apiBaseUrl= ",apiBaseUrl)
|
||||
// 创建 axios 实例
|
||||
const service = axios.create({
|
||||
// baseURL: '/laws-sinotruk',
|
||||
baseURL: apiBaseUrl, // api base_url
|
||||
timeout: 30 * 60 * 1000 // 请求超时时间
|
||||
})
|
||||
|
||||
const err = (error) => {
|
||||
if (error.response) {
|
||||
const data = error.response.data
|
||||
const token = Vue.ls.get(ACCESS_TOKEN)
|
||||
console.log('------异常响应------', token)
|
||||
console.log('------异常响应------', error.response.status)
|
||||
switch (error.response.status) {
|
||||
case 403:
|
||||
Vue.prototype.$Jnotification.error({ message: '系统提示', description: '拒绝访问', duration: 4 })
|
||||
break
|
||||
case 500:
|
||||
console.log('------error.response------', error.response)
|
||||
// update-begin- --- author:liusq ------ date:20200910 ---- for:处理Blob情况----
|
||||
if (error.response.request.responseType === 'blob') {
|
||||
blobToJson(data)
|
||||
break
|
||||
}
|
||||
// update-end- --- author:liusq ------ date:20200910 ---- for:处理Blob情况----
|
||||
if (data.includes('Token失效')) {
|
||||
// update-begin- --- author:scott ------ date:20190225 ---- for:Token失效采用弹框模式,不直接跳转----
|
||||
// if (/wxwork|dingtalk/i.test(navigator.userAgent)) {
|
||||
// Vue.prototype.$Jmessage.loading('登录已过期,正在重新登陆', 0)
|
||||
// } else {
|
||||
// Vue.prototype.$Jmodal.error({
|
||||
// title: '登录已过期',
|
||||
// content: '很抱歉,登录已过期,请重新登录',
|
||||
// okText: '重新登录',
|
||||
// mask: false,
|
||||
// onOk: () => {
|
||||
// store.dispatch('Logout')
|
||||
// }
|
||||
// })
|
||||
// }
|
||||
// update-end- --- author:scott ------ date:20190225 ---- for:Token失效采用弹框模式,不直接跳转----
|
||||
}
|
||||
break
|
||||
case 404:
|
||||
Vue.prototype.$Jnotification.error({ message: '系统提示', description: '很抱歉,资源未找到!', duration: 4 })
|
||||
break
|
||||
case 504:
|
||||
Vue.prototype.$Jnotification.error({ message: '系统提示', description: '网络超时' })
|
||||
break
|
||||
case 401:
|
||||
Vue.prototype.$Jnotification.error({ message: '系统提示', description: '未授权,请重新登录', duration: 4 })
|
||||
if (token) {
|
||||
store.dispatch('Logout').then(() => {
|
||||
setTimeout(() => {
|
||||
window.location.reload()
|
||||
}, 1500)
|
||||
})
|
||||
}
|
||||
break
|
||||
default:
|
||||
Vue.prototype.$Jnotification.error({
|
||||
message: '系统提示',
|
||||
description: data.message,
|
||||
duration: 4
|
||||
})
|
||||
break
|
||||
}
|
||||
} else if (error.message) {
|
||||
if (error.message.includes('timeout')) {
|
||||
Vue.prototype.$Jnotification.error({ message: '系统提示', description: '网络超时' })
|
||||
} else {
|
||||
Vue.prototype.$Jnotification.error({ message: '系统提示', description: error.message })
|
||||
}
|
||||
}
|
||||
return Promise.reject(error)
|
||||
}
|
||||
|
||||
// request interceptor
|
||||
service.interceptors.request.use(config => {
|
||||
const token = Vue.ls.get(ACCESS_TOKEN)
|
||||
if (token) {
|
||||
config.headers['X-Access-Token'] = token // 让每个请求携带自定义 token 请根据实际情况自行修改
|
||||
}
|
||||
// update-begin--author:sunjianlei---date:20200723---for 如果当前在low-app环境,并且携带了appId,就向Header里传递appId
|
||||
const $route = router.currentRoute
|
||||
if ($route && $route.name && $route.name.startsWith('low-app') && $route.params.appId) {
|
||||
config.headers['X-Low-App-ID'] = $route.params.appId
|
||||
}
|
||||
// update-end--author:sunjianlei---date:20200723---for 如果当前在low-app环境,并且携带了appId,就向Header里传递appId
|
||||
|
||||
// update-begin-author:taoyan date:2020707 for:多租户
|
||||
let tenantid = Vue.ls.get(TENANT_ID)
|
||||
if (!tenantid) {
|
||||
tenantid = 0
|
||||
}
|
||||
config.headers['tenant-id'] = tenantid
|
||||
|
||||
let language = localStorage.getItem('language') || ''
|
||||
if (!language) {
|
||||
language = 'zh-cn'
|
||||
}
|
||||
const cut = language === 'zh-cn' ? 'zh' : 'en'
|
||||
config.headers.Language = cut
|
||||
// update-end-author:taoyan date:2020707 for:多租户
|
||||
if (config.method === 'get') {
|
||||
if (config.url.indexOf('sys/dict/getDictItems') < 0) {
|
||||
config.params = {
|
||||
_t: Date.parse(new Date()) / 1000,
|
||||
...config.params
|
||||
}
|
||||
}
|
||||
}
|
||||
return config
|
||||
}, (error) => {
|
||||
return Promise.reject(error)
|
||||
})
|
||||
|
||||
// response interceptor
|
||||
service.interceptors.response.use((response) => {
|
||||
return response.data
|
||||
}, err)
|
||||
|
||||
const installer = {
|
||||
vm: {},
|
||||
install (Vue, router = {}) {
|
||||
Vue.use(VueAxios, router, service)
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Blob解析
|
||||
* @param data
|
||||
*/
|
||||
function blobToJson (data) {
|
||||
const fileReader = new FileReader()
|
||||
const token = Vue.ls.get(ACCESS_TOKEN)
|
||||
fileReader.onload = function () {
|
||||
try {
|
||||
const jsonData = JSON.parse(this.result) // 说明是普通对象数据,后台转换失败
|
||||
console.log('jsonData', jsonData)
|
||||
if (jsonData.status === 500) {
|
||||
console.log('token----------》', token)
|
||||
if (token && jsonData.message.includes('Token失效')) {
|
||||
Modal.error({
|
||||
title: '登录已过期',
|
||||
content: '很抱歉,登录已过期,请重新登录',
|
||||
okText: '重新登录',
|
||||
mask: false,
|
||||
onOk: () => {
|
||||
store.dispatch('Logout').then(() => {
|
||||
Vue.ls.remove(ACCESS_TOKEN)
|
||||
window.location.reload()
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
} catch (err) {
|
||||
// 解析成对象失败,说明是正常的文件流
|
||||
console.log('blob解析fileReader返回err', err)
|
||||
}
|
||||
}
|
||||
fileReader.readAsText(data)
|
||||
}
|
||||
|
||||
export {
|
||||
installer as VueAxios,
|
||||
service as axios
|
||||
}
|
||||
@@ -0,0 +1,106 @@
|
||||
const validateMobile = (rule, value, callback) => {
|
||||
const reg = /^1(3|4|5|7|8)\d{9}$/
|
||||
if (!reg.test(value)) {
|
||||
callback(new Error('请输入正确手机号'))
|
||||
} else {
|
||||
callback()
|
||||
}
|
||||
}
|
||||
const validateEn = (rule, value, callback) => {
|
||||
const reg = /^[_a-zA-Z0-9]+$/
|
||||
const reg2 = /^.{4,18}$/
|
||||
// 长度为6到18个字符
|
||||
if (value !== '' && !reg.test(value)) {
|
||||
callback(new Error('只允许字母、数字、下划线'))
|
||||
} else if (value !== '' && !reg2.test(value)) {
|
||||
callback(new Error('长度6到18个字符'))
|
||||
} else {
|
||||
callback()
|
||||
}
|
||||
}
|
||||
export const rules = {
|
||||
mobile: [{
|
||||
required: true,
|
||||
message: '请输入手机号',
|
||||
trigger: 'blur'
|
||||
}, { validator: validateMobile, trigger: 'blur' }],
|
||||
userName: [{
|
||||
required: true, message: '请输入用户名', trigger: 'blur'
|
||||
}, { validator: validateEn }],
|
||||
email: [
|
||||
{ required: false, type: 'email', message: '邮箱格式不正确', trigger: 'blur' }
|
||||
],
|
||||
// 验证自然数
|
||||
naturalNumber: /^(([0-9]*[1-9][0-9]*)|(0+))$/,
|
||||
naturalNumberMsg: '请输入自然数',
|
||||
// 英文
|
||||
english: /^.[A-Za-z]+$/,
|
||||
englishMsg: '请输入英文字符',
|
||||
// 座机
|
||||
telephone: /^\d{3}-\d{7,8}|\d{4}-\d{7,8}$/,
|
||||
telephoneMsg: '请输入正确的座机号',
|
||||
// 银行卡号码
|
||||
bankCard: /^[1-9]\d{9,19}$/,
|
||||
bankCardMsg: '请输入正确的银行卡号码',
|
||||
// 证件号码
|
||||
IDNumber: /^[a-z0-9A-Z]{0,50}$/,
|
||||
IDNumberMsg: '请输入正确的证件号码',
|
||||
// 身份证号码,包括15位和18位的
|
||||
IDCard: /(^[1-9]\d{5}(18|19|([23]\d))\d{2}((0[1-9])|(10|11|12))(([0-2][1-9])|10|20|30|31)\d{3}[0-9Xx]$)|(^[1-9]\d{7}((0[1-9])|(10|11|12))(([0-2][1-9])|10|20|30|31)\d{3}$)/,
|
||||
IDCardMsg: '请输入正确的身份证号码',
|
||||
// QQ号码
|
||||
qq: /^[1-9]\d{4,11}$/,
|
||||
qqMsg: '请输入正确的QQ号码',
|
||||
// 网址, 仅支持http和https开头的
|
||||
url: /^(http|https):\/\/[\w\-_]+(\.[\w\-_]+)+([\w\-.,@?^=%&:/~+#]*[\w\-@?^=%&/~+#])?$/,
|
||||
urlMsg: '请输入以http和https开头的网址',
|
||||
// 0到20位的英文字符和数字
|
||||
enNum0to20: /^[a-z0-9A-Z]{0,20}$/,
|
||||
enNum0to20Msg: '请输入20位以内的英文字符和数字',
|
||||
// 2到100位的中英文字符和空格
|
||||
cnEnSpace2to100: /^[a-zA-Z\u4E00-\u9FA5\s*]{2,100}$/,
|
||||
cnEnSpace2to100Msg: '请输入2到100位的中英文字符和空格',
|
||||
// 数字和换行符
|
||||
numLinefeed: /^[0-9\n*]+$/,
|
||||
numLinefeedMsg: '请输入数字和换行符',
|
||||
// 255位以内的字符
|
||||
char0to255: /^.{0,255}$/,
|
||||
char0to255Msg: '请输入255位以内的字符',
|
||||
required: function (min, max) {
|
||||
const rule = [{ required: true, message: '', trigger: 'blur' }]
|
||||
if (min) {
|
||||
const r = { min: min, message: '最小长度' + min + '位字符' }
|
||||
rule.push(r)
|
||||
}
|
||||
if (max) {
|
||||
const m = { max: max, message: '最大长度' + max + '位字符' }
|
||||
rule.push(m)
|
||||
}
|
||||
return rule
|
||||
},
|
||||
select: function () {
|
||||
return [{ required: true, message: '', trigger: 'change' }]
|
||||
},
|
||||
checked: function (min, max) {
|
||||
const rule = [{ required: true, type: 'array', message: '', trigger: 'change' }]
|
||||
if (min) {
|
||||
const r = { type: 'array', min: min, message: '最少选择' + min + '项' }
|
||||
rule.push(r)
|
||||
}
|
||||
if (max) {
|
||||
const m = { type: 'array', max: max, message: '最多选择' + max + '项' }
|
||||
rule.push(m)
|
||||
}
|
||||
return rule
|
||||
}
|
||||
}
|
||||
/**
|
||||
* @description 排序值验证,排序值不可以大于255
|
||||
*/
|
||||
export const validateOrder = function (rule, value, callback) {
|
||||
if (parseInt(value) > 255) {
|
||||
return callback(new Error('排序值不可以大于255'))
|
||||
} else {
|
||||
callback()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
/**
|
||||
* Set storage
|
||||
*
|
||||
* @param name
|
||||
* @param content
|
||||
* @param maxAge
|
||||
*/
|
||||
export const setStore = (name, content, maxAge = null) => {
|
||||
if (!global.window || !name) {
|
||||
return
|
||||
}
|
||||
|
||||
if (typeof content !== 'string') {
|
||||
content = JSON.stringify(content)
|
||||
}
|
||||
|
||||
const storage = global.window.localStorage
|
||||
|
||||
storage.setItem(name, content)
|
||||
if (maxAge && !isNaN(parseInt(maxAge))) {
|
||||
const timeout = parseInt(new Date().getTime() / 1000)
|
||||
storage.setItem(`${name}_expire`, timeout + maxAge)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get storage
|
||||
*
|
||||
* @param name
|
||||
* @returns {*}
|
||||
*/
|
||||
export const getStore = name => {
|
||||
if (!global.window || !name) {
|
||||
return
|
||||
}
|
||||
|
||||
const content = window.localStorage.getItem(name)
|
||||
const _expire = window.localStorage.getItem(`${name}_expire`)
|
||||
|
||||
if (_expire) {
|
||||
const now = parseInt(new Date().getTime() / 1000)
|
||||
if (now > _expire) {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
return JSON.parse(content)
|
||||
} catch (e) {
|
||||
return content
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear storage
|
||||
*
|
||||
* @param name
|
||||
*/
|
||||
export const clearStore = name => {
|
||||
if (!global.window || !name) {
|
||||
return
|
||||
}
|
||||
|
||||
window.localStorage.removeItem(name)
|
||||
window.localStorage.removeItem(`${name}_expire`)
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear all storage
|
||||
*/
|
||||
export const clearAll = () => {
|
||||
if (!global.window || !name) {
|
||||
return
|
||||
}
|
||||
|
||||
window.localStorage.clear()
|
||||
}
|
||||
@@ -0,0 +1,717 @@
|
||||
import Vue from 'vue'
|
||||
import * as api from '@/api/api'
|
||||
import { isURL } from '@/utils/validate'
|
||||
import { ACCESS_TOKEN } from '@/store/mutation-types'
|
||||
import { getFileInfo } from '@/api/api'
|
||||
import { dealUrl, kkFilePreview } from './kkFilePreview'
|
||||
import { previewPdf } from './previewPdf'
|
||||
// import onlineCommons from '@/components/onlineForm/onlineForm'
|
||||
|
||||
//
|
||||
export function timeFix () {
|
||||
const time = new Date()
|
||||
const hour = time.getHours()
|
||||
return hour < 9 ? '早上好' : (hour <= 11 ? '上午好' : (hour <= 13 ? '中午好' : (hour < 20 ? '下午好' : '晚上好')))
|
||||
}
|
||||
|
||||
export function welcome () {
|
||||
const arr = ['休息一会儿吧', '准备吃什么呢?', '要不要打一把 DOTA', '我猜你可能累了']
|
||||
const index = Math.floor((Math.random() * arr.length))
|
||||
return arr[index]
|
||||
}
|
||||
|
||||
/**
|
||||
* 触发 window.resize
|
||||
*/
|
||||
export function triggerWindowResizeEvent () {
|
||||
const event = document.createEvent('HTMLEvents')
|
||||
event.initEvent('resize', true, true)
|
||||
event.eventType = 'message'
|
||||
window.dispatchEvent(event)
|
||||
}
|
||||
|
||||
/**
|
||||
* 过滤对象中为空的属性
|
||||
* @param obj
|
||||
* @returns {*}
|
||||
*/
|
||||
export function filterObj (obj) {
|
||||
if (!(typeof obj === 'object')) {
|
||||
return
|
||||
}
|
||||
|
||||
for (const key in obj) {
|
||||
if (Object.prototype.hasOwnProperty.call(obj, key) && (obj[key] == null || obj[key] === undefined || obj[key] === '')) {
|
||||
delete obj[key]
|
||||
}
|
||||
}
|
||||
return obj
|
||||
}
|
||||
|
||||
/**
|
||||
* 时间格式化
|
||||
* @param value
|
||||
* @param fmt
|
||||
* @returns {*}
|
||||
*/
|
||||
export function formatDate (value, fmt) {
|
||||
const regPos = /^\d+(\.\d+)?$/
|
||||
if (regPos.test(value)) {
|
||||
// 如果是数字
|
||||
const getDate = new Date(value)
|
||||
const o = {
|
||||
'M+': getDate.getMonth() + 1,
|
||||
'd+': getDate.getDate(),
|
||||
'h+': getDate.getHours(),
|
||||
'm+': getDate.getMinutes(),
|
||||
's+': getDate.getSeconds(),
|
||||
'q+': Math.floor((getDate.getMonth() + 3) / 3),
|
||||
S: getDate.getMilliseconds()
|
||||
}
|
||||
if (/(y+)/.test(fmt)) {
|
||||
fmt = fmt.replace(RegExp.$1, (getDate.getFullYear() + '').substr(4 - RegExp.$1.length))
|
||||
}
|
||||
for (const k in o) {
|
||||
if (new RegExp('(' + k + ')').test(fmt)) {
|
||||
fmt = fmt.replace(RegExp.$1, (RegExp.$1.length === 1) ? (o[k]) : (('00' + o[k]).substr(('' + o[k]).length)))
|
||||
}
|
||||
}
|
||||
return fmt
|
||||
} else {
|
||||
// TODO
|
||||
value = value.trim()
|
||||
return value.substr(0, fmt.length)
|
||||
}
|
||||
}
|
||||
|
||||
// 生成首页路由
|
||||
export function generateIndexRouter (data) {
|
||||
const redirectPath = findFirstRoute(data)
|
||||
return [{
|
||||
path: '/',
|
||||
name: 'dashboard',
|
||||
// component: () => import('@/components/layouts/BasicLayout'),
|
||||
component: resolve => require(['@/components/layouts/TabLayout'], resolve),
|
||||
meta: { title: '首页' },
|
||||
redirect: redirectPath,
|
||||
children: [
|
||||
...generateChildRouters(data)
|
||||
]
|
||||
}, {
|
||||
path: '*', redirect: '/404', hidden: true
|
||||
}]
|
||||
}
|
||||
|
||||
// 生成嵌套路由(子路由)
|
||||
|
||||
function generateChildRouters (data) {
|
||||
const routers = []
|
||||
for (const item of data) {
|
||||
let component = ''
|
||||
if (item.component.indexOf('layouts') >= 0) {
|
||||
component = 'components/' + item.component
|
||||
} else {
|
||||
component = 'views/' + item.component
|
||||
}
|
||||
const URL = (item.meta.url || '').replace(/{{([^}}]+)?}}/g, (s1, s2) => evil(s2)) // URL支持{{ window.xxx }}占位符变量
|
||||
if (isURL(URL) || (item.meta.url && item.meta.url.indexOf('{{') === 0)) {
|
||||
item.meta.url = URL
|
||||
}
|
||||
|
||||
let componentPath
|
||||
// if (item.component === 'modules/online/cgform/OnlCgformHeadList') {
|
||||
// componentPath = onlineCommons.OnlCgformHeadList
|
||||
// } else if (item.component + '' === 'modules/online/cgform/OnlCgformCopyList') {
|
||||
// componentPath = onlineCommons.OnlCgformCopyList
|
||||
// } else if (item.component + '' === 'modules/online/cgform/auto/OnlCgformAutoList') {
|
||||
// componentPath = onlineCommons.OnlCgformAutoList
|
||||
// } else if (item.component + '' === 'modules/online/cgform/auto/OnlCgformTreeList') {
|
||||
// componentPath = onlineCommons.OnlCgformTreeList
|
||||
// } else if (item.component + '' === 'modules/online/cgform/auto/erp/OnlCgformErpList') {
|
||||
// componentPath = onlineCommons.OnlCgformErpList
|
||||
// } else if (item.component + '' === 'modules/online/cgform/auto/tab/OnlCgformTabList') {
|
||||
// componentPath = onlineCommons.OnlCgformTabList
|
||||
// } else if (item.component + '' === 'modules/online/cgform/auto/innerTable/OnlCgformInnerTableList') {
|
||||
// componentPath = onlineCommons.OnlCgformInnerTableList
|
||||
// } else if (item.component + '' === 'modules/online/cgreport/OnlCgreportHeadList') {
|
||||
// componentPath = onlineCommons.OnlCgreportHeadList
|
||||
// } else if (item.component + '' === 'modules/online/cgreport/auto/OnlCgreportAutoList') {
|
||||
// componentPath = onlineCommons.OnlCgreportAutoList
|
||||
// } else {
|
||||
componentPath = resolve => require(['@/' + component + '.vue'], resolve)
|
||||
// }
|
||||
|
||||
const menu = {
|
||||
path: item.path,
|
||||
name: item.name,
|
||||
redirect: item.redirect,
|
||||
component: componentPath,
|
||||
// component: resolve => require(['@/' + component+'.vue'], resolve),
|
||||
hidden: item.hidden,
|
||||
meta: {
|
||||
title: item.meta.title,
|
||||
icon: item.meta.icon,
|
||||
url: item.meta.url,
|
||||
permissionList: item.meta.permissionList,
|
||||
keepAlive: item.meta.keepAlive,
|
||||
/* update_begin author:wuxianquan date:20190908 for:赋值 */
|
||||
internalOrExternal: item.meta.internalOrExternal,
|
||||
/* update_end author:wuxianquan date:20190908 for:赋值 */
|
||||
componentName: item.meta.componentName
|
||||
}
|
||||
}
|
||||
if (item.alwaysShow) {
|
||||
menu.alwaysShow = true
|
||||
menu.redirect = menu.path
|
||||
}
|
||||
if (item.children && item.children.length > 0) {
|
||||
menu.children = [...generateChildRouters(item.children)]
|
||||
}
|
||||
// --update-begin----author:scott---date:20190320------for:根据后台菜单配置,判断是否路由菜单字段,动态选择是否生成路由(为了支持参数URL菜单)------
|
||||
// 判断是否生成路由
|
||||
if (item.route && item.route === '0') {
|
||||
// console.log(' 不生成路由 item.route: '+item.route);
|
||||
// console.log(' 不生成路由 item.path: '+item.path);
|
||||
} else {
|
||||
routers.push(menu)
|
||||
}
|
||||
// --update-end----author:scott---date:20190320------for:根据后台菜单配置,判断是否路由菜单字段,动态选择是否生成路由(为了支持参数URL菜单)------
|
||||
}
|
||||
return routers
|
||||
}
|
||||
|
||||
/**
|
||||
* 深度克隆对象、数组
|
||||
* @param obj 被克隆的对象
|
||||
* @return 克隆后的对象
|
||||
*/
|
||||
export function cloneObject (obj) {
|
||||
return JSON.parse(JSON.stringify(obj))
|
||||
}
|
||||
|
||||
/**
|
||||
* 随机生成数字
|
||||
*
|
||||
* 示例:生成长度为 12 的随机数:randomNumber(12)
|
||||
* 示例:生成 3~23 之间的随机数:randomNumber(3, 23)
|
||||
*
|
||||
* @param1 最小值 | 长度
|
||||
* @param2 最大值
|
||||
* @return int 生成后的数字
|
||||
*/
|
||||
export function randomNumber () {
|
||||
// 生成 最小值 到 最大值 区间的随机数
|
||||
const random = (min, max) => {
|
||||
return Math.floor(Math.random() * (max - min + 1) + min)
|
||||
}
|
||||
if (arguments.length === 1) {
|
||||
const [length] = arguments
|
||||
// 生成指定长度的随机数字,首位一定不是 0
|
||||
const nums = [...Array(length).keys()].map((i) => (i > 0 ? random(0, 9) : random(1, 9)))
|
||||
return parseInt(nums.join(''))
|
||||
} else if (arguments.length >= 2) {
|
||||
const [min, max] = arguments
|
||||
return random(min, max)
|
||||
} else {
|
||||
return Number.NaN
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 随机生成字符串
|
||||
* @param length 字符串的长度
|
||||
* @param chats 可选字符串区间(只会生成传入的字符串中的字符)
|
||||
* @return string 生成的字符串
|
||||
*/
|
||||
export function randomString (length, chats) {
|
||||
if (!length) length = 1
|
||||
if (!chats) chats = '0123456789qwertyuioplkjhgfdsazxcvbnm'
|
||||
let str = ''
|
||||
for (let i = 0; i < length; i++) {
|
||||
const num = randomNumber(0, chats.length - 1)
|
||||
str += chats[num]
|
||||
}
|
||||
return str
|
||||
}
|
||||
|
||||
/**
|
||||
* 随机生成uuid
|
||||
* @return string 生成的uuid
|
||||
*/
|
||||
export function randomUUID () {
|
||||
const chats = '0123456789abcdef'
|
||||
return randomString(32, chats)
|
||||
}
|
||||
|
||||
/**
|
||||
* 下划线转驼峰
|
||||
* @param string
|
||||
* @returns {*}
|
||||
*/
|
||||
export function underLine2CamelCase (string) {
|
||||
return string.replace(/_([a-z])/g, function (all, letter) {
|
||||
return letter.toUpperCase()
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断是否显示办理按钮
|
||||
* @param bpmStatus
|
||||
* @returns {*}
|
||||
*/
|
||||
export function showDealBtn (bpmStatus) {
|
||||
return bpmStatus + '' !== '1' && bpmStatus + '' !== '3' && bpmStatus + '' !== '4'
|
||||
}
|
||||
|
||||
/**
|
||||
* 增强CSS,可以在页面上输出全局css
|
||||
* @param css 要增强的css
|
||||
* @param id style标签的id,可以用来清除旧样式
|
||||
*/
|
||||
export function cssExpand (css, id) {
|
||||
const style = document.createElement('style')
|
||||
style.type = 'text/css'
|
||||
style.innerHTML = `@charset "UTF-8"; ${css}`
|
||||
// 清除旧样式
|
||||
if (id) {
|
||||
const $style = document.getElementById(id)
|
||||
if ($style != null) $style.outerHTML = ''
|
||||
style.id = id
|
||||
}
|
||||
// 应用新样式
|
||||
document.head.appendChild(style)
|
||||
}
|
||||
|
||||
/** 用于js增强事件,运行JS代码,可以传参 */
|
||||
// options 所需参数:
|
||||
// 参数名 类型 说明
|
||||
// vm VueComponent vue实例
|
||||
// event Object event对象
|
||||
// jsCode String 待执行的js代码
|
||||
// errorMessage String 执行出错后的提示(控制台)
|
||||
export function jsExpand (options = {}) {
|
||||
// 绑定到window上的keyName
|
||||
const windowKeyName = 'J_CLICK_EVENT_OPTIONS'
|
||||
if (typeof window[windowKeyName] !== 'object') {
|
||||
window[windowKeyName] = {}
|
||||
}
|
||||
|
||||
// 随机生成JS增强的执行id,防止冲突
|
||||
const id = randomString(16, 'qwertyuioplkjhgfdsazxcvbnm'.toUpperCase())
|
||||
// 封装按钮点击事件
|
||||
const code = `
|
||||
(function (o_${id}) {
|
||||
try {
|
||||
(function (globalEvent, vm) {
|
||||
${options.jsCode}
|
||||
})(o_${id}.event, o_${id}.vm)
|
||||
} catch (e) {
|
||||
o_${id}.error(e)
|
||||
}
|
||||
o_${id}.done()
|
||||
})(window['${windowKeyName}']['EVENT_${id}'])
|
||||
`
|
||||
// 创建script标签
|
||||
const script = document.createElement('script')
|
||||
// 将需要传递的参数挂载到window对象上
|
||||
window[windowKeyName]['EVENT_' + id] = {
|
||||
vm: options.vm,
|
||||
event: options.event,
|
||||
// 当执行完成时,无论如何都会调用的回调事件
|
||||
done () {
|
||||
// 执行完后删除新增的 script 标签不会撤销执行结果(已产生的结果不会被撤销)
|
||||
script.outerHTML = ''
|
||||
delete window[windowKeyName]['EVENT_' + id]
|
||||
},
|
||||
// 当js运行出错的时候调用的事件
|
||||
error (e) {
|
||||
console.group(`${options.errorMessage || '用户自定义JS增强代码运行出错'}(${new Date()})`)
|
||||
console.error(e)
|
||||
console.groupEnd()
|
||||
}
|
||||
}
|
||||
// 将事件挂载到document中
|
||||
script.innerHTML = code
|
||||
document.body.appendChild(script)
|
||||
}
|
||||
|
||||
/**
|
||||
* 重复值验证工具方法
|
||||
*
|
||||
* 使用示例:
|
||||
* { validator: (rule, value, callback) => validateDuplicateValue('sys_fill_rule', 'rule_code', value, this.model.id, callback) }
|
||||
*
|
||||
* @param tableName 被验证的表名
|
||||
* @param fieldName 被验证的字段名
|
||||
* @param fieldVal 被验证的值
|
||||
* @param dataId 数据ID,可空
|
||||
* @param callback
|
||||
*/
|
||||
export function validateDuplicateValue (isEncrypt, tableName, fieldName, fieldVal, dataId, callback) {
|
||||
if (fieldVal) {
|
||||
const confusionCode = getConfusionCode(tableName, fieldName)
|
||||
const params = { confusionCode, fieldVal, dataId }
|
||||
// 是否数据库中存储的加密信息
|
||||
if (isEncrypt) {
|
||||
params.encrypt = 1
|
||||
}
|
||||
api.duplicateCheck(params).then(res => {
|
||||
res.success ? callback() : callback(res.message)
|
||||
}).catch(err => {
|
||||
callback(err.message || err)
|
||||
})
|
||||
} else {
|
||||
callback()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据编码校验规则code,校验传入的值是否合法
|
||||
*
|
||||
* 使用示例:
|
||||
* { validator: (rule, value, callback) => validateCheckRule('common', value, callback) }
|
||||
*
|
||||
* @param ruleCode 编码校验规则 code
|
||||
* @param value 被验证的值
|
||||
* @param callback
|
||||
*/
|
||||
export function validateCheckRule (ruleCode, value, callback) {
|
||||
if (ruleCode && value) {
|
||||
value = encodeURIComponent(value)
|
||||
api.checkRuleByCode({ ruleCode, value }).then(res => {
|
||||
res.success ? callback() : callback(res.message)
|
||||
}).catch(err => {
|
||||
callback(err.message || err)
|
||||
})
|
||||
} else {
|
||||
callback()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 如果值不存在就 push 进数组,反之不处理
|
||||
* @param array 要操作的数据
|
||||
* @param value 要添加的值
|
||||
* @param key 可空,如果比较的是对象,可能存在地址不一样但值实际上是一样的情况,可以传此字段判断对象中唯一的字段,例如 id。不传则直接比较实际值
|
||||
* @returns {boolean} 成功 push 返回 true,不处理返回 false
|
||||
*/
|
||||
export function pushIfNotExist (array, value, key) {
|
||||
for (const item of array) {
|
||||
if (key && (item[key] === value[key])) {
|
||||
return false
|
||||
} else if (item === value) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
array.push(value)
|
||||
return true
|
||||
}
|
||||
|
||||
/**
|
||||
* 可用于判断是否成功
|
||||
* @type {symbol}
|
||||
*/
|
||||
export const succeedSymbol = Symbol('')
|
||||
/**
|
||||
* 可用于判断是否失败
|
||||
* @type {symbol}
|
||||
*/
|
||||
export const failedSymbol = Symbol('')
|
||||
|
||||
/**
|
||||
* 使 promise 无论如何都会 resolve,除非传入的参数不是一个Promise对象或返回Promise对象的方法
|
||||
* 一般用在 Promise.all 中
|
||||
*
|
||||
* @param promise 可传Promise对象或返回Promise对象的方法
|
||||
* @returns {Promise<any>}
|
||||
*/
|
||||
export function alwaysResolve (promise) {
|
||||
return new Promise((resolve, reject) => {
|
||||
let p = promise
|
||||
if (typeof promise === 'function') {
|
||||
p = promise()
|
||||
}
|
||||
if (p instanceof Promise) {
|
||||
p.then(data => {
|
||||
resolve({ type: succeedSymbol, data })
|
||||
}).catch(error => {
|
||||
resolve({ type: failedSymbol, error })
|
||||
})
|
||||
} else {
|
||||
reject('alwaysResolve: 传入的参数不是一个Promise对象或返回Promise对象的方法')
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 简单实现防抖方法
|
||||
*
|
||||
* 防抖(debounce)函数在第一次触发给定的函数时,不立即执行函数,而是给出一个期限值(delay),比如100ms。
|
||||
* 如果100ms内再次执行函数,就重新开始计时,直到计时结束后再真正执行函数。
|
||||
* 这样做的好处是如果短时间内大量触发同一事件,只会执行一次函数。
|
||||
*
|
||||
* @param fn 要防抖的函数
|
||||
* @param delay 防抖的毫秒数
|
||||
* @returns {Function}
|
||||
*/
|
||||
export function simpleDebounce (fn, delay = 100) {
|
||||
let timer = null
|
||||
return function () {
|
||||
const args = arguments
|
||||
if (timer) {
|
||||
clearTimeout(timer)
|
||||
}
|
||||
timer = setTimeout(() => {
|
||||
fn.apply(this, args)
|
||||
}, delay)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 不用正则的方式替换所有值
|
||||
* @param text 被替换的字符串
|
||||
* @param checker 替换前的内容
|
||||
* @param replacer 替换后的内容
|
||||
* @returns {String} 替换后的字符串
|
||||
*/
|
||||
export function replaceAll (text, checker, replacer) {
|
||||
const lastText = text
|
||||
text = text.replace(checker, replacer)
|
||||
if (lastText !== text) {
|
||||
return replaceAll(text, checker, replacer)
|
||||
}
|
||||
return text
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取事件冒泡路径,兼容 IE11,Edge,Chrome,Firefox,Safari
|
||||
* 目前使用的地方:JEditableTable Span模式
|
||||
*/
|
||||
export function getEventPath (event) {
|
||||
const target = event.target
|
||||
const path = (event.composedPath && event.composedPath()) || event.path
|
||||
|
||||
if (path != null) {
|
||||
return (path.indexOf(window) < 0) ? path.concat(window) : path
|
||||
}
|
||||
|
||||
if (target === window) {
|
||||
return [window]
|
||||
}
|
||||
|
||||
const getParents = (node, memo) => {
|
||||
memo = memo || []
|
||||
const parentNode = node.parentNode
|
||||
|
||||
if (!parentNode) {
|
||||
return memo
|
||||
} else {
|
||||
return getParents(parentNode, memo.concat(parentNode))
|
||||
}
|
||||
}
|
||||
return [target].concat(getParents(target), window)
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据组件名获取父级
|
||||
* @param vm
|
||||
* @param name
|
||||
* @returns {Vue | null|null|Vue}
|
||||
*/
|
||||
export function getVmParentByName (vm, name) {
|
||||
const parent = vm.$parent
|
||||
if (parent && parent.$options) {
|
||||
if (parent.$options.name === name) {
|
||||
return parent
|
||||
} else {
|
||||
const res = getVmParentByName(parent, name)
|
||||
if (res) {
|
||||
return res
|
||||
}
|
||||
}
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
/**
|
||||
* 使一个值永远不会为(null | undefined)
|
||||
*
|
||||
* @param value 要处理的值
|
||||
* @param def 默认值,如果value为(null | undefined)则返回的默认值,可不传,默认为''
|
||||
*/
|
||||
export function neverNull (value, def) {
|
||||
return value == null ? (neverNull(def, '')) : value
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据元素值移除数组中的一个元素
|
||||
* @param array 数组
|
||||
* @param prod 属性名
|
||||
* @param value 属性值
|
||||
* @returns {string}
|
||||
*/
|
||||
export function removeArrayElement (array, prod, value) {
|
||||
let index = -1
|
||||
for (let i = 0; i < array.length; i++) {
|
||||
if (array[i][prod] + '' === value + '') {
|
||||
index = i
|
||||
break
|
||||
}
|
||||
}
|
||||
if (index >= 0) {
|
||||
array.splice(index, 1)
|
||||
}
|
||||
}
|
||||
|
||||
export function findFirstRoute (data) {
|
||||
if (data[0]) {
|
||||
if (data[0] && data[0].children && data[0].children.length > 0) {
|
||||
return findFirstRoute(data[0].children)
|
||||
} else {
|
||||
return data[0].path
|
||||
}
|
||||
} else {
|
||||
return '/'
|
||||
}
|
||||
}
|
||||
|
||||
/** 判断是否是OAuth2APP环境 */
|
||||
export function isOAuth2AppEnv () {
|
||||
return /wxwork|dingtalk/i.test(navigator.userAgent)
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取积木报表打印地址
|
||||
* @param url
|
||||
* @param id
|
||||
* @param open 是否自动打开
|
||||
* @returns {*}
|
||||
*/
|
||||
export function getReportPrintUrl (url, id, open) {
|
||||
// URL支持{{ window.xxx }}占位符变量
|
||||
url = url.replace(/{{([^}]+)?}}/g, (s1, s2) => evil(s2))
|
||||
if (url.includes('?')) {
|
||||
url += '&'
|
||||
} else {
|
||||
url += '?'
|
||||
}
|
||||
url += `id=${id}`
|
||||
url += `&token=${Vue.ls.get(ACCESS_TOKEN)}`
|
||||
if (open) {
|
||||
window.open(url)
|
||||
}
|
||||
return url
|
||||
}
|
||||
|
||||
/**
|
||||
* 解决eval的eslint问题
|
||||
* @param fn
|
||||
* @returns {*}
|
||||
*/
|
||||
export function evil (fn) {
|
||||
const Fn = Function // 一个变量指向Function,防止有些前端编译工具报错
|
||||
return new Fn('return ' + fn)()
|
||||
}
|
||||
|
||||
/**
|
||||
* 将url的参数拆分成对象
|
||||
* @param url
|
||||
* @returns {{id: *, url}}
|
||||
*/
|
||||
export function urlToParams (url) {
|
||||
const commonUrl = window._CONFIG.staticDomainURL
|
||||
// url截取参数的部分
|
||||
const paramsStr = url.slice(url.indexOf('?') + 1)
|
||||
const paramsObj = {
|
||||
url,
|
||||
id: url.slice(url.indexOf(commonUrl) + commonUrl.length + 1, url.indexOf('?'))
|
||||
}
|
||||
paramsStr.split('&').forEach(item => {
|
||||
const arr = item.split('=')
|
||||
paramsObj[arr[0]] = arr[1]
|
||||
})
|
||||
return paramsObj
|
||||
}
|
||||
|
||||
/**
|
||||
* 重复校验:表名和字段名获取混淆code
|
||||
* @param tableName
|
||||
* @param fieldName
|
||||
* @return {string}
|
||||
*/
|
||||
export function getConfusionCode (tableName, fieldName) {
|
||||
// map对象对应数据库中 sys_confusion 表
|
||||
const map = {
|
||||
sys_user: {
|
||||
username: 'sys_username',
|
||||
phone: 'user_phone',
|
||||
email: 'user_email'
|
||||
},
|
||||
sys_role: {
|
||||
role_code: 'sys_rolecode',
|
||||
role_name: 'sys_rolename'
|
||||
},
|
||||
sys_dict: {
|
||||
dict_code: 'sys_dictcode'
|
||||
},
|
||||
sys_depart: {
|
||||
depart_name: 'depart_name'
|
||||
},
|
||||
sys_check_rule: {
|
||||
rule_code: 'check_rule_code'
|
||||
},
|
||||
sys_data_source: {
|
||||
code: 'data_source_code'
|
||||
},
|
||||
sys_fill_rule: {
|
||||
rule_code: 'fill_rule_code'
|
||||
},
|
||||
sys_sms_template: {
|
||||
template_code: 'sms_template_code'
|
||||
},
|
||||
sys_permission: {
|
||||
perms: 'sys_permission_perms'
|
||||
},
|
||||
sys_position: {
|
||||
code: 'sys_position_code'
|
||||
}
|
||||
}
|
||||
if (map[tableName] && map[tableName][fieldName]) {
|
||||
return map[tableName][fieldName]
|
||||
}
|
||||
return ''
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过文件id在当前窗口预览文件
|
||||
* @param fileId
|
||||
*/
|
||||
export function previewFileCurrentWindowByFileId (fileId) {
|
||||
return new Promise((resolve, reject) => {
|
||||
getFileInfo({ id: fileId }).then(res => {
|
||||
if (res.success) {
|
||||
const file = res.result || {}
|
||||
// 支持预览的文件后缀
|
||||
const CAN_PREVIEW_FILE_SUFFIX = ['jpg', 'jpeg', 'png', 'pdf', 'doc', 'docx', 'xls', 'xlsx', 'ppt', 'pptx']
|
||||
const fileSuffix = file.fileName ? file.fileName.split('.')[file.fileName.split('.').length - 1] : ''
|
||||
const canPreview = CAN_PREVIEW_FILE_SUFFIX.some(tt => fileSuffix.toLowerCase() === tt)
|
||||
// 判断是否为可预览格式的文件
|
||||
if (!canPreview) {
|
||||
reject('该文件类型不支持预览')
|
||||
}
|
||||
const fileFullUrl = `${window._CONFIG.domianWebSocketURL}/sys/common/view/${file.id}?at=${Vue.ls.get(ACCESS_TOKEN)}&fullfilename=${file.fileName}`
|
||||
const FILE_TYPE_IMGS = ['jpg', 'jpeg', 'png', 'raw']
|
||||
const FILE_TYPE_PDF = 'pdf'
|
||||
// pdf预览
|
||||
if (canPreview && FILE_TYPE_PDF.includes(fileSuffix)) {
|
||||
const url = previewPdf(file.id)
|
||||
window.open(url, '_self')
|
||||
return
|
||||
}
|
||||
// 其余可预览文件仍使用KKFile进行预览
|
||||
const kkFileUrl = dealUrl(fileFullUrl)
|
||||
window.open(kkFileUrl, '_self')
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
/**
|
||||
* 邮箱
|
||||
* @param {*} s
|
||||
* 之前的正则 /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/
|
||||
*/
|
||||
export function isEmail(s) {
|
||||
return /^\w[-\w.+]*@([A-Za-z0-9][-A-Za-z0-9]+\.)+[A-Za-z]{2,14}/.test(s)
|
||||
}
|
||||
|
||||
/**
|
||||
* 手机号码
|
||||
* @param {*} s
|
||||
*/
|
||||
export function isMobile (s) {
|
||||
return /^1[0-9]{10}$/.test(s)
|
||||
}
|
||||
|
||||
/**
|
||||
* 电话号码
|
||||
* @param {*} s
|
||||
*/
|
||||
export function isPhone (s) {
|
||||
return /^([0-9]{3,4}-)?[0-9]{7,8}$/.test(s)
|
||||
}
|
||||
|
||||
/**
|
||||
* URL地址
|
||||
* @param {*} s
|
||||
*/
|
||||
export function isURL (s) {
|
||||
return /^http[s]?:\/\/.*/.test(s)
|
||||
}
|
||||
|
||||
/**
|
||||
* 手机号或座机号
|
||||
*
|
||||
* /^((13[0-9])|(14[579])|(15([0-3]|[5-9]))|(17[0135678])|(18[0-9])|(19[8|9])|(16[6]))\d{8}$/
|
||||
* */
|
||||
export function phoneReg(s) {
|
||||
return /(^[1][3,4,5,6,7,8,9][0-9]{9}$)|(^0\d{2,3}-?\d{7,8}$)/.test(s)
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
import Bus from 'vue'
|
||||
const install = function (Vue) {
|
||||
Vue.prototype.$bus = new Bus()
|
||||
}
|
||||
export default { install }
|
||||
@@ -0,0 +1,46 @@
|
||||
import Vue from 'vue'
|
||||
|
||||
Vue.directive('watermark', {
|
||||
bind: function (el, binding) {
|
||||
// 水印文字,父元素,画布宽度,画布高度,字体,文字颜色,画布横坐标
|
||||
function addWaterMarker (str, parentNode, width, height, font, textColor, fillTextX = '10') {
|
||||
// 检查父元素是否包含子元素
|
||||
const elementContains = (parent, child) => parent !== child && parent.contains(child)
|
||||
const flag = elementContains(parentNode, document.querySelector('canvas'))
|
||||
// 防止重复创建
|
||||
if (!flag) {
|
||||
const can = document.createElement('canvas')
|
||||
parentNode.appendChild(can)
|
||||
can.width = width || 300
|
||||
can.height = height || 140
|
||||
can.style.display = 'none'
|
||||
const cans = can.getContext('2d')
|
||||
cans.rotate(-20 * Math.PI / 180)
|
||||
cans.font = font || window._CONFIG.watermarkConfig.font
|
||||
cans.fillStyle = textColor || '#DDDDDD'
|
||||
cans.textAlign = 'left'
|
||||
cans.textBaseline = 'Middle'
|
||||
cans.fillText(str, fillTextX, can.height)
|
||||
// 设置背景图(整个项目中都添加水印建议使用此方法)
|
||||
// parentNode.style.backgroundImage = "url(" + can.toDataURL("image/png") + ")";
|
||||
|
||||
// 创建div 定位覆盖(某个元素,如图片添加水印建议使用此方法)
|
||||
const div = document.createElement('div')
|
||||
div.id = str
|
||||
div.style.pointerEvents = 'none'
|
||||
div.style.top = '0'
|
||||
div.style.left = '0'
|
||||
div.style.position = 'absolute'
|
||||
div.style.zIndex = '100000'
|
||||
div.style.width = '100%'
|
||||
div.style.height = '100%'
|
||||
div.style.background = 'url(' + can.toDataURL('image/png') + ')'
|
||||
parentNode.appendChild(div)
|
||||
}
|
||||
}
|
||||
|
||||
if (binding.value.text) {
|
||||
addWaterMarker(binding.value.text, el, binding.value.width, binding.value.height, binding.value.font, binding.value.textColor, binding.value.fillTextX)
|
||||
}
|
||||
}
|
||||
})
|
||||
Reference in New Issue
Block a user