*时间区间选择器,控制时间区间
<el-date-picker
v-model="state.searchForm.date"
type="datetimerange"
:default-time="defaultTimeRange"
value-format="YYYY-MM-DD HH:mm:ss"
range-separator="-"
start-placeholder="开始日期"
end-placeholder="结束日期"
:disabled-date="disabledDate"
@calendar-change="calendarChange"
:clearable="true"
/>
function calendarChange(e) {
state.minDate = e[0].getTime();
}
//时间筛选范围一个月
function disabledDate(time) {
return (
time.getTime() <= moment(state.minDate).subtract(6, 'month').valueOf() ||
time.getTime() >= moment(state.minDate).add(6, 'month').valueOf()
);
}
- 居中布局
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
- 自定义指令
export default function (app) {
app.directive("special-chars", {
mounted(el, binding, vnode) {
el.addEventListener("input", function (event) {
// 获取输入的值
const value = event.target.value;
// 使用正则表达式检测反斜杠(根据需要匹配相应限制字符)
const regex =
/[`~!@#$%^&*()_\-+=<>?:"{}|,./;'\\[\]·~!@#¥%……&*()——\-+={}|《》?:“”【】、;‘’,。、]/g;
// 如果输入值包含反斜杠,则替换为空格
if (regex.test(value)) {
// 使用 replace 方法替换反斜杠为空格
const newValue = value.replace(regex, "");
// 将新值设置回输入框
event.target.value = newValue;
// 触发 @input 事件,使其更新组件中的数据
// vnode.componentInstance.$emit("input", newValue);
// 触发input事件来更新绑定的v-model值
el.dispatchEvent(new Event("input", { bubbles: true }));
}
});
},
unmounted(el) {
el.removeEventListener('input');
}
});
}
- 下载通知
// 下载视频
downLoad(item, tab) {
this.downLoadIndex++
const notify = this.$notify({
title: 'Work start download',
message: `<div id='notify-${this.downLoadIndex}'>The video is downloading, progress is 0%, please wait</div>`,
dangerouslyUseHTMLString: true,
type: 'success',
duration: 0,
})
this.downLoadFile(item, this.downLoadIndex, tab)
.then(() => {
notify.close()
this.$notify({
title: 'Work download completed',
type: 'success',
duration: 3000,
})
})
.catch(() => {
notify.close()
this.$notify({
title: 'Work download failed',
type: 'error',
duration: 3000,
})
})
},
downLoadFile(item, index, tab) {
let url = ''
if (tab == 'avatar') {
url = item.audioUrl
} else {
url = item.videoUrl
}
let name = item.workName + '_Anylang-ai'
return new Promise((resolve, reject) => {
const xhr = new XMLHttpRequest()
xhr.open('GET', url, true)
xhr.send()
xhr.responseType = 'blob'
xhr.addEventListener('progress', (ev) => {
const percent = parseInt((ev.loaded / ev.total) * 100)
const dom = document.getElementById(`notify-${index}`)
dom.innerText = `The video is downloading, progress is ${percent}%, please wait`
})
xhr.onload = (ev) => {
if (xhr.status == 200) {
const urlx = window.URL.createObjectURL(xhr.response)
const dom = document.createElement('a')
dom.href = urlx
dom.download = name
dom.click()
URL.revokeObjectURL(dom.href)
resolve()
} else if (response.status == 404) {
reject()
} else if (response.status == 500) {
reject()
}
}
})
},
- 分享一些::after和::before使用的经验
&:before画圆
<template>
<div>
<div class="title">今日新增量</div >
<div/>
<template>
<style>
title {
position: relative;
&:before {
// top: 5px;
// left: -15px;
position: absolute;
display: block;
width: 10px;
height: 10px;
border-radius: 50%;
background: #fa6861;
content: '';
}
}
<style/>
&:before竖条
<template>
<div>
<div class="title">前面加个竖条</div >
<div/>
<template>
<style>
.title {
position: relative;
&:before {
top: 25px;
left: 80px;
position: absolute;
display: block;
width: 6px;
height: 30px;
background: #4d99f9;
content: '';
}
}
<style/>
&:before插入图片
<template>
<div>
<div class="title">前面加个图片</div >
<div/>
<template>
<style>
.title {
position: relative;
&:before {
content: '';
position: absolute;
left: 75px;
top: 26px;
height: 28px;
width: 12px;
background: url('~@/assets/images/second-title.png') no-repeat;
background-size: 100% 100%;
}
}
<style/>
- 一行文字过多时,省略号隐藏显示
1.页面部分
<el-row>
<el-col :span="24">
<div class="information-title">
一行文字过多时,隐藏省略显示;一行文字过多时,隐藏省略显示;一行文字过多时,隐藏省略显示;
一行文字过多时,隐藏省略显示;一行文字过多时,隐藏省略显示;一行文字过多时,隐藏省略显示;
一行文字过多时,隐藏省略显示;一行文字过多时,隐藏省略显示;一行文字过多时,隐藏省略显示;
</div>
</el-col>
</el-row>
2.css样式部分
.information-title {
color: #19d3ea;
font-size: 18px;
width: 100%; /*一定要设置宽度,或者元素内含的百分比*/
overflow:hidden; /*溢出的部分隐藏*/
white-space: nowrap; /*文本不换行*/
text-overflow:ellipsis;/*ellipsis:文本溢出显示省略号(...);clip:不显示省略标记(...),而是简单的裁切*/
- 防止被压缩
flex-shrink: 0;
- vue3 使用类似
.sync
的功能:
// 父组件
<child-modal v-model:visible="visible"></child-modal>
// 子组件
<template>
<a-modal v-model:visible="show" title="Basic Modal" @ok="handleOk">
<p>Some contents...</p>
<p>Some contents...</p>
<p>Some contents...</p>
</a-modal>
</template>
<script setup>
import { computed, defineProps, defineEmits} from 'vue'
const props = defineProps({
visible: {
type: Boolean,
default: false,
},
})
const $emit = defineEmits(['update:visible'])
const show = computed({
get() {
return props.visible
},
set(v) {
$emit('update:visible', v)
},
})
const handleOk = e => {
console.log(e)
show.value = false
}
</script>
- Promise
Promise有三种状态,分别是“待定”、“已完成”和“已拒绝”。当一个Promise被创建时,它处于“待定”状态。当操作成功完成时,Promise进入“已完成”状态,并返回一个包含操作结果的值。当操作失败时,Promise进入“已拒绝”状态,并返回一个包含错误信息的原因。
Promise可以链式调用,这使得它们可以更方便地组合异步操作。Promise还可以通过catch()方法来处理错误,这使得代码的错误处理更加容易。
链式调用(实现同步操作):
下面直接return值,是因为Promise会自动用Promise包裹
image.png
-
列表网格排列:
image.png
-
更新列表item数据,无法响应问题,以下两种方式都可以 https://blog.csdn.net/qq_26780317/article/details/120130388
image.png 进度条随机值
// 进度条随机值
addIntervalProgress() {
//取[10, 20]之间的随机整数
this.currentProgress = Math.floor(Math.random() * (20 - 10 + 1)) + 10;
// console.log("1111 ---- ", this.currentProgress);
let timer = setInterval(() => {
this.currentProgress += Math.floor(Math.random() * 5);
// console.log("2222 ---- ", this.currentProgress);
if (this.currentProgress > 99) {
this.currentProgress = 99;
clearInterval(timer);
}
}, 100);
},
H5 播放rtsp视频流
前段目前不支持直接播放这种格式,一般都是通过把rtsp擦、转成前段支持的格式
1、https://cloud.tencent.com/developer/article/1805057
VLC是一个不错的Chrome播放rtsp视频流方案,延迟低,性能稳定。但是从2015年以后,Chrome等浏览器取消对NPAPI支持后,VLC就不能直接使用了mac可以用node.js的多版本管理器n来升级和切换,命令如下:
1、sudo npm cache clean -f //清除node.js的cache
2、sudo npm install -g n //使用npm安装n模块
3、npm view node versions // 查看node所有版本
4、sudo n latest // 升级到最新版本
sudo n stable // 升级到稳定版本
sudo n xx.xx // 升级到具体版本号
5、node -v //查看当前安装的版本号
6、n //检查目前安装了哪些版本的node,会出现已安装的node版本,选一个就可以直接切换了