wangxichen 1 هفته پیش
والد
کامیت
8e077dcc19

+ 15 - 0
src/main/java/com/jeesite/modules/mes/dao/MesDailyPieceworkDao.java

@@ -0,0 +1,15 @@
+package com.jeesite.modules.mes.dao;
+
+import com.jeesite.common.dao.CrudDao;
+import com.jeesite.common.mybatis.annotation.MyBatisDao;
+import com.jeesite.modules.mes.entity.MesDailyPiecework;
+
+/**
+ * 每日计件统计DAO接口
+ * @author system
+ * @version 2025-12-16
+ */
+@MyBatisDao
+public interface MesDailyPieceworkDao extends CrudDao<MesDailyPiecework> {
+	
+}

+ 167 - 0
src/main/java/com/jeesite/modules/mes/entity/MesDailyPiecework.java

@@ -0,0 +1,167 @@
+package com.jeesite.modules.mes.entity;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.jeesite.common.entity.DataEntity;
+import com.jeesite.common.mybatis.annotation.Column;
+import com.jeesite.common.mybatis.annotation.Table;
+import com.jeesite.common.utils.excel.annotation.ExcelField;
+import com.jeesite.common.utils.excel.annotation.ExcelField.Align;
+import com.jeesite.common.utils.excel.annotation.ExcelFields;
+
+import java.util.Date;
+
+/**
+ * 每日计件统计Entity
+ * @author system
+ * @version 2025-12-16
+ */
+@Table(name="mes_product_record", alias="a", label="每日计件统计", columns={
+		@Column(name="id", attrName="id", label="id", isPK=true),
+	}, orderBy="a.stat_date DESC, a.oprno ASC"
+)
+public class MesDailyPiecework extends DataEntity<MesDailyPiecework> {
+	
+	private static final long serialVersionUID = 1L;
+	
+	@ExcelFields({
+		@ExcelField(title="日期", attrName="statDate", align=Align.CENTER, sort=10, dataFormat="yyyy-MM-dd"),
+		@ExcelField(title="工位", attrName="oprno", align=Align.CENTER, sort=20),
+		@ExcelField(title="工位名称", attrName="processTitle", align=Align.CENTER, sort=30),
+		@ExcelField(title="计划数量", attrName="planCount", align=Align.CENTER, sort=40),
+		@ExcelField(title="实际产出", attrName="actualCount", align=Align.CENTER, sort=50),
+		@ExcelField(title="不良数", attrName="ngCount", align=Align.CENTER, sort=60),
+		@ExcelField(title="达成率", attrName="achievementRate", align=Align.CENTER, sort=70),
+		@ExcelField(title="合格率", attrName="qualifiedRate", align=Align.CENTER, sort=80)
+	})
+	
+	private Date statDate;			// 统计日期
+	private String statDateStr;		// 统计日期字符串
+	private String oprno;			// 工位号
+	private String processTitle;	// 工位名称
+	private String lineSn;			// 产线编号
+	private Integer planCount;		// 计划数量
+	private Integer actualCount;	// 实际产出(总数)
+	private Integer okCount;		// 合格数(从SQL查询中获取)
+	private Integer ngCount;		// 不良数
+	private String achievementRate;	// 达成率
+	private String qualifiedRate;	// 合格率
+	
+	// 查询条件
+	private Date startDate;			// 开始日期
+	private Date endDate;			// 结束日期
+	
+	public MesDailyPiecework() {
+		this(null);
+	}
+	
+	public MesDailyPiecework(String id){
+		super(id);
+	}
+	
+	@JsonFormat(pattern = "yyyy-MM-dd")
+	public Date getStatDate() {
+		return statDate;
+	}
+
+	public void setStatDate(Date statDate) {
+		this.statDate = statDate;
+	}
+	
+	public String getStatDateStr() {
+		return statDateStr;
+	}
+
+	public void setStatDateStr(String statDateStr) {
+		this.statDateStr = statDateStr;
+	}
+
+	public String getOprno() {
+		return oprno;
+	}
+
+	public void setOprno(String oprno) {
+		this.oprno = oprno;
+	}
+
+	public String getProcessTitle() {
+		return processTitle;
+	}
+
+	public void setProcessTitle(String processTitle) {
+		this.processTitle = processTitle;
+	}
+
+	public String getLineSn() {
+		return lineSn;
+	}
+
+	public void setLineSn(String lineSn) {
+		this.lineSn = lineSn;
+	}
+
+	public Integer getPlanCount() {
+		return planCount;
+	}
+
+	public void setPlanCount(Integer planCount) {
+		this.planCount = planCount;
+	}
+
+	public Integer getActualCount() {
+		return actualCount;
+	}
+
+	public void setActualCount(Integer actualCount) {
+		this.actualCount = actualCount;
+	}
+
+	public Integer getOkCount() {
+		return okCount;
+	}
+
+	public void setOkCount(Integer okCount) {
+		this.okCount = okCount;
+	}
+
+	public Integer getNgCount() {
+		return ngCount;
+	}
+
+	public void setNgCount(Integer ngCount) {
+		this.ngCount = ngCount;
+	}
+
+	public String getAchievementRate() {
+		return achievementRate;
+	}
+
+	public void setAchievementRate(String achievementRate) {
+		this.achievementRate = achievementRate;
+	}
+
+	public String getQualifiedRate() {
+		return qualifiedRate;
+	}
+
+	public void setQualifiedRate(String qualifiedRate) {
+		this.qualifiedRate = qualifiedRate;
+	}
+
+	@JsonFormat(pattern = "yyyy-MM-dd")
+	public Date getStartDate() {
+		return startDate;
+	}
+
+	public void setStartDate(Date startDate) {
+		this.startDate = startDate;
+	}
+
+	@JsonFormat(pattern = "yyyy-MM-dd")
+	public Date getEndDate() {
+		return endDate;
+	}
+
+	public void setEndDate(Date endDate) {
+		this.endDate = endDate;
+	}
+}

+ 277 - 0
src/main/java/com/jeesite/modules/mes/service/MesDailyPieceworkService.java

@@ -0,0 +1,277 @@
+package com.jeesite.modules.mes.service;
+
+import com.jeesite.common.entity.Page;
+import com.jeesite.common.mybatis.mapper.query.QueryType;
+import com.jeesite.common.service.CrudService;
+import com.jeesite.modules.mes.dao.MesDailyPieceworkDao;
+import com.jeesite.modules.mes.entity.MesDailyPiecework;
+import com.jeesite.modules.mes.entity.MesLineProcess;
+import com.jeesite.modules.mes.entity.MesScreenPlan;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.text.DecimalFormat;
+import java.text.SimpleDateFormat;
+import java.time.LocalDate;
+import java.time.format.DateTimeFormatter;
+import java.util.ArrayList;
+import java.util.Calendar;
+import java.util.Date;
+import java.util.List;
+
+/**
+ * 每日计件统计Service
+ * @author system
+ * @version 2025-12-16
+ */
+@Service
+public class MesDailyPieceworkService extends CrudService<MesDailyPieceworkDao, MesDailyPiecework> {
+
+	@Autowired
+	private MesScreenPlanService mesScreenPlanService;
+	
+	@Autowired
+	private MesLineProcessService mesLineProcessService;
+	
+	@Autowired
+	private MesProductRecordService mesProductRecordService;
+
+	/**
+	 * 查询分页数据(完全按照大屏逻辑)
+	 * @param mesDailyPiecework 查询条件
+	 * @return
+	 */
+	@Override
+	public Page<MesDailyPiecework> findPage(MesDailyPiecework mesDailyPiecework) {
+		// 设置默认查询条件(昨天和前天,共2天)
+		setDefaultDateRange(mesDailyPiecework);
+		
+		// 生成完整的数据列表(和大屏一样的逻辑)
+		List<MesDailyPiecework> fullList = generateDataList(mesDailyPiecework);
+		
+		// 手动分页
+		Page<MesDailyPiecework> page = mesDailyPiecework.getPage();
+		if (page == null) {
+			page = new Page<>();
+			page.setPageNo(1);
+			page.setPageSize(20);
+		}
+		
+		page.setCount(fullList.size());
+		
+		int pageNo = page.getPageNo();
+		int pageSize = page.getPageSize();
+		int fromIndex = (pageNo - 1) * pageSize;
+		int toIndex = Math.min(fromIndex + pageSize, fullList.size());
+		
+		if (fromIndex < fullList.size()) {
+			page.setList(fullList.subList(fromIndex, toIndex));
+		} else {
+			page.setList(new ArrayList<>());
+		}
+		
+		return page;
+	}
+
+	/**
+	 * 按天分批查询分页数据(优化性能)
+	 * @param mesDailyPiecework 查询条件
+	 * @param dayOffset 天数偏移,1=昨天,2=前天,null=按原逻辑查询2天
+	 * @return
+	 */
+	public Page<MesDailyPiecework> findPageByDay(MesDailyPiecework mesDailyPiecework, Integer dayOffset) {
+		// 如果没有指定dayOffset,按原逻辑查询
+		if (dayOffset == null) {
+			return findPage(mesDailyPiecework);
+		}
+		
+		// 根据dayOffset设置单天查询范围
+		Calendar cal = Calendar.getInstance();
+		cal.set(Calendar.HOUR_OF_DAY, 0);
+		cal.set(Calendar.MINUTE, 0);
+		cal.set(Calendar.SECOND, 0);
+		cal.set(Calendar.MILLISECOND, 0);
+		cal.add(Calendar.DAY_OF_MONTH, -dayOffset); // 往前推指定天数
+		
+		// 设置为查询单天
+		mesDailyPiecework.setStartDate(cal.getTime());
+		mesDailyPiecework.setEndDate(cal.getTime());
+		
+		// 生成该天的数据列表
+		List<MesDailyPiecework> fullList = generateDataList(mesDailyPiecework);
+		
+		// 手动分页
+		Page<MesDailyPiecework> page = mesDailyPiecework.getPage();
+		if (page == null) {
+			page = new Page<>();
+			page.setPageNo(1);
+			page.setPageSize(20);
+		}
+		
+		page.setCount(fullList.size());
+		
+		int pageNo = page.getPageNo();
+		int pageSize = page.getPageSize();
+		int fromIndex = (pageNo - 1) * pageSize;
+		int toIndex = Math.min(fromIndex + pageSize, fullList.size());
+		
+		if (fromIndex < fullList.size()) {
+			page.setList(fullList.subList(fromIndex, toIndex));
+		} else {
+			page.setList(new ArrayList<>());
+		}
+		
+		return page;
+	}
+	
+	/**
+	 * 查询列表数据(用于导出)
+	 * @param mesDailyPiecework
+	 * @return
+	 */
+	@Override
+	public List<MesDailyPiecework> findList(MesDailyPiecework mesDailyPiecework) {
+		// 导出时如果没有指定日期,则导出上一个月的数据
+		if (mesDailyPiecework.getStartDate() == null && mesDailyPiecework.getEndDate() == null) {
+			Calendar cal = Calendar.getInstance();
+			
+			// 设置为上个月的最后一天
+			cal.set(Calendar.DAY_OF_MONTH, 1); // 本月1号
+			cal.add(Calendar.DAY_OF_MONTH, -1); // 上月最后一天
+			cal.set(Calendar.HOUR_OF_DAY, 0);
+			cal.set(Calendar.MINUTE, 0);
+			cal.set(Calendar.SECOND, 0);
+			cal.set(Calendar.MILLISECOND, 0);
+			mesDailyPiecework.setEndDate(cal.getTime());
+			
+			// 设置为上个月的第一天
+			cal.set(Calendar.DAY_OF_MONTH, 1); // 上月1号
+			mesDailyPiecework.setStartDate(cal.getTime());
+		}
+		
+		// 生成完整的数据列表(和大屏一样的逻辑)
+		return generateDataList(mesDailyPiecework);
+	}
+	
+	/**
+	 * 设置默认日期范围(昨天和前天,共2天)
+	 */
+	private void setDefaultDateRange(MesDailyPiecework mesDailyPiecework) {
+		if (mesDailyPiecework.getStartDate() == null && mesDailyPiecework.getEndDate() == null) {
+			Calendar cal = Calendar.getInstance();
+			cal.set(Calendar.HOUR_OF_DAY, 0);
+			cal.set(Calendar.MINUTE, 0);
+			cal.set(Calendar.SECOND, 0);
+			cal.set(Calendar.MILLISECOND, 0);
+			cal.add(Calendar.DAY_OF_MONTH, -1); // 往前推1天,昨天
+			mesDailyPiecework.setEndDate(cal.getTime()); // 昨天 00:00:00
+			
+			cal.add(Calendar.DAY_OF_MONTH, -1); // 再往前推1天,前天
+			mesDailyPiecework.setStartDate(cal.getTime()); // 前天 00:00:00
+		}
+	}
+	
+	/**
+	 * 生成数据列表(完全按照大屏逻辑)
+	 */
+	private List<MesDailyPiecework> generateDataList(MesDailyPiecework mesDailyPiecework) {
+		List<MesDailyPiecework> resultList = new ArrayList<>();
+		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
+		DecimalFormat df = new DecimalFormat("0.00");
+		DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
+		
+		// 1. 查询所有主工位(和大屏一样)
+		MesLineProcess mesLineProcess = new MesLineProcess();
+		mesLineProcess.setStatus("0");
+		mesLineProcess.getSqlMap().getWhere().and("pid", QueryType.IS_NULL, "");
+		List<MesLineProcess> processList = mesLineProcessService.findList(mesLineProcess);
+		
+		// 如果指定了工位号,则过滤
+		if (mesDailyPiecework.getOprno() != null && !mesDailyPiecework.getOprno().isEmpty()) {
+			String searchOprno = mesDailyPiecework.getOprno();
+			processList.removeIf(p -> !p.getOprno().contains(searchOprno));
+		}
+		
+		// 2. 生成日期列表
+		Calendar startCal = Calendar.getInstance();
+		startCal.setTime(mesDailyPiecework.getStartDate());
+		Calendar endCal = Calendar.getInstance();
+		endCal.setTime(mesDailyPiecework.getEndDate());
+		
+		// 3. 遍历每一天
+		while (!startCal.after(endCal)) {
+			Date currentDate = startCal.getTime();
+			String dateStr = sdf.format(currentDate);
+			
+			// 计算当天的时间范围(08:00到次日08:00,和大屏一样)
+			LocalDate localDate = LocalDate.parse(dateStr, formatter);
+			LocalDate tomorrow = localDate.plusDays(1);
+			String sdate = dateStr + " 08:00:00";
+			String edate = tomorrow.format(formatter) + " 08:00:00";
+			
+			// 获取当天的计划
+			MesScreenPlan plan = mesScreenPlanService.getPlan(dateStr);
+			
+			// 4. 遍历每个工位(和大屏一样)
+			for (MesLineProcess process : processList) {
+				MesDailyPiecework item = new MesDailyPiecework();
+				item.setStatDate(currentDate);
+				item.setStatDateStr(dateStr);
+				item.setOprno(process.getOprno());
+				item.setProcessTitle(process.getTitle());
+				item.setLineSn(process.getLineSn());
+				
+				// 调用和大屏一样的方法获取数据
+				String dayTotal = mesProductRecordService.getSj(process.getOprno(), process.getLineSn(), sdate, edate);
+				int actualCount = Integer.parseInt(dayTotal);
+				item.setActualCount(actualCount);
+				
+				String dayOks = mesProductRecordService.getSjOk(process.getOprno(), process.getLineSn(), sdate, edate);
+				int okCount = Integer.parseInt(dayOks);
+				item.setOkCount(okCount);
+				
+				int ngCount = actualCount - okCount;
+				item.setNgCount(ngCount);
+				
+				// 设置计划数(和大屏一样的逻辑)
+				Integer planCount = 0;
+				if (plan != null) {
+					try {
+						int oprnoNum = Integer.parseInt(process.getOprno().replaceAll("[^0-9]", ""));
+						if (oprnoNum < 140) {
+							planCount = plan.getP1sx() != null ? plan.getP1sx() : 0;
+						} else {
+							planCount = plan.getP2sx() != null ? plan.getP2sx() : 0;
+						}
+					} catch (NumberFormatException e) {
+						planCount = 0;
+					}
+				}
+				item.setPlanCount(planCount);
+				
+				// 计算达成率
+				if (planCount > 0) {
+					double rate = (actualCount * 100.0) / planCount;
+					item.setAchievementRate(df.format(rate) + "%");
+				} else {
+					item.setAchievementRate("-");
+				}
+				
+				// 计算合格率
+				if (actualCount > 0) {
+					double rate = (okCount * 100.0) / actualCount;
+					item.setQualifiedRate(df.format(rate) + "%");
+				} else {
+					item.setQualifiedRate("-");
+				}
+				
+				resultList.add(item);
+			}
+			
+			// 下一天
+			startCal.add(Calendar.DAY_OF_MONTH, 1);
+		}
+		
+		return resultList;
+	}
+}

+ 79 - 0
src/main/java/com/jeesite/modules/mes/web/MesDailyPieceworkController.java

@@ -0,0 +1,79 @@
+package com.jeesite.modules.mes.web;
+
+import com.jeesite.common.entity.Page;
+import com.jeesite.common.lang.DateUtils;
+import com.jeesite.common.web.BaseController;
+import com.jeesite.modules.mes.entity.MesDailyPiecework;
+import com.jeesite.modules.mes.service.MesDailyPieceworkService;
+import com.jeesite.common.utils.excel.ExcelExport;
+import org.apache.shiro.authz.annotation.RequiresPermissions;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Controller;
+import org.springframework.ui.Model;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.ResponseBody;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.util.List;
+
+/**
+ * 每日计件统计Controller
+ * @author system
+ * @version 2025-12-16
+ */
+@Controller
+@RequestMapping(value = "${adminPath}/mes/mesDailyPiecework")
+public class MesDailyPieceworkController extends BaseController {
+
+	@Autowired
+	private MesDailyPieceworkService mesDailyPieceworkService;
+	
+	/**
+	 * 查询列表
+	 */
+	@RequiresPermissions("mes:mesDailyPiecework:view")
+	@RequestMapping(value = {"list", ""})
+	public String list(MesDailyPiecework mesDailyPiecework, Model model) {
+		model.addAttribute("mesDailyPiecework", mesDailyPiecework);
+		return "modules/mes/mesDailyPieceworkList";
+	}
+	
+	/**
+	 * 查询列表数据
+	 */
+	@RequiresPermissions("mes:mesDailyPiecework:view")
+	@RequestMapping(value = "listData")
+	@ResponseBody
+	public Page<MesDailyPiecework> listData(MesDailyPiecework mesDailyPiecework, HttpServletRequest request, HttpServletResponse response) {
+		mesDailyPiecework.setPage(new Page<>(request, response));
+		Page<MesDailyPiecework> page = mesDailyPieceworkService.findPage(mesDailyPiecework);
+		return page;
+	}
+	
+	/**
+	 * 分批查询列表数据(优化性能,先查昨天再查前天)
+	 * @param dayOffset 天数偏移,1=昨天,2=前天
+	 */
+	@RequiresPermissions("mes:mesDailyPiecework:view")
+	@RequestMapping(value = "listDataByDay")
+	@ResponseBody
+	public Page<MesDailyPiecework> listDataByDay(MesDailyPiecework mesDailyPiecework, Integer dayOffset, HttpServletRequest request, HttpServletResponse response) {
+		mesDailyPiecework.setPage(new Page<>(request, response));
+		Page<MesDailyPiecework> page = mesDailyPieceworkService.findPageByDay(mesDailyPiecework, dayOffset);
+		return page;
+	}
+	
+	/**
+	 * 导出数据
+	 */
+	@RequiresPermissions("mes:mesDailyPiecework:view")
+	@RequestMapping(value = "exportData")
+	public void exportData(MesDailyPiecework mesDailyPiecework, HttpServletResponse response) {
+		List<MesDailyPiecework> list = mesDailyPieceworkService.findList(mesDailyPiecework);
+		String fileName = "每日计件统计_" + DateUtils.getDate("yyyyMMddHHmmss") + ".xlsx";
+		try(ExcelExport ee = new ExcelExport("每日计件统计", MesDailyPiecework.class)){
+			ee.setDataList(list).write(response, fileName);
+		}
+	}
+}

+ 7 - 0
src/main/resources/mappings/modules/mes/MesDailyPieceworkDao.xml

@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.jeesite.modules.mes.dao.MesDailyPieceworkDao">
+	
+	<!-- 使用CrudDao默认方法,不需要自定义SQL -->
+	
+</mapper>

+ 129 - 0
src/main/resources/views/modules/mes/mesDailyPieceworkList.html

@@ -0,0 +1,129 @@
+<% layout('/layouts/default.html', {title: '每日计件统计', libs: ['dataGrid']}){ %>
+<div class="main-content">
+	<div class="box box-main">
+		<div class="box-header">
+			<div class="box-title">
+				<i class="fa icon-table"></i> ${text('每日计件统计')}
+			</div>
+			<div class="box-tools pull-right">
+				<a href="#" class="btn btn-default" id="btnSearch" title="${text('查询')}"><i class="fa fa-filter"></i> ${text('查询')}</a>
+				<% if(hasPermi('mes:mesDailyPiecework:view')){ %>
+					<a href="#" class="btn btn-default" id="btnExport" title="${text('导出Excel')}"><i class="fa fa-file-excel-o"></i> ${text('导出')}</a>
+				<% } %>
+				<a href="#" class="btn btn-default" id="btnSetting" title="${text('设置')}"><i class="fa fa-navicon"></i></a>
+			</div>
+		</div>
+		<div class="box-body">
+			<#form:form id="searchForm" model="${mesDailyPiecework}" action="${ctx}/mes/mesDailyPiecework/listData" method="post" class="form-inline hide"
+					data-page-no="${parameter.pageNo}" data-page-size="${parameter.pageSize}" data-order-by="${parameter.orderBy}">
+				<div class="form-group">
+					<label class="control-label">${text('开始日期')}:</label>
+					<div class="control-inline">
+						<#form:input path="startDate" readonly="true" maxlength="20" class="form-control laydate width-120"
+							dataFormat="date" data-type="date" data-format="yyyy-MM-dd" data-done="endDate.click()"/>
+					</div>
+				</div>
+				<div class="form-group">
+					<label class="control-label">${text('结束日期')}:</label>
+					<div class="control-inline">
+						<#form:input path="endDate" readonly="true" maxlength="20" class="form-control laydate width-120"
+							dataFormat="date" data-type="date" data-format="yyyy-MM-dd"/>
+					</div>
+				</div>
+				<div class="form-group">
+					<label class="control-label">${text('工位号')}:</label>
+					<div class="control-inline">
+						<#form:input path="oprno" maxlength="50" class="form-control width-120" placeholder="输入工位号"/>
+					</div>
+				</div>
+				<div class="form-group">
+					<button type="submit" class="btn btn-primary btn-sm">${text('查询')}</button>
+					<button type="reset" class="btn btn-default btn-sm">${text('重置')}</button>
+				</div>
+			</#form:form>
+			<table id="dataGrid"></table>
+			<div id="dataGridPage"></div>
+		</div>
+	</div>
+</div>
+<% } %>
+<script>
+// 初始化DataGrid对象
+var dataGridConfig = {
+	searchForm: $("#searchForm"),
+	columnModel: [
+		{header:'${text("日期")}', name:'statDateStr', index:'stat_date', width:120, align:"center", frozen:true},
+		{header:'${text("工位")}', name:'oprno', index:'a.oprno', width:100, align:"center"},
+		{header:'${text("工位名称")}', name:'processTitle', index:'process_title', width:150, align:"center"},
+		{header:'${text("计划数量")}', name:'planCount', index:'plan_count', width:100, align:"center", formatter: function(val, obj, row, act){
+			return val != null ? val : '-';
+		}},
+		{header:'${text("实际产出")}', name:'actualCount', index:'actual_count', width:100, align:"center", formatter: function(val, obj, row, act){
+			return val != null ? val : 0;
+		}},
+		{header:'${text("不良数")}', name:'ngCount', index:'ng_count', width:100, align:"center", formatter: function(val, obj, row, act){
+			return val != null ? val : 0;
+		}},
+		{header:'${text("达成率")}', name:'achievementRate', index:'achievement_rate', width:100, align:"center", formatter: function(val, obj, row, act){
+			if(val && val != '-'){
+				var rate = parseFloat(val);
+				if(rate >= 100){
+					return '<span style="color: green; font-weight: bold;">' + val + '</span>';
+				}else if(rate >= 80){
+					return '<span style="color: orange;">' + val + '</span>';
+				}else{
+					return '<span style="color: red;">' + val + '</span>';
+				}
+			}
+			return val;
+		}},
+		{header:'${text("合格率")}', name:'qualifiedRate', index:'qualified_rate', width:100, align:"center", formatter: function(val, obj, row, act){
+			if(val && val != '-'){
+				var rate = parseFloat(val);
+				if(rate >= 99){
+					return '<span style="color: green; font-weight: bold;">' + val + '</span>';
+				}else if(rate >= 95){
+					return '<span style="color: orange;">' + val + '</span>';
+				}else{
+					return '<span style="color: red;">' + val + '</span>';
+				}
+			}
+			return val;
+		}}
+	]
+};
+
+// 初始化表格
+$('#dataGrid').dataGrid(dataGridConfig);
+
+// 导出按钮事件
+$('#btnExport').click(function(){
+	js.ajaxSubmitForm($('#searchForm'), {
+		url:'${ctx}/mes/mesDailyPiecework/exportData',
+		downloadFile:true
+	});
+});
+
+// 页面加载时设置默认日期为昨天和前天
+$(function(){
+	if(!$('#startDate').val() && !$('#endDate').val()){
+		// 设置为默认查询昨天和前天
+		var today = new Date();
+		var yesterday = new Date(today);
+		yesterday.setDate(yesterday.getDate() - 1);
+		var dayBeforeYesterday = new Date(today);
+		dayBeforeYesterday.setDate(dayBeforeYesterday.getDate() - 2);
+
+		$('#startDate').val(formatDate(dayBeforeYesterday));
+		$('#endDate').val(formatDate(yesterday));
+	}
+});
+
+// 日期格式化函数
+function formatDate(date) {
+	var year = date.getFullYear();
+	var month = (date.getMonth() + 1).toString().padStart(2, '0');
+	var day = date.getDate().toString().padStart(2, '0');
+	return year + '-' + month + '-' + day;
+}
+</script>