util.js 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417
  1. import * as api from '@/api/api'
  2. import { isURL } from '@/utils/validate'
  3. export function timeFix() {
  4. const time = new Date()
  5. const hour = time.getHours()
  6. return hour < 9 ? '早上好' : (hour <= 11 ? '上午好' : (hour <= 13 ? '中午好' : (hour < 20 ? '下午好' : '晚上好')))
  7. }
  8. export function welcome() {
  9. const arr = ['休息一会儿吧', '准备吃什么呢?', '要不要打一把 DOTA', '我猜你可能累了']
  10. let index = Math.floor((Math.random()*arr.length))
  11. return arr[index]
  12. }
  13. /**
  14. * 触发 window.resize
  15. */
  16. export function triggerWindowResizeEvent() {
  17. let event = document.createEvent('HTMLEvents')
  18. event.initEvent('resize', true, true)
  19. event.eventType = 'message'
  20. window.dispatchEvent(event)
  21. }
  22. /**
  23. * 过滤对象中为空的属性
  24. * @param obj
  25. * @returns {*}
  26. */
  27. export function filterObj(obj) {
  28. if (!(typeof obj == 'object')) {
  29. return;
  30. }
  31. for ( var key in obj) {
  32. if (obj.hasOwnProperty(key)
  33. && (obj[key] == null || obj[key] == undefined || obj[key] === '')) {
  34. delete obj[key];
  35. }
  36. }
  37. return obj;
  38. }
  39. /**
  40. * 时间格式化
  41. * @param value
  42. * @param fmt
  43. * @returns {*}
  44. */
  45. export function formatDate(value, fmt) {
  46. var regPos = /^\d+(\.\d+)?$/;
  47. if(regPos.test(value)){
  48. //如果是数字
  49. let getDate = new Date(value);
  50. let o = {
  51. 'M+': getDate.getMonth() + 1,
  52. 'd+': getDate.getDate(),
  53. 'h+': getDate.getHours(),
  54. 'm+': getDate.getMinutes(),
  55. 's+': getDate.getSeconds(),
  56. 'q+': Math.floor((getDate.getMonth() + 3) / 3),
  57. 'S': getDate.getMilliseconds()
  58. };
  59. if (/(y+)/.test(fmt)) {
  60. fmt = fmt.replace(RegExp.$1, (getDate.getFullYear() + '').substr(4 - RegExp.$1.length))
  61. }
  62. for (let k in o) {
  63. if (new RegExp('(' + k + ')').test(fmt)) {
  64. fmt = fmt.replace(RegExp.$1, (RegExp.$1.length === 1) ? (o[k]) : (('00' + o[k]).substr(('' + o[k]).length)))
  65. }
  66. }
  67. return fmt;
  68. }else{
  69. //TODO
  70. value = value.trim();
  71. return value.substr(0,fmt.length);
  72. }
  73. }
  74. // 生成首页路由
  75. export function generateIndexRouter(data) {
  76. let indexRouter = [{
  77. path: '/',
  78. name: 'dashboard',
  79. //component: () => import('@/components/layouts/BasicLayout'),
  80. component: resolve => require(['@/components/layouts/TabLayout'], resolve),
  81. meta: { title: '首页' },
  82. redirect: '/dashboard/analysis',
  83. children: [
  84. ...generateChildRouters(data)
  85. ]
  86. },{
  87. "path": "*", "redirect": "/404", "hidden": true
  88. }]
  89. return indexRouter;
  90. }
  91. // 生成嵌套路由(子路由)
  92. function generateChildRouters (data) {
  93. const routers = [];
  94. for (var item of data) {
  95. let component = "";
  96. if(item.component.indexOf("layouts")>=0){
  97. component = "components/"+item.component;
  98. }else{
  99. component = "views/"+item.component;
  100. }
  101. // eslint-disable-next-line
  102. let URL = (item.meta.url|| '').replace(/{{([^}}]+)?}}/g, (s1, s2) => eval(s2)) // URL支持{{ window.xxx }}占位符变量
  103. if (isURL(URL)) {
  104. item.meta.url = URL;
  105. }
  106. let menu = {
  107. path: item.path,
  108. name: item.name,
  109. redirect:item.redirect,
  110. component: resolve => require(['@/' + component+'.vue'], resolve),
  111. hidden:item.hidden,
  112. //component:()=> import(`@/views/${item.component}.vue`),
  113. meta: {
  114. title:item.meta.title ,
  115. icon: item.meta.icon,
  116. url:item.meta.url ,
  117. permissionList:item.meta.permissionList,
  118. keepAlive:item.meta.keepAlive,
  119. /*update_begin author:wuxianquan date:20190908 for:赋值 */
  120. internalOrExternal:item.meta.internalOrExternal
  121. /*update_end author:wuxianquan date:20190908 for:赋值 */
  122. }
  123. }
  124. if(item.alwaysShow){
  125. menu.alwaysShow = true;
  126. menu.redirect = menu.path;
  127. }
  128. if (item.children && item.children.length > 0) {
  129. menu.children = [...generateChildRouters( item.children)];
  130. }
  131. //--update-begin----author:scott---date:20190320------for:根据后台菜单配置,判断是否路由菜单字段,动态选择是否生成路由(为了支持参数URL菜单)------
  132. //判断是否生成路由
  133. if(item.route && item.route === '0'){
  134. //console.log(' 不生成路由 item.route: '+item.route);
  135. //console.log(' 不生成路由 item.path: '+item.path);
  136. }else{
  137. routers.push(menu);
  138. }
  139. //--update-end----author:scott---date:20190320------for:根据后台菜单配置,判断是否路由菜单字段,动态选择是否生成路由(为了支持参数URL菜单)------
  140. }
  141. return routers
  142. }
  143. /**
  144. * 深度克隆对象、数组
  145. * @param obj 被克隆的对象
  146. * @return 克隆后的对象
  147. */
  148. export function cloneObject(obj) {
  149. return JSON.parse(JSON.stringify(obj))
  150. }
  151. /**
  152. * 随机生成数字
  153. *
  154. * 示例:生成长度为 12 的随机数:randomNumber(12)
  155. * 示例:生成 3~23 之间的随机数:randomNumber(3, 23)
  156. *
  157. * @param1 最小值 | 长度
  158. * @param2 最大值
  159. * @return int 生成后的数字
  160. */
  161. export function randomNumber() {
  162. // 生成 最小值 到 最大值 区间的随机数
  163. const random = (min, max) => {
  164. return Math.floor(Math.random() * (max - min + 1) + min)
  165. }
  166. if (arguments.length === 1) {
  167. let [length] = arguments
  168. // 生成指定长度的随机数字,首位一定不是 0
  169. let nums = [...Array(length).keys()].map((i) => (i > 0 ? random(0, 9) : random(1, 9)))
  170. return parseInt(nums.join(''))
  171. } else if (arguments.length >= 2) {
  172. let [min, max] = arguments
  173. return random(min, max)
  174. } else {
  175. return Number.NaN
  176. }
  177. }
  178. /**
  179. * 随机生成字符串
  180. * @param length 字符串的长度
  181. * @param chats 可选字符串区间(只会生成传入的字符串中的字符)
  182. * @return string 生成的字符串
  183. */
  184. export function randomString(length, chats) {
  185. if (!length) length = 1
  186. if (!chats) chats = '0123456789qwertyuioplkjhgfdsazxcvbnm'
  187. let str = ''
  188. for (let i = 0; i < length; i++) {
  189. let num = randomNumber(0, chats.length - 1)
  190. str += chats[num]
  191. }
  192. return str
  193. }
  194. /**
  195. * 随机生成uuid
  196. * @return string 生成的uuid
  197. */
  198. export function randomUUID() {
  199. let chats = '0123456789abcdef'
  200. return randomString(32, chats)
  201. }
  202. /**
  203. * 下划线转驼峰
  204. * @param string
  205. * @returns {*}
  206. */
  207. export function underLine2CamelCase(string){
  208. return string.replace( /_([a-z])/g, function( all, letter ) {
  209. return letter.toUpperCase();
  210. });
  211. }
  212. /**
  213. * 判断是否显示办理按钮
  214. * @param bpmStatus
  215. * @returns {*}
  216. */
  217. export function showDealBtn(bpmStatus){
  218. if(bpmStatus!="1"&&bpmStatus!="3"&&bpmStatus!="4"){
  219. return true;
  220. }
  221. return false;
  222. }
  223. /**
  224. * 增强CSS,可以在页面上输出全局css
  225. * @param css 要增强的css
  226. * @param id style标签的id,可以用来清除旧样式
  227. */
  228. export function cssExpand(css, id) {
  229. let style = document.createElement('style')
  230. style.type = "text/css"
  231. style.innerHTML = `@charset "UTF-8"; ${css}`
  232. // 清除旧样式
  233. if (id) {
  234. let $style = document.getElementById(id)
  235. if ($style != null) $style.outerHTML = ''
  236. style.id = id
  237. }
  238. // 应用新样式
  239. document.head.appendChild(style)
  240. }
  241. /** 用于js增强事件,运行JS代码,可以传参 */
  242. // options 所需参数:
  243. // 参数名 类型 说明
  244. // vm VueComponent vue实例
  245. // event Object event对象
  246. // jsCode String 待执行的js代码
  247. // errorMessage String 执行出错后的提示(控制台)
  248. export function jsExpand(options = {}) {
  249. // 绑定到window上的keyName
  250. let windowKeyName = 'J_CLICK_EVENT_OPTIONS'
  251. if (typeof window[windowKeyName] != 'object') {
  252. window[windowKeyName] = {}
  253. }
  254. // 随机生成JS增强的执行id,防止冲突
  255. let id = randomString(16, 'qwertyuioplkjhgfdsazxcvbnm'.toUpperCase())
  256. // 封装按钮点击事件
  257. let code = `
  258. (function (o_${id}) {
  259. try {
  260. (function (globalEvent, vm) {
  261. ${options.jsCode}
  262. })(o_${id}.event, o_${id}.vm)
  263. } catch (e) {
  264. o_${id}.error(e)
  265. }
  266. o_${id}.done()
  267. })(window['${windowKeyName}']['EVENT_${id}'])
  268. `
  269. // 创建script标签
  270. const script = document.createElement('script')
  271. // 将需要传递的参数挂载到window对象上
  272. window[windowKeyName]['EVENT_' + id] = {
  273. vm: options.vm,
  274. event: options.event,
  275. // 当执行完成时,无论如何都会调用的回调事件
  276. done() {
  277. // 执行完后删除新增的 script 标签不会撤销执行结果(已产生的结果不会被撤销)
  278. script.outerHTML = ''
  279. delete window[windowKeyName]['EVENT_' + id]
  280. },
  281. // 当js运行出错的时候调用的事件
  282. error(e) {
  283. console.group(`${options.errorMessage || '用户自定义JS增强代码运行出错'}(${new Date()})`)
  284. console.error(e)
  285. console.groupEnd()
  286. }
  287. }
  288. // 将事件挂载到document中
  289. script.innerHTML = code
  290. document.body.appendChild(script)
  291. }
  292. /**
  293. * 重复值验证工具方法
  294. *
  295. * 使用示例:
  296. * { validator: (rule, value, callback) => validateDuplicateValue('sys_fill_rule', 'rule_code', value, this.model.id, callback) }
  297. *
  298. * @param tableName 被验证的表名
  299. * @param fieldName 被验证的字段名
  300. * @param fieldVal 被验证的值
  301. * @param dataId 数据ID,可空
  302. * @param callback
  303. */
  304. export function validateDuplicateValue(tableName, fieldName, fieldVal, dataId, callback) {
  305. if (fieldVal) {
  306. let params = { tableName, fieldName, fieldVal, dataId }
  307. api.duplicateCheck(params).then(res => {
  308. res['success'] ? callback() : callback(res['message'])
  309. }).catch(err => {
  310. callback(err.message || err)
  311. })
  312. } else {
  313. callback()
  314. }
  315. }
  316. /**
  317. * 根据编码校验规则code,校验传入的值是否合法
  318. *
  319. * 使用示例:
  320. * { validator: (rule, value, callback) => validateCheckRule('common', value, callback) }
  321. *
  322. * @param ruleCode 编码校验规则 code
  323. * @param value 被验证的值
  324. * @param callback
  325. */
  326. export function validateCheckRule(ruleCode, value, callback) {
  327. if (ruleCode && value) {
  328. value = encodeURIComponent(value)
  329. api.checkRuleByCode({ ruleCode, value }).then(res => {
  330. res['success'] ? callback() : callback(res['message'])
  331. }).catch(err => {
  332. callback(err.message || err)
  333. })
  334. } else {
  335. callback()
  336. }
  337. }
  338. /**
  339. * 如果值不存在就 push 进数组,反之不处理
  340. * @param array 要操作的数据
  341. * @param value 要添加的值
  342. * @param key 可空,如果比较的是对象,可能存在地址不一样但值实际上是一样的情况,可以传此字段判断对象中唯一的字段,例如 id。不传则直接比较实际值
  343. * @returns {boolean} 成功 push 返回 true,不处理返回 false
  344. */
  345. export function pushIfNotExist(array, value, key) {
  346. for (let item of array) {
  347. if (key && (item[key] === value[key])) {
  348. return false
  349. } else if (item === value) {
  350. return false
  351. }
  352. }
  353. array.push(value)
  354. return true
  355. }
  356. /**
  357. * 可用于判断是否成功
  358. * @type {symbol}
  359. */
  360. export const succeedSymbol = Symbol()
  361. /**
  362. * 可用于判断是否失败
  363. * @type {symbol}
  364. */
  365. export const failedSymbol = Symbol()
  366. /**
  367. * 使 promise 无论如何都会 resolve,除非传入的参数不是一个Promise对象或返回Promise对象的方法
  368. * 一般用在 Promise.all 中
  369. *
  370. * @param promise 可传Promise对象或返回Promise对象的方法
  371. * @returns {Promise<any>}
  372. */
  373. export function alwaysResolve(promise) {
  374. return new Promise((resolve, reject) => {
  375. let p = promise
  376. if (typeof promise === 'function') {
  377. p = promise()
  378. }
  379. if (p instanceof Promise) {
  380. p.then(data => {
  381. resolve({ type: succeedSymbol, data })
  382. }).catch(error => {
  383. resolve({ type: failedSymbol, error })
  384. })
  385. } else {
  386. reject('alwaysResolve: 传入的参数不是一个Promise对象或返回Promise对象的方法')
  387. }
  388. })
  389. }