commit
This commit is contained in:
@@ -401,7 +401,8 @@ public class SysRoleController {
|
||||
public Object user(@Param("roleId") String roleId, @Param("searchName") String searchName, @Param("searchKeyword") String searchKeyword,
|
||||
@Param("pageNumber") int pageNumber, @Param("pageSize") int pageSize, @Param("pageOrderName") String pageOrderName, @Param("pageOrderBy") String pageOrderBy) {
|
||||
try {
|
||||
Sql sql = Sqls.create("SELECT a.*,c.name as unitname FROM sys_user a,sys_user_role b,sys_unit c WHERE a.unitid=c.id and a.id=b.userId and b.roleId=@roleId $s $o");
|
||||
// sys_user_role 会按单位、工会等业务范围保存多条记录,这里只按用户维度展示一次。
|
||||
Sql sql = Sqls.create("SELECT a.*,c.name as unitname FROM sys_user a,sys_unit c WHERE a.unitid=c.id and EXISTS (SELECT 1 FROM sys_user_role b WHERE b.userId=a.id and b.roleId=@roleId) $s $o");
|
||||
sql.params().set("roleId", roleId);
|
||||
if (Strings.isNotBlank(searchName) && Strings.isNotBlank(searchKeyword)) {
|
||||
sql.vars().set("s", " and a." + searchName + " like '%" + searchKeyword + "%'");
|
||||
|
||||
+39
@@ -0,0 +1,39 @@
|
||||
package com.budwk.app.zhgh.democratic.proposal.controller.query;
|
||||
|
||||
import cn.dev33.satoken.annotation.SaCheckPermission;
|
||||
import com.budwk.app.base.result.Result;
|
||||
import com.budwk.app.zhgh.democratic.proposal.param.ProposalSatisfactionStatisticsParam;
|
||||
import com.budwk.app.zhgh.democratic.proposal.service.common.ProposalCommonService;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import org.nutz.ioc.loader.annotation.Inject;
|
||||
import org.nutz.ioc.loader.annotation.IocBean;
|
||||
import org.nutz.mvc.annotation.At;
|
||||
import org.nutz.mvc.annotation.Ok;
|
||||
import org.nutz.mvc.annotation.Param;
|
||||
|
||||
import javax.validation.Valid;
|
||||
|
||||
@IocBean
|
||||
@At("/platform/proposal/query/satisfactionStatistics")
|
||||
@Ok("json:full")
|
||||
@Api(tags = "提案满意度统计")
|
||||
public class ProposalSatisfactionStatisticsController {
|
||||
|
||||
@Inject
|
||||
private ProposalCommonService proposalCommonService;
|
||||
|
||||
@At("")
|
||||
@Ok("beetl:/platform/zhgh/democratic/proposal/query/satisfactionStatistics/index.html")
|
||||
@SaCheckPermission("proposal.query.satisfactionStatistics")
|
||||
public void index() {
|
||||
}
|
||||
|
||||
@At
|
||||
@SaCheckPermission("proposal.query.satisfactionStatistics")
|
||||
@ApiOperation("提案满意度统计")
|
||||
public Result data(@Valid @Param("pageForm") ProposalSatisfactionStatisticsParam pageForm) {
|
||||
return Result.success(proposalCommonService.satisfactionStatistics(pageForm));
|
||||
}
|
||||
|
||||
}
|
||||
+17
@@ -0,0 +1,17 @@
|
||||
package com.budwk.app.zhgh.democratic.proposal.param;
|
||||
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
@ApiModel(description = "提案满意度统计参数")
|
||||
public class ProposalSatisfactionStatisticsParam {
|
||||
|
||||
@ApiModelProperty(name = "教代会ID")
|
||||
private String sessionId;
|
||||
|
||||
@ApiModelProperty(name = "提案类别ID")
|
||||
private String[] typeIds;
|
||||
|
||||
}
|
||||
+9
@@ -3,6 +3,7 @@ package com.budwk.app.zhgh.democratic.proposal.service.common;
|
||||
import com.budwk.app.base.service.BaseService;
|
||||
import com.budwk.app.zhgh.democratic.proposal.models.ProposalInfo;
|
||||
import com.budwk.app.zhgh.democratic.proposal.models.ProposalUndertake;
|
||||
import com.budwk.app.zhgh.democratic.proposal.param.ProposalSatisfactionStatisticsParam;
|
||||
import org.nutz.lang.util.NutMap;
|
||||
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
@@ -113,4 +114,12 @@ public interface ProposalCommonService extends BaseService<ProposalInfo> {
|
||||
*/
|
||||
List<String> mergeProposal(String id);
|
||||
|
||||
/**
|
||||
* 按提案类别统计立案同意提案的反馈完成率和满意率。
|
||||
*
|
||||
* @param param 统计筛选参数,包含届次和提案类别
|
||||
* @return 每个提案类别的统计结果
|
||||
*/
|
||||
List<NutMap> satisfactionStatistics(ProposalSatisfactionStatisticsParam param);
|
||||
|
||||
}
|
||||
|
||||
+79
-3
@@ -29,6 +29,7 @@ import com.budwk.app.web.commons.auth.utils.SecurityUtil;
|
||||
import com.budwk.app.web.commons.base.Globals;
|
||||
import com.budwk.app.zhgh.democratic.proposal.models.*;
|
||||
import com.budwk.app.zhgh.democratic.proposal.param.ProposalQueryComprehensiveParam;
|
||||
import com.budwk.app.zhgh.democratic.proposal.param.ProposalSatisfactionStatisticsParam;
|
||||
import com.budwk.app.zhgh.democratic.teachercongress.prepare.models.Teacher_congress_session;
|
||||
import com.deepoove.poi.XWPFTemplate;
|
||||
import com.deepoove.poi.config.Configure;
|
||||
@@ -513,6 +514,9 @@ public class ProposalCommonServiceImpl extends BaseServiceImpl<ProposalInfo> imp
|
||||
HashMap<String, Object> docData = new HashMap<>();
|
||||
|
||||
Teacher_congress_session session = dao().fetch(Teacher_congress_session.class, sessionId);
|
||||
if (ObjectUtil.isEmpty(session)) {
|
||||
throw new BaseException("请选择教代会后再导出年度报告");
|
||||
}
|
||||
docData.put("sessionName", session.getFullName());
|
||||
docData.put("startDate", DateUtil.format(session.getStartDate(), "yyyy年MM月dd日"));
|
||||
|
||||
@@ -623,7 +627,8 @@ public class ProposalCommonServiceImpl extends BaseServiceImpl<ProposalInfo> imp
|
||||
for (int i = 0; i < transactList.size(); i++) {
|
||||
NutMap v = transactList.get(i);
|
||||
v.setv("index", i + 1);
|
||||
v.setv("ratio", NumberUtil.decimalFormat("#.##%", v.getInt("sum") / sum));
|
||||
// 当前届次没有提案时避免除以 0;有数据时使用小数计算,保证比例准确。
|
||||
v.setv("ratio", sum == 0 ? "0%" : NumberUtil.decimalFormat("#.##%", v.getInt("sum") * 1.0 / sum));
|
||||
}
|
||||
|
||||
docData.put("transacts", transactList);
|
||||
@@ -649,9 +654,9 @@ public class ProposalCommonServiceImpl extends BaseServiceImpl<ProposalInfo> imp
|
||||
type.id
|
||||
ORDER BY
|
||||
type.CODE
|
||||
""");
|
||||
""");
|
||||
newSessionSql.setParam("newSessionId", nextSession.getId());
|
||||
List<NutMap> newSessionProposals = listMap(sql);
|
||||
List<NutMap> newSessionProposals = listMap(newSessionSql);
|
||||
docData.put("newSum", newSessionProposals.stream().mapToInt(v -> v.getInt("count", 0)).sum());
|
||||
|
||||
docData.put("newTypesSummary", newSessionProposals.stream()
|
||||
@@ -683,4 +688,75 @@ public class ProposalCommonServiceImpl extends BaseServiceImpl<ProposalInfo> imp
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<NutMap> satisfactionStatistics(ProposalSatisfactionStatisticsParam param) {
|
||||
Sql sql = Sqls.create("""
|
||||
SELECT
|
||||
type.id AS typeId,
|
||||
type.code AS typeCode,
|
||||
type.name AS typeName,
|
||||
COUNT(DISTINCT info.id) AS filingCount,
|
||||
COUNT(DISTINCT CASE WHEN latestFeedback.processInstanceId IS NOT NULL THEN info.id END) AS feedbackCount,
|
||||
COUNT(DISTINCT CASE WHEN latestFeedback.processInstanceId IS NULL AND info.id IS NOT NULL THEN info.id END) AS unFeedbackCount,
|
||||
COUNT(DISTINCT CASE WHEN latestFeedback.tf_feedback IS NOT NULL AND latestFeedback.tf_feedback != 'DISSATISFIED' THEN info.id END) AS satisfiedCount,
|
||||
COUNT(DISTINCT CASE WHEN latestFeedback.tf_feedback = 'DISSATISFIED' THEN info.id END) AS dissatisfiedCount,
|
||||
ROUND(
|
||||
CASE
|
||||
WHEN COUNT(DISTINCT info.id) = 0 THEN 0
|
||||
ELSE COUNT(DISTINCT CASE WHEN latestFeedback.processInstanceId IS NOT NULL THEN info.id END) * 100.0 / COUNT(DISTINCT info.id)
|
||||
END,
|
||||
2
|
||||
) AS completionRate,
|
||||
ROUND(
|
||||
CASE
|
||||
WHEN COUNT(DISTINCT CASE WHEN latestFeedback.processInstanceId IS NOT NULL THEN info.id END) = 0 THEN 0
|
||||
ELSE COUNT(DISTINCT CASE WHEN latestFeedback.tf_feedback IS NOT NULL AND latestFeedback.tf_feedback != 'DISSATISFIED' THEN info.id END) * 100.0 / COUNT(DISTINCT CASE WHEN latestFeedback.processInstanceId IS NOT NULL THEN info.id END)
|
||||
END,
|
||||
2
|
||||
) AS satisfactionRate
|
||||
FROM
|
||||
proposal_type type
|
||||
LEFT JOIN proposal_info info ON info.typeId = type.id
|
||||
AND info.caseFilingResult = 'CONFIRM_FILING'
|
||||
AND (@sessionId IS NULL OR @sessionId = '' OR info.sessionId = @sessionId)
|
||||
LEFT JOIN wf_process_instance ins ON ins.businessNo = info.id
|
||||
LEFT JOIN (
|
||||
SELECT
|
||||
processInstanceId,
|
||||
JSON_UNQUOTE(JSON_EXTRACT(variable, '$.tf_feedback')) AS tf_feedback
|
||||
FROM (
|
||||
SELECT
|
||||
processInstanceId,
|
||||
variable,
|
||||
ROW_NUMBER() OVER (PARTITION BY processInstanceId ORDER BY finishTime DESC, id DESC) AS rn
|
||||
FROM
|
||||
wf_process_task
|
||||
WHERE
|
||||
taskName = 'feedback'
|
||||
AND taskState = 20
|
||||
) feedbackTask
|
||||
WHERE feedbackTask.rn = 1
|
||||
) latestFeedback ON latestFeedback.processInstanceId = ins.id
|
||||
$condition
|
||||
GROUP BY
|
||||
type.id
|
||||
ORDER BY
|
||||
type.code
|
||||
""");
|
||||
sql.setParam("sessionId", param == null ? null : param.getSessionId());
|
||||
|
||||
Cnd cnd = Cnd.NEW();
|
||||
if (param != null && Lang.isNotEmpty(param.getTypeIds())) {
|
||||
cnd.and("type.id", "in", param.getTypeIds());
|
||||
}
|
||||
sql.setCondition(cnd);
|
||||
List<NutMap> list = listMap(sql);
|
||||
for (NutMap row : list) {
|
||||
// 前端直接展示百分比文本,避免每个页面重复处理空值和数值格式。
|
||||
row.put("completionRateText", ObjectUtil.defaultIfNull(row.get("completionRate"), 0).toString() + "%");
|
||||
row.put("satisfactionRateText", ObjectUtil.defaultIfNull(row.get("satisfactionRate"), 0).toString() + "%");
|
||||
}
|
||||
return list;
|
||||
}
|
||||
}
|
||||
|
||||
+12
@@ -34,6 +34,8 @@ import org.nutz.mvc.annotation.At;
|
||||
import org.nutz.mvc.annotation.Ok;
|
||||
import org.nutz.mvc.annotation.Param;
|
||||
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
/**
|
||||
* @ClassName CondolenceApplyController
|
||||
* @Author JyuHsin
|
||||
@@ -140,6 +142,16 @@ public class CondolenceMineController {
|
||||
//smsService.send("20182040", "这是一条由智慧工会系统发出的测试消息。");
|
||||
return Result.success(nutMap);
|
||||
}
|
||||
|
||||
@At
|
||||
@Ok("void")
|
||||
@ApiOperation("导出报销单")
|
||||
@SaCheckPermission("condolence.mine")
|
||||
@SLog(tag = "职工慰问系统-我的申请", msg = "导出慰问报销单")
|
||||
public void doExport(@Param("id") String id, HttpServletResponse response) {
|
||||
condolenceService.exportReimbursement(id, response);
|
||||
}
|
||||
|
||||
@Inject
|
||||
private SmsService smsService;
|
||||
}
|
||||
|
||||
+28
-90
@@ -5,29 +5,15 @@ import cn.afterturn.easypoi.excel.entity.ExportParams;
|
||||
import cn.afterturn.easypoi.excel.entity.enmus.ExcelType;
|
||||
import cn.afterturn.easypoi.excel.entity.params.ExcelExportEntity;
|
||||
import cn.dev33.satoken.annotation.SaCheckPermission;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.budwk.app.base.constant.RoleConstant;
|
||||
import com.budwk.app.base.page.Pagination;
|
||||
import com.budwk.app.base.param.PageForm;
|
||||
import com.budwk.app.base.result.Result;
|
||||
import com.budwk.app.base.utils.CommonDownloadUtil;
|
||||
import com.budwk.app.base.utils.PageUtil;
|
||||
import com.budwk.app.flow.entity.ProcessInstance;
|
||||
import com.budwk.app.flow.enums.ProcessTaskStateEnum;
|
||||
import com.budwk.app.sys.param.SysMsgSummaryPageForm;
|
||||
import com.budwk.app.web.commons.auth.utils.AuthUtil;
|
||||
import com.budwk.app.web.commons.auth.utils.SecurityUtil;
|
||||
import com.budwk.app.zhgh.staffbenefit.condolence.model.Condolence;
|
||||
import com.budwk.app.zhgh.staffbenefit.condolence.service.CondolenceService;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.poi.ss.usermodel.Workbook;
|
||||
import org.nutz.dao.Cnd;
|
||||
import org.nutz.dao.Dao;
|
||||
import org.nutz.dao.Sqls;
|
||||
import org.nutz.dao.sql.Sql;
|
||||
import org.nutz.dao.util.cri.SqlExpressionGroup;
|
||||
import org.nutz.ioc.loader.annotation.Inject;
|
||||
import org.nutz.ioc.loader.annotation.IocBean;
|
||||
import org.nutz.lang.util.NutMap;
|
||||
@@ -68,56 +54,16 @@ public class CondolenceReadController {
|
||||
@SaCheckPermission("condolence.read")
|
||||
public Result pageData(PageForm pageForm,
|
||||
@Param(value = "year") Integer year,
|
||||
@Param(value = "month") String month,
|
||||
@Param(value = "type") String type,
|
||||
@Param(value = "unionId") String unionId,
|
||||
@Param(value = "unitId") String unitId) {
|
||||
Sql sql = Sqls.create("""
|
||||
SELECT
|
||||
info.*,
|
||||
ins.id AS instanceId,
|
||||
type.name as typeName,
|
||||
ins.state instanceState,
|
||||
ins.processDefineId instanceProcessDefineId,
|
||||
t.displayName taskName
|
||||
FROM
|
||||
condolence info
|
||||
LEFT JOIN wf_process_instance ins ON ins.businessNo = info.id
|
||||
LEFT JOIN (
|
||||
SELECT
|
||||
processInstanceId,
|
||||
displayName,
|
||||
createdAt,
|
||||
ROW_NUMBER() OVER (PARTITION BY processInstanceId ORDER BY createdAt DESC) AS rn
|
||||
FROM wf_process_task
|
||||
) t ON t.processInstanceId = ins.id AND t.rn = 1
|
||||
LEFT JOIN condolence_type type ON info.type = type.id
|
||||
$condition
|
||||
""");
|
||||
Cnd cnd = Cnd.NEW();
|
||||
cnd.andEX("info.type", "=", type);
|
||||
cnd.andEX("YEAR(info.createTime)", "=", year);
|
||||
cnd.andEX("info.applyUnionId", "=", unionId);
|
||||
cnd.andEX("info.applyUnitId", "=", unitId);
|
||||
|
||||
if (StrUtil.isNotBlank(pageForm.getSearchKeyword())) {
|
||||
SqlExpressionGroup seg = new SqlExpressionGroup();
|
||||
seg.or("info.helpUserName", "like", "%" + pageForm.getSearchKeyword() + "%");
|
||||
seg.or("info.helpLoginName", "like", "%" + pageForm.getSearchKeyword() + "%");
|
||||
cnd.and(seg);
|
||||
}
|
||||
|
||||
if (!AuthUtil.hasRoleOr(RoleConstant.SYSADMIN.name(), RoleConstant.SCHOOL_UNION_ADMIN.name())) {
|
||||
cnd.and("info.applyUnionId", "=", SecurityUtil.getUnionId());
|
||||
}
|
||||
|
||||
if (StrUtil.isAllBlank(pageForm.getPageOrderName(), pageForm.getPageOrderBy())) {
|
||||
cnd.desc("info.createTime");
|
||||
} else {
|
||||
cnd.orderBy(pageForm.getPageOrderName(), PageUtil.getOrder(pageForm.getPageOrderBy()));
|
||||
}
|
||||
sql.setCondition(cnd);
|
||||
Pagination<NutMap> pageVO = condolenceService.listPageMap(pageForm.getPageNumber(), pageForm.getPageSize(), sql);
|
||||
return Result.success(pageVO);
|
||||
@Param(value = "unitId") String unitId,
|
||||
@Param(value = "userState") String userState) {
|
||||
Pagination<NutMap> pageVO = condolenceService.pageReadData(pageForm, year, month, type, unionId, unitId, userState);
|
||||
return Result.success(NutMap.NEW()
|
||||
.addv("list", pageVO.getList())
|
||||
.addv("totalCount", pageVO.getTotalCount())
|
||||
.addv("totalMoney", condolenceService.sumReadMoney(pageForm, year, month, type, unionId, unitId, userState)));
|
||||
}
|
||||
|
||||
@At
|
||||
@@ -126,47 +72,24 @@ public class CondolenceReadController {
|
||||
@ApiOperation("导出职工慰问汇总表")
|
||||
public void onExport(PageForm pageForm,
|
||||
@Param(value = "year") Integer year,
|
||||
@Param(value = "month") String month,
|
||||
@Param(value = "type") String type,
|
||||
@Param(value = "unionId") String unionId,
|
||||
@Param(value = "unitId") String unitId,
|
||||
@Param(value = "userState") String userState,
|
||||
HttpServletResponse response) {
|
||||
//查询审核通过的数据
|
||||
Sql sql = Sqls.create("""
|
||||
select
|
||||
con.*,
|
||||
type.name as typeName
|
||||
from
|
||||
condolence con
|
||||
left join wf_process_instance ins on ins.businessNo = con.id
|
||||
left join condolence_type type on type.id = con.type
|
||||
$condition
|
||||
""");
|
||||
Cnd cnd = Cnd.NEW();
|
||||
cnd.and(ProcessInstance::getState, "=", ProcessTaskStateEnum.FINISHED.getCode());
|
||||
cnd.andEX("con.type", "=", type);
|
||||
cnd.andEX("YEAR(info.createTime)", "=", year);
|
||||
cnd.andEX("con.applyUnionId", "=", unionId);
|
||||
cnd.andEX("con.applyUnitId", "=", unitId);
|
||||
if (StrUtil.isNotBlank(pageForm.getSearchKeyword())) {
|
||||
SqlExpressionGroup seg = new SqlExpressionGroup();
|
||||
seg.or("info.helpUserName", "like", "%" + pageForm.getSearchKeyword() + "%");
|
||||
seg.or("info.helpLoginName", "like", "%" + pageForm.getSearchKeyword() + "%");
|
||||
cnd.and(seg);
|
||||
}
|
||||
if (!AuthUtil.hasRoleOr(RoleConstant.SYSADMIN.name(), RoleConstant.SCHOOL_UNION_ADMIN.name())) {
|
||||
cnd.and("con.applyUnionId", "=", SecurityUtil.getUnionId());
|
||||
}
|
||||
sql.setCondition(cnd);
|
||||
List<NutMap> list = condolenceService.listMap(sql);
|
||||
List<NutMap> list = condolenceService.listCompletedReadData(pageForm, year, month, type, unionId, unitId, userState);
|
||||
|
||||
List<ExcelExportEntity> exportEntities = new ArrayList<>();
|
||||
exportEntities.add(new ExcelExportEntity("慰问对象", "helpUserName", 20));
|
||||
exportEntities.add(new ExcelExportEntity("慰问对象工号", "helpLoginName", 20));
|
||||
exportEntities.add(new ExcelExportEntity("在职状态", "userState", 20));
|
||||
exportEntities.add(new ExcelExportEntity("申请人", "applyUserName", 20));
|
||||
exportEntities.add(new ExcelExportEntity("所在工会", "helpUnionName", 20));
|
||||
exportEntities.add(new ExcelExportEntity("所在单位", "helpUnitName", 20));
|
||||
exportEntities.add(new ExcelExportEntity("慰问类型", "typeName", 20));
|
||||
exportEntities.add(new ExcelExportEntity("拟补贴金额", "money", 20));
|
||||
exportEntities.add(new ExcelExportEntity("慰问金额", "money", 20));
|
||||
exportEntities.add(new ExcelExportEntity("申请理由", "remark", 20));
|
||||
|
||||
ExportParams exportParams = new ExportParams();
|
||||
@@ -174,4 +97,19 @@ public class CondolenceReadController {
|
||||
Workbook workbook = ExcelExportUtil.exportExcel(exportParams, exportEntities, list);
|
||||
CommonDownloadUtil.download("申报人汇总.xlsx", workbook, response);
|
||||
}
|
||||
|
||||
@At
|
||||
@Ok("void")
|
||||
@SaCheckPermission("condolence.read")
|
||||
@ApiOperation("导出慰问附件压缩包")
|
||||
public void exportZip(PageForm pageForm,
|
||||
@Param(value = "year") Integer year,
|
||||
@Param(value = "month") String month,
|
||||
@Param(value = "type") String type,
|
||||
@Param(value = "unionId") String unionId,
|
||||
@Param(value = "unitId") String unitId,
|
||||
@Param(value = "userState") String userState,
|
||||
HttpServletResponse response) {
|
||||
condolenceService.exportReadZip(pageForm, year, month, type, unionId, unitId, userState, response);
|
||||
}
|
||||
}
|
||||
|
||||
+71
@@ -1,7 +1,14 @@
|
||||
package com.budwk.app.zhgh.staffbenefit.condolence.service;
|
||||
|
||||
import com.budwk.app.base.service.BaseService;
|
||||
import com.budwk.app.base.page.Pagination;
|
||||
import com.budwk.app.base.param.PageForm;
|
||||
import com.budwk.app.zhgh.staffbenefit.condolence.model.Condolence;
|
||||
import org.nutz.lang.util.NutMap;
|
||||
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.math.BigDecimal;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @ClassName CondolenceService
|
||||
@@ -11,4 +18,68 @@ import com.budwk.app.zhgh.staffbenefit.condolence.model.Condolence;
|
||||
* @Description TODO
|
||||
*/
|
||||
public interface CondolenceService extends BaseService<Condolence> {
|
||||
|
||||
/**
|
||||
* 导出已完成流程的慰问报销单。
|
||||
*
|
||||
* @param id 慰问申请ID
|
||||
* @param response 文件下载响应
|
||||
*/
|
||||
void exportReimbursement(String id, HttpServletResponse response);
|
||||
|
||||
/**
|
||||
* 查询阅览页列表数据,月份优先于年度筛选。
|
||||
*
|
||||
* @param pageForm 分页筛选参数
|
||||
* @param year 年度
|
||||
* @param month 月份,格式 yyyy-MM
|
||||
* @param type 慰问类型
|
||||
* @param unionId 所属工会
|
||||
* @param unitId 所属单位
|
||||
* @param userState 慰问对象在职状态
|
||||
* @return 阅览页分页数据
|
||||
*/
|
||||
Pagination<NutMap> pageReadData(PageForm pageForm, Integer year, String month, String type, String unionId, String unitId, String userState);
|
||||
|
||||
/**
|
||||
* 统计阅览页筛选条件下的慰问金额合计。
|
||||
*
|
||||
* @param pageForm 分页筛选参数
|
||||
* @param year 年度
|
||||
* @param month 月份,格式 yyyy-MM
|
||||
* @param type 慰问类型
|
||||
* @param unionId 所属工会
|
||||
* @param unitId 所属单位
|
||||
* @param userState 慰问对象在职状态
|
||||
* @return 慰问金额合计
|
||||
*/
|
||||
BigDecimal sumReadMoney(PageForm pageForm, Integer year, String month, String type, String unionId, String unitId, String userState);
|
||||
|
||||
/**
|
||||
* 查询阅览页筛选出的已完成慰问数据。
|
||||
*
|
||||
* @param pageForm 分页筛选参数
|
||||
* @param year 年度
|
||||
* @param month 月份,格式 yyyy-MM
|
||||
* @param type 慰问类型
|
||||
* @param unionId 所属工会
|
||||
* @param unitId 所属单位
|
||||
* @param userState 慰问对象在职状态
|
||||
* @return 已完成慰问数据
|
||||
*/
|
||||
List<NutMap> listCompletedReadData(PageForm pageForm, Integer year, String month, String type, String unionId, String unitId, String userState);
|
||||
|
||||
/**
|
||||
* 导出阅览页筛选出的慰问附件和报销单压缩包。
|
||||
*
|
||||
* @param pageForm 分页筛选参数
|
||||
* @param year 年度
|
||||
* @param month 月份,格式 yyyy-MM
|
||||
* @param type 慰问类型
|
||||
* @param unionId 所属工会
|
||||
* @param unitId 所属单位
|
||||
* @param userState 慰问对象在职状态
|
||||
* @param response 文件下载响应
|
||||
*/
|
||||
void exportReadZip(PageForm pageForm, Integer year, String month, String type, String unionId, String unitId, String userState, HttpServletResponse response);
|
||||
}
|
||||
|
||||
+452
@@ -1,11 +1,52 @@
|
||||
package com.budwk.app.zhgh.staffbenefit.condolence.service.impl;
|
||||
|
||||
import cn.hutool.core.date.DateUtil;
|
||||
import cn.hutool.core.lang.Dict;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.hutool.core.util.URLUtil;
|
||||
import cn.hutool.json.JSONObject;
|
||||
import cn.hutool.json.JSONUtil;
|
||||
import com.budwk.app.base.constant.RoleConstant;
|
||||
import com.budwk.app.base.page.Pagination;
|
||||
import com.budwk.app.base.param.PageForm;
|
||||
import com.budwk.app.base.service.impl.BaseServiceImpl;
|
||||
import com.budwk.app.base.utils.CommonDownloadUtil;
|
||||
import com.budwk.app.base.utils.PageUtil;
|
||||
import com.budwk.app.base.utils.SysOfficeTemplateUtil;
|
||||
import com.budwk.app.flow.engine.FlowEngine;
|
||||
import com.budwk.app.flow.entity.ProcessTask;
|
||||
import com.budwk.app.flow.enums.ProcessTaskStateEnum;
|
||||
import com.budwk.app.flow.vo.ProcessTaskVO;
|
||||
import com.budwk.app.sys.services.SysFileService;
|
||||
import com.budwk.app.web.commons.auth.utils.AuthUtil;
|
||||
import com.budwk.app.web.commons.auth.utils.SecurityUtil;
|
||||
import com.budwk.app.zhgh.staffbenefit.condolence.model.Condolence;
|
||||
import com.budwk.app.zhgh.staffbenefit.condolence.service.CondolenceService;
|
||||
import com.deepoove.poi.XWPFTemplate;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.nutz.dao.Dao;
|
||||
import org.nutz.dao.Cnd;
|
||||
import org.nutz.dao.Sqls;
|
||||
import org.nutz.dao.sql.Sql;
|
||||
import org.nutz.dao.util.cri.SqlExpressionGroup;
|
||||
import org.nutz.ioc.loader.annotation.Inject;
|
||||
import org.nutz.ioc.loader.annotation.IocBean;
|
||||
import org.nutz.lang.util.NutMap;
|
||||
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.math.BigDecimal;
|
||||
import java.math.RoundingMode;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Comparator;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipOutputStream;
|
||||
|
||||
/**
|
||||
* @ClassName CondolenceServiceImpl
|
||||
@@ -18,7 +59,418 @@ import org.nutz.ioc.loader.annotation.IocBean;
|
||||
@IocBean(args = {"refer:dao"})
|
||||
public class CondolenceServiceImpl extends BaseServiceImpl<Condolence> implements CondolenceService {
|
||||
|
||||
private static final String[] RMB_UPPER_DIGITS = {"零", "壹", "贰", "叁", "肆", "伍", "陆", "柒", "捌", "玖"};
|
||||
|
||||
@Inject
|
||||
private FlowEngine flowEngine;
|
||||
@Inject
|
||||
private SysOfficeTemplateUtil sysOfficeTemplateUtil;
|
||||
@Inject
|
||||
private SysFileService sysFileService;
|
||||
|
||||
public CondolenceServiceImpl(Dao dao) {
|
||||
super(dao);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void exportReimbursement(String id, HttpServletResponse response) {
|
||||
NutMap info = fetchCompletedCondolenceInfo(id);
|
||||
String memberName = StrUtil.blankToDefault(info.getString("helpUserName"), "慰问");
|
||||
CommonDownloadUtil.download(memberName + "慰问报销单.docx", createReimbursementDocxBytes(info), response);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Pagination<NutMap> pageReadData(PageForm pageForm, Integer year, String month, String type, String unionId, String unitId, String userState) {
|
||||
Sql sql = buildReadSql(pageForm, year, month, type, unionId, unitId, userState, false, true);
|
||||
return listPageMap(pageForm.getPageNumber(), pageForm.getPageSize(), sql);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BigDecimal sumReadMoney(PageForm pageForm, Integer year, String month, String type, String unionId, String unitId, String userState) {
|
||||
Sql sql = Sqls.create("""
|
||||
SELECT
|
||||
COALESCE(SUM(info.money), 0) AS totalMoney
|
||||
FROM
|
||||
condolence info
|
||||
LEFT JOIN wf_process_instance ins ON ins.businessNo = info.id
|
||||
LEFT JOIN condolence_type type ON type.id = info.type
|
||||
LEFT JOIN `vw_user` helpUser ON helpUser.id = info.helpUserId
|
||||
$condition
|
||||
""");
|
||||
sql.setCondition(buildReadCondition(pageForm, year, month, type, unionId, unitId, userState, false, false));
|
||||
sql.setCallback(Sqls.callback.map());
|
||||
dao().execute(sql);
|
||||
NutMap result = (NutMap) sql.getResult();
|
||||
return toBigDecimal(result == null ? null : result.get("totalMoney"));
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<NutMap> listCompletedReadData(PageForm pageForm, Integer year, String month, String type, String unionId, String unitId, String userState) {
|
||||
Sql sql = buildReadSql(pageForm, year, month, type, unionId, unitId, userState, true, false);
|
||||
return listMap(sql);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void exportReadZip(PageForm pageForm, Integer year, String month, String type, String unionId, String unitId, String userState, HttpServletResponse response) {
|
||||
List<NutMap> list = listCompletedReadData(pageForm, year, month, type, unionId, unitId, userState);
|
||||
response.setContentType("application/octet-stream;charset=UTF-8");
|
||||
response.setHeader("Content-Disposition", "attachment;filename=" + URLUtil.encode("职工慰问附件.zip"));
|
||||
try (ZipOutputStream zipOutputStream = new ZipOutputStream(response.getOutputStream())) {
|
||||
Set<String> entryNames = new HashSet<>();
|
||||
for (int i = 0; i < list.size(); i++) {
|
||||
NutMap row = list.get(i);
|
||||
String folderName = uniqueEntryName(entryNames, buildRowFolderName(row, i + 1) + "/");
|
||||
zipOutputStream.putNextEntry(new ZipEntry(folderName));
|
||||
zipOutputStream.closeEntry();
|
||||
|
||||
writeZipEntry(zipOutputStream, entryNames, folderName + sanitizeFileName(row.getString("helpUserName")) + "慰问报销单.docx", createReimbursementDocxBytes(row));
|
||||
writeAttachmentFolder(zipOutputStream, entryNames, folderName, row);
|
||||
}
|
||||
zipOutputStream.finish();
|
||||
} catch (IOException e) {
|
||||
log.error("职工慰问附件ZIP导出失败,错误信息:{}", e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 阅览页、ZIP 和 Excel 导出共用同一套筛选条件,避免不同出口查出的人员不一致。
|
||||
*/
|
||||
private Sql buildReadSql(PageForm pageForm, Integer year, String month, String type, String unionId, String unitId, String userState, boolean completedOnly, boolean withTask) {
|
||||
Sql sql = Sqls.create(withTask ? """
|
||||
SELECT
|
||||
info.*,
|
||||
helpUser.userState AS userState,
|
||||
ins.id AS instanceId,
|
||||
type.name AS typeName,
|
||||
ins.state AS instanceState,
|
||||
ins.processDefineId AS instanceProcessDefineId,
|
||||
t.displayName AS taskName
|
||||
FROM
|
||||
condolence info
|
||||
LEFT JOIN wf_process_instance ins ON ins.businessNo = info.id
|
||||
LEFT JOIN (
|
||||
SELECT
|
||||
processInstanceId,
|
||||
displayName,
|
||||
createdAt,
|
||||
ROW_NUMBER() OVER (PARTITION BY processInstanceId ORDER BY createdAt DESC) AS rn
|
||||
FROM wf_process_task
|
||||
) t ON t.processInstanceId = ins.id AND t.rn = 1
|
||||
LEFT JOIN condolence_type type ON info.type = type.id
|
||||
LEFT JOIN `vw_user` helpUser ON helpUser.id = info.helpUserId
|
||||
$condition
|
||||
""" : """
|
||||
SELECT
|
||||
info.*,
|
||||
helpUser.userState AS userState,
|
||||
type.name AS typeName,
|
||||
ins.id AS instanceId
|
||||
FROM
|
||||
condolence info
|
||||
LEFT JOIN wf_process_instance ins ON ins.businessNo = info.id
|
||||
LEFT JOIN condolence_type type ON type.id = info.type
|
||||
LEFT JOIN `vw_user` helpUser ON helpUser.id = info.helpUserId
|
||||
$condition
|
||||
""");
|
||||
sql.setCondition(buildReadCondition(pageForm, year, month, type, unionId, unitId, userState, completedOnly, true));
|
||||
return sql;
|
||||
}
|
||||
|
||||
/**
|
||||
* 组装阅览页查询条件,月份筛选优先于年度筛选。
|
||||
*/
|
||||
private Cnd buildReadCondition(PageForm pageForm, Integer year, String month, String type, String unionId, String unitId, String userState, boolean completedOnly, boolean withOrder) {
|
||||
Cnd cnd = Cnd.NEW();
|
||||
if (completedOnly) {
|
||||
cnd.and("ins.state", "=", ProcessTaskStateEnum.FINISHED.getCode());
|
||||
}
|
||||
cnd.andEX("info.type", "=", type);
|
||||
if (StrUtil.isNotBlank(month)) {
|
||||
cnd.and("DATE_FORMAT(info.createTime, '%Y-%m')", "=", month);
|
||||
} else {
|
||||
cnd.andEX("YEAR(info.createTime)", "=", year);
|
||||
}
|
||||
cnd.andEX("info.applyUnionId", "=", unionId);
|
||||
cnd.andEX("info.applyUnitId", "=", unitId);
|
||||
cnd.andEX("helpUser.userState", "=", userState);
|
||||
if (StrUtil.isNotBlank(pageForm.getSearchKeyword())) {
|
||||
SqlExpressionGroup seg = new SqlExpressionGroup();
|
||||
seg.or("info.helpUserName", "like", "%" + pageForm.getSearchKeyword() + "%");
|
||||
seg.or("info.helpLoginName", "like", "%" + pageForm.getSearchKeyword() + "%");
|
||||
cnd.and(seg);
|
||||
}
|
||||
if (!AuthUtil.hasRoleOr(RoleConstant.SYSADMIN.name(), RoleConstant.SCHOOL_UNION_ADMIN.name())) {
|
||||
cnd.and("info.applyUnionId", "=", SecurityUtil.getUnionId());
|
||||
}
|
||||
if (withOrder) {
|
||||
if (StrUtil.isAllBlank(pageForm.getPageOrderName(), pageForm.getPageOrderBy())) {
|
||||
cnd.desc("info.createTime");
|
||||
} else {
|
||||
cnd.orderBy(pageForm.getPageOrderName(), PageUtil.getOrder(pageForm.getPageOrderBy()));
|
||||
}
|
||||
}
|
||||
return cnd;
|
||||
}
|
||||
|
||||
private BigDecimal toBigDecimal(Object value) {
|
||||
if (value == null) {
|
||||
return BigDecimal.ZERO.setScale(2, RoundingMode.HALF_UP);
|
||||
}
|
||||
if (value instanceof BigDecimal) {
|
||||
return ((BigDecimal) value).setScale(2, RoundingMode.HALF_UP);
|
||||
}
|
||||
return new BigDecimal(value.toString()).setScale(2, RoundingMode.HALF_UP);
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据慰问记录生成报销单 Word 字节,供单条导出和 ZIP 导出复用。
|
||||
*/
|
||||
private byte[] createReimbursementDocxBytes(NutMap info) {
|
||||
HashMap<String, Object> docData = new HashMap<>();
|
||||
docData.put("condolenceType", info.getString("typeName"));
|
||||
docData.put("applyTime", formatDocDate(info.getString("createTime")));
|
||||
docData.put("condolenceTime", info.getString("occurTime"));
|
||||
docData.put("memberName", info.getString("helpUserName"));
|
||||
docData.put("reason", info.getString("remark"));
|
||||
docData.put("condolenceMoney", formatMoney(info.getDouble("money")));
|
||||
docData.put("applyUserName", info.getString("applyUserName"));
|
||||
docData.put("bankCardNumber", info.getString("bankCardNumber"));
|
||||
docData.put("bankOfDeposit", info.getString("bankOfDeposit"));
|
||||
putPictureRenderData(docData, info.getString("signature"), "applyUserSign", "applyUserSignature", "申请人签字");
|
||||
// 慰问金额合计(大写)按模板格子拆成“仟、佰、拾、元、角、分”六个字段。
|
||||
docData.putAll(buildMoneyDigitMap(info.getDouble("money")));
|
||||
|
||||
List<ProcessTaskVO> doneTaskVos = getDoneTaskVos(info.getLong("instanceId"));
|
||||
putApprovalSign(docData, doneTaskVos, "分工会审核", "branchChairmanSign", "branchChairmanSignTime", "branchChairmanTime", "分工会主席填写时间");
|
||||
putApprovalSign(docData, doneTaskVos, "校工会审核", "unionChairmanSign", "unionChairmanSignTime", "unionChairmanTime", "工会主席填写时间");
|
||||
|
||||
try (ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream()) {
|
||||
XWPFTemplate.compile(sysOfficeTemplateUtil.getTemplate("condolence"))
|
||||
.render(docData)
|
||||
.writeAndClose(byteArrayOutputStream);
|
||||
return byteArrayOutputStream.toByteArray();
|
||||
} catch (IOException e) {
|
||||
log.error("慰问报销单生成失败,id:{},错误信息:{}", info.getString("id"), e.getMessage());
|
||||
return new byte[0];
|
||||
}
|
||||
}
|
||||
|
||||
private void writeAttachmentFolder(ZipOutputStream zipOutputStream, Set<String> entryNames, String folderName, NutMap row) throws IOException {
|
||||
String attachmentFolder = folderName + "附件/";
|
||||
zipOutputStream.putNextEntry(new ZipEntry(uniqueEntryName(entryNames, attachmentFolder)));
|
||||
zipOutputStream.closeEntry();
|
||||
List<JSONObject> files = parseFiles(row.getString("files"));
|
||||
for (int i = 0; i < files.size(); i++) {
|
||||
JSONObject file = files.get(i);
|
||||
String fileId = getFileId(file);
|
||||
if (StrUtil.isBlank(fileId)) {
|
||||
continue;
|
||||
}
|
||||
try {
|
||||
String fileName = sanitizeFileName(StrUtil.blankToDefault(file.getStr("name"), "附件" + (i + 1)));
|
||||
writeZipEntry(zipOutputStream, entryNames, attachmentFolder + fileName, sysFileService.download(fileId));
|
||||
} catch (Exception e) {
|
||||
log.error("慰问附件写入ZIP失败,慰问ID:{},文件ID:{},错误信息:{}", row.getString("id"), fileId, e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private List<JSONObject> parseFiles(String filesStr) {
|
||||
if (StrUtil.isBlank(filesStr)) {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
try {
|
||||
return JSONUtil.parseArray(filesStr).toList(JSONObject.class);
|
||||
} catch (Exception e) {
|
||||
log.error("慰问附件解析失败,附件内容:{}", filesStr);
|
||||
return new ArrayList<>();
|
||||
}
|
||||
}
|
||||
|
||||
private String getFileId(JSONObject file) {
|
||||
String filePath = "";
|
||||
JSONObject response = file.getJSONObject("response");
|
||||
if (response != null) {
|
||||
filePath = response.getStr("data");
|
||||
}
|
||||
if (StrUtil.isBlank(filePath)) {
|
||||
filePath = file.getStr("url");
|
||||
}
|
||||
if (StrUtil.isBlank(filePath)) {
|
||||
filePath = file.getStr("downloadPath");
|
||||
}
|
||||
if (StrUtil.isBlank(filePath)) {
|
||||
filePath = file.getStr("id");
|
||||
}
|
||||
if (StrUtil.isBlank(filePath)) {
|
||||
return "";
|
||||
}
|
||||
int index = filePath.indexOf("id=");
|
||||
if (index >= 0) {
|
||||
return filePath.substring(index + 3);
|
||||
}
|
||||
return filePath;
|
||||
}
|
||||
|
||||
private void writeZipEntry(ZipOutputStream zipOutputStream, Set<String> entryNames, String entryName, byte[] bytes) throws IOException {
|
||||
if (bytes == null || bytes.length == 0) {
|
||||
return;
|
||||
}
|
||||
zipOutputStream.putNextEntry(new ZipEntry(uniqueEntryName(entryNames, entryName)));
|
||||
zipOutputStream.write(bytes);
|
||||
zipOutputStream.closeEntry();
|
||||
}
|
||||
|
||||
private String buildRowFolderName(NutMap row, int index) {
|
||||
String name = StrUtil.blankToDefault(row.getString("helpUserName"), "慰问人");
|
||||
String loginName = StrUtil.blankToDefault(row.getString("helpLoginName"), "");
|
||||
String createTime = StrUtil.blankToDefault(row.getString("createTime"), "");
|
||||
String folderName = index + "." + name + (StrUtil.isBlank(loginName) ? "" : "_" + loginName) + "_" + createTime;
|
||||
return sanitizeFileName(folderName);
|
||||
}
|
||||
|
||||
private String sanitizeFileName(String fileName) {
|
||||
String name = StrUtil.blankToDefault(fileName, "未命名");
|
||||
return name.replaceAll("[\\\\/:*?\"<>|\\r\\n]", "_");
|
||||
}
|
||||
|
||||
private String uniqueEntryName(Set<String> entryNames, String entryName) {
|
||||
String name = entryName;
|
||||
int count = 1;
|
||||
while (entryNames.contains(name)) {
|
||||
int slashIndex = entryName.lastIndexOf("/");
|
||||
int dotIndex = entryName.lastIndexOf(".");
|
||||
if (dotIndex > slashIndex) {
|
||||
name = entryName.substring(0, dotIndex) + "(" + count + ")" + entryName.substring(dotIndex);
|
||||
} else if (entryName.endsWith("/")) {
|
||||
name = entryName.substring(0, entryName.length() - 1) + "(" + count + ")/";
|
||||
} else {
|
||||
name = entryName + "(" + count + ")";
|
||||
}
|
||||
count++;
|
||||
}
|
||||
entryNames.add(name);
|
||||
return name;
|
||||
}
|
||||
|
||||
/**
|
||||
* 只允许已完成流程导出,避免未审批完成的数据生成正式报销单。
|
||||
*/
|
||||
private NutMap fetchCompletedCondolenceInfo(String id) {
|
||||
Sql sql = Sqls.create("""
|
||||
SELECT
|
||||
info.*,
|
||||
type.name AS typeName,
|
||||
ins.id AS instanceId
|
||||
FROM
|
||||
condolence info
|
||||
LEFT JOIN condolence_type type ON info.type = type.id
|
||||
LEFT JOIN wf_process_instance ins ON ins.businessNo = info.id
|
||||
WHERE
|
||||
ins.state = 20 AND info.id = @id
|
||||
""").setParam("id", id);
|
||||
sql.setCallback(Sqls.callback.map());
|
||||
dao().execute(sql);
|
||||
NutMap info = (NutMap) sql.getResult();
|
||||
if (info == null) {
|
||||
throw new RuntimeException("慰问流程未完成或记录不存在,不能导出报销单");
|
||||
}
|
||||
return info;
|
||||
}
|
||||
|
||||
/**
|
||||
* 读取已办流程任务,后续从任务表单变量中取审批签字。
|
||||
*/
|
||||
private List<ProcessTaskVO> getDoneTaskVos(Long instanceId) {
|
||||
List<ProcessTaskVO> doneTaskVos = new ArrayList<>();
|
||||
List<ProcessTask> doneTaskList = flowEngine.processTaskService().getDoneTaskList(instanceId, null);
|
||||
for (ProcessTask doneTask : doneTaskList) {
|
||||
ProcessTaskVO taskVO = flowEngine.processTaskService().findById(doneTask.getId());
|
||||
doneTaskVos.add(taskVO);
|
||||
}
|
||||
return doneTaskVos;
|
||||
}
|
||||
|
||||
/**
|
||||
* 将指定审批节点最近一次签字和填写时间放入模板字段。
|
||||
*/
|
||||
private void putApprovalSign(Map<String, Object> docData, List<ProcessTaskVO> doneTaskVos, String taskName, String templateField, String... timeFields) {
|
||||
doneTaskVos.stream()
|
||||
.filter(task -> taskName.equals(task.getDisplayName()))
|
||||
.max(Comparator.comparing(ProcessTaskVO::getCreatedAt))
|
||||
.ifPresent(task -> {
|
||||
Dict taskFormData = task.getTaskFormData();
|
||||
String signTime = taskFormData.getStr("finishTimeForDocx");
|
||||
if (StrUtil.isBlank(signTime) && task.getFinishTime() != null) {
|
||||
signTime = DateUtil.format(task.getFinishTime(), "yyyy年MM月dd日");
|
||||
}
|
||||
for (String timeField : timeFields) {
|
||||
docData.put(timeField, signTime);
|
||||
}
|
||||
String sign = taskFormData.getStr("tf_userSign");
|
||||
if (StrUtil.isBlank(sign)) {
|
||||
sign = taskFormData.getStr("tf_sign");
|
||||
}
|
||||
if (StrUtil.isNotBlank(sign)) {
|
||||
putPictureRenderData(docData, sign, templateField);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 将签字图片同时写入多个模板字段,兼容不同模板占位符命名。
|
||||
*/
|
||||
private void putPictureRenderData(Map<String, Object> docData, String sign, String... templateFields) {
|
||||
if (StrUtil.isBlank(sign)) {
|
||||
return;
|
||||
}
|
||||
for (String templateField : templateFields) {
|
||||
docData.put(templateField, sysOfficeTemplateUtil.createPictureRenderData(sign));
|
||||
}
|
||||
}
|
||||
|
||||
private String formatDocDate(String date) {
|
||||
if (StrUtil.isBlank(date)) {
|
||||
return "";
|
||||
}
|
||||
try {
|
||||
return DateUtil.format(DateUtil.parse(date), "yyyy年MM月dd日");
|
||||
} catch (Exception e) {
|
||||
return date;
|
||||
}
|
||||
}
|
||||
|
||||
private String formatMoney(Double money) {
|
||||
if (money == null) {
|
||||
return "";
|
||||
}
|
||||
return BigDecimal.valueOf(money).setScale(2, RoundingMode.HALF_UP).toPlainString();
|
||||
}
|
||||
|
||||
/**
|
||||
* 报销单模板只预留到仟位,金额超过 9999.99 时直接提示,防止生成错误单据。
|
||||
*/
|
||||
private Map<String, Object> buildMoneyDigitMap(Double money) {
|
||||
BigDecimal amount = money == null ? BigDecimal.ZERO : BigDecimal.valueOf(money);
|
||||
amount = amount.setScale(2, RoundingMode.HALF_UP);
|
||||
if (amount.compareTo(new BigDecimal("9999.99")) > 0) {
|
||||
throw new RuntimeException("慰问金额超过报销单模板支持范围");
|
||||
}
|
||||
long cents = amount.movePointRight(2).longValue();
|
||||
Map<String, Object> map = new HashMap<>();
|
||||
map.put("Qian", toUpperDigit((int) (cents / 100000 % 10)));
|
||||
map.put("Bai", toUpperDigit((int) (cents / 10000 % 10)));
|
||||
map.put("Shi", toUpperDigit((int) (cents / 1000 % 10)));
|
||||
map.put("Yuan", toUpperDigit((int) (cents / 100 % 10)));
|
||||
map.put("Jiao", toUpperDigit((int) (cents / 10 % 10)));
|
||||
map.put("Fen", toUpperDigit((int) (cents % 10)));
|
||||
return map;
|
||||
}
|
||||
|
||||
private String toUpperDigit(int digit) {
|
||||
if (digit < 0 || digit > 9) {
|
||||
return "";
|
||||
}
|
||||
return RMB_UPPER_DIGITS[digit];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,17 +1,85 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<configuration scan="false" scanPeriod="60000" debug="false">
|
||||
|
||||
<!-- 定义日志文件的存储路径 -->
|
||||
<!-- 日志存储路径 -->
|
||||
<property name="LOG_HOME" value="./logs"/>
|
||||
|
||||
<!-- 控制台输出配置 -->
|
||||
<!-- 控制台输出 -->
|
||||
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
|
||||
<encoder>
|
||||
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
|
||||
</encoder>
|
||||
</appender>
|
||||
|
||||
<!-- INFO级别日志文件配置 -->
|
||||
|
||||
<!--
|
||||
#################################################################################
|
||||
# #
|
||||
# 全文输出日志(一个文件存储)start #
|
||||
# #
|
||||
#################################################################################
|
||||
-->
|
||||
|
||||
<!-- 所有级别日志写入同一个文件 -->
|
||||
<appender name="ALL_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
|
||||
<file>${LOG_HOME}/app.log</file>
|
||||
<encoder>
|
||||
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
|
||||
</encoder>
|
||||
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
|
||||
<fileNamePattern>${LOG_HOME}/app-%d{yyyy-MM-dd}.log</fileNamePattern>
|
||||
<maxHistory>300</maxHistory>
|
||||
</rollingPolicy>
|
||||
</appender>
|
||||
|
||||
<!-- 框架日志级别(按需调整) -->
|
||||
<logger name="org.eclipse.jetty" level="INFO"/>
|
||||
<logger name="org.quartz" level="INFO"/>
|
||||
<logger name="org.nutz" level="DEBUG"/>
|
||||
|
||||
<!-- root logger:DEBUG 级别,输出到控制台和全量文件 -->
|
||||
<root level="DEBUG">
|
||||
<appender-ref ref="STDOUT"/>
|
||||
<appender-ref ref="ALL_FILE"/>
|
||||
</root>
|
||||
|
||||
<!--
|
||||
#################################################################################
|
||||
# #
|
||||
# 全文输出日志(一个文件存储)end #
|
||||
# #
|
||||
#################################################################################
|
||||
-->
|
||||
|
||||
|
||||
|
||||
|
||||
<!--
|
||||
#################################################################################
|
||||
# #
|
||||
# debug、info、error分文件输出 start #
|
||||
# #
|
||||
#################################################################################
|
||||
-->
|
||||
|
||||
<!-- DEBUG级别日志文件配置 -->
|
||||
<!--<appender name="DEBUG_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
|
||||
<file>${LOG_HOME}/debug.log</file>
|
||||
<encoder>
|
||||
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
|
||||
</encoder>
|
||||
<filter class="ch.qos.logback.classic.filter.LevelFilter">
|
||||
<level>DEBUG</level>
|
||||
<onMatch>ACCEPT</onMatch>
|
||||
<onMismatch>DENY</onMismatch>
|
||||
</filter>
|
||||
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
|
||||
<fileNamePattern>${LOG_HOME}/debug-%d{yyyy-MM-dd}.log</fileNamePattern>
|
||||
<maxHistory>300</maxHistory>
|
||||
</rollingPolicy>
|
||||
</appender>
|
||||
|
||||
<!– INFO级别日志文件配置 –>
|
||||
<appender name="INFO_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
|
||||
<file>${LOG_HOME}/info.log</file>
|
||||
<encoder>
|
||||
@@ -24,11 +92,11 @@
|
||||
</filter>
|
||||
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
|
||||
<fileNamePattern>${LOG_HOME}/info-%d{yyyy-MM-dd}.log</fileNamePattern>
|
||||
<maxHistory>30</maxHistory>
|
||||
<maxHistory>300</maxHistory>
|
||||
</rollingPolicy>
|
||||
</appender>
|
||||
|
||||
<!-- ERROR级别日志文件配置 -->
|
||||
<!– ERROR级别日志文件配置 –>
|
||||
<appender name="ERROR_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
|
||||
<file>${LOG_HOME}/error.log</file>
|
||||
<encoder>
|
||||
@@ -41,19 +109,31 @@
|
||||
</filter>
|
||||
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
|
||||
<fileNamePattern>${LOG_HOME}/error-%d{yyyy-MM-dd}.log</fileNamePattern>
|
||||
<maxHistory>30</maxHistory>
|
||||
<maxHistory>300</maxHistory>
|
||||
</rollingPolicy>
|
||||
</appender>
|
||||
|
||||
<logger name="java" additivity="false" />
|
||||
<!– 框架日志级别 –>
|
||||
<!– <logger name="java" additivity="false" />–>
|
||||
<logger name="org.eclipse.jetty" level="INFO"/>
|
||||
<logger name="org.quartz" level="INFO"/>
|
||||
<logger name="org.nutz" level="DEBUG"/>
|
||||
|
||||
<!-- 日志级别和appender的关联 -->
|
||||
<!– 日志级别和appender的关联 –>
|
||||
<root level="DEBUG">
|
||||
<appender-ref ref="STDOUT"/>
|
||||
<appender-ref ref="DEBUG_FILE"/>
|
||||
<appender-ref ref="INFO_FILE"/>
|
||||
<appender-ref ref="ERROR_FILE"/>
|
||||
</root>
|
||||
</root>-->
|
||||
|
||||
<!--
|
||||
#################################################################################
|
||||
# #
|
||||
# debug、info、error分文件输出 end #
|
||||
# #
|
||||
#################################################################################
|
||||
-->
|
||||
|
||||
</configuration>
|
||||
|
||||
|
||||
@@ -258,7 +258,12 @@ const user = {
|
||||
this.$message.warning("当前流程没有配置地址")
|
||||
return
|
||||
}
|
||||
window.open(formKey + "?taskId=" + taskId + "&bizId=" + businessNo + "&taskKey=" + taskKey + "&tab=" + this.activeTab)
|
||||
var viewUrl = formKey + "?taskId=" + taskId + "&bizId=" + businessNo + "&taskKey=" + taskKey + "&tab=" + this.activeTab
|
||||
// 首页待办进入提案附议 second 节点时,默认打开受邀附议页签,避免影响其他流程跳转。
|
||||
if (formKey === "/platform/proposal/seconded" && taskKey === "second" && this.activeTab === "todo") {
|
||||
viewUrl += "&secondedTab=inviteSeconded"
|
||||
}
|
||||
window.open(viewUrl)
|
||||
},
|
||||
getRoleNames() {
|
||||
$.post("/platform/sys/role/getRoleNames").then(res => {
|
||||
|
||||
@@ -420,7 +420,12 @@ layout("/layouts/v4/baseLayout.html"){
|
||||
this.$message.warning("当前流程没有配置地址")
|
||||
return
|
||||
}
|
||||
window.open(formKey + "?taskId=" + taskId + "bizId=" + businessNo + "taskKey=" + taskKey)
|
||||
var viewUrl = formKey + "?taskId=" + taskId + "bizId=" + businessNo + "taskKey=" + taskKey
|
||||
// 待办中心进入提案附议 second 节点时,默认打开受邀附议页签,避免影响其他流程跳转。
|
||||
if (formKey === "/platform/proposal/seconded" && taskKey === "second" && this.activeTab === "todo") {
|
||||
viewUrl += "&secondedTab=inviteSeconded"
|
||||
}
|
||||
window.open(viewUrl)
|
||||
},
|
||||
|
||||
// 获取空状态文本
|
||||
|
||||
@@ -464,7 +464,12 @@ layout("/layouts/v4/baseLayout.html"){
|
||||
this.$message.warning("当前流程没有配置地址")
|
||||
return
|
||||
}
|
||||
window.open(formKey + "?taskId=" + taskId + "bizId=" + businessNo + "taskKey=" + taskKey)
|
||||
var viewUrl = formKey + "?taskId=" + taskId + "bizId=" + businessNo + "taskKey=" + taskKey
|
||||
// 待办中心进入提案附议 second 节点时,默认打开受邀附议页签,避免影响其他流程跳转。
|
||||
if (formKey === "/platform/proposal/seconded" && taskKey === "second" && this.activeTab === "todo") {
|
||||
viewUrl += "&secondedTab=inviteSeconded"
|
||||
}
|
||||
window.open(viewUrl)
|
||||
},
|
||||
|
||||
// 获取空状态文本
|
||||
|
||||
+2
-1
@@ -337,12 +337,13 @@ layout("/layouts/platform.html"){
|
||||
},
|
||||
listSession() {
|
||||
this.$axios.post("/platform/proposal/common/listSession", {
|
||||
orderBy: "asc"
|
||||
orderBy: "desc"
|
||||
}).then((res) => {
|
||||
if (res.code === 0) {
|
||||
this.sessionOptions = res.data
|
||||
if (this.sessionOptions) {
|
||||
this.$set(this.pageForm, "sessionId", this.sessionOptions[0].id)
|
||||
this.$set(this.pageForm, "sessionIds", [this.sessionOptions[0].id])
|
||||
this.listDelegation()
|
||||
this.pageData()
|
||||
}
|
||||
|
||||
+106
@@ -0,0 +1,106 @@
|
||||
<!--#
|
||||
layout("/layouts/platform.html"){
|
||||
#-->
|
||||
|
||||
<div id="app" v-cloak>
|
||||
<el-card shadow="never">
|
||||
<search @search="doSearch">
|
||||
<search-item label="届次">
|
||||
<el-select clearable filterable placeholder="请选择届次" v-model="pageForm.sessionId">
|
||||
<el-option :key="item.id" :label="item.fullName" :value="item.id"
|
||||
v-for="item in sessionOptions"></el-option>
|
||||
</el-select>
|
||||
</search-item>
|
||||
<search-item label="提案类别">
|
||||
<el-select clearable collapse-tags filterable multiple placeholder="请选择提案类别"
|
||||
v-model="pageForm.typeIds">
|
||||
<el-option :key="item.id" :label="item.name" :value="item.id"
|
||||
v-for="item in typeOptions"></el-option>
|
||||
</el-select>
|
||||
</search-item>
|
||||
</search>
|
||||
</el-card>
|
||||
|
||||
<el-card shadow="never">
|
||||
<el-table :data="tableData" style="width: 100%">
|
||||
<el-table-column label="序号" type="index" width="50"></el-table-column>
|
||||
<el-table-column label="提案类别" prop="typeName" min-width="160" sortable></el-table-column>
|
||||
<el-table-column label="立案同意数" prop="filingCount" sortable></el-table-column>
|
||||
<el-table-column label="已反馈数" prop="feedbackCount" sortable></el-table-column>
|
||||
<el-table-column label="未反馈数" prop="unFeedbackCount" sortable></el-table-column>
|
||||
<el-table-column label="完成率" prop="completionRate" sortable>
|
||||
<template scope="{row}">
|
||||
{{ row.completionRateText }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="满意数" prop="satisfiedCount" sortable></el-table-column>
|
||||
<el-table-column label="不满意数" prop="dissatisfiedCount" sortable></el-table-column>
|
||||
<el-table-column label="满意率" prop="satisfactionRate" sortable>
|
||||
<template scope="{row}">
|
||||
{{ row.satisfactionRateText }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</el-card>
|
||||
</div>
|
||||
|
||||
<script nonce="${cspNonce!}">
|
||||
<!--#include("../../common/info.js"){}#-->
|
||||
|
||||
new Vue({
|
||||
el: "#app",
|
||||
mixins: [initTableMixins],
|
||||
data() {
|
||||
return {
|
||||
sessionOptions: [],
|
||||
typeOptions: [],
|
||||
pageForm: {
|
||||
sessionId: null,
|
||||
typeIds: []
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
doSearch() {
|
||||
this.pageData()
|
||||
},
|
||||
listSession() {
|
||||
this.$axios.post("/platform/proposal/common/listSession", {
|
||||
orderBy: "desc"
|
||||
}).then((res) => {
|
||||
if (res.code === 0) {
|
||||
this.$set(this, "sessionOptions", res.data)
|
||||
if (this.sessionOptions && this.sessionOptions.length > 0) {
|
||||
this.$set(this.pageForm, "sessionId", this.sessionOptions[0].id)
|
||||
}
|
||||
this.pageData()
|
||||
}
|
||||
})
|
||||
},
|
||||
listProposalType() {
|
||||
this.$axios.post("/platform/proposal/common/listProposalType").then((res) => {
|
||||
if (res.code === 0) {
|
||||
this.$set(this, "typeOptions", res.data)
|
||||
}
|
||||
})
|
||||
},
|
||||
pageData() {
|
||||
this.$axios.post(loc() + "/data", {
|
||||
pageForm: JSON.stringify(this.pageForm)
|
||||
}).then((res) => {
|
||||
if (res.code === 0) {
|
||||
this.$set(this, "tableData", res.data)
|
||||
}
|
||||
})
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.listSession()
|
||||
this.listProposalType()
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
<!--#
|
||||
}
|
||||
#-->
|
||||
+1
-1
@@ -87,7 +87,7 @@ layout("/layouts/platform.html"){
|
||||
<el-button @click="openView(row)" size="mini" type="primary">查看</el-button>
|
||||
<el-button v-if="row.taskState === 10" @click="openAudit(row)" size="mini" type="primary">审核
|
||||
</el-button>
|
||||
<el-button @click="onRevoke(row)" size="mini" type="danger">撤回
|
||||
<el-button v-if="row.canRevoke" @click="onRevoke(row)" size="mini" type="danger">撤回
|
||||
</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
+9
@@ -205,6 +205,14 @@ layout("/layouts/platform.html"){
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
initSecondedTab: function () {
|
||||
// 只响应首页待办跳转传入的提案附议专用参数,普通菜单进入仍默认主动附议。
|
||||
if (GetQueryString("secondedTab") === "inviteSeconded") {
|
||||
this.$set(this, "activeTab", "inviteSeconded")
|
||||
this.$set(this.pageForm, "approval", false)
|
||||
}
|
||||
},
|
||||
|
||||
syncTableColumns: function () {
|
||||
if (this.activeTab === "inviteSeconded") {
|
||||
this.$set(this, "tableColumns", this.inviteColumns)
|
||||
@@ -455,6 +463,7 @@ layout("/layouts/platform.html"){
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.initSecondedTab()
|
||||
this.syncTableColumns()
|
||||
this.pageData()
|
||||
this.listOpenSession()
|
||||
|
||||
+6
-1
@@ -81,6 +81,10 @@ layout("/layouts/platform.html"){
|
||||
:rules="[{required:true,message:'必填',trigger:['change','blur']}]">
|
||||
<user-opinion-textarea v-model="formData.tf_opinion"></user-opinion-textarea>
|
||||
</el-form-item>
|
||||
<el-form-item label="电子签名" prop="tf_userSign"
|
||||
:rules="[{required:true,message:'必填',trigger:['change','blur']}]">
|
||||
<pc-signature v-model="formData.tf_userSign"></pc-signature>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<el-row type="flex" justify="end">
|
||||
<el-button @click="$refs.guava.index()" size="small">取消</el-button>
|
||||
@@ -135,7 +139,8 @@ layout("/layouts/platform.html"){
|
||||
this.showApprovalForm = true
|
||||
this.formData = {
|
||||
processTaskId: row.taskId,
|
||||
taskName: row.curTaskName
|
||||
taskName: row.curTaskName,
|
||||
tf_userSign: null
|
||||
}
|
||||
this.$refs.condolenceInfoRef.onOpen(row)
|
||||
})
|
||||
|
||||
@@ -60,6 +60,7 @@ layout("/layouts/platform.html"){
|
||||
<el-table-column label="操作" fixed="right" width="300">
|
||||
<template slot-scope="{row}">
|
||||
<el-button @click="onView(row)" size="mini" type="primary">查看</el-button>
|
||||
<el-button v-if="row.instanceState === 20" @click="doExport(row)" size="mini" type="primary">导出报销单</el-button>
|
||||
<el-button v-if="row.taskKey === 'startTask' || !row.instanceId" @click="onEdit(row)" size="mini" type="primary">编辑</el-button>
|
||||
<el-button v-if="row.canRevoke" size="mini" type="danger" @click="onRevoke(row)">撤回</el-button>
|
||||
<el-button v-if="row.taskKey === 'startTask' || !row.instanceId" @click="onDelete(row.id)" size="mini" type="danger">
|
||||
@@ -102,6 +103,9 @@ layout("/layouts/platform.html"){
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
doExport(row) {
|
||||
window.location.href = "/platform/condolence/mine/doExport?id=" + (row.id || "")
|
||||
},
|
||||
onAdd() {
|
||||
commonUtil.pjaxPush('/platform/condolence/apply')
|
||||
},
|
||||
|
||||
@@ -16,6 +16,16 @@ layout("/layouts/platform.html"){
|
||||
@change="doSearch"
|
||||
></el-date-picker>
|
||||
</search-item>
|
||||
<search-item label="月份">
|
||||
<el-date-picker
|
||||
v-model="pageForm.month"
|
||||
type="month"
|
||||
value-format="yyyy-MM"
|
||||
placeholder="请选择月份"
|
||||
style="width: 100%"
|
||||
@change="doSearch"
|
||||
></el-date-picker>
|
||||
</search-item>
|
||||
<search-item label="姓名/工号">
|
||||
<el-input placeholder="请输入姓名或工号" clearable v-model="pageForm.searchKeyword"
|
||||
@keyup.enter.native="doSearch">
|
||||
@@ -31,6 +41,14 @@ layout("/layouts/platform.html"){
|
||||
></el-option>
|
||||
</el-select>
|
||||
</search-item>
|
||||
<search-item label="在职状态">
|
||||
<dict-select v-model="pageForm.userState"
|
||||
style="width: 100%"
|
||||
clearable
|
||||
placeholder="请选择在职状态"
|
||||
code="USER_STATE"
|
||||
@change="doSearch"></dict-select>
|
||||
</search-item>
|
||||
<search-item label="所属工会">
|
||||
<el-select v-model="pageForm.unionId" placeholder="请选择所属工会" filterable clearable
|
||||
@change="doSearch" style="width: 100%">
|
||||
@@ -56,8 +74,13 @@ layout("/layouts/platform.html"){
|
||||
<el-card shadow="never">
|
||||
<table-tool label="申请列表">
|
||||
<el-button @click="onExport" icon="el-icon-s-promotion" type="primary" size="small">导出</el-button>
|
||||
<el-button @click="onExportZip" icon="el-icon-folder-opened" type="primary" size="small">导出附件ZIP</el-button>
|
||||
</table-tool>
|
||||
<el-table :data="tableData" @sort-change="pageOrder" style="width: 100%">
|
||||
<el-table :data="tableData"
|
||||
@sort-change="pageOrder"
|
||||
:summary-method="getSummaries"
|
||||
show-summary
|
||||
style="width: 100%">
|
||||
<el-table-column type="index" width="50px" label="序号" :index="indexMethod"></el-table-column>
|
||||
<el-table-column
|
||||
:label="column.label"
|
||||
@@ -107,18 +130,46 @@ layout("/layouts/platform.html"){
|
||||
tableColumns: [
|
||||
{prop: 'helpUserName', label: '慰问对象'},
|
||||
{prop: 'helpLoginName', label: '慰问对象工号'},
|
||||
{prop: 'userState', label: '在职状态'},
|
||||
{prop: 'applyUserName', label: '申请人'},
|
||||
{prop: 'applyUnionName', label: '所属工会'},
|
||||
{prop: 'applyUnitName', label: '所属单位'},
|
||||
{prop: 'typeName', label: '慰问类型'},
|
||||
{prop: 'money', label: '慰问金额'},
|
||||
{prop: 'taskName', label: '当前节点'},
|
||||
{prop: 'instanceState', label: '流程状态'},
|
||||
],
|
||||
unionList: [],
|
||||
unitList: [],
|
||||
totalMoney: 0,
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
pageData(data) {
|
||||
const address = this.pageDataUrl ? this.pageDataUrl : loc() + "/pageData"
|
||||
this.tableLoading = true
|
||||
this.$axios.post(address, data ? data : this.pageForm).then((res) => {
|
||||
this.tableLoading = false
|
||||
if (res.code === 0) {
|
||||
this.tableData = res.data.list
|
||||
this.pageForm.totalCount = res.data.totalCount
|
||||
this.$set(this, "totalMoney", Number(res.data.totalMoney || 0))
|
||||
}
|
||||
})
|
||||
},
|
||||
getSummaries(param) {
|
||||
const sums = []
|
||||
param.columns.forEach((column, index) => {
|
||||
if (index === 0) {
|
||||
sums[index] = "合计"
|
||||
} else if (column.property === "money") {
|
||||
sums[index] = this.totalMoney.toFixed(2)
|
||||
} else {
|
||||
sums[index] = ""
|
||||
}
|
||||
})
|
||||
return sums
|
||||
},
|
||||
onDelete(id) {
|
||||
this.$confirm("您确定要删除吗?", "提示", {
|
||||
confirmButtonText: "确定",
|
||||
@@ -136,6 +187,9 @@ layout("/layouts/platform.html"){
|
||||
onExport() {
|
||||
this.$downLoad(loc() + '/onExport', this.pageForm)
|
||||
},
|
||||
onExportZip() {
|
||||
this.$downLoad(loc() + '/exportZip', this.pageForm)
|
||||
},
|
||||
onView(row) {
|
||||
this.$refs.guava.edit(()=>{
|
||||
this.$refs.condolenceInfoRef.onOpen(row)
|
||||
@@ -147,8 +201,17 @@ layout("/layouts/platform.html"){
|
||||
this.typeOptions = resp.data
|
||||
})
|
||||
},
|
||||
initPageForm() {
|
||||
this.$set(this.pageForm, "year", "")
|
||||
this.$set(this.pageForm, "month", "")
|
||||
this.$set(this.pageForm, "type", "")
|
||||
this.$set(this.pageForm, "unionId", "")
|
||||
this.$set(this.pageForm, "unitId", "")
|
||||
this.$set(this.pageForm, "userState", "")
|
||||
},
|
||||
},
|
||||
async created() {
|
||||
this.initPageForm()
|
||||
this.unionList = await this.$businessTool.listUnion()
|
||||
this.unitList = await this.$businessTool.listUnit()
|
||||
this.queryCondolenceType()
|
||||
|
||||
+6
-1
@@ -101,6 +101,10 @@ layout("/layouts/platform.html"){
|
||||
:rules="[{required:true,message:'必填',trigger:['change','blur']}]">
|
||||
<user-opinion-textarea v-model="formData.tf_opinion"></user-opinion-textarea>
|
||||
</el-form-item>
|
||||
<el-form-item label="电子签名" prop="tf_userSign"
|
||||
:rules="[{required:true,message:'必填',trigger:['change','blur']}]">
|
||||
<pc-signature v-model="formData.tf_userSign"></pc-signature>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<el-row type="flex" justify="end">
|
||||
<el-button @click="$refs.guava.index()" size="small">取消</el-button>
|
||||
@@ -158,7 +162,8 @@ layout("/layouts/platform.html"){
|
||||
this.showApprovalForm = true
|
||||
this.formData = {
|
||||
processTaskId: row.taskId,
|
||||
taskName: row.curTaskName
|
||||
taskName: row.curTaskName,
|
||||
tf_userSign: null
|
||||
}
|
||||
this.$refs.condolenceInfoRef.onOpen(row)
|
||||
})
|
||||
|
||||
+13
-1
@@ -70,6 +70,17 @@ layout("/layouts/platform_h5.html"){
|
||||
maxlength="100"
|
||||
show-word-limit
|
||||
></van-field>
|
||||
<van-field
|
||||
class="more-text"
|
||||
name="tf_userSign"
|
||||
label="电子签名"
|
||||
:rules="[{ required: true, message: '请签字' }]"
|
||||
required
|
||||
>
|
||||
<template #input>
|
||||
<h5-signature v-model="formData.tf_userSign"></h5-signature>
|
||||
</template>
|
||||
</van-field>
|
||||
</van-form>
|
||||
<div style="display: flex; justify-content: space-between; column-gap: 10px; padding: 10px">
|
||||
<van-button type="danger" block @click="handleTaskAction(6)">退回</van-button>
|
||||
@@ -128,7 +139,8 @@ layout("/layouts/platform_h5.html"){
|
||||
this.$refs.infoRef.onOpen(row)
|
||||
this.formData = {
|
||||
processTaskId: row.taskId,
|
||||
taskName: row.curTaskName
|
||||
taskName: row.curTaskName,
|
||||
tf_userSign: null
|
||||
}
|
||||
},
|
||||
async handleTaskAction(val) {
|
||||
|
||||
+13
-1
@@ -70,6 +70,17 @@ layout("/layouts/platform_h5.html"){
|
||||
maxlength="100"
|
||||
show-word-limit
|
||||
></van-field>
|
||||
<van-field
|
||||
class="more-text"
|
||||
name="tf_userSign"
|
||||
label="电子签名"
|
||||
:rules="[{ required: true, message: '请签字' }]"
|
||||
required
|
||||
>
|
||||
<template #input>
|
||||
<h5-signature v-model="formData.tf_userSign"></h5-signature>
|
||||
</template>
|
||||
</van-field>
|
||||
</van-form>
|
||||
<div style="display: flex; justify-content: space-between; column-gap: 10px; padding: 10px">
|
||||
<van-button type="danger" block @click="handleTaskAction(6)">退回</van-button>
|
||||
@@ -128,7 +139,8 @@ layout("/layouts/platform_h5.html"){
|
||||
this.$refs.infoRef.onOpen(row)
|
||||
this.formData = {
|
||||
processTaskId: row.taskId,
|
||||
taskName: row.curTaskName
|
||||
taskName: row.curTaskName,
|
||||
tf_userSign: null
|
||||
}
|
||||
},
|
||||
async handleTaskAction(val) {
|
||||
|
||||
Reference in New Issue
Block a user