【开发技巧之一】

1、数组的重复项的合并

 // prcdTermType 和 acctFnm 重复则合并,反之返回
    // 重复项合并
    mergeDuplicates(arr) {
      debugger;
      const obj = {
        prcdTermType: null,
        acctFnm: null,
        acctNo: null,
      };
      const mergedArray = arr.reduce((result, item) => {
        const existingItem = result.find(
          existing => existing.prcdTermType === item.prcdTermType && existing.acctFnm === item.acctFnm,
        );
        if (existingItem) {
          existingItem.pymtPrice = Number(existingItem.pymtPrice) + Number(item.pymtPrice);
          obj.prcdTermType = existingItem.prcdTermType;
          obj.acctFnm = existingItem.acctFnm;
          obj.acctNo = existingItem.acctNo;
        } else {
          result.push(item);
        }
        return result;
      }, []);
      return {mergedArray, obj};
    },

2、数组计算某个属性之和

    // 计算数组某个属性的总额
    getTableToll(arr, keyName) {
      let total = 0;
      total = arr.reduce((total, currentValue, currentIndex, arr) => {
        return currentValue[keyName] ? Number(total) + Number(currentValue[keyName]) : Number(total);
      }, 0);
      return total;
    },

3、枚举转换

    // 项目小类枚举
     prcdPrjList: [
        {value: '1', label: '意向金'},
        {value: '2', label: '定金'},
        {value: '3', label: '上牌'},
        {value: '4', label: '抵押'},
        {value: '5', label: '全款车款'},
        {value: '6', label: '首付款'},
        {value: '7', label: '前置利息'},
        {value: '8', label: '咨询费'},
        {value: '9', label: 'GPS'},
        {value: '10', label: '精品'},
        {value: '11', label: '粘性产品'},
        {value: '12', label: '小指标'},
        {value: '13', label: '其他项目'},
        {value: '14', label: '上牌押金'},
        {value: '15', label: '置换保证金'},
        {value: '16', label: 'GD应收'},
        {value: '17', label: 'GD收入'},
        {value: '18', label: '高开金额'},
        {value: '19', label: '其他押金'},
      ],
    getJcprcdPrjList(str) {
      if (!str) {
        return;
      }
      const arr = str.split(',');
      const nameArr = [];
      arr.forEach(item => {
        const josn = this.prcdPrjList.find(c => {
          return c.value === item;
        });
        if (josn === undefined) {
          nameArr.push(item);
        } else {
          nameArr.push(josn.label);
        }
      });
      return nameArr.toString();
    },

4、序列化排序,根据某个属性

    // 序列化排序
    sortByPayment(array, property) {
      return array.sort((a, b) => {
        const paymentOptions = ['5', '6'];
        const indexA = paymentOptions.indexOf(a[property]);
        const indexB = paymentOptions.indexOf(b[property]);

        if (indexA !== -1 && indexB === -1) {
          return -1; // a排在b之前
        } else if (indexA === -1 && indexB !== -1) {
          return 1; // a排在b之后
        }
        return 0; // 保持原有顺序
      });
    },

5、计算两个数据间的价格差异

 // 该函数用于计算两个数组中的价格差异。它通过将arr2数组中与arr中的每个元素具有相同prcdPrj属性的元素进行累加,然后将每个元素的prcdPrice属性减去累加结果得到价格差异,并返回一个新数组。
    calculatePriceDifferences(arr, arr2) {
      debugger;
      const result = arr.map(item => {
        debugger;
        const sumInArr2 = arr2
          .filter(i2 => i2.prcdPrj == item.prcdPrj)
          .reduce(
            (total, current) =>
              total + Number(current.pymtPrice) + Number(current.depositAmount) + Number(current.zhDeduction),
            0,
          );
        return {
          prcdPrj: item.prcdPrj,
          id: item.id,
          name: item.name,
          priceDifference: item.prcdPrice - sumInArr2,
        };
      });

      return result;
    },

6、vant 表单校验不通过,跳转到一个校验的地方

export function focusFirstErrorField() {
    const isError = document.getElementsByClassName('van-field--error');
    if (isError.length > 0) {
        const firstErrorField = isError[0].querySelector('.van-field__control');
        if (firstErrorField) {
            firstErrorField.focus();
        }
    }
}

7、下载文件

// 下载文件
export function downloadFile(obj, name, suffix) {
    const url = window.URL.createObjectURL(new Blob([obj]));
    const link = document.createElement('a');
    link.style.display = 'none';
    link.href = url;
    const fileName = parseTime(new Date()) + '-' + name + '.' + suffix;
    link.setAttribute('download', fileName);
    document.body.appendChild(link);
    link.click();
    document.body.removeChild(link);
}

8、判断增加样式class

/**
 * 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;
}



// 使用
// 导入addClass函数(假设在同一文件或已导入)
import { hasClass, addClass } from './utils.js';

// 获取HTML元素
let myElement = document.getElementById('myDiv');

// 定义要添加的CSS类
const newClass = 'myClass';

// 检查元素是否已有该类,如果没有,则添加
if (!hasClass(myElement, newClass)) {
    addClass(myElement, newClass);
}

console.log(myElement.className);  

9、创建32位随机字符串

/**
 * @returns {string}
 */
export function createUniqueString() {
    const timestamp = +new Date() + '';
    const randomNum = parseInt((1 + Math.random()) * 65536) + '';
    return (+(randomNum + timestamp)).toString(32);
}

10、对象数组去重

/**
 * @param {Array} arr
 * @returns {Array}
 */
export function uniqueArr(arr) {
    return Array.from(new Set(arr));
}

11、防抖函数

/**
 * @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;
    };
}

12、切换类名

/**
 * @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;
}

13、输出纯文本

/**
 * @param {string} val
 * @returns {string}
 */
export function html2Text(val) {
    const div = document.createElement('div');
    div.innerHTML = val;
    return div.textContent || div.innerText;
}

// 使用

import { html2Text } from './utils';

let htmlString = '<p>Hello <strong>World!</strong></p>';
let plainText = html2Text(htmlString);

console.log(plainText); // 输出: "Hello World!"

14、传换链接的参数

/**
 * @param {string} url
 * @returns {Object}
 */
export function param2Obj(url) {
    const search = url.split('?')[1];
    if (!search) {
        return {};
    }
    return JSON.parse('{"' + decodeURIComponent(search).replace(/"/g, '\\"').replace(/&/g, '","').replace(/=/g, '":"').replace(/\+/g, ' ') + '"}');
}

// 使用

import { param2Obj } from './utils';

let url = 'http://example.com/?name=John&age=30';
console.log(param2Obj(url)); 

// 输出: {"name": "John", "age": "30"}

15、将json数据转换成url链接

/**
 * @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('&');
}

// 使用
import { param } from './utils.js';

let json = {
    name: 'John Doe',
    age: 30,
    city: undefined,
    job: 'Developer'
};

let urlParams = param(json);
console.log(urlParams); // 输出:name=John%20Doe&age=30&job=Developer

16、从给定的URL或当前页面URL中获取查询参数

/**
 * @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;
}

// 使用
import { getQueryObject } from './utils.js'; // 假设此函数在一个名为utils.js的模块中

// 示例URL
let url = 'http://example.com/?name=John&age=30';

// 调用函数获取查询参数对象
let queryObj = getQueryObject(url);

console.log(queryObj); 
// 输出: { name: 'John', age: '30' }

17、计算两个日期的间隔

/** 计算来个日期的间隔
 * **/
// eslint-disable-next-line camelcase
export function t_parseTime_between(startTime, endTime) {
    if (!startTime || !endTime) {
        return 0;
    }
    var betweenTIime = endTime - startTime;
    return (betweenTIime / 1000 / 24 / 3600).toFixed();
}

18、时间格式转时间戳

/**
 *  时间格式转时间戳
 * **/
export function dataAlltime(data) {
    if (data) {
        let datatiem = '';
        if (data.length === 19) {
            datatiem = data.replace(/-/g, '/');
            return new Date(datatiem).getTime();
        } else {
            datatiem = (data + ':00').replace(/-/g, '/');
            return new Date(datatiem).getTime();
        }
    } else {
        return null;
    }
}

19、组件表单检验工具函数

// 组件表单检验工具函数
export function formValidate(ref, callback) {
  ref.validate(valid => {
    callback(valid);
  });
}

// 使用案例
<template>
  <el-form ref="myForm" :model="form" :rules="rules">
    <!-- 表单元素 -->
    <el-form-item label="用户名" prop="username">
      <el-input v-model="form.username"></el-input>
    </el-form-item>
    <!-- 其他表单元素... -->
    
    <el-button ="handleSubmit">提交</el-button>
  </el-form>
</template>

<script>
import { formValidate } from './validationUtils';

export default {
  data() {
    return {
      form: {
        username: '',
        // ...其他表单字段
      },
      rules: {
        username: [
          { required: true, message: '用户名不能为空', trigger: 'blur' },
          // ...其他校验规则
        ],
      },
    };
  },
  methods: {
    handleSubmit() {
      formValidate(this.$refs.myForm, (valid) => {
        if (valid) {
          // 提交表单数据到服务器或执行其他操作
          console.log('表单验证通过,可以提交:', this.form);
        } else {
          this.$message.error('表单验证未通过,请检查输入');
        }
      });
    },
  },
};
</script>

20、数字/货币金额 (只支持正数、不支持校验千分位分隔符)

// 数字/货币金额 (只支持正数、不支持校验千分位分隔符)
export function monetaryAmount(rule, value, callback) {
  const reg = /(?:^[1-9]([0-9]+)?(?:\.[0-9]{1,2})?$)|(?:^(?:0)$)|(?:^[0-9]\.[0-9](?:[0-9])?$)/;
  if (value === '' || value === undefined || value === null) {
    callback();
  } else {
    if (!reg.test(value)) {
      callback(new Error('请输入数字'));
    } else {
      callback();
    }
  }
}

21、 正数(大于等于零的数字包括小数)

// 正数(大于等于零的数字包括小数)
export function positive_number(rule, value, callback) {
  const reg = /^[+][1-9](\d+)$|^[+]{0,1}(\d+\.\d+)$/;
  if (value === '' || value === undefined || value === null) {
    callback();
  } else {
    if (!reg.test(value)) {
      callback(new Error('请输入正确的数字'));
    } else {
      callback();
    }
  }
}

22、 手机和固化校验

// 手机和固化校验
export function validateTLEPhone(rule, value, callback) {
  const mobileReg = /^(([1][3,4,5,7,8]\d{9})|([0]\d{10,11})|(\d{7,8})|(\d{4}|\d{3})-(\d{7,8}))$/;

  const phoneReg = /^\d{3}-\d{8}|\d{4}-\d{7}$/;

  if (!value || value === '') {
    callback(new Error('请输入联系方式'));
  } else if (value.length === 11) {
    console.log("value.indexOf('-')", value.indexOf('-') !== -1);
    if (value.indexOf('-') !== -1) {
      callback();
    } else {
      if (!mobileReg.test(value)) {
        callback(new Error('请输入正确的手机号码或者固话号码(固话格式:区号-号码)'));
      } else {
        callback();
      }
    }
  } else if (value.length === 12) {
    if (!phoneReg.test(value)) {
      callback(new Error('请输入正确的手机号码或者固话号码(固话格式:区号-号码)'));
    } else {
      callback();
    }
  } else {
    callback(new Error('请输入正确的手机号码或者固话号码(固话格式:区号-号码)'));
  }
}

23、 含有数字字母且必须有大写字母

// 含有数字字母且必须有大写字母
export function accountNumberTwo(rule, value, callback) {
  const reg = /^(?=.*[A-Z])(?=.*\d)[a-zA-Z\d]+$/;
  if (value === '' || value === undefined || value === null) {
    callback();
  } else {
    if (!reg.test(value)) {
      callback(new Error('请输入含有数字字母且必须有大写字母'));
    } else {
      callback();
    }
  }
}

24、并发请求

    async getStorefrontAccounts() {
      debugger;
      const promises = [
        crudCwOrgAcct.lists({ cpAcctId: this.piaoForm.form.cpAcctId }),
        crudCwOrgAcct.lists({ szAcctId: this.piaoForm.form.szAcctId })
      ];

      try {
        const [cpAcctRes, szAcctRes] = await Promise.all(promises);
        console.log('保证金账户 (CP Acct)', cpAcctRes);
        console.log('保证金账户 (SZ Acct)', szAcctRes);

        // 如果需要进一步处理结果,可以在这里操作 res.content
        // if (cpAcctRes && cpAcctRes.content) { ... }
        // if (szAcctRes && szAcctRes.content) { ... }

      } catch (error) {
        console.error('获取保证金账户信息时发生错误', error);
      }
    },

25、el-cascader 初始默认值

             <el-cascader
                  v-model="query.vehBrndlsit"
                  placeholder="车辆品牌"
                  :options="getBrandlist"
                  filterable
                  :props="defaultParamsSearch"
                  clearable
                />


         getBrandlist: [],
            defaultParamsSearch: {
                label: 'name',
                value: 'name',
                children: 'children',
                expandTrigger: 'hover',
                checkStrictly: true
            },

         
        getFirstOptionPath(options, children = 'children', name = 'name') {
            // 递归函数,用于获取第一个选项的值路径
            if (options && options.length > 0) {
                const firstOption = options[0];
                if (children in firstOption && firstOption[children].length > 0) {
                    // 如果有子选项,则继续递归
                    return [firstOption[name], ...this.getFirstOptionPath(firstOption[children])];
                } else {
                    // 如果是叶子节点,直接返回其值
                    return [firstOption[name]];
                }
            }
            return [];
        }

 使用
 this.query.vehBrndlsit = this.getFirstOptionPath(this.getBrandlist);

26、数组中检查某个属性,是否相同

        checkUniformProperty(array, propertyName,) {
            if (array.length === 0) return true; // 空数组视为所有元素相同

            const firstValue = array[0][propertyName];
            return array.every(item => item[propertyName] === firstValue);
        },

27、国标vin加权系数校验规则

validateVIN(vin) {
    // 正则表达式验证
    const vinRegex = /^[A-HJ-NPR-Z0-9]{17}$/;
    if (!vinRegex.test(vin)) {
        return false;
    }

    // 校验位计算
    const vinMapWeighting = [8, 7, 6, 5, 4, 3, 2, 10, 0, 9, 8, 7, 6, 5, 4, 3, 2];
    const vinMapValue = {
        0: 0, 1: 1, 2: 2, 3: 3, 4: 4, 5: 5, 6: 6, 7: 7, 8: 8, 9: 9,
        A: 1, B: 2, C: 3, D: 4, E: 5, F: 6, G: 7, H: 8,
        J: 1, K: 2, L: 3, M: 4, N: 5, P: 7, R: 9,
        S: 2, T: 3, U: 4, V: 5, W: 6, X: 7, Y: 8, Z: 9
    };

    let amount = 0;
    for (let i = 0; i < 17; i++) {
        const char = vin[i].toUpperCase();
        const value = vinMapValue[char];
        const weight = vinMapWeighting[i];
        amount += value * weight;
    }

    const remainder = amount % 11;
    const checkDigit = remainder === 10 ? 'X' : remainder.toString();
    return vin[8].toUpperCase() === checkDigit;
}

28、防抖函数

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);
                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(this, args);
        }
        return result;
    };
}

应用

import { debounce } from '@/utils/index.js'; // 确保正确引入 debounce 函数

export default {
    data() {
        return {
            outWhList: []
        };
    },
    methods: {
       通过箭头函数方式
        outWarehouseDebounced: debounce((orgId) => {
            this.outWhList = [];
            const params = {
                orgId: orgId,
                level: 1,
                isValid: true,
                storeMode: 2
            };
            crudJpAllocateDetail
                .getAll(params)
                .then(res => {
                    this.outWhList = res;
                });
        }, 300, false) // 300 毫秒内只调用一次
    }
};

29、 获取当天年月日

-当天年月日

getNowTime() {
    const today = new Date();
    const year = today.getFullYear();
    const month = String(today.getMonth() + 1).padStart(2, '0');
    const day = String(today.getDate()).padStart(2, '0');
    const thisDayDate = `${year}-${month}-${day}`;
    return thisDayDate;
},

-获取时分,转换成分钟

timeToMinutes(timeStr) {
   const [hours, minutes] = timeStr.split(':').map(Number);
   return hours * 60 + minutes;
},

30、picker 禁用时间

    computed: {
        pickerOptions() {
            return {
                disabledDate: (time) => {
                    return time.getTime() < Date.now() - 8.64e7; // 禁用以前的日期,今天不禁用
                    // return date.getTime() <= Date.now();    //禁用今天以及以前的日期
                }

            };
        }
    },
  • 时间范围在当天到 30后的范围可选
              disabledDate: time => {
                const endDateTime = new Date(new Date().getFullYear(), new Date().getMonth(), new Date().getDate() + Number(30), 8);
                const dd = new Date().getTime();
                return (
                  time.getTime() < dd || time.getTime() > new Date(endDateTime).getTime()
                );
              }

31、el-tabel 禁选

  • 勾选的方法
      <el-table-column
        align="center"
        fixed="left"
        type="selection"
        :selectable="checkSelectable"
        :reserve-selection="true"
        width="40"
      />
        checkSelectable(el) {
           //false 表示禁选
            return el.Selectable == false;
        },
  • 数组处理的方法
      arr.forEach((item) => {
        const currentQty = item.orderQty - item.executionsQty;
        item.Selectable = currentQty === 0 ? false : true;
      });

32、get params 序列化传参

  • 对象序列化
let obj = {
methods: 'get'
id: 1,
name: 'yjn'
}
qs.stringify(obj)
methods=get&id=1&name=yjn  
  • 数组序列化
  1. 数组形式
let arr = [2,3]

qs.stringify({a:arr})

// 'arr[0]=2&arr[1]=3'
  1. 处理默认带下标格式
// 常用并推荐使用
let arr = [2,3]
qs.stringify({a:arr},{indices:false});
// 'arr=2&arr=3'
  • 示例
export function group(params) {
  if (params.page == undefined) {
    params.page = 0;
    params.size = 9999;
    params.sort = "id,desc";
  }
  return request({
    url: "/api/yw/ywBxConfig/group?" + qs.stringify(params, { indices: false }),
    method: "get"
  });
}

33、el-table 合计

  • 表格
    在这里插入图片描述
  • 正常写法
        getSummaries({columns}) {
            const jsArr = [
                'amt',
                'costAmt',
                'qty',
                'recAmt'

            ];
            return [
                columns.map((column, index) => {
                    if (index === 0) {
                        return '合计';
                    }
                    let type = null;
                    if (column.property.indexOf('.') === -1) {
                        type = column.property;
                    } else {
                        type = column.property.split('.')[1];
                    }
                    if (jsArr.indexOf(type) !== -1) {
                        return this.crud.rows[`sum${this.capitalizeFirstLetter(type)}`];
                    }
                })
            ];
        },
  • crud 的写法
        tableBottomTotal({columns}) {
            if (crud.columnShowArr.length === 0 && crud.sumBackend.length === 0) {
                return false;
            }
            const jsArr = [...crud.columnShowArr];
            const sumsArr = [...crud.sumBackend];
            const getExistingValues = (row, keys) => {
                const values = {};
                if (!row) return values;
                // 创建一个键映射对象,将 jsArr 的键映射到 keys 的键
                // crud.columnShowArr 和 crud.sumBackend  字段顺序需要一一对应(切记)
                const keyMap = {};
                jsArr.forEach((j, index) => {
                    keyMap[keys[index]] = j;
                });
                keys.forEach(key => {
                    // 增加判断:只有当 key 在 sumBackend 中存在且 key 在 row 中存在时,才存入 values
                    if (sumsArr.includes(key) && key in row) {
                        // 使用映射关系获取对应的 jsArr 键
                        const mappedKey = keyMap[key];
                        if (mappedKey !== undefined) {
                            values[mappedKey] = row[key];
                        }
                    }
                });
                return values;
            };
            const arr = columns.map((column, index) => {
                if (index === 0) return '合计';
                const type = column.property.includes('.')
                    ? column.property.split('.')[1]
                    : column.property;
                // 判断 crud.rows 是否有值,防止首次进入, 接口未走完,crud.rows 为「」
                if (typeof crud.rows === 'object' && crud.rows !== null && Object.keys(crud.rows).length > 0) {
                    if (jsArr.includes(type) && crud.rows && crud.rows.content.length > 0) {
                        // 提取对应数据行的值
                        const valueObj = getExistingValues(crud.rows, sumsArr);
                        if (valueObj !== null) {
                            const objString = valueObj[type] !== undefined ? valueObj[type] : '';
                            return objString;
                        }
                    }
                }
                return '';
            });
            return [arr];
        },

34、el-form 样式问题

  • :inline=“false” 宽度自适应
    在这里插入图片描述
  • :inline=“true” 宽度不会自适应
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值