Compare commits
19
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4271924a2f | ||
|
|
9590ad5f8c | ||
|
|
e60d4d6c68 | ||
|
|
53005c448f | ||
|
|
1a688d80d1 | ||
|
|
81fd5cb773 | ||
|
|
efad953710 | ||
|
|
ceec8eb095 | ||
|
|
e0004e410f | ||
|
|
f8457386fd | ||
|
|
c1ac3db4bf | ||
|
|
6c6caa2558 | ||
|
|
16cae3ed2b | ||
|
|
35877f4b5c | ||
|
|
4f85bb08e2 | ||
|
|
001d456513 | ||
|
|
65f340e3b0 | ||
|
|
2a305a3f23 | ||
|
|
29260423d5 |
@@ -19,6 +19,7 @@ RoleConstant {
|
|||||||
SCHOOL_UNION_ADMIN("校工会管理员"),
|
SCHOOL_UNION_ADMIN("校工会管理员"),
|
||||||
SCHOOL_UNION_CHAIRMAN("校工会主席"),
|
SCHOOL_UNION_CHAIRMAN("校工会主席"),
|
||||||
SCHOOL_UNION_VICE_CHAIRMAN("校工会副主席"),
|
SCHOOL_UNION_VICE_CHAIRMAN("校工会副主席"),
|
||||||
|
SCHOOL_UNION_FINANCE("校工会财务"),
|
||||||
SCHOOL_OFFICE_DIRECTOR("校工会办公室主任"),
|
SCHOOL_OFFICE_DIRECTOR("校工会办公室主任"),
|
||||||
SCHOOL_UNION_WELFARE_ADMIN("校工会福利管理员"),
|
SCHOOL_UNION_WELFARE_ADMIN("校工会福利管理员"),
|
||||||
SCHOOL_UNION_MEMBER_ADMIN("校工会会员管理员"),
|
SCHOOL_UNION_MEMBER_ADMIN("校工会会员管理员"),
|
||||||
|
|||||||
@@ -1,10 +1,16 @@
|
|||||||
package com.budwk.app.base.utils;
|
package com.budwk.app.base.utils;
|
||||||
|
|
||||||
import cn.hutool.core.io.FileUtil;
|
import cn.hutool.core.io.FileUtil;
|
||||||
|
import com.aspose.cells.FontConfigs;
|
||||||
import com.aspose.cells.PdfSaveOptions;
|
import com.aspose.cells.PdfSaveOptions;
|
||||||
import com.aspose.cells.Workbook;
|
import com.aspose.cells.Workbook;
|
||||||
|
import com.aspose.slides.FontsLoader;
|
||||||
|
import com.aspose.slides.LoadOptions;
|
||||||
import com.aspose.slides.Presentation;
|
import com.aspose.slides.Presentation;
|
||||||
import com.aspose.words.Document;
|
import com.aspose.words.Document;
|
||||||
|
import com.aspose.words.FontSettings;
|
||||||
|
import com.aspose.words.FontSourceBase;
|
||||||
|
import com.aspose.words.MemoryFontSource;
|
||||||
import com.aspose.words.SaveFormat;
|
import com.aspose.words.SaveFormat;
|
||||||
import com.budwk.app.base.exception.BaseException;
|
import com.budwk.app.base.exception.BaseException;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
@@ -12,6 +18,8 @@ import lombok.extern.slf4j.Slf4j;
|
|||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileOutputStream;
|
import java.io.FileOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.util.Arrays;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 文档转换
|
* 文档转换
|
||||||
@@ -19,6 +27,81 @@ import java.io.IOException;
|
|||||||
@Slf4j
|
@Slf4j
|
||||||
public class OfficePlusUtil {
|
public class OfficePlusUtil {
|
||||||
|
|
||||||
|
private static final String DEFAULT_FONT_NAME = "Noto Sans SC";
|
||||||
|
private static final String DEFAULT_FONT_RESOURCE = "/fonts/NotoSansSC-VF.ttf";
|
||||||
|
private static final Object FONT_CONFIG_LOCK = new Object();
|
||||||
|
private static volatile boolean fontConfigured;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 注册系统内置字体,并将其作为 Office 文档缺失字体或缺失字形时的默认回退字体。
|
||||||
|
* 原文档字体在服务器可用时仍优先使用,只有找不到原字体时才使用内置字体。
|
||||||
|
*/
|
||||||
|
private static void configureDefaultFont() {
|
||||||
|
if (fontConfigured) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
synchronized (FONT_CONFIG_LOCK) {
|
||||||
|
if (fontConfigured) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
byte[] fontData = loadDefaultFontData();
|
||||||
|
configureWordFont(fontData);
|
||||||
|
configureExcelFont(fontData);
|
||||||
|
FontsLoader.loadExternalFont(fontData);
|
||||||
|
fontConfigured = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 从 classpath 读取随应用打包的字体,避免依赖线上服务器安装字体。
|
||||||
|
*
|
||||||
|
* @return 默认字体的二进制数据
|
||||||
|
*/
|
||||||
|
private static byte[] loadDefaultFontData() {
|
||||||
|
try (InputStream inputStream = OfficePlusUtil.class.getResourceAsStream(DEFAULT_FONT_RESOURCE)) {
|
||||||
|
if (inputStream == null) {
|
||||||
|
throw new BaseException("系统内置默认字体不存在");
|
||||||
|
}
|
||||||
|
return inputStream.readAllBytes();
|
||||||
|
} catch (IOException e) {
|
||||||
|
log.error("读取系统内置默认字体失败", e);
|
||||||
|
throw new BaseException("读取系统内置默认字体失败");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 为 Word 转换保留已有字体源并追加内置字体,同时配置缺失字体和缺失字形回退。
|
||||||
|
*
|
||||||
|
* @param fontData 默认字体的二进制数据
|
||||||
|
*/
|
||||||
|
private static void configureWordFont(byte[] fontData) {
|
||||||
|
FontSettings fontSettings = FontSettings.getDefaultInstance();
|
||||||
|
FontSourceBase[] currentSources = fontSettings.getFontsSources();
|
||||||
|
FontSourceBase[] fontSources = Arrays.copyOf(currentSources, currentSources.length + 1);
|
||||||
|
fontSources[currentSources.length] = new MemoryFontSource(fontData);
|
||||||
|
fontSettings.setFontsSources(fontSources);
|
||||||
|
fontSettings.getSubstitutionSettings().getDefaultFontSubstitution().setDefaultFontName(DEFAULT_FONT_NAME);
|
||||||
|
try {
|
||||||
|
fontSettings.getFallbackSettings().loadNotoFallbackSettings();
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("配置 Word 默认字体回退规则失败", e);
|
||||||
|
throw new BaseException("配置 Word 默认字体失败");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 为 Excel 转换追加内置字体,并将其设置为找不到原字体时的默认字体。
|
||||||
|
*
|
||||||
|
* @param fontData 默认字体的二进制数据
|
||||||
|
*/
|
||||||
|
private static void configureExcelFont(byte[] fontData) {
|
||||||
|
com.aspose.cells.FontSourceBase[] currentSources = FontConfigs.getFontSources();
|
||||||
|
com.aspose.cells.FontSourceBase[] fontSources = Arrays.copyOf(currentSources, currentSources.length + 1);
|
||||||
|
fontSources[currentSources.length] = new com.aspose.cells.MemoryFontSource(fontData);
|
||||||
|
FontConfigs.setFontSources(fontSources);
|
||||||
|
FontConfigs.setDefaultFontName(DEFAULT_FONT_NAME);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 转换
|
* 转换
|
||||||
*
|
*
|
||||||
@@ -47,7 +130,11 @@ public class OfficePlusUtil {
|
|||||||
public static void presentationConvertPdf(String sourcePath, String targetPath) {
|
public static void presentationConvertPdf(String sourcePath, String targetPath) {
|
||||||
Presentation presentation = null;
|
Presentation presentation = null;
|
||||||
try {
|
try {
|
||||||
presentation = new Presentation(sourcePath);
|
configureDefaultFont();
|
||||||
|
LoadOptions loadOptions = new LoadOptions();
|
||||||
|
loadOptions.setDefaultRegularFont(DEFAULT_FONT_NAME);
|
||||||
|
loadOptions.setDefaultAsianFont(DEFAULT_FONT_NAME);
|
||||||
|
presentation = new Presentation(sourcePath, loadOptions);
|
||||||
presentation.save(targetPath, com.aspose.slides.SaveFormat.Pdf);
|
presentation.save(targetPath, com.aspose.slides.SaveFormat.Pdf);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
log.info("转换pdf报错", e);
|
log.info("转换pdf报错", e);
|
||||||
@@ -68,10 +155,12 @@ public class OfficePlusUtil {
|
|||||||
public static void excelConvertPdf(String sourcePath, String targetPath) {
|
public static void excelConvertPdf(String sourcePath, String targetPath) {
|
||||||
FileOutputStream fileOS = null;
|
FileOutputStream fileOS = null;
|
||||||
try {
|
try {
|
||||||
|
configureDefaultFont();
|
||||||
Workbook wb = new Workbook(sourcePath);
|
Workbook wb = new Workbook(sourcePath);
|
||||||
fileOS = new FileOutputStream(targetPath);
|
fileOS = new FileOutputStream(targetPath);
|
||||||
PdfSaveOptions pdfSaveOptions = new PdfSaveOptions();
|
PdfSaveOptions pdfSaveOptions = new PdfSaveOptions();
|
||||||
pdfSaveOptions.setOnePagePerSheet(true);
|
pdfSaveOptions.setOnePagePerSheet(true);
|
||||||
|
pdfSaveOptions.setDefaultFont(DEFAULT_FONT_NAME);
|
||||||
// for (int i = 0; i < 3; i++) {
|
// for (int i = 0; i < 3; i++) {
|
||||||
// wb.getWorksheets().get(i).getHorizontalPageBreaks().clear();
|
// wb.getWorksheets().get(i).getHorizontalPageBreaks().clear();
|
||||||
// wb.getWorksheets().get(i).getVerticalPageBreaks().clear();
|
// wb.getWorksheets().get(i).getVerticalPageBreaks().clear();
|
||||||
@@ -105,6 +194,7 @@ public class OfficePlusUtil {
|
|||||||
public static void wordConvertPdf(String sourcePath, String targetPath) {
|
public static void wordConvertPdf(String sourcePath, String targetPath) {
|
||||||
FileOutputStream os = null;
|
FileOutputStream os = null;
|
||||||
try {
|
try {
|
||||||
|
configureDefaultFont();
|
||||||
File file = new File(targetPath);
|
File file = new File(targetPath);
|
||||||
os = new FileOutputStream(file);
|
os = new FileOutputStream(file);
|
||||||
Document doc = new Document(sourcePath);
|
Document doc = new Document(sourcePath);
|
||||||
|
|||||||
@@ -6,6 +6,8 @@ import com.budwk.app.base.exception.BaseException;
|
|||||||
import com.budwk.app.sys.models.Sys_file;
|
import com.budwk.app.sys.models.Sys_file;
|
||||||
import com.budwk.app.sys.models.Sys_office_template;
|
import com.budwk.app.sys.models.Sys_office_template;
|
||||||
import com.budwk.app.sys.utils.SysFileMinIoUtil;
|
import com.budwk.app.sys.utils.SysFileMinIoUtil;
|
||||||
|
import com.deepoove.poi.XWPFTemplate;
|
||||||
|
import com.deepoove.poi.config.Configure;
|
||||||
import com.deepoove.poi.data.ByteArrayPictureRenderData;
|
import com.deepoove.poi.data.ByteArrayPictureRenderData;
|
||||||
import com.deepoove.poi.data.PictureRenderData;
|
import com.deepoove.poi.data.PictureRenderData;
|
||||||
import com.deepoove.poi.data.PictureType;
|
import com.deepoove.poi.data.PictureType;
|
||||||
@@ -18,6 +20,12 @@ import org.nutz.ioc.loader.annotation.IocBean;
|
|||||||
|
|
||||||
import java.io.ByteArrayInputStream;
|
import java.io.ByteArrayInputStream;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
|
import java.io.ByteArrayOutputStream;
|
||||||
|
import java.io.File;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.LinkedHashSet;
|
||||||
|
import java.util.Set;
|
||||||
import java.util.regex.Matcher;
|
import java.util.regex.Matcher;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
@@ -66,6 +74,88 @@ public class SysOfficeTemplateUtil {
|
|||||||
return new ByteArrayInputStream(fileBytes);
|
return new ByteArrayInputStream(fileBytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 统一渲染 DOC/DOCX 模板,保留调用方的循环表格等策略;模板输入流由调用方关闭。
|
||||||
|
*/
|
||||||
|
public byte[] renderTemplate(InputStream input, Object data, Configure config, boolean pdf, String context) throws Exception {
|
||||||
|
if (input == null) throw new BaseException("模板文件不存在");
|
||||||
|
byte[] templateBytes = input.readAllBytes();
|
||||||
|
try (ByteArrayInputStream formatInput = new ByteArrayInputStream(templateBytes)) {
|
||||||
|
if (com.aspose.words.FileFormatUtil.detectFileFormat(formatInput).getLoadFormat() != com.aspose.words.LoadFormat.DOCX) {
|
||||||
|
try (ByteArrayInputStream source = new ByteArrayInputStream(templateBytes);
|
||||||
|
ByteArrayOutputStream converted = new ByteArrayOutputStream()) {
|
||||||
|
new com.aspose.words.Document(source).save(converted, com.aspose.words.SaveFormat.DOCX);
|
||||||
|
templateBytes = converted.toByteArray();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
byte[] wordBytes;
|
||||||
|
try (ByteArrayInputStream templateInput = new ByteArrayInputStream(templateBytes);
|
||||||
|
ByteArrayOutputStream output = new ByteArrayOutputStream();
|
||||||
|
XWPFTemplate template = XWPFTemplate.compile(templateInput, config == null ? Configure.builder().build() : config)) {
|
||||||
|
template.render(data).write(output);
|
||||||
|
wordBytes = output.toByteArray();
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("[Office模板渲染] Word模板渲染失败,context={}", context, e);
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
log.info("[Office模板渲染] Word渲染完成,context={}, templateBytes={}, outputBytes={}", context, templateBytes.length, wordBytes.length);
|
||||||
|
if (!pdf) return wordBytes;
|
||||||
|
try (ByteArrayInputStream wordInput = new ByteArrayInputStream(wordBytes);
|
||||||
|
ByteArrayOutputStream output = new ByteArrayOutputStream()) {
|
||||||
|
com.aspose.words.Document document = new com.aspose.words.Document(wordInput);
|
||||||
|
configureDocumentFonts(document, context);
|
||||||
|
com.aspose.words.PdfSaveOptions options = new com.aspose.words.PdfSaveOptions();
|
||||||
|
options.setFontEmbeddingMode(com.aspose.words.PdfFontEmbeddingMode.EMBED_ALL);
|
||||||
|
document.save(output, options);
|
||||||
|
log.info("[Office模板渲染] PDF转换完成,context={}, outputBytes={}", context, output.size());
|
||||||
|
return output.toByteArray();
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("[Office模板渲染] PDF转换失败,context={}", context, e);
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void configureDocumentFonts(com.aspose.words.Document document, String context) throws Exception {
|
||||||
|
com.aspose.words.FontSettings settings = new com.aspose.words.FontSettings();
|
||||||
|
List<com.aspose.words.FontSourceBase> sources = new ArrayList<>(List.of(settings.getFontsSources()));
|
||||||
|
Set<String> folders = new LinkedHashSet<>();
|
||||||
|
String windowsDir = System.getenv("WINDIR");
|
||||||
|
if (StrUtil.isNotBlank(windowsDir)) folders.add(new File(windowsDir, "Fonts").getPath());
|
||||||
|
String localAppData = System.getenv("LOCALAPPDATA");
|
||||||
|
if (StrUtil.isNotBlank(localAppData)) folders.add(new File(localAppData, "Microsoft/Windows/Fonts").getPath());
|
||||||
|
folders.add(new File(System.getProperty("user.dir"), "fonts").getPath());
|
||||||
|
for (String folder : folders) {
|
||||||
|
File directory = new File(folder);
|
||||||
|
log.info("[Office模板渲染] 字体目录,context={}, path={}, readable={}", context, folder, directory.isDirectory() && directory.canRead());
|
||||||
|
if (directory.isDirectory() && directory.canRead()) sources.add(new com.aspose.words.FolderFontSource(folder, true));
|
||||||
|
}
|
||||||
|
settings.setFontsSources(sources.toArray(new com.aspose.words.FontSourceBase[0]));
|
||||||
|
Set<String> availableFonts = new LinkedHashSet<>();
|
||||||
|
for (com.aspose.words.FontSourceBase source : sources) {
|
||||||
|
for (com.aspose.words.PhysicalFontInfo font : source.getAvailableFonts()) availableFonts.add(font.getFontFamilyName());
|
||||||
|
}
|
||||||
|
String chineseFont = null;
|
||||||
|
for (String candidate : List.of("SimSun", "宋体", "Microsoft YaHei", "微软雅黑", "DengXian", "等线", "SimHei", "黑体", "FangSong", "仿宋", "Noto Serif CJK SC", "Noto Sans CJK SC")) {
|
||||||
|
if (availableFonts.contains(candidate)) {
|
||||||
|
chineseFont = candidate;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
log.info("[Office模板渲染] 中文字体选择,context={}, fontCount={}, chineseFont={}", context, availableFonts.size(), chineseFont);
|
||||||
|
if (chineseFont != null) {
|
||||||
|
settings.getSubstitutionSettings().getDefaultFontSubstitution().setDefaultFontName(chineseFont);
|
||||||
|
for (String name : List.of("宋体", "SimSun", "新宋体", "NSimSun", "黑体", "SimHei", "仿宋", "FangSong", "楷体", "KaiTi", "微软雅黑", "Microsoft YaHei")) {
|
||||||
|
if (!availableFonts.contains(name)) settings.getSubstitutionSettings().getTableSubstitution().setSubstitutes(name, chineseFont);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
log.warn("[Office模板渲染] 未发现常用中文字体,context={}, availableFonts={}", context, availableFonts);
|
||||||
|
}
|
||||||
|
settings.getFallbackSettings().loadMsOfficeFallbackSettings();
|
||||||
|
document.setFontSettings(settings);
|
||||||
|
document.setWarningCallback(warning -> log.warn("[Office模板渲染] 字体或排版警告,context={}, type={}, detail={}", context, warning.getWarningType(), warning.getDescription()));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 签字url转换为poi的图片对象
|
* 签字url转换为poi的图片对象
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -41,6 +41,11 @@ public class FlowRecipientUnitSchoolLeaderHandler implements AssignmentHandler {
|
|||||||
throw new BaseException("未找到申请记录。");
|
throw new BaseException("未找到申请记录。");
|
||||||
}
|
}
|
||||||
unitId = condolence.getHelpUnitId();
|
unitId = condolence.getHelpUnitId();
|
||||||
|
} else if ("TSWW".equals(processName)) {
|
||||||
|
com.budwk.app.zhgh.staffbenefit.specialcondolence.model.SpecialCondolence info = dao.fetch(
|
||||||
|
com.budwk.app.zhgh.staffbenefit.specialcondolence.model.SpecialCondolence.class, businessNo);
|
||||||
|
if (info == null) throw new BaseException("未找到申请记录。");
|
||||||
|
unitId = info.getHelpUnitId();
|
||||||
} else {
|
} else {
|
||||||
throw new BaseException("当前流程不支持获取受助人所在单位分管校领导。");
|
throw new BaseException("当前流程不支持获取受助人所在单位分管校领导。");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,54 @@
|
|||||||
|
package com.budwk.app.flow.handler;
|
||||||
|
|
||||||
|
import com.budwk.app.base.constant.RoleConstant;
|
||||||
|
import com.budwk.app.flow.engine.AssignmentHandler;
|
||||||
|
import com.budwk.app.flow.engine.core.Execution;
|
||||||
|
import com.budwk.app.flow.engine.core.ServiceContext;
|
||||||
|
import com.budwk.app.flow.engine.model.TaskModel;
|
||||||
|
import org.nutz.dao.Dao;
|
||||||
|
import org.nutz.dao.Sqls;
|
||||||
|
import org.nutz.dao.sql.Sql;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 为流程任务分配拥有校工会财务角色的用户。
|
||||||
|
*/
|
||||||
|
public class FlowSchoolUnionFinanceHandler implements AssignmentHandler {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 按校工会财务角色查询参与者,并去除重复的用户 ID。
|
||||||
|
*
|
||||||
|
* @param model 当前流程任务模型,无需额外传入人员参数
|
||||||
|
* @param execution 当前流程执行上下文,无需额外传入业务参数
|
||||||
|
* @return 用户 ID 列表;未配置角色或角色用户时返回空列表
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public List<String> assign(TaskModel model, Execution execution) {
|
||||||
|
Dao dao = ServiceContext.find(Dao.class);
|
||||||
|
Sql sql = Sqls.create("""
|
||||||
|
SELECT
|
||||||
|
userRole.userId
|
||||||
|
FROM
|
||||||
|
`sys_user_role` userRole
|
||||||
|
LEFT JOIN sys_role role ON role.id = userRole.roleId
|
||||||
|
WHERE
|
||||||
|
role.`code` = @roleCode
|
||||||
|
GROUP BY
|
||||||
|
userRole.userId
|
||||||
|
""").setParam("roleCode", RoleConstant.SCHOOL_UNION_FINANCE.name());
|
||||||
|
sql.setCallback(Sqls.callback.strList());
|
||||||
|
dao.execute(sql);
|
||||||
|
return sql.getList(String.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 返回流程设计器中展示的参与者处理类名称。
|
||||||
|
*
|
||||||
|
* @return 流程设计器下拉选项名称
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public String getMessage() {
|
||||||
|
return "获取校工会财务";
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -57,6 +57,8 @@ public class SysV4ServController {
|
|||||||
$condition
|
$condition
|
||||||
""");
|
""");
|
||||||
Cnd cnd = Cnd.NEW();
|
Cnd cnd = Cnd.NEW();
|
||||||
|
// 先取每个流程的最新定义,再判断是否启用,避免最新版本停用后回退展示旧版本。
|
||||||
|
cnd.and("t.state", "=", 1);
|
||||||
if (StrUtil.isNotBlank(keyword)) {
|
if (StrUtil.isNotBlank(keyword)) {
|
||||||
cnd.where().andLike("t.disPlayName", keyword);
|
cnd.where().andLike("t.disPlayName", keyword);
|
||||||
}
|
}
|
||||||
|
|||||||
+21
@@ -620,6 +620,27 @@ public class ActivitySportsApplyUserServiceImpl extends BaseServiceImpl<Activity
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 以系统人员档案为准校验男女分组,不能用 Excel 性别绕过限制;校验失败时保留已有报名。
|
||||||
|
Integer isMenWomen = activityEvent.getIsMenWomen();
|
||||||
|
if (Integer.valueOf(1).equals(isMenWomen) || Integer.valueOf(2).equals(isMenWomen)) {
|
||||||
|
String sex = normalizeText(sysUser.getSex());
|
||||||
|
boolean male = "男".equals(sex) || "男性".equals(sex);
|
||||||
|
boolean female = "女".equals(sex) || "女性".equals(sex);
|
||||||
|
String errorMessage = null;
|
||||||
|
if (!male && !female) {
|
||||||
|
errorMessage = "系统人员档案性别为空或无法识别,请维护后重新导入";
|
||||||
|
} else if (Integer.valueOf(1).equals(isMenWomen) && !male) {
|
||||||
|
errorMessage = "该项目为男子组,系统人员档案性别为女,不能报名";
|
||||||
|
} else if (Integer.valueOf(2).equals(isMenWomen) && !female) {
|
||||||
|
errorMessage = "该项目为女子组,系统人员档案性别为男,不能报名";
|
||||||
|
}
|
||||||
|
if (errorMessage != null) {
|
||||||
|
importTemp.setNotes(errorMessage);
|
||||||
|
errorList.add(importTemp);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
activitySchoolApply.setEventId(schoolEvent.getEventId());
|
activitySchoolApply.setEventId(schoolEvent.getEventId());
|
||||||
activitySchoolApply.setAwardsMode(activityEvent.getProjectType());
|
activitySchoolApply.setAwardsMode(activityEvent.getProjectType());
|
||||||
if ("2".equals(activityEvent.getProjectType())) {
|
if ("2".equals(activityEvent.getProjectType())) {
|
||||||
|
|||||||
+94
-21
@@ -4,12 +4,14 @@ package com.budwk.app.zhgh.activity.sports.service.impl;
|
|||||||
import cn.afterturn.easypoi.excel.ExcelExportUtil;
|
import cn.afterturn.easypoi.excel.ExcelExportUtil;
|
||||||
import cn.afterturn.easypoi.excel.entity.ExportParams;
|
import cn.afterturn.easypoi.excel.entity.ExportParams;
|
||||||
import cn.afterturn.easypoi.excel.entity.enmus.ExcelType;
|
import cn.afterturn.easypoi.excel.entity.enmus.ExcelType;
|
||||||
|
import com.budwk.app.base.exception.BaseException;
|
||||||
import com.budwk.app.base.service.impl.BaseServiceImpl;
|
import com.budwk.app.base.service.impl.BaseServiceImpl;
|
||||||
import com.budwk.app.base.utils.CommonDownloadUtil;
|
import com.budwk.app.base.utils.CommonDownloadUtil;
|
||||||
import com.budwk.app.base.utils.DateUtil;
|
import com.budwk.app.base.utils.DateUtil;
|
||||||
import com.budwk.app.sys.models.Sys_home_activity;
|
import com.budwk.app.sys.models.Sys_home_activity;
|
||||||
import com.budwk.app.sys.models.Sys_home_template;
|
import com.budwk.app.sys.models.Sys_home_template;
|
||||||
import com.budwk.app.web.commons.auth.utils.SecurityUtil;
|
import com.budwk.app.web.commons.auth.utils.SecurityUtil;
|
||||||
|
import com.budwk.app.zhgh.activity.basic.models.ActivityEvent;
|
||||||
import com.budwk.app.zhgh.activity.basic.models.ActivityBasicUnit;
|
import com.budwk.app.zhgh.activity.basic.models.ActivityBasicUnit;
|
||||||
import com.budwk.app.zhgh.activity.basic.models.ActivityBasicUnion;
|
import com.budwk.app.zhgh.activity.basic.models.ActivityBasicUnion;
|
||||||
import com.budwk.app.zhgh.activity.culture.models.ActivityTissue;
|
import com.budwk.app.zhgh.activity.culture.models.ActivityTissue;
|
||||||
@@ -28,6 +30,7 @@ import org.nutz.dao.entity.Record;
|
|||||||
import org.nutz.dao.sql.Sql;
|
import org.nutz.dao.sql.Sql;
|
||||||
import org.nutz.ioc.aop.Aop;
|
import org.nutz.ioc.aop.Aop;
|
||||||
import org.nutz.ioc.loader.annotation.IocBean;
|
import org.nutz.ioc.loader.annotation.IocBean;
|
||||||
|
import org.nutz.json.Json;
|
||||||
import org.nutz.lang.Lang;
|
import org.nutz.lang.Lang;
|
||||||
import org.nutz.lang.Strings;
|
import org.nutz.lang.Strings;
|
||||||
|
|
||||||
@@ -55,6 +58,7 @@ public class ActivitySportsServiceImpl extends BaseServiceImpl<ActivitySchool> i
|
|||||||
@Override
|
@Override
|
||||||
@Aop(TransAop.READ_COMMITTED)
|
@Aop(TransAop.READ_COMMITTED)
|
||||||
public String doAdd(ActivitySchool activitySchool, ActivitySchoolEvent[] events) {
|
public String doAdd(ActivitySchool activitySchool, ActivitySchoolEvent[] events) {
|
||||||
|
events = validateAndApplySingleEventLimits(events);
|
||||||
ActivityBasicUnit activityBasicUnit = dao().fetch(ActivityBasicUnit.class, Cnd.where("id", "=", SecurityUtil.getUserId()));
|
ActivityBasicUnit activityBasicUnit = dao().fetch(ActivityBasicUnit.class, Cnd.where("id", "=", SecurityUtil.getUserId()));
|
||||||
|
|
||||||
if (activitySchool.getActivityLevel() == 40002) {
|
if (activitySchool.getActivityLevel() == 40002) {
|
||||||
@@ -101,6 +105,7 @@ public class ActivitySportsServiceImpl extends BaseServiceImpl<ActivitySchool> i
|
|||||||
@Override
|
@Override
|
||||||
@Aop(TransAop.READ_COMMITTED)
|
@Aop(TransAop.READ_COMMITTED)
|
||||||
public void doEdit(ActivitySchool activitySchool, ActivitySchoolEvent[] events) {
|
public void doEdit(ActivitySchool activitySchool, ActivitySchoolEvent[] events) {
|
||||||
|
events = validateAndApplySingleEventLimits(events);
|
||||||
ActivitySchool school = dao().fetch(ActivitySchool.class, activitySchool.getId());
|
ActivitySchool school = dao().fetch(ActivitySchool.class, activitySchool.getId());
|
||||||
if (school.getActivityLevel() == 40002) {
|
if (school.getActivityLevel() == 40002) {
|
||||||
school.setBelongUnionId(SecurityUtil.getUnionId());
|
school.setBelongUnionId(SecurityUtil.getUnionId());
|
||||||
@@ -161,6 +166,56 @@ public class ActivitySportsServiceImpl extends BaseServiceImpl<ActivitySchool> i
|
|||||||
dao().insertOrUpdate(sysHomeActivity);
|
dao().insertOrUpdate(sysHomeActivity);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 校验单项人数限制,并在具体单项未设置限制时应用“所有单项”的默认值。
|
||||||
|
*
|
||||||
|
* @param events 页面提交的项目配置,允许包含 eventId 为 allItems 的默认配置
|
||||||
|
* @return 已移除 allItems 临时配置、可直接持久化的项目配置数组
|
||||||
|
*/
|
||||||
|
private ActivitySchoolEvent[] validateAndApplySingleEventLimits(ActivitySchoolEvent[] events) {
|
||||||
|
if (events == null || events.length == 0) {
|
||||||
|
return new ActivitySchoolEvent[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
ActivitySchoolEvent allItems = Arrays.stream(events)
|
||||||
|
.filter(event -> event != null && "allItems".equals(event.getEventId()))
|
||||||
|
.findFirst()
|
||||||
|
.orElse(null);
|
||||||
|
List<ActivitySchoolEvent> result = new ArrayList<>();
|
||||||
|
for (ActivitySchoolEvent event : events) {
|
||||||
|
if (event == null || "allItems".equals(event.getEventId())) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
ActivityEvent activityEvent = dao().fetch(ActivityEvent.class, event.getEventId());
|
||||||
|
if (activityEvent != null && "1".equals(activityEvent.getProjectType())) {
|
||||||
|
applySingleEventDefaultLimit(event, allItems);
|
||||||
|
}
|
||||||
|
result.add(event);
|
||||||
|
}
|
||||||
|
return result.toArray(new ActivitySchoolEvent[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 单项的两个限制必须同时设置;均未设置或均为0时继承“所有单项”的对应值。
|
||||||
|
*/
|
||||||
|
private void applySingleEventDefaultLimit(ActivitySchoolEvent event, ActivitySchoolEvent allItems) {
|
||||||
|
Integer athletesMaxNum = event.getAthletesMaxNum();
|
||||||
|
Integer restrictRegNumber = event.getRestrictRegNumber();
|
||||||
|
if ((athletesMaxNum == null) != (restrictRegNumber == null)) {
|
||||||
|
throw new BaseException("每队(项)运动员最多人数和每人限报项目必须同时设置");
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean useDefault = athletesMaxNum == null || (athletesMaxNum == 0 && restrictRegNumber == 0);
|
||||||
|
if (!useDefault) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (allItems == null || allItems.getAthletesMaxNum() == null || allItems.getRestrictRegNumber() == null) {
|
||||||
|
throw new BaseException("请先设置所有单项的运动员最多人数和每人限报项目");
|
||||||
|
}
|
||||||
|
event.setAthletesMaxNum(allItems.getAthletesMaxNum());
|
||||||
|
event.setRestrictRegNumber(allItems.getRestrictRegNumber());
|
||||||
|
}
|
||||||
|
|
||||||
@Aop(TransAop.READ_COMMITTED)
|
@Aop(TransAop.READ_COMMITTED)
|
||||||
private void addTeam(String schoolId, ActivitySchoolEvent[] events) {
|
private void addTeam(String schoolId, ActivitySchoolEvent[] events) {
|
||||||
if (events.length > 0) {
|
if (events.length > 0) {
|
||||||
@@ -271,33 +326,19 @@ public class ActivitySportsServiceImpl extends BaseServiceImpl<ActivitySchool> i
|
|||||||
WHERE
|
WHERE
|
||||||
app.activityId = @id
|
app.activityId = @id
|
||||||
and app.status = 2
|
and app.status = 2
|
||||||
$cnd
|
and (@filterUnion = 0 or app.activityUnionId = @unionId)
|
||||||
ORDER BY
|
ORDER BY
|
||||||
ev.allName DESC,
|
ev.allName DESC,
|
||||||
u.unionname DESC,
|
u.unionname DESC,
|
||||||
app.`team` asc
|
app.`team` asc
|
||||||
""").setParam("id", id)
|
""").setParam("id", id);
|
||||||
.setVar("cnd", "");
|
// 参数必须声明在原始SQL中;setVar追加的字符串不会再次解析其中的@参数。
|
||||||
if (Strings.isNotBlank(unionId)) {
|
// 未选择分工会时导出整个活动,选择时按报名记录中的活动分工会过滤。
|
||||||
sql.setVar("cnd", "and u.unionid = @unionId");
|
sql.setParam("filterUnion", Strings.isNotBlank(unionId) ? 1 : 0);
|
||||||
sql.setParam("unionId", unionId);
|
sql.setParam("unionId", Strings.isNotBlank(unionId) ? unionId : "");
|
||||||
}
|
|
||||||
List<Record> list = list(sql);
|
List<Record> list = list(sql);
|
||||||
String activityName;
|
|
||||||
if (Lang.isNotEmpty(list)) {
|
|
||||||
activityName = list.get(0).getString("activityName");
|
|
||||||
} else {
|
|
||||||
activityName = "暂无人员";
|
|
||||||
}
|
|
||||||
|
|
||||||
List<ActivitySchoolApply> excels = new ArrayList<>();
|
List<ActivitySchoolApply> excels = new ArrayList<>();
|
||||||
|
list.forEach(record -> excels.add(toActivitySchoolApplyExport(record)));
|
||||||
list.forEach(z -> {
|
|
||||||
ActivitySchoolApply schoolApply = z.toPojo(ActivitySchoolApply.class);
|
|
||||||
String s = schoolApply.getIdentity().stream().map(personType::getName).toList().toString();
|
|
||||||
schoolApply.setSf(s);
|
|
||||||
excels.add(schoolApply);
|
|
||||||
});
|
|
||||||
|
|
||||||
ExportParams exportParams = new ExportParams();
|
ExportParams exportParams = new ExportParams();
|
||||||
exportParams.setType(ExcelType.XSSF);
|
exportParams.setType(ExcelType.XSSF);
|
||||||
@@ -305,10 +346,42 @@ public class ActivitySportsServiceImpl extends BaseServiceImpl<ActivitySchool> i
|
|||||||
CommonDownloadUtil.download(getUnionApplyExportFileName(unionId), workbook, response);
|
CommonDownloadUtil.download(getUnionApplyExportFileName(unionId), workbook, response);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
|
throw new BaseException("导出报名信息失败:" + e.getMessage());
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 将原生SQL查询结果转换为报名信息导出对象。
|
||||||
|
* identity 是数据库JSON文本,需要显式转换为身份编码集合,避免 Record.toPojo 自动转换失败导致整表无数据。
|
||||||
|
*
|
||||||
|
* @param record 导出SQL返回的一行报名数据
|
||||||
|
* @return EasyPoi 使用的 ActivitySchoolApply 导出对象
|
||||||
|
*/
|
||||||
|
private ActivitySchoolApply toActivitySchoolApplyExport(Record record) {
|
||||||
|
ActivitySchoolApply schoolApply = new ActivitySchoolApply();
|
||||||
|
schoolApply.setUnionname(record.getString("unionname"));
|
||||||
|
schoolApply.setTeam(record.getString("team"));
|
||||||
|
schoolApply.setAllName(record.getString("allName"));
|
||||||
|
schoolApply.setLoginname(record.getString("loginname"));
|
||||||
|
schoolApply.setUsername(record.getString("username"));
|
||||||
|
schoolApply.setMobile(record.getString("mobile"));
|
||||||
|
schoolApply.setIdCard(record.getString("idCard"));
|
||||||
|
schoolApply.setProfessionalLevel(record.getString("professionalLevel"));
|
||||||
|
schoolApply.setSex(record.getString("sex"));
|
||||||
|
|
||||||
|
String identityJson = record.getString("identity");
|
||||||
|
List<String> identities = Strings.isBlank(identityJson)
|
||||||
|
? new ArrayList<>()
|
||||||
|
: Json.fromJsonAsList(String.class, identityJson);
|
||||||
|
String identityName = identities.stream()
|
||||||
|
.map(personType::getName)
|
||||||
|
.filter(Strings::isNotBlank)
|
||||||
|
.collect(Collectors.joining("、"));
|
||||||
|
schoolApply.setSf(identityName);
|
||||||
|
return schoolApply;
|
||||||
|
}
|
||||||
|
|
||||||
private String getUnionApplyExportFileName(String unionId) {
|
private String getUnionApplyExportFileName(String unionId) {
|
||||||
String unionName = "分工会";
|
String unionName = "分工会";
|
||||||
if (Strings.isNotBlank(unionId)) {
|
if (Strings.isNotBlank(unionId)) {
|
||||||
|
|||||||
+13
-5
@@ -17,7 +17,6 @@ import com.budwk.app.flow.enums.ProcessInstanceStateEnum;
|
|||||||
import com.budwk.app.flow.enums.ProcessSubmitTypeEnum;
|
import com.budwk.app.flow.enums.ProcessSubmitTypeEnum;
|
||||||
import com.budwk.app.flow.service.FlowCommonService;
|
import com.budwk.app.flow.service.FlowCommonService;
|
||||||
import com.budwk.app.web.commons.auth.utils.SecurityUtil;
|
import com.budwk.app.web.commons.auth.utils.SecurityUtil;
|
||||||
import com.budwk.app.zhgh.club.model.ClubUser;
|
|
||||||
import com.budwk.app.zhgh.club.model.SysClub;
|
import com.budwk.app.zhgh.club.model.SysClub;
|
||||||
import com.budwk.app.zhgh.club.model.SysClubExamineRegister;
|
import com.budwk.app.zhgh.club.model.SysClubExamineRegister;
|
||||||
import com.budwk.app.zhgh.club.service.SysClubExamineService;
|
import com.budwk.app.zhgh.club.service.SysClubExamineService;
|
||||||
@@ -119,10 +118,7 @@ public class ClubExamineApplyController {
|
|||||||
if(StrUtil.isBlank(clubId)) {
|
if(StrUtil.isBlank(clubId)) {
|
||||||
return Result.error("社团信息为空,请核查");
|
return Result.error("社团信息为空,请核查");
|
||||||
}
|
}
|
||||||
int count = dao.count(ClubUser.class, Cnd.where("clubId", "=", clubId));
|
return Result.success(sysClubExamineService.getClubMemberMoney(clubId));
|
||||||
SysClub club = dao.fetch(SysClub.class, clubId);
|
|
||||||
int money = count * (club.getDue() != null ? Integer.parseInt(club.getDue()) : 0);
|
|
||||||
return Result.success(money);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@At
|
@At
|
||||||
@@ -175,6 +171,10 @@ public class ClubExamineApplyController {
|
|||||||
public Result save(@Param("data") SysClubExamineRegister examineRegister,
|
public Result save(@Param("data") SysClubExamineRegister examineRegister,
|
||||||
@Param("incomeDetailed") String incomeDetailed,
|
@Param("incomeDetailed") String incomeDetailed,
|
||||||
@Param("incomeCensus") String incomeCensus) {
|
@Param("incomeCensus") String incomeCensus) {
|
||||||
|
String validateMessage = sysClubExamineService.validateActivityRequired(examineRegister);
|
||||||
|
if (validateMessage != null) {
|
||||||
|
return Result.error(validateMessage);
|
||||||
|
}
|
||||||
if (StrUtil.isBlank(examineRegister.getId())) {
|
if (StrUtil.isBlank(examineRegister.getId())) {
|
||||||
sysClubExamineService.doAdd(examineRegister, incomeDetailed, incomeCensus);
|
sysClubExamineService.doAdd(examineRegister, incomeDetailed, incomeCensus);
|
||||||
} else {
|
} else {
|
||||||
@@ -190,6 +190,10 @@ public class ClubExamineApplyController {
|
|||||||
public Result submit(@Param("data") SysClubExamineRegister examineRegister,
|
public Result submit(@Param("data") SysClubExamineRegister examineRegister,
|
||||||
@Param("incomeDetailed") String incomeDetailed,
|
@Param("incomeDetailed") String incomeDetailed,
|
||||||
@Param("incomeCensus") String incomeCensus) {
|
@Param("incomeCensus") String incomeCensus) {
|
||||||
|
String validateMessage = sysClubExamineService.validateActivityRequired(examineRegister);
|
||||||
|
if (validateMessage != null) {
|
||||||
|
return Result.error(validateMessage);
|
||||||
|
}
|
||||||
SysClubExamineRegister reg;
|
SysClubExamineRegister reg;
|
||||||
if (StrUtil.isBlank(examineRegister.getId())) {
|
if (StrUtil.isBlank(examineRegister.getId())) {
|
||||||
reg = sysClubExamineService.doAdd(examineRegister, incomeDetailed, incomeCensus);
|
reg = sysClubExamineService.doAdd(examineRegister, incomeDetailed, incomeCensus);
|
||||||
@@ -221,6 +225,10 @@ public class ClubExamineApplyController {
|
|||||||
@Param("incomeDetailed") String incomeDetailed,
|
@Param("incomeDetailed") String incomeDetailed,
|
||||||
@Param("incomeCensus") String incomeCensus,
|
@Param("incomeCensus") String incomeCensus,
|
||||||
@Param("taskId") Long taskId) {
|
@Param("taskId") Long taskId) {
|
||||||
|
String validateMessage = sysClubExamineService.validateActivityRequired(examineRegister);
|
||||||
|
if (validateMessage != null) {
|
||||||
|
return Result.error(validateMessage);
|
||||||
|
}
|
||||||
if (StrUtil.isBlank(examineRegister.getId())) {
|
if (StrUtil.isBlank(examineRegister.getId())) {
|
||||||
sysClubExamineService.doAdd(examineRegister, incomeDetailed, incomeCensus);
|
sysClubExamineService.doAdd(examineRegister, incomeDetailed, incomeCensus);
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
+1
-1
@@ -86,7 +86,7 @@ public class ClubExamineMineController {
|
|||||||
//nutMap.setv("schoolName", Globals.MyConfig.getString("AppName"));
|
//nutMap.setv("schoolName", Globals.MyConfig.getString("AppName"));
|
||||||
nutMap.setv("clubName", register.getClubName());
|
nutMap.setv("clubName", register.getClubName());
|
||||||
nutMap.setv("create_time", register.getFoundTime());
|
nutMap.setv("create_time", register.getFoundTime());
|
||||||
nutMap.setv("dues_standard", register.getDue());
|
nutMap.setv("dues_standard", register.getDue() == null ? "--" : register.getDue() + "元/年");
|
||||||
// 生成材料中的年度与列表展示的登记年度保持一致。
|
// 生成材料中的年度与列表展示的登记年度保持一致。
|
||||||
nutMap.setv("year", register.getYear());
|
nutMap.setv("year", register.getYear());
|
||||||
nutMap.setv("registerDate", register.getRegisterDate());
|
nutMap.setv("registerDate", register.getRegisterDate());
|
||||||
|
|||||||
@@ -91,8 +91,8 @@ public class SysClub extends BaseModel {
|
|||||||
|
|
||||||
@Column
|
@Column
|
||||||
@Comment("会费标准")
|
@Comment("会费标准")
|
||||||
@ColDefine(type = ColType.VARCHAR, width = 50)
|
@ColDefine(type = ColType.DOUBLE, width = 10, precision = 2)
|
||||||
private String due;
|
private Double due;
|
||||||
|
|
||||||
@Column
|
@Column
|
||||||
@Comment("附件")
|
@Comment("附件")
|
||||||
|
|||||||
@@ -57,8 +57,8 @@ public class SysClubExamineRegister extends BaseModel {
|
|||||||
|
|
||||||
@Column
|
@Column
|
||||||
@Comment("会费标准")
|
@Comment("会费标准")
|
||||||
@ColDefine(type = ColType.VARCHAR, width = 32)
|
@ColDefine(type = ColType.DOUBLE, width = 10, precision = 2)
|
||||||
private String due;
|
private Double due;
|
||||||
|
|
||||||
@Column
|
@Column
|
||||||
@Comment("年度活动情况")
|
@Comment("年度活动情况")
|
||||||
|
|||||||
@@ -24,6 +24,21 @@ public interface SysClubExamineService extends BaseService<SysClubExamineRegiste
|
|||||||
|
|
||||||
List<NutMap> getJgUser(@Valid String clubId);
|
List<NutMap> getJgUser(@Valid String clubId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 计算指定社团的年度会费收入。
|
||||||
|
*
|
||||||
|
* @param clubId 社团ID,用于查询当前会员数量和社团会费标准
|
||||||
|
* @return 会员数量乘以会费标准后的金额;社团或会费标准为空时返回0
|
||||||
|
*/
|
||||||
|
Double getClubMemberMoney(@Valid String clubId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 校验考核登记的两组活动明细。
|
||||||
|
* @param examineRegister 页面data参数对应的登记实体,yearActivityList为本年度活动,plans为下一年度计划
|
||||||
|
* @return String类型;通过返回null,否则返回缺失的明细行号及字段提示
|
||||||
|
*/
|
||||||
|
String validateActivityRequired(SysClubExamineRegister examineRegister);
|
||||||
|
|
||||||
SysClubExamineRegister doAdd(SysClubExamineRegister examineRegister, String incomeDetailed, String incomeCensus);
|
SysClubExamineRegister doAdd(SysClubExamineRegister examineRegister, String incomeDetailed, String incomeCensus);
|
||||||
|
|
||||||
SysClubExamineRegister doEdit(SysClubExamineRegister examineRegister, String incomeDetailed, String incomeCensus);
|
SysClubExamineRegister doEdit(SysClubExamineRegister examineRegister, String incomeDetailed, String incomeCensus);
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ import com.budwk.app.flow.enums.ProcessInstanceStateEnum;
|
|||||||
import com.budwk.app.flow.enums.ProcessTaskStateEnum;
|
import com.budwk.app.flow.enums.ProcessTaskStateEnum;
|
||||||
import com.budwk.app.web.commons.auth.utils.AuthUtil;
|
import com.budwk.app.web.commons.auth.utils.AuthUtil;
|
||||||
import com.budwk.app.web.commons.auth.utils.SecurityUtil;
|
import com.budwk.app.web.commons.auth.utils.SecurityUtil;
|
||||||
|
import com.budwk.app.zhgh.club.model.ClubUser;
|
||||||
import com.budwk.app.zhgh.club.model.SysClub;
|
import com.budwk.app.zhgh.club.model.SysClub;
|
||||||
import com.budwk.app.zhgh.club.model.SysClubExamineRegister;
|
import com.budwk.app.zhgh.club.model.SysClubExamineRegister;
|
||||||
import com.budwk.app.zhgh.club.model.SysClubExamineRegisterDetailed;
|
import com.budwk.app.zhgh.club.model.SysClubExamineRegisterDetailed;
|
||||||
@@ -50,6 +51,15 @@ public class SysClubExamineServiceImpl extends BaseServiceImpl<SysClubExamineReg
|
|||||||
super(dao);
|
super(dao);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Double getClubMemberMoney(String clubId) {
|
||||||
|
int memberCount = dao().count(ClubUser.class, Cnd.where(ClubUser::getClubId, "=", clubId));
|
||||||
|
SysClub club = dao().fetch(SysClub.class, clubId);
|
||||||
|
// 社团或会费标准为空时按0计算,保证考核登记初始化能够正常完成。
|
||||||
|
Double due = club == null || club.getDue() == null ? 0D : club.getDue();
|
||||||
|
return memberCount * due;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<NutMap> getClubUserNum(String clubId, Integer year) {
|
public List<NutMap> getClubUserNum(String clubId, Integer year) {
|
||||||
Date yearStart = DateUtil.parse(year + "-01-01 00:00:00");
|
Date yearStart = DateUtil.parse(year + "-01-01 00:00:00");
|
||||||
@@ -345,6 +355,40 @@ public class SysClubExamineServiceImpl extends BaseServiceImpl<SysClubExamineReg
|
|||||||
return listMap;
|
return listMap;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 两组明细均至少填写一条;本年度主办单位和获奖情况保持选填。
|
||||||
|
* @param examineRegister data参数绑定的登记实体,包含yearActivityList和plans两组JSON明细
|
||||||
|
* @return 校验通过返回null,否则返回首个缺失字段的行号和名称
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public String validateActivityRequired(SysClubExamineRegister examineRegister) {
|
||||||
|
if (examineRegister == null) {
|
||||||
|
return "考核登记信息不能为空";
|
||||||
|
}
|
||||||
|
String message = validateActivityRows(examineRegister.getYearActivityList(), "本年度活动开展情况",
|
||||||
|
new String[]{"activityTime", "activityName", "activityAddress", "joinNum"},
|
||||||
|
new String[]{"活动时间", "活动主题/赛事名称", "活动地点", "参加人数"});
|
||||||
|
return message != null ? message : validateActivityRows(examineRegister.getPlans(), "下一年度活动计划",
|
||||||
|
new String[]{"activityName", "activityUnit", "activityAddress"},
|
||||||
|
new String[]{"活动主题/赛事名称", "活动/赛事主办单位", "活动地点"});
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 检查空列表、空行及纯空白字段;数值0按已填写处理,不扩大为人数范围校验。 */
|
||||||
|
private String validateActivityRows(List<JSONObject> rows, String label, String[] fields, String[] names) {
|
||||||
|
if (rows == null || rows.isEmpty()) {
|
||||||
|
return label + "至少填写一条";
|
||||||
|
}
|
||||||
|
for (int i = 0; i < rows.size(); i++) {
|
||||||
|
JSONObject row = rows.get(i);
|
||||||
|
for (int j = 0; j < fields.length; j++) {
|
||||||
|
if (row == null || StrUtil.isBlank(row.getStr(fields[j]))) {
|
||||||
|
return label + "第" + (i + 1) + "条:" + names[j] + "不能为空";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public SysClubExamineRegister doAdd(SysClubExamineRegister examineRegister, String incomeDetailed, String incomeCensus) {
|
public SysClubExamineRegister doAdd(SysClubExamineRegister examineRegister, String incomeDetailed, String incomeCensus) {
|
||||||
// JSON转换为实体列表(空值判断避免转换异常)
|
// JSON转换为实体列表(空值判断避免转换异常)
|
||||||
|
|||||||
+3
@@ -606,6 +606,9 @@ public class TourMySignupController {
|
|||||||
if (StrUtil.isBlank(ledger.getMobile())) {
|
if (StrUtil.isBlank(ledger.getMobile())) {
|
||||||
return Result.error("手机号不能为空");
|
return Result.error("手机号不能为空");
|
||||||
}
|
}
|
||||||
|
if (!ledger.getMobile().matches("^1[3-9]\\d{9}$")) {
|
||||||
|
return Result.error("请输入正确的11位手机号");
|
||||||
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+3
@@ -841,6 +841,9 @@ public class TourSignupController {
|
|||||||
if (StrUtil.isBlank(ledger.getMobile())) {
|
if (StrUtil.isBlank(ledger.getMobile())) {
|
||||||
return Result.error("手机号不能为空");
|
return Result.error("手机号不能为空");
|
||||||
}
|
}
|
||||||
|
if (!ledger.getMobile().matches("^1[3-9]\\d{9}$")) {
|
||||||
|
return Result.error("请输入正确的11位手机号");
|
||||||
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+7
-3
@@ -229,14 +229,18 @@ public class ProposalMineController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除当前用户可删除的提案。
|
||||||
|
*
|
||||||
|
* @param id 提案 ID;仅允许删除本人未发起流程或退回发起节点的提案
|
||||||
|
* @return Result,成功时返回成功结果,不满足删除条件时返回原因
|
||||||
|
*/
|
||||||
@At
|
@At
|
||||||
@SaCheckPermission("proposal.mine")
|
@SaCheckPermission("proposal.mine")
|
||||||
@Aop(TransAop.READ_COMMITTED)
|
@Aop(TransAop.READ_COMMITTED)
|
||||||
@SLog(tag = "提案管理系统-我的提案", msg = "删除提案")
|
@SLog(tag = "提案管理系统-我的提案", msg = "删除提案")
|
||||||
public Result delete(@Valid String id) {
|
public Result delete(@Valid String id) {
|
||||||
dao.delete(ProposalInfo.class, id);
|
return proposalCommonService.deleteMine(id, SecurityUtil.getUserId());
|
||||||
flowEngine.processInstanceService().deleteProcessInstanceByBusinessKey(id);
|
|
||||||
return Result.success();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@At
|
@At
|
||||||
|
|||||||
+10
@@ -3,6 +3,7 @@ package com.budwk.app.zhgh.democratic.proposal.service.common;
|
|||||||
import com.budwk.app.base.service.BaseService;
|
import com.budwk.app.base.service.BaseService;
|
||||||
import com.budwk.app.base.param.PageForm;
|
import com.budwk.app.base.param.PageForm;
|
||||||
import com.budwk.app.base.param.ExportTableColumns;
|
import com.budwk.app.base.param.ExportTableColumns;
|
||||||
|
import com.budwk.app.base.result.Result;
|
||||||
import com.budwk.app.zhgh.democratic.proposal.models.ProposalInfo;
|
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.models.ProposalUndertake;
|
||||||
import com.budwk.app.zhgh.democratic.proposal.param.ProposalQueryComprehensiveParam;
|
import com.budwk.app.zhgh.democratic.proposal.param.ProposalQueryComprehensiveParam;
|
||||||
@@ -19,6 +20,15 @@ import java.util.Set;
|
|||||||
|
|
||||||
public interface ProposalCommonService extends BaseService<ProposalInfo> {
|
public interface ProposalCommonService extends BaseService<ProposalInfo> {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除当前用户尚未发起流程或已退回发起节点的提案。
|
||||||
|
*
|
||||||
|
* @param id 待删除的提案 ID
|
||||||
|
* @param userId 当前登录用户 ID,用于核对提案创建人
|
||||||
|
* @return Result,删除成功返回 success;提案不存在、非本人或流程不允许删除时返回错误信息
|
||||||
|
*/
|
||||||
|
Result deleteMine(String id, String userId);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 按页面允许的字段白名单添加排序条件,避免前端字段直接进入SQL。
|
* 按页面允许的字段白名单添加排序条件,避免前端字段直接进入SQL。
|
||||||
*
|
*
|
||||||
|
|||||||
+42
@@ -17,6 +17,7 @@ import com.budwk.app.base.exception.BaseException;
|
|||||||
import com.budwk.app.base.param.ExportTableColumns;
|
import com.budwk.app.base.param.ExportTableColumns;
|
||||||
import com.budwk.app.base.param.PageForm;
|
import com.budwk.app.base.param.PageForm;
|
||||||
import com.budwk.app.base.page.Pagination;
|
import com.budwk.app.base.page.Pagination;
|
||||||
|
import com.budwk.app.base.result.Result;
|
||||||
import com.budwk.app.base.service.impl.BaseServiceImpl;
|
import com.budwk.app.base.service.impl.BaseServiceImpl;
|
||||||
import com.budwk.app.base.utils.CommonDownloadUtil;
|
import com.budwk.app.base.utils.CommonDownloadUtil;
|
||||||
import com.budwk.app.base.utils.PageUtil;
|
import com.budwk.app.base.utils.PageUtil;
|
||||||
@@ -52,6 +53,7 @@ import com.deepoove.poi.config.Configure;
|
|||||||
import com.deepoove.poi.plugin.table.LoopRowTableRenderPolicy;
|
import com.deepoove.poi.plugin.table.LoopRowTableRenderPolicy;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.ddr.poi.html.HtmlRenderPolicy;
|
import org.ddr.poi.html.HtmlRenderPolicy;
|
||||||
|
import org.nutz.aop.interceptor.ioc.TransAop;
|
||||||
import org.nutz.dao.Cnd;
|
import org.nutz.dao.Cnd;
|
||||||
import org.nutz.dao.Dao;
|
import org.nutz.dao.Dao;
|
||||||
import org.nutz.dao.FieldFilter;
|
import org.nutz.dao.FieldFilter;
|
||||||
@@ -62,6 +64,7 @@ import org.nutz.dao.util.cri.SqlExpressionGroup;
|
|||||||
import org.nutz.dao.util.cri.Static;
|
import org.nutz.dao.util.cri.Static;
|
||||||
import org.nutz.ioc.loader.annotation.Inject;
|
import org.nutz.ioc.loader.annotation.Inject;
|
||||||
import org.nutz.ioc.loader.annotation.IocBean;
|
import org.nutz.ioc.loader.annotation.IocBean;
|
||||||
|
import org.nutz.ioc.aop.Aop;
|
||||||
import org.nutz.json.Json;
|
import org.nutz.json.Json;
|
||||||
import org.nutz.lang.Lang;
|
import org.nutz.lang.Lang;
|
||||||
import org.nutz.lang.Strings;
|
import org.nutz.lang.Strings;
|
||||||
@@ -184,6 +187,45 @@ public class ProposalCommonServiceImpl extends BaseServiceImpl<ProposalInfo> imp
|
|||||||
super(dao);
|
super(dao);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 仅允许创建人删除草稿或退回发起节点的提案,并清理其 WF 流程。
|
||||||
|
*
|
||||||
|
* @param id 待删除的提案 ID
|
||||||
|
* @param userId 当前登录用户 ID,用于核对提案创建人
|
||||||
|
* @return Result,删除成功返回 success;提案不存在、非本人或流程不允许删除时返回错误信息
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
@Aop(TransAop.READ_COMMITTED)
|
||||||
|
public Result deleteMine(String id, String userId) {
|
||||||
|
if (StrUtil.isBlank(id) || StrUtil.isBlank(userId)) {
|
||||||
|
return Result.error("提案不存在或无权删除");
|
||||||
|
}
|
||||||
|
ProposalInfo proposal = dao().fetch(ProposalInfo.class, id);
|
||||||
|
if (proposal == null || !Objects.equals(proposal.getCreatedBy(), userId)) {
|
||||||
|
return Result.error("提案不存在或无权删除");
|
||||||
|
}
|
||||||
|
|
||||||
|
List<ProcessInstance> instances = dao().query(ProcessInstance.class,
|
||||||
|
Cnd.where(ProcessInstance::getBusinessNo, "=", id));
|
||||||
|
// 一个提案出现多个流程实例时无法安全判断当前节点,拒绝删除并保留数据。
|
||||||
|
if (instances.size() > 1) {
|
||||||
|
return Result.error("提案流程数据异常,无法删除");
|
||||||
|
}
|
||||||
|
if (!instances.isEmpty()) {
|
||||||
|
ProcessInstance instance = instances.get(0);
|
||||||
|
List<ProcessTask> tasks = flowEngine.processTaskService().getDoingTaskList(instance.getId(), null);
|
||||||
|
// 存在并行任务时,只有所有活动任务均位于发起节点才允许删除。
|
||||||
|
if (!Objects.equals(instance.getState(), ProcessInstanceStateEnum.DOING.getCode())
|
||||||
|
|| tasks.isEmpty() || tasks.stream().anyMatch(task -> !Objects.equals(task.getTaskName(), "startTask"))) {
|
||||||
|
return Result.error("仅未提交或退回发起节点的提案可以删除");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
dao().delete(ProposalInfo.class, id);
|
||||||
|
flowEngine.processInstanceService().deleteProcessInstanceByBusinessKey(id);
|
||||||
|
return Result.success();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 分页查询提案综合列表。
|
* 分页查询提案综合列表。
|
||||||
* 普通查询不关联历史任务表;仅在 origins 包含 answer 且 commonKeyword 非空时,
|
* 普通查询不关联历史任务表;仅在 origins 包含 answer 且 commonKeyword 非空时,
|
||||||
|
|||||||
+5
-23
@@ -28,7 +28,6 @@ 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.model.Condolence;
|
||||||
import com.budwk.app.zhgh.staffbenefit.condolence.model.CondolenceType;
|
import com.budwk.app.zhgh.staffbenefit.condolence.model.CondolenceType;
|
||||||
import com.budwk.app.zhgh.staffbenefit.condolence.service.CondolenceService;
|
import com.budwk.app.zhgh.staffbenefit.condolence.service.CondolenceService;
|
||||||
import com.deepoove.poi.XWPFTemplate;
|
|
||||||
import com.deepoove.poi.data.PictureRenderData;
|
import com.deepoove.poi.data.PictureRenderData;
|
||||||
import io.swagger.annotations.Api;
|
import io.swagger.annotations.Api;
|
||||||
import io.swagger.annotations.ApiOperation;
|
import io.swagger.annotations.ApiOperation;
|
||||||
@@ -48,8 +47,6 @@ import org.nutz.mvc.annotation.Ok;
|
|||||||
import org.nutz.mvc.annotation.Param;
|
import org.nutz.mvc.annotation.Param;
|
||||||
|
|
||||||
import javax.servlet.http.HttpServletResponse;
|
import javax.servlet.http.HttpServletResponse;
|
||||||
import java.io.ByteArrayInputStream;
|
|
||||||
import java.io.ByteArrayOutputStream;
|
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@@ -187,27 +184,12 @@ public class CondolenceMineController {
|
|||||||
log.info("[职工慰问导出] 渲染前图片字段,applyId={}, instanceId={}, field={}, valueType={}", id, instance.getId(), field, value == null ? "null" : value.getClass().getName());
|
log.info("[职工慰问导出] 渲染前图片字段,applyId={}, instanceId={}, field={}, valueType={}", id, instance.getId(), field, value == null ? "null" : value.getClass().getName());
|
||||||
}
|
}
|
||||||
String fileName = "重庆工贸职业技术学院职工慰问申请表_" + StrUtil.nullToEmpty(condolence.getHelpUserName());
|
String fileName = "重庆工贸职业技术学院职工慰问申请表_" + StrUtil.nullToEmpty(condolence.getHelpUserName());
|
||||||
try (InputStream input = getClass().getResourceAsStream("/templates/condolence/重庆工贸职业技术学院职工慰问申请表.doc");
|
try (InputStream input = getClass().getResourceAsStream("/templates/condolence/重庆工贸职业技术学院职工慰问申请表.doc")) {
|
||||||
ByteArrayOutputStream templateOutput = new ByteArrayOutputStream();
|
|
||||||
ByteArrayOutputStream output = new ByteArrayOutputStream()) {
|
|
||||||
if (input == null) throw new BaseException("职工慰问申请表模板不存在");
|
if (input == null) throw new BaseException("职工慰问申请表模板不存在");
|
||||||
com.aspose.words.Document document = new com.aspose.words.Document(input);
|
boolean pdf = Boolean.TRUE.equals(print);
|
||||||
document.save(templateOutput, com.aspose.words.SaveFormat.DOCX);
|
byte[] bytes = sysOfficeTemplateUtil.renderTemplate(input, docData, null, pdf, "condolence:" + id);
|
||||||
log.info("[职工慰问导出] 模板转换完成,applyId={}, templateBytes={}", id, templateOutput.size());
|
log.info("[职工慰问导出] 渲染完成,applyId={}, format={}, outputBytes={}", id, pdf ? "PDF" : "Word", bytes.length);
|
||||||
try (ByteArrayInputStream templateInput = new ByteArrayInputStream(templateOutput.toByteArray())) {
|
CommonDownloadUtil.download(fileName + (pdf ? ".pdf" : ".docx"), bytes, response);
|
||||||
XWPFTemplate.compile(templateInput).render(docData).writeAndClose(output);
|
|
||||||
}
|
|
||||||
log.info("[职工慰问导出] Word渲染完成,applyId={}, outputBytes={}", id, output.size());
|
|
||||||
if (Boolean.TRUE.equals(print)) {
|
|
||||||
try (ByteArrayInputStream wordInput = new ByteArrayInputStream(output.toByteArray());
|
|
||||||
ByteArrayOutputStream pdfOutput = new ByteArrayOutputStream()) {
|
|
||||||
new com.aspose.words.Document(wordInput).save(pdfOutput, com.aspose.words.SaveFormat.PDF);
|
|
||||||
log.info("[职工慰问导出] PDF转换完成,applyId={}, outputBytes={}", id, pdfOutput.size());
|
|
||||||
CommonDownloadUtil.download(fileName + ".pdf", pdfOutput.toByteArray(), response);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
CommonDownloadUtil.download(fileName + ".docx", output.toByteArray(), response);
|
|
||||||
}
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
log.error("[职工慰问导出] 模板渲染或文件输出失败,applyId={}, instanceId={}, format={}", id, instance.getId(), Boolean.TRUE.equals(print) ? "PDF" : "Word", e);
|
log.error("[职工慰问导出] 模板渲染或文件输出失败,applyId={}, instanceId={}, format={}", id, instance.getId(), Boolean.TRUE.equals(print) ? "PDF" : "Word", e);
|
||||||
throw e;
|
throw e;
|
||||||
|
|||||||
+6
-14
@@ -6,17 +6,14 @@ import cn.afterturn.easypoi.excel.entity.enmus.ExcelType;
|
|||||||
import cn.afterturn.easypoi.excel.entity.params.ExcelExportEntity;
|
import cn.afterturn.easypoi.excel.entity.params.ExcelExportEntity;
|
||||||
import cn.dev33.satoken.annotation.SaCheckPermission;
|
import cn.dev33.satoken.annotation.SaCheckPermission;
|
||||||
import cn.hutool.core.util.StrUtil;
|
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.page.Pagination;
|
||||||
import com.budwk.app.base.param.PageForm;
|
import com.budwk.app.base.param.PageForm;
|
||||||
import com.budwk.app.base.result.Result;
|
import com.budwk.app.base.result.Result;
|
||||||
import com.budwk.app.base.utils.CommonDownloadUtil;
|
import com.budwk.app.base.utils.CommonDownloadUtil;
|
||||||
import com.budwk.app.base.utils.PageUtil;
|
import com.budwk.app.base.utils.PageUtil;
|
||||||
import com.budwk.app.flow.entity.ProcessInstance;
|
import com.budwk.app.flow.entity.ProcessInstance;
|
||||||
import com.budwk.app.flow.enums.ProcessTaskStateEnum;
|
import com.budwk.app.flow.enums.ProcessInstanceStateEnum;
|
||||||
import com.budwk.app.sys.param.SysMsgSummaryPageForm;
|
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.model.Condolence;
|
||||||
import com.budwk.app.zhgh.staffbenefit.condolence.service.CondolenceService;
|
import com.budwk.app.zhgh.staffbenefit.condolence.service.CondolenceService;
|
||||||
import io.swagger.annotations.Api;
|
import io.swagger.annotations.Api;
|
||||||
@@ -94,6 +91,7 @@ public class CondolenceReadController {
|
|||||||
$condition
|
$condition
|
||||||
""");
|
""");
|
||||||
Cnd cnd = Cnd.NEW();
|
Cnd cnd = Cnd.NEW();
|
||||||
|
cnd.and("ins.state", "=", ProcessInstanceStateEnum.FINISHED.getCode());
|
||||||
cnd.andEX("info.type", "=", type);
|
cnd.andEX("info.type", "=", type);
|
||||||
cnd.andEX("YEAR(info.createTime)", "=", year);
|
cnd.andEX("YEAR(info.createTime)", "=", year);
|
||||||
cnd.andEX("info.applyUnionId", "=", unionId);
|
cnd.andEX("info.applyUnionId", "=", unionId);
|
||||||
@@ -106,9 +104,6 @@ public class CondolenceReadController {
|
|||||||
cnd.and(seg);
|
cnd.and(seg);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!AuthUtil.hasRoleOr(RoleConstant.SYSADMIN.name(), RoleConstant.SCHOOL_UNION_CHAIRMAN.name())) {
|
|
||||||
cnd.and("info.applyUnionId", "=", SecurityUtil.getUnionId());
|
|
||||||
}
|
|
||||||
|
|
||||||
if (StrUtil.isAllBlank(pageForm.getPageOrderName(), pageForm.getPageOrderBy())) {
|
if (StrUtil.isAllBlank(pageForm.getPageOrderName(), pageForm.getPageOrderBy())) {
|
||||||
cnd.desc("info.createTime");
|
cnd.desc("info.createTime");
|
||||||
@@ -142,20 +137,17 @@ public class CondolenceReadController {
|
|||||||
$condition
|
$condition
|
||||||
""");
|
""");
|
||||||
Cnd cnd = Cnd.NEW();
|
Cnd cnd = Cnd.NEW();
|
||||||
cnd.and(ProcessInstance::getState, "=", ProcessTaskStateEnum.FINISHED.getCode());
|
cnd.and("ins.state", "=", ProcessInstanceStateEnum.FINISHED.getCode());
|
||||||
cnd.andEX("con.type", "=", type);
|
cnd.andEX("con.type", "=", type);
|
||||||
cnd.andEX("YEAR(info.createTime)", "=", year);
|
cnd.andEX("YEAR(con.createTime)", "=", year);
|
||||||
cnd.andEX("con.applyUnionId", "=", unionId);
|
cnd.andEX("con.applyUnionId", "=", unionId);
|
||||||
cnd.andEX("con.applyUnitId", "=", unitId);
|
cnd.andEX("con.applyUnitId", "=", unitId);
|
||||||
if (StrUtil.isNotBlank(pageForm.getSearchKeyword())) {
|
if (StrUtil.isNotBlank(pageForm.getSearchKeyword())) {
|
||||||
SqlExpressionGroup seg = new SqlExpressionGroup();
|
SqlExpressionGroup seg = new SqlExpressionGroup();
|
||||||
seg.or("info.helpUserName", "like", "%" + pageForm.getSearchKeyword() + "%");
|
seg.or("con.helpUserName", "like", "%" + pageForm.getSearchKeyword() + "%");
|
||||||
seg.or("info.helpLoginName", "like", "%" + pageForm.getSearchKeyword() + "%");
|
seg.or("con.helpLoginName", "like", "%" + pageForm.getSearchKeyword() + "%");
|
||||||
cnd.and(seg);
|
cnd.and(seg);
|
||||||
}
|
}
|
||||||
if (!AuthUtil.hasRoleOr(RoleConstant.SYSADMIN.name(), RoleConstant.SCHOOL_UNION_CHAIRMAN.name())) {
|
|
||||||
cnd.and("con.applyUnionId", "=", SecurityUtil.getUnionId());
|
|
||||||
}
|
|
||||||
sql.setCondition(cnd);
|
sql.setCondition(cnd);
|
||||||
List<NutMap> list = condolenceService.listMap(sql);
|
List<NutMap> list = condolenceService.listMap(sql);
|
||||||
|
|
||||||
|
|||||||
+11
-8
@@ -43,9 +43,9 @@ public class DifficultHelpApprovalController {
|
|||||||
}
|
}
|
||||||
ProcessTask task = dao.fetch(ProcessTask.class, args.getLong(FlowConst.PROCESS_TASK_ID_KEY));
|
ProcessTask task = dao.fetch(ProcessTask.class, args.getLong(FlowConst.PROCESS_TASK_ID_KEY));
|
||||||
if (task == null) throw new BaseException("审批任务不存在");
|
if (task == null) throw new BaseException("审批任务不存在");
|
||||||
boolean amountApproval = "36ebafda-44c2-4bd3-bd7f-10839a575a0d".equals(task.getTaskName())
|
boolean amountApproval = "715ece82-4ae3-433c-ad18-ed875f45d1e3".equals(task.getTaskName());
|
||||||
|| "715ece82-4ae3-433c-ad18-ed875f45d1e3".equals(task.getTaskName());
|
if (!amountApproval && !"36ebafda-44c2-4bd3-bd7f-10839a575a0d".equals(task.getTaskName())
|
||||||
if (!amountApproval && !"e405f96c-5fc0-4f63-b323-e69dfe853253".equals(task.getTaskName())) {
|
&& !"e405f96c-5fc0-4f63-b323-e69dfe853253".equals(task.getTaskName())) {
|
||||||
throw new BaseException("当前任务不是困难帮扶审批任务");
|
throw new BaseException("当前任务不是困难帮扶审批任务");
|
||||||
}
|
}
|
||||||
ProcessInstance instance = dao.fetch(ProcessInstance.class, task.getProcessInstanceId());
|
ProcessInstance instance = dao.fetch(ProcessInstance.class, task.getProcessInstanceId());
|
||||||
@@ -54,20 +54,23 @@ public class DifficultHelpApprovalController {
|
|||||||
if (StrUtil.isBlank(args.getStr("tf_sign"))) throw new BaseException("请完成审批签字");
|
if (StrUtil.isBlank(args.getStr("tf_sign"))) throw new BaseException("请完成审批签字");
|
||||||
if (StrUtil.isBlank(args.getStr("tf_opinion"))) throw new BaseException("请填写审批意见");
|
if (StrUtil.isBlank(args.getStr("tf_opinion"))) throw new BaseException("请填写审批意见");
|
||||||
|
|
||||||
String level = args.getStr("level");
|
args.remove("level");
|
||||||
|
args.remove("tf_level");
|
||||||
Double money = amountApproval ? args.getDouble("money") : null;
|
Double money = amountApproval ? args.getDouble("money") : null;
|
||||||
if (amountApproval) {
|
if (amountApproval) {
|
||||||
if (StrUtil.isBlank(level) || money == null || !Double.isFinite(money) || money < 0) {
|
if (money == null || !Double.isFinite(money) || money < 0) {
|
||||||
throw new BaseException("请填写完整的级别和帮扶金额");
|
throw new BaseException("请填写有效的帮扶金额");
|
||||||
}
|
}
|
||||||
args.put("tf_level", level);
|
|
||||||
args.put("tf_money", money);
|
args.put("tf_money", money);
|
||||||
|
} else {
|
||||||
|
args.remove("money");
|
||||||
|
args.remove("tf_money");
|
||||||
}
|
}
|
||||||
// 参与者权限由流程引擎校验,业务入口不接受客户端指定管理员代办。
|
// 参与者权限由流程引擎校验,业务入口不接受客户端指定管理员代办。
|
||||||
args.remove(FlowConst.EXT_ENABLE_OPERATOR);
|
args.remove(FlowConst.EXT_ENABLE_OPERATOR);
|
||||||
flowCommonService.executeTask(args);
|
flowCommonService.executeTask(args);
|
||||||
if (amountApproval && Integer.valueOf(ProcessSubmitTypeEnum.AGREE.getCode()).equals(args.getInt(FlowConst.SUBMIT_TYPE))) {
|
if (amountApproval && Integer.valueOf(ProcessSubmitTypeEnum.AGREE.getCode()).equals(args.getInt(FlowConst.SUBMIT_TYPE))) {
|
||||||
dao.update(DifficultHelpInfo.class, Chain.make("level", level).add("money", money), Cnd.where("id", "=", info.getId()));
|
dao.update(DifficultHelpInfo.class, Chain.make("money", money), Cnd.where("id", "=", info.getId()));
|
||||||
}
|
}
|
||||||
return Result.success();
|
return Result.success();
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-1
@@ -1,6 +1,7 @@
|
|||||||
package com.budwk.app.zhgh.staffbenefit.difficulthelp.controller;
|
package com.budwk.app.zhgh.staffbenefit.difficulthelp.controller;
|
||||||
|
|
||||||
import cn.dev33.satoken.annotation.SaCheckPermission;
|
import cn.dev33.satoken.annotation.SaCheckPermission;
|
||||||
|
import cn.dev33.satoken.annotation.SaMode;
|
||||||
import cn.hutool.core.util.StrUtil;
|
import cn.hutool.core.util.StrUtil;
|
||||||
import com.budwk.app.base.annotation.SLog;
|
import com.budwk.app.base.annotation.SLog;
|
||||||
import com.budwk.app.base.page.Pagination;
|
import com.budwk.app.base.page.Pagination;
|
||||||
@@ -137,7 +138,7 @@ public class DifficultHelpMineController {
|
|||||||
|
|
||||||
@At
|
@At
|
||||||
@ApiModelProperty("获取困难补助申请")
|
@ApiModelProperty("获取困难补助申请")
|
||||||
@SaCheckPermission("difficultHelp.mine")
|
@SaCheckPermission(value = {"difficultHelp.mine", "difficultHelp.reading"}, mode = SaMode.OR)
|
||||||
public Result findOne(String id) {
|
public Result findOne(String id) {
|
||||||
DifficultHelpInfo helpInfo = dao.fetch(DifficultHelpInfo.class, id);
|
DifficultHelpInfo helpInfo = dao.fetch(DifficultHelpInfo.class, id);
|
||||||
return Result.success().addData(helpInfo);
|
return Result.success().addData(helpInfo);
|
||||||
|
|||||||
+21
-42
@@ -9,7 +9,6 @@ import cn.dev33.satoken.annotation.SaCheckLogin;
|
|||||||
import cn.dev33.satoken.annotation.SaCheckPermission;
|
import cn.dev33.satoken.annotation.SaCheckPermission;
|
||||||
import cn.hutool.core.date.DateUtil;
|
import cn.hutool.core.date.DateUtil;
|
||||||
import cn.hutool.core.io.FileUtil;
|
import cn.hutool.core.io.FileUtil;
|
||||||
import cn.hutool.core.io.IoUtil;
|
|
||||||
import cn.hutool.core.util.StrUtil;
|
import cn.hutool.core.util.StrUtil;
|
||||||
import cn.hutool.json.JSONUtil;
|
import cn.hutool.json.JSONUtil;
|
||||||
import com.alibaba.excel.EasyExcel;
|
import com.alibaba.excel.EasyExcel;
|
||||||
@@ -18,7 +17,6 @@ import com.budwk.app.base.page.Pagination;
|
|||||||
import com.budwk.app.base.result.Result;
|
import com.budwk.app.base.result.Result;
|
||||||
import com.budwk.app.base.utils.CommonDownloadUtil;
|
import com.budwk.app.base.utils.CommonDownloadUtil;
|
||||||
import com.budwk.app.base.utils.MoneyUtil;
|
import com.budwk.app.base.utils.MoneyUtil;
|
||||||
import com.budwk.app.base.utils.OfficePlusUtil;
|
|
||||||
import com.budwk.app.base.utils.SysOfficeTemplateUtil;
|
import com.budwk.app.base.utils.SysOfficeTemplateUtil;
|
||||||
import com.budwk.app.flow.engine.FlowEngine;
|
import com.budwk.app.flow.engine.FlowEngine;
|
||||||
import com.budwk.app.flow.entity.ProcessInstance;
|
import com.budwk.app.flow.entity.ProcessInstance;
|
||||||
@@ -39,7 +37,6 @@ import com.budwk.app.zhgh.staffbenefit.difficulthelp.service.DifficultHelpCommon
|
|||||||
import com.budwk.app.zhgh.staffbenefit.difficulthelp.vo.DifficultHelpPageParam;
|
import com.budwk.app.zhgh.staffbenefit.difficulthelp.vo.DifficultHelpPageParam;
|
||||||
import com.budwk.app.zhgh.staffbenefit.difficulthelp.vo.moneyImportVo;
|
import com.budwk.app.zhgh.staffbenefit.difficulthelp.vo.moneyImportVo;
|
||||||
import com.budwk.app.zhgh.staffbenefit.medicalMutualAid.aidFund.param.AidFundPageForm;
|
import com.budwk.app.zhgh.staffbenefit.medicalMutualAid.aidFund.param.AidFundPageForm;
|
||||||
import com.deepoove.poi.XWPFTemplate;
|
|
||||||
import com.deepoove.poi.config.Configure;
|
import com.deepoove.poi.config.Configure;
|
||||||
import com.deepoove.poi.data.PictureRenderData;
|
import com.deepoove.poi.data.PictureRenderData;
|
||||||
import com.deepoove.poi.plugin.table.LoopRowTableRenderPolicy;
|
import com.deepoove.poi.plugin.table.LoopRowTableRenderPolicy;
|
||||||
@@ -74,8 +71,6 @@ import javax.servlet.http.HttpServletResponse;
|
|||||||
import java.awt.image.BufferedImage;
|
import java.awt.image.BufferedImage;
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
import java.net.URLEncoder;
|
import java.net.URLEncoder;
|
||||||
import java.nio.file.Files;
|
|
||||||
import java.nio.file.StandardOpenOption;
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
@@ -159,7 +154,7 @@ public class DifficultHelpReadingController {
|
|||||||
""");
|
""");
|
||||||
Cnd cnd = Cnd.NEW();
|
Cnd cnd = Cnd.NEW();
|
||||||
cnd.and("ins.state", "=", 20);
|
cnd.and("ins.state", "=", 20);
|
||||||
pageParam.buildSearch(cnd, "info.");
|
pageParam.buildSearch(cnd, "info.", false);
|
||||||
cnd.groupBy("info.id");
|
cnd.groupBy("info.id");
|
||||||
sql.setCondition(cnd);
|
sql.setCondition(cnd);
|
||||||
Pagination<NutMap> pagination = difficultHelpCommonService.listPageMap(pageParam.getPageNumber(), pageParam.getPageSize(), sql);
|
Pagination<NutMap> pagination = difficultHelpCommonService.listPageMap(pageParam.getPageNumber(), pageParam.getPageSize(), sql);
|
||||||
@@ -243,6 +238,7 @@ public class DifficultHelpReadingController {
|
|||||||
|
|
||||||
@At
|
@At
|
||||||
@Ok("void")
|
@Ok("void")
|
||||||
|
@SaCheckPermission("difficultHelp.reading")
|
||||||
public void doExportAllApply(DifficultHelpPageParam pageParam, HttpServletResponse response) throws Exception {
|
public void doExportAllApply(DifficultHelpPageParam pageParam, HttpServletResponse response) throws Exception {
|
||||||
Sql sql = Sqls.create("""
|
Sql sql = Sqls.create("""
|
||||||
SELECT
|
SELECT
|
||||||
@@ -273,7 +269,7 @@ public class DifficultHelpReadingController {
|
|||||||
$condition
|
$condition
|
||||||
""");
|
""");
|
||||||
Cnd cnd = Cnd.NEW();
|
Cnd cnd = Cnd.NEW();
|
||||||
pageParam.buildSearch(cnd, "info.");
|
pageParam.buildSearch(cnd, "info.", false);
|
||||||
cnd.groupBy("info.id");
|
cnd.groupBy("info.id");
|
||||||
sql.setCondition(cnd);
|
sql.setCondition(cnd);
|
||||||
List<NutMap> list = difficultHelpCommonService.listMap(sql);
|
List<NutMap> list = difficultHelpCommonService.listMap(sql);
|
||||||
@@ -319,9 +315,9 @@ public class DifficultHelpReadingController {
|
|||||||
LoopRowTableRenderPolicy policy = new LoopRowTableRenderPolicy();
|
LoopRowTableRenderPolicy policy = new LoopRowTableRenderPolicy();
|
||||||
Configure config = Configure.builder().bind("familyList", policy).build();
|
Configure config = Configure.builder().bind("familyList", policy).build();
|
||||||
|
|
||||||
XWPFTemplate.compile(sysOfficeTemplateUtil.getTemplate("difficulty_apply"), config)
|
try (InputStream input = sysOfficeTemplateUtil.getTemplate("difficulty_apply")) {
|
||||||
.render(docData)
|
zipOutputStream.write(sysOfficeTemplateUtil.renderTemplate(input, docData, config, false, "difficulthelp:batch:" + record.getString("id")));
|
||||||
.write(zipOutputStream);
|
}
|
||||||
zipOutputStream.closeEntry();
|
zipOutputStream.closeEntry();
|
||||||
}
|
}
|
||||||
zipOutputStream.flush();
|
zipOutputStream.flush();
|
||||||
@@ -379,17 +375,18 @@ public class DifficultHelpReadingController {
|
|||||||
String[] taskKeys = {"36ebafda-44c2-4bd3-bd7f-10839a575a0d", "715ece82-4ae3-433c-ad18-ed875f45d1e3", "e405f96c-5fc0-4f63-b323-e69dfe853253"};
|
String[] taskKeys = {"36ebafda-44c2-4bd3-bd7f-10839a575a0d", "715ece82-4ae3-433c-ad18-ed875f45d1e3", "e405f96c-5fc0-4f63-b323-e69dfe853253"};
|
||||||
String[] fields = {"firstApproval", "secondApproval", "thirdApproval"};
|
String[] fields = {"firstApproval", "secondApproval", "thirdApproval"};
|
||||||
for (String field : fields) {
|
for (String field : fields) {
|
||||||
for (String suffix : List.of("", "Opinion", "User", "Date", "Year", "Month", "Day", "Sign")) docData.put(field + suffix, "");
|
for (String suffix : List.of("", "Opinion", "User", "Date", "Year", "Month", "Day", "Sign")) docData.put(field + suffix, "Sign".equals(suffix) ? null : "");
|
||||||
}
|
}
|
||||||
ProcessInstance instance = dao.fetch(ProcessInstance.class, Cnd.where("businessNo", "=", businessId).desc("id"));
|
ProcessInstance instance = dao.fetch(ProcessInstance.class, Cnd.where("businessNo", "=", businessId).desc("id"));
|
||||||
if (instance == null) return;
|
if (instance == null) return;
|
||||||
List<ProcessTask> tasks = dao.query(ProcessTask.class, Cnd.where("processInstanceId", "=", instance.getId()).asc("id"));
|
List<ProcessTask> tasks = dao.query(ProcessTask.class, Cnd.where("processInstanceId", "=", instance.getId()).asc("id"));
|
||||||
for (ProcessTask task : tasks) {
|
for (ProcessTask task : tasks) {
|
||||||
ProcessTaskVO taskVO = flowEngine.processTaskService().findById(task.getId());
|
ProcessTaskVO taskVO = flowEngine.processTaskService().findById(task.getId());
|
||||||
if ("startTask".equals(task.getTaskName()) || (taskVO.getExt() != null && Boolean.TRUE.equals(taskVO.getExt().getBool("isFirstTaskNode")))) {
|
if ("startTask".equals(task.getTaskName()) || (!List.of(taskKeys).contains(task.getTaskName())
|
||||||
|
&& taskVO.getExt() != null && Boolean.TRUE.equals(taskVO.getExt().getBool("isFirstTaskNode")))) {
|
||||||
// 重新申请后,仅导出本轮审批,避免混入上一次退回或撤销前的意见。
|
// 重新申请后,仅导出本轮审批,避免混入上一次退回或撤销前的意见。
|
||||||
for (String field : fields) {
|
for (String field : fields) {
|
||||||
for (String suffix : List.of("", "Opinion", "User", "Date", "Year", "Month", "Day", "Sign")) docData.put(field + suffix, "");
|
for (String suffix : List.of("", "Opinion", "User", "Date", "Year", "Month", "Day", "Sign")) docData.put(field + suffix, "Sign".equals(suffix) ? null : "");
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -453,22 +450,9 @@ public class DifficultHelpReadingController {
|
|||||||
String fileName = FileUtil.mainName(sysOfficeTemplateUtil.getTemplateFileName(templateName)) + "_" + difficultHelp.getUserName() + "_" +
|
String fileName = FileUtil.mainName(sysOfficeTemplateUtil.getTemplateFileName(templateName)) + "_" + difficultHelp.getUserName() + "_" +
|
||||||
DateUtil.format(difficultHelp.getApplyTime(), "yyyyMMdd") + ".pdf";
|
DateUtil.format(difficultHelp.getApplyTime(), "yyyyMMdd") + ".pdf";
|
||||||
|
|
||||||
try (ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream()) {
|
try (InputStream input = getApplyTemplate(templateName)) {
|
||||||
XWPFTemplate.compile(getApplyTemplate(templateName),config)
|
byte[] bytes = sysOfficeTemplateUtil.renderTemplate(input, docData, config, true, "difficulthelp:" + difficultHelp.getId());
|
||||||
.render(docData)
|
CommonDownloadUtil.download(fileName, bytes, response);
|
||||||
.writeAndClose(byteArrayOutputStream);
|
|
||||||
byte[] bytes = byteArrayOutputStream.toByteArray();
|
|
||||||
File sourceFile = File.createTempFile("file_convert_origin", ".docx");
|
|
||||||
Files.write(sourceFile.toPath(), bytes, StandardOpenOption.WRITE);
|
|
||||||
|
|
||||||
File pdfFile = File.createTempFile("file_convert", ".pdf");
|
|
||||||
OfficePlusUtil.convert(sourceFile.getPath(), pdfFile.getPath());
|
|
||||||
CommonDownloadUtil.download(fileName, IoUtil.readBytes(FileUtil.getInputStream(pdfFile)), response);
|
|
||||||
// 删除临时文件
|
|
||||||
FileUtil.del(sourceFile);
|
|
||||||
FileUtil.del(pdfFile.toPath());
|
|
||||||
} catch (IOException e) {
|
|
||||||
log.error("困难慰问申请表导出PDF失败,id:{},错误信息:{}", difficultHelp.getId(), e.getMessage());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -478,18 +462,15 @@ public class DifficultHelpReadingController {
|
|||||||
String fileName = FileUtil.mainName(sysOfficeTemplateUtil.getTemplateFileName(templateName)) + "_" + difficultHelp.getUserName() + "_" +
|
String fileName = FileUtil.mainName(sysOfficeTemplateUtil.getTemplateFileName(templateName)) + "_" + difficultHelp.getUserName() + "_" +
|
||||||
DateUtil.format(difficultHelp.getApplyTime(), "yyyyMMdd") + ".docx";
|
DateUtil.format(difficultHelp.getApplyTime(), "yyyyMMdd") + ".docx";
|
||||||
|
|
||||||
try (ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream()) {
|
try (InputStream input = getApplyTemplate(templateName)) {
|
||||||
XWPFTemplate.compile(getApplyTemplate(templateName),config)
|
byte[] bytes = sysOfficeTemplateUtil.renderTemplate(input, docData, config, false, "difficulthelp:" + difficultHelp.getId());
|
||||||
.render(docData)
|
CommonDownloadUtil.download(fileName, bytes, response);
|
||||||
.writeAndClose(byteArrayOutputStream);
|
|
||||||
CommonDownloadUtil.download(fileName, byteArrayOutputStream.toByteArray(), response);
|
|
||||||
} catch (IOException e) {
|
|
||||||
log.error("困难慰问申请表导出Word失败,id:{},错误信息:{}", difficultHelp.getId(), e.getMessage());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@At
|
@At
|
||||||
@Ok("void")
|
@Ok("void")
|
||||||
|
@SaCheckPermission("difficultHelp.reading")
|
||||||
public void exportSummary(DifficultHelpPageParam pageParam,String flag,
|
public void exportSummary(DifficultHelpPageParam pageParam,String flag,
|
||||||
HttpServletResponse response) throws Exception {
|
HttpServletResponse response) throws Exception {
|
||||||
NutMap result = new NutMap();
|
NutMap result = new NutMap();
|
||||||
@@ -519,7 +500,7 @@ public class DifficultHelpReadingController {
|
|||||||
$condition
|
$condition
|
||||||
""");
|
""");
|
||||||
Cnd cnd = Cnd.NEW();
|
Cnd cnd = Cnd.NEW();
|
||||||
pageParam.buildSearch(cnd, "info.");
|
pageParam.buildSearch(cnd, "info.", false);
|
||||||
cnd.groupBy("info.id");
|
cnd.groupBy("info.id");
|
||||||
sql.setCondition(cnd);
|
sql.setCondition(cnd);
|
||||||
List<NutMap> list = difficultHelpCommonService.listMap(sql);
|
List<NutMap> list = difficultHelpCommonService.listMap(sql);
|
||||||
@@ -562,15 +543,13 @@ public class DifficultHelpReadingController {
|
|||||||
throw new RuntimeException("导出Excel汇总表失败:" + e.getMessage());
|
throw new RuntimeException("导出Excel汇总表失败:" + e.getMessage());
|
||||||
}
|
}
|
||||||
} else if ("docx".equals(flag)) {
|
} else if ("docx".equals(flag)) {
|
||||||
try (ByteArrayOutputStream out = new ByteArrayOutputStream()) {
|
try (InputStream input = sysOfficeTemplateUtil.getTemplate(resource)) {
|
||||||
Configure config = Configure.builder()
|
Configure config = Configure.builder()
|
||||||
.bind("da", new LoopRowTableRenderPolicy())
|
.bind("da", new LoopRowTableRenderPolicy())
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
XWPFTemplate.compile(sysOfficeTemplateUtil.getTemplate(resource), config)
|
byte[] bytes = sysOfficeTemplateUtil.renderTemplate(input, result, config, false, "difficulthelp:summary:" + resource);
|
||||||
.render(result)
|
CommonDownloadUtil.download(fileName + ".docx", bytes, response);
|
||||||
.writeAndClose(out);
|
|
||||||
CommonDownloadUtil.download(fileName + ".docx", out.toByteArray(), response);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+255
@@ -0,0 +1,255 @@
|
|||||||
|
package com.budwk.app.zhgh.staffbenefit.specialcondolence.controller;
|
||||||
|
|
||||||
|
import cn.dev33.satoken.annotation.SaCheckLogin;
|
||||||
|
import cn.dev33.satoken.annotation.SaCheckRole;
|
||||||
|
import cn.dev33.satoken.annotation.SaCheckPermission;
|
||||||
|
import cn.dev33.satoken.annotation.SaMode;
|
||||||
|
import cn.hutool.core.date.DateUtil;
|
||||||
|
import cn.hutool.core.lang.Dict;
|
||||||
|
import cn.hutool.core.util.StrUtil;
|
||||||
|
import com.budwk.app.base.annotation.SLog;
|
||||||
|
import com.budwk.app.base.constant.RoleConstant;
|
||||||
|
import com.budwk.app.base.page.Pagination;
|
||||||
|
import com.budwk.app.base.result.Result;
|
||||||
|
import com.budwk.app.base.utils.SysOfficeTemplateUtil;
|
||||||
|
import com.budwk.app.flow.constant.FlowConst;
|
||||||
|
import com.budwk.app.flow.engine.FlowEngine;
|
||||||
|
import com.budwk.app.flow.entity.ProcessInstance;
|
||||||
|
import com.budwk.app.flow.entity.ProcessTask;
|
||||||
|
import com.budwk.app.flow.enums.ProcessSubmitTypeEnum;
|
||||||
|
import com.budwk.app.flow.service.FlowCommonService;
|
||||||
|
import com.budwk.app.sys.views.View_user;
|
||||||
|
import com.budwk.app.web.commons.auth.utils.AuthUtil;
|
||||||
|
import com.budwk.app.web.commons.auth.utils.SecurityUtil;
|
||||||
|
import com.budwk.app.zhgh.democratic.suggestionBox.models.SuggestionBox;
|
||||||
|
import com.budwk.app.zhgh.staffbenefit.specialcondolence.model.SpecialCondolence;
|
||||||
|
import com.budwk.app.zhgh.staffbenefit.specialcondolence.service.SpecialCondolenceService;
|
||||||
|
import io.swagger.annotations.Api;
|
||||||
|
import io.swagger.annotations.ApiOperation;
|
||||||
|
import org.nutz.aop.interceptor.ioc.TransAop;
|
||||||
|
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.aop.Aop;
|
||||||
|
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 java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ClassName SpecialCondolenceApplyController
|
||||||
|
* @Author JyuHsin
|
||||||
|
* @Date 2025/8/20 15:40
|
||||||
|
* @Version 1.0
|
||||||
|
* @Description TODO
|
||||||
|
*/
|
||||||
|
@SaCheckRole("BRANCH_UNION_CHAIRMAN")
|
||||||
|
@IocBean
|
||||||
|
@At("/platform/special_condolence/apply")
|
||||||
|
@Api("特殊慰问申请")
|
||||||
|
@Ok("json:full")
|
||||||
|
public class SpecialCondolenceApplyController {
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
private Dao dao;
|
||||||
|
@Inject
|
||||||
|
private FlowEngine flowEngine;
|
||||||
|
@Inject
|
||||||
|
private SpecialCondolenceService specialcondolenceService;
|
||||||
|
@Inject
|
||||||
|
private FlowCommonService flowCommonService;
|
||||||
|
@Inject
|
||||||
|
private SysOfficeTemplateUtil sysOfficeTemplateUtil;
|
||||||
|
|
||||||
|
@At("/")
|
||||||
|
@Ok("beetl:/platform/zhgh/staffbenefit/specialcondolence/apply/index.html")
|
||||||
|
@SaCheckPermission("special_condolence.apply")
|
||||||
|
public void index() {}
|
||||||
|
|
||||||
|
@At("/h5")
|
||||||
|
@Ok("beetl:/platform/zhghh5/staffbenefit/specialcondolence/apply/index.html")
|
||||||
|
@SaCheckPermission("h5.special_condolence.apply")
|
||||||
|
public void h5Index() {}
|
||||||
|
|
||||||
|
@At
|
||||||
|
@ApiOperation("保存申请")
|
||||||
|
@SaCheckPermission(value = {"special_condolence.apply", "h5.special_condolence.apply"}, mode = SaMode.OR)
|
||||||
|
@SLog(tag = "特殊慰问系统-慰问申请", msg = "保存申请")
|
||||||
|
public Result save(@Param("data") SpecialCondolence specialcondolence) {
|
||||||
|
if(StrUtil.isBlank(specialcondolence.getId())) specialcondolence.setCreateTime(DateUtil.now());
|
||||||
|
prepareApplication(specialcondolence);
|
||||||
|
specialcondolenceService.saveApplication(specialcondolence);
|
||||||
|
return Result.success();
|
||||||
|
}
|
||||||
|
|
||||||
|
@At
|
||||||
|
@ApiOperation("提交申请")
|
||||||
|
@SaCheckPermission(value = {"special_condolence.apply", "h5.special_condolence.apply"}, mode = SaMode.OR)
|
||||||
|
@SLog(tag = "特殊慰问系统-慰问申请", msg = "提交申请")
|
||||||
|
@Aop(TransAop.READ_COMMITTED)
|
||||||
|
public Result submit(@Param("data") SpecialCondolence specialcondolence) {
|
||||||
|
if (StrUtil.isBlank(specialcondolence.getRemark()) || specialcondolence.getRemark().trim().length() > 500) throw new com.budwk.app.base.exception.BaseException("请填写500字以内的申请事由");
|
||||||
|
if (StrUtil.isBlank(specialcondolence.getSignature())) throw new com.budwk.app.base.exception.BaseException("请完成申请人签字");
|
||||||
|
if(StrUtil.isBlank(specialcondolence.getId())) specialcondolence.setCreateTime(DateUtil.now());
|
||||||
|
prepareApplication(specialcondolence);
|
||||||
|
specialcondolenceService.saveApplication(specialcondolence);
|
||||||
|
// 开启流程实例
|
||||||
|
Dict args = Dict.create();
|
||||||
|
args.set(FlowConst.SUBMIT_TYPE, ProcessSubmitTypeEnum.APPLY.getCode());
|
||||||
|
args.set(FlowConst.FORM_DATA, specialcondolence);
|
||||||
|
ProcessInstance instance = flowEngine.startProcessInstanceByKey("TSWW", specialcondolence.getId(), SecurityUtil.getUserId(), args);
|
||||||
|
|
||||||
|
// 自动完成第一个申请任务
|
||||||
|
List<ProcessTask> doingTaskList = flowEngine.processTaskService().getDoingTaskList(instance.getId(), null);
|
||||||
|
for (ProcessTask task : doingTaskList) {
|
||||||
|
flowEngine.executeProcessTask(task.getId(), SecurityUtil.getUserId(), args);
|
||||||
|
}
|
||||||
|
return Result.success();
|
||||||
|
}
|
||||||
|
|
||||||
|
@At
|
||||||
|
@ApiOperation("重新提交申请")
|
||||||
|
@Aop(TransAop.READ_COMMITTED)
|
||||||
|
@SaCheckPermission(value = {"special_condolence.apply", "h5.special_condolence.apply"}, mode = SaMode.OR)
|
||||||
|
public Result submitAgain(@Param("data") SpecialCondolence specialcondolence, @Param("taskId") Long taskId) {
|
||||||
|
if (StrUtil.isBlank(specialcondolence.getRemark()) || specialcondolence.getRemark().trim().length() > 500) throw new com.budwk.app.base.exception.BaseException("请填写500字以内的申请事由");
|
||||||
|
if (StrUtil.isBlank(specialcondolence.getSignature())) throw new com.budwk.app.base.exception.BaseException("请完成申请人签字");
|
||||||
|
ProcessTask task = taskId == null ? null : dao.fetch(ProcessTask.class, taskId);
|
||||||
|
ProcessInstance instance = task == null ? null : dao.fetch(ProcessInstance.class, task.getProcessInstanceId());
|
||||||
|
if (instance == null || !StrUtil.equals(instance.getBusinessNo(), specialcondolence.getId())
|
||||||
|
|| !"startTask".equals(task.getTaskName()) || !SecurityUtil.getUserId().equals(instance.getOperator())) {
|
||||||
|
throw new com.budwk.app.base.exception.BaseException("申请任务不匹配");
|
||||||
|
}
|
||||||
|
prepareApplication(specialcondolence);
|
||||||
|
specialcondolenceService.saveApplication(specialcondolence);
|
||||||
|
|
||||||
|
Dict dict = Dict.create();
|
||||||
|
dict.set(FlowConst.PROCESS_TASK_ID_KEY, taskId);
|
||||||
|
dict.set(FlowConst.FORM_DATA, specialcondolence);
|
||||||
|
dict.set(FlowConst.SUBMIT_TYPE, ProcessSubmitTypeEnum.RE_APPLY.getCode());
|
||||||
|
flowCommonService.executeTask(dict);
|
||||||
|
return Result.success();
|
||||||
|
}
|
||||||
|
|
||||||
|
@At
|
||||||
|
@ApiOperation("查询用户")
|
||||||
|
@SaCheckPermission(value = {"special_condolence.apply", "h5.special_condolence.apply"}, mode = SaMode.OR)
|
||||||
|
public Object listUser(String keyword) {
|
||||||
|
Sql sql = Sqls.create("""
|
||||||
|
select
|
||||||
|
u.id,
|
||||||
|
u.idCard,
|
||||||
|
u.personType,
|
||||||
|
bank.bankOfDeposit,
|
||||||
|
bank.bankUserName,
|
||||||
|
bank.bankCardNumber,
|
||||||
|
username as userName,
|
||||||
|
loginname as loginName,
|
||||||
|
sex,
|
||||||
|
mobile,
|
||||||
|
technicalTitle,
|
||||||
|
IFNULL(unitname, '暂无') as unitName,
|
||||||
|
unitid as unitId,
|
||||||
|
unionid as unionId,
|
||||||
|
unionname as unionName
|
||||||
|
from
|
||||||
|
vw_user u
|
||||||
|
LEFT JOIN (
|
||||||
|
SELECT idCard, bankOfDeposit, bankUserName, bankCardNumber,
|
||||||
|
ROW_NUMBER() OVER (PARTITION BY idCard ORDER BY createdAt DESC, id DESC) rn
|
||||||
|
FROM special_condolence_recipient WHERE delFlag = false
|
||||||
|
) bank ON bank.idCard = u.idCard AND bank.rn = 1 AND u.idCard <> ''
|
||||||
|
$condition
|
||||||
|
""");
|
||||||
|
Cnd cnd = Cnd.NEW();
|
||||||
|
if (StrUtil.isNotBlank(keyword)) {
|
||||||
|
SqlExpressionGroup seg = new SqlExpressionGroup();
|
||||||
|
seg.or(View_user::getLoginname, "like", "%" + keyword + "%");
|
||||||
|
seg.or(View_user::getUsername, "like", "%" + keyword + "%");
|
||||||
|
cnd.and(seg);
|
||||||
|
}
|
||||||
|
if (StrUtil.isBlank(SecurityUtil.getUnionId())) throw new com.budwk.app.base.exception.BaseException("申请人未关联分工会");
|
||||||
|
cnd.and("u.unionId", "=", SecurityUtil.getUnionId());
|
||||||
|
sql.setCondition(cnd);
|
||||||
|
Pagination pagination = specialcondolenceService.listPageMap(1, 50, sql);
|
||||||
|
return Result.success(pagination.getList());
|
||||||
|
}
|
||||||
|
|
||||||
|
@At
|
||||||
|
@Ok("void")
|
||||||
|
@SaCheckPermission(value = {"special_condolence.apply", "h5.special_condolence.apply"}, mode = SaMode.OR)
|
||||||
|
public void importTemplate(javax.servlet.http.HttpServletResponse response) throws Exception {
|
||||||
|
String templateCode = "special_condolence_import";
|
||||||
|
try (java.io.InputStream input = sysOfficeTemplateUtil.getTemplate(templateCode)) {
|
||||||
|
com.budwk.app.base.utils.CommonDownloadUtil.download(
|
||||||
|
sysOfficeTemplateUtil.getTemplateFileName(templateCode), input.readAllBytes(), response);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@At
|
||||||
|
@SaCheckPermission(value = {"special_condolence.apply", "h5.special_condolence.apply"}, mode = SaMode.OR)
|
||||||
|
@org.nutz.mvc.annotation.AdaptBy(type = org.nutz.mvc.upload.UploadAdaptor.class, args = {"ioc:fileUpload"})
|
||||||
|
public Result importRecipients(@Param("file") org.nutz.mvc.upload.TempFile file) throws Exception {
|
||||||
|
if (file == null) throw new com.budwk.app.base.exception.BaseException("请选择Excel文件");
|
||||||
|
if (!file.getSubmittedFileName().toLowerCase(java.util.Locale.ROOT).matches(".*\\.(xlsx|xls)$")) throw new com.budwk.app.base.exception.BaseException("仅支持xlsx、xls文件");
|
||||||
|
String[] headers = {"慰问对象", "工号", "身份证号码", "开户行", "户名", "收款账户"};
|
||||||
|
String[] fields = {"helpUserName", "helpLoginName", "idCard", "bankOfDeposit", "bankUserName", "bankCardNumber"};
|
||||||
|
java.util.List<cn.hutool.json.JSONObject> result = new java.util.ArrayList<>();
|
||||||
|
try (java.io.InputStream input = new java.io.FileInputStream(file.getFile());
|
||||||
|
org.apache.poi.ss.usermodel.Workbook workbook = org.apache.poi.ss.usermodel.WorkbookFactory.create(input)) {
|
||||||
|
if (workbook.getNumberOfSheets() == 0) throw new com.budwk.app.base.exception.BaseException("Excel中没有工作表");
|
||||||
|
org.apache.poi.ss.usermodel.Sheet sheet = workbook.getSheetAt(0);
|
||||||
|
org.apache.poi.ss.usermodel.DataFormatter formatter = new org.apache.poi.ss.usermodel.DataFormatter();
|
||||||
|
org.apache.poi.ss.usermodel.Row header = sheet.getRow(0);
|
||||||
|
for (int c = 0; c < headers.length; c++) {
|
||||||
|
if (header == null || !headers[c].equals(formatter.formatCellValue(header.getCell(c)).trim())) throw new com.budwk.app.base.exception.BaseException("表头不正确,请下载导入模板");
|
||||||
|
}
|
||||||
|
if (sheet.getLastRowNum() > 1000) throw new com.budwk.app.base.exception.BaseException("最多导入1000行");
|
||||||
|
for (int r = 1; r <= sheet.getLastRowNum(); r++) {
|
||||||
|
org.apache.poi.ss.usermodel.Row excelRow = sheet.getRow(r);
|
||||||
|
if (excelRow == null) continue;
|
||||||
|
cn.hutool.json.JSONObject row = new cn.hutool.json.JSONObject();
|
||||||
|
boolean empty = true;
|
||||||
|
for (int c = 0; c < fields.length; c++) {
|
||||||
|
org.apache.poi.ss.usermodel.Cell cell = excelRow.getCell(c);
|
||||||
|
String value = formatter.formatCellValue(cell).trim();
|
||||||
|
if (c != 1 && cell != null && cell.getCellType() == org.apache.poi.ss.usermodel.CellType.FORMULA) throw new com.budwk.app.base.exception.BaseException("第" + (r + 1) + "行不支持公式,请填写实际值");
|
||||||
|
if ((c == 2 || c == 5) && cell != null && cell.getCellType() == org.apache.poi.ss.usermodel.CellType.NUMERIC) throw new com.budwk.app.base.exception.BaseException("第" + (r + 1) + "行工号、身份证和收款账户请使用文本格式,避免数字失真");
|
||||||
|
row.set(fields[c], value);
|
||||||
|
empty = empty && value.isEmpty();
|
||||||
|
}
|
||||||
|
if (empty) continue;
|
||||||
|
for (int c = 0; c < fields.length; c++) {
|
||||||
|
if (c != 1 && row.getStr(fields[c]).isEmpty()) throw new com.budwk.app.base.exception.BaseException("第" + (r + 1) + "行:请填写" + headers[c]);
|
||||||
|
}
|
||||||
|
if (!com.budwk.app.zhgh.staffbenefit.specialcondolence.service.SpecialCondolenceRecipients.validIdCard(row.getStr("idCard"))) throw new com.budwk.app.base.exception.BaseException("第" + (r + 1) + "行身份证号码格式不正确");
|
||||||
|
if (!row.getStr("bankCardNumber").matches("[0-9]{6,30}")) throw new com.budwk.app.base.exception.BaseException("第" + (r + 1) + "行收款账户格式不正确");
|
||||||
|
com.budwk.app.zhgh.staffbenefit.specialcondolence.service.SpecialCondolenceRecipients.resolveUser(row, dao, "第" + (r + 1) + "行:");
|
||||||
|
result.add(row);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (result.isEmpty()) throw new com.budwk.app.base.exception.BaseException("没有可导入的数据");
|
||||||
|
return Result.success(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void prepareApplication(SpecialCondolence info) {
|
||||||
|
if (StrUtil.isNotBlank(info.getId())) {
|
||||||
|
SpecialCondolence existing = dao.fetch(SpecialCondolence.class, info.getId());
|
||||||
|
if (existing == null || !SecurityUtil.getUserId().equals(existing.getCreatedBy())) {
|
||||||
|
throw new com.budwk.app.base.exception.BaseException("只能修改本人申请");
|
||||||
|
}
|
||||||
|
info.setCreatedBy(existing.getCreatedBy());
|
||||||
|
}
|
||||||
|
info.setApplyUserId(SecurityUtil.getUserId());
|
||||||
|
info.setApplyUserName(SecurityUtil.getUserUsername());
|
||||||
|
info.setApplyLoginName(SecurityUtil.getUserLoginname());
|
||||||
|
info.setApplyUnionId(SecurityUtil.getUnionId());
|
||||||
|
info.setApplyUnitId(SecurityUtil.getUnitId());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
+60
@@ -0,0 +1,60 @@
|
|||||||
|
package com.budwk.app.zhgh.staffbenefit.specialcondolence.controller;
|
||||||
|
|
||||||
|
import cn.dev33.satoken.annotation.SaCheckLogin;
|
||||||
|
import cn.hutool.core.lang.Dict;
|
||||||
|
import cn.hutool.core.util.StrUtil;
|
||||||
|
import com.budwk.app.base.exception.BaseException;
|
||||||
|
import com.budwk.app.base.result.Result;
|
||||||
|
import com.budwk.app.flow.constant.FlowConst;
|
||||||
|
import com.budwk.app.flow.entity.ProcessInstance;
|
||||||
|
import com.budwk.app.flow.entity.ProcessTask;
|
||||||
|
import com.budwk.app.flow.service.FlowCommonService;
|
||||||
|
import com.budwk.app.zhgh.staffbenefit.specialcondolence.model.SpecialCondolence;
|
||||||
|
import org.nutz.aop.interceptor.ioc.TransAop;
|
||||||
|
import org.nutz.dao.Dao;
|
||||||
|
import org.nutz.ioc.aop.Aop;
|
||||||
|
import org.nutz.ioc.loader.annotation.Inject;
|
||||||
|
import org.nutz.ioc.loader.annotation.IocBean;
|
||||||
|
import org.nutz.json.Json;
|
||||||
|
import org.nutz.mvc.annotation.At;
|
||||||
|
import org.nutz.mvc.annotation.Ok;
|
||||||
|
import org.nutz.mvc.annotation.Param;
|
||||||
|
|
||||||
|
@IocBean
|
||||||
|
@Ok("json")
|
||||||
|
@At("/platform/special_condolence/approval")
|
||||||
|
public class SpecialCondolenceApprovalController {
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
private Dao dao;
|
||||||
|
@Inject
|
||||||
|
private FlowCommonService flowCommonService;
|
||||||
|
|
||||||
|
@At
|
||||||
|
@SaCheckLogin
|
||||||
|
@Aop(TransAop.READ_COMMITTED)
|
||||||
|
public Result executeTask(@Param("data") String data) {
|
||||||
|
Dict args = Json.fromJson(Dict.class, data);
|
||||||
|
if (args == null || args.getLong(FlowConst.PROCESS_TASK_ID_KEY) == null) {
|
||||||
|
throw new BaseException("审批任务不能为空");
|
||||||
|
}
|
||||||
|
ProcessTask task = dao.fetch(ProcessTask.class, args.getLong(FlowConst.PROCESS_TASK_ID_KEY));
|
||||||
|
if (task == null) throw new BaseException("审批任务不存在");
|
||||||
|
if (!"c438972e-2f67-4907-b229-cb7aa17da147".equals(task.getTaskName())
|
||||||
|
&& !"7f560675-aeea-4254-a57e-957d03d6b786".equals(task.getTaskName())
|
||||||
|
&& !"af363a4e-fc56-42a0-9906-8c7a2814006b".equals(task.getTaskName())) {
|
||||||
|
throw new BaseException("当前任务不是特殊慰问审批任务");
|
||||||
|
}
|
||||||
|
ProcessInstance instance = dao.fetch(ProcessInstance.class, task.getProcessInstanceId());
|
||||||
|
com.budwk.app.flow.entity.ProcessDefine define = instance == null ? null : dao.fetch(com.budwk.app.flow.entity.ProcessDefine.class, instance.getProcessDefineId());
|
||||||
|
SpecialCondolence info = define == null || !"TSWW".equals(define.getName()) ? null : dao.fetch(SpecialCondolence.class, instance.getBusinessNo());
|
||||||
|
if (info == null) throw new BaseException("特殊慰问申请不存在");
|
||||||
|
if (StrUtil.isBlank(args.getStr("tf_sign"))) throw new BaseException("请完成审批签字");
|
||||||
|
if (StrUtil.isBlank(args.getStr("tf_opinion"))) throw new BaseException("请填写审批意见");
|
||||||
|
|
||||||
|
// 参与者权限由流程引擎校验,业务入口不接受客户端指定管理员代办。
|
||||||
|
args.remove(FlowConst.EXT_ENABLE_OPERATOR);
|
||||||
|
flowCommonService.executeTask(args);
|
||||||
|
return Result.success();
|
||||||
|
}
|
||||||
|
}
|
||||||
+168
@@ -0,0 +1,168 @@
|
|||||||
|
package com.budwk.app.zhgh.staffbenefit.specialcondolence.controller;
|
||||||
|
|
||||||
|
import cn.dev33.satoken.annotation.SaCheckPermission;
|
||||||
|
import cn.dev33.satoken.annotation.SaMode;
|
||||||
|
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.PageUtil;
|
||||||
|
import com.budwk.app.flow.enums.ProcessTaskStateEnum;
|
||||||
|
import com.budwk.app.web.commons.auth.utils.AuthUtil;
|
||||||
|
import com.budwk.app.web.commons.auth.utils.SecurityUtil;
|
||||||
|
import com.budwk.app.zhgh.staffbenefit.specialcondolence.model.SpecialCondolence;
|
||||||
|
import com.budwk.app.zhgh.staffbenefit.specialcondolence.service.SpecialCondolenceService;
|
||||||
|
import io.swagger.annotations.Api;
|
||||||
|
import io.swagger.annotations.ApiOperation;
|
||||||
|
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.dao.util.cri.Static;
|
||||||
|
import org.nutz.ioc.loader.annotation.Inject;
|
||||||
|
import org.nutz.ioc.loader.annotation.IocBean;
|
||||||
|
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 java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ClassName SpecialCondolenceFourthApprovalController
|
||||||
|
* @Author JyuHsin
|
||||||
|
* @Date 2025/7/29 16:23
|
||||||
|
* @Version 1.0
|
||||||
|
* @Description TODO
|
||||||
|
*/
|
||||||
|
@IocBean
|
||||||
|
@At("/platform/special_condolence/fourthApproval")
|
||||||
|
@Api("特殊慰问四级审核")
|
||||||
|
@Ok("json:full")
|
||||||
|
public class SpecialCondolenceFourthApprovalController {
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
private Dao dao;
|
||||||
|
@Inject
|
||||||
|
private SpecialCondolenceService specialcondolenceService;
|
||||||
|
|
||||||
|
@At("/")
|
||||||
|
@Ok("beetl:/platform/zhgh/staffbenefit/specialcondolence/fourthApproval/index.html")
|
||||||
|
@SaCheckPermission("special_condolence.fourthApproval")
|
||||||
|
public void index() {}
|
||||||
|
|
||||||
|
@At("/h5")
|
||||||
|
@Ok("beetl:/platform/zhghh5/staffbenefit/specialcondolence/fourthApproval/index.html")
|
||||||
|
@SaCheckPermission("h5.special_condolence.fourthApproval")
|
||||||
|
public void h5Index() {}
|
||||||
|
|
||||||
|
@At
|
||||||
|
@ApiOperation("分页查询")
|
||||||
|
@SaCheckPermission(value = {"special_condolence.fourthApproval", "h5.special_condolence.fourthApproval"}, mode = SaMode.OR)
|
||||||
|
public Result pageData(PageForm pageForm,
|
||||||
|
@Param(value = "year") Integer year,
|
||||||
|
@Param(value = "type") String type,
|
||||||
|
@Param(value = "unionId") String unionId,
|
||||||
|
@Param(value = "unitId") String unitId,
|
||||||
|
@Param(value = "approval") Boolean approval) {
|
||||||
|
Sql sql = Sqls.create("""
|
||||||
|
SELECT
|
||||||
|
info.*,
|
||||||
|
COALESCE(recipientTotals.recipientCount, 0) AS recipientCount,
|
||||||
|
type.name as typeName,
|
||||||
|
ins.id AS instanceId,
|
||||||
|
ins.businessNo,
|
||||||
|
ins.state instanceState,
|
||||||
|
ins.variable instanceVariable,
|
||||||
|
ins.processDefineId instanceProcessDefineId,
|
||||||
|
t.id taskId,
|
||||||
|
t.taskName AS taskKey,
|
||||||
|
t.displayName taskName,
|
||||||
|
t.taskType,
|
||||||
|
t.performType taskPerformType,
|
||||||
|
t.taskState,
|
||||||
|
t.finishTime,
|
||||||
|
t.taskParentId,
|
||||||
|
t.variable taskVariable,
|
||||||
|
IFNULL(GROUP_CONCAT(DISTINCT nt.displayName),'结束') curTaskName,
|
||||||
|
IF(rt.id IS NOT NULL, 1, 0) AS canRevoke
|
||||||
|
FROM
|
||||||
|
wf_process_task t
|
||||||
|
LEFT JOIN wf_process_instance ins ON ins.id = t.processInstanceId
|
||||||
|
LEFT JOIN special_condolence info ON info.id = ins.businessNo
|
||||||
|
LEFT JOIN wf_process_task_actor ta ON ta.processTaskId = t.id
|
||||||
|
LEFT JOIN (
|
||||||
|
SELECT applyId, COUNT(*) AS recipientCount
|
||||||
|
FROM special_condolence_recipient
|
||||||
|
WHERE delFlag = false
|
||||||
|
GROUP BY applyId
|
||||||
|
) recipientTotals ON recipientTotals.applyId = info.id
|
||||||
|
LEFT JOIN special_condolence_type type ON info.type = type.id
|
||||||
|
LEFT JOIN wf_process_task nt ON nt.processInstanceId = ins.id AND nt.taskState = 10
|
||||||
|
LEFT JOIN wf_process_task rt ON rt.processInstanceId = ins.id AND rt.taskParentId = t.id AND rt.taskState = 10
|
||||||
|
$condition
|
||||||
|
""");
|
||||||
|
Cnd cnd = Cnd.NEW();
|
||||||
|
cnd.and("info.id", "is not", null);
|
||||||
|
cnd.and(new Static("""
|
||||||
|
NOT EXISTS (
|
||||||
|
SELECT 1 FROM wf_process_task newer
|
||||||
|
WHERE newer.processInstanceId = t.processInstanceId
|
||||||
|
AND newer.taskName = t.taskName
|
||||||
|
AND newer.id > t.id
|
||||||
|
)
|
||||||
|
"""));
|
||||||
|
if (StrUtil.isNotBlank(pageForm.getSearchKeyword())) {
|
||||||
|
SqlExpressionGroup seg = new SqlExpressionGroup();
|
||||||
|
seg.or(SpecialCondolence::getHelpUserName, "like", "%" + pageForm.getSearchKeyword() + "%");
|
||||||
|
seg.or(SpecialCondolence::getHelpLoginName, "like", "%" + pageForm.getSearchKeyword() + "%");
|
||||||
|
cnd.and(seg);
|
||||||
|
}
|
||||||
|
cnd.andEX("info.type", "=", type);
|
||||||
|
cnd.andEX("YEAR(info.createTime)", "=", year);
|
||||||
|
cnd.andEX("info.applyUnionId", "=", unionId);
|
||||||
|
cnd.andEX("info.applyUnitId", "=", unitId);
|
||||||
|
|
||||||
|
cnd.and("t.taskName", "=", "af363a4e-fc56-42a0-9906-8c7a2814006b");
|
||||||
|
if (!"superadmin".equals(SecurityUtil.getUserLoginname()) && !AuthUtil.hasRoleOr(RoleConstant.SYSADMIN.name())) {
|
||||||
|
Sql unitSql = Sqls.queryString("""
|
||||||
|
SELECT DISTINCT ur.unitId
|
||||||
|
FROM sys_user_role ur
|
||||||
|
INNER JOIN sys_role r ON r.id = ur.roleId
|
||||||
|
WHERE ur.userId = @userId
|
||||||
|
AND ur.enable = true
|
||||||
|
AND r.disabled = false
|
||||||
|
AND r.code = @roleCode
|
||||||
|
AND ur.unitId IS NOT NULL
|
||||||
|
AND ur.unitId <> ''
|
||||||
|
""");
|
||||||
|
unitSql.setParam("userId", SecurityUtil.getUserId());
|
||||||
|
unitSql.setParam("roleCode", RoleConstant.UNIT_SCHOOL_LEADER.name());
|
||||||
|
dao.execute(unitSql);
|
||||||
|
List<String> managedUnitIds = unitSql.getList(String.class);
|
||||||
|
if (managedUnitIds.isEmpty()) {
|
||||||
|
cnd.and(new Static("1 = 0"));
|
||||||
|
} else {
|
||||||
|
cnd.and("info.applyUnitId", "in", managedUnitIds);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (approval) {
|
||||||
|
cnd.and("t.taskState", "in", List.of(ProcessTaskStateEnum.FINISHED.getCode(), ProcessTaskStateEnum.INTERRUPT.getCode()));
|
||||||
|
} else {
|
||||||
|
cnd.and("t.taskState", "=", ProcessTaskStateEnum.DOING.getCode());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (StrUtil.isAllBlank(pageForm.getPageOrderName(), pageForm.getPageOrderBy())) {
|
||||||
|
cnd.desc("info.createTime");
|
||||||
|
} else {
|
||||||
|
cnd.orderBy(pageForm.getPageOrderName(), PageUtil.getOrder(pageForm.getPageOrderBy()));
|
||||||
|
}
|
||||||
|
cnd.groupBy("t.id");
|
||||||
|
sql.setCondition(cnd);
|
||||||
|
Pagination<NutMap> pageVO = specialcondolenceService.listPageMap(pageForm.getPageNumber(), pageForm.getPageSize(), sql);
|
||||||
|
return Result.success(pageVO);
|
||||||
|
}
|
||||||
|
}
|
||||||
+303
@@ -0,0 +1,303 @@
|
|||||||
|
package com.budwk.app.zhgh.staffbenefit.specialcondolence.controller;
|
||||||
|
|
||||||
|
import cn.dev33.satoken.annotation.SaCheckLogin;
|
||||||
|
import cn.dev33.satoken.annotation.SaCheckPermission;
|
||||||
|
import cn.dev33.satoken.annotation.SaMode;
|
||||||
|
import cn.hutool.core.date.DateUtil;
|
||||||
|
import cn.hutool.core.lang.Dict;
|
||||||
|
import cn.hutool.core.util.StrUtil;
|
||||||
|
import com.budwk.app.base.annotation.SLog;
|
||||||
|
import com.budwk.app.base.constant.RoleConstant;
|
||||||
|
import com.budwk.app.base.exception.BaseException;
|
||||||
|
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.sms.SmsService;
|
||||||
|
import com.budwk.app.base.utils.PageUtil;
|
||||||
|
import com.budwk.app.base.utils.CommonDownloadUtil;
|
||||||
|
import com.budwk.app.base.utils.SysOfficeTemplateUtil;
|
||||||
|
import com.budwk.app.flow.engine.FlowEngine;
|
||||||
|
import com.budwk.app.flow.entity.ProcessInstance;
|
||||||
|
import com.budwk.app.flow.entity.ProcessTask;
|
||||||
|
import com.budwk.app.flow.enums.ProcessInstanceStateEnum;
|
||||||
|
import com.budwk.app.flow.enums.ProcessTaskStateEnum;
|
||||||
|
import com.budwk.app.flow.vo.ProcessTaskVO;
|
||||||
|
import com.budwk.app.sys.views.View_user;
|
||||||
|
import com.budwk.app.web.commons.auth.utils.AuthUtil;
|
||||||
|
import com.budwk.app.web.commons.auth.utils.SecurityUtil;
|
||||||
|
import com.budwk.app.zhgh.staffbenefit.specialcondolence.model.SpecialCondolence;
|
||||||
|
import com.budwk.app.zhgh.staffbenefit.specialcondolence.model.SpecialCondolenceType;
|
||||||
|
import com.budwk.app.zhgh.staffbenefit.specialcondolence.service.SpecialCondolenceService;
|
||||||
|
import com.deepoove.poi.data.PictureRenderData;
|
||||||
|
import io.swagger.annotations.Api;
|
||||||
|
import io.swagger.annotations.ApiOperation;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.nutz.aop.interceptor.ioc.TransAop;
|
||||||
|
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.aop.Aop;
|
||||||
|
import org.nutz.ioc.loader.annotation.Inject;
|
||||||
|
import org.nutz.ioc.loader.annotation.IocBean;
|
||||||
|
import org.nutz.lang.Lang;
|
||||||
|
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.InputStream;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ClassName SpecialCondolenceApplyController
|
||||||
|
* @Author JyuHsin
|
||||||
|
* @Date 2025/7/28 11:06
|
||||||
|
* @Version 1.0
|
||||||
|
* @Description TODO
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
@IocBean
|
||||||
|
@At("/platform/special_condolence/mine")
|
||||||
|
@Api("特殊慰问我的")
|
||||||
|
@Ok("json:full")
|
||||||
|
public class SpecialCondolenceMineController {
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
private SpecialCondolenceService specialcondolenceService;
|
||||||
|
@Inject
|
||||||
|
private FlowEngine flowEngine;
|
||||||
|
@Inject
|
||||||
|
private SysOfficeTemplateUtil sysOfficeTemplateUtil;
|
||||||
|
|
||||||
|
@At("/")
|
||||||
|
@Ok("beetl:/platform/zhgh/staffbenefit/specialcondolence/mine/index.html")
|
||||||
|
@SaCheckPermission("special_condolence.mine")
|
||||||
|
public void index() {}
|
||||||
|
|
||||||
|
@At("/h5")
|
||||||
|
@Ok("beetl:/platform/zhghh5/staffbenefit/specialcondolence/mine/index.html")
|
||||||
|
@SaCheckPermission("h5.special_condolence.mine")
|
||||||
|
public void h5Index() {}
|
||||||
|
|
||||||
|
@At
|
||||||
|
@ApiOperation("分页查询")
|
||||||
|
@SaCheckPermission(value = {"special_condolence.mine", "h5.special_condolence.mine"}, mode = SaMode.OR)
|
||||||
|
public Result pageData(PageForm pageForm,
|
||||||
|
@Param(value = "year") Integer year,
|
||||||
|
@Param(value = "type") String type) {
|
||||||
|
Sql sql = Sqls.create("""
|
||||||
|
SELECT
|
||||||
|
info.*,
|
||||||
|
COALESCE(recipientTotals.recipientCount, 0) AS recipientCount,
|
||||||
|
type.name as typeName,
|
||||||
|
ins.id AS instanceId,
|
||||||
|
ins.businessNo,
|
||||||
|
ins.state instanceState,
|
||||||
|
ins.variable instanceVariable,
|
||||||
|
ins.processDefineId instanceProcessDefineId,
|
||||||
|
t.id taskId,
|
||||||
|
t.taskName AS taskKey,
|
||||||
|
t.displayName taskName,
|
||||||
|
t.taskType,
|
||||||
|
t.performType taskPerformType,
|
||||||
|
t.taskState,
|
||||||
|
t.finishTime,
|
||||||
|
t.taskParentId,
|
||||||
|
t.variable taskVariable,
|
||||||
|
IF((SELECT taskName FROM wf_process_task tt WHERE tt.id = t.taskParentId) = 'startTask', 1, 0) canRevoke,
|
||||||
|
(select MAX(id) from wf_process_task where processInstanceId = ins.id and taskName = 'startTask') AS startTaskId
|
||||||
|
FROM
|
||||||
|
special_condolence info
|
||||||
|
LEFT JOIN (
|
||||||
|
SELECT applyId, COUNT(*) AS recipientCount
|
||||||
|
FROM special_condolence_recipient
|
||||||
|
WHERE delFlag = false
|
||||||
|
GROUP BY applyId
|
||||||
|
) recipientTotals ON recipientTotals.applyId = info.id
|
||||||
|
LEFT JOIN special_condolence_type type ON info.type = type.id
|
||||||
|
LEFT JOIN `wf_process_instance` ins ON ins.businessNo = info.id
|
||||||
|
LEFT JOIN (
|
||||||
|
SELECT
|
||||||
|
id,
|
||||||
|
processInstanceId,
|
||||||
|
taskName,
|
||||||
|
displayName,
|
||||||
|
taskType,
|
||||||
|
performType,
|
||||||
|
taskState,
|
||||||
|
finishTime,
|
||||||
|
taskParentId,
|
||||||
|
variable,
|
||||||
|
ROW_NUMBER() OVER (PARTITION BY processInstanceId ORDER BY createdAt DESC, id DESC) AS rn
|
||||||
|
FROM wf_process_task
|
||||||
|
WHERE taskState = 10
|
||||||
|
) t ON t.processInstanceId = ins.id AND t.rn = 1
|
||||||
|
$condition
|
||||||
|
""");
|
||||||
|
Cnd cnd = Cnd.NEW();
|
||||||
|
if (StrUtil.isNotBlank(pageForm.getSearchKeyword())) {
|
||||||
|
SqlExpressionGroup seg = new SqlExpressionGroup();
|
||||||
|
seg.or(SpecialCondolence::getHelpUserName, "like", "%" + pageForm.getSearchKeyword() + "%");
|
||||||
|
seg.or(SpecialCondolence::getHelpLoginName, "like", "%" + pageForm.getSearchKeyword() + "%");
|
||||||
|
cnd.and(seg);
|
||||||
|
}
|
||||||
|
cnd.andEX("year(info.createTime)", "=", year);
|
||||||
|
cnd.andEX("info.type", "=", type);
|
||||||
|
cnd.and("info.createdBy", "=", SecurityUtil.getUserId());
|
||||||
|
|
||||||
|
if (StrUtil.isNotBlank(pageForm.getPageOrderName()) && StrUtil.isNotBlank(pageForm.getPageOrderBy())) {
|
||||||
|
cnd.orderBy(pageForm.getPageOrderName(), PageUtil.getOrder(pageForm.getPageOrderBy()));
|
||||||
|
} else {
|
||||||
|
cnd.desc("info.createTime");
|
||||||
|
}
|
||||||
|
|
||||||
|
sql.setCondition(cnd);
|
||||||
|
Pagination<NutMap> pagination = specialcondolenceService.listPageMap(pageForm.getPageNumber(), pageForm.getPageSize(), sql);
|
||||||
|
return Result.success(pagination);
|
||||||
|
}
|
||||||
|
|
||||||
|
@At
|
||||||
|
@Ok("void")
|
||||||
|
@ApiOperation("导出特殊慰问申请表")
|
||||||
|
@SaCheckPermission("special_condolence.mine")
|
||||||
|
public void doExportApply(String id, HttpServletResponse response, Boolean print) throws Exception {
|
||||||
|
log.info("[特殊慰问导出] 开始,applyId={}, userId={}, format={}", id, SecurityUtil.getUserId(), Boolean.TRUE.equals(print) ? "PDF" : "Word");
|
||||||
|
SpecialCondolence specialcondolence = specialcondolenceService.loadApplication(id);
|
||||||
|
if (specialcondolence == null) throw new BaseException("该条记录不存在");
|
||||||
|
if (!SecurityUtil.getUserId().equals(specialcondolence.getCreatedBy())) {
|
||||||
|
throw new BaseException("只能导出本人提交的申请");
|
||||||
|
}
|
||||||
|
ProcessInstance instance = specialcondolenceService.dao().fetch(ProcessInstance.class,
|
||||||
|
Cnd.where("businessNo", "=", id).desc("id"));
|
||||||
|
if (instance == null || !ProcessInstanceStateEnum.FINISHED.getCode().equals(instance.getState())) {
|
||||||
|
throw new BaseException("只能导出已完成的申请");
|
||||||
|
}
|
||||||
|
log.info("[特殊慰问导出] 流程已完成,applyId={}, instanceId={}, state={}, applicantSignPresent={}", id, instance.getId(), instance.getState(), StrUtil.isNotBlank(specialcondolence.getSignature()));
|
||||||
|
NutMap docData = Lang.obj2nutmap(specialcondolence);
|
||||||
|
docData.put("payUserName", StrUtil.nullToEmpty(specialcondolence.getBankUserName()));
|
||||||
|
SpecialCondolenceType type = specialcondolenceService.dao().fetch(SpecialCondolenceType.class, specialcondolence.getType());
|
||||||
|
docData.put("typeName", type == null ? "" : type.getName());
|
||||||
|
docData.put("signature", null);
|
||||||
|
if (StrUtil.isNotBlank(specialcondolence.getSignature())) {
|
||||||
|
PictureRenderData signature = sysOfficeTemplateUtil.createPictureRenderData(90, 40, specialcondolence.getSignature());
|
||||||
|
if (signature == null) throw new BaseException("申请人签字图片读取失败");
|
||||||
|
docData.put("signature", signature);
|
||||||
|
}
|
||||||
|
fillApplyApprovals(docData, instance);
|
||||||
|
for (String field : List.of("signature", "secondApprovalSign", "thirdApprovalSign", "fourthApprovalSign")) {
|
||||||
|
Object value = docData.get(field);
|
||||||
|
log.info("[特殊慰问导出] 渲染前图片字段,applyId={}, instanceId={}, field={}, valueType={}", id, instance.getId(), field, value == null ? "null" : value.getClass().getName());
|
||||||
|
}
|
||||||
|
String fileName = "重庆工贸职业技术学院特殊慰问申请表_" + StrUtil.nullToEmpty(specialcondolence.getHelpUserName());
|
||||||
|
try (InputStream input = getClass().getResourceAsStream("/templates/condolence/重庆工贸职业技术学院职工慰问申请表.doc")) {
|
||||||
|
if (input == null) throw new BaseException("特殊慰问申请表模板不存在");
|
||||||
|
boolean pdf = Boolean.TRUE.equals(print);
|
||||||
|
com.aspose.words.Document template = new com.aspose.words.Document(input);
|
||||||
|
template.getRange().replace("职工慰问", "特殊慰问", new com.aspose.words.FindReplaceOptions());
|
||||||
|
com.aspose.words.NodeCollection rows = template.getChildNodes(com.aspose.words.NodeType.ROW, true);
|
||||||
|
for (int i = rows.getCount() - 1; i >= 0; i--) {
|
||||||
|
com.aspose.words.Node row = rows.get(i);
|
||||||
|
if (row.getText().contains("firstApproval") || row.getText().contains("分工会主席")) row.remove();
|
||||||
|
}
|
||||||
|
java.io.ByteArrayOutputStream templateOutput = new java.io.ByteArrayOutputStream();
|
||||||
|
template.save(templateOutput, com.aspose.words.SaveFormat.DOCX);
|
||||||
|
byte[] bytes;
|
||||||
|
if (specialcondolence.getRecipients() != null && !specialcondolence.getRecipients().isEmpty()) {
|
||||||
|
com.aspose.words.Document combined = null;
|
||||||
|
for (cn.hutool.json.JSONObject person : specialcondolence.getRecipients()) {
|
||||||
|
NutMap personData = new NutMap();
|
||||||
|
personData.putAll(docData);
|
||||||
|
personData.putAll(person);
|
||||||
|
personData.put("payUserName", person.getStr("bankUserName"));
|
||||||
|
byte[] rendered = sysOfficeTemplateUtil.renderTemplate(new java.io.ByteArrayInputStream(templateOutput.toByteArray()), personData, null, false, "specialcondolence:" + id);
|
||||||
|
com.aspose.words.Document part = new com.aspose.words.Document(new java.io.ByteArrayInputStream(rendered));
|
||||||
|
if (combined == null) combined = part;
|
||||||
|
else combined.appendDocument(part, com.aspose.words.ImportFormatMode.KEEP_SOURCE_FORMATTING);
|
||||||
|
}
|
||||||
|
java.io.ByteArrayOutputStream output = new java.io.ByteArrayOutputStream();
|
||||||
|
combined.save(output, pdf ? com.aspose.words.SaveFormat.PDF : com.aspose.words.SaveFormat.DOCX);
|
||||||
|
bytes = output.toByteArray();
|
||||||
|
} else {
|
||||||
|
bytes = sysOfficeTemplateUtil.renderTemplate(new java.io.ByteArrayInputStream(templateOutput.toByteArray()), docData, null, pdf, "specialcondolence:" + id);
|
||||||
|
}
|
||||||
|
log.info("[特殊慰问导出] 渲染完成,applyId={}, format={}, outputBytes={}", id, pdf ? "PDF" : "Word", bytes.length);
|
||||||
|
CommonDownloadUtil.download(fileName + (pdf ? ".pdf" : ".docx"), bytes, response);
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("[特殊慰问导出] 模板渲染或文件输出失败,applyId={}, instanceId={}, format={}", id, instance.getId(), Boolean.TRUE.equals(print) ? "PDF" : "Word", e);
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void fillApplyApprovals(NutMap docData, ProcessInstance instance) {
|
||||||
|
String[] taskKeys = {"c438972e-2f67-4907-b229-cb7aa17da147",
|
||||||
|
"7f560675-aeea-4254-a57e-957d03d6b786", "af363a4e-fc56-42a0-9906-8c7a2814006b"};
|
||||||
|
String[] fields = {"secondApproval", "thirdApproval", "fourthApproval"};
|
||||||
|
List<String> suffixes = List.of("Opinion", "Sign", "Year", "Month", "Day");
|
||||||
|
for (String field : fields) {
|
||||||
|
for (String suffix : suffixes) docData.put(field + suffix, "Sign".equals(suffix) ? null : "");
|
||||||
|
}
|
||||||
|
List<ProcessTask> tasks = specialcondolenceService.dao().query(ProcessTask.class,
|
||||||
|
Cnd.where("processInstanceId", "=", instance.getId()).asc("id"));
|
||||||
|
log.info("[特殊慰问导出] 查询审批记录,applyId={}, instanceId={}, taskCount={}, expectedTaskKeys={}", instance.getBusinessNo(), instance.getId(), tasks.size(), List.of(taskKeys));
|
||||||
|
for (ProcessTask task : tasks) {
|
||||||
|
ProcessTaskVO taskVO = flowEngine.processTaskService().findById(task.getId());
|
||||||
|
log.info("[特殊慰问导出] 审批记录,instanceId={}, taskId={}, taskKey={}, displayName={}, state={}, finishTime={}, isFirstTaskNode={}, matchedApproval={}", instance.getId(), task.getId(), task.getTaskName(), task.getDisplayName(), task.getTaskState(), task.getFinishTime(), taskVO.getExt() == null ? null : taskVO.getExt().get("isFirstTaskNode"), List.of(taskKeys).contains(task.getTaskName()));
|
||||||
|
if ("startTask".equals(task.getTaskName()) || (!List.of(taskKeys).contains(task.getTaskName())
|
||||||
|
&& taskVO.getExt() != null && Boolean.TRUE.equals(taskVO.getExt().getBool("isFirstTaskNode")))) {
|
||||||
|
log.info("[特殊慰问导出] 申请节点重置本轮审批字段,instanceId={}, taskId={}, taskKey={}", instance.getId(), task.getId(), task.getTaskName());
|
||||||
|
// 重新申请后,仅导出本轮审批记录。
|
||||||
|
for (String field : fields) {
|
||||||
|
for (String suffix : suffixes) docData.put(field + suffix, "Sign".equals(suffix) ? null : "");
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
for (int i = 0; i < taskKeys.length; i++) {
|
||||||
|
if (!taskKeys[i].equals(task.getTaskName())) continue;
|
||||||
|
for (String suffix : suffixes) docData.put(fields[i] + suffix, "Sign".equals(suffix) ? null : "");
|
||||||
|
if (!ProcessTaskStateEnum.FINISHED.getCode().equals(task.getTaskState())) {
|
||||||
|
log.info("[特殊慰问导出] 跳过未完成审批,instanceId={}, taskId={}, field={}, state={}", instance.getId(), task.getId(), fields[i], task.getTaskState());
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
Dict data = taskVO.getExt() == null ? Dict.create() : taskVO.getTaskFormData();
|
||||||
|
log.info("[特殊慰问导出] 读取审批表单,instanceId={}, taskId={}, field={}, formKeys={}, signPresent={}, signReferenceLength={}", instance.getId(), task.getId(), fields[i], data.keySet(), StrUtil.isNotBlank(data.getStr("sign")), StrUtil.nullToEmpty(data.getStr("sign")).length());
|
||||||
|
if (StrUtil.isBlank(data.getStr("sign"))) log.warn("[特殊慰问导出] 已完成审批缺少签名字段,instanceId={}, taskId={}, field={}", instance.getId(), task.getId(), fields[i]);
|
||||||
|
docData.put(fields[i] + "Opinion", StrUtil.nullToEmpty(data.getStr("opinion")));
|
||||||
|
if (StrUtil.isNotBlank(data.getStr("sign"))) {
|
||||||
|
PictureRenderData signature = sysOfficeTemplateUtil.createPictureRenderData(90, 40, data.getStr("sign"));
|
||||||
|
if (signature == null) throw new BaseException("审批签字图片读取失败");
|
||||||
|
docData.put(fields[i] + "Sign", signature);
|
||||||
|
log.info("[特殊慰问导出] 审批签名填充完成,instanceId={}, taskId={}, field={}", instance.getId(), task.getId(), fields[i] + "Sign");
|
||||||
|
}
|
||||||
|
docData.put(fields[i] + "Year", task.getFinishTime() == null ? "" : DateUtil.format(task.getFinishTime(), "yyyy"));
|
||||||
|
docData.put(fields[i] + "Month", task.getFinishTime() == null ? "" : DateUtil.format(task.getFinishTime(), "M"));
|
||||||
|
docData.put(fields[i] + "Day", task.getFinishTime() == null ? "" : DateUtil.format(task.getFinishTime(), "d"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@At
|
||||||
|
@ApiOperation("删除")
|
||||||
|
@Aop(TransAop.READ_COMMITTED)
|
||||||
|
@SaCheckPermission(value = {"special_condolence.mine", "h5.special_condolence.mine"}, mode = SaMode.OR)
|
||||||
|
@SLog(tag = "特殊慰问系统-我的申请", msg = "删除特殊慰问")
|
||||||
|
public Result delete(@Param("id") String id) {
|
||||||
|
specialcondolenceService.deleteApplication(id);
|
||||||
|
flowEngine.processInstanceService().deleteProcessInstanceByBusinessKey(id);
|
||||||
|
return Result.success();
|
||||||
|
}
|
||||||
|
|
||||||
|
@At
|
||||||
|
@ApiOperation("查询单个慰问申请信息")
|
||||||
|
@SaCheckPermission(value = {"special_condolence", "h5.special_condolence"}, mode = SaMode.OR)
|
||||||
|
public Result info(String id) {
|
||||||
|
SpecialCondolence specialcondolence = specialcondolenceService.loadApplication(id);
|
||||||
|
SpecialCondolenceType type = specialcondolenceService.dao().fetch(SpecialCondolenceType.class, Cnd.where(SpecialCondolenceType::getId, "=", specialcondolence.getType()));
|
||||||
|
NutMap nutMap = Lang.obj2nutmap(specialcondolence);
|
||||||
|
nutMap.put("typeName", type == null ? "" : type.getName());
|
||||||
|
return Result.success(nutMap);
|
||||||
|
}
|
||||||
|
@Inject
|
||||||
|
private SmsService smsService;
|
||||||
|
}
|
||||||
+179
@@ -0,0 +1,179 @@
|
|||||||
|
package com.budwk.app.zhgh.staffbenefit.specialcondolence.controller;
|
||||||
|
|
||||||
|
import cn.afterturn.easypoi.excel.ExcelExportUtil;
|
||||||
|
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.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.ProcessInstanceStateEnum;
|
||||||
|
import com.budwk.app.sys.param.SysMsgSummaryPageForm;
|
||||||
|
import com.budwk.app.zhgh.staffbenefit.specialcondolence.model.SpecialCondolence;
|
||||||
|
import com.budwk.app.zhgh.staffbenefit.specialcondolence.service.SpecialCondolenceService;
|
||||||
|
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;
|
||||||
|
import org.nutz.mvc.annotation.At;
|
||||||
|
import org.nutz.mvc.annotation.Ok;
|
||||||
|
import org.nutz.mvc.annotation.Param;
|
||||||
|
|
||||||
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
import javax.validation.Valid;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ClassName SpecialCondolenceReadController
|
||||||
|
* @Author JyuHsin
|
||||||
|
* @Date 2025/7/29 16:25
|
||||||
|
* @Version 1.0
|
||||||
|
* @Description TODO
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
@IocBean
|
||||||
|
@Ok("json:full")
|
||||||
|
@Api(tags = "特殊慰问阅览")
|
||||||
|
@At("/platform/special_condolence/read")
|
||||||
|
public class SpecialCondolenceReadController {
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
private SpecialCondolenceService specialcondolenceService;
|
||||||
|
|
||||||
|
@At("")
|
||||||
|
@SaCheckPermission("special_condolence.read")
|
||||||
|
@Ok("beetl:/platform/zhgh/staffbenefit/specialcondolence/read/index.html")
|
||||||
|
public void index() {
|
||||||
|
}
|
||||||
|
|
||||||
|
@At
|
||||||
|
@ApiOperation("分页查询")
|
||||||
|
@SaCheckPermission("special_condolence.read")
|
||||||
|
public Result pageData(PageForm pageForm,
|
||||||
|
@Param(value = "year") Integer year,
|
||||||
|
@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
|
||||||
|
special_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 special_condolence_type type ON info.type = type.id
|
||||||
|
$condition
|
||||||
|
""");
|
||||||
|
Cnd cnd = Cnd.NEW();
|
||||||
|
cnd.and("ins.state", "=", ProcessInstanceStateEnum.FINISHED.getCode());
|
||||||
|
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 (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 = specialcondolenceService.listPageMap(pageForm.getPageNumber(), pageForm.getPageSize(), sql);
|
||||||
|
return Result.success(pageVO);
|
||||||
|
}
|
||||||
|
|
||||||
|
@At
|
||||||
|
@Ok("void")
|
||||||
|
@SaCheckPermission("special_condolence.read")
|
||||||
|
@ApiOperation("导出特殊慰问汇总表")
|
||||||
|
public void onExport(PageForm pageForm,
|
||||||
|
@Param(value = "year") Integer year,
|
||||||
|
@Param(value = "type") String type,
|
||||||
|
@Param(value = "unionId") String unionId,
|
||||||
|
@Param(value = "unitId") String unitId,
|
||||||
|
HttpServletResponse response) {
|
||||||
|
//查询审核通过的数据
|
||||||
|
Sql sql = Sqls.create("""
|
||||||
|
select
|
||||||
|
con.subject,
|
||||||
|
case when recipient.id is null then con.helpUserName else recipient.helpUserName end as helpUserName,
|
||||||
|
case when recipient.id is null then con.helpLoginName else recipient.helpLoginName end as helpLoginName,
|
||||||
|
con.applyUserName,
|
||||||
|
con.helpUnionName,
|
||||||
|
con.helpUnitName,
|
||||||
|
case when recipient.id is null then type.name else recipient.typeName end as typeName,
|
||||||
|
case when recipient.id is null then con.money else recipient.money end as money,
|
||||||
|
con.remark
|
||||||
|
from
|
||||||
|
special_condolence con
|
||||||
|
left join special_condolence_recipient recipient on recipient.applyId = con.id and recipient.delFlag = false
|
||||||
|
left join wf_process_instance ins on ins.businessNo = con.id
|
||||||
|
left join special_condolence_type type on type.id = con.type
|
||||||
|
$condition
|
||||||
|
order by con.createTime desc, con.id, recipient.sortNum, recipient.id
|
||||||
|
""");
|
||||||
|
Cnd cnd = Cnd.NEW();
|
||||||
|
cnd.and("ins.state", "=", ProcessInstanceStateEnum.FINISHED.getCode());
|
||||||
|
cnd.andEX("con.type", "=", type);
|
||||||
|
cnd.andEX("YEAR(con.createTime)", "=", year);
|
||||||
|
cnd.andEX("con.applyUnionId", "=", unionId);
|
||||||
|
cnd.andEX("con.applyUnitId", "=", unitId);
|
||||||
|
if (StrUtil.isNotBlank(pageForm.getSearchKeyword())) {
|
||||||
|
SqlExpressionGroup seg = new SqlExpressionGroup();
|
||||||
|
seg.or("con.helpUserName", "like", "%" + pageForm.getSearchKeyword() + "%");
|
||||||
|
seg.or("con.helpLoginName", "like", "%" + pageForm.getSearchKeyword() + "%");
|
||||||
|
cnd.and(seg);
|
||||||
|
}
|
||||||
|
sql.setCondition(cnd);
|
||||||
|
List<NutMap> list = specialcondolenceService.listMap(sql);
|
||||||
|
|
||||||
|
List<ExcelExportEntity> exportEntities = new ArrayList<>();
|
||||||
|
exportEntities.add(new ExcelExportEntity("事项", "subject", 30));
|
||||||
|
exportEntities.add(new ExcelExportEntity("慰问对象", "helpUserName", 20));
|
||||||
|
exportEntities.add(new ExcelExportEntity("慰问对象工号", "helpLoginName", 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("申请理由", "remark", 20));
|
||||||
|
|
||||||
|
ExportParams exportParams = new ExportParams();
|
||||||
|
exportParams.setType(ExcelType.XSSF);
|
||||||
|
Workbook workbook = ExcelExportUtil.exportExcel(exportParams, exportEntities, list);
|
||||||
|
CommonDownloadUtil.download("申报人汇总.xlsx", workbook, response);
|
||||||
|
}
|
||||||
|
}
|
||||||
+140
@@ -0,0 +1,140 @@
|
|||||||
|
package com.budwk.app.zhgh.staffbenefit.specialcondolence.controller;
|
||||||
|
|
||||||
|
import cn.dev33.satoken.annotation.SaCheckPermission;
|
||||||
|
import cn.dev33.satoken.annotation.SaMode;
|
||||||
|
import cn.hutool.core.util.StrUtil;
|
||||||
|
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.PageUtil;
|
||||||
|
import com.budwk.app.flow.enums.ProcessTaskStateEnum;
|
||||||
|
import com.budwk.app.web.commons.auth.utils.SecurityUtil;
|
||||||
|
import com.budwk.app.zhgh.staffbenefit.specialcondolence.model.SpecialCondolence;
|
||||||
|
import com.budwk.app.zhgh.staffbenefit.specialcondolence.service.SpecialCondolenceService;
|
||||||
|
import io.swagger.annotations.Api;
|
||||||
|
import io.swagger.annotations.ApiOperation;
|
||||||
|
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.dao.util.cri.Static;
|
||||||
|
import org.nutz.ioc.loader.annotation.Inject;
|
||||||
|
import org.nutz.ioc.loader.annotation.IocBean;
|
||||||
|
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 java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author zhf
|
||||||
|
* @date 2025/12/23 14:13
|
||||||
|
* @description 校工会预审
|
||||||
|
*/
|
||||||
|
@IocBean
|
||||||
|
@At("/platform/special_condolence/schoolPrincipalApproval")
|
||||||
|
@Api("特殊慰问二级审核")
|
||||||
|
@Ok("json:full")
|
||||||
|
public class SpecialCondolenceSecondApprovalController {
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
private SpecialCondolenceService specialcondolenceService;
|
||||||
|
|
||||||
|
@At("/")
|
||||||
|
@Ok("beetl:/platform/zhgh/staffbenefit/specialcondolence/schoolPrincipalApproval/index.html")
|
||||||
|
@SaCheckPermission("special_condolence.secondApproval")
|
||||||
|
public void index() {}
|
||||||
|
|
||||||
|
@At("/h5")
|
||||||
|
@Ok("beetl:/platform/zhghh5/staffbenefit/specialcondolence/schoolPrincipalApproval/index.html")
|
||||||
|
@SaCheckPermission("h5.special_condolence.secondApproval")
|
||||||
|
public void h5Index() {}
|
||||||
|
|
||||||
|
@At
|
||||||
|
@ApiOperation("分页查询")
|
||||||
|
@SaCheckPermission(value = {"special_condolence.secondApproval", "h5.special_condolence.secondApproval"}, mode = SaMode.OR)
|
||||||
|
public Result pageData(PageForm pageForm,
|
||||||
|
@Param(value = "year") Integer year,
|
||||||
|
@Param(value = "type") String type,
|
||||||
|
@Param(value = "unionId") String unionId,
|
||||||
|
@Param(value = "unitId") String unitId,
|
||||||
|
@Param(value = "approval") Boolean approval) {
|
||||||
|
Sql sql = Sqls.create("""
|
||||||
|
SELECT
|
||||||
|
info.*,
|
||||||
|
COALESCE(recipientTotals.recipientCount, 0) AS recipientCount,
|
||||||
|
type.name as typeName,
|
||||||
|
ins.id AS instanceId,
|
||||||
|
ins.businessNo,
|
||||||
|
ins.state instanceState,
|
||||||
|
ins.variable instanceVariable,
|
||||||
|
ins.processDefineId instanceProcessDefineId,
|
||||||
|
t.id taskId,
|
||||||
|
t.taskName AS taskKey,
|
||||||
|
t.displayName taskName,
|
||||||
|
t.taskType,
|
||||||
|
t.performType taskPerformType,
|
||||||
|
t.taskState,
|
||||||
|
t.finishTime,
|
||||||
|
t.taskParentId,
|
||||||
|
t.variable taskVariable,
|
||||||
|
IFNULL(GROUP_CONCAT(DISTINCT nt.displayName),'结束') curTaskName,
|
||||||
|
IF(rt.id IS NOT NULL, 1, 0) AS canRevoke
|
||||||
|
FROM
|
||||||
|
wf_process_task t
|
||||||
|
LEFT JOIN wf_process_instance ins ON ins.id = t.processInstanceId
|
||||||
|
LEFT JOIN special_condolence info ON info.id = ins.businessNo
|
||||||
|
LEFT JOIN wf_process_task_actor ta ON ta.processTaskId = t.id
|
||||||
|
LEFT JOIN (
|
||||||
|
SELECT applyId, COUNT(*) AS recipientCount
|
||||||
|
FROM special_condolence_recipient
|
||||||
|
WHERE delFlag = false
|
||||||
|
GROUP BY applyId
|
||||||
|
) recipientTotals ON recipientTotals.applyId = info.id
|
||||||
|
LEFT JOIN special_condolence_type type ON info.type = type.id
|
||||||
|
LEFT JOIN wf_process_task nt ON nt.processInstanceId = ins.id AND nt.taskState = 10
|
||||||
|
LEFT JOIN wf_process_task rt ON rt.processInstanceId = ins.id AND rt.taskParentId = t.id AND rt.taskState = 10
|
||||||
|
$condition
|
||||||
|
""");
|
||||||
|
Cnd cnd = Cnd.NEW();
|
||||||
|
cnd.and("info.id", "is not", null);
|
||||||
|
cnd.and(new Static("""
|
||||||
|
NOT EXISTS (
|
||||||
|
SELECT 1 FROM wf_process_task newer
|
||||||
|
WHERE newer.processInstanceId = t.processInstanceId
|
||||||
|
AND newer.taskName = t.taskName
|
||||||
|
AND newer.id > t.id
|
||||||
|
)
|
||||||
|
"""));
|
||||||
|
if (StrUtil.isNotBlank(pageForm.getSearchKeyword())) {
|
||||||
|
SqlExpressionGroup seg = new SqlExpressionGroup();
|
||||||
|
seg.or(SpecialCondolence::getHelpUserName, "like", "%" + pageForm.getSearchKeyword() + "%");
|
||||||
|
seg.or(SpecialCondolence::getHelpLoginName, "like", "%" + pageForm.getSearchKeyword() + "%");
|
||||||
|
cnd.and(seg);
|
||||||
|
}
|
||||||
|
cnd.andEX("info.type", "=", type);
|
||||||
|
cnd.andEX("YEAR(info.createTime)", "=", year);
|
||||||
|
cnd.andEX("info.applyUnionId", "=", unionId);
|
||||||
|
cnd.andEX("info.applyUnitId", "=", unitId);
|
||||||
|
|
||||||
|
cnd.and("t.taskName", "=", "c438972e-2f67-4907-b229-cb7aa17da147");
|
||||||
|
// cnd.and("ta.actorId", "in", List.of(SecurityUtil.getUserId()));
|
||||||
|
|
||||||
|
if (approval) {
|
||||||
|
cnd.and("t.taskState", "in", List.of(ProcessTaskStateEnum.FINISHED.getCode(), ProcessTaskStateEnum.INTERRUPT.getCode()));
|
||||||
|
} else {
|
||||||
|
cnd.and("t.taskState", "=", ProcessTaskStateEnum.DOING.getCode());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (StrUtil.isAllBlank(pageForm.getPageOrderName(), pageForm.getPageOrderBy())) {
|
||||||
|
cnd.desc("info.createTime");
|
||||||
|
} else {
|
||||||
|
cnd.orderBy(pageForm.getPageOrderName(), PageUtil.getOrder(pageForm.getPageOrderBy()));
|
||||||
|
}
|
||||||
|
cnd.groupBy("t.id");
|
||||||
|
sql.setCondition(cnd);
|
||||||
|
Pagination<NutMap> pageVO = specialcondolenceService.listPageMap(pageForm.getPageNumber(), pageForm.getPageSize(), sql);
|
||||||
|
return Result.success(pageVO);
|
||||||
|
}
|
||||||
|
}
|
||||||
+144
@@ -0,0 +1,144 @@
|
|||||||
|
package com.budwk.app.zhgh.staffbenefit.specialcondolence.controller;
|
||||||
|
|
||||||
|
import cn.dev33.satoken.annotation.SaCheckPermission;
|
||||||
|
import cn.dev33.satoken.annotation.SaMode;
|
||||||
|
import cn.hutool.core.util.StrUtil;
|
||||||
|
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.PageUtil;
|
||||||
|
import com.budwk.app.flow.enums.ProcessTaskStateEnum;
|
||||||
|
import com.budwk.app.web.commons.auth.utils.SecurityUtil;
|
||||||
|
import com.budwk.app.zhgh.staffbenefit.specialcondolence.model.SpecialCondolence;
|
||||||
|
import com.budwk.app.zhgh.staffbenefit.specialcondolence.service.SpecialCondolenceService;
|
||||||
|
import io.swagger.annotations.Api;
|
||||||
|
import io.swagger.annotations.ApiOperation;
|
||||||
|
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.dao.util.cri.Static;
|
||||||
|
import org.nutz.ioc.loader.annotation.Inject;
|
||||||
|
import org.nutz.ioc.loader.annotation.IocBean;
|
||||||
|
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 java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ClassName SpecialCondolenceThirdApprovalController
|
||||||
|
* @Author JyuHsin
|
||||||
|
* @Date 2025/7/29 16:23
|
||||||
|
* @Version 1.0
|
||||||
|
* @Description TODO
|
||||||
|
*/
|
||||||
|
@IocBean
|
||||||
|
@At("/platform/special_condolence/schoolUnionApproval")
|
||||||
|
@Api("特殊慰问三级审核")
|
||||||
|
@Ok("json:full")
|
||||||
|
public class SpecialCondolenceThirdApprovalController {
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
private SpecialCondolenceService specialcondolenceService;
|
||||||
|
|
||||||
|
@At("/")
|
||||||
|
@Ok("beetl:/platform/zhgh/staffbenefit/specialcondolence/schoolUnionApproval/index.html")
|
||||||
|
@SaCheckPermission("special_condolence.thirdApproval")
|
||||||
|
public void index() {}
|
||||||
|
|
||||||
|
@At("/h5")
|
||||||
|
@Ok("beetl:/platform/zhghh5/staffbenefit/specialcondolence/schoolUnionApproval/index.html")
|
||||||
|
@SaCheckPermission("h5.special_condolence.thirdApproval")
|
||||||
|
public void h5Index() {}
|
||||||
|
|
||||||
|
@At
|
||||||
|
@ApiOperation("分页查询")
|
||||||
|
@SaCheckPermission(value = {"special_condolence.thirdApproval", "h5.special_condolence.thirdApproval"}, mode = SaMode.OR)
|
||||||
|
public Result pageData(PageForm pageForm,
|
||||||
|
@Param(value = "year") Integer year,
|
||||||
|
@Param(value = "type") String type,
|
||||||
|
@Param(value = "unionId") String unionId,
|
||||||
|
@Param(value = "unitId") String unitId,
|
||||||
|
@Param(value = "approval") Boolean approval) {
|
||||||
|
Sql sql = Sqls.create("""
|
||||||
|
SELECT
|
||||||
|
info.*,
|
||||||
|
COALESCE(recipientTotals.recipientCount, 0) AS recipientCount,
|
||||||
|
type.name as typeName,
|
||||||
|
ins.id AS instanceId,
|
||||||
|
ins.businessNo,
|
||||||
|
ins.state instanceState,
|
||||||
|
ins.variable instanceVariable,
|
||||||
|
ins.processDefineId instanceProcessDefineId,
|
||||||
|
t.id taskId,
|
||||||
|
t.taskName AS taskKey,
|
||||||
|
t.displayName taskName,
|
||||||
|
t.taskType,
|
||||||
|
t.performType taskPerformType,
|
||||||
|
t.taskState,
|
||||||
|
t.finishTime,
|
||||||
|
t.taskParentId,
|
||||||
|
t.variable taskVariable,
|
||||||
|
IFNULL(GROUP_CONCAT(DISTINCT nt.displayName),'结束') curTaskName,
|
||||||
|
IF(rt.id IS NOT NULL, 1, 0) AS canRevoke
|
||||||
|
FROM
|
||||||
|
wf_process_task t
|
||||||
|
LEFT JOIN wf_process_instance ins ON ins.id = t.processInstanceId
|
||||||
|
LEFT JOIN special_condolence info ON info.id = ins.businessNo
|
||||||
|
LEFT JOIN wf_process_task_actor ta ON ta.processTaskId = t.id
|
||||||
|
LEFT JOIN (
|
||||||
|
SELECT applyId, COUNT(*) AS recipientCount
|
||||||
|
FROM special_condolence_recipient
|
||||||
|
WHERE delFlag = false
|
||||||
|
GROUP BY applyId
|
||||||
|
) recipientTotals ON recipientTotals.applyId = info.id
|
||||||
|
LEFT JOIN special_condolence_type type ON info.type = type.id
|
||||||
|
LEFT JOIN wf_process_task nt ON nt.processInstanceId = ins.id AND nt.taskState = 10
|
||||||
|
LEFT JOIN wf_process_task rt ON rt.processInstanceId = ins.id AND rt.taskParentId = t.id AND rt.taskState = 10
|
||||||
|
$condition
|
||||||
|
""");
|
||||||
|
Cnd cnd = Cnd.NEW();
|
||||||
|
cnd.and("info.id", "is not", null);
|
||||||
|
cnd.and(new Static("""
|
||||||
|
NOT EXISTS (
|
||||||
|
SELECT 1 FROM wf_process_task newer
|
||||||
|
WHERE newer.processInstanceId = t.processInstanceId
|
||||||
|
AND newer.taskName = t.taskName
|
||||||
|
AND newer.id > t.id
|
||||||
|
)
|
||||||
|
"""));
|
||||||
|
if (StrUtil.isNotBlank(pageForm.getSearchKeyword())) {
|
||||||
|
SqlExpressionGroup seg = new SqlExpressionGroup();
|
||||||
|
seg.or(SpecialCondolence::getHelpUserName, "like", "%" + pageForm.getSearchKeyword() + "%");
|
||||||
|
seg.or(SpecialCondolence::getHelpLoginName, "like", "%" + pageForm.getSearchKeyword() + "%");
|
||||||
|
cnd.and(seg);
|
||||||
|
}
|
||||||
|
cnd.andEX("info.type", "=", type);
|
||||||
|
cnd.andEX("YEAR(info.createTime)", "=", year);
|
||||||
|
cnd.andEX("info.applyUnionId", "=", unionId);
|
||||||
|
cnd.andEX("info.applyUnitId", "=", unitId);
|
||||||
|
|
||||||
|
cnd.and("t.taskName", "=", "7f560675-aeea-4254-a57e-957d03d6b786");
|
||||||
|
if (!"superadmin".equals(SecurityUtil.getUserLoginname())) {
|
||||||
|
cnd.and("ta.actorId", "in", List.of(SecurityUtil.getUserId()));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (approval) {
|
||||||
|
cnd.and("t.taskState", "in", List.of(ProcessTaskStateEnum.FINISHED.getCode(), ProcessTaskStateEnum.INTERRUPT.getCode()));
|
||||||
|
} else {
|
||||||
|
cnd.and("t.taskState", "=", ProcessTaskStateEnum.DOING.getCode());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (StrUtil.isAllBlank(pageForm.getPageOrderName(), pageForm.getPageOrderBy())) {
|
||||||
|
cnd.desc("info.createTime");
|
||||||
|
} else {
|
||||||
|
cnd.orderBy(pageForm.getPageOrderName(), PageUtil.getOrder(pageForm.getPageOrderBy()));
|
||||||
|
}
|
||||||
|
cnd.groupBy("t.id");
|
||||||
|
sql.setCondition(cnd);
|
||||||
|
Pagination<NutMap> pageVO = specialcondolenceService.listPageMap(pageForm.getPageNumber(), pageForm.getPageSize(), sql);
|
||||||
|
return Result.success(pageVO);
|
||||||
|
}
|
||||||
|
}
|
||||||
+91
@@ -0,0 +1,91 @@
|
|||||||
|
package com.budwk.app.zhgh.staffbenefit.specialcondolence.controller;
|
||||||
|
|
||||||
|
import cn.dev33.satoken.annotation.SaCheckLogin;
|
||||||
|
import cn.dev33.satoken.annotation.SaCheckPermission;
|
||||||
|
import cn.hutool.core.util.StrUtil;
|
||||||
|
import com.budwk.app.base.annotation.SLog;
|
||||||
|
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.zhgh.staffbenefit.specialcondolence.model.SpecialCondolenceType;
|
||||||
|
import com.budwk.app.zhgh.staffbenefit.specialcondolence.service.SpecialCondolenceTypeService;
|
||||||
|
import io.swagger.annotations.Api;
|
||||||
|
import io.swagger.annotations.ApiOperation;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.nutz.dao.Cnd;
|
||||||
|
import org.nutz.dao.Dao;
|
||||||
|
import org.nutz.dao.util.cri.SqlExpressionGroup;
|
||||||
|
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 java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ClassName SpecialCondolenceTypeController
|
||||||
|
* @Author JyuHsin
|
||||||
|
* @Date 2025/7/29 10:00
|
||||||
|
* @Version 1.0
|
||||||
|
* @Description TODO
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
@IocBean
|
||||||
|
@Ok("json:full")
|
||||||
|
@Api(tags = "特殊慰问类型")
|
||||||
|
@At("/platform/special_condolence/type")
|
||||||
|
public class SpecialCondolenceTypeController {
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
private Dao dao;
|
||||||
|
@Inject
|
||||||
|
private SpecialCondolenceTypeService typeService;
|
||||||
|
|
||||||
|
@At("")
|
||||||
|
@SaCheckPermission("special_condolence.type")
|
||||||
|
@Ok("beetl:/platform/zhgh/staffbenefit/specialcondolence/type/index.html")
|
||||||
|
public void index() {
|
||||||
|
}
|
||||||
|
|
||||||
|
@At
|
||||||
|
@ApiOperation("分页查询")
|
||||||
|
@SaCheckPermission("special_condolence.type")
|
||||||
|
public Result pageData(PageForm pageForm) {
|
||||||
|
Cnd cnd = Cnd.NEW();
|
||||||
|
if (StrUtil.isNotBlank(pageForm.getSearchKeyword())) {
|
||||||
|
SqlExpressionGroup seg = new SqlExpressionGroup();
|
||||||
|
seg.or(SpecialCondolenceType::getName, "like", "%" + pageForm.getSearchKeyword() + "%");
|
||||||
|
seg.or(SpecialCondolenceType::getCode, "like", "%" + pageForm.getSearchKeyword() + "%");
|
||||||
|
cnd.and(seg);
|
||||||
|
}
|
||||||
|
cnd.asc("code");
|
||||||
|
Pagination pagination = typeService.listPageMap(pageForm.getPageNumber(), pageForm.getPageSize(), cnd);
|
||||||
|
return Result.success(pagination);
|
||||||
|
}
|
||||||
|
|
||||||
|
@At
|
||||||
|
@ApiOperation("新增/修改特殊慰问类型")
|
||||||
|
@SaCheckPermission("special_condolence.type")
|
||||||
|
@SLog(tag = "特殊慰问系统-慰问类型", msg = "新增/修改特殊慰问类型")
|
||||||
|
public Object onSubmit(SpecialCondolenceType type) {
|
||||||
|
typeService.insertOrUpdate(type);
|
||||||
|
return Result.success();
|
||||||
|
}
|
||||||
|
|
||||||
|
@At
|
||||||
|
@ApiOperation("删除特殊慰问类型")
|
||||||
|
@SaCheckPermission("special_condolence.type")
|
||||||
|
@SLog(tag = "特殊慰问系统-慰问类型", msg = "删除特殊慰问类型")
|
||||||
|
public Object onDelete(String id) {
|
||||||
|
typeService.delete(id);
|
||||||
|
return Result.success();
|
||||||
|
}
|
||||||
|
|
||||||
|
@At
|
||||||
|
@ApiOperation("查询特殊慰问类型")
|
||||||
|
@SaCheckLogin
|
||||||
|
public Result querySpecialCondolenceType() {
|
||||||
|
List<SpecialCondolenceType> list = typeService.query(Cnd.where(SpecialCondolenceType::getEnable, "=", true).asc(SpecialCondolenceType::getCode));
|
||||||
|
return Result.success(list);
|
||||||
|
}
|
||||||
|
}
|
||||||
+46
@@ -0,0 +1,46 @@
|
|||||||
|
package com.budwk.app.zhgh.staffbenefit.specialcondolence.interceptor;
|
||||||
|
|
||||||
|
import cn.hutool.core.date.DateUtil;
|
||||||
|
import cn.hutool.core.util.StrUtil;
|
||||||
|
import com.budwk.app.flow.constant.FlowConst;
|
||||||
|
import com.budwk.app.flow.engine.FlowInterceptor;
|
||||||
|
import com.budwk.app.flow.engine.core.Execution;
|
||||||
|
import com.budwk.app.flow.engine.core.ServiceContext;
|
||||||
|
import com.budwk.app.flow.entity.ProcessInstance;
|
||||||
|
import com.budwk.app.zhgh.dayofficework.article.models.Article;
|
||||||
|
import com.budwk.app.zhgh.staffbenefit.specialcondolence.model.SpecialCondolence;
|
||||||
|
import org.nutz.dao.Chain;
|
||||||
|
import org.nutz.dao.Cnd;
|
||||||
|
import org.nutz.dao.Dao;
|
||||||
|
import org.nutz.json.Json;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ClassName SpecialCondolenceSaveInterceptor
|
||||||
|
* @Author JyuHsin
|
||||||
|
* @Date 2025/7/28 11:01
|
||||||
|
* @Version 1.0
|
||||||
|
* @Description TODO
|
||||||
|
*/
|
||||||
|
public class SpecialCondolenceSaveInterceptor implements FlowInterceptor {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void intercept(Execution execution) {
|
||||||
|
if (!com.budwk.app.web.commons.auth.utils.AuthUtil.hasRoleOr("BRANCH_UNION_CHAIRMAN")) {
|
||||||
|
throw new com.budwk.app.base.exception.BaseException("仅分工会主席可发起特殊慰问申请");
|
||||||
|
}
|
||||||
|
String formDataStr = execution.getArgs().getStr(FlowConst.FORM_DATA);
|
||||||
|
SpecialCondolence specialcondolence = Json.fromJson(SpecialCondolence.class, formDataStr);
|
||||||
|
|
||||||
|
if(StrUtil.isBlank(specialcondolence.getId())) specialcondolence.setCreateTime(DateUtil.now());
|
||||||
|
|
||||||
|
Dao dao = ServiceContext.find(Dao.class);
|
||||||
|
ServiceContext.find(com.budwk.app.zhgh.staffbenefit.specialcondolence.service.SpecialCondolenceService.class).saveApplication(specialcondolence);
|
||||||
|
|
||||||
|
// 设置流程变量
|
||||||
|
execution.getArgs().set("origin", specialcondolence.getOrigin());
|
||||||
|
|
||||||
|
int instanceId = execution.getArgs().getInt(FlowConst.PROCESS_INSTANCE_ID_KEY);
|
||||||
|
dao.update(ProcessInstance.class, Chain.make("businessNo", specialcondolence.getId()), Cnd.where(ProcessInstance::getId, "=", instanceId));
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
+310
@@ -0,0 +1,310 @@
|
|||||||
|
package com.budwk.app.zhgh.staffbenefit.specialcondolence.model;
|
||||||
|
|
||||||
|
import cn.hutool.json.JSONObject;
|
||||||
|
import com.budwk.app.base.model.BaseModel;
|
||||||
|
import com.budwk.app.sys.models.Sys_file;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.EqualsAndHashCode;
|
||||||
|
import org.nutz.dao.entity.annotation.*;
|
||||||
|
import org.nutz.dao.interceptor.annotation.PrevInsert;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ClassName SpecialCondolence
|
||||||
|
* @Author JyuHsin
|
||||||
|
* @Date 2025/7/28 11:03
|
||||||
|
* @Version 1.0
|
||||||
|
* @Description TODO
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@EqualsAndHashCode(callSuper = true)
|
||||||
|
@Table("special_condolence")
|
||||||
|
@TableMeta("{'mysql-charset':'utf8mb4'}")
|
||||||
|
@Comment("特殊慰问")
|
||||||
|
public class SpecialCondolence extends BaseModel {
|
||||||
|
|
||||||
|
@Name
|
||||||
|
@Comment("ID")
|
||||||
|
@ColDefine(type = ColType.VARCHAR, width = 32)
|
||||||
|
@PrevInsert(uu32 = true)
|
||||||
|
private String id;
|
||||||
|
|
||||||
|
@Column
|
||||||
|
@Comment("事项")
|
||||||
|
@ColDefine(type = ColType.VARCHAR, width = 200)
|
||||||
|
private String subject;
|
||||||
|
|
||||||
|
|
||||||
|
@Column
|
||||||
|
@Comment("申请人ID")
|
||||||
|
@ColDefine(type = ColType.VARCHAR, width = 32)
|
||||||
|
private String applyUserId;
|
||||||
|
|
||||||
|
@Column
|
||||||
|
@Comment("申请人姓名")
|
||||||
|
@ColDefine(type = ColType.VARCHAR, width = 100)
|
||||||
|
private String applyUserName;
|
||||||
|
|
||||||
|
@Column
|
||||||
|
@Comment("申请人工号")
|
||||||
|
@ColDefine(type = ColType.VARCHAR, width = 120)
|
||||||
|
private String applyLoginName;
|
||||||
|
|
||||||
|
@Column
|
||||||
|
@Comment("申请人分工会ID")
|
||||||
|
@ColDefine(type = ColType.VARCHAR, width = 32)
|
||||||
|
private String applyUnionId;
|
||||||
|
|
||||||
|
@Column
|
||||||
|
@Comment("申请人分工会")
|
||||||
|
@ColDefine(type = ColType.VARCHAR, width = 100)
|
||||||
|
private String applyUnionName;
|
||||||
|
|
||||||
|
@Column
|
||||||
|
@Comment("申请人单位ID")
|
||||||
|
@ColDefine(type = ColType.VARCHAR, width = 32)
|
||||||
|
private String applyUnitId;
|
||||||
|
|
||||||
|
@Column
|
||||||
|
@Comment("申请人单位")
|
||||||
|
@ColDefine(type = ColType.VARCHAR, width = 100)
|
||||||
|
private String applyUnitName;
|
||||||
|
|
||||||
|
@Column
|
||||||
|
@Comment("补助人ID")
|
||||||
|
@ColDefine(type = ColType.VARCHAR, width = 32)
|
||||||
|
private String helpUserId;
|
||||||
|
|
||||||
|
@Column
|
||||||
|
@Comment("补助人姓名")
|
||||||
|
@ColDefine(type = ColType.VARCHAR, width = 100)
|
||||||
|
private String helpUserName;
|
||||||
|
|
||||||
|
@Column
|
||||||
|
@Comment("补助人工号")
|
||||||
|
@ColDefine(type = ColType.VARCHAR, width = 120)
|
||||||
|
private String helpLoginName;
|
||||||
|
|
||||||
|
@Column
|
||||||
|
@Comment("补助人分工会ID")
|
||||||
|
@ColDefine(type = ColType.VARCHAR, width = 32)
|
||||||
|
private String helpUnionId;
|
||||||
|
|
||||||
|
@Column
|
||||||
|
@Comment("补助人分工会")
|
||||||
|
@ColDefine(type = ColType.VARCHAR, width = 100)
|
||||||
|
private String helpUnionName;
|
||||||
|
|
||||||
|
@Column
|
||||||
|
@Comment("补助人单位ID")
|
||||||
|
@ColDefine(type = ColType.VARCHAR, width = 32)
|
||||||
|
private String helpUnitId;
|
||||||
|
|
||||||
|
@Column
|
||||||
|
@Comment("补助人单位")
|
||||||
|
@ColDefine(type = ColType.VARCHAR, width = 100)
|
||||||
|
private String helpUnitName;
|
||||||
|
|
||||||
|
@Column
|
||||||
|
@Comment("类型")
|
||||||
|
@ColDefine(type = ColType.VARCHAR, width = 20)
|
||||||
|
private String origin;
|
||||||
|
|
||||||
|
@Column
|
||||||
|
@Comment("收款人")
|
||||||
|
@ColDefine(type = ColType.VARCHAR, width = 32)
|
||||||
|
private String payUserId;
|
||||||
|
|
||||||
|
@Column
|
||||||
|
@Comment("收款人姓名")
|
||||||
|
@ColDefine(type = ColType.VARCHAR, width = 30)
|
||||||
|
private String payUserName;
|
||||||
|
|
||||||
|
@Column
|
||||||
|
@Comment("收款人工号")
|
||||||
|
@ColDefine(type = ColType.VARCHAR, width = 20)
|
||||||
|
private String payLoginName;
|
||||||
|
|
||||||
|
@Column
|
||||||
|
@Comment("慰问类型")
|
||||||
|
@ColDefine(type = ColType.VARCHAR, width = 32)
|
||||||
|
private String type;
|
||||||
|
|
||||||
|
@Column
|
||||||
|
@Comment("慰问编码")
|
||||||
|
@ColDefine(type = ColType.VARCHAR, width = 32)
|
||||||
|
private String typeCode;
|
||||||
|
|
||||||
|
@Column
|
||||||
|
@Comment("慰问方式")
|
||||||
|
@ColDefine(type = ColType.VARCHAR, width = 20)
|
||||||
|
private String way;
|
||||||
|
|
||||||
|
@Column
|
||||||
|
@Comment("统一每人慰问金额")
|
||||||
|
@ColDefine(customType = "decimal(10,2)")
|
||||||
|
private java.math.BigDecimal perMoney;
|
||||||
|
|
||||||
|
@Column
|
||||||
|
@Comment("慰问金额")
|
||||||
|
@ColDefine(type = ColType.FLOAT, width = 10, precision = 2)
|
||||||
|
private Double money;
|
||||||
|
|
||||||
|
@Column
|
||||||
|
@Comment("发生时间")
|
||||||
|
@ColDefine(type = ColType.VARCHAR, width = 30)
|
||||||
|
private String occurTime;
|
||||||
|
|
||||||
|
@Column
|
||||||
|
@Comment("生育几孩(孩次)")
|
||||||
|
@ColDefine(type = ColType.VARCHAR, width = 10)
|
||||||
|
private String child;
|
||||||
|
|
||||||
|
@Column
|
||||||
|
@Comment("所在医院")
|
||||||
|
@ColDefine(type = ColType.VARCHAR, width = 50)
|
||||||
|
private String hospital;
|
||||||
|
|
||||||
|
@Column
|
||||||
|
@Comment("病房床号")
|
||||||
|
@ColDefine(type = ColType.VARCHAR, width = 20)
|
||||||
|
private String hospitalHouseNum;
|
||||||
|
|
||||||
|
@Column
|
||||||
|
@Comment("病房床号")
|
||||||
|
@ColDefine(type = ColType.VARCHAR, width = 20)
|
||||||
|
private String hospitalHouseBedNum;
|
||||||
|
|
||||||
|
@Column
|
||||||
|
@Comment("住院病由")
|
||||||
|
@ColDefine(type = ColType.VARCHAR, width = 100)
|
||||||
|
private String hospitalBy;
|
||||||
|
|
||||||
|
@Column
|
||||||
|
@Comment("备注")
|
||||||
|
@ColDefine(type = ColType.VARCHAR, width = 500)
|
||||||
|
private String remark;
|
||||||
|
|
||||||
|
@Column
|
||||||
|
@Comment("附件")
|
||||||
|
@ColDefine(type = ColType.MYSQL_JSON)
|
||||||
|
private List<JSONObject> files;
|
||||||
|
|
||||||
|
@Comment("签字")
|
||||||
|
@ColDefine(type = ColType.VARCHAR, width = 255)
|
||||||
|
@Column(hump = true)
|
||||||
|
private String signature;
|
||||||
|
|
||||||
|
@Column
|
||||||
|
@Comment("申请时间")
|
||||||
|
@ColDefine(type = ColType.VARCHAR, width = 30)
|
||||||
|
private String createTime;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@Column
|
||||||
|
@Comment("户名")
|
||||||
|
@ColDefine(type = ColType.VARCHAR, width = 100)
|
||||||
|
private String bankUserName;
|
||||||
|
|
||||||
|
@Column
|
||||||
|
@Comment("银行账号")
|
||||||
|
@ColDefine(type = ColType.VARCHAR, width = 100)
|
||||||
|
private String bankCardNumber;
|
||||||
|
|
||||||
|
@Column
|
||||||
|
@Comment("开户行")
|
||||||
|
@ColDefine(type = ColType.VARCHAR, width = 100)
|
||||||
|
private String bankOfDeposit;
|
||||||
|
|
||||||
|
@Column
|
||||||
|
@Comment("证明人ID")
|
||||||
|
@ColDefine(type = ColType.VARCHAR, width = 32)
|
||||||
|
private String certifierUserId;
|
||||||
|
|
||||||
|
@Column
|
||||||
|
@Comment("证明人姓名")
|
||||||
|
@ColDefine(type = ColType.VARCHAR, width = 100)
|
||||||
|
private String certifierUserName;
|
||||||
|
|
||||||
|
@Column
|
||||||
|
@Comment("证明人工号")
|
||||||
|
@ColDefine(type = ColType.VARCHAR, width = 120)
|
||||||
|
private String certifierLoginName;
|
||||||
|
|
||||||
|
@Column
|
||||||
|
@Comment("证明人分工会ID")
|
||||||
|
@ColDefine(type = ColType.VARCHAR, width = 32)
|
||||||
|
private String certifierUnionId;
|
||||||
|
|
||||||
|
@Column
|
||||||
|
@Comment("证明人分工会")
|
||||||
|
@ColDefine(type = ColType.VARCHAR, width = 100)
|
||||||
|
private String certifierUnionName;
|
||||||
|
|
||||||
|
@Column
|
||||||
|
@Comment("证明人单位ID")
|
||||||
|
@ColDefine(type = ColType.VARCHAR, width = 32)
|
||||||
|
private String certifierUnitId;
|
||||||
|
|
||||||
|
@Column
|
||||||
|
@Comment("证明人单位")
|
||||||
|
@ColDefine(type = ColType.VARCHAR, width = 100)
|
||||||
|
private String certifierUnitName;
|
||||||
|
|
||||||
|
@Column
|
||||||
|
@Comment("经办人ID")
|
||||||
|
@ColDefine(type = ColType.VARCHAR, width = 32)
|
||||||
|
private String handlerUserId;
|
||||||
|
|
||||||
|
@Column
|
||||||
|
@Comment("经办人姓名")
|
||||||
|
@ColDefine(type = ColType.VARCHAR, width = 100)
|
||||||
|
private String handlerUserName;
|
||||||
|
|
||||||
|
@Column
|
||||||
|
@Comment("经办人工号")
|
||||||
|
@ColDefine(type = ColType.VARCHAR, width = 120)
|
||||||
|
private String handlerLoginName;
|
||||||
|
|
||||||
|
@Column
|
||||||
|
@Comment("经办人分工会ID")
|
||||||
|
@ColDefine(type = ColType.VARCHAR, width = 32)
|
||||||
|
private String handlerUnionId;
|
||||||
|
|
||||||
|
@Column
|
||||||
|
@Comment("经办人分工会")
|
||||||
|
@ColDefine(type = ColType.VARCHAR, width = 100)
|
||||||
|
private String handlerUnionName;
|
||||||
|
|
||||||
|
@Column
|
||||||
|
@Comment("经办人单位ID")
|
||||||
|
@ColDefine(type = ColType.VARCHAR, width = 32)
|
||||||
|
private String handlerUnitId;
|
||||||
|
|
||||||
|
@Column
|
||||||
|
@Comment("经办人单位")
|
||||||
|
@ColDefine(type = ColType.VARCHAR, width = 100)
|
||||||
|
private String handlerUnitName;
|
||||||
|
|
||||||
|
@Column
|
||||||
|
@Comment("入院时间")
|
||||||
|
@ColDefine(type = ColType.VARCHAR, width = 30)
|
||||||
|
private String hospitalizationTime;
|
||||||
|
|
||||||
|
@Column
|
||||||
|
@Comment("出院时间")
|
||||||
|
@ColDefine(type = ColType.VARCHAR, width = 30)
|
||||||
|
private String leaveHospitalTime;
|
||||||
|
|
||||||
|
@Column
|
||||||
|
@Comment("当年第几次住院")
|
||||||
|
@ColDefine(type = ColType.INT)
|
||||||
|
private Integer thisYearHospitalizationNum;
|
||||||
|
|
||||||
|
@Comment("慰问对象明细,由明细表加载")
|
||||||
|
private List<JSONObject> recipients;
|
||||||
|
|
||||||
|
}
|
||||||
+100
@@ -0,0 +1,100 @@
|
|||||||
|
package com.budwk.app.zhgh.staffbenefit.specialcondolence.model;
|
||||||
|
|
||||||
|
import com.budwk.app.base.model.BaseModel;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.EqualsAndHashCode;
|
||||||
|
import org.nutz.dao.entity.annotation.*;
|
||||||
|
import org.nutz.dao.interceptor.annotation.PrevInsert;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
@EqualsAndHashCode(callSuper = true)
|
||||||
|
@Table("special_condolence_recipient")
|
||||||
|
@TableMeta("{'mysql-charset':'utf8mb4'}")
|
||||||
|
@TableIndexes({@Index(name = "idx_special_condolence_recipient_apply", fields = {"applyId"}, unique = false)})
|
||||||
|
@Comment("特殊慰问被申请人明细")
|
||||||
|
public class SpecialCondolenceRecipient extends BaseModel {
|
||||||
|
@Name
|
||||||
|
@PrevInsert(uu32 = true)
|
||||||
|
@ColDefine(type = ColType.VARCHAR, width = 32)
|
||||||
|
private String id;
|
||||||
|
|
||||||
|
@Column
|
||||||
|
@Comment("申请ID")
|
||||||
|
@ColDefine(type = ColType.VARCHAR, width = 32)
|
||||||
|
private String applyId;
|
||||||
|
|
||||||
|
@Column
|
||||||
|
@Comment("慰问对象用户ID")
|
||||||
|
@ColDefine(type = ColType.VARCHAR, width = 32)
|
||||||
|
private String helpUserId;
|
||||||
|
|
||||||
|
@Column
|
||||||
|
@Comment("人员类型")
|
||||||
|
@ColDefine(type = ColType.VARCHAR, width = 50)
|
||||||
|
private String personType;
|
||||||
|
|
||||||
|
@Column
|
||||||
|
@Comment("慰问对象工号")
|
||||||
|
@ColDefine(type = ColType.VARCHAR, width = 120)
|
||||||
|
private String helpLoginName;
|
||||||
|
|
||||||
|
@Column
|
||||||
|
@Comment("慰问对象")
|
||||||
|
@ColDefine(type = ColType.VARCHAR, width = 100)
|
||||||
|
private String helpUserName;
|
||||||
|
|
||||||
|
@Column
|
||||||
|
@Comment("慰问类型ID")
|
||||||
|
@ColDefine(type = ColType.VARCHAR, width = 32)
|
||||||
|
private String type;
|
||||||
|
|
||||||
|
@Column
|
||||||
|
@Comment("慰问类型名称")
|
||||||
|
@ColDefine(type = ColType.VARCHAR, width = 50)
|
||||||
|
private String typeName;
|
||||||
|
|
||||||
|
@Column
|
||||||
|
@Comment("慰问类型编码")
|
||||||
|
@ColDefine(type = ColType.VARCHAR, width = 32)
|
||||||
|
private String typeCode;
|
||||||
|
|
||||||
|
@Column
|
||||||
|
@Comment("慰问方式")
|
||||||
|
@ColDefine(type = ColType.VARCHAR, width = 20)
|
||||||
|
private String way;
|
||||||
|
|
||||||
|
@Column
|
||||||
|
@Comment("身份证号码")
|
||||||
|
@ColDefine(type = ColType.VARCHAR, width = 18)
|
||||||
|
private String idCard;
|
||||||
|
|
||||||
|
@Column
|
||||||
|
@Comment("开户行")
|
||||||
|
@ColDefine(type = ColType.VARCHAR, width = 100)
|
||||||
|
private String bankOfDeposit;
|
||||||
|
|
||||||
|
@Column
|
||||||
|
@Comment("户名")
|
||||||
|
@ColDefine(type = ColType.VARCHAR, width = 100)
|
||||||
|
private String bankUserName;
|
||||||
|
|
||||||
|
@Column
|
||||||
|
@Comment("收款账户")
|
||||||
|
@ColDefine(type = ColType.VARCHAR, width = 30)
|
||||||
|
private String bankCardNumber;
|
||||||
|
|
||||||
|
@Column
|
||||||
|
@Comment("慰问金额")
|
||||||
|
@ColDefine(customType = "decimal(10,2)")
|
||||||
|
private java.math.BigDecimal money;
|
||||||
|
|
||||||
|
@Column
|
||||||
|
@Comment("慰问时间")
|
||||||
|
@ColDefine(type = ColType.VARCHAR, width = 30)
|
||||||
|
private String occurTime;
|
||||||
|
|
||||||
|
@Column
|
||||||
|
@Comment("行序号")
|
||||||
|
@ColDefine(type = ColType.INT)
|
||||||
|
private Integer sortNum;
|
||||||
|
}
|
||||||
+84
@@ -0,0 +1,84 @@
|
|||||||
|
package com.budwk.app.zhgh.staffbenefit.specialcondolence.model;
|
||||||
|
|
||||||
|
import com.budwk.app.base.model.BaseModel;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.EqualsAndHashCode;
|
||||||
|
import org.nutz.dao.DB;
|
||||||
|
import org.nutz.dao.entity.annotation.*;
|
||||||
|
import org.nutz.dao.interceptor.annotation.PrevInsert;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ClassName SpecialCondolenceType
|
||||||
|
* @Author JyuHsin
|
||||||
|
* @Date 2025/7/29 9:59
|
||||||
|
* @Version 1.0
|
||||||
|
* @Description TODO
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@EqualsAndHashCode(callSuper = true)
|
||||||
|
@Table("special_condolence_type")
|
||||||
|
@TableMeta("{'mysql-charset':'utf8mb4'}")
|
||||||
|
@Comment("特殊慰问类型")
|
||||||
|
public class SpecialCondolenceType extends BaseModel {
|
||||||
|
|
||||||
|
@Name
|
||||||
|
@Comment("ID")
|
||||||
|
@ColDefine(type = ColType.VARCHAR, width = 32)
|
||||||
|
@PrevInsert(uu32 = true)
|
||||||
|
private String id;
|
||||||
|
|
||||||
|
@Column
|
||||||
|
@Comment("编码")
|
||||||
|
@ColDefine(type = ColType.VARCHAR, width = 30)
|
||||||
|
private String code;
|
||||||
|
|
||||||
|
@Column
|
||||||
|
@Comment("名称")
|
||||||
|
@ColDefine(type = ColType.VARCHAR, width = 50)
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
@Column
|
||||||
|
@Comment("费用")
|
||||||
|
@ColDefine(type = ColType.FLOAT, width = 10, precision = 2)
|
||||||
|
private Double money;
|
||||||
|
|
||||||
|
@Column
|
||||||
|
@Comment("慰问方式")
|
||||||
|
@ColDefine(type = ColType.VARCHAR, width = 20)
|
||||||
|
private String way;
|
||||||
|
|
||||||
|
@Column
|
||||||
|
@Comment("是否启用")
|
||||||
|
@ColDefine(type = ColType.BOOLEAN)
|
||||||
|
@Default("1")
|
||||||
|
private Boolean enable;
|
||||||
|
|
||||||
|
@Column
|
||||||
|
@Comment("是否上传附件")
|
||||||
|
@ColDefine(type = ColType.BOOLEAN)
|
||||||
|
private Boolean isUploadFile;
|
||||||
|
|
||||||
|
@Column
|
||||||
|
@Comment("上传附件说明")
|
||||||
|
@ColDefine(type = ColType.VARCHAR,width = 50)
|
||||||
|
private String uploadFileDesc;
|
||||||
|
|
||||||
|
@Column
|
||||||
|
@Comment("排序字段")
|
||||||
|
@Prev({
|
||||||
|
@SQL(db = DB.MYSQL, value = "SELECT IFNULL(MAX(location),0)+1 FROM special_condolence_type"),
|
||||||
|
@SQL(db = DB.ORACLE, value = "SELECT COALESCE(MAX(location),0)+1 FROM special_condolence_type")
|
||||||
|
})
|
||||||
|
private Integer location;
|
||||||
|
|
||||||
|
@Column
|
||||||
|
@Comment("排序")
|
||||||
|
@ColDefine(type = ColType.INT)
|
||||||
|
private int sortNum;
|
||||||
|
|
||||||
|
@Column
|
||||||
|
@Comment("上传会议纪要")
|
||||||
|
@Default("0")
|
||||||
|
@ColDefine(type = ColType.BOOLEAN)
|
||||||
|
private Boolean uploadMeetingRecord;
|
||||||
|
}
|
||||||
+119
@@ -0,0 +1,119 @@
|
|||||||
|
package com.budwk.app.zhgh.staffbenefit.specialcondolence.service;
|
||||||
|
|
||||||
|
import cn.hutool.json.JSONObject;
|
||||||
|
import com.budwk.app.base.exception.BaseException;
|
||||||
|
import com.budwk.app.zhgh.staffbenefit.specialcondolence.model.SpecialCondolence;
|
||||||
|
import com.budwk.app.zhgh.staffbenefit.specialcondolence.model.SpecialCondolenceType;
|
||||||
|
import org.nutz.dao.Dao;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.time.LocalDate;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public final class SpecialCondolenceRecipients {
|
||||||
|
private SpecialCondolenceRecipients() {}
|
||||||
|
|
||||||
|
public static void prepare(SpecialCondolence info, Dao dao) {
|
||||||
|
if (info.getSubject() == null || info.getSubject().trim().isEmpty() || info.getSubject().trim().length() > 200) throw new BaseException("请填写200字以内的事项");
|
||||||
|
info.setSubject(info.getSubject().trim());
|
||||||
|
List<JSONObject> rows = info.getRecipients();
|
||||||
|
if (rows == null || rows.isEmpty()) throw new BaseException("请添加慰问对象");
|
||||||
|
if (rows.size() > 1000) throw new BaseException("每次申请最多1000人");
|
||||||
|
if (info.getFiles() != null && info.getFiles().size() > 5) throw new BaseException("最多上传5个附件");
|
||||||
|
if (info.getRemark() != null && info.getRemark().trim().length() > 500) throw new BaseException("申请事由最多500字");
|
||||||
|
if (info.getPerMoney() == null || info.getPerMoney().signum() <= 0 || info.getPerMoney().compareTo(new BigDecimal("10000")) > 0 || info.getPerMoney().scale() > 2) throw new BaseException("每人慰问金额须大于0且不超过10000元,最多两位小数");
|
||||||
|
try { LocalDate.parse(info.getOccurTime()); }
|
||||||
|
catch (Exception e) { throw new BaseException("请选择有效的统一慰问时间"); }
|
||||||
|
BigDecimal total = BigDecimal.ZERO;
|
||||||
|
for (int i = 0; i < rows.size(); i++) {
|
||||||
|
JSONObject row = rows.get(i);
|
||||||
|
String prefix = "第" + (i + 1) + "行:";
|
||||||
|
if (row == null) throw new BaseException(prefix + "明细不能为空");
|
||||||
|
row.set("type", info.getType());
|
||||||
|
row.set("money", info.getPerMoney().toPlainString());
|
||||||
|
row.set("occurTime", info.getOccurTime());
|
||||||
|
resolveUser(row, dao, prefix);
|
||||||
|
String[] fields = {"helpUserName", "type", "idCard", "bankOfDeposit", "bankUserName", "bankCardNumber", "money", "occurTime"};
|
||||||
|
for (String field : fields) {
|
||||||
|
String value = row.getStr(field);
|
||||||
|
if (value == null || value.trim().isEmpty()) throw new BaseException(prefix + "请填写完整的慰问对象信息");
|
||||||
|
row.set(field, value.trim());
|
||||||
|
}
|
||||||
|
if (!validIdCard(row.getStr("idCard"))) throw new BaseException(prefix + "身份证号码不正确");
|
||||||
|
if (!row.getStr("bankCardNumber").matches("[0-9]{6,30}")) throw new BaseException(prefix + "收款账户须为6至30位数字");
|
||||||
|
if (row.getStr("helpUserName").length() > 100 || row.getStr("bankOfDeposit").length() > 100 || row.getStr("bankUserName").length() > 100) throw new BaseException(prefix + "姓名、开户行、户名不能超过100字");
|
||||||
|
if (!row.getStr("money").matches("[0-9]+(\\.[0-9]{1,2})?")) throw new BaseException(prefix + "金额最多两位小数");
|
||||||
|
BigDecimal money = new BigDecimal(row.getStr("money"));
|
||||||
|
if (money.signum() <= 0 || money.compareTo(new BigDecimal("10000")) > 0) throw new BaseException(prefix + "金额须大于0且不超过10000元");
|
||||||
|
try { LocalDate.parse(row.getStr("occurTime")); }
|
||||||
|
catch (Exception e) { throw new BaseException(prefix + "慰问时间格式须为yyyy-MM-dd"); }
|
||||||
|
SpecialCondolenceType type = dao.fetch(SpecialCondolenceType.class, row.getStr("type"));
|
||||||
|
if (type == null || !Boolean.TRUE.equals(type.getEnable())) throw new BaseException(prefix + "慰问类型不存在或已停用");
|
||||||
|
row.set("typeName", type.getName());
|
||||||
|
row.set("typeCode", type.getCode());
|
||||||
|
row.set("way", type.getWay());
|
||||||
|
if (Boolean.TRUE.equals(type.getIsUploadFile()) && (info.getFiles() == null || info.getFiles().isEmpty())) throw new BaseException(prefix + "该慰问类型需要上传附件");
|
||||||
|
total = total.add(money);
|
||||||
|
}
|
||||||
|
JSONObject first = rows.get(0);
|
||||||
|
String name = first.getStr("helpUserName");
|
||||||
|
info.setHelpUserName((rows.size() > 1 && name.length() > 90 ? name.substring(0, 90) : name) + (rows.size() > 1 ? "等" + rows.size() + "人" : ""));
|
||||||
|
info.setHelpUnitId(info.getApplyUnitId());
|
||||||
|
info.setHelpUnitName(info.getApplyUnitName());
|
||||||
|
info.setHelpUnionId(info.getApplyUnionId());
|
||||||
|
info.setHelpUnionName(info.getApplyUnionName());
|
||||||
|
info.setType(first.getStr("type"));
|
||||||
|
info.setTypeCode(first.getStr("typeCode"));
|
||||||
|
info.setWay(first.getStr("way"));
|
||||||
|
info.setOccurTime(first.getStr("occurTime"));
|
||||||
|
info.setMoney(total.doubleValue());
|
||||||
|
info.setBankOfDeposit(first.getStr("bankOfDeposit"));
|
||||||
|
info.setBankUserName(first.getStr("bankUserName"));
|
||||||
|
info.setBankCardNumber(first.getStr("bankCardNumber"));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void resolveUser(JSONObject row, Dao dao, String prefix) {
|
||||||
|
String userId = row.getStr("helpUserId");
|
||||||
|
com.budwk.app.sys.views.View_user user;
|
||||||
|
String unionId = com.budwk.app.web.commons.auth.utils.SecurityUtil.getUnionId();
|
||||||
|
if (cn.hutool.core.util.StrUtil.isBlank(unionId)) throw new BaseException(prefix + "申请人未关联分工会");
|
||||||
|
if (cn.hutool.core.util.StrUtil.isNotBlank(userId)) {
|
||||||
|
user = dao.fetch(com.budwk.app.sys.views.View_user.class, org.nutz.dao.Cnd.where("id", "=", userId));
|
||||||
|
} else {
|
||||||
|
org.nutz.dao.Cnd identity = org.nutz.dao.Cnd.where("unionId", "=", unionId)
|
||||||
|
.and("idCard", "=", row.getStr("idCard")).and("username", "=", row.getStr("helpUserName"));
|
||||||
|
java.util.List<com.budwk.app.sys.views.View_user> dispatched = dao.query(com.budwk.app.sys.views.View_user.class,
|
||||||
|
identity.and("personType", "=", "劳务派遣人员"));
|
||||||
|
if (dispatched.size() > 1) throw new BaseException(prefix + "劳务派遣人员身份重复,请核对档案");
|
||||||
|
if (dispatched.size() == 1) {
|
||||||
|
user = dispatched.get(0);
|
||||||
|
} else {
|
||||||
|
if (cn.hutool.core.util.StrUtil.isBlank(row.getStr("helpLoginName"))) throw new BaseException(prefix + "普通人员必须填写工号");
|
||||||
|
java.util.List<com.budwk.app.sys.views.View_user> users = dao.query(com.budwk.app.sys.views.View_user.class,
|
||||||
|
org.nutz.dao.Cnd.where("unionId", "=", unionId).and("loginname", "=", row.getStr("helpLoginName"))
|
||||||
|
.and("username", "=", row.getStr("helpUserName")).and("idCard", "=", row.getStr("idCard")));
|
||||||
|
if (users.size() != 1) throw new BaseException(prefix + "工号、姓名、身份证不匹配或不属于申请人本工会");
|
||||||
|
user = users.get(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (user == null) throw new BaseException(prefix + "慰问对象不存在");
|
||||||
|
if (!java.util.Objects.equals(user.getUnionId(), unionId)) throw new BaseException(prefix + "只能选择申请人本工会人员");
|
||||||
|
if (!"劳务派遣人员".equals(user.getPersonType()) && (cn.hutool.core.util.StrUtil.isBlank(row.getStr("helpLoginName")) || !java.util.Objects.equals(user.getLoginname(), row.getStr("helpLoginName")))) throw new BaseException(prefix + "工号与慰问对象不一致");
|
||||||
|
if (cn.hutool.core.util.StrUtil.isNotBlank(user.getIdCard()) && !user.getIdCard().equalsIgnoreCase(row.getStr("idCard"))) throw new BaseException(prefix + "身份证号码与所选人员不一致");
|
||||||
|
row.set("helpUserId", user.getId());
|
||||||
|
row.set("helpLoginName", user.getLoginname());
|
||||||
|
row.set("personType", user.getPersonType());
|
||||||
|
row.set("helpUserName", user.getUsername());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean validIdCard(String value) {
|
||||||
|
if (value == null || !value.matches("[1-9][0-9]{16}[0-9Xx]")) return false;
|
||||||
|
try { LocalDate.parse(value.substring(6, 14), java.time.format.DateTimeFormatter.BASIC_ISO_DATE); }
|
||||||
|
catch (Exception e) { return false; }
|
||||||
|
int[] weights = {7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2};
|
||||||
|
int sum = 0;
|
||||||
|
for (int i = 0; i < weights.length; i++) sum += (value.charAt(i) - '0') * weights[i];
|
||||||
|
return "10X98765432".charAt(sum % 11) == Character.toUpperCase(value.charAt(17));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
+17
@@ -0,0 +1,17 @@
|
|||||||
|
package com.budwk.app.zhgh.staffbenefit.specialcondolence.service;
|
||||||
|
|
||||||
|
import com.budwk.app.base.service.BaseService;
|
||||||
|
import com.budwk.app.zhgh.staffbenefit.specialcondolence.model.SpecialCondolence;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ClassName SpecialCondolenceService
|
||||||
|
* @Author JyuHsin
|
||||||
|
* @Date 2025/7/29 11:21
|
||||||
|
* @Version 1.0
|
||||||
|
* @Description TODO
|
||||||
|
*/
|
||||||
|
public interface SpecialCondolenceService extends BaseService<SpecialCondolence> {
|
||||||
|
void saveApplication(SpecialCondolence info);
|
||||||
|
SpecialCondolence loadApplication(String id);
|
||||||
|
void deleteApplication(String id);
|
||||||
|
}
|
||||||
+14
@@ -0,0 +1,14 @@
|
|||||||
|
package com.budwk.app.zhgh.staffbenefit.specialcondolence.service;
|
||||||
|
|
||||||
|
import com.budwk.app.base.service.BaseService;
|
||||||
|
import com.budwk.app.zhgh.staffbenefit.specialcondolence.model.SpecialCondolenceType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ClassName SpecialCondolenceTypeService
|
||||||
|
* @Author JyuHsin
|
||||||
|
* @Date 2025/7/29 10:03
|
||||||
|
* @Version 1.0
|
||||||
|
* @Description TODO
|
||||||
|
*/
|
||||||
|
public interface SpecialCondolenceTypeService extends BaseService<SpecialCondolenceType> {
|
||||||
|
}
|
||||||
+87
@@ -0,0 +1,87 @@
|
|||||||
|
package com.budwk.app.zhgh.staffbenefit.specialcondolence.service.impl;
|
||||||
|
|
||||||
|
import com.budwk.app.base.service.impl.BaseServiceImpl;
|
||||||
|
import com.budwk.app.zhgh.staffbenefit.specialcondolence.model.SpecialCondolenceRecipient;
|
||||||
|
import com.budwk.app.zhgh.staffbenefit.specialcondolence.service.SpecialCondolenceRecipients;
|
||||||
|
import cn.hutool.json.JSONObject;
|
||||||
|
import cn.hutool.json.JSONUtil;
|
||||||
|
import org.nutz.ioc.aop.Aop;
|
||||||
|
import org.nutz.aop.interceptor.ioc.TransAop;
|
||||||
|
import org.nutz.dao.Cnd;
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import com.budwk.app.zhgh.staffbenefit.specialcondolence.model.SpecialCondolence;
|
||||||
|
import com.budwk.app.zhgh.staffbenefit.specialcondolence.service.SpecialCondolenceService;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.nutz.dao.Dao;
|
||||||
|
import org.nutz.ioc.loader.annotation.IocBean;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ClassName SpecialCondolenceServiceImpl
|
||||||
|
* @Author JyuHsin
|
||||||
|
* @Date 2025/7/29 11:22
|
||||||
|
* @Version 1.0
|
||||||
|
* @Description TODO
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
@IocBean(args = {"refer:dao"})
|
||||||
|
public class SpecialCondolenceServiceImpl extends BaseServiceImpl<SpecialCondolence> implements SpecialCondolenceService {
|
||||||
|
|
||||||
|
public SpecialCondolenceServiceImpl(Dao dao) {
|
||||||
|
super(dao);
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
@Aop(TransAop.READ_COMMITTED)
|
||||||
|
public void saveApplication(SpecialCondolence info) {
|
||||||
|
SpecialCondolenceRecipients.prepare(info, dao());
|
||||||
|
dao().insertOrUpdate(info);
|
||||||
|
dao().clear(SpecialCondolenceRecipient.class,
|
||||||
|
Cnd.where("applyId", "=", info.getId()));
|
||||||
|
int sort = 0;
|
||||||
|
for (JSONObject row : info.getRecipients()) {
|
||||||
|
SpecialCondolenceRecipient person = new SpecialCondolenceRecipient();
|
||||||
|
person.setApplyId(info.getId());
|
||||||
|
person.setHelpUserName(row.getStr("helpUserName"));
|
||||||
|
person.setHelpUserId(row.getStr("helpUserId"));
|
||||||
|
person.setHelpLoginName(row.getStr("helpLoginName"));
|
||||||
|
person.setPersonType(row.getStr("personType"));
|
||||||
|
person.setType(row.getStr("type"));
|
||||||
|
person.setTypeName(row.getStr("typeName"));
|
||||||
|
person.setTypeCode(row.getStr("typeCode"));
|
||||||
|
person.setWay(row.getStr("way"));
|
||||||
|
person.setIdCard(row.getStr("idCard"));
|
||||||
|
person.setBankOfDeposit(row.getStr("bankOfDeposit"));
|
||||||
|
person.setBankUserName(row.getStr("bankUserName"));
|
||||||
|
person.setBankCardNumber(row.getStr("bankCardNumber"));
|
||||||
|
person.setMoney(new BigDecimal(row.getStr("money")));
|
||||||
|
person.setOccurTime(row.getStr("occurTime"));
|
||||||
|
person.setSortNum(sort++);
|
||||||
|
dao().insert(person);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SpecialCondolence loadApplication(String id) {
|
||||||
|
SpecialCondolence info = fetch(id);
|
||||||
|
if (info != null) {
|
||||||
|
List<JSONObject> rows = new ArrayList<>();
|
||||||
|
for (SpecialCondolenceRecipient person : dao().query(
|
||||||
|
SpecialCondolenceRecipient.class,
|
||||||
|
Cnd.where("applyId", "=", id).asc("sortNum").asc("id"))) {
|
||||||
|
rows.add(JSONUtil.parseObj(person));
|
||||||
|
}
|
||||||
|
info.setRecipients(rows);
|
||||||
|
}
|
||||||
|
return info;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Aop(TransAop.READ_COMMITTED)
|
||||||
|
public void deleteApplication(String id) {
|
||||||
|
dao().clear(SpecialCondolenceRecipient.class,
|
||||||
|
Cnd.where("applyId", "=", id));
|
||||||
|
delete(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
+24
@@ -0,0 +1,24 @@
|
|||||||
|
package com.budwk.app.zhgh.staffbenefit.specialcondolence.service.impl;
|
||||||
|
|
||||||
|
import com.budwk.app.base.service.impl.BaseServiceImpl;
|
||||||
|
import com.budwk.app.zhgh.staffbenefit.specialcondolence.model.SpecialCondolenceType;
|
||||||
|
import com.budwk.app.zhgh.staffbenefit.specialcondolence.service.SpecialCondolenceTypeService;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.nutz.dao.Dao;
|
||||||
|
import org.nutz.ioc.loader.annotation.IocBean;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ClassName SpecialCondolenceTypeServiceImpl
|
||||||
|
* @Author JyuHsin
|
||||||
|
* @Date 2025/7/29 10:03
|
||||||
|
* @Version 1.0
|
||||||
|
* @Description TODO
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
@IocBean(args = {"refer:dao"})
|
||||||
|
public class SpecialCondolenceTypeServiceImpl extends BaseServiceImpl<SpecialCondolenceType> implements SpecialCondolenceTypeService {
|
||||||
|
|
||||||
|
public SpecialCondolenceTypeServiceImpl(Dao dao) {
|
||||||
|
super(dao);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -735,7 +735,6 @@ public class WelfareListServiceImpl extends BaseServiceImpl<WelfareList> impleme
|
|||||||
entities.add(new ExcelExportEntity("在职状态", "userState", 20));
|
entities.add(new ExcelExportEntity("在职状态", "userState", 20));
|
||||||
entities.add(new ExcelExportEntity("所属工会", "welfareUnionName", 20));
|
entities.add(new ExcelExportEntity("所属工会", "welfareUnionName", 20));
|
||||||
entities.add(new ExcelExportEntity("所属单位", "welfareUnitName", 20));
|
entities.add(new ExcelExportEntity("所属单位", "welfareUnitName", 20));
|
||||||
entities.add(new ExcelExportEntity("三级单位", "threeUnitName", 20));
|
|
||||||
entities.add(new ExcelExportEntity("备注", "remark", 20));
|
entities.add(new ExcelExportEntity("备注", "remark", 20));
|
||||||
|
|
||||||
// 设置导出参数
|
// 设置导出参数
|
||||||
|
|||||||
+57
-8
@@ -1,6 +1,5 @@
|
|||||||
package com.budwk.app.zhgh.welfare.service.impl;
|
package com.budwk.app.zhgh.welfare.service.impl;
|
||||||
|
|
||||||
import cn.afterturn.easypoi.entity.ImageEntity;
|
|
||||||
import cn.afterturn.easypoi.excel.ExcelExportUtil;
|
import cn.afterturn.easypoi.excel.ExcelExportUtil;
|
||||||
import cn.afterturn.easypoi.excel.entity.ExportParams;
|
import cn.afterturn.easypoi.excel.entity.ExportParams;
|
||||||
import cn.afterturn.easypoi.excel.entity.enmus.ExcelType;
|
import cn.afterturn.easypoi.excel.entity.enmus.ExcelType;
|
||||||
@@ -23,8 +22,12 @@ import com.budwk.app.zhgh.welfare.model.WelfareProjectSubjectOption;
|
|||||||
import com.budwk.app.zhgh.welfare.param.WelfareSelectionSituationPageForm;
|
import com.budwk.app.zhgh.welfare.param.WelfareSelectionSituationPageForm;
|
||||||
import com.budwk.app.zhgh.welfare.service.WelfareSelectionSituationService;
|
import com.budwk.app.zhgh.welfare.service.WelfareSelectionSituationService;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
|
import org.apache.poi.ss.usermodel.ClientAnchor;
|
||||||
|
import org.apache.poi.ss.usermodel.Drawing;
|
||||||
|
import org.apache.poi.ss.usermodel.Row;
|
||||||
|
import org.apache.poi.ss.usermodel.Sheet;
|
||||||
import org.apache.poi.ss.usermodel.Workbook;
|
import org.apache.poi.ss.usermodel.Workbook;
|
||||||
|
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
|
||||||
import org.nutz.dao.Cnd;
|
import org.nutz.dao.Cnd;
|
||||||
import org.nutz.dao.Dao;
|
import org.nutz.dao.Dao;
|
||||||
import org.nutz.dao.Sqls;
|
import org.nutz.dao.Sqls;
|
||||||
@@ -246,7 +249,8 @@ public class WelfareSelectionSituationServiceImpl extends BaseServiceImpl<Welfar
|
|||||||
byte[] userSignBytes = SysFileMinIoUtil.getFileBytes(file.getBucket(), file.getStoragePath());
|
byte[] userSignBytes = SysFileMinIoUtil.getFileBytes(file.getBucket(), file.getStoragePath());
|
||||||
map.put("userSign", userSignBytes);
|
map.put("userSign", userSignBytes);
|
||||||
}catch (Exception e){
|
}catch (Exception e){
|
||||||
e.printStackTrace();
|
// 下载失败时不把原文件地址写入签字单元格。
|
||||||
|
map.put("userSign", null);
|
||||||
log.error("下载图片失败", e);
|
log.error("下载图片失败", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -268,21 +272,66 @@ public class WelfareSelectionSituationServiceImpl extends BaseServiceImpl<Welfar
|
|||||||
optionList.forEach(option -> {
|
optionList.forEach(option -> {
|
||||||
entities.add(new ExcelExportEntity(option.getOptionName(), option.getOptionName(), 20));
|
entities.add(new ExcelExportEntity(option.getOptionName(), option.getOptionName(), 20));
|
||||||
});
|
});
|
||||||
|
// 签字列先按空白文本导出,图片另行写入,避开 EasyPOI 对 Map 图片字段的反射。
|
||||||
ExcelExportEntity userSignEntity = new ExcelExportEntity("签字", "userSign", 20);
|
ExcelExportEntity userSignEntity = new ExcelExportEntity("签字", "userSign", 20);
|
||||||
userSignEntity.setType(2);
|
|
||||||
userSignEntity.setExportImageType(2);
|
|
||||||
entities.add(userSignEntity);
|
entities.add(userSignEntity);
|
||||||
|
|
||||||
// 导出
|
// 导出
|
||||||
Workbook workbook = new HSSFWorkbook();
|
Workbook workbook = new XSSFWorkbook();
|
||||||
listMap.forEach((k, v) -> {
|
listMap.forEach((k, v) -> {
|
||||||
|
List<byte[]> signatures = new ArrayList<>();
|
||||||
|
v.forEach(row -> {
|
||||||
|
Object signature = row.remove("userSign");
|
||||||
|
signatures.add(signature instanceof byte[] ? (byte[]) signature : null);
|
||||||
|
});
|
||||||
ExcelExportService service = new ExcelExportService();
|
ExcelExportService service = new ExcelExportService();
|
||||||
ExportParams exportParams = new ExportParams();
|
ExportParams exportParams = new ExportParams();
|
||||||
exportParams.setSheetName(k);
|
exportParams.setSheetName(k);
|
||||||
exportParams.setType(ExcelType.HSSF);
|
exportParams.setType(ExcelType.XSSF);
|
||||||
|
int firstSheet = workbook.getNumberOfSheets();
|
||||||
service.createSheetForMap(workbook, exportParams, entities, v);
|
service.createSheetForMap(workbook, exportParams, entities, v);
|
||||||
|
// 无标题、单层列头的数据从第二行开始;按新增 Sheet 顺序兼容 EasyPOI 自动拆表。
|
||||||
|
int signatureIndex = 0;
|
||||||
|
for (int sheetIndex = firstSheet; sheetIndex < workbook.getNumberOfSheets(); sheetIndex++) {
|
||||||
|
Sheet sheet = workbook.getSheetAt(sheetIndex);
|
||||||
|
Drawing<?> drawing = sheet.createDrawingPatriarch();
|
||||||
|
for (int rowIndex = 1; rowIndex <= sheet.getLastRowNum() && signatureIndex < signatures.size(); rowIndex++) {
|
||||||
|
byte[] signature = signatures.get(signatureIndex++);
|
||||||
|
if (signature != null && signature.length > 0) {
|
||||||
|
insertReceiveSignature(workbook, sheet, drawing, rowIndex, entities.size() - 1, signature);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
CommonDownloadUtil.download("领取表.xls", workbook, response);
|
CommonDownloadUtil.download("领取表.xlsx", workbook, response);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 将签字字节数组写入领取表指定单元格。行列索引从 0 开始,图片统一转为 PNG;
|
||||||
|
* 无法解码的图片仅记录日志并保留空白签字格,不中断其他人员的导出。
|
||||||
|
*/
|
||||||
|
private void insertReceiveSignature(Workbook workbook, Sheet sheet, Drawing<?> drawing,
|
||||||
|
int rowIndex, int columnIndex, byte[] signature) {
|
||||||
|
try (ByteArrayInputStream input = new ByteArrayInputStream(signature);
|
||||||
|
ByteArrayOutputStream output = new ByteArrayOutputStream()) {
|
||||||
|
BufferedImage image = ImageIO.read(input);
|
||||||
|
if (image == null) {
|
||||||
|
log.warn("领取表签字图片无法识别,Sheet={},行={}", sheet.getSheetName(), rowIndex + 1);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
ImageIO.write(image, "png", output);
|
||||||
|
Row row = sheet.getRow(rowIndex);
|
||||||
|
row.setHeightInPoints(Math.max(row.getHeightInPoints(), 50));
|
||||||
|
ClientAnchor anchor = workbook.getCreationHelper().createClientAnchor();
|
||||||
|
anchor.setCol1(columnIndex);
|
||||||
|
anchor.setCol2(columnIndex + 1);
|
||||||
|
anchor.setRow1(rowIndex);
|
||||||
|
anchor.setRow2(rowIndex + 1);
|
||||||
|
anchor.setAnchorType(ClientAnchor.AnchorType.MOVE_AND_RESIZE);
|
||||||
|
drawing.createPicture(anchor, workbook.addPicture(output.toByteArray(), Workbook.PICTURE_TYPE_PNG));
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("领取表签字图片写入失败,Sheet={},行={}", sheet.getSheetName(), rowIndex + 1, e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,227 @@
|
|||||||
|
-- 全量初始化:完整定义特殊慰问申请主表、被申请人明细表和慰问类型表。
|
||||||
|
-- 表已存在时不执行本文件中的建表语句;本文件不复制数据、不配置角色授权和工作流。
|
||||||
|
CREATE TABLE `special_condolence` (
|
||||||
|
`id` varchar(32) NOT NULL COMMENT 'ID',
|
||||||
|
`subject` varchar(255) DEFAULT NULL COMMENT '事项',
|
||||||
|
`applyUserId` varchar(32) DEFAULT NULL COMMENT '申请人ID',
|
||||||
|
`applyUserName` varchar(100) DEFAULT NULL COMMENT '申请人姓名',
|
||||||
|
`applyLoginName` varchar(120) DEFAULT NULL COMMENT '申请人工号',
|
||||||
|
`applyUnionId` varchar(32) DEFAULT NULL COMMENT '申请人分工会ID',
|
||||||
|
`applyUnionName` varchar(100) DEFAULT NULL COMMENT '申请人分工会',
|
||||||
|
`applyUnitId` varchar(32) DEFAULT NULL COMMENT '申请人单位ID',
|
||||||
|
`applyUnitName` varchar(100) DEFAULT NULL COMMENT '申请人单位',
|
||||||
|
`helpUserId` varchar(32) DEFAULT NULL COMMENT '补助人ID',
|
||||||
|
`helpUserName` varchar(100) DEFAULT NULL COMMENT '补助人姓名',
|
||||||
|
`helpLoginName` varchar(120) DEFAULT NULL COMMENT '补助人工号',
|
||||||
|
`helpUnionId` varchar(32) DEFAULT NULL COMMENT '补助人分工会ID',
|
||||||
|
`helpUnionName` varchar(100) DEFAULT NULL COMMENT '补助人分工会',
|
||||||
|
`helpUnitId` varchar(32) DEFAULT NULL COMMENT '补助人单位ID',
|
||||||
|
`helpUnitName` varchar(100) DEFAULT NULL COMMENT '补助人单位',
|
||||||
|
`origin` varchar(20) DEFAULT NULL COMMENT '类型',
|
||||||
|
`payUserId` varchar(32) DEFAULT NULL COMMENT '收款人',
|
||||||
|
`payUserName` varchar(30) DEFAULT NULL COMMENT '收款人姓名',
|
||||||
|
`payLoginName` varchar(20) DEFAULT NULL COMMENT '收款人工号',
|
||||||
|
`type` varchar(32) DEFAULT NULL COMMENT '慰问类型',
|
||||||
|
`typeCode` varchar(32) DEFAULT NULL COMMENT '慰问编码',
|
||||||
|
`way` varchar(20) DEFAULT NULL COMMENT '慰问方式',
|
||||||
|
`perMoney` decimal(10,2) DEFAULT NULL COMMENT '统一每人慰问金额',
|
||||||
|
`money` float(10,2) DEFAULT NULL COMMENT '慰问金额',
|
||||||
|
`occurTime` varchar(30) DEFAULT NULL COMMENT '发生时间',
|
||||||
|
`child` varchar(10) DEFAULT NULL COMMENT '生育几孩(孩次)',
|
||||||
|
`hospital` varchar(50) DEFAULT NULL COMMENT '所在医院',
|
||||||
|
`hospitalHouseNum` varchar(20) DEFAULT NULL COMMENT '病房床号',
|
||||||
|
`hospitalHouseBedNum` varchar(20) DEFAULT NULL COMMENT '病房床号',
|
||||||
|
`hospitalBy` varchar(100) DEFAULT NULL COMMENT '住院病由',
|
||||||
|
`remark` varchar(500) DEFAULT NULL COMMENT '备注',
|
||||||
|
`files` json DEFAULT NULL COMMENT '附件',
|
||||||
|
`signature` varchar(255) DEFAULT NULL COMMENT '签字',
|
||||||
|
`createTime` varchar(30) DEFAULT NULL COMMENT '申请时间',
|
||||||
|
`bankUserName` varchar(100) DEFAULT NULL COMMENT '户名',
|
||||||
|
`bankCardNumber` varchar(100) DEFAULT NULL COMMENT '银行账号',
|
||||||
|
`bankOfDeposit` varchar(100) DEFAULT NULL COMMENT '开户行',
|
||||||
|
`certifierUserId` varchar(32) DEFAULT NULL COMMENT '证明人ID',
|
||||||
|
`certifierUserName` varchar(100) DEFAULT NULL COMMENT '证明人姓名',
|
||||||
|
`certifierLoginName` varchar(120) DEFAULT NULL COMMENT '证明人工号',
|
||||||
|
`certifierUnionId` varchar(32) DEFAULT NULL COMMENT '证明人分工会ID',
|
||||||
|
`certifierUnionName` varchar(100) DEFAULT NULL COMMENT '证明人分工会',
|
||||||
|
`certifierUnitId` varchar(32) DEFAULT NULL COMMENT '证明人单位ID',
|
||||||
|
`certifierUnitName` varchar(100) DEFAULT NULL COMMENT '证明人单位',
|
||||||
|
`handlerUserId` varchar(32) DEFAULT NULL COMMENT '经办人ID',
|
||||||
|
`handlerUserName` varchar(100) DEFAULT NULL COMMENT '经办人姓名',
|
||||||
|
`handlerLoginName` varchar(120) DEFAULT NULL COMMENT '经办人工号',
|
||||||
|
`handlerUnionId` varchar(32) DEFAULT NULL COMMENT '经办人分工会ID',
|
||||||
|
`handlerUnionName` varchar(100) DEFAULT NULL COMMENT '经办人分工会',
|
||||||
|
`handlerUnitId` varchar(32) DEFAULT NULL COMMENT '经办人单位ID',
|
||||||
|
`handlerUnitName` varchar(100) DEFAULT NULL COMMENT '经办人单位',
|
||||||
|
`hospitalizationTime` varchar(30) DEFAULT NULL COMMENT '入院时间',
|
||||||
|
`leaveHospitalTime` varchar(30) DEFAULT NULL COMMENT '出院时间',
|
||||||
|
`thisYearHospitalizationNum` int DEFAULT NULL COMMENT '当年第几次住院',
|
||||||
|
`createdBy` varchar(32) DEFAULT NULL COMMENT '创建人',
|
||||||
|
`createdAt` bigint DEFAULT NULL COMMENT '创建时间(毫秒时间戳)',
|
||||||
|
`updatedBy` varchar(32) DEFAULT NULL COMMENT '修改人',
|
||||||
|
`updatedAt` bigint DEFAULT NULL COMMENT '修改时间(毫秒时间戳)',
|
||||||
|
`delFlag` tinyint(1) DEFAULT 0 COMMENT '删除标记',
|
||||||
|
PRIMARY KEY (`id`)
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='特殊慰问申请';
|
||||||
|
|
||||||
|
CREATE TABLE `special_condolence_type` (
|
||||||
|
`id` varchar(32) NOT NULL COMMENT 'ID',
|
||||||
|
`code` varchar(30) DEFAULT NULL COMMENT '编码',
|
||||||
|
`name` varchar(50) DEFAULT NULL COMMENT '名称',
|
||||||
|
`money` float(10,2) DEFAULT NULL COMMENT '费用',
|
||||||
|
`way` varchar(20) DEFAULT NULL COMMENT '慰问方式',
|
||||||
|
`enable` tinyint(1) DEFAULT 1 COMMENT '是否启用',
|
||||||
|
`isUploadFile` tinyint(1) DEFAULT NULL COMMENT '是否上传附件',
|
||||||
|
`uploadFileDesc` varchar(50) DEFAULT NULL COMMENT '上传附件说明',
|
||||||
|
`location` int DEFAULT NULL COMMENT '排序字段',
|
||||||
|
`sortNum` int NOT NULL DEFAULT 0 COMMENT '排序',
|
||||||
|
`uploadMeetingRecord` tinyint(1) DEFAULT 0 COMMENT '上传会议纪要',
|
||||||
|
`createdBy` varchar(32) DEFAULT NULL COMMENT '创建人',
|
||||||
|
`createdAt` bigint DEFAULT NULL COMMENT '创建时间(毫秒时间戳)',
|
||||||
|
`updatedBy` varchar(32) DEFAULT NULL COMMENT '修改人',
|
||||||
|
`updatedAt` bigint DEFAULT NULL COMMENT '修改时间(毫秒时间戳)',
|
||||||
|
`delFlag` tinyint(1) DEFAULT 0 COMMENT '删除标记',
|
||||||
|
PRIMARY KEY (`id`)
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='特殊慰问类型';
|
||||||
|
|
||||||
|
-- 一份申请对应一个流程实例;多名被申请人通过 applyId 关联同一份申请。
|
||||||
|
CREATE TABLE `special_condolence_recipient` (
|
||||||
|
`id` varchar(32) NOT NULL COMMENT '明细ID',
|
||||||
|
`applyId` varchar(32) NOT NULL COMMENT '申请主表ID',
|
||||||
|
`helpUserId` varchar(32) NOT NULL COMMENT '慰问对象用户ID',
|
||||||
|
`helpLoginName` varchar(120) DEFAULT NULL COMMENT '慰问对象工号',
|
||||||
|
`personType` varchar(50) DEFAULT NULL COMMENT '人员类型',
|
||||||
|
`helpUserName` varchar(100) NOT NULL COMMENT '慰问对象',
|
||||||
|
`type` varchar(32) NOT NULL COMMENT '慰问类型ID',
|
||||||
|
`typeName` varchar(50) DEFAULT NULL COMMENT '慰问类型名称',
|
||||||
|
`typeCode` varchar(32) DEFAULT NULL COMMENT '慰问类型编码',
|
||||||
|
`way` varchar(20) DEFAULT NULL COMMENT '慰问方式',
|
||||||
|
`idCard` varchar(18) NOT NULL COMMENT '身份证号码',
|
||||||
|
`bankOfDeposit` varchar(100) NOT NULL COMMENT '开户行',
|
||||||
|
`bankUserName` varchar(100) NOT NULL COMMENT '户名',
|
||||||
|
`bankCardNumber` varchar(30) NOT NULL COMMENT '收款账户',
|
||||||
|
`money` decimal(10,2) NOT NULL COMMENT '慰问金额',
|
||||||
|
`occurTime` varchar(30) NOT NULL COMMENT '慰问时间',
|
||||||
|
`sortNum` int NOT NULL DEFAULT 0 COMMENT '行序号',
|
||||||
|
`createdBy` varchar(32) DEFAULT NULL COMMENT '创建人',
|
||||||
|
`createdAt` bigint DEFAULT NULL COMMENT '创建时间(毫秒时间戳)',
|
||||||
|
`updatedBy` varchar(32) DEFAULT NULL COMMENT '修改人',
|
||||||
|
`updatedAt` bigint DEFAULT NULL COMMENT '修改时间(毫秒时间戳)',
|
||||||
|
`delFlag` tinyint(1) DEFAULT 0 COMMENT '删除标记',
|
||||||
|
PRIMARY KEY (`id`),
|
||||||
|
KEY `idx_special_condolence_recipient_apply` (`applyId`)
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='特殊慰问被申请人明细';
|
||||||
|
|
||||||
|
-- 主表保留原有摘要字段兼容现有列表,money 为整份申请的金额合计。
|
||||||
|
-- 被申请人的完整信息保存在 special_condolence_recipient 中,不在主表使用 JSON 存储。
|
||||||
|
|
||||||
|
-- 新增 PC、H5 菜单,角色授权由管理员另行配置。
|
||||||
|
START TRANSACTION;
|
||||||
|
CREATE TEMPORARY TABLE special_condolence_menu_map AS
|
||||||
|
SELECT id oldId, MD5(CONCAT('special_condolence:', id)) newId
|
||||||
|
FROM sys_menu
|
||||||
|
WHERE id IN ('3b49290f7db44130b9f6394a8212321f', '024811fd168e44948e6ab84911fc26bb')
|
||||||
|
OR (href LIKE '/platform/condolence/%' AND href NOT LIKE '%/branchUnionApproval%');
|
||||||
|
CREATE TEMPORARY TABLE special_condolence_parent_map (
|
||||||
|
oldId varchar(32) NOT NULL COMMENT '原父菜单ID',
|
||||||
|
newId varchar(32) NOT NULL COMMENT '特殊慰问父菜单ID',
|
||||||
|
PRIMARY KEY (oldId)
|
||||||
|
);
|
||||||
|
INSERT INTO special_condolence_parent_map (oldId, newId)
|
||||||
|
SELECT oldId, newId FROM special_condolence_menu_map;
|
||||||
|
|
||||||
|
INSERT INTO sys_menu
|
||||||
|
(id, parentId, path, name, aliasName, type, href, target, icon, showit, disabled,
|
||||||
|
permission, note, location, hasChildren, createdBy, createdAt, updatedBy, updatedAt,
|
||||||
|
delFlag, processKey, platform, moduleId, isQuickEntry, picIcon, initialPinyinName,
|
||||||
|
isRecommendApp, isRecommendService)
|
||||||
|
SELECT map.newId, COALESCE(parent.newId, m.parentId),
|
||||||
|
CONCAT('T', SUBSTRING(map.newId, 1, 7)), REPLACE(m.name, '职工慰问', '特殊慰问'),
|
||||||
|
m.aliasName, m.type, REPLACE(m.href, '/condolence/', '/special_condolence/'), m.target,
|
||||||
|
m.icon, m.showit, m.disabled,
|
||||||
|
CASE m.id WHEN '3b49290f7db44130b9f6394a8212321f' THEN 'special_condolence'
|
||||||
|
WHEN '024811fd168e44948e6ab84911fc26bb' THEN 'h5.special_condolence'
|
||||||
|
ELSE REPLACE(m.permission, 'condolence', 'special_condolence') END,
|
||||||
|
REPLACE(m.note, '职工慰问', '特殊慰问'), m.location, m.hasChildren,
|
||||||
|
m.createdBy, UNIX_TIMESTAMP()*1000, m.updatedBy, UNIX_TIMESTAMP()*1000, m.delFlag,
|
||||||
|
REPLACE(m.processKey, 'ZGWW', 'TSWW'), m.platform, m.moduleId, m.isQuickEntry,
|
||||||
|
m.picIcon, IF(m.name = '职工慰问', 't', m.initialPinyinName), m.isRecommendApp, m.isRecommendService
|
||||||
|
FROM sys_menu m JOIN special_condolence_menu_map map ON map.oldId = m.id
|
||||||
|
LEFT JOIN special_condolence_parent_map parent ON parent.oldId = m.parentId
|
||||||
|
WHERE NOT EXISTS (SELECT 1 FROM sys_menu existing WHERE existing.id = map.newId);
|
||||||
|
|
||||||
|
-- 父子菜单路径保持树形前缀关系。
|
||||||
|
UPDATE sys_menu child JOIN sys_menu parent ON parent.id = child.parentId
|
||||||
|
JOIN special_condolence_menu_map map ON map.newId = child.id
|
||||||
|
SET child.path = CONCAT(parent.path, RIGHT(child.id, 4));
|
||||||
|
|
||||||
|
DROP TEMPORARY TABLE special_condolence_menu_map;
|
||||||
|
DROP TEMPORARY TABLE special_condolence_parent_map;
|
||||||
|
|
||||||
|
-- 权限部分,不要删除
|
||||||
|
-- SYSADMIN
|
||||||
|
-- 特殊慰问 web
|
||||||
|
INSERT INTO sys_role_menu (roleId, menuId) VALUES ('7f4a820d5a394bb8a0a92d6699afe7c8', '4c46696d75ff0eddf5cb57fac3e5d06d');
|
||||||
|
INSERT INTO sys_role_menu (roleId, menuId)
|
||||||
|
VALUES ('7f4a820d5a394bb8a0a92d6699afe7c8', '3e97a91e7aa9566cdae94850038a6212'),
|
||||||
|
('7f4a820d5a394bb8a0a92d6699afe7c8', '6c5be59ffb8d7c524ec72f2a02d6c6d2'),
|
||||||
|
('7f4a820d5a394bb8a0a92d6699afe7c8', '7f66eb63b6ebd81c5eee9c5c2de2ed98'),
|
||||||
|
('7f4a820d5a394bb8a0a92d6699afe7c8', '8d5ebaa091eee01abb33e89e3dcc92f8'),
|
||||||
|
('7f4a820d5a394bb8a0a92d6699afe7c8', '9c37242f50c5fb4a9c1b2b9b9dd0e2fd'),
|
||||||
|
('7f4a820d5a394bb8a0a92d6699afe7c8', '9f4f850904fe751db1cd13977374f99b'),
|
||||||
|
('7f4a820d5a394bb8a0a92d6699afe7c8', 'b24a5bef9ccbf7241c5bb85e80352f8f');
|
||||||
|
|
||||||
|
-- 特殊慰问 h5
|
||||||
|
INSERT INTO sys_role_menu (roleId, menuId) VALUES ('7f4a820d5a394bb8a0a92d6699afe7c8', '2145812145ee6548552504b4f5a55ff7');
|
||||||
|
INSERT INTO sys_role_menu (roleId, menuId)
|
||||||
|
VALUES ('7f4a820d5a394bb8a0a92d6699afe7c8', '42b4b5f54593cf023961ad1c9ce36f53'),
|
||||||
|
('7f4a820d5a394bb8a0a92d6699afe7c8', '4f3212a13a54fbb2a082ee77651c9a73'),
|
||||||
|
('7f4a820d5a394bb8a0a92d6699afe7c8', '739f64c71fe776dc3520ebb2977c2d68'),
|
||||||
|
('7f4a820d5a394bb8a0a92d6699afe7c8', 'b6c725beaf3bfe9f2b29f46855c45a24'),
|
||||||
|
('7f4a820d5a394bb8a0a92d6699afe7c8', 'eb3d1b27d51b84df1cebf24e1278e26c');
|
||||||
|
|
||||||
|
|
||||||
|
-- 校工会办公室主任
|
||||||
|
-- 特殊慰问 web
|
||||||
|
INSERT INTO sys_role_menu (roleId, menuId)
|
||||||
|
VALUES
|
||||||
|
('494ac71eb8b44d0e99e19b7fde6bd469', '4c46696d75ff0eddf5cb57fac3e5d06d'),
|
||||||
|
('494ac71eb8b44d0e99e19b7fde6bd469', '8d5ebaa091eee01abb33e89e3dcc92f8'),
|
||||||
|
('494ac71eb8b44d0e99e19b7fde6bd469', '7f66eb63b6ebd81c5eee9c5c2de2ed98');
|
||||||
|
|
||||||
|
-- 特殊慰问 h5
|
||||||
|
INSERT INTO sys_role_menu (roleId, menuId)
|
||||||
|
VALUES
|
||||||
|
('494ac71eb8b44d0e99e19b7fde6bd469', '2145812145ee6548552504b4f5a55ff7'),
|
||||||
|
('494ac71eb8b44d0e99e19b7fde6bd469', '42b4b5f54593cf023961ad1c9ce36f53');
|
||||||
|
|
||||||
|
-- 校工会主席
|
||||||
|
-- 特殊慰问 web
|
||||||
|
INSERT INTO sys_role_menu (roleId, menuId)
|
||||||
|
VALUES
|
||||||
|
('6aece46b946e4fb9ac4cb15c0cd8c3e6', '4c46696d75ff0eddf5cb57fac3e5d06d'),
|
||||||
|
('6aece46b946e4fb9ac4cb15c0cd8c3e6', '8d5ebaa091eee01abb33e89e3dcc92f8'),
|
||||||
|
('6aece46b946e4fb9ac4cb15c0cd8c3e6', 'b24a5bef9ccbf7241c5bb85e80352f8f');
|
||||||
|
|
||||||
|
-- 特殊慰问 h5
|
||||||
|
INSERT INTO sys_role_menu (roleId, menuId)
|
||||||
|
VALUES
|
||||||
|
('6aece46b946e4fb9ac4cb15c0cd8c3e6', '2145812145ee6548552504b4f5a55ff7'),
|
||||||
|
('6aece46b946e4fb9ac4cb15c0cd8c3e6', 'b6c725beaf3bfe9f2b29f46855c45a24');
|
||||||
|
|
||||||
|
-- 校工会主席
|
||||||
|
-- 特殊慰问 web
|
||||||
|
INSERT INTO sys_role_menu (roleId, menuId)
|
||||||
|
VALUES
|
||||||
|
('b3854469e6f44901b22bb791cb538431', '4c46696d75ff0eddf5cb57fac3e5d06d'),
|
||||||
|
('b3854469e6f44901b22bb791cb538431', '8d5ebaa091eee01abb33e89e3dcc92f8'),
|
||||||
|
('b3854469e6f44901b22bb791cb538431', '9c37242f50c5fb4a9c1b2b9b9dd0e2fd');
|
||||||
|
|
||||||
|
-- 特殊慰问 h5
|
||||||
|
INSERT INTO sys_role_menu (roleId, menuId)
|
||||||
|
VALUES
|
||||||
|
('b3854469e6f44901b22bb791cb538431', '2145812145ee6548552504b4f5a55ff7'),
|
||||||
|
('b3854469e6f44901b22bb791cb538431', '739f64c71fe776dc3520ebb2977c2d68');
|
||||||
|
|
||||||
|
|
||||||
|
COMMIT;
|
||||||
@@ -0,0 +1,92 @@
|
|||||||
|
This Font Software is licensed under the SIL Open Font License,
|
||||||
|
Version 1.1.
|
||||||
|
|
||||||
|
This license is copied below, and is also available with a FAQ at:
|
||||||
|
http://scripts.sil.org/OFL
|
||||||
|
|
||||||
|
-----------------------------------------------------------
|
||||||
|
SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
|
||||||
|
-----------------------------------------------------------
|
||||||
|
|
||||||
|
PREAMBLE
|
||||||
|
The goals of the Open Font License (OFL) are to stimulate worldwide
|
||||||
|
development of collaborative font projects, to support the font
|
||||||
|
creation efforts of academic and linguistic communities, and to
|
||||||
|
provide a free and open framework in which fonts may be shared and
|
||||||
|
improved in partnership with others.
|
||||||
|
|
||||||
|
The OFL allows the licensed fonts to be used, studied, modified and
|
||||||
|
redistributed freely as long as they are not sold by themselves. The
|
||||||
|
fonts, including any derivative works, can be bundled, embedded,
|
||||||
|
redistributed and/or sold with any software provided that any reserved
|
||||||
|
names are not used by derivative works. The fonts and derivatives,
|
||||||
|
however, cannot be released under any other type of license. The
|
||||||
|
requirement for fonts to remain under this license does not apply to
|
||||||
|
any document created using the fonts or their derivatives.
|
||||||
|
|
||||||
|
DEFINITIONS
|
||||||
|
"Font Software" refers to the set of files released by the Copyright
|
||||||
|
Holder(s) under this license and clearly marked as such. This may
|
||||||
|
include source files, build scripts and documentation.
|
||||||
|
|
||||||
|
"Reserved Font Name" refers to any names specified as such after the
|
||||||
|
copyright statement(s).
|
||||||
|
|
||||||
|
"Original Version" refers to the collection of Font Software
|
||||||
|
components as distributed by the Copyright Holder(s).
|
||||||
|
|
||||||
|
"Modified Version" refers to any derivative made by adding to,
|
||||||
|
deleting, or substituting -- in part or in whole -- any of the
|
||||||
|
components of the Original Version, by changing formats or by porting
|
||||||
|
the Font Software to a new environment.
|
||||||
|
|
||||||
|
"Author" refers to any designer, engineer, programmer, technical
|
||||||
|
writer or other person who contributed to the Font Software.
|
||||||
|
|
||||||
|
PERMISSION & CONDITIONS
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining
|
||||||
|
a copy of the Font Software, to use, study, copy, merge, embed,
|
||||||
|
modify, redistribute, and sell modified and unmodified copies of the
|
||||||
|
Font Software, subject to the following conditions:
|
||||||
|
|
||||||
|
1) Neither the Font Software nor any of its individual components, in
|
||||||
|
Original or Modified Versions, may be sold by itself.
|
||||||
|
|
||||||
|
2) Original or Modified Versions of the Font Software may be bundled,
|
||||||
|
redistributed and/or sold with any software, provided that each copy
|
||||||
|
contains the above copyright notice and this license. These can be
|
||||||
|
included either as stand-alone text files, human-readable headers or
|
||||||
|
in the appropriate machine-readable metadata fields within text or
|
||||||
|
binary files as long as those fields can be easily viewed by the user.
|
||||||
|
|
||||||
|
3) No Modified Version of the Font Software may use the Reserved Font
|
||||||
|
Name(s) unless explicit written permission is granted by the
|
||||||
|
corresponding Copyright Holder. This restriction only applies to the
|
||||||
|
primary font name as presented to the users.
|
||||||
|
|
||||||
|
4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
|
||||||
|
Software shall not be used to promote, endorse or advertise any
|
||||||
|
Modified Version, except to acknowledge the contribution(s) of the
|
||||||
|
Copyright Holder(s) and the Author(s) or with their explicit written
|
||||||
|
permission.
|
||||||
|
|
||||||
|
5) The Font Software, modified or unmodified, in part or in whole,
|
||||||
|
must be distributed entirely under this license, and must not be
|
||||||
|
distributed under any other license. The requirement for fonts to
|
||||||
|
remain under this license does not apply to any document created using
|
||||||
|
the Font Software.
|
||||||
|
|
||||||
|
TERMINATION
|
||||||
|
This license becomes null and void if any of the above conditions are
|
||||||
|
not met.
|
||||||
|
|
||||||
|
DISCLAIMER
|
||||||
|
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
|
||||||
|
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
|
||||||
|
OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
|
||||||
|
COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||||
|
INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
|
||||||
|
DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
|
||||||
|
OTHER DEALINGS IN THE FONT SOFTWARE.
|
||||||
Binary file not shown.
@@ -124,7 +124,10 @@
|
|||||||
#v4-home-app .todo-center .el-tabs__nav { display: flex; width: 100%; border-color: #e9eff6; border-radius: 6px 6px 0 0; }
|
#v4-home-app .todo-center .el-tabs__nav { display: flex; width: 100%; border-color: #e9eff6; border-radius: 6px 6px 0 0; }
|
||||||
#v4-home-app .todo-center .el-tabs__item { flex: 1; min-width: 0; padding: 0 7px; font-size: 12px; height: 36px; line-height: 36px; text-align: center; }
|
#v4-home-app .todo-center .el-tabs__item { flex: 1; min-width: 0; padding: 0 7px; font-size: 12px; height: 36px; line-height: 36px; text-align: center; }
|
||||||
#v4-home-app .todo-center .el-tabs__item.is-active { border-bottom: 2px solid #1687f5; color: #1687f5; }
|
#v4-home-app .todo-center .el-tabs__item.is-active { border-bottom: 2px solid #1687f5; color: #1687f5; }
|
||||||
#v4-home-app .portal-task-list { display: flex; flex-direction: column; justify-content: space-evenly; flex: 1; min-height: 180px; }
|
/* 任务从标签栏下方依次排列,避免单条记录被剩余高度推到中间。 */
|
||||||
|
#v4-home-app .portal-task-list { display: flex; flex-direction: column; justify-content: flex-start; flex: 1; min-height: 180px; }
|
||||||
|
/* 空数据提示独立占满列表区域,保留居中展示。 */
|
||||||
|
#v4-home-app .portal-task-list > .portal-empty { flex: 1; }
|
||||||
#v4-home-app .portal-task-row { display: flex; gap: 10px; align-items: center; padding: 8px 6px; border-bottom: 1px solid #eef3f8; }
|
#v4-home-app .portal-task-row { display: flex; gap: 10px; align-items: center; padding: 8px 6px; border-bottom: 1px solid #eef3f8; }
|
||||||
#v4-home-app .portal-task-row:last-child { border-bottom: 0; }
|
#v4-home-app .portal-task-row:last-child { border-bottom: 0; }
|
||||||
#v4-home-app .portal-task-row:hover { background: #f7fbff; }
|
#v4-home-app .portal-task-row:hover { background: #f7fbff; }
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
@@ -380,7 +380,7 @@
|
|||||||
</el-form>
|
</el-form>
|
||||||
<span slot="footer" class="dialog-footer">
|
<span slot="footer" class="dialog-footer">
|
||||||
<el-button @click="setDialogVisible = false">取消</el-button>
|
<el-button @click="setDialogVisible = false">取消</el-button>
|
||||||
<el-button type="primary" @click="doSetActivityUser" v-loading="settingLoading">确定</el-button>
|
<el-button type="primary" :disabled="settingLoading" @click="doSetActivityUser">确定</el-button>
|
||||||
</span>
|
</span>
|
||||||
</el-dialog>
|
</el-dialog>
|
||||||
|
|
||||||
@@ -646,7 +646,7 @@ module.exports = {
|
|||||||
doSearch(showFullLoading = false) {
|
doSearch(showFullLoading = false) {
|
||||||
this.tableKey = new Date().getTime()
|
this.tableKey = new Date().getTime()
|
||||||
this.pageForm.pageNumber = 1
|
this.pageForm.pageNumber = 1
|
||||||
this.pageData(showFullLoading === true)
|
return this.pageData(showFullLoading === true)
|
||||||
},
|
},
|
||||||
async pageData(showFullLoading = false) {
|
async pageData(showFullLoading = false) {
|
||||||
this.tableLoading = true
|
this.tableLoading = true
|
||||||
@@ -679,43 +679,74 @@ module.exports = {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
async doSetActivityUser() {
|
doSetActivityUser() {
|
||||||
const valid = await this.$refs.setForm.validate()
|
// 方法级状态保护与整页遮罩共同阻止慢请求期间的重复确认。
|
||||||
if (!valid) {
|
if (this.settingLoading) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.formData.groupType !== 2 && this.tableData.length === 0) {
|
this.$refs.setForm.validate((valid) => {
|
||||||
this.$message.warning("请先指定筛选条件!")
|
if (!valid) {
|
||||||
return
|
return
|
||||||
}
|
|
||||||
|
|
||||||
const confirm = await this.$confirm("是否将符合搜索条件的用户设为活动人员?", "提示", {
|
|
||||||
confirmButtonText: "确定",
|
|
||||||
cancelButtonText: "取消",
|
|
||||||
type: "warning"
|
|
||||||
})
|
|
||||||
|
|
||||||
if (confirm === "confirm") {
|
|
||||||
this.settingLoading = true
|
|
||||||
const pageForm = this.normalizePageForm(this.pageForm)
|
|
||||||
Object.assign(pageForm, this.formData)
|
|
||||||
const resp = await $.post("/platform/activity/basic/scope/doSetActivityUser", {
|
|
||||||
data: JSON.stringify(pageForm)
|
|
||||||
})
|
|
||||||
if (resp.code === 0) {
|
|
||||||
this.setDialogVisible = false
|
|
||||||
await this.getActivityGroup()
|
|
||||||
this.doSearch()
|
|
||||||
this.$message.success(resp.msg)
|
|
||||||
this.formData = this.getDefaultFormData()
|
|
||||||
} else {
|
|
||||||
this.$message.error(resp.msg)
|
|
||||||
}
|
}
|
||||||
this.settingLoading = false
|
|
||||||
this.$emit("update:group_id", resp.data)
|
if (this.formData.groupType !== 2 && this.tableData.length === 0) {
|
||||||
this.$emit("group_change")
|
this.$message.warning("请先指定筛选条件!")
|
||||||
}
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
this.$confirm("是否将符合搜索条件的用户设为活动人员?", "提示", {
|
||||||
|
confirmButtonText: "确定",
|
||||||
|
cancelButtonText: "取消",
|
||||||
|
type: "warning"
|
||||||
|
}).then(() => {
|
||||||
|
if (this.settingLoading) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
this.settingLoading = true
|
||||||
|
const loading = this.$loading({
|
||||||
|
lock: true,
|
||||||
|
text: "正在设置活动人员,请稍候...",
|
||||||
|
spinner: "el-icon-loading",
|
||||||
|
background: "rgba(255, 255, 255, 0.65)"
|
||||||
|
})
|
||||||
|
const pageForm = this.normalizePageForm(this.pageForm)
|
||||||
|
Object.assign(pageForm, this.formData)
|
||||||
|
|
||||||
|
$.post("/platform/activity/basic/scope/doSetActivityUser", {
|
||||||
|
data: JSON.stringify(pageForm)
|
||||||
|
}).then((resp) => {
|
||||||
|
if (resp.code !== 0) {
|
||||||
|
// 将后端业务错误转入统一失败分支,直接展示接口返回的真实原因。
|
||||||
|
throw new Error(resp.msg || "设置活动人员失败")
|
||||||
|
}
|
||||||
|
|
||||||
|
this.setDialogVisible = false
|
||||||
|
// 设置成功后等待分组和人员列表刷新完成,再解除整页操作锁定。
|
||||||
|
return this.getActivityGroup()
|
||||||
|
.then(() => this.doSearch())
|
||||||
|
.then(() => {
|
||||||
|
this.$message.success(resp.msg)
|
||||||
|
this.formData = this.getDefaultFormData()
|
||||||
|
this.$emit("update:group_id", resp.data)
|
||||||
|
this.$emit("group_change")
|
||||||
|
})
|
||||||
|
}).then(null, (error) => {
|
||||||
|
// 兼容业务错误、权限异常和网络异常,避免请求失败后页面持续加载。
|
||||||
|
const response = error && error.responseJSON ? error.responseJSON : null
|
||||||
|
const errorMessage = response && response.msg
|
||||||
|
? response.msg
|
||||||
|
: error && error.message
|
||||||
|
? error.message
|
||||||
|
: "设置活动人员失败"
|
||||||
|
this.$message.error(errorMessage)
|
||||||
|
}).always(() => {
|
||||||
|
this.settingLoading = false
|
||||||
|
loading.close()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
},
|
},
|
||||||
async getActivityGroup() {
|
async getActivityGroup() {
|
||||||
const resp = await $.get("/platform/activity/basic/scope/getActivityUserScopeGroup")
|
const resp = await $.get("/platform/activity/basic/scope/getActivityUserScopeGroup")
|
||||||
|
|||||||
@@ -10,7 +10,7 @@
|
|||||||
:finished="tableFinished"
|
:finished="tableFinished"
|
||||||
finished-text="没有更多了"
|
finished-text="没有更多了"
|
||||||
@load="onLoad">
|
@load="onLoad">
|
||||||
<div class="table-list-container">
|
<div class="table-list-container" @click="showOverflowText">
|
||||||
<div v-for="(row, index) in tableData" :key="index" class="table-list-item"
|
<div v-for="(row, index) in tableData" :key="index" class="table-list-item"
|
||||||
:data-row-id="row && row.id ? row.id : ''">
|
:data-row-id="row && row.id ? row.id : ''">
|
||||||
<slot name="header" :index="index" :row="row">
|
<slot name="header" :index="index" :row="row">
|
||||||
@@ -36,6 +36,12 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</van-list>
|
</van-list>
|
||||||
|
<van-popover ref="overflowPopover" :value="overflowVisible" :style="overflowAnchorStyle"
|
||||||
|
:placement="overflowPlacement" get-container="body" @input="onOverflowInput"
|
||||||
|
@opened="positionOverflow">
|
||||||
|
<div class="table-list-overflow-content">{{ overflowText }}</div>
|
||||||
|
<template #reference><span></span></template>
|
||||||
|
</van-popover>
|
||||||
</van-pull-refresh>
|
</van-pull-refresh>
|
||||||
</template>
|
</template>
|
||||||
<script>
|
<script>
|
||||||
@@ -90,10 +96,138 @@ module.exports = {
|
|||||||
tableLoading: false,
|
tableLoading: false,
|
||||||
tableFinished: false,
|
tableFinished: false,
|
||||||
tableRefreshing: false,
|
tableRefreshing: false,
|
||||||
localPageForm: {...this.page_form}
|
localPageForm: {...this.page_form},
|
||||||
|
overflowVisible: false,
|
||||||
|
overflowText: "",
|
||||||
|
overflowTarget: null,
|
||||||
|
overflowPlacement: "top",
|
||||||
|
overflowAnchorStyle: {}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
// 只响应真正被截断的纯文字,保留卡片内按钮和业务插槽原有的点击行为。
|
||||||
|
showOverflowText(event) {
|
||||||
|
const target = event.target
|
||||||
|
if (!target || !target.closest) return
|
||||||
|
const card = target.closest(".table-list-item")
|
||||||
|
if (!card || target.closest(".item-actions, a, button, input, textarea, select, [role=button], [tabindex], [onclick]")) return
|
||||||
|
if (target.children.length || !target.textContent.trim() || this.hasOverflowClickHandler(target, card)) return
|
||||||
|
const style = window.getComputedStyle(target)
|
||||||
|
if (style.textOverflow !== "ellipsis" || (target.scrollWidth <= target.clientWidth && target.scrollHeight <= target.clientHeight)) return
|
||||||
|
|
||||||
|
const rect = target.getBoundingClientRect()
|
||||||
|
this.overflowTarget = target
|
||||||
|
this.overflowText = target.textContent.trim()
|
||||||
|
this.overflowPlacement = rect.top < 180 ? "bottom" : "top"
|
||||||
|
this.overflowAnchorStyle = {
|
||||||
|
position: "fixed",
|
||||||
|
display: "block",
|
||||||
|
pointerEvents: "none",
|
||||||
|
left: rect.left + "px",
|
||||||
|
top: rect.top + "px",
|
||||||
|
width: rect.width + "px",
|
||||||
|
height: rect.height + "px"
|
||||||
|
}
|
||||||
|
if (!this.overflowVisible) this.bindOverflowListeners()
|
||||||
|
this.overflowVisible = true
|
||||||
|
this.$nextTick(() => {
|
||||||
|
const instance = this.$refs.overflowPopover
|
||||||
|
if (instance) instance.updateLocation()
|
||||||
|
setTimeout(() => this.positionOverflow(), 50)
|
||||||
|
setTimeout(() => this.positionOverflow(), 350)
|
||||||
|
})
|
||||||
|
},
|
||||||
|
|
||||||
|
// 检查文字及其卡片内的祖先节点,避免干扰已有 Vue 点击事件。
|
||||||
|
hasOverflowClickHandler(target, card) {
|
||||||
|
const ancestors = []
|
||||||
|
let element = target
|
||||||
|
while (element && element !== card.parentElement) {
|
||||||
|
ancestors.push(element)
|
||||||
|
element = element.parentElement
|
||||||
|
}
|
||||||
|
const visit = (node) => {
|
||||||
|
if (!node) return false
|
||||||
|
const events = node.data ? [node.data.on, node.data.nativeOn] : []
|
||||||
|
if (ancestors.includes(node.elm) && events.some((handlers) => handlers &&
|
||||||
|
Object.keys(handlers).some((key) => /^[~!&]*(click|touchstart|pointerdown|mousedown)$/.test(key)))) return true
|
||||||
|
if (node.componentInstance && visit(node.componentInstance._vnode)) return true
|
||||||
|
return Array.isArray(node.children) && node.children.some((child) => visit(child))
|
||||||
|
}
|
||||||
|
return visit(this._vnode)
|
||||||
|
},
|
||||||
|
|
||||||
|
// Vant 的弹层挂在 body;校正窗口边缘的位置,避免完整文字被屏幕裁掉。
|
||||||
|
positionOverflow() {
|
||||||
|
const instance = this.$refs.overflowPopover
|
||||||
|
const popup = instance && instance.$refs.popover && instance.$refs.popover.$el
|
||||||
|
if (!this.overflowVisible || !this.overflowTarget || !popup) return
|
||||||
|
const rect = popup.getBoundingClientRect()
|
||||||
|
const anchor = this.overflowTarget.getBoundingClientRect()
|
||||||
|
if (!rect.width || !rect.height) return
|
||||||
|
const margin = 8
|
||||||
|
const left = Math.max(margin, Math.min(rect.left, window.innerWidth - rect.width - margin))
|
||||||
|
let top = rect.top
|
||||||
|
if (top < margin) top = anchor.bottom + 8
|
||||||
|
if (top + rect.height > window.innerHeight - margin) top = anchor.top - rect.height - 8
|
||||||
|
top = Math.max(margin, Math.min(top, window.innerHeight - rect.height - margin))
|
||||||
|
popup.style.left = (parseFloat(popup.style.left) || 0) + left - rect.left + "px"
|
||||||
|
popup.style.top = (parseFloat(popup.style.top) || 0) + top - rect.top + "px"
|
||||||
|
const arrow = popup.querySelector(".van-popover__arrow")
|
||||||
|
if (arrow) {
|
||||||
|
arrow.style.left = Math.max(12, Math.min(anchor.left + anchor.width / 2 - left, rect.width - 12)) + "px"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
onOverflowInput(visible) {
|
||||||
|
this.overflowVisible = visible
|
||||||
|
if (!visible) {
|
||||||
|
this.overflowTarget = null
|
||||||
|
this.unbindOverflowListeners()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
// 监听只在气泡打开时存在,PJAX 替换页面前也会关闭气泡并注销。
|
||||||
|
bindOverflowListeners() {
|
||||||
|
document.addEventListener("click", this.closeOverflowOnClick)
|
||||||
|
window.addEventListener("scroll", this.closeOverflowOnMove, true)
|
||||||
|
window.addEventListener("resize", this.closeOverflowOnMove)
|
||||||
|
window.addEventListener("transitionend", this.onOverflowAnimationEnd)
|
||||||
|
window.addEventListener("animationend", this.onOverflowAnimationEnd)
|
||||||
|
$(document).on("pjax:send", this.closeOverflowForNavigation)
|
||||||
|
},
|
||||||
|
|
||||||
|
unbindOverflowListeners() {
|
||||||
|
document.removeEventListener("click", this.closeOverflowOnClick)
|
||||||
|
window.removeEventListener("scroll", this.closeOverflowOnMove, true)
|
||||||
|
window.removeEventListener("resize", this.closeOverflowOnMove)
|
||||||
|
window.removeEventListener("transitionend", this.onOverflowAnimationEnd)
|
||||||
|
window.removeEventListener("animationend", this.onOverflowAnimationEnd)
|
||||||
|
$(document).off("pjax:send", this.closeOverflowForNavigation)
|
||||||
|
},
|
||||||
|
|
||||||
|
closeOverflowForNavigation() {
|
||||||
|
this.onOverflowInput(false)
|
||||||
|
},
|
||||||
|
|
||||||
|
// Vant 会在动画结束时重新计算定位,随后再次限制气泡的屏幕边界。
|
||||||
|
onOverflowAnimationEnd() {
|
||||||
|
if (this.overflowVisible) setTimeout(() => this.positionOverflow(), 0)
|
||||||
|
},
|
||||||
|
|
||||||
|
// 滚动或改变屏幕尺寸时关闭气泡,避免气泡脱离原文字位置。
|
||||||
|
closeOverflowOnMove(event) {
|
||||||
|
if (event && event.target && event.target.closest && event.target.closest(".table-list-overflow-content")) return
|
||||||
|
this.onOverflowInput(false)
|
||||||
|
},
|
||||||
|
|
||||||
|
closeOverflowOnClick(event) {
|
||||||
|
if (!this.overflowVisible) return
|
||||||
|
if (this.overflowTarget && this.overflowTarget.contains(event.target)) return
|
||||||
|
if (event.target.closest && event.target.closest(".table-list-overflow-content")) return
|
||||||
|
this.onOverflowInput(false)
|
||||||
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取当前列表快照。
|
* 获取当前列表快照。
|
||||||
* 返回值包含已加载记录、分页参数和加载完成状态,供业务页面在进入详情前暂存列表现场。
|
* 返回值包含已加载记录、分页参数和加载完成状态,供业务页面在进入详情前暂存列表现场。
|
||||||
@@ -186,10 +320,28 @@ module.exports = {
|
|||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
this.$emit("ready")
|
this.$emit("ready")
|
||||||
|
},
|
||||||
|
beforeDestroy() {
|
||||||
|
this.unbindOverflowListeners()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
/* Vant 将气泡挂到 body,控制宽高并允许长文本在气泡内滚动。 */
|
||||||
|
.table-list-overflow-content {
|
||||||
|
max-width: min(240px, calc(100vw - 48px));
|
||||||
|
max-height: 160px;
|
||||||
|
padding: 10px 12px;
|
||||||
|
overflow-y: auto;
|
||||||
|
color: #253247;
|
||||||
|
font-size: 13px;
|
||||||
|
line-height: 1.55;
|
||||||
|
white-space: pre-wrap;
|
||||||
|
overflow-wrap: anywhere;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
.table-list-container {
|
.table-list-container {
|
||||||
padding: 0;
|
padding: 0;
|
||||||
|
|||||||
@@ -0,0 +1,98 @@
|
|||||||
|
<template>
|
||||||
|
<div class="h5-user-select">
|
||||||
|
<van-field v-bind="$attrs" :value="displayName" readonly clickable is-link @click="open"></van-field>
|
||||||
|
<van-popup v-model="visible" position="bottom" round get-container="body" class="h5-user-select-popup">
|
||||||
|
<div class="h5-user-select-popup__header">
|
||||||
|
<van-button native-type="button" type="default" size="small" @click="visible = false">取消</van-button>
|
||||||
|
<strong>选择慰问对象</strong>
|
||||||
|
<van-button native-type="button" type="info" size="small" :disabled="!pendingUser" @click="confirm">确认</van-button>
|
||||||
|
</div>
|
||||||
|
<van-search v-model="keyword" placeholder="请输入姓名或工号查询" @input="scheduleSearch" @search="search" @clear="search"></van-search>
|
||||||
|
<div class="h5-user-select-popup__list">
|
||||||
|
<div v-if="loading" class="h5-user-select-popup__status"><van-loading size="24px">加载中</van-loading></div>
|
||||||
|
<div v-else-if="error" class="h5-user-select-popup__status"><span class="h5-user-select-popup__error">{{ error }}</span><van-button native-type="button" size="small" @click="search">重新加载</van-button></div>
|
||||||
|
<van-empty v-else-if="!options.length" description="未找到本工会人员"></van-empty>
|
||||||
|
<template v-else>
|
||||||
|
<van-cell v-for="person in options" :key="person.id" clickable
|
||||||
|
:class="{ 'h5-user-select-popup__selected': pendingUser && pendingUser.id === person.id }"
|
||||||
|
:title="person.userName + (person.loginName ? '(' + person.loginName + ')' : '')"
|
||||||
|
:label="[person.unitName, person.personType].filter(Boolean).join(' · ')"
|
||||||
|
@click="pendingUser = person">
|
||||||
|
<van-icon v-if="pendingUser && pendingUser.id === person.id" name="success" color="#1989fa"></van-icon>
|
||||||
|
</van-cell>
|
||||||
|
</template>
|
||||||
|
</div>
|
||||||
|
</van-popup>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
module.exports = {
|
||||||
|
inheritAttrs: false,
|
||||||
|
model: { prop: 'value', event: 'change' },
|
||||||
|
props: {
|
||||||
|
value: { type: String, default: '' },
|
||||||
|
displayName: { type: String, default: '' },
|
||||||
|
api: { type: String, required: true }
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return { visible: false, keyword: '', options: [], pendingUser: null, loading: false, error: '', searchTimer: null, requestId: 0 }
|
||||||
|
},
|
||||||
|
beforeDestroy() {
|
||||||
|
clearTimeout(this.searchTimer)
|
||||||
|
this.requestId++
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
open() {
|
||||||
|
this.keyword = ''
|
||||||
|
this.pendingUser = null
|
||||||
|
this.visible = true
|
||||||
|
this.search()
|
||||||
|
},
|
||||||
|
scheduleSearch() {
|
||||||
|
clearTimeout(this.searchTimer)
|
||||||
|
this.requestId++
|
||||||
|
this.pendingUser = null
|
||||||
|
this.loading = true
|
||||||
|
this.searchTimer = setTimeout(() => this.search(), 250)
|
||||||
|
},
|
||||||
|
async search() {
|
||||||
|
clearTimeout(this.searchTimer)
|
||||||
|
const requestId = ++this.requestId
|
||||||
|
this.loading = true
|
||||||
|
this.error = ''
|
||||||
|
this.pendingUser = null
|
||||||
|
try {
|
||||||
|
const result = await this.$axios.post(this.api, { keyword: this.keyword })
|
||||||
|
if (requestId !== this.requestId) return
|
||||||
|
if (result.code !== 0) throw new Error(result.msg || '人员加载失败')
|
||||||
|
this.options = result.data || []
|
||||||
|
} catch (error) {
|
||||||
|
if (requestId !== this.requestId) return
|
||||||
|
this.options = []
|
||||||
|
this.error = error.message || '人员加载失败'
|
||||||
|
} finally {
|
||||||
|
if (requestId === this.requestId) this.loading = false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
confirm() {
|
||||||
|
if (!this.pendingUser) return
|
||||||
|
const person = this.pendingUser
|
||||||
|
this.$emit('change', person.id)
|
||||||
|
this.$emit('selected', person, person.id)
|
||||||
|
this.visible = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.h5-user-select-popup { display: flex; flex-direction: column; height: 72vh; max-height: 640px; padding-bottom: env(safe-area-inset-bottom); box-sizing: border-box; }
|
||||||
|
.h5-user-select-popup__header { display: flex; align-items: center; justify-content: space-between; flex-shrink: 0; padding: 14px 16px; border-bottom: 1px solid #ebedf0; }
|
||||||
|
.h5-user-select-popup__header strong { font-size: 16px; color: #323233; }
|
||||||
|
.h5-user-select-popup__header .van-button { min-width: 56px; }
|
||||||
|
.h5-user-select-popup__list { flex: 1; min-height: 0; overflow-y: auto; -webkit-overflow-scrolling: touch; }
|
||||||
|
.h5-user-select-popup__selected { background: #edf6ff; }
|
||||||
|
.h5-user-select-popup__status { display: flex; align-items: center; justify-content: center; flex-direction: column; gap: 12px; padding: 40px 16px; }
|
||||||
|
.h5-user-select-popup__error { color: #ee0a24; }
|
||||||
|
</style>
|
||||||
@@ -106,7 +106,9 @@ module.exports = {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
onChange(val) {
|
onChange(val) {
|
||||||
|
const selected = this.options.find(item => String(item[this.option_value]) === String(val)) || null
|
||||||
this.$emit("change", val)
|
this.$emit("change", val)
|
||||||
|
this.$emit("selected", selected, val)
|
||||||
},
|
},
|
||||||
|
|
||||||
clearOptions() {
|
clearOptions() {
|
||||||
@@ -114,7 +116,7 @@ module.exports = {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
created() {
|
created() {
|
||||||
this.clearOptions()
|
this.options = this.option_list || []
|
||||||
console.log(this.placeholder)
|
console.log(this.placeholder)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Binary file not shown.
@@ -706,7 +706,7 @@
|
|||||||
Vue.component("year-van-dropdown-item", httpVueLoader("/components/plugins/vantMore/yearVanDropDownItem.vue?v=" + h5ComponentVersion))
|
Vue.component("year-van-dropdown-item", httpVueLoader("/components/plugins/vantMore/yearVanDropDownItem.vue?v=" + h5ComponentVersion))
|
||||||
Vue.component("van-text-dialog", httpVueLoader("/components/plugins/vantMore/vantTextDialog.vue?v=" + h5ComponentVersion))
|
Vue.component("van-text-dialog", httpVueLoader("/components/plugins/vantMore/vantTextDialog.vue?v=" + h5ComponentVersion))
|
||||||
Vue.component("enum-tag", httpVueLoader("/components/plugins/sysEnum/EnumTag.vue?v=" + h5ComponentVersion))
|
Vue.component("enum-tag", httpVueLoader("/components/plugins/sysEnum/EnumTag.vue?v=" + h5ComponentVersion))
|
||||||
Vue.component("table-list", httpVueLoader("/components/plugins/h5/TableList.vue?v=" + h5ComponentVersion))
|
Vue.component("table-list", httpVueLoader("/components/plugins/h5/TableList.vue?v=" + h5ComponentVersion + "_overflow1"))
|
||||||
Vue.component("table-column", httpVueLoader("/components/plugins/h5/TableColumn.vue?v=" + h5ComponentVersion))
|
Vue.component("table-column", httpVueLoader("/components/plugins/h5/TableColumn.vue?v=" + h5ComponentVersion))
|
||||||
Vue.component("file-preview", httpVueLoader("/components/plugins/sysFilePreview/H5Index.vue?v=" + h5ComponentVersion))
|
Vue.component("file-preview", httpVueLoader("/components/plugins/sysFilePreview/H5Index.vue?v=" + h5ComponentVersion))
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -75,7 +75,7 @@
|
|||||||
|
|
||||||
<!-- 引入 form-create 和 designer -->
|
<!-- 引入 form-create 和 designer -->
|
||||||
<script src="${base!}/assets/platform/plugins/form-create/form-create.min.js"></script>
|
<script src="${base!}/assets/platform/plugins/form-create/form-create.min.js"></script>
|
||||||
<script src="${base!}/assets/platform/plugins/form-create/index.umd.js"></script>
|
<script src="${base!}/assets/platform/plugins/form-create/index.umd.js?v=20261030"></script>
|
||||||
|
|
||||||
<!-- swiper -->
|
<!-- swiper -->
|
||||||
<script src="${base!}/assets/platform/plugins/swiper/swiper-bundle.js"></script>
|
<script src="${base!}/assets/platform/plugins/swiper/swiper-bundle.js"></script>
|
||||||
|
|||||||
@@ -187,7 +187,7 @@ const act = {
|
|||||||
}
|
}
|
||||||
if (act.url === "/platform/activity/apply"
|
if (act.url === "/platform/activity/apply"
|
||||||
&& !this.$auth.hasRoleOr(["SYSADMIN", "SCHOOL_UNION_ADMIN", "BRANCH_UNION_CHAIRMAN", "BRANCH_UNION_WENTI_SPORTS"])) {
|
&& !this.$auth.hasRoleOr(["SYSADMIN", "SCHOOL_UNION_ADMIN", "BRANCH_UNION_CHAIRMAN", "BRANCH_UNION_WENTI_SPORTS"])) {
|
||||||
return this.$message.warning("PC端暂未开放报名,请前往移动端报名!")
|
return this.$message.warning("温馨提示:您没有参加该活动的权限!")
|
||||||
|
|
||||||
}
|
}
|
||||||
window.open(act.url)
|
window.open(act.url)
|
||||||
|
|||||||
@@ -116,9 +116,72 @@ layout("/layouts/v4/baseLayout.html"){
|
|||||||
object-fit: contain;
|
object-fit: contain;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 最新活动的作用域样式会在组件挂载后注入,首屏先固定布局和图片尺寸,避免刷新时放大闪烁。 */
|
||||||
|
#v4-home-app .act-card .activity-section-wrapper,
|
||||||
|
#v4-home-app .act-card .section-act,
|
||||||
|
#v4-home-app .act-card .activity-swiper {
|
||||||
|
width: 100%;
|
||||||
|
min-width: 0;
|
||||||
|
max-width: 100%;
|
||||||
|
box-sizing: border-box;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
#v4-home-app .act-card .activity-swiper-container {
|
||||||
|
position: relative;
|
||||||
|
width: 100%;
|
||||||
|
min-width: 0;
|
||||||
|
max-width: 100%;
|
||||||
|
box-sizing: border-box;
|
||||||
|
padding: 9px 54px 12px;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
#v4-home-app .act-card .activity-swiper .swiper-slide {
|
||||||
|
width: 100%;
|
||||||
|
height: auto;
|
||||||
|
min-width: 0;
|
||||||
|
flex-shrink: 0;
|
||||||
|
margin-right: 18px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#v4-home-app .act-card .activity-swiper .img-box {
|
||||||
|
width: 100%;
|
||||||
|
height: 128px;
|
||||||
|
border-radius: 8px;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
#v4-home-app .act-card .activity-swiper .img-box img {
|
||||||
|
display: block;
|
||||||
|
width: 100% !important;
|
||||||
|
height: 100% !important;
|
||||||
|
max-width: 100% !important;
|
||||||
|
max-height: 128px !important;
|
||||||
|
object-fit: fill !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (min-width: 768px) {
|
||||||
|
#v4-home-app .act-card .activity-swiper .swiper-slide {
|
||||||
|
width: calc((100% - 18px) / 2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (min-width: 1024px) {
|
||||||
|
#v4-home-app .act-card .activity-swiper .swiper-slide {
|
||||||
|
width: calc((100% - 54px) / 4);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (min-width: 1200px) {
|
||||||
|
#v4-home-app .act-card .activity-swiper .swiper-slide {
|
||||||
|
width: calc((100% - 72px) / 5);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<link rel="stylesheet" href="${base!}/assets/platform/css/home-portal.css?v=20261030-1" />
|
<link rel="stylesheet" href="${base!}/assets/platform/css/home-portal.css?v=20261102-1" />
|
||||||
|
|
||||||
<!-- 登录资料仅在 HTML 属性中输出并转义;放在 Vue 挂载区域外,避免名称被当作模板表达式解析。 -->
|
<!-- 登录资料仅在 HTML 属性中输出并转义;放在 Vue 挂载区域外,避免名称被当作模板表达式解析。 -->
|
||||||
<div id="v4-home-profile-data" hidden
|
<div id="v4-home-profile-data" hidden
|
||||||
|
|||||||
@@ -1050,7 +1050,14 @@ const ACTIVITY_CULTURE_APPLY_ACTIVITY = {
|
|||||||
if (code === 0) {
|
if (code === 0) {
|
||||||
if (data.userId) {
|
if (data.userId) {
|
||||||
const user = await this.queryUserByIds([data.userId])
|
const user = await this.queryUserByIds([data.userId])
|
||||||
await this.remoteMethod(user[0].loginname)
|
// 历史模板的负责人可能已删除;清空失效选择并继续回填,避免空数组中断整个表单。
|
||||||
|
if (Array.isArray(user) && user.length > 0 && user[0].loginname) {
|
||||||
|
await this.remoteMethod(user[0].loginname)
|
||||||
|
} else {
|
||||||
|
this.$set(data, "userId", null)
|
||||||
|
this.userList = []
|
||||||
|
this.$message.warning("原负责人已不存在,请重新选择负责人")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (data.goods) data.goods = JSON.parse(data.goods)
|
if (data.goods) data.goods = JSON.parse(data.goods)
|
||||||
if (data.billFiles && data.billFiles.length > 0) data.billFiles = JSON.parse(data.billFiles)
|
if (data.billFiles && data.billFiles.length > 0) data.billFiles = JSON.parse(data.billFiles)
|
||||||
|
|||||||
+1
-1
@@ -100,7 +100,7 @@ layout("/layouts/platform.html"){
|
|||||||
size="mini" type="danger">删除
|
size="mini" type="danger">删除
|
||||||
</el-button>
|
</el-button>
|
||||||
|
|
||||||
<el-button @click="doExportDeclare(row)" size="mini" type="primary">申请表导出</el-button>
|
<el-button v-if="row.instanceState === 20" @click="doExportDeclare(row)" size="mini" type="primary">申请表导出</el-button>
|
||||||
<el-button v-if="row.instanceState === 20" @click="doExportReimbursement(row)" size="mini"
|
<el-button v-if="row.instanceState === 20" @click="doExportReimbursement(row)" size="mini"
|
||||||
type="primary">报销凭证导出
|
type="primary">报销凭证导出
|
||||||
</el-button>
|
</el-button>
|
||||||
|
|||||||
@@ -221,8 +221,7 @@ layout("/layouts/platform.html"){
|
|||||||
placeholder="请输入姓名" filterable clearable
|
placeholder="请输入姓名" filterable clearable
|
||||||
style="width: 100%" size="small" v-if="awardsMode==1">
|
style="width: 100%" size="small" v-if="awardsMode==1">
|
||||||
<el-option
|
<el-option
|
||||||
v-for="item in userList"
|
v-for="item in getSelectableUserList(row)"
|
||||||
:disabled="item.disabled"
|
|
||||||
:key="item.id"
|
:key="item.id"
|
||||||
:label="item.username+'('+item.loginname+')'+item.sex"
|
:label="item.username+'('+item.loginname+')'+item.sex"
|
||||||
:value="item.id">
|
:value="item.id">
|
||||||
@@ -721,10 +720,15 @@ layout("/layouts/platform.html"){
|
|||||||
}
|
}
|
||||||
return score;
|
return score;
|
||||||
},
|
},
|
||||||
|
getSelectableUserList(row) {
|
||||||
|
// 其他行已经选择的人员不再显示,当前行人员保留用于姓名正常回显。
|
||||||
|
const selectedUserIds = this.userData
|
||||||
|
.map(item => item.userId)
|
||||||
|
.filter(userId => userId)
|
||||||
|
return this.userList.filter(item => item.id === row.userId || !selectedUserIds.includes(item.id))
|
||||||
|
},
|
||||||
userDetailsChange(val, row) {
|
userDetailsChange(val, row) {
|
||||||
const useridArr = this.userData.map(v => v.userId)
|
|
||||||
this.userList.forEach(v => {
|
this.userList.forEach(v => {
|
||||||
v.disabled = useridArr.includes(v.id)
|
|
||||||
if (row && row.userId === v.id) {
|
if (row && row.userId === v.id) {
|
||||||
const o = {
|
const o = {
|
||||||
unionId: v.unionId,
|
unionId: v.unionId,
|
||||||
|
|||||||
@@ -601,6 +601,8 @@
|
|||||||
eventForm: {
|
eventForm: {
|
||||||
isLeader: false
|
isLeader: false
|
||||||
},
|
},
|
||||||
|
// 独立记录当前编辑项目,避免下拉框切换后丢失切换前项目标识。
|
||||||
|
currentEventId: "",
|
||||||
eventsIds: [],
|
eventsIds: [],
|
||||||
rightChecked: [],
|
rightChecked: [],
|
||||||
checkedEventInfo: [],
|
checkedEventInfo: [],
|
||||||
@@ -778,8 +780,10 @@
|
|||||||
this.checkedEventInfo = this.checkedEvents.map((v) => {
|
this.checkedEventInfo = this.checkedEvents.map((v) => {
|
||||||
v.eventId = v.id
|
v.eventId = v.id
|
||||||
if (v.projectType === "1") {
|
if (v.projectType === "1") {
|
||||||
v.athletesMaxNum = 3
|
// “所有单项”保存默认值,具体单项以0表示尚未个性化设置。
|
||||||
v.restrictRegNumber = 2
|
const isAllItems = v.eventId === "allItems"
|
||||||
|
v.athletesMaxNum = isAllItems ? 3 : 0
|
||||||
|
v.restrictRegNumber = isAllItems ? 2 : 0
|
||||||
v.leanderNum = 0
|
v.leanderNum = 0
|
||||||
v.coachNum = 0
|
v.coachNum = 0
|
||||||
v.applyUserModel = 1
|
v.applyUserModel = 1
|
||||||
@@ -791,7 +795,23 @@
|
|||||||
return v
|
return v
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
cacheCurrentEventForm() {
|
||||||
|
if (!this.currentEventId || !this.eventForm) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
const current = clone(this.eventForm)
|
||||||
|
current.checkedEventId = this.currentEventId
|
||||||
|
current.eventId = this.currentEventId
|
||||||
|
|
||||||
|
const index = this.checkedEventInfo.findIndex((item) => item.eventId === this.currentEventId)
|
||||||
|
if (index >= 0) {
|
||||||
|
this.checkedEventInfo.splice(index, 1, current)
|
||||||
|
} else {
|
||||||
|
this.checkedEventInfo.push(current)
|
||||||
|
}
|
||||||
|
},
|
||||||
async eventChange(val) {
|
async eventChange(val) {
|
||||||
|
this.cacheCurrentEventForm()
|
||||||
const data = this.checkedEventInfo.find((v) => v.eventId === val)
|
const data = this.checkedEventInfo.find((v) => v.eventId === val)
|
||||||
const resp = await $.get("/platform/activity/sports/common/getEventData", { id: val })
|
const resp = await $.get("/platform/activity/sports/common/getEventData", { id: val })
|
||||||
await this.$nextTick()
|
await this.$nextTick()
|
||||||
@@ -804,10 +824,10 @@
|
|||||||
projectType: resp.data.projectType,
|
projectType: resp.data.projectType,
|
||||||
leanderNum: 0,
|
leanderNum: 0,
|
||||||
coachNum: 0,
|
coachNum: 0,
|
||||||
athletesMaxNum: resp.data.projectType === 1 ? 3 : null,
|
athletesMaxNum: resp.data.projectType === 1 ? 0 : null,
|
||||||
restrictTotalTeam: 1,
|
restrictTotalTeam: 1,
|
||||||
substituteNum: 0,
|
substituteNum: 0,
|
||||||
restrictRegNumber: resp.data.projectType === 1 ? 2 : null,
|
restrictRegNumber: resp.data.projectType === 1 ? 0 : null,
|
||||||
isLeader: false,
|
isLeader: false,
|
||||||
applyUserModel: 1
|
applyUserModel: 1
|
||||||
}
|
}
|
||||||
@@ -815,33 +835,27 @@
|
|||||||
this.projectType = resp.data.projectType
|
this.projectType = resp.data.projectType
|
||||||
}
|
}
|
||||||
this.$set(this.eventForm, "checkedEventId", val)
|
this.$set(this.eventForm, "checkedEventId", val)
|
||||||
|
this.currentEventId = val
|
||||||
},
|
},
|
||||||
async saveEvent() {
|
saveEvent() {
|
||||||
const data = clone(this.eventForm)
|
const data = clone(this.eventForm)
|
||||||
if (data.checkedEventId === "allItems") {
|
if (data.checkedEventId === "allItems") {
|
||||||
this.checkedEventInfo.forEach((v) => {
|
const allItemsIndex = this.checkedEventInfo.findIndex((v) => v.eventId === "allItems")
|
||||||
if (v.projectType === "1") {
|
if (allItemsIndex >= 0) {
|
||||||
v.applyUserModel = this.eventForm.applyUserModel
|
this.checkedEventInfo.splice(allItemsIndex, 1, data)
|
||||||
v.athletesMaxNum = data.athletesMaxNum
|
}
|
||||||
v.restrictRegNumber = data.restrictRegNumber
|
|
||||||
v.unionLimit = data.unionLimit
|
|
||||||
}
|
|
||||||
})
|
|
||||||
} else {
|
} else {
|
||||||
const info = this.checkedEventInfo.find((v) => v.eventId === data.checkedEventId)
|
const info = this.checkedEventInfo.find((v) => v.eventId === data.checkedEventId)
|
||||||
if (info != null) {
|
if (info != null) {
|
||||||
const index = this.checkedEventInfo.findIndex((v) => v.eventId === data.checkedEventId)
|
const index = this.checkedEventInfo.findIndex((v) => v.eventId === data.checkedEventId)
|
||||||
this.checkedEventInfo.splice(index, 1)
|
this.checkedEventInfo.splice(index, 1)
|
||||||
if (info.projectType === "1") {
|
|
||||||
this.$set(this.eventForm, "athletesMaxNum", data.athletesMaxNum)
|
|
||||||
this.$set(this.eventForm, "restrictRegNumber", data.restrictRegNumber)
|
|
||||||
}
|
|
||||||
this.$set(this.eventForm, "checkedEventId", info.eventId)
|
|
||||||
}
|
}
|
||||||
data.eventId = data.checkedEventId
|
data.eventId = data.checkedEventId
|
||||||
this.checkedEventInfo.push(data)
|
this.checkedEventInfo.push(data)
|
||||||
}
|
}
|
||||||
await this.doSave()
|
this.eventForm = clone(data)
|
||||||
|
this.currentEventId = data.checkedEventId
|
||||||
|
return this.doSave()
|
||||||
},
|
},
|
||||||
prev() {
|
prev() {
|
||||||
this.active--
|
this.active--
|
||||||
@@ -949,6 +963,7 @@
|
|||||||
this.copyTemplateMode = false
|
this.copyTemplateMode = false
|
||||||
this.copyTemplateName = ""
|
this.copyTemplateName = ""
|
||||||
this.pushTodoFlag = false
|
this.pushTodoFlag = false
|
||||||
|
this.currentEventId = ""
|
||||||
this.events = await this.getEvents(2)
|
this.events = await this.getEvents(2)
|
||||||
await this.getActivityGroup()
|
await this.getActivityGroup()
|
||||||
this.active = 0
|
this.active = 0
|
||||||
@@ -1028,6 +1043,7 @@
|
|||||||
async openEdit(row, flag, copyTemplateMode = false) {
|
async openEdit(row, flag, copyTemplateMode = false) {
|
||||||
this.copyTemplateMode = !!copyTemplateMode
|
this.copyTemplateMode = !!copyTemplateMode
|
||||||
this.pushTodoFlag = false
|
this.pushTodoFlag = false
|
||||||
|
this.currentEventId = ""
|
||||||
this.active = flag ? 0 : this.active
|
this.active = flag ? 0 : this.active
|
||||||
await this.getActivityGroup()
|
await this.getActivityGroup()
|
||||||
const { id } = row
|
const { id } = row
|
||||||
@@ -1184,7 +1200,8 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (this.eventForm.checkedEventId == "allItems") {
|
if (this.eventForm.checkedEventId == "allItems") {
|
||||||
events = events.filter((v) => v.projectType == 1 && v.id != "allItems")
|
// “所有单项”配置随具体单项提交,由后端统一校验并补齐继承值。
|
||||||
|
events = events.filter((v) => v.projectType == 1)
|
||||||
} else {
|
} else {
|
||||||
this.$set(this.eventForm, "activityId", this.formData.id)
|
this.$set(this.eventForm, "activityId", this.formData.id)
|
||||||
this.$set(this.eventForm, "eventId", this.eventForm.checkedEventId)
|
this.$set(this.eventForm, "eventId", this.eventForm.checkedEventId)
|
||||||
@@ -1192,9 +1209,10 @@
|
|||||||
this.$set(this.eventForm, "startAgeDate", this.eventForm.ageDate[0])
|
this.$set(this.eventForm, "startAgeDate", this.eventForm.ageDate[0])
|
||||||
this.$set(this.eventForm, "endAgeDate", this.eventForm.ageDate[1])
|
this.$set(this.eventForm, "endAgeDate", this.eventForm.ageDate[1])
|
||||||
}
|
}
|
||||||
events = this.eventForm
|
const allItems = this.checkedEventInfo.find((v) => v.eventId === "allItems")
|
||||||
|
events = allItems ? [clone(allItems), this.eventForm] : [this.eventForm]
|
||||||
if (this.copyTemplateMode) {
|
if (this.copyTemplateMode) {
|
||||||
this.cleanCopyTemplateData(null, [events])
|
this.cleanCopyTemplateData(null, events)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const loading = this.$loading({
|
const loading = this.$loading({
|
||||||
@@ -1215,6 +1233,7 @@
|
|||||||
this.copyTemplateMode = false
|
this.copyTemplateMode = false
|
||||||
}
|
}
|
||||||
await this.openEdit(formData, false)
|
await this.openEdit(formData, false)
|
||||||
|
this.currentEventId = this.eventForm.checkedEventId || ""
|
||||||
this.$message.success(resp.msg)
|
this.$message.success(resp.msg)
|
||||||
} else {
|
} else {
|
||||||
this.$message.error(resp.msg)
|
this.$message.error(resp.msg)
|
||||||
|
|||||||
@@ -1,4 +1,11 @@
|
|||||||
const REGISTER_INFO_COMPONENT = {
|
const REGISTER_INFO_COMPONENT = {
|
||||||
|
// 默认展示换届报告,仅由不需要查看该字段的业务页面显式关闭。
|
||||||
|
props: {
|
||||||
|
hideReplaceReport: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false
|
||||||
|
}
|
||||||
|
},
|
||||||
template: `
|
template: `
|
||||||
<div>
|
<div>
|
||||||
<el-tabs tab-position="top" v-model="activeName">
|
<el-tabs tab-position="top" v-model="activeName">
|
||||||
@@ -36,7 +43,7 @@ const REGISTER_INFO_COMPONENT = {
|
|||||||
{{viewData.createTime}}
|
{{viewData.createTime}}
|
||||||
</el-descriptions-item>
|
</el-descriptions-item>
|
||||||
<el-descriptions-item label="会费标准" :span="4">
|
<el-descriptions-item label="会费标准" :span="4">
|
||||||
{{viewData.due}}
|
{{ viewData.due === null || viewData.due === undefined ? "--" : viewData.due + " 元/年" }}
|
||||||
</el-descriptions-item>
|
</el-descriptions-item>
|
||||||
<el-descriptions-item :span="4">
|
<el-descriptions-item :span="4">
|
||||||
<template slot="label">社团介绍</template>
|
<template slot="label">社团介绍</template>
|
||||||
@@ -66,7 +73,7 @@ const REGISTER_INFO_COMPONENT = {
|
|||||||
<template slot="label">其他附件</template>
|
<template slot="label">其他附件</template>
|
||||||
<file-preview :files="viewData.files" complete_result></file-preview>
|
<file-preview :files="viewData.files" complete_result></file-preview>
|
||||||
</el-descriptions-item>
|
</el-descriptions-item>
|
||||||
<el-descriptions-item :span="2">
|
<el-descriptions-item :span="2" v-if="!hideReplaceReport">
|
||||||
<template slot="label">换届报告</template>
|
<template slot="label">换届报告</template>
|
||||||
<file-preview :files="viewData.replaceReport" complete_result></file-preview>
|
<file-preview :files="viewData.replaceReport" complete_result></file-preview>
|
||||||
</el-descriptions-item>
|
</el-descriptions-item>
|
||||||
|
|||||||
@@ -68,10 +68,12 @@ layout("/layouts/platform.html"){
|
|||||||
</el-steps>
|
</el-steps>
|
||||||
|
|
||||||
<!-- 第一步:基础信息表单 -->
|
<!-- 第一步:基础信息表单 -->
|
||||||
|
<!-- 本表单自行提示首个必填错误,关闭全局校验弹窗增强以免重复提示。 -->
|
||||||
<el-form
|
<el-form
|
||||||
v-show="step === 0"
|
v-show="step === 0"
|
||||||
:model="formData"
|
:model="formData"
|
||||||
ref="baseForm"
|
ref="baseForm"
|
||||||
|
no-auto-enhance
|
||||||
:rules="baseRules"
|
:rules="baseRules"
|
||||||
label-width="150px"
|
label-width="150px"
|
||||||
class="main-form"
|
class="main-form"
|
||||||
@@ -135,7 +137,9 @@ layout("/layouts/platform.html"){
|
|||||||
v-model="formData.due"
|
v-model="formData.due"
|
||||||
placeholder="请输入会费标准"
|
placeholder="请输入会费标准"
|
||||||
readonly
|
readonly
|
||||||
></el-input>
|
>
|
||||||
|
<template slot="append">元/年</template>
|
||||||
|
</el-input>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
</el-col>
|
||||||
</el-row>
|
</el-row>
|
||||||
@@ -146,7 +150,7 @@ layout("/layouts/platform.html"){
|
|||||||
<el-form-item
|
<el-form-item
|
||||||
class="is-required"
|
class="is-required"
|
||||||
label="本年度活动开展情况"
|
label="本年度活动开展情况"
|
||||||
prop="yearActivity"
|
prop="yearActivityList"
|
||||||
>
|
>
|
||||||
<span class="tip-text">说明:非赛事活动无需填写赛事举办单位、获奖情况。</span>
|
<span class="tip-text">说明:非赛事活动无需填写赛事举办单位、获奖情况。</span>
|
||||||
<el-table
|
<el-table
|
||||||
@@ -638,6 +642,7 @@ layout("/layouts/platform.html"){
|
|||||||
id: GetQueryString("bizId"),
|
id: GetQueryString("bizId"),
|
||||||
taskId: GetQueryString("taskId"),
|
taskId: GetQueryString("taskId"),
|
||||||
step: 0, // 当前步骤(0-基础信息,1-财务收支,2-成员名单)
|
step: 0, // 当前步骤(0-基础信息,1-财务收支,2-成员名单)
|
||||||
|
formLoading: false,
|
||||||
isRegistered: false, // 是否已登记
|
isRegistered: false, // 是否已登记
|
||||||
currentClubId: "", // 当前选中社团ID
|
currentClubId: "", // 当前选中社团ID
|
||||||
|
|
||||||
@@ -656,7 +661,7 @@ layout("/layouts/platform.html"){
|
|||||||
year: new Date().getFullYear() + "", // 默认当前年度
|
year: new Date().getFullYear() + "", // 默认当前年度
|
||||||
clubId: "",
|
clubId: "",
|
||||||
foundTime: "",
|
foundTime: "",
|
||||||
due: "",
|
due: null,
|
||||||
clubName: "",
|
clubName: "",
|
||||||
yearActivityList: [{}], // 本年度活动列表
|
yearActivityList: [{}], // 本年度活动列表
|
||||||
plans: [{}], // 下年度计划列表
|
plans: [{}], // 下年度计划列表
|
||||||
@@ -671,7 +676,10 @@ layout("/layouts/platform.html"){
|
|||||||
},
|
},
|
||||||
|
|
||||||
// 表单校验规则
|
// 表单校验规则
|
||||||
baseRules: {},
|
baseRules: {
|
||||||
|
yearActivityList: [{validator: this.validateActivityRows, trigger: ['change', 'blur']}],
|
||||||
|
plans: [{validator: this.validateActivityRows, trigger: ['change', 'blur']}]
|
||||||
|
},
|
||||||
financeRules: {},
|
financeRules: {},
|
||||||
memberRules: {}
|
memberRules: {}
|
||||||
};
|
};
|
||||||
@@ -724,6 +732,28 @@ layout("/layouts/platform.html"){
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
// 在列表级逐行校验,避免嵌套表单项未注册、空数组或纯空白文本绕过必填。
|
||||||
|
validateActivityRows(rule, value, callback) {
|
||||||
|
const currentYear = rule.field === 'yearActivityList';
|
||||||
|
const label = currentYear ? '本年度活动开展情况' : '下一年度活动计划';
|
||||||
|
const fields = currentYear
|
||||||
|
? [['activityTime', '活动时间'], ['activityName', '活动主题/赛事名称'], ['activityAddress', '活动地点'], ['joinNum', '参加人数']]
|
||||||
|
: [['activityName', '活动主题/赛事名称'], ['activityUnit', '活动/赛事主办单位'], ['activityAddress', '活动地点']];
|
||||||
|
if (!Array.isArray(value) || value.length === 0) {
|
||||||
|
callback(new Error(label + '至少填写一条'));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for (let i = 0; i < value.length; i++) {
|
||||||
|
for (const field of fields) {
|
||||||
|
const content = value[i] && value[i][field[0]];
|
||||||
|
if (content === null || content === undefined || String(content).trim() === '') {
|
||||||
|
callback(new Error(label + '第' + (i + 1) + '条:' + field[1] + '不能为空'));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
callback();
|
||||||
|
},
|
||||||
/************************ 通用工具方法 ************************/
|
/************************ 通用工具方法 ************************/
|
||||||
// 格式化数字(保留2位小数,空值显示0)
|
// 格式化数字(保留2位小数,空值显示0)
|
||||||
formatNumber(num) {
|
formatNumber(num) {
|
||||||
@@ -1110,7 +1140,7 @@ layout("/layouts/platform.html"){
|
|||||||
if (!val) return;
|
if (!val) return;
|
||||||
const club = this.clubOptions.find(item => item.id === val);
|
const club = this.clubOptions.find(item => item.id === val);
|
||||||
// 更新社团基础信息
|
// 更新社团基础信息
|
||||||
this.formData.due = club?.due || "";
|
this.formData.due = club && club.due !== null && club.due !== undefined ? club.due : null;
|
||||||
this.formData.foundTime = club?.foundTime
|
this.formData.foundTime = club?.foundTime
|
||||||
? this.$moment(club.foundTime).format("YYYY-MM-DD")
|
? this.$moment(club.foundTime).format("YYYY-MM-DD")
|
||||||
: this.$moment().format("YYYY-MM-DD");
|
: this.$moment().format("YYYY-MM-DD");
|
||||||
@@ -1161,73 +1191,63 @@ layout("/layouts/platform.html"){
|
|||||||
// 步骤前进
|
// 步骤前进
|
||||||
this.step++;
|
this.step++;
|
||||||
},
|
},
|
||||||
// 保存
|
// 三个操作共用基础信息校验,失败时返回第一步展示行号和必填字段。
|
||||||
async handleSave() {
|
validateBaseBeforeAction(action) {
|
||||||
try {
|
if (this.formLoading) return;
|
||||||
this.recalculateCensus();
|
this.$refs.baseForm.validate((valid, fields) => {
|
||||||
const resp = await this.$axios.post("/platform/club/examine/apply/save", {
|
if (!valid) {
|
||||||
data: JSON.stringify(this.formData),
|
this.step = 0;
|
||||||
incomeDetailed: JSON.stringify(this.financeData.incomeDetailed),
|
const firstError = Object.values(fields || {}).flat()[0];
|
||||||
incomeCensus: JSON.stringify(this.financeData.incomeCensus)
|
this.$message.warning('温馨提示:' + (firstError ? firstError.message : '请补全基础信息必填项'));
|
||||||
});
|
return;
|
||||||
if (resp.code === 0) {
|
|
||||||
this.$message.success(resp.msg);
|
|
||||||
commonUtil.pjaxPush('/platform/club/examine/mine');
|
|
||||||
}
|
}
|
||||||
} catch (error) {
|
action();
|
||||||
this.handleError(error, "保存失败");
|
});
|
||||||
}
|
|
||||||
},
|
},
|
||||||
// 提交(新增)
|
// 仅接收本页三个固定操作的接口后缀;data为登记实体JSON,另两项为财务数组JSON。
|
||||||
async handleSubmit() {
|
// 接口返回{code,msg,data},code为0时保存成功,否则展示后端校验提示。
|
||||||
try {
|
requestExamineAction(action) {
|
||||||
this.recalculateCensus();
|
if (this.formLoading) return;
|
||||||
await this.$confirm("确定要提交此申请吗?", "提示", {
|
this.recalculateCensus();
|
||||||
confirmButtonText: "确定",
|
const params = {
|
||||||
cancelButtonText: "取消",
|
data: JSON.stringify(this.formData),
|
||||||
type: "info"
|
incomeDetailed: JSON.stringify(this.financeData.incomeDetailed),
|
||||||
|
incomeCensus: JSON.stringify(this.financeData.incomeCensus)
|
||||||
|
};
|
||||||
|
if (action === 'submitAgain') params.taskId = this.taskId;
|
||||||
|
this.formLoading = true;
|
||||||
|
return this.$axios.post('/platform/club/examine/apply/' + action, params)
|
||||||
|
.then((resp) => {
|
||||||
|
if (resp.code === 0) {
|
||||||
|
this.$message.success(resp.msg);
|
||||||
|
commonUtil.pjaxPush('/platform/club/examine/mine');
|
||||||
|
} else {
|
||||||
|
this.$message.warning(resp.msg);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch(() => {
|
||||||
|
// 后端校验和网络异常已由全局axios拦截器提示,此处仅结束失败请求,避免再次弹窗。
|
||||||
|
})
|
||||||
|
.finally(() => {
|
||||||
|
this.formLoading = false;
|
||||||
});
|
});
|
||||||
const resp = await this.$axios.post("/platform/club/examine/apply/submit", {
|
|
||||||
data: JSON.stringify(this.formData),
|
|
||||||
incomeDetailed: JSON.stringify(this.financeData.incomeDetailed),
|
|
||||||
incomeCensus: JSON.stringify(this.financeData.incomeCensus)
|
|
||||||
});
|
|
||||||
if (resp.code === 0) {
|
|
||||||
this.$message.success(resp.msg);
|
|
||||||
commonUtil.pjaxPush('/platform/club/examine/mine');
|
|
||||||
} else {
|
|
||||||
this.$message.warning(resp.msg);
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
if (error !== "cancel") {
|
|
||||||
this.handleError(error, "提交失败");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
// 提交(任务处理)
|
handleSave() {
|
||||||
async handleFinishTask() {
|
this.validateBaseBeforeAction(() => this.requestExamineAction('save'));
|
||||||
try {
|
},
|
||||||
this.recalculateCensus();
|
handleSubmit() {
|
||||||
await this.$confirm("您确定要提交吗?", "提示", {
|
this.validateBaseBeforeAction(() => {
|
||||||
confirmButtonText: "确定",
|
this.$confirm('确定要提交此申请吗?', '提示', {
|
||||||
cancelButtonText: "取消",
|
confirmButtonText: '确定', cancelButtonText: '取消', type: 'info'
|
||||||
type: "warning"
|
}).then(() => this.requestExamineAction('submit')).catch(() => {});
|
||||||
});
|
});
|
||||||
const resp = await this.$axios.post('/platform/club/examine/apply/submitAgain', {
|
},
|
||||||
data: JSON.stringify(this.formData),
|
handleFinishTask() {
|
||||||
incomeDetailed: JSON.stringify(this.financeData.incomeDetailed),
|
this.validateBaseBeforeAction(() => {
|
||||||
incomeCensus: JSON.stringify(this.financeData.incomeCensus),
|
this.$confirm('您确定要提交吗?', '提示', {
|
||||||
taskId: this.taskId
|
confirmButtonText: '确定', cancelButtonText: '取消', type: 'warning'
|
||||||
});
|
}).then(() => this.requestExamineAction('submitAgain')).catch(() => {});
|
||||||
if (resp.code === 0) {
|
});
|
||||||
this.$message.success(resp.msg);
|
|
||||||
commonUtil.pjaxPush('/platform/club/examine/mine');
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
if (error !== "cancel") {
|
|
||||||
this.handleError(error, "提交失败");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -10,7 +10,7 @@
|
|||||||
<el-descriptions v-if="viewData" :column="3" border class="table_fixed">
|
<el-descriptions v-if="viewData" :column="3" border class="table_fixed">
|
||||||
<el-descriptions-item label="社团名称">{{ viewData.clubName }}</el-descriptions-item>
|
<el-descriptions-item label="社团名称">{{ viewData.clubName }}</el-descriptions-item>
|
||||||
<el-descriptions-item label="成立时间">{{ viewData.foundTime }} </el-descriptions-item>
|
<el-descriptions-item label="成立时间">{{ viewData.foundTime }} </el-descriptions-item>
|
||||||
<el-descriptions-item label="会费标准">{{ viewData.due }}</el-descriptions-item>
|
<el-descriptions-item label="会费标准">{{ viewData.due === null || viewData.due === undefined ? "--" : viewData.due + " 元/年" }}</el-descriptions-item>
|
||||||
<el-descriptions-item span="3">
|
<el-descriptions-item span="3">
|
||||||
<template slot="label">工作总结</template>
|
<template slot="label">工作总结</template>
|
||||||
<file-preview :files="viewData.summaryFiles" complete_result></file-preview>
|
<file-preview :files="viewData.summaryFiles" complete_result></file-preview>
|
||||||
|
|||||||
@@ -73,7 +73,7 @@ layout("/layouts/platform.html"){
|
|||||||
<el-descriptions-item label="联系人邮箱">{{viewData.concatPersonEmail}}</el-descriptions-item>
|
<el-descriptions-item label="联系人邮箱">{{viewData.concatPersonEmail}}</el-descriptions-item>
|
||||||
<el-descriptions-item>
|
<el-descriptions-item>
|
||||||
<template slot="label">会费标准</template>
|
<template slot="label">会费标准</template>
|
||||||
{{viewData.due}}
|
{{ viewData.due === null || viewData.due === undefined ? "--" : viewData.due + " 元/年" }}
|
||||||
</el-descriptions-item>
|
</el-descriptions-item>
|
||||||
<el-descriptions-item :span="2">
|
<el-descriptions-item :span="2">
|
||||||
<template slot="label">当前人数</template>
|
<template slot="label">当前人数</template>
|
||||||
|
|||||||
@@ -63,7 +63,7 @@ layout("/layouts/platform.html"){
|
|||||||
<el-descriptions-item label="社团编码">{{viewData.clubCode}}</el-descriptions-item>
|
<el-descriptions-item label="社团编码">{{viewData.clubCode}}</el-descriptions-item>
|
||||||
<el-descriptions-item label="社团类型">{{viewData.typeName}}</el-descriptions-item>
|
<el-descriptions-item label="社团类型">{{viewData.typeName}}</el-descriptions-item>
|
||||||
<el-descriptions-item label="发起人">{{viewData.sponsorName}}</el-descriptions-item>
|
<el-descriptions-item label="发起人">{{viewData.sponsorName}}</el-descriptions-item>
|
||||||
<el-descriptions-item label="会费标准">{{viewData.due}}</el-descriptions-item>
|
<el-descriptions-item label="会费标准">{{ viewData.due === null || viewData.due === undefined ? "--" : viewData.due + " 元/年" }}</el-descriptions-item>
|
||||||
<el-descriptions-item label="当前人数">{{viewData.currentPeopleNum}}</el-descriptions-item>
|
<el-descriptions-item label="当前人数">{{viewData.currentPeopleNum}}</el-descriptions-item>
|
||||||
<el-descriptions-item span="2">
|
<el-descriptions-item span="2">
|
||||||
<template slot="label">社团介绍</template>
|
<template slot="label">社团介绍</template>
|
||||||
|
|||||||
@@ -24,7 +24,13 @@ const CLUB_FORM_TEMPLATE = {
|
|||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="12">
|
<el-col :span="12">
|
||||||
<el-form-item label="会费标准" prop="due">
|
<el-form-item label="会费标准" prop="due">
|
||||||
<el-input placeholder="请填写会费标准" v-model="formData.due">
|
<el-input
|
||||||
|
min="0"
|
||||||
|
placeholder="请填写会费标准"
|
||||||
|
step="0.01"
|
||||||
|
type="number"
|
||||||
|
v-model.number="formData.due"
|
||||||
|
>
|
||||||
<template slot="append">元/年</template>
|
<template slot="append">元/年</template>
|
||||||
</el-input>
|
</el-input>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
@@ -156,12 +162,15 @@ const CLUB_FORM_TEMPLATE = {
|
|||||||
return {
|
return {
|
||||||
formData: {
|
formData: {
|
||||||
clubName: "",
|
clubName: "",
|
||||||
clubType: ""
|
clubType: "",
|
||||||
|
due: null
|
||||||
},
|
},
|
||||||
formRules: {
|
formRules: {
|
||||||
clubName: [{ required: true, message: "请填写社团名称", trigger: ["blur", "change"] }],
|
clubName: [{ required: true, message: "请填写社团名称", trigger: ["blur", "change"] }],
|
||||||
clubCode: [{ required: false, message: "请填写社团编码", trigger: ["blur", "change"] }],
|
clubCode: [{ required: false, message: "请填写社团编码", trigger: ["blur", "change"] }],
|
||||||
clubType: [{ required: true, message: "请选择社团类型", trigger: ["blur", "change"] }],
|
clubType: [{ required: true, message: "请选择社团类型", trigger: ["blur", "change"] }],
|
||||||
|
// 会费标准只保存数字,单位“元/年”由页面统一展示。
|
||||||
|
due: [{ type: "number", min: 0, message: "会费标准必须为不小于0的数字", trigger: ["blur", "change"] }],
|
||||||
//concatPerson: [{ required: true, message: "请选择社团联系人", trigger: ["blur", "change"] }],
|
//concatPerson: [{ required: true, message: "请选择社团联系人", trigger: ["blur", "change"] }],
|
||||||
foundTime: [{ required: true, message: "请选择成立时间", trigger: ["blur", "change"] }]
|
foundTime: [{ required: true, message: "请选择成立时间", trigger: ["blur", "change"] }]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -73,7 +73,7 @@ layout("/layouts/platform.html"){
|
|||||||
</el-card>
|
</el-card>
|
||||||
|
|
||||||
<template #public>
|
<template #public>
|
||||||
<register-info ref="registerInfoRef">
|
<register-info ref="registerInfoRef" :hide-replace-report="true">
|
||||||
<div v-if="showApprovalForm">
|
<div v-if="showApprovalForm">
|
||||||
<div class="process-title">
|
<div class="process-title">
|
||||||
{{formData.taskName}}
|
{{formData.taskName}}
|
||||||
|
|||||||
@@ -131,7 +131,7 @@ layout("/layouts/platform.html"){
|
|||||||
<el-option v-for="item in organizationTypeOptions" :key="item.code" :label="item.name" :value="item.code"></el-option>
|
<el-option v-for="item in organizationTypeOptions" :key="item.code" :label="item.name" :value="item.code"></el-option>
|
||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="所属工会" prop="unionId">
|
<el-form-item label="所属工会" prop="unionId" :required="formData.organizationType !== 'schoolUnion'">
|
||||||
<el-select v-model="formData.unionId" clearable filterable placeholder="请选择所属工会" style="width: 100%" :disabled="isUnionDisabled()">
|
<el-select v-model="formData.unionId" clearable filterable placeholder="请选择所属工会" style="width: 100%" :disabled="isUnionDisabled()">
|
||||||
<el-option v-for="item in unionOptions" :key="item.id" :label="item.name" :value="item.id"></el-option>
|
<el-option v-for="item in unionOptions" :key="item.id" :label="item.name" :value="item.id"></el-option>
|
||||||
</el-select>
|
</el-select>
|
||||||
@@ -255,7 +255,9 @@ layout("/layouts/platform.html"){
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
const validatePeople = (rule, value, callback) => {
|
const validatePeople = (rule, value, callback) => {
|
||||||
if (!value || value <= 0) {
|
if (value === null || value === undefined || value === "") {
|
||||||
|
callback(new Error("必填"))
|
||||||
|
} else if (!value || value <= 0) {
|
||||||
callback(new Error("人数必须大于0"))
|
callback(new Error("人数必须大于0"))
|
||||||
} else if (this.batchForm.minGroupPeople && this.batchForm.maxGroupPeople
|
} else if (this.batchForm.minGroupPeople && this.batchForm.maxGroupPeople
|
||||||
&& this.batchForm.minGroupPeople > this.batchForm.maxGroupPeople) {
|
&& this.batchForm.minGroupPeople > this.batchForm.maxGroupPeople) {
|
||||||
@@ -317,15 +319,15 @@ layout("/layouts/platform.html"){
|
|||||||
},
|
},
|
||||||
batchRules: {
|
batchRules: {
|
||||||
lineId: [{ required: true, message: "必填", trigger: ["blur", "change"] }],
|
lineId: [{ required: true, message: "必填", trigger: ["blur", "change"] }],
|
||||||
signupStartTime: [{ validator: validateBatchTime, trigger: ["blur", "change"] }],
|
signupStartTime: [{ required: true, validator: validateBatchTime, trigger: ["blur", "change"] }],
|
||||||
signupEndTime: [{ validator: validateBatchTime, trigger: ["blur", "change"] }],
|
signupEndTime: [{ required: true, validator: validateBatchTime, trigger: ["blur", "change"] }],
|
||||||
travelStartTime: [{ validator: validateBatchTime, trigger: ["blur", "change"] }],
|
travelStartTime: [{ required: true, validator: validateBatchTime, trigger: ["blur", "change"] }],
|
||||||
travelEndTime: [{ validator: validateBatchTime, trigger: ["blur", "change"] }],
|
travelEndTime: [{ required: true, validator: validateBatchTime, trigger: ["blur", "change"] }],
|
||||||
contactName: [{ required: true, message: "必填", trigger: ["blur", "change"] }],
|
contactName: [{ required: true, message: "必填", trigger: ["blur", "change"] }],
|
||||||
contactPhone: [{ validator: validateMobile, trigger: ["blur", "change"] }],
|
contactPhone: [{ required: true, validator: validateMobile, trigger: ["blur", "change"] }],
|
||||||
minGroupPeople: [{ validator: validatePeople, trigger: ["blur", "change"] }],
|
minGroupPeople: [{ required: true, validator: validatePeople, trigger: ["blur", "change"] }],
|
||||||
maxGroupPeople: [{ validator: validatePeople, trigger: ["blur", "change"] }],
|
maxGroupPeople: [{ required: true, validator: validatePeople, trigger: ["blur", "change"] }],
|
||||||
estimatedCost: [{ validator: validateMoney, trigger: ["blur", "change"] }]
|
estimatedCost: [{ required: true, validator: validateMoney, trigger: ["blur", "change"] }]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -216,7 +216,7 @@ layout("/layouts/platform.html"){
|
|||||||
</el-row>
|
</el-row>
|
||||||
<el-row :gutter="20">
|
<el-row :gutter="20">
|
||||||
<el-col :span="8">
|
<el-col :span="8">
|
||||||
<el-form-item label="身份证号">
|
<el-form-item label="身份证号" prop="idCard" :rules="requiredRules" required>
|
||||||
<el-input v-model="signupForm.idCard" readonly></el-input>
|
<el-input v-model="signupForm.idCard" readonly></el-input>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
</el-col>
|
||||||
@@ -233,8 +233,8 @@ layout("/layouts/platform.html"){
|
|||||||
</el-row>
|
</el-row>
|
||||||
<el-row :gutter="20">
|
<el-row :gutter="20">
|
||||||
<el-col :span="8">
|
<el-col :span="8">
|
||||||
<el-form-item label="手机号" required>
|
<el-form-item label="手机号" prop="mobile" :rules="mobileRules" required>
|
||||||
<el-input v-model="signupForm.mobile" maxlength="30" placeholder="请输入手机号"></el-input>
|
<el-input v-model="signupForm.mobile" maxlength="11" placeholder="请输入手机号"></el-input>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
</el-col>
|
||||||
</el-row>
|
</el-row>
|
||||||
@@ -325,17 +325,17 @@ layout("/layouts/platform.html"){
|
|||||||
<el-form :model="directRelativeForm" label-width="110px" ref="directRelativeForm">
|
<el-form :model="directRelativeForm" label-width="110px" ref="directRelativeForm">
|
||||||
<el-row :gutter="20">
|
<el-row :gutter="20">
|
||||||
<el-col :span="8">
|
<el-col :span="8">
|
||||||
<el-form-item label="亲属姓名">
|
<el-form-item label="亲属姓名" prop="relativeName" :rules="requiredRules" required>
|
||||||
<el-input v-model="directRelativeForm.relativeName" maxlength="100" placeholder="请输入亲属姓名"></el-input>
|
<el-input v-model="directRelativeForm.relativeName" maxlength="100" placeholder="请输入亲属姓名"></el-input>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="8">
|
<el-col :span="8">
|
||||||
<el-form-item label="所在单位">
|
<el-form-item label="所在单位" prop="unitName" :rules="requiredRules" required>
|
||||||
<el-input v-model="directRelativeForm.unitName" maxlength="100" placeholder="请输入所在单位"></el-input>
|
<el-input v-model="directRelativeForm.unitName" maxlength="100" placeholder="请输入所在单位"></el-input>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="8">
|
<el-col :span="8">
|
||||||
<el-form-item label="亲属关系">
|
<el-form-item label="亲属关系" prop="relationshipCode" :rules="requiredRules" required>
|
||||||
<el-select v-model="directRelativeForm.relationshipCode" clearable placeholder="请选择亲属关系" style="width: 100%" @change="directRelativeChange">
|
<el-select v-model="directRelativeForm.relationshipCode" clearable placeholder="请选择亲属关系" style="width: 100%" @change="directRelativeChange">
|
||||||
<el-option v-for="item in directRelativeOptions" :key="item.code" :label="item.name" :value="item.code"></el-option>
|
<el-option v-for="item in directRelativeOptions" :key="item.code" :label="item.name" :value="item.code"></el-option>
|
||||||
</el-select>
|
</el-select>
|
||||||
@@ -344,12 +344,12 @@ layout("/layouts/platform.html"){
|
|||||||
</el-row>
|
</el-row>
|
||||||
<el-row :gutter="20">
|
<el-row :gutter="20">
|
||||||
<el-col :span="8">
|
<el-col :span="8">
|
||||||
<el-form-item label="线路名称">
|
<el-form-item label="线路名称" prop="lineName" :rules="requiredRules" required>
|
||||||
<el-input v-model="directRelativeForm.lineName" maxlength="100" placeholder="请输入线路名称"></el-input>
|
<el-input v-model="directRelativeForm.lineName" maxlength="100" placeholder="请输入线路名称"></el-input>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="8">
|
<el-col :span="8">
|
||||||
<el-form-item label="出行开始日期">
|
<el-form-item label="出行开始日期" prop="travelStartTime" :rules="requiredRules" required>
|
||||||
<el-date-picker
|
<el-date-picker
|
||||||
v-model="directRelativeForm.travelStartTime"
|
v-model="directRelativeForm.travelStartTime"
|
||||||
type="date"
|
type="date"
|
||||||
@@ -360,7 +360,7 @@ layout("/layouts/platform.html"){
|
|||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="8">
|
<el-col :span="8">
|
||||||
<el-form-item label="出行结束日期">
|
<el-form-item label="出行结束日期" prop="travelEndTime" :rules="requiredRules" required>
|
||||||
<el-date-picker
|
<el-date-picker
|
||||||
v-model="directRelativeForm.travelEndTime"
|
v-model="directRelativeForm.travelEndTime"
|
||||||
type="date"
|
type="date"
|
||||||
@@ -379,34 +379,48 @@ layout("/layouts/platform.html"){
|
|||||||
<div class="tour-actions">
|
<div class="tour-actions">
|
||||||
<el-button size="medium" type="primary" icon="el-icon-plus" :disabled="!signupForm.hasFamily" @click="addFamily">增加一条</el-button>
|
<el-button size="medium" type="primary" icon="el-icon-plus" :disabled="!signupForm.hasFamily" @click="addFamily">增加一条</el-button>
|
||||||
</div>
|
</div>
|
||||||
<el-table :data="familyData" border :size="tableSize" empty-text="暂无亲属信息">
|
<el-form :model="{ rows: familyData }" ref="familyForm" label-width="0">
|
||||||
|
<el-table class="tour-family-table" :data="familyData" border :size="tableSize" empty-text="暂无亲属信息">
|
||||||
<el-table-column label="序号" type="index" width="70" align="center" header-align="center"></el-table-column>
|
<el-table-column label="序号" type="index" width="70" align="center" header-align="center"></el-table-column>
|
||||||
<el-table-column label="家属姓名" min-width="130" align="center" header-align="center">
|
<el-table-column label="家属姓名" min-width="130" align="center" header-align="center">
|
||||||
<template slot-scope="{row}">
|
<template slot="header"><span style="color: #f56c6c">*</span> 家属姓名</template>
|
||||||
|
<template slot-scope="{row, $index}">
|
||||||
|
<el-form-item :prop="'rows.' + $index + '.familyName'" :rules="requiredRules">
|
||||||
<el-input v-model="row.familyName" maxlength="100" placeholder="请输入"></el-input>
|
<el-input v-model="row.familyName" maxlength="100" placeholder="请输入"></el-input>
|
||||||
|
</el-form-item>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column label="性别" width="110" align="center" header-align="center">
|
<el-table-column label="性别" width="110" align="center" header-align="center">
|
||||||
<template slot-scope="{row}">
|
<template slot="header"><span style="color: #f56c6c">*</span> 性别</template>
|
||||||
|
<template slot-scope="{row, $index}">
|
||||||
|
<el-form-item :prop="'rows.' + $index + '.gender'" :rules="requiredRules">
|
||||||
<el-select v-model="row.gender" clearable placeholder="请选择">
|
<el-select v-model="row.gender" clearable placeholder="请选择">
|
||||||
<el-option label="男" value="男"></el-option>
|
<el-option label="男" value="男"></el-option>
|
||||||
<el-option label="女" value="女"></el-option>
|
<el-option label="女" value="女"></el-option>
|
||||||
</el-select>
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column label="身份证号码" min-width="180" align="center" header-align="center">
|
<el-table-column label="身份证号码" min-width="180" align="center" header-align="center">
|
||||||
<template slot-scope="{row}">
|
<template slot-scope="{row, $index}">
|
||||||
|
<el-form-item :prop="'rows.' + $index + '.idCard'" :rules="[{ required: familyContactRequired(row), validator: validateFamilyIdCard, trigger: ['blur', 'change'] }]">
|
||||||
<el-input v-model="row.idCard" maxlength="18" :placeholder="familyContactRequired(row) ? '16岁及以上必填' : '选填'" @blur="normalizeFamilyIdCard(row)"></el-input>
|
<el-input v-model="row.idCard" maxlength="18" :placeholder="familyContactRequired(row) ? '16岁及以上必填' : '选填'" @blur="normalizeFamilyIdCard(row)"></el-input>
|
||||||
|
</el-form-item>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column label="手机号" min-width="150" align="center" header-align="center">
|
<el-table-column label="手机号" min-width="150" align="center" header-align="center">
|
||||||
<template slot-scope="{row}">
|
<template slot-scope="{row, $index}">
|
||||||
|
<el-form-item :prop="'rows.' + $index + '.mobile'" :rules="[{ required: familyContactRequired(row), message: '必填', trigger: ['blur', 'change'] }]">
|
||||||
<el-input v-model="row.mobile" maxlength="30" :placeholder="familyContactRequired(row) ? '16岁及以上必填' : '选填'"></el-input>
|
<el-input v-model="row.mobile" maxlength="30" :placeholder="familyContactRequired(row) ? '16岁及以上必填' : '选填'"></el-input>
|
||||||
|
</el-form-item>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column label="年龄" width="110" align="center" header-align="center">
|
<el-table-column label="年龄" width="110" align="center" header-align="center">
|
||||||
<template slot-scope="{row}">
|
<template slot="header"><span style="color: #f56c6c">*</span> 年龄</template>
|
||||||
|
<template slot-scope="{row, $index}">
|
||||||
|
<el-form-item :prop="'rows.' + $index + '.age'" :rules="requiredRules">
|
||||||
<el-input-number v-model="row.age" :min="0" :max="120" :precision="0" controls-position="right" style="width: 100%"></el-input-number>
|
<el-input-number v-model="row.age" :min="0" :max="120" :precision="0" controls-position="right" style="width: 100%"></el-input-number>
|
||||||
|
</el-form-item>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column v-if="fillBedInfo" label="床型" min-width="120" align="center" header-align="center">
|
<el-table-column v-if="fillBedInfo" label="床型" min-width="120" align="center" header-align="center">
|
||||||
@@ -427,10 +441,13 @@ layout("/layouts/platform.html"){
|
|||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column label="关系" width="120" align="center" header-align="center">
|
<el-table-column label="关系" width="120" align="center" header-align="center">
|
||||||
<template slot-scope="{row}">
|
<template slot="header"><span style="color: #f56c6c">*</span> 关系</template>
|
||||||
|
<template slot-scope="{row, $index}">
|
||||||
|
<el-form-item :prop="'rows.' + $index + '.relationship'" :rules="requiredRules">
|
||||||
<el-select v-model="row.relationship" clearable placeholder="请选择">
|
<el-select v-model="row.relationship" clearable placeholder="请选择">
|
||||||
<el-option v-for="item in familyRelationshipOptions" :key="item.code" :label="item.name" :value="item.name"></el-option>
|
<el-option v-for="item in familyRelationshipOptions" :key="item.code" :label="item.name" :value="item.name"></el-option>
|
||||||
</el-select>
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column label="操作" width="90" align="center" header-align="center" fixed="right">
|
<el-table-column label="操作" width="90" align="center" header-align="center" fixed="right">
|
||||||
@@ -439,6 +456,8 @@ layout("/layouts/platform.html"){
|
|||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
</el-table>
|
</el-table>
|
||||||
|
<div v-if="familyValidationAttempted && familyData.length === 0" class="el-form-item__error" style="position: static">必填</div>
|
||||||
|
</el-form>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<span slot="footer" class="dialog-footer">
|
<span slot="footer" class="dialog-footer">
|
||||||
@@ -520,6 +539,10 @@ layout("/layouts/platform.html"){
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
|
/* 覆盖全局表格 div 文字颜色,保留输入组件下方校验提示的红色。 */
|
||||||
|
.tour-family-table.el-table td.el-table__cell .el-form-item__error {
|
||||||
|
color: #f56c6c;
|
||||||
|
}
|
||||||
.tour-section {
|
.tour-section {
|
||||||
margin-top: 10px;
|
margin-top: 10px;
|
||||||
padding: 0 2px;
|
padding: 0 2px;
|
||||||
@@ -763,6 +786,12 @@ layout("/layouts/platform.html"){
|
|||||||
fillBedInfo: true,
|
fillBedInfo: true,
|
||||||
signupForm: {},
|
signupForm: {},
|
||||||
familyData: [],
|
familyData: [],
|
||||||
|
familyValidationAttempted: false,
|
||||||
|
requiredRules: [{ required: true, message: "必填", trigger: ["blur", "change"] }],
|
||||||
|
mobileRules: [
|
||||||
|
{ required: true, message: "必填", trigger: ["blur", "change"] },
|
||||||
|
{ pattern: /^1[3-9]\d{9}$/, message: "请输入正确的11位手机号", trigger: ["blur", "change"] }
|
||||||
|
],
|
||||||
bedTypeOptions: [],
|
bedTypeOptions: [],
|
||||||
familyRelationshipOptions: [],
|
familyRelationshipOptions: [],
|
||||||
directRelativeOptions: [],
|
directRelativeOptions: [],
|
||||||
@@ -1161,6 +1190,11 @@ layout("/layouts/platform.html"){
|
|||||||
this.signupForm.hasFamily = true
|
this.signupForm.hasFamily = true
|
||||||
}
|
}
|
||||||
this.signupVisible = true
|
this.signupVisible = true
|
||||||
|
this.$nextTick(() => {
|
||||||
|
;[this.$refs.signupForm, this.$refs.directRelativeForm, this.$refs.familyForm].forEach(form => {
|
||||||
|
if (form) form.clearValidate()
|
||||||
|
})
|
||||||
|
})
|
||||||
} else {
|
} else {
|
||||||
this.$message.warning(res.msg || "查询失败")
|
this.$message.warning(res.msg || "查询失败")
|
||||||
}
|
}
|
||||||
@@ -1231,29 +1265,22 @@ layout("/layouts/platform.html"){
|
|||||||
this.signupForm.hasFamily = false
|
this.signupForm.hasFamily = false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
// 家属表格按行校验,缺失项显示在对应输入组件下方。
|
||||||
validateFamilies() {
|
validateFamilies() {
|
||||||
if (!this.allowFamily || !this.signupForm.hasFamily) return true
|
if (!this.allowFamily || !this.signupForm.hasFamily) return true
|
||||||
if (this.familyData.length === 0) {
|
this.familyValidationAttempted = true
|
||||||
this.$message.warning("请添加亲属信息")
|
if (this.familyData.length === 0) return false
|
||||||
return false
|
return new Promise(resolve => this.$refs.familyForm.validate(valid => resolve(valid)))
|
||||||
|
},
|
||||||
|
// 未满16岁的家属允许不填身份证,已填写时仍检查格式。
|
||||||
|
validateFamilyIdCard(rule, value, callback) {
|
||||||
|
if (!value) {
|
||||||
|
callback(rule.required ? new Error("必填") : undefined)
|
||||||
|
} else if (!this.isValidIdCard(value)) {
|
||||||
|
callback(new Error("请输入正确的身份证号码"))
|
||||||
|
} else {
|
||||||
|
callback()
|
||||||
}
|
}
|
||||||
const invalidBase = this.familyData.some(item => !item.familyName || item.age === null || item.age === undefined
|
|
||||||
|| !item.gender || !item.relationship)
|
|
||||||
if (invalidBase) {
|
|
||||||
this.$message.warning("请完善亲属姓名、年龄、性别和与本人关系")
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
const invalidContact = this.familyData.some(item => this.familyContactRequired(item) && (!item.idCard || !item.mobile))
|
|
||||||
if (invalidContact) {
|
|
||||||
this.$message.warning("年满16周岁的亲属必须填写身份证号码和手机号")
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
const invalidIdCard = this.familyData.some(item => item.idCard && !this.isValidIdCard(item.idCard))
|
|
||||||
if (invalidIdCard) {
|
|
||||||
this.$message.warning("请输入正确的身份证号码")
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
},
|
},
|
||||||
familyContactRequired(family) {
|
familyContactRequired(family) {
|
||||||
return family && family.age !== null && family.age !== undefined && Number(family.age) >= 16
|
return family && family.age !== null && family.age !== undefined && Number(family.age) >= 16
|
||||||
@@ -1269,39 +1296,17 @@ layout("/layouts/platform.html"){
|
|||||||
},
|
},
|
||||||
validateDirectRelative() {
|
validateDirectRelative() {
|
||||||
if (!this.isDirectFamilyLine(this.signupForm)) return true
|
if (!this.isDirectFamilyLine(this.signupForm)) return true
|
||||||
if (!this.directRelativeForm.relativeName) {
|
return new Promise(resolve => this.$refs.directRelativeForm.validate(valid => resolve(valid)))
|
||||||
this.$message.warning("请输入亲属姓名")
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
if (!this.directRelativeForm.unitName) {
|
|
||||||
this.$message.warning("请输入亲属所在单位")
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
if (!this.directRelativeForm.relationshipCode) {
|
|
||||||
this.$message.warning("请选择亲属关系")
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
if (!this.directRelativeForm.lineName) {
|
|
||||||
this.$message.warning("请输入直系亲属线路名称")
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
if (!this.directRelativeForm.travelStartTime) {
|
|
||||||
this.$message.warning("请选择出行开始日期")
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
if (!this.directRelativeForm.travelEndTime) {
|
|
||||||
this.$message.warning("请选择出行结束日期")
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
},
|
},
|
||||||
submitSignup() {
|
async submitSignup() {
|
||||||
if (!this.signupForm.idCard || !this.signupForm.mobile) {
|
if (this.signupLoading) return
|
||||||
this.$message.warning("请完善报名人身份证号码和手机号")
|
// 同时校验各区域,一次展示所有字段错误,通过后才提交报名。
|
||||||
return
|
const results = await Promise.all([
|
||||||
}
|
new Promise(resolve => this.$refs.signupForm.validate(valid => resolve(valid))),
|
||||||
if (!this.validateFamilies()) return
|
this.validateFamilies(),
|
||||||
if (!this.validateDirectRelative()) return
|
this.validateDirectRelative()
|
||||||
|
])
|
||||||
|
if (results.some(valid => !valid)) return
|
||||||
const families = this.allowFamily && this.signupForm.hasFamily ? this.familyData : []
|
const families = this.allowFamily && this.signupForm.hasFamily ? this.familyData : []
|
||||||
const form = Object.assign({}, this.signupForm, {
|
const form = Object.assign({}, this.signupForm, {
|
||||||
families: JSON.stringify(families),
|
families: JSON.stringify(families),
|
||||||
@@ -1352,6 +1357,7 @@ layout("/layouts/platform.html"){
|
|||||||
}).catch(() => {})
|
}).catch(() => {})
|
||||||
},
|
},
|
||||||
destroySignup() {
|
destroySignup() {
|
||||||
|
this.familyValidationAttempted = false
|
||||||
this.signupForm = {}
|
this.signupForm = {}
|
||||||
this.familyData = []
|
this.familyData = []
|
||||||
this.directRelativeForm = {}
|
this.directRelativeForm = {}
|
||||||
|
|||||||
@@ -182,7 +182,7 @@ layout("/layouts/platform.html"){
|
|||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col v-if="formData.outProvinceRatioType === '固定人数'" :span="12">
|
<el-col v-if="formData.outProvinceRatioType === '固定人数'" :span="12">
|
||||||
<el-form-item label="固定人数" prop="outProvinceFixedPeople">
|
<el-form-item label="固定人数" prop="outProvinceFixedPeople" :required="formData.outProvinceRatioType === '固定人数'">
|
||||||
<el-input-number v-model="formData.outProvinceFixedPeople" :controls="false" :min="0" :precision="0" placeholder="请输入固定人数" style="width: 100%"></el-input-number>
|
<el-input-number v-model="formData.outProvinceFixedPeople" :controls="false" :min="0" :precision="0" placeholder="请输入固定人数" style="width: 100%"></el-input-number>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
</el-col>
|
||||||
@@ -366,7 +366,9 @@ layout("/layouts/platform.html"){
|
|||||||
}
|
}
|
||||||
const checkOutProvinceFixedPeople = (rule, value, callback) => {
|
const checkOutProvinceFixedPeople = (rule, value, callback) => {
|
||||||
if (this.formData.outProvinceRatioType === "固定人数"
|
if (this.formData.outProvinceRatioType === "固定人数"
|
||||||
&& (value === null || value === undefined || value === "" || value < 0)) {
|
&& (value === null || value === undefined || value === "")) {
|
||||||
|
callback(new Error("必填"))
|
||||||
|
} else if (this.formData.outProvinceRatioType === "固定人数" && value < 0) {
|
||||||
callback(new Error("固定人数必须大于等于0"))
|
callback(new Error("固定人数必须大于等于0"))
|
||||||
} else {
|
} else {
|
||||||
callback()
|
callback()
|
||||||
|
|||||||
@@ -113,7 +113,7 @@ layout("/layouts/platform.html"){
|
|||||||
</el-row>
|
</el-row>
|
||||||
<el-row :gutter="20">
|
<el-row :gutter="20">
|
||||||
<el-col :span="8">
|
<el-col :span="8">
|
||||||
<el-form-item label="身份证号">
|
<el-form-item label="身份证号" prop="idCard" :rules="requiredRules" required>
|
||||||
<el-input v-model="signupForm.idCard" readonly></el-input>
|
<el-input v-model="signupForm.idCard" readonly></el-input>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
</el-col>
|
||||||
@@ -130,8 +130,8 @@ layout("/layouts/platform.html"){
|
|||||||
</el-row>
|
</el-row>
|
||||||
<el-row :gutter="20">
|
<el-row :gutter="20">
|
||||||
<el-col :span="8">
|
<el-col :span="8">
|
||||||
<el-form-item label="手机号" required>
|
<el-form-item label="手机号" prop="mobile" :rules="mobileRules" required>
|
||||||
<el-input v-model="signupForm.mobile" maxlength="30" placeholder="请输入手机号"></el-input>
|
<el-input v-model="signupForm.mobile" maxlength="11" placeholder="请输入手机号"></el-input>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
</el-col>
|
||||||
</el-row>
|
</el-row>
|
||||||
@@ -222,17 +222,17 @@ layout("/layouts/platform.html"){
|
|||||||
<el-form :model="directRelativeForm" label-width="110px" ref="directRelativeForm">
|
<el-form :model="directRelativeForm" label-width="110px" ref="directRelativeForm">
|
||||||
<el-row :gutter="20">
|
<el-row :gutter="20">
|
||||||
<el-col :span="8">
|
<el-col :span="8">
|
||||||
<el-form-item label="亲属姓名">
|
<el-form-item label="亲属姓名" prop="relativeName" :rules="requiredRules" required>
|
||||||
<el-input v-model="directRelativeForm.relativeName" maxlength="100" placeholder="请输入亲属姓名"></el-input>
|
<el-input v-model="directRelativeForm.relativeName" maxlength="100" placeholder="请输入亲属姓名"></el-input>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="8">
|
<el-col :span="8">
|
||||||
<el-form-item label="所在单位">
|
<el-form-item label="所在单位" prop="unitName" :rules="requiredRules" required>
|
||||||
<el-input v-model="directRelativeForm.unitName" maxlength="100" placeholder="请输入所在单位"></el-input>
|
<el-input v-model="directRelativeForm.unitName" maxlength="100" placeholder="请输入所在单位"></el-input>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="8">
|
<el-col :span="8">
|
||||||
<el-form-item label="亲属关系">
|
<el-form-item label="亲属关系" prop="relationshipCode" :rules="requiredRules" required>
|
||||||
<el-select v-model="directRelativeForm.relationshipCode" clearable placeholder="请选择亲属关系" style="width: 100%" @change="directRelativeChange">
|
<el-select v-model="directRelativeForm.relationshipCode" clearable placeholder="请选择亲属关系" style="width: 100%" @change="directRelativeChange">
|
||||||
<el-option v-for="item in directRelativeOptions" :key="item.code" :label="item.name" :value="item.code"></el-option>
|
<el-option v-for="item in directRelativeOptions" :key="item.code" :label="item.name" :value="item.code"></el-option>
|
||||||
</el-select>
|
</el-select>
|
||||||
@@ -241,12 +241,12 @@ layout("/layouts/platform.html"){
|
|||||||
</el-row>
|
</el-row>
|
||||||
<el-row :gutter="20">
|
<el-row :gutter="20">
|
||||||
<el-col :span="8">
|
<el-col :span="8">
|
||||||
<el-form-item label="线路名称">
|
<el-form-item label="线路名称" prop="lineName" :rules="requiredRules" required>
|
||||||
<el-input v-model="directRelativeForm.lineName" maxlength="100" placeholder="请输入线路名称"></el-input>
|
<el-input v-model="directRelativeForm.lineName" maxlength="100" placeholder="请输入线路名称"></el-input>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="8">
|
<el-col :span="8">
|
||||||
<el-form-item label="出行开始日期">
|
<el-form-item label="出行开始日期" prop="travelStartTime" :rules="requiredRules" required>
|
||||||
<el-date-picker
|
<el-date-picker
|
||||||
v-model="directRelativeForm.travelStartTime"
|
v-model="directRelativeForm.travelStartTime"
|
||||||
type="date"
|
type="date"
|
||||||
@@ -257,7 +257,7 @@ layout("/layouts/platform.html"){
|
|||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="8">
|
<el-col :span="8">
|
||||||
<el-form-item label="出行结束日期">
|
<el-form-item label="出行结束日期" prop="travelEndTime" :rules="requiredRules" required>
|
||||||
<el-date-picker
|
<el-date-picker
|
||||||
v-model="directRelativeForm.travelEndTime"
|
v-model="directRelativeForm.travelEndTime"
|
||||||
type="date"
|
type="date"
|
||||||
@@ -276,34 +276,48 @@ layout("/layouts/platform.html"){
|
|||||||
<div class="tour-signup-actions">
|
<div class="tour-signup-actions">
|
||||||
<el-button size="medium" type="primary" icon="el-icon-plus" :disabled="!signupForm.hasFamily" @click="addFamily">增加一条</el-button>
|
<el-button size="medium" type="primary" icon="el-icon-plus" :disabled="!signupForm.hasFamily" @click="addFamily">增加一条</el-button>
|
||||||
</div>
|
</div>
|
||||||
<el-table :data="familyData" border :size="tableSize" empty-text="暂无亲属信息">
|
<el-form :model="{ rows: familyData }" ref="familyForm" label-width="0">
|
||||||
|
<el-table class="tour-family-table" :data="familyData" border :size="tableSize" empty-text="暂无亲属信息">
|
||||||
<el-table-column label="序号" type="index" width="70" align="center" header-align="center"></el-table-column>
|
<el-table-column label="序号" type="index" width="70" align="center" header-align="center"></el-table-column>
|
||||||
<el-table-column label="家属姓名" min-width="130" align="center" header-align="center">
|
<el-table-column label="家属姓名" min-width="130" align="center" header-align="center">
|
||||||
<template slot-scope="{row}">
|
<template slot="header"><span style="color: #f56c6c">*</span> 家属姓名</template>
|
||||||
|
<template slot-scope="{row, $index}">
|
||||||
|
<el-form-item :prop="'rows.' + $index + '.familyName'" :rules="requiredRules">
|
||||||
<el-input v-model="row.familyName" maxlength="100" placeholder="请输入"></el-input>
|
<el-input v-model="row.familyName" maxlength="100" placeholder="请输入"></el-input>
|
||||||
|
</el-form-item>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column label="性别" width="110" align="center" header-align="center">
|
<el-table-column label="性别" width="110" align="center" header-align="center">
|
||||||
<template slot-scope="{row}">
|
<template slot="header"><span style="color: #f56c6c">*</span> 性别</template>
|
||||||
|
<template slot-scope="{row, $index}">
|
||||||
|
<el-form-item :prop="'rows.' + $index + '.gender'" :rules="requiredRules">
|
||||||
<el-select v-model="row.gender" clearable placeholder="请选择">
|
<el-select v-model="row.gender" clearable placeholder="请选择">
|
||||||
<el-option label="男" value="男"></el-option>
|
<el-option label="男" value="男"></el-option>
|
||||||
<el-option label="女" value="女"></el-option>
|
<el-option label="女" value="女"></el-option>
|
||||||
</el-select>
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column label="身份证号码" min-width="180" align="center" header-align="center">
|
<el-table-column label="身份证号码" min-width="180" align="center" header-align="center">
|
||||||
<template slot-scope="{row}">
|
<template slot-scope="{row, $index}">
|
||||||
|
<el-form-item :prop="'rows.' + $index + '.idCard'" :rules="[{ required: familyContactRequired(row), validator: validateFamilyIdCard, trigger: ['blur', 'change'] }]">
|
||||||
<el-input v-model="row.idCard" maxlength="18" :placeholder="familyContactRequired(row) ? '16岁及以上必填' : '选填'" @blur="normalizeFamilyIdCard(row)"></el-input>
|
<el-input v-model="row.idCard" maxlength="18" :placeholder="familyContactRequired(row) ? '16岁及以上必填' : '选填'" @blur="normalizeFamilyIdCard(row)"></el-input>
|
||||||
|
</el-form-item>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column label="手机号" min-width="150" align="center" header-align="center">
|
<el-table-column label="手机号" min-width="150" align="center" header-align="center">
|
||||||
<template slot-scope="{row}">
|
<template slot-scope="{row, $index}">
|
||||||
|
<el-form-item :prop="'rows.' + $index + '.mobile'" :rules="[{ required: familyContactRequired(row), message: '必填', trigger: ['blur', 'change'] }]">
|
||||||
<el-input v-model="row.mobile" maxlength="30" :placeholder="familyContactRequired(row) ? '16岁及以上必填' : '选填'"></el-input>
|
<el-input v-model="row.mobile" maxlength="30" :placeholder="familyContactRequired(row) ? '16岁及以上必填' : '选填'"></el-input>
|
||||||
|
</el-form-item>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column label="年龄" width="110" align="center" header-align="center">
|
<el-table-column label="年龄" width="110" align="center" header-align="center">
|
||||||
<template slot-scope="{row}">
|
<template slot="header"><span style="color: #f56c6c">*</span> 年龄</template>
|
||||||
|
<template slot-scope="{row, $index}">
|
||||||
|
<el-form-item :prop="'rows.' + $index + '.age'" :rules="requiredRules">
|
||||||
<el-input-number v-model="row.age" :min="0" :max="120" :precision="0" controls-position="right" style="width: 100%"></el-input-number>
|
<el-input-number v-model="row.age" :min="0" :max="120" :precision="0" controls-position="right" style="width: 100%"></el-input-number>
|
||||||
|
</el-form-item>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column v-if="fillBedInfo" label="床型" min-width="120" align="center" header-align="center">
|
<el-table-column v-if="fillBedInfo" label="床型" min-width="120" align="center" header-align="center">
|
||||||
@@ -336,10 +350,13 @@ layout("/layouts/platform.html"){
|
|||||||
</el-table-column>
|
</el-table-column>
|
||||||
-->
|
-->
|
||||||
<el-table-column label="关系" width="120" align="center" header-align="center">
|
<el-table-column label="关系" width="120" align="center" header-align="center">
|
||||||
<template slot-scope="{row}">
|
<template slot="header"><span style="color: #f56c6c">*</span> 关系</template>
|
||||||
|
<template slot-scope="{row, $index}">
|
||||||
|
<el-form-item :prop="'rows.' + $index + '.relationship'" :rules="requiredRules">
|
||||||
<el-select v-model="row.relationship" clearable placeholder="请选择">
|
<el-select v-model="row.relationship" clearable placeholder="请选择">
|
||||||
<el-option v-for="item in familyRelationshipOptions" :key="item.code" :label="item.name" :value="item.name"></el-option>
|
<el-option v-for="item in familyRelationshipOptions" :key="item.code" :label="item.name" :value="item.name"></el-option>
|
||||||
</el-select>
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column label="操作" width="90" align="center" header-align="center" fixed="right">
|
<el-table-column label="操作" width="90" align="center" header-align="center" fixed="right">
|
||||||
@@ -348,6 +365,8 @@ layout("/layouts/platform.html"){
|
|||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
</el-table>
|
</el-table>
|
||||||
|
<div v-if="familyValidationAttempted && familyData.length === 0" class="el-form-item__error" style="position: static">必填</div>
|
||||||
|
</el-form>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<span slot="footer" class="dialog-footer">
|
<span slot="footer" class="dialog-footer">
|
||||||
@@ -389,6 +408,10 @@ layout("/layouts/platform.html"){
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
|
/* 覆盖全局表格 div 文字颜色,保留输入组件下方校验提示的红色。 */
|
||||||
|
.tour-family-table.el-table td.el-table__cell .el-form-item__error {
|
||||||
|
color: #f56c6c;
|
||||||
|
}
|
||||||
.tour-signup-title {
|
.tour-signup-title {
|
||||||
border-left: 4px solid #0079c2;
|
border-left: 4px solid #0079c2;
|
||||||
color: #0079c2;
|
color: #0079c2;
|
||||||
@@ -489,6 +512,12 @@ layout("/layouts/platform.html"){
|
|||||||
fillBedInfo: true,
|
fillBedInfo: true,
|
||||||
signupForm: {},
|
signupForm: {},
|
||||||
familyData: [],
|
familyData: [],
|
||||||
|
familyValidationAttempted: false,
|
||||||
|
requiredRules: [{ required: true, message: "必填", trigger: ["blur", "change"] }],
|
||||||
|
mobileRules: [
|
||||||
|
{ required: true, message: "必填", trigger: ["blur", "change"] },
|
||||||
|
{ pattern: /^1[3-9]\d{9}$/, message: "请输入正确的11位手机号", trigger: ["blur", "change"] }
|
||||||
|
],
|
||||||
bedTypeOptions: [],
|
bedTypeOptions: [],
|
||||||
familyRelationshipOptions: [],
|
familyRelationshipOptions: [],
|
||||||
directRelativeOptions: [],
|
directRelativeOptions: [],
|
||||||
@@ -791,6 +820,11 @@ layout("/layouts/platform.html"){
|
|||||||
this.signupForm.hasFamily = true
|
this.signupForm.hasFamily = true
|
||||||
}
|
}
|
||||||
this.signupVisible = true
|
this.signupVisible = true
|
||||||
|
this.$nextTick(() => {
|
||||||
|
;[this.$refs.signupForm, this.$refs.directRelativeForm, this.$refs.familyForm].forEach(form => {
|
||||||
|
if (form) form.clearValidate()
|
||||||
|
})
|
||||||
|
})
|
||||||
} else {
|
} else {
|
||||||
this.$message.warning(res.msg || "查询失败")
|
this.$message.warning(res.msg || "查询失败")
|
||||||
}
|
}
|
||||||
@@ -847,29 +881,22 @@ layout("/layouts/platform.html"){
|
|||||||
this.signupForm.hasFamily = false
|
this.signupForm.hasFamily = false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
// 家属表格按行校验,缺失项显示在对应输入组件下方。
|
||||||
validateFamilies() {
|
validateFamilies() {
|
||||||
if (!this.allowFamily || !this.signupForm.hasFamily) return true
|
if (!this.allowFamily || !this.signupForm.hasFamily) return true
|
||||||
if (this.familyData.length === 0) {
|
this.familyValidationAttempted = true
|
||||||
this.$message.warning("请添加亲属信息")
|
if (this.familyData.length === 0) return false
|
||||||
return false
|
return new Promise(resolve => this.$refs.familyForm.validate(valid => resolve(valid)))
|
||||||
|
},
|
||||||
|
// 未满16岁的家属允许不填身份证,已填写时仍检查格式。
|
||||||
|
validateFamilyIdCard(rule, value, callback) {
|
||||||
|
if (!value) {
|
||||||
|
callback(rule.required ? new Error("必填") : undefined)
|
||||||
|
} else if (!this.isValidIdCard(value)) {
|
||||||
|
callback(new Error("请输入正确的身份证号码"))
|
||||||
|
} else {
|
||||||
|
callback()
|
||||||
}
|
}
|
||||||
const invalidBase = this.familyData.some(item => !item.familyName || item.age === null || item.age === undefined
|
|
||||||
|| !item.gender || !item.relationship)
|
|
||||||
if (invalidBase) {
|
|
||||||
this.$message.warning("请完善亲属姓名、年龄、性别和与本人关系")
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
const invalidContact = this.familyData.some(item => this.familyContactRequired(item) && (!item.idCard || !item.mobile))
|
|
||||||
if (invalidContact) {
|
|
||||||
this.$message.warning("年满16周岁的亲属必须填写身份证号码和手机号")
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
const invalidIdCard = this.familyData.some(item => item.idCard && !this.isValidIdCard(item.idCard))
|
|
||||||
if (invalidIdCard) {
|
|
||||||
this.$message.warning("请输入正确的身份证号码")
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
},
|
},
|
||||||
familyContactRequired(family) {
|
familyContactRequired(family) {
|
||||||
return family && family.age !== null && family.age !== undefined && Number(family.age) >= 16
|
return family && family.age !== null && family.age !== undefined && Number(family.age) >= 16
|
||||||
@@ -885,39 +912,17 @@ layout("/layouts/platform.html"){
|
|||||||
},
|
},
|
||||||
validateDirectRelative() {
|
validateDirectRelative() {
|
||||||
if (!this.isDirectFamilyLine(this.signupForm)) return true
|
if (!this.isDirectFamilyLine(this.signupForm)) return true
|
||||||
if (!this.directRelativeForm.relativeName) {
|
return new Promise(resolve => this.$refs.directRelativeForm.validate(valid => resolve(valid)))
|
||||||
this.$message.warning("请输入亲属姓名")
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
if (!this.directRelativeForm.unitName) {
|
|
||||||
this.$message.warning("请输入亲属所在单位")
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
if (!this.directRelativeForm.relationshipCode) {
|
|
||||||
this.$message.warning("请选择亲属关系")
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
if (!this.directRelativeForm.lineName) {
|
|
||||||
this.$message.warning("请输入直系亲属线路名称")
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
if (!this.directRelativeForm.travelStartTime) {
|
|
||||||
this.$message.warning("请选择出行开始日期")
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
if (!this.directRelativeForm.travelEndTime) {
|
|
||||||
this.$message.warning("请选择出行结束日期")
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
},
|
},
|
||||||
submitSignup() {
|
async submitSignup() {
|
||||||
if (!this.signupForm.idCard || !this.signupForm.mobile) {
|
if (this.signupLoading) return
|
||||||
this.$message.warning("请完善报名人身份证号码和手机号")
|
// 同时校验各区域,一次展示所有字段错误,通过后才提交报名。
|
||||||
return
|
const results = await Promise.all([
|
||||||
}
|
new Promise(resolve => this.$refs.signupForm.validate(valid => resolve(valid))),
|
||||||
if (!this.validateFamilies()) return
|
this.validateFamilies(),
|
||||||
if (!this.validateDirectRelative()) return
|
this.validateDirectRelative()
|
||||||
|
])
|
||||||
|
if (results.some(valid => !valid)) return
|
||||||
const families = this.allowFamily && this.signupForm.hasFamily ? this.familyData : []
|
const families = this.allowFamily && this.signupForm.hasFamily ? this.familyData : []
|
||||||
const form = Object.assign({}, this.signupForm, {
|
const form = Object.assign({}, this.signupForm, {
|
||||||
families: JSON.stringify(families),
|
families: JSON.stringify(families),
|
||||||
@@ -966,6 +971,7 @@ layout("/layouts/platform.html"){
|
|||||||
}).catch(() => {})
|
}).catch(() => {})
|
||||||
},
|
},
|
||||||
destroySignup() {
|
destroySignup() {
|
||||||
|
this.familyValidationAttempted = false
|
||||||
this.signupForm = {}
|
this.signupForm = {}
|
||||||
this.familyData = []
|
this.familyData = []
|
||||||
this.directRelativeForm = {}
|
this.directRelativeForm = {}
|
||||||
|
|||||||
@@ -138,14 +138,14 @@ layout("/layouts/platform.html"){
|
|||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="12">
|
<el-col :span="12">
|
||||||
<el-form-item label="联系人手机" prop="contactPhone">
|
<el-form-item label="联系人手机" prop="contactPhone" required>
|
||||||
<el-input v-model="formData.contactPhone" maxlength="30" placeholder="请输入联系人手机"></el-input>
|
<el-input v-model="formData.contactPhone" maxlength="30" placeholder="请输入联系人手机"></el-input>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
</el-col>
|
||||||
</el-row>
|
</el-row>
|
||||||
<el-row :gutter="20">
|
<el-row :gutter="20">
|
||||||
<el-col :span="12">
|
<el-col :span="12">
|
||||||
<el-form-item label="邮箱" prop="email">
|
<el-form-item label="邮箱" prop="email" required>
|
||||||
<el-input v-model="formData.email" maxlength="100" placeholder="请输入邮箱"></el-input>
|
<el-input v-model="formData.email" maxlength="100" placeholder="请输入邮箱"></el-input>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
</el-col>
|
||||||
@@ -221,8 +221,8 @@ layout("/layouts/platform.html"){
|
|||||||
agencyName: [{ required: true, message: "必填", trigger: ["blur", "change"] }],
|
agencyName: [{ required: true, message: "必填", trigger: ["blur", "change"] }],
|
||||||
agencyCode: [{ required: true, message: "必填", trigger: ["blur", "change"] }],
|
agencyCode: [{ required: true, message: "必填", trigger: ["blur", "change"] }],
|
||||||
contactName: [{ required: true, message: "必填", trigger: ["blur", "change"] }],
|
contactName: [{ required: true, message: "必填", trigger: ["blur", "change"] }],
|
||||||
contactPhone: [{ validator: validateMobile, trigger: ["blur", "change"] }],
|
contactPhone: [{ required: true, validator: validateMobile, trigger: ["blur", "change"] }],
|
||||||
email: [{ validator: validateEmail, trigger: ["blur", "change"] }]
|
email: [{ required: true, validator: validateEmail, trigger: ["blur", "change"] }]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -41,6 +41,30 @@ layout("/layouts/platform.html"){
|
|||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.qsv-online-answer-header {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
gap: 16px;
|
||||||
|
padding-right: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.qsv-online-quiz-timer {
|
||||||
|
flex-shrink: 0;
|
||||||
|
color: #e6a23c;
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
|
||||||
|
.qsv-online-description {
|
||||||
|
line-height: 1.8;
|
||||||
|
overflow-wrap: break-word;
|
||||||
|
}
|
||||||
|
|
||||||
|
.qsv-online-description img {
|
||||||
|
max-width: 100%;
|
||||||
|
height: auto;
|
||||||
|
}
|
||||||
|
|
||||||
.qsv-online-preview-title {
|
.qsv-online-preview-title {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
font-size: 18px;
|
font-size: 18px;
|
||||||
@@ -90,6 +114,33 @@ layout("/layouts/platform.html"){
|
|||||||
min-width: 72px;
|
min-width: 72px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.qsv-online-result-score {
|
||||||
|
color: #409eff;
|
||||||
|
font-size: 28px;
|
||||||
|
font-weight: 700;
|
||||||
|
}
|
||||||
|
|
||||||
|
.qsv-online-result-tags {
|
||||||
|
margin-bottom: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.qsv-online-result-option {
|
||||||
|
color: #303133;
|
||||||
|
}
|
||||||
|
|
||||||
|
.qsv-online-result-option.is-correct {
|
||||||
|
color: #67c23a;
|
||||||
|
}
|
||||||
|
|
||||||
|
.qsv-online-subject-result {
|
||||||
|
margin-top: 12px;
|
||||||
|
color: #f56c6c;
|
||||||
|
}
|
||||||
|
|
||||||
|
.qsv-online-subject-result.is-correct {
|
||||||
|
color: #67c23a;
|
||||||
|
}
|
||||||
|
|
||||||
.qsv-online-option-fill {
|
.qsv-online-option-fill {
|
||||||
width: 520px;
|
width: 520px;
|
||||||
max-width: 100%;
|
max-width: 100%;
|
||||||
@@ -495,8 +546,22 @@ layout("/layouts/platform.html"){
|
|||||||
size="1145px"
|
size="1145px"
|
||||||
custom-class="qsv-online-drawer"
|
custom-class="qsv-online-drawer"
|
||||||
append-to-body
|
append-to-body
|
||||||
@closed="stopVoteCountdown">
|
@close="stopAnswerTimers">
|
||||||
|
<div slot="title" class="qsv-online-answer-header">
|
||||||
|
<span>{{answerDialog.title}}</span>
|
||||||
|
<span v-if="answerDialog.activity.category === 'QUIZ' && answerDialog.activity.timeLimit > 0 && !answerDialog.readonly" class="qsv-online-quiz-timer">
|
||||||
|
<i class="el-icon-time"></i> 剩余时间:{{quizRemainingText}}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
<div class="qsv-online-preview-body" v-loading="answerDialog.loading">
|
<div class="qsv-online-preview-body" v-loading="answerDialog.loading">
|
||||||
|
<div v-if="answerDialog.activity.description" class="qsv-online-subject">
|
||||||
|
<div class="qsv-online-subject-title">说明</div>
|
||||||
|
<div class="qsv-online-description" v-html="answerDialog.activity.description"></div>
|
||||||
|
</div>
|
||||||
|
<div v-if="showQuizResult" class="qsv-online-subject">
|
||||||
|
<div class="qsv-online-subject-title">{{answerDialog.activity.title}}</div>
|
||||||
|
<div class="qsv-online-result-score">总分:{{quizTotalScore}} 分</div>
|
||||||
|
</div>
|
||||||
<div v-if="isVoteActivity" class="qsv-online-vote">
|
<div v-if="isVoteActivity" class="qsv-online-vote">
|
||||||
<div class="qsv-online-vote-header">
|
<div class="qsv-online-vote-header">
|
||||||
<h2 class="qsv-online-vote-title">{{answerDialog.activity.title}}</h2>
|
<h2 class="qsv-online-vote-title">{{answerDialog.activity.title}}</h2>
|
||||||
@@ -573,6 +638,11 @@ layout("/layouts/platform.html"){
|
|||||||
</div>
|
</div>
|
||||||
<el-empty v-if="!isVoteActivity && visibleSubjects.length === 0 && !answerDialog.loading" description="暂无题目"></el-empty>
|
<el-empty v-if="!isVoteActivity && visibleSubjects.length === 0 && !answerDialog.loading" description="暂无题目"></el-empty>
|
||||||
<div v-if="!isVoteActivity" v-for="(subject, index) in visibleSubjects" :key="subject.id" class="qsv-online-subject">
|
<div v-if="!isVoteActivity" v-for="(subject, index) in visibleSubjects" :key="subject.id" class="qsv-online-subject">
|
||||||
|
<div v-if="showQuizResult" class="qsv-online-result-tags">
|
||||||
|
<el-tag v-if="subject.type === 'radio'" size="small">单选</el-tag>
|
||||||
|
<el-tag v-else-if="subject.type === 'checkbox'" size="small">多选</el-tag>
|
||||||
|
<el-tag v-if="subject.score !== undefined && subject.score !== null" size="small">{{subject.score}}分</el-tag>
|
||||||
|
</div>
|
||||||
<div class="qsv-online-subject-title">
|
<div class="qsv-online-subject-title">
|
||||||
<span v-if="answerDialog.showIndex" class="qsv-online-subject-index">{{index + 1}}.</span>
|
<span v-if="answerDialog.showIndex" class="qsv-online-subject-index">{{index + 1}}.</span>
|
||||||
<span>{{subject.title}}</span>
|
<span>{{subject.title}}</span>
|
||||||
@@ -585,7 +655,7 @@ layout("/layouts/platform.html"){
|
|||||||
:value="getRadioValue(subject)"
|
:value="getRadioValue(subject)"
|
||||||
@input="setRadioValue(subject, $event)">
|
@input="setRadioValue(subject, $event)">
|
||||||
<template v-for="option in subject.options">
|
<template v-for="option in subject.options">
|
||||||
<el-radio :key="option.id" :label="option.id">{{option.text}}</el-radio>
|
<el-radio :key="option.id" :label="option.id"><span :class="{ 'qsv-online-result-option': showQuizResult, 'is-correct': showQuizResult && option.isCorrect }">{{option.text}}<span v-if="showQuizResult && option.isCorrect">(正确答案)</span></span></el-radio>
|
||||||
<el-input
|
<el-input
|
||||||
v-if="isOptionFillVisible(subject, option)"
|
v-if="isOptionFillVisible(subject, option)"
|
||||||
:key="option.id + '-fill'"
|
:key="option.id + '-fill'"
|
||||||
@@ -604,7 +674,7 @@ layout("/layouts/platform.html"){
|
|||||||
:disabled="answerDialog.readonly"
|
:disabled="answerDialog.readonly"
|
||||||
@change="onCheckboxChange(subject)">
|
@change="onCheckboxChange(subject)">
|
||||||
<template v-for="option in subject.options">
|
<template v-for="option in subject.options">
|
||||||
<el-checkbox :key="option.id" :label="option.id">{{option.text}}</el-checkbox>
|
<el-checkbox :key="option.id" :label="option.id"><span :class="{ 'qsv-online-result-option': showQuizResult, 'is-correct': showQuizResult && option.isCorrect }">{{option.text}}<span v-if="showQuizResult && option.isCorrect">(正确答案)</span></span></el-checkbox>
|
||||||
<el-input
|
<el-input
|
||||||
v-if="isOptionFillVisible(subject, option)"
|
v-if="isOptionFillVisible(subject, option)"
|
||||||
:key="option.id + '-fill'"
|
:key="option.id + '-fill'"
|
||||||
@@ -623,6 +693,10 @@ layout("/layouts/platform.html"){
|
|||||||
:readonly="answerDialog.readonly"
|
:readonly="answerDialog.readonly"
|
||||||
v-model="subject.userFillContent"
|
v-model="subject.userFillContent"
|
||||||
:placeholder="'请输入' + subject.title"></el-input>
|
:placeholder="'请输入' + subject.title"></el-input>
|
||||||
|
<div v-if="showQuizResult && getSubjectResult(subject)" class="qsv-online-subject-result" :class="{ 'is-correct': getSubjectResult(subject).isCorrect }">
|
||||||
|
<i :class="getSubjectResult(subject).isCorrect ? 'el-icon-circle-check' : 'el-icon-circle-close'"></i>
|
||||||
|
{{getSubjectResult(subject).isCorrect ? '回答正确' : '回答错误'}},得分:{{getSubjectResult(subject).score || 0}} 分
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="qsv-online-footer">
|
<div class="qsv-online-footer">
|
||||||
@@ -709,6 +783,10 @@ layout("/layouts/platform.html"){
|
|||||||
minutes: 0,
|
minutes: 0,
|
||||||
seconds: 0
|
seconds: 0
|
||||||
},
|
},
|
||||||
|
quizTimer: null,
|
||||||
|
quizStartedAt: 0,
|
||||||
|
quizElapsedSeconds: 0,
|
||||||
|
quizExpired: false,
|
||||||
voteTimer: null,
|
voteTimer: null,
|
||||||
voteRankVisible: false,
|
voteRankVisible: false,
|
||||||
voteDetailVisible: false,
|
voteDetailVisible: false,
|
||||||
@@ -717,6 +795,21 @@ layout("/layouts/platform.html"){
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
|
// 仅已完成的计分答题显示成绩和正确答案,普通调查与投票保持原有展示。
|
||||||
|
showQuizResult() {
|
||||||
|
return this.answerDialog.activity.category === "QUIZ" && !!this.answerDialog.answerRecord.isFinish
|
||||||
|
},
|
||||||
|
quizRemainingSeconds() {
|
||||||
|
return Math.max(0, Number(this.answerDialog.activity.timeLimit || 0) * 60 - this.answerDialog.quizElapsedSeconds)
|
||||||
|
},
|
||||||
|
quizRemainingText() {
|
||||||
|
const seconds = this.quizRemainingSeconds
|
||||||
|
return Math.floor(seconds / 60) + '分' + String(seconds % 60).padStart(2, '0') + '秒'
|
||||||
|
},
|
||||||
|
quizTotalScore() {
|
||||||
|
const answers = this.answerDialog.answerRecord.extJson || {}
|
||||||
|
return Object.keys(answers).reduce((total, id) => total + Number(answers[id].score || 0), 0)
|
||||||
|
},
|
||||||
visibleSubjects() {
|
visibleSubjects() {
|
||||||
return this.answerDialog.subjects.filter((subject) => {
|
return this.answerDialog.subjects.filter((subject) => {
|
||||||
return this.isSubjectVisible(subject)
|
return this.isSubjectVisible(subject)
|
||||||
@@ -862,6 +955,10 @@ layout("/layouts/platform.html"){
|
|||||||
this.$message.warning(unavailableMessage)
|
this.$message.warning(unavailableMessage)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
this.stopAnswerTimers()
|
||||||
|
this.answerDialog.quizStartedAt = 0
|
||||||
|
this.answerDialog.quizElapsedSeconds = 0
|
||||||
|
this.answerDialog.quizExpired = false
|
||||||
this.answerDialog.visible = true
|
this.answerDialog.visible = true
|
||||||
this.answerDialog.loading = true
|
this.answerDialog.loading = true
|
||||||
this.answerDialog.readonly = row.actionType === "view"
|
this.answerDialog.readonly = row.actionType === "view"
|
||||||
@@ -908,6 +1005,7 @@ layout("/layouts/platform.html"){
|
|||||||
this.answerDialog.answerRecord = res.data || {}
|
this.answerDialog.answerRecord = res.data || {}
|
||||||
this.answerDialog.readonly = !!this.answerDialog.answerRecord.isFinish
|
this.answerDialog.readonly = !!this.answerDialog.answerRecord.isFinish
|
||||||
this.initAnswer()
|
this.initAnswer()
|
||||||
|
this.startQuizTimer()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
@@ -928,6 +1026,10 @@ layout("/layouts/platform.html"){
|
|||||||
this.clearHiddenSubjectAnswers()
|
this.clearHiddenSubjectAnswers()
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
getSubjectResult(subject) {
|
||||||
|
const answers = this.answerDialog.answerRecord.extJson || {}
|
||||||
|
return answers[subject.id]
|
||||||
|
},
|
||||||
getRadioValue(subject) {
|
getRadioValue(subject) {
|
||||||
return subject.userSelectOptionIds && subject.userSelectOptionIds.length > 0
|
return subject.userSelectOptionIds && subject.userSelectOptionIds.length > 0
|
||||||
? subject.userSelectOptionIds[0]
|
? subject.userSelectOptionIds[0]
|
||||||
@@ -985,6 +1087,43 @@ layout("/layouts/platform.html"){
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
// 使用实际经过时间计时,避免切换浏览器标签后定时器节流导致倒计时变慢。
|
||||||
|
startQuizTimer() {
|
||||||
|
this.stopQuizTimer()
|
||||||
|
if (!this.answerDialog.visible || this.answerDialog.readonly || this.answerDialog.activity.category !== "QUIZ") return
|
||||||
|
this.answerDialog.quizStartedAt = Date.now()
|
||||||
|
this.answerDialog.quizElapsedSeconds = 0
|
||||||
|
this.answerDialog.quizExpired = false
|
||||||
|
this.answerDialog.quizTimer = setInterval(() => this.updateQuizTimer(), 1000)
|
||||||
|
},
|
||||||
|
updateQuizTimer() {
|
||||||
|
if (!this.answerDialog.quizStartedAt || this.answerDialog.readonly || !this.answerDialog.visible) return
|
||||||
|
this.answerDialog.quizElapsedSeconds = Math.floor((Date.now() - this.answerDialog.quizStartedAt) / 1000)
|
||||||
|
if (Number(this.answerDialog.activity.timeLimit) > 0 && this.quizRemainingSeconds === 0
|
||||||
|
&& !this.answerDialog.quizExpired && !this.answerDialog.submitLoading) {
|
||||||
|
this.answerDialog.quizExpired = true
|
||||||
|
this.stopQuizTimer()
|
||||||
|
// 与手机端一致:超时提示重新答题,不自动提交未完成的答卷。
|
||||||
|
this.$alert("答题时间到,请重新进入答题", "提示", {
|
||||||
|
confirmButtonText: "确定",
|
||||||
|
showClose: false,
|
||||||
|
closeOnClickModal: false,
|
||||||
|
closeOnPressEscape: false
|
||||||
|
}).then(() => {
|
||||||
|
this.answerDialog.visible = false
|
||||||
|
})
|
||||||
|
}
|
||||||
|
},
|
||||||
|
stopQuizTimer() {
|
||||||
|
if (this.answerDialog.quizTimer) {
|
||||||
|
clearInterval(this.answerDialog.quizTimer)
|
||||||
|
this.answerDialog.quizTimer = null
|
||||||
|
}
|
||||||
|
},
|
||||||
|
stopAnswerTimers() {
|
||||||
|
this.stopQuizTimer()
|
||||||
|
this.stopVoteCountdown()
|
||||||
|
},
|
||||||
startVoteCountdown() {
|
startVoteCountdown() {
|
||||||
this.stopVoteCountdown()
|
this.stopVoteCountdown()
|
||||||
this.updateVoteCountdown()
|
this.updateVoteCountdown()
|
||||||
@@ -1196,6 +1335,8 @@ layout("/layouts/platform.html"){
|
|||||||
return true
|
return true
|
||||||
},
|
},
|
||||||
submitAnswer() {
|
submitAnswer() {
|
||||||
|
this.updateQuizTimer()
|
||||||
|
if (this.answerDialog.readonly || this.answerDialog.quizExpired || this.answerDialog.submitLoading) return
|
||||||
if (!this.validateAnswer()) {
|
if (!this.validateAnswer()) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -1204,11 +1345,14 @@ layout("/layouts/platform.html"){
|
|||||||
cancelButtonText: "取消",
|
cancelButtonText: "取消",
|
||||||
type: "warning"
|
type: "warning"
|
||||||
}).then(() => {
|
}).then(() => {
|
||||||
|
this.updateQuizTimer()
|
||||||
|
if (!this.answerDialog.visible || this.answerDialog.readonly || this.answerDialog.quizExpired || this.answerDialog.submitLoading) return
|
||||||
this.answerDialog.submitLoading = true
|
this.answerDialog.submitLoading = true
|
||||||
$.post("/platform/qsv/online/submitAnswer", {
|
$.post("/platform/qsv/online/submitAnswer", {
|
||||||
answer: JSON.stringify({
|
answer: JSON.stringify({
|
||||||
activityId: this.answerDialog.activity.id,
|
activityId: this.answerDialog.activity.id,
|
||||||
answerRecordId: this.answerDialog.answerRecordId,
|
answerRecordId: this.answerDialog.answerRecordId,
|
||||||
|
answerTime: this.answerDialog.quizElapsedSeconds,
|
||||||
subjects: this.submitSubjects.map((subject) => {
|
subjects: this.submitSubjects.map((subject) => {
|
||||||
return {
|
return {
|
||||||
id: subject.id,
|
id: subject.id,
|
||||||
@@ -1221,7 +1365,14 @@ layout("/layouts/platform.html"){
|
|||||||
}).then((res) => {
|
}).then((res) => {
|
||||||
if (res.code === 0) {
|
if (res.code === 0) {
|
||||||
this.$message.success(res.msg)
|
this.$message.success(res.msg)
|
||||||
this.answerDialog.visible = false
|
if (this.answerDialog.activity.category === "QUIZ") {
|
||||||
|
// 提交后读取服务端判题结果,直接展示成绩并防止重复提交。
|
||||||
|
this.answerDialog.readonly = true
|
||||||
|
this.stopQuizTimer()
|
||||||
|
this.loadAnswerRecord()
|
||||||
|
} else {
|
||||||
|
this.answerDialog.visible = false
|
||||||
|
}
|
||||||
this.pageData()
|
this.pageData()
|
||||||
} else {
|
} else {
|
||||||
this.$message.error(res.msg)
|
this.$message.error(res.msg)
|
||||||
@@ -1237,7 +1388,7 @@ layout("/layouts/platform.html"){
|
|||||||
this.openAnswerFromUrl()
|
this.openAnswerFromUrl()
|
||||||
},
|
},
|
||||||
beforeDestroy() {
|
beforeDestroy() {
|
||||||
this.stopVoteCountdown()
|
this.stopAnswerTimers()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -76,8 +76,7 @@ layout("/layouts/platform.html"){
|
|||||||
<el-button v-if="row.canRevoke" size="mini" type="danger" @click="openRevoke(row)">
|
<el-button v-if="row.canRevoke" size="mini" type="danger" @click="openRevoke(row)">
|
||||||
撤回
|
撤回
|
||||||
</el-button>
|
</el-button>
|
||||||
<!-- v-if="row.taskKey === 'startTask' || !row.instanceId"-->
|
<el-button v-if="row.taskKey === 'startTask' || !row.instanceId" size="mini" type="danger" @click="del(row.id)">
|
||||||
<el-button size="mini" type="danger" @click="del(row.id)">
|
|
||||||
删除
|
删除
|
||||||
</el-button>
|
</el-button>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@@ -62,13 +62,7 @@ layout("/layouts/platform.html"){
|
|||||||
<el-button @click="onView(row)" size="mini" type="primary">查看</el-button>
|
<el-button @click="onView(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.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.canRevoke" size="mini" type="danger" @click="onRevoke(row)">撤回</el-button>
|
||||||
<el-dropdown v-if="row.createdBy === $store.state.user.id && row.instanceState == 20" trigger="click" @command="format => doExportApply(row, format)">
|
<el-button v-if="row.createdBy === $store.state.user.id && row.instanceState == 20" @click="doExportApply(row)" size="mini" type="primary">导出</el-button>
|
||||||
<el-button size="mini" type="primary">导出</el-button>
|
|
||||||
<el-dropdown-menu slot="dropdown">
|
|
||||||
<el-dropdown-item command="pdf">导出 PDF</el-dropdown-item>
|
|
||||||
<el-dropdown-item command="word">导出 Word</el-dropdown-item>
|
|
||||||
</el-dropdown-menu>
|
|
||||||
</el-dropdown>
|
|
||||||
<el-button v-if="row.taskKey === 'startTask' || !row.instanceId" @click="onDelete(row.id)" size="mini" type="danger">
|
<el-button v-if="row.taskKey === 'startTask' || !row.instanceId" @click="onDelete(row.id)" size="mini" type="danger">
|
||||||
删除
|
删除
|
||||||
</el-button>
|
</el-button>
|
||||||
@@ -109,8 +103,8 @@ layout("/layouts/platform.html"){
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
doExportApply(row, format) {
|
doExportApply(row) {
|
||||||
this.$downLoad('/platform/condolence/mine/doExportApply?id=' + row.id + '&print=' + (format === 'pdf'))
|
this.$downLoad('/platform/condolence/mine/doExportApply?id=' + row.id + '&print=false')
|
||||||
},
|
},
|
||||||
onAdd() {
|
onAdd() {
|
||||||
commonUtil.pjaxPush('/platform/condolence/apply')
|
commonUtil.pjaxPush('/platform/condolence/apply')
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
<!--#
|
<!--#
|
||||||
layout("/layouts/platform.html"){
|
layout("/layouts/platform.html"){
|
||||||
#-->
|
#-->
|
||||||
<div id="app">
|
<div id="app" v-cloak>
|
||||||
<el-card shadow="never" v-if="isShow">
|
<el-card shadow="never" v-if="pageLoading" v-loading="pageLoading" element-loading-text="正在加载申请信息" style="min-height: 300px"></el-card>
|
||||||
|
<el-card shadow="never" v-else-if="isShow">
|
||||||
<snaker-start slot="header" label="困难帮扶申请" define_key="KNBF"></snaker-start>
|
<snaker-start slot="header" label="困难帮扶申请" define_key="KNBF"></snaker-start>
|
||||||
<el-form :model="formData" ref="formRef" :rules="formRules" label-width="0" label-suffix=":" class="flow-task-form">
|
<el-form :model="formData" ref="formRef" :rules="formRules" label-width="0" label-suffix=":" class="flow-task-form">
|
||||||
<el-descriptions :column="3" border>
|
<el-descriptions :column="3" border>
|
||||||
@@ -318,6 +319,7 @@ layout("/layouts/platform.html"){
|
|||||||
bizId: GetQueryString("bizId"),
|
bizId: GetQueryString("bizId"),
|
||||||
taskId: GetQueryString("taskId"),
|
taskId: GetQueryString("taskId"),
|
||||||
isShow: false,
|
isShow: false,
|
||||||
|
pageLoading: true,
|
||||||
time: '',
|
time: '',
|
||||||
blockMessage: '',
|
blockMessage: '',
|
||||||
formData: {
|
formData: {
|
||||||
@@ -453,10 +455,12 @@ layout("/layouts/platform.html"){
|
|||||||
})
|
})
|
||||||
},
|
},
|
||||||
findOne(id) {
|
findOne(id) {
|
||||||
this.$axios.post('/platform/difficultHelp/mine/findOne', { id }).then(res => {
|
return this.$axios.post('/platform/difficultHelp/mine/findOne', { id }).then(res => {
|
||||||
if (res.code === 0) {
|
if (res.code === 0) {
|
||||||
this.formData = res.data
|
this.formData = res.data
|
||||||
this.queryRecipients(res.data.loginName)
|
this.queryRecipients(res.data.loginName)
|
||||||
|
} else {
|
||||||
|
throw new Error(res.msg || '申请信息加载失败,请刷新页面重试')
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
@@ -617,7 +621,7 @@ layout("/layouts/platform.html"){
|
|||||||
return { status: 200, msg: "卡号有效。" };
|
return { status: 200, msg: "卡号有效。" };
|
||||||
},
|
},
|
||||||
async getIsCanPlay() {
|
async getIsCanPlay() {
|
||||||
this.$axios.post('/platform/difficultHelp/apply/getIsCanPlay').then(res => {
|
return this.$axios.post('/platform/difficultHelp/apply/getIsCanPlay').then(res => {
|
||||||
if (res.code === 0) {
|
if (res.code === 0) {
|
||||||
// 新增申请进入页面时,优先校验当前登录人本年度是否已经申请过,已申请则直接拦截新增。
|
// 新增申请进入页面时,优先校验当前登录人本年度是否已经申请过,已申请则直接拦截新增。
|
||||||
if (!this.bizId && res.data.hasCurrentYearApply && !this.$auth.hasRoleOr('BRANCH_UNION_CHAIRMAN')) {
|
if (!this.bizId && res.data.hasCurrentYearApply && !this.$auth.hasRoleOr('BRANCH_UNION_CHAIRMAN')) {
|
||||||
@@ -631,16 +635,25 @@ layout("/layouts/platform.html"){
|
|||||||
if (res.data.applyCount !== null && res.data.applyCount !== undefined && res.data.applyCount !== 0) {
|
if (res.data.applyCount !== null && res.data.applyCount !== undefined && res.data.applyCount !== 0) {
|
||||||
this.$set(this.formData, 'applyCount', res.data.applyCount)
|
this.$set(this.formData, 'applyCount', res.data.applyCount)
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
throw new Error(res.msg || '申请资格加载失败,请刷新页面重试')
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
async created() {
|
async created() {
|
||||||
await this.getIsCanPlay();
|
try {
|
||||||
if (this.bizId) {
|
await this.getIsCanPlay();
|
||||||
this.findOne(this.bizId)
|
if (this.bizId) {
|
||||||
} else {
|
await this.findOne(this.bizId)
|
||||||
this.modeChange("1")
|
} else {
|
||||||
|
this.modeChange("1")
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
this.isShow = false
|
||||||
|
this.blockMessage = error.message || '申请信息加载失败,请刷新页面重试'
|
||||||
|
} finally {
|
||||||
|
this.pageLoading = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|||||||
-14
@@ -1,17 +1,5 @@
|
|||||||
<div id="difficult_help_branch_union_approval_form">
|
<div id="difficult_help_branch_union_approval_form">
|
||||||
<el-form :model="formData" ref="formRef" label-width="100px" label-suffix=":">
|
<el-form :model="formData" ref="formRef" label-width="100px" label-suffix=":">
|
||||||
<el-row :gutter="20">
|
|
||||||
<el-col :span="12">
|
|
||||||
<el-form-item label="级别" prop="level" :rules="[{required:true,message:'请选择级别',trigger:['change','blur']}]">
|
|
||||||
<dict-select v-model="formData.level" code="DIFFICULT_LEVEL" style="width: 100%" placeholder="请选择级别"></dict-select>
|
|
||||||
</el-form-item>
|
|
||||||
</el-col>
|
|
||||||
<el-col :span="12">
|
|
||||||
<el-form-item label="帮扶金额" prop="money" :rules="[{required:true,message:'请填写帮扶金额',trigger:['change','blur']}]">
|
|
||||||
<el-input-number v-model="formData.money" style="width: 100%" :precision="2" :min="0" placeholder="请输入帮扶金额"></el-input-number>
|
|
||||||
</el-form-item>
|
|
||||||
</el-col>
|
|
||||||
</el-row>
|
|
||||||
<el-form-item label="审批意见" prop="tf_opinion" :rules="[{required:true,message:'必填',trigger:['change','blur']}]">
|
<el-form-item label="审批意见" prop="tf_opinion" :rules="[{required:true,message:'必填',trigger:['change','blur']}]">
|
||||||
<user-opinion-textarea v-model="formData.tf_opinion"></user-opinion-textarea>
|
<user-opinion-textarea v-model="formData.tf_opinion"></user-opinion-textarea>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
@@ -29,8 +17,6 @@
|
|||||||
return {
|
return {
|
||||||
businessId: GetQueryString("businessId"),
|
businessId: GetQueryString("businessId"),
|
||||||
formData: {
|
formData: {
|
||||||
level: "",
|
|
||||||
money: undefined,
|
|
||||||
tf_sign: "", tf_opinion: ""
|
tf_sign: "", tf_opinion: ""
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-28
@@ -84,18 +84,6 @@ layout("/layouts/platform.html"){
|
|||||||
|
|
||||||
<el-dialog title="设置帮扶审批信息" :visible.sync="batchVisible" width="760px">
|
<el-dialog title="设置帮扶审批信息" :visible.sync="batchVisible" width="760px">
|
||||||
<el-form :model="batchForm" ref="batchFormRef" label-width="130px">
|
<el-form :model="batchForm" ref="batchFormRef" label-width="130px">
|
||||||
<el-row :gutter="20">
|
|
||||||
<el-col :span="12">
|
|
||||||
<el-form-item label="级别" prop="level" :rules="[{required:true,message:'请选择级别',trigger:['change','blur']}]">
|
|
||||||
<dict-select v-model="batchForm.level" code="DIFFICULT_LEVEL" style="width: 100%" placeholder="请选择级别"></dict-select>
|
|
||||||
</el-form-item>
|
|
||||||
</el-col>
|
|
||||||
<el-col :span="12">
|
|
||||||
<el-form-item label="帮扶金额(元)" prop="money" :rules="[{required:true,message:'请填写帮扶金额',trigger:['change','blur']}]">
|
|
||||||
<el-input-number v-model="batchForm.money" style="width: 100%" :precision="2" :min="0" placeholder="请输入帮扶金额"></el-input-number>
|
|
||||||
</el-form-item>
|
|
||||||
</el-col>
|
|
||||||
</el-row>
|
|
||||||
<el-form-item label="审批意见" prop="tf_opinion" :rules="[{required:true,whitespace:true,message:'请填写审批意见',trigger:['change','blur']}]">
|
<el-form-item label="审批意见" prop="tf_opinion" :rules="[{required:true,whitespace:true,message:'请填写审批意见',trigger:['change','blur']}]">
|
||||||
<user-opinion-textarea v-model="batchForm.tf_opinion"></user-opinion-textarea>
|
<user-opinion-textarea v-model="batchForm.tf_opinion"></user-opinion-textarea>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
@@ -113,18 +101,6 @@ layout("/layouts/platform.html"){
|
|||||||
{{formData.taskName}}
|
{{formData.taskName}}
|
||||||
</div>
|
</div>
|
||||||
<el-form :model="formData" ref="formRef" :rules="formRules" label-width="100px" label-suffix=":">
|
<el-form :model="formData" ref="formRef" :rules="formRules" label-width="100px" label-suffix=":">
|
||||||
<el-row :gutter="20">
|
|
||||||
<el-col :span="12">
|
|
||||||
<el-form-item label="级别" prop="level" :rules="[{required:true,message:'请选择级别',trigger:['change','blur']}]">
|
|
||||||
<dict-select v-model="formData.level" code="DIFFICULT_LEVEL" style="width: 100%" placeholder="请选择级别"></dict-select>
|
|
||||||
</el-form-item>
|
|
||||||
</el-col>
|
|
||||||
<el-col :span="12">
|
|
||||||
<el-form-item label="帮扶金额" prop="money" :rules="[{required:true,message:'请填写帮扶金额',trigger:['change','blur']}]">
|
|
||||||
<el-input-number v-model="formData.money" style="width: 100%" :precision="2" :min="0" placeholder="请输入帮扶金额"></el-input-number>
|
|
||||||
</el-form-item>
|
|
||||||
</el-col>
|
|
||||||
</el-row>
|
|
||||||
<el-form-item label="审批意见" prop="tf_opinion"
|
<el-form-item label="审批意见" prop="tf_opinion"
|
||||||
:rules="[{required:true,message:'必填',trigger:['change','blur']}]">
|
:rules="[{required:true,message:'必填',trigger:['change','blur']}]">
|
||||||
<user-opinion-textarea v-model="formData.tf_opinion"></user-opinion-textarea>
|
<user-opinion-textarea v-model="formData.tf_opinion"></user-opinion-textarea>
|
||||||
@@ -178,7 +154,7 @@ layout("/layouts/platform.html"){
|
|||||||
|
|
||||||
formData: {},
|
formData: {},
|
||||||
batchVisible: false,
|
batchVisible: false,
|
||||||
batchForm: {level: "", money: undefined, tf_sign: "", tf_opinion: ""},
|
batchForm: {tf_sign: "", tf_opinion: ""},
|
||||||
showApprovalForm: false,
|
showApprovalForm: false,
|
||||||
selectData: []
|
selectData: []
|
||||||
}
|
}
|
||||||
@@ -208,7 +184,7 @@ layout("/layouts/platform.html"){
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.batchForm = {level: "", money: undefined, tf_sign: "", tf_opinion: ""}
|
this.batchForm = {tf_sign: "", tf_opinion: ""}
|
||||||
this.batchVisible = true
|
this.batchVisible = true
|
||||||
},
|
},
|
||||||
async submitBatch() {
|
async submitBatch() {
|
||||||
@@ -295,8 +271,6 @@ layout("/layouts/platform.html"){
|
|||||||
this.formData = {
|
this.formData = {
|
||||||
processTaskId: row.taskId,
|
processTaskId: row.taskId,
|
||||||
taskName: row.curTaskName,
|
taskName: row.curTaskName,
|
||||||
level: "",
|
|
||||||
money: undefined,
|
|
||||||
tf_sign: "", tf_opinion: ""
|
tf_sign: "", tf_opinion: ""
|
||||||
}
|
}
|
||||||
this.$refs.infoRef.onOpen(row)
|
this.$refs.infoRef.onOpen(row)
|
||||||
|
|||||||
@@ -72,13 +72,7 @@ layout("/layouts/platform.html"){
|
|||||||
</el-button>
|
</el-button>
|
||||||
<el-button v-if="row.createdBy === $store.state.user.id && row.canRevoke" @click="onRevoke(row)" size="mini" type="danger">撤回
|
<el-button v-if="row.createdBy === $store.state.user.id && row.canRevoke" @click="onRevoke(row)" size="mini" type="danger">撤回
|
||||||
</el-button>
|
</el-button>
|
||||||
<el-dropdown v-if="row.createdBy === $store.state.user.id && row.instanceState == 20" trigger="click" @command="format => doExportApply(row, format)">
|
<el-button v-if="row.createdBy === $store.state.user.id && row.instanceState == 20" @click="doExportApply(row)" size="mini" type="primary">导出</el-button>
|
||||||
<el-button size="mini" type="primary">导出</el-button>
|
|
||||||
<el-dropdown-menu slot="dropdown">
|
|
||||||
<el-dropdown-item command="pdf">导出 PDF</el-dropdown-item>
|
|
||||||
<el-dropdown-item command="word">导出 Word</el-dropdown-item>
|
|
||||||
</el-dropdown-menu>
|
|
||||||
</el-dropdown>
|
|
||||||
<el-button v-if="row.createdBy === $store.state.user.id && (row.taskKey === 'startTask' || !row.instanceId)" @click="onDelete(row.id)" size="mini" type="danger">删除</el-button>
|
<el-button v-if="row.createdBy === $store.state.user.id && (row.taskKey === 'startTask' || !row.instanceId)" @click="onDelete(row.id)" size="mini" type="danger">删除</el-button>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
@@ -187,8 +181,8 @@ layout("/layouts/platform.html"){
|
|||||||
this.units = await this.$businessTool.listUnit((this.$store.state.user.union || {}).id || this.pageForm.unionId)
|
this.units = await this.$businessTool.listUnit((this.$store.state.user.union || {}).id || this.pageForm.unionId)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
doExportApply(row, format) {
|
doExportApply(row) {
|
||||||
this.$downLoad('/platform/difficultHelp/reading/doExportApply?id=' + row.id + '&print=' + (format === 'pdf'))
|
this.$downLoad('/platform/difficultHelp/reading/doExportApply?id=' + row.id + '&print=false')
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
async created() {
|
async created() {
|
||||||
|
|||||||
+2
-10
@@ -178,11 +178,7 @@ layout("/layouts/platform.html"){
|
|||||||
},
|
},
|
||||||
async flushUnits(){
|
async flushUnits(){
|
||||||
this.$set(this.pageForm, "unitId", null)
|
this.$set(this.pageForm, "unitId", null)
|
||||||
if (this.$auth.hasRoleOr('SYSADMIN, SCHOOL_UNION_ADMIN')) {
|
this.units = await this.$businessTool.listUnit(this.pageForm.unionId)
|
||||||
this.units = await this.$businessTool.listUnit(this.pageForm.unionId)
|
|
||||||
} else {
|
|
||||||
this.units = await this.$businessTool.listUnit((this.$store.state.user.union || {}).id || this.pageForm.unionId)
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
exportYearPayRecord(){
|
exportYearPayRecord(){
|
||||||
this.$downLoad('/platform/difficultHelp/reading/exportYearPayRecord', this.pageForm)
|
this.$downLoad('/platform/difficultHelp/reading/exportYearPayRecord', this.pageForm)
|
||||||
@@ -204,11 +200,7 @@ layout("/layouts/platform.html"){
|
|||||||
},
|
},
|
||||||
async created() {
|
async created() {
|
||||||
this.pageData()
|
this.pageData()
|
||||||
if (this.$auth.hasRoleOr('SYSADMIN, SCHOOL_UNION_ADMIN')) {
|
this.unions = await this.$businessTool.listUnion()
|
||||||
this.unions = await this.$businessTool.listUnion()
|
|
||||||
} else {
|
|
||||||
this.unions = await this.$businessTool.listUnion((this.$store.state.user.union || {}).id)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
-6
@@ -1,11 +1,6 @@
|
|||||||
<div id="difficult_help_branch_union_approval_form">
|
<div id="difficult_help_branch_union_approval_form">
|
||||||
<el-form :model="formData" ref="formRef" label-width="100px" label-suffix=":">
|
<el-form :model="formData" ref="formRef" label-width="100px" label-suffix=":">
|
||||||
<el-row :gutter="20">
|
<el-row :gutter="20">
|
||||||
<el-col :span="12">
|
|
||||||
<el-form-item label="级别" prop="level" :rules="[{required:true,message:'请选择级别',trigger:['change','blur']}]">
|
|
||||||
<dict-select v-model="formData.level" code="DIFFICULT_LEVEL" style="width: 100%" placeholder="请选择级别"></dict-select>
|
|
||||||
</el-form-item>
|
|
||||||
</el-col>
|
|
||||||
<el-col :span="12">
|
<el-col :span="12">
|
||||||
<el-form-item label="帮扶金额" prop="money" :rules="[{required:true,message:'请填写帮扶金额',trigger:['change','blur']}]">
|
<el-form-item label="帮扶金额" prop="money" :rules="[{required:true,message:'请填写帮扶金额',trigger:['change','blur']}]">
|
||||||
<el-input-number v-model="formData.money" style="width: 100%" :precision="2" :min="0" placeholder="请输入帮扶金额"></el-input-number>
|
<el-input-number v-model="formData.money" style="width: 100%" :precision="2" :min="0" placeholder="请输入帮扶金额"></el-input-number>
|
||||||
@@ -29,7 +24,6 @@
|
|||||||
return {
|
return {
|
||||||
businessId: GetQueryString("businessId"),
|
businessId: GetQueryString("businessId"),
|
||||||
formData: {
|
formData: {
|
||||||
level: "",
|
|
||||||
money: undefined,
|
money: undefined,
|
||||||
tf_sign: "", tf_opinion: ""
|
tf_sign: "", tf_opinion: ""
|
||||||
},
|
},
|
||||||
|
|||||||
+2
-13
@@ -84,11 +84,6 @@ layout("/layouts/platform.html"){
|
|||||||
<el-dialog title="设置帮扶审批信息" :visible.sync="batchVisible" width="760px">
|
<el-dialog title="设置帮扶审批信息" :visible.sync="batchVisible" width="760px">
|
||||||
<el-form :model="batchForm" ref="batchFormRef" label-width="130px">
|
<el-form :model="batchForm" ref="batchFormRef" label-width="130px">
|
||||||
<el-row :gutter="20">
|
<el-row :gutter="20">
|
||||||
<el-col :span="12">
|
|
||||||
<el-form-item label="级别" prop="level" :rules="[{required:true,message:'请选择级别',trigger:['change','blur']}]">
|
|
||||||
<dict-select v-model="batchForm.level" code="DIFFICULT_LEVEL" style="width: 100%" placeholder="请选择级别"></dict-select>
|
|
||||||
</el-form-item>
|
|
||||||
</el-col>
|
|
||||||
<el-col :span="12">
|
<el-col :span="12">
|
||||||
<el-form-item label="帮扶金额(元)" prop="money" :rules="[{required:true,message:'请填写帮扶金额',trigger:['change','blur']}]">
|
<el-form-item label="帮扶金额(元)" prop="money" :rules="[{required:true,message:'请填写帮扶金额',trigger:['change','blur']}]">
|
||||||
<el-input-number v-model="batchForm.money" style="width: 100%" :precision="2" :min="0" placeholder="请输入帮扶金额"></el-input-number>
|
<el-input-number v-model="batchForm.money" style="width: 100%" :precision="2" :min="0" placeholder="请输入帮扶金额"></el-input-number>
|
||||||
@@ -113,11 +108,6 @@ layout("/layouts/platform.html"){
|
|||||||
</div>
|
</div>
|
||||||
<el-form :model="formData" ref="formRef" :rules="formRules" label-width="100px" label-suffix=":">
|
<el-form :model="formData" ref="formRef" :rules="formRules" label-width="100px" label-suffix=":">
|
||||||
<el-row :gutter="20">
|
<el-row :gutter="20">
|
||||||
<el-col :span="12">
|
|
||||||
<el-form-item label="级别" prop="level" :rules="[{required:true,message:'请选择级别',trigger:['change','blur']}]">
|
|
||||||
<dict-select v-model="formData.level" code="DIFFICULT_LEVEL" style="width: 100%" placeholder="请选择级别"></dict-select>
|
|
||||||
</el-form-item>
|
|
||||||
</el-col>
|
|
||||||
<el-col :span="12">
|
<el-col :span="12">
|
||||||
<el-form-item label="帮扶金额" prop="money" :rules="[{required:true,message:'请填写帮扶金额',trigger:['change','blur']}]">
|
<el-form-item label="帮扶金额" prop="money" :rules="[{required:true,message:'请填写帮扶金额',trigger:['change','blur']}]">
|
||||||
<el-input-number v-model="formData.money" style="width: 100%" :precision="2" :min="0" placeholder="请输入帮扶金额"></el-input-number>
|
<el-input-number v-model="formData.money" style="width: 100%" :precision="2" :min="0" placeholder="请输入帮扶金额"></el-input-number>
|
||||||
@@ -177,7 +167,7 @@ layout("/layouts/platform.html"){
|
|||||||
|
|
||||||
formData: {},
|
formData: {},
|
||||||
batchVisible: false,
|
batchVisible: false,
|
||||||
batchForm: {level: "", money: undefined, tf_sign: "", tf_opinion: ""},
|
batchForm: {money: undefined, tf_sign: "", tf_opinion: ""},
|
||||||
showApprovalForm: false,
|
showApprovalForm: false,
|
||||||
selectData: [],
|
selectData: [],
|
||||||
}
|
}
|
||||||
@@ -201,7 +191,7 @@ layout("/layouts/platform.html"){
|
|||||||
this.$message.warning('请勾选待审核数据!');
|
this.$message.warning('请勾选待审核数据!');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this.batchForm = {level: "", money: undefined, tf_sign: "", tf_opinion: ""}
|
this.batchForm = {money: undefined, tf_sign: "", tf_opinion: ""}
|
||||||
this.batchVisible = true
|
this.batchVisible = true
|
||||||
},
|
},
|
||||||
async submitBatch() {
|
async submitBatch() {
|
||||||
@@ -288,7 +278,6 @@ layout("/layouts/platform.html"){
|
|||||||
this.formData = {
|
this.formData = {
|
||||||
processTaskId: row.taskId,
|
processTaskId: row.taskId,
|
||||||
taskName: row.curTaskName,
|
taskName: row.curTaskName,
|
||||||
level: "",
|
|
||||||
money: undefined,
|
money: undefined,
|
||||||
tf_sign: "", tf_opinion: ""
|
tf_sign: "", tf_opinion: ""
|
||||||
}
|
}
|
||||||
|
|||||||
+17
@@ -0,0 +1,17 @@
|
|||||||
|
<el-descriptions-item label="慰问类型" :span="2">
|
||||||
|
<el-form-item label="慰问类型" prop="type">
|
||||||
|
<el-select v-model="formData.type" filterable @change="typeChange" style="width:100%" placeholder="请选择慰问类型">
|
||||||
|
<el-option v-for="t in typeOptions" :key="t.id" :value="t.id" :label="t.name"></el-option>
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="慰问金额" :span="2">
|
||||||
|
<el-form-item label="慰问金额" prop="perMoney" :rules="recipientRules.money">
|
||||||
|
<el-input-number v-model="formData.perMoney" :precision="2" :min="0" :max="10000" :controls="false" style="width:100%" placeholder="每人慰问金额(元)"></el-input-number>
|
||||||
|
</el-form-item>
|
||||||
|
</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="慰问时间" :span="2">
|
||||||
|
<el-form-item label="慰问时间" prop="occurTime" :rules="recipientRules.occurTime">
|
||||||
|
<el-date-picker v-model="formData.occurTime" type="date" value-format="yyyy-MM-dd" style="width:100%" placeholder="请选择慰问时间"></el-date-picker>
|
||||||
|
</el-form-item>
|
||||||
|
</el-descriptions-item>
|
||||||
+313
@@ -0,0 +1,313 @@
|
|||||||
|
<!--#
|
||||||
|
layout("/layouts/platform.html"){
|
||||||
|
#-->
|
||||||
|
|
||||||
|
<style nonce="${cspNonce!}">
|
||||||
|
<!--#include('recipients.css'){}#-->
|
||||||
|
</style>
|
||||||
|
<div id="app" class="special-condolence-apply" v-cloak>
|
||||||
|
<el-card shadow="never">
|
||||||
|
<snaker-start slot="header" label="特殊慰问" define_key="TSWW"></snaker-start>
|
||||||
|
<el-form size="small" :model="formData" ref="formRef" :rules="formRules" label-width="0" label-suffix=":"
|
||||||
|
class="flow-task-form">
|
||||||
|
<el-tabs v-model="activeApplicationTab">
|
||||||
|
<el-tab-pane label="基础信息" name="form">
|
||||||
|
<el-descriptions :column="6" border size="small">
|
||||||
|
<el-descriptions-item label="事项" :span="2"><el-form-item prop="subject" label="事项"><el-input v-model="formData.subject" maxlength="200" show-word-limit placeholder="请输入特殊慰问事项"></el-input></el-form-item></el-descriptions-item>
|
||||||
|
|
||||||
|
<el-descriptions-item label="申请人姓名" :span="2">{{formData.applyUserName}}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="申请人工号" :span="2">{{formData.applyLoginName}}</el-descriptions-item>
|
||||||
|
|
||||||
|
|
||||||
|
<!--#include('config.html'){}#-->
|
||||||
|
<el-descriptions-item label="申请人单位" :span="2">{{formData.applyUnitName}}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="申请人工会" :span="2">{{formData.applyUnionName}}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="" :span="2"><span></span></el-descriptions-item>
|
||||||
|
<el-descriptions-item label="申请事由" :span="6">
|
||||||
|
<el-form-item prop="remark" label="申请事由">
|
||||||
|
<el-input maxlength="500" v-model="formData.remark" placeholder="请填写申请事由"
|
||||||
|
type="textarea" :rows="3" resize="none"></el-input>
|
||||||
|
</el-form-item>
|
||||||
|
</el-descriptions-item>
|
||||||
|
|
||||||
|
<el-descriptions-item :span="6" v-if="chooseType.isUploadFile === true">
|
||||||
|
<template slot="label">
|
||||||
|
附件
|
||||||
|
<el-tooltip class="item" effect="dark" :content="'上传附件说明:' + chooseType.uploadFileDesc"
|
||||||
|
placement="top-start"
|
||||||
|
v-if="chooseType.isUploadFile && chooseType.uploadFileDesc">
|
||||||
|
<i class="el-icon-question"></i>
|
||||||
|
</el-tooltip>
|
||||||
|
</template>
|
||||||
|
<el-form-item prop="files" label="附件">
|
||||||
|
<file-upload
|
||||||
|
:value.sync="formData.files"
|
||||||
|
:upload_number="5"
|
||||||
|
upload_result_category="array"
|
||||||
|
complete_result
|
||||||
|
upload_mode="drag"
|
||||||
|
></file-upload>
|
||||||
|
</el-form-item>
|
||||||
|
</el-descriptions-item>
|
||||||
|
|
||||||
|
<el-descriptions-item label="签字" :span="6">
|
||||||
|
<el-form-item prop="signature" label="签字">
|
||||||
|
<pc-signature v-model="formData.signature"></pc-signature>
|
||||||
|
</el-form-item>
|
||||||
|
</el-descriptions-item>
|
||||||
|
</el-descriptions>
|
||||||
|
</el-tab-pane>
|
||||||
|
<el-tab-pane label="慰问对象" name="recipients" :lazy="false">
|
||||||
|
<!--#include('recipients.html'){}#-->
|
||||||
|
</el-tab-pane>
|
||||||
|
</el-tabs>
|
||||||
|
</el-form>
|
||||||
|
<el-row type="flex" justify="end" class="special-condolence-actions">
|
||||||
|
<el-button type="primary" plain @click="onSave">保存申请</el-button>
|
||||||
|
<el-button type="primary" @click="onSubmit" v-if="!taskId">提交申请</el-button>
|
||||||
|
<el-button type="primary" @click="onFinishTask" v-else>提交申请</el-button>
|
||||||
|
</el-row>
|
||||||
|
</el-card>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script nonce="${cspNonce!}">
|
||||||
|
<!--#include('recipients.js'){}#-->
|
||||||
|
new Vue({
|
||||||
|
el: "#app",
|
||||||
|
store,
|
||||||
|
mixins: [specialCondolenceRecipients],
|
||||||
|
components: {
|
||||||
|
ElDatePicker: {
|
||||||
|
extends: ELEMENT.DatePicker,
|
||||||
|
mounted() {
|
||||||
|
// 手动输入触发 change 前初始化日期面板,避免 picker 尚未创建。
|
||||||
|
if (!this.picker) this.mountPicker()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
bizId: GetQueryString("bizId"),
|
||||||
|
taskId: GetQueryString("taskId"),
|
||||||
|
formData: { recipients: [] },
|
||||||
|
formRules: {
|
||||||
|
subject: [{ required: true, whitespace: true, message: "请填写事项", trigger: ["blur", "change"] }, { max: 200, message: "事项最多200字", trigger: "blur" }],
|
||||||
|
recipients: [{ validator: (rule, value, callback) => callback(Array.isArray(value) && value.length > 0 ? undefined : new Error("请至少添加一位慰问对象")), trigger: "change" }],
|
||||||
|
helpUserId: [{ required: true, message: "必填", trigger: ["change", "blur"] }],
|
||||||
|
payUserId: [{ required: true, message: "必填", trigger: ["change", "blur"] }],
|
||||||
|
type: [{ required: true, message: "必填", trigger: ["change", "blur"] }],
|
||||||
|
way: [{ required: true, message: "必填", trigger: ["change", "blur"] }],
|
||||||
|
money: [
|
||||||
|
{ required: true, message: "请填写慰问金额", trigger: ["change", "blur"] },
|
||||||
|
{ validator: (rule, value, callback) => callback(this.validateMoney(value) ? undefined : new Error("慰问金额须大于0且不超过10000元,最多两位小数")), trigger: ["change", "blur"] }
|
||||||
|
],
|
||||||
|
occurTime: [{ required: true, message: "必填", trigger: ["change", "blur"] }],
|
||||||
|
child: [{ required: true, message: "必填", trigger: ["change", "blur"] }],
|
||||||
|
hospital: [{ required: true, message: "必填", trigger: ["change", "blur"] }],
|
||||||
|
hospitalHouseNum: [{ required: true, message: "必填", trigger: ["change", "blur"] }],
|
||||||
|
hospitalHouseBedNum: [{ required: true, message: "必填", trigger: ["change", "blur"] }],
|
||||||
|
hospitalBy: [{ required: true, message: "必填", trigger: ["change", "blur"] }],
|
||||||
|
deadImmediateFamily: [{ required: true, message: "必填", trigger: ["change", "blur"] }],
|
||||||
|
remark: [{ required: true, message: "必填", trigger: ["change", "blur"] }],
|
||||||
|
files: [{ required: true, type: "array", min: 1, max: 5, message: "请上传1至5个附件", trigger: ["change", "blur"] }],
|
||||||
|
signature: [{ required: true, message: "必填", trigger: ["change", "blur"] }],
|
||||||
|
handlerUserId: [{ required: true, message: "必填", trigger: ["change", "blur"] }],
|
||||||
|
// certifierUserId: [{ required: true, message: "必填", trigger: ["change", "blur"] }],
|
||||||
|
bankCardNumber: [
|
||||||
|
{ required: true, message: "请填写银行卡号或对公账户号", trigger: ["change", "blur"] },
|
||||||
|
{ pattern: /^[0-9]{6,30}$/, message: "收款账户须为6至30位数字(银行卡号或对公账户号)", trigger: ["change", "blur"] }
|
||||||
|
],
|
||||||
|
bankUserName: [{ required: true, message: "必填", trigger: ["change", "blur"] }],
|
||||||
|
bankOfDeposit: [{ required: true, message: "必填", trigger: ["change", "blur"] }],
|
||||||
|
thisYearHospitalizationNum: [
|
||||||
|
{ required: true, message: "必填", trigger: ["change", "blur"] },
|
||||||
|
{ type: "integer", min: 0, max: 10000, message: "住院次数须为0至10000的整数", trigger: ["change", "blur"] }
|
||||||
|
],
|
||||||
|
leaveHospitalTime: [{ required: true, message: "必填", trigger: ["change", "blur"] }],
|
||||||
|
hospitalizationTime: [{ required: true, message: "必填", trigger: ["change", "blur"] }],
|
||||||
|
},
|
||||||
|
chooseType: {},
|
||||||
|
payUserOptions: [],
|
||||||
|
helpUserOptions: [],
|
||||||
|
typeOptions: [],
|
||||||
|
|
||||||
|
handlerUserOptions: [],
|
||||||
|
certifierUserOptions: []
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
validateMoney(value) {
|
||||||
|
return /^(0|[1-9][0-9]*)(\.[0-9]{1,2})?$/.test(String(value)) && Number(value) > 0 && Number(value) <= 10000
|
||||||
|
},
|
||||||
|
createRemoteMethod(options) {
|
||||||
|
return (keyword) => {
|
||||||
|
this.selectQueryUser(keyword, options)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
selectQueryUser(keyword, options) {
|
||||||
|
options.length = 0
|
||||||
|
this.$axios.post("/platform/special_condolence/apply/listUser", { keyword: keyword }).then((res) => {
|
||||||
|
if (res.code === 0) {
|
||||||
|
options.push(...res.data)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
helpUserChange(val) {
|
||||||
|
const user = this.helpUserOptions.find(o => o.id === val)
|
||||||
|
if (user) {
|
||||||
|
const { userName, loginName, unitId, unitName, unionId, unionName } = user
|
||||||
|
this.$set(this.formData, "helpUserName", userName)
|
||||||
|
this.$set(this.formData, "helpLoginName", loginName)
|
||||||
|
this.$set(this.formData, "helpUnitId", unitId)
|
||||||
|
this.$set(this.formData, "helpUnitName", unitName)
|
||||||
|
this.$set(this.formData, "helpUnionId", unionId)
|
||||||
|
this.$set(this.formData, "helpUnionName", unionName)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
handlerUserChange(val) {
|
||||||
|
const user = this.handlerUserOptions.find(o => o.id === val)
|
||||||
|
if (user) {
|
||||||
|
const { userName, loginName, unitId, unitName, unionId, unionName } = user
|
||||||
|
this.$set(this.formData, "handlerUserName", userName)
|
||||||
|
this.$set(this.formData, "handlerLoginName", loginName)
|
||||||
|
this.$set(this.formData, "handlerUnitId", unitId)
|
||||||
|
this.$set(this.formData, "handlerUnitName", unitName)
|
||||||
|
this.$set(this.formData, "handlerUnionId", unionId)
|
||||||
|
this.$set(this.formData, "handlerUnionName", unionName)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
certifierUserChange(val) {
|
||||||
|
const user = this.certifierUserOptions.find(o => o.id === val)
|
||||||
|
if (user) {
|
||||||
|
const { userName, loginName, unitId, unitName, unionId, unionName } = user
|
||||||
|
this.$set(this.formData, "certifierUserName", userName)
|
||||||
|
this.$set(this.formData, "certifierLoginName", loginName)
|
||||||
|
this.$set(this.formData, "certifierUnitId", unitId)
|
||||||
|
this.$set(this.formData, "certifierUnitName", unitName)
|
||||||
|
this.$set(this.formData, "certifierUnionId", unionId)
|
||||||
|
this.$set(this.formData, "certifierUnionName", unionName)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
payUserChange(val) {
|
||||||
|
const user = this.payUserOptions.find(o => o.id === val)
|
||||||
|
if (user) {
|
||||||
|
const { userName, loginName } = user
|
||||||
|
this.$set(this.formData, "payUserName", userName)
|
||||||
|
this.$set(this.formData, "payLoginName", loginName)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
typeChange(id) {
|
||||||
|
this.chooseType = this.typeOptions.find(o => o.id === id)
|
||||||
|
if (this.chooseType) {
|
||||||
|
this.$set(this.formData, "perMoney", this.chooseType.money)
|
||||||
|
this.$set(this.formData, "way", this.chooseType.way)
|
||||||
|
this.$set(this.formData, "typeCode", this.chooseType.code)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onSave() {
|
||||||
|
this.$refs.formRef.validate((valid, invalidFields) => {
|
||||||
|
if (!valid) { this.showInvalidApplicationTab(invalidFields); return }
|
||||||
|
this.$confirm("您确定保存吗?", "提示", {
|
||||||
|
confirmButtonText: "确定",
|
||||||
|
cancelButtonText: "取消",
|
||||||
|
type: "warning"
|
||||||
|
}).then(() => {
|
||||||
|
this.$axios.post("/platform/special_condolence/apply/save", { data: JSON.stringify(this.formData) }).then(res => {
|
||||||
|
if (res.code === 0) {
|
||||||
|
this.$message.success(res.msg)
|
||||||
|
window.location.replace("/platform/special_condolence/mine")
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
},
|
||||||
|
onSubmit() {
|
||||||
|
if (!this.ensureApplicationRecipients()) return
|
||||||
|
this.$refs.formRef.validate((valid, invalidFields) => {
|
||||||
|
if (!valid) { this.showInvalidApplicationTab(invalidFields); return }
|
||||||
|
if (valid) {
|
||||||
|
this.$confirm("您确定要提交吗?", "提示", {
|
||||||
|
confirmButtonText: "确定",
|
||||||
|
cancelButtonText: "取消",
|
||||||
|
type: "warning"
|
||||||
|
}).then(() => {
|
||||||
|
this.$axios.post("/platform/special_condolence/apply/submit", {
|
||||||
|
data: JSON.stringify(this.formData)
|
||||||
|
}).then(res => {
|
||||||
|
if (res.code === 0) {
|
||||||
|
this.$message.success(res.msg)
|
||||||
|
window.location.replace("/platform/special_condolence/mine")
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
onFinishTask() {
|
||||||
|
if (!this.ensureApplicationRecipients()) return
|
||||||
|
this.$refs.formRef.validate((valid, invalidFields) => {
|
||||||
|
if (!valid) { this.showInvalidApplicationTab(invalidFields); return }
|
||||||
|
if (valid) {
|
||||||
|
this.$confirm("您确定要提交吗?", "提示", {
|
||||||
|
confirmButtonText: "确定",
|
||||||
|
cancelButtonText: "取消",
|
||||||
|
type: "warning"
|
||||||
|
}).then(() => {
|
||||||
|
this.$axios.post("/platform/special_condolence/apply/submitAgain", {
|
||||||
|
data: JSON.stringify(this.formData),
|
||||||
|
taskId: GetQueryString("taskId")
|
||||||
|
}).then(res => {
|
||||||
|
if (res.code === 0) {
|
||||||
|
this.$message.success(res.msg)
|
||||||
|
window.location.replace("/platform/special_condolence/mine")
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
init() {
|
||||||
|
if (this.bizId) {
|
||||||
|
this.$axios.post("/platform/special_condolence/mine/info", { id: this.bizId }).then((res) => {
|
||||||
|
if (res.code === 0) {
|
||||||
|
this.formData = res.data
|
||||||
|
this.initRecipients()
|
||||||
|
this.selectQueryUser(this.formData.helpLoginName, this.helpUserOptions)
|
||||||
|
this.selectQueryUser(this.formData.certifierLoginName, this.certifierUserOptions)
|
||||||
|
this.selectQueryUser(this.formData.handlerLoginName, this.handlerUserOptions)
|
||||||
|
this.chooseType = this.typeOptions.find(o => o.id === this.formData.type)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
const { username, loginname, id, unit, union, mobile } = this.$store.state.user
|
||||||
|
this.formData = {
|
||||||
|
recipients: [this.newRecipient()],
|
||||||
|
perMoney: undefined,
|
||||||
|
occurTime: this.$moment().format('YYYY-MM-DD'),
|
||||||
|
applyUserName: username,
|
||||||
|
applyLoginName: loginname,
|
||||||
|
applyUserId: id,
|
||||||
|
applyUnitId: unit?.id,
|
||||||
|
applyUnitName: unit?.name,
|
||||||
|
applyUnionId: union?.id,
|
||||||
|
applyUnionName: union?.name
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
querySpecialCondolenceType() {
|
||||||
|
this.$axios.post("/platform/special_condolence/type/querySpecialCondolenceType")
|
||||||
|
.then((resp) => {
|
||||||
|
this.typeOptions = resp.data
|
||||||
|
})
|
||||||
|
}
|
||||||
|
},
|
||||||
|
created() {
|
||||||
|
this.querySpecialCondolenceType()
|
||||||
|
this.init()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<!--#
|
||||||
|
}
|
||||||
|
#-->
|
||||||
+67
@@ -0,0 +1,67 @@
|
|||||||
|
.special-condolence-apply .el-card__body { padding: 24px; }
|
||||||
|
.special-condolence-apply .special-condolence-section-title { display: flex; align-items: center; gap: 10px; margin: 24px 0 14px; color: #303133; font-size: 15px; font-weight: 600; line-height: 24px; }
|
||||||
|
.special-condolence-apply .el-descriptions__table { table-layout: fixed; }
|
||||||
|
.special-condolence-apply .flow-task-form > .special-condolence-section-title:first-child { margin-top: 0; }
|
||||||
|
.special-condolence-apply .el-descriptions { font-size: 14px; }
|
||||||
|
.special-condolence-apply .el-descriptions .el-descriptions-item__cell { height: 50px; padding: 8px 12px; box-sizing: border-box; font-size: 14px; line-height: 32px; vertical-align: middle; }
|
||||||
|
.special-condolence-apply .el-descriptions-item__label.is-bordered-label { width: 130px; min-width: 130px; max-width: 130px; font-weight: 400; }
|
||||||
|
.special-condolence-apply .el-descriptions-item__content { font-weight: 400; }
|
||||||
|
.special-condolence-apply .el-descriptions .el-form-item__content { line-height: 32px; }
|
||||||
|
.special-condolence-apply .el-descriptions .el-input__inner { height: 32px; line-height: 32px; font-size: 14px; }
|
||||||
|
.special-condolence-apply .el-descriptions .el-input__icon { line-height: 32px; }
|
||||||
|
.special-condolence-apply .el-descriptions .el-textarea__inner { font-size: 14px; line-height: 22px; }
|
||||||
|
|
||||||
|
.special-condolence-apply .el-descriptions-item__label { width: 130px; color: #606266; background: #f7f9fc; }
|
||||||
|
.special-condolence-apply .special-condolence-recipients { margin: 0; }
|
||||||
|
.special-condolence-apply .special-condolence-toolbar { display: flex; justify-content: flex-end; align-items: center; flex-wrap: wrap; gap: 14px; padding: 0 0 12px; }
|
||||||
|
.special-condolence-apply .special-condolence-toolbar .special-condolence-section-title { margin: 0 0 4px; }
|
||||||
|
.special-condolence-hint { color: #606266; font-size: 12px; line-height: 20px; }
|
||||||
|
.special-condolence-apply .special-condolence-toolbar-buttons { display: flex; flex-wrap: wrap; gap: 8px; }
|
||||||
|
.special-condolence-apply .special-condolence-toolbar-buttons .el-button { margin: 0; }
|
||||||
|
.special-condolence-apply .special-condolence-table-item { margin: 0; }
|
||||||
|
.special-condolence-apply .special-condolence-table-item > .el-form-item__content { line-height: normal; }
|
||||||
|
.special-condolence-apply .special-condolence-table-item .el-form-item__error { position: static; padding: 8px 20px; }
|
||||||
|
.special-condolence-apply .special-condolence-table-item .el-table th { background: #f5f7fa; color: #606266; font-weight: 600; }
|
||||||
|
.special-condolence-apply .special-condolence-table-item .el-table .cell { padding: 0 8px; }
|
||||||
|
.special-condolence-apply .special-condolence-table-item .el-select,
|
||||||
|
.special-condolence-apply .special-condolence-table-item .el-input-number,
|
||||||
|
.special-condolence-apply .special-condolence-table-item .el-date-editor { width: 100%; }
|
||||||
|
.special-condolence-apply .special-condolence-table-item .el-input-number .el-input__inner { text-align: right; }
|
||||||
|
.special-condolence-apply .special-condolence-delete { color: #d64040; }
|
||||||
|
.special-condolence-apply .special-condolence-table-footer { display: flex; justify-content: flex-end; align-items: center; flex-wrap: wrap; gap: 10px; padding: 10px 20px; background: #fafbfd; }
|
||||||
|
.special-condolence-apply .special-condolence-total { display: flex; align-items: baseline; gap: 6px; color: #606266; font-size: 13px; font-variant-numeric: tabular-nums; }
|
||||||
|
.special-condolence-apply .special-condolence-total > span { margin-left: 18px; }
|
||||||
|
.special-condolence-apply .special-condolence-total-amount { color: #303133; font-size: 20px; }
|
||||||
|
.special-condolence-apply .special-condolence-actions { gap: 12px; margin-top: 24px; padding-top: 20px; border-top: 1px solid #ebeef5; }
|
||||||
|
.special-condolence-apply .special-condolence-actions .el-button { margin: 0; min-width: 108px; }
|
||||||
|
.special-condolence-dialog { max-width: calc(100vw - 32px); border-radius: 8px; }
|
||||||
|
.special-condolence-dialog .el-dialog__header { padding: 22px 24px 16px; border-bottom: 1px solid #ebeef5; }
|
||||||
|
.special-condolence-dialog .el-dialog__body { padding: 24px; }
|
||||||
|
.special-condolence-dialog .el-dialog__footer { padding: 16px 24px; border-top: 1px solid #ebeef5; }
|
||||||
|
.special-condolence-dialog .special-condolence-template { display: flex; align-items: center; flex-wrap: wrap; gap: 12px; padding: 16px; border: 1px solid #dce6f3; border-radius: 6px; background: #f6f9fe; }
|
||||||
|
.special-condolence-dialog .special-condolence-template > i { color: #409eff; font-size: 28px; }
|
||||||
|
.special-condolence-dialog .special-condolence-template > div { flex: 1; min-width: 180px; }
|
||||||
|
.special-condolence-dialog .special-condolence-template p { margin: 5px 0 0; color: #606266; font-size: 12px; line-height: 18px; }
|
||||||
|
.special-condolence-dialog .special-condolence-upload-title { margin: 22px 0 12px; font-weight: 600; }
|
||||||
|
.special-condolence-dialog .special-condolence-upload .el-upload,
|
||||||
|
.special-condolence-dialog .special-condolence-upload .el-upload-dragger { width: 100%; }
|
||||||
|
.special-condolence-dialog .special-condolence-upload .el-upload-dragger { height: auto; min-height: 150px; padding: 22px 12px; }
|
||||||
|
.special-condolence-dialog .special-condolence-upload .el-icon-upload,
|
||||||
|
.special-condolence-dialog .special-condolence-upload .el-icon-loading { display: block; margin: 0 0 16px; color: #909399; font-size: 44px; line-height: 48px; }
|
||||||
|
.special-condolence-dialog .el-upload__tip { margin-bottom: 16px; line-height: 20px; }
|
||||||
|
.special-condolence-dialog .special-condolence-batch-note { margin-bottom: 24px; padding: 12px 16px; background: #f5f7fa; border-radius: 4px; line-height: 22px; }
|
||||||
|
.special-condolence-dialog .special-condolence-batch-form .el-select,
|
||||||
|
.special-condolence-dialog .special-condolence-batch-form .el-input-number,
|
||||||
|
.special-condolence-dialog .special-condolence-batch-form .el-date-editor { width: 100%; }
|
||||||
|
@media (max-width: 768px) {
|
||||||
|
.special-condolence-apply .el-card__body { padding: 16px; }
|
||||||
|
.special-condolence-apply .special-condolence-toolbar { padding: 14px; }
|
||||||
|
.special-condolence-apply .special-condolence-total > span { margin-left: 8px; }
|
||||||
|
}
|
||||||
|
|
||||||
|
.special-condolence-apply .special-condolence-table-item .el-table .el-form-item { margin: 8px 0 20px; }
|
||||||
|
.special-condolence-apply .special-condolence-table-item .el-table .el-form-item__error { position: absolute; padding: 4px 0 0; font-size: 11px; line-height: 14px; white-space: normal; }
|
||||||
|
|
||||||
|
.special-condolence-apply .flow-task-form .el-form-item__error { color: #f56c6c !important; }
|
||||||
|
.special-condolence-apply .el-form-item.is-error .el-input__inner,
|
||||||
|
.special-condolence-apply .el-form-item.is-error .el-textarea__inner { border-color: #f56c6c; }
|
||||||
+38
@@ -0,0 +1,38 @@
|
|||||||
|
<section class="special-condolence-recipients">
|
||||||
|
<div class="special-condolence-toolbar">
|
||||||
|
<div class="special-condolence-toolbar-buttons">
|
||||||
|
<el-button size="small" icon="el-icon-upload2" @click="importVisible = true">Excel 导入</el-button>
|
||||||
|
<el-button size="small" type="primary" icon="el-icon-plus" @click="formData.recipients.push(newRecipient())">新增慰问对象</el-button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<el-form-item prop="recipients" label-width="0" class="special-condolence-table-item">
|
||||||
|
<el-table ref="recipientTableRef" :data="formData.recipients" border stripe size="small" max-height="520" empty-text="暂无慰问对象,点击新增或从 Excel 导入">
|
||||||
|
<el-table-column type="index" label="序号" width="55" align="center" fixed="left"></el-table-column>
|
||||||
|
<el-table-column label="慰问对象" width="200" fixed="left"><template slot-scope="s"><el-form-item :prop="'recipients.' + s.$index + '.helpUserId'" :rules="recipientRules.helpUserId"><user-select size="small" v-model="s.row.helpUserId" api="/platform/special_condolence/apply/listUser" api_input_key_name="keyword" :option_list="recipientOptions(s.row)" :option_label_func="item => item.userName + '(' + (item.loginName || '') + ')'" @selected="(user, id) => recipientUserChange(s.row, s.$index, id, user)"></user-select></el-form-item></template></el-table-column>
|
||||||
|
<el-table-column label="工号" min-width="150"><template slot-scope="s"><el-form-item :prop="'recipients.' + s.$index + '.helpLoginName'" :rules="[{ validator: (rule, value, cb) => cb(s.row.personType === '劳务派遣人员' || value ? undefined : new Error('普通人员工号不能为空')), trigger: 'change' }]"><el-input size="small" v-model="s.row.helpLoginName" readonly placeholder="选人后带出,劳务派遣可空"></el-input></el-form-item></template></el-table-column>
|
||||||
|
<el-table-column label="身份证号码" min-width="205"><template slot-scope="s"><el-form-item :prop="'recipients.' + s.$index + '.idCard'" :rules="recipientRules.idCard"><el-input size="small" v-model="s.row.idCard" maxlength="18" placeholder="请输入18位身份证号"></el-input></el-form-item></template></el-table-column>
|
||||||
|
<el-table-column label="开户行" min-width="190"><template slot-scope="s"><el-form-item :prop="'recipients.' + s.$index + '.bankOfDeposit'" :rules="recipientRules.bankOfDeposit"><el-input size="small" v-model="s.row.bankOfDeposit" maxlength="100" placeholder="请输入开户银行及支行"></el-input></el-form-item></template></el-table-column>
|
||||||
|
<el-table-column label="户名" min-width="140"><template slot-scope="s"><el-form-item :prop="'recipients.' + s.$index + '.bankUserName'" :rules="recipientRules.bankUserName"><el-input size="small" v-model="s.row.bankUserName" maxlength="100" placeholder="请输入账户户名"></el-input></el-form-item></template></el-table-column>
|
||||||
|
<el-table-column label="收款账户" min-width="215"><template slot-scope="s"><el-form-item :prop="'recipients.' + s.$index + '.bankCardNumber'" :rules="recipientRules.bankCardNumber"><el-input size="small" v-model="s.row.bankCardNumber" maxlength="30" placeholder="银行卡号或对公账户号"></el-input></el-form-item></template></el-table-column>
|
||||||
|
<el-table-column label="操作" fixed="right" width="75" align="center"><template slot-scope="s"><el-button size="small" type="text" class="special-condolence-delete" @click="formData.recipients.splice(s.$index, 1)">删除</el-button></template></el-table-column>
|
||||||
|
</el-table>
|
||||||
|
</el-form-item>
|
||||||
|
<div class="special-condolence-table-footer">
|
||||||
|
<div class="special-condolence-total">共 <strong>{{ recipientCount }}</strong> 人<span>慰问金额合计</span><strong class="special-condolence-total-amount">¥ {{ recipientTotal }}</strong></div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
<el-dialog title="Excel 导入慰问对象" :visible.sync="importVisible" width="560px" custom-class="special-condolence-dialog" :close-on-click-modal="!importLoading" :close-on-press-escape="!importLoading" :show-close="!importLoading" append-to-body>
|
||||||
|
<div class="special-condolence-template">
|
||||||
|
<i class="el-icon-document"></i>
|
||||||
|
<div><strong>第一步:下载并填写模板</strong><p>按模板表头填写,一行对应一位慰问对象。</p></div>
|
||||||
|
<el-button size="small" type="primary" plain icon="el-icon-download" @click="$downLoad('/platform/special_condolence/apply/importTemplate')">下载模板</el-button>
|
||||||
|
</div>
|
||||||
|
<div class="special-condolence-upload-title">第二步:上传填写好的文件</div>
|
||||||
|
<el-upload class="special-condolence-upload" drag action="" accept=".xlsx,.xls" :http-request="importRecipients" :show-file-list="false" :disabled="importLoading">
|
||||||
|
<i :class="importLoading ? 'el-icon-loading' : 'el-icon-upload'"></i>
|
||||||
|
<div class="el-upload__text">{{ importLoading ? '正在导入,请稍候…' : '将 Excel 文件拖到此处,或点击选择文件' }}</div>
|
||||||
|
<div slot="tip" class="el-upload__tip">支持 .xlsx、.xls 格式,单次最多 1000 行。导入的数据将追加到当前表格。</div>
|
||||||
|
</el-upload>
|
||||||
|
<el-alert title="工号、身份证号码和收款账户请保持文本格式。普通人员须填写正确工号;劳务派遣人员免校验工号,均须属于申请人本工会。" type="info" :closable="false" show-icon></el-alert>
|
||||||
|
<span slot="footer"><el-button :disabled="importLoading" @click="importVisible = false">关闭</el-button></span>
|
||||||
|
</el-dialog>
|
||||||
+112
@@ -0,0 +1,112 @@
|
|||||||
|
const specialCondolenceRecipients = {
|
||||||
|
data() {
|
||||||
|
return { activeApplicationTab: 'form', recipientRules: this.createRecipientRules(), importVisible: false, importLoading: false }
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
recipientCount() {
|
||||||
|
return (this.formData.recipients || []).length
|
||||||
|
},
|
||||||
|
recipientTotal() {
|
||||||
|
const money = Number(this.formData.perMoney)
|
||||||
|
const cents = (Number.isFinite(money) && money > 0 ? Math.round(money * 100) : 0) * this.recipientCount
|
||||||
|
return (cents / 100).toLocaleString('zh-CN', { minimumFractionDigits: 2, maximumFractionDigits: 2 })
|
||||||
|
}
|
||||||
|
},
|
||||||
|
watch: {
|
||||||
|
activeApplicationTab() {
|
||||||
|
this.$nextTick(() => {
|
||||||
|
if (this.$refs.recipientTableRef) this.$refs.recipientTableRef.doLayout()
|
||||||
|
})
|
||||||
|
},
|
||||||
|
typeOptions() { this.chooseType = this.typeOptions.find(t => t.id === this.formData.type) || {} },
|
||||||
|
'formData.type'(value) { this.chooseType = this.typeOptions.find(t => t.id === value) || {} }
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
showInvalidApplicationTab(errors) {
|
||||||
|
const fields = Array.isArray(errors) ? errors.map(error => error.name || '') : Object.keys(errors || {})
|
||||||
|
if (!fields.length) return
|
||||||
|
this.activeApplicationTab = fields.some(field => !field.startsWith('recipients')) ? 'form' : 'recipients'
|
||||||
|
if (this.activeApplicationTab === 'recipients') this.notifyRecipientError('请完善慰问对象的必填信息')
|
||||||
|
},
|
||||||
|
notifyRecipientError(message) {
|
||||||
|
if (this.$toast && this.$toast.fail) this.$toast.fail(message)
|
||||||
|
else this.$message.error(message)
|
||||||
|
},
|
||||||
|
ensureApplicationRecipients() {
|
||||||
|
const rows = this.formData.recipients
|
||||||
|
if (!Array.isArray(rows) || rows.length === 0 || rows.some(row => !row || !String(row.helpUserId || '').trim())) {
|
||||||
|
this.activeApplicationTab = 'recipients'
|
||||||
|
this.notifyRecipientError('请先选择慰问对象,并填写完整信息')
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
},
|
||||||
|
createRecipientRules() {
|
||||||
|
const required = label => ({ required: true, whitespace: true, message: '请填写' + label, trigger: ['blur', 'change'] })
|
||||||
|
return {
|
||||||
|
helpUserId: [{ required: true, message: '请选择慰问对象', trigger: 'change' }],
|
||||||
|
type: [{ required: true, message: '请选择慰问类型', trigger: 'change' }],
|
||||||
|
idCard: [required('身份证号码'), { validator: (rule, value, cb) => cb(this.validRecipientIdCard(value) ? undefined : new Error('身份证号码不正确')), trigger: ['blur', 'change'] }],
|
||||||
|
bankOfDeposit: [required('开户行'), { max: 100, message: '开户行最多100字', trigger: 'blur' }],
|
||||||
|
bankUserName: [required('户名'), { max: 100, message: '户名最多100字', trigger: 'blur' }],
|
||||||
|
bankCardNumber: [required('收款账户'), { pattern: /^[0-9]{6,30}$/, message: '请输入6至30位数字账户', trigger: ['blur', 'change'] }],
|
||||||
|
money: [{ validator: (rule, value, cb) => cb(/^(0|[1-9][0-9]*)(\.[0-9]{1,2})?$/.test(String(value)) && Number(value) > 0 && Number(value) <= 10000 ? undefined : new Error('金额须大于0且不超过10000元,最多两位小数')), trigger: ['blur', 'change'] }],
|
||||||
|
occurTime: [{ validator: (rule, value, cb) => cb(this.$moment(value, 'YYYY-MM-DD', true).isValid() ? undefined : new Error('请选择有效慰问时间')), trigger: ['blur', 'change'] }]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
validRecipientIdCard(value) {
|
||||||
|
const card = String(value || '').toUpperCase()
|
||||||
|
if (!/^[1-9][0-9]{16}[0-9X]$/.test(card) || !this.$moment(card.substring(6, 14), 'YYYYMMDD', true).isValid()) return false
|
||||||
|
const weights = [7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2]
|
||||||
|
return '10X98765432'[weights.reduce((sum, weight, index) => sum + weight * Number(card[index]), 0) % 11] === card[17]
|
||||||
|
},
|
||||||
|
recipientOptions(row) {
|
||||||
|
return row.helpUserId ? [{ id: row.helpUserId, userName: row.helpUserName, loginName: row.helpLoginName, personType: row.personType, idCard: row.idCard, bankOfDeposit: row.bankOfDeposit, bankUserName: row.bankUserName, bankCardNumber: row.bankCardNumber }] : []
|
||||||
|
},
|
||||||
|
recipientUserChange(row, index, id, user) {
|
||||||
|
this.$set(row, 'helpUserId', user ? user.id : '')
|
||||||
|
this.$set(row, 'helpUserName', user ? user.userName : '')
|
||||||
|
this.$set(row, 'helpLoginName', user ? user.loginName : '')
|
||||||
|
this.$set(row, 'personType', user ? user.personType : '')
|
||||||
|
this.$set(row, 'idCard', user ? user.idCard || '' : '')
|
||||||
|
this.$set(row, 'bankOfDeposit', user ? user.bankOfDeposit || '' : '')
|
||||||
|
this.$set(row, 'bankUserName', user ? user.bankUserName || user.userName : '')
|
||||||
|
this.$set(row, 'bankCardNumber', user ? user.bankCardNumber || '' : '')
|
||||||
|
this.$nextTick(() => {
|
||||||
|
const fields = ['helpUserId', 'helpLoginName', 'idCard', 'bankOfDeposit', 'bankUserName', 'bankCardNumber']
|
||||||
|
const names = fields.map(field => 'recipients.' + index + '.' + field)
|
||||||
|
const form = this.$refs.formRef
|
||||||
|
if (typeof form.validateField === 'function') form.validateField(names)
|
||||||
|
else if (typeof form.validate === 'function') form.validate(names).catch(() => {})
|
||||||
|
})
|
||||||
|
},
|
||||||
|
|
||||||
|
newRecipient() {
|
||||||
|
return { helpUserId: '', helpLoginName: '', personType: '', helpUserName: '', idCard: '', bankOfDeposit: '', bankUserName: '', bankCardNumber: '' }
|
||||||
|
},
|
||||||
|
initRecipients() {
|
||||||
|
if (this.formData.perMoney == null && this.formData.recipients && this.formData.recipients.length) this.$set(this.formData, 'perMoney', Number(this.formData.recipients[0].money))
|
||||||
|
if (!this.formData.recipients || !this.formData.recipients.length) {
|
||||||
|
this.$set(this.formData, 'recipients', this.formData.helpUserName ? [Object.assign(this.newRecipient(), this.formData, { recipients: undefined })] : [this.newRecipient()])
|
||||||
|
}
|
||||||
|
},
|
||||||
|
async importRecipients(request) {
|
||||||
|
this.importLoading = true
|
||||||
|
try {
|
||||||
|
const data = new FormData()
|
||||||
|
data.append('file', request.file)
|
||||||
|
const result = await this.$axios.post('/platform/special_condolence/apply/importRecipients', data)
|
||||||
|
if (result.code === 0) {
|
||||||
|
const rows = this.formData.recipients.filter(r => r.helpUserName || r.type || r.idCard || r.bankCardNumber || r.bankUserName || r.bankOfDeposit || r.money)
|
||||||
|
this.$set(this.formData, 'recipients', rows.concat(result.data))
|
||||||
|
this.importVisible = false
|
||||||
|
this.$message.success('导入成功,共' + result.data.length + '人')
|
||||||
|
} else this.$message.error(result.msg || '导入失败')
|
||||||
|
} catch (error) {
|
||||||
|
this.$message.error('导入失败,请检查文件内容后重试')
|
||||||
|
} finally {
|
||||||
|
this.importLoading = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,181 @@
|
|||||||
|
const specialcondolenceInfo = {
|
||||||
|
template: /*language=HTML*/ `
|
||||||
|
<div>
|
||||||
|
<el-tabs v-model="activeInfoTab">
|
||||||
|
<el-tab-pane label="基础信息" name="form">
|
||||||
|
<div class="process-title">
|
||||||
|
申请信息
|
||||||
|
<el-link type="primary" @click="openChart">点击查看流程图</el-link>
|
||||||
|
</div>
|
||||||
|
<el-descriptions :column="6" border size="small" :label-style="{ width: '130px', minWidth: '130px', maxWidth: '130px', fontSize: '14px', fontWeight: 400, lineHeight: '32px', padding: '8px 12px' }" :content-style="{ fontSize: '14px', fontWeight: 400, lineHeight: '32px', padding: '8px 12px' }">
|
||||||
|
<el-descriptions-item label="事项" :span="2">{{ viewData.subject || '--' }}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="申请人姓名" :span="2">{{ viewData.applyUserName }}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="申请人工号" :span="2">{{ viewData.applyLoginName }}</el-descriptions-item>
|
||||||
|
<template v-if="viewData.recipients && viewData.recipients.length">
|
||||||
|
<el-descriptions-item label="慰问类型" :span="2">{{ viewData.typeName }}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="每人慰问金额" :span="2">{{ viewData.perMoney }} 元</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="慰问时间" :span="2">{{ viewData.occurTime }}</el-descriptions-item>
|
||||||
|
</template>
|
||||||
|
<el-descriptions-item label="申请人单位" :span="2">{{ viewData.applyUnitName }}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="申请人工会" :span="2">{{ viewData.applyUnionName }}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="" :span="2"><span></span></el-descriptions-item>
|
||||||
|
<el-descriptions-item label="申请事由" :span="6">
|
||||||
|
<div style="white-space: pre-line">{{ viewData.remark }}</div>
|
||||||
|
</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="附件" :span="6">
|
||||||
|
<file-preview v-if="viewData.files && viewData.files.length > 0" :files="viewData.files"
|
||||||
|
complete_result></file-preview>
|
||||||
|
<span v-else>暂无附件</span>
|
||||||
|
</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="签字" :span="6">
|
||||||
|
<el-image :src="viewData.signature"
|
||||||
|
v-if="viewData.signature"
|
||||||
|
class="signature-image"></el-image>
|
||||||
|
<span v-else>暂无签字</span>
|
||||||
|
</el-descriptions-item>
|
||||||
|
</el-descriptions>
|
||||||
|
|
||||||
|
|
||||||
|
</el-tab-pane>
|
||||||
|
<el-tab-pane label="慰问对象" name="recipients">
|
||||||
|
<el-descriptions v-if="!viewData.recipients || !viewData.recipients.length" :column="3" border>
|
||||||
|
<template v-if="!viewData.recipients || !viewData.recipients.length">
|
||||||
|
<el-descriptions-item label="慰问对象">{{ viewData.helpUserName }}</el-descriptions-item>
|
||||||
|
<!-- <el-descriptions-item label="经办人">{{ viewData.handlerUserName }}</el-descriptions-item>-->
|
||||||
|
<el-descriptions-item label="证明人">{{ viewData.certifierUserName }}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="慰问类型">{{ viewData.typeName }}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="慰问金额">{{ viewData.money }}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="慰问时间">{{ viewData.occurTime }}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="收款账户">{{ viewData.bankCardNumber }}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="户名">{{ viewData.bankUserName }}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="开户行">{{ viewData.bankOfDeposit }}</el-descriptions-item>
|
||||||
|
<template v-if="['2'].includes(viewData.typeCode)">
|
||||||
|
<el-descriptions-item label="入院时间">{{ viewData.hospitalizationTime }}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="出院时间">{{ viewData.leaveHospitalTime }}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="当年第几次住院">{{ viewData.thisYearHospitalizationNum }}
|
||||||
|
</el-descriptions-item>
|
||||||
|
</template>
|
||||||
|
</template>
|
||||||
|
</el-descriptions>
|
||||||
|
|
||||||
|
<div v-if="viewData.recipients && viewData.recipients.length" class="process-title" style="display:flex;justify-content:space-between;align-items:center;gap:12px;flex-wrap:wrap;margin-top:20px">
|
||||||
|
<span>慰问对象明细</span>
|
||||||
|
<span style="font-size:14px;font-weight:normal">慰问金额合计:<strong>¥ {{ detailTotal }}</strong></span>
|
||||||
|
</div>
|
||||||
|
<el-table ref="recipientInfoTableRef" v-if="viewData.recipients && viewData.recipients.length" :data="viewData.recipients" border stripe size="small" max-height="480" class="mt10" :header-cell-style="{ background: '#f5f7fa', color: '#606266' }">
|
||||||
|
<el-table-column type="index" label="序号" width="55" align="center" fixed="left"></el-table-column>
|
||||||
|
<el-table-column prop="helpUserName" label="慰问对象" width="130" fixed="left"></el-table-column>
|
||||||
|
<el-table-column prop="helpLoginName" label="工号" min-width="130"></el-table-column>
|
||||||
|
<el-table-column prop="idCard" label="身份证号码" min-width="190"></el-table-column>
|
||||||
|
<el-table-column prop="bankOfDeposit" label="开户行" min-width="180" show-overflow-tooltip></el-table-column>
|
||||||
|
<el-table-column prop="bankUserName" label="户名" min-width="150"></el-table-column>
|
||||||
|
<el-table-column prop="bankCardNumber" label="收款账户" min-width="210"></el-table-column>
|
||||||
|
</el-table>
|
||||||
|
</el-tab-pane>
|
||||||
|
<el-tab-pane label="审核记录" name="records">
|
||||||
|
<div v-if="!doneTasks.length" style="padding:32px;text-align:center;color:#909399">暂无审核记录</div>
|
||||||
|
<template v-for="task in doneTasks">
|
||||||
|
<div class="mt10">
|
||||||
|
<div class="process-title">{{ task.displayName }}</div>
|
||||||
|
<el-descriptions border class="flow-task-form" :column="3" :key="task.id"
|
||||||
|
v-if="task.ext.isFirstTaskNode">
|
||||||
|
<el-descriptions-item label="申请用户">{{ task.ext.initiatorName
|
||||||
|
}}({{task.ext.initiatorAccount}})
|
||||||
|
</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="申请时间">{{ task.finishTime }}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="办理结果">
|
||||||
|
<dict-tag :options="dict.type.PROCESS_TASK_SUBMIT_TYPE"
|
||||||
|
:value="task.ext.submitType"></dict-tag>
|
||||||
|
</el-descriptions-item>
|
||||||
|
</el-descriptions>
|
||||||
|
|
||||||
|
<el-descriptions border class="flow-task-form" :column="3" :key="task.id" v-else>
|
||||||
|
<el-descriptions-item label="办理用户">{{ task.taskFormData.userName
|
||||||
|
}}({{task.taskFormData.loginName}})
|
||||||
|
</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="办理时间">{{ task.finishTime }}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="办理结果">
|
||||||
|
<dict-tag :options="dict.type.PROCESS_TASK_SUBMIT_TYPE"
|
||||||
|
:value="task.ext.submitType"></dict-tag>
|
||||||
|
</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="审批签字" :span="3" v-if="task.taskFormData && task.taskFormData.sign">
|
||||||
|
<el-image :src="task.taskFormData.sign" style="height: 80px" fit="contain"></el-image>
|
||||||
|
</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="办理意见" v-if="!task.ext.isFirstTaskNode">{{
|
||||||
|
task.taskFormData.opinion }}
|
||||||
|
</el-descriptions-item>
|
||||||
|
</el-descriptions>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</el-tab-pane>
|
||||||
|
</el-tabs>
|
||||||
|
<slot></slot>
|
||||||
|
<snaker-chart ref="snakerChartRef"></snaker-chart>
|
||||||
|
</div>
|
||||||
|
`,
|
||||||
|
store,
|
||||||
|
dicts: ["PROCESS_TASK_SUBMIT_TYPE"],
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
activeInfoTab: 'form',
|
||||||
|
visible: false,
|
||||||
|
viewData: {},
|
||||||
|
doneTasks: [],
|
||||||
|
row: null
|
||||||
|
}
|
||||||
|
},
|
||||||
|
watch: {
|
||||||
|
activeInfoTab() {
|
||||||
|
this.$nextTick(() => {
|
||||||
|
if (this.$refs.recipientInfoTableRef) this.$refs.recipientInfoTableRef.doLayout()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
detailTotal() {
|
||||||
|
const cents = (this.viewData.recipients || []).reduce((sum, row) => {
|
||||||
|
const money = Number(row.money)
|
||||||
|
return sum + (Number.isFinite(money) ? Math.round(money * 100) : 0)
|
||||||
|
}, 0)
|
||||||
|
return (cents / 100).toLocaleString('zh-CN', { minimumFractionDigits: 2, maximumFractionDigits: 2 })
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
onOpen(row) {
|
||||||
|
this.activeInfoTab = 'form'
|
||||||
|
this.row = row
|
||||||
|
this.visible = true
|
||||||
|
this.getInfo()
|
||||||
|
this.getDoneTasks()
|
||||||
|
},
|
||||||
|
getInfo() {
|
||||||
|
this.$axios.post('/platform/special_condolence/mine/info', {id: this.row.id}).then((res) => {
|
||||||
|
if (res.code === 0) {
|
||||||
|
this.viewData = res.data
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
// 获取已办任务审批记录
|
||||||
|
getDoneTasks() {
|
||||||
|
this.$axios.post("/flow/common/doneTasks", {bizId: this.row.id}).then((res) => {
|
||||||
|
if (res.code === 0) {
|
||||||
|
this.doneTasks = res.data
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
// 查看流程图
|
||||||
|
openChart(){
|
||||||
|
this.$refs.snakerChartRef.onOpenFull(this.row.instanceProcessDefineId, this.row.instanceId)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
style: /*language=CSS*/ `
|
||||||
|
.el-descriptions-item__label {
|
||||||
|
width: 200px;
|
||||||
|
min-width: 200px;
|
||||||
|
max-width: 200px;
|
||||||
|
}
|
||||||
|
.el-tabs__header {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
`
|
||||||
|
}
|
||||||
+229
@@ -0,0 +1,229 @@
|
|||||||
|
<!--#
|
||||||
|
layout("/layouts/platform.html"){
|
||||||
|
#-->
|
||||||
|
|
||||||
|
<div id="app">
|
||||||
|
<guava ref="guava">
|
||||||
|
|
||||||
|
<el-card shadow="never">
|
||||||
|
<search @search="doSearch">
|
||||||
|
<search-item label="年度">
|
||||||
|
<el-date-picker
|
||||||
|
v-model="pageForm.year"
|
||||||
|
type="year"
|
||||||
|
value-format="yyyy"
|
||||||
|
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">
|
||||||
|
</el-input>
|
||||||
|
</search-item>
|
||||||
|
<search-item label="慰问类型">
|
||||||
|
<el-select v-model="pageForm.type" @change="doSearch" style="width: 100%"
|
||||||
|
placeholder="请选择慰问类型" filterable clearable>
|
||||||
|
<el-option v-for="item in typeOptions"
|
||||||
|
:value="item.id"
|
||||||
|
:key="item.id"
|
||||||
|
:label="item.name"
|
||||||
|
></el-option>
|
||||||
|
</el-select>
|
||||||
|
</search-item>
|
||||||
|
<search-item label="所属工会">
|
||||||
|
<el-select v-model="pageForm.unionId" placeholder="请选择所属工会" filterable clearable
|
||||||
|
@change="doSearch" style="width: 100%">
|
||||||
|
<el-option
|
||||||
|
v-for="item in unionList"
|
||||||
|
:key="item.id"
|
||||||
|
:label="item.name"
|
||||||
|
:value="item.id">
|
||||||
|
</el-option>
|
||||||
|
</el-select>
|
||||||
|
</search-item>
|
||||||
|
<search-item label="所属单位">
|
||||||
|
<el-select @change="doSearch"
|
||||||
|
clearable
|
||||||
|
filterable
|
||||||
|
placeholder="请选择单位" style="width: 100%" v-model="pageForm.unitId">
|
||||||
|
<el-option :key="item.id" :label="item.name" :value="item.id" v-for="item in unitList"></el-option>
|
||||||
|
</el-select>
|
||||||
|
</search-item>
|
||||||
|
</search>
|
||||||
|
</el-card>
|
||||||
|
|
||||||
|
<el-card shadow="never">
|
||||||
|
<table-tool label="申请列表">
|
||||||
|
<el-radio-group v-model="pageForm.approval" size="small" @change="doSearch">
|
||||||
|
<el-radio-button :label="true">已审核</el-radio-button>
|
||||||
|
<el-radio-button :label="false">未审核</el-radio-button>
|
||||||
|
</el-radio-group>
|
||||||
|
</table-tool>
|
||||||
|
<el-table :data="tableData" @sort-change="pageOrder" style="width: 100%">
|
||||||
|
<el-table-column type="index" width="50px" label="序号" :index="indexMethod"></el-table-column>
|
||||||
|
<el-table-column
|
||||||
|
:label="column.label"
|
||||||
|
:prop="column.prop"
|
||||||
|
:key="column.prop"
|
||||||
|
:width="column.width"
|
||||||
|
:sortable="column.sortable"
|
||||||
|
align="center"
|
||||||
|
header-align="center"
|
||||||
|
show-overflow-tooltip
|
||||||
|
v-for="column in tableColumns"
|
||||||
|
>
|
||||||
|
<template v-slot="{ row }" v-if="column.prop === 'instanceState'">
|
||||||
|
<enum-tag :value="row.instanceState" name="ProcessInstanceStateEnum" label_key="message" size="small"></enum-tag>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column label="操作" fixed="right" width="300px">
|
||||||
|
<template slot-scope="{row}">
|
||||||
|
<el-button @click="onView(row)" size="mini" type="primary">查看</el-button>
|
||||||
|
<el-button v-if="row.taskState === 10" @click="onAudit(row)" size="mini" type="primary">审核</el-button>
|
||||||
|
<el-button v-if="row.canRevoke" @click="onRevoke(row)" size="mini" type="danger">撤回</el-button>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
</el-table>
|
||||||
|
<!--#include("/layouts/pagination.html"){}#-->
|
||||||
|
</el-card>
|
||||||
|
|
||||||
|
<template #edit>
|
||||||
|
<specialcondolence-info ref="specialcondolenceInfoRef">
|
||||||
|
<div v-if="showApprovalForm">
|
||||||
|
<div class="process-title">
|
||||||
|
{{formData.taskName}}
|
||||||
|
</div>
|
||||||
|
<el-form :model="formData" ref="formRef" :rules="formRules" label-width="0" label-suffix=":"
|
||||||
|
class="flow-task-form">
|
||||||
|
<el-form-item label="审批意见" prop="tf_opinion"
|
||||||
|
: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_sign" :rules="[{required:true,message:'请完成审批签字',trigger:['change','blur']}]">
|
||||||
|
<pc-signature v-model="formData.tf_sign" :key="formData.processTaskId"></pc-signature>
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
<el-row type="flex" justify="end">
|
||||||
|
<el-button @click="handleTaskAction(1)" size="small" type="primary">同意申请</el-button>
|
||||||
|
<el-button @click="handleTaskAction(2)" size="small" type="danger">拒绝申请</el-button>
|
||||||
|
<el-button @click="handleTaskAction(6)" size="small" type="info">退回到发起人</el-button>
|
||||||
|
<el-button @click="$refs.guava.index()" size="small">取消</el-button>
|
||||||
|
</el-row>
|
||||||
|
</div>
|
||||||
|
</specialcondolence-info>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
</guava>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script nonce="${cspNonce!}">
|
||||||
|
<!--#include('../common/info.js'){}#-->
|
||||||
|
new Vue({
|
||||||
|
el: "#app",
|
||||||
|
store,
|
||||||
|
mixins: [initTableMixins],
|
||||||
|
components: {
|
||||||
|
"specialcondolence-info": specialcondolenceInfo
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
pageForm: {
|
||||||
|
approval: false
|
||||||
|
},
|
||||||
|
typeOptions: [],
|
||||||
|
tableColumns: [
|
||||||
|
{prop: 'subject', label: '事项'},
|
||||||
|
{prop: 'applyUserName', label: '申请人'},
|
||||||
|
{prop: 'applyUnionName', label: '所属工会'},
|
||||||
|
{prop: 'applyUnitName', label: '所属单位'},
|
||||||
|
{prop: 'typeName', label: '慰问类型'},
|
||||||
|
{prop: 'recipientCount', label: '慰问人数', width: 100},
|
||||||
|
{prop: 'curTaskName', label: '当前节点'},
|
||||||
|
{prop: 'instanceState', label: '流程状态'},
|
||||||
|
],
|
||||||
|
unionList: [],
|
||||||
|
unitList: [],
|
||||||
|
formData: {},
|
||||||
|
showApprovalForm: false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
onView(row) {
|
||||||
|
this.$refs.guava.edit(()=>{
|
||||||
|
this.showApprovalForm = false
|
||||||
|
this.$refs.specialcondolenceInfoRef.onOpen(row)
|
||||||
|
})
|
||||||
|
},
|
||||||
|
onAudit(row) {
|
||||||
|
this.$refs.guava.edit(()=>{
|
||||||
|
this.showApprovalForm = true
|
||||||
|
this.formData = {
|
||||||
|
processTaskId: row.taskId,
|
||||||
|
taskName: row.curTaskName,
|
||||||
|
tf_sign: "",
|
||||||
|
tf_opinion: ""
|
||||||
|
}
|
||||||
|
this.$refs.specialcondolenceInfoRef.onOpen(row)
|
||||||
|
})
|
||||||
|
},
|
||||||
|
async handleTaskAction(val) {
|
||||||
|
try {
|
||||||
|
const valid = await this.$refs.formRef.validate()
|
||||||
|
if (!valid) return
|
||||||
|
} catch (error) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
this.$confirm("您确定要提交吗?", "提示", {
|
||||||
|
confirmButtonText: "确定",
|
||||||
|
cancelButtonText: "取消",
|
||||||
|
type: "warning"
|
||||||
|
}).then(() => {
|
||||||
|
this.$axios.post("/platform/special_condolence/approval/executeTask", {
|
||||||
|
data: JSON.stringify({
|
||||||
|
...this.formData,
|
||||||
|
submitType: val
|
||||||
|
})
|
||||||
|
}).then((res) => {
|
||||||
|
if (res.code === 0) {
|
||||||
|
this.$refs.guava.index()
|
||||||
|
this.$message.success(res.msg)
|
||||||
|
this.doSearch()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
},
|
||||||
|
onRevoke(row) {
|
||||||
|
this.$confirm("您确定要撤回吗?", "提示", {
|
||||||
|
confirmButtonText: "确定",
|
||||||
|
cancelButtonText: "取消",
|
||||||
|
type: "info"
|
||||||
|
}).then(() => {
|
||||||
|
this.$axios.post("/flow/common/revokeTask", {taskId: row.taskId}).then((res) => {
|
||||||
|
if (res.code === 0) {
|
||||||
|
this.$message.success(res.msg)
|
||||||
|
this.doSearch()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
},
|
||||||
|
querySpecialCondolenceType() {
|
||||||
|
this.$axios.post('/platform/special_condolence/type/querySpecialCondolenceType')
|
||||||
|
.then((resp) => {
|
||||||
|
this.typeOptions = resp.data
|
||||||
|
})
|
||||||
|
},
|
||||||
|
},
|
||||||
|
async created() {
|
||||||
|
this.unionList = await this.$businessTool.listUnion()
|
||||||
|
this.unitList = await this.$businessTool.listUnit()
|
||||||
|
this.querySpecialCondolenceType()
|
||||||
|
this.pageData()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<!--#
|
||||||
|
}
|
||||||
|
#-->
|
||||||
+165
@@ -0,0 +1,165 @@
|
|||||||
|
<!--#
|
||||||
|
layout("/layouts/platform.html"){
|
||||||
|
#-->
|
||||||
|
<div id="app">
|
||||||
|
<guava ref="guava">
|
||||||
|
<el-card shadow="never">
|
||||||
|
<search @search="doSearch">
|
||||||
|
<search-item label="年度">
|
||||||
|
<el-date-picker
|
||||||
|
v-model="pageForm.year"
|
||||||
|
type="year"
|
||||||
|
value-format="yyyy"
|
||||||
|
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">
|
||||||
|
</el-input>
|
||||||
|
</search-item>
|
||||||
|
<search-item label="慰问类型">
|
||||||
|
<el-select v-model="pageForm.type" @change="doSearch" style="width: 100%"
|
||||||
|
placeholder="请选择慰问类型" filterable clearable>
|
||||||
|
<el-option v-for="item in typeOptions"
|
||||||
|
:value="item.id"
|
||||||
|
:key="item.id"
|
||||||
|
:label="item.name"
|
||||||
|
></el-option>
|
||||||
|
</el-select>
|
||||||
|
</search-item>
|
||||||
|
</search>
|
||||||
|
</el-card>
|
||||||
|
|
||||||
|
<el-card shadow="never">
|
||||||
|
<table-tool label="申请列表">
|
||||||
|
<el-button type="primary" size="small" @click="onAdd">
|
||||||
|
<i class="ti-plus"></i>
|
||||||
|
新增申请
|
||||||
|
</el-button>
|
||||||
|
</table-tool>
|
||||||
|
<el-table :data="tableData" @sort-change="pageOrder" style="width: 100%">
|
||||||
|
<el-table-column type="index" width="50px" label="序号" :index="indexMethod"></el-table-column>
|
||||||
|
<el-table-column
|
||||||
|
:label="column.label"
|
||||||
|
:prop="column.prop"
|
||||||
|
:key="column.prop"
|
||||||
|
:width="column.width"
|
||||||
|
:sortable="column.sortable"
|
||||||
|
align="center"
|
||||||
|
header-align="center"
|
||||||
|
show-overflow-tooltip
|
||||||
|
v-for="column in tableColumns"
|
||||||
|
>
|
||||||
|
<template v-slot="{ row }" v-if="column.prop === 'instanceState'">
|
||||||
|
<enum-tag :value="row.instanceState" name="ProcessInstanceStateEnum" label_key="message" size="small"></enum-tag>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<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.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.createdBy === $store.state.user.id && row.instanceState == 20" @click="doExportApply(row)" size="mini" type="primary">导出</el-button>
|
||||||
|
<el-button v-if="row.taskKey === 'startTask' || !row.instanceId" @click="onDelete(row.id)" size="mini" type="danger">
|
||||||
|
删除
|
||||||
|
</el-button>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
</el-table>
|
||||||
|
<!--#include("/layouts/pagination.html"){}#-->
|
||||||
|
</el-card>
|
||||||
|
|
||||||
|
<template #view>
|
||||||
|
<specialcondolence-info ref="specialcondolenceInfoRef"></specialcondolence-info>
|
||||||
|
</template>
|
||||||
|
</guava>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script nonce="${cspNonce!}">
|
||||||
|
<!--#include('../common/info.js'){}#-->
|
||||||
|
new Vue({
|
||||||
|
el: "#app",
|
||||||
|
store,
|
||||||
|
mixins: [initTableMixins],
|
||||||
|
components: {
|
||||||
|
"specialcondolence-info": specialcondolenceInfo
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
typeOptions: [],
|
||||||
|
pageDataUrl: "/platform/special_condolence/mine/pageData",
|
||||||
|
tableColumns: [
|
||||||
|
{prop: 'subject', label: '事项'},
|
||||||
|
{prop: 'applyUserName', label: '申请人'},
|
||||||
|
{prop: 'applyUnionName', label: '所属工会'},
|
||||||
|
{prop: 'applyUnitName', label: '所属单位'},
|
||||||
|
{prop: 'typeName', label: '慰问类型'},
|
||||||
|
{prop: 'recipientCount', label: '慰问人数', width: 100},
|
||||||
|
{prop: 'taskName', label: '当前节点'},
|
||||||
|
{prop: 'instanceState', label: '流程状态'},
|
||||||
|
],
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
doExportApply(row) {
|
||||||
|
this.$downLoad('/platform/special_condolence/mine/doExportApply?id=' + row.id + '&print=false')
|
||||||
|
},
|
||||||
|
onAdd() {
|
||||||
|
commonUtil.pjaxPush('/platform/special_condolence/apply')
|
||||||
|
},
|
||||||
|
onView(row) {
|
||||||
|
this.$refs.guava.view(()=>{
|
||||||
|
this.$refs.specialcondolenceInfoRef.onOpen(row)
|
||||||
|
})
|
||||||
|
},
|
||||||
|
onEdit(row) {
|
||||||
|
commonUtil.pjaxPush('/platform/special_condolence/apply?taskId=' + (row.startTaskId || '') + "&bizId=" + row.id)
|
||||||
|
},
|
||||||
|
onRevoke(row) {
|
||||||
|
this.$confirm("您确定要撤回吗?", "提示", {
|
||||||
|
confirmButtonText: "确定",
|
||||||
|
cancelButtonText: "取消",
|
||||||
|
type: "warning"
|
||||||
|
}).then(() => {
|
||||||
|
this.$axios.post("/flow/common/revokeTask", { taskId: row.startTaskId }).then((res) => {
|
||||||
|
if (res.code === 0) {
|
||||||
|
this.$message.success(res.msg)
|
||||||
|
this.pageData()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
},
|
||||||
|
onDelete(id) {
|
||||||
|
this.$confirm("您确定要删除吗?", "提示", {
|
||||||
|
confirmButtonText: "确定",
|
||||||
|
cancelButtonText: "取消",
|
||||||
|
type: "warning"
|
||||||
|
}).then(() => {
|
||||||
|
this.$axios.post("/platform/special_condolence/mine/delete", { id }).then((res) => {
|
||||||
|
if (res.code === 0) {
|
||||||
|
this.$message.success(res.msg)
|
||||||
|
this.pageData()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
},
|
||||||
|
querySpecialCondolenceType() {
|
||||||
|
this.$axios.post('/platform/special_condolence/type/querySpecialCondolenceType')
|
||||||
|
.then((resp) => {
|
||||||
|
this.typeOptions = resp.data
|
||||||
|
})
|
||||||
|
},
|
||||||
|
},
|
||||||
|
created() {
|
||||||
|
this.querySpecialCondolenceType()
|
||||||
|
this.pageData()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<!--#
|
||||||
|
}
|
||||||
|
#-->
|
||||||
+161
@@ -0,0 +1,161 @@
|
|||||||
|
<!--#
|
||||||
|
layout("/layouts/platform.html"){
|
||||||
|
#-->
|
||||||
|
|
||||||
|
<div id="app">
|
||||||
|
<guava ref="guava">
|
||||||
|
<el-card shadow="never">
|
||||||
|
<search @search="doSearch">
|
||||||
|
<search-item label="年度">
|
||||||
|
<el-date-picker
|
||||||
|
v-model="pageForm.year"
|
||||||
|
type="year"
|
||||||
|
value-format="yyyy"
|
||||||
|
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">
|
||||||
|
</el-input>
|
||||||
|
</search-item>
|
||||||
|
<search-item label="慰问类型">
|
||||||
|
<el-select v-model="pageForm.type" @change="doSearch" style="width: 100%"
|
||||||
|
placeholder="请选择慰问类型" filterable clearable>
|
||||||
|
<el-option v-for="item in typeOptions"
|
||||||
|
:value="item.id"
|
||||||
|
:key="item.id"
|
||||||
|
:label="item.name"
|
||||||
|
></el-option>
|
||||||
|
</el-select>
|
||||||
|
</search-item>
|
||||||
|
<search-item label="所属工会">
|
||||||
|
<el-select v-model="pageForm.unionId" placeholder="请选择所属工会" filterable clearable
|
||||||
|
@change="doSearch" style="width: 100%">
|
||||||
|
<el-option
|
||||||
|
v-for="item in unionList"
|
||||||
|
:key="item.id"
|
||||||
|
:label="item.name"
|
||||||
|
:value="item.id">
|
||||||
|
</el-option>
|
||||||
|
</el-select>
|
||||||
|
</search-item>
|
||||||
|
<search-item label="所属单位">
|
||||||
|
<el-select @change="doSearch"
|
||||||
|
clearable
|
||||||
|
filterable
|
||||||
|
placeholder="请选择单位" style="width: 100%" v-model="pageForm.unitId">
|
||||||
|
<el-option :key="item.id" :label="item.name" :value="item.id" v-for="item in unitList"></el-option>
|
||||||
|
</el-select>
|
||||||
|
</search-item>
|
||||||
|
</search>
|
||||||
|
</el-card>
|
||||||
|
|
||||||
|
<el-card shadow="never">
|
||||||
|
<table-tool label="申请列表">
|
||||||
|
<el-button @click="onExport" icon="el-icon-s-promotion" type="primary" size="small">导出</el-button>
|
||||||
|
</table-tool>
|
||||||
|
<el-table :data="tableData" @sort-change="pageOrder" style="width: 100%">
|
||||||
|
<el-table-column type="index" width="50px" label="序号" :index="indexMethod"></el-table-column>
|
||||||
|
<el-table-column
|
||||||
|
:label="column.label"
|
||||||
|
:prop="column.prop"
|
||||||
|
:key="column.prop"
|
||||||
|
:width="column.width"
|
||||||
|
:sortable="column.sortable"
|
||||||
|
align="center"
|
||||||
|
header-align="center"
|
||||||
|
show-overflow-tooltip
|
||||||
|
v-for="column in tableColumns"
|
||||||
|
>
|
||||||
|
<template v-slot="{ row }" v-if="column.prop === 'instanceState'">
|
||||||
|
<enum-tag :value="row.instanceState" name="ProcessInstanceStateEnum" label_key="message" size="small"></enum-tag>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column label="操作" fixed="right" width="180">
|
||||||
|
<template slot-scope="{row}">
|
||||||
|
<el-button @click="onView(row)" size="mini" type="primary">查看</el-button>
|
||||||
|
<el-button v-if="$auth.hasRoleOr('SYSADMIN, SCHOOL_UNION_ADMIN')" @click="onDelete(row.id)" size="mini" type="danger">
|
||||||
|
删除
|
||||||
|
</el-button>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
</el-table>
|
||||||
|
<!--#include("/layouts/pagination.html"){}#-->
|
||||||
|
</el-card>
|
||||||
|
|
||||||
|
<template #edit>
|
||||||
|
<specialcondolence-info ref="specialcondolenceInfoRef"></specialcondolence-info>
|
||||||
|
</template>
|
||||||
|
</guava>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script nonce="${cspNonce!}">
|
||||||
|
<!--#include('../common/info.js'){}#-->
|
||||||
|
new Vue({
|
||||||
|
el: "#app",
|
||||||
|
store,
|
||||||
|
mixins: [initTableMixins],
|
||||||
|
components: {
|
||||||
|
"specialcondolence-info": specialcondolenceInfo
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
typeOptions: [],
|
||||||
|
tableColumns: [
|
||||||
|
{prop: 'subject', label: '事项'},
|
||||||
|
{prop: 'applyUserName', label: '申请人'},
|
||||||
|
{prop: 'applyUnionName', label: '所属工会'},
|
||||||
|
{prop: 'applyUnitName', label: '所属单位'},
|
||||||
|
{prop: 'typeName', label: '慰问类型'},
|
||||||
|
{prop: 'taskName', label: '当前节点'},
|
||||||
|
{prop: 'instanceState', label: '流程状态'},
|
||||||
|
],
|
||||||
|
unionList: [],
|
||||||
|
unitList: [],
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
onDelete(id) {
|
||||||
|
this.$confirm("您确定要删除吗?", "提示", {
|
||||||
|
confirmButtonText: "确定",
|
||||||
|
cancelButtonText: "取消",
|
||||||
|
type: "warning"
|
||||||
|
}).then(() => {
|
||||||
|
this.$axios.post("/platform/special_condolence/mine/delete", { id }).then((res) => {
|
||||||
|
if (res.code === 0) {
|
||||||
|
this.$message.success(res.msg)
|
||||||
|
this.pageData()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
},
|
||||||
|
onExport() {
|
||||||
|
this.$downLoad(loc() + '/onExport', this.pageForm)
|
||||||
|
},
|
||||||
|
onView(row) {
|
||||||
|
this.$refs.guava.edit(()=>{
|
||||||
|
this.$refs.specialcondolenceInfoRef.onOpen(row)
|
||||||
|
})
|
||||||
|
},
|
||||||
|
querySpecialCondolenceType() {
|
||||||
|
this.$axios.post('/platform/special_condolence/type/querySpecialCondolenceType')
|
||||||
|
.then((resp) => {
|
||||||
|
this.typeOptions = resp.data
|
||||||
|
})
|
||||||
|
},
|
||||||
|
},
|
||||||
|
async created() {
|
||||||
|
this.unionList = await this.$businessTool.listUnion()
|
||||||
|
this.unitList = await this.$businessTool.listUnit()
|
||||||
|
this.querySpecialCondolenceType()
|
||||||
|
this.pageData()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<!--#
|
||||||
|
}
|
||||||
|
#-->
|
||||||
+229
@@ -0,0 +1,229 @@
|
|||||||
|
<!--#
|
||||||
|
layout("/layouts/platform.html"){
|
||||||
|
#-->
|
||||||
|
|
||||||
|
<div id="app">
|
||||||
|
<guava ref="guava">
|
||||||
|
|
||||||
|
<el-card shadow="never">
|
||||||
|
<search @search="doSearch">
|
||||||
|
<search-item label="年度">
|
||||||
|
<el-date-picker
|
||||||
|
v-model="pageForm.year"
|
||||||
|
type="year"
|
||||||
|
value-format="yyyy"
|
||||||
|
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">
|
||||||
|
</el-input>
|
||||||
|
</search-item>
|
||||||
|
<search-item label="慰问类型">
|
||||||
|
<el-select v-model="pageForm.type" @change="doSearch" style="width: 100%"
|
||||||
|
placeholder="请选择慰问类型" filterable clearable>
|
||||||
|
<el-option v-for="item in typeOptions"
|
||||||
|
:value="item.id"
|
||||||
|
:key="item.id"
|
||||||
|
:label="item.name"
|
||||||
|
></el-option>
|
||||||
|
</el-select>
|
||||||
|
</search-item>
|
||||||
|
<search-item label="所属工会">
|
||||||
|
<el-select v-model="pageForm.unionId" placeholder="请选择所属工会" filterable clearable
|
||||||
|
@change="doSearch" style="width: 100%">
|
||||||
|
<el-option
|
||||||
|
v-for="item in unionList"
|
||||||
|
:key="item.id"
|
||||||
|
:label="item.name"
|
||||||
|
:value="item.id">
|
||||||
|
</el-option>
|
||||||
|
</el-select>
|
||||||
|
</search-item>
|
||||||
|
<search-item label="所属单位">
|
||||||
|
<el-select @change="doSearch"
|
||||||
|
clearable
|
||||||
|
filterable
|
||||||
|
placeholder="请选择单位" style="width: 100%" v-model="pageForm.unitId">
|
||||||
|
<el-option :key="item.id" :label="item.name" :value="item.id" v-for="item in unitList"></el-option>
|
||||||
|
</el-select>
|
||||||
|
</search-item>
|
||||||
|
</search>
|
||||||
|
</el-card>
|
||||||
|
|
||||||
|
<el-card shadow="never">
|
||||||
|
<table-tool label="申请列表">
|
||||||
|
<el-radio-group v-model="pageForm.approval" size="small" @change="doSearch">
|
||||||
|
<el-radio-button :label="true">已审核</el-radio-button>
|
||||||
|
<el-radio-button :label="false">未审核</el-radio-button>
|
||||||
|
</el-radio-group>
|
||||||
|
</table-tool>
|
||||||
|
<el-table :data="tableData" @sort-change="pageOrder" style="width: 100%">
|
||||||
|
<el-table-column type="index" width="50px" label="序号" :index="indexMethod"></el-table-column>
|
||||||
|
<el-table-column
|
||||||
|
:label="column.label"
|
||||||
|
:prop="column.prop"
|
||||||
|
:key="column.prop"
|
||||||
|
:width="column.width"
|
||||||
|
:sortable="column.sortable"
|
||||||
|
align="center"
|
||||||
|
header-align="center"
|
||||||
|
show-overflow-tooltip
|
||||||
|
v-for="column in tableColumns"
|
||||||
|
>
|
||||||
|
<template v-slot="{ row }" v-if="column.prop === 'instanceState'">
|
||||||
|
<enum-tag :value="row.instanceState" name="ProcessInstanceStateEnum" label_key="message" size="small"></enum-tag>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column label="操作" fixed="right" width="300px">
|
||||||
|
<template slot-scope="{row}">
|
||||||
|
<el-button @click="onView(row)" size="mini" type="primary">查看</el-button>
|
||||||
|
<el-button v-if="row.taskState === 10" @click="onAudit(row)" size="mini" type="primary">审核</el-button>
|
||||||
|
<el-button v-if="row.canRevoke" @click="onRevoke(row)" size="mini" type="danger">撤回</el-button>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
</el-table>
|
||||||
|
<!--#include("/layouts/pagination.html"){}#-->
|
||||||
|
</el-card>
|
||||||
|
|
||||||
|
<template #edit>
|
||||||
|
<specialcondolence-info ref="specialcondolenceInfoRef">
|
||||||
|
<div v-if="showApprovalForm">
|
||||||
|
<div class="process-title">
|
||||||
|
{{formData.taskName}}
|
||||||
|
</div>
|
||||||
|
<el-form :model="formData" ref="formRef" :rules="formRules" label-width="0" label-suffix=":"
|
||||||
|
class="flow-task-form">
|
||||||
|
<el-form-item label="审批意见" prop="tf_opinion"
|
||||||
|
: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_sign" :rules="[{required:true,message:'请完成审批签字',trigger:['change','blur']}]">
|
||||||
|
<pc-signature v-model="formData.tf_sign" :key="formData.processTaskId"></pc-signature>
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
<el-row type="flex" justify="end">
|
||||||
|
<el-button @click="handleTaskAction(1)" size="small" type="primary">同意申请</el-button>
|
||||||
|
<el-button @click="handleTaskAction(2)" size="small" type="danger">拒绝申请</el-button>
|
||||||
|
<el-button @click="handleTaskAction(6)" size="small" type="info">退回到发起人</el-button>
|
||||||
|
<el-button @click="$refs.guava.index()" size="small">取消</el-button>
|
||||||
|
</el-row>
|
||||||
|
</div>
|
||||||
|
</specialcondolence-info>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
</guava>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script nonce="${cspNonce!}">
|
||||||
|
<!--#include('../common/info.js'){}#-->
|
||||||
|
new Vue({
|
||||||
|
el: "#app",
|
||||||
|
store,
|
||||||
|
mixins: [initTableMixins],
|
||||||
|
components: {
|
||||||
|
"specialcondolence-info": specialcondolenceInfo
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
pageForm: {
|
||||||
|
approval: false
|
||||||
|
},
|
||||||
|
typeOptions: [],
|
||||||
|
tableColumns: [
|
||||||
|
{prop: 'subject', label: '事项'},
|
||||||
|
{prop: 'applyUserName', label: '申请人'},
|
||||||
|
{prop: 'applyUnionName', label: '所属工会'},
|
||||||
|
{prop: 'applyUnitName', label: '所属单位'},
|
||||||
|
{prop: 'typeName', label: '慰问类型'},
|
||||||
|
{prop: 'recipientCount', label: '慰问人数', width: 100},
|
||||||
|
{prop: 'curTaskName', label: '当前节点'},
|
||||||
|
{prop: 'instanceState', label: '流程状态'},
|
||||||
|
],
|
||||||
|
unionList: [],
|
||||||
|
unitList: [],
|
||||||
|
formData: {},
|
||||||
|
showApprovalForm: false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
onView(row) {
|
||||||
|
this.$refs.guava.edit(()=>{
|
||||||
|
this.showApprovalForm = false
|
||||||
|
this.$refs.specialcondolenceInfoRef.onOpen(row)
|
||||||
|
})
|
||||||
|
},
|
||||||
|
onAudit(row) {
|
||||||
|
this.$refs.guava.edit(()=>{
|
||||||
|
this.showApprovalForm = true
|
||||||
|
this.formData = {
|
||||||
|
processTaskId: row.taskId,
|
||||||
|
taskName: row.curTaskName,
|
||||||
|
tf_sign: "",
|
||||||
|
tf_opinion: ""
|
||||||
|
}
|
||||||
|
this.$refs.specialcondolenceInfoRef.onOpen(row)
|
||||||
|
})
|
||||||
|
},
|
||||||
|
async handleTaskAction(val) {
|
||||||
|
try {
|
||||||
|
const valid = await this.$refs.formRef.validate()
|
||||||
|
if (!valid) return
|
||||||
|
} catch (error) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
this.$confirm("您确定要提交吗?", "提示", {
|
||||||
|
confirmButtonText: "确定",
|
||||||
|
cancelButtonText: "取消",
|
||||||
|
type: "warning"
|
||||||
|
}).then(() => {
|
||||||
|
this.$axios.post("/platform/special_condolence/approval/executeTask", {
|
||||||
|
data: JSON.stringify({
|
||||||
|
...this.formData,
|
||||||
|
submitType: val
|
||||||
|
})
|
||||||
|
}).then((res) => {
|
||||||
|
if (res.code === 0) {
|
||||||
|
this.$refs.guava.index()
|
||||||
|
this.$message.success(res.msg)
|
||||||
|
this.doSearch()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
},
|
||||||
|
onRevoke(row) {
|
||||||
|
this.$confirm("您确定要撤回吗?", "提示", {
|
||||||
|
confirmButtonText: "确定",
|
||||||
|
cancelButtonText: "取消",
|
||||||
|
type: "info"
|
||||||
|
}).then(() => {
|
||||||
|
this.$axios.post("/flow/common/revokeTask", {taskId: row.taskId}).then((res) => {
|
||||||
|
if (res.code === 0) {
|
||||||
|
this.$message.success(res.msg)
|
||||||
|
this.doSearch()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
},
|
||||||
|
querySpecialCondolenceType() {
|
||||||
|
this.$axios.post('/platform/special_condolence/type/querySpecialCondolenceType')
|
||||||
|
.then((resp) => {
|
||||||
|
this.typeOptions = resp.data
|
||||||
|
})
|
||||||
|
},
|
||||||
|
},
|
||||||
|
async created() {
|
||||||
|
this.unionList = await this.$businessTool.listUnion()
|
||||||
|
this.unitList = await this.$businessTool.listUnit()
|
||||||
|
this.querySpecialCondolenceType()
|
||||||
|
this.pageData()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<!--#
|
||||||
|
}
|
||||||
|
#-->
|
||||||
+229
@@ -0,0 +1,229 @@
|
|||||||
|
<!--#
|
||||||
|
layout("/layouts/platform.html"){
|
||||||
|
#-->
|
||||||
|
|
||||||
|
<div id="app">
|
||||||
|
<guava ref="guava">
|
||||||
|
|
||||||
|
<el-card shadow="never">
|
||||||
|
<search @search="doSearch">
|
||||||
|
<search-item label="年度">
|
||||||
|
<el-date-picker
|
||||||
|
v-model="pageForm.year"
|
||||||
|
type="year"
|
||||||
|
value-format="yyyy"
|
||||||
|
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">
|
||||||
|
</el-input>
|
||||||
|
</search-item>
|
||||||
|
<search-item label="慰问类型">
|
||||||
|
<el-select v-model="pageForm.type" @change="doSearch" style="width: 100%"
|
||||||
|
placeholder="请选择慰问类型" filterable clearable>
|
||||||
|
<el-option v-for="item in typeOptions"
|
||||||
|
:value="item.id"
|
||||||
|
:key="item.id"
|
||||||
|
:label="item.name"
|
||||||
|
></el-option>
|
||||||
|
</el-select>
|
||||||
|
</search-item>
|
||||||
|
<search-item label="所属工会">
|
||||||
|
<el-select v-model="pageForm.unionId" placeholder="请选择所属工会" filterable clearable
|
||||||
|
@change="doSearch" style="width: 100%">
|
||||||
|
<el-option
|
||||||
|
v-for="item in unionList"
|
||||||
|
:key="item.id"
|
||||||
|
:label="item.name"
|
||||||
|
:value="item.id">
|
||||||
|
</el-option>
|
||||||
|
</el-select>
|
||||||
|
</search-item>
|
||||||
|
<search-item label="所属单位">
|
||||||
|
<el-select @change="doSearch"
|
||||||
|
clearable
|
||||||
|
filterable
|
||||||
|
placeholder="请选择单位" style="width: 100%" v-model="pageForm.unitId">
|
||||||
|
<el-option :key="item.id" :label="item.name" :value="item.id" v-for="item in unitList"></el-option>
|
||||||
|
</el-select>
|
||||||
|
</search-item>
|
||||||
|
</search>
|
||||||
|
</el-card>
|
||||||
|
|
||||||
|
<el-card shadow="never">
|
||||||
|
<table-tool label="申请列表">
|
||||||
|
<el-radio-group v-model="pageForm.approval" size="small" @change="doSearch">
|
||||||
|
<el-radio-button :label="true">已审核</el-radio-button>
|
||||||
|
<el-radio-button :label="false">未审核</el-radio-button>
|
||||||
|
</el-radio-group>
|
||||||
|
</table-tool>
|
||||||
|
<el-table :data="tableData" @sort-change="pageOrder" style="width: 100%">
|
||||||
|
<el-table-column type="index" width="50px" label="序号" :index="indexMethod"></el-table-column>
|
||||||
|
<el-table-column
|
||||||
|
:label="column.label"
|
||||||
|
:prop="column.prop"
|
||||||
|
:key="column.prop"
|
||||||
|
:width="column.width"
|
||||||
|
:sortable="column.sortable"
|
||||||
|
align="center"
|
||||||
|
header-align="center"
|
||||||
|
show-overflow-tooltip
|
||||||
|
v-for="column in tableColumns"
|
||||||
|
>
|
||||||
|
<template v-slot="{ row }" v-if="column.prop === 'instanceState'">
|
||||||
|
<enum-tag :value="row.instanceState" name="ProcessInstanceStateEnum" label_key="message" size="small"></enum-tag>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column label="操作" fixed="right" width="300px">
|
||||||
|
<template slot-scope="{row}">
|
||||||
|
<el-button @click="onView(row)" size="mini" type="primary">查看</el-button>
|
||||||
|
<el-button v-if="row.taskState === 10" @click="onAudit(row)" size="mini" type="primary">审核</el-button>
|
||||||
|
<el-button v-if="row.canRevoke" @click="onRevoke(row)" size="mini" type="danger">撤回</el-button>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
</el-table>
|
||||||
|
<!--#include("/layouts/pagination.html"){}#-->
|
||||||
|
</el-card>
|
||||||
|
|
||||||
|
<template #edit>
|
||||||
|
<specialcondolence-info ref="specialcondolenceInfoRef">
|
||||||
|
<div v-if="showApprovalForm">
|
||||||
|
<div class="process-title">
|
||||||
|
{{formData.taskName}}
|
||||||
|
</div>
|
||||||
|
<el-form :model="formData" ref="formRef" :rules="formRules" label-width="0" label-suffix=":"
|
||||||
|
class="flow-task-form">
|
||||||
|
<el-form-item label="审批意见" prop="tf_opinion"
|
||||||
|
: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_sign" :rules="[{required:true,message:'请完成审批签字',trigger:['change','blur']}]">
|
||||||
|
<pc-signature v-model="formData.tf_sign" :key="formData.processTaskId"></pc-signature>
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
<el-row type="flex" justify="end">
|
||||||
|
<el-button @click="handleTaskAction(1)" size="small" type="primary">同意申请</el-button>
|
||||||
|
<el-button @click="handleTaskAction(2)" size="small" type="danger">拒绝申请</el-button>
|
||||||
|
<el-button @click="handleTaskAction(6)" size="small" type="info">退回到发起人</el-button>
|
||||||
|
<el-button @click="$refs.guava.index()" size="small">取消</el-button>
|
||||||
|
</el-row>
|
||||||
|
</div>
|
||||||
|
</specialcondolence-info>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
</guava>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script nonce="${cspNonce!}">
|
||||||
|
<!--#include('../common/info.js'){}#-->
|
||||||
|
new Vue({
|
||||||
|
el: "#app",
|
||||||
|
store,
|
||||||
|
mixins: [initTableMixins],
|
||||||
|
components: {
|
||||||
|
"specialcondolence-info": specialcondolenceInfo
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
pageForm: {
|
||||||
|
approval: false
|
||||||
|
},
|
||||||
|
typeOptions: [],
|
||||||
|
tableColumns: [
|
||||||
|
{prop: 'subject', label: '事项'},
|
||||||
|
{prop: 'applyUserName', label: '申请人'},
|
||||||
|
{prop: 'applyUnionName', label: '所属工会'},
|
||||||
|
{prop: 'applyUnitName', label: '所属单位'},
|
||||||
|
{prop: 'typeName', label: '慰问类型'},
|
||||||
|
{prop: 'recipientCount', label: '慰问人数', width: 100},
|
||||||
|
{prop: 'curTaskName', label: '当前节点'},
|
||||||
|
{prop: 'instanceState', label: '流程状态'},
|
||||||
|
],
|
||||||
|
unionList: [],
|
||||||
|
unitList: [],
|
||||||
|
formData: {},
|
||||||
|
showApprovalForm: false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
onView(row) {
|
||||||
|
this.$refs.guava.edit(()=>{
|
||||||
|
this.showApprovalForm = false
|
||||||
|
this.$refs.specialcondolenceInfoRef.onOpen(row)
|
||||||
|
})
|
||||||
|
},
|
||||||
|
onAudit(row) {
|
||||||
|
this.$refs.guava.edit(()=>{
|
||||||
|
this.showApprovalForm = true
|
||||||
|
this.formData = {
|
||||||
|
processTaskId: row.taskId,
|
||||||
|
taskName: row.curTaskName,
|
||||||
|
tf_sign: "",
|
||||||
|
tf_opinion: ""
|
||||||
|
}
|
||||||
|
this.$refs.specialcondolenceInfoRef.onOpen(row)
|
||||||
|
})
|
||||||
|
},
|
||||||
|
async handleTaskAction(val) {
|
||||||
|
try {
|
||||||
|
const valid = await this.$refs.formRef.validate()
|
||||||
|
if (!valid) return
|
||||||
|
} catch (error) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
this.$confirm("您确定要提交吗?", "提示", {
|
||||||
|
confirmButtonText: "确定",
|
||||||
|
cancelButtonText: "取消",
|
||||||
|
type: "warning"
|
||||||
|
}).then(() => {
|
||||||
|
this.$axios.post("/platform/special_condolence/approval/executeTask", {
|
||||||
|
data: JSON.stringify({
|
||||||
|
...this.formData,
|
||||||
|
submitType: val
|
||||||
|
})
|
||||||
|
}).then((res) => {
|
||||||
|
if (res.code === 0) {
|
||||||
|
this.$refs.guava.index()
|
||||||
|
this.$message.success(res.msg)
|
||||||
|
this.doSearch()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
},
|
||||||
|
onRevoke(row) {
|
||||||
|
this.$confirm("您确定要撤回吗?", "提示", {
|
||||||
|
confirmButtonText: "确定",
|
||||||
|
cancelButtonText: "取消",
|
||||||
|
type: "info"
|
||||||
|
}).then(() => {
|
||||||
|
this.$axios.post("/flow/common/revokeTask", {taskId: row.taskId}).then((res) => {
|
||||||
|
if (res.code === 0) {
|
||||||
|
this.$message.success(res.msg)
|
||||||
|
this.doSearch()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
},
|
||||||
|
querySpecialCondolenceType() {
|
||||||
|
this.$axios.post('/platform/special_condolence/type/querySpecialCondolenceType')
|
||||||
|
.then((resp) => {
|
||||||
|
this.typeOptions = resp.data
|
||||||
|
})
|
||||||
|
},
|
||||||
|
},
|
||||||
|
async created() {
|
||||||
|
this.unionList = await this.$businessTool.listUnion()
|
||||||
|
this.unitList = await this.$businessTool.listUnit()
|
||||||
|
this.querySpecialCondolenceType()
|
||||||
|
this.pageData()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<!--#
|
||||||
|
}
|
||||||
|
#-->
|
||||||
+101
@@ -0,0 +1,101 @@
|
|||||||
|
const basicForm = {
|
||||||
|
template: /*language=HTML*/ `
|
||||||
|
<div>
|
||||||
|
<el-form :model="formData" ref="formRef" :rules="formRules" label-width="110px" label-position="left">
|
||||||
|
<el-form-item label="类型编码" prop="code">
|
||||||
|
<el-input type="text" v-model="formData.code" maxlength="50"
|
||||||
|
placeholder="请填写类型编码"></el-input>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="类型名称" prop="name">
|
||||||
|
<el-input type="text" v-model="formData.name" maxlength="50"
|
||||||
|
placeholder="请填写类型名称"></el-input>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="慰问费用" prop="money">
|
||||||
|
<el-input-number style="width: 100%" v-model="formData.money"
|
||||||
|
placeholder="请填写慰问费用" controls-position="right" :controls="false"
|
||||||
|
precision="2"
|
||||||
|
:min="0"
|
||||||
|
:max="10000"></el-input-number>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="慰问方式" prop="way">
|
||||||
|
<el-radio-group v-model="formData.way">
|
||||||
|
<el-radio-button label="慰问金 (A)" border>慰问金 (A)</el-radio-button>
|
||||||
|
<el-radio-button label="提货券 (B)" border>提货券 (B)</el-radio-button>
|
||||||
|
<el-radio-button label="慰问品 (C)" border>慰问品 (C)</el-radio-button>
|
||||||
|
</el-radio-group>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="是否启用" prop="enable">
|
||||||
|
<el-switch
|
||||||
|
v-model="formData.enable"
|
||||||
|
active-color="#13ce66"
|
||||||
|
inactive-color="#ff4949">
|
||||||
|
</el-switch>
|
||||||
|
</el-form-item>
|
||||||
|
<!--<el-form-item label="上传会议纪要" prop="uploadMeetingRecord">
|
||||||
|
<el-radio-group v-model="formData.uploadMeetingRecord">
|
||||||
|
<el-radio-button :label="true">上传</el-radio-button>
|
||||||
|
<el-radio-button :label="false">不上传</el-radio-button>
|
||||||
|
</el-radio-group>
|
||||||
|
</el-form-item>-->
|
||||||
|
<el-form-item label="是否上传附件" prop="isUploadFile">
|
||||||
|
<el-radio-group v-model="formData.isUploadFile">
|
||||||
|
<el-radio-button :label="true">是</el-radio-button>
|
||||||
|
<el-radio-button :label="false">否</el-radio-button>
|
||||||
|
</el-radio-group>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="上传附件说明" prop="uploadFileDesc" v-if="formData.isUploadFile">
|
||||||
|
<el-input v-model="formData.uploadFileDesc" maxlength="50" clearable placeholder="请填写上传附件说明"></el-input>
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
<el-row class="mt10" justify="end" type="flex">
|
||||||
|
<el-button @click="$emit('refresh')">取消</el-button>
|
||||||
|
<el-button @click="onSubmit" type="primary">提交</el-button>
|
||||||
|
</el-row>
|
||||||
|
</div>
|
||||||
|
`,
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
formData: { isUploadFile: false },
|
||||||
|
formRules: {
|
||||||
|
name: [{required: true, message: '必填', trigger: ['blur', 'change']}],
|
||||||
|
money: [{required: true, message: '必填', trigger: ['blur', 'change']}],
|
||||||
|
way: [{required: true, message: '必填', trigger: ['blur', 'change']}],
|
||||||
|
code: [{required: true, message: '必填', trigger: ['blur', 'change']}],
|
||||||
|
isUploadFile: [{required: true, message: '必填', trigger: ['blur', 'change']}],
|
||||||
|
},
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
onOpen(row) {
|
||||||
|
if(row && row.id) {
|
||||||
|
this.formData = clone(row)
|
||||||
|
} else {
|
||||||
|
this.formData = { isUploadFile: false }
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onSubmit() {
|
||||||
|
this.$refs.formRef.validate((valid) => {
|
||||||
|
if (valid) {
|
||||||
|
this.$confirm("您确定要提交吗?", "提示", {
|
||||||
|
confirmButtonText: "确定",
|
||||||
|
cancelButtonText: "取消",
|
||||||
|
type: "warning"
|
||||||
|
}).then(async () => {
|
||||||
|
const resp = await this.$axios.post("/platform/special_condolence/type/onSubmit", this.formData)
|
||||||
|
if (resp.code === 0) {
|
||||||
|
this.$message.success(resp.msg)
|
||||||
|
this.$emit('refresh')
|
||||||
|
} else {
|
||||||
|
this.$message.warning(resp.msg)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
},
|
||||||
|
style: /*language=CSS*/ `
|
||||||
|
.el-input-number .el-input__inner {
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
`
|
||||||
|
}
|
||||||
+148
@@ -0,0 +1,148 @@
|
|||||||
|
<!--#
|
||||||
|
layout("/layouts/platform.html"){
|
||||||
|
#-->
|
||||||
|
|
||||||
|
<style>
|
||||||
|
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<div id="app" v-cloak>
|
||||||
|
<guava ref="guava">
|
||||||
|
<template>
|
||||||
|
<el-card shadow="never">
|
||||||
|
<search @search="doSearch">
|
||||||
|
<search-item label="名称/编码">
|
||||||
|
<el-input placeholder="请输入名称或编码" clearable v-model="pageForm.searchKeyword"
|
||||||
|
@keyup.enter.native="doSearch">
|
||||||
|
</el-input>
|
||||||
|
</search-item>
|
||||||
|
</search>
|
||||||
|
</el-card>
|
||||||
|
|
||||||
|
<el-card shadow="never" class="mt20">
|
||||||
|
<table-tool label="类型列表">
|
||||||
|
<el-button type="primary" size="small" @click="onAdd">
|
||||||
|
<i class="ti-plus"></i>
|
||||||
|
新增类型
|
||||||
|
</el-button>
|
||||||
|
</table-tool>
|
||||||
|
<el-table :data="tableData" @sort-change="pageOrder" :size="tableSize">
|
||||||
|
<el-table-column label="序号" type="index" :index="indexMethod" width="60"></el-table-column>
|
||||||
|
<el-table-column
|
||||||
|
:label="column.label"
|
||||||
|
:prop="column.prop"
|
||||||
|
:key="column.prop"
|
||||||
|
:width="column.width"
|
||||||
|
:sortable="column.sortable"
|
||||||
|
align="center"
|
||||||
|
header-align="center"
|
||||||
|
show-overflow-tooltip
|
||||||
|
v-for="column in tableColumns"
|
||||||
|
>
|
||||||
|
<template v-slot="{ row }" v-if="column.prop === 'isUploadFile'">
|
||||||
|
<span v-if="row.isUploadFile" class="text-success">是</span>
|
||||||
|
<span v-else class="text-danger">否</span>
|
||||||
|
</template>
|
||||||
|
<template v-slot="{ row }" v-else-if="column.prop === 'enable'">
|
||||||
|
<el-switch
|
||||||
|
@change="switchChange(row)"
|
||||||
|
v-model="row.enable"
|
||||||
|
active-color="#13ce66"
|
||||||
|
inactive-color="#ff4949">
|
||||||
|
</el-switch>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column label="操作" width="230">
|
||||||
|
<template v-slot="{ row }">
|
||||||
|
<el-button @click="onEdit(row)" size="mini" type="primary">编辑</el-button>
|
||||||
|
<el-button @click="onDelete(row)" size="mini" type="danger">删除</el-button>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
</el-table>
|
||||||
|
<!--#include("/layouts/pagination.html"){}#-->
|
||||||
|
</el-card>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<template #edit>
|
||||||
|
<basic-form ref="basicFormRef" @refresh="refresh"></basic-form>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
</guava>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<script nonce="${cspNonce!}">
|
||||||
|
<!--#include('basicForm.js'){}#-->
|
||||||
|
const vue = new Vue({
|
||||||
|
el: "#app",
|
||||||
|
mixins: [initTableMixins],
|
||||||
|
components: {
|
||||||
|
"basic-form": basicForm,
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
tableColumns: [
|
||||||
|
{prop: 'code', label: '类型编码'},
|
||||||
|
{prop: 'name', label: '类型名称'},
|
||||||
|
{prop: 'money', label: '金额'},
|
||||||
|
{prop: 'way', label: '慰问方式'},
|
||||||
|
// {prop: 'isUploadFile', label: '是否上传附件'},
|
||||||
|
{prop: 'enable', label: '是否启用'},
|
||||||
|
],
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
refresh() {
|
||||||
|
this.doSearch()
|
||||||
|
this.$refs.guava.index()
|
||||||
|
},
|
||||||
|
onAdd() {
|
||||||
|
this.$refs.guava.edit(() => {
|
||||||
|
this.$refs.basicFormRef.onOpen()
|
||||||
|
})
|
||||||
|
},
|
||||||
|
onEdit(row) {
|
||||||
|
this.$refs.guava.edit(() => {
|
||||||
|
this.$refs.basicFormRef.onOpen(row)
|
||||||
|
})
|
||||||
|
},
|
||||||
|
onDelete(row) {
|
||||||
|
this.$confirm("您确定要删除吗, 是否继续?", "提示", {
|
||||||
|
confirmButtonText: "确定",
|
||||||
|
cancelButtonText: "取消",
|
||||||
|
type: "warning"
|
||||||
|
})
|
||||||
|
.then(() => {
|
||||||
|
this.$axios.post("/platform/special_condolence/type/onDelete", { id: row.id }).then((res) => {
|
||||||
|
if (res.code === 0) {
|
||||||
|
this.$message.success(res.msg)
|
||||||
|
this.pageData()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
.catch(() => {})
|
||||||
|
},
|
||||||
|
switchChange(row) {
|
||||||
|
this.$axios.post("/platform/special_condolence/type/onSubmit", row).then((res) => {
|
||||||
|
if (res.code === 0) {
|
||||||
|
this.$message.success(res.msg)
|
||||||
|
this.pageData()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
pageData() {
|
||||||
|
this.$axios.post(loc() + "/pageData", this.pageForm).then((res) => {
|
||||||
|
if (res.code === 0) {
|
||||||
|
this.tableData = res.data.list
|
||||||
|
this.pageForm.totalCount = res.data.totalCount
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
},
|
||||||
|
async created() {
|
||||||
|
this.pageData()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
<!--#
|
||||||
|
}
|
||||||
|
#-->
|
||||||
+14
-3
@@ -82,6 +82,7 @@ layout("/layouts/platform.html"){
|
|||||||
</el-popover>
|
</el-popover>
|
||||||
</table-tool>
|
</table-tool>
|
||||||
<el-table
|
<el-table
|
||||||
|
ref="memberTableRef"
|
||||||
:data="tableData"
|
:data="tableData"
|
||||||
style="width: 100%"
|
style="width: 100%"
|
||||||
stripe
|
stripe
|
||||||
@@ -102,12 +103,12 @@ layout("/layouts/platform.html"){
|
|||||||
<el-table-column
|
<el-table-column
|
||||||
align="center"
|
align="center"
|
||||||
header-align="center"
|
header-align="center"
|
||||||
v-for="column in tableColumns"
|
v-for="column in showColumns"
|
||||||
|
:key="column.prop"
|
||||||
show-overflow-tooltip
|
show-overflow-tooltip
|
||||||
v-if="checkedFields.includes(column.prop)"
|
|
||||||
:label="column.label"
|
:label="column.label"
|
||||||
:prop="column.prop"
|
:prop="column.prop"
|
||||||
:width="column.width"
|
:min-width="column.width || 120"
|
||||||
:fixed="column.fixed"
|
:fixed="column.fixed"
|
||||||
:sortable="column.sortable"
|
:sortable="column.sortable"
|
||||||
>
|
>
|
||||||
@@ -268,6 +269,16 @@ layout("/layouts/platform.html"){
|
|||||||
this.checkedFields = all.filter(p => !this.checkedFields.includes(p));
|
this.checkedFields = all.filter(p => !this.checkedFields.includes(p));
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
watch: {
|
||||||
|
checkedFields() {
|
||||||
|
// 可见列更新后重新计算列宽,保证右侧固定操作列与表头、数据行对齐。
|
||||||
|
this.$nextTick(() => {
|
||||||
|
if (this.$refs.memberTableRef) {
|
||||||
|
this.$refs.memberTableRef.doLayout()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
},
|
||||||
computed: {
|
computed: {
|
||||||
showColumns() {
|
showColumns() {
|
||||||
return this.tableColumns.filter(c => this.checkedFields.includes(c.prop));
|
return this.tableColumns.filter(c => this.checkedFields.includes(c.prop));
|
||||||
|
|||||||
@@ -62,7 +62,7 @@ const filterUser = {
|
|||||||
</search-item>
|
</search-item>
|
||||||
|
|
||||||
<search-item label="所属单位">
|
<search-item label="所属单位">
|
||||||
<el-select @change="unitChange" clearable filterable
|
<el-select clearable filterable
|
||||||
placeholder="请选择所属单位" style="width: 100%"
|
placeholder="请选择所属单位" style="width: 100%"
|
||||||
v-model="pageForm.unitId">
|
v-model="pageForm.unitId">
|
||||||
<el-option
|
<el-option
|
||||||
@@ -74,17 +74,6 @@ const filterUser = {
|
|||||||
</el-select>
|
</el-select>
|
||||||
</search-item>
|
</search-item>
|
||||||
|
|
||||||
<search-item label="三级单位">
|
|
||||||
<el-select clearable filterable placeholder="请先选择所属单位" style="width: 100%"
|
|
||||||
v-model="pageForm.threeUnitId">
|
|
||||||
<el-option
|
|
||||||
:key="item.id"
|
|
||||||
:label="item.name"
|
|
||||||
:value="item.id"
|
|
||||||
v-for="item in threeUnitOptions">
|
|
||||||
</el-option>
|
|
||||||
</el-select>
|
|
||||||
</search-item>
|
|
||||||
|
|
||||||
<search-item label="人员类型:">
|
<search-item label="人员类型:">
|
||||||
<dict-select clearable code="USER_PERSON_TYPE"
|
<dict-select clearable code="USER_PERSON_TYPE"
|
||||||
@@ -94,13 +83,6 @@ const filterUser = {
|
|||||||
v-model="pageForm.personTypes"></dict-select>
|
v-model="pageForm.personTypes"></dict-select>
|
||||||
</search-item>
|
</search-item>
|
||||||
|
|
||||||
<search-item label="人员属性:">
|
|
||||||
<dict-select clearable code="USER_ATTRIBUTE"
|
|
||||||
multiple
|
|
||||||
collapse-tags
|
|
||||||
placeholder="请选择人员属性"
|
|
||||||
v-model="pageForm.userAttributes"></dict-select>
|
|
||||||
</search-item>
|
|
||||||
|
|
||||||
<search-item label="在职状态:">
|
<search-item label="在职状态:">
|
||||||
<dict-select clearable code="USER_STATE"
|
<dict-select clearable code="USER_STATE"
|
||||||
@@ -169,14 +151,11 @@ const filterUser = {
|
|||||||
userStates: [],
|
userStates: [],
|
||||||
personTypes: [],
|
personTypes: [],
|
||||||
preparedBys: [],
|
preparedBys: [],
|
||||||
userAttributes: [],
|
unitId: null
|
||||||
unitId: null,
|
|
||||||
threeUnitId: null
|
|
||||||
},
|
},
|
||||||
sexOptions: ["男", "女"],
|
sexOptions: ["男", "女"],
|
||||||
unionOptions: [],
|
unionOptions: [],
|
||||||
unitOptions: [],
|
unitOptions: [],
|
||||||
threeUnitOptions: [],
|
|
||||||
tableColumns: [
|
tableColumns: [
|
||||||
{ prop: "loginname", label: "工号" },
|
{ prop: "loginname", label: "工号" },
|
||||||
{ prop: "username", label: "姓名" },
|
{ prop: "username", label: "姓名" },
|
||||||
@@ -185,8 +164,7 @@ const filterUser = {
|
|||||||
{ prop: "personType", label: "人员类型", sortable: true },
|
{ prop: "personType", label: "人员类型", sortable: true },
|
||||||
{ prop: "userState", label: "在职状态", sortable: true },
|
{ prop: "userState", label: "在职状态", sortable: true },
|
||||||
{ prop: "unionName", label: "所属工会", sortable: true },
|
{ prop: "unionName", label: "所属工会", sortable: true },
|
||||||
{ prop: "unitName", label: "所属单位", sortable: true },
|
{ prop: "unitName", label: "所属单位", sortable: true }
|
||||||
{ prop: "threeUnitName", label: "三级单位", sortable: true }
|
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -208,35 +186,12 @@ const filterUser = {
|
|||||||
this.$set(this.pageForm, "birthMonths", [])
|
this.$set(this.pageForm, "birthMonths", [])
|
||||||
this.$set(this.pageForm, "unionId", null)
|
this.$set(this.pageForm, "unionId", null)
|
||||||
this.$set(this.pageForm, "unitId", null)
|
this.$set(this.pageForm, "unitId", null)
|
||||||
this.$set(this.pageForm, "threeUnitId", null)
|
|
||||||
this.threeUnitOptions = []
|
|
||||||
this.$set(this.pageForm, "personTypes", [])
|
this.$set(this.pageForm, "personTypes", [])
|
||||||
this.$set(this.pageForm, "preparedBys", [])
|
this.$set(this.pageForm, "preparedBys", [])
|
||||||
this.$set(this.pageForm, "userAttributes", [])
|
|
||||||
this.$set(this.pageForm, "userStates", [])
|
this.$set(this.pageForm, "userStates", [])
|
||||||
this.$set(this.pageForm, "isMember", null)
|
this.$set(this.pageForm, "isMember", null)
|
||||||
},
|
},
|
||||||
|
|
||||||
// 所属单位改变后,仅加载该单位直属的三级单位,避免跨单位筛选。
|
|
||||||
unitChange(unitId) {
|
|
||||||
this.$set(this.pageForm, "threeUnitId", null)
|
|
||||||
this.threeUnitOptions = []
|
|
||||||
if (!unitId) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
this.$axios.post("/platform/sys/unit/child", { pid: unitId })
|
|
||||||
.then((res) => {
|
|
||||||
if (res.code === 0) {
|
|
||||||
this.threeUnitOptions = res.data || []
|
|
||||||
} else {
|
|
||||||
this.$message.error(res.msg || "三级单位查询失败")
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.catch(() => {
|
|
||||||
this.$message.error("三级单位查询失败,请稍后重试")
|
|
||||||
})
|
|
||||||
},
|
|
||||||
|
|
||||||
pageData() {
|
pageData() {
|
||||||
this.tableLoading = true
|
this.tableLoading = true
|
||||||
this.$axios
|
this.$axios
|
||||||
|
|||||||
@@ -65,10 +65,6 @@ layout("/layouts/platform.html"){
|
|||||||
<dict-select v-model="pageForm.aidFundMemberUserType" placeholder="请选择人员分类" @change="doSearch"
|
<dict-select v-model="pageForm.aidFundMemberUserType" placeholder="请选择人员分类" @change="doSearch"
|
||||||
code="AIDFUND_MEMBER_USER_TYPE"></dict-select>
|
code="AIDFUND_MEMBER_USER_TYPE"></dict-select>
|
||||||
</search-item>
|
</search-item>
|
||||||
<search-item label="人员属性">
|
|
||||||
<dict-select v-model="pageForm.userAttribute" placeholder="请选择人员属性" @change="doSearch"
|
|
||||||
code="USER_ATTRIBUTE"></dict-select>
|
|
||||||
</search-item>
|
|
||||||
</search>
|
</search>
|
||||||
</el-card>
|
</el-card>
|
||||||
|
|
||||||
|
|||||||
@@ -63,7 +63,7 @@ const addUser = {
|
|||||||
</search-item>
|
</search-item>
|
||||||
|
|
||||||
<search-item label="所属单位">
|
<search-item label="所属单位">
|
||||||
<el-select @change="unitChange" clearable
|
<el-select clearable
|
||||||
filterable
|
filterable
|
||||||
placeholder="请选择所属单位" style="width: 100%"
|
placeholder="请选择所属单位" style="width: 100%"
|
||||||
v-model="pageForm.unitId">
|
v-model="pageForm.unitId">
|
||||||
@@ -76,17 +76,6 @@ const addUser = {
|
|||||||
</el-select>
|
</el-select>
|
||||||
</search-item>
|
</search-item>
|
||||||
|
|
||||||
<search-item label="三级单位">
|
|
||||||
<el-select clearable filterable placeholder="请先选择所属单位" style="width: 100%"
|
|
||||||
v-model="pageForm.threeUnitId">
|
|
||||||
<el-option
|
|
||||||
:key="item.id"
|
|
||||||
:label="item.name"
|
|
||||||
:value="item.id"
|
|
||||||
v-for="item in threeUnitOptions">
|
|
||||||
</el-option>
|
|
||||||
</el-select>
|
|
||||||
</search-item>
|
|
||||||
|
|
||||||
<search-item label="人员类型:">
|
<search-item label="人员类型:">
|
||||||
<dict-select clearable code="USER_PERSON_TYPE"
|
<dict-select clearable code="USER_PERSON_TYPE"
|
||||||
@@ -96,13 +85,6 @@ const addUser = {
|
|||||||
v-model="pageForm.personTypes"></dict-select>
|
v-model="pageForm.personTypes"></dict-select>
|
||||||
</search-item>
|
</search-item>
|
||||||
|
|
||||||
<search-item label="人员属性:">
|
|
||||||
<dict-select clearable code="USER_ATTRIBUTE"
|
|
||||||
multiple
|
|
||||||
collapse-tags
|
|
||||||
placeholder="请选择人员属性"
|
|
||||||
v-model="pageForm.userAttributes"></dict-select>
|
|
||||||
</search-item>
|
|
||||||
|
|
||||||
<search-item label="在职状态:">
|
<search-item label="在职状态:">
|
||||||
<dict-select clearable code="USER_STATE"
|
<dict-select clearable code="USER_STATE"
|
||||||
@@ -171,9 +153,7 @@ const addUser = {
|
|||||||
birthMonths: [],
|
birthMonths: [],
|
||||||
unionId: null,
|
unionId: null,
|
||||||
unitId: null,
|
unitId: null,
|
||||||
threeUnitId: null,
|
|
||||||
personTypes: [],
|
personTypes: [],
|
||||||
userAttributes: [],
|
|
||||||
preparedBys: [],
|
preparedBys: [],
|
||||||
userStates: [],
|
userStates: [],
|
||||||
isMember: null
|
isMember: null
|
||||||
@@ -181,7 +161,6 @@ const addUser = {
|
|||||||
sexOptions: ["男", "女"],
|
sexOptions: ["男", "女"],
|
||||||
unionOptions: [],
|
unionOptions: [],
|
||||||
unitOptions: [],
|
unitOptions: [],
|
||||||
threeUnitOptions: [],
|
|
||||||
tableColumns: [
|
tableColumns: [
|
||||||
{ prop: "loginname", label: "工号" },
|
{ prop: "loginname", label: "工号" },
|
||||||
{ prop: "username", label: "姓名" },
|
{ prop: "username", label: "姓名" },
|
||||||
@@ -190,8 +169,7 @@ const addUser = {
|
|||||||
{ prop: "personType", label: "人员类型", sortable: true },
|
{ prop: "personType", label: "人员类型", sortable: true },
|
||||||
{ prop: "userState", label: "在职状态", sortable: true },
|
{ prop: "userState", label: "在职状态", sortable: true },
|
||||||
{ prop: "unionName", label: "所属工会", sortable: true },
|
{ prop: "unionName", label: "所属工会", sortable: true },
|
||||||
{ prop: "unitName", label: "所属单位", sortable: true },
|
{ prop: "unitName", label: "所属单位", sortable: true }
|
||||||
{ prop: "threeUnitName", label: "三级单位", sortable: true }
|
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -213,10 +191,7 @@ const addUser = {
|
|||||||
this.$set(this.pageForm, "birthMonths", [])
|
this.$set(this.pageForm, "birthMonths", [])
|
||||||
this.$set(this.pageForm, "unionId", null)
|
this.$set(this.pageForm, "unionId", null)
|
||||||
this.$set(this.pageForm, "unitId", null)
|
this.$set(this.pageForm, "unitId", null)
|
||||||
this.$set(this.pageForm, "threeUnitId", null)
|
|
||||||
this.$set(this, "threeUnitOptions", [])
|
|
||||||
this.$set(this.pageForm, "personTypes", [])
|
this.$set(this.pageForm, "personTypes", [])
|
||||||
this.$set(this.pageForm, "userAttributes", [])
|
|
||||||
this.$set(this.pageForm, "preparedBys", [])
|
this.$set(this.pageForm, "preparedBys", [])
|
||||||
this.$set(this.pageForm, "userStates", [])
|
this.$set(this.pageForm, "userStates", [])
|
||||||
this.$set(this.pageForm, "isMember", null)
|
this.$set(this.pageForm, "isMember", null)
|
||||||
@@ -224,7 +199,6 @@ const addUser = {
|
|||||||
|
|
||||||
async unionIdChange(val) {
|
async unionIdChange(val) {
|
||||||
this.$set(this.pageForm, "unitId", null)
|
this.$set(this.pageForm, "unitId", null)
|
||||||
this.unitChange(null)
|
|
||||||
if (val) {
|
if (val) {
|
||||||
this.$set(this, "unitOptions", await this.$businessTool.listUnit(val))
|
this.$set(this, "unitOptions", await this.$businessTool.listUnit(val))
|
||||||
} else {
|
} else {
|
||||||
@@ -232,26 +206,6 @@ const addUser = {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
// 所属单位改变后,仅加载该单位直属的三级单位,避免跨单位筛选。
|
|
||||||
unitChange(unitId) {
|
|
||||||
this.$set(this.pageForm, "threeUnitId", null)
|
|
||||||
this.$set(this, "threeUnitOptions", [])
|
|
||||||
if (!unitId) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
this.$axios.post("/platform/sys/unit/child", { pid: unitId })
|
|
||||||
.then((res) => {
|
|
||||||
if (res.code === 0) {
|
|
||||||
this.$set(this, "threeUnitOptions", res.data || [])
|
|
||||||
} else {
|
|
||||||
this.$message.error(res.msg || "三级单位查询失败")
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.catch(() => {
|
|
||||||
this.$message.error("三级单位查询失败,请稍后重试")
|
|
||||||
})
|
|
||||||
},
|
|
||||||
|
|
||||||
pageData() {
|
pageData() {
|
||||||
this.tableLoading = true
|
this.tableLoading = true
|
||||||
this.$axios
|
this.$axios
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user