Selaa lähdekoodia

用户管理新增二维码导出功能

dzc 1 viikko sitten
vanhempi
commit
21ce7ff4dd

+ 119 - 0
mappings/modules/sys/EmpUserDao.xml

@@ -0,0 +1,119 @@
+<?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.sys.dao.EmpUserDao">
+    
+    <!-- 查询数据  -->
+	<select id="findList" resultType="EmpUser">
+		SELECT ${sqlMap.column.toSql()}
+		FROM ${sqlMap.table.toSql()}
+		<if test="roleCode != null and roleCode != ''">
+			JOIN ${_prefix}sys_user_role ur2 ON ur2.user_code = a.user_code
+		</if>
+		<if test="employee.postCode != null and employee.postCode != ''">
+			JOIN ${_prefix}sys_employee_post ep ON e.emp_code = ep.emp_code
+		</if>
+		<where>
+			${sqlMap.where.toSql()}
+			<if test="roleCode != null and roleCode != ''">
+				AND ur2.role_code = #{roleCode}
+			</if>
+			<if test="employee.postCode != null and employee.postCode != ''">
+				AND (
+					ep.post_code = #{employee.postCode}
+					OR EXISTS (
+						SELECT 1 FROM ${_prefix}sys_employee_office
+						WHERE emp_code = e.emp_code
+							AND post_code = #{employee.postCode}
+					)
+				)
+			</if>
+			<!-- 附属部门查询,根据业务需要添加查询条件
+			<if test="employee.office.officeCode != null and employee.office.officeCode != ''">
+				OR EXISTS (
+					SELECT 1 FROM ${_prefix}sys_employee_office
+					WHERE emp_code = e.emp_code
+						AND office_code = #{employee.office.officeCode}
+				)
+			</if> -->
+		</where>
+		ORDER BY ${sqlMap.order.toSql()}
+	</select>
+	
+	<sql id="userColumns">
+		a.user_code as "userCode",
+		a.user_name as "userName"
+	</sql>
+	
+	<!-- 查询全部用户,仅返回基本信息  -->
+	<select id="findUserList" resultType="EmpUser">
+		SELECT 
+		    <include refid="userColumns"/>
+		FROM ${_prefix}sys_user a
+		WHERE a.status = #{STATUS_NORMAL}
+			AND a.user_type = #{USER_TYPE_EMPLOYEE}
+			<if test="global.useCorpModel">
+		    	AND a.corp_code = #{corpCode}
+		    </if>
+	</select>
+	
+	<!-- 根据部门编码查询用户,仅返回基本信息  -->
+	<select id="findUserListByOfficeCodes" resultType="EmpUser">
+		SELECT 
+		    <include refid="userColumns"/>
+		FROM ${_prefix}sys_user a
+		JOIN ${_prefix}sys_employee e ON e.emp_code = a.ref_code
+		JOIN ${_prefix}sys_office o ON o.office_code = e.office_code
+		WHERE a.status = #{STATUS_NORMAL}
+			AND a.user_type = #{USER_TYPE_EMPLOYEE}
+			<if test="global.useCorpModel">
+		    	AND a.corp_code = #{corpCode}
+		    </if>
+		    AND e.status = #{STATUS_NORMAL}
+		    AND o.status = #{STATUS_NORMAL}
+			AND o.office_code IN
+			<foreach item="code" index="index" collection="codes" open="(" separator="," close=")">
+				#{code}
+			</foreach>
+	</select>
+	
+	<!-- 根据角色编码查询用户,仅返回基本信息  -->
+	<select id="findUserListByRoleCodes" resultType="EmpUser">
+		SELECT 
+		    <include refid="userColumns"/>
+		FROM ${_prefix}sys_user a
+		JOIN ${_prefix}sys_user_role ur2 ON ur2.user_code = a.user_code
+		JOIN ${_prefix}sys_role r ON r.role_code = ur2.role_code
+		WHERE a.status = #{STATUS_NORMAL}
+			AND a.user_type = #{USER_TYPE_EMPLOYEE}
+			<if test="global.useCorpModel">
+		    	AND a.corp_code = #{corpCode}
+		    </if>
+		    AND r.status = #{STATUS_NORMAL}
+			AND r.role_code IN
+			<foreach item="code" index="index" collection="codes" open="(" separator="," close=")">
+				#{code}
+			</foreach>
+	</select>
+	
+	<!-- 根据岗位编码查询用户,仅返回基本信息  -->
+	<select id="findUserListByPostCodes" resultType="EmpUser">
+		SELECT 
+		    <include refid="userColumns"/>
+		FROM ${_prefix}sys_user a
+		JOIN ${_prefix}sys_employee e ON e.emp_code = a.ref_code
+		JOIN ${_prefix}sys_employee_post ep ON ep.emp_code = e.emp_code
+		JOIN ${_prefix}sys_post p ON p.post_code = ep.post_code
+		WHERE a.status = #{STATUS_NORMAL}
+			AND a.user_type = #{USER_TYPE_EMPLOYEE}
+			<if test="global.useCorpModel">
+		    	AND a.corp_code = #{corpCode}
+		    </if>
+		    AND e.status = #{STATUS_NORMAL}
+		    AND p.status = #{STATUS_NORMAL}
+			AND p.post_code IN
+			<foreach item="code" index="index" collection="codes" open="(" separator="," close=")">
+				#{code}
+			</foreach>
+	</select>
+	
+</mapper>

+ 15 - 0
mappings/modules/sys/UserDataScopeDao.xml

@@ -0,0 +1,15 @@
+<?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.sys.dao.UserDataScopeDao">
+	
+	<!-- 查询数据
+	<select id="findList" resultType="UserDataScope">
+		SELECT ${sqlMap.column.toSql()}
+		FROM ${sqlMap.table.toSql()}
+		<where>
+			${sqlMap.where.toSql()}
+		</where>
+		ORDER BY ${sqlMap.order.toSql()}
+	</select> -->
+	
+</mapper>

+ 5 - 0
src/main/java/com/jeesite/modules/mes/dao/MesUserSkillDao.java

@@ -14,4 +14,9 @@ import java.util.List;
 @MyBatisDao
 public interface MesUserSkillDao extends CrudDao<MesUserSkill> {
     List<MesUserSkill> findListBySkillId(MesUserSkill mesUserSkill);
+
+    /**
+     * 导出用技能列表(LEFT JOIN,避免关联缺失导致查不到)
+     */
+    List<MesUserSkill> findExportList();
 }

+ 59 - 3
src/main/java/com/jeesite/modules/mes/entity/MesLineProcessUser.java

@@ -1,6 +1,5 @@
 package com.jeesite.modules.mes.entity;
 
-import javax.validation.constraints.Size;
 import com.jeesite.modules.sys.entity.User;
 import com.jeesite.common.mybatis.annotation.JoinTable;
 import com.jeesite.common.mybatis.annotation.JoinTable.Type;
@@ -8,7 +7,6 @@ import com.jeesite.common.mybatis.annotation.JoinTable.Type;
 import com.jeesite.common.entity.DataEntity;
 import com.jeesite.common.mybatis.annotation.Column;
 import com.jeesite.common.mybatis.annotation.Table;
-import com.jeesite.common.mybatis.mapper.query.QueryType;
 
 /**
  * 生成工序表Entity
@@ -26,8 +24,21 @@ import com.jeesite.common.mybatis.mapper.query.QueryType;
 						on="a.user_code = b.user_code",
 						columns={
 								@Column(name="user_name", attrName="userName", label="用户"),
+								@Column(name="login_code", attrName="loginCode", label="登录账号"),
+								@Column(name="ref_name", attrName="refName", label="员工姓名"),
 						}),
-		}, orderBy="a.id ASC"
+				@JoinTable(type= Type.LEFT_JOIN, entity=MesLineProcess.class, attrName="this", alias="p",
+						on="a.line_process_id = p.id",
+						columns={
+								@Column(name="oprno", attrName="oprno", label="工位号"),
+								@Column(name="title", attrName="oprnoTitle", label="工位名称"),
+						}),
+				@JoinTable(type= Type.LEFT_JOIN, entity=MesLine.class, attrName="this", alias="l",
+						on="p.line_id = l.id",
+						columns={
+								@Column(name="sn", attrName="lineSn", label="产线编号"),
+						}),
+		}, orderBy="b.login_code ASC, p.oprno ASC, a.id ASC"
 )
 public class MesLineProcessUser extends DataEntity<MesLineProcessUser> {
 	
@@ -35,7 +46,12 @@ public class MesLineProcessUser extends DataEntity<MesLineProcessUser> {
 	private String lineProcessId;
 	private String userCode;
 	private String userName;// 用户
+	private String loginCode;
+	private String refName;
 	private String auth;
+	private String oprno;
+	private String oprnoTitle;
+	private String lineSn;
 
 	public MesLineProcessUser() {
 		this(null);
@@ -76,4 +92,44 @@ public class MesLineProcessUser extends DataEntity<MesLineProcessUser> {
 	public void setAuth(String auth) {
 		this.auth = auth;
 	}
+
+	public String getLoginCode() {
+		return loginCode;
+	}
+
+	public void setLoginCode(String loginCode) {
+		this.loginCode = loginCode;
+	}
+
+	public String getRefName() {
+		return refName;
+	}
+
+	public void setRefName(String refName) {
+		this.refName = refName;
+	}
+
+	public String getOprno() {
+		return oprno;
+	}
+
+	public void setOprno(String oprno) {
+		this.oprno = oprno;
+	}
+
+	public String getOprnoTitle() {
+		return oprnoTitle;
+	}
+
+	public void setOprnoTitle(String oprnoTitle) {
+		this.oprnoTitle = oprnoTitle;
+	}
+
+	public String getLineSn() {
+		return lineSn;
+	}
+
+	public void setLineSn(String lineSn) {
+		this.lineSn = lineSn;
+	}
 }

+ 114 - 0
src/main/java/com/jeesite/modules/mes/entity/MesUserAuthExport.java

@@ -0,0 +1,114 @@
+package com.jeesite.modules.mes.entity;
+
+
+
+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;
+
+
+
+/**
+
+ * 员工权限导出
+
+ */
+
+public class MesUserAuthExport {
+
+
+
+	private String userName;
+
+	private String roleNames;
+
+	private String oprnoAuth;
+
+	private String qrcode;
+
+
+
+	@ExcelFields({
+
+		@ExcelField(title="用户昵称", attrName="userName", align=Align.CENTER, sort=10),
+
+		@ExcelField(title="分配角色", attrName="roleNames", align=Align.CENTER, sort=20),
+
+		@ExcelField(title="二维码", attrName="qrcode", align=Align.CENTER, sort=30),
+
+		@ExcelField(title="工位授权", attrName="oprnoAuth", align=Align.CENTER, sort=40),
+
+	})
+
+	public MesUserAuthExport() {
+
+	}
+
+
+
+	public String getUserName() {
+
+		return userName;
+
+	}
+
+
+
+	public void setUserName(String userName) {
+
+		this.userName = userName;
+
+	}
+
+
+
+	public String getRoleNames() {
+
+		return roleNames;
+
+	}
+
+
+
+	public void setRoleNames(String roleNames) {
+
+		this.roleNames = roleNames;
+
+	}
+
+
+
+	public String getOprnoAuth() {
+
+		return oprnoAuth;
+
+	}
+
+
+
+	public void setOprnoAuth(String oprnoAuth) {
+
+		this.oprnoAuth = oprnoAuth;
+
+	}
+
+
+
+	public String getQrcode() {
+
+		return qrcode;
+
+	}
+
+
+
+	public void setQrcode(String qrcode) {
+
+		this.qrcode = qrcode;
+
+	}
+
+}
+

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

@@ -131,6 +131,11 @@ public class MesDeviceTimeService extends CrudService<MesDeviceTimeDao, MesDevic
 	//开始工作
 	@Transactional
 	public String add(MesDeviceTime mesDeviceTime) {
+
+		if(mesDeviceTime.getStartDate()==null)
+		{
+			mesDeviceTime.setStartDate(new Date());
+		}
 		Long time = mesDeviceTime.getStartDate().getTime();
 		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
 		String format = sdf.format(time);// 格式化时间

+ 298 - 0
src/main/java/com/jeesite/modules/mes/service/MesEmpUserExportService.java

@@ -0,0 +1,298 @@
+package com.jeesite.modules.mes.service;
+
+import cn.hutool.extra.qrcode.QrCodeUtil;
+import com.jeesite.common.codec.DesUtils;
+import com.jeesite.common.collect.ListUtils;
+import com.jeesite.common.config.Global;
+import com.jeesite.common.lang.DateUtils;
+import com.jeesite.common.lang.StringUtils;
+import com.jeesite.common.utils.excel.ExcelExport;
+import com.jeesite.modules.mes.entity.MesLineProcessUser;
+import com.jeesite.modules.mes.entity.MesUserAuthExport;
+import com.jeesite.modules.sys.dao.UserRoleDao;
+import com.jeesite.modules.sys.entity.EmpUser;
+import com.jeesite.modules.sys.entity.Role;
+import com.jeesite.modules.sys.entity.User;
+import com.jeesite.modules.sys.entity.UserRole;
+import com.jeesite.modules.sys.service.EmpUserService;
+import com.jeesite.modules.sys.service.RoleService;
+import com.jeesite.modules.sys.service.UserService;
+import org.apache.poi.ss.usermodel.Cell;
+import org.apache.poi.ss.usermodel.CellStyle;
+import org.apache.poi.ss.usermodel.CellType;
+import org.apache.poi.ss.usermodel.ClientAnchor;
+import org.apache.poi.ss.usermodel.Drawing;
+import org.apache.poi.ss.usermodel.HorizontalAlignment;
+import org.apache.poi.ss.usermodel.Row;
+import org.apache.poi.ss.usermodel.Sheet;
+import org.apache.poi.ss.usermodel.VerticalAlignment;
+import org.apache.poi.ss.usermodel.Workbook;
+import org.apache.poi.util.Units;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import javax.servlet.http.HttpServletResponse;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+/**
+ * 员工权限导出 Service
+ */
+@Service
+public class MesEmpUserExportService {
+
+	private static final int QRCODE_COLUMN_INDEX = 2;
+	private static final int QRCODE_SIZE = 200;
+	private static final int QRCODE_DISPLAY_SIZE_PX = 120;
+	private static final float QRCODE_ROW_HEIGHT = 95F;
+	private static final float MIN_ROW_HEIGHT = 15F;
+	private static final float LINE_HEIGHT = 15F;
+	/** ExcelExport 会先写标题行和表头行,数据从第 3 行开始 */
+	private static final int DATA_ROW_OFFSET = 2;
+	private static final int[] COLUMN_WIDTH_CHARS = {14, 18, 22, 50};
+	private static final String MULTI_VALUE_SEPARATOR = "、";
+
+	@Autowired
+	private EmpUserService empUserService;
+	@Autowired
+	private UserService userService;
+	@Autowired
+	private RoleService roleService;
+	@Autowired
+	private UserRoleDao userRoleDao;
+	@Autowired
+	private MesLineProcessUserService mesLineProcessUserService;
+
+	/**
+	 * 组装员工权限导出数据(一行一个用户)
+	 */
+	public List<MesUserAuthExport> findUserAuthExportList() {
+		List<EmpUser> userList = empUserService.findList(new EmpUser());
+		if (ListUtils.isEmpty(userList)) {
+			return new ArrayList<>();
+		}
+
+		Map<String, String> loginCodeMap = buildLoginCodeMap(userList);
+		Map<String, String> roleNameMap = buildRoleNameMap();
+		Map<String, List<String>> userRoleMap = buildUserRoleMap(roleNameMap);
+		Map<String, List<MesLineProcessUser>> userOprnoMap = buildUserOprnoMap();
+		String secretKey = Global.getConfig("shiro.loginSubmit.secretKey");
+
+		List<MesUserAuthExport> result = new ArrayList<>();
+		for (EmpUser user : userList) {
+			if (user == null || StringUtils.isBlank(user.getUserCode())) {
+				continue;
+			}
+			MesUserAuthExport row = new MesUserAuthExport();
+			row.setUserName(user.getUserName());
+			row.setRoleNames(joinList(userRoleMap.get(user.getUserCode())));
+			row.setOprnoAuth(defaultDisplay(formatOprnos(userOprnoMap.get(user.getUserCode()))));
+			String loginCode = loginCodeMap.get(user.getUserCode());
+			if (StringUtils.isNotBlank(loginCode)) {
+				row.setQrcode(DesUtils.encode(loginCode, secretKey));
+			}
+			result.add(row);
+		}
+		return result;
+	}
+
+	/**
+	 * 导出员工权限 Excel(二维码列嵌入图片)
+	 */
+	public void exportUserAuth(HttpServletResponse response) {
+		List<MesUserAuthExport> list = findUserAuthExportList();
+		List<String> qrcodeContents = new ArrayList<>(list.size());
+		for (MesUserAuthExport row : list) {
+			qrcodeContents.add(row.getQrcode());
+			row.setQrcode("");
+		}
+		String fileName = "员工权限导出" + DateUtils.getDate("yyyyMMddHHmmss") + ".xlsx";
+		try (ExcelExport ee = new ExcelExport("员工权限导出", MesUserAuthExport.class)) {
+			ee.setDataList(list);
+			finalizeExportSheet(ee.getWorkbook(), list.size(), qrcodeContents);
+			ee.write(response, fileName);
+		}
+	}
+
+	private void finalizeExportSheet(Workbook workbook, int dataSize, List<String> qrcodeContents) {
+		if (workbook == null || dataSize <= 0) {
+			return;
+		}
+		Sheet sheet = workbook.getNumberOfSheets() > 0 ? workbook.getSheetAt(0) : null;
+		if (sheet == null) {
+			return;
+		}
+		for (int i = 0; i < COLUMN_WIDTH_CHARS.length; i++) {
+			sheet.setColumnWidth(i, COLUMN_WIDTH_CHARS[i] * 256);
+		}
+		Drawing<?> drawing = sheet.createDrawingPatriarch();
+		for (int i = 0; i < dataSize; i++) {
+			int rowIndex = i + DATA_ROW_OFFSET;
+			Row row = sheet.getRow(rowIndex);
+			if (row == null) {
+				continue;
+			}
+			float textHeight = MIN_ROW_HEIGHT;
+			for (int col = 0; col < COLUMN_WIDTH_CHARS.length; col++) {
+				if (col == QRCODE_COLUMN_INDEX) {
+					continue;
+				}
+				Cell cell = row.getCell(col);
+				if (cell == null) {
+					continue;
+				}
+				applyWrapStyle(workbook, cell);
+				textHeight = Math.max(textHeight, calculateWrapHeight(getCellStringValue(cell), COLUMN_WIDTH_CHARS[col]));
+			}
+			boolean hasQrcode = i < qrcodeContents.size() && StringUtils.isNotBlank(qrcodeContents.get(i));
+			float rowHeight = Math.max(textHeight, hasQrcode ? QRCODE_ROW_HEIGHT : MIN_ROW_HEIGHT);
+			row.setHeightInPoints(rowHeight);
+			if (hasQrcode) {
+				appendQrcodeImage(workbook, drawing, row, rowIndex, qrcodeContents.get(i));
+			}
+		}
+	}
+
+	private void applyWrapStyle(Workbook workbook, Cell cell) {
+		CellStyle style = workbook.createCellStyle();
+		CellStyle existing = cell.getCellStyle();
+		if (existing != null) {
+			style.cloneStyleFrom(existing);
+		}
+		style.setWrapText(true);
+		style.setVerticalAlignment(VerticalAlignment.CENTER);
+		style.setAlignment(HorizontalAlignment.CENTER);
+		cell.setCellStyle(style);
+	}
+
+	private void appendQrcodeImage(Workbook workbook, Drawing<?> drawing, Row row, int rowIndex, String content) {
+		Cell cell = row.getCell(QRCODE_COLUMN_INDEX);
+		if (cell == null) {
+			cell = row.createCell(QRCODE_COLUMN_INDEX);
+		}
+		cell.setCellValue("");
+		byte[] pngBytes = QrCodeUtil.generatePng(content, QRCODE_SIZE, QRCODE_SIZE);
+		int pictureIndex = workbook.addPicture(pngBytes, Workbook.PICTURE_TYPE_PNG);
+		int margin = Units.pixelToEMU(4);
+		int size = Units.pixelToEMU(QRCODE_DISPLAY_SIZE_PX);
+		ClientAnchor anchor = drawing.createAnchor(margin, margin, margin + size, margin + size,
+				QRCODE_COLUMN_INDEX, rowIndex, QRCODE_COLUMN_INDEX, rowIndex);
+		drawing.createPicture(anchor, pictureIndex);
+	}
+
+	private float calculateWrapHeight(String text, int columnWidthChars) {
+		if (StringUtils.isBlank(text)) {
+			return MIN_ROW_HEIGHT;
+		}
+		int maxLineLength = Math.max(columnWidthChars, 1);
+		String[] lines = text.split("\\R");
+		int totalLines = 0;
+		for (String line : lines) {
+			totalLines += Math.max(1, (int) Math.ceil((double) line.length() / maxLineLength));
+		}
+		return Math.min(totalLines * LINE_HEIGHT + 5F, 409F);
+	}
+
+	private String getCellStringValue(Cell cell) {
+		if (cell == null) {
+			return "";
+		}
+		if (cell.getCellType() == CellType.STRING) {
+			return cell.getStringCellValue();
+		}
+		if (cell.getCellType() == CellType.NUMERIC) {
+			return String.valueOf(cell.getNumericCellValue());
+		}
+		return "";
+	}
+
+	private Map<String, String> buildLoginCodeMap(List<EmpUser> userList) {
+		Map<String, String> loginCodeMap = new HashMap<>();
+		for (EmpUser user : userList) {
+			if (user == null || StringUtils.isBlank(user.getUserCode())) {
+				continue;
+			}
+			if (StringUtils.isNotBlank(user.getLoginCode())) {
+				loginCodeMap.put(user.getUserCode(), user.getLoginCode());
+				continue;
+			}
+			User fullUser = userService.get(user.getUserCode());
+			if (fullUser != null && StringUtils.isNotBlank(fullUser.getLoginCode())) {
+				loginCodeMap.put(user.getUserCode(), fullUser.getLoginCode());
+			}
+		}
+		return loginCodeMap;
+	}
+
+	private Map<String, String> buildRoleNameMap() {
+		Map<String, String> roleNameMap = new HashMap<>();
+		List<Role> roleList = roleService.findList(new Role());
+		if (ListUtils.isEmpty(roleList)) {
+			return roleNameMap;
+		}
+		for (Role role : roleList) {
+			if (role != null && StringUtils.isNotBlank(role.getRoleCode())) {
+				roleNameMap.put(role.getRoleCode(), StringUtils.defaultString(role.getRoleName(), role.getRoleCode()));
+			}
+		}
+		return roleNameMap;
+	}
+
+	private Map<String, List<String>> buildUserRoleMap(Map<String, String> roleNameMap) {
+		Map<String, List<String>> userRoleMap = new HashMap<>();
+		List<UserRole> userRoleList = userRoleDao.findList(new UserRole());
+		if (ListUtils.isEmpty(userRoleList)) {
+			return userRoleMap;
+		}
+		for (UserRole userRole : userRoleList) {
+			if (userRole == null || StringUtils.isBlank(userRole.getUserCode())) {
+				continue;
+			}
+			String roleName = roleNameMap.getOrDefault(userRole.getRoleCode(), userRole.getRoleCode());
+			userRoleMap.computeIfAbsent(userRole.getUserCode(), k -> new ArrayList<>()).add(roleName);
+		}
+		return userRoleMap;
+	}
+
+	private Map<String, List<MesLineProcessUser>> buildUserOprnoMap() {
+		return mesLineProcessUserService.findList(new MesLineProcessUser()).stream()
+				.filter(item -> item != null && StringUtils.isNotBlank(item.getUserCode()))
+				.collect(Collectors.groupingBy(MesLineProcessUser::getUserCode));
+	}
+
+	private String formatOprnos(List<MesLineProcessUser> processUsers) {
+		if (ListUtils.isEmpty(processUsers)) {
+			return "";
+		}
+		Set<String> items = new LinkedHashSet<>();
+		for (MesLineProcessUser processUser : processUsers) {
+			if (processUser != null && StringUtils.isNotBlank(processUser.getOprno())) {
+				items.add(processUser.getOprno());
+			}
+		}
+		return joinSet(items);
+	}
+
+	private String joinList(List<String> list) {
+		if (ListUtils.isEmpty(list)) {
+			return "";
+		}
+		return String.join(MULTI_VALUE_SEPARATOR, list);
+	}
+
+	private String joinSet(Set<String> set) {
+		if (set == null || set.isEmpty()) {
+			return "";
+		}
+		return String.join(MULTI_VALUE_SEPARATOR, set);
+	}
+
+	private String defaultDisplay(String value) {
+		return StringUtils.isBlank(value) ? "无" : value;
+	}
+}

+ 3 - 13
src/main/java/com/jeesite/modules/mes/service/MesLineProcessUserService.java

@@ -1,20 +1,13 @@
 package com.jeesite.modules.mes.service;
 
-import com.jeesite.common.collect.ListUtils;
 import com.jeesite.common.entity.Page;
 import com.jeesite.common.service.CrudService;
-import com.jeesite.modules.mes.dao.MesLineProcessMaterialDao;
 import com.jeesite.modules.mes.dao.MesLineProcessUserDao;
-import com.jeesite.modules.mes.entity.MesLineProcessMaterial;
 import com.jeesite.modules.mes.entity.MesLineProcessUser;
-import com.jeesite.modules.mes.entity.MesMaterialPrebind;
-import com.jeesite.modules.mes.resp.BindMaterialResp;
-import com.jeesite.modules.mes.util.CommonUitl;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 
-import java.util.ArrayList;
 import java.util.List;
 
 /**
@@ -28,9 +21,6 @@ public class MesLineProcessUserService extends CrudService<MesLineProcessUserDao
 	@Autowired
 	private MesLineProcessUserDao mesLineProcessUserDao;
 
-	@Autowired
-	private MesMaterialPrebindService mesMaterialPrebindService;
-
 	/**
 	 * 获取单条数据
 	 * @param mesLineProcessUser
@@ -59,14 +49,14 @@ public class MesLineProcessUserService extends CrudService<MesLineProcessUserDao
 	
 	/**
 	 * 查询列表数据
-	 * @param mesLineProcessMaterial
+	 * @param mesLineProcessUser
 	 * @return
 	 */
 	@Override
 	public List<MesLineProcessUser> findList(MesLineProcessUser mesLineProcessUser) {
 		return super.findList(mesLineProcessUser);
 	}
-	
+
 	/**
 	 * 保存数据(插入或更新)
 	 * @param mesLineProcessUser
@@ -87,4 +77,4 @@ public class MesLineProcessUserService extends CrudService<MesLineProcessUserDao
 		super.updateStatus(mesLineProcessUser);
 	}
 
-}
+}

+ 1 - 1
src/main/java/com/jeesite/modules/mes/service/MesProductDbjRecordService.java

@@ -201,7 +201,7 @@ public class MesProductDbjRecordService extends CrudService<MesProductDbjRecordD
 		if (ListUtils.isEmpty(paramsResps)) {
 			return items;
 		}
-		Map<String, String> craftMaterialMap = buildCraftMaterialNameMap(oprno, lineSn, bmlists);
+		Map<String, String> craftMaterialMap = buildCraftMaterialNameMap(oprno, lineSn, bmlists);//将工艺号和物料名称对应
 		Map<String, Integer> craftConsumeMap = buildCraftConsumeMap(bmlists);
 		int sort = 0;
 		for (ParamsResp paramsResp : paramsResps) {

+ 4 - 0
src/main/java/com/jeesite/modules/mes/service/MesUserSkillService.java

@@ -97,6 +97,10 @@ public class MesUserSkillService extends CrudService<MesUserSkillDao, MesUserSki
 			return mesUserSkillDao.findListBySkillId(mesUserSkill);
 	}
 
+	public List<MesUserSkill> findExportList() {
+		return mesUserSkillDao.findExportList();
+	}
+
 	@Transactional
 	public String save2(MesUserSkill mesUserSkill) {
 		if (!mesUserSkill.getIsNewRecord()){

+ 13 - 7
src/main/java/com/jeesite/modules/mes/web/MesLineProcessUserController.java

@@ -1,15 +1,11 @@
 package com.jeesite.modules.mes.web;
 
-import com.jeesite.common.collect.ListUtils;
 import com.jeesite.common.config.Global;
 import com.jeesite.common.entity.Page;
 import com.jeesite.common.web.BaseController;
 import com.jeesite.modules.mes.entity.MesLineProcess;
-import com.jeesite.modules.mes.entity.MesLineProcessMaterial;
 import com.jeesite.modules.mes.entity.MesLineProcessUser;
-import com.jeesite.modules.mes.resp.BindMaterialResp;
-import com.jeesite.modules.mes.resp.CommonResp;
-import com.jeesite.modules.mes.service.MesLineProcessMaterialService;
+import com.jeesite.modules.mes.service.MesEmpUserExportService;
 import com.jeesite.modules.mes.service.MesLineProcessService;
 import com.jeesite.modules.mes.service.MesLineProcessUserService;
 import org.apache.shiro.authz.annotation.RequiresPermissions;
@@ -24,8 +20,6 @@ import org.springframework.web.bind.annotation.ResponseBody;
 
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
-import java.util.List;
-
 /**
  * 生产工序物料表Controller
  * @author mes
@@ -39,6 +33,9 @@ public class MesLineProcessUserController extends BaseController {
 	private MesLineProcessUserService mesLineProcessUserService;
 
 	@Autowired
+	private MesEmpUserExportService mesEmpUserExportService;
+
+	@Autowired
 	private MesLineProcessService mesLineProcessService;
 	
 	/**
@@ -118,5 +115,14 @@ public class MesLineProcessUserController extends BaseController {
 		mesLineProcessUserService.delete(mesLineProcessUser);
 		return renderResult(Global.TRUE, text("删除成功!"));
 	}
+
+	/**
+	 * 一键导出员工权限信息
+	 */
+	@RequiresPermissions("sys:empUser:view")
+	@RequestMapping(value = "exportUserAuth")
+	public void exportUserAuth(HttpServletResponse response) {
+		mesEmpUserExportService.exportUserAuth(response);
+	}
 	
 }

+ 15 - 0
src/main/resources/mappings/modules/mes/MesUserSkillDao.xml

@@ -22,4 +22,19 @@
             AND b.user_name like #{userName}
         </if>
     </select>
+
+    <select id="findExportList" resultType="com.jeesite.modules.mes.entity.MesUserSkill">
+        SELECT
+            a.user_code AS userCode,
+            a.degree AS degree,
+            b.skill AS skill,
+            d.oprno AS oprno,
+            d.title AS title,
+            e.title AS lineTitle
+        FROM mes_user_skill a
+        LEFT JOIN mes_skill b ON b.id = a.skill_id
+        LEFT JOIN mes_line_process d ON d.id = b.line_process_id
+        LEFT JOIN mes_line e ON e.id = b.line_id
+        ORDER BY a.user_code ASC, d.oprno ASC, a.id ASC
+    </select>
 </mapper>

+ 2 - 2
src/main/resources/views/modules/sys/user/empUserList.html

@@ -7,7 +7,7 @@
 			</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>
-				<a href="#" class="btn btn-default" id="btnExport"><i class="glyphicon glyphicon-export"></i> ${text('导出')}</a>
+				<a href="#" class="btn btn-default" id="btnExport" title="${text('导出用户昵称及权限信息')}"><i class="glyphicon glyphicon-export"></i> ${text('导出')}</a>
 				<% if(hasPermi('sys:empUser:edit')){ %>
 					<a href="#" class="btn btn-default" id="btnImport"><i class="glyphicon glyphicon-import"></i> ${text('导入')}</a>
 					<a href="${ctx}/sys/empUser/form?op=add" class="btn btn-default btnTool" title="${text('新增用户')}"><i class="fa fa-plus"></i> ${text('新增')}</a>
@@ -182,7 +182,7 @@ $('#dataGrid').dataGrid({
 });
 $('#btnExport').click(function(){
 	js.ajaxSubmitForm($('#searchForm'), {
-		url:'${ctx}/sys/empUser/exportData',
+		url:'${ctx}/mes/mesLineProcessUser/exportUserAuth',
 		downloadFile:true
 	});
 });

+ 174 - 0
views/modules/sys/user/empUserFormAuthDataScope.html

@@ -0,0 +1,174 @@
+<% layout('/layouts/default.html', {title: '用户管理', libs: ['validate', 'zTree']}){ %>
+<div class="main-content">
+	<div class="box box-main">
+		<div class="box-header">
+			<div class="box-title">
+				<i class="fa icon-people"></i> ${text('用户分配数据权限')}
+			</div>
+			<div class="box-tools pull-right">
+				<button type="button" class="btn btn-box-tool" data-widget="collapse"><i class="fa fa-minus"></i></button>
+			</div>
+		</div>
+		<#form:form id="inputForm" model="${empUser}" action="${ctx}/sys/empUser/saveAuthDataScope" method="post" class="form-horizontal">
+			<#form:hidden path="userCode"/>
+			<div class="box-body"><br/>
+				<div class="row">
+					<div class="col-xs-6">
+						<div class="form-group">
+							<label class="control-label col-sm-4" title="">
+								<span class="required ">*</span> ${text('登录账号')}:<i class="fa icon-question hide"></i></label>
+							<div class="col-sm-8">
+								<#form:input path="loginCode" maxlength="32" readonly="${!empUser.isNewRecord}" class="form-control required "/>
+							</div>
+						</div>
+					</div>
+					<div class="col-xs-6">
+						<div class="form-group">
+							<label class="control-label col-sm-4" title="">
+								<span class="required ">*</span> ${text('用户昵称')}:<i class="fa icon-question hide"></i></label>
+							<div class="col-sm-8">
+								<#form:input path="userName" maxlength="32" readonly="${!empUser.isNewRecord}" class="form-control required "/>
+							</div>
+						</div>
+					</div>
+				</div>
+				<div class="form-unit">${text('数据权限')}</div>
+				<div id="dataScopeTrees"></div>
+				<script id="dataScopeTpl" type="text/template">
+					<div class="pull-left" style="padding:0 15px;min-width:300px;">
+						<div class="box box-solid box-trees">
+							<div class="box-header">
+								<div class="box-title icheck">
+									<label><input type="checkbox" id="checkall_{{d.key}}"
+										class="checkall"/> {{d.label}}</label>
+								</div>
+								<div class="box-tools pull-right" style="top:8px;">
+									<a class="btn btn-box-tool" id="expand_{{d.key}}"
+										value="dataScopeTree_{{d.key}}" >${text('展开')}</a>/<a
+										class="btn btn-box-tool" id="collapse_{{d.key}}"
+										value="dataScopeTree_{{d.key}}" >${text('折叠')}</a>
+								</div>
+							</div>
+							<div class="box-body">
+								<div id="dataScopeTree_{{d.key}}" class="ztree"></div>
+							</div>
+						</div>
+					</div>
+				</script>
+			    <#form:hidden name="userDataScopeListJson"/>
+			</div>
+			<div class="box-footer">
+				<div class="row">
+					<div class="col-sm-offset-2 col-sm-10">
+						<% if (hasPermi('sys:empUser:authDataScope')){ %>
+							<button type="submit" class="btn btn-sm btn-primary" id="btnSubmit"><i class="fa fa-check"></i> ${text('保 存')}</button>&nbsp;
+						<% } %>
+						<button type="button" class="btn btn-sm btn-default" id="btnCancel" onclick="js.closeCurrentTabPage()"><i class="fa fa-reply-all"></i> ${text('关 闭')}</button>
+					</div>
+				</div>
+			</div>
+		</#form:form>
+	</div>
+</div>
+<% } %>
+<script>
+$("#inputForm").validate({
+	submitHandler: function(form){
+		// 获取数据权限数据
+		var dataScopeData = [];
+		$.each(dataScopeTrees, function(key, dataScopeTree){
+			var treeNodes = dataScopeTree.getCheckedNodes(true);
+			for(var i=0; i<treeNodes.length; i++) {
+				dataScopeData.push({
+					ctrlType: key, ctrlData: treeNodes[i].id
+				});
+			}
+		});
+		$("#userDataScopeListJson").val(JSON.stringify(dataScopeData));
+		// 提交表单数据
+		js.ajaxSubmitForm($(form), function(data){
+			js.showMessage(data.message);
+			if(data.result == Global.TRUE){
+				js.closeCurrentTabPage(function(contentWindow){
+					contentWindow.page();
+				});
+			}
+		}, "json");
+    }
+});
+//加载数据权限树结构
+var setting = {
+	check:{enable:true,nocheckInherit:true},
+	view:{selectedMulti:false,nameIsHTML: true},
+	data:{simpleData:{enable:true},key:{title:"title"}},
+	callback:{
+		beforeClick: function (treeId, treeNode, clickFlag) {
+			var tree = $.fn.zTree.getZTreeObj(treeId);
+			tree.checkNode(treeNode, !treeNode.checked, true, true);
+			return false;
+		},
+		onCheck: function (event, treeId, treeNode){ }
+	}
+},
+moduleCodes = '${toJson(moduleCodes)}';
+dataScopes = ${toJson(dataScopes)},
+dataScopeTrees = {}; // 用sysCode分类存储所有菜单树
+for (var i=0; i<dataScopes.length; i++){
+	var dataScope = dataScopes[i];
+	// 验证模块是否开启,如果未开启,则跳过
+	if (moduleCodes.indexOf("\""+dataScope.moduleCode+"\"") == -1){
+		continue;
+	}
+	// 控制权限 ctrlPermi: 0全部  1拥有权限  2管理权限
+	if (!(dataScope.ctrlPermi == '0' || dataScope.ctrlPermi == '1')){
+		continue;
+	}
+ 	$('#dataScopeTrees').append(js.template('dataScopeTpl', {
+ 		key: dataScope.ctrlType, label: dataScope.ctrlName_${lang()} || dataScope.ctrlName}));
+ 	var ctrlDataUrl = dataScope.ctrlDataUrl || '';
+	$.ajax({
+		type: 'POST',
+		url: "${ctx}" + ctrlDataUrl + (ctrlDataUrl.indexOf("?")!=-1?'&':'?') + "___t=" + new Date().getTime(),
+		data: {ctrlPermi: '${ctrlPermi}'},
+		dataType: 'json',
+		async: false,
+		error: function(data){
+			js.showErrorMessage(data.responseText);
+		},
+		success: function(data, status, xhr){
+			// 初始化树结构
+			var tree = $.fn.zTree.init($("#dataScopeTree_"+dataScope.ctrlType), setting, data);
+			tree.setting.check.chkboxType = dataScope.chkboxType;
+			// 默认展开节点(如果级别设置为-1,则:如果有1个根节点,则展开一级节点,否则不展开)
+			$.fn.zTree.expandNodeByLevel(tree, dataScope.expandLevel);
+			// 树结构:全选、取消全选
+			$('#checkall_'+dataScope.ctrlType).iCheck({
+		 		checkboxClass:'icheckbox_minimal-grey'
+		 	}).on('ifChecked ifUnchecked', function(){
+	        	var ctrlType = $(this).attr('ctrlType');
+				if(this.checked){
+					dataScopeTrees[ctrlType].checkAllNodes(true);
+				}else{
+					dataScopeTrees[ctrlType].checkAllNodes(false);
+				}
+			}).attr("ctrlType", dataScope.ctrlType);
+			// 展开和折叠按钮绑定
+			$('#expand_'+dataScope.ctrlType).click(function(){
+				var ctrlType = $(this).attr('ctrlType');
+				dataScopeTrees[ctrlType].expandAll(true);
+			}).attr("ctrlType", dataScope.ctrlType);
+			$('#collapse_'+dataScope.ctrlType).click(function(){
+				var ctrlType = $(this).attr('ctrlType');
+				dataScopeTrees[ctrlType].expandAll(false);
+			}).attr("ctrlType", dataScope.ctrlType);
+			// 将树对象存储到全局数组里
+			dataScopeTrees[dataScope.ctrlType] = tree;
+		}
+	});
+}
+// 默认选择节点
+//<% for(dataScope in userDataScopeList){ %>
+try{dataScopeTrees['${dataScope.ctrlType}'].checkNode(dataScopeTrees['${dataScope.ctrlType}']
+	.getNodeByParam("id","${dataScope.ctrlData}"), true, false);}catch(e){}
+//<% } %>
+</script>