1,js年月日减年月日获得相差日天数 将日期转化为yyyy-mm-dd然后传两个参数进去
const days = daysBetween('2023-01-01', '2023-03-01');
console.log(days); // 输出:60
在element Ui中使用el-table组件的数据懒加载,删除时无法更新数据:
当点击父级添加子级时:在请求接口之后对其进行更新操作,同时要在el-table组件中绑定ref=“table”
if(response.rows.length === 0){
this.$set(this.$refs.table.store.states.lazyTreeNodeMap, tree.taskId, {})
}
echarts图表中x轴数据超多,对其x轴进行设置左右滑动,并且滑块紧贴x轴上
data_echarts(){
let chartDom = document.getElementById('main_data');
let myChart = echarts.init(chartDom);myChart.setOption({
tooltip: {
trigger: 'axis',
axisPointer: {
type: 'cross',
crossStyle: {
color: '#999'
}
}
},
toolbox: {
feature: {//设置复制,下载等小工具,true为使用
dataView: { show: false, readOnly: false },
magicType: { show: false, type: ['line', 'bar']},
restore: { show: false },
saveAsImage: { show: false }
}
},
grid:{ //设置图表的偏移量,让滑块靠近x轴上
bottom:'15%',
left:'10%'
},
legend: {
data: ['总投资(万元)','投资完成率(%)']
},
xAxis: [
{
type: 'category',
data: ['石台县秋浦河鸿陵河段防洪综合治理工程', '历溪河山洪沟防洪治理工程', '杨墩站拆除重建工程', '新建张溪水厂', '贵池区农村水系及水美乡村建设试点县四标', '池州市升金湖泵站工程', '池州市九华河下游段综合治理工程','贵池区农村水系及水美乡村建设试点县三标','东至县侯店河山洪沟防洪治理工程','池州市九华河碧山段防洪治理工程','青阳县东山水库除险加固工程一标','东至县黄湓河张溪段防洪治理工程','东至县县城防洪应急工程'],
axisPointer: {
type: 'shadow'
},
axisLabel: {
show: true,
rotate: 35,//35度角倾斜显示
},
axisLine: { //y轴不显示
"show": true
},
axisTick: { //y轴刻度线不显示
"show": false
},
}
],
yAxis: [
{
type: 'value',
name: '总投资(万元)',
min: 0,
max: 400,
interval:50,
},
{
type: 'value',
name: '投资完成率(%)',
min: 0,
max: 100,
interval: 10,
}
],
series: [
{
name: '总投资(万元)',
type: 'bar',
tooltip: {
valueFormatter: function (value) {
return value + ' 万元';
}
},
data: [200.0,178.02,197.6,14.9,23.4,138.5,203.7,300.9,323.89,200.0,129.1,208.7,145.6]
},
{
name: '投资完成率(%)',
type: 'line',
yAxisIndex: 1,
tooltip: {
valueFormatter: function (value) {
return value + ' %';
}
},
data: [29,26,28,5,9,21,30.2,42.5,52.9,29,22.8,32.2,23.9]
}
],
//滚动条样式
dataZoom: [
{
xAxisIndex: 0,
show: true,//是否显示
type: "slider",
startValue: 0, //从头开始
endValue:5, //显示多少条,从下标0开始
height: 8,//滑块的高度
showDetail: false,
xAxisIndex: [0],//默认离近x轴
backgroundColor: 'rgba(39, 57, 70, 0.0)',//设置滑块的背景色
fillerColor: 'rgba(143, 157, 175, 0.4)',//设置滑块的边颜色
handleColor: 'rgba(68, 80, 98, 0.7)',//滑块颜色
},
],
});
},
当在页面中设置了高度和 height: 35%;overflow-y:scroll;可以滚动时,要想隐藏滚动条,需要使用如下css样式:
/* 隐藏滚动条 */
.element::-webkit-scrollbar {
display: none; /* 对于Webkit浏览器 */
}
/* 兼容Firefox */
.element {
scrollbar-width: none; /* 对于Firefox */
}
/* 兼容IE和Edge */
.element {
-ms-overflow-style: none; /* 对于IE和Edge */
}
<div class="element">
<!-- 长内容,足以产生滚动 -->
</div>
要隐藏overflow-y: scroll;
样式的滚动条,可以使用CSS中的::-webkit-scrollbar
伪元素。以下是一个示例代码,它将隐藏一个元素的滚动条:
请注意,这种方法主要针对Webkit内核的浏览器(如Chrome、Safari)和基于Firefox的浏览器。对于Internet Explorer和Edge,需要使用-ms-overflow-style
属性。对于不支持::-webkit-scrollbar
的浏览器,滚动条将正常显示。
前端鼠标右击事件(代码块)
在Vue中,可以通过监听原生的contextmenu事件来实现鼠标右击事件的处理。以下是一个简单的示例:
<template>
<div @contextmenu.prevent="onRightClick">
右键点击这里测试
</div>
</template>
<script>
export default {
methods: {
onRightClick(event) {
// 处理右键点击事件
console.log('鼠标右键被点击', event);
// 可以在这里执行你需要的操作
}
}
}
</script>
在这个例子中,@contextmenu.prevent="onRightClick"
是关键,它绑定了一个方法onRightClick
到contextmenu事件上,并阻止了默认的右键菜单显示。在onRightClick
方法中,你可以添加你需要执行的逻辑。
改变vue单个页面body的背景颜色
-
利用beforeCreate和beforeDestroy
beforeCreate () {
document.querySelector('body').setAttribute('style', 'background-color:#efeff4;')
},
beforeDestroy () {
document.querySelector('body').removeAttribute('style')
}
后端返回文件流(任何类型的文档或图片都可以访问),前台使用XMLHttpRequest转换成base64位,随后再转换成url地址
代码如下:
handlePictureCardPreview(file, type) {
console.log('预览', file, type)
let parmes = {
action: 'lookFile',
file_cd: 'E7A84FE77B2F408DAEEC5C9208EDF62D'
}
let url = process.env.VUE_APP_BASE_API + '/file/info?'+'action='+'lookFile&'+'file_cd='+ parmes.file_cd
this.pdfimg(url)
},
pdfimg(url){
let xhr = new XMLHttpRequest()
xhr.open('GET', url, true)
xhr.responseType = 'blob'
xhr.setRequestHeader(
'Authorization',
'Bearer ' + getToken()
) // 设置token
let that = this
xhr.onreadystatechange = function() {
console.log('xhr',xhr)
if (xhr.readyState == 4) {
if (xhr.status == 200) {
let blob = this.response
// 将blob转化为base64形式
let reader = new FileReader()
reader.readAsDataURL(blob)
reader.onloadend = function() {
let base64data = reader.result // 这里base64data就是请求到的图片的base64码
// that.imgUrl = base64data
that.imgUrl = that.base64ToImageUrl(base64data)
console.log('64位字符',that.imgUrl)
}
}
}
}
xhr.send()
},
base64ToImageUrl(base64) {
// 将base64字符串转换为二进制数据
var binary = atob(base64.split(',')[1]);
var mimeString = base64.split(',')[0].match(/:(.*?);/)[1];
// 创建Blob对象
var array = [];
for (var i = 0; i < binary.length; i++) {
array.push(binary.charCodeAt(i));
}
var blob = new Blob([new Uint8Array(array)], {type: mimeString});// 创建URL
return URL.createObjectURL(blob);
},
前端创建打印模版,使用el-form传导数据,写法模版如下:
<template>
<el-dialog title="打印日志" :visible.sync="open" append-to-body width="800px" style="height:100%;">//数据传导模块并创建打印模版
<el-form ref="form" :model="dataForm" style="width:100%;height:800px;" label-width="140px" label-position="center"
:hide-required-asterisk="true" :disabled="true">
<el-col :span="22" style="border-top: 2px solid black;">
<el-form-item label="项目名称" prop="largeProjectname" class="right_br1">
<span slot="label" class="labelStyle">项目名称</span>
<div class="boxStyle boxStylebor">
<input class="inputStyle" v-model="dataForm.prOname" :readonly="true" />
</div>
</el-form-item>
</el-col>
<!-- <el-col :span="22">
<el-form-item label="职位" prop="largeProjectname" class="right_br1">
<span slot="label" class="labelStyle">职位</span>
<div class="boxStyle boxStylebor">
<input class="inputStyle" v-model="dataForm.largeProjectname" :readonly="true" />
</div>
</el-form-item>
</el-col> -->
<el-col :span="22">
<div style="display: flex;">
<el-form-item label="日期" prop="largeProjectname" class="right_brriz">
<span slot="label" class="labelStyle">日期</span>
<div class="boxStyle2 boxStylebor">
<input class="inputStyle" v-model="dataForm.timedate" :readonly="true" />
</div>
</el-form-item>
<el-form-item label="日志填报人" prop="largeProjectname" class="right_br12">
<span slot="label" class="labelStyle">日志填报人</span>
<div class="boxStyle2 boxStylebor">
<input class="inputStyle" v-model="dataForm.fillin" :readonly="true" />
</div>
</el-form-item>
</div>
</el-col><el-col :span="22" style="height:500px;">
<el-form-item label="工作描述" prop="largeProjectname" class="right_br1" style="height:500px;">
<span slot="label" class="labelStyle">工作描述:</span>
<div class="boxStyle23">//这里使用textarea会导致打印后只有一行 使用div标签保留数据回显 用v-html绑定值可以解决
其他格式情况不边 <div class="inputStyleer" v-html="dataForm.description"></div>
<!-- <textarea class="inputStyleer" v-model="dataForm.description" :readonly="true"></textarea> -->
<div class="inputStyleer" v-html="dataForm.description"></div>
</div>
</el-form-item>
</el-col><el-col :span="22">
<el-form-item label="填写时间" prop="largeProjectname" class="right_br1">
<span slot="label" class="labelStyle">填写时间</span>
<div class="boxStyle boxStylebor">
<input class="inputStyle" v-model="dataForm.fillindate" :readonly="true" />
</div>
</el-form-item>
</el-col>
</el-form>
<div class="prints">
<el-button type="primary" @click="printdayin">打印</el-button>
</div>
</el-dialog>
</template><script>
import html2canvas from 'html2canvas';
import jsPDF from 'jspdf';
export default {
data() {
return {
open: false,
dataForm: {
prOname: '', //项目(工程)名称
fillin: '', //填报人
timedate: '', //日志日期
description: '', //工作描述
fillindate: '', //填报日期
}
}
},
methods: {
loadings(parmes) {
let gmtDate = this.dateToGMT(parmes.fillindate)
parmes.fillindate = gmtDate
this.dataForm = {
...parmes
}
console.log('展开了吗', this.dataForm)
this.open = true
},
dateToGMT(date) {
const year = date.getUTCFullYear();
const month = (date.getUTCMonth() + 1).toString().padStart(2, '0');
const day = date.getUTCDate().toString().padStart(2, '0');
const hours = (date.getUTCHours() + 8).toString().padStart(2, '0'); // 转换为本地时间
const minutes = date.getUTCMinutes().toString().padStart(2, '0');
const seconds = date.getUTCSeconds().toString().padStart(2, '0');return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;
},
async printdayin() {
const formElement = this.$refs.form.$el; // 获取表单的DOM元素
const canvas = await html2canvas(formElement); // 将表单渲染成canvas
const imgData = canvas.toDataURL('image/png'); // 将canvas转换为图片const pdf = new jsPDF('p', 'mm', 'a4'); // 创建PDF实例
const imgProps = pdf.getImageProperties(imgData);
console.log('获取图片的数据信息', imgProps)
const pdfWidth = pdf.internal.pageSize.getWidth();
const pdfHeight = (imgProps.height * pdfWidth) / imgProps.width;
pdf.addImage(imgData, 'PNG', 10, 10, pdfWidth, pdfHeight); // 将图片添加到PDF中
pdf.save('form.pdf'); // 保存PDF文件
}
}
}
</script><style lang="scss" scoped>
.prints {
display: flex;
justify-content: right;
margin-right: 30px;
}.right_br1 {
border-right: 2px solid black !important;
border-left: 2px solid black !important;
border-bottom: 2px solid black;
}.right_brriz {
border-right: 1px solid black !important;
border-left: 2px solid black !important;
border-bottom: 2px solid black;
}.right_br12 {
border-right: 2px solid black !important;
border-bottom: 2px solid black;
}.labelStyle {
font-size: 16px;
color: #000;
padding-left: 10px;
display: flex;
justify-content: center;
}.boxStyle {
min-height: 1cm;
max-height: 1.5cm;
width: 100%;
}.boxStyle2 {
min-height: 1cm;
max-height: 1.5cm;
width: 90%;
}
.boxStyle23 {
min-height: 1cm;
max-height: 1.5cm;
width: 98%;
}.boxStylebor {
border-left: 1px solid #000
}.inputStyle {
/* padding: 15px 5px 15px 10px; */
margin-left: 5px;
font-size: 16px;
height: 100%;
width: 95%;
line-height: 1.8;
border-style: none;
font-weight: bold;
}.inputStyle:focus {
outline: none;
/* 去除边框 */
border: none;
/* 也可以设置边框为透明或者去掉border属性 */
box-shadow: none;
/* 可选,去除聚焦时的阴影 */
}::v-deep .el-form-item {
margin-bottom: 0 !important;
}.inputStyleer {
font-size: 16px;
height: 497px;
width: 100%;
line-height: 1.8;
border-style: none;
white-space: pre-wrap;
/* 保留空白符,自动换行 */
word-wrap: break-word;
/* 在长单词或URL地址内部进行换行 */
font-weight: 700;
border-left: 1px solid #000;
overflow-y: hidden;
}.inputStyleer:focus {
outline: none;
/* 去除边框 */
/* border: none; */
border-top: none;
border-bottom: none;
border-right: none;
border-left: 1px solid #000;
/* 也可以设置边框为透明或者去掉border属性 */
box-shadow: none;
/* 可选,去除聚焦时的阴影 */
}
</style>
详细代码:
<template>
<div>
<!-- 使用v-html确保内容格式正确 -->
<div v-html="formattedText"></div>
<!-- 原始textarea,供用户编辑 -->
<textarea v-model="text"></textarea>
<!-- 打印按钮,点击后触发打印方法 -->
<button @click="print">打印</button>
</div>
</template>
<script>
export default {
data() {
return {
text: `这是一个
多行文本
用于测试打印`
};
},
computed: {
// 使用计算属性将textarea的值转换为HTML格式
formattedText() {
return this.text.replace(/\n/g, '<br>');
}
},
methods: {
print() {
// 创建一个新窗口用于打印
const printWindow = window.open('', '_blank');
// 写入要打印的内容
printWindow.document.write(this.formattedText);
// 执行打印
printWindow.document.close(); // 关闭文档
printWindow.focus(); // 聚焦新窗口
printWindow.print(); // 执行打印
printWindow.close(); // 关闭新窗口
}
}
};
</script>
将二进制的文件流转换成blob的URL地址如下:
<template>
<el-dialog title="预览文件" append-to-body :visible.sync="yl_open" width="80%"
style="margin-top: 0vh !important;position:absolute;">
<img :src="imgUrl" alt="" style="width:100%;height:100%;" />
</el-dialog>
</template>
<script>
import {
getToken
} from '@/utils/auth'
export default {
data() {
return {
imgUrl: '',
yl_open: false,
typeurl:{}
}
},
methods:{
loading(file){
this.typeurl = {}
this.imgUrl = ''
this.typeurl = file
let url = process.env.VUE_APP_HOST + '/file/info?'+'action='+'lookFile&'+'file_cd='+ file.fileId
this.loadImage(url)
},
async loadImage(url) {
try {
const loading = this.$loading({
lock: true,
text: 'Loading',
spinner: 'el-icon-loading',
background: 'rgba(0, 0, 0, 0.7)'
});
const token = getToken();// Replace with your actual token
const response = await fetch(url, {
method: 'GET',
headers: {
'Authorization': `Bearer ${token}`
}
});
if (!response.ok) {
throw new Error('Network response was not ok');
}
const blob = await response.blob();
const imageUrl = URL.createObjectURL(blob);
//在这里是将所有的类型都给记录进数组中 然后判断是否这些类型 不是就是图片否则打开新的页面
let type = ['.docx','.xlsx','.doc','.pdf','.txt']
const result = this.containsAny(this.typeurl.name, type)
if(result){
loading.close();
console.log('进来了吗',imageUrl)
window.open(imageUrl)
}else{
loading.close();
this.imgUrl = imageUrl
this.yl_open = true
}
} catch (error) {
console.error('请求异常',error);
}
},
containsAny(str, arr) {
return arr.some(item => str.includes(item));
},
}
}
</script>
<style lang="scss" scoped>
</style>
vue2在pc端中长按触发事件(自定义事件鼠标长按)
写在main.js中,在页面中可直接使用:
例如:<div v-longpress="longPressHandler">长按我</div>
methods: {
longPressHandler() {
console.log('Mouse long press event triggered');
}
}
let start = ''
Vue.directive('longpress', {
bind: function(el, binding, vNode) {
// 确保提供的表达式是函数
if (typeof binding.value !== 'function') {
// 获取组件名称
const compName = vNode.context.name;
let warn =
`[longpress:] provided expression '${binding.expression}' is not a function, but has to be`;
if (compName) {
warn += `Found in component '${compName}'`;
}
console.warn(warn);
}
// 定义变量
let pressTimer = null;
// 创建计时器( 1秒后执行函数 )
start = (e) => {
if (e.type === 'click' && e.button !== 0) {
return;
}
if (pressTimer === null) {
pressTimer = setTimeout(() => {
// 执行函数
handler(e);
}, 3000);
}
}
// 取消计时器
let cancel = () => {
if (pressTimer !== null) {
clearTimeout(pressTimer);
pressTimer = null;
}
}
// 运行函数
const handler = (e) => {
binding.value(e);
}
// 添加事件监听器
el.addEventListener('mousedown', start);
el.addEventListener('click', cancel);
el.addEventListener('mouseout', cancel);
},
unbind: function(el) {
// 移除事件监听器
el.removeEventListener('mousedown', start);
el.removeEventListener('click', cancel);
el.removeEventListener('mouseout', cancel);
}
})