多模块重构 12:修改项目名字,按照新的规则

This commit is contained in:
YunaiV
2022-02-02 22:33:39 +08:00
parent 352a67c530
commit 0773a4c4d7
1040 changed files with 12 additions and 190 deletions

View File

@ -0,0 +1,15 @@
import Cookies from 'js-cookie'
const TokenKey = 'Admin-Token'
export function getToken() {
return Cookies.get(TokenKey)
}
export function setToken(token) {
return Cookies.set(TokenKey, token)
}
export function removeToken() {
return Cookies.remove(TokenKey)
}

View File

@ -0,0 +1,227 @@
/**
* Created by 芋道源码
*
* 枚举类
*/
/**
* 全局通用状态枚举
*/
export const CommonStatusEnum = {
ENABLE: 0, // 开启
DISABLE: 1 // 禁用
}
/**
* 菜单的类型枚举
*/
export const SystemMenuTypeEnum = {
DIR: 1, // 目录
MENU: 2, // 菜单
BUTTON: 3 // 按钮
}
/**
* 角色的类型枚举
*/
export const SystemRoleTypeEnum = {
SYSTEM: 1, // 内置角色
CUSTOM: 2 // 自定义角色
}
/**
* 数据权限的范围枚举
*/
export const SystemDataScopeEnum = {
ALL: 1, // 全部数据权限
DEPT_CUSTOM: 2, // 指定部门数据权限
DEPT_ONLY: 3, // 部门数据权限
DEPT_AND_CHILD: 4, // 部门及以下数据权限
DEPT_SELF: 5 // 仅本人数据权限
}
/**
* 代码生成模板类型
*/
export const ToolCodegenTemplateTypeEnum = {
CRUD: 1, // 基础 CRUD
TREE: 2, // 树形 CRUD
SUB: 3, // 主子表 CRUD
}
/**
* 任务状态的枚举
*/
export const InfraJobStatusEnum = {
INIT: 0, // 初始化中
NORMAL: 1, // 运行中
STOP: 2, // 暂停运行
}
/**
* API 异常数据的处理状态
*/
export const InfraApiErrorLogProcessStatusEnum = {
INIT: 0, // 未处理
DONE: 1, // 已处理
IGNORE: 2, // 已忽略
}
/**
* 用户的社交平台的类型枚举
*/
export const SystemUserSocialTypeEnum = {
// GITEE: {
// title: "码云",
// type: 10,
// source: "gitee",
// img: "https://cdn.jsdelivr.net/gh/justauth/justauth-oauth-logo@1.11/gitee.png",
// },
DINGTALK: {
title: "钉钉",
type: 20,
source: "dingtalk",
img: "https://cdn.jsdelivr.net/gh/justauth/justauth-oauth-logo@1.11/dingtalk.png",
},
WECHAT_ENTERPRISE: {
title: "企业微信",
type: 30,
source: "wechat_enterprise",
img: "https://cdn.jsdelivr.net/gh/justauth/justauth-oauth-logo@1.11/wechat_enterprise.png",
}
}
/**
* 支付渠道枚举
*/
export const PayChannelEnum = {
WX_PUB: {
"code": "wx_pub",
"name": "微信 JSAPI 支付",
},
WX_LITE: {
"code": "wx_lite",
"name": "微信小程序支付"
},
WX_APP: {
"code": "wx_app",
"name": "微信 APP 支付"
},
ALIPAY_PC: {
"code": "alipay_pc",
"name": "支付宝 PC 网站支付"
},
ALIPAY_WAP: {
"code": "alipay_wap",
"name": "支付宝 WAP 网站支付"
},
ALIPAY_APP: {
"code": "alipay_app",
"name": "支付宝 APP 支付"
},
ALIPAY_QR: {
"code": "alipay_qr",
"name": "支付宝扫码支付"
},
}
/**
* 支付类型枚举
*/
export const PayType = {
WECHAT: "WECHAT",
ALIPAY: "ALIPAY"
}
/**
* 支付订单状态枚举
*/
export const PayOrderStatusEnum = {
WAITING: {
status: 0,
name: '未支付'
},
SUCCESS: {
status: 10,
name: '已支付'
},
CLOSED: {
status: 20,
name: '未支付'
}
}
/**
* 支付订单回调状态枚举
*/
export const PayOrderNotifyStatusEnum = {
NO: {
status: 0,
name: '未通知'
},
SUCCESS: {
status: 10,
name: '通知成功'
},
FAILURE: {
status: 20,
name: '通知失败'
}
}
/**
* 支付订单退款状态枚举
*/
export const PayOrderRefundStatusEnum = {
NO: {
status: 0,
name: '未退款'
},
SOME: {
status: 10,
name: '部分退款'
},
ALL: {
status: 20,
name: '全部退款'
}
}
/**
* 支付退款订单状态枚举
*/
export const PayRefundStatusEnum = {
CREATE:{
status:0,
name: '退款订单生成'
},
SUCCESS:{
status:1,
name: '退款成功'
},
FAILURE:{
status:2,
name: '退款失败'
},
PROCESSING_NOTIFY:{
status:3,
name: '退款中,渠道通知结果'
},
PROCESSING_QUERY:{
status:4,
name: '退款中,系统查询结果'
},
UNKNOWN_RETRY:{
status:5,
name: '状态未知,请重试'
},
UNKNOWN_QUERY:{
status:6,
name: '状态未知,系统查询结果'
},
CLOSE:{
status:99,
name: '退款关闭'
}
}

View File

@ -0,0 +1,26 @@
/**
* 将毫秒转换成时间字符串。例如说xx 分钟
*
* @param ms 毫秒
* @returns {string} 字符串
*/
export function getDate(ms) {
const day = Math.floor(ms / (24 * 60 * 60 * 1000));
const hour = Math.floor((ms / (60 * 60 * 1000) - day * 24));
const minute = Math.floor(((ms / (60 * 1000)) - day * 24 * 60 - hour * 60));
const second = Math.floor((ms / 1000 - day * 24 * 60 * 60 - hour * 60 * 60 - minute * 60));
if (day > 0) {
return day + "天" + hour + "小时" + minute + "分钟";
}
if (hour > 0) {
return hour + "小时" + minute + "分钟";
}
if (minute > 0) {
return minute + "分钟";
}
if (second > 0) {
return second + "秒";
} else {
return 0 + "秒";
}
}

View File

@ -0,0 +1,54 @@
const DRAWING_ITEMS = 'drawingItems'
const DRAWING_ITEMS_VERSION = '1.2'
const DRAWING_ITEMS_VERSION_KEY = 'DRAWING_ITEMS_VERSION'
const DRAWING_ID = 'idGlobal'
const TREE_NODE_ID = 'treeNodeId'
const FORM_CONF = 'formConf'
export function getDrawingList() {
// 加入缓存版本的概念,保证缓存数据与程序匹配
const version = localStorage.getItem(DRAWING_ITEMS_VERSION_KEY)
if (version !== DRAWING_ITEMS_VERSION) {
localStorage.setItem(DRAWING_ITEMS_VERSION_KEY, DRAWING_ITEMS_VERSION)
saveDrawingList([])
return null
}
const str = localStorage.getItem(DRAWING_ITEMS)
if (str) return JSON.parse(str)
return null
}
export function saveDrawingList(list) {
localStorage.setItem(DRAWING_ITEMS, JSON.stringify(list))
}
export function getIdGlobal() {
const str = localStorage.getItem(DRAWING_ID)
if (str) return parseInt(str, 10)
return 100
}
export function saveIdGlobal(id) {
localStorage.setItem(DRAWING_ID, `${id}`)
}
export function getTreeNodeId() {
const str = localStorage.getItem(TREE_NODE_ID)
if (str) return parseInt(str, 10)
return 100
}
export function saveTreeNodeId(id) {
localStorage.setItem(TREE_NODE_ID, `${id}`)
}
export function getFormConf() {
const str = localStorage.getItem(FORM_CONF)
if (str) return JSON.parse(str)
return null
}
export function saveFormConf(obj) {
localStorage.setItem(FORM_CONF, JSON.stringify(obj))
}

View File

@ -0,0 +1,88 @@
/**
* Created by 芋道源码
*
* 数据字典工具类
*/
import store from '@/store'
export const DICT_TYPE = {
USER_TYPE: 'user_type',
COMMON_STATUS: 'common_status',
// ========== SYSTEM 模块 ==========
SYSTEM_USER_SEX: 'system_user_sex',
SYSTEM_MENU_TYPE: 'system_menu_type',
SYSTEM_ROLE_TYPE: 'system_role_type',
SYSTEM_DATA_SCOPE: 'system_data_scope',
SYSTEM_NOTICE_TYPE: 'system_notice_type',
SYSTEM_OPERATE_TYPE: 'system_operate_type',
SYSTEM_LOGIN_TYPE: 'system_login_type',
SYSTEM_LOGIN_RESULT: 'system_login_result',
SYSTEM_SMS_CHANNEL_CODE: 'system_sms_channel_code',
SYSTEM_SMS_TEMPLATE_TYPE: 'system_sms_template_type',
SYSTEM_SMS_SEND_STATUS: 'system_sms_send_status',
SYSTEM_SMS_RECEIVE_STATUS: 'system_sms_receive_status',
SYSTEM_ERROR_CODE_TYPE: 'system_error_code_type',
// ========== INFRA 模块 ==========
INFRA_REDIS_TIMEOUT_TYPE: 'infra_redis_timeout_type',
INFRA_JOB_STATUS: 'infra_job_status',
INFRA_JOB_LOG_STATUS: 'infra_job_log_status',
INFRA_API_ERROR_LOG_PROCESS_STATUS: 'infra_api_error_log_process_status',
INFRA_CONFIG_TYPE: 'infra_config_type',
// ========== TOOL 模块 ==========
TOOL_CODEGEN_TEMPLATE_TYPE: 'tool_codegen_template_type',
TOOL_CODEGEN_SCENE: 'tool_codegen_scene',
// ========== BPM 模块 ==========
BPM_MODEL_CATEGORY: 'bpm_model_category',
BPM_MODEL_FORM_TYPE: 'bpm_model_form_type',
BPM_TASK_ASSIGN_RULE_TYPE: 'bpm_task_assign_rule_type',
BPM_PROCESS_INSTANCE_STATUS: 'bpm_process_instance_status',
BPM_PROCESS_INSTANCE_RESULT: 'bpm_process_instance_result',
BPM_TASK_ASSIGN_SCRIPT: 'bpm_task_assign_script',
BPM_OA_LEAVE_TYPE: 'bpm_oa_leave_type',
// ========== PAY 模块 ==========
PAY_CHANNEL_WECHAT_VERSION: 'pay_channel_wechat_version', // 微信渠道版本
PAY_CHANNEL_ALIPAY_SIGN_TYPE: 'pay_channel_alipay_sign_type', // 支付渠道支付宝算法类型
PAY_CHANNEL_ALIPAY_MODE: 'pay_channel_alipay_mode', // 支付宝公钥类型
PAY_CHANNEL_ALIPAY_SERVER_TYPE: 'pay_channel_alipay_server_type', // 支付宝网关地址
PAY_CHANNEL_CODE_TYPE: 'pay_channel_code_type', // 支付渠道编码类型
PAY_ORDER_NOTIFY_STATUS: 'pay_order_notify_status', // 商户支付订单回调状态
PAY_ORDER_STATUS: 'pay_order_status', // 商户支付订单状态
PAY_ORDER_REFUND_STATUS: 'pay_order_refund_status', // 商户支付订单退款状态
PAY_REFUND_ORDER_STATUS: 'pay_refund_order_status', // 退款订单状态
PAY_REFUND_ORDER_TYPE: 'pay_refund_order_type', // 退款订单类别
}
/**
* 获取 dictType 对应的数据字典数组
*
* @param dictType 数据类型
* @returns {*|Array} 数据字典数组
*/
export function getDictDatas(dictType) {
// if (dictType === 'bpm_task_assign_script') {
// console.log(store.getters.dict_datas[dictType]);
// debugger
// }
return store.getters.dict_datas[dictType] || []
}
export function getDictDataLabel(dictType, value) {
// 获取 dictType 对应的数据字典数组
const dictDatas = getDictDatas(dictType)
if (!dictDatas || dictDatas.length === 0) {
return ''
}
// 获取 value 对应的展示名
value = value + '' // 强制转换成字符串,因为 DictData 小类数值,是字符串
for (const dictData of dictDatas) {
if (dictData.value === value) {
return dictData.label
}
}
return ''
}

View File

@ -0,0 +1,6 @@
export default {
'401': '认证失败,无法访问系统资源',
'403': '当前操作没有权限',
'404': '访问资源不存在',
'default': '系统未知错误,请反馈给管理员'
}

View File

@ -0,0 +1,13 @@
/**
* 将服务端返回的 fields 字符串数组,解析成 JSON 数组
*
* @param fields JSON 字符串数组
* @returns {*[]} JSON 数组
*/
export function decodeFields(fields) {
const drawingList = []
fields.forEach(item => {
drawingList.push(JSON.parse(item))
})
return drawingList
}

View File

@ -0,0 +1 @@
["platform-eleme","eleme","delete-solid","delete","s-tools","setting","user-solid","user","phone","phone-outline","more","more-outline","star-on","star-off","s-goods","goods","warning","warning-outline","question","info","remove","circle-plus","success","error","zoom-in","zoom-out","remove-outline","circle-plus-outline","circle-check","circle-close","s-help","help","minus","plus","check","close","picture","picture-outline","picture-outline-round","upload","upload2","download","camera-solid","camera","video-camera-solid","video-camera","message-solid","bell","s-cooperation","s-order","s-platform","s-fold","s-unfold","s-operation","s-promotion","s-home","s-release","s-ticket","s-management","s-open","s-shop","s-marketing","s-flag","s-comment","s-finance","s-claim","s-custom","s-opportunity","s-data","s-check","s-grid","menu","share","d-caret","caret-left","caret-right","caret-bottom","caret-top","bottom-left","bottom-right","back","right","bottom","top","top-left","top-right","arrow-left","arrow-right","arrow-down","arrow-up","d-arrow-left","d-arrow-right","video-pause","video-play","refresh","refresh-right","refresh-left","finished","sort","sort-up","sort-down","rank","loading","view","c-scale-to-original","date","edit","edit-outline","folder","folder-opened","folder-add","folder-remove","folder-delete","folder-checked","tickets","document-remove","document-delete","document-copy","document-checked","document","document-add","printer","paperclip","takeaway-box","search","monitor","attract","mobile","scissors","umbrella","headset","brush","mouse","coordinate","magic-stick","reading","data-line","data-board","pie-chart","data-analysis","collection-tag","film","suitcase","suitcase-1","receiving","collection","files","notebook-1","notebook-2","toilet-paper","office-building","school","table-lamp","house","no-smoking","smoking","shopping-cart-full","shopping-cart-1","shopping-cart-2","shopping-bag-1","shopping-bag-2","sold-out","sell","present","box","bank-card","money","coin","wallet","discount","price-tag","news","guide","male","female","thumb","cpu","link","connection","open","turn-off","set-up","chat-round","chat-line-round","chat-square","chat-dot-round","chat-dot-square","chat-line-square","message","postcard","position","turn-off-microphone","microphone","close-notification","bangzhu","time","odometer","crop","aim","switch-button","full-screen","copy-document","mic","stopwatch","medal-1","medal","trophy","trophy-1","first-aid-kit","discover","place","location","location-outline","location-information","add-location","delete-location","map-location","alarm-clock","timer","watch-1","watch","lock","unlock","key","service","mobile-phone","bicycle","truck","ship","basketball","football","soccer","baseball","wind-power","light-rain","lightning","heavy-rain","sunrise","sunrise-1","sunset","sunny","cloudy","partly-cloudy","cloudy-and-sunny","moon","moon-night","dish","dish-1","food","chicken","fork-spoon","knife-fork","burger","tableware","sugar","dessert","ice-cream","hot-water","water-cup","coffee-cup","cold-drink","goblet","goblet-full","goblet-square","goblet-square-full","refrigerator","grape","watermelon","cherry","apple","pear","orange","coffee","ice-tea","ice-drink","milk-tea","potato-strips","lollipop","ice-cream-square","ice-cream-round"]

View File

@ -0,0 +1,429 @@
import { parseTime } from './ruoyi'
/**
* 表格时间格式化
*/
export function formatDate(cellValue) {
if (cellValue == null || cellValue == "") return "";
var date = new Date(cellValue)
var year = date.getFullYear()
var month = date.getMonth() + 1 < 10 ? '0' + (date.getMonth() + 1) : date.getMonth() + 1
var day = date.getDate() < 10 ? '0' + date.getDate() : date.getDate()
var hours = date.getHours() < 10 ? '0' + date.getHours() : date.getHours()
var minutes = date.getMinutes() < 10 ? '0' + date.getMinutes() : date.getMinutes()
var seconds = date.getSeconds() < 10 ? '0' + date.getSeconds() : date.getSeconds()
return year + '-' + month + '-' + day + ' ' + hours + ':' + minutes + ':' + seconds
}
/**
* @param {number} time
* @param {string} option
* @returns {string}
*/
export function formatTime(time, option) {
if (('' + time).length === 10) {
time = parseInt(time) * 1000
} else {
time = +time
}
const d = new Date(time)
const now = Date.now()
const diff = (now - d) / 1000
if (diff < 30) {
return '刚刚'
} else if (diff < 3600) {
// less 1 hour
return Math.ceil(diff / 60) + '分钟前'
} else if (diff < 3600 * 24) {
return Math.ceil(diff / 3600) + '小时前'
} else if (diff < 3600 * 24 * 2) {
return '1天前'
}
if (option) {
return parseTime(time, option)
} else {
return (
d.getMonth() +
1 +
'月' +
d.getDate() +
'日' +
d.getHours() +
'时' +
d.getMinutes() +
'分'
)
}
}
/**
* @param {string} url
* @returns {Object}
*/
export function getQueryObject(url) {
url = url == null ? window.location.href : url
const search = url.substring(url.lastIndexOf('?') + 1)
const obj = {}
const reg = /([^?&=]+)=([^?&=]*)/g
search.replace(reg, (rs, $1, $2) => {
const name = decodeURIComponent($1)
let val = decodeURIComponent($2)
val = String(val)
obj[name] = val
return rs
})
return obj
}
/**
* @param {string} input value
* @returns {number} output value
*/
export function byteLength(str) {
// returns the byte length of an utf8 string
let s = str.length
for (var i = str.length - 1; i >= 0; i--) {
const code = str.charCodeAt(i)
if (code > 0x7f && code <= 0x7ff) s++
else if (code > 0x7ff && code <= 0xffff) s += 2
if (code >= 0xDC00 && code <= 0xDFFF) i--
}
return s
}
/**
* @param {Array} actual
* @returns {Array}
*/
export function cleanArray(actual) {
const newArray = []
for (let i = 0; i < actual.length; i++) {
if (actual[i]) {
newArray.push(actual[i])
}
}
return newArray
}
/**
* @param {Object} json
* @returns {Array}
*/
export function param(json) {
if (!json) return ''
return cleanArray(
Object.keys(json).map(key => {
if (json[key] === undefined) return ''
return encodeURIComponent(key) + '=' + encodeURIComponent(json[key])
})
).join('&')
}
/**
* @param {string} url
* @returns {Object}
*/
export function param2Obj(url) {
const search = decodeURIComponent(url.split('?')[1]).replace(/\+/g, ' ')
if (!search) {
return {}
}
const obj = {}
const searchArr = search.split('&')
searchArr.forEach(v => {
const index = v.indexOf('=')
if (index !== -1) {
const name = v.substring(0, index)
const val = v.substring(index + 1, v.length)
obj[name] = val
}
})
return obj
}
/**
* @param {string} val
* @returns {string}
*/
export function html2Text(val) {
const div = document.createElement('div')
div.innerHTML = val
return div.textContent || div.innerText
}
/**
* Merges two objects, giving the last one precedence
* @param {Object} target
* @param {(Object|Array)} source
* @returns {Object}
*/
export function objectMerge(target, source) {
if (typeof target !== 'object') {
target = {}
}
if (Array.isArray(source)) {
return source.slice()
}
Object.keys(source).forEach(property => {
const sourceProperty = source[property]
if (typeof sourceProperty === 'object') {
target[property] = objectMerge(target[property], sourceProperty)
} else {
target[property] = sourceProperty
}
})
return target
}
/**
* @param {HTMLElement} element
* @param {string} className
*/
export function toggleClass(element, className) {
if (!element || !className) {
return
}
let classString = element.className
const nameIndex = classString.indexOf(className)
if (nameIndex === -1) {
classString += '' + className
} else {
classString =
classString.substr(0, nameIndex) +
classString.substr(nameIndex + className.length)
}
element.className = classString
}
/**
* @param {string} type
* @returns {Date}
*/
export function getTime(type) {
if (type === 'start') {
return new Date().getTime() - 3600 * 1000 * 24 * 90
} else {
return new Date(new Date().toDateString())
}
}
/**
* @param {Function} func
* @param {number} wait
* @param {boolean} immediate
* @return {*}
*/
export function debounce(func, wait, immediate) {
let timeout, args, context, timestamp, result
const later = function() {
// 据上一次触发时间间隔
const last = +new Date() - timestamp
// 上次被包装函数被调用时间间隔 last 小于设定时间间隔 wait
if (last < wait && last > 0) {
timeout = setTimeout(later, wait - last)
} else {
timeout = null
// 如果设定为immediate===true因为开始边界已经调用过了此处无需调用
if (!immediate) {
result = func.apply(context, args)
if (!timeout) context = args = null
}
}
}
return function(...args) {
context = this
timestamp = +new Date()
const callNow = immediate && !timeout
// 如果延时不存在,重新设定延时
if (!timeout) timeout = setTimeout(later, wait)
if (callNow) {
result = func.apply(context, args)
context = args = null
}
return result
}
}
// /**
// * This is just a simple version of deep copy
// * Has a lot of edge cases bug
// * If you want to use a perfect deep copy, use lodash's _.cloneDeep
// * @param {Object} source
// * @returns {Object}
// */
// export function deepClone(source) {
// if (!source && typeof source !== 'object') {
// throw new Error('error arguments', 'deepClone')
// }
// const targetObj = source.constructor === Array ? [] : {}
// Object.keys(source).forEach(keys => {
// if (source[keys] && typeof source[keys] === 'object') {
// targetObj[keys] = deepClone(source[keys])
// } else {
// targetObj[keys] = source[keys]
// }
// })
// return targetObj
// }
// 深拷贝对象
// add by 芋道源码 https://github.com/JakHuang/form-generator/blob/dev/src/utils/index.js#L107
export function deepClone(obj) {
const _toString = Object.prototype.toString
// null, undefined, non-object, function
if (!obj || typeof obj !== 'object') {
return obj
}
// DOM Node
if (obj.nodeType && 'cloneNode' in obj) {
return obj.cloneNode(true)
}
// Date
if (_toString.call(obj) === '[object Date]') {
return new Date(obj.getTime())
}
// RegExp
if (_toString.call(obj) === '[object RegExp]') {
const flags = []
if (obj.global) { flags.push('g') }
if (obj.multiline) { flags.push('m') }
if (obj.ignoreCase) { flags.push('i') }
return new RegExp(obj.source, flags.join(''))
}
const result = Array.isArray(obj) ? [] : obj.constructor ? new obj.constructor() : {}
for (const key in obj) {
result[key] = deepClone(obj[key])
}
return result
}
/**
* @param {Array} arr
* @returns {Array}
*/
export function uniqueArr(arr) {
return Array.from(new Set(arr))
}
/**
* @returns {string}
*/
export function createUniqueString() {
const timestamp = +new Date() + ''
const randomNum = parseInt((1 + Math.random()) * 65536) + ''
return (+(randomNum + timestamp)).toString(32)
}
/**
* Check if an element has a class
* @param {HTMLElement} elm
* @param {string} cls
* @returns {boolean}
*/
export function hasClass(ele, cls) {
return !!ele.className.match(new RegExp('(\\s|^)' + cls + '(\\s|$)'))
}
/**
* Add class to element
* @param {HTMLElement} elm
* @param {string} cls
*/
export function addClass(ele, cls) {
if (!hasClass(ele, cls)) ele.className += ' ' + cls
}
/**
* Remove class from element
* @param {HTMLElement} elm
* @param {string} cls
*/
export function removeClass(ele, cls) {
if (hasClass(ele, cls)) {
const reg = new RegExp('(\\s|^)' + cls + '(\\s|$)')
ele.className = ele.className.replace(reg, ' ')
}
}
export function makeMap(str, expectsLowerCase) {
const map = Object.create(null)
const list = str.split(',')
for (let i = 0; i < list.length; i++) {
map[list[i]] = true
}
return expectsLowerCase
? val => map[val.toLowerCase()]
: val => map[val]
}
export const exportDefault = 'export default '
export const beautifierConf = {
html: {
indent_size: '2',
indent_char: ' ',
max_preserve_newlines: '-1',
preserve_newlines: false,
keep_array_indentation: false,
break_chained_methods: false,
indent_scripts: 'separate',
brace_style: 'end-expand',
space_before_conditional: true,
unescape_strings: false,
jslint_happy: false,
end_with_newline: true,
wrap_line_length: '110',
indent_inner_html: true,
comma_first: false,
e4x: true,
indent_empty_lines: true
},
js: {
indent_size: '2',
indent_char: ' ',
max_preserve_newlines: '-1',
preserve_newlines: false,
keep_array_indentation: false,
break_chained_methods: false,
indent_scripts: 'normal',
brace_style: 'end-expand',
space_before_conditional: true,
unescape_strings: false,
jslint_happy: true,
end_with_newline: true,
wrap_line_length: '110',
indent_inner_html: true,
comma_first: false,
e4x: true,
indent_empty_lines: true
}
}
// 首字母大小
export function titleCase(str) {
return str.replace(/( |^)[a-z]/g, L => L.toUpperCase())
}
// 下划转驼峰
export function camelCase(str) {
return str.replace(/-[a-z]/g, str1 => str1.substr(-1).toUpperCase())
}
export function isNumberStr(str) {
return /^[+-]?(0|([1-9]\d*))(\.\d+)?$/g.test(str)
}

View File

@ -0,0 +1,30 @@
import JSEncrypt from 'jsencrypt/bin/jsencrypt.min'
// 密钥对生成 http://web.chacuo.net/netrsakeypair
const publicKey = 'MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAKoR8mX0rGKLqzcWmOzbfj64K8ZIgOdH\n' +
'nzkXSOVOZbFu/TJhZ7rFAN+eaGkl3C4buccQd/EjEsj9ir7ijT7h96MCAwEAAQ=='
const privateKey = 'MIIBVAIBADANBgkqhkiG9w0BAQEFAASCAT4wggE6AgEAAkEAqhHyZfSsYourNxaY\n' +
'7Nt+PrgrxkiA50efORdI5U5lsW79MmFnusUA355oaSXcLhu5xxB38SMSyP2KvuKN\n' +
'PuH3owIDAQABAkAfoiLyL+Z4lf4Myxk6xUDgLaWGximj20CUf+5BKKnlrK+Ed8gA\n' +
'kM0HqoTt2UZwA5E2MzS4EI2gjfQhz5X28uqxAiEA3wNFxfrCZlSZHb0gn2zDpWow\n' +
'cSxQAgiCstxGUoOqlW8CIQDDOerGKH5OmCJ4Z21v+F25WaHYPxCFMvwxpcw99Ecv\n' +
'DQIgIdhDTIqD2jfYjPTY8Jj3EDGPbH2HHuffvflECt3Ek60CIQCFRlCkHpi7hthh\n' +
'YhovyloRYsM+IS9h/0BzlEAuO0ktMQIgSPT3aFAgJYwKpqRYKlLDVcflZFCKY7u3\n' +
'UP8iWi1Qw0Y='
// 加密
export function encrypt(txt) {
const encryptor = new JSEncrypt()
encryptor.setPublicKey(publicKey) // 设置公钥
return encryptor.encrypt(txt) // 对数据进行加密
}
// 解密
export function decrypt(txt) {
const encryptor = new JSEncrypt()
encryptor.setPrivateKey(privateKey) // 设置私钥
return encryptor.decrypt(txt) // 对数据进行解密
}

View File

@ -0,0 +1,28 @@
import loadScript from './loadScript'
import ELEMENT from 'element-ui'
import pluginsConfig from './pluginsConfig'
let beautifierObj
export default function loadBeautifier(cb) {
const { beautifierUrl } = pluginsConfig
if (beautifierObj) {
cb(beautifierObj)
return
}
const loading = ELEMENT.Loading.service({
fullscreen: true,
lock: true,
text: '格式化资源加载中...',
spinner: 'el-icon-loading',
background: 'rgba(255, 255, 255, 0.5)'
})
loadScript(beautifierUrl, () => {
loading.close()
// eslint-disable-next-line no-undef
beautifierObj = beautifier
cb(beautifierObj)
})
}

View File

@ -0,0 +1,40 @@
import loadScript from './loadScript'
import ELEMENT from 'element-ui'
import pluginsConfig from './pluginsConfig'
// monaco-editor单例
let monacoEidtor
/**
* 动态加载monaco-editor cdn资源
* @param {Function} cb 回调,必填
*/
export default function loadMonaco(cb) {
if (monacoEidtor) {
cb(monacoEidtor)
return
}
const { monacoEditorUrl: vs } = pluginsConfig
// 使用element ui实现加载提示
const loading = ELEMENT.Loading.service({
fullscreen: true,
lock: true,
text: '编辑器资源初始化中...',
spinner: 'el-icon-loading',
background: 'rgba(255, 255, 255, 0.5)'
})
!window.require && (window.require = {})
!window.require.paths && (window.require.paths = {})
window.require.paths.vs = vs
loadScript(`${vs}/loader.js`, () => {
window.require(['vs/editor/editor.main'], () => {
loading.close()
monacoEidtor = window.monaco
cb(monacoEidtor)
})
})
}

View File

@ -0,0 +1,60 @@
const callbacks = {}
/**
* 加载一个远程脚本
* @param {String} src 一个远程脚本
* @param {Function} callback 回调
*/
function loadScript(src, callback) {
const existingScript = document.getElementById(src)
const cb = callback || (() => {})
if (!existingScript) {
callbacks[src] = []
const $script = document.createElement('script')
$script.src = src
$script.id = src
$script.async = 1
document.body.appendChild($script)
const onEnd = 'onload' in $script ? stdOnEnd.bind($script) : ieOnEnd.bind($script)
onEnd($script)
}
callbacks[src].push(cb)
function stdOnEnd(script) {
script.onload = () => {
this.onerror = this.onload = null
callbacks[src].forEach(item => {
item(null, script)
})
delete callbacks[src]
}
script.onerror = () => {
this.onerror = this.onload = null
cb(new Error(`Failed to load ${src}`), script)
}
}
function ieOnEnd(script) {
script.onreadystatechange = () => {
if (this.readyState !== 'complete' && this.readyState !== 'loaded') return
this.onreadystatechange = null
callbacks[src].forEach(item => {
item(null, script)
})
delete callbacks[src]
}
}
}
/**
* 顺序加载一组远程脚本
* @param {Array} list 一组远程脚本
* @param {Function} cb 回调
*/
export function loadScriptQueue(list, cb) {
const first = list.shift()
list.length ? loadScript(first, () => loadScriptQueue(list, cb)) : loadScript(first, cb)
}
export default loadScript

View File

@ -0,0 +1,29 @@
import loadScript from './loadScript'
import ELEMENT from 'element-ui'
import pluginsConfig from './pluginsConfig'
let tinymceObj
export default function loadTinymce(cb) {
const { tinymceUrl } = pluginsConfig
if (tinymceObj) {
cb(tinymceObj)
return
}
const loading = ELEMENT.Loading.service({
fullscreen: true,
lock: true,
text: '富文本资源加载中...',
spinner: 'el-icon-loading',
background: 'rgba(255, 255, 255, 0.5)'
})
loadScript(tinymceUrl, () => {
loading.close()
// eslint-disable-next-line no-undef
tinymceObj = tinymce
cb(tinymceObj)
})
}

View File

@ -0,0 +1,51 @@
import store from '@/store'
/**
* 字符权限校验
* @param {Array} value 校验值
* @returns {Boolean}
*/
export function checkPermi(value) {
if (value && value instanceof Array && value.length > 0) {
const permissions = store.getters && store.getters.permissions
const permissionDatas = value
const all_permission = "*:*:*";
const hasPermission = permissions.some(permission => {
return all_permission === permission || permissionDatas.includes(permission)
})
if (!hasPermission) {
return false
}
return true
} else {
console.error(`need roles! Like checkPermi="['system:user:add','system:user:edit']"`)
return false
}
}
/**
* 角色权限校验
* @param {Array} value 校验值
* @returns {Boolean}
*/
export function checkRole(value) {
if (value && value instanceof Array && value.length > 0) {
const roles = store.getters && store.getters.roles
const permissionRoles = value
const super_admin = "admin";
const hasRole = roles.some(role => {
return super_admin === role || permissionRoles.includes(role)
})
if (!hasRole) {
return false
}
return true
} else {
console.error(`need roles! Like checkRole="['admin','editor']"`)
return false
}
}

View File

@ -0,0 +1,13 @@
const CDN = 'https://lib.baomitu.com/' // CDN Homepage: https://cdn.baomitu.com/
const publicPath = process.env.BASE_URL
function splicingPluginUrl(PluginName, version, fileName) {
return `${CDN}${PluginName}/${version}/${fileName}`
}
export default {
beautifierUrl: splicingPluginUrl('js-beautify', '1.13.5', 'beautifier.min.js'),
// monacoEditorUrl: splicingPluginUrl('monaco-editor', '0.19.3', 'min/vs'), // 使用 monaco-editor CDN 链接
monacoEditorUrl: `${publicPath}libs/monaco-editor/vs`, // 使用 monaco-editor 本地代码
tinymceUrl: splicingPluginUrl('tinymce', '5.7.0', 'tinymce.min.js')
}

View File

@ -0,0 +1,131 @@
import axios from 'axios'
import { Notification, MessageBox, Message } from 'element-ui'
import store from '@/store'
import { getToken } from '@/utils/auth'
import errorCode from '@/utils/errorCode'
import Cookies from "js-cookie";
axios.defaults.headers['Content-Type'] = 'application/json;charset=utf-8'
// 创建axios实例
const service = axios.create({
// axios中请求配置有baseURL选项表示请求URL公共部分
baseURL: process.env.VUE_APP_BASE_API + '/admin-api/', // 此处的 /admin-api/ 地址,原因是后端的基础路径为 /admin-api/
// 超时
timeout: 10000
})
// request拦截器
service.interceptors.request.use(config => {
// 是否需要设置 token
const isToken = (config.headers || {}).isToken === false
if (getToken() && !isToken) {
config.headers['Authorization'] = 'Bearer ' + getToken() // 让每个请求携带自定义token 请根据实际情况自行修改
}
// 设置租户
const tenantId = Cookies.get('tenantId');
if (tenantId) {
config.headers['tenant-id'] = tenantId;
}
// get请求映射params参数
if (config.method === 'get' && config.params) {
let url = config.url + '?';
for (const propName of Object.keys(config.params)) {
const value = config.params[propName];
var part = encodeURIComponent(propName) + "=";
if (value !== null && typeof(value) !== "undefined") {
if (typeof value === 'object') {
for (const key of Object.keys(value)) {
let params = propName + '[' + key + ']';
var subPart = encodeURIComponent(params) + "=";
url += subPart + encodeURIComponent(value[key]) + "&";
}
} else {
url += part + encodeURIComponent(value) + "&";
}
}
}
url = url.slice(0, -1);
config.params = {};
config.url = url;
}
return config
}, error => {
console.log(error)
Promise.reject(error)
})
// 响应拦截器
service.interceptors.response.use(res => {
// 未设置状态码则默认成功状态
const code = res.data.code || 200;
// 获取错误信息
const msg = errorCode[code] || res.data.msg || errorCode['default']
if (code === 401) {
MessageBox.confirm('登录状态已过期,您可以继续留在该页面,或者重新登录', '系统提示', {
confirmButtonText: '重新登录',
cancelButtonText: '取消',
type: 'warning'
}
).then(() => {
store.dispatch('LogOut').then(() => {
// if (location.pathname !== '/login') { // 避免重复跳转
//
// }
location.href = '/index';
})
})
} else if (code === 500) {
Message({
message: msg,
type: 'error'
})
return Promise.reject(new Error(msg))
} else if (code === 901) {
Message({
type: 'error',
duration: 0,
dangerouslyUseHTMLString: true,
message: '<div>演示模式,不发进行写操作</div>'
+ '<div> &nbsp; </div>'
+ '<div>参考 https://www.iocoder.cn/Yudao/build-debugger-environment 教程</div>'
+ '<div> &nbsp; </div>'
+ '<div>5 分钟搭建本地环境</div>',
})
return Promise.reject(new Error(msg))
} else if (code !== 200) {
Notification.error({
title: msg
})
return Promise.reject('error')
} else {
return res.data
}
},
error => {
console.log('err' + error)
let { message } = error;
if (message === "Network Error") {
message = "后端接口连接异常";
}
else if (message.includes("timeout")) {
message = "系统接口请求超时";
}
else if (message.includes("Request failed with status code")) {
message = "系统接口" + message.substr(message.length - 3) + "异常";
}
Message({
message: message,
type: 'error',
duration: 5 * 1000
})
return Promise.reject(error)
}
)
export function getBaseHeader() {
return {
'Authorization': "Bearer " + getToken(),
'tenant-id': Cookies.get('tenantId'),
}
}
export default service

View File

@ -0,0 +1,228 @@
/**
* 通用js方法封装处理
* Copyright (c) 2019 ruoyi
*/
const baseURL = process.env.VUE_APP_BASE_API
// 日期格式化
export function parseTime(time, pattern) {
if (arguments.length === 0 || !time) {
return null
}
const format = pattern || '{y}-{m}-{d} {h}:{i}:{s}'
let date
if (typeof time === 'object') {
date = time
} else {
if ((typeof time === 'string') && (/^[0-9]+$/.test(time))) {
time = parseInt(time)
} else if (typeof time === 'string') {
time = time.replace(new RegExp(/-/gm), '/');
}
if ((typeof time === 'number') && (time.toString().length === 10)) {
time = time * 1000
}
date = new Date(time)
}
const formatObj = {
y: date.getFullYear(),
m: date.getMonth() + 1,
d: date.getDate(),
h: date.getHours(),
i: date.getMinutes(),
s: date.getSeconds(),
a: date.getDay()
}
const time_str = format.replace(/{(y|m|d|h|i|s|a)+}/g, (result, key) => {
let value = formatObj[key]
// Note: getDay() returns 0 on Sunday
if (key === 'a') {
return ['日', '一', '二', '三', '四', '五', '六'][value]
}
if (result.length > 0 && value < 10) {
value = '0' + value
}
return value || 0
})
return time_str
}
// 表单重置
export function resetForm(refName) {
if (this.$refs[refName]) {
this.$refs[refName].resetFields();
}
}
// 添加日期范围
export function addDateRange(params, dateRange, propName) {
const search = params;
search.params = {};
if (null != dateRange && '' !== dateRange) {
if (typeof (propName) === "undefined") {
search["beginTime"] = dateRange[0];
search["endTime"] = dateRange[1];
} else {
search["begin" + propName] = dateRange[0];
search["end" + propName] = dateRange[1];
}
}
return search;
}
/**
* 添加开始和结束时间到 params 参数中
*
* @param params 参数
* @param dateRange 时间范围。
* 大小为 2 的数组,每个时间为 yyyy-MM-dd 格式
* @param propName 加入的参数名,可以为空
*/
export function addBeginAndEndTime(params, dateRange, propName) {
// 必须传入参数
if (!dateRange) {
return params;
}
// 如果未传递 propName 属性,默认为 time
if (!propName) {
propName = 'Time';
} else {
propName = propName.charAt(0).toUpperCase() + propName.slice(1);
}
// 设置参数
if (dateRange[0]) {
params['begin' + propName] = dateRange[0] + ' 00:00:00';
}
if (dateRange[1]) {
params['end' + propName] = dateRange[1] + ' 23:59:59';
}
return params;
}
// 回显数据字典 原若依所保留,请使用 dict.js 中的新方法
export function selectDictLabel(datas, value) {
var actions = [];
Object.keys(datas).some((key) => {
if (datas[key].dictValue == ('' + value)) {
actions.push(datas[key].dictLabel);
return true;
}
})
return actions.join('');
}
// 通用下载方法
export function download(fileName) {
window.location.href = baseURL + "/common/download?fileName=" + encodeURI(fileName) + "&delete=" + true;
}
// 下载 Excel 方法
export function downloadExcel(data, fileName) {
download0(data, fileName, 'application/vnd.ms-excel');
}
// 下载 Word 方法
export function downloadWord(data, fileName) {
download0(data, fileName, 'application/msword');
}
// 下载 Zip 方法
export function downloadZip(data, fileName) {
download0(data, fileName, 'application/zip');
}
// 下载 Html 方法
export function downloadHtml(data, fileName) {
download0(data, fileName, 'text/html');
}
// 下载 Markdown 方法
export function downloadMarkdown(data, fileName) {
download0(data, fileName, 'text/markdown');
}
function download0(data, fileName, mineType) {
// 创建 blob
let blob = new Blob([data], {type: mineType});
// 创建 href 超链接,点击进行下载
window.URL = window.URL || window.webkitURL;
let href = URL.createObjectURL(blob);
let downA = document.createElement("a");
downA.href = href;
downA.download = fileName;
downA.click();
// 销毁超连接
window.URL.revokeObjectURL(href);
}
// 字符串格式化(%s )
export function sprintf(str) {
var args = arguments, flag = true, i = 1;
str = str.replace(/%s/g, function () {
var arg = args[i++];
if (typeof arg === 'undefined') {
flag = false;
return '';
}
return arg;
});
return flag ? str : '';
}
// 转换字符串undefined,null等转化为""
export function praseStrEmpty(str) {
if (!str || str == "undefined" || str == "null") {
return "";
}
return str;
}
/**
* 构造树型结构数据
* @param {*} data 数据源
* @param {*} id id字段 默认 'id'
* @param {*} parentId 父节点字段 默认 'parentId'
* @param {*} children 孩子节点字段 默认 'children'
* @param {*} rootId 根Id 默认 0
*/
export function handleTree(data, id, parentId, children, rootId) {
id = id || 'id'
parentId = parentId || 'parentId'
children = children || 'children'
rootId = rootId || Math.min.apply(Math, data.map(item => {
return item[parentId]
})) || 0
//对源数据深度克隆
const cloneData = JSON.parse(JSON.stringify(data))
//循环所有项
const treeData = cloneData.filter(father => {
let branchArr = cloneData.filter(child => {
//返回每一项的子级数组
return father[id] === child[parentId]
});
branchArr.length > 0 ? father.children = branchArr : '';
//返回第一层
return father[parentId] === rootId;
});
return treeData !== '' ? treeData : data;
}
/**
* 获取当前时间
* @param timeStr 时分秒 字符串 格式为 xx:xx:xx
*/
export function getNowDateTime(timeStr) {
let now = new Date();
let year = now.getFullYear(); //得到年份
let month = (now.getMonth() + 1).toString().padStart(2, "0"); //得到月份
let day = now.getDate().toString().padStart(2, "0"); //得到日期
if (timeStr != null) {
return `${year}-${month}-${day} ${timeStr}`;
}
let hours = now.getHours().toString().padStart(2, "0") // 得到小时;
let minutes = now.getMinutes().toString().padStart(2, "0") // 得到分钟;
let seconds = now.getSeconds().toString().padStart(2, "0") // 得到秒;
return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;
}

View File

@ -0,0 +1,58 @@
Math.easeInOutQuad = function(t, b, c, d) {
t /= d / 2
if (t < 1) {
return c / 2 * t * t + b
}
t--
return -c / 2 * (t * (t - 2) - 1) + b
}
// requestAnimationFrame for Smart Animating http://goo.gl/sx5sts
var requestAnimFrame = (function() {
return window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || function(callback) { window.setTimeout(callback, 1000 / 60) }
})()
/**
* Because it's so fucking difficult to detect the scrolling element, just move them all
* @param {number} amount
*/
function move(amount) {
document.documentElement.scrollTop = amount
document.body.parentNode.scrollTop = amount
document.body.scrollTop = amount
}
function position() {
return document.documentElement.scrollTop || document.body.parentNode.scrollTop || document.body.scrollTop
}
/**
* @param {number} to
* @param {number} duration
* @param {Function} callback
*/
export function scrollTo(to, duration, callback) {
const start = position()
const change = to - start
const increment = 20
let currentTime = 0
duration = (typeof (duration) === 'undefined') ? 500 : duration
var animateScroll = function() {
// increment the time
currentTime += increment
// find the value with the quadratic in-out easing function
var val = Math.easeInOutQuad(currentTime, start, change, duration)
// move the document.body
move(val)
// do the animation unless its over
if (currentTime < duration) {
requestAnimFrame(animateScroll)
} else {
if (callback && typeof (callback) === 'function') {
// the animation is done so lets callback
callback()
}
}
}
animateScroll()
}

View File

@ -0,0 +1,83 @@
/**
* @param {string} path
* @returns {Boolean}
*/
export function isExternal(path) {
return /^(https?:|mailto:|tel:)/.test(path)
}
/**
* @param {string} str
* @returns {Boolean}
*/
export function validUsername(str) {
const valid_map = ['admin', 'editor']
return valid_map.indexOf(str.trim()) >= 0
}
/**
* @param {string} url
* @returns {Boolean}
*/
export function validURL(url) {
const reg = /^(https?|ftp):\/\/([a-zA-Z0-9.-]+(:[a-zA-Z0-9.&%$-]+)*@)*((25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9][0-9]?)(\.(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])){3}|([a-zA-Z0-9-]+\.)*[a-zA-Z0-9-]+\.(com|edu|gov|int|mil|net|org|biz|arpa|info|name|pro|aero|coop|museum|[a-zA-Z]{2}))(:[0-9]+)*(\/($|[a-zA-Z0-9.,?'\\+&%$#=~_-]+))*$/
return reg.test(url)
}
/**
* @param {string} str
* @returns {Boolean}
*/
export function validLowerCase(str) {
const reg = /^[a-z]+$/
return reg.test(str)
}
/**
* @param {string} str
* @returns {Boolean}
*/
export function validUpperCase(str) {
const reg = /^[A-Z]+$/
return reg.test(str)
}
/**
* @param {string} str
* @returns {Boolean}
*/
export function validAlphabets(str) {
const reg = /^[A-Za-z]+$/
return reg.test(str)
}
/**
* @param {string} email
* @returns {Boolean}
*/
export function validEmail(email) {
const reg = /^(([^<>()\[\]\\.,;:\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,}))$/
return reg.test(email)
}
/**
* @param {string} str
* @returns {Boolean}
*/
export function isString(str) {
if (typeof str === 'string' || str instanceof String) {
return true
}
return false
}
/**
* @param {Array} arg
* @returns {Boolean}
*/
export function isArray(arg) {
if (typeof Array.isArray === 'undefined') {
return Object.prototype.toString.call(arg) === '[object Array]'
}
return Array.isArray(arg)
}