Procházet zdrojové kódy

个人能力提升功能开发

徐滕 před 2 týdny
rodič
revize
b20d2418cd
35 změnil soubory, kde provedl 10258 přidání a 3 odebrání
  1. 1 0
      src/main/java/com/jeeplus/common/utils/MenuStatusEnum.java
  2. 3 0
      src/main/java/com/jeeplus/modules/workprojectnotify/dao/WorkProjectNotifyDao.java
  3. 14 0
      src/main/java/com/jeeplus/modules/workprojectnotify/service/WorkProjectNotifyService.java
  4. 14 0
      src/main/java/com/jeeplus/modules/workprojectnotify/web/WorkProjectNotifyController.java
  5. 80 0
      src/main/java/com/jeeplus/modules/workqualityimprovement/dao/WkQualityImprovementRecordDao.java
  6. 40 0
      src/main/java/com/jeeplus/modules/workqualityimprovement/dao/WkQualityImprovementTaskDao.java
  7. 556 0
      src/main/java/com/jeeplus/modules/workqualityimprovement/entity/WkQualityImprovementRecord.java
  8. 163 0
      src/main/java/com/jeeplus/modules/workqualityimprovement/entity/WkQualityImprovementTask.java
  9. 197 0
      src/main/java/com/jeeplus/modules/workqualityimprovement/service/WkQualityImprovementRecordService.java
  10. 318 0
      src/main/java/com/jeeplus/modules/workqualityimprovement/service/WkQualityImprovementTaskService.java
  11. 1607 0
      src/main/java/com/jeeplus/modules/workqualityimprovement/web/WkQualityImprovementController.java
  12. 31 0
      src/main/resources/act/designs/workqualityimprovement/qualityImprovement.bpmn
  13. 14 0
      src/main/resources/freemarker/docx_template/[Content_Types].xml
  14. 6 0
      src/main/resources/freemarker/docx_template/_rels/.rels
  15. 18 0
      src/main/resources/freemarker/docx_template/docProps/app.xml
  16. 7 0
      src/main/resources/freemarker/docx_template/docProps/core.xml
  17. 11 0
      src/main/resources/freemarker/docx_template/docProps/custom.xml
  18. 7 0
      src/main/resources/freemarker/docx_template/word/_rels/document.xml.rels
  19. 38 0
      src/main/resources/freemarker/docx_template/word/fontTable.xml
  20. 66 0
      src/main/resources/freemarker/docx_template/word/settings.xml
  21. 423 0
      src/main/resources/freemarker/docx_template/word/styles.xml
  22. 245 0
      src/main/resources/freemarker/docx_template/word/theme/theme1.xml
  23. 1 0
      src/main/resources/freemarker/docx_template/word/webSettings.xml
  24. 4485 0
      src/main/resources/freemarker/qualityImprovementPlan.ftl
  25. 2 2
      src/main/resources/jeeplus.properties
  26. 9 0
      src/main/resources/mappings/modules/workprojectnotify/WorkProjectNotifyDao.xml
  27. 347 0
      src/main/resources/mappings/modules/workqualityimprovement/WkQualityImprovementRecordDao.xml
  28. 160 0
      src/main/resources/mappings/modules/workqualityimprovement/WkQualityImprovementTaskDao.xml
  29. 7 0
      src/main/webapp/webpage/modules/sys/sysHome.jsp
  30. 38 1
      src/main/webapp/webpage/modules/workprojectnotify/workProjectNotifyList.jsp
  31. 6 0
      src/main/webapp/webpage/modules/workprojectnotify/workProjectNotifyReadShowList.jsp
  32. 575 0
      src/main/webapp/webpage/modules/workqualityimprovement/recordForm.jsp
  33. 315 0
      src/main/webapp/webpage/modules/workqualityimprovement/recordList.jsp
  34. 231 0
      src/main/webapp/webpage/modules/workqualityimprovement/taskForm.jsp
  35. 223 0
      src/main/webapp/webpage/modules/workqualityimprovement/taskList.jsp

+ 1 - 0
src/main/java/com/jeeplus/common/utils/MenuStatusEnum.java

@@ -85,6 +85,7 @@ public enum MenuStatusEnum {
     ELECTRONIC_SIGNATURE("50cfb2ad32814623a976bb7776e87c12","电子用章管理"),
     EBUSINESS_SIGNATURE("976b008b2c0f402ea7015bb15665d1f4","业务用章管理"),
     EXTERNAL_UNIT("7bc8ffdcf9764f28999dd67c1657bb78","外部单位"),
+    WORK_QUALITY_IMPROVEMENT("b78ad72dc2a44705989681c948360e70","个人素养提升管理"),
     END("19940722131313","废弃");
 
     private String value;

+ 3 - 0
src/main/java/com/jeeplus/modules/workprojectnotify/dao/WorkProjectNotifyDao.java

@@ -66,6 +66,9 @@ public interface WorkProjectNotifyDao extends CrudDao<WorkProjectNotify> {
 
     int updateReadStateByNotifyIdAndNotifyUser(WorkProjectNotify notify);
 
+    //根据通知ID、用户、类型更新状态和备注(素养提升计划提交后置为已完成)
+    int updateStatusAndRemarksByNotifyIdAndUserId(WorkProjectNotify notify);
+
     int updateReadStateByNotifyRoleAndUser(WorkProjectNotify notify);
 
     int updateOverDueInfo(WorkProjectNotify notify);

+ 14 - 0
src/main/java/com/jeeplus/modules/workprojectnotify/service/WorkProjectNotifyService.java

@@ -405,6 +405,20 @@ public class WorkProjectNotifyService extends CrudService<WorkProjectNotifyDao,
 		notify.preUpdate();
 		return dao.updateReadStateByNotifyIdAndNotifyUser(notify);
 	}
+
+	/**
+	 * 素养提升计划提交后,将对应通知标记为已完成(remarks置为已完成,status置为1,不再出现在首页待办栏)
+	 * @param notify 需设置notifyId、user、type
+	 * @param status 目标状态
+	 * @param remarks 目标备注
+	 */
+	@Transactional(readOnly = false)
+	public int completeNotifyByNotifyIdAndUser(WorkProjectNotify notify, String status, String remarks) {
+		notify.setStatus(status);
+		notify.setRemarks(remarks);
+		notify.preUpdate();
+		return dao.updateStatusAndRemarksByNotifyIdAndUserId(notify);
+	}
 	@Transactional(readOnly = false)
 	public void save(WorkProjectNotify workProjectNotify) {
 		User user = workProjectNotify.getUser();

+ 14 - 0
src/main/java/com/jeeplus/modules/workprojectnotify/web/WorkProjectNotifyController.java

@@ -233,6 +233,8 @@ import com.jeeplus.modules.workprojectnotify.entity.WorkProjectNotify;
 import com.jeeplus.modules.workprojectnotify.entity.WorkProjectNotifyRecover;
 import com.jeeplus.modules.workprojectnotify.service.WorkProjectNotifyRecoverService;
 import com.jeeplus.modules.workprojectnotify.service.WorkProjectNotifyService;
+import com.jeeplus.modules.workqualityimprovement.entity.WkQualityImprovementRecord;
+import com.jeeplus.modules.workqualityimprovement.service.WkQualityImprovementRecordService;
 import com.jeeplus.modules.workreceiptsrevise.entity.WorkReceiptsRevise;
 import com.jeeplus.modules.workreceiptsrevise.service.WorkReceiptsReviseService;
 import com.jeeplus.modules.workreceiptssettle.entity.WorkReceiptsSettle;
@@ -650,6 +652,9 @@ public class WorkProjectNotifyController extends BaseController {
 	@Autowired
 	private WkPointSnapshotService wkPointSnapshotService;
 
+	@Autowired
+	private WkQualityImprovementRecordService wkQualityImprovementRecordService;
+
 
 	@ModelAttribute
 	public WorkProjectNotify get(@RequestParam(required = false) String id) {
@@ -8306,6 +8311,15 @@ public class WorkProjectNotifyController extends BaseController {
 					if (workProjectNotify.getRemarks().contains("待通知") || "view".equals(workProjectNotify.getView())) {
 						return "modules/WorkKnowledgeBase/workKnowledgeBasePointDashboard";
 					}
+				}else if ("202".equals(workProjectNotify.getType())) {//素养提升计划待填写
+					User currentUser = UserUtils.getUser();
+					WkQualityImprovementRecord record = wkQualityImprovementRecordService.findByTaskIdAndUserId(workProjectNotify.getNotifyId(), currentUser.getId());
+					if (record == null) {
+						record = new WkQualityImprovementRecord();
+					}
+					model.addAttribute("wkQualityImprovementRecord", record);
+					model.addAttribute("readOnly", "1".equals(record.getSubmitStatus()));
+					return "modules/workqualityimprovement/recordForm";
 				}
 			}
 		}

+ 80 - 0
src/main/java/com/jeeplus/modules/workqualityimprovement/dao/WkQualityImprovementRecordDao.java

@@ -0,0 +1,80 @@
+/**
+ * Copyright &copy; 2015-2020 <a href="http://www.jeeplus.org/">JeePlus</a> All rights reserved.
+ */
+package com.jeeplus.modules.workqualityimprovement.dao;
+
+import com.jeeplus.common.persistence.CrudDao;
+import com.jeeplus.common.persistence.annotation.MyBatisDao;
+import com.jeeplus.modules.workqualityimprovement.entity.WkQualityImprovementRecord;
+import org.apache.ibatis.annotations.Param;
+
+import java.util.List;
+
+/**
+ * 素养提升个人记录DAO接口
+ * @author jeeplus
+ * @version 2026-07-31
+ */
+@MyBatisDao
+public interface WkQualityImprovementRecordDao extends CrudDao<WkQualityImprovementRecord> {
+
+	/**
+	 * 根据ID查询记录
+	 */
+	WkQualityImprovementRecord getById(@Param("id") String id);
+
+	/**
+	 * 查询记录列表
+	 */
+	List<WkQualityImprovementRecord> findList(WkQualityImprovementRecord record);
+
+	/**
+	 * 查询记录总数(分页用,与 findList 同条件,含数据权限过滤)
+	 */
+	Integer queryCount(WkQualityImprovementRecord record);
+
+	/**
+	 * 根据任务ID查询所有记录
+	 */
+	List<WkQualityImprovementRecord> findByTaskId(@Param("taskId") String taskId);
+
+	/**
+	 * 根据任务ID和用户ID查询记录
+	 */
+	WkQualityImprovementRecord findByTaskIdAndUserId(@Param("taskId") String taskId, @Param("userId") String userId);
+
+	/**
+	 * 根据流程实例ID查询记录
+	 */
+	WkQualityImprovementRecord getByProcessInstanceId(@Param("processInstanceId") String processInstanceId);
+
+	/**
+	 * 更新提交状态
+	 */
+	int updateSubmitStatus(WkQualityImprovementRecord record);
+
+	/**
+	 * 根据任务ID统计已提交人数
+	 */
+	int countSubmittedByTaskId(@Param("taskId") String taskId);
+
+	/**
+	 * 根据任务ID统计总人数
+	 */
+	int countByTaskId(@Param("taskId") String taskId);
+
+	/**
+	 * 根据任务ID删除记录
+	 */
+	int deleteByTaskId(@Param("taskId") String taskId);
+
+	/**
+	 * 根据ID逻辑删除记录
+	 */
+	int logicalDeleteById(@Param("id") String id);
+
+	/**
+	 * 查询全部记录(用于导出)
+	 */
+	List<WkQualityImprovementRecord> findAllList(WkQualityImprovementRecord record);
+}

+ 40 - 0
src/main/java/com/jeeplus/modules/workqualityimprovement/dao/WkQualityImprovementTaskDao.java

@@ -0,0 +1,40 @@
+/**
+ * Copyright &copy; 2015-2020 <a href="http://www.jeeplus.org/">JeePlus</a> All rights reserved.
+ */
+package com.jeeplus.modules.workqualityimprovement.dao;
+
+import com.jeeplus.common.persistence.CrudDao;
+import com.jeeplus.common.persistence.annotation.MyBatisDao;
+import com.jeeplus.modules.workqualityimprovement.entity.WkQualityImprovementTask;
+import org.apache.ibatis.annotations.Param;
+
+import java.util.List;
+
+/**
+ * 素养提升任务DAO接口
+ * @author jeeplus
+ * @version 2026-07-31
+ */
+@MyBatisDao
+public interface WkQualityImprovementTaskDao extends CrudDao<WkQualityImprovementTask> {
+
+	/**
+	 * 根据ID查询任务(关联创建人信息)
+	 */
+	WkQualityImprovementTask getById(@Param("id") String id);
+
+	/**
+	 * 查询任务列表(关联统计已提交人数)
+	 */
+	List<WkQualityImprovementTask> findList(WkQualityImprovementTask task);
+
+	/**
+	 * 更新任务状态
+	 */
+	int updateStatus(WkQualityImprovementTask task);
+
+	/**
+	 * 根据ID更新流程实例ID
+	 */
+	int updateProcessInstanceId(@Param("id") String id, @Param("processInstanceId") String processInstanceId);
+}

+ 556 - 0
src/main/java/com/jeeplus/modules/workqualityimprovement/entity/WkQualityImprovementRecord.java

@@ -0,0 +1,556 @@
+/**
+ * Copyright &copy; 2015-2020 <a href="http://www.jeeplus.org/">JeePlus</a> All rights reserved.
+ */
+package com.jeeplus.modules.workqualityimprovement.entity;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.jeeplus.common.persistence.ActEntity;
+import com.jeeplus.modules.sys.entity.User;
+
+import java.util.Date;
+
+/**
+ * 素养提升个人记录Entity
+ * @author jeeplus
+ * @version 2026-07-31
+ */
+public class WkQualityImprovementRecord extends ActEntity<WkQualityImprovementRecord> {
+
+	private static final long serialVersionUID = 1L;
+	private String taskId;			// 关联任务ID
+	private String taskTitle;		// 任务标题(冗余)
+	private String taskYear;		// 任务年份(冗余)
+	private String userId;			// 填写人ID
+	private String userName;		// 姓名(冗余)
+	private String recordOfficeId;	// 填写人部门ID(数据权限用,对应表字段 office_id)
+	private String companyId;		// 所属公司ID(数据权限用,对应表字段 company_id)
+	private String officeName;		// 部门(冗余)
+	private String position;		// 岗位
+	private String workYears;		// 入职年限
+	private String growthStage;		// 当前成长阶段
+	private String weaknessGoal;	// 短板与不足/总体目标
+
+	// 专业实操能力提升(4个方向)
+	private Integer scoreMapping;	// 识图/算量/建模 评分(1-5)
+	private String planMapping;		// 识图/算量/建模 目标措施
+	private Integer scorePricing;	// 清单/定额计价 评分(1-5)
+	private String planPricing;		// 清单/定额计价 目标措施
+	private Integer scoreChange;	// 变更/签证/索赔/争议处理 评分(1-5)
+	private String planChange;		// 变更/签证/索赔/争议处理 目标措施
+	private Integer scoreProcess;	// 全过程业务能力 评分(1-5)
+	private String planProcess;		// 全过程业务能力 目标措施
+
+	// 数字化与办公能力提升(3个方向)
+	private Integer scoreCcpm;		// CCPM系统全流程操作 评分(1-5)
+	private String planCcpm;		// CCPM系统 目标措施
+	private Integer scoreSoftware;	// 广联达/未来/博威等软件 评分(1-5)
+	private String planSoftware;	// 广联达等软件 目标措施
+	private Integer scoreAi;		// AI辅助工具应用 评分(1-5)
+	private String planAi;			// AI辅助工具 目标措施
+
+	// 学习考证与知识更新
+	private String engineerStatus;	// 造价工程师状态(备考中/已通过/已取得)
+	private String engineerPlan;	// 造价工程师具体计划
+	private String engineerDeadline;// 造价工程师完成时限
+	private String trainingTypes;	// 培训类型(多选逗号分隔)
+	private String trainingDirection;// 培训方向
+	private String trainingDeadline;// 培训完成时限
+	private String regulationLevel;	// 清单/定额/新规掌握程度
+	private String regulationDeadline;// 新规掌握完成时限
+	private Integer caseCount;		// 案例篇数
+	private Integer insightCount;	// 心得篇数
+	private Integer paperCount;		// 论文篇数
+	private String outputDifficulty;// 输出困难说明
+	private String outputDeadline;	// 输出完成时限
+
+	// 沟通服务与业务开拓能力提升(5个方向)
+	private Integer scoreCommClient;	// 与甲方/施工单位沟通 评分(1-5)
+	private String planCommClient;		// 与甲方/施工单位沟通 目标措施
+	private Integer scoreCommWriting;	// 书面表达/底稿/报告撰写 评分(1-5)
+	private String planCommWriting;		// 书面表达 目标措施
+	private Integer scoreCommResponse;	// 客户需求响应与关系维护 评分(1-5)
+	private String planCommResponse;	// 客户需求响应 目标措施
+	private Integer scoreCommCross;		// 跨专业贯通 评分(1-5)
+	private String planCommCross;		// 跨专业贯通 目标措施
+	private Integer scoreCommExpand;	// 主动开拓/洽谈业务能力 评分(1-5)
+	private String planCommExpand;		// 主动开拓 目标措施
+
+	// 底部总结
+	private String coreAdvantage;	// 核心优势与提升思路
+
+	// 流程与状态
+	private String processInstanceId;	// Activiti流程实例ID
+	private String submitStatus;		// 提交状态(0:未填写 1:已提交)
+	@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+	private Date submitDate;			// 提交时间
+
+	// 非数据库字段
+	private WkQualityImprovementTask task;	// 关联任务对象
+	private User user;						// 填写人对象
+	private String toflag;					// 查询标记
+	private String officeId;				// 查询用-部门ID
+
+	public WkQualityImprovementRecord() {
+		super();
+	}
+
+	public WkQualityImprovementRecord(String id) {
+		super(id);
+	}
+
+	public String getTaskId() {
+		return taskId;
+	}
+
+	public void setTaskId(String taskId) {
+		this.taskId = taskId;
+	}
+
+	public String getTaskTitle() {
+		return taskTitle;
+	}
+
+	public void setTaskTitle(String taskTitle) {
+		this.taskTitle = taskTitle;
+	}
+
+	public String getTaskYear() {
+		return taskYear;
+	}
+
+	public void setTaskYear(String taskYear) {
+		this.taskYear = taskYear;
+	}
+
+	public String getUserId() {
+		return userId;
+	}
+
+	public void setUserId(String userId) {
+		this.userId = userId;
+	}
+
+	public String getUserName() {
+		return userName;
+	}
+
+	public void setUserName(String userName) {
+		this.userName = userName;
+	}
+
+	public String getOfficeName() {
+		return officeName;
+	}
+
+	public void setOfficeName(String officeName) {
+		this.officeName = officeName;
+	}
+
+	public String getPosition() {
+		return position;
+	}
+
+	public void setPosition(String position) {
+		this.position = position;
+	}
+
+	public String getWorkYears() {
+		return workYears;
+	}
+
+	public void setWorkYears(String workYears) {
+		this.workYears = workYears;
+	}
+
+	public String getGrowthStage() {
+		return growthStage;
+	}
+
+	public void setGrowthStage(String growthStage) {
+		this.growthStage = growthStage;
+	}
+
+	public String getWeaknessGoal() {
+		return weaknessGoal;
+	}
+
+	public void setWeaknessGoal(String weaknessGoal) {
+		this.weaknessGoal = weaknessGoal;
+	}
+
+	public Integer getScoreMapping() {
+		return scoreMapping;
+	}
+
+	public void setScoreMapping(Integer scoreMapping) {
+		this.scoreMapping = scoreMapping;
+	}
+
+	public String getPlanMapping() {
+		return planMapping;
+	}
+
+	public void setPlanMapping(String planMapping) {
+		this.planMapping = planMapping;
+	}
+
+	public Integer getScorePricing() {
+		return scorePricing;
+	}
+
+	public void setScorePricing(Integer scorePricing) {
+		this.scorePricing = scorePricing;
+	}
+
+	public String getPlanPricing() {
+		return planPricing;
+	}
+
+	public void setPlanPricing(String planPricing) {
+		this.planPricing = planPricing;
+	}
+
+	public Integer getScoreChange() {
+		return scoreChange;
+	}
+
+	public void setScoreChange(Integer scoreChange) {
+		this.scoreChange = scoreChange;
+	}
+
+	public String getPlanChange() {
+		return planChange;
+	}
+
+	public void setPlanChange(String planChange) {
+		this.planChange = planChange;
+	}
+
+	public Integer getScoreProcess() {
+		return scoreProcess;
+	}
+
+	public void setScoreProcess(Integer scoreProcess) {
+		this.scoreProcess = scoreProcess;
+	}
+
+	public String getPlanProcess() {
+		return planProcess;
+	}
+
+	public void setPlanProcess(String planProcess) {
+		this.planProcess = planProcess;
+	}
+
+	public Integer getScoreCcpm() {
+		return scoreCcpm;
+	}
+
+	public void setScoreCcpm(Integer scoreCcpm) {
+		this.scoreCcpm = scoreCcpm;
+	}
+
+	public String getPlanCcpm() {
+		return planCcpm;
+	}
+
+	public void setPlanCcpm(String planCcpm) {
+		this.planCcpm = planCcpm;
+	}
+
+	public Integer getScoreSoftware() {
+		return scoreSoftware;
+	}
+
+	public void setScoreSoftware(Integer scoreSoftware) {
+		this.scoreSoftware = scoreSoftware;
+	}
+
+	public String getPlanSoftware() {
+		return planSoftware;
+	}
+
+	public void setPlanSoftware(String planSoftware) {
+		this.planSoftware = planSoftware;
+	}
+
+	public Integer getScoreAi() {
+		return scoreAi;
+	}
+
+	public void setScoreAi(Integer scoreAi) {
+		this.scoreAi = scoreAi;
+	}
+
+	public String getPlanAi() {
+		return planAi;
+	}
+
+	public void setPlanAi(String planAi) {
+		this.planAi = planAi;
+	}
+
+	public String getEngineerStatus() {
+		return engineerStatus;
+	}
+
+	public void setEngineerStatus(String engineerStatus) {
+		this.engineerStatus = engineerStatus;
+	}
+
+	public String getEngineerPlan() {
+		return engineerPlan;
+	}
+
+	public void setEngineerPlan(String engineerPlan) {
+		this.engineerPlan = engineerPlan;
+	}
+
+	public String getEngineerDeadline() {
+		return engineerDeadline;
+	}
+
+	public void setEngineerDeadline(String engineerDeadline) {
+		this.engineerDeadline = engineerDeadline;
+	}
+
+	public String getTrainingTypes() {
+		return trainingTypes;
+	}
+
+	public void setTrainingTypes(String trainingTypes) {
+		this.trainingTypes = trainingTypes;
+	}
+
+	public String getTrainingDirection() {
+		return trainingDirection;
+	}
+
+	public void setTrainingDirection(String trainingDirection) {
+		this.trainingDirection = trainingDirection;
+	}
+
+	public String getTrainingDeadline() {
+		return trainingDeadline;
+	}
+
+	public void setTrainingDeadline(String trainingDeadline) {
+		this.trainingDeadline = trainingDeadline;
+	}
+
+	public String getRegulationLevel() {
+		return regulationLevel;
+	}
+
+	public void setRegulationLevel(String regulationLevel) {
+		this.regulationLevel = regulationLevel;
+	}
+
+	public String getRegulationDeadline() {
+		return regulationDeadline;
+	}
+
+	public void setRegulationDeadline(String regulationDeadline) {
+		this.regulationDeadline = regulationDeadline;
+	}
+
+	public Integer getCaseCount() {
+		return caseCount;
+	}
+
+	public void setCaseCount(Integer caseCount) {
+		this.caseCount = caseCount;
+	}
+
+	public Integer getInsightCount() {
+		return insightCount;
+	}
+
+	public void setInsightCount(Integer insightCount) {
+		this.insightCount = insightCount;
+	}
+
+	public Integer getPaperCount() {
+		return paperCount;
+	}
+
+	public void setPaperCount(Integer paperCount) {
+		this.paperCount = paperCount;
+	}
+
+	public String getOutputDifficulty() {
+		return outputDifficulty;
+	}
+
+	public void setOutputDifficulty(String outputDifficulty) {
+		this.outputDifficulty = outputDifficulty;
+	}
+
+	public String getOutputDeadline() {
+		return outputDeadline;
+	}
+
+	public void setOutputDeadline(String outputDeadline) {
+		this.outputDeadline = outputDeadline;
+	}
+
+	public Integer getScoreCommClient() {
+		return scoreCommClient;
+	}
+
+	public void setScoreCommClient(Integer scoreCommClient) {
+		this.scoreCommClient = scoreCommClient;
+	}
+
+	public String getPlanCommClient() {
+		return planCommClient;
+	}
+
+	public void setPlanCommClient(String planCommClient) {
+		this.planCommClient = planCommClient;
+	}
+
+	public Integer getScoreCommWriting() {
+		return scoreCommWriting;
+	}
+
+	public void setScoreCommWriting(Integer scoreCommWriting) {
+		this.scoreCommWriting = scoreCommWriting;
+	}
+
+	public String getPlanCommWriting() {
+		return planCommWriting;
+	}
+
+	public void setPlanCommWriting(String planCommWriting) {
+		this.planCommWriting = planCommWriting;
+	}
+
+	public Integer getScoreCommResponse() {
+		return scoreCommResponse;
+	}
+
+	public void setScoreCommResponse(Integer scoreCommResponse) {
+		this.scoreCommResponse = scoreCommResponse;
+	}
+
+	public String getPlanCommResponse() {
+		return planCommResponse;
+	}
+
+	public void setPlanCommResponse(String planCommResponse) {
+		this.planCommResponse = planCommResponse;
+	}
+
+	public Integer getScoreCommCross() {
+		return scoreCommCross;
+	}
+
+	public void setScoreCommCross(Integer scoreCommCross) {
+		this.scoreCommCross = scoreCommCross;
+	}
+
+	public String getPlanCommCross() {
+		return planCommCross;
+	}
+
+	public void setPlanCommCross(String planCommCross) {
+		this.planCommCross = planCommCross;
+	}
+
+	public Integer getScoreCommExpand() {
+		return scoreCommExpand;
+	}
+
+	public void setScoreCommExpand(Integer scoreCommExpand) {
+		this.scoreCommExpand = scoreCommExpand;
+	}
+
+	public String getPlanCommExpand() {
+		return planCommExpand;
+	}
+
+	public void setPlanCommExpand(String planCommExpand) {
+		this.planCommExpand = planCommExpand;
+	}
+
+	public String getCoreAdvantage() {
+		return coreAdvantage;
+	}
+
+	public void setCoreAdvantage(String coreAdvantage) {
+		this.coreAdvantage = coreAdvantage;
+	}
+
+	public String getProcessInstanceId() {
+		return processInstanceId;
+	}
+
+	public void setProcessInstanceId(String processInstanceId) {
+		this.processInstanceId = processInstanceId;
+	}
+
+	public String getSubmitStatus() {
+		return submitStatus;
+	}
+
+	public void setSubmitStatus(String submitStatus) {
+		this.submitStatus = submitStatus;
+	}
+
+	public Date getSubmitDate() {
+		return submitDate;
+	}
+
+	public void setSubmitDate(Date submitDate) {
+		this.submitDate = submitDate;
+	}
+
+	public WkQualityImprovementTask getTask() {
+		return task;
+	}
+
+	public void setTask(WkQualityImprovementTask task) {
+		this.task = task;
+	}
+
+	public User getUser() {
+		return user;
+	}
+
+	public void setUser(User user) {
+		this.user = user;
+	}
+
+	public String getToflag() {
+		return toflag;
+	}
+
+	public void setToflag(String toflag) {
+		this.toflag = toflag;
+	}
+
+	public String getCompanyId() {
+		return companyId;
+	}
+
+	public void setCompanyId(String companyId) {
+		this.companyId = companyId;
+	}
+
+	public String getRecordOfficeId() {
+		return recordOfficeId;
+	}
+
+	public void setRecordOfficeId(String recordOfficeId) {
+		this.recordOfficeId = recordOfficeId;
+	}
+
+	public String getOfficeId() {
+		return officeId;
+	}
+
+	public void setOfficeId(String officeId) {
+		this.officeId = officeId;
+	}
+}

+ 163 - 0
src/main/java/com/jeeplus/modules/workqualityimprovement/entity/WkQualityImprovementTask.java

@@ -0,0 +1,163 @@
+/**
+ * Copyright &copy; 2015-2020 <a href="http://www.jeeplus.org/">JeePlus</a> All rights reserved.
+ */
+package com.jeeplus.modules.workqualityimprovement.entity;
+
+import com.jeeplus.common.persistence.ActEntity;
+import com.jeeplus.modules.sys.entity.Office;
+import com.jeeplus.modules.sys.entity.User;
+
+/**
+ * 素养提升任务Entity
+ * @author jeeplus
+ * @version 2026-07-31
+ */
+public class WkQualityImprovementTask extends ActEntity<WkQualityImprovementTask> {
+
+	private static final long serialVersionUID = 1L;
+	private String title;			// 活动标题
+	private String year;			// 活动年份
+	private String description;		// 活动描述
+	private String status;			// 状态(0:草稿 1:已发送 2:已截止)
+	private String processInstanceId;	// Activiti流程实例ID
+	private String officeId;		// 创建部门ID
+	private String officeName;		// 创建部门名称
+
+	// 非数据库字段
+	private Office office;			// 创建部门对象
+	private User createByName;		// 创建人对象(用于展示)
+	private String createByNameStr;	// 创建人姓名
+	private String toflag;			// 查询标记
+	private String userId;			// 查询用-用户ID
+	private String submitStatus;	// 查询用-提交状态
+	private Integer submitCount;	// 已提交人数
+	private Integer totalCount;	// 总人数
+
+	public WkQualityImprovementTask() {
+		super();
+	}
+
+	public WkQualityImprovementTask(String id) {
+		super(id);
+	}
+
+	public String getTitle() {
+		return title;
+	}
+
+	public void setTitle(String title) {
+		this.title = title;
+	}
+
+	public String getYear() {
+		return year;
+	}
+
+	public void setYear(String year) {
+		this.year = year;
+	}
+
+	public String getDescription() {
+		return description;
+	}
+
+	public void setDescription(String description) {
+		this.description = description;
+	}
+
+	public String getStatus() {
+		return status;
+	}
+
+	public void setStatus(String status) {
+		this.status = status;
+	}
+
+	public String getProcessInstanceId() {
+		return processInstanceId;
+	}
+
+	public void setProcessInstanceId(String processInstanceId) {
+		this.processInstanceId = processInstanceId;
+	}
+
+	public String getOfficeId() {
+		return officeId;
+	}
+
+	public void setOfficeId(String officeId) {
+		this.officeId = officeId;
+	}
+
+	public String getOfficeName() {
+		return officeName;
+	}
+
+	public void setOfficeName(String officeName) {
+		this.officeName = officeName;
+	}
+
+	public Office getOffice() {
+		return office;
+	}
+
+	public void setOffice(Office office) {
+		this.office = office;
+	}
+
+	public User getCreateByName() {
+		return createByName;
+	}
+
+	public void setCreateByName(User createByName) {
+		this.createByName = createByName;
+	}
+
+	public String getCreateByNameStr() {
+		return createByNameStr;
+	}
+
+	public void setCreateByNameStr(String createByNameStr) {
+		this.createByNameStr = createByNameStr;
+	}
+
+	public String getToflag() {
+		return toflag;
+	}
+
+	public void setToflag(String toflag) {
+		this.toflag = toflag;
+	}
+
+	public String getUserId() {
+		return userId;
+	}
+
+	public void setUserId(String userId) {
+		this.userId = userId;
+	}
+
+	public String getSubmitStatus() {
+		return submitStatus;
+	}
+
+	public void setSubmitStatus(String submitStatus) {
+		this.submitStatus = submitStatus;
+	}
+
+	public Integer getSubmitCount() {
+		return submitCount;
+	}
+
+	public void setSubmitCount(Integer submitCount) {
+		this.submitCount = submitCount;
+	}
+
+	public Integer getTotalCount() {
+		return totalCount;
+	}
+
+	public void setTotalCount(Integer totalCount) {
+		this.totalCount = totalCount;
+	}
+}

+ 197 - 0
src/main/java/com/jeeplus/modules/workqualityimprovement/service/WkQualityImprovementRecordService.java

@@ -0,0 +1,197 @@
+/**
+ * Copyright &copy; 2015-2020 <a href="http://www.jeeplus.org/">JeePlus</a> All rights reserved.
+ */
+package com.jeeplus.modules.workqualityimprovement.service;
+
+import com.jeeplus.common.persistence.Page;
+import com.jeeplus.common.service.CrudService;
+import com.jeeplus.common.utils.MenuStatusEnum;
+import com.jeeplus.common.utils.StringUtils;
+import com.jeeplus.modules.sys.entity.User;
+import com.jeeplus.modules.sys.utils.UserUtils;
+import com.jeeplus.modules.workqualityimprovement.dao.WkQualityImprovementRecordDao;
+import com.jeeplus.modules.workqualityimprovement.entity.WkQualityImprovementRecord;
+import com.jeeplus.modules.workprojectnotify.entity.WorkProjectNotify;
+import com.jeeplus.modules.workprojectnotify.service.WorkProjectNotifyService;
+import org.activiti.engine.TaskService;
+import org.activiti.engine.task.Task;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.util.Date;
+import java.util.List;
+
+/**
+ * 素养提升个人记录Service
+ * @author jeeplus
+ * @version 2026-07-31
+ */
+@Service
+@Transactional(readOnly = true)
+public class WkQualityImprovementRecordService extends CrudService<WkQualityImprovementRecordDao, WkQualityImprovementRecord> {
+
+	@Autowired
+	private WkQualityImprovementRecordDao recordDao;
+
+	@Autowired
+	private TaskService taskService;
+
+	@Autowired
+	private WorkProjectNotifyService workProjectNotifyService;
+
+	@Override
+	public WkQualityImprovementRecord get(String id) {
+		return recordDao.getById(id);
+	}
+
+	@Override
+	public List<WkQualityImprovementRecord> findList(WkQualityImprovementRecord record) {
+		return recordDao.findList(record);
+	}
+
+	@Override
+	public Page<WkQualityImprovementRecord> findPage(Page<WkQualityImprovementRecord> page, WkQualityImprovementRecord record) {
+		//设置数据权限
+		if(!UserUtils.getUser().isAdmin()) {
+			String dataScopeSql = null;
+			dataScopeSql = dataScopeFilterOR(record.getCurrentUser(), "o", "u", "s", MenuStatusEnum.WORK_QUALITY_IMPROVEMENT.getValue());
+			if (StringUtils.isNotBlank(dataScopeSql)) {
+				record.getSqlMap().put("dsf", dataScopeSql);
+			} else {
+				// 未配置数据范围时兑底:仅可查看本人记录,避免看到全部数据
+				record.getSqlMap().put("onlySelf", "1");
+			}
+			record.getSqlMap().put("delFlag", "AND a.del_flag = 0");
+		}
+		int count = recordDao.queryCount(record);
+		page.setCount(count);
+		page.setCountFlag(false);
+		record.setPage(page);
+		List<WkQualityImprovementRecord> recordsList = findList(record);
+		page.setList(recordsList);
+		return page;
+	}
+
+	@Override
+	@Transactional(readOnly = false)
+	public void save(WkQualityImprovementRecord record) {
+		super.save(record);
+	}
+
+	@Override
+	@Transactional(readOnly = false)
+	public void delete(WkQualityImprovementRecord record) {
+		super.delete(record);
+	}
+
+	/**
+	 * 根据任务ID查询所有记录
+	 */
+	public List<WkQualityImprovementRecord> findByTaskId(String taskId) {
+		return recordDao.findByTaskId(taskId);
+	}
+
+	/**
+	 * 根据任务ID和用户ID查询记录
+	 */
+	public WkQualityImprovementRecord findByTaskIdAndUserId(String taskId, String userId) {
+		return recordDao.findByTaskIdAndUserId(taskId, userId);
+	}
+
+	/**
+	 * 根据流程实例ID查询记录
+	 */
+	public WkQualityImprovementRecord getByProcessInstanceId(String processInstanceId) {
+		return recordDao.getByProcessInstanceId(processInstanceId);
+	}
+
+	/**
+	 * 提交记录(填写完成后提交,不可再修改)
+	 */
+	@Transactional(readOnly = false)
+	public String submit(WkQualityImprovementRecord record) {
+		if (record == null || StringUtils.isBlank(record.getId())) {
+			return "记录不存在!";
+		}
+
+		WkQualityImprovementRecord existing = recordDao.getById(record.getId());
+		if (existing == null) {
+			return "记录不存在!";
+		}
+
+		// 填写提交仅限本人,禁止代填
+		if (StringUtils.isNotBlank(existing.getUserId()) && !existing.getUserId().equals(UserUtils.getUser().getId())) {
+			return "该记录仅限本人填写提交,不可代填!";
+		}
+
+		if ("1".equals(existing.getSubmitStatus())) {
+			return "该记录已提交,不可重复提交!";
+		}
+
+		// 更新记录内容
+		record.setId(existing.getId());
+		record.setSubmitStatus("1");
+		record.setSubmitDate(new Date());
+		record.setProcessInstanceId(existing.getProcessInstanceId());
+		record.preUpdate();
+		recordDao.update(record);
+		recordDao.updateSubmitStatus(record);
+
+		// 提交后同步更新待办通知:remarks置为已完成,status置为1,使其不再出现在首页待办栏
+		try {
+			WorkProjectNotify notify = new WorkProjectNotify();
+			notify.setNotifyId(existing.getTaskId());
+			notify.setUser(new User(existing.getUserId()));
+			notify.setType("202");
+			workProjectNotifyService.completeNotifyByNotifyIdAndUser(notify, "1", "已完成");
+		} catch (Exception e) {
+			// 通知更新失败不影响记录提交
+		}
+
+		// 完成Activiti任务
+		completeActivitiTask(existing.getProcessInstanceId());
+
+		return "";
+	}
+
+	/**
+	 * 完成Activiti任务
+	 */
+	private void completeActivitiTask(String processInstanceId) {
+		if (StringUtils.isBlank(processInstanceId)) {
+			return;
+		}
+		try {
+			List<Task> tasks = taskService.createTaskQuery()
+					.processInstanceId(processInstanceId)
+					.list();
+			for (Task task : tasks) {
+				taskService.complete(task.getId());
+			}
+		} catch (Exception e) {
+			// 流程任务完成失败不影响数据提交
+		}
+	}
+
+	/**
+	 * 查询全部记录(用于导出)
+	 */
+	public List<WkQualityImprovementRecord> findAllList(WkQualityImprovementRecord record) {
+		return recordDao.findAllList(record);
+	}
+
+	/**
+	 * 根据任务ID统计已提交人数
+	 */
+	public int countSubmittedByTaskId(String taskId) {
+		return recordDao.countSubmittedByTaskId(taskId);
+	}
+
+	/**
+	 * 根据任务ID统计总人数
+	 */
+	public int countByTaskId(String taskId) {
+		return recordDao.countByTaskId(taskId);
+	}
+}

+ 318 - 0
src/main/java/com/jeeplus/modules/workqualityimprovement/service/WkQualityImprovementTaskService.java

@@ -0,0 +1,318 @@
+/**
+ * Copyright &copy; 2015-2020 <a href="http://www.jeeplus.org/">JeePlus</a> All rights reserved.
+ */
+package com.jeeplus.modules.workqualityimprovement.service;
+
+import com.jeeplus.common.persistence.Page;
+import com.jeeplus.common.service.CrudService;
+import com.jeeplus.common.utils.IdGen;
+import com.jeeplus.common.utils.StringUtils;
+import com.jeeplus.modules.sys.entity.Office;
+import com.jeeplus.modules.sys.entity.User;
+import com.jeeplus.modules.sys.utils.UserUtils;
+import com.jeeplus.modules.workqualityimprovement.dao.WkQualityImprovementRecordDao;
+import com.jeeplus.modules.workqualityimprovement.dao.WkQualityImprovementTaskDao;
+import com.jeeplus.modules.workqualityimprovement.entity.WkQualityImprovementRecord;
+import com.jeeplus.modules.workqualityimprovement.entity.WkQualityImprovementTask;
+import com.jeeplus.modules.workprojectnotify.entity.WorkProjectNotify;
+import com.jeeplus.modules.workprojectnotify.service.WorkProjectNotifyService;
+import org.activiti.engine.IdentityService;
+import org.activiti.engine.RuntimeService;
+import org.activiti.engine.runtime.ProcessInstance;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.util.*;
+
+/**
+ * 素养提升任务Service
+ * @author jeeplus
+ * @version 2026-07-31
+ */
+@Service
+@Transactional(readOnly = true)
+public class WkQualityImprovementTaskService extends CrudService<WkQualityImprovementTaskDao, WkQualityImprovementTask> {
+
+	@Autowired
+	private WkQualityImprovementTaskDao taskDao;
+
+	@Autowired
+	private WkQualityImprovementRecordDao recordDao;
+
+	@Autowired
+	private RuntimeService runtimeService;
+
+	@Autowired
+	private IdentityService identityService;
+
+	@Autowired
+	private WorkProjectNotifyService workProjectNotifyService;
+
+	@Override
+	public WkQualityImprovementTask get(String id) {
+		return taskDao.getById(id);
+	}
+
+	@Override
+	public List<WkQualityImprovementTask> findList(WkQualityImprovementTask task) {
+		return taskDao.findList(task);
+	}
+
+	@Override
+	public Page<WkQualityImprovementTask> findPage(Page<WkQualityImprovementTask> page, WkQualityImprovementTask task) {
+		task.setPage(page);
+		page.setList(taskDao.findList(task));
+		return page;
+	}
+
+	@Override
+	@Transactional(readOnly = false)
+	public void save(WkQualityImprovementTask task) {
+		super.save(task);
+	}
+
+	@Override
+	@Transactional(readOnly = false)
+	public void delete(WkQualityImprovementTask task) {
+		// 先获取关联记录,用于清理通知
+		List<WkQualityImprovementRecord> existingRecords = recordDao.findByTaskId(task.getId());
+		// 逻辑删除每个用户在work_project_notify中的通知记录
+		if (existingRecords != null) {
+			for (WkQualityImprovementRecord r : existingRecords) {
+				WorkProjectNotify notify = new WorkProjectNotify();
+				notify.setNotifyId(task.getId());
+				User removedUser = new User(r.getUserId());
+				notify.setUser(removedUser);
+				workProjectNotifyService.modifyDelflagByUser(notify);
+			}
+		}
+		// 删除关联的记录
+		recordDao.deleteByTaskId(task.getId());
+		super.delete(task);
+	}
+
+	/**
+	 * 创建任务并为每个被选人创建记录
+	 * @param task 任务对象
+	 * @param userIds 被选人ID列表
+	 * @return 错误信息,空字符串表示成功
+	 */
+	@Transactional(readOnly = false)
+	public String createTaskAndSend(WkQualityImprovementTask task, List<String> userIds) {
+		if (userIds == null || userIds.size() == 0) {
+			return "请选择至少一名填写人员!";
+		}
+
+		// 1. 保存任务
+		task.setStatus("1"); // 已发送
+		// 设置创建部门信息
+		if (task.getOffice() != null && StringUtils.isNotBlank(task.getOffice().getId())) {
+			task.setOfficeId(task.getOffice().getId());
+			task.setOfficeName(task.getOffice().getName());
+		} else if (UserUtils.getUser().getOffice() != null) {
+			task.setOfficeId(UserUtils.getUser().getOffice().getId());
+			task.setOfficeName(UserUtils.getUser().getOffice().getName());
+		}
+		task.preInsert();
+		taskDao.insert(task);
+
+		// 2. 为每个被选人创建记录
+		for (String userId : userIds) {
+			User user = UserUtils.get(userId);
+			if (user == null) {
+				continue;
+			}
+
+			// 创建个人记录
+			WkQualityImprovementRecord record = new WkQualityImprovementRecord();
+			record.preInsert();
+			record.setTaskId(task.getId());
+			record.setTaskTitle(task.getTitle());
+			record.setTaskYear(task.getYear());
+			record.setUserId(userId);
+			record.setUserName(user.getName());
+			if (user.getOffice() != null) {
+				record.setOfficeName(user.getOffice().getName());
+			}
+			// 写入数据权限字段(部门/公司)
+			fillDataScopeFields(record, user);
+			record.setSubmitStatus("0"); // 未填写
+			recordDao.insert(record);
+		}
+
+		return "";
+	}
+
+	/**
+	 * 编辑任务并处理人员变动
+	 * 新增的人 -> 创建记录 + 发起流程
+	 * 去除的人 -> 逻辑删除记录
+	 * 未变化的人 -> 不做处理
+	 * @param task 任务对象
+	 * @param userIds 新的被选人ID列表
+	 * @return 错误信息,空字符串表示成功
+	 */
+	@Transactional(readOnly = false)
+	public String editTaskAndSend(WkQualityImprovementTask task, List<String> userIds) {
+		// 1. 更新任务基本信息
+		// 设置创建部门信息
+		if (StringUtils.isBlank(task.getOfficeId()) && UserUtils.getUser().getOffice() != null) {
+			task.setOfficeId(UserUtils.getUser().getOffice().getId());
+			task.setOfficeName(UserUtils.getUser().getOffice().getName());
+		}
+		task.preUpdate();
+		taskDao.update(task);
+
+		// 2. 获取现有的记录
+		List<WkQualityImprovementRecord> existingRecords = recordDao.findByTaskId(task.getId());
+		Set<String> existingUserIds = new HashSet<>();
+		if (existingRecords != null) {
+			for (WkQualityImprovementRecord r : existingRecords) {
+				existingUserIds.add(r.getUserId());
+			}
+		}
+
+		Set<String> newUserIds = new HashSet<>(userIds);
+
+		// 3. 找出新增的人
+		List<String> addedUserIds = new ArrayList<>();
+		for (String uid : newUserIds) {
+			if (!existingUserIds.contains(uid)) {
+				addedUserIds.add(uid);
+			}
+		}
+
+		// 4. 找出被去除的人
+		List<String> removedUserIds = new ArrayList<>();
+		for (String uid : existingUserIds) {
+			if (!newUserIds.contains(uid)) {
+				removedUserIds.add(uid);
+			}
+		}
+
+		// 5. 为新增的人创建记录
+		for (String uid : addedUserIds) {
+			User user = UserUtils.get(uid);
+			if (user == null) {
+				continue;
+			}
+			WkQualityImprovementRecord record = new WkQualityImprovementRecord();
+			record.preInsert();
+			record.setTaskId(task.getId());
+			record.setTaskTitle(task.getTitle());
+			record.setTaskYear(task.getYear());
+			record.setUserId(uid);
+			record.setUserName(user.getName());
+			if (user.getOffice() != null) {
+				record.setOfficeName(user.getOffice().getName());
+			}
+			// 写入数据权限字段(部门/公司)
+			fillDataScopeFields(record, user);
+			record.setSubmitStatus("0");
+			recordDao.insert(record);
+		}
+
+		// 6. 逻辑删除被去除的人的记录,并删除对应的通知记录
+		for (WkQualityImprovementRecord r : existingRecords) {
+			if (removedUserIds.contains(r.getUserId())) {
+				recordDao.logicalDeleteById(r.getId());
+				// 逻辑删除该用户在work_project_notify中对应的通知记录
+				WorkProjectNotify notify = new WorkProjectNotify();
+				notify.setNotifyId(task.getId());
+				User removedUser = new User(r.getUserId());
+				notify.setUser(removedUser);
+				workProjectNotifyService.modifyDelflagByUser(notify);
+			}
+		}
+
+		return "";
+	}
+
+	/**
+	 * 填充记录的数据权限字段:office_id 取填写人当前部门,company_id 取当前登录用户所属公司
+	 * (供 dataScopeFilterOR 生成的权限 SQL 按 a.office_id / a.company_id 过滤)
+	 */
+	private void fillDataScopeFields(WkQualityImprovementRecord record, User user) {
+		if (user.getOffice() != null && StringUtils.isNotBlank(user.getOffice().getId())) {
+			record.setRecordOfficeId(user.getOffice().getId());
+		}
+		Office company = null;
+		try {
+			company = UserUtils.getUser().getCompany();
+		} catch (Exception e) {
+			// 忽略
+		}
+		if (company == null || StringUtils.isBlank(company.getId())) {
+			try {
+				company = UserUtils.getSelectCompany();
+			} catch (Exception e) {
+				// 忽略
+			}
+		}
+		if (company != null && StringUtils.isNotBlank(company.getId())) {
+			record.setCompanyId(company.getId());
+		}
+	}
+
+	/**
+	 * 为任务下的所有记录启动Activiti流程(非事务,失败不影响数据)
+	 * @param taskId 任务ID
+	 */
+	public void startProcessesForTask(String taskId) {
+		List<WkQualityImprovementRecord> records = recordDao.findByTaskId(taskId);
+		if (records == null || records.isEmpty()) {
+			return;
+		}
+		for (WkQualityImprovementRecord record : records) {
+			User user = UserUtils.get(record.getUserId());
+			if (user == null) {
+				continue;
+			}
+			try {
+				String processInstanceId = startProcess(record, user);
+				if (StringUtils.isNotBlank(processInstanceId)) {
+					record.setProcessInstanceId(processInstanceId);
+					recordDao.updateSubmitStatus(record);
+				}
+			} catch (Exception e) {
+				// 流程启动失败不影响数据
+			}
+		}
+	}
+
+	/**
+	 * 启动Activiti流程(每个被选人一个独立流程实例)
+	 */
+	private String startProcess(WkQualityImprovementRecord record, User user) {
+		Map<String, Object> variables = new HashMap<String, Object>();
+		identityService.setAuthenticatedUserId(user.getId());
+
+		String businessKey = record.getId();
+		String processType = "qualityImprovement";
+
+		variables.put("busId", businessKey);
+		variables.put("type", processType);
+		variables.put("title", "素养提升计划填写:" + record.getTaskTitle());
+		variables.put("assignee", user.getId());
+
+		ProcessInstance processInstance = runtimeService.startProcessInstanceByKey(processType, businessKey, variables);
+
+		return processInstance.getId();
+	}
+
+	/**
+	 * 更新任务状态
+	 */
+	@Transactional(readOnly = false)
+	public void updateStatus(WkQualityImprovementTask task) {
+		taskDao.updateStatus(task);
+	}
+
+	/**
+	 * 根据ID查询任务
+	 */
+	public WkQualityImprovementTask getById(String id) {
+		return taskDao.getById(id);
+	}
+}

Rozdílová data souboru nebyla zobrazena, protože soubor je příliš velký
+ 1607 - 0
src/main/java/com/jeeplus/modules/workqualityimprovement/web/WkQualityImprovementController.java


+ 31 - 0
src/main/resources/act/designs/workqualityimprovement/qualityImprovement.bpmn

@@ -0,0 +1,31 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<definitions xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:activiti="http://activiti.org/bpmn" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:omgdc="http://www.omg.org/spec/DD/20100524/DC" xmlns:omgdi="http://www.omg.org/spec/DD/20100524/DI" typeLanguage="http://www.w3.org/2001/XMLSchema" expressionLanguage="http://www.w3.org/1999/XPath" targetNamespace="http://www.activiti.org/test">
+  <process id="qualityImprovement" name="素养提升计划填写流程" isExecutable="true">
+    <startEvent id="start" name="启动"/>
+    <endEvent id="end" name="结束"/>
+    <userTask id="fillTask" name="填写个人素养提升计划表" activiti:assignee="${assignee}"/>
+    <sequenceFlow id="flow1" sourceRef="start" targetRef="fillTask"/>
+    <sequenceFlow id="flow2" sourceRef="fillTask" targetRef="end"/>
+  </process>
+  <bpmndi:BPMNDiagram id="BPMNDiagram_qualityImprovement">
+    <bpmndi:BPMNPlane bpmnElement="qualityImprovement" id="BPMNPlane_qualityImprovement">
+      <bpmndi:BPMNShape bpmnElement="start" id="BPMNShape_start">
+        <omgdc:Bounds height="30.0" width="30.0" x="30.0" y="150.0"/>
+      </bpmndi:BPMNShape>
+      <bpmndi:BPMNShape bpmnElement="end" id="BPMNShape_end">
+        <omgdc:Bounds height="28.0" width="28.0" x="350.0" y="152.0"/>
+      </bpmndi:BPMNShape>
+      <bpmndi:BPMNShape bpmnElement="fillTask" id="BPMNShape_fillTask">
+        <omgdc:Bounds height="80.0" width="120.0" x="140.0" y="125.0"/>
+      </bpmndi:BPMNShape>
+      <bpmndi:BPMNEdge bpmnElement="flow1" id="BPMNEdge_flow1">
+        <omgdi:waypoint x="60.0" y="165.0"/>
+        <omgdi:waypoint x="140.0" y="165.0"/>
+      </bpmndi:BPMNEdge>
+      <bpmndi:BPMNEdge bpmnElement="flow2" id="BPMNEdge_flow2">
+        <omgdi:waypoint x="260.0" y="165.0"/>
+        <omgdi:waypoint x="350.0" y="166.0"/>
+      </bpmndi:BPMNEdge>
+    </bpmndi:BPMNPlane>
+  </bpmndi:BPMNDiagram>
+</definitions>

+ 14 - 0
src/main/resources/freemarker/docx_template/[Content_Types].xml

@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<Types xmlns="http://schemas.openxmlformats.org/package/2006/content-types">
+  <Default Extension="rels" ContentType="application/vnd.openxmlformats-package.relationships+xml"/>
+  <Default Extension="xml" ContentType="application/xml"/>
+  <Override PartName="/word/document.xml" ContentType="application/vnd.openxmlformats-officedocument.wordprocessingml.document.main+xml"/>
+  <Override PartName="/word/styles.xml" ContentType="application/vnd.openxmlformats-officedocument.wordprocessingml.styles+xml"/>
+  <Override PartName="/word/settings.xml" ContentType="application/vnd.openxmlformats-officedocument.wordprocessingml.settings+xml"/>
+  <Override PartName="/word/fontTable.xml" ContentType="application/vnd.openxmlformats-officedocument.wordprocessingml.fontTable+xml"/>
+  <Override PartName="/word/webSettings.xml" ContentType="application/vnd.openxmlformats-officedocument.wordprocessingml.webSettings+xml"/>
+  <Override PartName="/word/theme/theme1.xml" ContentType="application/vnd.openxmlformats-officedocument.theme+xml"/>
+  <Override PartName="/docProps/core.xml" ContentType="application/vnd.openxmlformats-package.core-properties+xml"/>
+  <Override PartName="/docProps/app.xml" ContentType="application/vnd.ms-office.activeX+xml"/>
+  <Override PartName="/docProps/custom.xml" ContentType="application/vnd.openxmlformats-officedocument.custom-properties+xml"/>
+</Types>

+ 6 - 0
src/main/resources/freemarker/docx_template/_rels/.rels

@@ -0,0 +1,6 @@
+			<Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships">
+				<Relationship Id="rId3" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/extended-properties" Target="docProps/app.xml"/>
+				<Relationship Id="rId2" Type="http://schemas.openxmlformats.org/package/2006/relationships/metadata/core-properties" Target="docProps/core.xml"/>
+				<Relationship Id="rId1" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument" Target="word/document.xml"/>
+				<Relationship Id="rId4" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/custom-properties" Target="docProps/custom.xml"/>
+			</Relationships>

+ 18 - 0
src/main/resources/freemarker/docx_template/docProps/app.xml

@@ -0,0 +1,18 @@
+			<Properties xmlns="http://schemas.openxmlformats.org/officeDocument/2006/extended-properties" xmlns:vt="http://schemas.openxmlformats.org/officeDocument/2006/docPropsVTypes">
+				<Template>Normal.dotm</Template>
+				<TotalTime>1</TotalTime>
+				<Pages>2</Pages>
+				<Words>110</Words>
+				<Characters>633</Characters>
+				<Application>Microsoft Office Word</Application>
+				<DocSecurity>0</DocSecurity>
+				<Lines>5</Lines>
+				<Paragraphs>1</Paragraphs>
+				<ScaleCrop>false</ScaleCrop>
+				<Company/>
+				<LinksUpToDate>false</LinksUpToDate>
+				<CharactersWithSpaces>742</CharactersWithSpaces>
+				<SharedDoc>false</SharedDoc>
+				<HyperlinksChanged>false</HyperlinksChanged>
+				<AppVersion>16.0000</AppVersion>
+			</Properties>

+ 7 - 0
src/main/resources/freemarker/docx_template/docProps/core.xml

@@ -0,0 +1,7 @@
+			<cp:coreProperties xmlns:cp="http://schemas.openxmlformats.org/package/2006/metadata/core-properties" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:dcterms="http://purl.org/dc/terms/" xmlns:dcmitype="http://purl.org/dc/dcmitype/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+				<dc:creator>静秋草</dc:creator>
+				<cp:lastModifiedBy>CDB</cp:lastModifiedBy>
+				<cp:revision>2</cp:revision>
+				<dcterms:created xsi:type="dcterms:W3CDTF">2026-07-31T08:54:00Z</dcterms:created>
+				<dcterms:modified xsi:type="dcterms:W3CDTF">2026-07-31T08:54:00Z</dcterms:modified>
+			</cp:coreProperties>

+ 11 - 0
src/main/resources/freemarker/docx_template/docProps/custom.xml

@@ -0,0 +1,11 @@
+			<Properties xmlns="http://schemas.openxmlformats.org/officeDocument/2006/custom-properties" xmlns:vt="http://schemas.openxmlformats.org/officeDocument/2006/docPropsVTypes">
+				<property fmtid="{D5CDD505-2E9C-101B-9397-08002B2CF9AE}" pid="2" name="KSOProductBuildVer">
+					<vt:lpwstr>2052-12.1.0.28043</vt:lpwstr>
+				</property>
+				<property fmtid="{D5CDD505-2E9C-101B-9397-08002B2CF9AE}" pid="3" name="ICV">
+					<vt:lpwstr>C4ECDF8FE17A4437956BCCBAEA8711E8_11</vt:lpwstr>
+				</property>
+				<property fmtid="{D5CDD505-2E9C-101B-9397-08002B2CF9AE}" pid="4" name="KSOTemplateDocerSaveRecord">
+					<vt:lpwstr>eyJoZGlkIjoiMGUyMzFjYzM5YTVhNGUwNzBkNGM0OTYzYmNiMjk3YWEiLCJ1c2VySWQiOiIyNTg1MTkyNjUifQ==</vt:lpwstr>
+				</property>
+			</Properties>

+ 7 - 0
src/main/resources/freemarker/docx_template/word/_rels/document.xml.rels

@@ -0,0 +1,7 @@
+			<Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships">
+				<Relationship Id="rId3" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/webSettings" Target="webSettings.xml"/>
+				<Relationship Id="rId2" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/settings" Target="settings.xml"/>
+				<Relationship Id="rId1" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/styles" Target="styles.xml"/>
+				<Relationship Id="rId5" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/theme" Target="theme/theme1.xml"/>
+				<Relationship Id="rId4" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/fontTable" Target="fontTable.xml"/>
+			</Relationships>

+ 38 - 0
src/main/resources/freemarker/docx_template/word/fontTable.xml

@@ -0,0 +1,38 @@
+			<w:fonts xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships" xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main" xmlns:w14="http://schemas.microsoft.com/office/word/2010/wordml" xmlns:w15="http://schemas.microsoft.com/office/word/2012/wordml" xmlns:w16se="http://schemas.microsoft.com/office/word/2015/wordml/symex" mc:Ignorable="w14 w15 w16se">
+				<w:font w:name="Times New Roman">
+					<w:panose1 w:val="02020603050405020304"/>
+					<w:charset w:val="00"/>
+					<w:family w:val="roman"/>
+					<w:pitch w:val="variable"/>
+					<w:sig w:usb0="E0002EFF" w:usb1="C000785B" w:usb2="00000009" w:usb3="00000000" w:csb0="000001FF" w:csb1="00000000"/>
+				</w:font>
+				<w:font w:name="宋体">
+					<w:altName w:val="SimSun"/>
+					<w:panose1 w:val="02010600030101010101"/>
+					<w:charset w:val="86"/>
+					<w:family w:val="auto"/>
+					<w:pitch w:val="variable"/>
+					<w:sig w:usb0="00000203" w:usb1="288F0000" w:usb2="00000016" w:usb3="00000000" w:csb0="00040001" w:csb1="00000000"/>
+				</w:font>
+				<w:font w:name="Calibri">
+					<w:panose1 w:val="020F0502020204030204"/>
+					<w:charset w:val="00"/>
+					<w:family w:val="swiss"/>
+					<w:pitch w:val="variable"/>
+					<w:sig w:usb0="E4002EFF" w:usb1="C000247B" w:usb2="00000009" w:usb3="00000000" w:csb0="000001FF" w:csb1="00000000"/>
+				</w:font>
+				<w:font w:name="Segoe UI">
+					<w:panose1 w:val="020B0502040204020203"/>
+					<w:charset w:val="00"/>
+					<w:family w:val="swiss"/>
+					<w:pitch w:val="variable"/>
+					<w:sig w:usb0="E4002EFF" w:usb1="C000E47F" w:usb2="00000009" w:usb3="00000000" w:csb0="000001FF" w:csb1="00000000"/>
+				</w:font>
+				<w:font w:name="Calibri Light">
+					<w:panose1 w:val="020F0302020204030204"/>
+					<w:charset w:val="00"/>
+					<w:family w:val="swiss"/>
+					<w:pitch w:val="variable"/>
+					<w:sig w:usb0="E4002EFF" w:usb1="C000247B" w:usb2="00000009" w:usb3="00000000" w:csb0="000001FF" w:csb1="00000000"/>
+				</w:font>
+			</w:fonts>

Rozdílová data souboru nebyla zobrazena, protože soubor je příliš velký
+ 66 - 0
src/main/resources/freemarker/docx_template/word/settings.xml


+ 423 - 0
src/main/resources/freemarker/docx_template/word/styles.xml

@@ -0,0 +1,423 @@
+			<w:styles xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships" xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main" xmlns:w14="http://schemas.microsoft.com/office/word/2010/wordml" xmlns:w15="http://schemas.microsoft.com/office/word/2012/wordml" xmlns:w16se="http://schemas.microsoft.com/office/word/2015/wordml/symex" mc:Ignorable="w14 w15 w16se">
+				<w:docDefaults>
+					<w:rPrDefault>
+						<w:rPr>
+							<w:rFonts w:ascii="Times New Roman" w:eastAsia="宋体" w:hAnsi="Times New Roman" w:cs="Times New Roman"/>
+							<w:lang w:val="en-US" w:eastAsia="zh-CN" w:bidi="ar-SA"/>
+						</w:rPr>
+					</w:rPrDefault>
+					<w:pPrDefault/>
+				</w:docDefaults>
+				<w:latentStyles w:defLockedState="0" w:defUIPriority="0" w:defSemiHidden="0" w:defUnhideWhenUsed="0" w:defQFormat="0" w:count="371">
+					<w:lsdException w:name="Normal" w:qFormat="1"/>
+					<w:lsdException w:name="heading 1" w:qFormat="1"/>
+					<w:lsdException w:name="heading 2" w:unhideWhenUsed="1" w:qFormat="1"/>
+					<w:lsdException w:name="heading 3" w:unhideWhenUsed="1" w:qFormat="1"/>
+					<w:lsdException w:name="heading 4" w:semiHidden="1" w:unhideWhenUsed="1" w:qFormat="1"/>
+					<w:lsdException w:name="heading 5" w:semiHidden="1" w:unhideWhenUsed="1" w:qFormat="1"/>
+					<w:lsdException w:name="heading 6" w:semiHidden="1" w:unhideWhenUsed="1" w:qFormat="1"/>
+					<w:lsdException w:name="heading 7" w:semiHidden="1" w:unhideWhenUsed="1" w:qFormat="1"/>
+					<w:lsdException w:name="heading 8" w:semiHidden="1" w:unhideWhenUsed="1" w:qFormat="1"/>
+					<w:lsdException w:name="heading 9" w:semiHidden="1" w:unhideWhenUsed="1" w:qFormat="1"/>
+					<w:lsdException w:name="caption" w:semiHidden="1" w:unhideWhenUsed="1" w:qFormat="1"/>
+					<w:lsdException w:name="Title" w:qFormat="1"/>
+					<w:lsdException w:name="Default Paragraph Font" w:semiHidden="1" w:qFormat="1"/>
+					<w:lsdException w:name="Subtitle" w:qFormat="1"/>
+					<w:lsdException w:name="Strong" w:qFormat="1"/>
+					<w:lsdException w:name="Emphasis" w:qFormat="1"/>
+					<w:lsdException w:name="HTML Top of Form" w:semiHidden="1" w:uiPriority="99" w:unhideWhenUsed="1"/>
+					<w:lsdException w:name="HTML Bottom of Form" w:semiHidden="1" w:uiPriority="99" w:unhideWhenUsed="1"/>
+					<w:lsdException w:name="Normal (Web)" w:qFormat="1"/>
+					<w:lsdException w:name="Normal Table" w:semiHidden="1" w:unhideWhenUsed="1" w:qFormat="1"/>
+					<w:lsdException w:name="No List" w:semiHidden="1" w:uiPriority="99" w:unhideWhenUsed="1"/>
+					<w:lsdException w:name="Outline List 1" w:semiHidden="1" w:uiPriority="99" w:unhideWhenUsed="1"/>
+					<w:lsdException w:name="Outline List 2" w:semiHidden="1" w:uiPriority="99" w:unhideWhenUsed="1"/>
+					<w:lsdException w:name="Outline List 3" w:semiHidden="1" w:uiPriority="99" w:unhideWhenUsed="1"/>
+					<w:lsdException w:name="Table Simple 1" w:semiHidden="1" w:unhideWhenUsed="1"/>
+					<w:lsdException w:name="Table Simple 2" w:semiHidden="1" w:unhideWhenUsed="1"/>
+					<w:lsdException w:name="Table Simple 3" w:semiHidden="1" w:unhideWhenUsed="1"/>
+					<w:lsdException w:name="Table Classic 1" w:semiHidden="1" w:unhideWhenUsed="1"/>
+					<w:lsdException w:name="Table Classic 2" w:semiHidden="1" w:unhideWhenUsed="1"/>
+					<w:lsdException w:name="Table Classic 3" w:semiHidden="1" w:unhideWhenUsed="1"/>
+					<w:lsdException w:name="Table Classic 4" w:semiHidden="1" w:unhideWhenUsed="1"/>
+					<w:lsdException w:name="Table Colorful 1" w:semiHidden="1" w:unhideWhenUsed="1"/>
+					<w:lsdException w:name="Table Colorful 2" w:semiHidden="1" w:unhideWhenUsed="1"/>
+					<w:lsdException w:name="Table Colorful 3" w:semiHidden="1" w:unhideWhenUsed="1"/>
+					<w:lsdException w:name="Table Columns 1" w:semiHidden="1" w:unhideWhenUsed="1"/>
+					<w:lsdException w:name="Table Columns 2" w:semiHidden="1" w:unhideWhenUsed="1"/>
+					<w:lsdException w:name="Table Columns 3" w:semiHidden="1" w:unhideWhenUsed="1"/>
+					<w:lsdException w:name="Table Columns 4" w:semiHidden="1" w:unhideWhenUsed="1"/>
+					<w:lsdException w:name="Table Columns 5" w:semiHidden="1" w:unhideWhenUsed="1"/>
+					<w:lsdException w:name="Table Grid 1" w:semiHidden="1" w:unhideWhenUsed="1"/>
+					<w:lsdException w:name="Table Grid 2" w:semiHidden="1" w:unhideWhenUsed="1"/>
+					<w:lsdException w:name="Table Grid 3" w:semiHidden="1" w:unhideWhenUsed="1"/>
+					<w:lsdException w:name="Table Grid 4" w:semiHidden="1" w:unhideWhenUsed="1"/>
+					<w:lsdException w:name="Table Grid 5" w:semiHidden="1" w:unhideWhenUsed="1"/>
+					<w:lsdException w:name="Table Grid 6" w:semiHidden="1" w:unhideWhenUsed="1"/>
+					<w:lsdException w:name="Table Grid 7" w:semiHidden="1" w:unhideWhenUsed="1"/>
+					<w:lsdException w:name="Table Grid 8" w:semiHidden="1" w:unhideWhenUsed="1"/>
+					<w:lsdException w:name="Table List 1" w:semiHidden="1" w:unhideWhenUsed="1"/>
+					<w:lsdException w:name="Table List 2" w:semiHidden="1" w:unhideWhenUsed="1"/>
+					<w:lsdException w:name="Table List 3" w:semiHidden="1" w:unhideWhenUsed="1"/>
+					<w:lsdException w:name="Table List 4" w:semiHidden="1" w:unhideWhenUsed="1"/>
+					<w:lsdException w:name="Table List 5" w:semiHidden="1" w:unhideWhenUsed="1"/>
+					<w:lsdException w:name="Table List 6" w:semiHidden="1" w:unhideWhenUsed="1"/>
+					<w:lsdException w:name="Table List 7" w:semiHidden="1" w:unhideWhenUsed="1"/>
+					<w:lsdException w:name="Table List 8" w:semiHidden="1" w:unhideWhenUsed="1"/>
+					<w:lsdException w:name="Table 3D effects 1" w:semiHidden="1" w:unhideWhenUsed="1"/>
+					<w:lsdException w:name="Table 3D effects 2" w:semiHidden="1" w:unhideWhenUsed="1"/>
+					<w:lsdException w:name="Table 3D effects 3" w:semiHidden="1" w:unhideWhenUsed="1"/>
+					<w:lsdException w:name="Table Contemporary" w:semiHidden="1" w:unhideWhenUsed="1"/>
+					<w:lsdException w:name="Table Elegant" w:semiHidden="1" w:unhideWhenUsed="1"/>
+					<w:lsdException w:name="Table Professional" w:semiHidden="1" w:unhideWhenUsed="1"/>
+					<w:lsdException w:name="Table Subtle 1" w:semiHidden="1" w:unhideWhenUsed="1"/>
+					<w:lsdException w:name="Table Subtle 2" w:semiHidden="1" w:unhideWhenUsed="1"/>
+					<w:lsdException w:name="Table Web 1" w:semiHidden="1" w:unhideWhenUsed="1"/>
+					<w:lsdException w:name="Table Web 2" w:semiHidden="1" w:unhideWhenUsed="1"/>
+					<w:lsdException w:name="Table Web 3" w:semiHidden="1" w:unhideWhenUsed="1"/>
+					<w:lsdException w:name="Table Grid" w:semiHidden="1" w:unhideWhenUsed="1" w:qFormat="1"/>
+					<w:lsdException w:name="Table Theme" w:semiHidden="1" w:unhideWhenUsed="1"/>
+					<w:lsdException w:name="Placeholder Text" w:semiHidden="1" w:uiPriority="99"/>
+					<w:lsdException w:name="No Spacing" w:uiPriority="99"/>
+					<w:lsdException w:name="Light Shading" w:uiPriority="60"/>
+					<w:lsdException w:name="Light List" w:uiPriority="61"/>
+					<w:lsdException w:name="Light Grid" w:uiPriority="62"/>
+					<w:lsdException w:name="Medium Shading 1" w:uiPriority="63"/>
+					<w:lsdException w:name="Medium Shading 2" w:uiPriority="64"/>
+					<w:lsdException w:name="Medium List 1" w:uiPriority="65"/>
+					<w:lsdException w:name="Medium List 2" w:uiPriority="66"/>
+					<w:lsdException w:name="Medium Grid 1" w:uiPriority="67"/>
+					<w:lsdException w:name="Medium Grid 2" w:uiPriority="68"/>
+					<w:lsdException w:name="Medium Grid 3" w:uiPriority="69"/>
+					<w:lsdException w:name="Dark List" w:uiPriority="70"/>
+					<w:lsdException w:name="Colorful Shading" w:uiPriority="71"/>
+					<w:lsdException w:name="Colorful List" w:uiPriority="72"/>
+					<w:lsdException w:name="Colorful Grid" w:uiPriority="73"/>
+					<w:lsdException w:name="Light Shading Accent 1" w:uiPriority="60"/>
+					<w:lsdException w:name="Light List Accent 1" w:uiPriority="61"/>
+					<w:lsdException w:name="Light Grid Accent 1" w:uiPriority="62"/>
+					<w:lsdException w:name="Medium Shading 1 Accent 1" w:uiPriority="63"/>
+					<w:lsdException w:name="Medium Shading 2 Accent 1" w:uiPriority="64"/>
+					<w:lsdException w:name="Medium List 1 Accent 1" w:uiPriority="65"/>
+					<w:lsdException w:name="Revision" w:semiHidden="1" w:uiPriority="99"/>
+					<w:lsdException w:name="List Paragraph" w:uiPriority="99"/>
+					<w:lsdException w:name="Quote" w:uiPriority="99"/>
+					<w:lsdException w:name="Intense Quote" w:uiPriority="99"/>
+					<w:lsdException w:name="Medium List 2 Accent 1" w:uiPriority="66"/>
+					<w:lsdException w:name="Medium Grid 1 Accent 1" w:uiPriority="67"/>
+					<w:lsdException w:name="Medium Grid 2 Accent 1" w:uiPriority="68"/>
+					<w:lsdException w:name="Medium Grid 3 Accent 1" w:uiPriority="69"/>
+					<w:lsdException w:name="Dark List Accent 1" w:uiPriority="70"/>
+					<w:lsdException w:name="Colorful Shading Accent 1" w:uiPriority="71"/>
+					<w:lsdException w:name="Colorful List Accent 1" w:uiPriority="72"/>
+					<w:lsdException w:name="Colorful Grid Accent 1" w:uiPriority="73"/>
+					<w:lsdException w:name="Light Shading Accent 2" w:uiPriority="60"/>
+					<w:lsdException w:name="Light List Accent 2" w:uiPriority="61"/>
+					<w:lsdException w:name="Light Grid Accent 2" w:uiPriority="62"/>
+					<w:lsdException w:name="Medium Shading 1 Accent 2" w:uiPriority="63"/>
+					<w:lsdException w:name="Medium Shading 2 Accent 2" w:uiPriority="64"/>
+					<w:lsdException w:name="Medium List 1 Accent 2" w:uiPriority="65"/>
+					<w:lsdException w:name="Medium List 2 Accent 2" w:uiPriority="66"/>
+					<w:lsdException w:name="Medium Grid 1 Accent 2" w:uiPriority="67"/>
+					<w:lsdException w:name="Medium Grid 2 Accent 2" w:uiPriority="68"/>
+					<w:lsdException w:name="Medium Grid 3 Accent 2" w:uiPriority="69"/>
+					<w:lsdException w:name="Dark List Accent 2" w:uiPriority="70"/>
+					<w:lsdException w:name="Colorful Shading Accent 2" w:uiPriority="71"/>
+					<w:lsdException w:name="Colorful List Accent 2" w:uiPriority="72"/>
+					<w:lsdException w:name="Colorful Grid Accent 2" w:uiPriority="73"/>
+					<w:lsdException w:name="Light Shading Accent 3" w:uiPriority="60"/>
+					<w:lsdException w:name="Light List Accent 3" w:uiPriority="61"/>
+					<w:lsdException w:name="Light Grid Accent 3" w:uiPriority="62"/>
+					<w:lsdException w:name="Medium Shading 1 Accent 3" w:uiPriority="63"/>
+					<w:lsdException w:name="Medium Shading 2 Accent 3" w:uiPriority="64"/>
+					<w:lsdException w:name="Medium List 1 Accent 3" w:uiPriority="65"/>
+					<w:lsdException w:name="Medium List 2 Accent 3" w:uiPriority="66"/>
+					<w:lsdException w:name="Medium Grid 1 Accent 3" w:uiPriority="67"/>
+					<w:lsdException w:name="Medium Grid 2 Accent 3" w:uiPriority="68"/>
+					<w:lsdException w:name="Medium Grid 3 Accent 3" w:uiPriority="69"/>
+					<w:lsdException w:name="Dark List Accent 3" w:uiPriority="70"/>
+					<w:lsdException w:name="Colorful Shading Accent 3" w:uiPriority="71"/>
+					<w:lsdException w:name="Colorful List Accent 3" w:uiPriority="72"/>
+					<w:lsdException w:name="Colorful Grid Accent 3" w:uiPriority="73"/>
+					<w:lsdException w:name="Light Shading Accent 4" w:uiPriority="60"/>
+					<w:lsdException w:name="Light List Accent 4" w:uiPriority="61"/>
+					<w:lsdException w:name="Light Grid Accent 4" w:uiPriority="62"/>
+					<w:lsdException w:name="Medium Shading 1 Accent 4" w:uiPriority="63"/>
+					<w:lsdException w:name="Medium Shading 2 Accent 4" w:uiPriority="64"/>
+					<w:lsdException w:name="Medium List 1 Accent 4" w:uiPriority="65"/>
+					<w:lsdException w:name="Medium List 2 Accent 4" w:uiPriority="66"/>
+					<w:lsdException w:name="Medium Grid 1 Accent 4" w:uiPriority="67"/>
+					<w:lsdException w:name="Medium Grid 2 Accent 4" w:uiPriority="68"/>
+					<w:lsdException w:name="Medium Grid 3 Accent 4" w:uiPriority="69"/>
+					<w:lsdException w:name="Dark List Accent 4" w:uiPriority="70"/>
+					<w:lsdException w:name="Colorful Shading Accent 4" w:uiPriority="71"/>
+					<w:lsdException w:name="Colorful List Accent 4" w:uiPriority="72"/>
+					<w:lsdException w:name="Colorful Grid Accent 4" w:uiPriority="73"/>
+					<w:lsdException w:name="Light Shading Accent 5" w:uiPriority="60"/>
+					<w:lsdException w:name="Light List Accent 5" w:uiPriority="61"/>
+					<w:lsdException w:name="Light Grid Accent 5" w:uiPriority="62"/>
+					<w:lsdException w:name="Medium Shading 1 Accent 5" w:uiPriority="63"/>
+					<w:lsdException w:name="Medium Shading 2 Accent 5" w:uiPriority="64"/>
+					<w:lsdException w:name="Medium List 1 Accent 5" w:uiPriority="65"/>
+					<w:lsdException w:name="Medium List 2 Accent 5" w:uiPriority="66"/>
+					<w:lsdException w:name="Medium Grid 1 Accent 5" w:uiPriority="67"/>
+					<w:lsdException w:name="Medium Grid 2 Accent 5" w:uiPriority="68"/>
+					<w:lsdException w:name="Medium Grid 3 Accent 5" w:uiPriority="69"/>
+					<w:lsdException w:name="Dark List Accent 5" w:uiPriority="70"/>
+					<w:lsdException w:name="Colorful Shading Accent 5" w:uiPriority="71"/>
+					<w:lsdException w:name="Colorful List Accent 5" w:uiPriority="72"/>
+					<w:lsdException w:name="Colorful Grid Accent 5" w:uiPriority="73"/>
+					<w:lsdException w:name="Light Shading Accent 6" w:uiPriority="60"/>
+					<w:lsdException w:name="Light List Accent 6" w:uiPriority="61"/>
+					<w:lsdException w:name="Light Grid Accent 6" w:uiPriority="62"/>
+					<w:lsdException w:name="Medium Shading 1 Accent 6" w:uiPriority="63"/>
+					<w:lsdException w:name="Medium Shading 2 Accent 6" w:uiPriority="64"/>
+					<w:lsdException w:name="Medium List 1 Accent 6" w:uiPriority="65"/>
+					<w:lsdException w:name="Medium List 2 Accent 6" w:uiPriority="66"/>
+					<w:lsdException w:name="Medium Grid 1 Accent 6" w:uiPriority="67"/>
+					<w:lsdException w:name="Medium Grid 2 Accent 6" w:uiPriority="68"/>
+					<w:lsdException w:name="Medium Grid 3 Accent 6" w:uiPriority="69"/>
+					<w:lsdException w:name="Dark List Accent 6" w:uiPriority="70"/>
+					<w:lsdException w:name="Colorful Shading Accent 6" w:uiPriority="71"/>
+					<w:lsdException w:name="Colorful List Accent 6" w:uiPriority="72"/>
+					<w:lsdException w:name="Colorful Grid Accent 6" w:uiPriority="73"/>
+					<w:lsdException w:name="Subtle Emphasis" w:uiPriority="19" w:qFormat="1"/>
+					<w:lsdException w:name="Intense Emphasis" w:uiPriority="21" w:qFormat="1"/>
+					<w:lsdException w:name="Subtle Reference" w:uiPriority="31" w:qFormat="1"/>
+					<w:lsdException w:name="Intense Reference" w:uiPriority="32" w:qFormat="1"/>
+					<w:lsdException w:name="Book Title" w:uiPriority="33" w:qFormat="1"/>
+					<w:lsdException w:name="Bibliography" w:semiHidden="1" w:uiPriority="37" w:unhideWhenUsed="1"/>
+					<w:lsdException w:name="TOC Heading" w:semiHidden="1" w:uiPriority="39" w:unhideWhenUsed="1" w:qFormat="1"/>
+					<w:lsdException w:name="Plain Table 1" w:uiPriority="41"/>
+					<w:lsdException w:name="Plain Table 2" w:uiPriority="42"/>
+					<w:lsdException w:name="Plain Table 3" w:uiPriority="43"/>
+					<w:lsdException w:name="Plain Table 4" w:uiPriority="44"/>
+					<w:lsdException w:name="Plain Table 5" w:uiPriority="45"/>
+					<w:lsdException w:name="Grid Table Light" w:uiPriority="40"/>
+					<w:lsdException w:name="Grid Table 1 Light" w:uiPriority="46"/>
+					<w:lsdException w:name="Grid Table 2" w:uiPriority="47"/>
+					<w:lsdException w:name="Grid Table 3" w:uiPriority="48"/>
+					<w:lsdException w:name="Grid Table 4" w:uiPriority="49"/>
+					<w:lsdException w:name="Grid Table 5 Dark" w:uiPriority="50"/>
+					<w:lsdException w:name="Grid Table 6 Colorful" w:uiPriority="51"/>
+					<w:lsdException w:name="Grid Table 7 Colorful" w:uiPriority="52"/>
+					<w:lsdException w:name="Grid Table 1 Light Accent 1" w:uiPriority="46"/>
+					<w:lsdException w:name="Grid Table 2 Accent 1" w:uiPriority="47"/>
+					<w:lsdException w:name="Grid Table 3 Accent 1" w:uiPriority="48"/>
+					<w:lsdException w:name="Grid Table 4 Accent 1" w:uiPriority="49"/>
+					<w:lsdException w:name="Grid Table 5 Dark Accent 1" w:uiPriority="50"/>
+					<w:lsdException w:name="Grid Table 6 Colorful Accent 1" w:uiPriority="51"/>
+					<w:lsdException w:name="Grid Table 7 Colorful Accent 1" w:uiPriority="52"/>
+					<w:lsdException w:name="Grid Table 1 Light Accent 2" w:uiPriority="46"/>
+					<w:lsdException w:name="Grid Table 2 Accent 2" w:uiPriority="47"/>
+					<w:lsdException w:name="Grid Table 3 Accent 2" w:uiPriority="48"/>
+					<w:lsdException w:name="Grid Table 4 Accent 2" w:uiPriority="49"/>
+					<w:lsdException w:name="Grid Table 5 Dark Accent 2" w:uiPriority="50"/>
+					<w:lsdException w:name="Grid Table 6 Colorful Accent 2" w:uiPriority="51"/>
+					<w:lsdException w:name="Grid Table 7 Colorful Accent 2" w:uiPriority="52"/>
+					<w:lsdException w:name="Grid Table 1 Light Accent 3" w:uiPriority="46"/>
+					<w:lsdException w:name="Grid Table 2 Accent 3" w:uiPriority="47"/>
+					<w:lsdException w:name="Grid Table 3 Accent 3" w:uiPriority="48"/>
+					<w:lsdException w:name="Grid Table 4 Accent 3" w:uiPriority="49"/>
+					<w:lsdException w:name="Grid Table 5 Dark Accent 3" w:uiPriority="50"/>
+					<w:lsdException w:name="Grid Table 6 Colorful Accent 3" w:uiPriority="51"/>
+					<w:lsdException w:name="Grid Table 7 Colorful Accent 3" w:uiPriority="52"/>
+					<w:lsdException w:name="Grid Table 1 Light Accent 4" w:uiPriority="46"/>
+					<w:lsdException w:name="Grid Table 2 Accent 4" w:uiPriority="47"/>
+					<w:lsdException w:name="Grid Table 3 Accent 4" w:uiPriority="48"/>
+					<w:lsdException w:name="Grid Table 4 Accent 4" w:uiPriority="49"/>
+					<w:lsdException w:name="Grid Table 5 Dark Accent 4" w:uiPriority="50"/>
+					<w:lsdException w:name="Grid Table 6 Colorful Accent 4" w:uiPriority="51"/>
+					<w:lsdException w:name="Grid Table 7 Colorful Accent 4" w:uiPriority="52"/>
+					<w:lsdException w:name="Grid Table 1 Light Accent 5" w:uiPriority="46"/>
+					<w:lsdException w:name="Grid Table 2 Accent 5" w:uiPriority="47"/>
+					<w:lsdException w:name="Grid Table 3 Accent 5" w:uiPriority="48"/>
+					<w:lsdException w:name="Grid Table 4 Accent 5" w:uiPriority="49"/>
+					<w:lsdException w:name="Grid Table 5 Dark Accent 5" w:uiPriority="50"/>
+					<w:lsdException w:name="Grid Table 6 Colorful Accent 5" w:uiPriority="51"/>
+					<w:lsdException w:name="Grid Table 7 Colorful Accent 5" w:uiPriority="52"/>
+					<w:lsdException w:name="Grid Table 1 Light Accent 6" w:uiPriority="46"/>
+					<w:lsdException w:name="Grid Table 2 Accent 6" w:uiPriority="47"/>
+					<w:lsdException w:name="Grid Table 3 Accent 6" w:uiPriority="48"/>
+					<w:lsdException w:name="Grid Table 4 Accent 6" w:uiPriority="49"/>
+					<w:lsdException w:name="Grid Table 5 Dark Accent 6" w:uiPriority="50"/>
+					<w:lsdException w:name="Grid Table 6 Colorful Accent 6" w:uiPriority="51"/>
+					<w:lsdException w:name="Grid Table 7 Colorful Accent 6" w:uiPriority="52"/>
+					<w:lsdException w:name="List Table 1 Light" w:uiPriority="46"/>
+					<w:lsdException w:name="List Table 2" w:uiPriority="47"/>
+					<w:lsdException w:name="List Table 3" w:uiPriority="48"/>
+					<w:lsdException w:name="List Table 4" w:uiPriority="49"/>
+					<w:lsdException w:name="List Table 5 Dark" w:uiPriority="50"/>
+					<w:lsdException w:name="List Table 6 Colorful" w:uiPriority="51"/>
+					<w:lsdException w:name="List Table 7 Colorful" w:uiPriority="52"/>
+					<w:lsdException w:name="List Table 1 Light Accent 1" w:uiPriority="46"/>
+					<w:lsdException w:name="List Table 2 Accent 1" w:uiPriority="47"/>
+					<w:lsdException w:name="List Table 3 Accent 1" w:uiPriority="48"/>
+					<w:lsdException w:name="List Table 4 Accent 1" w:uiPriority="49"/>
+					<w:lsdException w:name="List Table 5 Dark Accent 1" w:uiPriority="50"/>
+					<w:lsdException w:name="List Table 6 Colorful Accent 1" w:uiPriority="51"/>
+					<w:lsdException w:name="List Table 7 Colorful Accent 1" w:uiPriority="52"/>
+					<w:lsdException w:name="List Table 1 Light Accent 2" w:uiPriority="46"/>
+					<w:lsdException w:name="List Table 2 Accent 2" w:uiPriority="47"/>
+					<w:lsdException w:name="List Table 3 Accent 2" w:uiPriority="48"/>
+					<w:lsdException w:name="List Table 4 Accent 2" w:uiPriority="49"/>
+					<w:lsdException w:name="List Table 5 Dark Accent 2" w:uiPriority="50"/>
+					<w:lsdException w:name="List Table 6 Colorful Accent 2" w:uiPriority="51"/>
+					<w:lsdException w:name="List Table 7 Colorful Accent 2" w:uiPriority="52"/>
+					<w:lsdException w:name="List Table 1 Light Accent 3" w:uiPriority="46"/>
+					<w:lsdException w:name="List Table 2 Accent 3" w:uiPriority="47"/>
+					<w:lsdException w:name="List Table 3 Accent 3" w:uiPriority="48"/>
+					<w:lsdException w:name="List Table 4 Accent 3" w:uiPriority="49"/>
+					<w:lsdException w:name="List Table 5 Dark Accent 3" w:uiPriority="50"/>
+					<w:lsdException w:name="List Table 6 Colorful Accent 3" w:uiPriority="51"/>
+					<w:lsdException w:name="List Table 7 Colorful Accent 3" w:uiPriority="52"/>
+					<w:lsdException w:name="List Table 1 Light Accent 4" w:uiPriority="46"/>
+					<w:lsdException w:name="List Table 2 Accent 4" w:uiPriority="47"/>
+					<w:lsdException w:name="List Table 3 Accent 4" w:uiPriority="48"/>
+					<w:lsdException w:name="List Table 4 Accent 4" w:uiPriority="49"/>
+					<w:lsdException w:name="List Table 5 Dark Accent 4" w:uiPriority="50"/>
+					<w:lsdException w:name="List Table 6 Colorful Accent 4" w:uiPriority="51"/>
+					<w:lsdException w:name="List Table 7 Colorful Accent 4" w:uiPriority="52"/>
+					<w:lsdException w:name="List Table 1 Light Accent 5" w:uiPriority="46"/>
+					<w:lsdException w:name="List Table 2 Accent 5" w:uiPriority="47"/>
+					<w:lsdException w:name="List Table 3 Accent 5" w:uiPriority="48"/>
+					<w:lsdException w:name="List Table 4 Accent 5" w:uiPriority="49"/>
+					<w:lsdException w:name="List Table 5 Dark Accent 5" w:uiPriority="50"/>
+					<w:lsdException w:name="List Table 6 Colorful Accent 5" w:uiPriority="51"/>
+					<w:lsdException w:name="List Table 7 Colorful Accent 5" w:uiPriority="52"/>
+					<w:lsdException w:name="List Table 1 Light Accent 6" w:uiPriority="46"/>
+					<w:lsdException w:name="List Table 2 Accent 6" w:uiPriority="47"/>
+					<w:lsdException w:name="List Table 3 Accent 6" w:uiPriority="48"/>
+					<w:lsdException w:name="List Table 4 Accent 6" w:uiPriority="49"/>
+					<w:lsdException w:name="List Table 5 Dark Accent 6" w:uiPriority="50"/>
+					<w:lsdException w:name="List Table 6 Colorful Accent 6" w:uiPriority="51"/>
+					<w:lsdException w:name="List Table 7 Colorful Accent 6" w:uiPriority="52"/>
+				</w:latentStyles>
+				<w:style w:type="paragraph" w:default="1" w:styleId="a">
+					<w:name w:val="Normal"/>
+					<w:qFormat/>
+					<w:pPr>
+						<w:widowControl w:val="0"/>
+						<w:jc w:val="both"/>
+					</w:pPr>
+					<w:rPr>
+						<w:rFonts w:asciiTheme="minorHAnsi" w:eastAsiaTheme="minorEastAsia" w:hAnsiTheme="minorHAnsi" w:cstheme="minorBidi"/>
+						<w:kern w:val="2"/>
+						<w:sz w:val="21"/>
+						<w:szCs w:val="24"/>
+					</w:rPr>
+				</w:style>
+				<w:style w:type="paragraph" w:styleId="1">
+					<w:name w:val="heading 1"/>
+					<w:basedOn w:val="a"/>
+					<w:next w:val="a"/>
+					<w:qFormat/>
+					<w:pPr>
+						<w:spacing w:beforeAutospacing="1" w:afterAutospacing="1"/>
+						<w:jc w:val="left"/>
+						<w:outlineLvl w:val="0"/>
+					</w:pPr>
+					<w:rPr>
+						<w:rFonts w:ascii="宋体" w:eastAsia="宋体" w:hAnsi="宋体" w:cs="Times New Roman" w:hint="eastAsia"/>
+						<w:b/>
+						<w:bCs/>
+						<w:kern w:val="44"/>
+						<w:sz w:val="48"/>
+						<w:szCs w:val="48"/>
+					</w:rPr>
+				</w:style>
+				<w:style w:type="paragraph" w:styleId="2">
+					<w:name w:val="heading 2"/>
+					<w:basedOn w:val="a"/>
+					<w:next w:val="a"/>
+					<w:unhideWhenUsed/>
+					<w:qFormat/>
+					<w:pPr>
+						<w:spacing w:beforeAutospacing="1" w:afterAutospacing="1"/>
+						<w:jc w:val="left"/>
+						<w:outlineLvl w:val="1"/>
+					</w:pPr>
+					<w:rPr>
+						<w:rFonts w:ascii="宋体" w:eastAsia="宋体" w:hAnsi="宋体" w:cs="Times New Roman" w:hint="eastAsia"/>
+						<w:b/>
+						<w:bCs/>
+						<w:kern w:val="0"/>
+						<w:sz w:val="36"/>
+						<w:szCs w:val="36"/>
+					</w:rPr>
+				</w:style>
+				<w:style w:type="paragraph" w:styleId="3">
+					<w:name w:val="heading 3"/>
+					<w:basedOn w:val="a"/>
+					<w:next w:val="a"/>
+					<w:unhideWhenUsed/>
+					<w:qFormat/>
+					<w:pPr>
+						<w:spacing w:beforeAutospacing="1" w:afterAutospacing="1"/>
+						<w:jc w:val="left"/>
+						<w:outlineLvl w:val="2"/>
+					</w:pPr>
+					<w:rPr>
+						<w:rFonts w:ascii="宋体" w:eastAsia="宋体" w:hAnsi="宋体" w:cs="Times New Roman" w:hint="eastAsia"/>
+						<w:b/>
+						<w:bCs/>
+						<w:kern w:val="0"/>
+						<w:sz w:val="27"/>
+						<w:szCs w:val="27"/>
+					</w:rPr>
+				</w:style>
+				<w:style w:type="character" w:default="1" w:styleId="a0">
+					<w:name w:val="Default Paragraph Font"/>
+					<w:uiPriority w:val="1"/>
+					<w:semiHidden/>
+					<w:unhideWhenUsed/>
+				</w:style>
+				<w:style w:type="table" w:default="1" w:styleId="a1">
+					<w:name w:val="Normal Table"/>
+					<w:uiPriority w:val="99"/>
+					<w:semiHidden/>
+					<w:unhideWhenUsed/>
+					<w:tblPr>
+						<w:tblInd w:w="0" w:type="dxa"/>
+						<w:tblCellMar>
+							<w:top w:w="0" w:type="dxa"/>
+							<w:left w:w="108" w:type="dxa"/>
+							<w:bottom w:w="0" w:type="dxa"/>
+							<w:right w:w="108" w:type="dxa"/>
+						</w:tblCellMar>
+					</w:tblPr>
+				</w:style>
+				<w:style w:type="numbering" w:default="1" w:styleId="a2">
+					<w:name w:val="No List"/>
+					<w:uiPriority w:val="99"/>
+					<w:semiHidden/>
+					<w:unhideWhenUsed/>
+				</w:style>
+				<w:style w:type="paragraph" w:styleId="a3">
+					<w:name w:val="Normal (Web)"/>
+					<w:basedOn w:val="a"/>
+					<w:qFormat/>
+					<w:rPr>
+						<w:sz w:val="24"/>
+					</w:rPr>
+				</w:style>
+				<w:style w:type="table" w:styleId="a4">
+					<w:name w:val="Table Grid"/>
+					<w:basedOn w:val="a1"/>
+					<w:qFormat/>
+					<w:pPr>
+						<w:widowControl w:val="0"/>
+						<w:jc w:val="both"/>
+					</w:pPr>
+					<w:tblPr>
+						<w:tblBorders>
+							<w:top w:val="single" w:sz="4" w:space="0" w:color="auto"/>
+							<w:left w:val="single" w:sz="4" w:space="0" w:color="auto"/>
+							<w:bottom w:val="single" w:sz="4" w:space="0" w:color="auto"/>
+							<w:right w:val="single" w:sz="4" w:space="0" w:color="auto"/>
+							<w:insideH w:val="single" w:sz="4" w:space="0" w:color="auto"/>
+							<w:insideV w:val="single" w:sz="4" w:space="0" w:color="auto"/>
+						</w:tblBorders>
+					</w:tblPr>
+				</w:style>
+			</w:styles>

+ 245 - 0
src/main/resources/freemarker/docx_template/word/theme/theme1.xml

@@ -0,0 +1,245 @@
+			<a:theme xmlns:a="http://schemas.openxmlformats.org/drawingml/2006/main" name="WPS">
+				<a:themeElements>
+					<a:clrScheme name="WPS">
+						<a:dk1>
+							<a:sysClr val="windowText" lastClr="000000"/>
+						</a:dk1>
+						<a:lt1>
+							<a:sysClr val="window" lastClr="FFFFFF"/>
+						</a:lt1>
+						<a:dk2>
+							<a:srgbClr val="44546A"/>
+						</a:dk2>
+						<a:lt2>
+							<a:srgbClr val="E7E6E6"/>
+						</a:lt2>
+						<a:accent1>
+							<a:srgbClr val="4874CB"/>
+						</a:accent1>
+						<a:accent2>
+							<a:srgbClr val="EE822F"/>
+						</a:accent2>
+						<a:accent3>
+							<a:srgbClr val="F2BA02"/>
+						</a:accent3>
+						<a:accent4>
+							<a:srgbClr val="75BD42"/>
+						</a:accent4>
+						<a:accent5>
+							<a:srgbClr val="30C0B4"/>
+						</a:accent5>
+						<a:accent6>
+							<a:srgbClr val="E54C5E"/>
+						</a:accent6>
+						<a:hlink>
+							<a:srgbClr val="0026E5"/>
+						</a:hlink>
+						<a:folHlink>
+							<a:srgbClr val="7E1FAD"/>
+						</a:folHlink>
+					</a:clrScheme>
+					<a:fontScheme name="WPS">
+						<a:majorFont>
+							<a:latin typeface="Calibri Light"/>
+							<a:ea typeface=""/>
+							<a:cs typeface=""/>
+							<a:font script="Jpan" typeface="游ゴシック Light"/>
+							<a:font script="Hang" typeface="맑은 고딕"/>
+							<a:font script="Hans" typeface="宋体"/>
+							<a:font script="Hant" typeface="新細明體"/>
+							<a:font script="Arab" typeface="Times New Roman"/>
+							<a:font script="Hebr" typeface="Times New Roman"/>
+							<a:font script="Thai" typeface="Angsana New"/>
+							<a:font script="Ethi" typeface="Nyala"/>
+							<a:font script="Beng" typeface="Vrinda"/>
+							<a:font script="Gujr" typeface="Shruti"/>
+							<a:font script="Khmr" typeface="MoolBoran"/>
+							<a:font script="Knda" typeface="Tunga"/>
+							<a:font script="Guru" typeface="Raavi"/>
+							<a:font script="Cans" typeface="Euphemia"/>
+							<a:font script="Cher" typeface="Plantagenet Cherokee"/>
+							<a:font script="Yiii" typeface="Microsoft Yi Baiti"/>
+							<a:font script="Tibt" typeface="Microsoft Himalaya"/>
+							<a:font script="Thaa" typeface="MV Boli"/>
+							<a:font script="Deva" typeface="Mangal"/>
+							<a:font script="Telu" typeface="Gautami"/>
+							<a:font script="Taml" typeface="Latha"/>
+							<a:font script="Syrc" typeface="Estrangelo Edessa"/>
+							<a:font script="Orya" typeface="Kalinga"/>
+							<a:font script="Mlym" typeface="Kartika"/>
+							<a:font script="Laoo" typeface="DokChampa"/>
+							<a:font script="Sinh" typeface="Iskoola Pota"/>
+							<a:font script="Mong" typeface="Mongolian Baiti"/>
+							<a:font script="Viet" typeface="Times New Roman"/>
+							<a:font script="Uigh" typeface="Microsoft Uighur"/>
+							<a:font script="Geor" typeface="Sylfaen"/>
+						</a:majorFont>
+						<a:minorFont>
+							<a:latin typeface="Calibri"/>
+							<a:ea typeface=""/>
+							<a:cs typeface=""/>
+							<a:font script="Jpan" typeface="游明朝"/>
+							<a:font script="Hang" typeface="맑은 고딕"/>
+							<a:font script="Hans" typeface="宋体"/>
+							<a:font script="Hant" typeface="新細明體"/>
+							<a:font script="Arab" typeface="Arial"/>
+							<a:font script="Hebr" typeface="Arial"/>
+							<a:font script="Thai" typeface="Cordia New"/>
+							<a:font script="Ethi" typeface="Nyala"/>
+							<a:font script="Beng" typeface="Vrinda"/>
+							<a:font script="Gujr" typeface="Shruti"/>
+							<a:font script="Khmr" typeface="DaunPenh"/>
+							<a:font script="Knda" typeface="Tunga"/>
+							<a:font script="Guru" typeface="Raavi"/>
+							<a:font script="Cans" typeface="Euphemia"/>
+							<a:font script="Cher" typeface="Plantagenet Cherokee"/>
+							<a:font script="Yiii" typeface="Microsoft Yi Baiti"/>
+							<a:font script="Tibt" typeface="Microsoft Himalaya"/>
+							<a:font script="Thaa" typeface="MV Boli"/>
+							<a:font script="Deva" typeface="Mangal"/>
+							<a:font script="Telu" typeface="Gautami"/>
+							<a:font script="Taml" typeface="Latha"/>
+							<a:font script="Syrc" typeface="Estrangelo Edessa"/>
+							<a:font script="Orya" typeface="Kalinga"/>
+							<a:font script="Mlym" typeface="Kartika"/>
+							<a:font script="Laoo" typeface="DokChampa"/>
+							<a:font script="Sinh" typeface="Iskoola Pota"/>
+							<a:font script="Mong" typeface="Mongolian Baiti"/>
+							<a:font script="Viet" typeface="Arial"/>
+							<a:font script="Uigh" typeface="Microsoft Uighur"/>
+							<a:font script="Geor" typeface="Sylfaen"/>
+						</a:minorFont>
+					</a:fontScheme>
+					<a:fmtScheme name="WPS">
+						<a:fillStyleLst>
+							<a:solidFill>
+								<a:schemeClr val="phClr"/>
+							</a:solidFill>
+							<a:gradFill>
+								<a:gsLst>
+									<a:gs pos="0">
+										<a:schemeClr val="phClr">
+											<a:lumOff val="17500"/>
+										</a:schemeClr>
+									</a:gs>
+									<a:gs pos="100000">
+										<a:schemeClr val="phClr"/>
+									</a:gs>
+								</a:gsLst>
+								<a:lin ang="2700000" scaled="0"/>
+							</a:gradFill>
+							<a:gradFill>
+								<a:gsLst>
+									<a:gs pos="0">
+										<a:schemeClr val="phClr">
+											<a:hueOff val="-2520000"/>
+										</a:schemeClr>
+									</a:gs>
+									<a:gs pos="100000">
+										<a:schemeClr val="phClr"/>
+									</a:gs>
+								</a:gsLst>
+								<a:lin ang="2700000" scaled="0"/>
+							</a:gradFill>
+						</a:fillStyleLst>
+						<a:lnStyleLst>
+							<a:ln w="12700" cap="flat" cmpd="sng" algn="ctr">
+								<a:solidFill>
+									<a:schemeClr val="phClr"/>
+								</a:solidFill>
+								<a:prstDash val="solid"/>
+								<a:miter lim="800000"/>
+							</a:ln>
+							<a:ln w="12700" cap="flat" cmpd="sng" algn="ctr">
+								<a:solidFill>
+									<a:schemeClr val="phClr"/>
+								</a:solidFill>
+								<a:prstDash val="solid"/>
+								<a:miter lim="800000"/>
+							</a:ln>
+							<a:ln w="12700" cap="flat" cmpd="sng" algn="ctr">
+								<a:gradFill>
+									<a:gsLst>
+										<a:gs pos="0">
+											<a:schemeClr val="phClr">
+												<a:hueOff val="-4200000"/>
+											</a:schemeClr>
+										</a:gs>
+										<a:gs pos="100000">
+											<a:schemeClr val="phClr"/>
+										</a:gs>
+									</a:gsLst>
+									<a:lin ang="2700000" scaled="1"/>
+								</a:gradFill>
+								<a:prstDash val="solid"/>
+								<a:miter lim="800000"/>
+							</a:ln>
+						</a:lnStyleLst>
+						<a:effectStyleLst>
+							<a:effectStyle>
+								<a:effectLst>
+									<a:outerShdw blurRad="101600" dist="50800" dir="5400000" algn="ctr" rotWithShape="0">
+										<a:schemeClr val="phClr">
+											<a:alpha val="60000"/>
+										</a:schemeClr>
+									</a:outerShdw>
+								</a:effectLst>
+							</a:effectStyle>
+							<a:effectStyle>
+								<a:effectLst>
+									<a:reflection stA="50000" endA="300" endPos="40000" dist="25400" dir="5400000" sy="-100000" algn="bl" rotWithShape="0"/>
+								</a:effectLst>
+							</a:effectStyle>
+							<a:effectStyle>
+								<a:effectLst>
+									<a:outerShdw blurRad="57150" dist="19050" dir="5400000" algn="ctr" rotWithShape="0">
+										<a:srgbClr val="000000">
+											<a:alpha val="63000"/>
+										</a:srgbClr>
+									</a:outerShdw>
+								</a:effectLst>
+							</a:effectStyle>
+						</a:effectStyleLst>
+						<a:bgFillStyleLst>
+							<a:solidFill>
+								<a:schemeClr val="phClr"/>
+							</a:solidFill>
+							<a:solidFill>
+								<a:schemeClr val="phClr">
+									<a:tint val="95000"/>
+									<a:satMod val="170000"/>
+								</a:schemeClr>
+							</a:solidFill>
+							<a:gradFill rotWithShape="1">
+								<a:gsLst>
+									<a:gs pos="0">
+										<a:schemeClr val="phClr">
+											<a:tint val="93000"/>
+											<a:satMod val="150000"/>
+											<a:shade val="98000"/>
+											<a:lumMod val="102000"/>
+										</a:schemeClr>
+									</a:gs>
+									<a:gs pos="50000">
+										<a:schemeClr val="phClr">
+											<a:tint val="98000"/>
+											<a:satMod val="130000"/>
+											<a:shade val="90000"/>
+											<a:lumMod val="103000"/>
+										</a:schemeClr>
+									</a:gs>
+									<a:gs pos="100000">
+										<a:schemeClr val="phClr">
+											<a:shade val="63000"/>
+											<a:satMod val="120000"/>
+										</a:schemeClr>
+									</a:gs>
+								</a:gsLst>
+								<a:lin ang="5400000" scaled="0"/>
+							</a:gradFill>
+						</a:bgFillStyleLst>
+					</a:fmtScheme>
+				</a:themeElements>
+				<a:objectDefaults/>
+				<a:extraClrSchemeLst/>
+			</a:theme>

+ 1 - 0
src/main/resources/freemarker/docx_template/word/webSettings.xml

@@ -0,0 +1 @@
+			<w:webSettings xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships" xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main" xmlns:w14="http://schemas.microsoft.com/office/word/2010/wordml" xmlns:w15="http://schemas.microsoft.com/office/word/2012/wordml" xmlns:w16se="http://schemas.microsoft.com/office/word/2015/wordml/symex" mc:Ignorable="w14 w15 w16se"/>

Rozdílová data souboru nebyla zobrazena, protože soubor je příliš velký
+ 4485 - 0
src/main/resources/freemarker/qualityImprovementPlan.ftl


+ 2 - 2
src/main/resources/jeeplus.properties

@@ -443,5 +443,5 @@ oidc.clientId=simple-xg-web
 #?????
 oidc.clientSecret=KCOPjVcNFIEyUdxalBHNWuIpdBDQY5X8Eg0V36FPt3J2VzIapPqJo5HdjJCI3YPHGh9xTqSTJ2Ndtdr0Se63jj
 #????
-oidc.redirectUri=http://127.0.0.1:8080/a/oidc/callback
-oidc.postLogoutRedirectUri=http://127.0.0.1:8080/a/login?oidcChecked=1
+oidc.redirectUri=http://127.0.0.1:8090/a/oidc/callback
+oidc.postLogoutRedirectUri=http://127.0.0.1:8090/a/login?oidcChecked=1

+ 9 - 0
src/main/resources/mappings/modules/workprojectnotify/WorkProjectNotifyDao.xml

@@ -671,6 +671,15 @@
 		WHERE notify_id = #{notifyId} AND notify_user = #{user.id}
 	</update>
 
+	<update id="updateStatusAndRemarksByNotifyIdAndUserId">
+		UPDATE work_project_notify SET
+									   update_by = #{updateBy.id},
+									   update_date = #{updateDate},
+									   status = #{status},
+									   remarks = #{remarks}
+		WHERE notify_id = #{notifyId} AND notify_user = #{user.id} AND type = #{type}
+	</update>
+
 	<update id="updateReadStateByNotifyId">
 		UPDATE work_project_notify SET
 									   update_by = #{updateBy.id},

+ 347 - 0
src/main/resources/mappings/modules/workqualityimprovement/WkQualityImprovementRecordDao.xml

@@ -0,0 +1,347 @@
+<?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.jeeplus.modules.workqualityimprovement.dao.WkQualityImprovementRecordDao">
+
+    <sql id="recordColumns">
+        a.id AS "id",
+        a.task_id AS "taskId",
+        a.task_title AS "taskTitle",
+        a.task_year AS "taskYear",
+        a.user_id AS "userId",
+        a.user_name AS "userName",
+        a.office_id AS "recordOfficeId",
+        a.company_id AS "companyId",
+        a.office_name AS "officeName",
+        a.position AS "position",
+        a.work_years AS "workYears",
+        a.growth_stage AS "growthStage",
+        a.weakness_goal AS "weaknessGoal",
+        a.score_mapping AS "scoreMapping",
+        a.plan_mapping AS "planMapping",
+        a.score_pricing AS "scorePricing",
+        a.plan_pricing AS "planPricing",
+        a.score_change AS "scoreChange",
+        a.plan_change AS "planChange",
+        a.score_process AS "scoreProcess",
+        a.plan_process AS "planProcess",
+        a.score_ccpm AS "scoreCcpm",
+        a.plan_ccpm AS "planCcpm",
+        a.score_software AS "scoreSoftware",
+        a.plan_software AS "planSoftware",
+        a.score_ai AS "scoreAi",
+        a.plan_ai AS "planAi",
+        a.engineer_status AS "engineerStatus",
+        a.engineer_plan AS "engineerPlan",
+        a.engineer_deadline AS "engineerDeadline",
+        a.training_types AS "trainingTypes",
+        a.training_direction AS "trainingDirection",
+        a.training_deadline AS "trainingDeadline",
+        a.regulation_level AS "regulationLevel",
+        a.regulation_deadline AS "regulationDeadline",
+        a.case_count AS "caseCount",
+        a.insight_count AS "insightCount",
+        a.paper_count AS "paperCount",
+        a.output_difficulty AS "outputDifficulty",
+        a.output_deadline AS "outputDeadline",
+        a.score_comm_client AS "scoreCommClient",
+        a.plan_comm_client AS "planCommClient",
+        a.score_comm_writing AS "scoreCommWriting",
+        a.plan_comm_writing AS "planCommWriting",
+        a.score_comm_response AS "scoreCommResponse",
+        a.plan_comm_response AS "planCommResponse",
+        a.score_comm_cross AS "scoreCommCross",
+        a.plan_comm_cross AS "planCommCross",
+        a.score_comm_expand AS "scoreCommExpand",
+        a.plan_comm_expand AS "planCommExpand",
+        a.core_advantage AS "coreAdvantage",
+        a.process_instance_id AS "processInstanceId",
+        a.submit_status AS "submitStatus",
+        a.submit_date AS "submitDate",
+        a.create_by AS "createBy.id",
+        a.create_date AS "createDate",
+        a.update_by AS "updateBy.id",
+        a.update_date AS "updateDate",
+        a.remarks AS "remarks",
+        a.del_flag AS "delFlag"
+    </sql>
+
+    <sql id="recordJoins">
+        LEFT JOIN sys_user createBy ON createBy.id = a.create_by
+        LEFT JOIN sys_user u ON u.id = a.user_id
+        LEFT JOIN sys_office o ON o.id = u.office_id
+    </sql>
+
+    <select id="get" resultType="WkQualityImprovementRecord">
+        SELECT
+            <include refid="recordColumns"/>
+        FROM wk_quality_improvement_record a
+        <include refid="recordJoins"/>
+        WHERE a.id = #{id} AND a.del_flag = 0
+    </select>
+
+    <select id="getById" resultType="WkQualityImprovementRecord">
+        SELECT
+            <include refid="recordColumns"/>
+        FROM wk_quality_improvement_record a
+        <include refid="recordJoins"/>
+        WHERE a.id = #{id} AND a.del_flag = 0
+    </select>
+
+    <select id="findList" resultType="WkQualityImprovementRecord">
+        SELECT
+            <include refid="recordColumns"/>
+        FROM wk_quality_improvement_record a
+        <include refid="recordJoins"/>
+        <where>
+            a.del_flag = 0
+            <if test="taskId != null and taskId != ''">
+                AND a.task_id = #{taskId}
+            </if>
+            <if test="userId != null and userId != ''">
+                AND a.user_id = #{userId}
+            </if>
+            <if test="submitStatus != null and submitStatus != ''">
+                AND a.submit_status = #{submitStatus}
+            </if>
+            <if test="taskYear != null and taskYear != ''">
+                AND a.task_year LIKE CONCAT('%', #{taskYear}, '%')
+            </if>
+            <if test="taskTitle != null and taskTitle != ''">
+                AND a.task_title LIKE CONCAT('%', #{taskTitle}, '%')
+            </if>
+            <if test="officeId != null and officeId != ''">
+                AND o.id = #{officeId}
+            </if>
+            <if test="sqlMap.delFlag != null and sqlMap.delFlag != ''">
+                ${sqlMap.delFlag}
+            </if>
+            <if test="sqlMap.dsf != null and sqlMap.dsf != ''">
+                AND ((a.user_id = #{currentUser.id} AND a.del_flag = '0' AND a.company_id = #{currentUser.company.id})${sqlMap.dsf} )
+            </if>
+            AND a.company_id = #{currentUser.company.id} ${sqlMap.dsf}
+        </where>
+        <choose>
+            <when test="page !=null and page.orderBy != null and page.orderBy != ''">
+                ORDER BY ${page.orderBy}
+            </when>
+            <otherwise>
+                ORDER BY a.create_date DESC
+            </otherwise>
+        </choose>
+    </select>
+
+    <select id="queryCount" resultType="int">
+        SELECT COUNT(a.id)
+        FROM wk_quality_improvement_record a
+        <include refid="recordJoins"/>
+        <where>
+            a.del_flag = 0
+            <if test="taskId != null and taskId != ''">
+                AND a.task_id = #{taskId}
+            </if>
+            <if test="userId != null and userId != ''">
+                AND a.user_id = #{userId}
+            </if>
+            <if test="submitStatus != null and submitStatus != ''">
+                AND a.submit_status = #{submitStatus}
+            </if>
+            <if test="taskYear != null and taskYear != ''">
+                AND a.task_year LIKE CONCAT('%', #{taskYear}, '%')
+            </if>
+            <if test="taskTitle != null and taskTitle != ''">
+                AND a.task_title LIKE CONCAT('%', #{taskTitle}, '%')
+            </if>
+            <if test="officeId != null and officeId != ''">
+                AND o.id = #{officeId}
+            </if>
+            <if test="sqlMap.delFlag != null and sqlMap.delFlag != ''">
+                ${sqlMap.delFlag}
+            </if>
+            <if test="sqlMap.dsf != null and sqlMap.dsf != ''">
+                AND ((a.user_id = #{currentUser.id} AND a.del_flag = '0' AND a.company_id = #{currentUser.company.id})${sqlMap.dsf} )
+            </if>
+            AND a.company_id = #{currentUser.company.id} ${sqlMap.dsf}
+        </where>
+    </select>
+
+    <select id="findAllList" resultType="WkQualityImprovementRecord">
+        SELECT
+            <include refid="recordColumns"/>
+        FROM wk_quality_improvement_record a
+        <include refid="recordJoins"/>
+        <where>
+            a.del_flag = 0
+            <if test="taskId != null and taskId != ''">
+                AND a.task_id = #{taskId}
+            </if>
+        </where>
+        ORDER BY a.create_date ASC
+    </select>
+
+    <select id="findByTaskId" resultType="WkQualityImprovementRecord">
+        SELECT
+            <include refid="recordColumns"/>
+        FROM wk_quality_improvement_record a
+        <include refid="recordJoins"/>
+        WHERE a.task_id = #{taskId} AND a.del_flag = 0
+        ORDER BY a.create_date ASC
+    </select>
+
+    <select id="findByTaskIdAndUserId" resultType="WkQualityImprovementRecord">
+        SELECT
+            <include refid="recordColumns"/>
+        FROM wk_quality_improvement_record a
+        WHERE a.task_id = #{taskId} AND a.user_id = #{userId} AND a.del_flag = 0
+        LIMIT 1
+    </select>
+
+    <select id="getByProcessInstanceId" resultType="WkQualityImprovementRecord">
+        SELECT
+            <include refid="recordColumns"/>
+        FROM wk_quality_improvement_record a
+        WHERE a.process_instance_id = #{processInstanceId} AND a.del_flag = 0
+        LIMIT 1
+    </select>
+
+    <select id="countSubmittedByTaskId" resultType="java.lang.Integer">
+        SELECT COUNT(1)
+        FROM wk_quality_improvement_record
+        WHERE task_id = #{taskId} AND submit_status = '1' AND del_flag = 0
+    </select>
+
+    <select id="countByTaskId" resultType="java.lang.Integer">
+        SELECT COUNT(1)
+        FROM wk_quality_improvement_record
+        WHERE task_id = #{taskId} AND del_flag = 0
+    </select>
+
+    <insert id="insert">
+        INSERT INTO wk_quality_improvement_record(
+            id, task_id, task_title, task_year, user_id, user_name, office_id, company_id, office_name, position,
+            work_years, growth_stage, weakness_goal,
+            score_mapping, plan_mapping, score_pricing, plan_pricing,
+            score_change, plan_change, score_process, plan_process,
+            score_ccpm, plan_ccpm, score_software, plan_software,
+            score_ai, plan_ai,
+            engineer_status, engineer_plan, engineer_deadline,
+            training_types, training_direction, training_deadline,
+            regulation_level, regulation_deadline,
+            case_count, insight_count, paper_count, output_difficulty, output_deadline,
+            score_comm_client, plan_comm_client, score_comm_writing, plan_comm_writing,
+            score_comm_response, plan_comm_response, score_comm_cross, plan_comm_cross,
+            score_comm_expand, plan_comm_expand,
+            core_advantage,
+            process_instance_id, submit_status, submit_date,
+            create_by, create_date, update_by, update_date, remarks, del_flag
+        ) VALUES (
+            #{id}, #{taskId}, #{taskTitle}, #{taskYear}, #{userId}, #{userName}, #{recordOfficeId}, #{companyId}, #{officeName}, #{position},
+            #{workYears}, #{growthStage}, #{weaknessGoal},
+            #{scoreMapping}, #{planMapping}, #{scorePricing}, #{planPricing},
+            #{scoreChange}, #{planChange}, #{scoreProcess}, #{planProcess},
+            #{scoreCcpm}, #{planCcpm}, #{scoreSoftware}, #{planSoftware},
+            #{scoreAi}, #{planAi},
+            #{engineerStatus}, #{engineerPlan}, #{engineerDeadline},
+            #{trainingTypes}, #{trainingDirection}, #{trainingDeadline},
+            #{regulationLevel}, #{regulationDeadline},
+            #{caseCount}, #{insightCount}, #{paperCount}, #{outputDifficulty}, #{outputDeadline},
+            #{scoreCommClient}, #{planCommClient}, #{scoreCommWriting}, #{planCommWriting},
+            #{scoreCommResponse}, #{planCommResponse}, #{scoreCommCross}, #{planCommCross},
+            #{scoreCommExpand}, #{planCommExpand},
+            #{coreAdvantage},
+            #{processInstanceId}, #{submitStatus}, #{submitDate},
+            <choose>
+                <when test="createBy != null and createBy.id != null">#{createBy.id}</when>
+                <otherwise>''</otherwise>
+            </choose>,
+            #{createDate},
+            <choose>
+                <when test="updateBy != null and updateBy.id != null">#{updateBy.id}</when>
+                <otherwise>''</otherwise>
+            </choose>,
+            #{updateDate}, #{remarks}, #{delFlag}
+        )
+    </insert>
+
+    <update id="update">
+        UPDATE wk_quality_improvement_record SET
+            position = #{position},
+            work_years = #{workYears},
+            growth_stage = #{growthStage},
+            weakness_goal = #{weaknessGoal},
+            score_mapping = #{scoreMapping},
+            plan_mapping = #{planMapping},
+            score_pricing = #{scorePricing},
+            plan_pricing = #{planPricing},
+            score_change = #{scoreChange},
+            plan_change = #{planChange},
+            score_process = #{scoreProcess},
+            plan_process = #{planProcess},
+            score_ccpm = #{scoreCcpm},
+            plan_ccpm = #{planCcpm},
+            score_software = #{scoreSoftware},
+            plan_software = #{planSoftware},
+            score_ai = #{scoreAi},
+            plan_ai = #{planAi},
+            engineer_status = #{engineerStatus},
+            engineer_plan = #{engineerPlan},
+            engineer_deadline = #{engineerDeadline},
+            training_types = #{trainingTypes},
+            training_direction = #{trainingDirection},
+            training_deadline = #{trainingDeadline},
+            regulation_level = #{regulationLevel},
+            regulation_deadline = #{regulationDeadline},
+            case_count = #{caseCount},
+            insight_count = #{insightCount},
+            paper_count = #{paperCount},
+            output_difficulty = #{outputDifficulty},
+            output_deadline = #{outputDeadline},
+            score_comm_client = #{scoreCommClient},
+            plan_comm_client = #{planCommClient},
+            score_comm_writing = #{scoreCommWriting},
+            plan_comm_writing = #{planCommWriting},
+            score_comm_response = #{scoreCommResponse},
+            plan_comm_response = #{planCommResponse},
+            score_comm_cross = #{scoreCommCross},
+            plan_comm_cross = #{planCommCross},
+            score_comm_expand = #{scoreCommExpand},
+            plan_comm_expand = #{planCommExpand},
+            core_advantage = #{coreAdvantage},
+            <if test="updateBy != null and updateBy.id != null">
+                update_by = #{updateBy.id},
+            </if>
+            update_date = #{updateDate},
+            remarks = #{remarks}
+        WHERE id = #{id}
+    </update>
+
+    <update id="delete">
+        UPDATE wk_quality_improvement_record SET
+            del_flag = 1
+        WHERE id = #{id}
+    </update>
+
+    <update id="updateSubmitStatus">
+        UPDATE wk_quality_improvement_record SET
+            submit_status = #{submitStatus},
+            submit_date = #{submitDate},
+            process_instance_id = #{processInstanceId},
+            <if test="updateBy != null and updateBy.id != null">
+                update_by = #{updateBy.id},
+            </if>
+            update_date = #{updateDate}
+        WHERE id = #{id}
+    </update>
+
+    <update id="deleteByTaskId">
+        UPDATE wk_quality_improvement_record SET
+            del_flag = 1
+        WHERE task_id = #{taskId}
+    </update>
+
+    <update id="logicalDeleteById">
+        UPDATE wk_quality_improvement_record SET
+            del_flag = 1
+        WHERE id = #{id}
+    </update>
+
+</mapper>

+ 160 - 0
src/main/resources/mappings/modules/workqualityimprovement/WkQualityImprovementTaskDao.xml

@@ -0,0 +1,160 @@
+<?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.jeeplus.modules.workqualityimprovement.dao.WkQualityImprovementTaskDao">
+
+    <sql id="taskColumns">
+        a.id AS "id",
+        a.title AS "title",
+        a.year AS "year",
+        a.description AS "description",
+        a.status AS "status",
+        a.process_instance_id AS "processInstanceId",
+        a.office_id AS "officeId",
+
+        a.create_by AS "createBy.id",
+        a.create_date AS "createDate",
+        a.update_by AS "updateBy.id",
+        a.update_date AS "updateDate",
+        a.remarks AS "remarks",
+        a.del_flag AS "delFlag"
+    </sql>
+
+    <sql id="taskJoins">
+        LEFT JOIN sys_user createBy ON createBy.id = a.create_by
+        LEFT JOIN sys_user updateBy ON updateBy.id = a.update_by
+        LEFT JOIN sys_office office ON office.id = createBy.office_id
+    </sql>
+
+    <select id="get" resultType="WkQualityImprovementTask">
+        SELECT
+            <include refid="taskColumns"/>,
+            createBy.name AS "createByNameStr"
+        FROM wk_quality_improvement_task a
+        <include refid="taskJoins"/>
+        WHERE a.id = #{id} AND a.del_flag = 0
+    </select>
+
+    <select id="getById" resultType="WkQualityImprovementTask">
+        SELECT
+            <include refid="taskColumns"/>,
+            createBy.name AS "createByNameStr"
+        FROM wk_quality_improvement_task a
+        <include refid="taskJoins"/>
+        WHERE a.id = #{id} AND a.del_flag = 0
+    </select>
+
+    <select id="findList" resultType="WkQualityImprovementTask">
+        SELECT
+            <include refid="taskColumns"/>,
+            office.name as "officeName",
+            createBy.name AS "createByNameStr",
+            (SELECT COUNT(1) FROM wk_quality_improvement_record r WHERE r.task_id = a.id AND r.submit_status = '1' AND r.del_flag = 0) AS "submitCount",
+            (SELECT COUNT(1) FROM wk_quality_improvement_record r WHERE r.task_id = a.id AND r.del_flag = 0) AS "totalCount"
+        FROM wk_quality_improvement_task a
+        <include refid="taskJoins"/>
+        <where>
+            a.del_flag = 0
+            <if test="title != null and title != ''">
+                AND a.title LIKE CONCAT('%', #{title}, '%')
+            </if>
+            <if test="year != null and year != ''">
+                AND a.year = #{year}
+            </if>
+            <if test="status != null and status != ''">
+                AND a.status = #{status}
+            </if>
+            <if test="officeId != null and officeId != ''">
+                AND a.office_id = #{officeId}
+            </if>
+        </where>
+        <choose>
+            <when test="page !=null and page.orderBy != null and page.orderBy != ''">
+                ORDER BY ${page.orderBy}
+            </when>
+            <otherwise>
+                ORDER BY a.create_date DESC
+            </otherwise>
+        </choose>
+    </select>
+
+    <insert id="insert">
+        INSERT INTO wk_quality_improvement_task(
+            id,
+            title,
+            year,
+            description,
+            status,
+            process_instance_id,
+            office_id,
+            office_name,
+            create_by,
+            create_date,
+            update_by,
+            update_date,
+            remarks,
+            del_flag
+        ) VALUES (
+            #{id},
+            #{title},
+            #{year},
+            #{description},
+            #{status},
+            #{processInstanceId},
+            #{officeId},
+            #{officeName},
+            <choose>
+                <when test="createBy != null and createBy.id != null">#{createBy.id}</when>
+                <otherwise>''</otherwise>
+            </choose>,
+            #{createDate},
+            <choose>
+                <when test="updateBy != null and updateBy.id != null">#{updateBy.id}</when>
+                <otherwise>''</otherwise>
+            </choose>,
+            #{updateDate},
+            #{remarks},
+            #{delFlag}
+        )
+    </insert>
+
+    <update id="update">
+        UPDATE wk_quality_improvement_task SET
+            title = #{title},
+            year = #{year},
+            description = #{description},
+            status = #{status},
+            process_instance_id = #{processInstanceId},
+            office_id = #{officeId},
+            office_name = #{officeName},
+            <if test="updateBy != null and updateBy.id != null">
+                update_by = #{updateBy.id},
+            </if>
+            update_date = #{updateDate},
+            remarks = #{remarks}
+        WHERE id = #{id}
+    </update>
+
+    <update id="delete">
+        UPDATE wk_quality_improvement_task SET
+            del_flag = #{DEL_FLAG_DELETE}
+        WHERE id = #{id}
+    </update>
+
+    <update id="updateStatus">
+        UPDATE wk_quality_improvement_task SET
+            status = #{status},
+            <if test="updateBy != null and updateBy.id != null">
+                update_by = #{updateBy.id},
+            </if>
+            update_date = #{updateDate}
+        WHERE id = #{id}
+    </update>
+
+    <update id="updateProcessInstanceId">
+        UPDATE wk_quality_improvement_task SET
+            process_instance_id = #{processInstanceId},
+            update_date = NOW()
+        WHERE id = #{id}
+    </update>
+
+</mapper>

+ 7 - 0
src/main/webapp/webpage/modules/sys/sysHome.jsp

@@ -879,6 +879,7 @@
         }
         /** 打开确认最佳答案页面(带提交/关闭按钮) */
         function openConfirmAnswerDialog(title,url,width,height) {
+            console.log(123)
             if (navigator.userAgent.match(/(iPhone|iPod|Android|ios)/i)) {
                 var width = 'auto';
                 var height = 'auto';
@@ -1232,6 +1233,9 @@
         <c:when test="${workProjectNotify.remarks eq '待审批' && workProjectNotify.status != 1 && workProjectNotify.type != 100 }">
         xml = "<a  href=\"javascript:void(0)\" onclick=\"openDialogre('${fns:getDictLabel(workProjectNotify.type, 'project_notify_type', '')}待审批', '${ctx}/workprojectnotify/workProjectNotify/form?id=${workProjectNotify.id}','95%','95%')\">";
         </c:when>
+        <c:when test="${workProjectNotify.type eq 202}">
+        xml = "<a href=\"javascript:void(0)\" onclick=\"openConfirmAnswerDialog('填写个人提升计划表','${ctx}/workprojectnotify/workProjectNotify/form?id=${workProjectNotify.id}','95%','95%')\">";
+        </c:when>
 
         <c:otherwise>
         xml = "<a  href=\"javascript:void(0)\" onclick=\"openDialogView('${fns:getDictLabel(workProjectNotify.type, 'project_notify_type', '')}', '${ctx}/workprojectnotify/workProjectNotify/form?id=${workProjectNotify.id}','95%','95%')\">";
@@ -1303,6 +1307,9 @@
         <c:when test="${workProjectNotify.type eq 199}">
         xml = "<a href=\"javascript:void(0)\" onclick=\"openConfirmAnswerDialog('确认最佳答案','${ctx}/workprojectnotify/workProjectNotify/form?id=${workProjectNotify.id}','95%','95%')\">";
         </c:when>
+        <c:when test="${workProjectNotify.type eq 202}">
+        xml = "<a href=\"javascript:void(0)\" onclick=\"openConfirmAnswerDialog('填写个人提升计划表','${ctx}/workprojectnotify/workProjectNotify/form?id=${workProjectNotify.id}','95%','95%')\">";
+        </c:when>
         <c:otherwise>
         xml = "<a  href=\"javascript:void(0)\" onclick=\"homeOpenDialogView('查看通知', '${ctx}/workprojectnotify/workProjectNotify/form?id=${workProjectNotify.id}','95%','95%')\">";
         </c:otherwise>

+ 38 - 1
src/main/webapp/webpage/modules/workprojectnotify/workProjectNotifyList.jsp

@@ -56,6 +56,37 @@
 				type : 'date'
 			});
 		});
+        /** 打开素养提升计划填写页面(带提交/关闭按钮) */
+        function openConfirmAnswerDialog(title,url,width,height) {
+            if (navigator.userAgent.match(/(iPhone|iPod|Android|ios)/i)) {//如果是移动端,就使用自适应大小弹窗
+                width = 'auto';
+                height = 'auto';
+            }
+            top.layer.open({
+                type: 2,
+                area: [width, height],
+                title: title,
+                skin: 'three-btns',
+                maxmin: true, //开启最大化最小化按钮
+                content: url,
+                btn: ['提交', '关闭'],
+                btn1: function(index, layero) {
+                    var body = top.layer.getChildFrame('body', index);
+                    var iframeWin = layero.find('iframe')[0]; //得到iframe页的窗口对象,执行iframe页的方法:iframeWin.method();
+                    var inputForm = body.find('#inputForm');
+                    var top_iframe = top.getActiveTab().attr("name");//获取当前active的tab的iframe
+                    inputForm.attr("target", top_iframe);//表单提交成功后,从服务器返回的url在当前tab中展示
+                    if (iframeWin.contentWindow.doSubmit(1)) {
+                        top.layer.close(index);//关闭对话框。
+                        setTimeout(function() {
+                            top.layer.close(index);
+                        }, 100);//延时0.1秒,对应360 7.1版本bug
+                    }
+                },
+                btn2: function(index) {
+                }
+            });
+        }
         function openDialogre(title,url,width,height,target){
             if(navigator.userAgent.match(/(iPhone|iPod|Android|ios)/i)){//如果是移动端,就使用自适应大小弹窗
                 width='auto';
@@ -1319,7 +1350,13 @@
 						return "<a class=\"attention-info\" href=\"javascript:void(0)\" onclick=\"openConfirmSpecialistWorkKnowledge('"+ d.type1 +"待审批', '${ctx}/workprojectnotify/workProjectNotify/form?id="+d.id+"&home=notifyList','95%','95%')\">" +
 								"<span title=\""+ d.title +"\">"+ d.title +"</span>" +
 								"</a>";
-
+					
+					}
+					else if(d.type == "202"){
+						return "<a class=\"attention-info\" href=\"javascript:void(0)\" onclick=\"openConfirmAnswerDialog('填写个人提升计划表', '${ctx}/workprojectnotify/workProjectNotify/form?id="+d.id+"&home=notifyList','95%','95%')\">" +
+								"<span title=\""+ d.title +"\">"+ d.title +"</span>" +
+								"</a>";
+					
 					}
 
                     else if(d.remarks == "待审批" && d.status != "1") {

+ 6 - 0
src/main/webapp/webpage/modules/workprojectnotify/workProjectNotifyReadShowList.jsp

@@ -411,6 +411,12 @@
 									"</a>";
 
 						}
+						else if(d.type == "202"){
+							return "<a class=\"attention-info\"  href=\"javascript:void(0)\" onclick=\"openConfirmAnswerDialog('填写个人提升计划表', '${ctx}/workprojectnotify/workProjectNotify/form?id="+d.id+"','95%','95%')\">" +
+									"<span title=\""+ d.title +"\">"+ d.title +"</span>" +
+									"</a>";
+
+						}
 						else if(d.type == "200"){
 							return "<a class=\"attention-info\"  href=\"javascript:void(0)\" onclick=\"openDialogView('查看通知', '${ctx}/workprojectnotify/workProjectNotify/form?id="+d.id+"','95%','95%')\">" +
 									"<span title=\""+ d.title +"\">"+ d.title +"</span>" +

+ 575 - 0
src/main/webapp/webpage/modules/workqualityimprovement/recordForm.jsp

@@ -0,0 +1,575 @@
+<%@ page contentType="text/html;charset=UTF-8" %>
+<%@ include file="/webpage/include/taglib.jsp"%>
+<html>
+<head>
+    <title>个人素养提升计划表</title>
+    <meta name="decorator" content="default"/>
+    <script type="text/javascript" src="${ctxStatic}/layui/layui.js"></script>
+    <link rel='stylesheet' type="text/css" href="${ctxStatic}/layui/css/layui.css"/>
+    <style type="text/css">
+        .section-title { background: #f2f2f2; font-weight: bold; font-size: 14px; padding: 10px 15px; margin: 15px 0 10px 0; border-left: 3px solid #1E9FFF; }
+        .score-row { margin-bottom: 10px; padding: 12px 15px; border: 1px solid #e6e6e6; border-radius: 4px; background: #fafafa; }
+        .score-row .score-title { font-weight: bold; margin-bottom: 8px; font-size: 14px; color: #333; }
+        .score-row .layui-form-label { width: 100px; padding: 9px 0; text-align: right; }
+        .score-row .layui-input-block { margin-left: 120px; }
+        .rate-disabled .layui-rate { pointer-events: none; }
+        .form-section { margin-bottom: 20px; }
+        .info-bar { background: #e8f4fd; padding: 10px 15px; border-radius: 4px; margin-bottom: 15px; }
+        .info-bar span { margin-right: 30px; font-size: 14px; }
+        .cert-table { width: 100%; border-collapse: collapse; margin: 10px 0; }
+        .cert-table td, .cert-table th { border: 1px solid #e6e6e6; padding: 8px 12px; text-align: center; }
+        .cert-table th { background: #f2f2f2; font-weight: bold; }
+        .radio-group { padding: 9px 0; }
+        .radio-group .layui-form-radio { margin-right: 10px; }
+        .work-years-other input { width: 200px; }
+        .readonly-field { background: #f5f5f5; color: #666; cursor: not-allowed; }
+        .layui-form-select .layui-input { background-color: #fff !important; }
+        .require-item { color: red; margin-right: 2px; font-weight: bold; }
+    </style>
+    <script type="text/javascript">
+        var validateForm;
+        var isReadOnly = ${readOnly};
+
+        function doSubmit(type){
+            if(isReadOnly){
+                top.layer.msg('该记录已提交,不可修改!', {icon: 5});
+                return false;
+            }
+            if(type == 1){
+                // 提交 - 先同步动态字段值,再验证
+                syncWorkYears();
+                var errorMsg = validateAllFields();
+                if(errorMsg){
+                    top.layer.msg(errorMsg, {icon: 5});
+                    return false;
+                }
+                $("#inputForm").attr("action", "${ctx}/workqualityimprovement/wkQualityImprovement/recordSubmit");
+                $("#inputForm").submit();
+                return true;
+            } else {
+                // 暂存
+                syncWorkYears();
+                $("#inputForm").attr("action", "${ctx}/workqualityimprovement/wkQualityImprovement/recordSave");
+                $("#inputForm").submit();
+                return true;
+            }
+        }
+
+        // 验证所有必填项
+        function validateAllFields() {
+            if(!$('#position').val() || !$.trim($('#position').val())) return '请填写岗位';
+            if(!$('#growthStage').val()) return '请选择当前成长阶段';
+            var workYearsVal = $('#workYearsHidden').val();
+            if(!workYearsVal) return '请选择入职年限';
+            if(!$('#weaknessGoal').val() || !$.trim($('#weaknessGoal').val())) return '请填写短板与不足/总体目标';
+
+            var scorePlanFields = [
+                {scoreName: 'scoreMapping', planName: 'planMapping', label: '识图/算量/建模'},
+                {scoreName: 'scorePricing', planName: 'planPricing', label: '清单/定额计价'},
+                {scoreName: 'scoreChange', planName: 'planChange', label: '变更/签证/索赔/争议处理'},
+                {scoreName: 'scoreProcess', planName: 'planProcess', label: '全过程业务能力'},
+                {scoreName: 'scoreCcpm', planName: 'planCcpm', label: 'CCPM系统全流程操作'},
+                {scoreName: 'scoreSoftware', planName: 'planSoftware', label: '广联达/未来/博威等软件'},
+                {scoreName: 'scoreAi', planName: 'planAi', label: 'AI辅助工具应用'},
+                {scoreName: 'scoreCommClient', planName: 'planCommClient', label: '与甲方/施工单位沟通'},
+                {scoreName: 'scoreCommWriting', planName: 'planCommWriting', label: '书面表达/底稿/报告撰写'},
+                {scoreName: 'scoreCommResponse', planName: 'planCommResponse', label: '客户需求响应与关系维护'},
+                {scoreName: 'scoreCommCross', planName: 'planCommCross', label: '跨专业贯通'},
+                {scoreName: 'scoreCommExpand', planName: 'planCommExpand', label: '主动开拓/洽谈业务能力'}
+            ];
+            for(var i = 0; i < scorePlanFields.length; i++){
+                var f = scorePlanFields[i];
+                var scoreVal = parseInt($('input[name="' + f.scoreName + '"]').val());
+                if(!scoreVal || scoreVal <= 0) return '请对「' + f.label + '」进行评分';
+                var planVal = $('textarea[name="' + f.planName + '"]').val();
+                if(!planVal || !$.trim(planVal)) return '请填写「' + f.label + '」的目标措施';
+            }
+
+            // 学习考证与知识更新
+            if(!$('#engineerStatus').val()) return '请选择一级/二级造价工程师状态';
+            if(!$('#engineerPlan').val() || !$.trim($('#engineerPlan').val())) return '请填写一级/二级造价工程师具体计划';
+            if(!$('#engineerDeadline').val() || !$.trim($('#engineerDeadline').val())) return '请填写一级/二级造价工程师完成时限';
+            if(!$('#trainingTypes').val() || !$.trim($('#trainingTypes').val())) return '请选择培训类型';
+            if(!$('#trainingDirection').val() || !$.trim($('#trainingDirection').val())) return '请填写培训方向';
+            if(!$('#trainingDeadline').val() || !$.trim($('#trainingDeadline').val())) return '请填写年度培训完成时限';
+            if(!$('#regulationLevel').val() || !$.trim($('#regulationLevel').val())) return '请选择清单/定额/新规的掌握程度';
+            if(!$('#regulationDeadline').val() || !$.trim($('#regulationDeadline').val())) return '请填写清单/定额/新规完成时限';
+            var caseCount = parseInt($('#caseCount').val());
+            if(isNaN(caseCount) || caseCount < 0) return '请填写案例篇数';
+            var insightCount = parseInt($('#insightCount').val());
+            if(isNaN(insightCount) || insightCount < 0) return '请填写心得篇数';
+            var paperCount = parseInt($('#paperCount').val());
+            if(isNaN(paperCount) || paperCount < 0) return '请填写论文篇数';
+            if(!$('#outputDifficulty').val() || !$.trim($('#outputDifficulty').val())) return '请填写输出困难说明';
+            if(!$('#outputDeadline').val() || !$.trim($('#outputDeadline').val())) return '请填写输出/分享完成时限';
+
+            if(!$('#coreAdvantage').val() || !$.trim($('#coreAdvantage').val())) return '请填写核心优势与提升思路';
+
+            return '';
+        }
+
+        $(document).ready(function() {
+            layui.use(['form', 'layer', 'rate'], function () {
+                var form = layui.form;
+                var rate = layui.rate;
+
+                // 初始化星级评分
+                initRate('scoreMapping', ${wkQualityImprovementRecord.scoreMapping != null ? wkQualityImprovementRecord.scoreMapping : 0});
+                initRate('scorePricing', ${wkQualityImprovementRecord.scorePricing != null ? wkQualityImprovementRecord.scorePricing : 0});
+                initRate('scoreChange', ${wkQualityImprovementRecord.scoreChange != null ? wkQualityImprovementRecord.scoreChange : 0});
+                initRate('scoreProcess', ${wkQualityImprovementRecord.scoreProcess != null ? wkQualityImprovementRecord.scoreProcess : 0});
+                initRate('scoreCcpm', ${wkQualityImprovementRecord.scoreCcpm != null ? wkQualityImprovementRecord.scoreCcpm : 0});
+                initRate('scoreSoftware', ${wkQualityImprovementRecord.scoreSoftware != null ? wkQualityImprovementRecord.scoreSoftware : 0});
+                initRate('scoreAi', ${wkQualityImprovementRecord.scoreAi != null ? wkQualityImprovementRecord.scoreAi : 0});
+                initRate('scoreCommClient', ${wkQualityImprovementRecord.scoreCommClient != null ? wkQualityImprovementRecord.scoreCommClient : 0});
+                initRate('scoreCommWriting', ${wkQualityImprovementRecord.scoreCommWriting != null ? wkQualityImprovementRecord.scoreCommWriting : 0});
+                initRate('scoreCommResponse', ${wkQualityImprovementRecord.scoreCommResponse != null ? wkQualityImprovementRecord.scoreCommResponse : 0});
+                initRate('scoreCommCross', ${wkQualityImprovementRecord.scoreCommCross != null ? wkQualityImprovementRecord.scoreCommCross : 0});
+                initRate('scoreCommExpand', ${wkQualityImprovementRecord.scoreCommExpand != null ? wkQualityImprovementRecord.scoreCommExpand : 0});
+
+                // 初始化入职年限单选按钮(字典value为数字,"其他"对应value=5)
+                var workYearsVal = $('#workYearsHidden').val();
+                if (workYearsVal) {
+                    var presetValues = ['1', '2', '3', '4'];
+                    if (presetValues.indexOf(workYearsVal) >= 0) {
+                        $('input[name="workYearsRadio"][value="' + workYearsVal + '"]').prop('checked', true);
+                    } else {
+                        $('input[name="workYearsRadio"][value="5"]').prop('checked', true);
+                        $('#workYearsOtherDiv').show();
+                        $('#workYearsOtherInput').val(workYearsVal);
+                    }
+                }
+                form.render('radio');
+                form.render('select');
+
+                // layui单选切换监听
+                form.on('radio(workYearsRadio)', function(data) {
+                    toggleWorkYearsOther(data.value);
+                });
+            });
+
+            validateForm = $("#inputForm").validate({
+                submitHandler: function(form){
+                    loading('正在提交,请稍等...');
+                    form.submit();
+                },
+                errorContainer: "#messageBox",
+                errorPlacement: function(error, element) {
+                    $("#messageBox").text("输入有误,请先更正。");
+                    if (element.is(":checkbox")||element.is(":radio")||element.parent().is(".input-append")){
+                        error.appendTo(element.parent().parent());
+                    } else {
+                        error.insertAfter(element);
+                    }
+                }
+            });
+
+            // 只读模式禁用所有输入
+            if(isReadOnly){
+                $('input,textarea,select').attr('disabled', true);
+                $('.layui-rate').css('pointer-events', 'none');
+            }
+
+            // 提交前同步动态字段值
+            $('#inputForm').on('submit', function() {
+                syncWorkYears();
+            });
+        });
+
+        function initRate(elemId, value){
+            layui.rate.render({
+                elem: '#' + elemId,
+                value: value,
+                text: true,
+                choose: function(value){
+                    $('input[name="' + elemId + '"]').val(value);
+                }
+            });
+        }
+
+        // 入职年限单选切换(字典value=5为"其他")
+        function toggleWorkYearsOther(val) {
+            if (val === '5') {
+                $('#workYearsOtherDiv').show();
+                $('#workYearsOtherInput').focus();
+            } else {
+                $('#workYearsOtherDiv').hide();
+                $('#workYearsOtherInput').val('');
+            }
+        }
+
+        // 提交前将入职年限值同步到隐藏字段(字典value=5为"其他")
+        function syncWorkYears() {
+            var selected = $('input[name="workYearsRadio"]:checked').val();
+            if (selected === '5') {
+                $('#workYearsHidden').val($('#workYearsOtherInput').val());
+            } else {
+                $('#workYearsHidden').val(selected || '');
+            }
+        }
+    </script>
+</head>
+<body>
+<div class="single-form">
+    <div class="container">
+        <form:form id="inputForm" modelAttribute="wkQualityImprovementRecord" action="${ctx}/workqualityimprovement/wkQualityImprovement/recordSave" method="post" class="form-horizontal layui-form">
+            <form:hidden path="id"/>
+            <form:hidden path="taskId"/>
+            <form:hidden path="userId"/>
+            <form:hidden path="processInstanceId"/>
+            <sys:message content="${message}"/>
+
+            <div class="info-bar">
+                <span><b>姓名:</b>${wkQualityImprovementRecord.userName}</span>
+                <span><b>部门:</b>${wkQualityImprovementRecord.officeName}</span>
+                <c:if test="${wkQualityImprovementRecord.submitStatus == '1'}">
+                    <span style="color:#5FB878;"><b>状态:已提交</b></span>
+                </c:if>
+            </div>
+
+            <!-- 基本信息 -->
+            <div class="form-section">
+                <div class="layui-row" style="margin-bottom:15px;">
+                    <div class="layui-item layui-col-sm6">
+                        <label class="layui-form-label"><span class="require-item">*</span>岗位:</label>
+                        <div class="layui-input-block">
+                            <form:input path="position" htmlEscape="false" placeholder="请输入岗位" maxlength="50" class="form-control layui-input"/>
+                        </div>
+                    </div>
+                    <div class="layui-item layui-col-sm6">
+                        <label class="layui-form-label double-line"><span class="require-item">*</span>当前成长阶段:</label>
+                        <div class="layui-input-block">
+                            <form:select path="growthStage" class="form-control judgment layui-input">
+                                <form:option value="" label="请选择"/>
+                                <c:forEach items="${fns:getDictList('growth_stage')}" var="dict">
+                                    <form:option value="${dict.value}" label="${dict.label}"/>
+                                </c:forEach>
+                            </form:select>
+                        </div>
+                    </div>
+                </div>
+                <div class="layui-row" style="margin-bottom:15px;">
+                    <div class="layui-item layui-col-sm12">
+                        <label class="layui-form-label double-line"><span class="require-item">*</span>入职年限:</label>
+                        <div class="layui-input-block">
+                            <div class="radio-group">
+                                <c:forEach items="${fns:getDictList('work_years')}" var="dict">
+                                    <input type="radio" name="workYearsRadio" value="${dict.value}" title="${dict.label}" lay-skin="primary" lay-filter="workYearsRadio"/>
+                                </c:forEach>
+                            </div>
+                            <div id="workYearsOtherDiv" style="display:none; padding:5px 0;">
+                                <input type="text" id="workYearsOtherInput" class="layui-input" placeholder="请输入具体年限" style="width:200px;"/>
+                            </div>
+                            <input type="hidden" id="workYearsHidden" name="workYears" value="${wkQualityImprovementRecord.workYears}"/>
+                        </div>
+                    </div>
+                </div>
+                <div class="layui-row" style="margin-bottom:15px;">
+                    <div class="layui-item layui-col-sm12 with-textarea">
+                        <label class="layui-form-label double-line"><span class="require-item">*</span>短板与不足/总体目标:</label>
+                        <div class="layui-input-block">
+                            <form:textarea path="weaknessGoal" htmlEscape="false" rows="4" placeholder="请描述您的短板与不足,以及总体提升目标" maxlength="500" class="form-control"/>
+                        </div>
+                    </div>
+                </div>
+            </div>
+
+            <!-- (一)专业实操能力提升 -->
+            <div class="section-title">(一)专业实操能力提升</div>
+            <div class="form-section">
+                <div class="score-row">
+                    <div class="score-title">1. 识图/算量/建模</div>
+                    <div class="layui-row">
+                        <div class="layui-item layui-col-sm4">
+                            <label class="layui-form-label double-line"><span class="require-item">*</span>当前水平评分:</label>
+                            <div class="layui-input-block" id="scoreMapping"></div>
+                            <input type="hidden" name="scoreMapping" value="${wkQualityImprovementRecord.scoreMapping}"/>
+                        </div>
+                        <div class="layui-item layui-col-sm8 with-textarea">
+                            <label class="layui-form-label"><span class="require-item">*</span>目标措施:</label>
+                            <div class="layui-input-block">
+                                <form:textarea path="planMapping" htmlEscape="false" rows="3" placeholder="一年内希望达到的水平及具体行动措施" maxlength="500" class="form-control"/>
+                            </div>
+                        </div>
+                    </div>
+                </div>
+                <div class="score-row">
+                    <div class="score-title">2. 清单/定额计价</div>
+                    <div class="layui-row">
+                        <div class="layui-item layui-col-sm4">
+                            <label class="layui-form-label double-line"><span class="require-item">*</span>当前水平评分:</label>
+                            <div class="layui-input-block" id="scorePricing"></div>
+                            <input type="hidden" name="scorePricing" value="${wkQualityImprovementRecord.scorePricing}"/>
+                        </div>
+                        <div class="layui-item layui-col-sm8 with-textarea">
+                            <label class="layui-form-label"><span class="require-item">*</span>目标措施:</label>
+                            <div class="layui-input-block">
+                                <form:textarea path="planPricing" htmlEscape="false" rows="3" placeholder="一年内希望达到的水平及具体行动措施" maxlength="500" class="form-control"/>
+                            </div>
+                        </div>
+                    </div>
+                </div>
+                <div class="score-row">
+                    <div class="score-title">3. 变更/签证/索赔/争议处理</div>
+                    <div class="layui-row">
+                        <div class="layui-item layui-col-sm4">
+                            <label class="layui-form-label double-line"><span class="require-item">*</span>当前水平评分:</label>
+                            <div class="layui-input-block" id="scoreChange"></div>
+                            <input type="hidden" name="scoreChange" value="${wkQualityImprovementRecord.scoreChange}"/>
+                        </div>
+                        <div class="layui-item layui-col-sm8 with-textarea">
+                            <label class="layui-form-label"><span class="require-item">*</span>目标措施:</label>
+                            <div class="layui-input-block">
+                                <form:textarea path="planChange" htmlEscape="false" rows="3" placeholder="一年内希望达到的水平及具体行动措施" maxlength="500" class="form-control"/>
+                            </div>
+                        </div>
+                    </div>
+                </div>
+                <div class="score-row">
+                    <div class="score-title">4. 全过程业务能力</div>
+                    <div class="layui-row">
+                        <div class="layui-item layui-col-sm4">
+                            <label class="layui-form-label double-line"><span class="require-item">*</span>当前水平评分:</label>
+                            <div class="layui-input-block" id="scoreProcess"></div>
+                            <input type="hidden" name="scoreProcess" value="${wkQualityImprovementRecord.scoreProcess}"/>
+                        </div>
+                        <div class="layui-item layui-col-sm8 with-textarea">
+                            <label class="layui-form-label"><span class="require-item">*</span>目标措施:</label>
+                            <div class="layui-input-block">
+                                <form:textarea path="planProcess" htmlEscape="false" rows="3" placeholder="一年内希望达到的水平及具体行动措施" maxlength="500" class="form-control"/>
+                            </div>
+                        </div>
+                    </div>
+                </div>
+            </div>
+
+            <!-- (二)数字化与办公能力提升 -->
+            <div class="section-title">(二)数字化与办公能力提升</div>
+            <div class="form-section">
+                <div class="score-row">
+                    <div class="score-title">1. CCPM系统全流程操作</div>
+                    <div class="layui-row">
+                        <div class="layui-item layui-col-sm4">
+                            <label class="layui-form-label double-line"><span class="require-item">*</span>当前水平评分:</label>
+                            <div class="layui-input-block" id="scoreCcpm"></div>
+                            <input type="hidden" name="scoreCcpm" value="${wkQualityImprovementRecord.scoreCcpm}"/>
+                        </div>
+                        <div class="layui-item layui-col-sm8 with-textarea">
+                            <label class="layui-form-label"><span class="require-item">*</span>目标措施:</label>
+                            <div class="layui-input-block">
+                                <form:textarea path="planCcpm" htmlEscape="false" rows="3" placeholder="一年内希望达到的水平及具体行动措施" maxlength="500" class="form-control"/>
+                            </div>
+                        </div>
+                    </div>
+                </div>
+                <div class="score-row">
+                    <div class="score-title">2. 广联达/未来/博威等软件</div>
+                    <div class="layui-row">
+                        <div class="layui-item layui-col-sm4">
+                            <label class="layui-form-label double-line"><span class="require-item">*</span>当前水平评分:</label>
+                            <div class="layui-input-block" id="scoreSoftware"></div>
+                            <input type="hidden" name="scoreSoftware" value="${wkQualityImprovementRecord.scoreSoftware}"/>
+                        </div>
+                        <div class="layui-item layui-col-sm8 with-textarea">
+                            <label class="layui-form-label"><span class="require-item">*</span>目标措施:</label>
+                            <div class="layui-input-block">
+                                <form:textarea path="planSoftware" htmlEscape="false" rows="3" placeholder="一年内希望达到的水平及具体行动措施" maxlength="500" class="form-control"/>
+                            </div>
+                        </div>
+                    </div>
+                </div>
+                <div class="score-row">
+                    <div class="score-title">3. AI辅助工具应用</div>
+                    <div class="layui-row">
+                        <div class="layui-item layui-col-sm4">
+                            <label class="layui-form-label double-line"><span class="require-item">*</span>当前水平评分:</label>
+                            <div class="layui-input-block" id="scoreAi"></div>
+                            <input type="hidden" name="scoreAi" value="${wkQualityImprovementRecord.scoreAi}"/>
+                        </div>
+                        <div class="layui-item layui-col-sm8 with-textarea">
+                            <label class="layui-form-label"><span class="require-item">*</span>目标措施:</label>
+                            <div class="layui-input-block">
+                                <form:textarea path="planAi" htmlEscape="false" rows="3" placeholder="一年内希望达到的水平及具体行动措施" maxlength="500" class="form-control"/>
+                            </div>
+                        </div>
+                    </div>
+                </div>
+            </div>
+
+            <!-- (三)学习考证与知识更新 -->
+            <div class="section-title">(三)学习考证与知识更新</div>
+            <div class="form-section">
+                <table class="cert-table">
+                    <tr>
+                        <th style="width:20%;">项目</th>
+                        <th style="width:25%;">目标/状态</th>
+                        <th style="width:35%;">具体计划</th>
+                        <th style="width:20%;">完成时限</th>
+                    </tr>
+                    <tr>
+                        <td><span class="require-item">*</span>一级/二级造价工程师</td>
+                        <td>
+                            <form:select path="engineerStatus" class="form-control">
+                                <form:option value="" label="请选择"/>
+                                <c:forEach items="${fns:getDictList('engineer_status')}" var="dict">
+                                    <form:option value="${dict.value}" label="${dict.label}"/>
+                                </c:forEach>
+                            </form:select>
+                        </td>
+                        <td><form:input path="engineerPlan" htmlEscape="false" placeholder="具体计划" maxlength="200" class="form-control layui-input"/></td>
+                        <td><form:input path="engineerDeadline" htmlEscape="false" placeholder="完成时限" maxlength="50" class="form-control layui-input"/></td>
+                    </tr>
+                    <tr>
+                        <td><span class="require-item">*</span>年度培训计划</td>
+                        <td>
+                            <form:select path="trainingTypes" class="form-control">
+                                <form:option value="" label="请选择"/>
+                                <c:forEach items="${fns:getDictList('training_type')}" var="dict">
+                                    <form:option value="${dict.value}" label="${dict.label}"/>
+                                </c:forEach>
+                            </form:select>
+                        </td>
+                        <td><form:input path="trainingDirection" htmlEscape="false" placeholder="可列出想培训的方向" maxlength="200" class="form-control layui-input"/></td>
+                        <td><form:input path="trainingDeadline" htmlEscape="false" placeholder="完成时限" maxlength="50" class="form-control layui-input"/></td>
+                    </tr>
+                    <tr>
+                        <td><span class="require-item">*</span>清单/定额/新规的掌握</td>
+                        <td>
+                            <form:select path="regulationLevel" class="form-control">
+                                <form:option value="" label="请选择"/>
+                                <c:forEach items="${fns:getDictList('regulation_level')}" var="dict">
+                                    <form:option value="${dict.value}" label="${dict.label}"/>
+                                </c:forEach>
+                            </form:select>
+                        </td>
+                        <td></td>
+                        <td><form:input path="regulationDeadline" htmlEscape="false" placeholder="完成时限" maxlength="50" class="form-control layui-input"/></td>
+                    </tr>
+                    <tr>
+                        <td><span class="require-item">*</span>输出/分享</td>
+                        <td>
+                            <div class="layui-row">
+                                <div class="layui-col-sm4">
+                                    <label class="layui-form-label" style="width:auto;">案例(篇):</label>
+                                    <form:input path="caseCount" htmlEscape="false" type="number" min="0" class="form-control layui-input" style="width:60px;display:inline;"/>
+                                </div>
+                                <div class="layui-col-sm4">
+                                    <label class="layui-form-label" style="width:auto;">心得(篇):</label>
+                                    <form:input path="insightCount" htmlEscape="false" type="number" min="0" class="form-control layui-input" style="width:60px;display:inline;"/>
+                                </div>
+                                <div class="layui-col-sm4">
+                                    <label class="layui-form-label" style="width:auto;">论文(篇):</label>
+                                    <form:input path="paperCount" htmlEscape="false" type="number" min="0" class="form-control layui-input" style="width:60px;display:inline;"/>
+                                </div>
+                            </div>
+                        </td>
+                        <td><form:input path="outputDifficulty" htmlEscape="false" placeholder="输出困难说明" maxlength="200" class="form-control layui-input"/></td>
+                        <td><form:input path="outputDeadline" htmlEscape="false" placeholder="完成时限" maxlength="50" class="form-control layui-input"/></td>
+                    </tr>
+                </table>
+            </div>
+
+            <!-- (四)沟通服务与业务开拓能力提升 -->
+            <div class="section-title">(四)沟通服务与业务开拓能力提升</div>
+            <div class="form-section">
+                <div class="score-row">
+                    <div class="score-title">1. 与甲方/施工单位沟通</div>
+                    <div class="layui-row">
+                        <div class="layui-item layui-col-sm4">
+                            <label class="layui-form-label double-line"><span class="require-item">*</span>当前水平评分:</label>
+                            <div class="layui-input-block" id="scoreCommClient"></div>
+                            <input type="hidden" name="scoreCommClient" value="${wkQualityImprovementRecord.scoreCommClient}"/>
+                        </div>
+                        <div class="layui-item layui-col-sm8 with-textarea">
+                            <label class="layui-form-label"><span class="require-item">*</span>目标措施:</label>
+                            <div class="layui-input-block">
+                                <form:textarea path="planCommClient" htmlEscape="false" rows="3" placeholder="一年内希望达到的水平及具体行动措施" maxlength="500" class="form-control"/>
+                            </div>
+                        </div>
+                    </div>
+                </div>
+                <div class="score-row">
+                    <div class="score-title">2. 书面表达/底稿/报告撰写</div>
+                    <div class="layui-row">
+                        <div class="layui-item layui-col-sm4">
+                            <label class="layui-form-label double-line"><span class="require-item">*</span>当前水平评分:</label>
+                            <div class="layui-input-block" id="scoreCommWriting"></div>
+                            <input type="hidden" name="scoreCommWriting" value="${wkQualityImprovementRecord.scoreCommWriting}"/>
+                        </div>
+                        <div class="layui-item layui-col-sm8 with-textarea">
+                            <label class="layui-form-label"><span class="require-item">*</span>目标措施:</label>
+                            <div class="layui-input-block">
+                                <form:textarea path="planCommWriting" htmlEscape="false" rows="3" placeholder="一年内希望达到的水平及具体行动措施" maxlength="500" class="form-control"/>
+                            </div>
+                        </div>
+                    </div>
+                </div>
+                <div class="score-row">
+                    <div class="score-title">3. 客户需求响应与关系维护</div>
+                    <div class="layui-row">
+                        <div class="layui-item layui-col-sm4">
+                            <label class="layui-form-label double-line"><span class="require-item">*</span>当前水平评分:</label>
+                            <div class="layui-input-block" id="scoreCommResponse"></div>
+                            <input type="hidden" name="scoreCommResponse" value="${wkQualityImprovementRecord.scoreCommResponse}"/>
+                        </div>
+                        <div class="layui-item layui-col-sm8 with-textarea">
+                            <label class="layui-form-label"><span class="require-item">*</span>目标措施:</label>
+                            <div class="layui-input-block">
+                                <form:textarea path="planCommResponse" htmlEscape="false" rows="3" placeholder="一年内希望达到的水平及具体行动措施" maxlength="500" class="form-control"/>
+                            </div>
+                        </div>
+                    </div>
+                </div>
+                <div class="score-row">
+                    <div class="score-title">4. 跨专业(财务/评估/税务)贯通</div>
+                    <div class="layui-row">
+                        <div class="layui-item layui-col-sm4">
+                            <label class="layui-form-label double-line"><span class="require-item">*</span>当前水平评分:</label>
+                            <div class="layui-input-block" id="scoreCommCross"></div>
+                            <input type="hidden" name="scoreCommCross" value="${wkQualityImprovementRecord.scoreCommCross}"/>
+                        </div>
+                        <div class="layui-item layui-col-sm8 with-textarea">
+                            <label class="layui-form-label"><span class="require-item">*</span>目标措施:</label>
+                            <div class="layui-input-block">
+                                <form:textarea path="planCommCross" htmlEscape="false" rows="3" placeholder="一年内希望达到的水平及具体行动措施" maxlength="500" class="form-control"/>
+                            </div>
+                        </div>
+                    </div>
+                </div>
+                <div class="score-row">
+                    <div class="score-title">5. 主动开拓/洽谈业务能力</div>
+                    <div class="layui-row">
+                        <div class="layui-item layui-col-sm4">
+                            <label class="layui-form-label double-line"><span class="require-item">*</span>当前水平评分:</label>
+                            <div class="layui-input-block" id="scoreCommExpand"></div>
+                            <input type="hidden" name="scoreCommExpand" value="${wkQualityImprovementRecord.scoreCommExpand}"/>
+                        </div>
+                        <div class="layui-item layui-col-sm8 with-textarea">
+                            <label class="layui-form-label"><span class="require-item">*</span>目标措施:</label>
+                            <div class="layui-input-block">
+                                <form:textarea path="planCommExpand" htmlEscape="false" rows="3" placeholder="一年内希望达到的水平及具体行动措施" maxlength="500" class="form-control"/>
+                            </div>
+                        </div>
+                    </div>
+                </div>
+            </div>
+
+            <!-- 核心优势 -->
+            <div class="section-title">"我靠什么赢得客户信任"——核心优势与提升思路</div>
+            <div class="form-section">
+                <div class="layui-row">
+                    <div class="layui-item layui-col-sm12 with-textarea">
+                        <label class="layui-form-label double-line"><span class="require-item">*</span>核心优势与提升思路:</label>
+                        <div class="layui-input-block">
+                            <form:textarea path="coreAdvantage" htmlEscape="false" rows="4" placeholder="请描述您的核心优势以及未来的提升思路" maxlength="1000" class="form-control"/>
+                        </div>
+                    </div>
+                </div>
+            </div>
+
+            <div class="form-group layui-row page-end"></div>
+        </form:form>
+    </div>
+</div>
+</body>
+</html>

+ 315 - 0
src/main/webapp/webpage/modules/workqualityimprovement/recordList.jsp

@@ -0,0 +1,315 @@
+<%@ page contentType="text/html;charset=UTF-8" %>
+<%@ include file="/webpage/include/taglib.jsp"%>
+<html>
+<head>
+	<title>素养提升我的待办</title>
+	<meta name="decorator" content="default"/>
+	<script type="text/javascript">
+		$(document).ready(function() {
+			$('#moresee').click(function(){
+				if($('#moresees').is(':visible')){
+					$('#moresees').slideUp(0,resizeListWindow2);
+					$('#moresee i').removeClass("glyphicon glyphicon-menu-up").addClass("glyphicon glyphicon-menu-down");
+				}else{
+					$('#moresees').slideDown(0,resizeListWindow2);
+					$('#moresee i').removeClass("glyphicon glyphicon-menu-down").addClass("glyphicon glyphicon-menu-up");
+				}
+			});
+		});
+
+		function search() {
+			$("#pageNo").val(1);
+			$("#searchForm").submit();
+		}
+
+		function resetSearch() {
+			$("#taskYear").val("");
+			$("#taskTitle").val("");
+			$("#submitStatus").val("");
+			$("#searchForm").submit();
+		}
+
+		function openRecordForm(id) {
+			var url = '${ctx}/workqualityimprovement/wkQualityImprovement/recordForm?id=' + id;
+			top.layer.open({
+				type: 2,
+				area: ['95%', '95%'],
+				title: '填写个人素养提升计划表',
+				maxmin: true,
+				content: url,
+				skin: "three-btns",
+				btn: ['提交', '关闭'],
+				btn1: function(index, layero){
+					var body = top.layer.getChildFrame('body', index);
+					var iframeWin = layero.find('iframe')[0];
+					var inputForm = body.find('#inputForm');
+					var top_iframe = top.getActiveTab().attr("name");
+					inputForm.attr("target", top_iframe);
+					if(iframeWin.contentWindow.doSubmit(1)){
+						setTimeout(function(){top.layer.close(index); search();}, 100);
+					}
+				},
+				btn2: function(index){
+					top.layer.close(index);
+				}
+			});
+		}
+
+		function viewRecord(id) {
+			var url = '${ctx}/workqualityimprovement/wkQualityImprovement/recordForm?id=' + id + '&view=1';
+			top.layer.open({
+				type: 2,
+				area: ['95%', '95%'],
+				title: '查看个人素养提升计划表',
+				maxmin: true,
+				content: url,
+				btn: ['关闭'],
+				btn1: function(index){
+					top.layer.close(index);
+				}
+			});
+		}
+
+		function downloadRecord(id) {
+			window.location = '${ctx}/workqualityimprovement/wkQualityImprovement/downloadRecordDocx?id=' + id;
+		}
+
+		function batchDownload() {
+			var checked = layui.table.checkStatus('contentTable');
+			var data = checked.data;
+			if (!data || data.length == 0) {
+				top.layer.msg('请至少选择一条记录!', {icon: 5});
+				return;
+			}
+			// 未填写(未提交)的记录不可下载,自动排除
+			var ids = '';
+			var skipCount = 0;
+			for (var i = 0; i < data.length; i++) {
+				if (data[i].submitStatus == '1') {
+					ids += data[i].id + ',';
+				} else {
+					skipCount++;
+				}
+			}
+			if (!ids) {
+				top.layer.msg('所选记录均未填写,暂不可下载!', {icon: 5});
+				return;
+			}
+			if (skipCount > 0) {
+				top.layer.msg('已跳过 ' + skipCount + ' 条未填写的记录!', {icon: 0});
+			}
+			window.location = '${ctx}/workqualityimprovement/wkQualityImprovement/batchDownloadRecords?ids=' + ids;
+		}
+
+		function openTaskEdit(taskId) {
+			top.layer.open({
+				type: 2,
+				area: ['90%', '90%'],
+				title: '编辑任务',
+				maxmin: true,
+				content: '${ctx}/workqualityimprovement/wkQualityImprovement/taskForm?id=' + taskId,
+				btn: ['保存', '关闭'],
+				btn1: function(index, layero){
+					var body = top.layer.getChildFrame('body', index);
+					var iframeWin = layero.find('iframe')[0];
+					var inputForm = body.find('#inputForm');
+					var top_iframe = top.getActiveTab().attr("name");
+					inputForm.attr("target", top_iframe);
+					if(iframeWin.contentWindow.doSubmit(1)){
+						setTimeout(function(){top.layer.close(index); search();}, 100);
+					}
+				},
+				btn2: function(index) {
+					top.layer.close(index);
+				}
+			});
+		}
+
+		function openTaskCreate() {
+			top.layer.open({
+				type: 2,
+				area: ['90%', '90%'],
+				title: '新建任务',
+				maxmin: true,
+				content: '${ctx}/workqualityimprovement/wkQualityImprovement/taskForm',
+				btn: ['保存并发送', '关闭'],
+				btn1: function(index, layero){
+					var body = top.layer.getChildFrame('body', index);
+					var iframeWin = layero.find('iframe')[0];
+					var inputForm = body.find('#inputForm');
+					var top_iframe = top.getActiveTab().attr("name");
+					inputForm.attr("target", top_iframe);
+					if(iframeWin.contentWindow.doSubmit(1)){
+						setTimeout(function(){top.layer.close(index); search();}, 100);
+					}
+				},
+				btn2: function(index) {
+					top.layer.close(index);
+				}
+			});
+		}
+	</script>
+	<style>
+		body{
+			background-color:transparent;
+			filter:progid:DXImageTransform.Microsoft.gradient(startColorstr=#26FFFFFF, endColorstr=#26FFFFFF);
+			color:#ffffff;
+			background-color:rgba(255,255,255,0);
+			height:100%;
+		}
+		/* 标题可点击样式 */
+		.title-link{
+			color:#5FB878;
+			cursor:pointer;
+			text-decoration:none;
+		}
+		.title-link:hover{
+			text-decoration:underline;
+		}
+	</style>
+</head>
+<body>
+<div class="wrapper wrapper-content">
+	<sys:message content="${message}"/>
+	<div class="layui-row ">
+		<div class="full-width fl">
+			<div class=" layui-row contentShadow shadowLR" id="queryDiv">
+				<form:form id="searchForm" modelAttribute="wkQualityImprovementRecord" action="${ctx}/workqualityimprovement/wkQualityImprovement/recordList" method="post" class="form-inline">
+					<input id="pageNo" name="pageNo" type="hidden" value="${page.pageNo}"/>
+					<input id="pageSize" name="pageSize" type="hidden" value="${page.pageSize}"/>
+					<input type="hidden" name="toflag" value="1"/>
+
+					<div class="commonQuery lw6">
+						<div class="layui-item query athird" style="width: 25%">
+							<label class="layui-form-label">年份:</label>
+							<div class="layui-input-block with-icon">
+								<form:input path="taskYear" htmlEscape="false" maxlength="10" class="form-control layui-input" placeholder="如:2026年度"/>
+							</div>
+						</div>
+						<div class="layui-item query athird" style="width: 25%">
+							<label class="layui-form-label">标题:</label>
+							<div class="layui-input-block with-icon">
+								<form:input path="taskTitle" htmlEscape="false" maxlength="50" class="form-control layui-input"/>
+							</div>
+						</div>
+						<div class="layui-item query athird" style="width: 25%">
+							<label class="layui-form-label">状态:</label>
+							<div class="layui-input-block with-icon">
+								<form:select path="submitStatus" class="form-control simple-select">
+									<form:option value="" label="全部"/>
+									<form:option value="0" label="未填写"/>
+									<form:option value="1" label="已提交"/>
+								</form:select>
+							</div>
+						</div>
+						<div class="layui-item athird" style="width: 25%">
+							<div class="input-group">
+								<a href="#" id="moresee"><i class="glyphicon glyphicon-menu-down"></i></a>
+								<div class="layui-btn-group search-spacing">
+									<button id="searchQuery" class="layui-btn layui-btn-sm layui-bg-blue" onclick="search()">查询</button>
+									<button id="searchReset" class="layui-btn layui-btn-sm " onclick="resetSearch()">重置</button>
+								</div>
+							</div>
+						</div>
+						<div style="clear:both;"></div>
+					</div>
+				</form:form>
+			</div>
+		</div>
+		<div class="full-width fl">
+			<div class=" contentShadow shadowLBR layui-form contentDetails">
+				<div class="nav-btns">
+					<div class="layui-btn-group" style="float: left">
+						<shiro:hasPermission name="workqualityimprovement:task:add">
+							<button class="layui-btn layui-btn-sm layui-bg-blue" onclick="openTaskCreate()">&nbsp;新建任务</button>
+						</shiro:hasPermission>
+						<button class="layui-btn layui-btn-sm layui-bg-green" onclick="batchDownload()">批量下载</button>
+						<button class="layui-btn layui-btn-sm layui-bg-green" data-toggle="tooltip" data-placement="left" onclick="search()" title="刷新"> 刷新</button>
+					</div>
+					<div style="clear: both;"></div>
+				</div>
+				<table class="oa-table layui-table" id="contentTable"></table>
+				<table:page page="${page}"></table:page>
+				<div style="clear: both;"></div>
+			</div>
+		</div>
+	</div>
+</div>
+<script src="${ctxStatic}/layer-v2.3/layui/layui.all.js" charset="utf-8"></script>
+<script>
+	// 当前登录用户ID:填写仅限本人,其他人不可代填
+	var currentUserId = '${fns:getUser().id}';
+	layui.use('table', function(){
+		layui.table.render({
+			limit:${page.pageSize}
+			,elem: '#contentTable'
+			,page: false
+			,cols: [[
+				{checkbox: true, fixed: true}
+				,{field:'index', align:'center', title: '序号', width:50}
+				,{field:'taskTitle', align:'center', title: '标题', minWidth:250, templet: function(d){
+					// 标题可点击,点击查看(同下方“查看”按钮)
+					if(d.submitStatus == '1'){
+						return '<a href="javascript:void(0);" onclick="viewRecord(\''+d.id+'\')" class="title-link" title="点击查看">'+(d.taskTitle || '')+'</a>';
+					}
+					return d.taskTitle || '';
+				}}
+				,{field:'taskYear', align:'center', title: '年份', width:100}
+				,{field:'userName', align:'center', title: '姓名', width:100}
+				,{field:'officeName', align:'center', title: '部门', minWidth:120}
+				,{field:'submitStatus', align:'center', title: '状态', width:100, templet: function(d){
+					if(d.submitStatus == '0') return '<span style="color:#FF9800;">未填写</span>';
+					if(d.submitStatus == '1') return '<span style="color:#5FB878;">已提交</span>';
+					return d.submitStatus;
+				}}
+				,{field:'createDate', align:'center', title: '创建时间', minWidth:160}
+				,{field:'op', align:'center', title: '操作', width:220, templet: function(d){
+					var html = '';
+					if(d.submitStatus == '1'){
+						html += '<a href="javascript:void(0);" onclick="viewRecord(\''+d.id+'\')" class="op-btn op-btn-view">查看</a>';
+					} else if(d.userId == currentUserId){
+						// 仅本人可填写,其他人不展示填写按钮
+						html += '<a href="javascript:void(0);" onclick="openRecordForm(\''+d.id+'\')" class="op-btn op-btn-edit">填写</a>';
+					}
+					// 仅已提交(已填写)的记录可下载,未填写的不展示下载按钮
+					if(d.submitStatus == '1'){
+						html += '<a href="javascript:void(0);" onclick="downloadRecord(\''+d.id+'\')" class="op-btn op-btn-download">下载</a>';
+					}
+					return html;
+				}}
+			]]
+			,data: [
+				<c:choose>
+					<c:when test="${not empty page.list}">
+						<c:forEach items="${page.list}" var="row" varStatus="st">
+							<c:if test="${st.index != 0}">,</c:if>
+							{
+								"index": "${st.index + 1 + (page.pageNo - 1) * page.pageSize}"
+								,"id": "${row.id}"
+								,"taskId": "${row.taskId}"
+								,"userId": "${row.userId}"
+								,"taskYear": "<c:out value='${row.taskYear}'/>"
+								,"taskTitle": "<c:out value='${row.taskTitle}'/>"
+								,"userName": "<c:out value='${row.userName}'/>"
+								,"officeName": "<c:out value='${row.officeName}'/>"
+								,"submitStatus": "${row.submitStatus}"
+								,"createDate": "<fmt:formatDate value='${row.createDate}' pattern='yyyy-MM-dd HH:mm:ss'/>"
+							}
+						</c:forEach>
+					</c:when>
+					<c:otherwise></c:otherwise>
+				</c:choose>
+			]
+		});
+	});
+
+	resizeListTable();
+</script>
+<script>
+	resizeListWindow2();
+	$(window).resize(function(){
+		resizeListWindow2();
+	});
+</script>
+</body>
+</html>

+ 231 - 0
src/main/webapp/webpage/modules/workqualityimprovement/taskForm.jsp

@@ -0,0 +1,231 @@
+<%@ page contentType="text/html;charset=UTF-8" %>
+<%@ include file="/webpage/include/taglib.jsp"%>
+<html>
+<head>
+    <title>任务管理</title>
+    <meta name="decorator" content="default"/>
+    <script type="text/javascript" src="${ctxStatic}/layui/layui.js"></script>
+    <link rel='stylesheet' type="text/css" href="${ctxStatic}/layui/css/layui.css"/>
+    <script src="${ctxStatic}/common/html/js/script.js"></script>
+    <script type="text/javascript">
+        var validateForm;
+        function doSubmit(i){
+            if(validateForm.form()){
+                // 收集选中的人员ID
+                var userIds = getSelectUserIds();
+                if(!userIds || userIds == ''){
+                    top.layer.msg('请至少选择一名填写人员!', {icon: 5});
+                    return false;
+                }
+                $("#userIdsHidden").val(userIds);
+                // 收集选中的部门ID
+                var officeIds = getSelectOfficeIds();
+                $("#officeIdsHidden").val(officeIds);
+
+                $("#inputForm").submit();
+                return true;
+            }else {
+                top.layer.msg("信息未填写完整!", {icon: 5});
+            }
+            return false;
+        }
+
+        function changeOffice(ids,names,parentIds) {
+            $("#officeTableList").html("");
+            officeIdx=0;
+            for(var i=0;i<ids.length;i++){
+                var obj = {'id':ids[i],'name':parentIds[i]};
+                addRow('#officeTableList',officeIdx,officeTpl,obj);
+                officeIdx+=1;
+            }
+        }
+
+        function changeUser(ids,names,parents) {
+            var split = ids.split(',');
+            var split2 = names.split(',');
+            $("#userTableList").html("");
+            userIdx=0;
+            for(var i=0;i<split.length;i++){
+                var id = split[i];
+                if(id==''||id==null){
+                    continue;
+                }
+                var obj = {'id':id,'name':split2[i],'officeName':parents[i]};
+                addRow('#userTableList',userIdx,userTpl,obj);
+                userIdx+=1;
+            }
+        }
+
+        function getSelectOfficeIds() {
+            var selectedIds = "";
+            var pidArr = $("#officeTableList tr .officeId");
+            for(var i=0;i<pidArr.length;i++){
+                selectedIds+=$(pidArr[i]).val();
+                selectedIds+=",";
+            }
+            return selectedIds;
+        }
+
+        function getSelectUserIds() {
+            var selectedIds = "";
+            var pidArr = $("#userTableList tr .userId");
+            for(var i=0;i<pidArr.length;i++){
+                selectedIds+=$(pidArr[i]).val();
+                selectedIds+=",";
+            }
+            return selectedIds;
+        }
+
+        $(document).ready(function() {
+            layui.use(['form', 'layer'], function () {
+                var form = layui.form;
+            });
+            validateForm = $("#inputForm").validate({
+                submitHandler: function(form){
+                    loading('正在提交,请稍等...');
+                    form.submit();
+                },
+                errorContainer: "#messageBox",
+                errorPlacement: function(error, element) {
+                    $("#messageBox").text("输入有误,请先更正。");
+                    if (element.is(":checkbox")||element.is(":radio")||element.parent().is(".input-append")){
+                        error.appendTo(element.parent().parent());
+                    } else {
+                        error.insertAfter(element);
+                    }
+                }
+            });
+
+            // 编辑模式:加载已选人员
+            var taskId = $("#inputForm input[name='id']").val();
+            if (taskId && taskId != '') {
+                $.ajax({
+                    url: '${ctx}/workqualityimprovement/wkQualityImprovement/getTaskUsers?taskId=' + taskId,
+                    type: 'get',
+                    dataType: 'json',
+                    success: function(data) {
+                        if (data.users && data.users.length > 0) {
+                            var ids = [], names = [], parents = [];
+                            for (var i = 0; i < data.users.length; i++) {
+                                ids.push(data.users[i].id);
+                                names.push(data.users[i].name);
+                                parents.push(data.users[i].officeName);
+                            }
+                            changeUser(ids.join(','), names.join(','), parents);
+                        }
+                    }
+                });
+            }
+        });
+    </script>
+</head>
+<body>
+<div class="single-form">
+    <div class="container">
+        <form:form id="inputForm" modelAttribute="wkQualityImprovementTask" action="${ctx}/workqualityimprovement/wkQualityImprovement/taskSave" method="post" class="form-horizontal layui-form">
+            <form:hidden path="id"/>
+            <input type="hidden" id="userIdsHidden" name="userIds" value=""/>
+            <input type="hidden" id="officeIdsHidden" name="officeIds" value=""/>
+            <sys:message content="${message}"/>
+            <div class="form-group layui-row first">
+                <div class="layui-row">
+                    <div class="layui-item layui-col-sm6">
+                        <label class="layui-form-label"><span class="require-item">*</span>标题:</label>
+                        <div class="layui-input-block">
+                            <form:input path="title" htmlEscape="false" placeholder="请输入活动标题" maxlength="100" class="form-control judgment layui-input required"/>
+                        </div>
+                    </div>
+                    <div class="layui-item layui-col-sm6">
+                        <label class="layui-form-label"><span class="require-item">*</span>年份:</label>
+                        <div class="layui-input-block">
+                            <form:input path="year" htmlEscape="false" placeholder="如:2026年度" maxlength="20" class="form-control judgment layui-input required"/>
+                        </div>
+                    </div>
+                </div>
+            </div>
+            <div class="form-group layui-row">
+                <div class="layui-item layui-col-sm12  with-textarea">
+                    <label class="layui-form-label">活动描述:</label>
+                    <div class="layui-input-block">
+                        <form:textarea path="description" htmlEscape="false" rows="4" maxlength="500" class="form-control"/>
+                    </div>
+                </div>
+            </div>
+            <div class="form-group layui-row">
+
+                <div class="layui-item layui-col-sm12">
+                    <div class="form-group-label"><h2>提升范围-成员</h2></div>
+                    <div class="layui-item nav-btns">
+                        <sys:treeselectusers id="users" name="" value="" labelName="memberNameStr" labelValue=""
+                                             retnParent="true" title="用户" url="/sys/office/treeData?type=3" checked="true" cssClass="form-control" allowClear="true" notAllowSelectParent="true"/>
+                    </div>
+                    <table id="userTable" class="table table-bordered table-condensed details">
+                        <thead>
+                        <tr>
+                            <th class="hide"></th>
+                            <th>姓名</th>
+                            <th>部门</th>
+                            <th>操作</th>
+                        </tr>
+                        </thead>
+                        <tbody id="userTableList">
+                        </tbody>
+                    </table>
+                    <script type="text/template" id="userTpl">//<!--
+                        <tr id="userList{{idx}}">
+                            <td class="hide">
+                                <input id="userList{{idx}}_id" name="userList[{{idx}}].id" readonly="true" value="{{row.id}}" type="hidden" class="form-control userId"/>
+                            </td>
+                            <td>
+                            {{row.name}}
+                            </td>
+                            <td>
+                            {{row.officeName}}
+                            </td>
+                            <td class="text-center op-td">
+                                <a href=javascript:void(0); onclick="delRow(this, '#userList{{idx}}')" class="op-btn op-btn-delete"><i class="fa fa-trash"></i> 取消</a>
+                            </td>
+                        </tr>//-->
+                    </script>
+                    <script type="text/javascript">
+                        var userIdx = 0, userTpl = $("#userTpl").html().replace(/(\/\/\<!\-\-)|(\/\/\-\->)/g,"");
+                        var officeIdx = 0, officeTpl = $("#officeTpl").html().replace(/(\/\/\<!\-\-)|(\/\/\-\->)/g,"");
+
+                        function addRow(list, idx, tpl, row){
+                            var idx1 = 0;
+                            if('#userTableList'==list){
+                                idx1 = $("#userTableList tr").length
+                            }else if('#officeTableList'==list){
+                                idx1 = $("#officeTableList tr").length
+                            }
+                            bornTemplete(list, idx, tpl, row, idx1);
+                        }
+                        function bornTemplete(list, idx, tpl, row, idx1){
+                            $(list).append(Mustache.render(tpl, {
+                                idx: idx, delBtn: true, row: row,
+                                order:idx1 + 1, idx1:idx1
+                            }));
+                            $(list+idx).find("select").each(function(){
+                                $(this).val($(this).attr("data-value"));
+                            });
+                            $(list+idx).find("input[type='checkbox'], input[type='radio']").each(function(){
+                                var ss = $(this).attr("data-value").split(',');
+                                for (var i=0; i<ss.length; i++){
+                                    if($(this).val() == ss[i]){
+                                        $(this).attr("checked","checked");
+                                    }
+                                }
+                            });
+                        }
+                        function delRow(obj, prefix,idx){
+                            $(obj).parent().parent().remove();
+                        }
+                    </script>
+                </div>
+            </div>
+            <div class="form-group layui-row page-end"></div>
+        </form:form>
+    </div>
+</div>
+</body>
+</html>

+ 223 - 0
src/main/webapp/webpage/modules/workqualityimprovement/taskList.jsp

@@ -0,0 +1,223 @@
+<%@ page contentType="text/html;charset=UTF-8" %>
+<%@ include file="/webpage/include/taglib.jsp"%>
+<html>
+<head>
+	<title>素养提升任务管理</title>
+	<meta name="decorator" content="default"/>
+	<script type="text/javascript">
+		$(document).ready(function() {
+			$('#moresee').click(function(){
+				if($('#moresees').is(':visible')){
+					$('#moresees').slideUp(0,resizeListWindow2);
+					$('#moresee i').removeClass("glyphicon glyphicon-menu-up").addClass("glyphicon glyphicon-menu-down");
+				}else{
+					$('#moresees').slideDown(0,resizeListWindow2);
+					$('#moresee i').removeClass("glyphicon glyphicon-menu-down").addClass("glyphicon glyphicon-menu-up");
+				}
+			});
+		});
+
+		function search() {
+			$("#pageNo").val(1);
+			$("#searchForm").submit();
+		}
+
+		function resetSearch() {
+			$("#title").val("");
+			$("#year").val("");
+			$("#status").val("");
+			$("#searchForm").submit();
+		}
+
+		function openTaskForm(id) {
+			var url = '${ctx}/workqualityimprovement/wkQualityImprovement/taskForm';
+			if (id) {
+				url += '?id=' + id;
+			}
+			top.layer.open({
+				type: 2,
+				area: ['90%', '90%'],
+				title: id ? '编辑任务' : '新建任务',
+				maxmin: true,
+				content: url,
+				btn: ['保存并发送', '关闭'],
+				btn1: function(index, layero){
+					var body = top.layer.getChildFrame('body', index);
+					var iframeWin = layero.find('iframe')[0];
+					var inputForm = body.find('#inputForm');
+					var top_iframe = top.getActiveTab().attr("name");
+					inputForm.attr("target", top_iframe);
+					if(iframeWin.contentWindow.doSubmit(1)){
+						setTimeout(function(){top.layer.close(index)}, 100);
+					}
+				},
+				btn2: function(index) {
+					top.layer.close(index);
+				}
+			});
+		}
+
+		function deleteTask(id) {
+			top.layer.confirm('确定要删除该任务吗?删除后关联的填写记录也会被删除。', {icon: 3, title:'提示'}, function(index){
+				window.location = '${ctx}/workqualityimprovement/wkQualityImprovement/taskDelete?id=' + id;
+				top.layer.close(index);
+			});
+		}
+
+		function exportList(taskId) {
+			window.location = '${ctx}/workqualityimprovement/wkQualityImprovement/exportList?taskId=' + taskId;
+		}
+
+		function exportPersonal(taskId) {
+			window.location = '${ctx}/workqualityimprovement/wkQualityImprovement/exportPersonal?taskId=' + taskId;
+		}
+
+		function viewRecords(taskId) {
+			top.layer.open({
+				type: 2,
+				area: ['90%', '90%'],
+				title: '填写记录',
+				maxmin: true,
+				content: '${ctx}/workqualityimprovement/wkQualityImprovement/recordList?taskId=' + taskId + '&toflag=1'
+			});
+		}
+	</script>
+	<style>
+		body{
+			background-color:transparent;
+			filter:progid:DXImageTransform.Microsoft.gradient(startColorstr=#26FFFFFF, endColorstr=#26FFFFFF);
+			color:#ffffff;
+			background-color:rgba(255,255,255,0);
+			height:100%;
+		}
+	</style>
+</head>
+<body>
+<div class="wrapper wrapper-content">
+	<sys:message content="${message}"/>
+	<div class="layui-row ">
+		<div class="full-width fl">
+			<div class=" layui-row contentShadow shadowLR" id="queryDiv">
+				<form:form id="searchForm" modelAttribute="wkQualityImprovementTask" action="${ctx}/workqualityimprovement/wkQualityImprovement/taskList" method="post" class="form-inline">
+					<input id="pageNo" name="pageNo" type="hidden" value="${page.pageNo}"/>
+					<input id="pageSize" name="pageSize" type="hidden" value="${page.pageSize}"/>
+					<input type="hidden" name="toflag" value="1"/>
+
+					<div class="commonQuery lw6">
+						<div class="layui-item query athird" >
+							<label class="layui-form-label">标题:</label>
+							<div class="layui-input-block with-icon">
+								<form:input path="title" htmlEscape="false" maxlength="50" class="form-control layui-input"/>
+							</div>
+						</div>
+						<div class="layui-item query athird">
+							<label class="layui-form-label">年份:</label>
+							<div class="layui-input-block with-icon">
+								<form:input path="year" htmlEscape="false" maxlength="10" class="form-control layui-input" placeholder="如:2026年度"/>
+							</div>
+						</div>
+						<%--<div class="layui-item query athird" style="width: 25%">
+							<label class="layui-form-label">状态:</label>
+							<div class="layui-input-block with-icon">
+								<form:select path="status" class="form-control simple-select">
+									<form:option value="" label="全部"/>
+									<form:option value="0" label="草稿"/>
+									<form:option value="1" label="已发送"/>
+								</form:select>
+							</div>
+						</div>--%>
+						<div class="layui-item athird">
+							<div class="input-group">
+								<a href="#" id="moresee"><i class="glyphicon glyphicon-menu-down"></i></a>
+								<div class="layui-btn-group search-spacing">
+									<button id="searchQuery" class="layui-btn layui-btn-sm layui-bg-blue" onclick="search()">查询</button>
+									<button id="searchReset" class="layui-btn layui-btn-sm " onclick="resetSearch()">重置</button>
+								</div>
+							</div>
+						</div>
+						<div style="clear:both;"></div>
+					</div>
+				</form:form>
+			</div>
+		</div>
+		<div class="full-width fl">
+			<div class=" contentShadow shadowLBR layui-form contentDetails">
+				<div class="nav-btns">
+					<div class="layui-btn-group" style="float: left">
+						<button class="layui-btn layui-btn-sm layui-bg-blue" onclick="openTaskForm()">&nbsp;新建</button>
+						<button class="layui-btn layui-btn-sm layui-bg-green" data-toggle="tooltip" data-placement="left" onclick="search()" title="刷新"> 刷新</button>
+					</div>
+					<div style="clear: both;"></div>
+				</div>
+				<table class="oa-table layui-table" id="contentTable"></table>
+				<table:page page="${page}"></table:page>
+				<div style="clear: both;"></div>
+			</div>
+		</div>
+	</div>
+</div>
+<script src="${ctxStatic}/layer-v2.3/layui/layui.all.js" charset="utf-8"></script>
+<script>
+	layui.use('table', function(){
+		layui.table.render({
+			limit:${page.pageSize}
+			,elem: '#contentTable'
+			,page: false
+			,cols: [[
+				{field:'index', align:'center', title: '序号', width:50}
+				,{field:'year', align:'center', title: '年份', minWidth:100}
+				,{field:'title', align:'center', title: '标题', minWidth:250}
+				,{field:'createByNameStr', align:'center', title: '创建人', minWidth:100}
+				,{field:'officeName', align:'center', title: '创建部门', minWidth:120}
+				,{field:'totalCount', align:'center', title: '应填人数', width:100}
+				,{field:'submitCount', align:'center', title: '已提交', width:100}
+				,{field:'status', align:'center', title: '状态', width:80, templet: function(d){
+					if(d.status == '0') return '<span style="color:#999;">草稿</span>';
+					if(d.status == '1') return '<span style="color:#5FB878;">已发送</span>';
+					return d.status;
+				}}
+				,{field:'createDate', align:'center', title: '创建时间', minWidth:160}
+				,{field:'op', align:'center', title: '操作', width:280, templet: function(d){
+					var html = '<a href="javascript:void(0);" onclick="openTaskForm(\''+d.id+'\')" class="op-btn op-btn-edit">编辑</a>';
+					html += '<a href="javascript:void(0);" onclick="viewRecords(\''+d.id+'\')" class="op-btn op-btn-view">查看记录</a>';
+					/*html += '<a href="javascript:void(0);" onclick="exportList(\''+d.id+'\')" class="op-btn op-btn-download">导出汇总</a>';*/
+					html += '<a href="javascript:void(0);" onclick="exportPersonal(\''+d.id+'\')" class="op-btn op-btn-download">导出表格</a>';
+					html += '<a href="javascript:void(0);" onclick="deleteTask(\''+d.id+'\')" class="op-btn op-btn-delete">删除</a>';
+					return html;
+				}}
+			]]
+			,data: [
+				<c:choose>
+					<c:when test="${not empty page.list}">
+						<c:forEach items="${page.list}" var="row" varStatus="st">
+							<c:if test="${st.index != 0}">,</c:if>
+							{
+								"index": "${st.index + 1 + (page.pageNo - 1) * page.pageSize}"
+								,"id": "${row.id}"
+								,"year": "<c:out value='${row.year}'/>"
+								,"title": "<c:out value='${row.title}'/>"
+								,"createByNameStr": "<c:out value='${row.createByNameStr}'/>"
+								,"officeName": "<c:out value='${row.officeName}'/>"
+								,"totalCount": "${row.totalCount != null ? row.totalCount : 0}"
+								,"submitCount": "${row.submitCount != null ? row.submitCount : 0}"
+								,"status": "${row.status}"
+								,"createDate": "<fmt:formatDate value='${row.createDate}' pattern='yyyy-MM-dd HH:mm:ss'/>"
+							}
+						</c:forEach>
+					</c:when>
+					<c:otherwise></c:otherwise>
+				</c:choose>
+			]
+		});
+	});
+
+	resizeListTable();
+</script>
+<script>
+	resizeListWindow2();
+	$(window).resize(function(){
+		resizeListWindow2();
+	});
+</script>
+</body>
+</html>