Changes
This commit is contained in:
@@ -18,6 +18,7 @@ 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.Chain;
|
||||
import org.nutz.dao.Cnd;
|
||||
import org.nutz.dao.Dao;
|
||||
import org.nutz.dao.Sqls;
|
||||
@@ -110,14 +111,39 @@ public class FlowDesignController {
|
||||
@ApiOperation("获取流程设计分页列表")
|
||||
@SaCheckPermission("flow.design")
|
||||
public Result pageData(PageForm pageForm, String displayName, String name, String category, Boolean deployed) {
|
||||
Sql sql = Sqls.create("""
|
||||
SELECT
|
||||
pd.*
|
||||
FROM
|
||||
wf_process_design pd
|
||||
LEFT JOIN wf_process_category pc ON pc.id = pd.category
|
||||
$condition
|
||||
""");
|
||||
Cnd cnd = Cnd.NEW();
|
||||
|
||||
cnd.and(Cnd.likeEX(ProcessDesign::getDisplayName, displayName));
|
||||
cnd.and(Cnd.likeEX(ProcessDesign::getName, name));
|
||||
cnd.andEX(ProcessDesign::getCategory, "=", category);
|
||||
cnd.andEX(ProcessDesign::getIsDeployed, "=", deployed);
|
||||
cnd.and(Cnd.likeEX("pd.displayName", displayName));
|
||||
cnd.and(Cnd.likeEX("pd.name", name));
|
||||
cnd.andEX("pd.category", "=", category);
|
||||
cnd.andEX("pd.isDeployed", "=", deployed);
|
||||
if ("sortNo".equals(pageForm.getPageOrderName())) {
|
||||
if ("descending".equals(pageForm.getPageOrderBy())) {
|
||||
cnd.desc("pd.sortNo");
|
||||
} else {
|
||||
cnd.asc("pd.sortNo");
|
||||
}
|
||||
} else if ("category".equals(pageForm.getPageOrderName())) {
|
||||
if ("descending".equals(pageForm.getPageOrderBy())) {
|
||||
cnd.desc("pc.name");
|
||||
} else {
|
||||
cnd.asc("pc.name");
|
||||
}
|
||||
} else {
|
||||
cnd.asc("pd.sortNo");
|
||||
}
|
||||
cnd.asc("pd.id");
|
||||
|
||||
Pagination pagination = processDesignService.listPage(pageForm.getPageNumber(), pageForm.getPageSize(), cnd);
|
||||
sql.setCondition(cnd);
|
||||
Pagination pagination = processDesignService.listPageMap(pageForm.getPageNumber(), pageForm.getPageSize(), sql);
|
||||
return Result.success(pagination);
|
||||
}
|
||||
|
||||
@@ -206,6 +232,17 @@ public class FlowDesignController {
|
||||
return Result.success();
|
||||
}
|
||||
|
||||
@At
|
||||
@ApiOperation("修改流程设计排序编码")
|
||||
@SaCheckPermission("flow.design")
|
||||
public Result updateSortNo(@Param("id") Long id, @Param("sortNo") Integer sortNo) {
|
||||
if (id == null || sortNo == null || sortNo < 0) {
|
||||
return Result.error("排序编码必须是非负整数");
|
||||
}
|
||||
processDesignService.update(Chain.make("sortNo", sortNo), Cnd.where(ProcessDesign::getId, "=", id));
|
||||
return Result.success();
|
||||
}
|
||||
|
||||
@At
|
||||
@SaCheckLogin
|
||||
@ApiOperation("获取流程设计任务参与者处理类")
|
||||
|
||||
@@ -68,6 +68,11 @@ public class ProcessDesign extends BaseModel {
|
||||
@Column
|
||||
private Integer isDeployed;
|
||||
|
||||
@Comment("排序编码")
|
||||
@Column
|
||||
@Default("0")
|
||||
private Integer sortNo;
|
||||
|
||||
@Comment("备注")
|
||||
@Column
|
||||
private String remark;
|
||||
|
||||
@@ -0,0 +1,451 @@
|
||||
package com.budwk.app.sys.controller;
|
||||
|
||||
import cn.afterturn.easypoi.excel.ExcelExportUtil;
|
||||
import cn.afterturn.easypoi.excel.annotation.Excel;
|
||||
import cn.afterturn.easypoi.excel.entity.ExportParams;
|
||||
import cn.dev33.satoken.annotation.SaCheckPermission;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.budwk.app.base.annotation.SLog;
|
||||
import com.budwk.app.base.result.Result;
|
||||
import com.budwk.app.base.utils.CommonDownloadUtil;
|
||||
import com.budwk.app.sys.enums.SysDataImportPlugin;
|
||||
import com.budwk.app.sys.services.SysRoleService;
|
||||
import com.budwk.app.sys.services.SysUserService;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.poi.ss.usermodel.Cell;
|
||||
import org.apache.poi.ss.usermodel.CellType;
|
||||
import org.apache.poi.ss.usermodel.DateUtil;
|
||||
import org.apache.poi.ss.usermodel.Row;
|
||||
import org.apache.poi.ss.usermodel.Sheet;
|
||||
import org.apache.poi.ss.usermodel.WorkbookFactory;
|
||||
import org.nutz.dao.Chain;
|
||||
import org.nutz.dao.Cnd;
|
||||
import org.nutz.dao.Sqls;
|
||||
import org.nutz.dao.entity.Record;
|
||||
import org.nutz.dao.sql.Sql;
|
||||
import org.nutz.integration.jedis.RedisService;
|
||||
import org.nutz.ioc.loader.annotation.Inject;
|
||||
import org.nutz.ioc.loader.annotation.IocBean;
|
||||
import org.nutz.json.Json;
|
||||
import org.nutz.lang.random.R;
|
||||
import org.nutz.lang.util.NutMap;
|
||||
import org.nutz.mvc.annotation.AdaptBy;
|
||||
import org.nutz.mvc.annotation.At;
|
||||
import org.nutz.mvc.annotation.Ok;
|
||||
import org.nutz.mvc.annotation.Param;
|
||||
import org.nutz.mvc.upload.TempFile;
|
||||
import org.nutz.mvc.upload.UploadAdaptor;
|
||||
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.ZoneId;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Comparator;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
|
||||
@Slf4j
|
||||
@IocBean
|
||||
@Ok("json:full")
|
||||
@At("/platform/sys/data/tool")
|
||||
@Api("系统数据高级工具")
|
||||
public class SysDataToolController {
|
||||
|
||||
private static final DateTimeFormatter DATE_TIME_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
|
||||
|
||||
@Inject
|
||||
private SysUserService sysUserService;
|
||||
@Inject
|
||||
private SysRoleService sysRoleService;
|
||||
@Inject
|
||||
private RedisService redisService;
|
||||
|
||||
@At("")
|
||||
@Ok("beetl:/platform/sys/data/tool/index.html")
|
||||
@SaCheckPermission("sys.data.advanced.tool")
|
||||
public void index() {
|
||||
}
|
||||
|
||||
@At
|
||||
@ApiOperation("查询数据库中的表")
|
||||
@SaCheckPermission("sys.data.advanced.tool")
|
||||
public Result tableNames() {
|
||||
Sql sql = Sqls.create("""
|
||||
SELECT
|
||||
table_name,
|
||||
table_rows,
|
||||
table_comment
|
||||
FROM
|
||||
information_schema.TABLES
|
||||
WHERE
|
||||
table_schema = (SELECT DATABASE())
|
||||
ORDER BY
|
||||
table_name
|
||||
""");
|
||||
return Result.success(sysUserService.listMap(sql));
|
||||
}
|
||||
|
||||
@At
|
||||
@ApiOperation("查询数据表字段")
|
||||
@SaCheckPermission("sys.data.advanced.tool")
|
||||
public Result columns(String tableName) {
|
||||
if (StrUtil.isBlank(tableName)) {
|
||||
return Result.error("请选择数据表");
|
||||
}
|
||||
return Result.success(getColumns(tableName));
|
||||
}
|
||||
|
||||
@At
|
||||
@ApiOperation("执行高级导入")
|
||||
@SLog(tag = "数据管理-高级工具", msg = "执行高级导入")
|
||||
@SaCheckPermission("sys.data.advanced.tool")
|
||||
@AdaptBy(type = UploadAdaptor.class, args = {"ioc:fileUpload"})
|
||||
public Result importData(@Param("file") TempFile file,
|
||||
String tableName,
|
||||
String relation,
|
||||
Integer method,
|
||||
String field,
|
||||
String plugins) throws IOException {
|
||||
if (file == null) {
|
||||
return Result.error("请上传 Excel 文件");
|
||||
}
|
||||
if (StrUtil.isBlank(tableName)) {
|
||||
return Result.error("请选择数据表");
|
||||
}
|
||||
if (method == null) {
|
||||
return Result.error("请选择导入方式");
|
||||
}
|
||||
if ((method == 1 || method == 3) && StrUtil.isBlank(field)) {
|
||||
return Result.error("请选择关键字段");
|
||||
}
|
||||
if (StrUtil.isBlank(relation)) {
|
||||
return Result.error("请配置字段对应关系");
|
||||
}
|
||||
|
||||
List<Record> columns = getColumns(tableName);
|
||||
if (columns.isEmpty()) {
|
||||
return Result.error("未获取到数据表字段");
|
||||
}
|
||||
|
||||
NutMap[] relations = parseRelations(relation);
|
||||
List<NutMap> dataList = getDataForExcel(file, relations);
|
||||
List<SysDataImportPlugin> pluginList = parsePlugins(plugins);
|
||||
pluginList.sort(Comparator.comparingInt(SysDataImportPlugin::getLocation));
|
||||
Record pkRecord = getPrimaryKey(columns).orElse(null);
|
||||
Set<String> tableColumns = new HashSet<>();
|
||||
columns.forEach(column -> tableColumns.add(column.getString("column_name")));
|
||||
|
||||
int total = 0;
|
||||
int success = 0;
|
||||
List<ImportError> errors = new ArrayList<>();
|
||||
|
||||
for (NutMap row : dataList) {
|
||||
total++;
|
||||
try {
|
||||
if (StrUtil.isNotBlank(field)) {
|
||||
row.setv(field, row.getString(field));
|
||||
}
|
||||
|
||||
Chain chain = buildChain(row, tableColumns);
|
||||
if (chain == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
Object pk;
|
||||
if (method == 1) {
|
||||
Record currentRecord = sysUserService.dao().fetch(tableName, Cnd.where(field, "=", row.get(field)));
|
||||
if (currentRecord == null) {
|
||||
pk = prepareBefore(tableName, pkRecord, field, pluginList, true, chain, row, tableColumns);
|
||||
sysUserService.dao().insert(tableName, chain);
|
||||
} else {
|
||||
pk = prepareBefore(tableName, pkRecord, field, pluginList, false, chain, row, tableColumns);
|
||||
sysUserService.dao().update(tableName, chain, Cnd.where(field, "=", row.get(field)));
|
||||
}
|
||||
} else if (method == 2) {
|
||||
pk = prepareBefore(tableName, pkRecord, field, pluginList, true, chain, row, tableColumns);
|
||||
sysUserService.dao().insert(tableName, chain);
|
||||
} else if (method == 3) {
|
||||
pk = prepareBefore(tableName, pkRecord, field, pluginList, false, chain, row, tableColumns);
|
||||
sysUserService.dao().update(tableName, chain, Cnd.where(field, "=", row.get(field)));
|
||||
} else {
|
||||
throw new IllegalArgumentException("导入方式不正确");
|
||||
}
|
||||
|
||||
applyAfterPlugins(tableName, tableColumns, chain, pk, pluginList);
|
||||
success++;
|
||||
} catch (Exception e) {
|
||||
log.error("高级导入失败, table={}, row={}", tableName, row, e);
|
||||
errors.add(new ImportError(Json.toJson(row), e.getMessage()));
|
||||
}
|
||||
}
|
||||
|
||||
String cacheKey = "";
|
||||
if (!errors.isEmpty()) {
|
||||
cacheKey = R.UU32();
|
||||
redisService.setex(cacheKey, 60 * 60 * 5, Json.toJson(errors));
|
||||
}
|
||||
|
||||
sysUserService.clearCache();
|
||||
sysRoleService.clearCache();
|
||||
return Result.success(NutMap.NEW().addv("total", total).addv("success", success).addv("cacheKey", cacheKey));
|
||||
}
|
||||
|
||||
@At
|
||||
@Ok("void")
|
||||
@ApiOperation("导出错误记录")
|
||||
@SaCheckPermission("sys.data.advanced.tool")
|
||||
public void exportErrors(HttpServletResponse response, String cacheKey) {
|
||||
if (StrUtil.isBlank(cacheKey)) {
|
||||
CommonDownloadUtil.download("导入错误记录.xlsx",
|
||||
ExcelExportUtil.exportExcel(new ExportParams(), ImportError.class, new ArrayList<>()),
|
||||
response);
|
||||
return;
|
||||
}
|
||||
String json = redisService.get(cacheKey);
|
||||
List<ImportError> errors = StrUtil.isBlank(json) ? new ArrayList<>() : Json.fromJsonAsList(ImportError.class, json);
|
||||
CommonDownloadUtil.download("导入错误记录.xlsx",
|
||||
ExcelExportUtil.exportExcel(new ExportParams(), ImportError.class, errors),
|
||||
response);
|
||||
}
|
||||
|
||||
private void applyAfterPlugins(String tableName,
|
||||
Set<String> tableColumns,
|
||||
Chain chain,
|
||||
Object pk,
|
||||
List<SysDataImportPlugin> pluginList) {
|
||||
if (pluginList.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
SysDataImportPlugin.PluginContext context = new SysDataImportPlugin.PluginContext(
|
||||
tableName,
|
||||
tableColumns,
|
||||
chain,
|
||||
pk,
|
||||
sysUserService.dao(),
|
||||
sysRoleService
|
||||
);
|
||||
pluginList.forEach(plugin -> plugin.after(context));
|
||||
}
|
||||
|
||||
private Object prepareBefore(String tableName,
|
||||
Record pkRecord,
|
||||
String field,
|
||||
List<SysDataImportPlugin> pluginList,
|
||||
boolean save,
|
||||
Chain chain,
|
||||
NutMap row,
|
||||
Set<String> tableColumns) {
|
||||
Object pk = resolvePrimaryKeyValue(tableName, pkRecord, field, save, chain, row);
|
||||
SysDataImportPlugin.PluginContext context = new SysDataImportPlugin.PluginContext(
|
||||
tableName,
|
||||
tableColumns,
|
||||
chain,
|
||||
pk,
|
||||
sysUserService.dao(),
|
||||
sysRoleService
|
||||
);
|
||||
pluginList.forEach(plugin -> plugin.before(context));
|
||||
return pk;
|
||||
}
|
||||
|
||||
private Object resolvePrimaryKeyValue(String tableName,
|
||||
Record pkRecord,
|
||||
String field,
|
||||
boolean save,
|
||||
Chain chain,
|
||||
NutMap row) {
|
||||
if (pkRecord == null) {
|
||||
return null;
|
||||
}
|
||||
String pkColumnName = pkRecord.getString("column_name");
|
||||
String pkColumnType = pkRecord.getString("column_type");
|
||||
|
||||
Object pk;
|
||||
if (save) {
|
||||
pk = row.get(pkColumnName);
|
||||
if (pk == null) {
|
||||
pk = generatePrimaryKey(pkColumnType);
|
||||
chain.add(pkColumnName, pk);
|
||||
}
|
||||
} else {
|
||||
Record record = sysUserService.dao().fetch(tableName, Cnd.where(field, "=", row.get(field)));
|
||||
if (record == null) {
|
||||
throw new IllegalArgumentException("未找到关键字段匹配的记录");
|
||||
}
|
||||
pk = record.get(pkColumnName);
|
||||
}
|
||||
|
||||
if (pk == null) {
|
||||
throw new IllegalArgumentException("主键生成失败");
|
||||
}
|
||||
return pk;
|
||||
}
|
||||
|
||||
private Object generatePrimaryKey(String pkColumnType) {
|
||||
if (StrUtil.isBlank(pkColumnType)) {
|
||||
return R.UU32();
|
||||
}
|
||||
return switch (pkColumnType.toLowerCase()) {
|
||||
case "int", "integer" -> R.random(1000, 9999);
|
||||
case "varchar(16)" -> R.UU16();
|
||||
case "varchar(64)" -> R.UU64();
|
||||
default -> R.UU32();
|
||||
};
|
||||
}
|
||||
|
||||
private Chain buildChain(NutMap row, Set<String> tableColumns) {
|
||||
NutMap filtered = NutMap.NEW();
|
||||
row.forEach((key, value) -> {
|
||||
if (key != null && tableColumns.contains(key)) {
|
||||
filtered.addv(key, value);
|
||||
}
|
||||
});
|
||||
return filtered.isEmpty() ? null : Chain.from(filtered);
|
||||
}
|
||||
|
||||
private NutMap[] parseRelations(String relationJson) {
|
||||
List<NutMap> relationList = Json.fromJsonAsList(NutMap.class, relationJson);
|
||||
return relationList.toArray(new NutMap[0]);
|
||||
}
|
||||
|
||||
private List<SysDataImportPlugin> parsePlugins(String pluginsJson) {
|
||||
if (StrUtil.isBlank(pluginsJson)) {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
List<String> pluginNames = Json.fromJsonAsList(String.class, pluginsJson);
|
||||
List<SysDataImportPlugin> plugins = new ArrayList<>();
|
||||
for (String pluginName : pluginNames) {
|
||||
if (StrUtil.isBlank(pluginName)) {
|
||||
continue;
|
||||
}
|
||||
plugins.add(SysDataImportPlugin.valueOf(pluginName));
|
||||
}
|
||||
return plugins;
|
||||
}
|
||||
|
||||
private Optional<Record> getPrimaryKey(List<Record> columns) {
|
||||
return columns.stream().filter(column -> "PRI".equalsIgnoreCase(column.getString("column_key"))).findFirst();
|
||||
}
|
||||
|
||||
private List<Record> getColumns(String tableName) {
|
||||
Sql sql = Sqls.create("""
|
||||
SELECT
|
||||
column_name,
|
||||
is_nullable,
|
||||
column_type,
|
||||
column_key,
|
||||
column_comment
|
||||
FROM
|
||||
information_schema.COLUMNS
|
||||
WHERE
|
||||
table_name = @tableName
|
||||
AND table_schema = (SELECT DATABASE())
|
||||
ORDER BY
|
||||
ordinal_position
|
||||
""").setParam("tableName", tableName);
|
||||
return sysUserService.list(sql);
|
||||
}
|
||||
|
||||
private List<NutMap> getDataForExcel(TempFile file, NutMap[] relation) throws IOException {
|
||||
List<NutMap> result = new ArrayList<>();
|
||||
Map<Integer, String> headerColumnMap = new HashMap<>();
|
||||
|
||||
Sheet sheet = WorkbookFactory.create(file.getInputStream()).getSheetAt(0);
|
||||
Row headerRow = sheet.getRow(0);
|
||||
if (headerRow == null) {
|
||||
return result;
|
||||
}
|
||||
|
||||
int columnNum = headerRow.getPhysicalNumberOfCells();
|
||||
for (int i = 0; i < columnNum; i++) {
|
||||
Cell cell = headerRow.getCell(i);
|
||||
if (cell == null) {
|
||||
continue;
|
||||
}
|
||||
String header = cell.getStringCellValue();
|
||||
for (NutMap item : relation) {
|
||||
if (StrUtil.equals(item.getString("relation"), header)) {
|
||||
headerColumnMap.put(i, item.getString("column_name"));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int rowNum = sheet.getPhysicalNumberOfRows();
|
||||
for (int i = 1; i < rowNum; i++) {
|
||||
Row row = sheet.getRow(i);
|
||||
if (row == null) {
|
||||
continue;
|
||||
}
|
||||
NutMap data = NutMap.NEW();
|
||||
for (int j = 0; j < columnNum; j++) {
|
||||
String columnName = headerColumnMap.get(j);
|
||||
if (columnName == null) {
|
||||
continue;
|
||||
}
|
||||
data.setv(columnName, getCellValue(row.getCell(j)));
|
||||
}
|
||||
if (!data.isEmpty()) {
|
||||
result.add(data);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private Object getCellValue(Cell cell) {
|
||||
if (cell == null) {
|
||||
return null;
|
||||
}
|
||||
CellType cellType = cell.getCellType();
|
||||
if (cellType == CellType.NUMERIC) {
|
||||
if (DateUtil.isCellDateFormatted(cell)) {
|
||||
Date date = cell.getDateCellValue();
|
||||
return DATE_TIME_FORMATTER.format(LocalDateTime.ofInstant(date.toInstant(), ZoneId.systemDefault()));
|
||||
}
|
||||
double numericValue = cell.getNumericCellValue();
|
||||
BigDecimal decimal = BigDecimal.valueOf(numericValue);
|
||||
if (String.valueOf(numericValue).contains("E")) {
|
||||
return decimal.toPlainString();
|
||||
}
|
||||
if (numericValue == Math.rint(numericValue)) {
|
||||
return decimal.toBigInteger();
|
||||
}
|
||||
return numericValue;
|
||||
}
|
||||
if (cellType == CellType.STRING) {
|
||||
return cell.getStringCellValue();
|
||||
}
|
||||
if (cellType == CellType.BOOLEAN) {
|
||||
return cell.getBooleanCellValue();
|
||||
}
|
||||
if (cellType == CellType.ERROR) {
|
||||
return cell.getErrorCellValue();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public static class ImportError {
|
||||
@Excel(name = "行数据", width = 80)
|
||||
private String row;
|
||||
|
||||
@Excel(name = "错误原因", width = 40)
|
||||
private String errorMsg;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,123 @@
|
||||
package com.budwk.app.sys.enums;
|
||||
|
||||
import com.budwk.app.base.annotation.DictEnum;
|
||||
import com.budwk.app.base.constant.RoleConstant;
|
||||
import com.budwk.app.base.utils.PwdUtil;
|
||||
import com.budwk.app.sys.models.Sys_role;
|
||||
import com.budwk.app.sys.models.Sys_user_role;
|
||||
import com.budwk.app.sys.services.SysRoleService;
|
||||
import lombok.Getter;
|
||||
import org.nutz.dao.Chain;
|
||||
import org.nutz.dao.Cnd;
|
||||
import org.nutz.dao.Dao;
|
||||
import org.nutz.lang.random.R;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* 高级导入工具插件。
|
||||
*/
|
||||
@Getter
|
||||
@DictEnum(key = "sysDataImportPlugin", name = "系统数据高级工具插件")
|
||||
public enum SysDataImportPlugin {
|
||||
|
||||
USER_INIT(1, "初始化系统用户"),
|
||||
MEMBER_INIT(2, "设置为会员");
|
||||
|
||||
private final int location;
|
||||
private final String description;
|
||||
|
||||
SysDataImportPlugin(int location, String description) {
|
||||
this.location = location;
|
||||
this.description = description;
|
||||
}
|
||||
|
||||
public void before(PluginContext context) {
|
||||
if (!context.isSysUserTable()) {
|
||||
return;
|
||||
}
|
||||
if (this == USER_INIT) {
|
||||
String salt = R.UU32();
|
||||
context.addValue("salt", salt);
|
||||
context.addValue("password", PwdUtil.getPassword(PwdUtil.generate(12), salt));
|
||||
context.addValue("loginCount", 0);
|
||||
context.addValue("disabled", false);
|
||||
return;
|
||||
}
|
||||
if (this == MEMBER_INIT) {
|
||||
context.addValue("member", true);
|
||||
context.addValue("memberTime", new Date());
|
||||
}
|
||||
}
|
||||
|
||||
public void after(PluginContext context) {
|
||||
if (!context.isSysUserTable()) {
|
||||
return;
|
||||
}
|
||||
if (this == USER_INIT) {
|
||||
context.ensureRole(RoleConstant.PUBLIC);
|
||||
return;
|
||||
}
|
||||
if (this == MEMBER_INIT) {
|
||||
context.ensureRole(RoleConstant.MEMBER);
|
||||
}
|
||||
}
|
||||
|
||||
@Getter
|
||||
public static class PluginContext {
|
||||
private final String tableName;
|
||||
private final Set<String> tableColumns;
|
||||
private final Chain chain;
|
||||
private final Object pk;
|
||||
private final Dao dao;
|
||||
private final SysRoleService sysRoleService;
|
||||
|
||||
public PluginContext(String tableName,
|
||||
Set<String> tableColumns,
|
||||
Chain chain,
|
||||
Object pk,
|
||||
Dao dao,
|
||||
SysRoleService sysRoleService) {
|
||||
this.tableName = tableName;
|
||||
this.tableColumns = tableColumns;
|
||||
this.chain = chain;
|
||||
this.pk = pk;
|
||||
this.dao = dao;
|
||||
this.sysRoleService = sysRoleService;
|
||||
}
|
||||
|
||||
public boolean isSysUserTable() {
|
||||
return "sys_user".equalsIgnoreCase(tableName);
|
||||
}
|
||||
|
||||
public boolean hasColumn(String columnName) {
|
||||
return tableColumns.contains(columnName);
|
||||
}
|
||||
|
||||
public void addValue(String columnName, Object value) {
|
||||
if (hasColumn(columnName)) {
|
||||
chain.add(columnName, value);
|
||||
}
|
||||
}
|
||||
|
||||
public void ensureRole(RoleConstant roleConstant) {
|
||||
if (pk == null || !isSysUserTable()) {
|
||||
return;
|
||||
}
|
||||
Sys_role sysRole = sysRoleService.getByCode(roleConstant);
|
||||
if (sysRole == null) {
|
||||
return;
|
||||
}
|
||||
int count = dao.count(Sys_user_role.class, Cnd.where("userId", "=", String.valueOf(pk))
|
||||
.and("roleId", "=", sysRole.getId()));
|
||||
if (count > 0) {
|
||||
return;
|
||||
}
|
||||
Sys_user_role userRole = new Sys_user_role();
|
||||
userRole.setUserId(String.valueOf(pk));
|
||||
userRole.setRoleId(sysRole.getId());
|
||||
dao.insert(userRole);
|
||||
}
|
||||
}
|
||||
}
|
||||
+53
-10
@@ -311,10 +311,7 @@ public class ActivityBasicScopeController {
|
||||
cnd.orderBy(activityUserScopePageParam.getPageOrderName(), activityUserScopePageParam.getPageOrderBy().equalsIgnoreCase("ascending") ? "ASC" : "DESC");
|
||||
}
|
||||
|
||||
if (activityUserScopePageParam.getActivityGroupId() != null) {
|
||||
Sql sqlx = activityBasicScopeService.buildGroupUserIdSubSql(activityUserScopePageParam.getActivityGroupId());
|
||||
cnd.and("u.id", activityUserScopePageParam.getReverseSelection() ? "IN" : "NOT IN", sqlx);
|
||||
}
|
||||
appendActivityGroupCondition(cnd, activityUserScopePageParam);
|
||||
|
||||
cnd.andEX("u.id", IN_OR_NIN_OP, activityUserScopePageParam.getUserId());
|
||||
|
||||
@@ -326,7 +323,7 @@ public class ActivityBasicScopeController {
|
||||
cnd.and("u.welfareMember", EQ_OR_NEQ_OP, 1);
|
||||
}
|
||||
if (ArrayUtils.contains(activityUserScopePageParam.getMemberTypes(), "基金会员")) {
|
||||
cnd.and(new Static(" u.loginname " + IN_OR_NIN_OP + " (select loginname from sick_fund_member)"));
|
||||
cnd.and("u.aidFundMember", EQ_OR_NEQ_OP, 1);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -351,8 +348,12 @@ public class ActivityBasicScopeController {
|
||||
if (!AuthUtil.hasRoleOr(RoleConstant.SYSADMIN.name(), RoleConstant.SCHOOL_UNION_ADMIN.name())){
|
||||
cnd.andEX("u.unionid", "=", SecurityUtil.getUnionId());
|
||||
}
|
||||
cnd.andEX("u.unionid", EQ_OR_NEQ_OP, activityUserScopePageParam.getUnionId());
|
||||
cnd.andEX("u.unitid", EQ_OR_NEQ_OP, activityUserScopePageParam.getUnitId());
|
||||
String[] unionIds = getUnionIds(activityUserScopePageParam);
|
||||
if (Lang.isNotEmpty(unionIds)) {
|
||||
cnd.andEX("u.unionid", IN_OR_NIN_OP, unionIds);
|
||||
} else {
|
||||
cnd.andEX("u.unionid", EQ_OR_NEQ_OP, activityUserScopePageParam.getUnionId());
|
||||
}
|
||||
cnd.andEX("u.personType", IN_OR_NIN_OP, activityUserScopePageParam.getPersonTypes());
|
||||
cnd.andEX("u.userState", IN_OR_NIN_OP, activityUserScopePageParam.getUserStates());
|
||||
cnd.andEX("u.sex", IN_OR_NIN_OP, activityUserScopePageParam.getSexTypes());
|
||||
@@ -367,6 +368,34 @@ public class ActivityBasicScopeController {
|
||||
|
||||
}
|
||||
|
||||
private void appendActivityGroupCondition(Cnd cnd, ActivityUserScopePageParam activityUserScopePageParam) {
|
||||
Integer activityGroupId = activityUserScopePageParam.getActivityGroupId();
|
||||
if (activityGroupId == null) {
|
||||
return;
|
||||
}
|
||||
boolean reverseSelection = Boolean.TRUE.equals(activityUserScopePageParam.getReverseSelection());
|
||||
Integer groupType = activityBasicScopeService.getGroupType(activityGroupId);
|
||||
if (GROUP_TYPE_RESULT == groupType) {
|
||||
String existsSql = """
|
||||
EXISTS (
|
||||
SELECT 1
|
||||
FROM activity_user_scope aus
|
||||
WHERE aus.groupId = %d
|
||||
AND aus.userId = u.id
|
||||
)
|
||||
""".formatted(activityGroupId);
|
||||
cnd.and(new Static(reverseSelection ? existsSql : "NOT " + existsSql));
|
||||
return;
|
||||
}
|
||||
|
||||
ActivityUserScope groupInfo = activityBasicScopeService.getGroupInfo(activityGroupId);
|
||||
if (groupInfo == null || StrUtil.isBlank(groupInfo.getGroupSql())) {
|
||||
return;
|
||||
}
|
||||
String groupSql = "(" + groupInfo.getGroupSql() + ")";
|
||||
cnd.and(new Static(reverseSelection ? groupSql : "NOT " + groupSql));
|
||||
}
|
||||
|
||||
/**
|
||||
* 结果分组会把当前筛选出的用户快照保存下来,因此只落 userId 明细数据。
|
||||
*/
|
||||
@@ -550,7 +579,7 @@ public class ActivityBasicScopeController {
|
||||
conditionList.add("u.welfareMember " + eqOrNeq + " 1");
|
||||
}
|
||||
if (ArrayUtils.contains(activityUserScopePageParam.getMemberTypes(), "基金会员")) {
|
||||
conditionList.add("u.loginname " + inOrNotIn + " (select loginname from sick_fund_member)");
|
||||
conditionList.add("u.aidFundMember " + eqOrNeq + " 1");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -574,8 +603,12 @@ public class ActivityBasicScopeController {
|
||||
conditionList.add("u.unionid = " + wrapSqlValue(SecurityUtil.getUnionId()));
|
||||
}
|
||||
|
||||
addSingleValueCondition(conditionList, "u.unionid", eqOrNeq, activityUserScopePageParam.getUnionId());
|
||||
addSingleValueCondition(conditionList, "u.unitid", eqOrNeq, activityUserScopePageParam.getUnitId());
|
||||
String[] unionIds = getUnionIds(activityUserScopePageParam);
|
||||
if (Lang.isNotEmpty(unionIds)) {
|
||||
addArrayCondition(conditionList, "u.unionid", inOrNotIn, unionIds);
|
||||
} else {
|
||||
addSingleValueCondition(conditionList, "u.unionid", eqOrNeq, activityUserScopePageParam.getUnionId());
|
||||
}
|
||||
addArrayCondition(conditionList, "u.personType", inOrNotIn, activityUserScopePageParam.getPersonTypes());
|
||||
addArrayCondition(conditionList, "u.userState", inOrNotIn, activityUserScopePageParam.getUserStates());
|
||||
addArrayCondition(conditionList, "u.sex", inOrNotIn, activityUserScopePageParam.getSexTypes());
|
||||
@@ -610,6 +643,16 @@ public class ActivityBasicScopeController {
|
||||
}
|
||||
}
|
||||
|
||||
private String[] getUnionIds(ActivityUserScopePageParam activityUserScopePageParam) {
|
||||
if (Lang.isNotEmpty(activityUserScopePageParam.getUnionIds())) {
|
||||
return activityUserScopePageParam.getUnionIds();
|
||||
}
|
||||
if (StrUtil.isNotBlank(activityUserScopePageParam.getUnionId())) {
|
||||
return new String[]{activityUserScopePageParam.getUnionId()};
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private void addArrayCondition(List<String> conditionList, String columnName, String operator, String[] values) {
|
||||
if (Lang.isNotEmpty(values)) {
|
||||
conditionList.add(columnName + " " + operator + " (" + buildSqlStringList(values) + ")");
|
||||
|
||||
@@ -20,7 +20,8 @@ import java.io.Serializable;
|
||||
@Comment("活动人员范围设置")
|
||||
@TableIndexes({
|
||||
@Index(name = "INDEX_ACTIVITY_USER_SCOPE_GROUPID", fields = {"groupId"}, unique = false),
|
||||
@Index(name = "INDEX_ACTIVITY_USER_SCOPE_USERID", fields = {"userId"}, unique = false)
|
||||
@Index(name = "INDEX_ACTIVITY_USER_SCOPE_USERID", fields = {"userId"}, unique = false),
|
||||
@Index(name = "INDEX_ACTIVITY_USER_SCOPE_GROUPID_USERID", fields = {"groupId", "userId"}, unique = false)
|
||||
})
|
||||
public class ActivityUserScope extends BaseModel implements Serializable {
|
||||
|
||||
|
||||
@@ -16,6 +16,7 @@ public class ActivityUserScopePageParam extends PageForm {
|
||||
|
||||
// 工会id
|
||||
private String unionId;
|
||||
private String[] unionIds;
|
||||
// 单位id
|
||||
private String unitId;
|
||||
// 人类型
|
||||
|
||||
@@ -148,6 +148,7 @@
|
||||
:prop="column.prop"
|
||||
:key="column.prop"
|
||||
:sortable="column.sortable"
|
||||
:formatter="column.formatter"
|
||||
></el-table-column>
|
||||
<el-table-column align="center" header-align="center" label="操作" width="100">
|
||||
<template slot-scope="{ row }">
|
||||
@@ -232,7 +233,7 @@ module.exports = {
|
||||
{prop: "loginName", label: "工号"},
|
||||
{prop: "userName", label: "姓名"},
|
||||
{prop: "sex", label: "性别", sortable: true},
|
||||
{prop: "birthday", label: "出生年月"},
|
||||
{prop: "birthday", label: "出生年月", formatter: this.formatDate},
|
||||
{prop: "mobile", label: "联系电话"},
|
||||
{prop: "personType", label: "教职工类别", sortable: true},
|
||||
{prop: "userState", label: "在职状态", sortable: true},
|
||||
@@ -263,6 +264,9 @@ module.exports = {
|
||||
}
|
||||
return group.groupName + "(人员结果)"
|
||||
},
|
||||
formatDate(row, column, cellValue) {
|
||||
return cellValue ? moment(cellValue).format("YYYY-MM-DD") : ""
|
||||
},
|
||||
viewGroupName() {
|
||||
if (this.pageForm.groupId) {
|
||||
const group = this.activityGroupList.find((v) => v.groupId === this.pageForm.groupId)
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -43,7 +43,7 @@ layout("/layouts/platform.html"){
|
||||
<el-table-column type="index" width="50px" label="序号" :index="indexMethod"></el-table-column>
|
||||
<el-table-column prop="displayName" label="流程定义名称"></el-table-column>
|
||||
<el-table-column prop="name" label="流程定义编码"></el-table-column>
|
||||
<el-table-column prop="category" label="流程分类">
|
||||
<el-table-column prop="category" label="流程分类" sortable="custom">
|
||||
<template slot-scope="{row}">
|
||||
{{categoryOptions.find(v=>v.id === row.category)?.name}}
|
||||
</template>
|
||||
@@ -54,6 +54,19 @@ layout("/layouts/platform.html"){
|
||||
<el-tag size="mini" v-else-if="row.isDeployed===0" type="info">否</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="排序编码" prop="sortNo" width="120" align="center" header-align="center" sortable="custom">
|
||||
<template slot-scope="{row}">
|
||||
<el-input-number
|
||||
v-model="row.sortNo"
|
||||
:controls="false"
|
||||
:min="0"
|
||||
:precision="0"
|
||||
size="mini"
|
||||
style="width: 88px"
|
||||
@change="updateSortNo(row)"
|
||||
></el-input-number>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" fixed="right" width="450px">
|
||||
<template slot-scope="{row}">
|
||||
<el-button size="mini" type="primary" @click="onDesign(row)">设计</el-button>
|
||||
@@ -237,6 +250,22 @@ layout("/layouts/platform.html"){
|
||||
}
|
||||
})
|
||||
},
|
||||
updateSortNo(row) {
|
||||
const sortNo = Number(row.sortNo)
|
||||
if (!Number.isInteger(sortNo) || sortNo < 0) {
|
||||
this.$message.error("排序编码必须是非负整数")
|
||||
return
|
||||
}
|
||||
$.post("/flow/design/updateSortNo", {
|
||||
id: row.id,
|
||||
sortNo
|
||||
}).then((res) => {
|
||||
if (res.code === 0) {
|
||||
this.$message.success(res.msg)
|
||||
this.pageData()
|
||||
}
|
||||
})
|
||||
},
|
||||
},
|
||||
created() {
|
||||
this.pageData()
|
||||
|
||||
@@ -0,0 +1,524 @@
|
||||
<!--#
|
||||
layout("/layouts/platform.html"){
|
||||
#-->
|
||||
<style>
|
||||
#app {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
min-height: calc(100vh - 40px);
|
||||
}
|
||||
|
||||
.tool-card {
|
||||
width: calc(100% - 20px);
|
||||
min-height: calc(100vh - 60px);
|
||||
}
|
||||
|
||||
.tool-card .el-card__body {
|
||||
height: calc(100% - 57px);
|
||||
}
|
||||
|
||||
.tool-body {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
min-height: calc(100vh - 180px);
|
||||
}
|
||||
|
||||
.tool-body-center {
|
||||
width: 70%;
|
||||
min-width: 900px;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.wizard-box {
|
||||
margin-top: 20px;
|
||||
border: 1px solid #ebeef5;
|
||||
border-radius: 8px;
|
||||
background: #fff;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.wizard-panel {
|
||||
padding: 18px;
|
||||
min-height: 520px;
|
||||
}
|
||||
|
||||
.option-toolbar {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
.option-list {
|
||||
width: 100%;
|
||||
display: block;
|
||||
max-height: 470px;
|
||||
overflow-y: auto;
|
||||
padding-right: 8px;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.option-list .el-radio,
|
||||
.option-list .el-checkbox {
|
||||
display: flex;
|
||||
width: 100%;
|
||||
margin: 0 0 12px 0 !important;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.option-list .el-radio.is-bordered,
|
||||
.option-list .el-checkbox.is-bordered {
|
||||
margin-left: 0 !important;
|
||||
width: 100%;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.option-list .el-radio__label,
|
||||
.option-list .el-checkbox__label {
|
||||
display: flex;
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
padding-right: 0;
|
||||
}
|
||||
|
||||
.option-extra {
|
||||
color: #f56c6c;
|
||||
margin-left: auto;
|
||||
padding-left: 12px;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.option-item-content {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
width: 100%;
|
||||
min-width: 0;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.option-item-main {
|
||||
min-width: 0;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.relation-table {
|
||||
height: 500px;
|
||||
}
|
||||
|
||||
.submit-panel {
|
||||
max-width: 900px;
|
||||
margin: 0 auto;
|
||||
padding-top: 10px;
|
||||
}
|
||||
|
||||
.result-panel {
|
||||
min-height: 420px;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.wizard-footer {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
gap: 12px;
|
||||
margin-top: 18px;
|
||||
}
|
||||
</style>
|
||||
|
||||
<div id="app" v-cloak>
|
||||
<el-card class="tool-card" shadow="never">
|
||||
<div slot="header">
|
||||
<span>高级工具</span>
|
||||
</div>
|
||||
|
||||
<div class="tool-body">
|
||||
<div class="tool-body-center">
|
||||
<el-steps :active="active" align-center finish-status="success">
|
||||
<el-step title="选择数据表" icon="el-icon-coin"></el-step>
|
||||
<el-step title="选择字段" icon="el-icon-s-grid"></el-step>
|
||||
<el-step title="字段对应" icon="el-icon-connection"></el-step>
|
||||
<el-step title="提交导入" icon="el-icon-upload2"></el-step>
|
||||
<el-step title="导入结果" icon="el-icon-success"></el-step>
|
||||
</el-steps>
|
||||
|
||||
<div class="wizard-box">
|
||||
<div class="wizard-panel" v-if="active === 0">
|
||||
<div class="option-toolbar">
|
||||
<el-input
|
||||
v-model.trim="tableKeyword"
|
||||
clearable
|
||||
placeholder="输入表名或备注搜索"
|
||||
style="width: 260px">
|
||||
</el-input>
|
||||
<el-button type="primary" icon="el-icon-search" @click="filterTables">搜索</el-button>
|
||||
<el-button v-if="formData.tableName" type="text">当前选择:{{ formData.tableName }}</el-button>
|
||||
</div>
|
||||
<el-radio-group v-model="formData.tableName" class="option-list">
|
||||
<el-radio
|
||||
v-for="item in filteredTables"
|
||||
:key="item.table_name"
|
||||
:label="item.table_name"
|
||||
border>
|
||||
<div class="option-item-content">
|
||||
<span class="option-item-main">{{ item.table_name }}</span>
|
||||
<span v-if="item.table_comment" class="option-item-main">({{ item.table_comment }})</span>
|
||||
<span class="option-extra">rows: {{ item.table_rows || 0 }}</span>
|
||||
</div>
|
||||
</el-radio>
|
||||
</el-radio-group>
|
||||
</div>
|
||||
|
||||
<div class="wizard-panel" v-if="active === 1">
|
||||
<div class="option-toolbar">
|
||||
<el-input
|
||||
v-model.trim="columnKeyword"
|
||||
clearable
|
||||
placeholder="输入字段名或备注搜索"
|
||||
style="width: 260px">
|
||||
</el-input>
|
||||
<el-button type="primary" icon="el-icon-search" @click="filterColumns">搜索</el-button>
|
||||
<el-button type="text">{{ formData.tableName }}</el-button>
|
||||
</div>
|
||||
<el-checkbox-group v-model="formData.columns" class="option-list">
|
||||
<el-checkbox
|
||||
v-for="item in filteredColumns"
|
||||
:key="item.column_name"
|
||||
:label="item.column_name"
|
||||
border>
|
||||
<div class="option-item-content">
|
||||
<span class="option-item-main">{{ item.column_name }}</span>
|
||||
<span v-if="item.column_comment" class="option-item-main">({{ item.column_comment }})</span>
|
||||
<span class="option-extra">{{ item.column_type }}</span>
|
||||
</div>
|
||||
</el-checkbox>
|
||||
</el-checkbox-group>
|
||||
</div>
|
||||
|
||||
<div class="wizard-panel" v-if="active === 2">
|
||||
<el-alert
|
||||
title="这里填写 Excel 第一行表头名称,用来和数据库字段建立对应关系。"
|
||||
type="info"
|
||||
:closable="false"
|
||||
style="margin-bottom: 16px">
|
||||
</el-alert>
|
||||
<el-table :data="relation" border class="relation-table">
|
||||
<el-table-column prop="column_name" label="字段名" min-width="180"></el-table-column>
|
||||
<el-table-column prop="column_comment" label="字段备注" min-width="220" show-overflow-tooltip></el-table-column>
|
||||
<el-table-column prop="column_type" label="字段类型" width="160"></el-table-column>
|
||||
<el-table-column prop="column_key" label="键" width="80"></el-table-column>
|
||||
<el-table-column label="Excel 表头" min-width="260">
|
||||
<template slot-scope="{ row }">
|
||||
<el-input v-model.trim="row.relation" placeholder="请输入 Excel 表头名称"></el-input>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</div>
|
||||
|
||||
<div class="wizard-panel" v-if="active === 3">
|
||||
<div class="submit-panel">
|
||||
<el-form label-width="120px">
|
||||
<el-form-item label="导入方式">
|
||||
<el-radio-group v-model="formData.method">
|
||||
<el-radio-button :label="1">追加或更新</el-radio-button>
|
||||
<el-radio-button :label="2">仅追加</el-radio-button>
|
||||
<el-radio-button :label="3">仅更新</el-radio-button>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="关键字段" v-if="[1, 3].includes(formData.method)">
|
||||
<el-select
|
||||
v-model="formData.field"
|
||||
clearable
|
||||
filterable
|
||||
placeholder="请选择关键字段"
|
||||
style="width: 360px">
|
||||
<el-option
|
||||
v-for="item in relation"
|
||||
:key="item.column_name"
|
||||
:label="item.column_name"
|
||||
:value="item.column_name">
|
||||
</el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="可选插件">
|
||||
<el-checkbox-group v-model="formData.plugins">
|
||||
<el-checkbox
|
||||
v-for="item in plugins"
|
||||
:key="item.name"
|
||||
:label="item.name"
|
||||
border>
|
||||
{{ item.description }}
|
||||
</el-checkbox>
|
||||
</el-checkbox-group>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="Excel 文件" required>
|
||||
<el-upload
|
||||
ref="upload"
|
||||
drag
|
||||
action="#"
|
||||
:auto-upload="false"
|
||||
:limit="1"
|
||||
:file-list="fileList"
|
||||
:on-change="handleFileChange"
|
||||
:on-remove="handleFileRemove">
|
||||
<i class="el-icon-upload"></i>
|
||||
<div class="el-upload__text">将文件拖到此处,或<em>点击上传</em></div>
|
||||
<div slot="tip" class="el-upload__tip">仅支持 `xls`、`xlsx` 文件</div>
|
||||
</el-upload>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="wizard-panel" v-if="active === 4">
|
||||
<div class="result-panel">
|
||||
<el-progress type="circle" :percentage="resultPercentage" status="success"></el-progress>
|
||||
<div style="margin-top: 18px; color: #606266;">
|
||||
共 {{ result.total || 0 }} 条,成功 {{ result.success || 0 }} 条
|
||||
</div>
|
||||
<div v-if="result.cacheKey" style="margin-top: 10px;">
|
||||
<el-link type="primary" :href="loc() + '/exportErrors?cacheKey=' + result.cacheKey">下载错误记录</el-link>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="wizard-footer">
|
||||
<el-button :disabled="active === 0 || loading" @click="prevStep">上一步</el-button>
|
||||
<el-button v-if="active < 4" type="primary" :loading="loading" @click="nextStep">下一步</el-button>
|
||||
<el-button v-else type="primary" @click="restart">重新开始</el-button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</el-card>
|
||||
</div>
|
||||
|
||||
<script nonce="${cspNonce!}">
|
||||
new Vue({
|
||||
el: "#app",
|
||||
data() {
|
||||
return {
|
||||
active: 0,
|
||||
loading: false,
|
||||
tableKeyword: "",
|
||||
columnKeyword: "",
|
||||
tables: [],
|
||||
filteredTables: [],
|
||||
columns: [],
|
||||
filteredColumns: [],
|
||||
relation: [],
|
||||
plugins: [],
|
||||
fileList: [],
|
||||
result: {
|
||||
total: 0,
|
||||
success: 0,
|
||||
cacheKey: ""
|
||||
},
|
||||
formData: {
|
||||
tableName: "",
|
||||
columns: [],
|
||||
method: 1,
|
||||
field: "",
|
||||
plugins: []
|
||||
}
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
resultPercentage() {
|
||||
if (!this.result.total) {
|
||||
return 0
|
||||
}
|
||||
return Number(((this.result.success / this.result.total) * 100).toFixed(2))
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
normalizeRecord(item) {
|
||||
const normalized = {}
|
||||
Object.keys(item || {}).forEach(key => {
|
||||
normalized[(key || "").toLowerCase()] = item[key]
|
||||
})
|
||||
return normalized
|
||||
},
|
||||
async loadTables() {
|
||||
const resp = await this.$axios.post(loc() + "/tableNames")
|
||||
if (resp.code === 0) {
|
||||
this.tables = Array.isArray(resp.data)
|
||||
? resp.data.map(item => this.normalizeRecord(item))
|
||||
: []
|
||||
this.filteredTables = this.tables.slice()
|
||||
}
|
||||
},
|
||||
async loadPlugins() {
|
||||
this.plugins = await this.$businessTool.getEnumOptions("SysDataImportPlugin")
|
||||
},
|
||||
async loadColumns() {
|
||||
const resp = await this.$axios.post(loc() + "/columns", {
|
||||
tableName: this.formData.tableName
|
||||
})
|
||||
if (resp.code === 0) {
|
||||
this.columns = Array.isArray(resp.data)
|
||||
? resp.data.map(item => this.normalizeRecord(item))
|
||||
: []
|
||||
this.filteredColumns = this.columns.slice()
|
||||
}
|
||||
},
|
||||
filterTables() {
|
||||
const keyword = (this.tableKeyword || "").toLowerCase()
|
||||
if (!keyword) {
|
||||
this.filteredTables = this.tables.slice()
|
||||
return
|
||||
}
|
||||
this.filteredTables = this.tables.filter(item => {
|
||||
const tableName = (item.table_name || "").toLowerCase()
|
||||
const tableComment = (item.table_comment || "").toLowerCase()
|
||||
return tableName.includes(keyword) || tableComment.includes(keyword)
|
||||
})
|
||||
},
|
||||
filterColumns() {
|
||||
const keyword = (this.columnKeyword || "").toLowerCase()
|
||||
if (!keyword) {
|
||||
this.filteredColumns = this.columns.slice()
|
||||
return
|
||||
}
|
||||
this.filteredColumns = this.columns.filter(item => {
|
||||
const columnName = (item.column_name || "").toLowerCase()
|
||||
const columnComment = (item.column_comment || "").toLowerCase()
|
||||
return columnName.includes(keyword) || columnComment.includes(keyword)
|
||||
})
|
||||
},
|
||||
buildRelation() {
|
||||
this.relation = this.columns
|
||||
.filter(item => this.formData.columns.includes(item.column_name))
|
||||
.map(item => Object.assign({}, item, { relation: "" }))
|
||||
},
|
||||
async nextStep() {
|
||||
if (this.active === 0) {
|
||||
if (!this.formData.tableName) {
|
||||
this.$message.warning("请选择数据表")
|
||||
return
|
||||
}
|
||||
await this.loadColumns()
|
||||
this.formData.columns = []
|
||||
this.formData.field = ""
|
||||
} else if (this.active === 1) {
|
||||
if (!this.formData.columns.length) {
|
||||
this.$message.warning("请至少选择一个字段")
|
||||
return
|
||||
}
|
||||
this.buildRelation()
|
||||
} else if (this.active === 2) {
|
||||
const hasEmptyRelation = this.relation.some(item => !item.relation)
|
||||
if (hasEmptyRelation) {
|
||||
this.$message.warning("请填写所有 Excel 表头对应关系")
|
||||
return
|
||||
}
|
||||
} else if (this.active === 3) {
|
||||
const success = await this.submitImport()
|
||||
if (!success) {
|
||||
return
|
||||
}
|
||||
}
|
||||
this.active += 1
|
||||
},
|
||||
prevStep() {
|
||||
if (this.active > 0) {
|
||||
this.active -= 1
|
||||
}
|
||||
},
|
||||
handleFileRemove(file, fileList) {
|
||||
this.fileList = fileList
|
||||
},
|
||||
handleFileChange(file, fileList) {
|
||||
const extension = ((file.name || "").split(".").pop() || "").toLowerCase()
|
||||
const removeIndex = fileList.findIndex(item => item.uid === file.uid)
|
||||
if (!["xls", "xlsx"].includes(extension)) {
|
||||
this.$message.warning("仅支持 xls、xlsx 文件")
|
||||
if (removeIndex > -1) {
|
||||
fileList.splice(removeIndex, 1)
|
||||
}
|
||||
} else if (file.size === 0) {
|
||||
this.$message.warning("上传文件不能为空")
|
||||
if (removeIndex > -1) {
|
||||
fileList.splice(removeIndex, 1)
|
||||
}
|
||||
}
|
||||
this.fileList = fileList
|
||||
},
|
||||
async submitImport() {
|
||||
if ([1, 3].includes(this.formData.method) && !this.formData.field) {
|
||||
this.$message.warning("请选择关键字段")
|
||||
return false
|
||||
}
|
||||
if (!this.fileList.length) {
|
||||
this.$message.warning("请上传 Excel 文件")
|
||||
return false
|
||||
}
|
||||
|
||||
const formData = new FormData()
|
||||
formData.append("tableName", this.formData.tableName)
|
||||
formData.append("method", this.formData.method)
|
||||
formData.append("field", this.formData.field || "")
|
||||
formData.append("relation", JSON.stringify(this.relation))
|
||||
formData.append("plugins", JSON.stringify(this.formData.plugins || []))
|
||||
formData.append("file", this.fileList[0].raw, this.fileList[0].name)
|
||||
|
||||
this.loading = true
|
||||
try {
|
||||
const resp = await this.$axios.post(loc() + "/importData", formData, {
|
||||
headers: {
|
||||
"Content-Type": "multipart/form-data"
|
||||
}
|
||||
})
|
||||
if (resp.code !== 0) {
|
||||
this.$message.error(resp.msg)
|
||||
return false
|
||||
}
|
||||
this.result = resp.data || { total: 0, success: 0, cacheKey: "" }
|
||||
this.$message.success(resp.msg)
|
||||
return true
|
||||
} finally {
|
||||
this.loading = false
|
||||
}
|
||||
},
|
||||
restart() {
|
||||
this.active = 0
|
||||
this.tableKeyword = ""
|
||||
this.columnKeyword = ""
|
||||
this.columns = []
|
||||
this.filteredColumns = []
|
||||
this.relation = []
|
||||
this.fileList = []
|
||||
this.result = {
|
||||
total: 0,
|
||||
success: 0,
|
||||
cacheKey: ""
|
||||
}
|
||||
this.formData = {
|
||||
tableName: "",
|
||||
columns: [],
|
||||
method: 1,
|
||||
field: "",
|
||||
plugins: []
|
||||
}
|
||||
if (this.$refs.upload) {
|
||||
this.$refs.upload.clearFiles()
|
||||
}
|
||||
this.filterTables()
|
||||
}
|
||||
},
|
||||
async created() {
|
||||
await this.loadTables()
|
||||
await this.loadPlugins()
|
||||
}
|
||||
})
|
||||
</script>
|
||||
<!--#
|
||||
}
|
||||
#-->
|
||||
@@ -65,6 +65,19 @@ layout("/layouts/platform.html"){
|
||||
row-key="id"
|
||||
>
|
||||
<el-table-column align="left" header-align="left" label="菜单名称" prop="name" width="200"></el-table-column>
|
||||
<el-table-column align="center" header-align="center" label="排序编码" prop="location" width="120">
|
||||
<template slot-scope="{row}">
|
||||
<el-input-number
|
||||
v-model="row.location"
|
||||
:controls="false"
|
||||
:min="0"
|
||||
:precision="0"
|
||||
size="mini"
|
||||
style="width: 88px"
|
||||
@change="updateLocation(row)"
|
||||
></el-input-number>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column align="center" header-align="center" label="菜单图标" prop="icon" width="100">
|
||||
<template slot-scope="scope">
|
||||
<template v-if="pageForm.platform==='PC'">
|
||||
@@ -325,6 +338,26 @@ layout("/layouts/platform.html"){
|
||||
this.moduleOptions = res.data
|
||||
}
|
||||
})
|
||||
},
|
||||
updateLocation(row) {
|
||||
const location = Number(row.location)
|
||||
if (!Number.isInteger(location) || location < 0) {
|
||||
this.$message.error("排序编码必须是非负整数")
|
||||
return
|
||||
}
|
||||
$.post("/platform/sys/menu/updateLocation", {
|
||||
id: row.id,
|
||||
location
|
||||
}).then((res) => {
|
||||
if (res.code === 0) {
|
||||
this.$message.success(res.msg)
|
||||
if (row.parentId) {
|
||||
this.loadChildByExpandedKeys()
|
||||
} else {
|
||||
this.initTreeTable()
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
|
||||
@@ -20,6 +20,24 @@ const branchUnionUserManage = {
|
||||
<el-option label="工号" value="loginname"></el-option>
|
||||
</el-select>
|
||||
</el-input>
|
||||
<el-select
|
||||
v-model="pageForm.j"
|
||||
placeholder="届数"
|
||||
size="small"
|
||||
clearable
|
||||
class="j-search-select"
|
||||
@change="handleJChange"
|
||||
>
|
||||
<el-option
|
||||
v-for="item in jOptions"
|
||||
:key="item.code"
|
||||
:label="item.name"
|
||||
:value="item.code"
|
||||
>
|
||||
<span>{{ item.name }}</span>
|
||||
<span v-if="hasCadreData(item.code)" class="j-used-mark">*</span>
|
||||
</el-option>
|
||||
</el-select>
|
||||
<el-button type="primary" size="small" icon="el-icon-search" @click="doSearch"></el-button>
|
||||
<el-button type="primary" size="small" icon="el-icon-plus" style="margin-left: auto"
|
||||
@click="openAdd" v-if="$auth.hasPermission('sys.manager.union.branchOfficer')">添加
|
||||
@@ -31,11 +49,23 @@ const branchUnionUserManage = {
|
||||
<el-table-column prop="loginName" label="工号"></el-table-column>
|
||||
<el-table-column prop="userName" label="姓名"></el-table-column>
|
||||
<el-table-column prop="mobile" label="联系方式"></el-table-column>
|
||||
<el-table-column label="届数">
|
||||
<template scope="{row}">
|
||||
{{ row.jName || row.j }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="roleName" label="职务"></el-table-column>
|
||||
<el-table-column prop="taskName" label="当前状态"></el-table-column>
|
||||
<el-table-column label="操作" width="100px"
|
||||
<el-table-column prop="displayStatus" label="当前状态"></el-table-column>
|
||||
<el-table-column label="操作" width="150px"
|
||||
v-if="$auth.hasPermission('sys.manager.union.branchOfficer')">
|
||||
<template scope="scope">
|
||||
<el-button
|
||||
v-if="!isLeft(scope.row)"
|
||||
size="mini"
|
||||
type="warning"
|
||||
icon="el-icon-switch-button"
|
||||
@click="openLeave(scope.row)"
|
||||
></el-button>
|
||||
<el-button size="mini" type="danger" icon="el-icon-delete"
|
||||
@click="doDelete(scope.row)"></el-button>
|
||||
</template>
|
||||
@@ -47,6 +77,9 @@ const branchUnionUserManage = {
|
||||
<el-form-item prop="roleCode" label="角色">
|
||||
<dict-select v-model="formData.roleCode" code="BRANCH_UNION_ROLES" placeholder="请选择角色"></dict-select>
|
||||
</el-form-item>
|
||||
<el-form-item prop="j" label="届数">
|
||||
<dict-select v-model="formData.j" code="TEACHER_CONGRESS_J" placeholder="请选择届数"></dict-select>
|
||||
</el-form-item>
|
||||
<el-form-item prop="userId" label="人员">
|
||||
<user-select
|
||||
v-model="formData.userId"
|
||||
@@ -66,6 +99,23 @@ const branchUnionUserManage = {
|
||||
<el-button type="primary" @click="doSubmit">确 定</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
<el-dialog title="离任" :visible.sync="leaveDialogVisible" width="420px" :close-on-click-modal="false">
|
||||
<el-form :model="leaveForm" ref="leaveForm" size="small" label-width="90px">
|
||||
<el-form-item label="离任时间" required>
|
||||
<el-date-picker
|
||||
v-model="leaveForm.leaveDate"
|
||||
type="date"
|
||||
value-format="yyyy-MM-dd"
|
||||
placeholder="请选择离任时间"
|
||||
style="width: 100%"
|
||||
></el-date-picker>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<div slot="footer" class="dialog-footer">
|
||||
<el-button @click="leaveDialogVisible = false">取 消</el-button>
|
||||
<el-button type="primary" @click="doLeave">确 定</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
</div>
|
||||
`,
|
||||
mixins: [initTableMixins],
|
||||
@@ -78,32 +128,114 @@ const branchUnionUserManage = {
|
||||
data() {
|
||||
return {
|
||||
pageForm: {
|
||||
searchName: "username"
|
||||
searchName: "username",
|
||||
j: ""
|
||||
},
|
||||
dialogFormVisible: false,
|
||||
formData: {}
|
||||
formData: {},
|
||||
leaveDialogVisible: false,
|
||||
leaveForm: {
|
||||
id: "",
|
||||
leaveDate: ""
|
||||
},
|
||||
jOptions: [],
|
||||
usedJCodes: []
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
union_id(val) {
|
||||
this.doSearch()
|
||||
this.pageForm.j = ""
|
||||
this.initJSearch()
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
loadJOptions() {
|
||||
return $.get("/open/common/dictOptions", { code: "TEACHER_CONGRESS_J" }).then((res) => {
|
||||
this.jOptions = res.data || []
|
||||
})
|
||||
},
|
||||
loadUsedJCodes() {
|
||||
if (!this.union_id) {
|
||||
this.usedJCodes = []
|
||||
return $.Deferred().resolve().promise()
|
||||
}
|
||||
return $.get("/platform/sys/union/branchUnionUserUsedJData", {
|
||||
unionId: this.union_id
|
||||
}).then((res) => {
|
||||
if (res.code === 0) {
|
||||
this.usedJCodes = res.data || []
|
||||
}
|
||||
})
|
||||
},
|
||||
hasCadreData(code) {
|
||||
return this.usedJCodes.includes(code)
|
||||
},
|
||||
getHighestUsedJ() {
|
||||
if (!this.usedJCodes.length) {
|
||||
return ""
|
||||
}
|
||||
for (let i = this.jOptions.length - 1; i >= 0; i--) {
|
||||
if (this.usedJCodes.includes(this.jOptions[i].code)) {
|
||||
return this.jOptions[i].code
|
||||
}
|
||||
}
|
||||
return this.usedJCodes[0]
|
||||
},
|
||||
initJSearch() {
|
||||
const optionTask = this.jOptions.length ? $.Deferred().resolve().promise() : this.loadJOptions()
|
||||
$.when(optionTask, this.loadUsedJCodes()).then(() => {
|
||||
this.pageForm.j = this.getHighestUsedJ()
|
||||
this.pageData()
|
||||
})
|
||||
},
|
||||
handleJChange(val) {
|
||||
this.pageForm.j = val || ""
|
||||
this.doSearch()
|
||||
},
|
||||
isLeft(row) {
|
||||
return row.isServing === false || row.isServing === 0 || row.displayStatus === "离任"
|
||||
},
|
||||
openAdd() {
|
||||
this.dialogFormVisible = true
|
||||
this.$nextTick(() => {
|
||||
this.formData = {}
|
||||
})
|
||||
},
|
||||
openLeave(row) {
|
||||
this.leaveForm = {
|
||||
id: row.id,
|
||||
leaveDate: ""
|
||||
}
|
||||
this.leaveDialogVisible = true
|
||||
},
|
||||
doSubmit() {
|
||||
this.$axios.post("/platform/sys/union/insertBranchUnionUserRole", {
|
||||
if (!this.formData.j) {
|
||||
this.$message.error("请选择届数")
|
||||
return
|
||||
}
|
||||
$.post("/platform/sys/union/insertBranchUnionUserRole", {
|
||||
...this.formData,
|
||||
unionId: this.union_id
|
||||
}).then((res) => {
|
||||
if (res.code === 0) {
|
||||
this.dialogFormVisible = false
|
||||
this.$message.success(res.msg)
|
||||
this.loadUsedJCodes()
|
||||
this.doSearch()
|
||||
} else {
|
||||
this.$message.error(res.msg)
|
||||
}
|
||||
})
|
||||
},
|
||||
doLeave() {
|
||||
if (!this.leaveForm.leaveDate) {
|
||||
this.$message.error("请选择离任时间")
|
||||
return
|
||||
}
|
||||
$.post("/platform/sys/union/leaveBranchUnionUserRole", this.leaveForm).then((res) => {
|
||||
if (res.code === 0) {
|
||||
this.leaveDialogVisible = false
|
||||
this.$message.success(res.msg)
|
||||
this.doSearch()
|
||||
} else {
|
||||
this.$message.error(res.msg)
|
||||
@@ -123,6 +255,7 @@ const branchUnionUserManage = {
|
||||
}).then((res) => {
|
||||
if (res.code === 0) {
|
||||
this.$message.success(res.msg)
|
||||
this.loadUsedJCodes()
|
||||
this.doSearch()
|
||||
}
|
||||
})
|
||||
@@ -131,7 +264,8 @@ const branchUnionUserManage = {
|
||||
pageData() {
|
||||
$.get("/platform/sys/union/branchUnionUserPageData", {
|
||||
...this.pageForm,
|
||||
unionId: this.union_id
|
||||
unionId: this.union_id,
|
||||
j: this.pageForm.j || ""
|
||||
}).then((res) => {
|
||||
if (res.code === 0) {
|
||||
this.tableData = res.data
|
||||
@@ -140,11 +274,19 @@ const branchUnionUserManage = {
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.pageData()
|
||||
this.initJSearch()
|
||||
},
|
||||
style: /*language=CSS*/ `
|
||||
/deep/ .el-select {
|
||||
width: 100% !important;
|
||||
}
|
||||
/deep/ .j-search-select {
|
||||
width: 80px !important;
|
||||
}
|
||||
.j-used-mark {
|
||||
color: #f56c6c;
|
||||
margin-left: 4px;
|
||||
font-weight: 700;
|
||||
}
|
||||
`
|
||||
}
|
||||
|
||||
@@ -3,6 +3,13 @@ layout("/layouts/platform.html"){
|
||||
#-->
|
||||
|
||||
<style>
|
||||
.page-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: flex-start;
|
||||
gap: 16px;
|
||||
}
|
||||
|
||||
.page-tip {
|
||||
color: #c64120;
|
||||
line-height: 24px;
|
||||
@@ -11,9 +18,14 @@ layout("/layouts/platform.html"){
|
||||
|
||||
<div id="app" v-cloak>
|
||||
<el-card shadow="never">
|
||||
<div class="left-span-label">活动类型年度报名次数配置</div>
|
||||
<div class="page-tip mt10">
|
||||
注:这里配置的是“同一活动类型在同一年度内最多可报名多少次”。未单独配置过的活动类型默认按 2 次处理。
|
||||
<div class="page-header">
|
||||
<div>
|
||||
<div class="left-span-label">活动分类年度报名次数配置</div>
|
||||
<div class="page-tip mt10">
|
||||
注:这里配置的是“同一活动分类在同一年度内最多可报名多少次”。未单独配置过的活动分类默认按 2 次处理。
|
||||
</div>
|
||||
</div>
|
||||
<el-button plain icon="el-icon-back" @click="goBack">返回</el-button>
|
||||
</div>
|
||||
</el-card>
|
||||
|
||||
@@ -22,8 +34,8 @@ layout("/layouts/platform.html"){
|
||||
<el-form ref="formRef" :model="formData">
|
||||
<el-table :data="formData.configList">
|
||||
<el-table-column label="序号" type="index" width="80"></el-table-column>
|
||||
<el-table-column label="活动类型" prop="trainTypeName"></el-table-column>
|
||||
<el-table-column label="活动类型编码" prop="trainType"></el-table-column>
|
||||
<el-table-column label="活动分类" prop="trainTypeName"></el-table-column>
|
||||
<el-table-column label="活动分类编码" prop="trainType"></el-table-column>
|
||||
<el-table-column label="每年可报名次数" prop="annualLimitCount" width="220">
|
||||
<template v-slot="{row}">
|
||||
<el-input-number v-model="row.annualLimitCount" :min="1" :precision="0" :step="1"></el-input-number>
|
||||
@@ -33,7 +45,8 @@ layout("/layouts/platform.html"){
|
||||
</el-form>
|
||||
|
||||
<div style="margin-top: 20px; text-align: right">
|
||||
<el-button type="primary" @click="onSave">保 存</el-button>
|
||||
<el-button @click="goBack">返回</el-button>
|
||||
<el-button type="primary" @click="onSave">保存</el-button>
|
||||
</div>
|
||||
</el-card>
|
||||
</div>
|
||||
@@ -49,6 +62,9 @@ layout("/layouts/platform.html"){
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
goBack: function () {
|
||||
commonUtil.pjaxPush('/platform/trainSignUp/type')
|
||||
},
|
||||
fetchData: function () {
|
||||
this.$axios.post('/platform/trainSignUp/annualLimit/listData').then((res) => {
|
||||
if (res.code === 0) {
|
||||
@@ -63,10 +79,10 @@ layout("/layouts/platform.html"){
|
||||
return !item.annualLimitCount || item.annualLimitCount <= 0
|
||||
})
|
||||
if (hasInvalidData) {
|
||||
this.$message.warning('每年可报名次数必须大于0')
|
||||
this.$message.warning('每年可报名次数必须大于 0')
|
||||
return
|
||||
}
|
||||
// 页面直接按活动类型整表提交,后端会按活动类型编码进行新增或更新。
|
||||
// 页面直接按活动分类整表提交,后端会按活动分类编码进行新增或更新。
|
||||
this.$axios.post('/platform/trainSignUp/annualLimit/save', {
|
||||
configList: JSON.stringify(this.formData.configList)
|
||||
}).then((res) => {
|
||||
|
||||
Reference in New Issue
Block a user