1.智能设备 在线人员添加广播功能(聊天框);2.首页人员概况接口更改
This commit is contained in:
parent
8bc763406f
commit
09d08d49ae
@ -29,6 +29,10 @@ export const getCompanyDataList = (params: {}) => {
|
||||
export const getPersonTypeAndEduStatisticsApi = (params: {}) => {
|
||||
return http.post(BASEURL + `/xmgl/workerInfo/selectPersonTypeAndEduStatistics`, params, { headers: { noLoading: true } });
|
||||
};
|
||||
//查询人员人数-新
|
||||
export const getWorkerByNatureApi = (params: {}) => {
|
||||
return http.post(BASEURL + `/xmgl/workerInfo/getWorkerByNature`, params, { headers: { noLoading: true } });
|
||||
};
|
||||
//查询今日作业人员趋势
|
||||
export const getQueryTodayAttendanceTrendApi = (params: {}) => {
|
||||
return http.get(BASEURL + `/xmgl/workerAttendance/queryTodayAttendanceTrend`, params, { headers: { noLoading: true } });
|
||||
|
||||
@ -92,3 +92,15 @@ export const addSafeHatPositionFence = (params: {}) => {
|
||||
export const getSafeyHatSessionApi = (params: {}) => {
|
||||
return http.post(BASEURL + `/xmgl/projectApi/getSafeyHatSession`, params);
|
||||
};
|
||||
|
||||
// 查询历史记录
|
||||
export const getTaskMessageRecordApi = (params: {}) => {
|
||||
return http.post(BASEURL + `/xmgl/task/messageRecord`, params, {
|
||||
headers: { noLoading: true }
|
||||
});
|
||||
};
|
||||
|
||||
// 文字转语音并发送
|
||||
export const getTaskTextToAudioApi = (params: {}) => {
|
||||
return http.post(BASEURL + `/xmgl/task/textToAudio`, params);
|
||||
};
|
||||
|
||||
BIN
src/assets/images/broadcast.png
Normal file
BIN
src/assets/images/broadcast.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 493 B |
@ -20,11 +20,21 @@
|
||||
<div class="bottomPeopleNum">
|
||||
<div style="display: flex; margin-left: 2%">
|
||||
<div style="width: 5px; height: 5px; background: rgba(130, 251, 234, 1); border-radius: 10px; margin: 2%"></div>
|
||||
<div><i>管理人员</i></div>
|
||||
<div><i>人员数量</i></div>
|
||||
</div>
|
||||
<div class="peopleData">
|
||||
<div class="peoImg"><img src="@/assets/images/comprehensiveManage/project3.png" alt="" /></div>
|
||||
<div class="peoNum">
|
||||
<div class="penName"></div>
|
||||
<div class="penN"></div>
|
||||
<div class="numData" v-for="item in personalList" :key="item.name">
|
||||
<div class="text"><i>{{ item.name }}</i></div>
|
||||
<div class="num">
|
||||
<i style="color: #eea959">{{ item.num }}</i>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- <div class="peoNum">
|
||||
<div class="penName"></div>
|
||||
<div class="penN"></div>
|
||||
<div class="numData1 numData">
|
||||
@ -56,7 +66,7 @@
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div> -->
|
||||
</div>
|
||||
</div>
|
||||
</Card>
|
||||
@ -68,7 +78,7 @@ import Card from "@/components/card.vue";
|
||||
import { GlobalStore } from "@/stores";
|
||||
import { COMPANY } from "@/config/config";
|
||||
import { ref, onMounted, watch } from "vue";
|
||||
import { getPersonTypeAndEduStatisticsApi } from "@/api/modules/labor";
|
||||
import { getPersonTypeAndEduStatisticsApi, getWorkerByNatureApi } from "@/api/modules/labor";
|
||||
const store = GlobalStore();
|
||||
// ts
|
||||
type Props = {
|
||||
@ -84,6 +94,8 @@ const statisticsCount = ref({
|
||||
presencecount: {}
|
||||
} as any);
|
||||
|
||||
const personalList = ref([]);
|
||||
|
||||
watch(
|
||||
() => props.statisticsCount,
|
||||
newVal => {
|
||||
@ -99,15 +111,21 @@ const attendancePerson = ref(0)
|
||||
const toaltPerson = ref(0)
|
||||
//获取人员数据
|
||||
const getPersonList = async () => {
|
||||
const res = await getPersonTypeAndEduStatisticsApi({
|
||||
// const res = await getPersonTypeAndEduStatisticsApi({
|
||||
// projectSn: store.sn
|
||||
// });
|
||||
// if (res.result) {
|
||||
// console.log("+++++++++++++++++++++++++++++++++")
|
||||
// console.log(res)
|
||||
// presencePerson.value = res.result.personType.presencePerson;
|
||||
// attendancePerson.value = res.result.personType.attendancePerson;
|
||||
// toaltPerson.value = res.result.personType.toaltPerson;
|
||||
// }
|
||||
const res = await getWorkerByNatureApi({
|
||||
projectSn: store.sn
|
||||
});
|
||||
if (res.result) {
|
||||
console.log("+++++++++++++++++++++++++++++++++")
|
||||
console.log(res)
|
||||
presencePerson.value = res.result.personType.presencePerson;
|
||||
attendancePerson.value = res.result.personType.attendancePerson;
|
||||
toaltPerson.value = res.result.personType.toaltPerson;
|
||||
personalList.value = res.result || [];
|
||||
}
|
||||
};
|
||||
onMounted( async () => {
|
||||
@ -175,15 +193,22 @@ onMounted( async () => {
|
||||
height: 100%;
|
||||
width: 70%;
|
||||
position: relative;
|
||||
display: flex;
|
||||
.penName {
|
||||
background: rgba(39, 88, 192, 0.6);
|
||||
margin: 5% 5%;
|
||||
margin: 6% 5%;
|
||||
width: 90%;
|
||||
position: absolute;
|
||||
z-index: 0;
|
||||
}
|
||||
.penN {
|
||||
height: 10px;
|
||||
background: url("@/assets/images/comprehensiveManage/project8.png") no-repeat;
|
||||
background-size: 100% 100%;
|
||||
margin: 13% 5%;
|
||||
margin: 0 5%;
|
||||
margin-top: 24%;
|
||||
width: 90%;
|
||||
position: absolute;
|
||||
}
|
||||
.numData1 {
|
||||
left: 5%;
|
||||
@ -198,15 +223,18 @@ onMounted( async () => {
|
||||
top: -10%;
|
||||
}
|
||||
.numData {
|
||||
position: absolute;
|
||||
// position: absolute;
|
||||
height: 60%;
|
||||
width: 30%;
|
||||
// width: 30%;
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
.text {
|
||||
margin-top: 18%;
|
||||
margin-top: 15%;
|
||||
color: #fff;
|
||||
font-size: 16px;
|
||||
z-index: 1;
|
||||
}
|
||||
.num {
|
||||
font-size: 20px;
|
||||
|
||||
@ -60,16 +60,25 @@
|
||||
label: 'name'
|
||||
}"
|
||||
show-checkbox
|
||||
check-on-click-node
|
||||
default-expand-all
|
||||
node-key="devSn"
|
||||
ref="tree"
|
||||
>
|
||||
<!-- check-on-click-node -->
|
||||
<template #default="{ node, data }">
|
||||
<span class="custom-tree-node">
|
||||
<img :src="personOn" v-if="data.online === 1" />
|
||||
<img :src="personOff" v-if="data.online === 0" />
|
||||
<span class="nodeName">{{ node.label }}</span>
|
||||
<img
|
||||
class="icon"
|
||||
v-if="data.online === 1 && data.extUserId"
|
||||
@click="handleBroadcast(data)"
|
||||
src="@/assets/images/broadcast.png"
|
||||
/>
|
||||
<!-- <el-icon class="icon" v-if="laborType === 1 && data.extUserId" @click="handleBroadcast(data)"
|
||||
><BellFilled
|
||||
/></el-icon> -->
|
||||
</span>
|
||||
</template>
|
||||
</el-tree>
|
||||
@ -93,7 +102,7 @@
|
||||
<el-form :inline="true" size="medium" :model="queryInfo" class="demo-form-inline">
|
||||
<el-form-item>
|
||||
<span style="color: #fff; margin-left: 25px; margin-right: 10px">人员名称</span>
|
||||
<el-select filterable v-model="queryInfo.devSn" placeholder="请选择或搜索" @change="devChange" clearable>
|
||||
<el-select filterable v-model="queryInfo.devSn" placeholder="请选择或搜索" @change="devChange">
|
||||
<el-option
|
||||
v-for="(item, index) in nameOptions"
|
||||
:key="index"
|
||||
@ -106,7 +115,17 @@
|
||||
</el-form>
|
||||
</div>
|
||||
<div class="track-calendar">
|
||||
<el-calendar v-model="dayValue" class="custom-hover">
|
||||
<el-calendar v-model="dayValue" class="custom-hover" ref="calendar">
|
||||
<template #header="{ date }">
|
||||
<span>{{ date }}</span>
|
||||
<el-button-group>
|
||||
<el-button size="small" @click="selectDate('prev-month')"> 上个月 </el-button>
|
||||
<el-button size="small" @click="selectDate('today')">今天</el-button>
|
||||
<el-button size="small" :disabled="isDisabledNextMount" @click="selectDate('next-month')">
|
||||
下个月
|
||||
</el-button>
|
||||
</el-button-group>
|
||||
</template>
|
||||
<template #dateCell="{ data }">
|
||||
<!-- <span>{{ dealMyDate(data.day, data) }}</span> -->
|
||||
<div :class="data.styleFlag == true ? 'preventClick' : ''" style="font-size: 14px">
|
||||
@ -427,10 +446,55 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="custom-dialog">
|
||||
<el-dialog
|
||||
:modal-append-to-body="false"
|
||||
:close-on-click-modal="false"
|
||||
:close-on-press-escape="false"
|
||||
title="广播内容"
|
||||
v-model="dialogVisible"
|
||||
width="667px"
|
||||
>
|
||||
<el-scrollbar style="height: 500px" ref="refScrollbar">
|
||||
<div class="items" ref="innerRef">
|
||||
<div :class="{ item: true, i_right: sendItYourself(item) }" v-for="item in messageList" :key="item.ctime">
|
||||
<!-- <img src="@/assets/images/profile_photo.png" alt="" /> -->
|
||||
<el-icon size="32"><UserFilled /></el-icon>
|
||||
<div class="c_right">
|
||||
<div class="info">
|
||||
<div class="name">{{ item.send_user_name }}</div>
|
||||
<div class="time">{{ dateFormat(item.ctime) }}</div>
|
||||
</div>
|
||||
<div
|
||||
:class="{ 'box-warp': true, animation: currentPlayVideo == item.ctime }"
|
||||
:style="{ width: Number(item.length) * 2 + 80 + 'px' }"
|
||||
@click="playAudio(item)"
|
||||
>
|
||||
<div class="wifi-symbol">
|
||||
<div class="wifi-circle first"></div>
|
||||
<div class="wifi-circle second"></div>
|
||||
<div class="wifi-circle third"></div>
|
||||
</div>
|
||||
<span class="audio-length"> {{ item.length == 0 ? 1 : item.length }}" </span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="message_no_data" v-if="!messageList.length">
|
||||
<img src="@/assets/images/notoDataImg.png" />
|
||||
</div>
|
||||
</el-scrollbar>
|
||||
<div class="message_go">
|
||||
<el-input ref="messageIptRef" v-model="messageText" type="textarea" :rows="5" />
|
||||
<el-button class="send_btn" type="primary" @click="sendMessage">发送</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import moment from "moment";
|
||||
// import { getWorkerInfoList } from "@/assets/js/api/laborPerson";
|
||||
import {
|
||||
getAlarmRecordInfoApi,
|
||||
@ -453,7 +517,9 @@ import {
|
||||
getSafeHatTypeTotalApi,
|
||||
getVehiclePositionFence,
|
||||
addVehiclePositionFence,
|
||||
getRegionListApi
|
||||
getRegionListApi,
|
||||
getTaskMessageRecordApi,
|
||||
getTaskTextToAudioApi
|
||||
} from "@/api/modules/smartSafeHat";
|
||||
// import carIcon from "@/assets/images/carPosition/carIcon.png";
|
||||
import carOn from "@/assets/images/carPosition/carOn2.png";
|
||||
@ -465,6 +531,7 @@ import startIcon from "@/assets/images/carPosition/startIcon.png";
|
||||
import endIcon from "@/assets/images/carPosition/endIcon.png";
|
||||
import personOn from "@/assets/images/carPosition/personOn.png";
|
||||
import { GlobalStore } from "@/stores";
|
||||
import { UserFilled, BellFilled } from "@element-plus/icons-vue";
|
||||
import { ElMessage, ElMessageBox } from "element-plus";
|
||||
import type { FormInstance, FormRules } from "element-plus";
|
||||
import Card from "@/components/card.vue";
|
||||
@ -501,6 +568,19 @@ let isIndeterminateFence = ref(true);
|
||||
let checked = ref(1);
|
||||
let devName = ref("");
|
||||
let locationList = ref([]);
|
||||
|
||||
const calendar = ref(null);
|
||||
const refScrollbar = ref(null);
|
||||
const innerRef = ref(null);
|
||||
const messageIptRef = ref(null);
|
||||
|
||||
const userId = ref(0);
|
||||
const dialogVisible = ref(false);
|
||||
const messageList = ref([]);
|
||||
const messageText = ref("");
|
||||
const currentPlayVideo = ref("");
|
||||
const audioDOM = ref(null);
|
||||
|
||||
interface RuleForm {
|
||||
// fenceName: string
|
||||
// areaRadius: number
|
||||
@ -622,6 +702,84 @@ onMounted(async () => {
|
||||
});
|
||||
getRegionList();
|
||||
});
|
||||
|
||||
const selectDate = val => {
|
||||
if (!calendar.value) return;
|
||||
calendar.value.selectDate(val);
|
||||
};
|
||||
|
||||
const dateFormat = date => {
|
||||
return moment.unix(date).format("YYYY-MM-DD HH:mm:ss");
|
||||
};
|
||||
const handleBroadcast = async data => {
|
||||
userId.value = data.extUserId;
|
||||
await getTaskMessageRecord();
|
||||
dialogVisible.value = true;
|
||||
setTimeout(() => {
|
||||
messageIptRef.value?.focus();
|
||||
}, 10);
|
||||
};
|
||||
|
||||
const getTaskMessageRecord = async () => {
|
||||
const res = await getTaskMessageRecordApi({
|
||||
projectSn: store.sn,
|
||||
userId: userId.value
|
||||
});
|
||||
if (res.code === 200) {
|
||||
messageList.value = res.result || [];
|
||||
messageList.value = messageList.value.reverse();
|
||||
}
|
||||
// 设置滚动条到最底部
|
||||
setTimeout(function () {
|
||||
refScrollbar.value!.setScrollTop(innerRef.value!.clientHeight);
|
||||
}, 10);
|
||||
};
|
||||
|
||||
const sendMessage = async () => {
|
||||
await getTaskTextToAudioApi({
|
||||
content: messageText.value,
|
||||
projectSn: store.sn,
|
||||
userId: userId.value
|
||||
});
|
||||
setTimeout(() => {
|
||||
messageText.value = "";
|
||||
getTaskMessageRecord();
|
||||
}, 100);
|
||||
setTimeout(() => {
|
||||
ElMessage.success("发送成功");
|
||||
}, 200);
|
||||
};
|
||||
const playAudio = item => {
|
||||
let audio = audioDOM.value;
|
||||
if (audio != null) {
|
||||
if (currentPlayVideo.value == item.ctime) {
|
||||
audio.pause();
|
||||
currentPlayVideo.value = -1;
|
||||
return;
|
||||
}
|
||||
audio.pause();
|
||||
} else {
|
||||
audio = document.createElement("audio");
|
||||
audioDOM.value = audio;
|
||||
}
|
||||
audio.src = item.url;
|
||||
audio.onload = function () {
|
||||
audio.play();
|
||||
};
|
||||
audio.play();
|
||||
currentPlayVideo.value = item.ctime;
|
||||
audio.addEventListener(
|
||||
"ended",
|
||||
function () {
|
||||
currentPlayVideo.value = -1;
|
||||
},
|
||||
false
|
||||
);
|
||||
};
|
||||
const sendItYourself = item => {
|
||||
return item.send_user_name == "ZMML30";
|
||||
};
|
||||
|
||||
const resetMapSize = () => {
|
||||
console.log(666);
|
||||
setTimeout(() => {
|
||||
@ -636,6 +794,13 @@ onBeforeMount(() => {
|
||||
});
|
||||
});
|
||||
|
||||
// 是否禁用下个月按钮
|
||||
const isDisabledNextMount = computed(() => {
|
||||
const curMonth = formatMonthTime(new Date());
|
||||
const checkedMount = formatMonthTime(dayValue.value);
|
||||
return curMonth <= checkedMount;
|
||||
});
|
||||
|
||||
watch(dayValue, newVal => {
|
||||
// console.log(newVal, "切换日期");
|
||||
if (newVal) {
|
||||
@ -744,14 +909,16 @@ function areaRadiusChange() {
|
||||
}
|
||||
}
|
||||
function latLongChange() {
|
||||
console.info('change', addForm.value.lngLat)
|
||||
let lng = addForm.value.lngLat.split(',')[0]
|
||||
let lat = addForm.value.lngLat.split(',')[1]
|
||||
console.info("change", addForm.value.lngLat);
|
||||
let lng = addForm.value.lngLat.split(",")[0];
|
||||
let lat = addForm.value.lngLat.split(",")[1];
|
||||
if (lng && lat) {
|
||||
locationList.value = [{
|
||||
longitude: lng,
|
||||
latitude: lat
|
||||
}]
|
||||
locationList.value = [
|
||||
{
|
||||
longitude: lng,
|
||||
latitude: lat
|
||||
}
|
||||
];
|
||||
drawCircle();
|
||||
} else {
|
||||
ElMessage({
|
||||
@ -1410,7 +1577,6 @@ function pointSelectChange() {
|
||||
console.log("当前devSn", alarmDevSn.value);
|
||||
getProgressListData();
|
||||
}
|
||||
|
||||
function fenceAllChange(val) {
|
||||
clearFn();
|
||||
let nameArr = fenceList.value.map(item => item.id);
|
||||
@ -1708,10 +1874,12 @@ function initMap() {
|
||||
}
|
||||
console.log("您在 [ " + e.lnglat.getLng() + "," + e.lnglat.getLat() + " ] 的位置单击了地图!");
|
||||
if (addForm.value.rangeType == 1) {
|
||||
locationList.value = [{
|
||||
longitude: e.lnglat.getLng(),
|
||||
latitude: e.lnglat.getLat()
|
||||
}];
|
||||
locationList.value = [
|
||||
{
|
||||
longitude: e.lnglat.getLng(),
|
||||
latitude: e.lnglat.getLat()
|
||||
}
|
||||
];
|
||||
addForm.value.lngLat = e.lnglat.getLng() + "," + e.lnglat.getLat();
|
||||
var lnglatXY = new AMap.LngLat(e.lnglat.getLng(), e.lnglat.getLat());
|
||||
geocoder.getAddress(lnglatXY, function (status, result) {
|
||||
@ -3169,11 +3337,20 @@ function echoPersonMarker(item) {
|
||||
}
|
||||
.custom-tree-node {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
img {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
margin-right: 4px;
|
||||
}
|
||||
.nodeName {
|
||||
flex: 1;
|
||||
}
|
||||
.icon {
|
||||
margin: 0 12px;
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
.nodeName {
|
||||
overflow: hidden;
|
||||
@ -3182,4 +3359,182 @@ function echoPersonMarker(item) {
|
||||
display: inline-block;
|
||||
color: #fff;
|
||||
}
|
||||
.items {
|
||||
width: 100%;
|
||||
overflow: hidden;
|
||||
padding: 0 24px;
|
||||
box-sizing: border-box;
|
||||
.item {
|
||||
width: 100%;
|
||||
min-height: 40px;
|
||||
height: auto;
|
||||
font-size: 16px;
|
||||
display: flex;
|
||||
text-align: left;
|
||||
margin: 8px 0;
|
||||
&.i_right {
|
||||
flex-flow: row-reverse;
|
||||
.c_right {
|
||||
align-items: flex-end;
|
||||
.info {
|
||||
flex-flow: row-reverse;
|
||||
}
|
||||
.box-warp {
|
||||
background: #95ec69;
|
||||
justify-content: flex-end;
|
||||
&:hover {
|
||||
background: #89d961;
|
||||
}
|
||||
.wifi-symbol {
|
||||
transform: rotate(-45deg);
|
||||
}
|
||||
.audio-length {
|
||||
right: 50px;
|
||||
left: auto;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
img {
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
object-fit: cover;
|
||||
border-radius: 50%;
|
||||
}
|
||||
.c_right {
|
||||
width: calc(100% - 40px);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
.info {
|
||||
display: flex;
|
||||
align-items: flex-end;
|
||||
.name {
|
||||
margin-left: 12px;
|
||||
margin-right: 5px;
|
||||
font-size: 20px;
|
||||
color: #333;
|
||||
}
|
||||
.time {
|
||||
font-size: 14px;
|
||||
color: #999;
|
||||
}
|
||||
}
|
||||
.text {
|
||||
font-size: 14px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.message_go {
|
||||
width: 100%;
|
||||
height: 146px;
|
||||
border-top: 1px solid #e7e7e7;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
flex-direction: column;
|
||||
margin-top: 20px;
|
||||
position: relative;
|
||||
.send_btn {
|
||||
position: absolute;
|
||||
right: 24px;
|
||||
bottom: 12px;
|
||||
}
|
||||
}
|
||||
.custom-dialog {
|
||||
:deep(.el-dialog__body) {
|
||||
padding: 0 !important;
|
||||
border-top: 1px solid #e7e7e7;
|
||||
}
|
||||
:deep(.el-textarea__inner) {
|
||||
box-shadow: none;
|
||||
resize: none;
|
||||
}
|
||||
}
|
||||
.box-warp {
|
||||
background: #f5f5f5;
|
||||
border-radius: 6px;
|
||||
height: 40px;
|
||||
margin: 6px 12px;
|
||||
cursor: pointer;
|
||||
position: relative;
|
||||
display: flex;
|
||||
&:hover {
|
||||
background: #ebebeb;
|
||||
}
|
||||
.audio-length {
|
||||
font-size: 14px;
|
||||
line-height: 24px;
|
||||
white-space: nowrap;
|
||||
position: absolute;
|
||||
left: 50px;
|
||||
top: 8px;
|
||||
}
|
||||
}
|
||||
.wifi-symbol {
|
||||
margin: 0 20px;
|
||||
width: 38px;
|
||||
height: 38px;
|
||||
box-sizing: border-box;
|
||||
overflow: hidden;
|
||||
transform: rotate(135deg);
|
||||
position: relative;
|
||||
}
|
||||
.wifi-circle {
|
||||
border: 4px solid #828487;
|
||||
border-radius: 999px;
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
.first {
|
||||
width: 5px;
|
||||
height: 5px;
|
||||
background: #828487;
|
||||
top: 32px;
|
||||
left: 32px;
|
||||
}
|
||||
|
||||
.second {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
top: 25px;
|
||||
left: 25px;
|
||||
}
|
||||
|
||||
.third {
|
||||
width: 26px;
|
||||
height: 26px;
|
||||
top: 18px;
|
||||
left: 18px;
|
||||
}
|
||||
|
||||
.animation .second {
|
||||
animation: fadeInOut 1s infinite 0.2s;
|
||||
}
|
||||
|
||||
.animation .third {
|
||||
animation: fadeInOut 1s infinite 0.4s;
|
||||
}
|
||||
|
||||
@keyframes fadeInOut {
|
||||
0% {
|
||||
opacity: 0; /*初始状态 透明度为0*/
|
||||
}
|
||||
100% {
|
||||
opacity: 1; /*结尾状态 透明度为1*/
|
||||
}
|
||||
}
|
||||
.message_no_data {
|
||||
width: 100%;
|
||||
height: 500px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
flex-direction: column;
|
||||
img {
|
||||
width: 208px;
|
||||
height: 208px;
|
||||
-webkit-user-drag: none;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user