Merge remote-tracking branch 'origin/main'

# Conflicts:
#	src/main/java/io/v/nutz/wakershome/service/impl/review/CommentPeoServiceImpl.java
This commit is contained in:
2024-08-26 13:55:19 +08:00
11 changed files with 419 additions and 34 deletions
@@ -1,26 +1,53 @@
package io.v.nutz.wakershome.controller.review;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.util.StrUtil;
import com.deepoove.poi.XWPFTemplate;
import com.deepoove.poi.config.Configure;
import com.deepoove.poi.policy.HackLoopTableRenderPolicy;
import io.v.nutz.annontation.ViReturn;
import io.v.nutz.base.utils.Vi;
import io.v.nutz.modules.models.PageForm;
import io.v.nutz.sys.models.Sys_file;
import io.v.nutz.util.ShiroUtil;
import io.v.nutz.wakershome.model.review.CommentBz;
import io.v.nutz.wakershome.model.review.CommentNr;
import io.v.nutz.wakershome.model.review.CommentPeo;
import io.v.nutz.wakershome.model.review.CommentZb;
import io.v.nutz.wakershome.service.review.CommentPeoService;
import io.v.nutz.wakershome.service.review.CommentStatisticsService;
import io.v.nutz.wakershome.service.review.CommentZbService;
import io.v.nutz.web.commons.base.Globals;
import io.v.nutz.web.commons.utils.FileUtil;
import org.apache.commons.io.IOUtils;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.ddr.poi.html.HtmlRenderPolicy;
import org.nutz.boot.starter.ftp.FtpService;
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.Lang;
import org.nutz.lang.random.R;
import org.nutz.lang.util.NutMap;
import org.nutz.mvc.annotation.At;
import org.nutz.mvc.annotation.Ok;
import org.nutz.mvc.annotation.Param;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
/**
* @ClassName statisticsController
* @Description TODO
@@ -32,12 +59,18 @@ import org.nutz.mvc.annotation.Param;
@IocBean
public class StatisticsZpController {
@Inject
private FtpService ftpService;
@Inject
private CommentZbService commentZbService;
@Inject
private CommentPeoService commentPeoService;
@Inject
private CommentStatisticsService commentStatisticsService;
@At("")
@Ok("beetl:/platform/wakeshome/review/statistics.html")
@@ -92,7 +125,6 @@ public class StatisticsZpController {
Sql sql = Sqls.create("""
SELECT
peo.*,
u.username userName,
u.loginname loginName,
unitname unitName
FROM
@@ -142,4 +174,208 @@ public class StatisticsZpController {
}
/**
* 分工会自评导出(单个)
*
* @param zbId
* @param unionId
* @param response
*/
@At
@Ok("void")
@RequiresPermissions("wakeshome.review.statistics")
public void doDownLoadSingleByUnionId(String zbId, String unionId, HttpServletResponse response) {
CommentPeo peo = commentZbService.dao().fetch(CommentPeo.class, Cnd.where("unionId", "=", unionId).and("zbId", "=", zbId));
String fileName = peo.getUnionName() + "(" + peo.getUserName() + ")“模范教工小家”评议结果";
try {
response.addHeader("Content-Type", "application/octet-stream");
response.addHeader("Content-Disposition", "attachment; filename=\"" + new String(fileName.getBytes("UTF-8"), "ISO-8859-1") + "\".docx");
commentStatisticsService.exportWord(peo, response.getOutputStream());
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 分工会下所有测评结果导出(多个)压缩包
* @param zbId
* @param unionId
* @param response
*/
@At
@Ok("void")
@RequiresPermissions("wakeshome.review.statistics")
public void doDownLoadZipByUnionId(String zbId, String unionId, HttpServletResponse response) {
try {
List<CommentPeo> peoList = commentPeoService.dao().query(CommentPeo.class, Cnd.where("unionId", "=", unionId).and("zbId", "=", zbId));
CommentPeo commentPeo = peoList.stream().findFirst().orElse(new CommentPeo());
String zipName = commentPeo.getUnionName() + "评议结果.zip";
response.setContentType("application/octet-stream");
response.setHeader("content-disposition", "attachment;filename=" + URLEncoder.encode(zipName, "UTF-8"));
ZipOutputStream zipOutputStream = new ZipOutputStream(new BufferedOutputStream(response.getOutputStream()));
for (CommentPeo peo : peoList) {
String fileName = peo.getUnionName() + "(" + peo.getUserName() + ")“模范教工小家”评议结果.docx";
zipOutputStream.putNextEntry(new ZipEntry(fileName));
commentStatisticsService.exportWord(peo, zipOutputStream);
zipOutputStream.closeEntry();
response.flushBuffer();
}
zipOutputStream.flush();
zipOutputStream.close();
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 分工会导出附件
* @param zbId
* @param unionId
* @param response
*/
@At
@Ok("void")
@RequiresPermissions("wakeshome.review.statistics")
public void exportFilesByUnionId(String zbId, String unionId, HttpServletResponse response) {
List<CommentPeo> peoList = commentPeoService.dao().query(CommentPeo.class, Cnd.where("unionId", "=", unionId).and("zbId", "=", zbId));
CommentPeo commentPeo = peoList.stream().findFirst().orElse(new CommentPeo());
response.reset();
response.setContentType("application/x-msdownload;charset=utf-8");
String tmpPath = "tmp/" + R.UU32();
File tmpDir = new File(tmpPath + "/附件信息");
tmpDir.mkdirs();
try {
for (CommentPeo peo : peoList) {
String fileName = peo.getUnionName() + "(" + peo.getUserName() + ")";
List<Sys_file> files = peo.getFiles();
File tDir = new File(tmpDir + "/" + fileName);
tDir.mkdirs();
if (Lang.isNotEmpty(files)) {
for (Sys_file file : files) {
if(Lang.isNotEmpty(file)) {
FileOutputStream outputStream = new FileOutputStream(tDir.getPath() + "/" + file.getFilename());
ftpService.download(file.getFilepath(), outputStream);
outputStream.close();
}
}
}
}
String aimsDir = "zipTmp/" + R.UU32();
String aimsName = commentPeo.getUnionName() + "评议信息.zip";
String aimsPath = aimsDir + "/" + aimsName;
FileUtil.compressToZip(tmpDir.getPath(), aimsDir, aimsName);
response.setHeader("content-disposition", "attachment;filename=" + URLEncoder.encode(aimsName, "UTF-8"));
File aimsFile = new File(aimsPath);
FileInputStream inputStream = new FileInputStream(aimsFile);
IOUtils.copy(inputStream, response.getOutputStream());
inputStream.close();
aimsFile.delete();
FileUtil.deleteDir(new File(tmpPath));
FileUtil.deleteDir(new File(aimsDir));
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 个人上传附件导出
*
* @param peoId
* @param response
*/
@At
@Ok("void")
@RequiresPermissions("wakeshome.review.statistics")
public void exportFilesByPeoId(String peoId, HttpServletResponse response) {
CommentPeo peo = commentPeoService.dao().fetch(CommentPeo.class, peoId);
List<Sys_file> files = peo.getFiles();
response.reset();
response.setContentType("application/x-msdownload;charset=utf-8");
String tmpPath = "tmp/" + R.UU32();
File tmpDir = new File(tmpPath + "/个人附件信息");
tmpDir.mkdirs();
try {
for (Sys_file file : files) {
if (Lang.isNotEmpty(files)) {
FileOutputStream out = new FileOutputStream(tmpDir.getPath() + "/" + file.getFilename());
ftpService.download(file.getFilepath(), out);
out.close();
}
}
String aimsDir = "zipTmp/" + R.UU32();
String aimsName = peo.getUnionName() + "(" + peo.getUserName() + ")个人附件信息.zip";
String aimsPath = aimsDir + "/" + aimsName;
FileUtil.compressToZip(tmpDir.getPath(), aimsDir, aimsName);
response.setHeader("content-disposition", "attachment;filename=" + URLEncoder.encode(aimsName, "UTF-8"));
File aimsFile = new File(aimsPath);
FileInputStream inputStream = new FileInputStream(aimsFile);
IOUtils.copy(inputStream, response.getOutputStream());
inputStream.close();
aimsFile.delete();
FileUtil.deleteDir(new File(tmpPath));
FileUtil.deleteDir(new File(aimsDir));
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 个人评议结果导出(得分)
*
* @param peoId
* @param response
*/
@At
@Ok("void")
@RequiresPermissions("wakeshome.review.statistics")
public void exportByPeoId(String peoId, HttpServletResponse response) {
CommentPeo peo = commentPeoService.dao().fetch(CommentPeo.class, peoId);
String fileName = peo.getUnionName() + "(" + peo.getUserName() + ")“模范教工小家”评议结果";
try {
response.addHeader("Content-Type", "application/octet-stream");
response.addHeader("Content-Disposition", "attachment; filename=\"" + new String(fileName.getBytes("UTF-8"), "ISO-8859-1") + "\".docx");
commentStatisticsService.exportWord(peo, response.getOutputStream());
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 导出所有分工会评议结果和附件信息
*
* @param zbId
* @param response
*/
@At
@Ok("void")
@RequiresPermissions("wakeshome.review.statistics")
public void exportAllUnions(String zbId, HttpServletResponse response) {
// List<CommentPeo> peoList = commentPeoService.dao().query(CommentPeo.class, Cnd.where("zbId", "=", zbId));
// Map<String, List<CommentPeo>> collect = peoList.stream().collect(Collectors.groupingBy(CommentPeo::getUnionId));
}
}
@@ -12,6 +12,7 @@ import io.v.nutz.base.utils.Vi;
import io.v.nutz.dao.CndPlus;
import io.v.nutz.modules.models.PageForm;
import io.v.nutz.sys.models.Sys_union;
import io.v.nutz.sys.models.User;
import io.v.nutz.wakershome.model.review.CommentBz;
import io.v.nutz.wakershome.model.review.CommentPeo;
import io.v.nutz.wakershome.model.review.CommentResult;
@@ -148,7 +149,7 @@ public class MWakesHomeReviewController {
@Aop(TransAop.READ_COMMITTED)
public Object doSubmit(WakesHomeVo wakesHomeVo) {
try {
System.out.println(wakesHomeVo);
User user = baseService.dao().fetch(User.class, Cnd.where("id", "=", ShiroUtil.getUser()));
CommentPeo peo = new CommentPeo();
if (Strings.isNotBlank(wakesHomeVo.getEvaluatedPersonId())) {
peo.setEvaluatedPersonId(wakesHomeVo.getEvaluatedPersonId());
@@ -159,7 +160,10 @@ public class MWakesHomeReviewController {
peo.setZbId(wakesHomeVo.getId());
peo.setReviewTime(DateUtil.now());
peo.setFiles(wakesHomeVo.getFiles());
peo.setUserId((String) ShiroUtil.getPrincipalProperty("id"));
peo.setUserId(user.getId());
peo.setUserName(user.getUsername());
peo.setUnionId(user.getUnionid());
peo.setUnionName(user.getUnionname());
if (Strings.isNotBlank(wakesHomeVo.getPresidentOpinions())) {
peo.setPresidentOpinions(wakesHomeVo.getPresidentOpinions());
}
@@ -18,12 +18,25 @@ public class CommentPeo {
@Prev(els = {@EL("uuid()")})
private String id;
@Column
@Comment("测评人")
@ColDefine(type = ColType.VARCHAR, width = 32)
private String userId;
@Column
@Comment("测评人姓名")
@ColDefine(type = ColType.VARCHAR, width = 50)
private String userName;
@Column
@Comment("测评人工会id")
@ColDefine(type = ColType.VARCHAR, width = 32)
private String unionId;
@Column
@Comment("测评人工会名称")
@ColDefine(type = ColType.VARCHAR, width = 50)
private String unionName;
@Column
@Comment("被测评人id")
@@ -1,6 +1,7 @@
package io.v.nutz.wakershome.service.impl.review;
import cn.hutool.core.util.StrUtil;
import cn.wizzer.framework.base.service.BaseService;
import io.v.nutz.service.impl.ViServiceImpl;
import io.v.nutz.wakershome.model.review.CommentNr;
@@ -50,7 +51,7 @@ public class CommentPeoServiceImpl extends ViServiceImpl<CommentPeo> implements
//赋值测评结果
CommentResult result = commentResultMap.get(o.getId());
if (Lang.isNotEmpty(result)){
o.setOptions(result.getRecommendation());
o.setOptions(StrUtil.isNotBlank(result.getRecommendation()) ? result.getRecommendation() : "未填写备注");
o.setResultScore(result.getAssessResult());
}
});
@@ -0,0 +1,94 @@
package io.v.nutz.wakershome.service.impl.review;
import cn.hutool.core.convert.Convert;
import com.deepoove.poi.XWPFTemplate;
import com.deepoove.poi.config.Configure;
import com.deepoove.poi.policy.HackLoopTableRenderPolicy;
import io.v.nutz.base.service.impl.BaseServiceImpl;
import io.v.nutz.wakershome.model.review.CommentBz;
import io.v.nutz.wakershome.model.review.CommentNr;
import io.v.nutz.wakershome.model.review.CommentPeo;
import io.v.nutz.wakershome.model.review.CommentZb;
import io.v.nutz.wakershome.service.review.CommentPeoService;
import io.v.nutz.wakershome.service.review.CommentStatisticsService;
import io.v.nutz.web.commons.base.Globals;
import org.ddr.poi.html.HtmlRenderPolicy;
import org.nutz.dao.Dao;
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.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;
/**
* @version 1.0
* @Author zzr
* @name:CommentStatisticsServiceImpl
* @Date 2024/8/26 9:48
* @注释
*/
@IocBean(args = {"refer:dao"})
public class CommentStatisticsServiceImpl extends BaseServiceImpl<CommentPeo> implements CommentStatisticsService {
public CommentStatisticsServiceImpl(Dao dao) {
super(dao);
}
@Inject
private CommentPeoService commentPeoService;
@Override
public void exportWord(CommentPeo peo, OutputStream outputStream) {
NutMap map = commentPeoService.getBzById(peo.getId());
//最后的导出表
NutMap resultMap = NutMap.NEW();
List<NutMap> list = new ArrayList<>();
resultMap.put("schoolName", Globals.schoolName);
CommentZb khzb = map.getAs("zbxx", CommentZb.class);
List<CommentNr> nrs = khzb.getNrs();
nrs.forEach(v -> {
NutMap nutMap = NutMap.NEW();
List<CommentBz> bzs = v.getBzs();
String nr = bzs.stream().sorted(Comparator.comparing(CommentBz::getContentNumber)).map(item -> {
return item.getContentNumber() + "." + item.getInspection() + "(" + item.getScore() + "分)";
}).collect(Collectors.joining("\n"));
int jf = bzs.stream().mapToInt(item -> Integer.parseInt(item.getScore())).sum();
int zpf = bzs.stream().mapToInt(item -> Integer.parseInt(item.getResultScore())).sum();
CommentBz commentBz = bzs.stream().findFirst().orElse(new CommentBz());
nutMap.put("xh", Convert.numberToChinese(Double.parseDouble(v.getContentNumber()), false));
nutMap.put("zb", v.getContent());
nutMap.put("nr", nr);
nutMap.put("jf", jf);
nutMap.put("zpf", zpf);
nutMap.put("bz", commentBz.getOptions());
list.add(nutMap);
});
HackLoopTableRenderPolicy policy = new HackLoopTableRenderPolicy();
HtmlRenderPolicy htmlRenderPolicy = new HtmlRenderPolicy();
htmlRenderPolicy.getConfig().setShowDefaultTableBorderInTableCell(true);
Configure config = Configure.newBuilder().bind("list", policy)
.bind("list.nr", htmlRenderPolicy).build();
resultMap.put("list", list);
try {
InputStream inputStream = Thread.currentThread().getContextClassLoader().getResourceAsStream("docTemplate/WakesHome.docx");
XWPFTemplate.compile(inputStream, config).render(resultMap, outputStream);
inputStream.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
@@ -4,6 +4,8 @@ import io.v.nutz.service.ViService;
import io.v.nutz.wakershome.model.review.CommentPeo;
import org.nutz.lang.util.NutMap;
import java.io.InputStream;
public interface CommentPeoService extends ViService<CommentPeo> {
/**
@@ -12,4 +14,5 @@ public interface CommentPeoService extends ViService<CommentPeo> {
* @return
*/
NutMap getBzById(String peoId);
}
@@ -0,0 +1,23 @@
package io.v.nutz.wakershome.service.review;
import io.v.nutz.base.service.BaseService;
import io.v.nutz.wakershome.model.review.CommentPeo;
import org.nutz.lang.util.NutMap;
import javax.servlet.http.HttpServletResponse;
import java.io.OutputStream;
/**
* @version 1.0
* @Author zzr
* @name:CommentStatisticsService
* @Date 2024/8/26 9:47
* @注释
*/
public interface CommentStatisticsService extends BaseService<CommentPeo> {
void exportWord(CommentPeo peo, OutputStream outputStream);
}
@@ -8,6 +8,4 @@ public interface CommentZbService extends ViService<CommentZb> {
CommentZb khzb(String zbid);
}
Binary file not shown.
@@ -66,7 +66,7 @@
<el-divider content-position="left">备注</el-divider>
<el-row>
<el-col :span="24">
<el-input type="textarea" :rows="2" maxlength="300" show-word-limit disabled
<el-input type="textarea" :rows="2" maxlength="300" show-word-limit readonly
v-model="nr.bzs[0].options" placeholder="请输入备注"></el-input>
</el-col>
</el-row>
@@ -5,7 +5,6 @@ layout("/layouts/platform.html"){
<guava ref="guava">
<el-card shadow="never">
<div class="search">
<div class="search-item">
<div class="search-item-label">年度:</div>
<div class="search-item-option">
@@ -79,11 +78,13 @@ layout("/layouts/platform.html"){
:prop="column.prop" :width="column.width" min-width="100px">
</el-table-column>
<el-table-column prop="userOnline" align="center" header-align="center" label="操作"
width="200px"
fixed="right">
width="240px" fixed="right">
<template scope="{row}">
<el-button size="mini" @click="openView(row)">查看</el-button>
<el-button v-if="canDownload()" size="mini" type="primary" @click="openView(row)">查看</el-button>
<el-tooltip :content="canDownload ? ('导出【'+ row.unionName +'】管理员自我评议的评议结果') : ('导出【'+ row.unionName +'】下所有评议结果的压缩包') " placement="top">
<el-button v-if="canDownload" size="mini" type="primary" @click="doDownLoad(row,canDownload)">导出</el-button>
</el-tooltip>
<el-button size="mini" type="primary" @click="downloadFilesByUnion(row)">导出附件</el-button>
</template>
</el-table-column>
</el-table>
@@ -97,7 +98,6 @@ layout("/layouts/platform.html"){
<div class="search-item-label">工号/姓名:</div>
<div class="search-item-option">
<el-input placeholder="请输入工号/姓名" v-model="userPageForm.searchKeyword">
<template slot="prepend">姓名/工号</template>
</el-input>
</div>
</div>
@@ -112,36 +112,30 @@ layout("/layouts/platform.html"){
</span>
</el-radio-button>
<el-radio-button label="满意">满意
<span class="ml2">{{reviewResultData.my}}</span>
<span class="ml2">{{reviewResultData.my || 0}}</span>
</el-radio-button>
<el-radio-button label="基本满意">基本满意
<span class="ml2">{{reviewResultData.jbmy}}</span>
<span class="ml2">{{reviewResultData.jbmy || 0}}</span>
</el-radio-button>
<el-radio-button label="不满意">不满意
<span class="ml2">{{reviewResultData.bmy}}</span>
<span class="ml2">{{reviewResultData.bmy || 0}}</span>
</el-radio-button>
</el-radio-group>
</div>
</div>
<div class="search-query">
<el-button type="primary" icon="el-icon-search" @click="doUserSearch">搜索
</el-button>
<el-button type="primary" icon="el-icon-search" @click="doUserSearch">搜索</el-button>
</div>
</div>
</el-card>
<el-card shadow="never" class="mt20">
<el-table :data="userTableData" style="width: 100%" row-key="id"
:size="tableSize"
v-loading="tableLoading" ref="table" class="vi-table">
:size="tableSize" v-loading="tableLoading" ref="table" class="vi-table">
<el-table-column align="center" header-align="center" type="index"
:index="indexMethod" label="序号"
width="80px"></el-table-column>
:index="indexMethod" label="序号" width="80px"></el-table-column>
<el-table-column
align="center"
@@ -151,7 +145,6 @@ layout("/layouts/platform.html"){
:sortable="column.sortable"
:label="column.label"
:prop="column.prop" :width="column.width" min-width="100px">
</el-table-column>
<el-table-column prop="evaluatedPersonName" align="center" show-overflow-tooltip
label="被测评人" v-if="zbData.assessmentMode==2"></el-table-column>
@@ -160,13 +153,11 @@ layout("/layouts/platform.html"){
<el-table-column prop="reviewTime" align="center"
label="测评时间"></el-table-column>
<el-table-column prop="userOnline" align="center" header-align="center"
label="操作"
width="100px"
fixed="right">
label="操作" width="240px" fixed="right">
<template scope="{row}">
<el-button plain size="mini" @click="openUserView(row)">
查看
</el-button>
<el-button plain size="mini" @click="openUserView(row)">查看</el-button>
<el-button plain size="mini" type="primary" @click="downloadByPeoId(row)">导出</el-button>
<el-button plain size="mini" type="primary" @click="downloadFilesByPeoId(row)">导出附件</el-button>
</template>
</el-table-column>
</el-table>
@@ -246,6 +237,24 @@ layout("/layouts/platform.html"){
'wakes-home-review': httpVueLoader('/components/wakeshome/review/ReviewResult.vue?v=' + moment(new Date()).unix()),
},
methods: {
doDownLoad(row,flag){
if (flag) {
// 为true,自我评议
window.open(loc() + '/doDownLoadSingleByUnionId?zbId=' + this.pageForm.zbId + '&unionId=' + row.id)
} else {
// false, 会员评议,导出压缩包
window.open(loc() + '/doDownLoadZipByUnionId?zbId=' + this.pageForm.zbId + '&unionId=' + row.id)
}
},
downloadFilesByUnion(row){
window.open(loc() + '/exportFilesByUnionId?zbId=' + this.pageForm.zbId + '&unionId=' + row.id)
},
downloadByPeoId(row){
window.open(loc() + '/exportByPeoId?peoId=' + row.id)
},
downloadFilesByPeoId(){
window.open(loc() + '/exportFilesByPeoId?peoId=' + row.id)
},
async getReviewResultNum(row) {
const res = await $.post(loc() + "/getReviewResultNum", {
zbId: this.userPageForm.zbId,
@@ -254,8 +263,6 @@ layout("/layouts/platform.html"){
this.reviewResultData = res.data
},
async openUserView(row) {
// const res = await $.post(loc() + "/getBzById", {peoId: row.id})
// this.zpxx = res.data
this.userDrawer = true
this.$nextTick(() => {
this.$refs.wakesHomeReview.findOne(row.id)
@@ -309,6 +316,12 @@ layout("/layouts/platform.html"){
this.doSearch()
},
},
computed: {
canDownload() {
const data = this.zbList.find(v=> v.id === this.pageForm.zbId)
return data.commentTarget===3 && data.unionIds && data.unionIds.length > 0
}
},
async created() {
await this.getZbList()
this.unions = await getUnions(null)