iview-admin框架搭建

## iview-admin框架[下载地址](https://github.com/Inspiration1/asteroid) ## api #### 新建项目接口文件: ```js import axios from '@/libs/api.request' /** * chenwan * 新增 * 2019-07-19 * @param {*} parameter */ const InsertData = (parameter) => { return axios.request({ url: '/api/services/app/ArchvieMilitary/Create', data: parameter, method: 'post' }); } const APIS = { InsertData, } export default APIS; ``` #### 新建index.js ```js import Military from "./military"; const APIS = { Military, } export default APIS ``` #### main.js中加入vue属性 ```js import Apis from "./api" Vue.prototype.$api = Apis; ``` #### 调用时: ```js this.$api.Military.InsertData ``` ## 通用方法 #### libs下面新建tools-new.js ```js /** * 创建唯一标识 */ const newGuid = () => { const S4 = () => (((1 + Math.random()) * 0x10000) | 0).toString(16).substring(1); return `${S4()}${S4()}-${S4()}-${S4()}-${S4()}-${S4()}${S4()}${S4()}`; } /** * 数组去重 * @param {Array} arry */ const uniq = (arry) => { return [...new Set(arry)]; } /** * 求数组交集 * @param {Array} a * @param {Array} b */ const intersection = (a, b) => { return [...new Set(a.filter(v => new Set(b).has(v)))]; } /** * 求数组并集 * @param {Array} a * @param {Array} b */ const union = (a, b) => { return [...new Set(a.concat(b))]; } /** * 求数组差集 * @param {Array} a * @param {Array} b */ const difference = (a, b) => { return a.concat(b).filter(v => !a.includes(v) || !b.includes(v)); } /** * 将数组转换为树形数组 * @param {Array} data 原数组 * @param {String} searchKey 记录父节点标识的键名 */ const toTree = (data, searchKey = "parentId") => { if (!Array.isArray(data)) return []; let result = [] data.forEach(item => { delete item.children; }); let hash = new Map(); data.forEach(item => { hash.set(item.id, item); }); data.forEach(item => { if (hash.has(item[searchKey])) { let parent = hash.get(item[searchKey]); (parent.children || (parent.children = [])).push(item); } else { result.push(item); } }); return result; } /** * 递归查询 * @param {*} obj 查询对象 * @param {*} predicate 搜索条件 */ const recursiveSearch = (obj, predicate) => { if (!(predicate instanceof Function)) { throw new TypeError("递归查询的搜索条件必须是一个函数!用于检查是否满足条件的函数"); } for (let item in obj) { let element = obj[item]; if (predicate(element)) { return element; } else if (element instanceof Object) { return recursiveSearch(element, predicate); } } return undefined; } /** * 递归查询(异步) * @param {*} obj 查询对象 * @param {*} predicate 搜索条件 */ const recursiveSearchAsync = async (obj, predicate) => { if (!(predicate instanceof Function)) { throw new TypeError("递归查询的搜索条件必须是一个函数!用于检查是否满足条件的函数"); } for (let item in obj) { let element = obj[item]; if (predicate(element)) { return element; } else if (element instanceof Object) { return await recursiveSearchAsync(element, predicate); } } return undefined; } /** * 将Date对象转换为yyyy-MM-dd HH:mm:ss格式 * @param {Date} date */ const dateFormat = (date = new Date(), withoutTime = true) => { const innerFormat = (date) => { const month = (date.getMonth() + 1).toString().padStart(2, '0'); const strDate = date.getDate().toString().padStart(2, '0'); if (withoutTime) { return `${date.getFullYear()}-${month}-${strDate}`; } else { return `${date.getFullYear()}-${month}-${strDate} ${date.getHours()}:${date.getMinutes()}:${date.getSeconds()}`; } } if (date instanceof Date) { return innerFormat(date); } else if (typeof date === "string") { let innerDate = new Date(date); return innerFormat(innerDate); } } /** * 深拷贝 * @param {*} obj 要拷贝的对象 */ const deepClone = (obj, hash = new WeakMap()) => { //递归拷贝 if (obj instanceof RegExp) return new RegExp(obj); if (obj instanceof Date) return new Date(obj); if (obj === null || typeof obj !== 'object') { //如果不是复杂数据类型,直接返回 return obj; } if (hash.has(obj)) { return hash.get(obj); } /** * 如果obj是数组,那么 obj.constructor 是 [Function: Array] * 如果obj是对象,那么 obj.constructor 是 [Function: Object] */ let t = new obj.constructor(); hash.set(obj, t); for (let key in obj) { //如果 obj[key] 是复杂数据类型,递归 if (obj.hasOwnProperty(key)) {//是否是自身的属性 if (obj[key] && typeof obj[key] === 'object') { t[key] = deepClone(obj[key], hash); } else { t[key] = obj[key]; } } } return t; } /** * 防抖函数 * @param {Function} func * @param {Number} wait * @param {Boolean} immediate */ const debounce = (func, wait, immediate = true) => { let timer; // 延迟执行函数 const later = (context, args) => setTimeout(() => { timer = null;// 倒计时结束 if (!immediate) { func.apply(context, args); //执行回调 context = args = null; } }, wait); let debounced = function (...params) { let context = this; let args = params; if (!timer) { timer = later(context, args); if (immediate) { //立即执行 func.apply(context, args); } } else { clearTimeout(timer); //函数在每个等待时延的结束被调用 timer = later(context, args); } } debounced.cancel = function () { clearTimeout(timer); timer = null; }; return debounced; }; /** * 节流函数 * @param {Function} func * @param {Number} wait * @param {Object} options */ const throttle = (func, wait, options) => { let timeout, context, args, result; let previous = 0; if (!options) options = {}; const later = () => { previous = options.leading === false ? 0 : Date.now() || new Date().getTime(); timeout = null; result = func.apply(context, args); if (!timeout) context = args = null; }; let throttled = function () { let now = Date.now() || new Date().getTime(); if (!previous && options.leading === false) previous = now; let remaining = wait - (now - previous); context = this; args = arguments; if (remaining <= 0 || remaining > wait) { if (timeout) { clearTimeout(timeout); timeout = null; } previous = now; result = func.apply(context, args); if (!timeout) context = args = null; } else if (!timeout && options.trailing !== false) { // 判断是否设置了定时器和 trailing timeout = setTimeout(later, remaining); } return result; }; throttled.cancel = function () { clearTimeout(timeout); previous = 0; timeout = context = args = null; }; return throttled; } const regExpMap = new Map ([ ['手机号', /^1((3[\d])|(4[5,6,7,9])|(5[0-3,5-9])|(6[5-7])|(7[0-8])|(8[\d])|(9[1,8,9]))\d{8}$/],//根据工信部2019年最新公布的手机号段 ['座机电话', /\d{3}-\d{8}|\d{4}-\d{7}/],//如: 0341-86091234 ['身份证', /(^\d{8}(0\d|11|12)([0-2]\d|30|31)\d{3}$)|(^\d{6}(18|19|20)\d{2}(0\d|11|12)([0-2]\d|30|31)\d{3}(\d|X|x)$)/], ['帐号', /^[a-zA-Z][a-zA-Z0-9_]{4,15}$/],//字母开头,允许5-16字节,允许字母数字下划线组合 ['纯中文', /^[\u4E00-\u9FA5]+$/], ['小数', /^\d+\.\d+$/], ['数字', /^\d{1,}$/], ['QQ号', /^[1-9][0-9]{4,10}$/], ['微信号', /^[a-zA-Z][-_a-zA-Z0-9]{5,19}$/], ['纯英文', /^[a-zA-Z]+$/], ['密码强度', /^.*(?=.{6,})(?=.*\d)(?=.*[A-Z])(?=.*[a-z])(?=.*[!@#$%^&*? ]).*$/],//最少6位,包括至少1个大写字母,1个小写字母,1个数字,1个特殊字符 ['URL', /^((https?|ftp|file):\/\/)?([\da-z.-]+)\.([a-z.]{2,6})(\/\w\.-]*)*\/?/], ['IPv4地址', /^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/], ['16进制颜色', /^#?([a-fA-F0-9]{6}|[a-fA-F0-9]{3})$/], ['邮政编码', /^(0[1-7]|1[0-356]|2[0-7]|3[0-6]|4[0-7]|5[1-7]|6[1-7]|7[0-5]|8[013-6])\d{4}$/], ['Email', /^\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$/], ]); /** * 验证生成器 * @param {String} key * @param {String} message */ const validateProvider = (key, message = "") => { let regExp = regExpMap.get(key); if (!regExp) throw new Error("没有找到对应的正则规则"); const validator = (rule, value, callback) => { if (regExp.test(value)) { callback(); } else { callback(new Error(!message ? `请输入正确的${key}!` : message)); } } return { validator }; } const HEPLER = { newGuid, uniq, intersection, union, difference, toTree, recursiveSearch, recursiveSearchAsync, dateFormat, deepClone, debounce, throttle, validateProvider } export default HEPLER; ``` #### main.js中加入vue属性 ```js import Helper from "@/libs/tools-new.js" Vue.prototype.$helper = Helper; ``` #### 调用时: `this.$helper.deepClone();` ## config下的index.js,修改url地址及项目名称 ``` js title: 'iView-admin', baseUrl: { dev: 'https://www.easy-mock.com/mock/5add9213ce4d0e69998a6f51/iview-admin/', pro: 'https://produce.com' }, ``` ## 路由配置 router下面的routers.js locale=>lang=>zh-CN.js等设置中文/繁體 ## 登录之后页面结构布局 src=>components=>main