/* * @Author: Pengjiantian * @Date: 2020-02-27 16:45:10 * @Last Modified by: Pengjiantian * @Last Modified time: 2020-02-28 17:44:50 */ import dayjs from 'dayjs' import CommFetch from '@/utils/core/commFetch' /** * ApiModel 接口映射模型 */ export default class ApiModel { /** * constructor 初始化 * @param {Object} options 配置项 @example * { * api: '接口地址', // required * formList: [ // 表单映射信息(通常用来渲染表单) * { * type: 'input',label: '客户名称:',value: '',name: 'customerName' * } * ], * responseMap: [ // 接口响应映射信息(通常用来表格或类似表单展示的数据) * { * label: '车位首付(元)',field: 'downpayparkingamount',isMoney: true,isDesc: true * } * ], * computedResponse: item => { * return {...item} * }, * computedItem: item => { * return {...item} * }, * */ constructor(options = {}) { const { baseConf, fetchConf = {}, ...other } = options // 默认日期格式 this.dateFormate = 'YYYY/MM/DD' this.ruleAction = (rule, message) => { if (typeof rule === 'string') { if (rule === 'required') { return (rule, value, callback) => { value = this.getItemValue(value) if (value.toString().trim() === '') { callback(new Error(message || '该字段必填')) } else { callback() } callback() } } if (rule === 'phone') { return (rule, value, callback) => { value = this.getItemValue(value) if (!/1\d{10}/.test(value)) { callback(new Error('手机号格式有误')) } else { callback() } } } if (rule === 'number') { return (rule, value, callback) => { value = this.getItemValue(value) if (isNaN(value)) { callback(new Error('必须输入数字')) } else { callback() } } } } if (typeof rule === 'object') { let { required, pattern, maxLength, minLength } = rule if (required) { return (rule, value, callback) => { // console.log(value) value = this.getItemValue(value) if (value === '') { callback(new Error('该字段必填')) } else { callback() } } } if (maxLength) { return (rule, value, callback) => { value = this.getItemValue(value) if (value.length > maxLength) { callback(new Error(`最多输入${maxLength}个字符`)) } else { callback() } } } if (minLength) { return (rule, value, callback) => { value = this.getItemValue(value) if (value.length < minLength) { callback(new Error(`最少输入${minLength}个字符`)) } else { callback() } } } if (pattern) { if (pattern === 'string') { pattern = new RegExp(pattern) } return (rule, value, callback) => { value = this.getItemValue(value) if (!pattern.test(value)) { callback(new Error('输入格式有误')) } else { callback() } } } } return false } this.commFetch = new CommFetch(baseConf, fetchConf) this.setOptions(other) } getItemValue(value) { if (Array.isArray(value)) { return value.join('') } // return (value || '').trim() // 修复value为number时会报错 return (value.toString() || '').trim() } /** * 获取表单信息 * @param {Object} initValues 初始值对象 */ getFormList(initValues = {}, list) { const { formList } = this if (typeof list === 'undefined') { list = [...formList] } const keys = Object.keys(initValues) if (keys.length > 0) { return list.reduce((pre, curr) => { let { value, name, descName, descValue, children } = curr if (typeof value === 'undefined' && Array.isArray(children)) { // has children pre.push({ ...curr, children: this.getFormList(initValues, children) }) } else { let result = { ...curr } result.value = typeof initValues[name] === 'undefined' ? value : initValues[name] if (typeof descValue === 'undefined' && descName) { const dValue = initValues[descName] result.descValue = typeof dValue === 'undefined' ? '' : dValue } pre.push(result) } return pre }, []) } return [...list] } // 获取表单数据值 getFormValues(list) { const { formList } = this if (typeof list === 'undefined') { list = [...formList] } return list.reduce((pre, curr) => { const { name, names, value, children } = curr // 父级不包含value,则取子级 if (typeof value === 'undefined' && Array.isArray(children)) { children.forEach(subItem => { const { name: subName, value: subValue } = subItem pre[subName] = this.formatInput(subValue, subName, list) }) } else if (Array.isArray(names) && Array.isArray(value)) { // 将数组值传送到names字段对应的key中 names.forEach((subName, index) => { pre[subName] = this.formatInput(value[index] || '', subName, list) }) pre[name] = this.formatInput(value, name, list) } else { pre[name] = this.formatInput(value, name, list) } return pre }, {}) } // 获取表单验证规则 getFormRules(list) { const { formList } = this if (typeof list === 'undefined') { list = [...formList] } return list.reduce((pre, curr) => { const { rules = [], name, children, attrs = [] } = curr if (Array.isArray(children)) { pre = { ...pre, ...this.getFormRules(children) } } else { const ruleArray = rules.reduce((rulePre, ruleCurr) => { if (this.getRule(ruleCurr)) { rulePre.push(this.getRule(ruleCurr)) } return rulePre }, []) if (ruleArray.length > 0) { const requiredRule = ruleArray.find(({ required }) => required) if ( requiredRule && !ruleArray.some(({ trigger }) => trigger === 'change') && !attrs.some(attr => attr === 'multiple') ) { // change 多选初始会显示错误信息,临时不加change ruleArray.push({ ...requiredRule, trigger: 'change' }) } pre[name] = ruleArray } } return pre }, {}) } getRule(rule) { if (typeof rule === 'string') { // rule: required phone number const temp = rule === 'required' ? { required: true } : {} return { validator: this.ruleAction(rule), ...temp, trigger: 'blur' } } if (typeof rule === 'object') { const { validator, trigger = 'blur', message } = rule if (typeof validator === 'function') { return { trigger, ...rule } } else { return { trigger, ...rule, validator: this.ruleAction(rule, message) } } } return false } // 统一输出数据格式,如日期格式化 formatInput(val, name, list) { const { dateFormate } = this if (typeof this.computedValue === 'function') { val = this.computedValue(val, name, list) } if (Array.isArray(val) && val.length > 0) { return val.reduce((pre, curr) => { pre.push(this.formatInput(curr, name, list)) return pre }, []) } if (val instanceof Date) { val = dayjs(val).format(dateFormate) } return val } /** * 获取表格信息 */ getTableList() { const { tableList } = this return [...tableList] } /** * post 请求处理 * @param {String} api 接口地址 * @param {Object|String} body 请求参数 */ post(body = {}, conf = {}) { return this.toRequest(body, { method: 'post', ...conf }) } /** * post 请求处理 * @param {String} api 接口地址 * @param {Object|String} body 请求参数 */ upload(body = {}, conf = { headers: false }) { const formData = this.getFormData(body) return this.toRequest(formData, { method: 'post', ...conf }) } /** * post 请求处理 * @param {String} api 接口地址 * @param {Object|String} body 请求参数 */ submit(body = {}, conf = {}) { const { api } = this const tempForm = document.createElement('form') tempForm.method = 'post' tempForm.target = '_blank' tempForm.action = this.commFetch.mixApi(api) document.body.appendChild(tempForm) Object.keys(body).forEach(key => { const tempInput = document.createElement('input') tempInput.type = 'hidden' tempInput.name = key tempInput.value = body[key] tempForm.appendChild(tempInput) }) tempForm.submit() document.body.removeChild(tempForm) } getFormData(body) { let formData = null if (typeof body === 'object' && !(body instanceof FormData)) { formData = new FormData() Object.keys(body).forEach(key => { formData.append(key, body[key]) }) } return formData === null ? body : formData } /** * get 请求处理 * @param {String} api 接口地址 * @param {Object|String} body 请求参数 */ get(body = {}, conf = {}) { return this.toRequest(body, { method: 'get', ...conf }) } // 遍历options内容到实例 setOptions(options) { Object.keys(options).forEach(key => { this[key] = options[key] }) } // 请求统一处理 toRequest(body = {}, conf = {}) { const { api } = this return new Promise((resolve, reject) => { this.commFetch .fetch(api, body, conf) .then(res => { resolve(this.formateResponse(res)) }) .catch(reson => { reject(reson) }) }) } // 输出数据统一处理(这里为将列表项转换为list字段值) formateResponse(res) { let { result = {}, code, ext, msg, ...other } = res // let list = {} if (Array.isArray(result)) { result = { list: this.computedList(result) } } else { const { records, ...other } = result if (Array.isArray(records)) { result = { list: this.computedList(records), ...other } } } const temp = { ...other, ...result } if (typeof this.computedResponse === 'function') { // 响应数据的进一步处理 return this.computedResponse(temp) } return temp } // 列表数据处理 computedList(list = []) { const { computedItem } = this if (typeof computedItem === 'function') { return list.reduce((pre, curr) => { pre.push(this.computedItem(curr)) return pre }, []) } return [...list] } }