Procházet zdrojové kódy

Merge remote-tracking branch 'origin/master'

# Conflicts:
#	src/main/java/com/jeesite/modules/mes/web/MesProductController.java
#	src/main/resources/config/application.yml
jingbo před 3 dny
rodič
revize
226911a5b1

+ 19 - 1
src/main/java/com/jeesite/modules/mes/entity/MesLineProcess.java

@@ -67,6 +67,8 @@ public class MesLineProcess extends DataEntity<MesLineProcess> {
 	private String pid;
 	private Integer shiftCount;
 	private Integer dayCount;
+	private Integer shiftOkCount;
+	private Integer shiftNgCount;
 	private Integer shift5305;
 	private Integer day5305;
 	private Integer shift5308;
@@ -212,6 +214,22 @@ public class MesLineProcess extends DataEntity<MesLineProcess> {
 		this.dayCount = dayCount;
 	}
 
+	public Integer getShiftOkCount() {
+		return shiftOkCount;
+	}
+
+	public void setShiftOkCount(Integer shiftOkCount) {
+		this.shiftOkCount = shiftOkCount;
+	}
+
+	public Integer getShiftNgCount() {
+		return shiftNgCount;
+	}
+
+	public void setShiftNgCount(Integer shiftNgCount) {
+		this.shiftNgCount = shiftNgCount;
+	}
+
 	public Integer getShift5305() {
 		return shift5305;
 	}
@@ -363,4 +381,4 @@ public class MesLineProcess extends DataEntity<MesLineProcess> {
 	public void setMesLineProcessUserList(List<MesLineProcessUser> mesLineProcessUserList) {
 		this.mesLineProcessUserList = mesLineProcessUserList;
 	}
-}
+}

+ 5 - 5
src/main/java/com/jeesite/modules/mes/service/MesProductRecordService.java

@@ -201,7 +201,7 @@ public class MesProductRecordService extends CrudService<MesProductRecordDao, Me
 		mesProductRecord.setLineSn(cate);
 		return mesProductRecordDao.findInfo(mesProductRecord);
 	}
-	
+
 	/**
 	 * 查询分页数据
 	 * @param mesProductRecord 查询条件
@@ -301,7 +301,7 @@ public class MesProductRecordService extends CrudService<MesProductRecordDao, Me
 			mesProductService.save(mesProduct);
 		}
 	}
-	
+
 	/**
 	 * 保存数据(插入或更新) 生产订单,仅生成模板
 	 * @param mesProductRecord
@@ -1001,7 +1001,7 @@ public class MesProductRecordService extends CrudService<MesProductRecordDao, Me
 
 
 	}
-	
+
 	/**
 	 * 更新状态
 	 * @param mesProductRecord
@@ -1011,7 +1011,7 @@ public class MesProductRecordService extends CrudService<MesProductRecordDao, Me
 	public void updateStatus(MesProductRecord mesProductRecord) {
 		super.updateStatus(mesProductRecord);
 	}
-	
+
 	/**
 	 * 删除数据
 	 * @param mesProductRecord
@@ -1195,4 +1195,4 @@ public class MesProductRecordService extends CrudService<MesProductRecordDao, Me
 	public void updateResultByCheckFirst(MesProductRecord mesProductRecord){
 		mesProductRecordDao.updateResultByCheckFirst(mesProductRecord);
 	}
-}
+}

+ 532 - 173
src/main/resources/views/modules/mes/mesScreen2.html

@@ -8,120 +8,226 @@
 	<link rel="stylesheet" href="${ctxStatic}/bootstrap/css/bootstrap.min.css">
 	<link rel="stylesheet" href="${ctxStatic}/screen/style.css">
 	<style>
-		.oprnobox{
+		.dashboard{
 			position: absolute;
-			/*width: 930px;*/
-			height: 688px;
-			z-index: 100;
-		}
-		.oprnobox.box1{
-			top: 171px;
+			top: 132px;
 			left: 25px;
 			right: 25px;
+			bottom: 110px;
+			z-index: 100;
 		}
-		.oprnobox.box2{
-			top: 171px;
-			right: 25px;
+		.overview-row{
+			display: flex;
+			gap: 18px;
+			height: 126px;
+			margin-bottom: 18px;
 		}
-		.oprnobox-header{
+		.overview-card{
+			position: relative;
+			flex: 1;
+			padding: 24px 28px;
+			background: linear-gradient(135deg, rgba(17, 46, 109, 0.88), rgba(7, 22, 54, 0.78));
+			border: 1px solid rgba(64, 173, 255, 0.35);
+			box-shadow: inset 0 0 26px rgba(56, 160, 255, 0.12), 0 10px 24px rgba(0, 10, 35, 0.4);
+			overflow: hidden;
+		}
+		.overview-card:before{
+			content: "";
+			position: absolute;
+			top: 0;
+			left: 0;
 			width: 100%;
+			height: 3px;
+			background: linear-gradient(90deg, rgba(55, 180, 255, 0.1), rgba(55, 180, 255, 0.9), rgba(55, 180, 255, 0.1));
+		}
+		.overview-label{
+			font-size: 18px;
+			color: #79CFFF;
+			letter-spacing: 2px;
+		}
+		.overview-value{
+			margin-top: 16px;
+			font-size: 46px;
+			line-height: 1;
+			font-weight: bold;
+			color: #FFFFFF;
+			font-family: FZChaoCuHei-M10S;
+		}
+		.overview-sub{
+			margin-top: 14px;
+			font-size: 16px;
+			color: rgba(196, 231, 255, 0.72);
+		}
+		.dashboard-main{
+			display: flex;
+			gap: 18px;
+			height: calc(100% - 144px);
+		}
+		.panel-box{
+			background: linear-gradient(180deg, rgba(10, 28, 70, 0.92), rgba(5, 15, 38, 0.88));
+			border: 1px solid rgba(64, 173, 255, 0.28);
+			box-shadow: inset 0 0 32px rgba(60, 143, 255, 0.12), 0 12px 30px rgba(0, 0, 0, 0.22);
+		}
+		.table-panel{
+			flex: 0 0 1210px;
+			padding: 22px 22px 18px;
+		}
+		.side-panel{
+			flex: 1;
+			display: flex;
+			flex-direction: column;
+			gap: 18px;
+		}
+		.panel-title{
+			display: flex;
+			align-items: center;
+			justify-content: space-between;
+			height: 42px;
+			line-height: 42px;
+			margin-bottom: 16px;
+			padding-left: 16px;
+			padding-right: 16px;
+			background: linear-gradient(90deg, rgba(24, 78, 166, 0.58), rgba(24, 78, 166, 0.08));
+			color: #7ED4FF;
+			font-size: 22px;
+			font-weight: bold;
+		}
+		.panel-title span{
+			font-size: 16px;
+			font-weight: normal;
+			color: rgba(182, 227, 255, 0.75);
+		}
+		.oprnobox-header{
+			display: flex;
+			align-items: center;
 			height: 58px;
-			line-height: 58px;
-			overflow: hidden;
-			background-color: rgba(20, 55, 120, 0.8);
+			padding: 0 12px;
+			background: rgba(20, 55, 120, 0.85);
 			font-size: 20px;
-			color: #008FFD;
+			color: #3DB3FF;
 			font-weight: bold;
 			text-align: center;
+			border: 1px solid rgba(73, 163, 255, 0.2);
 		}
-		.oprnobox-header .oprno-num{
-			width: 178px;
-			/*background-color: #00F7DE;*/
-			float: left;
+		.oprnobox-header > div{
+			flex-shrink: 0;
 		}
-		.oprnobox-header .oprno-title{
-			width: 397px;
-			/*background-color: red;*/
-			float: left;
+		.oprno-num{
+			width: 150px;
 		}
-		.oprnobox-header .oprno-classes{
-			width: 180px;
-			/*background-color: green;*/
-			float: left;
+		.oprno-title{
+			width: 330px;
 		}
-		.oprnobox-header .oprno-day{
-			width: 180px;
-			/*background-color: salmon;*/
-			float: left;
+		.oprno-shift{
+			width: 170px;
 		}
-
-		.oprno-val{
-			width: 161px;
-			float: left;
+		.oprno-day{
+			width: 170px;
+		}
+		.oprno-rate{
+			flex: 1;
+			min-width: 0;
+		}
+		#numbox{
+			margin-top: 14px;
 		}
-		
 		.oprnobox-list{
-			width: 100%;
-			height: 80px;
-			line-height: 80px;
-			overflow: hidden;
-			font-size: 36px;
+			display: flex;
+			align-items: center;
+			height: 68px;
+			padding: 0 12px;
+			margin-bottom: 12px;
+			background: linear-gradient(90deg, rgba(14, 49, 108, 0.86), rgba(8, 25, 59, 0.78));
+			border: 1px solid rgba(62, 163, 255, 0.18);
+			box-shadow: inset 0 0 18px rgba(56, 160, 255, 0.08);
+			font-size: 28px;
 			text-align: center;
 			font-family: FZChaoCuHei-M10S;
 			font-weight: 400;
 			color: #FFFFFF;
 		}
+		.oprnobox-list:nth-child(even){
+			background: linear-gradient(90deg, rgba(11, 41, 92, 0.92), rgba(6, 22, 51, 0.82));
+		}
 		.oprnobox-list .oprno-num{
-			background-image: url("${ctxStatic}/screen/imgs/lbg.png");
-			background-size: 100% 100%;
-			background-repeat: no-repeat;
-			float: left;
-			width: 178px;
-			height: 80px;
-		}
-		.oprnobox-list .oprno-right{
+			font-size: 24px;
+			color: #6CD6FF;
+		}
+		.oprnobox-list .oprno-title{
+			padding: 0 12px;
+			font-size: 24px;
+			text-align: left;
+			white-space: nowrap;
+			overflow: hidden;
+			text-overflow: ellipsis;
+		}
+		.oprnobox-list .oprno-shift,
+		.oprnobox-list .oprno-day{
+			font-size: 28px;
+			color: #FFFFFF;
+		}
+		.rate-box{
+			display: flex;
+			align-items: center;
+			gap: 14px;
+			padding-right: 8px;
+		}
+		.rate-track{
 			position: relative;
+			flex: 1;
+			height: 14px;
+			border-radius: 10px;
+			background: rgba(255, 255, 255, 0.08);
 			overflow: hidden;
-			background-image: url("${ctxStatic}/screen/imgs/rbg.png");
-			background-size: 100% 100%;
-			background-repeat: no-repeat;
-			float: right;
-			/*width: 752px;*/
-			width: 1692px;
-			height: 80px;
-		}
-		.oprnobox-list .oprno-right .oprno-title{
-			width: 392px;
-			height: 80px;
-			float: left;
-		}
-		.oprnobox-list .oprno-right .oprno-classes{
-			width: 180px;
-			height: 80px;
-			float: left;
-		}
-		.oprnobox-list .oprno-right .oprno-day{
-			width: 180px;
-			float: left;
-			height: 80px;
 		}
-
+		.rate-bar{
+			height: 100%;
+			border-radius: 10px;
+			background: linear-gradient(90deg, #1ED4FF, #2FF4A6);
+			box-shadow: 0 0 12px rgba(47, 244, 166, 0.35);
+		}
+		.rate-text{
+			width: 76px;
+			font-size: 22px;
+			color: #8AE4FF;
+		}
+		.chart-panel{
+			flex: 1;
+			padding: 18px 18px 10px;
+		}
+		.chart-box{
+			height: calc(100% - 58px);
+		}
+		.empty-box{
+			display: flex;
+			align-items: center;
+			justify-content: center;
+			height: calc(100% - 58px);
+			font-size: 28px;
+			color: rgba(185, 223, 255, 0.6);
+			letter-spacing: 4px;
+		}
 		.dangerbox{
 			position: absolute;
 			z-index: 100000;
 			bottom: 25px;
 			left: 25px;
-			width:1880px;
-			height:70px;
-			line-height: 70px;
+			width: 1870px;
+			height: 64px;
+			line-height: 64px;
+			padding: 0 20px;
 			text-align: center;
-			background: rgba(255,0,0,0.2);
-			border: 1px solid #FF0000;
-			color: #D13D3E;
+			background: rgba(255, 0, 0, 0.15);
+			border: 1px solid rgba(255, 74, 74, 0.6);
+			box-shadow: inset 0 0 20px rgba(255, 0, 0, 0.08);
+			color: #FF8F8F;
 			font-family: Microsoft YaHei;
 			font-weight: 400;
-			font-size: 34px;
+			font-size: 28px;
 			display: none;
+			overflow: hidden;
+			white-space: nowrap;
+			text-overflow: ellipsis;
 		}
 	</style>
 </head>
@@ -133,64 +239,69 @@
 <div class="screenbox1">
 	<div class="screenmain">
 		<div class="screen-title">MES系统生产数据大屏</div>
-
-		<div class="oprnobox box1">
-			<div class="oprnobox-header">
-				<div class="oprno-num">工位</div>
-				<div class="oprno-title">工位名称</div>
-				<div class="oprno-val">当班/当日产值</div>
-				<div class="oprno-val">5308产值</div>
-				<div class="oprno-val">5305产值</div>
-				<div class="oprno-val">8302产值</div>
-				<div class="oprno-val">8301产值</div>
-				<div class="oprno-val">7939产值</div>
-				<div class="oprno-val">7933产值</div>
-				<div class="oprno-val">印尼产值</div>
+		<div class="dashboard">
+			<div class="overview-row">
+				<div class="overview-card">
+					<div class="overview-label">工位总数</div>
+					<div class="overview-value" id="overviewCount">46</div>
+					<div class="overview-sub" id="overviewPageCount">当前页 46 个工位</div>
+				</div>
+				<div class="overview-card">
+					<div class="overview-label">当班总产值</div>
+					<div class="overview-value" id="overviewShift">0</div>
+					<div class="overview-sub">当前班次累计</div>
+				</div>
+				<div class="overview-card">
+					<div class="overview-label">当日总产值</div>
+					<div class="overview-value" id="overviewDay">0</div>
+					<div class="overview-sub">08:00 至次日 08:00</div>
+				</div>
+				<div class="overview-card">
+					<div class="overview-label">当班合格率</div>
+					<div class="overview-value" id="overviewRate">0%</div>
+					<div class="overview-sub" id="overviewPage">OK 0 / NG 0</div>
+				</div>
 			</div>
-
-			<div id="numbox">
-				<!--<div class="oprnobox-list">
-					<div class="oprno-num">OP060</div>
-					<div class="oprno-right">
-						<div class="oprno-title">后梁FSW</div>
-						<div class="oprno-val">0/0</div>
-						<div class="oprno-val">0/0</div>
-						<div class="oprno-val">0/0</div>
-						<div class="oprno-val">0/0</div>
-						<div class="oprno-val">0/0</div>
-						<div class="oprno-val">0/0</div>
-						<div class="oprno-val">0/0</div>
+			<div class="dashboard-main">
+				<div class="table-panel panel-box">
+					<div class="panel-title">工位产值明细 </div>
+					<div class="oprnobox-header">
+						<div class="oprno-num">工位</div>
+						<div class="oprno-title">工位名称</div>
+						<div class="oprno-shift">当班产值</div>
+						<div class="oprno-day">当日产值</div>
+						<div class="oprno-rate">合格率</div>
 					</div>
+					<div id="numbox"></div>
 				</div>
-				<div class="oprnobox-list">
-					<div class="oprno-num">OP060</div>
-					<div class="oprno-right">
-						<div class="oprno-title">后梁FSW</div>
-						<div class="oprno-val">0/0</div>
-						<div class="oprno-val">0/0</div>
-						<div class="oprno-val">0/0</div>
-						<div class="oprno-val">0/0</div>
-						<div class="oprno-val">0/0</div>
-						<div class="oprno-val">0/0</div>
-						<div class="oprno-val">0/0</div>
+				<div class="side-panel">
+					<div class="chart-panel panel-box">
+						<div class="panel-title">当前页工位对比 <span>当班 / 当日</span></div>
+						<div id="shiftDayChart" class="chart-box"></div>
 					</div>
-				</div>-->
+					<div class="chart-panel panel-box">
+						<div class="panel-title">日产值 TOP 6 <span>全工位排名</span></div>
+						<div id="topChart" class="chart-box"></div>
+					</div>
+				</div>
 			</div>
-
 		</div>
 
 		<div class="dangerbox" id="dangerbox">
-<!--			2025-05-12 11:23:30 【OP060A-后梁FSW】异常报警:000020015308-0100101425042600115-->
 		</div>
 	</div>
 </div>
 
 <script src="${ctxStatic}/jquery-1.11.3.min.js"></script>
-<!--<script src="${ctxStatic}/common/vue2.7.14.min.js"></script>-->
+<script src="${ctxStatic}/leaflet/js/echarts.min.js"></script>
 <script>
 	let lists = [];
-	let info = null;
-	let curIdx = 0;
+	let overviewData = {};
+	let topListData = [];
+	let pageSize = 9;
+	let pageIndex = 0;
+	let shiftDayChart = null;
+	let topChart = null;
 
 	$(window).resize(function(){
 		location.reload()
@@ -198,6 +309,7 @@
 
 	$(function () {
 		changeZoom();
+		initCharts();
 
 		getData();
 		getAlarmData();
@@ -212,11 +324,21 @@
 		},1000*10);
 	});
 
+	function initCharts() {
+		if (window.echarts) {
+			shiftDayChart = echarts.init(document.getElementById('shiftDayChart'));
+			topChart = echarts.init(document.getElementById('topChart'));
+		}
+	}
+
 	function getData() {
-		let url = "/js/a/mes/mesProduct/screenData";
+		let url = "/js/a/mes/mesProduct/screenDashboardData";
 		$.post(url,function (ret) {
-			lists = ret.data;
-			curIdx = 0;
+			let data = ret.data || {};
+			lists = $.isArray(data.list) ? data.list : [];
+			overviewData = data.overview || {};
+			topListData = $.isArray(data.topList) ? data.topList : [];
+			pageIndex = 0;
 			formatData();
 		});
 	}
@@ -224,64 +346,301 @@
 	function getAlarmData() {
 		let url = "/js/a/mes/mesProduct/alarmData";
 		$.post(url,function (ret) {
-			console.log(ret); //2025-05-12 11:23:30 【OP060A-后梁FSW】异常报警:000020015308-0100101425042600115
 			if(ret.result == "true"){
-				str = ret.data.createDate+" 【"+ret.data.oprno+"-"+ret.data.title+"】"+ret.data.remark+":"+ret.data.sn;
-				$("#dangerbox").show().html(str)
+				let str = ret.data.createDate+" 【"+ret.data.oprno+"-"+ret.data.title+"】"+ret.data.remark+""+ret.data.sn;
+				$("#dangerbox").show().text(str);
 			}else{
-				$("#dangerbox").hide().html("");
+				$("#dangerbox").hide().text("");
 			}
 		});
 	}
 
 	function formatData(){
+		let pageData = getPageData();
+		renderOverview(pageData);
+		renderTable(pageData.list);
+		renderCharts(pageData.list);
+		if (pageData.totalPages > 1) {
+			pageIndex = (pageIndex + 1) % pageData.totalPages;
+		}
+	}
+
+	function getPageData() {
+		let totalPages = Math.ceil(lists.length / pageSize);
+		if (totalPages < 1) {
+			totalPages = 1;
+		}
+		if (pageIndex >= totalPages) {
+			pageIndex = 0;
+		}
+		let start = pageIndex * pageSize;
+		let end = start + pageSize;
+		return {
+			list: lists.slice(start, end),
+			totalPages: totalPages,
+			currentPage: lists.length ? pageIndex + 1 : 0
+		};
+	}
+
+	function renderOverview(pageData) {
+		let totalShift = normalizeNumber(overviewData.totalShift);
+		let totalDay = normalizeNumber(overviewData.totalDay);
+		let shiftOkCount = normalizeNumber(overviewData.shiftOkCount);
+		let shiftNgCount = normalizeNumber(overviewData.shiftNgCount);
+		let rate = normalizeDecimal(overviewData.qualityRate).toFixed(1);
+		$("#overviewCount").text(normalizeNumber(46));
+		$("#overviewPageCount").text("当前页 " + pageData.list.length + " 个工位");
+		$("#overviewShift").text(totalShift);
+		$("#overviewDay").text(totalDay);
+		$("#overviewRate").text(rate + "%");
+		$("#overviewPage").text("OK " + shiftOkCount + " / NG " + shiftNgCount);
+	}
+
+	function renderTable(dataList) {
 		let str = '';
-		if(curIdx == 0){
-			curIdx = 1;
-			let i = 0;
-			for (let o in lists) {
-				if(i < 9){
-					str += '<div class="oprnobox-list">';
-					str += '<div class="oprno-num">'+lists[o].oprno+'</div>';
-					str += '<div class="oprno-right">';
-					str += '<div class="oprno-title">'+lists[o].title+'</div>';
-					str += '<div class="oprno-val">'+lists[o].shiftCount+'/'+lists[o].dayCount+'</div>';
-					str += '<div class="oprno-val">'+lists[o].shift5308+'/'+lists[o].day5308+'</div>';
-					str += '<div class="oprno-val">'+lists[o].shift5305+'/'+lists[o].day5305+'</div>';
-					str += '<div class="oprno-val">'+lists[o].shift8302+'/'+lists[o].day8302+'</div>';
-					str += '<div class="oprno-val">'+lists[o].shift8301+'/'+lists[o].day8301+'</div>';
-					str += '<div class="oprno-val">'+lists[o].shift7939+'/'+lists[o].day7939+'</div>';
-					str += '<div class="oprno-val">'+lists[o].shift7933+'/'+lists[o].day7933+'</div>';
-					str += '<div class="oprno-val">'+lists[o].shiftyn+'/'+lists[o].dayyn+'</div>';
-					str += '</div>';
-					str += '</div>';
+		if (!dataList.length) {
+			str = '<div class="empty-box">暂无生产数据</div>';
+			$("#numbox").html(str);
+			return;
+		}
+		$.each(dataList, function (idx, item) {
+			let shiftCount = normalizeNumber(item.shiftCount);
+			let dayCount = normalizeNumber(item.dayCount);
+			let rateValue = normalizeDecimal(item.qualityRate);
+			let rateWidth = Math.max(6, Math.min(rateValue, 100));
+			str += '<div class="oprnobox-list">';
+			str += '<div class="oprno-num">' + escapeHtml(item.oprno) + '</div>';
+			str += '<div class="oprno-title">' + escapeHtml(item.title) + '</div>';
+			str += '<div class="oprno-shift">' + shiftCount + '</div>';
+			str += '<div class="oprno-day">' + dayCount + '</div>';
+			str += '<div class="oprno-rate">';
+			str += '<div class="rate-box">';
+			str += '<div class="rate-track"><div class="rate-bar" style="width:' + rateWidth + '%;"></div></div>';
+			str += '<div class="rate-text">' + rateValue.toFixed(1) + '%</div>';
+			str += '</div>';
+			str += '</div>';
+			str += '</div>';
+		});
+		$("#numbox").html(str);
+	}
+
+	function renderCharts(dataList) {
+		renderShiftDayChart(dataList);
+		renderTopChart();
+	}
+
+	function renderShiftDayChart(dataList) {
+		if (!shiftDayChart) {
+			return;
+		}
+		if (!dataList.length) {
+			shiftDayChart.clear();
+			return;
+		}
+		let categories = [];
+		let shiftData = [];
+		let dayData = [];
+		$.each(dataList, function (idx, item) {
+			categories.push(item.oprno || '');
+			shiftData.push(normalizeNumber(item.shiftCount));
+			dayData.push(normalizeNumber(item.dayCount));
+		});
+		shiftDayChart.setOption({
+			backgroundColor: 'transparent',
+			tooltip: {
+				trigger: 'axis'
+			},
+			legend: {
+				top: 6,
+				right: 10,
+				textStyle: {
+					color: '#BFE8FF'
+				},
+				data: ['当班产值', '当日产值']
+			},
+			grid: {
+				top: 46,
+				left: 44,
+				right: 22,
+				bottom: 42,
+				borderWidth: 0
+			},
+			xAxis: [
+				{
+					type: 'category',
+					data: categories,
+					axisLine: {
+						lineStyle: {
+							color: 'rgba(120, 187, 255, 0.35)'
+						}
+					},
+					axisLabel: {
+						textStyle: {
+							color: '#CDEFFF',
+							fontSize: 12
+						}
+					}
 				}
-				i++;
-			}
-		}else{
-			curIdx = 0;
-			let i = 0;
-			for (let o in lists) {
-				if(i >= 9){
-					str += '<div class="oprnobox-list">';
-					str += '<div class="oprno-num">'+lists[o].oprno+'</div>';
-					str += '<div class="oprno-right">';
-					str += '<div class="oprno-title">'+lists[o].title+'</div>';
-					str += '<div class="oprno-val">'+lists[o].shiftCount+'/'+lists[o].dayCount+'</div>';
-					str += '<div class="oprno-val">'+lists[o].shift5308+'/'+lists[o].day5308+'</div>';
-					str += '<div class="oprno-val">'+lists[o].shift5305+'/'+lists[o].day5305+'</div>';
-					str += '<div class="oprno-val">'+lists[o].shift8302+'/'+lists[o].day8302+'</div>';
-					str += '<div class="oprno-val">'+lists[o].shift8301+'/'+lists[o].day8301+'</div>';
-					str += '<div class="oprno-val">'+lists[o].shift7939+'/'+lists[o].day7939+'</div>';
-					str += '<div class="oprno-val">'+lists[o].shift7933+'/'+lists[o].day7933+'</div>';
-					str += '<div class="oprno-val">'+lists[o].shiftyn+'/'+lists[o].dayyn+'</div>';
-					str += '</div>';
-					str += '</div>';
+			],
+			yAxis: [
+				{
+					type: 'value',
+					axisLine: {
+						lineStyle: {
+							color: 'rgba(120, 187, 255, 0.35)'
+						}
+					},
+					splitLine: {
+						lineStyle: {
+							color: 'rgba(120, 187, 255, 0.12)'
+						}
+					},
+					axisLabel: {
+						textStyle: {
+							color: '#CDEFFF',
+							fontSize: 12
+						}
+					}
 				}
-				i++;
-			}
+			],
+			series: [
+				{
+					name: '当班产值',
+					type: 'bar',
+					barMaxWidth: 18,
+					itemStyle: {
+						normal: {
+							color: '#1FD6FF'
+						}
+					},
+					data: shiftData
+				},
+				{
+					name: '当日产值',
+					type: 'bar',
+					barMaxWidth: 18,
+					itemStyle: {
+						normal: {
+							color: '#35E595'
+						}
+					},
+					data: dayData
+				}
+			]
+		}, true);
+	}
+
+	function renderTopChart() {
+		if (!topChart) {
+			return;
 		}
-		$("#numbox").html(str);
+		if (!topListData.length) {
+			topChart.clear();
+			return;
+		}
+		let categories = [];
+		let values = [];
+		$.each(topListData, function (idx, item) {
+			categories.push(item.oprno || '');
+			values.push(normalizeNumber(item.dayCount));
+		});
+		topChart.setOption({
+			backgroundColor: 'transparent',
+			tooltip: {
+				trigger: 'axis',
+				axisPointer: {
+					type: 'shadow'
+				}
+			},
+			grid: {
+				top: 16,
+				left: 90,
+				right: 30,
+				bottom: 18,
+				borderWidth: 0
+			},
+			xAxis: [
+				{
+					type: 'value',
+					splitLine: {
+						lineStyle: {
+							color: 'rgba(120, 187, 255, 0.12)'
+						}
+					},
+					axisLine: {
+						lineStyle: {
+							color: 'rgba(120, 187, 255, 0.35)'
+						}
+					},
+					axisLabel: {
+						textStyle: {
+							color: '#CDEFFF',
+							fontSize: 12
+						}
+					}
+				}
+			],
+			yAxis: [
+				{
+					type: 'category',
+					data: categories,
+					axisLine: {
+						lineStyle: {
+							color: 'rgba(120, 187, 255, 0.35)'
+						}
+					},
+					axisTick: {
+						show: false
+					},
+					axisLabel: {
+						textStyle: {
+							color: '#CDEFFF',
+							fontSize: 12
+						}
+					}
+				}
+			],
+			series: [
+				{
+					name: '当日产值',
+					type: 'bar',
+					barMaxWidth: 18,
+					itemStyle: {
+						normal: {
+							color: '#3C86FF',
+							label: {
+								show: true,
+								position: 'right',
+								textStyle: {
+									color: '#E4F7FF'
+								}
+							}
+						}
+					},
+					data: values
+				}
+			]
+		}, true);
+	}
+
+	function normalizeNumber(value) {
+		let num = parseInt(value, 10);
+		return isNaN(num) ? 0 : num;
+	}
+
+	function normalizeDecimal(value) {
+		let num = parseFloat(value);
+		return isNaN(num) ? 0 : num;
+	}
+
+	function escapeHtml(value) {
+		let text = value == null ? '' : String(value);
+		return text
+			.replace(/&/g, '&amp;')
+			.replace(/</g, '&lt;')
+			.replace(/>/g, '&gt;')
+			.replace(/"/g, '&quot;')
+			.replace(/'/g, '&#39;');
 	}
 
 	function changeZoom() {
@@ -300,4 +659,4 @@
 
 </script>
 </body>
-</html>
+</html>