Jeecg-Boot 2.1.0 版本发布,Online表单开发&在线代码生成器(迟到的版本)

This commit is contained in:
zhangdaihao
2019-08-24 00:15:45 +08:00
parent f5eb69d7b2
commit 5a74539c22
165 changed files with 13536 additions and 17580 deletions

View File

@ -1,37 +1,34 @@
package org.jeecg;
import java.net.InetAddress;
import java.net.UnknownHostException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.core.env.Environment;
import lombok.extern.slf4j.Slf4j;
import springfox.documentation.swagger2.annotations.EnableSwagger2;
import java.net.InetAddress;
import java.net.UnknownHostException;
@Slf4j
@EnableSwagger2
@SpringBootApplication
public class JeecgApplication {
public static void main(String[] args) throws UnknownHostException {
//System.setProperty("spring.devtools.restart.enabled", "true");
public static void main(String[] args) throws UnknownHostException {
//System.setProperty("spring.devtools.restart.enabled", "true");
ConfigurableApplicationContext application = SpringApplication.run(JeecgApplication.class, args);
Environment env = application.getEnvironment();
String ip = InetAddress.getLocalHost().getHostAddress();
String port = env.getProperty("server.port");
String path = env.getProperty("server.servlet.context-path");
log.info("\n----------------------------------------------------------\n\t" +
"Application Jeecg-Boot is running! Access URLs:\n\t" +
"Local: \t\thttp://localhost:" + port + path + "/\n\t" +
"External: \thttp://" + ip + ":" + port + path + "/\n\t" +
"swagger-ui: \thttp://" + ip + ":" + port + path + "/swagger-ui.html\n\t" +
"Doc: \t\thttp://" + ip + ":" + port + path + "/doc.html\n" +
"----------------------------------------------------------");
}
ConfigurableApplicationContext application = SpringApplication.run(JeecgApplication.class, args);
Environment env = application.getEnvironment();
String ip = InetAddress.getLocalHost().getHostAddress();
String port = env.getProperty("server.port");
String path = env.getProperty("server.servlet.context-path");
log.info("\n----------------------------------------------------------\n\t" +
"Application Jeecg-Boot is running! Access URLs:\n\t" +
"Local: \t\thttp://localhost:" + port + path + "/\n\t" +
"External: \thttp://" + ip + ":" + port + path + "/\n\t" +
"swagger-ui: \thttp://" + ip + ":" + port + path + "/swagger-ui.html\n\t" +
"Doc: \t\thttp://" + ip + ":" + port + path + "/doc.html\n" +
"----------------------------------------------------------");
}
}

View File

@ -17,7 +17,9 @@ import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.cache.RedisCacheWriter;
import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializationContext;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import com.fasterxml.jackson.annotation.JsonAutoDetect.Visibility;
@ -82,13 +84,18 @@ public class RedisConfig extends CachingConfigurerSupport {
*/
@Bean
public CacheManager cacheManager(LettuceConnectionFactory factory) {
// 配置序列化
RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig().entryTtl(Duration.ofHours(1));
RedisCacheConfiguration redisCacheConfiguration = config.serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(new StringRedisSerializer()))
.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(new GenericJackson2JsonRedisSerializer()));
// 以锁写入的方式创建RedisCacheWriter对象
RedisCacheWriter writer = RedisCacheWriter.lockingRedisCacheWriter(factory);
//RedisCacheWriter writer = RedisCacheWriter.lockingRedisCacheWriter(factory);
// 创建默认缓存配置对象
/* 默认配置,设置缓存有效期 1小时*/
RedisCacheConfiguration defaultCacheConfig = RedisCacheConfiguration.defaultCacheConfig().entryTtl(Duration.ofHours(1));
//RedisCacheConfiguration defaultCacheConfig = RedisCacheConfiguration.defaultCacheConfig().entryTtl(Duration.ofHours(1));
/* 配置test的超时时间为120s*/
RedisCacheManager cacheManager = RedisCacheManager.builder(RedisCacheWriter.lockingRedisCacheWriter(lettuceConnectionFactory)).cacheDefaults(defaultCacheConfig)
RedisCacheManager cacheManager = RedisCacheManager.builder(RedisCacheWriter.lockingRedisCacheWriter(factory)).cacheDefaults(redisCacheConfiguration)
.withInitialCacheConfigurations(singletonMap("test", RedisCacheConfiguration.defaultCacheConfig().entryTtl(Duration.ofMinutes(120)).disableCachingNullValues()))
.transactionAware().build();
return cacheManager;

View File

@ -42,8 +42,11 @@ public class ShiroConfig {
shiroFilterFactoryBean.setSecurityManager(securityManager);
// 拦截器
Map<String, String> filterChainDefinitionMap = new LinkedHashMap<String, String>();
//cas验证登录
filterChainDefinitionMap.put("/cas/client/validateLogin", "anon");
// 配置不会被拦截的链接 顺序判断
filterChainDefinitionMap.put("/sys/login", "anon"); //登录接口排除
filterChainDefinitionMap.put("/sys/logout", "anon"); //登出接口排除
filterChainDefinitionMap.put("/sys/getEncryptedString", "anon"); //获取加密串
filterChainDefinitionMap.put("/sys/sms", "anon");//短信验证码
filterChainDefinitionMap.put("/sys/phoneLogin", "anon");//手机登录
@ -63,9 +66,16 @@ public class ShiroConfig {
filterChainDefinitionMap.put("/**/*.css", "anon");
filterChainDefinitionMap.put("/**/*.html", "anon");
filterChainDefinitionMap.put("/**/*.svg", "anon");
filterChainDefinitionMap.put("/**/*.pdf", "anon");
filterChainDefinitionMap.put("/**/*.jpg", "anon");
filterChainDefinitionMap.put("/**/*.png", "anon");
filterChainDefinitionMap.put("/**/*.ico", "anon");
// update-begin--Author:sunjianlei Date:20190813 for排除字体格式的后缀
filterChainDefinitionMap.put("/**/*.ttf", "anon");
filterChainDefinitionMap.put("/**/*.woff", "anon");
// update-begin--Author:sunjianlei Date:20190813 for排除字体格式的后缀
filterChainDefinitionMap.put("/druid/**", "anon");
filterChainDefinitionMap.put("/swagger-ui.html", "anon");
filterChainDefinitionMap.put("/swagger**/**", "anon");
@ -76,7 +86,20 @@ public class ShiroConfig {
filterChainDefinitionMap.put("/actuator/metrics/**", "anon");
filterChainDefinitionMap.put("/actuator/httptrace/**", "anon");
filterChainDefinitionMap.put("/actuator/redis/**", "anon");
filterChainDefinitionMap.put("/test/jeecgDemo/demo3", "anon"); //模板测试
filterChainDefinitionMap.put("/test/jeecgDemo/redisDemo/**", "anon"); //redis测试
//排除Online请求
filterChainDefinitionMap.put("/auto/cgform/**", "anon");
//websocket排除
filterChainDefinitionMap.put("/websocket/**", "anon");
// 添加自己的过滤器并且取名为jwt
Map<String, Filter> filterMap = new HashMap<String, Filter>(1);
filterMap.put("jwt", new JwtFilter());

View File

@ -0,0 +1,25 @@
package org.jeecg.config;
import org.jeecg.common.util.DySmsHelper;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* 设置静态参数初始化
*/
@Configuration
public class StaticConfig {
@Value("${jeecg.sms.accessKeyId}")
private String accessKeyId;
@Value("${jeecg.sms.accessKeySecret}")
private String accessKeySecret;
@Bean
public void initStatic() {
DySmsHelper.setAccessKeyId(accessKeyId);
DySmsHelper.setAccessKeySecret(accessKeySecret);
}
}

View File

@ -0,0 +1,18 @@
package org.jeecg.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.socket.server.standard.ServerEndpointExporter;
@Configuration
public class WebSocketConfig {
/**
* 注入ServerEndpointExporter
* 这个bean会自动注册使用了@ServerEndpoint注解声明的Websocket endpoint
*/
@Bean
public ServerEndpointExporter serverEndpointExporter() {
return new ServerEndpointExporter();
}
}

View File

@ -106,11 +106,13 @@ public class MybatisInterceptor implements Interceptor {
Field[] fields = null;
if (parameter instanceof ParamMap) {
ParamMap<?> p = (ParamMap<?>) parameter;
//update-begin-author:scott date:20190729 for:批量更新报错issues/IZA3Q--
if (p.containsKey("et")) {
parameter = p.get("et");
} else {
parameter = p.get("param1");
}
//update-end-author:scott date:20190729 for:批量更新报错issues/IZA3Q-
fields = oConvertUtils.getAllFields(parameter);
} else {
fields = oConvertUtils.getAllFields(parameter);

View File

@ -0,0 +1,110 @@
package org.jeecg.modules.cas.controller;
import java.util.List;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.lang.StringUtils;
import org.jeecg.common.api.vo.Result;
import org.jeecg.common.constant.CommonConstant;
import org.jeecg.common.system.util.JwtUtil;
import org.jeecg.common.util.RedisUtil;
import org.jeecg.modules.cas.util.CASServiceUtil;
import org.jeecg.modules.cas.util.XmlUtils;
import org.jeecg.modules.system.entity.SysDepart;
import org.jeecg.modules.system.entity.SysUser;
import org.jeecg.modules.system.service.ISysDepartService;
import org.jeecg.modules.system.service.ISysUserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
/**
* <p>
* CAS单点登录客户端登录认证
* </p>
*
* @Author zhoujf
* @since 2018-12-20
*/
@Slf4j
@RestController
@RequestMapping("/cas/client")
public class CasClientController {
@Autowired
private ISysUserService sysUserService;
@Autowired
private ISysDepartService sysDepartService;
@Autowired
private RedisUtil redisUtil;
@Value("${cas.prefixUrl}")
private String prefixUrl;
@GetMapping("/validateLogin")
public Object validateLogin(@RequestParam(name="ticket") String ticket,
@RequestParam(name="service") String service,
HttpServletRequest request,
HttpServletResponse response) throws Exception {
Result<JSONObject> result = new Result<JSONObject>();
log.info("Rest api login.");
try {
String validateUrl = prefixUrl+"/p3/serviceValidate";
String res = CASServiceUtil.getSTValidate(validateUrl, ticket, service);
log.info("res."+res);
final String error = XmlUtils.getTextForElement(res, "authenticationFailure");
if(StringUtils.isNotEmpty(error)) {
throw new Exception(error);
}
final String principal = XmlUtils.getTextForElement(res, "user");
if (StringUtils.isEmpty(principal)) {
throw new Exception("No principal was found in the response from the CAS server.");
}
log.info("-------token----username---"+principal);
//1. 校验用户是否有效
SysUser sysUser = sysUserService.getUserByName(principal);
result = sysUserService.checkUserIsEffective(sysUser);
if(!result.isSuccess()) {
return result;
}
String token = JwtUtil.sign(sysUser.getUsername(), sysUser.getPassword());
redisUtil.set(CommonConstant.PREFIX_USER_TOKEN + token, token);
// 设置超时时间
redisUtil.expire(CommonConstant.PREFIX_USER_TOKEN + token, JwtUtil.EXPIRE_TIME / 1000);
// 获取用户部门信息
JSONObject obj = new JSONObject();
List<SysDepart> departs = sysDepartService.queryUserDeparts(sysUser.getId());
obj.put("departs", departs);
if (departs == null || departs.size() == 0) {
obj.put("multi_depart", 0);
} else if (departs.size() == 1) {
sysUserService.updateUserDepart(principal, departs.get(0).getOrgCode());
obj.put("multi_depart", 1);
} else {
obj.put("multi_depart", 2);
}
obj.put("token", token);
obj.put("userInfo", sysUser);
result.setResult(obj);
result.success("登录成功");
} catch (Exception e) {
//e.printStackTrace();
result.error500(e.getMessage());
}
return new HttpEntity<>(result);
}
}

View File

@ -0,0 +1,103 @@
package org.jeecg.modules.cas.util;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.security.cert.X509Certificate;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import org.apache.http.HttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.conn.socket.LayeredConnectionSocketFactory;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
public class CASServiceUtil {
public static void main(String[] args) {
String serviceUrl = "https://cas.8f8.com.cn:8443/cas/p3/serviceValidate";
String service = "http://localhost:3003/user/login";
String ticket = "ST-5-1g-9cNES6KXNRwq-GuRET103sm0-DESKTOP-VKLS8B3";
String res = getSTValidate(serviceUrl,ticket, service);
System.out.println("---------res-----"+res);
}
/**
* 验证ST
*/
public static String getSTValidate(String url,String st, String service){
try {
url = url+"?service="+service+"&ticket="+st;
CloseableHttpClient httpclient = createHttpClientWithNoSsl();
HttpGet httpget = new HttpGet(url);
HttpResponse response = httpclient.execute(httpget);
String res = readResponse(response);
return res == null ? null : (res == "" ? null : res);
} catch (Exception e) {
e.printStackTrace();
}
return "";
}
/**
* 读取 response body 内容为字符串
*
* @param response
* @return
* @throws IOException
*/
private static String readResponse(HttpResponse response) throws IOException {
BufferedReader in = new BufferedReader(new InputStreamReader(response.getEntity().getContent()));
String result = new String();
String line;
while ((line = in.readLine()) != null) {
result += line;
}
return result;
}
/**
* 创建模拟客户端(针对 https 客户端禁用 SSL 验证)
*
* @param cookieStore 缓存的 Cookies 信息
* @return
* @throws Exception
*/
private static CloseableHttpClient createHttpClientWithNoSsl() throws Exception {
// Create a trust manager that does not validate certificate chains
TrustManager[] trustAllCerts = new TrustManager[]{
new X509TrustManager() {
@Override
public X509Certificate[] getAcceptedIssuers() {
return null;
}
@Override
public void checkClientTrusted(X509Certificate[] certs, String authType) {
// don't check
}
@Override
public void checkServerTrusted(X509Certificate[] certs, String authType) {
// don't check
}
}
};
SSLContext ctx = SSLContext.getInstance("TLS");
ctx.init(null, trustAllCerts, null);
LayeredConnectionSocketFactory sslSocketFactory = new SSLConnectionSocketFactory(ctx);
return HttpClients.custom()
.setSSLSocketFactory(sslSocketFactory)
.build();
}
}

View File

@ -0,0 +1,292 @@
package org.jeecg.modules.cas.util;
import java.io.StringReader;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import javax.xml.XMLConstants;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import org.w3c.dom.Document;
import org.xml.sax.Attributes;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.XMLReader;
import org.xml.sax.helpers.DefaultHandler;
import lombok.extern.slf4j.Slf4j;
/**
* 解析cas,ST验证后的xml
*
*/
@Slf4j
public final class XmlUtils {
/**
* Creates a new namespace-aware DOM document object by parsing the given XML.
*
* @param xml XML content.
*
* @return DOM document.
*/
public static Document newDocument(final String xml) {
final DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
final Map<String, Boolean> features = new HashMap<String, Boolean>();
features.put(XMLConstants.FEATURE_SECURE_PROCESSING, true);
features.put("http://apache.org/xml/features/nonvalidating/load-external-dtd", false);
for (final Map.Entry<String, Boolean> entry : features.entrySet()) {
try {
factory.setFeature(entry.getKey(), entry.getValue());
} catch (ParserConfigurationException e) {
log.warn("Failed setting XML feature {}: {}", entry.getKey(), e);
}
}
factory.setNamespaceAware(true);
try {
return factory.newDocumentBuilder().parse(new InputSource(new StringReader(xml)));
} catch (Exception e) {
throw new RuntimeException("XML parsing error: " + e);
}
}
/**
* Get an instance of an XML reader from the XMLReaderFactory.
*
* @return the XMLReader.
*/
public static XMLReader getXmlReader() {
try {
final XMLReader reader = SAXParserFactory.newInstance().newSAXParser().getXMLReader();
reader.setFeature("http://xml.org/sax/features/namespaces", true);
reader.setFeature("http://xml.org/sax/features/namespace-prefixes", false);
reader.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false);
return reader;
} catch (final Exception e) {
throw new RuntimeException("Unable to create XMLReader", e);
}
}
/**
* Retrieve the text for a group of elements. Each text element is an entry
* in a list.
* <p>This method is currently optimized for the use case of two elements in a list.
*
* @param xmlAsString the xml response
* @param element the element to look for
* @return the list of text from the elements.
*/
public static List<String> getTextForElements(final String xmlAsString, final String element) {
final List<String> elements = new ArrayList<String>(2);
final XMLReader reader = getXmlReader();
final DefaultHandler handler = new DefaultHandler() {
private boolean foundElement = false;
private StringBuilder buffer = new StringBuilder();
public void startElement(final String uri, final String localName, final String qName,
final Attributes attributes) throws SAXException {
if (localName.equals(element)) {
this.foundElement = true;
}
}
public void endElement(final String uri, final String localName, final String qName) throws SAXException {
if (localName.equals(element)) {
this.foundElement = false;
elements.add(this.buffer.toString());
this.buffer = new StringBuilder();
}
}
public void characters(char[] ch, int start, int length) throws SAXException {
if (this.foundElement) {
this.buffer.append(ch, start, length);
}
}
};
reader.setContentHandler(handler);
reader.setErrorHandler(handler);
try {
reader.parse(new InputSource(new StringReader(xmlAsString)));
} catch (final Exception e) {
log.error(e.getMessage(), e);
return null;
}
return elements;
}
/**
* Retrieve the text for a specific element (when we know there is only
* one).
*
* @param xmlAsString the xml response
* @param element the element to look for
* @return the text value of the element.
*/
public static String getTextForElement(final String xmlAsString, final String element) {
final XMLReader reader = getXmlReader();
final StringBuilder builder = new StringBuilder();
final DefaultHandler handler = new DefaultHandler() {
private boolean foundElement = false;
public void startElement(final String uri, final String localName, final String qName,
final Attributes attributes) throws SAXException {
if (localName.equals(element)) {
this.foundElement = true;
}
}
public void endElement(final String uri, final String localName, final String qName) throws SAXException {
if (localName.equals(element)) {
this.foundElement = false;
}
}
public void characters(char[] ch, int start, int length) throws SAXException {
if (this.foundElement) {
builder.append(ch, start, length);
}
}
};
reader.setContentHandler(handler);
reader.setErrorHandler(handler);
try {
reader.parse(new InputSource(new StringReader(xmlAsString)));
} catch (final Exception e) {
log.error(e.getMessage(), e);
return null;
}
return builder.toString();
}
public static Map<String, Object> extractCustomAttributes(final String xml) {
final SAXParserFactory spf = SAXParserFactory.newInstance();
spf.setNamespaceAware(true);
spf.setValidating(false);
try {
final SAXParser saxParser = spf.newSAXParser();
final XMLReader xmlReader = saxParser.getXMLReader();
final CustomAttributeHandler handler = new CustomAttributeHandler();
xmlReader.setContentHandler(handler);
xmlReader.parse(new InputSource(new StringReader(xml)));
return handler.getAttributes();
} catch (final Exception e) {
log.error(e.getMessage(), e);
return Collections.emptyMap();
}
}
private static class CustomAttributeHandler extends DefaultHandler {
private Map<String, Object> attributes;
private boolean foundAttributes;
private String currentAttribute;
private StringBuilder value;
@Override
public void startDocument() throws SAXException {
this.attributes = new HashMap<String, Object>();
}
@Override
public void startElement(final String namespaceURI, final String localName, final String qName,
final Attributes attributes) throws SAXException {
if ("attributes".equals(localName)) {
this.foundAttributes = true;
} else if (this.foundAttributes) {
this.value = new StringBuilder();
this.currentAttribute = localName;
}
}
@Override
public void characters(final char[] chars, final int start, final int length) throws SAXException {
if (this.currentAttribute != null) {
value.append(chars, start, length);
}
}
@Override
public void endElement(final String namespaceURI, final String localName, final String qName)
throws SAXException {
if ("attributes".equals(localName)) {
this.foundAttributes = false;
this.currentAttribute = null;
} else if (this.foundAttributes) {
final Object o = this.attributes.get(this.currentAttribute);
if (o == null) {
this.attributes.put(this.currentAttribute, this.value.toString());
} else {
final List<Object> items;
if (o instanceof List) {
items = (List<Object>) o;
} else {
items = new LinkedList<Object>();
items.add(o);
this.attributes.put(this.currentAttribute, items);
}
items.add(this.value.toString());
}
}
}
public Map<String, Object> getAttributes() {
return this.attributes;
}
}
public static void main(String[] args) {
String result = "<cas:serviceResponse xmlns:cas='http://www.yale.edu/tp/cas'>\r\n" +
" <cas:authenticationSuccess>\r\n" +
" <cas:user>admin</cas:user>\r\n" +
" <cas:attributes>\r\n" +
" <cas:credentialType>UsernamePasswordCredential</cas:credentialType>\r\n" +
" <cas:isFromNewLogin>true</cas:isFromNewLogin>\r\n" +
" <cas:authenticationDate>2019-08-01T19:33:21.527+08:00[Asia/Shanghai]</cas:authenticationDate>\r\n" +
" <cas:authenticationMethod>RestAuthenticationHandler</cas:authenticationMethod>\r\n" +
" <cas:successfulAuthenticationHandlers>RestAuthenticationHandler</cas:successfulAuthenticationHandlers>\r\n" +
" <cas:longTermAuthenticationRequestTokenUsed>false</cas:longTermAuthenticationRequestTokenUsed>\r\n" +
" </cas:attributes>\r\n" +
" </cas:authenticationSuccess>\r\n" +
"</cas:serviceResponse>";
String errorRes = "<cas:serviceResponse xmlns:cas='http://www.yale.edu/tp/cas'>\r\n" +
" <cas:authenticationFailure code=\"INVALID_TICKET\">未能够识别出目标 &#39;ST-5-1g-9cNES6KXNRwq-GuRET103sm0-DESKTOP-VKLS8B3&#39;票根</cas:authenticationFailure>\r\n" +
"</cas:serviceResponse>";
String error = XmlUtils.getTextForElement(errorRes, "authenticationFailure");
System.out.println("------"+error);
String error2 = XmlUtils.getTextForElement(result, "authenticationFailure");
System.out.println("------"+error2);
String principal = XmlUtils.getTextForElement(result, "user");
System.out.println("---principal---"+principal);
Map<String, Object> attributes = XmlUtils.extractCustomAttributes(result);
System.out.println("---attributes---"+attributes);
}
}

File diff suppressed because one or more lines are too long

View File

@ -11,6 +11,7 @@ import javax.servlet.http.HttpServletResponse;
import org.jeecg.common.api.vo.Result;
import org.jeecg.common.aspect.annotation.AutoLog;
import org.jeecg.common.aspect.annotation.PermissionData;
import org.jeecg.common.constant.CommonConstant;
import org.jeecg.common.system.base.controller.JeecgController;
import org.jeecg.common.system.query.QueryGenerator;
import org.jeecg.common.util.DateUtils;
@ -143,7 +144,8 @@ public class JeecgDemoController extends JeecgController<JeecgDemo,IJeecgDemoSer
*/
@PutMapping(value = "/edit")
@ApiOperation(value = "编辑DEMO", notes = "编辑DEMO")
public Result<JeecgDemo> eidt(@RequestBody JeecgDemo jeecgDemo) {
@AutoLog(value = "编辑DEMO",operateType= CommonConstant.OPERATE_TYPE_3)
public Result<JeecgDemo> edit(@RequestBody JeecgDemo jeecgDemo) {
Result<JeecgDemo> result = new Result<JeecgDemo>();
JeecgDemo jeecgDemoEntity = jeecgDemoService.getById(jeecgDemo.getId());
if (jeecgDemoEntity == null) {

View File

@ -25,7 +25,7 @@ import lombok.experimental.Accessors;
public class SysMessage extends JeecgEntity {
/**推送内容*/
@Excel(name = "推送内容", width = 15)
private java.lang.Object esContent;
private java.lang.String esContent;
/**推送所需参数Json格式*/
@Excel(name = "推送所需参数Json格式", width = 15)
private java.lang.String esParam;

View File

@ -0,0 +1,47 @@
package org.jeecg.modules.message.websocket;
import org.jeecg.common.api.vo.Result;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.alibaba.fastjson.JSONObject;
@RestController
@RequestMapping("webSocketApi")
public class TestController {
@Autowired
private WebSocket webSocket;
@PostMapping("/sendAll")
public Result<String> sendAll(@RequestBody JSONObject jsonObject) {
Result<String> result = new Result<String>();
String message = jsonObject.getString("message");
JSONObject obj = new JSONObject();
obj.put("cmd", "topic");
obj.put("msgId", "M0001");
obj.put("msgTxt", message);
webSocket.sendAllMessage(obj.toJSONString());
result.setResult("群发!");
return result;
}
@PostMapping("/sendUser")
public Result<String> sendUser(@RequestBody JSONObject jsonObject) {
Result<String> result = new Result<String>();
String userId = jsonObject.getString("userId");
String message = jsonObject.getString("message");
JSONObject obj = new JSONObject();
obj.put("cmd", "user");
obj.put("userId", userId);
obj.put("msgId", "M0001");
obj.put("msgTxt", message);
webSocket.sendOneMessage(userId, obj.toJSONString());
result.setResult("单发");
return result;
}
}

View File

@ -0,0 +1,97 @@
package org.jeecg.modules.message.websocket;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.CopyOnWriteArraySet;
import javax.websocket.OnClose;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import org.springframework.stereotype.Component;
import lombok.extern.slf4j.Slf4j;
@Component
@Slf4j
@ServerEndpoint("/websocket/{userId}")
//此注解相当于设置访问URL
public class WebSocket {
private Session session;
private static CopyOnWriteArraySet<WebSocket> webSockets =new CopyOnWriteArraySet<>();
private static Map<String,Session> sessionPool = new HashMap<String,Session>();
@OnOpen
public void onOpen(Session session, @PathParam(value="userId")String userId) {
try {
this.session = session;
webSockets.add(this);
sessionPool.put(userId, session);
log.info("【websocket消息】有新的连接总数为:"+webSockets.size());
} catch (Exception e) {
}
}
@OnClose
public void onClose() {
try {
webSockets.remove(this);
log.info("【websocket消息】连接断开总数为:"+webSockets.size());
} catch (Exception e) {
}
}
@OnMessage
public void onMessage(String message) {
log.info("【websocket消息】收到客户端消息:"+message);
}
// 此为广播消息
public void sendAllMessage(String message) {
log.info("【websocket消息】广播消息:"+message);
for(WebSocket webSocket : webSockets) {
try {
if(webSocket.session.isOpen()) {
webSocket.session.getAsyncRemote().sendText(message);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
// 此为单点消息
public void sendOneMessage(String userId, String message) {
Session session = sessionPool.get(userId);
if (session != null&&session.isOpen()) {
try {
log.info("【websocket消息】 单点消息:"+message);
session.getAsyncRemote().sendText(message);
} catch (Exception e) {
e.printStackTrace();
}
}
}
// 此为单点消息(多人)
public void sendMoreMessage(String[] userIds, String message) {
for(String userId:userIds) {
Session session = sessionPool.get(userId);
if (session != null&&session.isOpen()) {
try {
log.info("【websocket消息】 单点消息:"+message);
session.getAsyncRemote().sendText(message);
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
}

View File

@ -2,6 +2,6 @@
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="org.jeecg.modules.ngalain.mapper.NgAlainMapper">
<select id="getDictByTable" parameterType="String" resultType="java.util.HashMap">
select ${key} as 'label',${value} as 'value' from ${table}
select ${key} as "label",${value} as "value" from ${table}
</select>
</mapper>

View File

@ -6,6 +6,7 @@ import org.jeecgframework.poi.excel.annotation.Excel;
import org.springframework.format.annotation.DateTimeFormat;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.fasterxml.jackson.annotation.JsonFormat;
@ -55,4 +56,5 @@ public class QuartzJob implements Serializable {
/**状态 0正常 -1停止*/
@Excel(name="状态",width=15)
private java.lang.Integer status;
}

View File

@ -117,7 +117,9 @@ public class QuartzJobServiceImpl extends ServiceImpl<QuartzJobMapper, QuartzJob
scheduler.scheduleJob(jobDetail, trigger);
} catch (SchedulerException e) {
throw new JeecgBootException("创建定时任务失败", e);
} catch (Exception e) {
} catch (RuntimeException e) {
throw new JeecgBootException(e.getMessage(), e);
}catch (Exception e) {
throw new JeecgBootException("后台找不到该类名:" + jobClassName, e);
}
}

View File

@ -14,6 +14,7 @@ import org.jeecg.common.constant.CommonConstant;
import org.jeecg.common.system.util.JwtUtil;
import org.jeecg.common.system.vo.LoginUser;
import org.jeecg.common.util.RedisUtil;
import org.jeecg.common.util.SpringContextUtils;
import org.jeecg.common.util.oConvertUtils;
import org.jeecg.modules.system.entity.SysUser;
import org.jeecg.modules.system.service.ISysUserService;
@ -84,9 +85,9 @@ public class ShiroRealm extends AuthorizingRealm {
*/
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken auth) throws AuthenticationException {
log.debug("————身份认证————");
String token = (String) auth.getCredentials();
if (token == null) {
log.info("————————身份认证失败——————————IP地址: "+ oConvertUtils.getIpAddrByRequest(SpringContextUtils.getHttpServletRequest()));
throw new AuthenticationException("token为空!");
}
// 校验token有效性
@ -145,7 +146,7 @@ public class ShiroRealm extends AuthorizingRealm {
String cacheToken = String.valueOf(redisUtil.get(CommonConstant.PREFIX_USER_TOKEN + token));
if (oConvertUtils.isNotEmpty(cacheToken)) {
// 校验token有效性
if (!JwtUtil.verify(token, userName, passWord)) {
if (!JwtUtil.verify(cacheToken, userName, passWord)) {
String newAuthorization = JwtUtil.sign(userName, passWord);
redisUtil.set(CommonConstant.PREFIX_USER_TOKEN + token, newAuthorization);
// 设置超时时间

View File

@ -12,6 +12,7 @@ import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.jeecg.common.aspect.annotation.AutoLog;
import org.jeecg.common.constant.CommonConstant;
import org.jeecg.common.system.vo.LoginUser;
import org.jeecg.common.util.IPUtils;
import org.jeecg.common.util.SpringContextUtils;
@ -65,12 +66,19 @@ public class AutoLogAspect {
//注解上的描述,操作日志内容
sysLog.setLogContent(syslog.value());
sysLog.setLogType(syslog.logType());
}
//请求的方法名
String className = joinPoint.getTarget().getClass().getName();
String methodName = signature.getName();
sysLog.setMethod(className + "." + methodName + "()");
//设置操作类型
if (sysLog.getLogType() == CommonConstant.LOG_TYPE_2) {
sysLog.setOperateType(getOperateType(methodName, syslog.operateType()));
}
//请求的参数
Object[] args = joinPoint.getArgs();
@ -99,4 +107,31 @@ public class AutoLogAspect {
//保存系统日志
sysLogService.save(sysLog);
}
/**
* 获取操作类型
*/
private int getOperateType(String methodName,int operateType) {
if (operateType > 0) {
return operateType;
}
if (methodName.startsWith("list")) {
return CommonConstant.OPERATE_TYPE_1;
}
if (methodName.startsWith("add")) {
return CommonConstant.OPERATE_TYPE_2;
}
if (methodName.startsWith("edit")) {
return CommonConstant.OPERATE_TYPE_3;
}
if (methodName.startsWith("delete")) {
return CommonConstant.OPERATE_TYPE_4;
}
if (methodName.startsWith("import")) {
return CommonConstant.OPERATE_TYPE_5;
}
if (methodName.startsWith("export")) {
return CommonConstant.OPERATE_TYPE_6;
}
return CommonConstant.OPERATE_TYPE_1;
}
}

View File

@ -1,23 +1,27 @@
package org.jeecg.modules.system.controller;
import java.util.*;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.subject.Subject;
import org.jeecg.common.api.vo.Result;
import org.jeecg.common.constant.CommonConstant;
import org.jeecg.common.system.api.ISysBaseAPI;
import org.jeecg.common.system.util.JwtUtil;
import org.jeecg.common.system.vo.LoginUser;
import org.jeecg.common.util.DySmsEnum;
import org.jeecg.common.util.DySmsHelper;
import org.jeecg.common.util.PasswordUtil;
import org.jeecg.common.util.RedisUtil;
import org.jeecg.common.util.encryption.AesEncryptUtil;
import org.jeecg.common.util.encryption.EncryptedString;
import org.jeecg.common.util.oConvertUtils;
import org.jeecg.common.util.encryption.EncryptedString;
import org.jeecg.modules.shiro.vo.DefContants;
import org.jeecg.modules.system.entity.SysDepart;
import org.jeecg.modules.system.entity.SysUser;
@ -103,19 +107,24 @@ public class LoginController {
@RequestMapping(value = "/logout")
public Result<Object> logout(HttpServletRequest request,HttpServletResponse response) {
//用户退出逻辑
Subject subject = SecurityUtils.getSubject();
LoginUser sysUser = (LoginUser)subject.getPrincipal();
sysBaseAPI.addLog("用户名: "+sysUser.getRealname()+",退出成功!", CommonConstant.LOG_TYPE_1, null);
log.info(" 用户名: "+sysUser.getRealname()+",退出成功! ");
subject.logout();
String token = request.getHeader(DefContants.X_ACCESS_TOKEN);
//清空用户Token缓存
redisUtil.del(CommonConstant.PREFIX_USER_TOKEN + token);
//清空用户权限缓存权限Perms和角色集合
redisUtil.del(CommonConstant.LOGIN_USER_CACHERULES_ROLE + sysUser.getUsername());
redisUtil.del(CommonConstant.LOGIN_USER_CACHERULES_PERMISSION + sysUser.getUsername());
return Result.ok("退出登录成功!");
if(oConvertUtils.isEmpty(token)) {
return Result.error("退出登录失败!");
}
String username = JwtUtil.getUsername(token);
SysUser sysUser = sysUserService.getUserByName(username);
if(sysUser!=null) {
sysBaseAPI.addLog("用户名: "+sysUser.getRealname()+",退出成功!", CommonConstant.LOG_TYPE_1, null);
log.info(" 用户名: "+sysUser.getRealname()+",退出成功! ");
//清空用户Token缓存
redisUtil.del(CommonConstant.PREFIX_USER_TOKEN + token);
//清空用户权限缓存权限Perms和角色集合
redisUtil.del(CommonConstant.LOGIN_USER_CACHERULES_ROLE + username);
redisUtil.del(CommonConstant.LOGIN_USER_CACHERULES_PERMISSION + username);
return Result.ok("退出登录成功!");
}else {
return Result.error("无效的token");
}
}
/**
@ -177,7 +186,8 @@ public class LoginController {
* @return
*/
@RequestMapping(value = "/selectDepart", method = RequestMethod.PUT)
public Result<?> selectDepart(@RequestBody SysUser user) {
public Result<JSONObject> selectDepart(@RequestBody SysUser user) {
Result<JSONObject> result = new Result<JSONObject>();
String username = user.getUsername();
if(oConvertUtils.isEmpty(username)) {
LoginUser sysUser = (LoginUser)SecurityUtils.getSubject().getPrincipal();
@ -185,7 +195,11 @@ public class LoginController {
}
String orgCode= user.getOrgCode();
this.sysUserService.updateUserDepart(username, orgCode);
return Result.ok();
SysUser sysUser = sysUserService.getUserByName(username);
JSONObject obj = new JSONObject();
obj.put("userInfo", sysUser);
result.setResult(obj);
return result;
}
/**
@ -209,6 +223,8 @@ public class LoginController {
//随机数
String captcha = RandomUtil.randomNumbers(6);
JSONObject obj = new JSONObject();
obj.put("code", captcha);
try {
boolean b = false;
//注册模板
@ -219,7 +235,7 @@ public class LoginController {
sysBaseAPI.addLog("手机号已经注册,请直接登录!", CommonConstant.LOG_TYPE_1, null);
return result;
}
b = DySmsHelper.sendSms(mobile, captcha, DySmsHelper.REGISTER_TEMPLATE_CODE);
b = DySmsHelper.sendSms(mobile, obj, DySmsEnum.REGISTER_TEMPLATE_CODE);
}else {
//登录模式,校验用户有效性
SysUser sysUser = sysUserService.getUserByPhone(mobile);
@ -233,10 +249,10 @@ public class LoginController {
*/
if (CommonConstant.SMS_TPL_TYPE_0.equals(smsmode)) {
//登录模板
b = DySmsHelper.sendSms(mobile, captcha, DySmsHelper.LOGIN_TEMPLATE_CODE);
b = DySmsHelper.sendSms(mobile, obj, DySmsEnum.LOGIN_TEMPLATE_CODE);
} else if(CommonConstant.SMS_TPL_TYPE_2.equals(smsmode)) {
//忘记密码模板
b = DySmsHelper.sendSms(mobile, captcha, DySmsHelper.FORGET_PASSWORD_TEMPLATE_CODE);
b = DySmsHelper.sendSms(mobile, obj, DySmsEnum.FORGET_PASSWORD_TEMPLATE_CODE);
}
}
@ -247,7 +263,9 @@ public class LoginController {
}
//验证码10分钟内有效
redisUtil.set(mobile, captcha, 600);
result.setResult(captcha);
//update-begin--Author:scott Date:20190812 forissues#391
//result.setResult(captcha);
//update-end--Author:scott Date:20190812 forissues#391
result.setSuccess(true);
} catch (ClientException e) {

View File

@ -1,14 +1,13 @@
package org.jeecg.modules.system.controller;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@ -20,6 +19,7 @@ import org.jeecg.common.system.query.QueryGenerator;
import org.jeecg.common.system.util.JwtUtil;
import org.jeecg.common.system.vo.LoginUser;
import org.jeecg.common.util.oConvertUtils;
import org.jeecg.modules.message.websocket.WebSocket;
import org.jeecg.modules.system.entity.SysAnnouncement;
import org.jeecg.modules.system.entity.SysAnnouncementSend;
import org.jeecg.modules.system.service.ISysAnnouncementSendService;
@ -39,7 +39,7 @@ import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;
import org.springframework.web.servlet.ModelAndView;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
@ -62,6 +62,8 @@ public class SysAnnouncementController {
private ISysAnnouncementService sysAnnouncementService;
@Autowired
private ISysAnnouncementSendService sysAnnouncementSendService;
@Resource
private WebSocket webSocket;
/**
* 分页列表查询
@ -223,6 +225,24 @@ public class SysAnnouncementController {
boolean ok = sysAnnouncementService.updateById(sysAnnouncement);
if(ok) {
result.success("该系统通知发布成功");
if(sysAnnouncement.getMsgType().equals(CommonConstant.MSG_TYPE_ALL)) {
JSONObject obj = new JSONObject();
obj.put("cmd", "topic");
obj.put("msgId", sysAnnouncement.getId());
obj.put("msgTxt", sysAnnouncement.getTitile());
webSocket.sendAllMessage(obj.toJSONString());
}else {
// 2.插入用户通告阅读标记表记录
String userId = sysAnnouncement.getUserIds();
String[] userIds = userId.substring(0, (userId.length()-1)).split(",");
String anntId = sysAnnouncement.getId();
Date refDate = new Date();
JSONObject obj = new JSONObject();
obj.put("cmd", "user");
obj.put("msgId", sysAnnouncement.getId());
obj.put("msgTxt", sysAnnouncement.getTitile());
webSocket.sendMoreMessage(userIds, obj.toJSONString());
}
}
}

View File

@ -40,7 +40,7 @@ import lombok.extern.slf4j.Slf4j;
* @Version: V1.0
*/
@RestController
@RequestMapping("/system/sysAnnouncementSend")
@RequestMapping("/sys/sysAnnouncementSend")
@Slf4j
public class SysAnnouncementSendController {
@Autowired

View File

@ -72,7 +72,13 @@ public class SysCategoryController {
sysCategory.setPid("0");
}
Result<IPage<SysCategory>> result = new Result<IPage<SysCategory>>();
QueryWrapper<SysCategory> queryWrapper = QueryGenerator.initQueryWrapper(sysCategory, req.getParameterMap());
//--author:os_chengtgen---date:20190804 -----for: 分类字典页面显示错误,issues:377--------start
//QueryWrapper<SysCategory> queryWrapper = QueryGenerator.initQueryWrapper(sysCategory, req.getParameterMap());
QueryWrapper<SysCategory> queryWrapper = new QueryWrapper<SysCategory>();
queryWrapper.eq("pid", sysCategory.getPid());
//--author:os_chengtgen---date:20190804 -----for: 分类字典页面显示错误,issues:377--------end
Page<SysCategory> page = new Page<SysCategory>(pageNo, pageSize);
IPage<SysCategory> pageList = sysCategoryService.page(page, queryWrapper);
result.setSuccess(true);

View File

@ -13,6 +13,7 @@ import javax.servlet.http.HttpServletResponse;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authz.annotation.RequiresRoles;
import org.jeecg.common.api.vo.Result;
import org.jeecg.common.constant.CacheConstant;
import org.jeecg.common.system.query.QueryGenerator;
import org.jeecg.common.system.util.JwtUtil;
import org.jeecg.common.system.vo.LoginUser;
@ -20,8 +21,6 @@ import org.jeecg.modules.system.entity.SysDepart;
import org.jeecg.modules.system.model.DepartIdModel;
import org.jeecg.modules.system.model.SysDepartTreeModel;
import org.jeecg.modules.system.service.ISysDepartService;
import org.jeecg.modules.system.service.ISysUserDepartService;
import org.jeecg.modules.system.service.ISysUserService;
import org.jeecg.modules.system.util.FindsDepartsChildrenUtil;
import org.jeecgframework.poi.excel.ExcelImportUtil;
import org.jeecgframework.poi.excel.def.NormalExcelConstants;
@ -29,6 +28,8 @@ import org.jeecgframework.poi.excel.entity.ExportParams;
import org.jeecgframework.poi.excel.entity.ImportParams;
import org.jeecgframework.poi.excel.view.JeecgEntityExcelView;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
@ -50,16 +51,12 @@ import lombok.extern.slf4j.Slf4j;
* @Author: Steve @Since 2019-01-22
*/
@RestController
@RequestMapping("/sysdepart/sysDepart")
@RequestMapping("/sys/sysDepart")
@Slf4j
public class SysDepartController {
@Autowired
private ISysDepartService sysDepartService;
@Autowired
private ISysUserService sysUserService;
@Autowired
private ISysUserDepartService sysUserDepartService;
/**
* 查询数据 查出所有部门,并以树结构数据格式响应给前端
@ -70,6 +67,11 @@ public class SysDepartController {
public Result<List<SysDepartTreeModel>> queryTreeList() {
Result<List<SysDepartTreeModel>> result = new Result<>();
try {
// 从内存中读取
// List<SysDepartTreeModel> list =FindsDepartsChildrenUtil.getSysDepartTreeList();
// if (CollectionUtils.isEmpty(list)) {
// list = sysDepartService.queryTreeList();
// }
List<SysDepartTreeModel> list = sysDepartService.queryTreeList();
result.setResult(list);
result.setSuccess(true);
@ -86,12 +88,16 @@ public class SysDepartController {
* @return
*/
@RequestMapping(value = "/add", method = RequestMethod.POST)
@CacheEvict(value= {CacheConstant.DEPART_INFO_CACHE,CacheConstant.DEPART_IDMODEL_CACHE}, allEntries=true)
public Result<SysDepart> add(@RequestBody SysDepart sysDepart, HttpServletRequest request) {
Result<SysDepart> result = new Result<SysDepart>();
String username = JwtUtil.getUserNameByToken(request);
try {
sysDepart.setCreateBy(username);
sysDepartService.saveDepartData(sysDepart, username);
//清除部门树内存
// FindsDepartsChildrenUtil.clearSysDepartTreeList();
// FindsDepartsChildrenUtil.clearDepartIdModel();
result.success("添加成功!");
} catch (Exception e) {
log.error(e.getMessage(),e);
@ -107,6 +113,7 @@ public class SysDepartController {
* @return
*/
@RequestMapping(value = "/edit", method = RequestMethod.PUT)
@CacheEvict(value= {CacheConstant.DEPART_INFO_CACHE,CacheConstant.DEPART_IDMODEL_CACHE}, allEntries=true)
public Result<SysDepart> edit(@RequestBody SysDepart sysDepart, HttpServletRequest request) {
String username = JwtUtil.getUserNameByToken(request);
sysDepart.setUpdateBy(username);
@ -118,6 +125,9 @@ public class SysDepartController {
boolean ok = sysDepartService.updateDepartDataById(sysDepart, username);
// TODO 返回false说明什么
if (ok) {
//清除部门树内存
//FindsDepartsChildrenUtil.clearSysDepartTreeList();
//FindsDepartsChildrenUtil.clearDepartIdModel();
result.success("修改成功!");
}
}
@ -129,7 +139,8 @@ public class SysDepartController {
* @param id
* @return
*/
@RequestMapping(value = "/delete", method = RequestMethod.DELETE)
@RequestMapping(value = "/delete", method = RequestMethod.DELETE)
@CacheEvict(value= {CacheConstant.DEPART_INFO_CACHE,CacheConstant.DEPART_IDMODEL_CACHE}, allEntries=true)
public Result<SysDepart> delete(@RequestParam(name="id",required=true) String id) {
Result<SysDepart> result = new Result<SysDepart>();
@ -139,6 +150,9 @@ public class SysDepartController {
}else {
boolean ok = sysDepartService.delete(id);
if(ok) {
//清除部门树内存
//FindsDepartsChildrenUtil.clearSysDepartTreeList();
// FindsDepartsChildrenUtil.clearDepartIdModel();
result.success("删除成功!");
}
}
@ -153,13 +167,14 @@ public class SysDepartController {
* @return
*/
@RequestMapping(value = "/deleteBatch", method = RequestMethod.DELETE)
@CacheEvict(value= {CacheConstant.DEPART_INFO_CACHE,CacheConstant.DEPART_IDMODEL_CACHE}, allEntries=true)
public Result<SysDepart> deleteBatch(@RequestParam(name = "ids", required = true) String ids) {
Result<SysDepart> result = new Result<SysDepart>();
if (ids == null || "".equals(ids.trim())) {
result.error500("参数不识别!");
} else {
this.sysDepartService.removeByIds(Arrays.asList(ids.split(",")));
this.sysDepartService.deleteBatchWithChildren(Arrays.asList(ids.split(",")));
result.success("删除成功!");
}
return result;
@ -172,25 +187,34 @@ public class SysDepartController {
*/
@RequestMapping(value = "/queryIdTree", method = RequestMethod.GET)
public Result<List<DepartIdModel>> queryIdTree() {
Result<List<DepartIdModel>> result = new Result<List<DepartIdModel>>();
List<DepartIdModel> idList;
// Result<List<DepartIdModel>> result = new Result<List<DepartIdModel>>();
// List<DepartIdModel> idList;
// try {
// idList = FindsDepartsChildrenUtil.wrapDepartIdModel();
// if (idList != null && idList.size() > 0) {
// result.setResult(idList);
// result.setSuccess(true);
// } else {
// sysDepartService.queryTreeList();
// idList = FindsDepartsChildrenUtil.wrapDepartIdModel();
// result.setResult(idList);
// result.setSuccess(true);
// }
// return result;
// } catch (Exception e) {
// log.error(e.getMessage(),e);
// result.setSuccess(false);
// return result;
// }
Result<List<DepartIdModel>> result = new Result<>();
try {
idList = FindsDepartsChildrenUtil.wrapDepartIdModel();
if (idList != null && idList.size() > 0) {
result.setResult(idList);
result.setSuccess(true);
} else {
sysDepartService.queryTreeList();
idList = FindsDepartsChildrenUtil.wrapDepartIdModel();
result.setResult(idList);
result.setSuccess(true);
}
return result;
List<DepartIdModel> list = sysDepartService.queryDepartIdTreeList();
result.setResult(list);
result.setSuccess(true);
} catch (Exception e) {
log.error(e.getMessage(),e);
result.setSuccess(false);
return result;
}
return result;
}
/**

View File

@ -219,7 +219,7 @@ public class SysPermissionController {
public Result<SysPermission> deleteBatch(@RequestParam(name = "ids", required = true) String ids) {
Result<SysPermission> result = new Result<>();
try {
String arr[] = ids.split(",");
String[] arr = ids.split(",");
for (String id : arr) {
if (oConvertUtils.isNotEmpty(id)) {
sysPermissionService.deletePermission(id);

View File

@ -52,7 +52,7 @@ import lombok.extern.slf4j.Slf4j;
* @Version: V1.0
*/
@RestController
@RequestMapping("/system/sysUserAgent")
@RequestMapping("/sys/sysUserAgent")
@Slf4j
public class SysUserAgentController {
@Autowired

View File

@ -761,13 +761,14 @@ public class SysUserController {
String passwordEncode = PasswordUtil.encrypt(username, password, salt);
user.setSalt(salt);
user.setUsername(username);
user.setRealname(username);
user.setPassword(passwordEncode);
user.setEmail(email);
user.setPhone(phone);
user.setStatus(1);
user.setDelFlag(CommonConstant.DEL_FLAG_0.toString());
user.setActivitiSync(CommonConstant.ACT_SYNC_1);
sysUserService.save(user);
sysUserService.addUserWithRole(user,"ee8626f80f7c2619917b6236f3a7f02b");//默认临时角色 test
result.success("注册成功");
} catch (Exception e) {
result.error500("注册失败");

View File

@ -104,8 +104,9 @@ public class SysLog implements Serializable {
private Integer logType;
/**
* 操作类型()
* 操作类型(1查询2添加3修改4删除,5导入6导出
*/
@Dict(dicCode = "operate_type")
private Integer operateType;
}

View File

@ -25,13 +25,11 @@
<select id="querySysCementListByUserId" parameterType="String" resultMap="SysAnnouncement">
select sa.* from sys_announcement sa,sys_announcement_send sas
where sa.id = sas.annt_id
and sa.send_status = '1'
and sa.del_flag = '0'
and sas.user_id = #{userId}
and sa.msg_category = #{msgCategory}
and sas.read_flag = '0'
select * from sys_announcement
where send_status = '1'
and del_flag = '0'
and msg_category = #{msgCategory}
and id IN ( select annt_id from sys_announcement_send where user_id = #{userId} and read_flag = '0')
</select>
</mapper>

View File

@ -4,9 +4,9 @@
<select id="queryListByPid" parameterType="String" resultType="org.jeecg.modules.system.model.TreeSelectModel">
select code,
name as 'title',
id as 'key',
(case has_child when '1' then 0 else 1 end) as isLeaf,
name as "title",
id as "key",
(case when has_child = '1' then 0 else 1 end) as isLeaf,
pid as parentId
from sys_category
where pid = #{pid}

View File

@ -3,8 +3,6 @@
<mapper namespace="org.jeecg.modules.system.mapper.SysDepartMapper">
<select id="queryUserDeparts" parameterType="String" resultType="org.jeecg.modules.system.entity.SysDepart">
select a.* from sys_depart a
join sys_user_depart b on a.id = b.dep_id
where b.user_id = #{userId}
select * from sys_depart where id IN ( select dep_id from sys_user_depart where user_id = #{userId} )
</select>
</mapper>

View File

@ -4,7 +4,7 @@
<!-- 通过字典code获取字典数据 -->
<select id="queryDictItemsByCode" parameterType="String" resultType="org.jeecg.common.system.vo.DictModel">
select s.item_value as value,s.item_text as text from sys_dict_item s
select s.item_value as "value",s.item_text as "text" from sys_dict_item s
where dict_id = (select id from sys_dict where dict_code = #{code})
order by s.sort_order asc
</select>
@ -19,17 +19,17 @@
<!--通过查询指定table的 text code 获取字典-->
<select id="queryTableDictItemsByCode" parameterType="String" resultType="org.jeecg.common.system.vo.DictModel">
select ${text} as 'text',${code} as 'value' from ${table}
select ${text} as "text",${code} as "value" from ${table}
</select>
<!--通过查询指定table的 text code 获取字典(指定查询条件)-->
<select id="queryTableDictItemsByCodeAndFilter" parameterType="String" resultType="org.jeecg.common.system.vo.DictModel">
select ${text} as 'text',${code} as 'value' from ${table} where ${filterSql}
select ${text} as "text",${code} as "value" from ${table} where ${filterSql}
</select>
<!--通过查询指定table的 text code key 获取字典值-->
<select id="queryTableDictTextByKey" parameterType="String" resultType="String">
select ${text} as 'text' from ${table} where ${code}= #{key}
select ${text} as "text" from ${table} where ${code}= #{key}
</select>
<!-- 重复校验 sql语句 -->
@ -44,25 +44,25 @@
<!-- 查询部门信息 作为字典数据 -->
<select id="queryAllDepartBackDictModel" resultType="org.jeecg.common.system.vo.DictModel">
select id as value,depart_name as text from sys_depart where del_flag = '0'
select id as "value",depart_name as "text" from sys_depart where del_flag = '0'
</select>
<!-- 查询部门信息 作为字典数据 -->
<select id="queryAllUserBackDictModel" resultType="org.jeecg.common.system.vo.DictModel">
select username as value,realname as text from sys_depart where del_flag = '0'
select username as "value",realname as "text" from sys_depart where del_flag = '0'
</select>
<!--通过查询指定table的 text code 获取字典数据,且支持关键字查询 -->
<select id="queryTableDictItems" parameterType="String" resultType="org.jeecg.common.system.vo.DictModel">
select ${text} as 'text',${code} as 'value' from ${table} where ${text} like #{keyword}
select ${text} as "text",${code} as "value" from ${table} where ${text} like #{keyword}
</select>
<!-- 根据表名、显示字段名、存储字段名、父ID查询树 -->
<select id="queryTreeList" parameterType="String" resultType="org.jeecg.modules.system.model.TreeSelectModel">
select ${text} as 'title',
${code} as 'key',
select ${text} as "title",
${code} as "key",
<if test="hasChildField != null and hasChildField != ''">
(case ${hasChildField} when '1' then 0 else 1 end) as 'isLeaf',
(case ${hasChildField} when '1' then 0 else 1 end) as isLeaf,
</if>
${pidField} as parentId
from ${table} where ${pidField} = #{pid}

View File

@ -2,6 +2,7 @@ package org.jeecg.modules.system.service;
import com.baomidou.mybatisplus.extension.service.IService;
import org.jeecg.modules.system.entity.SysDepart;
import org.jeecg.modules.system.model.DepartIdModel;
import org.jeecg.modules.system.model.SysDepartTreeModel;
import java.util.List;
@ -22,6 +23,12 @@ public interface ISysDepartService extends IService<SysDepart>{
*/
List<SysDepartTreeModel> queryTreeList();
/**
* 查询所有部门DepartId信息,并分节点进行显示
* @return
*/
public List<DepartIdModel> queryDepartIdTreeList();
/**
* 保存部门数据
* @param sysDepart
@ -62,5 +69,13 @@ public interface ISysDepartService extends IService<SysDepart>{
* @return
*/
public List<SysDepart> queryUserDeparts(String userId);
/**
* 根据部门id批量删除并删除其可能存在的子级部门
* @param id
* @return
*/
void deleteBatchWithChildren(List<String> ids);
}

View File

@ -8,6 +8,7 @@ import java.util.List;
import javax.annotation.Resource;
import org.jeecg.common.constant.CommonConstant;
import org.jeecg.common.util.oConvertUtils;
import org.jeecg.modules.system.entity.SysAnnouncement;
import org.jeecg.modules.system.entity.SysAnnouncementSend;
import org.jeecg.modules.system.mapper.SysAnnouncementMapper;
@ -67,9 +68,9 @@ public class SysAnnouncementServiceImpl extends ServiceImpl<SysAnnouncementMappe
public boolean upDateAnnouncement(SysAnnouncement sysAnnouncement) {
// 1.更新系统信息表数据
sysAnnouncementMapper.updateById(sysAnnouncement);
if(sysAnnouncement.getMsgType().equals(CommonConstant.MSG_TYPE_UESR)) {
String userId = sysAnnouncement.getUserIds();
if(oConvertUtils.isNotEmpty(userId)&&sysAnnouncement.getMsgType().equals(CommonConstant.MSG_TYPE_UESR)) {
// 2.补充新的通知用户数据
String userId = sysAnnouncement.getUserIds();
String[] userIds = userId.substring(0, (userId.length()-1)).split(",");
String anntId = sysAnnouncement.getId();
Date refDate = new Date();

View File

@ -20,6 +20,7 @@ import org.jeecg.common.system.vo.LoginUser;
import org.jeecg.common.util.IPUtils;
import org.jeecg.common.util.SpringContextUtils;
import org.jeecg.common.util.oConvertUtils;
import org.jeecg.modules.message.websocket.WebSocket;
import org.jeecg.modules.system.entity.SysAnnouncement;
import org.jeecg.modules.system.entity.SysAnnouncementSend;
import org.jeecg.modules.system.entity.SysDict;
@ -35,6 +36,7 @@ import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import lombok.extern.slf4j.Slf4j;
@ -66,6 +68,8 @@ public class SysBaseApiImpl implements ISysBaseAPI {
private SysAnnouncementMapper sysAnnouncementMapper;
@Resource
private SysAnnouncementSendMapper sysAnnouncementSendMapper;
@Resource
private WebSocket webSocket;
@Override
public void addLog(String LogContent, Integer logType, Integer operatetype) {
@ -167,8 +171,15 @@ public class SysBaseApiImpl implements ISysBaseAPI {
announcementSend.setUserId(sysUser.getId());
announcementSend.setReadFlag(CommonConstant.NO_READ_FLAG);
sysAnnouncementSendMapper.insert(announcementSend);
JSONObject obj = new JSONObject();
obj.put("cmd", "user");
obj.put("userId", sysUser.getId());
obj.put("msgId", announcement.getId());
obj.put("msgTxt", announcement.getTitile());
webSocket.sendOneMessage(sysUser.getId(), obj.toJSONString());
}
}
}
/**
* 获取数据库类型

View File

@ -5,13 +5,16 @@ import java.util.Date;
import java.util.List;
import java.util.UUID;
import org.jeecg.common.constant.CacheConstant;
import org.jeecg.common.constant.CommonConstant;
import org.jeecg.common.util.YouBianCodeUtil;
import org.jeecg.modules.system.entity.SysDepart;
import org.jeecg.modules.system.mapper.SysDepartMapper;
import org.jeecg.modules.system.model.DepartIdModel;
import org.jeecg.modules.system.model.SysDepartTreeModel;
import org.jeecg.modules.system.service.ISysDepartService;
import org.jeecg.modules.system.util.FindsDepartsChildrenUtil;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@ -34,6 +37,7 @@ public class SysDepartServiceImpl extends ServiceImpl<SysDepartMapper, SysDepart
/**
* queryTreeList 对应 queryTreeList 查询所有的部门数据,以树结构形式响应给前端
*/
@Cacheable(value = CacheConstant.DEPART_INFO_CACHE)
@Override
public List<SysDepartTreeModel> queryTreeList() {
LambdaQueryWrapper<SysDepart> query = new LambdaQueryWrapper<SysDepart>();
@ -45,6 +49,18 @@ public class SysDepartServiceImpl extends ServiceImpl<SysDepartMapper, SysDepart
return listResult;
}
@Cacheable(value = CacheConstant.DEPART_IDMODEL_CACHE)
@Override
public List<DepartIdModel> queryDepartIdTreeList() {
LambdaQueryWrapper<SysDepart> query = new LambdaQueryWrapper<SysDepart>();
query.eq(SysDepart::getDelFlag, CommonConstant.DEL_FLAG_0.toString());
query.orderByAsc(SysDepart::getDepartOrder);
List<SysDepart> list = this.list(query);
// 调用wrapTreeDataToTreeList方法生成树状数据
List<DepartIdModel> listResult = FindsDepartsChildrenUtil.wrapTreeDataToDepartIdTreeList(list);
return listResult;
}
/**
* saveDepartData 对应 add 保存用户在页面添加的新的部门对象数据
*/
@ -75,8 +91,6 @@ public class SysDepartServiceImpl extends ServiceImpl<SysDepartMapper, SysDepart
* saveDepartData 的调用方法,生成部门编码和部门类型
*
* @param parentId
* @param strArray
* @param departList
* @return
*/
private String[] generateOrgCode(String parentId) {
@ -168,8 +182,18 @@ public class SysDepartServiceImpl extends ServiceImpl<SysDepartMapper, SysDepart
}
}
@Override
@Transactional
public void deleteBatchWithChildren(List<String> ids) {
List<String> idList = new ArrayList<String>();
for(String id: ids) {
idList.add(id);
this.checkChildrenExists(id, idList);
}
this.removeByIds(idList);
}
/**
* <p>
* 根据关键字搜索相关的部门数据
@ -203,6 +227,8 @@ public class SysDepartServiceImpl extends ServiceImpl<SysDepartMapper, SysDepart
List<String> idList = new ArrayList<>();
idList.add(id);
this.checkChildrenExists(id, idList);
//清空部门树内存
//FindsDepartsChildrenUtil.clearDepartIdModel();
boolean ok = this.removeByIds(idList);
return ok;
}

View File

@ -68,7 +68,7 @@ public class SysPermissionDataRuleImpl extends ServiceImpl<SysPermissionDataRule
if(ids==null) {
continue;
}
String arr[] = ids.split(",");
String[] arr = ids.split(",");
for (String id : arr) {
if(oConvertUtils.isNotEmpty(id)) {
set.add(id);
@ -86,7 +86,7 @@ public class SysPermissionDataRuleImpl extends ServiceImpl<SysPermissionDataRule
public void savePermissionDataRule(SysPermissionDataRule sysPermissionDataRule) {
this.save(sysPermissionDataRule);
SysPermission permission = sysPermissionMapper.selectById(sysPermissionDataRule.getPermissionId());
if(permission!=null && (permission.getRuleFlag()==null || permission.getRuleFlag()==CommonConstant.RULE_FLAG_0)) {
if(permission!=null && (permission.getRuleFlag()==null || permission.getRuleFlag().equals(CommonConstant.RULE_FLAG_0))) {
permission.setRuleFlag(CommonConstant.RULE_FLAG_1);
sysPermissionMapper.updateById(permission);
}
@ -102,7 +102,7 @@ public class SysPermissionDataRuleImpl extends ServiceImpl<SysPermissionDataRule
//注:同一个事务中删除后再查询是会认为数据已被删除的 若事务回滚上述删除无效
if(count==null || count==0) {
SysPermission permission = sysPermissionMapper.selectById(dataRule.getPermissionId());
if(permission!=null && permission.getRuleFlag()==CommonConstant.RULE_FLAG_1) {
if(permission!=null && permission.getRuleFlag().equals(CommonConstant.RULE_FLAG_1)) {
permission.setRuleFlag(CommonConstant.RULE_FLAG_0);
sysPermissionMapper.updateById(permission);
}

View File

@ -36,7 +36,7 @@ public class SysRolePermissionServiceImpl extends ServiceImpl<SysRolePermissionM
LambdaQueryWrapper<SysRolePermission> query = new QueryWrapper<SysRolePermission>().lambda().eq(SysRolePermission::getRoleId, roleId);
this.remove(query);
List<SysRolePermission> list = new ArrayList<SysRolePermission>();
String arr[] = permissionIds.split(",");
String[] arr = permissionIds.split(",");
for (String p : arr) {
if(oConvertUtils.isNotEmpty(p)) {
SysRolePermission rolepms = new SysRolePermission(roleId, p);

View File

@ -1,9 +1,12 @@
package org.jeecg.modules.system.util;
import org.jeecg.common.constant.CommonConstant;
import org.jeecg.common.util.RedisUtil;
import org.jeecg.common.util.oConvertUtils;
import org.jeecg.modules.system.entity.SysDepart;
import org.jeecg.modules.system.model.DepartIdModel;
import org.jeecg.modules.system.model.SysDepartTreeModel;
import org.springframework.beans.factory.annotation.Autowired;
import java.util.ArrayList;
import java.util.List;
@ -18,8 +21,11 @@ import java.util.List;
*/
public class FindsDepartsChildrenUtil {
private static List<DepartIdModel> idList = new ArrayList<>(4);
//部门树信息-树结构
//private static List<SysDepartTreeModel> sysDepartTreeList = new ArrayList<SysDepartTreeModel>();
//部门树id-树结构
//private static List<DepartIdModel> idList = new ArrayList<>();
/**
@ -27,8 +33,9 @@ public class FindsDepartsChildrenUtil {
* 该方法是s将SysDepart类型的list集合转换成SysDepartTreeModel类型的集合
*/
public static List<SysDepartTreeModel> wrapTreeDataToTreeList(List<SysDepart> recordList) {
// 在该方法每请求一次,都要对全局list集合进行一次清理
idList.clear();
// 在该方法每请求一次,都要对全局list集合进行一次清理
//idList.clear();
List<DepartIdModel> idList = new ArrayList<DepartIdModel>();
List<SysDepartTreeModel> records = new ArrayList<>();
for (int i = 0; i < recordList.size(); i++) {
SysDepart depart = recordList.get(i);
@ -39,7 +46,21 @@ public class FindsDepartsChildrenUtil {
return tree;
}
public static List<DepartIdModel> wrapDepartIdModel() {
/**
* 获取 DepartIdModel
* @param recordList
* @return
*/
public static List<DepartIdModel> wrapTreeDataToDepartIdTreeList(List<SysDepart> recordList) {
// 在该方法每请求一次,都要对全局list集合进行一次清理
//idList.clear();
List<DepartIdModel> idList = new ArrayList<DepartIdModel>();
List<SysDepartTreeModel> records = new ArrayList<>();
for (int i = 0; i < recordList.size(); i++) {
SysDepart depart = recordList.get(i);
records.add(new SysDepartTreeModel(depart));
}
findChildren(records, idList);
return idList;
}
@ -48,7 +69,7 @@ public class FindsDepartsChildrenUtil {
* 该方法是找到并封装顶级父类的节点到TreeList集合
*/
private static List<SysDepartTreeModel> findChildren(List<SysDepartTreeModel> recordList,
List<DepartIdModel> idList) {
List<DepartIdModel> departIdList) {
List<SysDepartTreeModel> treeList = new ArrayList<>();
for (int i = 0; i < recordList.size(); i++) {
@ -56,10 +77,12 @@ public class FindsDepartsChildrenUtil {
if (oConvertUtils.isEmpty(branch.getParentId())) {
treeList.add(branch);
DepartIdModel departIdModel = new DepartIdModel().convert(branch);
idList.add(departIdModel);
departIdList.add(departIdModel);
}
}
getGrandChildren(treeList,recordList,idList);
getGrandChildren(treeList,recordList,departIdList);
//idList = departIdList;
return treeList;
}
@ -102,5 +125,6 @@ public class FindsDepartsChildrenUtil {
model.setIsLeaf(false);
}
}
// sysDepartTreeList = treeList;
}
}

View File

@ -1,5 +1,7 @@
server:
port: 8080
tomcat:
max-swallow-size: -1
servlet:
context-path: /jeecg-boot
compression:
@ -64,6 +66,7 @@ spring:
enabled: true
loginUsername: admin
loginPassword: 123456
allow:
web-stat-filter:
enabled: true
dynamic:
@ -136,3 +139,10 @@ jeecg :
upload: D://upFiles
#webapp文件路径
webapp: D://webapp
#短信秘钥
sms:
accessKeyId: LTAIpW4gUG7xYDNI
accessKeySecret: ???
#cas单点登录
cas:
prefixUrl: http://cas.example.org:8443/cas

View File

@ -1,5 +1,7 @@
server:
port: 8080
tomcat:
max-swallow-size: -1
servlet:
context-path: /jeecg-boot
compression:
@ -64,6 +66,7 @@ spring:
enabled: true
loginUsername: admin
loginPassword: 123456
allow:
web-stat-filter:
enabled: true
dynamic:
@ -105,7 +108,7 @@ spring:
#redis 配置
redis:
database: 0
host: 118.89.223.144
host: 127.0.0.1
lettuce:
pool:
max-active: 8 #最大连接数据库连接数,设 0 为没有限制
@ -133,3 +136,10 @@ jeecg :
upload: /opt/jeecg-boot/upload
#webapp文件路径
webapp: /opt/jeecg-boot/webapp
#短信秘钥
sms:
accessKeyId: LTAIpW4gUG7xYDNI
accessKeySecret: ???
#cas单点登录
cas:
prefixUrl: http://cas.example.org:8443/cas

View File

@ -1,5 +1,7 @@
server:
port: 8080
tomcat:
max-swallow-size: -1
servlet:
context-path: /jeecg-boot
compression:
@ -64,6 +66,7 @@ spring:
enabled: true
loginUsername: admin
loginPassword: 123456
allow:
web-stat-filter:
enabled: true
dynamic:
@ -136,6 +139,13 @@ jeecg :
upload: D://upFiles
#webapp文件路径
webapp: D://webapp
#短信秘钥
sms:
accessKeyId: LTAIpW4gUG7xYDNI
accessKeySecret: ???
logging:
level:
org.jeecg.modules.system.mapper : debug
#cas单点登录
cas:
prefixUrl: http://cas.example.org:8443/cas

View File

@ -9,6 +9,6 @@ ${AnsiColor.BRIGHT_BLUE}
${AnsiColor.BRIGHT_GREEN}
Jeecg Boot Version: 2.0.2
Jeecg Boot Version: 2.1.0
Spring Boot Version: ${spring-boot.version}${spring-boot.formatted-version}
${AnsiColor.BLACK}

View File

@ -0,0 +1,226 @@
package ${bussiPackage}.${entityPackage}.controller;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.jeecg.common.api.vo.Result;
import org.jeecg.common.system.query.QueryGenerator;
import org.jeecg.common.util.oConvertUtils;
import ${bussiPackage}.${entityPackage}.entity.${entityName};
import ${bussiPackage}.${entityPackage}.service.I${entityName}Service;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.extern.slf4j.Slf4j;
import org.jeecgframework.poi.excel.ExcelImportUtil;
import org.jeecgframework.poi.excel.def.NormalExcelConstants;
import org.jeecgframework.poi.excel.entity.ExportParams;
import org.jeecgframework.poi.excel.entity.ImportParams;
import org.jeecgframework.poi.excel.view.JeecgEntityExcelView;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;
import org.springframework.web.servlet.ModelAndView;
import com.alibaba.fastjson.JSON;
/**
* @Description: ${tableVo.ftlDescription}
* @Author: jeecg-boot
* @Date: ${.now?string["yyyy-MM-dd"]}
* @Version: V1.0
*/
@RestController
@RequestMapping("/${entityPackage}/${entityName?uncap_first}")
@Slf4j
public class ${entityName}Controller {
@Autowired
private I${entityName}Service ${entityName?uncap_first}Service;
/**
* 分页列表查询
* @param ${entityName?uncap_first}
* @param pageNo
* @param pageSize
* @param req
* @return
*/
@GetMapping(value = "/list")
public Result<IPage<${entityName}>> queryPageList(${entityName} ${entityName?uncap_first},
@RequestParam(name="pageNo", defaultValue="1") Integer pageNo,
@RequestParam(name="pageSize", defaultValue="10") Integer pageSize,
HttpServletRequest req) {
Result<IPage<${entityName}>> result = new Result<IPage<${entityName}>>();
QueryWrapper<${entityName}> queryWrapper = QueryGenerator.initQueryWrapper(${entityName?uncap_first}, req.getParameterMap());
Page<${entityName}> page = new Page<${entityName}>(pageNo, pageSize);
IPage<${entityName}> pageList = ${entityName?uncap_first}Service.page(page, queryWrapper);
result.setSuccess(true);
result.setResult(pageList);
return result;
}
/**
* 添加
* @param ${entityName?uncap_first}
* @return
*/
@PostMapping(value = "/add")
public Result<${entityName}> add(@RequestBody ${entityName} ${entityName?uncap_first}) {
Result<${entityName}> result = new Result<${entityName}>();
try {
${entityName?uncap_first}Service.save(${entityName?uncap_first});
result.success("添加成功!");
} catch (Exception e) {
log.error(e.getMessage(),e);
result.error500("操作失败");
}
return result;
}
/**
* 编辑
* @param ${entityName?uncap_first}
* @return
*/
@PutMapping(value = "/edit")
public Result<${entityName}> edit(@RequestBody ${entityName} ${entityName?uncap_first}) {
Result<${entityName}> result = new Result<${entityName}>();
${entityName} ${entityName?uncap_first}Entity = ${entityName?uncap_first}Service.getById(${entityName?uncap_first}.getId());
if(${entityName?uncap_first}Entity==null) {
result.error500("未找到对应实体");
}else {
boolean ok = ${entityName?uncap_first}Service.updateById(${entityName?uncap_first});
//TODO 返回false说明什么
if(ok) {
result.success("修改成功!");
}
}
return result;
}
/**
* 通过id删除
* @param id
* @return
*/
@DeleteMapping(value = "/delete")
public Result<?> delete(@RequestParam(name="id",required=true) String id) {
try {
${entityName?uncap_first}Service.removeById(id);
} catch (Exception e) {
log.error("删除失败",e.getMessage());
return Result.error("删除失败!");
}
return Result.ok("删除成功!");
}
/**
* 批量删除
* @param ids
* @return
*/
@DeleteMapping(value = "/deleteBatch")
public Result<${entityName}> deleteBatch(@RequestParam(name="ids",required=true) String ids) {
Result<${entityName}> result = new Result<${entityName}>();
if(ids==null || "".equals(ids.trim())) {
result.error500("参数不识别!");
}else {
this.${entityName?uncap_first}Service.removeByIds(Arrays.asList(ids.split(",")));
result.success("删除成功!");
}
return result;
}
/**
* 通过id查询
* @param id
* @return
*/
@GetMapping(value = "/queryById")
public Result<${entityName}> queryById(@RequestParam(name="id",required=true) String id) {
Result<${entityName}> result = new Result<${entityName}>();
${entityName} ${entityName?uncap_first} = ${entityName?uncap_first}Service.getById(id);
if(${entityName?uncap_first}==null) {
result.error500("未找到对应实体");
}else {
result.setResult(${entityName?uncap_first});
result.setSuccess(true);
}
return result;
}
/**
* 导出excel
*
* @param request
* @param response
*/
@RequestMapping(value = "/exportXls")
public ModelAndView exportXls(HttpServletRequest request, ${entityName} ${entityName?uncap_first}) {
// Step.1 组装查询条件查询数据
QueryWrapper<${entityName}> queryWrapper = QueryGenerator.initQueryWrapper(${entityName?uncap_first}, request.getParameterMap());
List<${entityName}> pageList = ${entityName?uncap_first}Service.list(queryWrapper);
// Step.2 AutoPoi 导出Excel
ModelAndView mv = new ModelAndView(new JeecgEntityExcelView());
// 过滤选中数据
String selections = request.getParameter("selections");
if(oConvertUtils.isEmpty(selections)) {
mv.addObject(NormalExcelConstants.DATA_LIST, pageList);
}else {
List<String> selectionList = Arrays.asList(selections.split(","));
List<${entityName}> exportList = pageList.stream().filter(item -> selectionList.contains(item.getId())).collect(Collectors.toList());
mv.addObject(NormalExcelConstants.DATA_LIST, exportList);
}
//导出文件名称
mv.addObject(NormalExcelConstants.FILE_NAME, "${tableVo.ftlDescription}列表");
mv.addObject(NormalExcelConstants.CLASS, ${entityName}.class);
mv.addObject(NormalExcelConstants.PARAMS, new ExportParams("${tableVo.ftlDescription}列表数据", "导出人:Jeecg", "导出信息"));
return mv;
}
/**
* 通过excel导入数据
*
* @param request
* @param response
* @return
*/
@RequestMapping(value = "/importExcel", method = RequestMethod.POST)
public Result<?> importExcel(HttpServletRequest request, HttpServletResponse response) {
MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request;
Map<String, MultipartFile> fileMap = multipartRequest.getFileMap();
for (Map.Entry<String, MultipartFile> entity : fileMap.entrySet()) {
MultipartFile file = entity.getValue();// 获取上传文件对象
ImportParams params = new ImportParams();
params.setTitleRows(2);
params.setHeadRows(1);
params.setNeedSave(true);
try {
List<${entityName}> list${entityName}s = ExcelImportUtil.importExcel(file.getInputStream(), ${entityName}.class, params);
${entityName?uncap_first}Service.saveBatch(list${entityName}s);
return Result.ok("文件导入成功!数据行数:" + list${entityName}s.size());
} catch (Exception e) {
log.error(e.getMessage(),e);
return Result.error("文件导入失败:"+e.getMessage());
} finally {
try {
file.getInputStream().close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return Result.ok("文件导入失败!");
}
}

View File

@ -0,0 +1,54 @@
package ${bussiPackage}.${entityPackage}.entity;
import java.io.Serializable;
import java.util.Date;
import java.math.BigDecimal;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import com.fasterxml.jackson.annotation.JsonFormat;
import org.springframework.format.annotation.DateTimeFormat;
import org.jeecgframework.poi.excel.annotation.Excel;
import org.jeecg.common.aspect.annotation.Dict;
/**
* @Description: ${tableVo.ftlDescription}
* @Author: jeecg-boot
* @Date: ${.now?string["yyyy-MM-dd"]}
* @Version: V1.0
*/
@Data
@TableName("${tableName}")
public class ${entityName} implements Serializable {
private static final long serialVersionUID = 1L;
<#list originalColumns as po>
/**${po.filedComment}*/
<#if po.fieldName == primaryKeyField>
@TableId(type = IdType.UUID)
<#else>
<#if po.fieldDbType =='Date'>
<#if po.classType=='date'>
@Excel(name = "${po.filedComment}", width = 15, format = "yyyy-MM-dd")
@JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd")
@DateTimeFormat(pattern="yyyy-MM-dd")
<#else>
@Excel(name = "${po.filedComment}", width = 20, format = "yyyy-MM-dd HH:mm:ss")
@JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd HH:mm:ss")
@DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss")
</#if>
<#else>
@Excel(name = "${po.filedComment}", width = 15)
</#if>
<#-- <#if po.classType!='popup'>
<#if po.dictTable?default("")?trim?length gt 1>
@Dict(dicCode="${po.dictField}",dicText="${po.dictText}",dictTable="${po.dictTable}")
<#elseif po.dictField?default("")?trim?length gt 1>
@Dict(dicCode="${po.dictField}")
</#if>
</#if>-->
</#if>
private <#if po.fieldType=='java.sql.Blob'>byte[]<#else>${po.fieldType}</#if> ${po.fieldName};
</#list>
}

View File

@ -0,0 +1,17 @@
package ${bussiPackage}.${entityPackage}.mapper;
import java.util.List;
import org.apache.ibatis.annotations.Param;
import ${bussiPackage}.${entityPackage}.entity.${entityName};
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
/**
* @Description: ${tableVo.ftlDescription}
* @Author: jeecg-boot
* @Date: ${.now?string["yyyy-MM-dd"]}
* @Version: V1.0
*/
public interface ${entityName}Mapper extends BaseMapper<${entityName}> {
}

View File

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="${bussiPackage}.${entityPackage}.mapper.${entityName}Mapper">
</mapper>

View File

@ -0,0 +1,14 @@
package ${bussiPackage}.${entityPackage}.service;
import ${bussiPackage}.${entityPackage}.entity.${entityName};
import com.baomidou.mybatisplus.extension.service.IService;
/**
* @Description: ${tableVo.ftlDescription}
* @Author: jeecg-boot
* @Date: ${.now?string["yyyy-MM-dd"]}
* @Version: V1.0
*/
public interface I${entityName}Service extends IService<${entityName}> {
}

View File

@ -0,0 +1,19 @@
package ${bussiPackage}.${entityPackage}.service.impl;
import ${bussiPackage}.${entityPackage}.entity.${entityName};
import ${bussiPackage}.${entityPackage}.mapper.${entityName}Mapper;
import ${bussiPackage}.${entityPackage}.service.I${entityName}Service;
import org.springframework.stereotype.Service;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
/**
* @Description: ${tableVo.ftlDescription}
* @Author: jeecg-boot
* @Date: ${.now?string["yyyy-MM-dd"]}
* @Version: V1.0
*/
@Service
public class ${entityName}ServiceImpl extends ServiceImpl<${entityName}Mapper, ${entityName}> implements I${entityName}Service {
}

View File

@ -0,0 +1,297 @@
<template>
<a-card :bordered="false">
<!-- 查询区域 -->
<div class="table-page-search-wrapper">
<a-form layout="inline">
<a-row :gutter="24">
<#assign query_field_no=0>
<#assign query_field_select=false>
<#assign query_field_date=false>
<#assign list_need_dict=false>
<#assign query_flag=false>
<#-- 开始循环 -->
<#list columns as po>
<#if po.isQuery=='Y'>
<#assign query_flag=true>
<#if query_field_no==2>
<template v-if="toggleSearchStatus">
</#if>
<#if po.queryMode=='single'>
<#if query_field_no gt 1> </#if><a-col :md="6" :sm="8">
<#if query_field_no gt 1> </#if><a-form-item label="${po.filedComment}">
<#if po.classType=='date'>
<#assign query_field_date=true>
<#if query_field_no gt 1> </#if><j-date placeholder="请选择${po.filedComment}" v-model="queryParam.${po.fieldName}"></j-date>
<#elseif po.classType=='datetime'>
<#assign query_field_date=true>
<#if query_field_no gt 1> </#if><j-date :show-time="true" date-format="YYYY-MM-DD HH:mm:ss" placeholder="请选择${po.filedComment}" v-model="queryParam.${po.fieldName}"></j-date>
<#elseif po.classType=='list' || po.classType=='radio' || po.classType=='checkbox'>
<#assign query_field_select=true>
<#-- ---------------------------下拉或是单选 判断数据字典是表字典还是普通字典------------------------------- -->
<#if po.dictTable?default("")?trim?length gt 1>
<#if query_field_no gt 1> </#if><j-dict-select-tag placeholder="请选择${po.filedComment}" v-model="queryParam.${po.fieldName}" dictCode="${po.dictTable},${po.dictText},${po.dictField}"/>
<#elseif po.dictField?default("")?trim?length gt 1>
<#if query_field_no gt 1> </#if><j-dict-select-tag placeholder="请选择${po.filedComment}" v-model="queryParam.${po.fieldName}" dictCode="${po.dictField}"/>
<#else>
<#if query_field_no gt 1> </#if><a-input placeholder="请输入${po.filedComment}" v-model="queryParam.${po.fieldName}"></a-input>
</#if>
<#else>
<#if query_field_no gt 1> </#if><a-input placeholder="请输入${po.filedComment}" v-model="queryParam.${po.fieldName}"></a-input>
</#if>
<#if query_field_no gt 1> </#if></a-form-item>
<#if query_field_no gt 1> </#if></a-col>
<#else>
<#if query_field_no gt 1> </#if><a-col :md="12" :sm="16">
<#if query_field_no gt 1> </#if><a-form-item label="${po.filedComment}">
<#if po.classType=='date'>
<#assign query_field_date=true>
<#if query_field_no gt 1> </#if><j-date placeholder="请选择开始日期" class="query-group-cust" v-model="queryParam.${po.fieldName}_begin"></j-date>
<#if query_field_no gt 1> </#if><span class="query-group-split-cust"></span>
<#if query_field_no gt 1> </#if><j-date placeholder="请选择结束日期" class="query-group-cust" v-model="queryParam.${po.fieldName}_end"></j-date>
<#elseif po.classType=='datetime'>
<#assign query_field_date=true>
<#if query_field_no gt 1> </#if><j-date :show-time="true" date-format="YYYY-MM-DD HH:mm:ss" placeholder="请选择开始时间" class="query-group-cust" v-model="queryParam.${po.fieldName}_begin"></j-date>
<#if query_field_no gt 1> </#if><span class="query-group-split-cust"></span>
<#if query_field_no gt 1> </#if><j-date :show-time="true" date-format="YYYY-MM-DD HH:mm:ss" placeholder="请选择结束时间" class="query-group-cust" v-model="queryParam.${po.fieldName}_end"></j-date>
<#else>
<#if query_field_no gt 1> </#if><a-input placeholder="请输入最小值" class="query-group-cust" v-model="queryParam.${po.fieldName}_begin"></a-input>
<#if query_field_no gt 1> </#if><span class="query-group-split-cust"></span>
<#if query_field_no gt 1> </#if><a-input placeholder="请输入最大值" class="query-group-cust" v-model="queryParam.${po.fieldName}_end"></a-input>
</#if>
<#if query_field_no gt 1> </#if></a-form-item>
<#if query_field_no gt 1> </#if></a-col>
</#if>
<#assign query_field_no=query_field_no+1>
</#if>
<#if !list_need_dict && po.fieldShowType!='popup' && po.dictField?default("")?trim?length gt 1>
<#assign list_need_dict=true>
</#if>
</#list>
<#t>
<#if query_field_no gt 2>
</template>
</#if>
<#if query_flag>
<a-col :md="6" :sm="8" >
<span style="float: left;overflow: hidden;" class="table-page-search-submitButtons">
<a-button type="primary" @click="searchQuery" icon="search">查询</a-button>
<a-button type="primary" @click="searchReset" icon="reload" style="margin-left: 8px">重置</a-button>
<a @click="handleToggleSearch" style="margin-left: 8px">
{{ toggleSearchStatus ? '收起' : '展开' }}
<a-icon :type="toggleSearchStatus ? 'up' : 'down'"/>
</a>
</span>
</a-col>
</#if>
</a-row>
</a-form>
</div>
<!-- 查询区域-END -->
<!-- 操作按钮区域 -->
<div class="table-operator">
<a-button @click="handleAdd" type="primary" icon="plus">新增</a-button>
<a-button type="primary" icon="download" @click="handleExportXls('${tableVo.ftlDescription}')">导出</a-button>
<a-upload name="file" :showUploadList="false" :multiple="false" :action="importExcelUrl" @change="handleImportExcel">
<a-button type="primary" icon="import">导入</a-button>
</a-upload>
<a-dropdown v-if="selectedRowKeys.length > 0">
<a-menu slot="overlay">
<a-menu-item key="1" @click="batchDel"><a-icon type="delete"/>删除</a-menu-item>
</a-menu>
<a-button style="margin-left: 8px"> 批量操作 <a-icon type="down" /></a-button>
</a-dropdown>
</div>
<!-- table区域-begin -->
<div>
<div class="ant-alert ant-alert-info" style="margin-bottom: 16px;">
<i class="anticon anticon-info-circle ant-alert-icon"></i> 已选择 <a style="font-weight: 600">{{ selectedRowKeys.length }}</a>项
<a style="margin-left: 24px" @click="onClearSelected">清空</a>
</div>
<a-table
ref="table"
size="middle"
bordered
rowKey="id"
:columns="columns"
:dataSource="dataSource"
:pagination="ipagination"
:loading="loading"
:rowSelection="{selectedRowKeys: selectedRowKeys, onChange: onSelectChange}"
@change="handleTableChange">
<template slot="imgSlot" slot-scope="text">
<span v-if="!text" style="font-size: 12px;font-style: italic;">无此图片</span>
<img v-else :src="getImgView(text)" height="25px" alt="图片不存在" style="max-width:80px;font-size: 12px;font-style: italic;"/>
</template>
<template slot="fileSlot" slot-scope="text">
<span v-if="!text" style="font-size: 12px;font-style: italic;">无此文件</span>
<a-button
v-else
:ghost="true"
type="primary"
icon="download"
size="small"
@click="uploadFile(text)">
下载
</a-button>
</template>
<span slot="action" slot-scope="text, record">
<a @click="handleEdit(record)">编辑</a>
<a-divider type="vertical" />
<a-dropdown>
<a class="ant-dropdown-link">更多 <a-icon type="down" /></a>
<a-menu slot="overlay">
<a-menu-item>
<a-popconfirm title="确定删除吗?" @confirm="() => handleDelete(record.id)">
<a>删除</a>
</a-popconfirm>
</a-menu-item>
</a-menu>
</a-dropdown>
</span>
</a-table>
</div>
<${entityName?uncap_first}-modal ref="modalForm" @ok="modalFormOk"></${entityName?uncap_first}-modal>
</a-card>
</template>
<script>
import { JeecgListMixin } from '@/mixins/JeecgListMixin'
import ${entityName}Modal from './modules/${entityName}Modal'
<#if query_field_select>
import JDictSelectTag from '@/components/dict/JDictSelectTag.vue'
</#if>
<#if query_field_date>
import JDate from '@/components/jeecg/JDate.vue'
</#if>
<#if list_need_dict>
import {initDictOptions, filterMultiDictText} from '@/components/dict/JDictSelectUtil'
</#if>
export default {
name: "${entityName}List",
mixins:[JeecgListMixin],
components: {
<#if query_field_select>
JDictSelectTag,
</#if>
<#if query_field_date>
JDate,
</#if>
${entityName}Modal
},
data () {
return {
description: '${tableVo.ftlDescription}管理页面',
// 表头
columns: [
{
title: '#',
dataIndex: '',
key:'rowIndex',
width:60,
align:"center",
customRender:function (t,r,index) {
return parseInt(index)+1;
}
},
<#list columns as po>
{
title:'${po.filedComment}',
align:"center",
<#if po.classType=='date'>
dataIndex: '${po.fieldName}',
customRender:function (text) {
return !text?"":(text.length>10?text.substr(0,10):text)
}
<#elseif po.classType=='file'>
dataIndex: '${po.fieldName}',
scopedSlots: {customRender: 'fileSlot'}
<#elseif po.classType=='image'>
dataIndex: '${po.fieldName}',
scopedSlots: {customRender: 'imgSlot'}
<#elseif po.classType=='list_multi' || po.classType=='list' || po.classType=='radio' || po.classType=='checkbox' || po.classType=='sel_depart'>
dataIndex: '${po.fieldName}',
customRender:(text)=>{
if(!text){
return ''
}else{
return filterMultiDictText(this.dictOptions['${po.fieldName}'], text+"")
}
}
<#else>
dataIndex: '${po.fieldName}'
</#if>
},
</#list>
{
title: '操作',
dataIndex: 'action',
align:"center",
scopedSlots: { customRender: 'action' },
}
],
url: {
list: "/${entityPackage}/${entityName?uncap_first}/list",
delete: "/${entityPackage}/${entityName?uncap_first}/delete",
deleteBatch: "/${entityPackage}/${entityName?uncap_first}/deleteBatch",
exportXlsUrl: "/${entityPackage}/${entityName?uncap_first}/exportXls",
importExcelUrl: "${entityPackage}/${entityName?uncap_first}/importExcel",
},
dictOptions:{
<#list columns as po>
<#if (po.isQuery=='Y' || po.isShowList=='Y')>
<#if po.classType='sel_depart' || po.classType=='list_multi' || po.classType=='list' || po.classType=='radio' || po.classType=='checkbox'>
${po.fieldName}:[],
</#if>
</#if>
</#list>
}
}
},
computed: {
importExcelUrl: function(){
<#noparse>return `${window._CONFIG['domianURL']}/${this.url.importExcelUrl}`;</#noparse>
}
},
methods: {
initDictConfig(){
<#list columns as po>
<#if (po.isQuery=='Y' || po.isShowList=='Y') && po.classType!='popup'>
<#if po.classType='sel_depart'>
initDictOptions('sys_depart,depart_name,id').then((res) => {
if (res.success) {
this.$set(this.dictOptions, '${po.fieldName}', res.result)
}
})
<#elseif po.classType=='list_multi' || po.classType=='list' || po.classType=='radio' || po.classType=='checkbox'>
<#assign list_field_dictCode="">
<#if po.dictTable?default("")?trim?length gt 1>
<#assign list_field_dictCode="${po.dictTable},${po.dictText},${po.dictField}">
<#elseif po.dictField?default("")?trim?length gt 1>
<#assign list_field_dictCode="${po.dictField}">
</#if>
initDictOptions('${list_field_dictCode}').then((res) => {
if (res.success) {
this.$set(this.dictOptions, '${po.fieldName}', res.result)
}
})
</#if>
</#if>
</#list>
}
}
}
</script>
<style scoped>
@import '~@assets/less/common.less'
</style>

View File

@ -0,0 +1,219 @@
<template>
<a-modal
:title="title"
:width="width"
:visible="visible"
:confirmLoading="confirmLoading"
@ok="handleOk"
@cancel="handleCancel"
cancelText="关闭">
<a-spin :spinning="confirmLoading">
<a-form :form="form">
<#assign form_date = false>
<#assign form_select = false>
<#assign form_select_multi = false>
<#assign form_popup = false>
<#assign form_sel_depart = false>
<#assign form_sel_user = false>
<#assign form_file = false>
<#list columns as po>
<#assign form_field_dictCode="">
<#if po.dictTable?default("")?trim?length gt 1>
<#assign form_field_dictCode="${po.dictTable},${po.dictText},${po.dictField}">
<#elseif po.dictField?default("")?trim?length gt 1>
<#assign form_field_dictCode="${po.dictField}">
</#if>
<a-form-item label="${po.filedComment}" :labelCol="labelCol" :wrapperCol="wrapperCol">
<#if po.classType =='date'>
<#assign form_date=true>
<j-date placeholder="请选择${po.filedComment}" v-decorator="[ '${po.fieldName}', validatorRules.${po.fieldName}]" :trigger-change="true" style="width: 100%"/>
<#elseif po.classType =='datetime'>
<#assign form_date=true>
<j-date placeholder="请选择${po.filedComment}" v-decorator="[ '${po.fieldName}', validatorRules.${po.fieldName}]" :trigger-change="true" :show-time="true" date-format="YYYY-MM-DD HH:mm:ss" style="width: 100%"/>
<#elseif po.classType =='popup'>
<#assign form_popup=true>
<j-popup
v-decorator="['${po.fieldName}']"
:trigger-change="true"
org-fields="${po.dictField}"
dest-fields="${po.dictText}"
code="${po.dictTable}"
@callback="popupCallback"/>
<#elseif po.classType =='sel_depart'>
<#assign form_sel_depart=true>
<j-select-depart v-decorator="['${po.fieldName}']" :trigger-change="true"/>
<#elseif po.classType =='sel_user'>
<#assign form_sel_user = true>
<j-select-user-by-dep v-decorator="['${po.fieldName}']" :trigger-change="true"/>
<#elseif po.classType =='textarea'>
<a-textarea v-decorator="['${po.fieldName}']" rows="4" placeholder="请输入${po.filedComment}"/>
<#elseif po.classType=='list' || po.classType=='radio'>
<#assign form_select = true>
<j-dict-select-tag type="${po.classType}" v-decorator="['${po.fieldName}']" :trigger-change="true" dictCode="${form_field_dictCode}" placeholder="请选择${po.filedComment}"/>
<#elseif po.classType=='list_multi' || po.classType=='checkbox'>
<#assign form_select_multi = true>
<j-multi-select-tag type="${po.classType}" v-decorator="['${po.fieldName}']" :trigger-change="true" dictCode="${form_field_dictCode}" placeholder="请选择${po.filedComment}"/>
<#elseif po.fieldDbType=='int' || po.fieldDbType=='double' || po.fieldDbType=='BigDecimal'>
<a-input-number v-decorator="[ '${po.fieldName}', validatorRules.${po.fieldName}]" placeholder="请输入${po.filedComment}" style="width: 100%"/>
<#elseif po.classType=='file' || po.classType=='image'>
<#assign form_file = true>
<j-upload v-decorator="['${po.fieldName}']" :trigger-change="true"></j-upload>
<#else>
<a-input v-decorator="[ '${po.fieldName}', validatorRules.${po.fieldName}]" placeholder="请输入${po.filedComment}"></a-input>
</#if>
</a-form-item>
</#list>
</a-form>
</a-spin>
</a-modal>
</template>
<script>
import { httpAction } from '@/api/manage'
import pick from 'lodash.pick'
<#if form_date>
import JDate from '@/components/jeecg/JDate'
</#if>
<#if form_file>
import JUpload from '@/components/jeecg/JUpload'
</#if>
<#if form_popup>
import JPopup from '@/components/jeecgbiz/JPopup'
</#if>
<#if form_sel_depart>
import JSelectDepart from '@/components/jeecgbiz/JSelectDepart'
</#if>
<#if form_sel_user>
import JSelectUserByDep from '@/components/jeecgbiz/JSelectUserByDep'
</#if>
<#if form_select>
import JDictSelectTag from "@/components/dict/JDictSelectTag"
</#if>
<#if form_select_multi>
import JMultiSelectTag from "@/components/dict/JMultiSelectTag"
</#if>
export default {
name: "${entityName}Modal",
components: {
<#if form_date>
JDate,
</#if>
<#if form_file>
JUpload,
</#if>
<#if form_popup>
JPopup,
</#if>
<#if form_sel_depart>
JSelectDepart,
</#if>
<#if form_sel_user>
JSelectUserByDep,
</#if>
<#if form_select>
JDictSelectTag,
</#if>
<#if form_select_multi>
JMultiSelectTag,
</#if>
},
data () {
return {
form: this.$form.createForm(this),
title:"操作",
width:800,
visible: false,
model: {},
labelCol: {
xs: { span: 24 },
sm: { span: 5 },
},
wrapperCol: {
xs: { span: 24 },
sm: { span: 16 },
},
confirmLoading: false,
validatorRules:{
<#list columns as po>
<#if po.fieldName !='id'>
<#if po.nullable =='N'>
${po.fieldName}:{rules: [{ required: true, message: '请输入${po.filedComment}!' }]},
<#else>
${po.fieldName}:{},
</#if>
</#if>
</#list>
},
url: {
add: "/${entityPackage}/${entityName?uncap_first}/add",
edit: "/${entityPackage}/${entityName?uncap_first}/edit",
}
}
},
created () {
},
methods: {
add () {
this.edit({});
},
edit (record) {
this.form.resetFields();
this.model = Object.assign({}, record);
this.visible = true;
this.$nextTick(() => {
this.form.setFieldsValue(pick(this.model<#list columns as po><#if po.fieldName !='id'>,'${po.fieldName}'</#if></#list>))
})
},
close () {
this.$emit('close');
this.visible = false;
},
handleOk () {
const that = this;
// 触发表单验证
this.form.validateFields((err, values) => {
if (!err) {
that.confirmLoading = true;
let httpurl = '';
let method = '';
if(!this.model.id){
httpurl+=this.url.add;
method = 'post';
}else{
httpurl+=this.url.edit;
method = 'put';
}
let formData = Object.assign(this.model, values);
console.log("表单提交数据",formData)
httpAction(httpurl,formData,method).then((res)=>{
if(res.success){
that.$message.success(res.message);
that.$emit('ok');
}else{
that.$message.warning(res.message);
}
}).finally(() => {
that.confirmLoading = false;
that.close();
})
}
})
},
handleCancel () {
this.close()
},
popupCallback(row){
this.form.setFieldsValue(pick(row<#list columns as po><#if po.fieldName !='id'>,'${po.fieldName}'</#if></#list>))
}
}
}
</script>

View File

@ -0,0 +1,229 @@
<template>
<a-drawer
:title="title"
:width="width"
placement="right"
:closable="false"
@close="close"
:visible="visible">
<a-spin :spinning="confirmLoading">
<a-form :form="form">
<#assign form_date = false>
<#assign form_select = false>
<#assign form_select_multi = false>
<#assign form_popup = false>
<#assign form_sel_depart = false>
<#assign form_sel_user = false>
<#assign form_file = false>
<#list columns as po>
<#assign form_field_dictCode="">
<#if po.dictTable?default("")?trim?length gt 1>
<#assign form_field_dictCode="${po.dictTable},${po.dictText},${po.dictField}">
<#elseif po.dictField?default("")?trim?length gt 1>
<#assign form_field_dictCode="${po.dictField}">
</#if>
<a-form-item label="${po.filedComment}" :labelCol="labelCol" :wrapperCol="wrapperCol">
<#if po.classType =='date'>
<#assign form_date=true>
<j-date placeholder="请选择${po.filedComment}" v-decorator="[ '${po.fieldName}', validatorRules.${po.fieldName}]" :trigger-change="true" style="width: 100%"/>
<#elseif po.classType =='datetime'>
<#assign form_date=true>
<j-date placeholder="请选择${po.filedComment}" v-decorator="[ '${po.fieldName}', validatorRules.${po.fieldName}]" :trigger-change="true" :show-time="true" date-format="YYYY-MM-DD HH:mm:ss" style="width: 100%"/>
<#elseif po.classType =='popup'>
<#assign form_popup=true>
<j-popup
v-decorator="['${po.fieldName}']"
:trigger-change="true"
org-fields="${po.dictField}"
dest-fields="${po.dictText}"
code="${po.dictTable}"
@callback="popupCallback"/>
<#elseif po.classType =='sel_depart'>
<#assign form_sel_depart=true>
<j-select-depart v-decorator="['${po.fieldName}']" :trigger-change="true"/>
<#elseif po.classType =='sel_user'>
<#assign form_sel_user = true>
<j-select-user-by-dep v-decorator="['${po.fieldName}']" :trigger-change="true"/>
<#elseif po.classType =='textarea'>
<a-textarea v-decorator="['${po.fieldName}']" rows="4" placeholder="请输入${po.filedComment}"/>
<#elseif po.classType=='list' || po.classType=='radio'>
<#assign form_select = true>
<j-dict-select-tag type="${po.classType}" v-decorator="['${po.fieldName}']" :trigger-change="true" dictCode="${form_field_dictCode}" placeholder="请选择${po.filedComment}"/>
<#elseif po.classType=='list_multi' || po.classType=='checkbox'>
<#assign form_select_multi = true>
<j-multi-select-tag type="${po.classType}" v-decorator="['${po.fieldName}']" :trigger-change="true" dictCode="${form_field_dictCode}" placeholder="请选择${po.filedComment}"/>
<#elseif po.fieldDbType=='int' || po.fieldDbType=='double' || po.fieldDbType=='BigDecimal'>
<a-input-number v-decorator="[ '${po.fieldName}', validatorRules.${po.fieldName}]" placeholder="请输入${po.filedComment}" style="width: 100%"/>
<#elseif po.classType=='file' || po.classType=='image'>
<#assign form_file = true>
<j-upload v-decorator="['${po.fieldName}']" :trigger-change="true"></j-upload>
<#else>
<a-input v-decorator="[ '${po.fieldName}', validatorRules.${po.fieldName}]" placeholder="请输入${po.filedComment}"></a-input>
</#if>
</a-form-item>
</#list>
</a-form>
</a-spin>
<a-button type="primary" @click="handleOk">确定</a-button>
<a-button type="primary" @click="handleCancel">取消</a-button>
</a-drawer>
</template>
<script>
import { httpAction } from '@/api/manage'
import pick from 'lodash.pick'
<#if form_date>
import JDate from '@/components/jeecg/JDate'
</#if>
<#if form_file>
import JUpload from '@/components/jeecg/JUpload'
</#if>
<#if form_popup>
import JPopup from '@/components/jeecgbiz/JPopup'
</#if>
<#if form_sel_depart>
import JSelectDepart from '@/components/jeecgbiz/JSelectDepart'
</#if>
<#if form_sel_user>
import JSelectUserByDep from '@/components/jeecgbiz/JSelectUserByDep'
</#if>
<#if form_select>
import JDictSelectTag from "@/components/dict/JDictSelectTag"
</#if>
<#if form_select_multi>
import JMultiSelectTag from "@/components/dict/JMultiSelectTag"
</#if>
export default {
name: "${entityName}Modal",
components: {
<#if form_date>
JDate,
</#if>
<#if form_file>
JUpload,
</#if>
<#if form_popup>
JPopup,
</#if>
<#if form_sel_depart>
JSelectDepart,
</#if>
<#if form_sel_user>
JSelectUserByDep,
</#if>
<#if form_select>
JDictSelectTag,
</#if>
<#if form_select_multi>
JMultiSelectTag,
</#if>
},
data () {
return {
form: this.$form.createForm(this),
title:"操作",
width:800,
visible: false,
model: {},
labelCol: {
xs: { span: 24 },
sm: { span: 5 },
},
wrapperCol: {
xs: { span: 24 },
sm: { span: 16 },
},
confirmLoading: false,
validatorRules:{
<#list columns as po>
<#if po.fieldName !='id'>
<#if po.nullable =='N'>
${po.fieldName}:{rules: [{ required: true, message: '请输入${po.filedComment}!' }]},
<#else>
${po.fieldName}:{},
</#if>
</#if>
</#list>
},
url: {
add: "/${entityPackage}/${entityName?uncap_first}/add",
edit: "/${entityPackage}/${entityName?uncap_first}/edit",
}
}
},
created () {
},
methods: {
add () {
this.edit({});
},
edit (record) {
this.form.resetFields();
this.model = Object.assign({}, record);
this.visible = true;
this.$nextTick(() => {
this.form.setFieldsValue(pick(this.model<#list columns as po><#if po.fieldName !='id'>,'${po.fieldName}'</#if></#list>))
})
},
close () {
this.$emit('close');
this.visible = false;
},
handleOk () {
const that = this;
// 触发表单验证
this.form.validateFields((err, values) => {
if (!err) {
that.confirmLoading = true;
let httpurl = '';
let method = '';
if(!this.model.id){
httpurl+=this.url.add;
method = 'post';
}else{
httpurl+=this.url.edit;
method = 'put';
}
let formData = Object.assign(this.model, values);
console.log("表单提交数据",formData)
httpAction(httpurl,formData,method).then((res)=>{
if(res.success){
that.$message.success(res.message);
that.$emit('ok');
}else{
that.$message.warning(res.message);
}
}).finally(() => {
that.confirmLoading = false;
that.close();
})
}
})
},
handleCancel () {
this.close()
},
popupCallback(row){
this.form.setFieldsValue(pick(row<#list columns as po><#if po.fieldName !='id'>,'${po.fieldName}'</#if></#list>))
}
}
}
</script>
<style lang="less" scoped>
/** Button按钮间距 */
.ant-btn {
margin-left: 30px;
margin-bottom: 30px;
float: right;
}
</style>

View File

@ -0,0 +1,273 @@
package ${bussiPackage}.${entityPackage}.controller;
import java.io.UnsupportedEncodingException;
import java.io.IOException;
import java.net.URLDecoder;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.jeecgframework.poi.excel.ExcelImportUtil;
import org.jeecgframework.poi.excel.def.NormalExcelConstants;
import org.jeecgframework.poi.excel.entity.ExportParams;
import org.jeecgframework.poi.excel.entity.ImportParams;
import org.jeecgframework.poi.excel.view.JeecgEntityExcelView;
import org.jeecg.common.api.vo.Result;
import org.jeecg.common.system.query.QueryGenerator;
import org.jeecg.common.util.oConvertUtils;
<#list subTables as sub>
import ${bussiPackage}.${entityPackage}.entity.${sub.entityName};
</#list>
import ${bussiPackage}.${entityPackage}.entity.${entityName};
import ${bussiPackage}.${entityPackage}.vo.${entityName}Page;
import ${bussiPackage}.${entityPackage}.service.I${entityName}Service;
<#list subTables as sub>
import ${bussiPackage}.${entityPackage}.service.I${sub.entityName}Service;
</#list>
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.extern.slf4j.Slf4j;
import com.alibaba.fastjson.JSON;
/**
* @Description: ${tableVo.ftlDescription}
* @Author: jeecg-boot
* @Date: ${.now?string["yyyy-MM-dd"]}
* @Version: V1.0
*/
@RestController
@RequestMapping("/${entityPackage}/${entityName?uncap_first}")
@Slf4j
public class ${entityName}Controller {
@Autowired
private I${entityName}Service ${entityName?uncap_first}Service;
<#list subTables as sub>
@Autowired
private I${sub.entityName}Service ${sub.entityName?uncap_first}Service;
</#list>
/**
* 分页列表查询
* @param ${entityName?uncap_first}
* @param pageNo
* @param pageSize
* @param req
* @return
*/
@GetMapping(value = "/list")
public Result<IPage<${entityName}>> queryPageList(${entityName} ${entityName?uncap_first},
@RequestParam(name="pageNo", defaultValue="1") Integer pageNo,
@RequestParam(name="pageSize", defaultValue="10") Integer pageSize,
HttpServletRequest req) {
Result<IPage<${entityName}>> result = new Result<IPage<${entityName}>>();
QueryWrapper<${entityName}> queryWrapper = QueryGenerator.initQueryWrapper(${entityName?uncap_first}, req.getParameterMap());
Page<${entityName}> page = new Page<${entityName}>(pageNo, pageSize);
IPage<${entityName}> pageList = ${entityName?uncap_first}Service.page(page, queryWrapper);
result.setSuccess(true);
result.setResult(pageList);
return result;
}
/**
* 添加
* @param ${entityName?uncap_first}Page
* @return
*/
@PostMapping(value = "/add")
public Result<${entityName}> add(@RequestBody ${entityName}Page ${entityName?uncap_first}Page) {
Result<${entityName}> result = new Result<${entityName}>();
try {
${entityName} ${entityName?uncap_first} = new ${entityName}();
BeanUtils.copyProperties(${entityName?uncap_first}Page, ${entityName?uncap_first});
${entityName?uncap_first}Service.saveMain(${entityName?uncap_first}, <#list subTables as sub>${entityName?uncap_first}Page.get${sub.entityName}List()<#if sub_has_next>,</#if></#list>);
result.success("添加成功!");
} catch (Exception e) {
log.error(e.getMessage(),e);
result.error500("操作失败");
}
return result;
}
/**
* 编辑
* @param ${entityName?uncap_first}Page
* @return
*/
@PutMapping(value = "/edit")
public Result<${entityName}> edit(@RequestBody ${entityName}Page ${entityName?uncap_first}Page) {
Result<${entityName}> result = new Result<${entityName}>();
${entityName} ${entityName?uncap_first} = new ${entityName}();
BeanUtils.copyProperties(${entityName?uncap_first}Page, ${entityName?uncap_first});
${entityName} ${entityName?uncap_first}Entity = ${entityName?uncap_first}Service.getById(${entityName?uncap_first}.getId());
if(${entityName?uncap_first}Entity==null) {
result.error500("未找到对应实体");
}else {
boolean ok = ${entityName?uncap_first}Service.updateById(${entityName?uncap_first});
${entityName?uncap_first}Service.updateMain(${entityName?uncap_first}, <#list subTables as sub>${entityName?uncap_first}Page.get${sub.entityName}List()<#if sub_has_next>,</#if></#list>);
result.success("修改成功!");
}
return result;
}
/**
* 通过id删除
* @param id
* @return
*/
@DeleteMapping(value = "/delete")
public Result<?> delete(@RequestParam(name="id",required=true) String id) {
try {
${entityName?uncap_first}Service.delMain(id);
} catch (Exception e) {
log.error("删除失败",e.getMessage());
return Result.error("删除失败!");
}
return Result.ok("删除成功!");
}
/**
* 批量删除
* @param ids
* @return
*/
@DeleteMapping(value = "/deleteBatch")
public Result<${entityName}> deleteBatch(@RequestParam(name="ids",required=true) String ids) {
Result<${entityName}> result = new Result<${entityName}>();
if(ids==null || "".equals(ids.trim())) {
result.error500("参数不识别!");
}else {
this.${entityName?uncap_first}Service.delBatchMain(Arrays.asList(ids.split(",")));
result.success("删除成功!");
}
return result;
}
/**
* 通过id查询
* @param id
* @return
*/
@GetMapping(value = "/queryById")
public Result<${entityName}> queryById(@RequestParam(name="id",required=true) String id) {
Result<${entityName}> result = new Result<${entityName}>();
${entityName} ${entityName?uncap_first} = ${entityName?uncap_first}Service.getById(id);
if(${entityName?uncap_first}==null) {
result.error500("未找到对应实体");
}else {
result.setResult(${entityName?uncap_first});
result.setSuccess(true);
}
return result;
}
<#list subTables as sub>
/**
* 通过id查询
* @param id
* @return
*/
@GetMapping(value = "/query${sub.entityName}ByMainId")
public Result<List<${sub.entityName}>> query${sub.entityName}ListByMainId(@RequestParam(name="id",required=true) String id) {
Result<List<${sub.entityName}>> result = new Result<List<${sub.entityName}>>();
List<${sub.entityName}> ${sub.entityName?uncap_first}List = ${sub.entityName?uncap_first}Service.selectByMainId(id);
result.setResult(${sub.entityName?uncap_first}List);
result.setSuccess(true);
return result;
}
</#list>
/**
* 导出excel
*
* @param request
* @param response
*/
@RequestMapping(value = "/exportXls")
public ModelAndView exportXls(HttpServletRequest request, ${entityName} ${entityName?uncap_first}) {
// Step.1 组装查询条件查询数据
QueryWrapper<${entityName}> queryWrapper = QueryGenerator.initQueryWrapper(${entityName?uncap_first}, request.getParameterMap());
List<${entityName}> queryList = ${entityName?uncap_first}Service.list(queryWrapper);
// 过滤选中数据
String selections = request.getParameter("selections");
List<${entityName}> ${entityName?uncap_first}List = new ArrayList<${entityName}>();
if(oConvertUtils.isEmpty(selections)) {
${entityName?uncap_first}List = queryList;
}else {
List<String> selectionList = Arrays.asList(selections.split(","));
${entityName?uncap_first}List = queryList.stream().filter(item -> selectionList.contains(item.getId())).collect(Collectors.toList());
}
// Step.2 组装pageList
List<${entityName}Page> pageList = new ArrayList<${entityName}Page>();
for (${entityName} main : ${entityName?uncap_first}List) {
${entityName}Page vo = new ${entityName}Page();
BeanUtils.copyProperties(main, vo);
<#list subTables as sub>
List<${sub.entityName}> ${sub.entityName?uncap_first}List = ${sub.entityName?uncap_first}Service.selectByMainId(main.getId());
vo.set${sub.entityName}List(${sub.entityName?uncap_first}List);
</#list>
pageList.add(vo);
}
// Step.3 AutoPoi 导出Excel
ModelAndView mv = new ModelAndView(new JeecgEntityExcelView());
mv.addObject(NormalExcelConstants.FILE_NAME, "${tableVo.ftlDescription}列表");
mv.addObject(NormalExcelConstants.CLASS, ${entityName}Page.class);
mv.addObject(NormalExcelConstants.PARAMS, new ExportParams("${tableVo.ftlDescription}列表数据", "导出人:Jeecg", "导出信息"));
mv.addObject(NormalExcelConstants.DATA_LIST, pageList);
return mv;
}
/**
* 通过excel导入数据
*
* @param request
* @param response
* @return
*/
@RequestMapping(value = "/importExcel", method = RequestMethod.POST)
public Result<?> importExcel(HttpServletRequest request, HttpServletResponse response) {
MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request;
Map<String, MultipartFile> fileMap = multipartRequest.getFileMap();
for (Map.Entry<String, MultipartFile> entity : fileMap.entrySet()) {
MultipartFile file = entity.getValue();// 获取上传文件对象
ImportParams params = new ImportParams();
params.setTitleRows(2);
params.setHeadRows(1);
params.setNeedSave(true);
try {
List<${entityName}Page> list = ExcelImportUtil.importExcel(file.getInputStream(), ${entityName}Page.class, params);
for (${entityName}Page page : list) {
${entityName} po = new ${entityName}();
BeanUtils.copyProperties(page, po);
${entityName?uncap_first}Service.saveMain(po, <#list subTables as sub>page.get${sub.entityName}List()<#if sub_has_next>,</#if></#list>);
}
return Result.ok("文件导入成功!数据行数:" + list.size());
} catch (Exception e) {
log.error(e.getMessage(),e);
return Result.error("文件导入失败:"+e.getMessage());
} finally {
try {
file.getInputStream().close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return Result.ok("文件导入失败!");
}
}

View File

@ -0,0 +1,41 @@
package ${bussiPackage}.${entityPackage}.entity;
import java.io.Serializable;
import java.util.Date;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import com.fasterxml.jackson.annotation.JsonFormat;
import org.springframework.format.annotation.DateTimeFormat;
/**
* @Description: ${tableVo.ftlDescription}
* @Author: jeecg-boot
* @Date: ${.now?string["yyyy-MM-dd"]}
* @Version: V1.0
*/
@Data
@TableName("${tableName}")
public class ${entityName} implements Serializable {
private static final long serialVersionUID = 1L;
<#list originalColumns as po>
/**${po.filedComment}*/
<#if po.fieldName == primaryKeyField>
@TableId(type = IdType.UUID)
<#else>
<#if po.fieldDbType =='Date'>
<#if po.classType=='date'>
@JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd")
@DateTimeFormat(pattern="yyyy-MM-dd")
<#else>
@JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd HH:mm:ss")
@DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss")
</#if>
<#else>
</#if>
</#if>
private <#if po.fieldType=='java.sql.Blob'>byte[]<#else>${po.fieldType}</#if> ${po.fieldName};
</#list>
}

View File

@ -0,0 +1,48 @@
<#list subTables as subTab>
#segment#${subTab.entityName}.java
package ${bussiPackage}.${entityPackage}.entity;
import java.io.Serializable;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import com.fasterxml.jackson.annotation.JsonFormat;
import org.springframework.format.annotation.DateTimeFormat;
import org.jeecgframework.poi.excel.annotation.Excel;
import java.util.Date;
/**
* @Description: ${subTab.ftlDescription}
* @Author: jeecg-boot
* @Date: ${.now?string["yyyy-MM-dd"]}
* @Version: V1.0
*/
@Data
@TableName("${subTab.tableName}")
public class ${subTab.entityName} implements Serializable {
private static final long serialVersionUID = 1L;
<#list subTab.originalColumns as po>
/**${po.filedComment}*/
<#if po.fieldName == primaryKeyField>
@TableId(type = IdType.UUID)
<#else>
<#if po.fieldDbType =='Date'>
<#if po.classType=='date'>
@Excel(name = "${po.filedComment}", width = 15, format = "yyyy-MM-dd")
@JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd")
@DateTimeFormat(pattern="yyyy-MM-dd")
<#else>
@Excel(name = "${po.filedComment}", width = 20, format = "yyyy-MM-dd HH:mm:ss")
@JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd HH:mm:ss")
@DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss")
</#if>
<#elseif !subTab.foreignKeys?seq_contains(po.fieldName?cap_first)>
@Excel(name = "${po.filedComment}", width = 15)
</#if>
</#if>
private <#if po.fieldType=='java.sql.Blob'>byte[]<#else>${po.fieldType}</#if> ${po.fieldName};
</#list>
}
</#list>

View File

@ -0,0 +1,17 @@
package ${bussiPackage}.${entityPackage}.mapper;
import java.util.List;
import org.apache.ibatis.annotations.Param;
import ${bussiPackage}.${entityPackage}.entity.${entityName};
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
/**
* @Description: ${tableVo.ftlDescription}
* @Author: jeecg-boot
* @Date: ${.now?string["yyyy-MM-dd"]}
* @Version: V1.0
*/
public interface ${entityName}Mapper extends BaseMapper<${entityName}> {
}

View File

@ -0,0 +1,22 @@
<#list subTables as subTab>
#segment#${subTab.entityName}Mapper.java
package ${bussiPackage}.${entityPackage}.mapper;
import java.util.List;
import ${bussiPackage}.${entityPackage}.entity.${subTab.entityName};
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Param;
/**
* @Description: ${subTab.ftlDescription}
* @Author: jeecg-boot
* @Date: ${.now?string["yyyy-MM-dd"]}
* @Version: V1.0
*/
public interface ${subTab.entityName}Mapper extends BaseMapper<${subTab.entityName}> {
public boolean deleteByMainId(@Param("mainId") String mainId);
public List<${subTab.entityName}> selectByMainId(@Param("mainId") String mainId);
}
</#list>

View File

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="${bussiPackage}.${entityPackage}.mapper.${entityName}Mapper">
</mapper>

View File

@ -0,0 +1,26 @@
<#list subTables as subTab>
<#assign originalForeignKeys = subTab.originalForeignKeys>
#segment#${subTab.entityName}Mapper.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="${bussiPackage}.${entityPackage}.mapper.${subTab.entityName}Mapper">
<delete id="deleteByMainId" parameterType="java.lang.String">
DELETE
FROM ${subTab.tableName}
WHERE
<#list originalForeignKeys as key>
${key} = ${r'#'}{mainId} <#rt/>
</#list>
</delete>
<select id="selectByMainId" parameterType="java.lang.String" resultType="${bussiPackage}.${entityPackage}.entity.${subTab.entityName}">
SELECT *
FROM ${subTab.tableName}
WHERE
<#list originalForeignKeys as key>
${key} = ${r'#'}{mainId} <#rt/>
</#list>
</select>
</mapper>
</#list>

View File

@ -0,0 +1,42 @@
package ${bussiPackage}.${entityPackage}.service;
<#list subTables as sub>
import ${bussiPackage}.${entityPackage}.entity.${sub.entityName};
</#list>
import ${bussiPackage}.${entityPackage}.entity.${entityName};
import com.baomidou.mybatisplus.extension.service.IService;
import java.io.Serializable;
import java.util.Collection;
import java.util.List;
/**
* @Description: ${tableVo.ftlDescription}
* @Author: jeecg-boot
* @Date: ${.now?string["yyyy-MM-dd"]}
* @Version: V1.0
*/
public interface I${entityName}Service extends IService<${entityName}> {
/**
* 添加一对多
*
*/
public void saveMain(${entityName} ${entityName?uncap_first},<#list subTables as sub>List<${sub.entityName}> ${sub.entityName?uncap_first}List<#if sub_has_next>,</#if></#list>) ;
/**
* 修改一对多
*
*/
public void updateMain(${entityName} ${entityName?uncap_first},<#list subTables as sub>List<${sub.entityName}> ${sub.entityName?uncap_first}List<#if sub_has_next>,</#if></#list>);
/**
* 删除一对多
*/
public void delMain (String id);
/**
* 批量删除一对多
*/
public void delBatchMain (Collection<? extends Serializable> idList);
}

View File

@ -0,0 +1,19 @@
<#list subTables as subTab>
#segment#I${subTab.entityName}Service.java
package ${bussiPackage}.${entityPackage}.service;
import ${bussiPackage}.${entityPackage}.entity.${subTab.entityName};
import com.baomidou.mybatisplus.extension.service.IService;
import java.util.List;
/**
* @Description: ${subTab.ftlDescription}
* @Author: jeecg-boot
* @Date: ${.now?string["yyyy-MM-dd"]}
* @Version: V1.0
*/
public interface I${subTab.entityName}Service extends IService<${subTab.entityName}> {
public List<${subTab.entityName}> selectByMainId(String mainId);
}
</#list>

View File

@ -0,0 +1,105 @@
package ${bussiPackage}.${entityPackage}.service.impl;
import ${bussiPackage}.${entityPackage}.entity.${entityName};
<#list subTables as sub>
import ${bussiPackage}.${entityPackage}.entity.${sub.entityName};
</#list>
<#list subTables as sub>
import ${bussiPackage}.${entityPackage}.mapper.${sub.entityName}Mapper;
</#list>
import ${bussiPackage}.${entityPackage}.mapper.${entityName}Mapper;
import ${bussiPackage}.${entityPackage}.service.I${entityName}Service;
import org.springframework.stereotype.Service;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import java.io.Serializable;
import java.util.List;
import java.util.Collection;
/**
* @Description: ${tableVo.ftlDescription}
* @Author: jeecg-boot
* @Date: ${.now?string["yyyy-MM-dd"]}
* @Version: V1.0
*/
@Service
public class ${entityName}ServiceImpl extends ServiceImpl<${entityName}Mapper, ${entityName}> implements I${entityName}Service {
@Autowired
private ${entityName}Mapper ${entityName?uncap_first}Mapper;
<#list subTables as sub>
@Autowired
private ${sub.entityName}Mapper ${sub.entityName?uncap_first}Mapper;
</#list>
@Override
@Transactional
public void saveMain(${entityName} ${entityName?uncap_first}, <#list subTables as sub>List<${sub.entityName}> ${sub.entityName?uncap_first}List<#if sub_has_next>,</#if></#list>) {
${entityName?uncap_first}Mapper.insert(${entityName?uncap_first});
<#list subTables as sub>
if(${sub.entityName?uncap_first}List!=null && ${sub.entityName?uncap_first}List.size()>0) {
for(${sub.entityName} entity:${sub.entityName?uncap_first}List) {
<#list sub.foreignKeys as key>
//外键设置
<#if key?lower_case?index_of("${primaryKeyField}")!=-1>
entity.set${key?cap_first}(${entityName?uncap_first}.get${primaryKeyField?cap_first}());
<#else>
entity.set${key?cap_first}(${entityName?uncap_first}.get${key}());
</#if>
</#list>
${sub.entityName?uncap_first}Mapper.insert(entity);
}
}
</#list>
}
@Override
@Transactional
public void updateMain(${entityName} ${entityName?uncap_first},<#list subTables as sub>List<${sub.entityName}> ${sub.entityName?uncap_first}List<#if sub_has_next>,</#if></#list>) {
${entityName?uncap_first}Mapper.updateById(${entityName?uncap_first});
//1.先删除子表数据
<#list subTables as sub>
${sub.entityName?uncap_first}Mapper.deleteByMainId(${entityName?uncap_first}.getId());
</#list>
//2.子表数据重新插入
<#list subTables as sub>
if(${sub.entityName?uncap_first}List!=null && ${sub.entityName?uncap_first}List.size()>0) {
for(${sub.entityName} entity:${sub.entityName?uncap_first}List) {
<#list sub.foreignKeys as key>
//外键设置
<#if key?lower_case?index_of("${primaryKeyField}")!=-1>
entity.set${key?cap_first}(${entityName?uncap_first}.get${primaryKeyField?cap_first}());
<#else>
entity.set${key?cap_first}(${entityName?uncap_first}.get${key}());
</#if>
</#list>
${sub.entityName?uncap_first}Mapper.insert(entity);
}
}
</#list>
}
@Override
@Transactional
public void delMain(String id) {
<#list subTables as sub>
${sub.entityName?uncap_first}Mapper.deleteByMainId(id);
</#list>
${entityName?uncap_first}Mapper.deleteById(id);
}
@Override
@Transactional
public void delBatchMain(Collection<? extends Serializable> idList) {
for(Serializable id:idList) {
<#list subTables as sub>
${sub.entityName?uncap_first}Mapper.deleteByMainId(id.toString());
</#list>
${entityName?uncap_first}Mapper.deleteById(id);
}
}
}

View File

@ -0,0 +1,30 @@
<#list subTables as subTab>
#segment#${subTab.entityName}ServiceImpl.java
package ${bussiPackage}.${entityPackage}.service.impl;
import ${bussiPackage}.${entityPackage}.entity.${subTab.entityName};
import ${bussiPackage}.${entityPackage}.mapper.${subTab.entityName}Mapper;
import ${bussiPackage}.${entityPackage}.service.I${subTab.entityName}Service;
import org.springframework.stereotype.Service;
import java.util.List;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
/**
* @Description: ${subTab.ftlDescription}
* @Author: jeecg-boot
* @Date: ${.now?string["yyyy-MM-dd"]}
* @Version: V1.0
*/
@Service
public class ${subTab.entityName}ServiceImpl extends ServiceImpl<${subTab.entityName}Mapper, ${subTab.entityName}> implements I${subTab.entityName}Service {
@Autowired
private ${subTab.entityName}Mapper ${subTab.entityName?uncap_first}Mapper;
@Override
public List<${subTab.entityName}> selectByMainId(String mainId) {
return ${subTab.entityName?uncap_first}Mapper.selectByMainId(mainId);
}
}
</#list>

View File

@ -0,0 +1,51 @@
package ${bussiPackage}.${entityPackage}.vo;
import java.util.List;
import ${bussiPackage}.${entityPackage}.entity.${entityName};
<#list subTables as sub>
import ${bussiPackage}.${entityPackage}.entity.${sub.entityName};
</#list>
import lombok.Data;
import org.jeecgframework.poi.excel.annotation.Excel;
import org.jeecgframework.poi.excel.annotation.ExcelEntity;
import org.jeecgframework.poi.excel.annotation.ExcelCollection;
import com.fasterxml.jackson.annotation.JsonFormat;
import org.springframework.format.annotation.DateTimeFormat;
import java.util.Date;
/**
* @Description: ${tableVo.ftlDescription}
* @Author: jeecg-boot
* @Date: ${.now?string["yyyy-MM-dd"]}
* @Version: V1.0
*/
@Data
public class ${entityName}Page {
<#list originalColumns as po>
/**${po.filedComment}*/
<#if po.fieldName == primaryKeyField>
<#else>
<#if po.fieldDbType =='Date'>
<#if po.classType=='date'>
@Excel(name = "${po.filedComment}", width = 15, format = "yyyy-MM-dd")
@JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd")
@DateTimeFormat(pattern="yyyy-MM-dd")
<#else>
@Excel(name = "${po.filedComment}", width = 20, format = "yyyy-MM-dd HH:mm:ss")
@JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd HH:mm:ss")
@DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss")
</#if>
<#else>
@Excel(name = "${po.filedComment}", width = 15)
</#if>
</#if>
private <#if po.fieldType=='java.sql.Blob'>byte[]<#else>${po.fieldType}</#if> ${po.fieldName};
</#list>
<#list subTables as sub>
@ExcelCollection(name="${sub.ftlDescription}")
private List<${sub.entityName}> ${sub.entityName?uncap_first}List;
</#list>
}

View File

@ -0,0 +1,297 @@
<template>
<a-card :bordered="false">
<!-- 查询区域 -->
<div class="table-page-search-wrapper">
<a-form layout="inline">
<a-row :gutter="24">
<#assign query_field_no=0>
<#assign query_field_select=false>
<#assign query_field_date=false>
<#assign list_need_dict=false>
<#assign query_flag=false>
<#-- 开始循环 -->
<#list columns as po>
<#if po.isQuery=='Y'>
<#assign query_flag=true>
<#if query_field_no==2>
<template v-if="toggleSearchStatus">
</#if>
<#if po.queryMode=='single'>
<#if query_field_no gt 1> </#if><a-col :md="6" :sm="8">
<#if query_field_no gt 1> </#if><a-form-item label="${po.filedComment}">
<#if po.classType=='date'>
<#assign query_field_date=true>
<#if query_field_no gt 1> </#if><j-date placeholder="请选择${po.filedComment}" v-model="queryParam.${po.fieldName}"></j-date>
<#elseif po.classType=='datetime'>
<#assign query_field_date=true>
<#if query_field_no gt 1> </#if><j-date :show-time="true" date-format="YYYY-MM-DD HH:mm:ss" placeholder="请选择${po.filedComment}" v-model="queryParam.${po.fieldName}"></j-date>
<#elseif po.classType=='list' || po.classType=='radio' || po.classType=='checkbox'>
<#assign query_field_select=true>
<#-- ---------------------------下拉或是单选 判断数据字典是表字典还是普通字典------------------------------- -->
<#if po.dictTable?default("")?trim?length gt 1>
<#if query_field_no gt 1> </#if><j-dict-select-tag placeholder="请选择${po.filedComment}" v-model="queryParam.${po.fieldName}" dictCode="${po.dictTable},${po.dictText},${po.dictField}"/>
<#elseif po.dictField?default("")?trim?length gt 1>
<#if query_field_no gt 1> </#if><j-dict-select-tag placeholder="请选择${po.filedComment}" v-model="queryParam.${po.fieldName}" dictCode="${po.dictField}"/>
<#else>
<#if query_field_no gt 1> </#if><a-input placeholder="请输入${po.filedComment}" v-model="queryParam.${po.fieldName}"></a-input>
</#if>
<#else>
<#if query_field_no gt 1> </#if><a-input placeholder="请输入${po.filedComment}" v-model="queryParam.${po.fieldName}"></a-input>
</#if>
<#if query_field_no gt 1> </#if></a-form-item>
<#if query_field_no gt 1> </#if></a-col>
<#else>
<#if query_field_no gt 1> </#if><a-col :md="12" :sm="16">
<#if query_field_no gt 1> </#if><a-form-item label="${po.filedComment}">
<#if po.classType=='date'>
<#assign query_field_date=true>
<#if query_field_no gt 1> </#if><j-date placeholder="请选择开始日期" class="query-group-cust" v-model="queryParam.${po.fieldName}_begin"></j-date>
<#if query_field_no gt 1> </#if><span class="query-group-split-cust"></span>
<#if query_field_no gt 1> </#if><j-date placeholder="请选择结束日期" class="query-group-cust" v-model="queryParam.${po.fieldName}_end"></j-date>
<#elseif po.classType=='datetime'>
<#assign query_field_date=true>
<#if query_field_no gt 1> </#if><j-date :show-time="true" date-format="YYYY-MM-DD HH:mm:ss" placeholder="请选择开始时间" class="query-group-cust" v-model="queryParam.${po.fieldName}_begin"></j-date>
<#if query_field_no gt 1> </#if><span class="query-group-split-cust"></span>
<#if query_field_no gt 1> </#if><j-date :show-time="true" date-format="YYYY-MM-DD HH:mm:ss" placeholder="请选择结束时间" class="query-group-cust" v-model="queryParam.${po.fieldName}_end"></j-date>
<#else>
<#if query_field_no gt 1> </#if><a-input placeholder="请输入最小值" class="query-group-cust" v-model="queryParam.${po.fieldName}_begin"></a-input>
<#if query_field_no gt 1> </#if><span class="query-group-split-cust"></span>
<#if query_field_no gt 1> </#if><a-input placeholder="请输入最大值" class="query-group-cust" v-model="queryParam.${po.fieldName}_end"></a-input>
</#if>
<#if query_field_no gt 1> </#if></a-form-item>
<#if query_field_no gt 1> </#if></a-col>
</#if>
<#assign query_field_no=query_field_no+1>
</#if>
<#if !list_need_dict && po.fieldShowType!='popup' && po.dictField?default("")?trim?length gt 1>
<#assign list_need_dict=true>
</#if>
</#list>
<#t>
<#if query_field_no gt 2>
</template>
</#if>
<#if query_flag>
<a-col :md="6" :sm="8">
<span style="float: left;overflow: hidden;" class="table-page-search-submitButtons">
<a-button type="primary" @click="searchQuery" icon="search">查询</a-button>
<a-button type="primary" @click="searchReset" icon="reload" style="margin-left: 8px">重置</a-button>
<a @click="handleToggleSearch" style="margin-left: 8px">
{{ toggleSearchStatus ? '收起' : '展开' }}
<a-icon :type="toggleSearchStatus ? 'up' : 'down'"/>
</a>
</span>
</a-col>
</#if>
</a-row>
</a-form>
</div>
<!-- 查询区域-END -->
<!-- 操作按钮区域 -->
<div class="table-operator">
<a-button @click="handleAdd" type="primary" icon="plus">新增</a-button>
<a-button type="primary" icon="download" @click="handleExportXls('${tableVo.ftlDescription}')">导出</a-button>
<a-upload name="file" :showUploadList="false" :multiple="false" :action="importExcelUrl" @change="handleImportExcel">
<a-button type="primary" icon="import">导入</a-button>
</a-upload>
<a-dropdown v-if="selectedRowKeys.length > 0">
<a-menu slot="overlay">
<a-menu-item key="1" @click="batchDel"><a-icon type="delete"/>删除</a-menu-item>
</a-menu>
<a-button style="margin-left: 8px"> 批量操作 <a-icon type="down" /></a-button>
</a-dropdown>
</div>
<!-- table区域-begin -->
<div>
<div class="ant-alert ant-alert-info" style="margin-bottom: 16px;">
<i class="anticon anticon-info-circle ant-alert-icon"></i> 已选择 <a style="font-weight: 600">{{ selectedRowKeys.length }}</a>项
<a style="margin-left: 24px" @click="onClearSelected">清空</a>
</div>
<a-table
ref="table"
size="middle"
bordered
rowKey="id"
:columns="columns"
:dataSource="dataSource"
:pagination="ipagination"
:loading="loading"
:rowSelection="{selectedRowKeys: selectedRowKeys, onChange: onSelectChange}"
@change="handleTableChange">
<template slot="imgSlot" slot-scope="text">
<span v-if="!text" style="font-size: 12px;font-style: italic;">无此图片</span>
<img v-else :src="getImgView(text)" height="25px" alt="图片不存在" style="max-width:80px;font-size: 12px;font-style: italic;"/>
</template>
<template slot="fileSlot" slot-scope="text">
<span v-if="!text" style="font-size: 12px;font-style: italic;">无此文件</span>
<a-button
v-else
:ghost="true"
type="primary"
icon="download"
size="small"
@click="uploadFile(text)">
下载
</a-button>
</template>
<span slot="action" slot-scope="text, record">
<a @click="handleEdit(record)">编辑</a>
<a-divider type="vertical" />
<a-dropdown>
<a class="ant-dropdown-link">更多 <a-icon type="down" /></a>
<a-menu slot="overlay">
<a-menu-item>
<a-popconfirm title="确定删除吗?" @confirm="() => handleDelete(record.id)">
<a>删除</a>
</a-popconfirm>
</a-menu-item>
</a-menu>
</a-dropdown>
</span>
</a-table>
</div>
<${entityName?uncap_first}-modal ref="modalForm" @ok="modalFormOk"></${entityName?uncap_first}-modal>
</a-card>
</template>
<script>
import { JeecgListMixin } from '@/mixins/JeecgListMixin'
import ${entityName}Modal from './modules/${entityName}Modal'
<#if query_field_select>
import JDictSelectTag from '@/components/dict/JDictSelectTag.vue'
</#if>
<#if query_field_date>
import JDate from '@/components/jeecg/JDate.vue'
</#if>
<#if list_need_dict>
import {initDictOptions, filterMultiDictText} from '@/components/dict/JDictSelectUtil'
</#if>
export default {
name: "${entityName}List",
mixins:[JeecgListMixin],
components: {
<#if query_field_select>
JDictSelectTag,
</#if>
<#if query_field_date>
JDate,
</#if>
${entityName}Modal
},
data () {
return {
description: '${tableVo.ftlDescription}管理页面',
// 表头
columns: [
{
title: '#',
dataIndex: '',
key:'rowIndex',
width:60,
align:"center",
customRender:function (t,r,index) {
return parseInt(index)+1;
}
},
<#list columns as po>
{
title:'${po.filedComment}',
align:"center",
<#if po.classType=='date'>
dataIndex: '${po.fieldName}',
customRender:function (text) {
return !text?"":(text.length>10?text.substr(0,10):text)
}
<#elseif po.classType=='file'>
dataIndex: '${po.fieldName}',
scopedSlots: {customRender: 'fileSlot'}
<#elseif po.classType=='image'>
dataIndex: '${po.fieldName}',
scopedSlots: {customRender: 'imgSlot'}
<#elseif po.classType=='list_multi' || po.classType=='list' || po.classType=='radio' || po.classType=='checkbox' || po.classType=='sel_depart'>
dataIndex: '${po.fieldName}',
customRender:(text)=>{
if(!text){
return ''
}else{
return filterMultiDictText(this.dictOptions['${po.fieldName}'], text+"")
}
}
<#else>
dataIndex: '${po.fieldName}'
</#if>
},
</#list>
{
title: '操作',
dataIndex: 'action',
align:"center",
scopedSlots: { customRender: 'action' },
}
],
url: {
list: "/${entityPackage}/${entityName?uncap_first}/list",
delete: "/${entityPackage}/${entityName?uncap_first}/delete",
deleteBatch: "/${entityPackage}/${entityName?uncap_first}/deleteBatch",
exportXlsUrl: "/${entityPackage}/${entityName?uncap_first}/exportXls",
importExcelUrl: "${entityPackage}/${entityName?uncap_first}/importExcel",
},
dictOptions:{
<#list columns as po>
<#if (po.isQuery=='Y' || po.isShowList=='Y')>
<#if po.classType='sel_depart' || po.classType=='list_multi' || po.classType=='list' || po.classType=='radio' || po.classType=='checkbox'>
${po.fieldName}:[],
</#if>
</#if>
</#list>
}
}
},
computed: {
importExcelUrl: function(){
<#noparse>return `${window._CONFIG['domianURL']}/${this.url.importExcelUrl}`;</#noparse>
}
},
methods: {
initDictConfig(){
<#list columns as po>
<#if (po.isQuery=='Y' || po.isShowList=='Y') && po.classType!='popup'>
<#if po.classType='sel_depart'>
initDictOptions('sys_depart,depart_name,id').then((res) => {
if (res.success) {
this.$set(this.dictOptions, '${po.fieldName}', res.result)
}
})
<#elseif po.classType=='list_multi' || po.classType=='list' || po.classType=='radio' || po.classType=='checkbox'>
<#assign list_field_dictCode="">
<#if po.dictTable?default("")?trim?length gt 1>
<#assign list_field_dictCode="${po.dictTable},${po.dictText},${po.dictField}">
<#elseif po.dictField?default("")?trim?length gt 1>
<#assign list_field_dictCode="${po.dictField}">
</#if>
initDictOptions('${list_field_dictCode}').then((res) => {
if (res.success) {
this.$set(this.dictOptions, '${po.fieldName}', res.result)
}
})
</#if>
</#if>
</#list>
}
}
}
</script>
<style scoped>
@import '~@assets/less/common.less'
</style>

View File

@ -0,0 +1,297 @@
<template>
<a-modal
:title="title"
:width="1200"
:visible="visible"
:maskClosable="false"
:confirmLoading="confirmLoading"
@ok="handleOk"
@cancel="handleCancel">
<a-spin :spinning="confirmLoading">
<!-- 主表单区域 -->
<a-form :form="form">
<a-row>
<#assign form_date = false>
<#assign form_select = false>
<#assign form_select_multi = false>
<#assign form_popup = false>
<#assign form_sel_depart = false>
<#assign form_sel_user = false>
<#assign form_file = false>
<#list columns as po>
<#assign form_field_dictCode="">
<#if po.dictTable?default("")?trim?length gt 1>
<#assign form_field_dictCode="${po.dictTable},${po.dictText},${po.dictField}">
<#elseif po.dictField?default("")?trim?length gt 1>
<#assign form_field_dictCode="${po.dictField}">
</#if>
<#if po.classType =='textarea'>
<a-col :span="24">
<a-form-item label="${po.filedComment}" :labelCol="labelCol2" :wrapperCol="wrapperCol2">
<#else>
<a-col :span="12">
<a-form-item label="${po.filedComment}" :labelCol="labelCol" :wrapperCol="wrapperCol">
</#if>
<#if po.classType =='date'>
<#assign form_date=true>
<j-date placeholder="请选择${po.filedComment}" v-decorator="[ '${po.fieldName}', validatorRules.${po.fieldName}]" :trigger-change="true" style="width: 100%"/>
<#elseif po.classType =='datetime'>
<#assign form_date=true>
<j-date placeholder="请选择${po.filedComment}" v-decorator="[ '${po.fieldName}', validatorRules.${po.fieldName}]" :trigger-change="true" :show-time="true" date-format="YYYY-MM-DD HH:mm:ss" style="width: 100%"/>
<#elseif po.classType =='popup'>
<#assign form_popup=true>
<j-popup
v-decorator="['${po.fieldName}']"
:trigger-change="true"
org-fields="${po.dictField}"
dest-fields="${po.dictText}"
code="${po.dictTable}"
@callback="popupCallback"/>
<#elseif po.classType =='sel_depart'>
<#assign form_sel_depart=true>
<j-select-depart v-decorator="['${po.fieldName}']" :trigger-change="true"/>
<#elseif po.classType =='sel_user'>
<#assign form_sel_user = true>
<j-select-user-by-dep v-decorator="['${po.fieldName}']" :trigger-change="true"/>
<#elseif po.classType =='textarea'>
<a-textarea v-decorator="['${po.fieldName}']" rows="4" placeholder="请输入${po.filedComment}"/>
<#elseif po.classType=='list' || po.classType=='radio'>
<#assign form_select = true>
<j-dict-select-tag type="${po.classType}" v-decorator="['${po.fieldName}']" :trigger-change="true" dictCode="${form_field_dictCode}" placeholder="请选择${po.filedComment}"/>
<#elseif po.classType=='list_multi' || po.classType=='checkbox'>
<#assign form_select_multi = true>
<j-multi-select-tag type="${po.classType}" v-decorator="['${po.fieldName}']" :trigger-change="true" dictCode="${form_field_dictCode}" placeholder="请选择${po.filedComment}"/>
<#elseif po.fieldDbType=='int' || po.fieldDbType=='double' || po.fieldDbType=='BigDecimal'>
<a-input-number v-decorator="[ '${po.fieldName}', validatorRules.${po.fieldName}]" placeholder="请输入${po.filedComment}" style="width: 100%"/>
<#elseif po.classType=='file' || po.classType=='image'>
<#assign form_file = true>
<j-upload v-decorator="['${po.fieldName}']" :trigger-change="true"></j-upload>
<#else>
<a-input v-decorator="[ '${po.fieldName}', validatorRules.${po.fieldName}]" placeholder="请输入${po.filedComment}"></a-input>
</#if>
</a-form-item>
</a-col>
</#list>
</a-row>
</a-form>
<!-- 子表单区域 -->
<a-tabs v-model="activeKey" @change="handleChangeTabs">
<#list subTables as sub><#rt/>
<#if sub.foreignRelationType =='1'>
<a-tab-pane tab="${sub.ftlDescription}" :key="refKeys[${sub_index}]" :forceRender="true">
<${Format.humpToShortbar(sub.entityName)}-form ref="${sub.entityName?uncap_first}Form" @validateError="validateError"></${Format.humpToShortbar(sub.entityName)}-form>
</a-tab-pane>
<#else>
<a-tab-pane tab="${sub.ftlDescription}" :key="refKeys[${sub_index}]" :forceRender="true">
<j-editable-table
:ref="refKeys[${sub_index}]"
:loading="${sub.entityName?uncap_first}Table.loading"
:columns="${sub.entityName?uncap_first}Table.columns"
:dataSource="${sub.entityName?uncap_first}Table.dataSource"
:maxHeight="300"
:rowNumber="true"
:rowSelection="true"
:actionButton="true"/>
</a-tab-pane>
</#if>
</#list>
</a-tabs>
</a-spin>
</a-modal>
</template>
<script>
import pick from 'lodash.pick'
import { FormTypes,getRefPromise } from '@/utils/JEditableTableUtil'
import { JEditableTableMixin } from '@/mixins/JEditableTableMixin'
<#list subTables as sub>
<#if sub.foreignRelationType =='1'>
import ${sub.entityName}Form from './${sub.entityName}Form.vue'
</#if>
</#list>
<#if form_date>
import JDate from '@/components/jeecg/JDate'
</#if>
<#if form_file>
import JUpload from '@/components/jeecg/JUpload'
</#if>
<#if form_popup>
import JPopup from '@/components/jeecgbiz/JPopup'
</#if>
<#if form_sel_depart>
import JSelectDepart from '@/components/jeecgbiz/JSelectDepart'
</#if>
<#if form_sel_user>
import JSelectUserByDep from '@/components/jeecgbiz/JSelectUserByDep'
</#if>
<#if form_select>
import JDictSelectTag from "@/components/dict/JDictSelectTag"
</#if>
<#if form_select_multi>
import JMultiSelectTag from "@/components/dict/JMultiSelectTag"
</#if>
export default {
name: '${entityName}Modal',
mixins: [JEditableTableMixin],
components: {
<#list subTables as sub>
<#if sub.foreignRelationType =='1'>
${sub.entityName}Form,
</#if>
</#list>
<#if form_date>
JDate,
</#if>
<#if form_file>
JUpload,
</#if>
<#if form_popup>
JPopup,
</#if>
<#if form_sel_depart>
JSelectDepart,
</#if>
<#if form_sel_user>
JSelectUserByDep,
</#if>
<#if form_select>
JDictSelectTag,
</#if>
<#if form_select_multi>
JMultiSelectTag,
</#if>
},
data() {
return {
labelCol: {
span: 6
},
wrapperCol: {
span: 16
},
labelCol2: {
span: 3
},
wrapperCol2: {
span: 20
},
// 新增时子表默认添加几行空数据
addDefaultRowNum: 1,
validatorRules: {
<#list columns as po>
<#if po.fieldName !='id'>
<#if po.nullable =='N'>
${po.fieldName}: { rules: [{ required: true, message: '请输入${po.filedComment}!' }] },
<#else>
${po.fieldName}:{},
</#if>
</#if>
</#list>
},
refKeys: [<#list subTables as sub>'${sub.entityName?uncap_first}', </#list>],
tableKeys:[<#list subTables as sub><#if sub.foreignRelationType =='0'>'${sub.entityName?uncap_first}', </#if></#list>],
activeKey: '${subTables[0].entityName?uncap_first}',
<#list subTables as sub><#rt/>
// ${sub.ftlDescription}
${sub.entityName?uncap_first}Table: {
loading: false,
dataSource: [],
columns: [
<#list sub.colums as col><#rt/>
<#if sub.foreignRelationType =='0'>
<#if col.filedComment !='外键'>
{
title: '${col.filedComment}',
key: '${col.fieldName}',
<#if col.classType =='date'>
type: FormTypes.date,
<#elseif col.classType =='datetime'>
type: FormTypes.datetime,
<#elseif "int,decimal,double,"?contains(col.classType)>
type: FormTypes.inputNumber,
<#else>
type: FormTypes.input,
</#if>
defaultValue: '',
placeholder: '请输入${'$'}{title}',
<#if col.nullable =='N'>
validateRules: [{ required: true, message: '${'$'}{title}不能为空' }],
</#if>
},
</#if>
</#if>
</#list>
]
},
</#list>
url: {
add: "/${entityPackage}/${entityName?uncap_first}/add",
edit: "/${entityPackage}/${entityName?uncap_first}/edit",
<#list subTables as sub><#rt/>
${sub.entityName?uncap_first}: {
list: '/${entityPackage}/${entityName?uncap_first}/query${sub.entityName}ByMainId'
},
</#list>
}
}
},
methods: {
getAllTable() {
let values = this.tableKeys.map(key => getRefPromise(this, key))
return Promise.all(values)
},
/** 调用完edit()方法之后会自动调用此方法 */
editAfter() {
let fieldval = pick(this.model<#list columns as po><#if po.fieldName !='id'>,'${po.fieldName}'</#if></#list>)
this.$nextTick(() => {
this.form.setFieldsValue(fieldval)
<#list subTables as sub><#rt/>
<#if sub.foreignRelationType =='1'>
this.$refs.${sub.entityName?uncap_first}Form.initFormData(this.url.${sub.entityName?uncap_first}.list,this.model.id)
</#if>
</#list>
})
// 加载子表数据
if (this.model.id) {
let params = { id: this.model.id }
<#list subTables as sub><#rt/>
<#if sub.foreignRelationType =='0'>
this.requestSubTableData(this.url.${sub.entityName?uncap_first}.list, params, this.${sub.entityName?uncap_first}Table)
</#if>
</#list>
}
},
/** 整理成formData */
classifyIntoFormData(allValues) {
let main = Object.assign(this.model, allValues.formValue)
return {
...main, // 展开
<#list subTables as sub><#rt/>
<#if sub.foreignRelationType =='0'>
${sub.entityName?uncap_first}List: allValues.tablesValue[${sub_index}].values,
<#else>
${sub.entityName?uncap_first}List: this.$refs.${sub.entityName?uncap_first}Form.getFormData(),
</#if>
</#list>
}
},
validateError(msg){
this.$message.error(msg)
}
}
}
</script>
<style scoped>
</style>

View File

@ -0,0 +1,213 @@
<#list subTables as sub>
<#if sub.foreignRelationType=='1'>
#segment#${sub.entityName}Form.vue
<template>
<div>
<a-form :form="form">
<a-row>
<#assign form_date = false>
<#assign form_select = false>
<#assign form_select_multi = false>
<#assign form_popup = false>
<#assign form_sel_depart = false>
<#assign form_sel_user = false>
<#assign form_file = false>
<#list sub.colums as po>
<#assign form_field_dictCode="">
<#if po.dictTable?default("")?trim?length gt 1>
<#assign form_field_dictCode="${po.dictTable},${po.dictText},${po.dictField}">
<#elseif po.dictField?default("")?trim?length gt 1>
<#assign form_field_dictCode="${po.dictField}">
</#if>
<#if po.classType =='textarea'>
<a-col :span="24">
<a-form-item label="${po.filedComment}" :labelCol="labelCol2" :wrapperCol="wrapperCol2">
<#else>
<a-col :span="12">
<a-form-item label="${po.filedComment}" :labelCol="labelCol" :wrapperCol="wrapperCol">
</#if>
<#if po.classType =='date'>
<#assign form_date=true>
<j-date placeholder="请选择${po.filedComment}" v-decorator="[ '${po.fieldName}', validatorRules.${po.fieldName}]" :trigger-change="true" style="width: 100%"/>
<#elseif po.classType =='datetime'>
<#assign form_date=true>
<j-date placeholder="请选择${po.filedComment}" v-decorator="[ '${po.fieldName}', validatorRules.${po.fieldName}]" :trigger-change="true" :show-time="true" date-format="YYYY-MM-DD HH:mm:ss" style="width: 100%"/>
<#elseif po.classType =='popup'>
<#assign form_popup=true>
<j-popup
v-decorator="['${po.fieldName}']"
:trigger-change="true"
org-fields="${po.dictField}"
dest-fields="${po.dictText}"
code="${po.dictTable}"
@callback="popupCallback"/>
<#elseif po.classType =='sel_depart'>
<#assign form_sel_depart=true>
<j-select-depart v-decorator="['${po.fieldName}']" :trigger-change="true"/>
<#elseif po.classType =='sel_user'>
<#assign form_sel_user = true>
<j-select-user-by-dep v-decorator="['${po.fieldName}']" :trigger-change="true"/>
<#elseif po.classType =='textarea'>
<a-textarea v-decorator="['${po.fieldName}']" rows="4" placeholder="请输入${po.filedComment}"/>
<#elseif po.classType=='list' || po.classType=='radio'>
<#assign form_select = true>
<j-dict-select-tag type="${po.classType}" v-decorator="['${po.fieldName}']" :trigger-change="true" dictCode="${form_field_dictCode}" placeholder="请选择${po.filedComment}"/>
<#elseif po.classType=='list_multi' || po.classType=='checkbox'>
<#assign form_select_multi = true>
<j-multi-select-tag type="${po.classType}" v-decorator="['${po.fieldName}']" :trigger-change="true" dictCode="${form_field_dictCode}" placeholder="请选择${po.filedComment}"/>
<#elseif po.fieldDbType=='int' || po.fieldDbType=='double' || po.fieldDbType=='BigDecimal'>
<a-input-number v-decorator="[ '${po.fieldName}', validatorRules.${po.fieldName}]" placeholder="请输入${po.filedComment}" style="width: 100%"/>
<#elseif po.classType=='file' || po.classType=='image'>
<#assign form_file = true>
<j-upload v-decorator="['${po.fieldName}']" :trigger-change="true"></j-upload>
<#else>
<a-input v-decorator="[ '${po.fieldName}', validatorRules.${po.fieldName}]" placeholder="请输入${po.filedComment}"></a-input>
</#if>
</a-form-item>
</a-col>
</#list>
</a-row>
</a-form>
</div>
</template>
<script>
import pick from 'lodash.pick'
import { getAction } from '@/api/manage'
<#if form_date>
import JDate from '@/components/jeecg/JDate'
</#if>
<#if form_file>
import JUpload from '@/components/jeecg/JUpload'
</#if>
<#if form_popup>
import JPopup from '@/components/jeecgbiz/JPopup'
</#if>
<#if form_sel_depart>
import JSelectDepart from '@/components/jeecgbiz/JSelectDepart'
</#if>
<#if form_sel_user>
import JSelectUserByDep from '@/components/jeecgbiz/JSelectUserByDep'
</#if>
<#if form_select>
import JDictSelectTag from "@/components/dict/JDictSelectTag"
</#if>
<#if form_select_multi>
import JMultiSelectTag from "@/components/dict/JMultiSelectTag"
</#if>
export default {
name: '${sub.entityName}Form',
components: {
<#if form_date>
JDate,
</#if>
<#if form_file>
JUpload,
</#if>
<#if form_popup>
JPopup,
</#if>
<#if form_sel_depart>
JSelectDepart,
</#if>
<#if form_sel_user>
JSelectUserByDep,
</#if>
<#if form_select>
JDictSelectTag,
</#if>
<#if form_select_multi>
JMultiSelectTag,
</#if>
},
data () {
return {
form: this.$form.createForm(this),
model: {},
labelCol: {
span: 6
},
wrapperCol: {
span: 16
},
labelCol2: {
span: 3
},
wrapperCol2: {
span: 20
},
confirmLoading: false,
validatorRules:{
<#list sub.colums as po>
<#if po.fieldName !='id'>
<#if po.nullable =='N'>
${po.fieldName}:{rules: [{ required: true, message: '请输入${po.filedComment}!' }]},
<#else>
${po.fieldName}:{},
</#if>
</#if>
</#list>
},
}
},
methods:{
initFormData(url,id){
this.clearFormData()
if(!id){
this.edit({})
}else{
getAction(url,{id:id}).then(res=>{
if(res.success){
let records = res.result
if(records && records.length>0){
this.edit(records[0])
}
}
})
}
},
edit(record){
this.model = Object.assign({}, record)
console.log("${sub.entityName}Form-edit",this.model);
let fieldval = pick(this.model<#list sub.colums as po><#if po.fieldName !='id'>,'${po.fieldName}'</#if></#list>)
this.$nextTick(() => {
this.form.setFieldsValue(fieldval)
})
},
getFormData(){
let formdata_arr = []
this.form.validateFields((err, values) => {
if (!err) {
let formdata = Object.assign(this.model, values)
let isNullObj = true
Object.keys(formdata).forEach(key=>{
if(formdata[key]){
isNullObj = false
}
})
if(!isNullObj){
formdata_arr.push(formdata)
}
}else{
this.$emit("validateError","${sub.ftlDescription}表单校验未通过");
}
})
console.log("${sub.ftlDescription}表单数据集",formdata_arr);
return formdata_arr;
},
popupCallback(row){
this.form.setFieldsValue(pick(row<#list sub.colums as po><#if po.fieldName !='id'>,'${po.fieldName}'</#if></#list>))
},
clearFormData(){
this.form.resetFields()
this.model={}
}
}
}
</script>
</#if>
</#list>

View File

@ -0,0 +1,242 @@
package ${bussiPackage}.${entityPackage}.controller;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.jeecg.common.api.vo.Result;
import org.jeecg.common.system.query.QueryGenerator;
import org.jeecg.common.util.oConvertUtils;
import ${bussiPackage}.${entityPackage}.entity.${entityName};
import ${bussiPackage}.${entityPackage}.service.I${entityName}Service;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.extern.slf4j.Slf4j;
import org.jeecgframework.poi.excel.ExcelImportUtil;
import org.jeecgframework.poi.excel.def.NormalExcelConstants;
import org.jeecgframework.poi.excel.entity.ExportParams;
import org.jeecgframework.poi.excel.entity.ImportParams;
import org.jeecgframework.poi.excel.view.JeecgEntityExcelView;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;
import org.springframework.web.servlet.ModelAndView;
import com.alibaba.fastjson.JSON;
/**
* @Description: ${tableVo.ftlDescription}
* @Author: jeecg-boot
* @Date: ${.now?string["yyyy-MM-dd"]}
* @Version: V1.0
*/
<#assign pidFieldName = "">
<#list originalColumns as po>
<#if po.fieldDbName == tableVo.extendParams.pidField>
<#assign pidFieldName = po.fieldName>
</#if>
</#list>
@RestController
@RequestMapping("/${entityPackage}/${entityName?uncap_first}")
@Slf4j
public class ${entityName}Controller {
@Autowired
private I${entityName}Service ${entityName?uncap_first}Service;
/**
* 分页列表查询
* @param ${entityName?uncap_first}
* @param pageNo
* @param pageSize
* @param req
* @return
*/
@GetMapping(value = "/rootList")
public Result<IPage<${entityName}>> queryPageList(${entityName} ${entityName?uncap_first},
@RequestParam(name="pageNo", defaultValue="1") Integer pageNo,
@RequestParam(name="pageSize", defaultValue="10") Integer pageSize,
HttpServletRequest req) {
if(oConvertUtils.isEmpty(${entityName?uncap_first}.get${pidFieldName?cap_first}())){
${entityName?uncap_first}.set${pidFieldName?cap_first}("0");
}
Result<IPage<${entityName}>> result = new Result<IPage<${entityName}>>();
QueryWrapper<${entityName}> queryWrapper = QueryGenerator.initQueryWrapper(${entityName?uncap_first}, req.getParameterMap());
Page<${entityName}> page = new Page<${entityName}>(pageNo, pageSize);
IPage<${entityName}> pageList = ${entityName?uncap_first}Service.page(page, queryWrapper);
result.setSuccess(true);
result.setResult(pageList);
return result;
}
@GetMapping(value = "/childList")
public Result<List<${entityName}>> queryPageList(${entityName} ${entityName?uncap_first},HttpServletRequest req) {
Result<List<${entityName}>> result = new Result<List<${entityName}>>();
QueryWrapper<${entityName}> queryWrapper = QueryGenerator.initQueryWrapper(${entityName?uncap_first}, req.getParameterMap());
List<${entityName}> list = ${entityName?uncap_first}Service.list(queryWrapper);
result.setSuccess(true);
result.setResult(list);
return result;
}
/**
* 添加
* @param ${entityName?uncap_first}
* @return
*/
@PostMapping(value = "/add")
public Result<${entityName}> add(@RequestBody ${entityName} ${entityName?uncap_first}) {
Result<${entityName}> result = new Result<${entityName}>();
try {
${entityName?uncap_first}Service.add${entityName}(${entityName?uncap_first});
result.success("添加成功!");
} catch (Exception e) {
log.error(e.getMessage(),e);
result.error500("操作失败");
}
return result;
}
/**
* 编辑
* @param ${entityName?uncap_first}
* @return
*/
@PutMapping(value = "/edit")
public Result<${entityName}> edit(@RequestBody ${entityName} ${entityName?uncap_first}) {
Result<${entityName}> result = new Result<${entityName}>();
try {
${entityName?uncap_first}Service.update${entityName}(${entityName?uncap_first});
result.success("修改成功!");
} catch (Exception e) {
result.error500(e.getMessage());
}
return result;
}
/**
* 通过id删除
* @param id
* @return
*/
@DeleteMapping(value = "/delete")
public Result<${entityName}> delete(@RequestParam(name="id",required=true) String id) {
Result<${entityName}> result = new Result<${entityName}>();
try {
${entityName?uncap_first}Service.delete${entityName}(id);
result.success("删除成功!");
} catch (Exception e) {
result.error500(e.getMessage());
}
return result;
}
/**
* 批量删除
* @param ids
* @return
*/
@DeleteMapping(value = "/deleteBatch")
public Result<${entityName}> deleteBatch(@RequestParam(name="ids",required=true) String ids) {
Result<${entityName}> result = new Result<${entityName}>();
if(ids==null || "".equals(ids.trim())) {
result.error500("参数不识别!");
}else {
this.${entityName?uncap_first}Service.removeByIds(Arrays.asList(ids.split(",")));
result.success("删除成功!");
}
return result;
}
/**
* 通过id查询
* @param id
* @return
*/
@GetMapping(value = "/queryById")
public Result<${entityName}> queryById(@RequestParam(name="id",required=true) String id) {
Result<${entityName}> result = new Result<${entityName}>();
${entityName} ${entityName?uncap_first} = ${entityName?uncap_first}Service.getById(id);
if(${entityName?uncap_first}==null) {
result.error500("未找到对应实体");
}else {
result.setResult(${entityName?uncap_first});
result.setSuccess(true);
}
return result;
}
/**
* 导出excel
*
* @param request
* @param response
*/
@RequestMapping(value = "/exportXls")
public ModelAndView exportXls(HttpServletRequest request, ${entityName} ${entityName?uncap_first}) {
// Step.1 组装查询条件查询数据
QueryWrapper<${entityName}> queryWrapper = QueryGenerator.initQueryWrapper(${entityName?uncap_first}, request.getParameterMap());
List<${entityName}> pageList = ${entityName?uncap_first}Service.list(queryWrapper);
// Step.2 AutoPoi 导出Excel
ModelAndView mv = new ModelAndView(new JeecgEntityExcelView());
// 过滤选中数据
String selections = request.getParameter("selections");
if(oConvertUtils.isEmpty(selections)) {
mv.addObject(NormalExcelConstants.DATA_LIST, pageList);
}else {
List<String> selectionList = Arrays.asList(selections.split(","));
List<${entityName}> exportList = pageList.stream().filter(item -> selectionList.contains(item.getId())).collect(Collectors.toList());
mv.addObject(NormalExcelConstants.DATA_LIST, exportList);
}
//导出文件名称
mv.addObject(NormalExcelConstants.FILE_NAME, "${tableVo.ftlDescription}列表");
mv.addObject(NormalExcelConstants.CLASS, ${entityName}.class);
mv.addObject(NormalExcelConstants.PARAMS, new ExportParams("${tableVo.ftlDescription}列表数据", "导出人:Jeecg", "导出信息"));
return mv;
}
/**
* 通过excel导入数据
*
* @param request
* @param response
* @return
*/
@RequestMapping(value = "/importExcel", method = RequestMethod.POST)
public Result<?> importExcel(HttpServletRequest request, HttpServletResponse response) {
MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request;
Map<String, MultipartFile> fileMap = multipartRequest.getFileMap();
for (Map.Entry<String, MultipartFile> entity : fileMap.entrySet()) {
MultipartFile file = entity.getValue();// 获取上传文件对象
ImportParams params = new ImportParams();
params.setTitleRows(2);
params.setHeadRows(1);
params.setNeedSave(true);
try {
List<${entityName}> list${entityName}s = ExcelImportUtil.importExcel(file.getInputStream(), ${entityName}.class, params);
${entityName?uncap_first}Service.saveBatch(list${entityName}s);
return Result.ok("文件导入成功!数据行数:" + list${entityName}s.size());
} catch (Exception e) {
log.error(e.getMessage(),e);
return Result.error("文件导入失败:"+e.getMessage());
} finally {
try {
file.getInputStream().close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return Result.ok("文件导入失败!");
}
}

View File

@ -0,0 +1,54 @@
package ${bussiPackage}.${entityPackage}.entity;
import java.io.Serializable;
import java.util.Date;
import java.math.BigDecimal;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import com.fasterxml.jackson.annotation.JsonFormat;
import org.springframework.format.annotation.DateTimeFormat;
import org.jeecgframework.poi.excel.annotation.Excel;
import org.jeecg.common.aspect.annotation.Dict;
/**
* @Description: ${tableVo.ftlDescription}
* @Author: jeecg-boot
* @Date: ${.now?string["yyyy-MM-dd"]}
* @Version: V1.0
*/
@Data
@TableName("${tableName}")
public class ${entityName} implements Serializable {
private static final long serialVersionUID = 1L;
<#list originalColumns as po>
/**${po.filedComment}*/
<#if po.fieldName == primaryKeyField>
@TableId(type = IdType.UUID)
<#else>
<#if po.fieldDbType =='Date'>
<#if po.classType=='date'>
@Excel(name = "${po.filedComment}", width = 15, format = "yyyy-MM-dd")
@JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd")
@DateTimeFormat(pattern="yyyy-MM-dd")
<#else>
@Excel(name = "${po.filedComment}", width = 20, format = "yyyy-MM-dd HH:mm:ss")
@JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd HH:mm:ss")
@DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss")
</#if>
<#else>
@Excel(name = "${po.filedComment}", width = 15)
</#if>
<#-- <#if po.classType!='popup'>
<#if po.dictTable?default("")?trim?length gt 1>
@Dict(dicCode="${po.dictField}",dicText="${po.dictText}",dictTable="${po.dictTable}")
<#elseif po.dictField?default("")?trim?length gt 1>
@Dict(dicCode="${po.dictField}")
</#if>
</#if>-->
</#if>
private <#if po.fieldType=='java.sql.Blob'>byte[]<#else>${po.fieldType}</#if> ${po.fieldName};
</#list>
}

View File

@ -0,0 +1,22 @@
package ${bussiPackage}.${entityPackage}.mapper;
import org.apache.ibatis.annotations.Param;
import ${bussiPackage}.${entityPackage}.entity.${entityName};
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
/**
* @Description: ${tableVo.ftlDescription}
* @Author: jeecg-boot
* @Date: ${.now?string["yyyy-MM-dd"]}
* @Version: V1.0
*/
public interface ${entityName}Mapper extends BaseMapper<${entityName}> {
/**
* 编辑节点状态
* @param id
* @param status
*/
void updateTreeNodeStatus(@Param("id") String id,@Param("status") String status);
}

View File

@ -0,0 +1,15 @@
<#assign hasChildrenField = "">
<#list originalColumns as po>
<#if po.fieldDbName == tableVo.extendParams.hasChildren>
<#assign hasChildrenField = po.fieldName>
</#if>
</#list>
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="${bussiPackage}.${entityPackage}.mapper.${entityName}Mapper">
<update id="updateTreeNodeStatus" parameterType="java.lang.String">
update ${tableName} set ${hasChildrenField} = ${r'#'}{status} where id = ${r'#'}{id}
</update>
</mapper>

View File

@ -0,0 +1,33 @@
package ${bussiPackage}.${entityPackage}.service;
import ${bussiPackage}.${entityPackage}.entity.${entityName};
import com.baomidou.mybatisplus.extension.service.IService;
import org.jeecg.common.exception.JeecgBootException;
/**
* @Description: ${tableVo.ftlDescription}
* @Author: jeecg-boot
* @Date: ${.now?string["yyyy-MM-dd"]}
* @Version: V1.0
*/
public interface I${entityName}Service extends IService<${entityName}> {
/**根节点父ID的值*/
public static final String ROOT_PID_VALUE = "0";
/**树节点有子节点状态值*/
public static final String HASCHILD = "1";
/**树节点无子节点状态值*/
public static final String NOCHILD = "0";
/**新增节点*/
void add${entityName}(${entityName} ${entityName?uncap_first});
/**修改节点*/
void update${entityName}(${entityName} ${entityName?uncap_first}) throws JeecgBootException;
/**删除节点*/
void delete${entityName}(String id) throws JeecgBootException;
}

View File

@ -0,0 +1,92 @@
package ${bussiPackage}.${entityPackage}.service.impl;
import org.jeecg.common.exception.JeecgBootException;
import org.jeecg.common.util.oConvertUtils;
import ${bussiPackage}.${entityPackage}.entity.${entityName};
import ${bussiPackage}.${entityPackage}.mapper.${entityName}Mapper;
import ${bussiPackage}.${entityPackage}.service.I${entityName}Service;
import org.springframework.stereotype.Service;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
<#assign pidFieldName = "">
<#assign hasChildrenField = "">
<#list originalColumns as po>
<#if po.fieldDbName == tableVo.extendParams.pidField>
<#assign pidFieldName = po.fieldName>
</#if>
<#if po.fieldDbName == tableVo.extendParams.hasChildren>
<#assign hasChildrenField = po.fieldName>
</#if>
</#list>
/**
* @Description: ${tableVo.ftlDescription}
* @Author: jeecg-boot
* @Date: ${.now?string["yyyy-MM-dd"]}
* @Version: V1.0
*/
@Service
public class ${entityName}ServiceImpl extends ServiceImpl<${entityName}Mapper, ${entityName}> implements I${entityName}Service {
@Override
public void add${entityName}(${entityName} ${entityName?uncap_first}) {
if(oConvertUtils.isEmpty(${entityName?uncap_first}.get${pidFieldName?cap_first}())){
${entityName?uncap_first}.set${pidFieldName?cap_first}(I${entityName}Service.ROOT_PID_VALUE);
}else{
//如果当前节点父ID不为空 则设置父节点的hasChildren 为1
${entityName} parent = baseMapper.selectById(${entityName?uncap_first}.get${pidFieldName?cap_first}());
if(parent!=null && !"1".equals(parent.get${hasChildrenField?cap_first}())){
parent.set${hasChildrenField?cap_first}("1");
baseMapper.updateById(parent);
}
}
baseMapper.insert(${entityName?uncap_first});
}
@Override
public void update${entityName}(${entityName} ${entityName?uncap_first}) {
${entityName} entity = this.getById(${entityName?uncap_first}.getId());
if(entity==null) {
throw new JeecgBootException("未找到对应实体");
}
String old_pid = entity.get${pidFieldName?cap_first}();
String new_pid = ${entityName?uncap_first}.get${pidFieldName?cap_first}();
if(!old_pid.equals(new_pid)) {
updateOldParentNode(old_pid);
if(oConvertUtils.isEmpty(new_pid)){
${entityName?uncap_first}.set${pidFieldName?cap_first}(I${entityName}Service.ROOT_PID_VALUE);
}
if(!I${entityName}Service.ROOT_PID_VALUE.equals(${entityName?uncap_first}.get${pidFieldName?cap_first}())) {
baseMapper.updateTreeNodeStatus(${entityName?uncap_first}.get${pidFieldName?cap_first}(), I${entityName}Service.HASCHILD);
}
}
baseMapper.updateById(${entityName?uncap_first});
}
@Override
public void delete${entityName}(String id) throws JeecgBootException {
${entityName} ${entityName?uncap_first} = this.getById(id);
if(${entityName?uncap_first}==null) {
throw new JeecgBootException("未找到对应实体");
}
updateOldParentNode(${entityName?uncap_first}.get${pidFieldName?cap_first}());
baseMapper.deleteById(id);
}
/**
* 根据所传pid查询旧的父级节点的子节点并修改相应状态值
* @param pid
*/
private void updateOldParentNode(String pid) {
if(!I${entityName}Service.ROOT_PID_VALUE.equals(pid)) {
Integer count = baseMapper.selectCount(new QueryWrapper<${entityName}>().eq("${tableVo.extendParams.pidField}", pid));
if(count==null || count<=1) {
baseMapper.updateTreeNodeStatus(pid, I${entityName}Service.NOCHILD);
}
}
}
}

View File

@ -0,0 +1,355 @@
<#assign pidFieldName = "">
<#assign hasChildrenField = "">
<#list originalColumns as po>
<#if po.fieldDbName == tableVo.extendParams.pidField>
<#assign pidFieldName = po.fieldName>
</#if>
<#if po.fieldDbName == tableVo.extendParams.hasChildren>
<#assign hasChildrenField = po.fieldName>
</#if>
</#list>
<template>
<a-card :bordered="false">
<!-- 操作按钮区域 -->
<div class="table-operator">
<a-button @click="handleAdd" type="primary" icon="plus">新增</a-button>
<a-button type="primary" icon="download" @click="handleExportXls('${tableVo.ftlDescription}')">导出</a-button>
<a-upload name="file" :showUploadList="false" :multiple="false" :action="importExcelUrl" @change="handleImportExcel">
<a-button type="primary" icon="import">导入</a-button>
</a-upload>
<a-dropdown v-if="selectedRowKeys.length > 0">
<a-menu slot="overlay">
<a-menu-item key="1" @click="batchDel"><a-icon type="delete"/>删除</a-menu-item>
</a-menu>
<a-button style="margin-left: 8px"> 批量操作 <a-icon type="down" /></a-button>
</a-dropdown>
</div>
<!-- table区域-begin -->
<div>
<div class="ant-alert ant-alert-info" style="margin-bottom: 16px;">
<i class="anticon anticon-info-circle ant-alert-icon"></i> 已选择 <a style="font-weight: 600">{{ selectedRowKeys.length }}</a>项
<a style="margin-left: 24px" @click="onClearSelected">清空</a>
</div>
<a-table
ref="table"
size="middle"
rowKey="id"
:columns="columns"
:dataSource="dataSource"
:pagination="ipagination"
:loading="loading"
:expandedRowKeys="expandedRowKeys"
@change="handleTableChange"
@expand="handleExpand"
v-bind="tableProps">
<template slot="imgSlot" slot-scope="text">
<span v-if="!text" style="font-size: 12px;font-style: italic;">无此图片</span>
<img v-else :src="getImgView(text)" height="25px" alt="图片不存在" style="max-width:80px;font-size: 12px;font-style: italic;"/>
</template>
<template slot="fileSlot" slot-scope="text">
<span v-if="!text" style="font-size: 12px;font-style: italic;">无此文件</span>
<a-button
v-else
:ghost="true"
type="primary"
icon="download"
size="small"
@click="uploadFile(text)">
下载
</a-button>
</template>
<span slot="action" slot-scope="text, record">
<a @click="handleEdit(record)">编辑</a>
<a-divider type="vertical" />
<a-dropdown>
<a class="ant-dropdown-link">更多 <a-icon type="down" /></a>
<a-menu slot="overlay">
<a-menu-item>
<a-popconfirm title="确定删除吗?" @confirm="() => handleDelete(record.id)">
<a>删除</a>
</a-popconfirm>
</a-menu-item>
</a-menu>
</a-dropdown>
</span>
</a-table>
</div>
<${entityName?uncap_first}-modal ref="modalForm" @ok="modalFormOk"></${entityName?uncap_first}-modal>
</a-card>
</template>
<script>
import { getAction } from '@/api/manage'
import { JeecgListMixin } from '@/mixins/JeecgListMixin'
import ${entityName}Modal from './modules/${entityName}Modal'
import {initDictOptions, filterMultiDictText} from '@/components/dict/JDictSelectUtil'
export default {
name: "${entityName}List",
mixins:[JeecgListMixin],
components: {
${entityName}Modal
},
data () {
return {
description: '${tableVo.ftlDescription}管理页面',
// 表头
columns: [
<#list columns as po>
<#if po.fieldDbName==tableVo.extendParams.textField>
{
title:'${po.filedComment}',
align:"left",
dataIndex: '${po.fieldName}'
},
</#if>
</#list>
<#list columns as po>
<#if po.fieldDbName!=tableVo.extendParams.textField && po.fieldName!=pidFieldName>
{
title:'${po.filedComment}',
align:"left",
<#if po.classType=='date'>
dataIndex: '${po.fieldName}',
customRender:function (text) {
return !text?"":(text.length>10?text.substr(0,10):text)
}
<#elseif po.classType=='file'>
dataIndex: '${po.fieldName}',
scopedSlots: {customRender: 'fileSlot'}
<#elseif po.classType=='image'>
dataIndex: '${po.fieldName}',
scopedSlots: {customRender: 'imgSlot'}
<#elseif po.classType=='list_multi' || po.classType=='list' || po.classType=='radio' || po.classType=='checkbox' || po.classType=='sel_depart'>
dataIndex: '${po.fieldName}',
customRender:(text)=>{
if(!text){
return ''
}else{
return filterMultiDictText(this.dictOptions['${po.fieldName}'], text+"")
}
}
<#else>
dataIndex: '${po.fieldName}'
</#if>
},
</#if>
</#list>
{
title: '操作',
dataIndex: 'action',
align:"center",
scopedSlots: { customRender: 'action' },
}
],
url: {
list: "/${entityPackage}/${entityName?uncap_first}/rootList",
childList: "/${entityPackage}/${entityName?uncap_first}/childList",
delete: "/${entityPackage}/${entityName?uncap_first}/delete",
deleteBatch: "/${entityPackage}/${entityName?uncap_first}/deleteBatch",
exportXlsUrl: "/${entityPackage}/${entityName?uncap_first}/exportXls",
importExcelUrl: "${entityPackage}/${entityName?uncap_first}/importExcel",
},
expandedRowKeys:[],
hasChildrenField:"${hasChildrenField}",
pidField:"${pidFieldName}",
dictOptions:{
<#list columns as po>
<#if (po.isQuery=='Y' || po.isShowList=='Y')>
<#if po.classType='sel_depart' || po.classType=='list_multi' || po.classType=='list' || po.classType=='radio' || po.classType=='checkbox'>
${po.fieldName}:[],
</#if>
</#if>
</#list>
}
}
},
computed: {
importExcelUrl(){
<#noparse>return `${window._CONFIG['domianURL']}/${this.url.importExcelUrl}`;</#noparse>
},
tableProps() {
let _this = this
return {
// 列表项是否可选择
rowSelection: {
selectedRowKeys: _this.selectedRowKeys,
onChange: (selectedRowKeys) => _this.selectedRowKeys = selectedRowKeys
}
}
}
},
methods: {
loadData(arg){
if(arg==1){
this.ipagination.current=1
}
this.loading = true
this.expandedRowKeys = []
let params = this.getQueryParams()
return new Promise((resolve) => {
getAction(this.url.list,params).then(res=>{
if(res.success){
let result = res.result
if(Number(result.total)>0){
this.ipagination.total = Number(result.total)
this.dataSource = this.getDataByResult(res.result.records)
resolve()
}else{
this.ipagination.total=0
this.dataSource=[]
}
}else{
this.$message.warning(res.message)
}
this.loading = false
})
})
},
getDataByResult(result){
return result.map(item=>{
//判断是否标记了带有子节点
if(item[this.hasChildrenField]=='1'){
let loadChild = { id: item.id+'_loadChild', name: 'loading...', isLoading: true }
item.children = [loadChild]
}
return item
})
},
handleExpand(expanded, record){
// 判断是否是展开状态
if (expanded) {
this.expandedRowKeys.push(record.id)
if (record.children.length>0 && record.children[0].isLoading === true) {
let params = this.getQueryParams();//查询条件
params[this.pidField] = record.id
getAction(this.url.childList,params).then((res)=>{
if(res.success){
if(res.result && res.result.length>0){
record.children = this.getDataByResult(res.result)
this.dataSource = [...this.dataSource]
}else{
record.children=''
record.hasChildrenField='0'
}
}else{
this.$message.warning(res.message)
}
})
}
}else{
let keyIndex = this.expandedRowKeys.indexOf(record.id)
if(keyIndex>=0){
this.expandedRowKeys.splice(keyIndex, 1);
}
}
},
initDictConfig(){
<#list columns as po>
<#if (po.isQuery=='Y' || po.isShowList=='Y') && po.classType!='popup'>
<#if po.classType='sel_depart'>
initDictOptions('sys_depart,depart_name,id').then((res) => {
if (res.success) {
this.$set(this.dictOptions, '${po.fieldName}', res.result)
}
})
<#elseif po.classType=='list_multi' || po.classType=='list' || po.classType=='radio' || po.classType=='checkbox'>
<#assign list_field_dictCode="">
<#if po.dictTable?default("")?trim?length gt 1>
<#assign list_field_dictCode="${po.dictTable},${po.dictText},${po.dictField}">
<#elseif po.dictField?default("")?trim?length gt 1>
<#assign list_field_dictCode="${po.dictField}">
</#if>
initDictOptions('${list_field_dictCode}').then((res) => {
if (res.success) {
this.$set(this.dictOptions, '${po.fieldName}', res.result)
}
})
</#if>
</#if>
</#list>
},
modalFormOk(formData,arr){
if(!formData.id){
this.addOk(formData,arr)
}else{
if(!arr){
this.loadData()
}else{
this.editOk(formData,this.dataSource)
this.dataSource=[...this.dataSource]
}
}
},
editOk(formData,arr){
if(arr && arr.length>0){
for(let i=0;i<arr.length;i++){
if(arr[i].id==formData.id){
arr[i]=formData
break
}else{
this.editOk(formData,arr[i].children)
}
}
}
},
async addOk(formData,arr){
if(!formData[this.pidField]){
this.loadData()
}else{
this.expandedRowKeys=[]
for(let i of arr){
await this.expandTreeNode(i)
}
}
},
expandTreeNode(nodeId){
return new Promise((resolve,reject)=>{
this.getFormDataById(nodeId,this.dataSource)
let row = this.parentFormData
this.expandedRowKeys.push(nodeId)
let params = this.getQueryParams();//查询条件
params[this.pidField] = nodeId
getAction(this.url.childList,params).then((res)=>{
if(res.success){
if(res.result && res.result.length>0){
row.children = this.getDataByResult(res.result)
this.dataSource = [...this.dataSource]
resolve()
}else{
reject()
}
}else{
reject()
}
})
})
},
getFormDataById(id,arr){
if(arr && arr.length>0){
for(let i=0;i<arr.length;i++){
if(arr[i].id==id){
this.parentFormData = arr[i]
}else{
this.getFormDataById(id,arr[i].children)
}
}
}
},
}
}
</script>
<style scoped>
@import '~@assets/less/common.less'
</style>

View File

@ -0,0 +1,266 @@
<template>
<a-modal
:title="title"
:width="width"
:visible="visible"
:confirmLoading="confirmLoading"
@ok="handleOk"
@cancel="handleCancel"
:destroyOnClose="true"
cancelText="关闭">
<a-spin :spinning="confirmLoading">
<a-form :form="form">
<#assign form_date = false>
<#assign form_select = false>
<#assign form_select_multi = false>
<#assign form_popup = false>
<#assign form_sel_depart = false>
<#assign form_sel_user = false>
<#assign form_file = false>
<#assign form_tree_select = false>
<#assign pidFieldName = "">
<#list columns as po>
<#assign form_field_dictCode="">
<#if po.dictTable?default("")?trim?length gt 1>
<#assign form_field_dictCode="${po.dictTable},${po.dictText},${po.dictField}">
<#elseif po.dictField?default("")?trim?length gt 1>
<#assign form_field_dictCode="${po.dictField}">
</#if>
<a-form-item label="${po.filedComment}" :labelCol="labelCol" :wrapperCol="wrapperCol">
<#if po.fieldDbName == tableVo.extendParams.pidField>
<#assign form_tree_select = true>
<#assign pidFieldName = po.fieldName>
<j-tree-select
ref="treeSelect"
placeholder="请选择${po.filedComment}"
v-decorator="['${po.fieldName}', validatorRules.${po.fieldName}]"
dict="${tableVo.tableName},${tableVo.extendParams.textField},id"
pidField="${tableVo.extendParams.pidField}"
hasChildField="${tableVo.extendParams.hasChildren}">
</j-tree-select>
<#elseif po.classType =='date'>
<#assign form_date=true>
<j-date placeholder="请选择${po.filedComment}" v-decorator="[ '${po.fieldName}', validatorRules.${po.fieldName}]" :trigger-change="true" style="width: 100%"/>
<#elseif po.classType =='datetime'>
<#assign form_date=true>
<j-date placeholder="请选择${po.filedComment}" v-decorator="[ '${po.fieldName}', validatorRules.${po.fieldName}]" :trigger-change="true" :show-time="true" date-format="YYYY-MM-DD HH:mm:ss" style="width: 100%"/>
<#elseif po.classType =='popup'>
<#assign form_popup=true>
<j-popup
v-decorator="['${po.fieldName}']"
:trigger-change="true"
org-fields="${po.dictField}"
dest-fields="${po.dictText}"
code="${po.dictTable}"
@callback="popupCallback"/>
<#elseif po.classType =='sel_depart'>
<#assign form_sel_depart=true>
<j-select-depart v-decorator="['${po.fieldName}']" :trigger-change="true"/>
<#elseif po.classType =='sel_user'>
<#assign form_sel_user = true>
<j-select-user-by-dep v-decorator="['${po.fieldName}']" :trigger-change="true"/>
<#elseif po.classType =='textarea'>
<a-textarea v-decorator="['${po.fieldName}']" rows="4" placeholder="请输入${po.filedComment}"/>
<#elseif po.classType=='list' || po.classType=='radio'>
<#assign form_select = true>
<j-dict-select-tag type="${po.classType}" v-decorator="['${po.fieldName}']" :trigger-change="true" dictCode="${form_field_dictCode}" placeholder="请选择${po.filedComment}"/>
<#elseif po.classType=='list_multi' || po.classType=='checkbox'>
<#assign form_select_multi = true>
<j-multi-select-tag type="${po.classType}" v-decorator="['${po.fieldName}']" :trigger-change="true" dictCode="${form_field_dictCode}" placeholder="请选择${po.filedComment}"/>
<#elseif po.fieldDbType=='int' || po.fieldDbType=='double' || po.fieldDbType=='BigDecimal'>
<a-input-number v-decorator="[ '${po.fieldName}', validatorRules.${po.fieldName}]" placeholder="请输入${po.filedComment}" style="width: 100%"/>
<#elseif po.classType=='file' || po.classType=='image'>
<#assign form_file = true>
<j-upload v-decorator="['${po.fieldName}']" :trigger-change="true"></j-upload>
<#else>
<a-input v-decorator="[ '${po.fieldName}', validatorRules.${po.fieldName}]" placeholder="请输入${po.filedComment}"></a-input>
</#if>
</a-form-item>
</#list>
</a-form>
</a-spin>
</a-modal>
</template>
<script>
import { httpAction } from '@/api/manage'
import pick from 'lodash.pick'
<#if form_date>
import JDate from '@/components/jeecg/JDate'
</#if>
<#if form_file>
import JUpload from '@/components/jeecg/JUpload'
</#if>
<#if form_popup>
import JPopup from '@/components/jeecgbiz/JPopup'
</#if>
<#if form_sel_depart>
import JSelectDepart from '@/components/jeecgbiz/JSelectDepart'
</#if>
<#if form_sel_user>
import JSelectUserByDep from '@/components/jeecgbiz/JSelectUserByDep'
</#if>
<#if form_select>
import JDictSelectTag from "@/components/dict/JDictSelectTag"
</#if>
<#if form_select_multi>
import JMultiSelectTag from "@/components/dict/JMultiSelectTag"
</#if>
<#if form_tree_select>
import JTreeSelect from '@/components/jeecg/JTreeSelect'
</#if>
export default {
name: "${entityName}Modal",
components: {
<#if form_date>
JDate,
</#if>
<#if form_file>
JUpload,
</#if>
<#if form_popup>
JPopup,
</#if>
<#if form_sel_depart>
JSelectDepart,
</#if>
<#if form_sel_user>
JSelectUserByDep,
</#if>
<#if form_select>
JDictSelectTag,
</#if>
<#if form_select_multi>
JMultiSelectTag,
</#if>
<#if form_tree_select>
JTreeSelect
</#if>
},
data () {
return {
form: this.$form.createForm(this),
title:"操作",
width:800,
visible: false,
model: {},
labelCol: {
xs: { span: 24 },
sm: { span: 5 },
},
wrapperCol: {
xs: { span: 24 },
sm: { span: 16 },
},
confirmLoading: false,
validatorRules:{
<#list columns as po>
<#if po.fieldName !='id'>
<#if po.nullable =='N'>
${po.fieldName}:{rules: [{ required: true, message: '请输入${po.filedComment}!' }]},
<#else>
${po.fieldName}:{},
</#if>
</#if>
</#list>
},
url: {
add: "/${entityPackage}/${entityName?uncap_first}/add",
edit: "/${entityPackage}/${entityName?uncap_first}/edit",
},
expandedRowKeys:[],
pidField:"${pidFieldName}"
}
},
created () {
},
methods: {
add () {
this.edit({});
},
edit (record) {
this.form.resetFields();
this.model = Object.assign({}, record);
this.visible = true;
this.$nextTick(() => {
this.form.setFieldsValue(pick(this.model<#list columns as po><#if po.fieldName !='id'>,'${po.fieldName}'</#if></#list>))
})
},
close () {
this.$emit('close');
this.visible = false;
},
handleOk () {
const that = this;
// 触发表单验证
this.form.validateFields((err, values) => {
if (!err) {
that.confirmLoading = true;
let httpurl = '';
let method = '';
if(!this.model.id){
httpurl+=this.url.add;
method = 'post';
}else{
httpurl+=this.url.edit;
method = 'put';
}
let old_pid = this.model[this.pidField]
let formData = Object.assign(this.model, values);
let new_pid = this.model[this.pidField]
console.log("表单提交数据",formData)
httpAction(httpurl,formData,method).then((res)=>{
if(res.success){
that.$message.success(res.message);
that.submitSuccess(formData,old_pid==new_pid)
}else{
that.$message.warning(res.message);
}
}).finally(() => {
that.confirmLoading = false;
that.close();
})
}
})
},
handleCancel () {
this.close()
},
popupCallback(row){
this.form.setFieldsValue(pick(row<#list columns as po><#if po.fieldName !='id'>,'${po.fieldName}'</#if></#list>))
},
submitSuccess(formData,flag){
if(!formData.id){
let treeData = this.$refs.treeSelect.getCurrTreeData()
this.expandedRowKeys=[]
this.getExpandKeysByPid(formData[this.pidField],treeData,treeData)
this.$emit('ok',formData,this.expandedRowKeys.reverse());
}else{
this.$emit('ok',formData,flag);
}
},
getExpandKeysByPid(pid,arr,all){
if(pid && arr && arr.length>0){
for(let i=0;i<arr.length;i++){
if(arr[i].key==pid){
this.expandedRowKeys.push(arr[i].key)
this.getExpandKeysByPid(arr[i]['parentId'],all,all)
}else{
this.getExpandKeysByPid(pid,arr[i].children,all)
}
}
}
}
}
}
</script>

View File

@ -0,0 +1,49 @@
package org.jeecg;
import cn.hutool.json.JSONObject;
import org.jeecg.common.util.security.SecurityTools;
import org.jeecg.common.util.security.entity.*;
import org.junit.Test;
public class SecurityToolsTest {
@Test
public void Test(){
MyKeyPair mkeyPair = SecurityTools.generateKeyPair();
JSONObject msg = new JSONObject();
msg.put("name", "党政辉");
msg.put("age", 50);
JSONObject identity = new JSONObject();
identity.put("type", "01");
identity.put("no", "210882165896524512");
msg.put("identity", identity);
// 签名加密部分
SecuritySignReq signReq = new SecuritySignReq();
// data为要加密的报文字符串
signReq.setData(msg.toString());
// 为rsa私钥
signReq.setPrikey(mkeyPair.getPriKey());
// 调用签名方法
SecuritySignResp sign = SecurityTools.sign(signReq);
// 打印出来加密数据
// signData为签名数据
// data为aes加密数据
// asekey为ras加密过的aeskey
System.out.println(new JSONObject(sign).toStringPretty());
// 验签解密部分
SecurityReq req = new SecurityReq();
//对方传过来的数据一一对应
req.setAesKey(sign.getAesKey());
req.setData(sign.getData());
req.setSignData(sign.getSignData());
//我们的公钥
req.setPubKey(mkeyPair.getPubKey());
//验签方法调用
SecurityResp securityResp = SecurityTools.valid(req);
//解密报文data为解密报文
//sucess 为验签成功失败标志 true代码验签成功false代表失败
System.out.println(new JSONObject(securityResp).toStringPretty());
}
}