feat: 添加人员总览弹窗以及AI预警页面修改
This commit is contained in:
parent
e8b9db8c66
commit
d6350419f2
@ -26,7 +26,7 @@ export const staticRouter: RouteRecordRaw[] = [
|
||||
name: "大屏",
|
||||
// component: () => import("@/views/sevenLargeScreen/indexL.vue"), //七参数标准版
|
||||
component: () => import("@/views/commandScreen/indexCommand.vue"), //指挥部大屏
|
||||
component: () => import("@/views/agjtLiveScreen/indexLive.vue"), //鞍钢现场大屏
|
||||
// component: () => import("@/views/agjtLiveScreen/indexLive.vue"), //鞍钢现场大屏
|
||||
// component: () => import("@/views/overviewScreen/indexCommand.vue"), //总览大屏
|
||||
// component: () => import("@/views/agjtProjectKanban/indexL.vue"), //鞍钢集团项目看板大屏
|
||||
// component: () => import("@/views/sevenLargeScreen/indexL_syhy.vue"), // 只有一级路由(盘锦、嘉兴、鄱湖美湾医疗项目需切换至该首页)
|
||||
|
||||
@ -80,7 +80,7 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="classify-div">
|
||||
<div class="classify-div-item" @click="openDialogData({ index: 98, title: '人员总览' })">
|
||||
<div class="classify-div-item" @click="openDialogData({ index: 12, title: '人员总览', type: 2 })">
|
||||
<span style="font-size: 12px">人员总览</span>
|
||||
</div>
|
||||
<div class="classify-div-item" style="width: 250px" @click="openDialogData({ index: 1, title: '' })">
|
||||
@ -93,19 +93,13 @@
|
||||
<span style="font-size: 12px">影响进度计划因素 {{ statsDirectorateBigScreen.taskProgressContentNum }}</span>
|
||||
</div>
|
||||
<div class="classify-div-item" @click="openDialogData({ index: 4, title: '风险统计' })">
|
||||
<span style="font-size: 12px"
|
||||
>风险统计 {{ statsDirectorateBigScreen.securityQualityInspectionRecordNum }}</span
|
||||
>
|
||||
<span style="font-size: 12px">风险统计 {{ statsDirectorateBigScreen.securityQualityInspectionRecordNum }}</span>
|
||||
</div>
|
||||
<div class="classify-div-item" @click="openDialogData({ index: 5, title: '安全隐患' })">
|
||||
<span style="font-size: 12px"
|
||||
>安全隐患 {{ statsDirectorateBigScreen.securityQualityInspectionRecordNum }}</span
|
||||
>
|
||||
<span style="font-size: 12px">安全隐患 {{ statsDirectorateBigScreen.securityQualityInspectionRecordNum }}</span>
|
||||
</div>
|
||||
<div class="classify-div-item" @click="openDialogData({ index: 99, title: '质量管理' })">
|
||||
<span style="font-size: 12px"
|
||||
>质量管理 {{ statsDirectorateBigScreen.securityQualityInspectionRecordNum }}</span
|
||||
>
|
||||
<span style="font-size: 12px">质量管理 {{ statsDirectorateBigScreen.securityQualityInspectionRecordNum }}</span>
|
||||
</div>
|
||||
<div class="classify-div-item" @click="openDialogData({ index: 6, title: 'AI警报' })">
|
||||
<span style="font-size: 12px">AI警报 {{ statsDirectorateBigScreen.aiAnalyseHardWareAlarmRecordNum }}</span>
|
||||
|
||||
@ -327,6 +327,7 @@ const handleTab = (val: number) => {
|
||||
activeIfo.activeIndex = val;
|
||||
queryAttendanceOfEachCompany(false);
|
||||
} else if (activeIfo.activeIndex == 0) {
|
||||
activeIfo.activeIndex = val;
|
||||
getWorkerRiskByProject(false, 1);
|
||||
}
|
||||
};
|
||||
@ -546,7 +547,7 @@ const getWorkerRiskByProject = async (showLoading: boolean, val: number) => {
|
||||
];
|
||||
randerInfo.titleInfo.percentage = res.result.area;
|
||||
}
|
||||
activeIfo.activeIndex = val;
|
||||
// activeIfo.activeIndex = val;
|
||||
};
|
||||
|
||||
const setIntervalFn = (showLoading: boolean) => {
|
||||
|
||||
@ -3,22 +3,35 @@
|
||||
<div class="content">
|
||||
<!-- v-show="topDangerList.length > 0" -->
|
||||
<div class="top-statistics" v-show="topDangerList.length > 0">
|
||||
<el-scrollbar class="statistics-listBox" ref="refAlarmScrollbar">
|
||||
<div
|
||||
class="statistics-item"
|
||||
<div class="top-statistics-left">
|
||||
<el-scrollbar class="statistics-listBox" ref="refAlarmScrollbar">
|
||||
<div
|
||||
class="statistics-item"
|
||||
:style="{
|
||||
background: `url(${bgImgSet(index)}) no-repeat`,
|
||||
backgroundSize: '100% 100%'
|
||||
}"
|
||||
v-for="(item, index) in topDangerList"
|
||||
:key="index"
|
||||
>
|
||||
<span class="title">{{ item.alarmTypeName }}</span>
|
||||
<span class="statistics-item-content">今日报警次数:{{ item.alarmNumToday }}</span>
|
||||
<span class="statistics-item-content">本月报警次数:{{ item.alarmNumMonth }}</span>
|
||||
<span class="statistics-item-content">历史报警次数:{{ item.alarmNum }}</span>
|
||||
</div>
|
||||
</el-scrollbar>
|
||||
</div>
|
||||
<!-- <div class="top-statistics-right">
|
||||
<div>sss</div>
|
||||
播放海康
|
||||
<div ref="playWndBox" style="width: 96%; height: 100%;">
|
||||
<div id="playWnd" class="playWnd" style="width: 100%; height: 100%"></div>
|
||||
:style="{
|
||||
background: `url(${bgImgSet(index)}) no-repeat`,
|
||||
backgroundSize: '100% 100%'
|
||||
}"
|
||||
v-for="(item, index) in topDangerList"
|
||||
:key="index"
|
||||
>
|
||||
<span class="title">{{ item.alarmTypeName }}</span>
|
||||
<span class="statistics-item-content">今日报警次数:{{ item.alarmNumToday }}</span>
|
||||
<span class="statistics-item-content">本月报警次数:{{ item.alarmNumMonth }}</span>
|
||||
<span class="statistics-item-content">历史报警次数:{{ item.alarmNum }}</span>
|
||||
height: playWndHeight + 'px',
|
||||
width: playWndWidth + 'px'
|
||||
}"
|
||||
</div>
|
||||
</el-scrollbar>
|
||||
</div> -->
|
||||
</div>
|
||||
<div style="position: relative; height: 180px" v-if="topDangerList.length == 0">
|
||||
<div class="notoDta">
|
||||
@ -26,7 +39,31 @@
|
||||
<p>暂无数据</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="top-search">
|
||||
<div class="search-item">
|
||||
<span>设备名称</span>
|
||||
<el-input style="width: 150px;" size="small" v-model="searchForm.hardwareName" placeholder="请输入内容" @input="conditionSearch"></el-input>
|
||||
</div>
|
||||
<div class="search-item">
|
||||
<span>不安全行为类型</span>
|
||||
<el-input style="width: 150px;" size="small" v-model="searchForm.alarmTypeName" placeholder="请输入内容" @input="conditionSearch"></el-input>
|
||||
</div>
|
||||
<div class="search-item">
|
||||
<span>警告时间</span>
|
||||
<el-date-picker
|
||||
style="width: 240px;"
|
||||
size="small"
|
||||
v-model="searchForm.dateRange"
|
||||
type="daterange"
|
||||
range-separator="至"
|
||||
start-placeholder="开始日期"
|
||||
end-placeholder="结束日期"
|
||||
value-format="YYYY-MM-DD"
|
||||
@change="conditionSearch"
|
||||
/>
|
||||
</div>
|
||||
<!-- <el-button @click="getMemberCountList('search')">查询</el-button> -->
|
||||
</div>
|
||||
<div class="table-one">
|
||||
<div class="tabList">
|
||||
<div>序号</div>
|
||||
@ -99,13 +136,14 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { ref, onMounted } from "vue";
|
||||
import { ref, onMounted, onBeforeMount, onBeforeUnmount, getCurrentInstance } from "vue";
|
||||
import { GlobalStore } from "@/stores";
|
||||
import { getCompanyDataList } from "@/api/modules/labor";
|
||||
// import type { TabsPaneContext } from "element-plus";
|
||||
import { getAlarmTypeOption } from "@/api/modules/aIEarlyWarn";
|
||||
import noDataImage from "@/assets/images/vehicleManagement/car.png";
|
||||
import { getAlarmRecordApi, getAlarmTypeCountPageApi } from "@/api/modules/agjtCommandApi";
|
||||
import { ElMessage } from "element-plus";
|
||||
import bgImg1 from "@/assets/images/commandScreen/bg1.png";
|
||||
import bgImg2 from "@/assets/images/commandScreen/bg2.png";
|
||||
import bgImg3 from "@/assets/images/commandScreen/bg3.png";
|
||||
@ -118,6 +156,34 @@ const bgImgList = ref([bgImg1, bgImg2, bgImg3, bgImg4, bgImg5, bgImg6, bgImg7, b
|
||||
const store = GlobalStore();
|
||||
// eslint-disable-next-line vue/require-prop-types, @typescript-eslint/no-unused-vars
|
||||
const props = defineProps(["tip"]);
|
||||
const searchForm = ref({
|
||||
hardwareName: '',
|
||||
alarmTypeName: '',
|
||||
dateRange: [],
|
||||
});
|
||||
const playWndBox = ref(null);
|
||||
let playWndHeight = ref("");
|
||||
let playWndWidth = ref("");
|
||||
let oWebControl = ref(null);
|
||||
let pubKey = ref("");
|
||||
let initCount = ref(0);
|
||||
// const objData = ref({
|
||||
// appkey: "23071374", //海康提供的appkey
|
||||
// ip: "42.180.188.17", //海康提供的ip
|
||||
// secret: "skaSIHSYPRIynnxz7o57", //海康提供的secret
|
||||
// port: 8443,
|
||||
// playMode: 0, // 0 预览 1回放
|
||||
// layout: "1x1" //页面展示的模块数【16】
|
||||
// });
|
||||
let objData = ref({
|
||||
appkey: "23071374", //anjt的appkey
|
||||
ip: "42.180.188.17", //anjt的ip
|
||||
secret: "skaSIHSYPRIynnxz7o57", //anjt的secret
|
||||
port: 8443,//anjt的端口
|
||||
playMode: 0, // 0 预览 1回放
|
||||
layout: "1x1" //页面展示的模块数【16】
|
||||
});
|
||||
let cameraIndexCode = ref<string>("");
|
||||
const BASEURL = import.meta.env.VITE_API_URL;
|
||||
let showDialog = ref(false as any);
|
||||
const enterpriseListData = ref([] as any);
|
||||
@ -133,6 +199,23 @@ const refScrollbar = ref(null as any); // 绑定到滚动的盒子上
|
||||
const detailData = ref({} as any);
|
||||
const partyMemberList = ref({} as any);
|
||||
let aiAlarmTypeEnum = ref([] as any);
|
||||
// 条件查询
|
||||
const conditionSearch = async () => {
|
||||
getMemberCountList('search')
|
||||
}
|
||||
//获取视频列表
|
||||
const getVideoList = async () => {
|
||||
// objData.value.appkey = "23071374";
|
||||
// objData.value.ip = "42.180.188.17";
|
||||
// objData.value.secret = "skaSIHSYPRIynnxz7o57";
|
||||
// objData.value.port = 8443;
|
||||
// cameraIndexCode.value = "210d4649ec0d4e6899b0394e5d8eeec2";
|
||||
// objData.value.appkey = "24017757";
|
||||
// objData.value.ip = "182.101.141.23";
|
||||
// objData.value.secret = "VJz0FbzmE6drPQ7egsBi";
|
||||
// objData.value.port = 18443;
|
||||
// cameraIndexCode.value = "fa34ed90c1564841b14fed388741bbe2";
|
||||
};
|
||||
// 背景图设置
|
||||
const bgImgSet = (index: any) => {
|
||||
return bgImgList.value[index % bgImgList.value.length];
|
||||
@ -204,10 +287,16 @@ const getCompanyList = async () => {
|
||||
const getMemberCountList = async (tip: any) => {
|
||||
let requestData: any = {
|
||||
projectSn: store.sn,
|
||||
hardwareName: searchForm.value.hardwareName,
|
||||
alarmTypeName: searchForm.value.alarmTypeName,
|
||||
pageNo: tip == "search" ? 1 : pageNo.value,
|
||||
pageSize: 100,
|
||||
isPushed: 1
|
||||
};
|
||||
if(searchForm.value.dateRange && searchForm.value.dateRange.length > 0){
|
||||
requestData.startTime = searchForm.value.dateRange[0]
|
||||
requestData.endTime = searchForm.value.dateRange[1]
|
||||
}
|
||||
const res: any = await getAlarmRecordApi(requestData);
|
||||
if (tip == "more") {
|
||||
partyMemberList.value = partyMemberList.value.concat(res.result.records);
|
||||
@ -224,7 +313,9 @@ const getMemberCountList = async (tip: any) => {
|
||||
pageNo.value = pageNo.value + 1;
|
||||
}
|
||||
};
|
||||
|
||||
// onBeforeMount(async () => {
|
||||
// getVideoList();
|
||||
// });
|
||||
onMounted(async () => {
|
||||
await getCompanyList();
|
||||
await getMemberCountList("search");
|
||||
@ -252,7 +343,226 @@ onMounted(async () => {
|
||||
}
|
||||
}
|
||||
});
|
||||
// 加载海康插件
|
||||
// setTimeout(() => {
|
||||
// }, 2500);
|
||||
await initPlugin();
|
||||
// 获取页面的实例对象 ee
|
||||
const pageInstance = getCurrentInstance();
|
||||
// 获取dom节点对象
|
||||
const tagDomObj = pageInstance?.refs.playWndBox;
|
||||
playWndHeight.value = tagDomObj?.clientHeight;
|
||||
playWndWidth.value = tagDomObj?.clientWidth;
|
||||
|
||||
// 监听scroll事件,使插件窗口尺寸跟随DIV窗口变化
|
||||
window.addEventListener("scroll", () => {
|
||||
if (oWebControl.value == undefined) {
|
||||
setTimeout(function () {
|
||||
oWebControl.JS_Resize(playWndWidth.value * store.globalScale, playWndHeight.value * store.globalScale);
|
||||
}, 200);
|
||||
}
|
||||
});
|
||||
|
||||
// 监听resize事件,使插件窗口尺寸跟随DIV窗口变化
|
||||
window.addEventListener("resize", e => {
|
||||
if (oWebControl.value == undefined) {
|
||||
setTimeout(function () {
|
||||
oWebControl.JS_Resize(playWndWidth.value * store.globalScale, playWndHeight.value * store.globalScale);
|
||||
}, 200);
|
||||
}
|
||||
// if (oWebControl.value == undefined) {
|
||||
// // console.log("wwwww", e);
|
||||
// oWebControl.JS_Resize(tagDomObj?.clientWidth, tagDomObj?.clientHeight);
|
||||
// // oWebControl.JS_Resize(playWndHeight.value, playWndWidth.value);
|
||||
// // setWndCover();
|
||||
// }
|
||||
});
|
||||
// previewVideo(cameraIndexCode.value)
|
||||
});
|
||||
onBeforeUnmount(() => {
|
||||
// 先让窗口隐藏,规避可能的插件窗口滞后于浏览器消失问题
|
||||
oWebControl.JS_HideWnd();
|
||||
// 销毁当前播放的视频
|
||||
oWebControl.JS_RequestInterface({ funcName: "destroyWnd" });
|
||||
// 断开与插件服务连接
|
||||
oWebControl.JS_Disconnect();
|
||||
});
|
||||
|
||||
const initPlugin = () => {
|
||||
oWebControl = new WebControl({
|
||||
szPluginContainer: "playWnd", // 指定容器id
|
||||
iServicePortStart: 15900, // 指定起止端口号,建议使用该值
|
||||
iServicePortEnd: 15900,
|
||||
szClassId: "23BF3B0A-2C56-4D97-9C03-0CB103AA8F11", // 用于IE10使用ActiveX的clsid
|
||||
cbConnectSuccess: () => {
|
||||
// 创建WebControl实例成功
|
||||
oWebControl
|
||||
.JS_StartService("window", {
|
||||
// WebControl实例创建成功后需要启动服务
|
||||
// 值"./VideoPluginConnect.dll"写死
|
||||
dllPath: "./VideoPluginConnect.dll"
|
||||
})
|
||||
.then(
|
||||
function () {
|
||||
// 设置消息回调
|
||||
oWebControl.JS_SetWindowControlCallback({
|
||||
// cbIntegrationCallBack: cbIntegrationCallBack,
|
||||
});
|
||||
//JS_CreateWnd创建视频播放窗口,宽高可设定
|
||||
oWebControl
|
||||
.JS_CreateWnd("playWnd", 1000, 600, { bEmbed: true }) //这一部分很重要,两个参数为你盒子的宽高,这样是写死是防止组件加载之前出现白屏;bEmbed: true 防止窗口闪烁
|
||||
.then(function () {
|
||||
// 创建播放实例成功后初始化
|
||||
init();
|
||||
});
|
||||
},
|
||||
function () {
|
||||
// 启动插件服务失败
|
||||
}
|
||||
);
|
||||
},
|
||||
// 创建WebControl实例失败
|
||||
cbConnectError: function () {
|
||||
// 这里写创建WebControl实例失败时的处理步骤,下面的代码仅做参看,具体实现步骤根据个人需求进行编写!!!!!!!!
|
||||
// console.log(0);
|
||||
// oWebControl.value = null;
|
||||
console.log(oWebControl.value);
|
||||
// 程序未启动时执行error函数,采用wakeup来启动程序
|
||||
window.WebControl.JS_WakeUp("VideoWebPlugin://");
|
||||
initCount.value++;
|
||||
if (initCount.value < 3) {
|
||||
setTimeout(function () {
|
||||
initPlugin();
|
||||
}, 3000);
|
||||
}
|
||||
// else {
|
||||
// setTimeout(function () {
|
||||
// setTimeout(function () {
|
||||
// router.push("/home");
|
||||
// }, 4000);
|
||||
// }, 4000);
|
||||
// }
|
||||
if (initCount.value < 2) {
|
||||
oWebControl.value = null;
|
||||
ElMessage.warning("插件未启动,正在尝试启动,请稍候...");
|
||||
// 程序未启动时执行error函数,采用wakeup来启动程序
|
||||
window.WebControl.JS_WakeUp("VideoWebPlugin://");
|
||||
setTimeout(() => {
|
||||
initPlugin();
|
||||
}, 3000);
|
||||
initCount.value++;
|
||||
}
|
||||
// else {
|
||||
// window.location.href = this.videoWebPluginUrl;
|
||||
// }
|
||||
// console.log(oWebControl.value);
|
||||
},
|
||||
cbConnectClose: () => {
|
||||
// 异常断开:bNormalClose = false
|
||||
// JS_Disconnect正常断开:bNormalClose = true
|
||||
// console.log("cbConnectClose");
|
||||
oWebControl.value = null;
|
||||
}
|
||||
});
|
||||
// oWebControl.JS_CuttingPartWindow(500, 500, 500, 500);
|
||||
};
|
||||
|
||||
// 初始化
|
||||
const init = (callback: (() => void) | undefined) => {
|
||||
console.log(objData.value, "我的视频服务器");
|
||||
getPubKey(() => {
|
||||
let appkey = objData.value.appkey; //综合安防管理平台提供的appkey,必填
|
||||
let secret = setEncrypt(objData.value.secret); //综合安防管理平台提供的secret,必填
|
||||
let ip = objData.value.ip; //综合安防管理平台IP地址,必填
|
||||
let playMode = objData.value.playMode; //初始播放模式:0-预览,1-回放
|
||||
let port = objData.value.port; //综合安防管理平台端口,若启用HTTPS协议,默认443
|
||||
let snapDir = "D:\\SnapDir"; //抓图存储路径
|
||||
let videoDir = "D:\\VideoDir"; //紧急录像或录像剪辑存储路径
|
||||
let layout = objData.value.layout; //playMode指定模式的布局
|
||||
let enableHTTPS = 1; //是否启用HTTPS协议与综合安防管理平台交互,这里总是填1
|
||||
let encryptedFields = "secret"; //加密字段,默认加密领域为secret
|
||||
let showToolbar = 1; //是否显示工具栏,0-不显示,非0-显示
|
||||
let showSmart = 0; //是否显示移动框线框,0-不显示,非0-显示
|
||||
let buttonIDs = "0,16,256,257,258,259,260,512,513,514,515,516,517,768,769"; //自定义工具条按钮
|
||||
// var toolBarButtonIDs = "2049,2304" // 工具栏上自定义按钮
|
||||
oWebControl
|
||||
?.JS_RequestInterface({
|
||||
funcName: "init",
|
||||
argument: JSON.stringify({
|
||||
appkey: appkey, //API网关提供的appkey
|
||||
secret: secret, //API网关提供的secret
|
||||
// ip: ip + ":" + port, //API网关IP地址
|
||||
ip: ip, //API网关IP地址
|
||||
playMode: playMode, //播放模式(决定显示预览还是回放界面)
|
||||
port: port, //端口
|
||||
snapDir: snapDir, //抓图存储路径
|
||||
videoDir: videoDir, //紧急录像或录像剪辑存储路径
|
||||
layout: layout, //布局
|
||||
enableHTTPS: enableHTTPS, //是否启用HTTPS协议
|
||||
encryptedFields: encryptedFields, //加密字段
|
||||
showToolbar: showToolbar, //是否显示工具栏
|
||||
showSmart: showSmart, //是否显示智能信息
|
||||
buttonIDs //自定义工具条按钮
|
||||
})
|
||||
})
|
||||
.then(function (oData: any) {
|
||||
oWebControl.JS_Resize(playWndWidth.value * store.globalScale, playWndHeight.value * store.globalScale); // 初始化后resize一次,规避firefox下首次显示窗口后插件窗口未与DIV窗口重合问题
|
||||
|
||||
if (callback) {
|
||||
callback();
|
||||
}
|
||||
// 隐藏
|
||||
// oWebControl.JS_HideWnd()
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
// RSA 加密
|
||||
let setEncrypt = (value: string) => {
|
||||
let encrypt = new window.JSEncrypt();
|
||||
encrypt.setPublicKey(pubKey);
|
||||
return encrypt.encrypt(value);
|
||||
};
|
||||
// 获取公钥
|
||||
const getPubKey = (callback: { (): void; (): void }) => {
|
||||
oWebControl
|
||||
.JS_RequestInterface({
|
||||
funcName: "getRSAPubKey",
|
||||
argument: JSON.stringify({
|
||||
keyLength: 1024
|
||||
})
|
||||
})
|
||||
.then(function (oData: { responseMsg: { data: Ref<string> } }) {
|
||||
if (oData.responseMsg.data) {
|
||||
pubKey = oData.responseMsg.data;
|
||||
callback();
|
||||
}
|
||||
});
|
||||
};
|
||||
// 调用这个函数可进行视频播放
|
||||
// 视频预览功能
|
||||
const previewVideo = (data: string | null) => {
|
||||
let cameraIndexCode = data; // 获取输入的监控点编号值,必填
|
||||
let streamMode = 0; // 主子码流标识:0-主码流,1-子码流
|
||||
let transMode = 1; // 传输协议:0-UDP,1-TCP
|
||||
let gpuMode = 0; // 是否启用GPU硬解,0-不启用,1-启用
|
||||
let wndId = -1; // 播放窗口序号(在2x2以上布局下可指定播放窗口)
|
||||
|
||||
oWebControl
|
||||
.JS_RequestInterface({
|
||||
funcName: "startPreview",
|
||||
argument: JSON.stringify({
|
||||
cameraIndexCode: cameraIndexCode, // 监控点编号
|
||||
streamMode: streamMode, // 主子码流标识
|
||||
transMode: transMode, // 传输协议
|
||||
gpuMode: gpuMode, // 是否开启GPU硬解
|
||||
wndId: wndId // 可指定播放窗口
|
||||
})
|
||||
})
|
||||
.then(function () {
|
||||
oWebControl.JS_SetWindowControlCallback({});
|
||||
});
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@ -376,49 +686,61 @@ onMounted(async () => {
|
||||
height: 35%;
|
||||
color: white;
|
||||
margin: 0 auto;
|
||||
.statistics-listBox {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
&-left {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
:deep() {
|
||||
.el-scrollbar__view {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(4, 1fr);
|
||||
grid-gap: 20px;
|
||||
.statistics-listBox {
|
||||
height: 100%;
|
||||
:deep() {
|
||||
.el-scrollbar__view {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(3, 1fr);
|
||||
grid-gap: 20px;
|
||||
// grid-row-gap: 20px;
|
||||
// grid-column-gap: 60px;
|
||||
}
|
||||
}
|
||||
}
|
||||
.statistics-item {
|
||||
width: 200px;
|
||||
// height: 95px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
position: relative;
|
||||
background-size: 100% 100%;
|
||||
.title {
|
||||
position: absolute;
|
||||
top: 4%;
|
||||
left: 4%;
|
||||
}
|
||||
&-content {
|
||||
display: inline-block;
|
||||
width: 100%;
|
||||
height: auto;
|
||||
text-indent: 1.5em;
|
||||
}
|
||||
&-content:nth-child(2) {
|
||||
margin-top: 15%;
|
||||
}
|
||||
&-content:nth-child(3) {
|
||||
margin-top: 2%;
|
||||
}
|
||||
&-content:nth-child(4) {
|
||||
margin-top: 2%;
|
||||
}
|
||||
&-content:last-child {
|
||||
margin-bottom: 4%;
|
||||
}
|
||||
// &-content:nth-child(3){
|
||||
// margin-top: 8%;
|
||||
// }
|
||||
}
|
||||
}
|
||||
.statistics-item {
|
||||
width: 200px;
|
||||
// height: 95px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
position: relative;
|
||||
background-size: 100% 100%;
|
||||
.title {
|
||||
position: absolute;
|
||||
top: 4%;
|
||||
left: 4%;
|
||||
}
|
||||
&-content {
|
||||
display: inline-block;
|
||||
width: 100%;
|
||||
height: auto;
|
||||
text-indent: 1.5em;
|
||||
}
|
||||
&-content:nth-child(2) {
|
||||
margin-top: 15%;
|
||||
}
|
||||
&-content:nth-child(3) {
|
||||
margin-top: 2%;
|
||||
}
|
||||
&-content:nth-child(4) {
|
||||
margin-top: 2%;
|
||||
}
|
||||
&-content:last-child {
|
||||
margin-bottom: 4%;
|
||||
}
|
||||
// &-content:nth-child(3){
|
||||
// margin-top: 8%;
|
||||
// }
|
||||
&-right {
|
||||
width: 390px;
|
||||
height: 100%;
|
||||
}
|
||||
// .statistics-item:nth-child(1){
|
||||
// background: url("@/assets/images/commandScreen/bg6.png") no-repeat;
|
||||
@ -455,8 +777,8 @@ onMounted(async () => {
|
||||
}
|
||||
.top-search {
|
||||
@include flex;
|
||||
justify-content: center;
|
||||
margin-bottom: 15px;
|
||||
width: 90%;
|
||||
margin: 0 auto;
|
||||
margin-top: 20px;
|
||||
.search-item {
|
||||
@include flex;
|
||||
@ -489,7 +811,7 @@ onMounted(async () => {
|
||||
}
|
||||
}
|
||||
.listBox {
|
||||
height: 90%;
|
||||
height: 82%;
|
||||
.listStyle {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<div class="list-detail" v-if="showDialog && mapsDetail.length == 0">
|
||||
<div :class="postData.type == 1 ? 'dialog-content' : postData.type == 2 ? 'dialog-content-show' : 'dialog-content-more'"
|
||||
<div :class="postData.type == 1 ? 'dialog-content' : postData.type == 2 ? 'dialog-content-show' : postData.type == 3 ? 'dialog-content-three' : 'dialog-content-more'"
|
||||
:style="postData.index == 98 ? {'left':'5%','width':'90%','top':'5%','height':'90%'} : {}">
|
||||
<div class="dialog-title">
|
||||
<!-- <div class="title-img"><img src="@/assets/images/titleIcon.png" alt="" /></div> -->
|
||||
@ -62,11 +62,17 @@
|
||||
<div class="political-outlook" v-if="showIndex == 11">
|
||||
<radarMapList ref="historyAlarmList" :randerDetail="postData" :tip="postData.title"></radarMapList>
|
||||
</div>
|
||||
<div class="political-outlook" v-if="showIndex == 12">
|
||||
<memberAllShow ref="historyAlarmList" :tip="postData.title"></memberAllShow>
|
||||
</div>
|
||||
<div class="political-outlook" v-if="showIndex == 13">
|
||||
<memberMoreList ref="historyAlarmList"></memberMoreList>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div v-else-if="showIndex == 10">
|
||||
<div class="list-detail" v-for="ele in mapsDetail.filter((option: any) => option.show)" :key="ele.id">
|
||||
<div :class="postData.type == 1 ? 'dialog-content' : postData.type == 2 ? 'dialog-content-show' : 'dialog-content-more'">
|
||||
<div :class="postData.type == 1 ? 'dialog-content' : postData.type == 2 ? 'dialog-content-show' : postData.type == 3 ? 'dialog-content-three' : 'dialog-content-more'">
|
||||
<div class="warning-bg"></div>
|
||||
<div class="dialog-title">
|
||||
<!-- <div class="title-img"><img src="@/assets/images/titleIcon.png" alt="" /></div> -->
|
||||
@ -105,7 +111,8 @@ import majorHidder from "./major-hidder.vue";
|
||||
import monthSafeScore from "./month-safe-score.vue";
|
||||
import myMap from "./my-map.vue";
|
||||
import radarMapList from "./radar-map-list.vue";
|
||||
import { log } from "console";
|
||||
import memberAllShow from "./member-all-show.vue";
|
||||
import memberMoreList from "./member-more-list.vue";
|
||||
|
||||
// import { GlobalStore } from "@/stores";
|
||||
let showDialog = ref(false as any);
|
||||
@ -268,15 +275,26 @@ onMounted(async () => {
|
||||
position: absolute;
|
||||
box-sizing: border-box;
|
||||
padding: 1%;
|
||||
left: 15%;
|
||||
left: 12%;
|
||||
top: 1%;
|
||||
width: 70%;
|
||||
width: 80%;
|
||||
height: 98%;
|
||||
background: url("@/assets/images/commandScreen/dialog-bg.png") no-repeat;
|
||||
background-size: 100% 100%;
|
||||
z-index: 21;
|
||||
}
|
||||
|
||||
.dialog-content-three {
|
||||
position: absolute;
|
||||
box-sizing: border-box;
|
||||
padding: 1%;
|
||||
left: 5%;
|
||||
top: 21%;
|
||||
width: 90%;
|
||||
height: 60%;
|
||||
background: url("@/assets/images/commandScreen/dialog-bg.png") no-repeat;
|
||||
background-size: 100% 100%;
|
||||
z-index: 21;
|
||||
}
|
||||
.dialog-content-more {
|
||||
position: absolute;
|
||||
box-sizing: border-box;
|
||||
@ -292,7 +310,8 @@ onMounted(async () => {
|
||||
|
||||
.dialog-content,
|
||||
.dialog-content-show,
|
||||
.dialog-content-more {
|
||||
.dialog-content-more,
|
||||
.dialog-content-three {
|
||||
padding-top: 50px;
|
||||
position: relative;
|
||||
|
||||
@ -347,6 +366,10 @@ onMounted(async () => {
|
||||
}
|
||||
}
|
||||
}
|
||||
.dialog-content-show {
|
||||
padding-top: 70px;
|
||||
position: relative;
|
||||
}
|
||||
}
|
||||
|
||||
.notoDta {
|
||||
|
||||
661
src/views/commandScreen/dialogCompnnents/member-all-show.vue
Normal file
661
src/views/commandScreen/dialogCompnnents/member-all-show.vue
Normal file
@ -0,0 +1,661 @@
|
||||
<template>
|
||||
<div class="political-outlook">
|
||||
<div class="content">
|
||||
<div class="dialog-title">
|
||||
<div class="title-img"><img src="@/assets/images/titleIcon.png" alt="" /></div>
|
||||
<div class="title-text">
|
||||
<i>人员类型统计</i>
|
||||
</div>
|
||||
</div>
|
||||
<div class="PersonnelType_wrap">
|
||||
<div class="title_wrap" style="margin-bottom: 18px">
|
||||
<div>
|
||||
<div class="headcount">工地总人数:{{ memberCountData.totalPersonNum }}</div>
|
||||
<div class="headcount">今日出勤人数:{{ memberCountData.attendancePersonNum }}</div>
|
||||
<div class="headcount">今日在场人数:{{ memberCountData.presencePersonNum }}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="echarts" ref="personnelTypeRef"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="content">
|
||||
<div class="dialog-title">
|
||||
<div class="title-img"><img src="@/assets/images/titleIcon.png" alt="" /></div>
|
||||
<div class="title-text">
|
||||
<i>企业出勤排名</i>
|
||||
</div>
|
||||
</div>
|
||||
<div class="manager_wrap">
|
||||
<div class="echarts" ref="ageChartRef" style="width: 100%; height: 100%"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="list-content">
|
||||
<div class="dialog-title">
|
||||
<div class="title-img"><img src="@/assets/images/titleIcon.png" alt="" /></div>
|
||||
<div class="title-text">
|
||||
<i>人员实时动态</i>
|
||||
</div>
|
||||
</div>
|
||||
<div class="show-more" @click="openPeopleCountDialog({ index: 13, type: 3, title: '人员实时动态' })">
|
||||
<span>更多</span>
|
||||
</div>
|
||||
<div class="tabList">
|
||||
<div>类型</div>
|
||||
<div>姓名</div>
|
||||
<div>班组</div>
|
||||
<div>图片</div>
|
||||
<div style="width: 25%">通行时间</div>
|
||||
</div>
|
||||
|
||||
<el-scrollbar class="listBox" ref="refScrollbar">
|
||||
<div v-for="(item, index) in crewRealTimeList" class="listStyle" :key="item.id">
|
||||
<div>{{ item.passType == 1 ? "进" : "出" }}</div>
|
||||
<div>{{ item.workerName }}</div>
|
||||
<div>{{ item.teamName ? item.teamName : item.departmentName }}</div>
|
||||
<div class="list-img">
|
||||
<el-image v-if="item.imageUrl" fit="contain" class="el-img" :src="item.imageUrl" :preview-src-list="[item.imageUrl]">
|
||||
<template #error>
|
||||
<el-image :src="noDataImage" :preview-src-list="[noDataImage]" fit="contain" class="el-no-img" alt="" />
|
||||
</template>
|
||||
</el-image>
|
||||
<el-image v-else :src="noDataImage" :preview-src-list="[noDataImage]" fit="contain" class="el-no-img" alt="" />
|
||||
</div>
|
||||
<div style="width: 25%">{{ item.createTime }}</div>
|
||||
</div>
|
||||
<div class="notoDta" v-if="crewRealTimeList.length == 0">
|
||||
<img src="@/assets/images/noData.png" alt="" />
|
||||
<p>暂无数据</p>
|
||||
</div>
|
||||
</el-scrollbar>
|
||||
</div>
|
||||
<div class="list-content">
|
||||
<div class="dialog-title">
|
||||
<div class="title-img"><img src="@/assets/images/titleIcon.png" alt="" /></div>
|
||||
<div class="title-text">
|
||||
<i>班组人员统计</i>
|
||||
</div>
|
||||
</div>
|
||||
<div class="tabList">
|
||||
<div>序号</div>
|
||||
<div>班组名称</div>
|
||||
<div>在册人数</div>
|
||||
<div>出场人数</div>
|
||||
<div>在场人数</div>
|
||||
</div>
|
||||
<el-scrollbar class="listBox" ref="refScrollbar">
|
||||
<div v-for="(item, index) in teamList" class="listStyle" :key="item.id">
|
||||
<div>{{ index + 1 }}</div>
|
||||
<div>{{ item.teamName }}</div>
|
||||
<div>{{ item.totalPerson }}</div>
|
||||
<div>{{ item.attendancePersonTotal }}</div>
|
||||
<div>{{ item.presencePersonTotal }}</div>
|
||||
</div>
|
||||
<div class="notoDta" v-if="teamList.length == 0">
|
||||
<img src="@/assets/images/noData.png" alt="" />
|
||||
<p>暂无数据</p>
|
||||
</div>
|
||||
</el-scrollbar>
|
||||
</div>
|
||||
<dataDialog ref="partyBuildRefMore"></dataDialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { ref, onMounted } from "vue";
|
||||
import { GlobalStore } from "@/stores";
|
||||
import {
|
||||
getPersonTypeAndEduStatisticsApi,
|
||||
getComapnyWorkTotalListApi,
|
||||
getRealTimeDataApi,
|
||||
getWorkerInfoApi
|
||||
} from "@/api/modules/labor";
|
||||
import * as echarts from "echarts";
|
||||
import dataDialog from "./data-dialog.vue";
|
||||
import noDataImage from "@/assets/images/vehicleManagement/car.png";
|
||||
const store = GlobalStore();
|
||||
const props = defineProps(["tip"]);
|
||||
const partyBuildRefMore = ref();
|
||||
const teamList = ref([] as any);
|
||||
const BASEURL = import.meta.env.VITE_API_URL;
|
||||
const crewRealTimeList = ref([] as any);
|
||||
const ageChartRef = ref();
|
||||
const memberCountData = ref({
|
||||
totalPersonNum: 0,
|
||||
totalEducationPerson: 0,
|
||||
attendancePersonNum: 0,
|
||||
presencePersonNum: 0
|
||||
});
|
||||
const personnelTypeRef = ref();
|
||||
// 弹窗
|
||||
const openPeopleCountDialog = (obj: any) => {
|
||||
partyBuildRefMore.value.openDialog(obj);
|
||||
// console.log(partyBuildRef.value);
|
||||
};
|
||||
// 查询项目下按照班组统计
|
||||
const selectWorkerTeamStatistics = async () => {
|
||||
const res: any = await getWorkerInfoApi({
|
||||
projectSn: store.sn,
|
||||
userEnterpriseId: store.userInfo?.userEnterpriseId
|
||||
});
|
||||
teamList.value = res.result;
|
||||
};
|
||||
//获取人员实时动态
|
||||
const getCrewRealTimeData = async () => {
|
||||
let data = {
|
||||
projectSn: store.sn,
|
||||
userEnterpriseId: store.userInfo?.userEnterpriseId
|
||||
};
|
||||
const res: any = await getRealTimeDataApi(data);
|
||||
if (res.code == 200) {
|
||||
crewRealTimeList.value = res.result;
|
||||
crewRealTimeList.value.map((item: any) => {
|
||||
if (item.imageUrl) {
|
||||
item.imageUrl = BASEURL + "/image/" + item.imageUrl;
|
||||
} else if (item.fieldAcquisitionUrl) {
|
||||
item.fieldAcquisitionUrl = BASEURL + "/image/" + item.fieldAcquisitionUrl;
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
//获取企业出勤数据
|
||||
const getCompanyAttendData = async () => {
|
||||
let data = {
|
||||
projectSn: store.sn
|
||||
};
|
||||
const res: any = await getComapnyWorkTotalListApi(data);
|
||||
|
||||
if (res.code == 200) {
|
||||
var Data = res.result;
|
||||
var xData: any = [],
|
||||
yData1: any = [],
|
||||
yData2: any = [],
|
||||
yData3: any = [];
|
||||
Data.forEach((element: any) => {
|
||||
xData.push(element.enterpriseName);
|
||||
yData1.push(element.attendancePersonNum);
|
||||
yData2.push(element.totalPersonNum);
|
||||
yData3.push(element.presencePersonNum);
|
||||
});
|
||||
createdBarCharts(xData, yData1, yData2, yData3, ageChartRef.value, ["出勤人数", "在册人数", "在场人数"]);
|
||||
}
|
||||
};
|
||||
//企业出勤---图表
|
||||
const createdBarCharts = (xData: any, yData1: any, yData2: any, yData3: any, el: any, legendData: any) => {
|
||||
let that = this;
|
||||
let ageChart = echarts.init(el);
|
||||
ageChart.clear();
|
||||
let option = {
|
||||
grid: {
|
||||
width: "92%",
|
||||
height: "82%",
|
||||
left: 20,
|
||||
containLabel: true
|
||||
},
|
||||
color: ["#5CE2F6", "#5181F6", "#8EBDD2"],
|
||||
tooltip: {
|
||||
trigger: "axis",
|
||||
axisPointer: {
|
||||
type: "shadow"
|
||||
}
|
||||
},
|
||||
legend: {
|
||||
show: true,
|
||||
// align: "left",
|
||||
top: 0,
|
||||
// left: 0,
|
||||
itemWidth: 13,
|
||||
itemHeight: 5,
|
||||
textStyle: {
|
||||
color: "#9fa2ad"
|
||||
}
|
||||
},
|
||||
|
||||
xAxis: [
|
||||
{
|
||||
type: "category",
|
||||
data: xData,
|
||||
boundaryGap: true,
|
||||
axisTick: {
|
||||
show: false
|
||||
},
|
||||
axisLine: {
|
||||
show: false
|
||||
},
|
||||
axisLabel: {
|
||||
color: "#9fa2ad",
|
||||
fontSize: 12,
|
||||
interval: 0, // 强制显示所有标签
|
||||
}
|
||||
}
|
||||
],
|
||||
dataZoom: [
|
||||
{
|
||||
type: "slider", // 使用滑动条形式的数据区域缩放组件
|
||||
start: 0, // 数据窗口范围的起始百分比
|
||||
end: 50, // 数据窗口范围的结束百分比
|
||||
height: 10, // 滑动条组件高度
|
||||
bottom: 0, // 距离图表区域下边的距离
|
||||
showDetail: false, // 拖拽时是否显示详情
|
||||
showDataShadow: false, // 是否在组件中显示数据阴影
|
||||
fillerColor: "#2758C0", // 平移条的填充颜色
|
||||
borderColor: "transparent", // 边框颜色
|
||||
zoomLock: true, // 锁定视图
|
||||
},
|
||||
],
|
||||
yAxis: {
|
||||
type: "value",
|
||||
axisTick: {
|
||||
show: false
|
||||
},
|
||||
axisLine: {
|
||||
show: false
|
||||
},
|
||||
splitLine: {
|
||||
lineStyle: {
|
||||
type: "dashed",
|
||||
color: "rgba(231, 233, 243, 1)"
|
||||
}
|
||||
},
|
||||
axisLabel: {
|
||||
color: "#9fa2ad"
|
||||
}
|
||||
},
|
||||
// dataZoom: [
|
||||
// {
|
||||
// show: true,
|
||||
// start: 50,
|
||||
// end: 100,
|
||||
// height: 8,
|
||||
// borderColor: "transparent",
|
||||
// backgroundColor: "#fff",
|
||||
// filterColor: "#999999",
|
||||
// bottom: 0,
|
||||
// },
|
||||
// ],
|
||||
series: [
|
||||
{
|
||||
name: legendData[1],
|
||||
type: "bar",
|
||||
data: yData2,
|
||||
// stack: 'product',
|
||||
barWidth: 35,
|
||||
barGap: 0.1
|
||||
},
|
||||
{
|
||||
name: legendData[0],
|
||||
type: "bar",
|
||||
// stack: 'product',
|
||||
data: yData1,
|
||||
barMaxWidth: 35
|
||||
},
|
||||
{
|
||||
name: legendData[2],
|
||||
type: "bar",
|
||||
data: yData3,
|
||||
// stack: 'product',
|
||||
barMaxWidth: 35,
|
||||
barGap: 0.1
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
ageChart.setOption(option);
|
||||
};
|
||||
//人员类型统计
|
||||
const createdEcharts = (yAxisData1: any, yAxisData2: any, yAxisData3: any) => {
|
||||
// let yAxisData1 = [1, 2, 3, 4, 5, 6, 7];
|
||||
// let yAxisData2 = [2, 3, 7, 4, 5, 6, 7];
|
||||
let personnelType = echarts.init(personnelTypeRef.value);
|
||||
let option = {
|
||||
color: ["#8FC8FF", "rgba(126,150,232,1)", "#61D2B9"],
|
||||
tooltip: {
|
||||
show: true,
|
||||
trigger: "axis",
|
||||
formatter: "{b} <br /> {a0}: {c0}<br /> {a1}: {c1} <br /> {a2}: {c2}",
|
||||
axisPointer: {
|
||||
lineStyle: {
|
||||
color: "transparent"
|
||||
}
|
||||
},
|
||||
textStyle: {
|
||||
color: "#000",
|
||||
fontSize: 12
|
||||
},
|
||||
backgroundColor: "rgba(236,236,236,0.75)"
|
||||
},
|
||||
grid: {
|
||||
left: 30,
|
||||
right: 30,
|
||||
bottom: 15,
|
||||
top: 20,
|
||||
containLabel: true
|
||||
},
|
||||
xAxis: {
|
||||
type: "category",
|
||||
boundaryGap: false,
|
||||
axisLine: {
|
||||
show: false
|
||||
},
|
||||
axisTick: { show: false },
|
||||
data: ["项目管理人员", "劳务工", "临时工"],
|
||||
axisLabel: {
|
||||
// rotate: 30,
|
||||
textStyle: {
|
||||
color: "#9fa2ad",
|
||||
fontSize: 10
|
||||
}
|
||||
}
|
||||
},
|
||||
yAxis: {
|
||||
show: true,
|
||||
// type: "time",
|
||||
axisTick: { show: false },
|
||||
axisLine: {
|
||||
show: false
|
||||
},
|
||||
splitLine: {
|
||||
lineStyle: {
|
||||
type: "dashed",
|
||||
color: "rgba(231, 233, 243, 0.5)"
|
||||
}
|
||||
},
|
||||
axisLabel: {
|
||||
// show: false,
|
||||
textStyle: {
|
||||
color: "#9fa2ad",
|
||||
fontSize: 10
|
||||
}
|
||||
}
|
||||
},
|
||||
series: [
|
||||
{
|
||||
name: "在册人数",
|
||||
data: yAxisData2,
|
||||
type: "line",
|
||||
symbolSize: 10,
|
||||
// symbol: "circle",
|
||||
lineStyle: {
|
||||
width: 1
|
||||
},
|
||||
areaStyle: {
|
||||
normal: {
|
||||
// opacity: 0.2
|
||||
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
|
||||
{
|
||||
offset: 0,
|
||||
color: "rgba(126,150,232,0.56)"
|
||||
},
|
||||
{
|
||||
offset: 1,
|
||||
color: "rgba(30, 72, 223, 0)"
|
||||
}
|
||||
])
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
name: "出勤人数",
|
||||
data: yAxisData3,
|
||||
type: "line",
|
||||
symbolSize: 10,
|
||||
// symbol: "circle",
|
||||
lineStyle: {
|
||||
width: 1
|
||||
},
|
||||
areaStyle: {
|
||||
normal: {
|
||||
// opacity: 0.2
|
||||
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
|
||||
{
|
||||
offset: 0,
|
||||
color: "rgba(126,150,232,0.56)"
|
||||
},
|
||||
{
|
||||
offset: 1,
|
||||
color: "rgba(30, 72, 223, 0)"
|
||||
}
|
||||
])
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
name: "在场人数",
|
||||
data: yAxisData1,
|
||||
type: "line",
|
||||
symbolSize: 10,
|
||||
// symbol: "circle",
|
||||
lineStyle: {
|
||||
width: 1
|
||||
},
|
||||
areaStyle: {
|
||||
normal: {
|
||||
// opacity: 0.2
|
||||
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
|
||||
{
|
||||
offset: 0,
|
||||
color: "rgba(37,82,228,0.56)"
|
||||
},
|
||||
{
|
||||
offset: 1,
|
||||
color: "rgba(30, 72, 223, 0)"
|
||||
}
|
||||
])
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
};
|
||||
personnelType.setOption(option);
|
||||
};
|
||||
//查询人员类型和教育统计
|
||||
const selectPersonTypeAndEduStatistics = async () => {
|
||||
const res: any = await getPersonTypeAndEduStatisticsApi({
|
||||
projectSn: store.sn,
|
||||
userEnterpriseId: store.userInfo?.userEnterpriseId
|
||||
});
|
||||
console.log(res);
|
||||
memberCountData.value.totalPersonNum = res.result.personType.toaltPerson.totalPerson; //总人数
|
||||
memberCountData.value.totalEducationPerson = res.result.totalEducationPerson;
|
||||
memberCountData.value.attendancePersonNum = res.result.personType.attendancePerson.totalPerson; //出勤总人数
|
||||
memberCountData.value.presencePersonNum = res.result.personType.presencePerson.totalPerson; //在场 总人数
|
||||
var personTypeData = res.result.personType;
|
||||
var arr1 = [
|
||||
personTypeData.presencePerson.glPersonTotal,
|
||||
personTypeData.presencePerson.lwPersonTotal,
|
||||
personTypeData.presencePerson.lsPersonTotal
|
||||
];
|
||||
var arr2 = [
|
||||
personTypeData.toaltPerson.glPersonTotal,
|
||||
personTypeData.toaltPerson.lwPersonTotal,
|
||||
personTypeData.toaltPerson.lsPersonTotal
|
||||
];
|
||||
var attendance = [
|
||||
//出勤总人数
|
||||
personTypeData.attendancePerson.glPersonTotal,
|
||||
personTypeData.attendancePerson.lwPersonTotal,
|
||||
personTypeData.attendancePerson.lsPersonTotal
|
||||
];
|
||||
createdEcharts(arr1, arr2, attendance);
|
||||
// createdEcharts3()
|
||||
};
|
||||
onMounted(async () => {
|
||||
await selectPersonTypeAndEduStatistics();
|
||||
await getCompanyAttendData();
|
||||
await getCrewRealTimeData();
|
||||
await selectWorkerTeamStatistics();
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@mixin flex {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
.political-outlook {
|
||||
width: 100%;
|
||||
height: 97% !important;
|
||||
@include flex;
|
||||
flex-wrap: wrap;
|
||||
justify-content: space-around;
|
||||
margin-top: 1%;
|
||||
.content {
|
||||
height: 45%;
|
||||
width: 45%;
|
||||
margin-top: 10px;
|
||||
// background: url("@/assets/images/cardImg.png") no-repeat;
|
||||
background-size: 100% 100%;
|
||||
.dialog-title {
|
||||
color: #ffffff;
|
||||
font-weight: bold;
|
||||
font-size: 18px;
|
||||
font-family: "OPPOSans-Bold";
|
||||
@include flex;
|
||||
.title-img {
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
.title-text {
|
||||
margin-bottom: 0.3%;
|
||||
margin-left: 0.2%;
|
||||
}
|
||||
}
|
||||
.PersonnelType_wrap {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
.title_wrap {
|
||||
> div {
|
||||
@include flex;
|
||||
justify-content: flex-end;
|
||||
.headcount {
|
||||
color: white;
|
||||
font-size: 14px;
|
||||
padding: 3px 10px;
|
||||
// border-radius: 30px;
|
||||
background: #2758c0;
|
||||
margin-right: 10px;
|
||||
}
|
||||
}
|
||||
margin-top: 12px;
|
||||
}
|
||||
}
|
||||
.manager_wrap {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
.echarts {
|
||||
width: 100%;
|
||||
height: calc(100% - 50px);
|
||||
}
|
||||
}
|
||||
.list-content {
|
||||
height: 45%;
|
||||
width: 45%;
|
||||
margin-top: 10px;
|
||||
// background: url("@/assets/images/cardImg.png") no-repeat;
|
||||
background-size: 100% 100%;
|
||||
.dialog-title {
|
||||
color: #ffffff;
|
||||
font-weight: bold;
|
||||
font-size: 18px;
|
||||
font-family: "OPPOSans-Bold";
|
||||
@include flex;
|
||||
margin-bottom: 20px;
|
||||
.title-img {
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
.title-text {
|
||||
margin-bottom: 0.3%;
|
||||
margin-left: 0.2%;
|
||||
}
|
||||
}
|
||||
.show-more {
|
||||
cursor: pointer;
|
||||
font-size: 12px;
|
||||
font-family: Source Han Sans CN-Regular, Source Han Sans CN;
|
||||
color: #4ac0f3;
|
||||
@include flex;
|
||||
justify-content: flex-end;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
.tabList {
|
||||
display: flex;
|
||||
width: 100%;
|
||||
height: 5%;
|
||||
background: url("@/assets/images/vehicleManagement/ListTitleImg.png") no-repeat;
|
||||
background-size: 100% 100%;
|
||||
// position: absolute;
|
||||
left: 75.5%;
|
||||
top: 75%;
|
||||
color: #ccc;
|
||||
font-size: calc(100vw * 14 / 1920);
|
||||
line-height: 30px;
|
||||
align-items: center;
|
||||
div {
|
||||
text-align: center;
|
||||
width: 20%;
|
||||
}
|
||||
}
|
||||
.listBox {
|
||||
height: 78%;
|
||||
.listStyle {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
text-align: center;
|
||||
color: #fff;
|
||||
font-size: 12px;
|
||||
margin-bottom: 5px;
|
||||
.list-img {
|
||||
.el-img {
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
img {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
.el-no-img {
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
}
|
||||
}
|
||||
div {
|
||||
width: 20%;
|
||||
white-space: nowrap; //单行
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
}
|
||||
.listStyle:hover {
|
||||
background: #091f3f;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.notoDta {
|
||||
top: 28%;
|
||||
width: 50%;
|
||||
left: 22%;
|
||||
position: absolute;
|
||||
text-align: center;
|
||||
img {
|
||||
width: 40%;
|
||||
margin: 5% 30%;
|
||||
}
|
||||
p {
|
||||
color: #fff;
|
||||
font-size: calc(100vw * 14 / 1920);
|
||||
margin: -6% 37%;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
352
src/views/commandScreen/dialogCompnnents/member-more-list.vue
Normal file
352
src/views/commandScreen/dialogCompnnents/member-more-list.vue
Normal file
@ -0,0 +1,352 @@
|
||||
<template>
|
||||
<div class="political-outlook">
|
||||
<div class="content">
|
||||
<div class="top-search">
|
||||
<div class="search-item">
|
||||
<span>姓名</span>
|
||||
<el-input placeholder="请输入" size="small" v-model="searchForm.name" :clearable="true" style="width: 100px" />
|
||||
</div>
|
||||
<div class="search-item">
|
||||
<span>通行时间</span>
|
||||
<el-date-picker
|
||||
style="width: 300px"
|
||||
v-model="searchForm.rangeTime"
|
||||
type="datetimerange"
|
||||
size="small"
|
||||
range-separator="至"
|
||||
start-placeholder="开始日期"
|
||||
end-placeholder="结束日期"
|
||||
format="YYYY-MM-DD HH:mm:ss"
|
||||
value-format="YYYY-MM-DD HH:mm:ss"
|
||||
:clearable="true"
|
||||
/>
|
||||
</div>
|
||||
<div class="search-item">
|
||||
<span>所属企业</span>
|
||||
<el-select
|
||||
class="m-2"
|
||||
placeholder="请选择"
|
||||
size="small"
|
||||
v-model="searchForm.belongCompany"
|
||||
:clearable="true"
|
||||
@change="companySelect"
|
||||
style="width: 100px"
|
||||
>
|
||||
<el-option v-for="(item, index) in enterpriseListData" :key="index" :label="item.enterpriseName" :value="item.id" />
|
||||
</el-select>
|
||||
</div>
|
||||
<div class="search-item">
|
||||
<span>所属班组</span>
|
||||
<el-select
|
||||
class="m-2"
|
||||
placeholder="请选择"
|
||||
size="small"
|
||||
v-model="searchForm.belongTeam"
|
||||
:clearable="true"
|
||||
style="width: 100px"
|
||||
>
|
||||
<el-option v-for="(item, index) in teamListData" :key="index" :label="item.teamName" :value="item.id" />
|
||||
</el-select>
|
||||
</div>
|
||||
<div class="search-item">
|
||||
<span>所属部门</span>
|
||||
<el-select
|
||||
class="m-2"
|
||||
placeholder="请选择"
|
||||
size="small"
|
||||
v-model="searchForm.belongDepart"
|
||||
:clearable="true"
|
||||
style="width: 100px"
|
||||
>
|
||||
<el-option v-for="(item, index) in departListData" :key="index" :label="item.departmentName" :value="item.id" />
|
||||
</el-select>
|
||||
</div>
|
||||
<el-button @click="getMemberCountList('search')">查询</el-button>
|
||||
</div>
|
||||
<div class="tabList">
|
||||
<div>类型</div>
|
||||
<div>姓名</div>
|
||||
<div>班组</div>
|
||||
<div>通行时间</div>
|
||||
<div>闸机名称</div>
|
||||
<div>图片</div>
|
||||
</div>
|
||||
|
||||
<el-scrollbar class="listBox" ref="refScrollbar">
|
||||
<div v-for="(item, index) in crewRealTimeList" class="listStyle" :key="item.id">
|
||||
<div>{{ item.passType == 1 ? "进" : "出" }}</div>
|
||||
<div>{{ item.workerName }}</div>
|
||||
<div>{{ item.teamName ? item.teamName : item.departmentName }}</div>
|
||||
<div>{{ item.createTime }}</div>
|
||||
<div>{{ item.passagewayName }}</div>
|
||||
<div class="list-img">
|
||||
<el-image v-if="item.imageUrl" fit="contain" class="el-img" :src="item.imageUrl" :preview-src-list="[item.imageUrl]">
|
||||
<template #error>
|
||||
<el-image :src="noDataImage" :preview-src-list="[noDataImage]" fit="contain" class="el-no-img" alt="" />
|
||||
</template>
|
||||
</el-image>
|
||||
<el-image v-else :src="noDataImage" :preview-src-list="[noDataImage]" fit="contain" class="el-no-img" alt="" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="notoDta" v-if="partyMemberList.length == 0">
|
||||
<img src="@/assets/images/noData.png" alt="" />
|
||||
<p>暂无数据</p>
|
||||
</div>
|
||||
</el-scrollbar>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { ref, onMounted } from "vue";
|
||||
import { GlobalStore } from "@/stores";
|
||||
import {
|
||||
getCompanyDataList,
|
||||
getMemberInfoList,
|
||||
getTeamDataList,
|
||||
getDepartDataList,
|
||||
getRealTimeMoreDataApi
|
||||
} from "@/api/modules/labor";
|
||||
import noDataImage from "@/assets/images/vehicleManagement/car.png";
|
||||
const store = GlobalStore();
|
||||
const props = defineProps(["tip"]);
|
||||
const crewRealTimeList = ref([] as any);
|
||||
const BASEURL = import.meta.env.VITE_API_URL;
|
||||
const departListData = ref([] as any);
|
||||
const teamListData = ref([] as any);
|
||||
const enterpriseListData = ref([] as any)
|
||||
let pageNo = ref(1 as any);
|
||||
let moreScroll = ref(true as any);
|
||||
const refScrollbar = ref(null as any); // 绑定到滚动的盒子上
|
||||
const searchForm = ref({
|
||||
name: "",
|
||||
rangeTime: "",
|
||||
belongCompany: "",
|
||||
belongTeam: "",
|
||||
belongDepart: ""
|
||||
});
|
||||
|
||||
const partyMemberList = ref({} as any);
|
||||
// 所属企业选择
|
||||
const companySelect = async () => {
|
||||
await getTeamList();
|
||||
await getDepartmentList();
|
||||
};
|
||||
//获取 部门 列表
|
||||
const getDepartmentList = async () => {
|
||||
let data = {
|
||||
enterpriseId: searchForm.value.belongCompany,
|
||||
projectSn: store.sn
|
||||
};
|
||||
const res: any = await getDepartDataList(data);
|
||||
departListData.value = res.result.list;
|
||||
};
|
||||
//获取企业的 - 班组列表
|
||||
const getTeamList = async () => {
|
||||
let data = {
|
||||
enterpriseId: searchForm.value.belongCompany,
|
||||
projectSn: store.sn
|
||||
};
|
||||
const res: any = await getTeamDataList(data);
|
||||
teamListData.value = res.result.list;
|
||||
};
|
||||
//获取企业列表
|
||||
const getCompanyList = async () => {
|
||||
let data = {
|
||||
projectSn: store.sn,
|
||||
enterpriseName: "",
|
||||
userEnterpriseId: store.userInfo?.userEnterpriseId
|
||||
};
|
||||
const res: any = await getCompanyDataList(data);
|
||||
if (res.code == 200) {
|
||||
enterpriseListData.value = res.result;
|
||||
}
|
||||
};
|
||||
//获取数据
|
||||
const getMemberCountList = async (tip: any) => {
|
||||
let data:any = {
|
||||
projectSn: store.sn,
|
||||
userEnterpriseId: store.userInfo?.userEnterpriseId,
|
||||
workerName: searchForm.value.name,
|
||||
enterpriseId: searchForm.value.belongCompany,
|
||||
teamId: searchForm.value.belongTeam,
|
||||
departmentId: searchForm.value.belongDepart,
|
||||
pageNo: tip == 'search'?1:pageNo.value,
|
||||
pageSize: 20
|
||||
};
|
||||
if(searchForm.value.rangeTime){
|
||||
data.startTime = searchForm.value.rangeTime[0]
|
||||
data.endTime = searchForm.value.rangeTime[1]
|
||||
}
|
||||
const res: any = await getRealTimeMoreDataApi(data);
|
||||
if (tip == "more") {
|
||||
crewRealTimeList.value = crewRealTimeList.value.concat(res.result.records);
|
||||
} else {
|
||||
crewRealTimeList.value = res.result.records;
|
||||
}
|
||||
crewRealTimeList.value.map((item: any) => {
|
||||
if (item.imageUrl) {
|
||||
if(item.imageUrl.indexOf("http") == -1 && item.imageUrl.indexOf("https") == -1){
|
||||
item.imageUrl = BASEURL + "/image/" + item.imageUrl;
|
||||
}
|
||||
} else if (item.fieldAcquisitionUrl) {
|
||||
if(item.fieldAcquisitionUrl.indexOf("http") == -1 && item.fieldAcquisitionUrl.indexOf("https") == -1){
|
||||
item.fieldAcquisitionUrl = BASEURL + "/image/" + item.fieldAcquisitionUrl;
|
||||
}
|
||||
}
|
||||
});
|
||||
console.log(crewRealTimeList.value,777888)
|
||||
if (res.result.pages == pageNo.value) {
|
||||
moreScroll.value = false;
|
||||
} else {
|
||||
pageNo.value = pageNo.value + 1;
|
||||
}
|
||||
};
|
||||
|
||||
onMounted(async () => {
|
||||
await getCompanyList();
|
||||
await getMemberCountList("search");
|
||||
refScrollbar.value.wrapRef.addEventListener("scroll", (e: any) => {
|
||||
// console.log("滚动容器", e);
|
||||
const scrollTop = e.target.scrollTop;
|
||||
const scrollHeight = e.target.scrollHeight;
|
||||
const clientHeight = e.target.clientHeight;
|
||||
// console.log("滚动容器", scrollTop, scrollHeight, clientHeight);
|
||||
// 向上加载更多
|
||||
if (scrollTop >= scrollHeight - clientHeight - 1) {
|
||||
// console.log("加载更多");
|
||||
if (moreScroll.value) {
|
||||
getMemberCountList("more");
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@mixin flex {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
.political-outlook {
|
||||
width: 100%;
|
||||
height: 97%;
|
||||
.content {
|
||||
height: 95%;
|
||||
width: 100%;
|
||||
margin-top: 10px;
|
||||
// background: url("@/assets/images/cardImg.png") no-repeat;
|
||||
background-size: 100% 100%;
|
||||
.top-search {
|
||||
width: 95%;
|
||||
margin: 0 auto;
|
||||
@include flex;
|
||||
justify-content: flex-end;
|
||||
margin-bottom: 15px;
|
||||
margin-top: 30px;
|
||||
.search-item {
|
||||
@include flex;
|
||||
margin-right: 20px;
|
||||
span {
|
||||
color: white;
|
||||
margin-right: 10px;
|
||||
}
|
||||
}
|
||||
}
|
||||
.tabList {
|
||||
display: flex;
|
||||
width: 95%;
|
||||
height: 5%;
|
||||
margin: 0 auto;
|
||||
background: url("@/assets/images/vehicleManagement/ListTitleImg.png") no-repeat;
|
||||
background-size: 100% 100%;
|
||||
// position: absolute;
|
||||
left: 75.5%;
|
||||
top: 75%;
|
||||
color: #ccc;
|
||||
font-size: calc(100vw * 14 / 1920);
|
||||
line-height: 30px;
|
||||
align-items: center;
|
||||
div {
|
||||
text-align: center;
|
||||
width: 17%;
|
||||
}
|
||||
}
|
||||
.listBox {
|
||||
width: 95%;
|
||||
margin: 0 auto;
|
||||
height: 80%;
|
||||
.listStyle {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
text-align: center;
|
||||
color: #fff;
|
||||
font-size: 12px;
|
||||
margin-bottom: 5px;
|
||||
.list-img {
|
||||
.el-img {
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
img {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
.el-no-img {
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
}
|
||||
}
|
||||
div {
|
||||
width: 17%;
|
||||
white-space: nowrap; //单行
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
}
|
||||
.listStyle:hover {
|
||||
background: #091f3f;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.notoDta {
|
||||
top: 35%;
|
||||
width: 20%;
|
||||
left: 40%;
|
||||
position: absolute;
|
||||
text-align: center;
|
||||
img {
|
||||
width: 40%;
|
||||
margin: 5% 30%;
|
||||
}
|
||||
p {
|
||||
color: #fff;
|
||||
font-size: calc(100vw * 14 / 1920);
|
||||
margin: -6% 37%;
|
||||
}
|
||||
}
|
||||
// element 组件样式
|
||||
:deep() {
|
||||
.el-date-editor .el-range-input,
|
||||
.el-range-separator {
|
||||
color: #fff;
|
||||
}
|
||||
.el-input__wrapper {
|
||||
background: #112d59;
|
||||
}
|
||||
.el-input__inner {
|
||||
color: #fff;
|
||||
}
|
||||
.el-button {
|
||||
background-color: #2758c0;
|
||||
color: white;
|
||||
border-color: transparent;
|
||||
}
|
||||
}
|
||||
// ::v-deep .el-select .el-input .el-select__caret {
|
||||
// color: #fff;
|
||||
// }
|
||||
</style>
|
||||
Loading…
x
Reference in New Issue
Block a user