一:对比2个数组不同
1.JSON.Stringfy(a)===JSON.Stringfy(b)
2. this._.isEqualWith(this.fileList, this.initFileList, (a, b) => {
return a.fileInfoId === b.fileInfoId
}) 判断2个数组某一个单一对应的值进行比对
二:vue获取接口里面获取对应的属性赋值给data
const arrList = [‘portfolioAccountList’, ‘custodianAccountInfo’, ‘files’, ‘applyFiles’, ‘sealFiles’, ‘activeAccountList’]
for (const item of arr) {
if (!arrList.includes(item)) {
this.$set(this.detailInfo, item, res[item])
}
三:对比2个对象不同
lodash
isEqual(a,b)
四:获取后端数据,得到自己想要的字段。
1.第一种
const arr = [‘formTypeName’, ‘uploadDateTime’, ‘fileName’, ‘fileId’, ‘uploadUserName’, ‘priceDay’, ‘uploadTypeName’, ‘directives’, ‘id’, ‘memo’, ‘accountName’, ‘planType’, ‘planTypeName’]
for (const i of arr) {
this.detailsInfo[i] = res[i] }
2:第二种 解构赋值
const { formTypeName, uploadDateTime, fileName, fileId, uploadUserName, priceDay, uploadTypeName, directives, id, memo, accountName, planType, planTypeName } = res
this.detailsInfo = {
formTypeName,
uploadDateTime,
fileName,
fileId,
id,
uploadUserName,
priceDay,
uploadTypeName,
accountName,
planType,
planTypeName,
memo: memos
}
五:后端返回数据字符串,前端进行分割处理。
memos = memo.split(‘\r\n’).map(item => {
return ·\xa0${item}
})
六:常用的正则。
1: rules: [{ pattern: /^1[3-9][0-9]{9}KaTeX parse error: Expected 'EOF', got '}' at position 28: …'请输入正确的"移动电话"' }̲], 2: r…/, message: ‘请输入正确的"邮政编码"’ }]
5: (/^(-)(\d+).(\d{2}).$/, ‘$1$2.$3’),保留2位小数,只能输入一个小数点。
// 常用的正则规则
// eslint-disable-next-line
export const regExpConfig = {
IDcard: /^[1-9]\d{7}((0\d)|(1[0-2]))(([0|1|2]\d)|3[0-1])\d{3}$|^[1-9]\d{5}[1-9]\d{3}((0\d)|(1[0-2]))(([0|1|2]\d)|3[0-1])\d{3}([0-9]|X)$/, // 身份证
mobile: /^1([3|4|5|7|8|])\d{9}$/, // 手机号码
telephone: /^(\(\d{3,4}\)|\d{3,4}-|\s)?\d{7,14}$/, // 固定电话
num: /^[0-9]*$/, // 数字
phoneNo: /(^1([3|4|5|7|8|])\d{9}$)|(^(\(\d{3,4}\)|\d{3,4}-|\s)?\d{7,14}$)/, // 电话或者手机
policeNo: /^[0-9A-Za-z]{4,10}$/, // 账号4-10位数字或字母组成
pwd: /^[0-9A-Za-z]{6,16}$/, // 密码由6-16位数字或者字母组成
isNumAlpha: /^[0-9A-Za-z]*$/, // 字母或数字
isAlpha: /^[a-zA-Z]*$/, // 是否字母
isNumAlphaCn: /^[0-9a-zA-Z\u4E00-\uFA29]*$/, // 是否数字或字母或汉字
isPostCode: /^[\d\-]*$/i, // 是否邮编
isNumAlphaUline: /^[0-9a-zA-Z_]*$/, // 是否数字、字母或下划线
isNumAndThanZero: /^([1-9]\d*(\.\d+)?|0)$/, // 是否为整数且大于0/^[1-9]\d*(\.\d+)?$/
isNormalEncode: /^(\w||[\u4e00-\u9fa5]){0,}$/, // 是否为非特殊字符(包括数字字母下划线中文)
isTableName: /^[a-zA-Z][A-Za-z0-9\#\$\_\-]{0,29}$/, // 表名
isInt: /^-?\d+$/, // 整数
isTableOtherName: /^[\u4e00-\u9fa5]{0,20}$/, // 别名
// isText_30: /^(\W|\w{1,2}){0,15}$/, // 正则
// isText_20: /^(\W|\w{1,2}){0,10}$/, // 正则
isText_30: /^(\W|\w{1}){0,30}$/, // 匹配30个字符,字符可以使字母、数字、下划线、非字母,一个汉字算1个字符
isText_50: /^(\W|\w{1}){0,50}$/, // 匹配50个字符,字符可以使字母、数字、下划线、非字母,一个汉字算1个字符
isText_20: /^(\W|\w{1}){0,20}$/, // 匹配20个字符,字符可以使字母、数字、下划线、非字母,一个汉字算1个字符
isText_100: /^(\W|\w{1}){0,100}$/, // 匹配100个字符,字符可以使字母、数字、下划线、非字母,一个汉字算1个字符
isText_250: /^(\W|\w{1}){0,250}$/, // 匹配250个字符,字符可以使字母、数字、下划线、非字母,一个汉字算1个字符
isNotChina: /^[^\u4e00-\u9fa5]{0,}$/, // 不为中文 IDcard: /^[1-9]\d{7}((0\d)|(1[0-2]))(([0|1|2]\d)|3[0-1])\d{3}$|^[1-9]\d{5}[1-9]\d{3}((0\d)|(1[0-2]))(([0|1|2]\d)|3[0-1])\d{3}([0-9]|X)$/, // 身份证
IDcardAndAdmin: /^(([1-9]\d{7}((0\d)|(1[0-2]))(([0|1|2]\d)|3[0-1])\d{3}$|^[1-9]\d{5}[1-9]\d{3}((0\d)|(1[0-2]))(([0|1|2]\d)|3[0-1])\d{3}([0-9]|X))|(admin))$/, // 身份证或者是admin账号
IDcardTrim: /^\s*(([1-9]\d{7}((0\d)|(1[0-2]))(([0|1|2]\d)|3[0-1])\d{3})|([1-9]\d{5}[1-9]\d{3}((0\d)|(1[0-2]))(([0|1|2]\d)|3[0-1])\d{3}([0-9]|X))|(admin))\s*$/, // 身份证
num1: /^[1-9]*$/, // 数字
companyNO: /^qqb_[0-9a-zA-Z_]{1,}$/, // 公司人员账号
imgType: /image\/(png|jpg|jpeg|gif)$/, // 上传图片类型
isChina: /^[\u4e00-\u9fa5]{2,8}$/,
isNozeroNumber: /^\+?[1-9]\d*$/, // 大于零的正整数
float: /^\d+(\.?|(\.\d+)?)$/, // 匹配正整数或者小数 或者0.这个特殊值
}
七,前端不设置宽高,水平垂直居中的几种方法:
1、flex
大家的第一反应,可能就是 flex 了。因为它的写法够简单直观,兼容性也没什么问题。是手机端居中方式的首选。
<div class="wrapper flex-center">
<p>horizontal and vertical</p>
</div>
.wrapper {
width: 300px;
height: 300px;
border: 1px solid #ccc;
}
.flex-center {
display: flex;
justify-content: center;
align-items: center;
}
利用到了 2 个关键属性:justify-content 和 align-items,都设置为 center,即可实现居中。
需要注意的是,一定要把这里的 flex-center 挂在父级元素,才能使得其中 唯一的 子元素居中。
2、flex + margin
这是 flex 方法的变种。父级元素设置 flex,子元素设置 margin: auto;。可以理解为子元素被四周的 margin “挤” 到了中间。
<div class="wrapper">
<p>horizontal and vertical</p>
</div>
.wrapper {
width: 300px;
height: 300px;
border: 1px solid #ccc;
display: flex;
}
.wrapper > p {
margin: auto;
}
3、transform + absolute
这个组合,常用于图片的居中显示。
<div class="wrapper">
<img src="test.png">
</div>
.wrapper {
width: 300px;
height: 300px;
border: 1px solid #ccc;
position: relative;
}
.wrapper > img {
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
}
当然,也可以将父元素 wrapper 的相对定位,移入子元素 img 中,替换掉绝对定位。效果是一样的。
4、table-cell
利用 table 的单元格居中效果展示。与 flex 一样,需要写在父级元素上。
<div class="wrapper">
<p>horizontal and vertical</p>
</div>
.wrapper {
width: 300px;
height: 300px;
border: 1px solid #ccc;
display: table-cell;
text-align: center;
vertical-align: middle;
}
5、absolute + 四个方向的值相等
使用绝对定位布局,设置 margin:auto;,并设置 top、left、right、bottom 的 值相等即可(不一定要都是 0)。
<div class="wrapper">
<p>horizontal and vertical</p>
</div>
.wrapper {
width: 300px;
height: 300px;
border: 1px solid #ccc;
position: relative;
}
.wrapper > p {
width: 170px;
height: 20px;
margin: auto;
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
}
这种方法一般用于弹出层,需要设置弹出层的宽高。
6、writing-mode
这个方法可以改变文字的显示方向,比如让文字的显示变为垂直方向。
<div class="wrapper">
<div class="wrapper-inner">
<p>horizontal and vertical</p>
</div>
</div>
.wrapper {
width: 300px;
height: 300px;
border: 1px solid #ccc;
writing-mode: vertical-lr;
text-align: center;
}
.wrapper > .wrapper-inner {
writing-mode: horizontal-tb;
display: inline-block;
text-align: center;
width: 100%;
}
.wrapper > .wrapper-inner > p {
display: inline-block;
margin: auto;
text-align: left;
}
兼容性上还有些小瑕疵,但大部分浏览器,包括手机端已支持 writing-mode 的写法了。
7、grid
像表格一样,网格布局让我们能够按行或列来对齐元素。然而在布局上,网格比表格更可能做到或更简单。
<div class="wrapper">
<p>horizontal and vertical</p>
</div>
.wrapper {
width: 300px;
height: 300px;
border: 1px solid #ccc;
display: grid;
}
.wrapper > p {
align-self: center;
justify-self: center;
}
但它在兼容性上不如 flex,特别是 IE 浏览器,只支持 IE10 及以上。
8、::after
伪元素也能用来实现居中么?感觉还是挺神奇的,看下面这个例子:
<div class="wrapper">
<img src="test.png">
</div>
.wrapper {
width: 300px;
height: 300px;
border: 1px solid #ccc;
text-align: center;
}
.wrapper::after {
content: '';
display: inline-block;
vertical-align: middle;
height: 100%;
}
.wrapper > img {
vertical-align: middle;
}
水平方向很好理解。垂直方向,可以理解为 ::after 把 img 往下拉到了中间。
9、::before
另一种是配合 font-size: 0; 共同施展的魔法。
<div class="wrapper">
<img src="test.png">
</div>
.wrapper {
width: 300px;
height: 300px;
border: 1px solid #ccc;
text-align: center;
font-size: 0;
}
.wrapper::before {
display: inline-block;
vertical-align: middle;
font-size: 14px;
content: '';
height: 100%;
}
.wrapper > img {
vertical-align: middle;
font-size: 14px;
}
font-size: 0; 的神秘之处在于,可以消除标签之间的间隙。另外,因为伪元素搭配的,都是最基础的 CSS 写法,所以不存在兼容性的风险。
七,css 左右不舍宽高,中间自适应
参考博客
八:css解决高度塌陷
1.将父元素的高度设置固定值
2.开启BFC(块格式化上下文)
(1)设置元素浮动
(2)设置元素为inline-block
(3)将元素的overflow设置为hidden (推荐该方法)
(4)设置元素绝对定位
3.直接在高度他闲的父元素最后家空白标签<div>
4.通过after伪类
clearfix::after{
content:" ";
display:block;
clear:both;
}
既可以解决高度塌陷又可以解决父子内外边距重叠
.clearfix:before,
.clearfix:after{
content:" ";
display:table;
clear:both;
}
九 css伪类元素及其用法:
具体详解
十:css选择器优先级
权重之和,和越大,越优先,和一样,后者覆盖前者。!important(权重:无穷)>内联式(即行内样式)(1000)>id选择器(100)>类选择器、伪类选择器、属性选择器(10)>标签选择器和伪元素选择器;(1)>通用选择器、相邻兄弟选择器(+)、兄弟选择器(~)、子选择器(>)(0)>继承(了解)>默认(了解)
1、css 属性 !important v-deep:
2、内联式(即行内样式)
<元素 style=" 属性:属性值; "></元素> // 权重1000
3、id选择器
#id名{ 属性:属性值;} // 权重100
4、类选择器、伪类选择器、属性选择器
.类名{ 属性:属性值;} // 权重10
元素:hover { 属性:属性值; }
input[type="text"]{ 属性:属性值; }
具体举例如:
input[type="text"]
{
width:150px;
background-color:yellow;
}
5、标签选择器和伪元素选择器;
标签 { 属性:属性值;} // 权重1
// 伪元素选择器:例如:
::after, ::before, ::fist-inline, ::selection等
::after { 属性:属性值; }
6、通用选择器、相邻兄弟选择器(+)、兄弟选择器(~)、子选择器(>)
*{ 属性:属性值;} // 权重0
h1+p{ // 相邻兄弟选择器(+)
color:red;
}
h1 ~ p{ //兄弟选择器(~)
color:red;
}
html > body table + ul {margin-top:20px;} //子选择器(>)
十一:ajax请求应该放在哪个生命周期?
mounted,因为js是单线程,ajax异步获取数据
十二:导出xlsx
export const changeExport = (res, name) => {
//res:后端返回文件流 name:'文件名字'
const aEle = document.createElement('a') // 创建a标签
const href = window.URL.createObjectURL(res) // 创建下载的链接
aEle.href = href
aEle.download = `${name}.xlsx` // 下载后文件名
document.body.appendChild(aEle)
aEle.click() // 点击下载
document.body.removeChild(aEle) // 下载完成移除元素
window.URL.revokeObjectURL(href)
}
//后台系统可直接使用
// 名字脱敏 只展示姓 后面展示**
export function anonymizedName(val) {
const reg = /(?<=.)./g
return val.replace(reg, '*')
}
十三:日历,带农历按周一到周日排列
<div class="week-wrapper text-[#969798] mb-[4px]">
<div class="week-item">一</div>
<div class="week-item">二</div>
<div class="week-item">三</div>
<div class="week-item">四</div>
<div class="week-item">五</div>
<div class="week-item">六</div>
<div class="week-item">日</div>
</div>
<div class="month-day-wrapper">
<div v-for="(day, index) in days" :key="index" class="day-item" @click="handleDay(day)">
<!-- day.isToday ? '今天' : -->
<div class="text-[10px] text-center">
{{ day.dateText }}
</div>
<!-- <div class="text-center text-[10px]" :class="day.selected ? 'text-[#fff]' : 'text-[#969798]'">
{{ day.chineseDateText }}
</div> -->
</div>
<!-- v-if="isMonth" -->
<div v-for="(item, indexx) in 7 - (days.length % 7)" :key="indexx" class="day-item"></div>
</div>
import { toLunar } from '../../calendar/utils.js'
export default {
data() {
return {
days: [], // 当前月的所有日期的数据集合
currentDateText: '', // 头部标题年月
currentDate: '', // 初始化时为当前日期
showPicker: false,
isMonth: true,
selectedObj: {
dateText: ''
},
// 周末所用日期
weekDay: '',
weekDays: '',
currentFirstDates: ''
}
},
mounted() {
this.currentDate = new Date()
this.initPickers()
},
methods: {
chineseNumber(num, month) {
let dateHash = ['', '一', '二', '三', '四', '五', '六', '七', '八', '九', '十']
let res = ''
if (num === 1) {
res = month
} else if (num <= 10) {
res = '初' + dateHash[num]
} else if (num > 10 && num < 20) {
res = '十' + dateHash[num - 10]
} else if (num === 20) {
res = '二十'
} else if (num > 20 && num < 30) {
res = '廿' + dateHash[num - 20]
} else if (num === 30) {
res = '三十'
}
return res
},
open() {
this.showPicker = true
},
confirm() {
this.getSelectedDay()
},
cancle() {
this.showPicker = false
},
getSelectedDay() {
for (let i = 0; i < this.days.length; i++) {
if (this.days[i].selected) return this.days[i]
}
},
/**
* 日历点击事件,更新点击选中状态
* @param {Object} day
*/
handleDay(day) {
if (!day.date) return
for (let i = 0; i < this.days.length; i++) {
this.days[i].selected = day.dateText === this.days[i].dateText
}
this.selectedObj = day
this.updateTitle(day)
},
/**
* 更新标题年月
* @param {Object} day
*/
updateTitle(day) {
this.currentDateText = this.getDateText(day.date)
},
/**
* 设置日历标题
* @param {Object} day
*/
getDateText(day) {
return day.getFullYear() + '年' + (day.getMonth() + 1) + '月'
},
/**
* 转换成周几
* @param {Object} day
*/
getWeekText(day) {
let weekVal = day.getDay()
let weekText = ''
switch (weekVal) {
case 0:
weekText = '日'
break
case 1:
weekText = '一'
break
case 2:
weekText = '二'
break
case 3:
weekText = '三'
break
case 4:
weekText = '四'
break
case 5:
weekText = '五'
break
case 6:
weekText = '六'
break
}
return '周' + weekText
},
/**
* 计算某个月的天数
* @param {Object} month
*/
getMonthDaysLength(day, month) {
day.setMonth(month)
day.setDate(0)
return day.getDate()
},
/**
* 根据日期对象计算当前月份1日为星期几,
* 从而计算日期数组开始需要添加几个空数据
* @param {Object} day
*/
getEmptyDays(day) {
return new Date(day.setDate(1)).getDay() - 1
},
/**
* 根据传入的day对象获取当前月的所有日期数据
* @param {Object} day
*/
getPickerData(day) {
let that = this
let arr = []
let emptyLength = this.getEmptyDays(day)
for (let i = 0; i < emptyLength; i++) {
arr.push({}) // 根据当前月份1号是星期几向往数组里添加空数据
}
// let month = day.getMonth() + 1
let month = that.currentDate.getMonth() + 1
let daysLength = this.getMonthDaysLength(day, month) // 计算当前月份一共有多少天
for (let a = 0; a < daysLength; a++) {
let obj = {}
if (that.selectedObj.dateText == '') {
obj = {
date: new Date(day.setDate(a + 1)), // Date类型的日期数据
dateText: a + 1, // 用于显示的日期
isToday: new Date().toDateString() === new Date(day.setDate(a + 1)).toDateString(), // 是否是今天
selected: new Date().toDateString() === new Date(day.setDate(a + 1)).toDateString(), // 设置今天为选中状态
chineseDateText: toLunar(day.getFullYear(), month, a + 1).day
}
} else {
obj = {
date: new Date(day.setDate(a + 1)), // Date类型的日期数据
dateText: a + 1, // 用于显示的日期
isToday: new Date().toDateString() === new Date(day.setDate(a + 1)).toDateString(), // 是否是今天
selected:
that.selectedObj.dateText === a + 1 &&
that.selectedObj.chineseDateText === toLunar(day.getFullYear(), month, a + 1).day, // 设置今天为选中状态
chineseDateText: toLunar(day.getFullYear(), month, a + 1).day
}
}
arr.push(obj)
}
return arr
},
initPicker() {
this.days = this.getPickerData(this.currentDate) // 默认当前日期初始化日历
},
// 回到今天
initPickers() {
this.currentDate = new Date()
this.selectedObj = {
dateText: ''
}
this.days = this.getPickerData(new Date()) // 默认当前日期初始化日历
}
}
}
// toLunar开始
var MIN_YEAR = 1891
var MAX_YEAR = 2100
var lunarInfo = [
[0, 2, 9, 21936],
[6, 1, 30, 9656],
[0, 2, 17, 9584],
[0, 2, 6, 21168],
[5, 1, 26, 43344],
[0, 2, 13, 59728],
[0, 2, 2, 27296],
[3, 1, 22, 44368],
[0, 2, 10, 43856],
[8, 1, 30, 19304],
[0, 2, 19, 19168],
[0, 2, 8, 42352],
[5, 1, 29, 21096],
[0, 2, 16, 53856],
[0, 2, 4, 55632],
[4, 1, 25, 27304],
[0, 2, 13, 22176],
[0, 2, 2, 39632],
[2, 1, 22, 19176],
[0, 2, 10, 19168],
[6, 1, 30, 42200],
[0, 2, 18, 42192],
[0, 2, 6, 53840],
[5, 1, 26, 54568],
[0, 2, 14, 46400],
[0, 2, 3, 54944],
[2, 1, 23, 38608],
[0, 2, 11, 38320],
[7, 2, 1, 18872],
[0, 2, 20, 18800],
[0, 2, 8, 42160],
[5, 1, 28, 45656],
[0, 2, 16, 27216],
[0, 2, 5, 27968],
[4, 1, 24, 44456],
[0, 2, 13, 11104],
[0, 2, 2, 38256],
[2, 1, 23, 18808],
[0, 2, 10, 18800],
[6, 1, 30, 25776],
[0, 2, 17, 54432],
[0, 2, 6, 59984],
[5, 1, 26, 27976],
[0, 2, 14, 23248],
[0, 2, 4, 11104],
[3, 1, 24, 37744],
[0, 2, 11, 37600],
[7, 1, 31, 51560],
[0, 2, 19, 51536],
[0, 2, 8, 54432],
[6, 1, 27, 55888],
[0, 2, 15, 46416],
[0, 2, 5, 22176],
[4, 1, 25, 43736],
[0, 2, 13, 9680],
[0, 2, 2, 37584],
[2, 1, 22, 51544],
[0, 2, 10, 43344],
[7, 1, 29, 46248],
[0, 2, 17, 27808],
[0, 2, 6, 46416],
[5, 1, 27, 21928],
[0, 2, 14, 19872],
[0, 2, 3, 42416],
[3, 1, 24, 21176],
[0, 2, 12, 21168],
[8, 1, 31, 43344],
[0, 2, 18, 59728],
[0, 2, 8, 27296],
[6, 1, 28, 44368],
[0, 2, 15, 43856],
[0, 2, 5, 19296],
[4, 1, 25, 42352],
[0, 2, 13, 42352],
[0, 2, 2, 21088],
[3, 1, 21, 59696],
[0, 2, 9, 55632],
[7, 1, 30, 23208],
[0, 2, 17, 22176],
[0, 2, 6, 38608],
[5, 1, 27, 19176],
[0, 2, 15, 19152],
[0, 2, 3, 42192],
[4, 1, 23, 53864],
[0, 2, 11, 53840],
[8, 1, 31, 54568],
[0, 2, 18, 46400],
[0, 2, 7, 46752],
[6, 1, 28, 38608],
[0, 2, 16, 38320],
[0, 2, 5, 18864],
[4, 1, 25, 42168],
[0, 2, 13, 42160],
[10, 2, 2, 45656],
[0, 2, 20, 27216],
[0, 2, 9, 27968],
[6, 1, 29, 44448],
[0, 2, 17, 43872],
[0, 2, 6, 38256],
[5, 1, 27, 18808],
[0, 2, 15, 18800],
[0, 2, 4, 25776],
[3, 1, 23, 27216],
[0, 2, 10, 59984],
[8, 1, 31, 27432],
[0, 2, 19, 23232],
[0, 2, 7, 43872],
[5, 1, 28, 37736],
[0, 2, 16, 37600],
[0, 2, 5, 51552],
[4, 1, 24, 54440],
[0, 2, 12, 54432],
[0, 2, 1, 55888],
[2, 1, 22, 23208],
[0, 2, 9, 22176],
[7, 1, 29, 43736],
[0, 2, 18, 9680],
[0, 2, 7, 37584],
[5, 1, 26, 51544],
[0, 2, 14, 43344],
[0, 2, 3, 46240],
[4, 1, 23, 46416],
[0, 2, 10, 44368],
[9, 1, 31, 21928],
[0, 2, 19, 19360],
[0, 2, 8, 42416],
[6, 1, 28, 21176],
[0, 2, 16, 21168],
[0, 2, 5, 43312],
[4, 1, 25, 29864],
[0, 2, 12, 27296],
[0, 2, 1, 44368],
[2, 1, 22, 19880],
[0, 2, 10, 19296],
[6, 1, 29, 42352],
[0, 2, 17, 42208],
[0, 2, 6, 53856],
[5, 1, 26, 59696],
[0, 2, 13, 54576],
[0, 2, 3, 23200],
[3, 1, 23, 27472],
[0, 2, 11, 38608],
[11, 1, 31, 19176],
[0, 2, 19, 19152],
[0, 2, 8, 42192],
[6, 1, 28, 53848],
[0, 2, 15, 53840],
[0, 2, 4, 54560],
[5, 1, 24, 55968],
[0, 2, 12, 46496],
[0, 2, 1, 22224],
[2, 1, 22, 19160],
[0, 2, 10, 18864],
[7, 1, 30, 42168],
[0, 2, 17, 42160],
[0, 2, 6, 43600],
[5, 1, 26, 46376],
[0, 2, 14, 27936],
[0, 2, 2, 44448],
[3, 1, 23, 21936],
[0, 2, 11, 37744],
[8, 2, 1, 18808],
[0, 2, 19, 18800],
[0, 2, 8, 25776],
[6, 1, 28, 27216],
[0, 2, 15, 59984],
[0, 2, 4, 27424],
[4, 1, 24, 43872],
[0, 2, 12, 43744],
[0, 2, 2, 37600],
[3, 1, 21, 51568],
[0, 2, 9, 51552],
[7, 1, 29, 54440],
[0, 2, 17, 54432],
[0, 2, 5, 55888],
[5, 1, 26, 23208],
[0, 2, 14, 22176],
[0, 2, 3, 42704],
[4, 1, 23, 21224],
[0, 2, 11, 21200],
[8, 1, 31, 43352],
[0, 2, 19, 43344],
[0, 2, 7, 46240],
[6, 1, 27, 46416],
[0, 2, 15, 44368],
[0, 2, 5, 21920],
[4, 1, 24, 42448],
[0, 2, 12, 42416],
[0, 2, 2, 21168],
[3, 1, 22, 43320],
[0, 2, 9, 26928],
[7, 1, 29, 29336],
[0, 2, 17, 27296],
[0, 2, 6, 44368],
[5, 1, 26, 19880],
[0, 2, 14, 19296],
[0, 2, 3, 42352],
[4, 1, 24, 21104],
[0, 2, 10, 53856],
[8, 1, 30, 59696],
[0, 2, 18, 54560],
[0, 2, 7, 55968],
[6, 1, 27, 27472],
[0, 2, 15, 22224],
[0, 2, 5, 19168],
[4, 1, 25, 42216],
[0, 2, 12, 42192],
[0, 2, 1, 53584],
[2, 1, 21, 55592],
[0, 2, 9, 54560]
]
//是否闰年
function isLeapYear(year) {
return (year % 4 === 0 && year % 100 !== 0) || year % 400 === 0
}
//天干地支年
function lunarYear(year) {
var gan = ['庚', '辛', '壬', '癸', '甲', '乙', '丙', '丁', '戊', '己']
var zhi = ['申', '酉', '戌', '亥', '子', '丑', '寅', '卯', '辰', '巳', '午', '未']
var str = year.toString().split('')
return gan[str[3]] + zhi[year % 12]
}
//生肖年
function zodiacYear(year) {
var zodiac = ['猴', '鸡', '狗', '猪', '鼠', '牛', '虎', '兔', '龙', '蛇', '马', '羊']
return zodiac[year % 12]
}
//公历月份天数
//@param year 阳历-年
//@param month 阳历-月
function solarMonthDays(year, month) {
var FebDays = isLeapYear(year) ? 29 : 28
var monthHash = ['', 31, FebDays, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
return monthHash[month]
}
//农历月份天数
function lunarMonthDays(year, month) {
var monthData = lunarMonths(year)
return monthData[month - 1]
}
//农历月份天数数组
function lunarMonths(year) {
var yearData = lunarInfo[year - MIN_YEAR]
var leapMonth = yearData[0]
var bit = (+yearData[3]).toString(2)
var months = []
for (var i = 0; i < bit.length; i++) {
months[i] = bit.substr(i, 1)
}
for (var k = 0, len = 16 - months.length; k < len; k++) {
months.unshift('0')
}
months = months.slice(0, leapMonth === 0 ? 12 : 13)
for (var i = 0; i < months.length; i++) {
months[i] = +months[i] + 29
}
return months
}
//农历每年的天数
//@param year 农历年份
function lunarYearDays(year) {
var monthArray = lunarYearMonths(year)
var len = monthArray.length
return monthArray[len - 1] === 0 ? monthArray[len - 2] : monthArray[len - 1]
}
//
function lunarYearMonths(year) {
var monthData = lunarMonths(year)
var res = []
var temp = 0
var yearData = lunarInfo[year - MIN_YEAR]
var len = yearData[0] === 0 ? 12 : 13
for (var i = 0; i < len; i++) {
temp = 0
for (var j = 0; j <= i; j++) {
temp += monthData[j]
}
res.push(temp)
}
return res
}
//获取闰月
//@param year 农历年份
function leapMonth(year) {
var yearData = lunarInfo[year - MIN_YEAR]
return yearData[0]
}
//计算农历日期与正月初一相隔的天数
function betweenLunarDays(year, month, day) {
var yearMonth = lunarMonths(year)
var res = 0
for (var i = 1; i < month; i++) {
res += yearMonth[i - 1]
}
res += day - 1
return res
}
//计算2个阳历日期之间的天数
//@param year 阳历年
//@param month
//@param day
//@param l_month 阴历正月对应的阳历月份
//@param l_day 阴历初一对应的阳历天
function betweenSolarDays(year, month, day, l_month, l_day) {
var time1 = new Date(year + '-' + month + '-' + day).getTime()
var time2 = new Date(year + '-' + l_month + '-' + l_day).getTime()
return Math.ceil((time1 - time2) / 24 / 3600 / 1000)
}
//根据距离正月初一的天数计算阴历日期
//@param year 阳历年
//@param between 天数
function lunarByBetween(year, between) {
var lunarArray = {}
var yearMonth = []
var t = 0
var e = 0
var leapMonthVal = 0
var m = ''
if (between === 0) {
t = 1
e = 1
m = '正月'
} else {
year = between > 0 ? year : year - 1
yearMonth = lunarYearMonths(year)
leapMonthVal = leapMonth(year)
between = between > 0 ? between : lunarYearDays(year) + between
for (var i = 0; i < 13; i++) {
if (between === yearMonth[i]) {
t = i + 2
e = 1
break
} else if (between < yearMonth[i]) {
t = i + 1
e = between - (yearMonth[i - 1] ? yearMonth[i - 1] : 0) + 1
break
}
}
m =
leapMonthVal !== 0 && t === leapMonthVal + 1
? '闰'.chineseMonth(t - 1)
: chineseMonth(leapMonthVal !== 0 && leapMonthVal + 1 < t ? t - 1 : t)
}
lunarArray.lunarDate = year + '-' + t + '-' + e // 年月日
lunarArray.repetMonth = leapMonthVal //闰几月
lunarArray.yearType = lunarYear(year) // 天干地支年
lunarArray.animal = zodiacYear(year) // 生肖年
lunarArray.month = m // 月份
lunarArray.day = chineseNumber(e, m) // 日
return lunarArray
}
//中文月份
function chineseMonth(month) {
var monthHash = [
'',
'正月',
'二月',
'三月',
'四月',
'五月',
'六月',
'七月',
'八月',
'九月',
'十月',
'冬月',
'腊月'
]
return monthHash[month]
}
//中文日期
function chineseNumber(num, month) {
var dateHash = ['', '一', '二', '三', '四', '五', '六', '七', '八', '九', '十']
var res = ''
if (num === 1) {
res = month
} else if (num <= 10) {
res = '初' + dateHash[num]
} else if (num > 10 && num < 20) {
res = '十' + dateHash[num - 10]
} else if (num === 20) {
res = '二十'
} else if (num > 20 && num < 30) {
res = '廿' + dateHash[num - 20]
} else if (num === 30) {
res = '三十'
}
return res
}
//转换农历
export function toLunar(year, month, day) {
var yearData = lunarInfo[year - MIN_YEAR]
if (year === MIN_YEAR && month <= 2 && day <= 9) {
return [1891, 1, 1, '辛卯', '兔', '正月', '初一']
}
return lunarByBetween(year, betweenSolarDays(year, month, day, yearData[1], yearData[2]))
}
//转换公历
//@param year 阴历-年
//@param month 阴历-月,闰月处理:例如如果当年闰五月,那么第二个五月就传六月,相当于阴历有13个月
//@param date 阴历-日
export function toSolar(year, month, day) {
var yearData = lunarInfo[year - MIN_YEAR]
var between = betweenLunarDays(year, month, day)
var ms = new Date(year + '-' + yearData[1] + '-' + yearData[2]).getTime()
var s = ms + between * 24 * 60 * 60 * 1000
var d = new Date()
d.setTime(s)
year = d.getFullYear()
month = d.getMonth() + 1
day = d.getDate()
return [year, month, day]
}
// toLunar开始
```javascript
css 文件
* {
box-sizing: border-box;
}
.window-backdrop {
position: fixed;
left: 0;
top: 0;
width: 100%;
height: 100%;
background: rgba(0, 0, 0, 0.6);
display: flex;
align-items: center;
justify-content: center;
z-index: 9999;
}
.window-wrapper {
width: 80%;
min-width: 300px;
max-width: 800px;
padding: 10px 15px;
background: #fff;
border-radius: 10px;
border: 1px #000 solid;
}
.week-wrapper {
display: flex;
align-items: center;
justify-content: space-between;
font-weight: bold;
.week-item {
font-size: 10px;
flex: 14.2857%;
text-align: center;
}
}
.today-date-text {
display: flex;
height: 50px;
align-items: center;
justify-content: space-between;
line-height: 100%;
padding: 0 20px;
.text-button {
font-size: 16px;
color: #000;
}
.arrow-img {
height: 30px;
width: 30px;
}
.today-date {
font-size: 18px;
font-weight: bold;
}
}
.month-day-wrapper {
display: flex;
flex-wrap: wrap;
justify-content: space-between;
.day-item,
.day-item-actived {
flex: 14.2857%;
margin-bottom: 4.5px;
font-size: 10px;
cursor: pointer;
overflow: hidden;
font-weight: normal;
.chinese-date-text {
text-align: center;
color: #fff;
}
}
.date-text {
text-align: center;
color: #343538;
}
.day-item {
color: #343538;
}
.day-item-actived {
padding: 4px;
color: #fff;
background: #2875dd;
border-radius: 50%;
}
}
十四:深拷贝
export const deepClone = (obj) => {
if (obj === null || typeof obj !== 'object') {
return obj
}
if (obj instanceof Date) {
return new Date(obj.getTime())
}
if (obj instanceof Array) {
return obj.reduce((arr, item, i) => {
arr[i] = deepClone(item)
return arr
}, [])
}
if (obj instanceof Object) {
return Object.keys(obj).reduce((newObj, key) => {
newObj[key] = deepClone(obj[key])
return newObj
}, {})
}
}
十五:递归清除数组每个元素下的children为空的数组,避免渲染多余
export const clearAllChildren = (items, childrenName) => {
for (let i = 0; i < items.length; i++) {
const item = items[i]
// 当前对象存在children
if (item && item[childrenName]) {
// children为空数组时删除
if (item[childrenName].length === 0) {
delete item[childrenName]
} else {
// 递归当前children数组
clearAllChildren(item[childrenName], childrenName)
}
}
}
return items
}
十六:echarts 初始化展示默认当前月份信息
echartsExtmp.setOption(option)
//dataIndex 随便赋值你想要展示的哪条数据
setTimeout(function () {
echartsExtmp.dispatchAction({
type: 'showTip',
seriesIndex: 0, // 显示第几个series
dataIndex: 2, // 显示第几个数据
})
})
十七:这个是为了实现el-cascader 点击父级自动勾选子级但是后端传数据只传最外层
props:{ multiple: true,//可多选
checkStrictly: false, //父级勾选状态影响子级,true为单选状态
emitPath: false,}
//handleActiveItemChange 数据el-cascader @change方法 'mycascader'就是获取vue DOM的方法
handleActiveItemChange() {
this.$nextTick(() => {
if (this.$refs['mycascader'][0].getCheckedNodes().length > 0) {
let a = this.$refs['mycascader'][0].getCheckedNodes() //获取到选中值的node数据
let b = a[0].value.substring(0, 3) //根据选中的value值判断条件,可以换成别的值,比如层级字段,
let c = []
a.map((i) => {
if (i.value.substring(0, 3) == b) {
c.push({
organGrade: i.data.organGrade,
organCode: i.data.organCode,
})
}
return c
})
this.formInline.cascade = c
}
})
},