diff --git a/src/main/java/xyz/wbsite/dbtool/javafx/manger/callable/SpringBootCallable.java b/src/main/java/xyz/wbsite/dbtool/javafx/manger/callable/SpringBootCallable.java index 1db56371..86d54ee7 100644 --- a/src/main/java/xyz/wbsite/dbtool/javafx/manger/callable/SpringBootCallable.java +++ b/src/main/java/xyz/wbsite/dbtool/javafx/manger/callable/SpringBootCallable.java @@ -233,6 +233,7 @@ public class SpringBootCallable implements Callable { freeMarkerManager.outputTemp(new File(system.getAbsolutePath(), "AuthAjax.java"), option + "/java/action/ajax/system/AuthAjax.java", ctx); freeMarkerManager.outputTemp(new File(system.getAbsolutePath(), "DictAjax.java"), option + "/java/action/ajax/system/DictAjax.java", ctx); freeMarkerManager.outputTemp(new File(system.getAbsolutePath(), "DictItemAjax.java"), option + "/java/action/ajax/system/DictItemAjax.java", ctx); + freeMarkerManager.outputTemp(new File(system.getAbsolutePath(), "FileAjax.java"), option + "/java/action/ajax/system/FileAjax.java", ctx); for (Module module : project.getModules()) { @@ -870,6 +871,7 @@ public class SpringBootCallable implements Callable { ctx.put("author", project.getProjectAuthor()); ctx.put("date", new Date()); ctx.put("table", table); + ctx.put("module", module.getName()); ctx.put("fields", table.getFields()); freeMarkerManager.outputTemp(new File(module.getAbsolutePath(), table.getFName() + ".ftl"), option + "/resources/templates/screen/module/mgr.ftl", ctx); } diff --git a/src/main/resources/modules/SpringBoot/java/action/GlobalController.java b/src/main/resources/modules/SpringBoot/java/action/GlobalController.java index 46dfc51e..fd12ddd5 100644 --- a/src/main/resources/modules/SpringBoot/java/action/GlobalController.java +++ b/src/main/resources/modules/SpringBoot/java/action/GlobalController.java @@ -278,6 +278,7 @@ public class GlobalController implements ErrorController { if (methodC == null) { BaseResponse baseResponse = new BaseResponse(); baseResponse.addError(ErrorType.BUSINESS_ERROR, "未找到对应的方法!"); + return baseResponse; } Parameter[] parameters = methodC.getParameters(); diff --git a/src/main/resources/modules/SpringBoot/java/action/ajax/Ajax.java b/src/main/resources/modules/SpringBoot/java/action/ajax/Ajax.java index a8c5748c..7dffc577 100644 --- a/src/main/resources/modules/SpringBoot/java/action/ajax/Ajax.java +++ b/src/main/resources/modules/SpringBoot/java/action/ajax/Ajax.java @@ -60,4 +60,47 @@ public class ${table.getCName()}Ajax{ return ${table.getFName()}Manager.getAll(request, LocalData.getToken()); } +<#if table.getHtml()> + + + public Object template(){ + try { + WSheet sheet = new WSheet<>(DictItemCreateRequest.class); + byte[] bytes = sheet.getBytes(); + HttpHeaders headers = new HttpHeaders(); + headers.setContentType(MediaType.APPLICATION_OCTET_STREAM); + headers.setContentDispositionFormData("attachment", URLEncoder.encode(sheet.getName() + ".xlsx","utf-8")); + return new ResponseEntity<>(bytes, headers, HttpStatus.OK); + } catch (IOException e) { + BaseResponse baseResponse = new BaseResponse(); + baseResponse.addError(ErrorType.BUSINESS_ERROR, ""); + return baseResponse; + } + } + + public Object imports(MultipartFile file) { + BaseResponse baseResponse = new BaseResponse(); + try { + byte[] bytes = file.getBytes(); + + WSheet sheet = new WSheet<>(bytes, DictCreateRequest.class); + + if (sheet.hasError()) { + byte[] sheetBytes = sheet.getBytes(true); + HttpHeaders headers = new HttpHeaders(); + headers.setContentType(MediaType.APPLICATION_OCTET_STREAM); + headers.setContentDispositionFormData("attachment", URLEncoder.encode(sheet.getName() + "-err.xlsx","utf-8")); + return new ResponseEntity<>(sheetBytes, headers, HttpStatus.OK); + } else { + return baseResponse; + } + } catch (IOException e) { + baseResponse.addError(ErrorType.BUSINESS_ERROR, "上传文件出错"); + } catch (TemplateNotMatchException | ReadErrorException e) { + baseResponse.addError(ErrorType.BUSINESS_ERROR, e.getMessage()); + } + + return baseResponse; + } + } diff --git a/src/main/resources/modules/SpringBoot/java/action/ajax/system/DictAjax.java b/src/main/resources/modules/SpringBoot/java/action/ajax/system/DictAjax.java index a876374b..7978c97b 100644 --- a/src/main/resources/modules/SpringBoot/java/action/ajax/system/DictAjax.java +++ b/src/main/resources/modules/SpringBoot/java/action/ajax/system/DictAjax.java @@ -82,7 +82,7 @@ public class DictAjax { byte[] sheetBytes = sheet.getBytes(true); HttpHeaders headers = new HttpHeaders(); headers.setContentType(MediaType.APPLICATION_OCTET_STREAM); - headers.setContentDispositionFormData("attachment", URLEncoder.encode(sheet.getName() + ".xlsx","utf-8")); + headers.setContentDispositionFormData("attachment", URLEncoder.encode(sheet.getName() + "-err.xlsx","utf-8")); return new ResponseEntity<>(sheetBytes, headers, HttpStatus.OK); } else { return baseResponse; diff --git a/src/main/resources/modules/SpringBoot/java/action/ajax/system/DictItemAjax.java b/src/main/resources/modules/SpringBoot/java/action/ajax/system/DictItemAjax.java index 25fa7f99..2df710eb 100644 --- a/src/main/resources/modules/SpringBoot/java/action/ajax/system/DictItemAjax.java +++ b/src/main/resources/modules/SpringBoot/java/action/ajax/system/DictItemAjax.java @@ -1,39 +1,93 @@ package ${basePackage}.action.ajax.system; -import org.springframework.beans.factory.annotation.Autowired; import ${basePackage}.frame.auth.LocalData; +import ${basePackage}.frame.excel.WSheet; import ${basePackage}.frame.utils.MapperUtil; import ${basePackage}.module.system.mgr.DictItemManager; import ${basePackage}.module.system.req.*; import ${basePackage}.module.system.rsp.*; +import ${basePackage}.frame.base.BaseResponse; +import ${basePackage}.frame.base.ErrorType; +import ${basePackage}.frame.excel.exception.ReadErrorException; +import ${basePackage}.frame.excel.exception.TemplateNotMatchException; +import org.springframework.web.multipart.MultipartFile; +import com.fasterxml.jackson.core.TreeNode; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; + +import java.io.IOException; +import java.net.URLEncoder; public class DictItemAjax { @Autowired private DictItemManager dictManager; - public DictItemCreateResponse create(String jsonParam) { + public DictItemCreateResponse create(TreeNode jsonParam) { DictItemCreateRequest request = MapperUtil.toJava(jsonParam, DictItemCreateRequest.class); return dictManager.create(request, LocalData.getToken()); } - public DictItemDeleteResponse delete(String jsonParam) { + public DictItemDeleteResponse delete(TreeNode jsonParam) { DictItemDeleteRequest request = MapperUtil.toJava(jsonParam, DictItemDeleteRequest.class); return dictManager.delete(request, LocalData.getToken()); } - public DictItemUpdateResponse update(String jsonParam) { + public DictItemUpdateResponse update(TreeNode jsonParam) { DictItemUpdateRequest request = MapperUtil.toJava(jsonParam, DictItemUpdateRequest.class); return dictManager.update(request, LocalData.getToken()); } - public DictItemFindResponse find(String jsonParam) { + public DictItemFindResponse find(TreeNode jsonParam) { DictItemFindRequest request = MapperUtil.toJava(jsonParam, DictItemFindRequest.class); return dictManager.find(request, LocalData.getToken()); } - public DictItemGetResponse get(String jsonParam) { + public DictItemGetResponse get(TreeNode jsonParam) { DictItemGetRequest request = MapperUtil.toJava(jsonParam, DictItemGetRequest.class); return dictManager.get(request, LocalData.getToken()); } + + public Object template(){ + try { + WSheet sheet = new WSheet<>(DictItemCreateRequest.class); + byte[] bytes = sheet.getBytes(); + HttpHeaders headers = new HttpHeaders(); + headers.setContentType(MediaType.APPLICATION_OCTET_STREAM); + headers.setContentDispositionFormData("attachment", URLEncoder.encode(sheet.getName() + ".xlsx","utf-8")); + return new ResponseEntity<>(bytes, headers, HttpStatus.OK); + } catch (IOException e) { + BaseResponse baseResponse = new BaseResponse(); + baseResponse.addError(ErrorType.BUSINESS_ERROR, ""); + return baseResponse; + } + } + + public Object imports(MultipartFile file) { + BaseResponse baseResponse = new BaseResponse(); + try { + byte[] bytes = file.getBytes(); + + WSheet sheet = new WSheet<>(bytes, DictItemCreateRequest.class); + + if (sheet.hasError()) { + byte[] sheetBytes = sheet.getBytes(true); + HttpHeaders headers = new HttpHeaders(); + headers.setContentType(MediaType.APPLICATION_OCTET_STREAM); + headers.setContentDispositionFormData("attachment", URLEncoder.encode(sheet.getName() + "-err.xlsx","utf-8")); + return new ResponseEntity<>(sheetBytes, headers, HttpStatus.OK); + } else { + return baseResponse; + } + } catch (IOException e) { + baseResponse.addError(ErrorType.BUSINESS_ERROR, "上传文件出错"); + } catch (TemplateNotMatchException | ReadErrorException e) { + baseResponse.addError(ErrorType.BUSINESS_ERROR, e.getMessage()); + } + + return baseResponse; + } } diff --git a/src/main/resources/modules/SpringBoot/java/action/ajax/system/FileAjax.java b/src/main/resources/modules/SpringBoot/java/action/ajax/system/FileAjax.java new file mode 100644 index 00000000..a735bc66 --- /dev/null +++ b/src/main/resources/modules/SpringBoot/java/action/ajax/system/FileAjax.java @@ -0,0 +1,54 @@ +package ${basePackage}.action.ajax.system; + +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.web.multipart.MultipartFile; +import ${basePackage}.frame.base.BaseResponse; +import ${basePackage}.frame.base.ErrorType; +import ${basePackage}.frame.base.FileUploadResponse; + +import javax.swing.tree.TreeNode; +import java.io.IOException; +import java.net.URLEncoder; + +public class FileAjax { + + public Object upload(MultipartFile file) { + FileUploadResponse fileUploadResponse = new FileUploadResponse(); + String fileName = file.getOriginalFilename(); + + //======== + // todo 处理文件 + //======== + fileUploadResponse.setId(1L); + fileUploadResponse.setUrl("example.com\\img\\1.jpg"); + fileUploadResponse.setDownloadUrl("example.com\\img\\1.jpg"); + + if (file != null) { + fileUploadResponse.addError(ErrorType.BUSINESS_ERROR, "文件上传成功,但未处理文件[" + fileName + "]!"); + } else { + fileUploadResponse.addError(ErrorType.BUSINESS_ERROR, "文件上传失败!"); + } + + return fileUploadResponse; + } + + public Object download(TreeNode jsonParam) { + try { + //======== + // todo 下载示例 + //======== + byte[] bytes = "test".getBytes(); + HttpHeaders headers = new HttpHeaders(); + headers.setContentType(MediaType.APPLICATION_OCTET_STREAM); + headers.setContentDispositionFormData("attachment", URLEncoder.encode("example.test", "utf-8")); + return new ResponseEntity<>(bytes, headers, HttpStatus.OK); + } catch (IOException e) { + BaseResponse baseResponse = new BaseResponse(); + baseResponse.addError(ErrorType.BUSINESS_ERROR, ""); + return baseResponse; + } + } +} diff --git a/src/main/resources/modules/SpringBoot/resources/templates/control/nav.ftl b/src/main/resources/modules/SpringBoot/resources/templates/control/nav.ftl index abed9760..8913f10f 100644 --- a/src/main/resources/modules/SpringBoot/resources/templates/control/nav.ftl +++ b/src/main/resources/modules/SpringBoot/resources/templates/control/nav.ftl @@ -16,83 +16,13 @@ method: 'post', timeout: 30000, baseURL: '', + responseType: 'blob', headers: {'Content-Type': 'multipart/form-data'}, onUploadProgress: function (progressEvent) { var complete = (progressEvent.loaded / progressEvent.total * 100 | 0) + '%' - app.tipShow("上传中(" + complete + ")") + nav.tipShow("上传中(" + complete + ")") }, }); - - // 添加JSON请求拦截器 - jsonService.interceptors.request.use(function (config) { - // 在发送请求之前做些什么 - app.barShow(); - app.tipShow(); - return config; - }, function (error) { - return Promise.reject(error); - }); - uploadService.interceptors.request.use(function (config) { - // 在发送请求之前做些什么 - app.barShow(); - app.tipShow("上传中 ..."); - return config; - }, function (error) { - return Promise.reject(error); - }); - - // 添加JSON响应拦截器 - jsonService.interceptors.response.use(function (response) { - // 对响应数据做点什么 - app.tipClose(); - try {//确保服务器正确返回Json - if (response.data.errors.length > 0) { - console.error(response.data.errors) - } - app.barFinish(); - } catch (e) { - app.barError(); - response.data = {errors: [{message: '服务器响应错误'}]}; - } - return response; - }, function (error) { - // 对响应错误做点什么,并返回错误结果 - app.tipClose(); - app.barError(); - const rsp = {errors: []}; - if (!error.response) { - rsp.errors.push({message: error.message}); - } else { - rsp.errors.push(handleError(error.response.status)); - } - return Promise.reject(rsp); - }); - // 添加Upload响应拦截器 - uploadService.interceptors.response.use(function (response) { - // 对响应数据做点什么 - app.tipClose(); - try {//确保服务器正确返回Json - if (response.data.errors.length > 0) { - console.error(response.data.errors) - } - app.barFinish(); - } catch (e) { - app.barError(); - response.data = {errors: [{message: '服务器响应错误'}]}; - } - return response; - }, function (error) { - // 对响应错误做点什么,并返回错误结果 - app.tipClose(); - app.barError(); - const rsp = {errors: []}; - if (!error.response) { - rsp.errors.push({message: error.message}); - } else { - rsp.errors.push(handleError(error.response.status)); - } - return Promise.reject(rsp); - }); function handleError(status) { switch (status) { case 401: @@ -111,55 +41,144 @@ return {message: "请求错误(" + error.response.status + ")"}; } } - jsonRequest = function (data) { + function jsonRequest(data) { + nav.barShow(); + nav.tipShow(); return jsonService.request(data) .then(function (response) { + nav.tipClose(); + if (response.data.errors) {// 确保服务器正确返回Json + nav.barFinish(); + } else { + response.data = {errors: [{message: '服务器响应错误'}]}; + nav.barError(); + } return Promise.resolve(response.data); - }, function (response) { - return Promise.resolve(response); + }, function (error) { + nav.tipClose(); + nav.barError(); + const rsp = {errors: []}; + if (!error.response) { + rsp.errors.push({message: error.message}); + } else { + rsp.errors.push(handleError(error.response.status)); + } + return Promise.reject(rsp); }) - }; - upRequest = function (data) { + } + function upRequest(data) { + nav.barShow(); + nav.tipShow("上传中..."); var fd = new FormData(); fd.append("file", data.data); data.data = fd; return uploadService.request(data) .then(function (response) { - return Promise.resolve(response.data); - }, function (response) { - return Promise.resolve(response); + nav.tipClose(); + if (!response.data) { + nav.barError(); + return Promise.resolve({errors: [{message: '下载错误'}]}); + } else if ("application/json" == response.data.type) { + var reader = new FileReader(); + reader.addEventListener("loadend", function () { + var rsp = JSON.parse(reader.result); + if (rsp.errors.length > 0) { + nav.barError(); + nav.e(rsp.errors[0].message) + } else { + nav.barFinish(); + } + }); + reader.readAsText(response.data, "utf-8"); + return Promise.resolve({errors: []}); + } else { + nav.barFinish(); + // 获取响应header中文件信息 + var dis = response.headers['content-disposition']; + // 正则匹配文件名 + var fileName = dis.match(/filename="(.*\..*)"/)[1]; + // 模拟下载 + var url = window.URL.createObjectURL(new Blob([response.data])); + var link = document.createElement('a') + link.style.display = 'none'; + link.href = url; + link.setAttribute('download', decodeURIComponent(fileName)) + document.body.appendChild(link) + link.click(); + return Promise.resolve({errors: []}); + } + }, function (error) { + nav.tipClose(); + nav.barError(); + const rsp = {errors: []}; + if (!error.response) { + rsp.errors.push({message: error.message}); + } else { + rsp.errors.push(handleError(error.response.status)); + } + return Promise.reject(rsp); }) }; - downRequest = function (data) { + function downRequest(data) { + nav.barShow(); return downloadService.request(data) .then(function (response) { if (!response.data) { + nav.barError(); return Promise.resolve({errors: [{message: '下载错误'}]}); + } else if ("application/json" == response.data.type) { + var reader = new FileReader(); + reader.addEventListener("loadend", function () { + var rsp = JSON.parse(reader.result); + if (rsp.errors.length > 0) { + nav.barError(); + nav.e(rsp.errors[0].message) + } else { + nav.barFinish(); + } + }); + reader.readAsText(response.data, "utf-8"); + return Promise.resolve({errors: []}); + } else { + nav.barFinish(); + // 获取响应header中文件信息 + var dis = response.headers['content-disposition']; + // 正则匹配文件名 + var fileName = dis.match(/filename="(.*\..*)"/)[1]; + // 模拟下载 + var url = window.URL.createObjectURL(new Blob([response.data])); + var link = document.createElement('a') + link.style.display = 'none'; + link.href = url; + link.setAttribute('download', decodeURIComponent(fileName)) + document.body.appendChild(link) + link.click(); + return Promise.resolve({errors: []}); } - // 获取响应header中文件信息 - var dis = response.headers['content-disposition']; - // 正则匹配文件名 - var fileName = dis.match(/filename="(.*\..*)"/)[1]; - // 模拟下载 - var url = window.URL.createObjectURL(new Blob([response.data])); - var link = document.createElement('a') - link.style.display = 'none'; - link.href = url; - link.setAttribute('download', decodeURIComponent(fileName)) - document.body.appendChild(link) - link.click(); - return Promise.resolve({errors: []}); }, function (response) { - return Promise.resolve(response); + return Promise.resolve(handleError(response.response.status)); }) }; - window.ajax = { + // 定义共享异步请求对象 + Vue.prototype.$ajax = { login: function (data) { return jsonRequest({ url: "system/Auth/login", data: JSON.stringify(data), }) }, + upload: function (data) { + return upRequest({ + url: "system/File/upload", + data: data, + }) + }, + download: function (data) { + return downRequest({ + url: "system/File/download", + data: JSON.stringify(data), + }) + }, create: function (module, target, data) { return jsonRequest({ url: module + "/" + target + "/create", @@ -214,15 +233,17 @@ data: data, }) }, - } + }; var mixin = { data: { activeIndex: 'home', - contextPath: '${contextPath?default("")}', - homePath: '${homePath?default("")}', + contextPath: '${context?default("")}', + homePath: '${home?default("")}', loadingTip: '', loadingBar: '', - isSubmit:false + isSubmit: false, + result: [], + select: [] }, methods: { tipShow: function (msg) { @@ -384,22 +405,18 @@ this.select = select; }, excelTemplate: function () { - ajax.template(this.module, this.target, {}).then(function (response) { - if (response.errors.length > 0) { - this.e(response.errors[0].message); - } - }.bind(this)); + this.$ajax.template(this.module, this.target, {}); }, excelSelect: function () { this.$refs['excel'].dispatchEvent(new MouseEvent('click')) }, excelImport: function (item) { const file = item.target.files[0]; - ajax.imports(this.module, this.target, file).then(function (response) { + this.$ajax.imports(this.module, this.target, file).then(function (response) { if (response.errors.length > 0) { this.e(response.errors[0].message); } else { - this.i("文件导入成功!"); + this.i("文件上传成功!"); } }.bind(this)) }, @@ -407,7 +424,7 @@ this.$refs['form'].validate(function (valid) { if (valid) { if (this.form.id) { - ajax.update(this.module, this.target, this.form).then(function (response) { + this.$ajax.update(this.module, this.target, this.form).then(function (response) { if (response.errors.length > 0) { nav.e(response.errors[0].message); } else { @@ -416,7 +433,7 @@ } }.bind(this)) } else { - ajax.create(this.module, this.target, this.form).then(function (response) { + this.$ajax.create(this.module, this.target, this.form).then(function (response) { if (response.errors.length > 0) { nav.e(response.errors[0].message); } else { @@ -431,7 +448,7 @@ }.bind(this)); }, onFind: function () { - ajax.find(this.module, this.target, this.vm).then(function (response) { + this.$ajax.find(this.module, this.target, this.vm).then(function (response) { if (response.errors.length > 0) { this.e(response.errors[0].message); } else { @@ -446,7 +463,7 @@ cancelButtonText: '取消', type: 'warning' }).then(function () { - ajax.delete(this.module, this.target, {id: item.id}).then(function (response) { + this.$ajax.delete(this.module, this.target, {id: item.id}).then(function (response) { if (response.errors.length > 0) { this.e(response.errors[0].message); } else { @@ -469,7 +486,7 @@ }).then(function () { for (var i = 0; i < this.select.length; i++) { var obj = this.select[i]; - ajax.delete(this.module, this.target, {id: obj.id}).then(function (response) { + this.$ajax.delete(this.module, this.target, {id: obj.id}).then(function (response) { if (response.errors.length > 0) { this.e(response.errors[0].message); } else { @@ -498,4 +515,8 @@ filters: {}, watch: {} } + // 实例化工具 + window.nav = new Vue({ + mixins: [mixin] + }) \ No newline at end of file diff --git a/src/main/resources/modules/SpringBoot/resources/templates/layout/app.ftl b/src/main/resources/modules/SpringBoot/resources/templates/layout/app.ftl index 3be5daf5..a29f63b0 100644 --- a/src/main/resources/modules/SpringBoot/resources/templates/layout/app.ftl +++ b/src/main/resources/modules/SpringBoot/resources/templates/layout/app.ftl @@ -7,7 +7,6 @@ - diff --git a/src/main/resources/modules/SpringBoot/resources/templates/screen/module/system/dict.ftl b/src/main/resources/modules/SpringBoot/resources/templates/screen/module/system/dict.ftl index f0187ac9..40b0a2ef 100644 --- a/src/main/resources/modules/SpringBoot/resources/templates/screen/module/system/dict.ftl +++ b/src/main/resources/modules/SpringBoot/resources/templates/screen/module/system/dict.ftl @@ -74,6 +74,7 @@ + @@ -134,8 +135,8 @@ width="120" label="操作">