From be370ba2cf190b1a441b13ff13074eba1a79bc11 Mon Sep 17 00:00:00 2001 From: franky Date: Tue, 5 Jul 2022 22:33:11 +0800 Subject: [PATCH 001/135] =?UTF-8?q?spu=20=E4=BF=AE=E6=94=B9=E8=B0=83?= =?UTF-8?q?=E6=95=B4=EF=BC=8C=E7=BB=84=E5=90=88=E5=88=86=E7=B1=BB=E5=92=8C?= =?UTF-8?q?=E8=A7=84=E6=A0=BC=E5=B1=9E=E6=80=A7=EF=BC=8C=E6=96=B9=E4=BE=BF?= =?UTF-8?q?=E5=89=8D=E7=AB=AF=E4=BF=AE=E6=94=B9=E7=9A=84=E5=9B=9E=E6=98=BE?= =?UTF-8?q?=E5=B1=95=E7=A4=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../vo/ProductPropertyViewRespVO.java | 43 +++++++++++++++++++ .../controller/admin/spu/vo/SpuRespVO.java | 11 +++-- .../service/spu/ProductSpuServiceImpl.java | 31 +++++++++++++ 3 files changed, 82 insertions(+), 3 deletions(-) create mode 100644 yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/ProductPropertyViewRespVO.java diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/ProductPropertyViewRespVO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/ProductPropertyViewRespVO.java new file mode 100644 index 0000000000..0499138a96 --- /dev/null +++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/ProductPropertyViewRespVO.java @@ -0,0 +1,43 @@ +package cn.iocoder.yudao.module.product.controller.admin.property.vo; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import lombok.ToString; + +import java.util.Set; + +/** + * @Description: ProductPropertyViewRespVO + * @Author: franky + * @CreateDate: 2022/7/5 21:29 + * @Version: 1.0.0 + */ +@ApiModel("管理后台 - 规格名称详情展示 Request VO") +@Data +@ToString(callSuper = true) +public class ProductPropertyViewRespVO { + + @ApiModelProperty(value = "规格名称id", example = "1") + public Long propertyId; + + @ApiModelProperty(value = "规格名称", example = "内存") + public String name; + + @ApiModelProperty(value = "规格属性值集合", example = "[{\"v1\":11,\"v2\":\"64G\"},{\"v1\":10,\"v2\":\"32G\"}]") + public Set propertyValues; + + @Data + @ApiModel(value = "规格属性值元组") + public static class Tuple2 { + private final long v1; + private final String v2; + public Tuple2(Long v1, String v2) { + this.v1 = v1; + this.v2 = v2; + } + + } + + +} diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/SpuRespVO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/SpuRespVO.java index 90387f90aa..0121aec475 100755 --- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/SpuRespVO.java +++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/SpuRespVO.java @@ -1,5 +1,6 @@ package cn.iocoder.yudao.module.product.controller.admin.spu.vo; +import cn.iocoder.yudao.module.product.controller.admin.property.vo.ProductPropertyViewRespVO; import cn.iocoder.yudao.module.product.controller.admin.sku.vo.ProductSkuRespVO; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; @@ -19,7 +20,7 @@ public class SpuRespVO extends ProductSpuBaseVO { // TODO @franky:注解要完整 - @ApiModelProperty(value = "主键", required = true) + @ApiModelProperty(value = "主键", required = true, example = "1") private Long id; @ApiModelProperty(value = "创建时间") @@ -28,9 +29,13 @@ public class SpuRespVO extends ProductSpuBaseVO { /** * SKU 数组 */ - List skus; + @ApiModelProperty(value = "sku 数组", example = "[{\"spuId\":4,\"properties\":[{\"propertyId\":3,\"valueId\":15},{\"propertyId\":2,\"valueId\":10}],\"price\":12,\"originalPrice\":32,\"costPrice\":22,\"barCode\":\"765670123123\",\"picUrl\":\"http://test.yudao.iocoder.cn/72938088f1ca8438837c3b51394aea43.jpg\",\"status\":0,\"id\":7,\"createTime\":1656683270000},{\"spuId\":4,\"properties\":[{\"propertyId\":3,\"valueId\":15},{\"propertyId\":2,\"valueId\":11}],\"price\":13,\"originalPrice\":33,\"costPrice\":23,\"barCode\":\"888788770999\",\"picUrl\":\"http://test.yudao.iocoder.cn/6b902c700e5d32e862b6fd9af2e1c0e4.jpg\",\"status\":0,\"id\":8,\"createTime\":1656683270000},{\"spuId\":4,\"properties\":[{\"propertyId\":3,\"valueId\":16},{\"propertyId\":2,\"valueId\":10}],\"price\":14,\"originalPrice\":34,\"costPrice\":24,\"barCode\":\"9999981212\",\"picUrl\":\"http://test.yudao.iocoder.cn/eddf3c79b1917160d94d05244e1f47da.jpg\",\"status\":0,\"id\":9,\"createTime\":1656683270000},{\"spuId\":4,\"properties\":[{\"propertyId\":3,\"valueId\":16},{\"propertyId\":2,\"valueId\":11}],\"price\":15,\"originalPrice\":35,\"costPrice\":25,\"barCode\":\"4444121212\",\"picUrl\":\"http://test.yudao.iocoder.cn/88ac3eb068ea9cfac4726879b2776ccf.jpg\",\"status\":0,\"id\":10,\"createTime\":1656683270000}]") + private List skus; @ApiModelProperty(value = "分类id数组,一直递归到一级父节点", example = "[1,2,4]") - LinkedList categoryIds; + private LinkedList categoryIds; + + @ApiModelProperty(value = "规格属性修改和详情展示组合", example = "[{\"propertyId\":2,\"name\":\"内存\",\"propertyValues\":[{\"v1\":11,\"v2\":\"64G\"},{\"v1\":10,\"v2\":\"32G\"}]},{\"propertyId\":3,\"name\":\"尺寸\",\"propertyValues\":[{\"v1\":16,\"v2\":\"6.1\"},{\"v1\":15,\"v2\":\"5.7\"}]}]") + private List productPropertyViews; } diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/spu/ProductSpuServiceImpl.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/spu/ProductSpuServiceImpl.java index 4420b0af81..eb48bed250 100755 --- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/spu/ProductSpuServiceImpl.java +++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/spu/ProductSpuServiceImpl.java @@ -1,6 +1,10 @@ package cn.iocoder.yudao.module.product.service.spu; import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.product.controller.admin.property.vo.ProductPropertyRespVO; +import cn.iocoder.yudao.module.product.controller.admin.property.vo.ProductPropertyViewRespVO; +import cn.iocoder.yudao.module.product.controller.admin.propertyvalue.vo.ProductPropertyValueRespVO; +import cn.iocoder.yudao.module.product.controller.admin.sku.vo.ProductSkuBaseVO; import cn.iocoder.yudao.module.product.controller.admin.sku.vo.ProductSkuCreateReqVO; import cn.iocoder.yudao.module.product.controller.admin.sku.vo.ProductSkuRespVO; import cn.iocoder.yudao.module.product.controller.admin.spu.vo.*; @@ -11,6 +15,7 @@ import cn.iocoder.yudao.module.product.dal.dataobject.sku.ProductSkuDO; import cn.iocoder.yudao.module.product.dal.dataobject.spu.ProductSpuDO; import cn.iocoder.yudao.module.product.dal.mysql.spu.ProductSpuMapper; import cn.iocoder.yudao.module.product.service.category.CategoryService; +import cn.iocoder.yudao.module.product.service.property.ProductPropertyService; import cn.iocoder.yudao.module.product.service.sku.ProductSkuService; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -41,6 +46,9 @@ public class ProductSpuServiceImpl implements ProductSpuService { @Resource private ProductSkuService productSkuService; + @Resource + private ProductPropertyService productPropertyService; + @Override @Transactional public Long createSpu(ProductSpuCreateReqVO createReqVO) { @@ -104,6 +112,29 @@ public class ProductSpuServiceImpl implements ProductSpuService { if (null != spuVO) { List skuReqs = ProductSkuConvert.INSTANCE.convertList(productSkuService.getSkusBySpuId(id)); spuVO.setSkus(skuReqs); + List properties = new ArrayList<>(); + // 组合 sku 规格属性 + for (ProductSkuRespVO productSkuRespVO : skuReqs) { + properties.addAll(productSkuRespVO.getProperties()); + } + Map> propertyMaps = properties.stream().collect(Collectors.groupingBy(ProductSkuBaseVO.Property::getPropertyId)); + List propertyAndValueList = productPropertyService.selectByIds(new ArrayList<>(propertyMaps.keySet())); + // 装载组装过后的属性 + List productPropertyViews = new ArrayList<>(); + propertyAndValueList.forEach(p -> { + ProductPropertyViewRespVO productPropertyViewRespVO = new ProductPropertyViewRespVO(); + productPropertyViewRespVO.setPropertyId(p.getId()); + productPropertyViewRespVO.setName(p.getName()); + Set propertyValues = new HashSet<>(); + Map propertyValueMaps = p.getPropertyValueList().stream().collect(Collectors.toMap(ProductPropertyValueRespVO::getId, pv -> pv)); + propertyMaps.get(p.getId()).forEach(pv -> { + ProductPropertyViewRespVO.Tuple2 tuple2 = new ProductPropertyViewRespVO.Tuple2(pv.getValueId(), propertyValueMaps.get(pv.getValueId()).getName()); + propertyValues.add(tuple2); + }); + productPropertyViewRespVO.setPropertyValues(propertyValues); + productPropertyViews.add(productPropertyViewRespVO); + }); + spuVO.setProductPropertyViews(productPropertyViews); // 组合分类 if (null != spuVO.getCategoryId()) { LinkedList categoryArray = new LinkedList<>(); From f3c83488a3f0aee95609d80e1a424eb32638a434 Mon Sep 17 00:00:00 2001 From: franky <16621167566@163.com> Date: Wed, 6 Jul 2022 17:06:19 +0800 Subject: [PATCH 002/135] =?UTF-8?q?spu=20=E4=BF=AE=E6=94=B9=E9=A1=B5?= =?UTF-8?q?=E9=9D=A2=E5=B1=95=E7=A4=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/views/mall/product/spu/index.vue | 1019 +++++++++-------- 1 file changed, 560 insertions(+), 459 deletions(-) diff --git a/yudao-ui-admin/src/views/mall/product/spu/index.vue b/yudao-ui-admin/src/views/mall/product/spu/index.vue index da7d181157..7535897199 100644 --- a/yudao-ui-admin/src/views/mall/product/spu/index.vue +++ b/yudao-ui-admin/src/views/mall/product/spu/index.vue @@ -55,8 +55,8 @@ - - + + + diff --git a/yudao-ui-admin-vue3/src/components/Verifition/src/Verify/VerifyPoints.vue b/yudao-ui-admin-vue3/src/components/Verifition/src/Verify/VerifyPoints.vue new file mode 100644 index 0000000000..36fdae889a --- /dev/null +++ b/yudao-ui-admin-vue3/src/components/Verifition/src/Verify/VerifyPoints.vue @@ -0,0 +1,279 @@ + + diff --git a/yudao-ui-admin-vue3/src/components/Verifition/src/Verify/VerifySlide.vue b/yudao-ui-admin-vue3/src/components/Verifition/src/Verify/VerifySlide.vue new file mode 100644 index 0000000000..a31f4587f5 --- /dev/null +++ b/yudao-ui-admin-vue3/src/components/Verifition/src/Verify/VerifySlide.vue @@ -0,0 +1,422 @@ + + diff --git a/yudao-ui-admin-vue3/src/components/Verifition/src/Verify/index.ts b/yudao-ui-admin-vue3/src/components/Verifition/src/Verify/index.ts new file mode 100644 index 0000000000..0daa63a560 --- /dev/null +++ b/yudao-ui-admin-vue3/src/components/Verifition/src/Verify/index.ts @@ -0,0 +1,4 @@ +import VerifySlide from './VerifySlide.vue' +import VerifyPoints from './VerifyPoints.vue' + +export { VerifySlide, VerifyPoints } diff --git a/yudao-ui-admin-vue3/src/components/Verifition/src/api/index.ts b/yudao-ui-admin-vue3/src/components/Verifition/src/api/index.ts new file mode 100644 index 0000000000..6a67b71199 --- /dev/null +++ b/yudao-ui-admin-vue3/src/components/Verifition/src/api/index.ts @@ -0,0 +1,24 @@ +/** + * 此处可直接引用自己项目封装好的 axios 配合后端联调 + */ + +import request from './../utils/axios' //组件内部封装的axios +// import request from "@/api/axios.js" //调用项目封装的axios + +//获取验证图片 以及token +export function reqGet(data) { + return request({ + url: '/captcha/get', + method: 'post', + data + }) +} + +//滑动或者点选验证 +export function reqCheck(data) { + return request({ + url: '/captcha/check', + method: 'post', + data + }) +} diff --git a/yudao-ui-admin-vue3/src/components/Verifition/src/utils/ase.ts b/yudao-ui-admin-vue3/src/components/Verifition/src/utils/ase.ts new file mode 100644 index 0000000000..d2e6b988f1 --- /dev/null +++ b/yudao-ui-admin-vue3/src/components/Verifition/src/utils/ase.ts @@ -0,0 +1,14 @@ +import CryptoJS from 'crypto-js' +/** + * @word 要加密的内容 + * @keyWord String 服务器随机返回的关键字 + * */ +export function aesEncrypt(word, keyWord = 'XwKsGlMcdPMEhR1B') { + const key = CryptoJS.enc.Utf8.parse(keyWord) + const srcs = CryptoJS.enc.Utf8.parse(word) + const encrypted = CryptoJS.AES.encrypt(srcs, key, { + mode: CryptoJS.mode.ECB, + padding: CryptoJS.pad.Pkcs7 + }) + return encrypted.toString() +} diff --git a/yudao-ui-admin-vue3/src/components/Verifition/src/utils/axios.ts b/yudao-ui-admin-vue3/src/components/Verifition/src/utils/axios.ts new file mode 100644 index 0000000000..ca68097e76 --- /dev/null +++ b/yudao-ui-admin-vue3/src/components/Verifition/src/utils/axios.ts @@ -0,0 +1,26 @@ +import axios from 'axios' + +axios.defaults.baseURL = import.meta.env.VITE_BASE_URL + +const service = axios.create({ + timeout: 40000, + headers: { + 'X-Requested-With': 'XMLHttpRequest', + 'Content-Type': 'application/json; charset=UTF-8' + } +}) +service.interceptors.request.use( + (config) => { + return config + }, + (error) => { + Promise.reject(error) + } +) + +// response interceptor +service.interceptors.response.use((response) => { + const res = response.data + return res +}) +export default service diff --git a/yudao-ui-admin-vue3/src/components/Verifition/src/utils/util.ts b/yudao-ui-admin-vue3/src/components/Verifition/src/utils/util.ts new file mode 100644 index 0000000000..15c16270df --- /dev/null +++ b/yudao-ui-admin-vue3/src/components/Verifition/src/utils/util.ts @@ -0,0 +1,97 @@ +export function resetSize(vm) { + let img_width, img_height, bar_width, bar_height //图片的宽度、高度,移动条的宽度、高度 + const EmployeeWindow = window as any + const parentWidth = vm.$el.parentNode.offsetWidth || EmployeeWindow.offsetWidth + const parentHeight = vm.$el.parentNode.offsetHeight || EmployeeWindow.offsetHeight + if (vm.imgSize.width.indexOf('%') != -1) { + img_width = (parseInt(vm.imgSize.width) / 100) * parentWidth + 'px' + } else { + img_width = vm.imgSize.width + } + + if (vm.imgSize.height.indexOf('%') != -1) { + img_height = (parseInt(vm.imgSize.height) / 100) * parentHeight + 'px' + } else { + img_height = vm.imgSize.height + } + + if (vm.barSize.width.indexOf('%') != -1) { + bar_width = (parseInt(vm.barSize.width) / 100) * parentWidth + 'px' + } else { + bar_width = vm.barSize.width + } + + if (vm.barSize.height.indexOf('%') != -1) { + bar_height = (parseInt(vm.barSize.height) / 100) * parentHeight + 'px' + } else { + bar_height = vm.barSize.height + } + + return { imgWidth: img_width, imgHeight: img_height, barWidth: bar_width, barHeight: bar_height } +} + +export const _code_chars = [ + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 'a', + 'b', + 'c', + 'd', + 'e', + 'f', + 'g', + 'h', + 'i', + 'j', + 'k', + 'l', + 'm', + 'n', + 'o', + 'p', + 'q', + 'r', + 's', + 't', + 'u', + 'v', + 'w', + 'x', + 'y', + 'z', + 'A', + 'B', + 'C', + 'D', + 'E', + 'F', + 'G', + 'H', + 'I', + 'J', + 'K', + 'L', + 'M', + 'N', + 'O', + 'P', + 'Q', + 'R', + 'S', + 'T', + 'U', + 'V', + 'W', + 'X', + 'Y', + 'Z' +] +export const _code_color1 = ['#fffff0', '#f0ffff', '#f0fff0', '#fff0f0'] +export const _code_color2 = ['#FF0033', '#006699', '#993366', '#FF9900', '#66CC66', '#FF33CC'] diff --git a/yudao-ui-admin-vue3/src/views/Login/components/LoginForm.vue b/yudao-ui-admin-vue3/src/views/Login/components/LoginForm.vue index bb876e0a3c..0a43fa675f 100644 --- a/yudao-ui-admin-vue3/src/views/Login/components/LoginForm.vue +++ b/yudao-ui-admin-vue3/src/views/Login/components/LoginForm.vue @@ -30,6 +30,7 @@ import { required } from '@/utils/formRules' import { Icon } from '@/components/Icon' import { LoginStateEnum, useLoginState, useFormValid } from './useLogin' import type { RouteLocationNormalizedLoaded, RouteRecordRaw } from 'vue-router' +import { Verify } from '@/components/Verifition' const { currentRoute, addRoute, push } = useRouter() const permissionStore = usePermissionStore() @@ -46,12 +47,10 @@ const { t } = useI18n() const iconHouse = useIcon({ icon: 'ep:house' }) const iconAvatar = useIcon({ icon: 'ep:avatar' }) const iconLock = useIcon({ icon: 'ep:lock' }) -const iconCircleCheck = useIcon({ icon: 'ep:circle-check' }) const LoginCaptchaRules = { tenantName: [required], username: [required], - password: [required], - code: [required] + password: [required] } const LoginRules = { tenantName: [required], @@ -60,7 +59,6 @@ const LoginRules = { } const loginLoading = ref(false) const loginData = reactive({ - codeImg: '', isShowPassword: false, captchaEnable: true, tenantEnable: true, @@ -72,20 +70,16 @@ const loginData = reactive({ tenantName: '芋道源码', username: 'admin', password: 'admin123', - rememberMe: false, - code: '', - uuid: '' + rememberMe: false } }) +// blockPuzzle 滑块 clickWord 点击文字 +const verify = ref() +const captchaType = ref('blockPuzzle') // 获取验证码 const getCode = async () => { - const res = await LoginApi.getCodeImgApi() - loginData.captchaEnable = res.enable - if (res.enable) { - loginData.codeImg = 'data:image/gif;base64,' + res.img - loginData.loginForm.uuid = res.uuid - } + verify.value.show() } //获取租户ID const getTenantId = async () => { @@ -112,19 +106,12 @@ const handleLogin = async () => { const data = await validForm() if (!data) return loginLoading.value = true - await LoginApi.loginApi(loginData.loginForm) - .then(async (res) => { - setToken(res) - const userInfo = await LoginApi.getInfoApi() - await userStore.getUserInfoAction(userInfo) - await getRoutes() - }) - .catch(() => { - getCode() - }) - .finally(() => { - loginLoading.value = false - }) + const res = await LoginApi.loginApi(loginData.loginForm) + setToken(res) + const userInfo = await LoginApi.getInfoApi() + await userStore.getUserInfoAction(userInfo) + await getRoutes() + loginLoading.value = false } // 获取路由 @@ -159,8 +146,7 @@ watch( immediate: true } ) -onMounted(async () => { - await getCode() +onMounted(() => { getCookie() }) @@ -207,31 +193,11 @@ onMounted(async () => { type="password" :placeholder="t('login.passwordPlaceholder')" show-password - @keyup.enter="handleLogin" + @keyup.enter="getCode()" :prefix-icon="iconLock" /> - - - - - - - - - - - - { - + {{ t('login.login') }} + From 460597e03c5479da124744d3dcdb8b52ba725bdc Mon Sep 17 00:00:00 2001 From: xingyu Date: Tue, 2 Aug 2022 17:17:53 +0800 Subject: [PATCH 020/135] =?UTF-8?q?=E4=BC=98=E5=8C=96=E8=A1=8C=E4=B8=BA?= =?UTF-8?q?=E9=AA=8C=E8=AF=81=E7=A0=81=E9=85=8D=E7=BD=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- yudao-server/src/main/resources/application.yaml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/yudao-server/src/main/resources/application.yaml b/yudao-server/src/main/resources/application.yaml index 06a66388ed..e510a68cad 100644 --- a/yudao-server/src/main/resources/application.yaml +++ b/yudao-server/src/main/resources/application.yaml @@ -75,18 +75,18 @@ aj: cache-number: 1000 # local定时清除过期缓存(单位秒),设置为0代表不执行 timing-clear: 180 - # 验证码类型default两种都实例化。 - type: default - # 右下角水印文字(我的水印)https://tool.chinaz.com/tools/unicode.aspx 中文转Unicode + # 验证码类型 default两种都实例化。 blockPuzzle 滑块拼图 clickWord 文字点选 + type: blockPuzzle + # 右下角水印文字(我的水印)https://tool.chinaz.com/tools/unicode.aspx 中文转Unicode Linux可能需要转unicode water-mark: 芋道源码 # 滑动干扰项(0/1/2) interference-options: 2 # 接口请求次数一分钟限制是否开启 true|false - req-frequency-limit-enable: false + req-frequency-limit-enable: true # 验证失败5次,get接口锁定 req-get-lock-limit: 5 # 验证失败后,锁定时间间隔,s - req-get-lock-seconds: 360 + req-get-lock-seconds: 10 # get接口一分钟内请求数限制 req-get-minute-limit: 30 # check接口一分钟内请求数限制 From eff9cb6510b23fd65d80d36ffaa131a48212379c Mon Sep 17 00:00:00 2001 From: xingyu Date: Tue, 2 Aug 2022 17:33:38 +0800 Subject: [PATCH 021/135] perf: remove console --- yudao-ui-admin-vue3/src/hooks/web/useAxios.ts | 6 ------ 1 file changed, 6 deletions(-) diff --git a/yudao-ui-admin-vue3/src/hooks/web/useAxios.ts b/yudao-ui-admin-vue3/src/hooks/web/useAxios.ts index 2769d275a8..331969c6e0 100644 --- a/yudao-ui-admin-vue3/src/hooks/web/useAxios.ts +++ b/yudao-ui-admin-vue3/src/hooks/web/useAxios.ts @@ -20,37 +20,31 @@ const request = (option: AxiosConfig) => { async function getFn(option: AxiosConfig): Promise { const res = await request({ method: 'GET', ...option }) - console.info(res) return res.data } async function postFn(option: AxiosConfig): Promise { const res = await request({ method: 'POST', ...option }) - console.info(res) return res.data } async function deleteFn(option: AxiosConfig): Promise { const res = await request({ method: 'DELETE', ...option }) - console.info(res) return res.data } async function putFn(option: AxiosConfig): Promise { const res = await request({ method: 'PUT', ...option }) - console.info(res) return res.data } async function downloadFn(option: AxiosConfig): Promise { const res = await request({ method: 'GET', responseType: 'blob', ...option }) - console.info(res) return res as unknown as Promise } async function uploadFn(option: AxiosConfig): Promise { option.headersType = 'multipart/form-data' const res = await request({ method: 'PUT', ...option }) - console.info(res) return res as unknown as Promise } From c859bc933286d048e9426bba21e44b38281465ea Mon Sep 17 00:00:00 2001 From: xingyu Date: Tue, 2 Aug 2022 18:27:23 +0800 Subject: [PATCH 022/135] fix: axios config --- .../src/main/resources/application-local.yaml | 38 +++++++++---------- yudao-ui-admin-vue3/src/config/axios/index.ts | 1 + 2 files changed, 20 insertions(+), 19 deletions(-) diff --git a/yudao-server/src/main/resources/application-local.yaml b/yudao-server/src/main/resources/application-local.yaml index 0735842759..1cfcdf2a2e 100644 --- a/yudao-server/src/main/resources/application-local.yaml +++ b/yudao-server/src/main/resources/application-local.yaml @@ -45,33 +45,33 @@ spring: datasource: master: name: ruoyi-vue-pro - url: jdbc:mysql://127.0.0.1:3306/${spring.datasource.dynamic.datasource.master.name}?allowMultiQueries=true&useUnicode=true&useSSL=false&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&autoReconnect=true&nullCatalogMeansCurrent=true # MySQL Connector/J 8.X 连接的示例 -# url: jdbc:mysql://127.0.0.1:3306/${spring.datasource.dynamic.datasource.master.name}?useSSL=false&allowPublicKeyRetrieval=true&useUnicode=true&characterEncoding=UTF-8&serverTimezone=CTT # MySQL Connector/J 5.X 连接的示例 -# url: jdbc:postgresql://127.0.0.1:5432/${spring.datasource.dynamic.datasource.slave.name} # PostgreSQL 连接的示例 -# url: jdbc:oracle:thin:@127.0.0.1:1521:xe # Oracle 连接的示例 -# url: jdbc:sqlserver://127.0.0.1:1433;DatabaseName=${spring.datasource.dynamic.datasource.master.name} # SQLServer 连接的示例 + url: jdbc:mysql://39.107.87.6:3306/${spring.datasource.dynamic.datasource.master.name}?allowMultiQueries=true&useUnicode=true&useSSL=false&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&autoReconnect=true&nullCatalogMeansCurrent=true # MySQL Connector/J 8.X 连接的示例 + # url: jdbc:mysql://127.0.0.1:3306/${spring.datasource.dynamic.datasource.master.name}?useSSL=false&allowPublicKeyRetrieval=true&useUnicode=true&characterEncoding=UTF-8&serverTimezone=CTT # MySQL Connector/J 5.X 连接的示例 + # url: jdbc:postgresql://127.0.0.1:5432/${spring.datasource.dynamic.datasource.slave.name} # PostgreSQL 连接的示例 + # url: jdbc:oracle:thin:@127.0.0.1:1521:xe # Oracle 连接的示例 + # url: jdbc:sqlserver://127.0.0.1:1433;DatabaseName=${spring.datasource.dynamic.datasource.master.name} # SQLServer 连接的示例 username: root - password: 123456 -# username: sa -# password: JSm:g(*%lU4ZAkz06cd52KqT3)i1?H7W + password: Root@xingyu123 + # username: sa + # password: JSm:g(*%lU4ZAkz06cd52KqT3)i1?H7W slave: # 模拟从库,可根据自己需要修改 name: ruoyi-vue-pro - url: jdbc:mysql://127.0.0.1:3306/${spring.datasource.dynamic.datasource.slave.name}?allowMultiQueries=true&useUnicode=true&useSSL=false&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&autoReconnect=true&nullCatalogMeansCurrent=true # MySQL Connector/J 8.X 连接的示例 -# url: jdbc:mysql://127.0.0.1:3306/${spring.datasource.dynamic.datasource.slave.name}?useSSL=false&allowPublicKeyRetrieval=true&useUnicode=true&characterEncoding=UTF-8&serverTimezone=CTT # MySQL Connector/J 5.X 连接的示例 -# url: jdbc:postgresql://127.0.0.1:5432/${spring.datasource.dynamic.datasource.slave.name} # PostgreSQL 连接的示例 -# url: jdbc:oracle:thin:@127.0.0.1:1521:xe # Oracle 连接的示例 -# url: jdbc:sqlserver://127.0.0.1:1433;DatabaseName=${spring.datasource.dynamic.datasource.slave.name} # SQLServer 连接的示例 + url: jdbc:mysql://39.107.87.6:3306/${spring.datasource.dynamic.datasource.slave.name}?allowMultiQueries=true&useUnicode=true&useSSL=false&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&autoReconnect=true&nullCatalogMeansCurrent=true # MySQL Connector/J 8.X 连接的示例 + # url: jdbc:mysql://127.0.0.1:3306/${spring.datasource.dynamic.datasource.slave.name}?useSSL=false&allowPublicKeyRetrieval=true&useUnicode=true&characterEncoding=UTF-8&serverTimezone=CTT # MySQL Connector/J 5.X 连接的示例 + # url: jdbc:postgresql://127.0.0.1:5432/${spring.datasource.dynamic.datasource.slave.name} # PostgreSQL 连接的示例 + # url: jdbc:oracle:thin:@127.0.0.1:1521:xe # Oracle 连接的示例 + # url: jdbc:sqlserver://127.0.0.1:1433;DatabaseName=${spring.datasource.dynamic.datasource.slave.name} # SQLServer 连接的示例 username: root - password: 123456 -# username: sa -# password: JSm:g(*%lU4ZAkz06cd52KqT3)i1?H7W + password: Root@xingyu123 +# username: sa +# password: JSm:g(*%lU4ZAkz06cd52KqT3)i1?H7W # Redis 配置。Redisson 默认的配置足够使用,一般不需要进行调优 redis: - host: 127.0.0.1 # 地址 + host: 39.107.87.6 # 地址 port: 6379 # 端口 - database: 0 # 数据库索引 -# password: 123456 # 密码,建议生产环境开启 + database: 4 # 数据库索引 + password: xingyu # 密码,建议生产环境开启 jasypt: encryptor: diff --git a/yudao-ui-admin-vue3/src/config/axios/index.ts b/yudao-ui-admin-vue3/src/config/axios/index.ts index 14bd90bad4..8396105957 100644 --- a/yudao-ui-admin-vue3/src/config/axios/index.ts +++ b/yudao-ui-admin-vue3/src/config/axios/index.ts @@ -172,6 +172,7 @@ const handleAuthorized = () => { isRelogin.show = true ElNotification.error(t('sys.api.timeoutMessage')) } + location.href = '/' return Promise.reject(t('sys.api.timeoutMessage')) } export { service } From 6eabf509d9a31f74854c413e6d32f042ca0a5f52 Mon Sep 17 00:00:00 2001 From: xingyu Date: Tue, 2 Aug 2022 12:49:41 +0000 Subject: [PATCH 023/135] =?UTF-8?q?=E5=88=A0=E9=99=A4=E6=96=87=E4=BB=B6=20?= =?UTF-8?q?yudao-server/src/main/resources/application-local.yaml?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/main/resources/application-local.yaml | 240 ------------------ 1 file changed, 240 deletions(-) delete mode 100644 yudao-server/src/main/resources/application-local.yaml diff --git a/yudao-server/src/main/resources/application-local.yaml b/yudao-server/src/main/resources/application-local.yaml deleted file mode 100644 index 1cfcdf2a2e..0000000000 --- a/yudao-server/src/main/resources/application-local.yaml +++ /dev/null @@ -1,240 +0,0 @@ -server: - port: 48080 - ---- #################### 数据库相关配置 #################### - -spring: - # 数据源配置项 - autoconfigure: - exclude: - - com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceAutoConfigure # 排除 Druid 的自动配置,使用 dynamic-datasource-spring-boot-starter 配置多数据源 - - org.springframework.boot.autoconfigure.mongo.MongoAutoConfiguration # 排除积木报表带来的 MongoDB 的自动配置 - datasource: - druid: # Druid 【监控】相关的全局配置 - web-stat-filter: - enabled: true - stat-view-servlet: - enabled: true - allow: # 设置白名单,不填则允许所有访问 - url-pattern: /druid/* - login-username: # 控制台管理用户名和密码 - login-password: - filter: - stat: - enabled: true - log-slow-sql: true # 慢 SQL 记录 - slow-sql-millis: 100 - merge-sql: true - wall: - config: - multi-statement-allow: true - dynamic: # 多数据源配置 - druid: # Druid 【连接池】相关的全局配置 - initial-size: 5 # 初始连接数 - min-idle: 10 # 最小连接池数量 - max-active: 20 # 最大连接池数量 - max-wait: 600000 # 配置获取连接等待超时的时间,单位:毫秒 - time-between-eviction-runs-millis: 60000 # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位:毫秒 - min-evictable-idle-time-millis: 300000 # 配置一个连接在池中最小生存的时间,单位:毫秒 - max-evictable-idle-time-millis: 900000 # 配置一个连接在池中最大生存的时间,单位:毫秒 - validation-query: SELECT 1 FROM DUAL # 配置检测连接是否有效 - test-while-idle: true - test-on-borrow: false - test-on-return: false - primary: master - datasource: - master: - name: ruoyi-vue-pro - url: jdbc:mysql://39.107.87.6:3306/${spring.datasource.dynamic.datasource.master.name}?allowMultiQueries=true&useUnicode=true&useSSL=false&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&autoReconnect=true&nullCatalogMeansCurrent=true # MySQL Connector/J 8.X 连接的示例 - # url: jdbc:mysql://127.0.0.1:3306/${spring.datasource.dynamic.datasource.master.name}?useSSL=false&allowPublicKeyRetrieval=true&useUnicode=true&characterEncoding=UTF-8&serverTimezone=CTT # MySQL Connector/J 5.X 连接的示例 - # url: jdbc:postgresql://127.0.0.1:5432/${spring.datasource.dynamic.datasource.slave.name} # PostgreSQL 连接的示例 - # url: jdbc:oracle:thin:@127.0.0.1:1521:xe # Oracle 连接的示例 - # url: jdbc:sqlserver://127.0.0.1:1433;DatabaseName=${spring.datasource.dynamic.datasource.master.name} # SQLServer 连接的示例 - username: root - password: Root@xingyu123 - # username: sa - # password: JSm:g(*%lU4ZAkz06cd52KqT3)i1?H7W - slave: # 模拟从库,可根据自己需要修改 - name: ruoyi-vue-pro - url: jdbc:mysql://39.107.87.6:3306/${spring.datasource.dynamic.datasource.slave.name}?allowMultiQueries=true&useUnicode=true&useSSL=false&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&autoReconnect=true&nullCatalogMeansCurrent=true # MySQL Connector/J 8.X 连接的示例 - # url: jdbc:mysql://127.0.0.1:3306/${spring.datasource.dynamic.datasource.slave.name}?useSSL=false&allowPublicKeyRetrieval=true&useUnicode=true&characterEncoding=UTF-8&serverTimezone=CTT # MySQL Connector/J 5.X 连接的示例 - # url: jdbc:postgresql://127.0.0.1:5432/${spring.datasource.dynamic.datasource.slave.name} # PostgreSQL 连接的示例 - # url: jdbc:oracle:thin:@127.0.0.1:1521:xe # Oracle 连接的示例 - # url: jdbc:sqlserver://127.0.0.1:1433;DatabaseName=${spring.datasource.dynamic.datasource.slave.name} # SQLServer 连接的示例 - username: root - password: Root@xingyu123 -# username: sa -# password: JSm:g(*%lU4ZAkz06cd52KqT3)i1?H7W - - # Redis 配置。Redisson 默认的配置足够使用,一般不需要进行调优 - redis: - host: 39.107.87.6 # 地址 - port: 6379 # 端口 - database: 4 # 数据库索引 - password: xingyu # 密码,建议生产环境开启 - -jasypt: - encryptor: - password: yuanma # 加解密的秘钥 - ---- #################### 定时任务相关配置 #################### - -# Quartz 配置项,对应 QuartzProperties 配置类 -spring: - quartz: - auto-startup: false # 本地开发环境,尽量不要开启 Job - scheduler-name: schedulerName # Scheduler 名字。默认为 schedulerName - job-store-type: jdbc # Job 存储器类型。默认为 memory 表示内存,可选 jdbc 使用数据库。 - wait-for-jobs-to-complete-on-shutdown: true # 应用关闭时,是否等待定时任务执行完成。默认为 false ,建议设置为 true - properties: # 添加 Quartz Scheduler 附加属性,更多可以看 http://www.quartz-scheduler.org/documentation/2.4.0-SNAPSHOT/configuration.html 文档 - org: - quartz: - # Scheduler 相关配置 - scheduler: - instanceName: schedulerName - instanceId: AUTO # 自动生成 instance ID - # JobStore 相关配置 - jobStore: - # JobStore 实现类。可见博客:https://blog.csdn.net/weixin_42458219/article/details/122247162 - class: org.springframework.scheduling.quartz.LocalDataSourceJobStore - isClustered: true # 是集群模式 - clusterCheckinInterval: 15000 # 集群检查频率,单位:毫秒。默认为 15000,即 15 秒 - misfireThreshold: 60000 # misfire 阀值,单位:毫秒。 - # 线程池相关配置 - threadPool: - threadCount: 25 # 线程池大小。默认为 10 。 - threadPriority: 5 # 线程优先级 - class: org.quartz.simpl.SimpleThreadPool # 线程池类型 - jdbc: # 使用 JDBC 的 JobStore 的时候,JDBC 的配置 - initialize-schema: NEVER # 是否自动使用 SQL 初始化 Quartz 表结构。这里设置成 never ,我们手动创建表结构。 - ---- #################### 配置中心相关配置 #################### - -# Apollo 配置中心 -apollo: - bootstrap: - enabled: true # 设置 Apollo 在启动阶段生效 - eagerLoad: - enabled: true # 设置 Apollo 在日志初始化前生效,可以实现日志的动态级别配置 - jdbc: # 自定义的 JDBC 配置项,用于数据库的地址 - dao: cn.iocoder.yudao.module.infra.dal.mysql.config.ConfigDAOImpl - url: ${spring.datasource.dynamic.datasource.master.url} - username: ${spring.datasource.dynamic.datasource.master.username} - password: ${spring.datasource.dynamic.datasource.master.password} - ---- #################### 服务保障相关配置 #################### - -# Lock4j 配置项 -lock4j: - acquire-timeout: 3000 # 获取分布式锁超时时间,默认为 3000 毫秒 - expire: 30000 # 分布式锁的超时时间,默认为 30 毫秒 - -# Resilience4j 配置项 -resilience4j: - ratelimiter: - instances: - backendA: - limit-for-period: 1 # 每个周期内,允许的请求数。默认为 50 - limit-refresh-period: 60s # 每个周期的时长,单位:微秒。默认为 500 - timeout-duration: 1s # 被限流时,阻塞等待的时长,单位:微秒。默认为 5s - register-health-indicator: true # 是否注册到健康监测 - ---- #################### 监控相关配置 #################### - -# Actuator 监控端点的配置项 -management: - endpoints: - web: - base-path: /actuator # Actuator 提供的 API 接口的根目录。默认为 /actuator - exposure: - include: '*' # 需要开放的端点。默认值只打开 health 和 info 两个端点。通过设置 * ,可以开放所有端点。 - -# Spring Boot Admin 配置项 -spring: - boot: - admin: - # Spring Boot Admin Client 客户端的相关配置 - client: - url: http://127.0.0.1:${server.port}/${spring.boot.admin.context-path} # 设置 Spring Boot Admin Server 地址 - instance: - service-host-type: IP # 注册实例时,优先使用 IP [IP, HOST_NAME, CANONICAL_HOST_NAME] - # Spring Boot Admin Server 服务端的相关配置 - context-path: /admin # 配置 Spring - -# 日志文件配置 -logging: - file: - name: ${user.home}/logs/${spring.application.name}.log # 日志文件名,全路径 - level: - # 配置自己写的 MyBatis Mapper 打印日志 - cn.iocoder.yudao.module.bpm.dal.mysql: debug - cn.iocoder.yudao.module.infra.dal.mysql: debug - cn.iocoder.yudao.module.pay.dal.mysql: debug - cn.iocoder.yudao.module.system.dal.mysql: debug - cn.iocoder.yudao.module.tool.dal.mysql: debug - cn.iocoder.yudao.module.member.dal.mysql: debug - ---- #################### 微信公众号、小程序相关配置 #################### -wx: - mp: # 公众号配置(必填),参见 https://github.com/Wechat-Group/WxJava/blob/develop/spring-boot-starters/wx-java-mp-spring-boot-starter/README.md 文档 - app-id: wx041349c6f39b268b - secret: 5abee519483bc9f8cb37ce280e814bd0 - # 存储配置,解决 AccessToken 的跨节点的共享 - config-storage: - type: RedisTemplate # 采用 RedisTemplate 操作 Redis,会自动从 Spring 中获取 - key-prefix: wx # Redis Key 的前缀 TODO 芋艿:解决下 Redis key 管理的配置 - http-client-type: HttpClient # 采用 HttpClient 请求微信公众号平台 - miniapp: # 小程序配置(必填),参见 https://github.com/Wechat-Group/WxJava/blob/develop/spring-boot-starters/wx-java-miniapp-spring-boot-starter/README.md 文档 - appid: wx63c280fe3248a3e7 - secret: 6f270509224a7ae1296bbf1c8cb97aed - config-storage: - type: RedisTemplate # 采用 RedisTemplate 操作 Redis,会自动从 Spring 中获取 - key-prefix: wa # Redis Key 的前缀 TODO 芋艿:解决下 Redis key 管理的配置 - http-client-type: HttpClient # 采用 HttpClient 请求微信公众号平台 - ---- #################### 芋道相关配置 #################### - -# 芋道配置项,设置当前项目所有自定义的配置 -yudao: - captcha: - enable: false # 本地环境,暂时关闭图片验证码,方便登录等接口的测试 - security: - mock-enable: true - xss: - enable: false - exclude-urls: # 如下两个 url,仅仅是为了演示,去掉配置也没关系 - - ${spring.boot.admin.context-path}/** # 不处理 Spring Boot Admin 的请求 - - ${management.endpoints.web.base-path}/** # 不处理 Actuator 的请求 - pay: - pay-notify-url: http://niubi.natapp1.cc/api/pay/order/notify - pay-return-url: http://niubi.natapp1.cc/api/pay/order/return - refund-notify-url: http://niubi.natapp1.cc/api/pay/refund/notify - access-log: # 访问日志的配置项 - enable: false - error-code: # 错误码相关配置项 - enable: false - demo: false # 关闭演示模式 - -justauth: - enabled: true - type: - DINGTALK: # 钉钉 - client-id: dingvrnreaje3yqvzhxg - client-secret: i8E6iZyDvZj51JIb0tYsYfVQYOks9Cq1lgryEjFRqC79P3iJcrxEwT6Qk2QvLrLI - ignore-check-redirect-uri: true - WECHAT_ENTERPRISE: # 企业微信 - client-id: wwd411c69a39ad2e54 - client-secret: 1wTb7hYxnpT2TUbIeHGXGo7T0odav1ic10mLdyyATOw - agent-id: 1000004 - ignore-check-redirect-uri: true - WECHAT_MINI_APP: # 微信小程序 - client-id: ${wx.miniapp.appid} - client-secret: ${wx.miniapp.secret} - ignore-check-redirect-uri: true - ignore-check-state: true # 微信小程序,不会使用到 state,所以不进行校验 - - cache: - type: REDIS - prefix: 'social_auth_state:' # 缓存前缀,目前只对 Redis 缓存生效,默认 JUSTAUTH::STATE:: - timeout: 24h # 超时时长,目前只对 Redis 缓存生效,默认 3 分钟 - From aa0f63ea7093e45996a2952e35bcba92441f3330 Mon Sep 17 00:00:00 2001 From: xingyu Date: Tue, 2 Aug 2022 20:58:08 +0800 Subject: [PATCH 024/135] update hutool 5.8.5 --- yudao-dependencies/pom.xml | 2 +- .../common/util/collection/ArrayUtils.java | 3 +- .../core/client/impl/AbstractPayClient.java | 5 +- .../src/main/resources/application-local.yaml | 240 ++++++++++++++++++ 4 files changed, 246 insertions(+), 4 deletions(-) create mode 100644 yudao-server/src/main/resources/application-local.yaml diff --git a/yudao-dependencies/pom.xml b/yudao-dependencies/pom.xml index 9bfaaadbd7..2e1d15f595 100644 --- a/yudao-dependencies/pom.xml +++ b/yudao-dependencies/pom.xml @@ -46,7 +46,7 @@ 3.0.4 1.18.20 1.4.1.Final - 5.7.22 + 5.8.5 3.1.1 2.2 1.0.5 diff --git a/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/collection/ArrayUtils.java b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/collection/ArrayUtils.java index 366f960084..4285b8f4c1 100644 --- a/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/collection/ArrayUtils.java +++ b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/collection/ArrayUtils.java @@ -1,6 +1,7 @@ package cn.iocoder.yudao.framework.common.util.collection; import cn.hutool.core.collection.CollectionUtil; +import cn.hutool.core.collection.IterUtil; import cn.hutool.core.util.ArrayUtil; import java.util.Collection; @@ -44,7 +45,7 @@ public class ArrayUtils { if (CollectionUtil.isEmpty(from)) { return (T[]) (new Object[0]); } - return ArrayUtil.toArray(from, (Class) CollectionUtil.getElementType(from.iterator())); + return ArrayUtil.toArray(from, (Class) IterUtil.getElementType(from.iterator())); } public static T get(T[] array, int index) { diff --git a/yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/AbstractPayClient.java b/yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/AbstractPayClient.java index 292b6cf01d..3253709c89 100644 --- a/yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/AbstractPayClient.java +++ b/yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/AbstractPayClient.java @@ -1,6 +1,5 @@ package cn.iocoder.yudao.framework.pay.core.client.impl; -import cn.hutool.extra.validation.ValidationUtil; import cn.iocoder.yudao.framework.pay.core.client.AbstractPayCodeMapping; import cn.iocoder.yudao.framework.pay.core.client.PayClient; import cn.iocoder.yudao.framework.pay.core.client.PayClientConfig; @@ -10,6 +9,8 @@ import cn.iocoder.yudao.framework.pay.core.client.dto.PayRefundUnifiedReqDTO; import cn.iocoder.yudao.framework.pay.core.client.dto.PayRefundUnifiedRespDTO; import lombok.extern.slf4j.Slf4j; +import javax.validation.Validation; + import static cn.iocoder.yudao.framework.common.util.json.JsonUtils.toJsonString; /** @@ -79,7 +80,7 @@ public abstract class AbstractPayClient implemen @Override public final PayCommonResult unifiedOrder(PayOrderUnifiedReqDTO reqDTO) { - ValidationUtil.validate(reqDTO); + Validation.buildDefaultValidatorFactory().getValidator().validate(reqDTO); // 执行短信发送 PayCommonResult result; try { diff --git a/yudao-server/src/main/resources/application-local.yaml b/yudao-server/src/main/resources/application-local.yaml new file mode 100644 index 0000000000..fb31aa3451 --- /dev/null +++ b/yudao-server/src/main/resources/application-local.yaml @@ -0,0 +1,240 @@ +server: + port: 48080 + +--- #################### 数据库相关配置 #################### + +spring: + # 数据源配置项 + autoconfigure: + exclude: + - com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceAutoConfigure # 排除 Druid 的自动配置,使用 dynamic-datasource-spring-boot-starter 配置多数据源 + - org.springframework.boot.autoconfigure.mongo.MongoAutoConfiguration # 排除积木报表带来的 MongoDB 的自动配置 + datasource: + druid: # Druid 【监控】相关的全局配置 + web-stat-filter: + enabled: true + stat-view-servlet: + enabled: true + allow: # 设置白名单,不填则允许所有访问 + url-pattern: /druid/* + login-username: # 控制台管理用户名和密码 + login-password: + filter: + stat: + enabled: true + log-slow-sql: true # 慢 SQL 记录 + slow-sql-millis: 100 + merge-sql: true + wall: + config: + multi-statement-allow: true + dynamic: # 多数据源配置 + druid: # Druid 【连接池】相关的全局配置 + initial-size: 5 # 初始连接数 + min-idle: 10 # 最小连接池数量 + max-active: 20 # 最大连接池数量 + max-wait: 600000 # 配置获取连接等待超时的时间,单位:毫秒 + time-between-eviction-runs-millis: 60000 # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位:毫秒 + min-evictable-idle-time-millis: 300000 # 配置一个连接在池中最小生存的时间,单位:毫秒 + max-evictable-idle-time-millis: 900000 # 配置一个连接在池中最大生存的时间,单位:毫秒 + validation-query: SELECT 1 FROM DUAL # 配置检测连接是否有效 + test-while-idle: true + test-on-borrow: false + test-on-return: false + primary: master + datasource: + master: + name: ruoyi-vue-pro + url: jdbc:mysql://127.0.0.1:3306/${spring.datasource.dynamic.datasource.master.name}?allowMultiQueries=true&useUnicode=true&useSSL=false&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&autoReconnect=true&nullCatalogMeansCurrent=true # MySQL Connector/J 8.X 连接的示例 + # url: jdbc:mysql://127.0.0.1:3306/${spring.datasource.dynamic.datasource.master.name}?useSSL=false&allowPublicKeyRetrieval=true&useUnicode=true&characterEncoding=UTF-8&serverTimezone=CTT # MySQL Connector/J 5.X 连接的示例 + # url: jdbc:postgresql://127.0.0.1:5432/${spring.datasource.dynamic.datasource.slave.name} # PostgreSQL 连接的示例 + # url: jdbc:oracle:thin:@127.0.0.1:1521:xe # Oracle 连接的示例 + # url: jdbc:sqlserver://127.0.0.1:1433;DatabaseName=${spring.datasource.dynamic.datasource.master.name} # SQLServer 连接的示例 + username: root + password: 123456 + # username: sa + # password: JSm:g(*%lU4ZAkz06cd52KqT3)i1?H7W + slave: # 模拟从库,可根据自己需要修改 + name: ruoyi-vue-pro + url: jdbc:mysql://127.0.0.1:3306/${spring.datasource.dynamic.datasource.slave.name}?allowMultiQueries=true&useUnicode=true&useSSL=false&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&autoReconnect=true&nullCatalogMeansCurrent=true # MySQL Connector/J 8.X 连接的示例 + # url: jdbc:mysql://127.0.0.1:3306/${spring.datasource.dynamic.datasource.slave.name}?useSSL=false&allowPublicKeyRetrieval=true&useUnicode=true&characterEncoding=UTF-8&serverTimezone=CTT # MySQL Connector/J 5.X 连接的示例 + # url: jdbc:postgresql://127.0.0.1:5432/${spring.datasource.dynamic.datasource.slave.name} # PostgreSQL 连接的示例 + # url: jdbc:oracle:thin:@127.0.0.1:1521:xe # Oracle 连接的示例 + # url: jdbc:sqlserver://127.0.0.1:1433;DatabaseName=${spring.datasource.dynamic.datasource.slave.name} # SQLServer 连接的示例 + username: root + password: 123456 + # username: sa + # password: JSm:g(*%lU4ZAkz06cd52KqT3)i1?H7W + + # Redis 配置。Redisson 默认的配置足够使用,一般不需要进行调优 + redis: + host: 127.0.0.1 # 地址 + port: 6379 # 端口 + database: 0 # 数据库索引 +# password: 123456 # 密码,建议生产环境开启 + +jasypt: + encryptor: + password: yuanma # 加解密的秘钥 + +--- #################### 定时任务相关配置 #################### + +# Quartz 配置项,对应 QuartzProperties 配置类 +spring: + quartz: + auto-startup: false # 本地开发环境,尽量不要开启 Job + scheduler-name: schedulerName # Scheduler 名字。默认为 schedulerName + job-store-type: jdbc # Job 存储器类型。默认为 memory 表示内存,可选 jdbc 使用数据库。 + wait-for-jobs-to-complete-on-shutdown: true # 应用关闭时,是否等待定时任务执行完成。默认为 false ,建议设置为 true + properties: # 添加 Quartz Scheduler 附加属性,更多可以看 http://www.quartz-scheduler.org/documentation/2.4.0-SNAPSHOT/configuration.html 文档 + org: + quartz: + # Scheduler 相关配置 + scheduler: + instanceName: schedulerName + instanceId: AUTO # 自动生成 instance ID + # JobStore 相关配置 + jobStore: + # JobStore 实现类。可见博客:https://blog.csdn.net/weixin_42458219/article/details/122247162 + class: org.springframework.scheduling.quartz.LocalDataSourceJobStore + isClustered: true # 是集群模式 + clusterCheckinInterval: 15000 # 集群检查频率,单位:毫秒。默认为 15000,即 15 秒 + misfireThreshold: 60000 # misfire 阀值,单位:毫秒。 + # 线程池相关配置 + threadPool: + threadCount: 25 # 线程池大小。默认为 10 。 + threadPriority: 5 # 线程优先级 + class: org.quartz.simpl.SimpleThreadPool # 线程池类型 + jdbc: # 使用 JDBC 的 JobStore 的时候,JDBC 的配置 + initialize-schema: NEVER # 是否自动使用 SQL 初始化 Quartz 表结构。这里设置成 never ,我们手动创建表结构。 + +--- #################### 配置中心相关配置 #################### + +# Apollo 配置中心 +apollo: + bootstrap: + enabled: true # 设置 Apollo 在启动阶段生效 + eagerLoad: + enabled: true # 设置 Apollo 在日志初始化前生效,可以实现日志的动态级别配置 + jdbc: # 自定义的 JDBC 配置项,用于数据库的地址 + dao: cn.iocoder.yudao.module.infra.dal.mysql.config.ConfigDAOImpl + url: ${spring.datasource.dynamic.datasource.master.url} + username: ${spring.datasource.dynamic.datasource.master.username} + password: ${spring.datasource.dynamic.datasource.master.password} + +--- #################### 服务保障相关配置 #################### + +# Lock4j 配置项 +lock4j: + acquire-timeout: 3000 # 获取分布式锁超时时间,默认为 3000 毫秒 + expire: 30000 # 分布式锁的超时时间,默认为 30 毫秒 + +# Resilience4j 配置项 +resilience4j: + ratelimiter: + instances: + backendA: + limit-for-period: 1 # 每个周期内,允许的请求数。默认为 50 + limit-refresh-period: 60s # 每个周期的时长,单位:微秒。默认为 500 + timeout-duration: 1s # 被限流时,阻塞等待的时长,单位:微秒。默认为 5s + register-health-indicator: true # 是否注册到健康监测 + +--- #################### 监控相关配置 #################### + +# Actuator 监控端点的配置项 +management: + endpoints: + web: + base-path: /actuator # Actuator 提供的 API 接口的根目录。默认为 /actuator + exposure: + include: '*' # 需要开放的端点。默认值只打开 health 和 info 两个端点。通过设置 * ,可以开放所有端点。 + +# Spring Boot Admin 配置项 +spring: + boot: + admin: + # Spring Boot Admin Client 客户端的相关配置 + client: + url: http://127.0.0.1:${server.port}/${spring.boot.admin.context-path} # 设置 Spring Boot Admin Server 地址 + instance: + service-host-type: IP # 注册实例时,优先使用 IP [IP, HOST_NAME, CANONICAL_HOST_NAME] + # Spring Boot Admin Server 服务端的相关配置 + context-path: /admin # 配置 Spring + +# 日志文件配置 +logging: + file: + name: ${user.home}/logs/${spring.application.name}.log # 日志文件名,全路径 + level: + # 配置自己写的 MyBatis Mapper 打印日志 + cn.iocoder.yudao.module.bpm.dal.mysql: debug + cn.iocoder.yudao.module.infra.dal.mysql: debug + cn.iocoder.yudao.module.pay.dal.mysql: debug + cn.iocoder.yudao.module.system.dal.mysql: debug + cn.iocoder.yudao.module.tool.dal.mysql: debug + cn.iocoder.yudao.module.member.dal.mysql: debug + +--- #################### 微信公众号、小程序相关配置 #################### +wx: + mp: # 公众号配置(必填),参见 https://github.com/Wechat-Group/WxJava/blob/develop/spring-boot-starters/wx-java-mp-spring-boot-starter/README.md 文档 + app-id: wx041349c6f39b268b + secret: 5abee519483bc9f8cb37ce280e814bd0 + # 存储配置,解决 AccessToken 的跨节点的共享 + config-storage: + type: RedisTemplate # 采用 RedisTemplate 操作 Redis,会自动从 Spring 中获取 + key-prefix: wx # Redis Key 的前缀 TODO 芋艿:解决下 Redis key 管理的配置 + http-client-type: HttpClient # 采用 HttpClient 请求微信公众号平台 + miniapp: # 小程序配置(必填),参见 https://github.com/Wechat-Group/WxJava/blob/develop/spring-boot-starters/wx-java-miniapp-spring-boot-starter/README.md 文档 + appid: wx63c280fe3248a3e7 + secret: 6f270509224a7ae1296bbf1c8cb97aed + config-storage: + type: RedisTemplate # 采用 RedisTemplate 操作 Redis,会自动从 Spring 中获取 + key-prefix: wa # Redis Key 的前缀 TODO 芋艿:解决下 Redis key 管理的配置 + http-client-type: HttpClient # 采用 HttpClient 请求微信公众号平台 + +--- #################### 芋道相关配置 #################### + +# 芋道配置项,设置当前项目所有自定义的配置 +yudao: + captcha: + enable: false # 本地环境,暂时关闭图片验证码,方便登录等接口的测试 + security: + mock-enable: true + xss: + enable: false + exclude-urls: # 如下两个 url,仅仅是为了演示,去掉配置也没关系 + - ${spring.boot.admin.context-path}/** # 不处理 Spring Boot Admin 的请求 + - ${management.endpoints.web.base-path}/** # 不处理 Actuator 的请求 + pay: + pay-notify-url: http://niubi.natapp1.cc/api/pay/order/notify + pay-return-url: http://niubi.natapp1.cc/api/pay/order/return + refund-notify-url: http://niubi.natapp1.cc/api/pay/refund/notify + access-log: # 访问日志的配置项 + enable: false + error-code: # 错误码相关配置项 + enable: false + demo: false # 关闭演示模式 + +justauth: + enabled: true + type: + DINGTALK: # 钉钉 + client-id: dingvrnreaje3yqvzhxg + client-secret: i8E6iZyDvZj51JIb0tYsYfVQYOks9Cq1lgryEjFRqC79P3iJcrxEwT6Qk2QvLrLI + ignore-check-redirect-uri: true + WECHAT_ENTERPRISE: # 企业微信 + client-id: wwd411c69a39ad2e54 + client-secret: 1wTb7hYxnpT2TUbIeHGXGo7T0odav1ic10mLdyyATOw + agent-id: 1000004 + ignore-check-redirect-uri: true + WECHAT_MINI_APP: # 微信小程序 + client-id: ${wx.miniapp.appid} + client-secret: ${wx.miniapp.secret} + ignore-check-redirect-uri: true + ignore-check-state: true # 微信小程序,不会使用到 state,所以不进行校验 + + cache: + type: REDIS + prefix: 'social_auth_state:' # 缓存前缀,目前只对 Redis 缓存生效,默认 JUSTAUTH::STATE:: + timeout: 24h # 超时时长,目前只对 Redis 缓存生效,默认 3 分钟 + From abb94eae87d179a9214171536fef3942225997c2 Mon Sep 17 00:00:00 2001 From: xingyu Date: Tue, 2 Aug 2022 23:01:47 +0800 Subject: [PATCH 025/135] =?UTF-8?q?=E5=8D=87=E7=BA=A7=E9=83=A8=E5=88=86?= =?UTF-8?q?=E4=BE=9D=E8=B5=96=EF=BC=8C=E5=AD=98=E5=9C=A8=E9=AB=98=E5=8D=B1?= =?UTF-8?q?=E6=BC=8F=E6=B4=9E=E6=8A=A5=E9=94=99=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- yudao-dependencies/pom.xml | 10 +++++----- .../yudao-spring-boot-starter-biz-pay/pom.xml | 10 ++++++++-- .../yudao-spring-boot-starter-biz-weixin/pom.xml | 4 ++-- .../yudao-spring-boot-starter-captcha/pom.xml | 5 ----- 4 files changed, 15 insertions(+), 14 deletions(-) diff --git a/yudao-dependencies/pom.xml b/yudao-dependencies/pom.xml index 2e1d15f595..86b693affb 100644 --- a/yudao-dependencies/pom.xml +++ b/yudao-dependencies/pom.xml @@ -41,14 +41,14 @@ 0.1.16 4.0.0 - 6.7.0 + 6.7.2 3.0.4 1.18.20 1.4.1.Final 5.8.5 3.1.1 - 2.2 + 2.3 1.0.5 1.2.83 30.1.1-jre @@ -60,9 +60,9 @@ 1.3.0 8.2.2 - 4.5.25 - 2.1.0 - 3.1.471 + 4.6.0 + 2.2.1 + 3.1.561 1.2.7 1.4.0 1.5.2 diff --git a/yudao-framework/yudao-spring-boot-starter-biz-pay/pom.xml b/yudao-framework/yudao-spring-boot-starter-biz-pay/pom.xml index 4153c25c44..e6106b9d94 100644 --- a/yudao-framework/yudao-spring-boot-starter-biz-pay/pom.xml +++ b/yudao-framework/yudao-spring-boot-starter-biz-pay/pom.xml @@ -52,12 +52,18 @@ com.alipay.sdk alipay-sdk-java - 4.17.9.ALL + 4.31.72.ALL + + + org.bouncycastle + bcprov-jdk15on + + com.github.binarywang weixin-java-pay - 4.1.9.B + 4.3.8.B diff --git a/yudao-framework/yudao-spring-boot-starter-biz-weixin/pom.xml b/yudao-framework/yudao-spring-boot-starter-biz-weixin/pom.xml index 9572391db3..2dc2fe6881 100644 --- a/yudao-framework/yudao-spring-boot-starter-biz-weixin/pom.xml +++ b/yudao-framework/yudao-spring-boot-starter-biz-weixin/pom.xml @@ -35,12 +35,12 @@ com.github.binarywang wx-java-mp-spring-boot-starter - 4.3.4.B + 4.3.8.B com.github.binarywang wx-java-miniapp-spring-boot-starter - 4.3.4.B + 4.3.8.B diff --git a/yudao-framework/yudao-spring-boot-starter-captcha/pom.xml b/yudao-framework/yudao-spring-boot-starter-captcha/pom.xml index 7fc7eb00b8..cbdb3a100f 100644 --- a/yudao-framework/yudao-spring-boot-starter-captcha/pom.xml +++ b/yudao-framework/yudao-spring-boot-starter-captcha/pom.xml @@ -17,11 +17,6 @@ - - cn.iocoder.boot - yudao-common - - org.springframework.boot From b6c7d8685cb9ce98e96eb887d96659cae3a9dd86 Mon Sep 17 00:00:00 2001 From: xingyu Date: Wed, 3 Aug 2022 00:41:59 +0800 Subject: [PATCH 026/135] perf: refresh token && delete console --- .../src/api/system/user/profile/index.ts | 4 +- .../src/components/Verifition/src/Verify.vue | 3 - .../Verifition/src/Verify/VerifySlide.vue | 1 - yudao-ui-admin-vue3/src/config/axios/index.ts | 76 ++++++++++++++----- yudao-ui-admin-vue3/src/router/index.ts | 11 +-- .../views/Profile/components/UserAvatar.vue | 56 +++++++------- .../src/views/system/menu/index.vue | 1 - .../src/views/system/oauth2/client/index.vue | 2 +- .../src/views/system/role/index.vue | 5 +- .../src/views/system/tenantPackage/index.vue | 4 +- 10 files changed, 100 insertions(+), 63 deletions(-) diff --git a/yudao-ui-admin-vue3/src/api/system/user/profile/index.ts b/yudao-ui-admin-vue3/src/api/system/user/profile/index.ts index a5a24490f5..3eab59e014 100644 --- a/yudao-ui-admin-vue3/src/api/system/user/profile/index.ts +++ b/yudao-ui-admin-vue3/src/api/system/user/profile/index.ts @@ -24,6 +24,6 @@ export const updateUserPwdApi = (oldPassword: string, newPassword: string) => { } // 用户头像上传 -export const uploadAvatarApi = (params) => { - return request.upload({ url: '/system/user/profile/update-avatar', params }) +export const uploadAvatarApi = (data) => { + return request.upload({ url: '/system/user/profile/update-avatar', data: data }) } diff --git a/yudao-ui-admin-vue3/src/components/Verifition/src/Verify.vue b/yudao-ui-admin-vue3/src/components/Verifition/src/Verify.vue index 9fe0c54759..2e4af5ccee 100644 --- a/yudao-ui-admin-vue3/src/components/Verifition/src/Verify.vue +++ b/yudao-ui-admin-vue3/src/components/Verifition/src/Verify.vue @@ -102,7 +102,6 @@ export default { * @description 刷新 * */ const refresh = () => { - console.log(instance.value) if (instance.value.refresh) { instance.value.refresh() } @@ -271,7 +270,6 @@ export default { -moz-box-sizing: content-box; box-sizing: content-box; border: 1px solid #ddd; - -webkit-border-radius: 4px; } .verify-bar-area .verify-move-block { @@ -284,7 +282,6 @@ export default { -moz-box-sizing: content-box; box-sizing: content-box; box-shadow: 0 0 2px #888888; - -webkit-border-radius: 1px; } .verify-bar-area .verify-move-block:hover { diff --git a/yudao-ui-admin-vue3/src/components/Verifition/src/Verify/VerifySlide.vue b/yudao-ui-admin-vue3/src/components/Verifition/src/Verify/VerifySlide.vue index a31f4587f5..65136ff700 100644 --- a/yudao-ui-admin-vue3/src/components/Verifition/src/Verify/VerifySlide.vue +++ b/yudao-ui-admin-vue3/src/components/Verifition/src/Verify/VerifySlide.vue @@ -242,7 +242,6 @@ export default { //兼容移动端 var x = e.touches[0].pageX } - console.log(barArea) startLeft.value = Math.floor(x - barArea.value.getBoundingClientRect().left) startMoveTime.value = +new Date() //开始滑动的时间 if (isEnd.value == false) { diff --git a/yudao-ui-admin-vue3/src/config/axios/index.ts b/yudao-ui-admin-vue3/src/config/axios/index.ts index 8396105957..123a7fbe84 100644 --- a/yudao-ui-admin-vue3/src/config/axios/index.ts +++ b/yudao-ui-admin-vue3/src/config/axios/index.ts @@ -1,10 +1,11 @@ import axios, { AxiosInstance, AxiosRequestConfig, AxiosResponse, AxiosError } from 'axios' -import { ElMessage, ElNotification } from 'element-plus' +import { ElMessage, ElMessageBox, ElNotification } from 'element-plus' import qs from 'qs' import { config } from '@/config/axios/config' -import { getAccessToken, getTenantId, removeToken } from '@/utils/auth' +import { getAccessToken, getRefreshToken, getTenantId, removeToken, setToken } from '@/utils/auth' import errorCode from './errorCode' import { useI18n } from '@/hooks/web/useI18n' +import { resetRouter } from '@/router' const tenantEnable = import.meta.env.VITE_APP_TENANT_ENABLE const BASE_URL = import.meta.env.VITE_BASE_URL @@ -20,9 +21,9 @@ const ignoreMsgs = [ export const isRelogin = { show: false } // Axios 无感知刷新令牌,参考 https://www.dashingdog.cn/article/11 与 https://segmentfault.com/a/1190000020210980 实现 // 请求队列 -// const requestList = [] +let requestList: any[] = [] // 是否正在刷新中 -// const isRefreshToken = false +let isRefreshToken = false export const PATH_URL = base_url[import.meta.env.VITE_API_BASEPATH] @@ -91,6 +92,7 @@ service.interceptors.request.use( service.interceptors.response.use( async (response: AxiosResponse) => { const { data } = response + console.info(data) if (!data) { // 返回“[HTTP]请求没有返回值”; throw new Error() @@ -112,16 +114,38 @@ service.interceptors.response.use( return Promise.reject(msg) } else if (code === 401) { // 如果未认证,并且未进行刷新令牌,说明可能是访问令牌过期了 - return handleAuthorized() - // if (!isRefreshToken) { - // isRefreshToken = true - // // 1. 如果获取不到刷新令牌,则只能执行登出操作 - // if (!getRefreshToken()) { - // return handleAuthorized() - // } - // // 2. 进行刷新访问令牌 - // // TODO: 引入refreshToken会循环依赖报错 - // } + if (!isRefreshToken) { + isRefreshToken = true + // 1. 如果获取不到刷新令牌,则只能执行登出操作 + if (!getRefreshToken()) { + return handleAuthorized() + } + // 2. 进行刷新访问令牌 + try { + const refreshTokenRes = await refreshToken() + // 2.1 刷新成功,则回放队列的请求 + 当前请求 + setToken(refreshTokenRes.data) + requestList.forEach((cb: any) => cb()) + return service(response.config) + } catch (e) { + // 为什么需要 catch 异常呢?刷新失败时,请求因为 Promise.reject 触发异常。 + // 2.2 刷新失败,只回放队列的请求 + requestList.forEach((cb: any) => cb()) + // 提示是否要登出。即不回放当前请求!不然会形成递归 + return handleAuthorized() + } finally { + requestList = [] + isRefreshToken = false + } + } else { + // 添加到队列,等待刷新获取到新的令牌 + return new Promise((resolve) => { + requestList.push(() => { + ;(config as Recordable).headers.Authorization = 'Bearer ' + getAccessToken() // 让每个请求携带自定义token 请根据实际情况自行修改 + resolve(service(response.config)) + }) + }) + } } else if (code === 500) { ElMessage.error(t('sys.api.errMsg500')) return Promise.reject(new Error(msg)) @@ -165,14 +189,32 @@ service.interceptors.response.use( return Promise.reject(error) } ) + +const refreshToken = async () => { + return await service({ + url: '/system/auth/refresh-token?refreshToken=' + getRefreshToken(), + method: 'post' + }) +} const handleAuthorized = () => { const { t } = useI18n() if (!isRelogin.show) { - removeToken() isRelogin.show = true - ElNotification.error(t('sys.api.timeoutMessage')) + ElMessageBox.confirm(t('sys.api.timeoutMessage'), t('common.confirmTitle'), { + confirmButtonText: t('login.relogin'), + cancelButtonText: t('common.cancel'), + type: 'warning' + }) + .then(() => { + removeToken() + resetRouter() // 重置静态路由表 + isRelogin.show = false + location.href = '/' + }) + .catch(() => { + isRelogin.show = false + }) } - location.href = '/' return Promise.reject(t('sys.api.timeoutMessage')) } export { service } diff --git a/yudao-ui-admin-vue3/src/router/index.ts b/yudao-ui-admin-vue3/src/router/index.ts index 812ec4f7a5..022042eebe 100644 --- a/yudao-ui-admin-vue3/src/router/index.ts +++ b/yudao-ui-admin-vue3/src/router/index.ts @@ -10,6 +10,7 @@ import { createRouter, createWebHashHistory } from 'vue-router' import { usePermissionStoreWithOut } from '@/store/modules/permission' import { useDictStoreWithOut } from '@/store/modules/dict' import { listSimpleDictDataApi } from '@/api/system/dict/dict.data' +import { isRelogin } from '@/config/axios' const permissionStore = usePermissionStoreWithOut() @@ -48,14 +49,14 @@ router.beforeEach(async (to, from, next) => { next({ path: '/' }) } else { if (!dictStore.getIsSetDict) { + isRelogin.show = true // 获取所有字典 const res = await listSimpleDictDataApi() - if (res) { - dictStore.setDictMap(res) - dictStore.setIsSetDict(true) - } + dictStore.setDictMap(res) + dictStore.setIsSetDict(true) } if (permissionStore.getIsAddRouters) { + isRelogin.show = false next() return } @@ -77,7 +78,7 @@ router.beforeEach(async (to, from, next) => { if (whiteList.indexOf(to.path) !== -1) { next() } else { - next(`/login?redirect=${to.path}`) // 否则全部重定向到登录页 + next(`/login?redirect=${to.fullPath}`) // 否则全部重定向到登录页 } } }) diff --git a/yudao-ui-admin-vue3/src/views/Profile/components/UserAvatar.vue b/yudao-ui-admin-vue3/src/views/Profile/components/UserAvatar.vue index 4cdfb14840..b7a08de3a3 100644 --- a/yudao-ui-admin-vue3/src/views/Profile/components/UserAvatar.vue +++ b/yudao-ui-admin-vue3/src/views/Profile/components/UserAvatar.vue @@ -6,12 +6,12 @@ import { ElRow, ElCol, ElUpload, ElMessage, ElDialog } from 'element-plus' import { propTypes } from '@/utils/propTypes' import { uploadAvatarApi } from '@/api/system/user/profile' const cropper = ref() +const dialogVisible = ref(false) +const cropperVisible = ref(false) const props = defineProps({ img: propTypes.string.def('') }) -const state = reactive({ - dialogVisible: false, - cropperVisible: false, +const options = reactive({ dialogTitle: '编辑头像', options: { img: props.img, //裁剪图片的地址 @@ -27,8 +27,11 @@ const state = reactive({ }) /** 编辑头像 */ const editCropper = () => { - state.dialogVisible = true - state.cropperVisible = true + dialogVisible.value = true +} +// 打开弹出层结束时的回调 +const modalOpened = () => { + cropperVisible.value = true } /** 向左旋转 */ const rotateLeft = () => { @@ -44,7 +47,7 @@ const changeScale = (num: number) => { cropper.value.changeScale(num) } // 覆盖默认的上传行为 -const requestUpload = () => {} +const requestUpload: any = () => {} /** 上传预处理 */ const beforeUpload = (file: Blob) => { if (file.type.indexOf('image/') == -1) { @@ -54,64 +57,65 @@ const beforeUpload = (file: Blob) => { reader.readAsDataURL(file) reader.onload = () => { if (reader.result) { - state.options.img = reader.result as string + options.options.img = reader.result as string } } } } /** 上传图片 */ const uploadImg = () => { - cropper.value.getCropBlob((data) => { + cropper.value.getCropBlob((data: any) => { let formData = new FormData() formData.append('avatarfile', data) uploadAvatarApi(formData) }) } /** 实时预览 */ -const realTime = (data) => { - state.previews = data +const realTime = (data: any) => { + options.previews = data } watch( () => props.img, () => { if (props.img) { - state.options.img = props.img - state.previews.img = props.img - state.previews.url = props.img + options.options.img = props.img + options.previews.img = props.img + options.previews.url = props.img } } ) + diff --git a/yudao-ui-admin-vue3/src/components/Verifition/src/Verify/VerifyPoints.vue b/yudao-ui-admin-vue3/src/components/Verifition/src/Verify/VerifyPoints.vue new file mode 100644 index 0000000000..36fdae889a --- /dev/null +++ b/yudao-ui-admin-vue3/src/components/Verifition/src/Verify/VerifyPoints.vue @@ -0,0 +1,279 @@ + + diff --git a/yudao-ui-admin-vue3/src/components/Verifition/src/Verify/VerifySlide.vue b/yudao-ui-admin-vue3/src/components/Verifition/src/Verify/VerifySlide.vue new file mode 100644 index 0000000000..a31f4587f5 --- /dev/null +++ b/yudao-ui-admin-vue3/src/components/Verifition/src/Verify/VerifySlide.vue @@ -0,0 +1,422 @@ + + diff --git a/yudao-ui-admin-vue3/src/components/Verifition/src/Verify/index.ts b/yudao-ui-admin-vue3/src/components/Verifition/src/Verify/index.ts new file mode 100644 index 0000000000..0daa63a560 --- /dev/null +++ b/yudao-ui-admin-vue3/src/components/Verifition/src/Verify/index.ts @@ -0,0 +1,4 @@ +import VerifySlide from './VerifySlide.vue' +import VerifyPoints from './VerifyPoints.vue' + +export { VerifySlide, VerifyPoints } diff --git a/yudao-ui-admin-vue3/src/components/Verifition/src/api/index.ts b/yudao-ui-admin-vue3/src/components/Verifition/src/api/index.ts new file mode 100644 index 0000000000..6a67b71199 --- /dev/null +++ b/yudao-ui-admin-vue3/src/components/Verifition/src/api/index.ts @@ -0,0 +1,24 @@ +/** + * 此处可直接引用自己项目封装好的 axios 配合后端联调 + */ + +import request from './../utils/axios' //组件内部封装的axios +// import request from "@/api/axios.js" //调用项目封装的axios + +//获取验证图片 以及token +export function reqGet(data) { + return request({ + url: '/captcha/get', + method: 'post', + data + }) +} + +//滑动或者点选验证 +export function reqCheck(data) { + return request({ + url: '/captcha/check', + method: 'post', + data + }) +} diff --git a/yudao-ui-admin-vue3/src/components/Verifition/src/utils/ase.ts b/yudao-ui-admin-vue3/src/components/Verifition/src/utils/ase.ts new file mode 100644 index 0000000000..d2e6b988f1 --- /dev/null +++ b/yudao-ui-admin-vue3/src/components/Verifition/src/utils/ase.ts @@ -0,0 +1,14 @@ +import CryptoJS from 'crypto-js' +/** + * @word 要加密的内容 + * @keyWord String 服务器随机返回的关键字 + * */ +export function aesEncrypt(word, keyWord = 'XwKsGlMcdPMEhR1B') { + const key = CryptoJS.enc.Utf8.parse(keyWord) + const srcs = CryptoJS.enc.Utf8.parse(word) + const encrypted = CryptoJS.AES.encrypt(srcs, key, { + mode: CryptoJS.mode.ECB, + padding: CryptoJS.pad.Pkcs7 + }) + return encrypted.toString() +} diff --git a/yudao-ui-admin-vue3/src/components/Verifition/src/utils/axios.ts b/yudao-ui-admin-vue3/src/components/Verifition/src/utils/axios.ts new file mode 100644 index 0000000000..ca68097e76 --- /dev/null +++ b/yudao-ui-admin-vue3/src/components/Verifition/src/utils/axios.ts @@ -0,0 +1,26 @@ +import axios from 'axios' + +axios.defaults.baseURL = import.meta.env.VITE_BASE_URL + +const service = axios.create({ + timeout: 40000, + headers: { + 'X-Requested-With': 'XMLHttpRequest', + 'Content-Type': 'application/json; charset=UTF-8' + } +}) +service.interceptors.request.use( + (config) => { + return config + }, + (error) => { + Promise.reject(error) + } +) + +// response interceptor +service.interceptors.response.use((response) => { + const res = response.data + return res +}) +export default service diff --git a/yudao-ui-admin-vue3/src/components/Verifition/src/utils/util.ts b/yudao-ui-admin-vue3/src/components/Verifition/src/utils/util.ts new file mode 100644 index 0000000000..15c16270df --- /dev/null +++ b/yudao-ui-admin-vue3/src/components/Verifition/src/utils/util.ts @@ -0,0 +1,97 @@ +export function resetSize(vm) { + let img_width, img_height, bar_width, bar_height //图片的宽度、高度,移动条的宽度、高度 + const EmployeeWindow = window as any + const parentWidth = vm.$el.parentNode.offsetWidth || EmployeeWindow.offsetWidth + const parentHeight = vm.$el.parentNode.offsetHeight || EmployeeWindow.offsetHeight + if (vm.imgSize.width.indexOf('%') != -1) { + img_width = (parseInt(vm.imgSize.width) / 100) * parentWidth + 'px' + } else { + img_width = vm.imgSize.width + } + + if (vm.imgSize.height.indexOf('%') != -1) { + img_height = (parseInt(vm.imgSize.height) / 100) * parentHeight + 'px' + } else { + img_height = vm.imgSize.height + } + + if (vm.barSize.width.indexOf('%') != -1) { + bar_width = (parseInt(vm.barSize.width) / 100) * parentWidth + 'px' + } else { + bar_width = vm.barSize.width + } + + if (vm.barSize.height.indexOf('%') != -1) { + bar_height = (parseInt(vm.barSize.height) / 100) * parentHeight + 'px' + } else { + bar_height = vm.barSize.height + } + + return { imgWidth: img_width, imgHeight: img_height, barWidth: bar_width, barHeight: bar_height } +} + +export const _code_chars = [ + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 'a', + 'b', + 'c', + 'd', + 'e', + 'f', + 'g', + 'h', + 'i', + 'j', + 'k', + 'l', + 'm', + 'n', + 'o', + 'p', + 'q', + 'r', + 's', + 't', + 'u', + 'v', + 'w', + 'x', + 'y', + 'z', + 'A', + 'B', + 'C', + 'D', + 'E', + 'F', + 'G', + 'H', + 'I', + 'J', + 'K', + 'L', + 'M', + 'N', + 'O', + 'P', + 'Q', + 'R', + 'S', + 'T', + 'U', + 'V', + 'W', + 'X', + 'Y', + 'Z' +] +export const _code_color1 = ['#fffff0', '#f0ffff', '#f0fff0', '#fff0f0'] +export const _code_color2 = ['#FF0033', '#006699', '#993366', '#FF9900', '#66CC66', '#FF33CC'] diff --git a/yudao-ui-admin-vue3/src/views/Login/components/LoginForm.vue b/yudao-ui-admin-vue3/src/views/Login/components/LoginForm.vue index bb876e0a3c..0a43fa675f 100644 --- a/yudao-ui-admin-vue3/src/views/Login/components/LoginForm.vue +++ b/yudao-ui-admin-vue3/src/views/Login/components/LoginForm.vue @@ -30,6 +30,7 @@ import { required } from '@/utils/formRules' import { Icon } from '@/components/Icon' import { LoginStateEnum, useLoginState, useFormValid } from './useLogin' import type { RouteLocationNormalizedLoaded, RouteRecordRaw } from 'vue-router' +import { Verify } from '@/components/Verifition' const { currentRoute, addRoute, push } = useRouter() const permissionStore = usePermissionStore() @@ -46,12 +47,10 @@ const { t } = useI18n() const iconHouse = useIcon({ icon: 'ep:house' }) const iconAvatar = useIcon({ icon: 'ep:avatar' }) const iconLock = useIcon({ icon: 'ep:lock' }) -const iconCircleCheck = useIcon({ icon: 'ep:circle-check' }) const LoginCaptchaRules = { tenantName: [required], username: [required], - password: [required], - code: [required] + password: [required] } const LoginRules = { tenantName: [required], @@ -60,7 +59,6 @@ const LoginRules = { } const loginLoading = ref(false) const loginData = reactive({ - codeImg: '', isShowPassword: false, captchaEnable: true, tenantEnable: true, @@ -72,20 +70,16 @@ const loginData = reactive({ tenantName: '芋道源码', username: 'admin', password: 'admin123', - rememberMe: false, - code: '', - uuid: '' + rememberMe: false } }) +// blockPuzzle 滑块 clickWord 点击文字 +const verify = ref() +const captchaType = ref('blockPuzzle') // 获取验证码 const getCode = async () => { - const res = await LoginApi.getCodeImgApi() - loginData.captchaEnable = res.enable - if (res.enable) { - loginData.codeImg = 'data:image/gif;base64,' + res.img - loginData.loginForm.uuid = res.uuid - } + verify.value.show() } //获取租户ID const getTenantId = async () => { @@ -112,19 +106,12 @@ const handleLogin = async () => { const data = await validForm() if (!data) return loginLoading.value = true - await LoginApi.loginApi(loginData.loginForm) - .then(async (res) => { - setToken(res) - const userInfo = await LoginApi.getInfoApi() - await userStore.getUserInfoAction(userInfo) - await getRoutes() - }) - .catch(() => { - getCode() - }) - .finally(() => { - loginLoading.value = false - }) + const res = await LoginApi.loginApi(loginData.loginForm) + setToken(res) + const userInfo = await LoginApi.getInfoApi() + await userStore.getUserInfoAction(userInfo) + await getRoutes() + loginLoading.value = false } // 获取路由 @@ -159,8 +146,7 @@ watch( immediate: true } ) -onMounted(async () => { - await getCode() +onMounted(() => { getCookie() }) @@ -207,31 +193,11 @@ onMounted(async () => { type="password" :placeholder="t('login.passwordPlaceholder')" show-password - @keyup.enter="handleLogin" + @keyup.enter="getCode()" :prefix-icon="iconLock" /> - - - - - - - - - - - - { - + {{ t('login.login') }} + From 6b2fbdf8c1db18609b301f1e7e8fb8427aa85c84 Mon Sep 17 00:00:00 2001 From: xingyu Date: Tue, 2 Aug 2022 17:17:53 +0800 Subject: [PATCH 041/135] =?UTF-8?q?=E4=BC=98=E5=8C=96=E8=A1=8C=E4=B8=BA?= =?UTF-8?q?=E9=AA=8C=E8=AF=81=E7=A0=81=E9=85=8D=E7=BD=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- yudao-server/src/main/resources/application.yaml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/yudao-server/src/main/resources/application.yaml b/yudao-server/src/main/resources/application.yaml index 06a66388ed..e510a68cad 100644 --- a/yudao-server/src/main/resources/application.yaml +++ b/yudao-server/src/main/resources/application.yaml @@ -75,18 +75,18 @@ aj: cache-number: 1000 # local定时清除过期缓存(单位秒),设置为0代表不执行 timing-clear: 180 - # 验证码类型default两种都实例化。 - type: default - # 右下角水印文字(我的水印)https://tool.chinaz.com/tools/unicode.aspx 中文转Unicode + # 验证码类型 default两种都实例化。 blockPuzzle 滑块拼图 clickWord 文字点选 + type: blockPuzzle + # 右下角水印文字(我的水印)https://tool.chinaz.com/tools/unicode.aspx 中文转Unicode Linux可能需要转unicode water-mark: 芋道源码 # 滑动干扰项(0/1/2) interference-options: 2 # 接口请求次数一分钟限制是否开启 true|false - req-frequency-limit-enable: false + req-frequency-limit-enable: true # 验证失败5次,get接口锁定 req-get-lock-limit: 5 # 验证失败后,锁定时间间隔,s - req-get-lock-seconds: 360 + req-get-lock-seconds: 10 # get接口一分钟内请求数限制 req-get-minute-limit: 30 # check接口一分钟内请求数限制 From a1f10e68f54f5d67ffcc8f9b48a2235b1f905617 Mon Sep 17 00:00:00 2001 From: xingyu Date: Tue, 2 Aug 2022 17:33:38 +0800 Subject: [PATCH 042/135] perf: remove console --- yudao-ui-admin-vue3/src/hooks/web/useAxios.ts | 6 ------ 1 file changed, 6 deletions(-) diff --git a/yudao-ui-admin-vue3/src/hooks/web/useAxios.ts b/yudao-ui-admin-vue3/src/hooks/web/useAxios.ts index 2769d275a8..331969c6e0 100644 --- a/yudao-ui-admin-vue3/src/hooks/web/useAxios.ts +++ b/yudao-ui-admin-vue3/src/hooks/web/useAxios.ts @@ -20,37 +20,31 @@ const request = (option: AxiosConfig) => { async function getFn(option: AxiosConfig): Promise { const res = await request({ method: 'GET', ...option }) - console.info(res) return res.data } async function postFn(option: AxiosConfig): Promise { const res = await request({ method: 'POST', ...option }) - console.info(res) return res.data } async function deleteFn(option: AxiosConfig): Promise { const res = await request({ method: 'DELETE', ...option }) - console.info(res) return res.data } async function putFn(option: AxiosConfig): Promise { const res = await request({ method: 'PUT', ...option }) - console.info(res) return res.data } async function downloadFn(option: AxiosConfig): Promise { const res = await request({ method: 'GET', responseType: 'blob', ...option }) - console.info(res) return res as unknown as Promise } async function uploadFn(option: AxiosConfig): Promise { option.headersType = 'multipart/form-data' const res = await request({ method: 'PUT', ...option }) - console.info(res) return res as unknown as Promise } From 5ce8e6436997271585656959ec5aec9d656c5e23 Mon Sep 17 00:00:00 2001 From: xingyu Date: Tue, 2 Aug 2022 18:27:23 +0800 Subject: [PATCH 043/135] fix: axios config --- .../src/main/resources/application-local.yaml | 38 +++++++++---------- yudao-ui-admin-vue3/src/config/axios/index.ts | 1 + 2 files changed, 20 insertions(+), 19 deletions(-) diff --git a/yudao-server/src/main/resources/application-local.yaml b/yudao-server/src/main/resources/application-local.yaml index 0735842759..1cfcdf2a2e 100644 --- a/yudao-server/src/main/resources/application-local.yaml +++ b/yudao-server/src/main/resources/application-local.yaml @@ -45,33 +45,33 @@ spring: datasource: master: name: ruoyi-vue-pro - url: jdbc:mysql://127.0.0.1:3306/${spring.datasource.dynamic.datasource.master.name}?allowMultiQueries=true&useUnicode=true&useSSL=false&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&autoReconnect=true&nullCatalogMeansCurrent=true # MySQL Connector/J 8.X 连接的示例 -# url: jdbc:mysql://127.0.0.1:3306/${spring.datasource.dynamic.datasource.master.name}?useSSL=false&allowPublicKeyRetrieval=true&useUnicode=true&characterEncoding=UTF-8&serverTimezone=CTT # MySQL Connector/J 5.X 连接的示例 -# url: jdbc:postgresql://127.0.0.1:5432/${spring.datasource.dynamic.datasource.slave.name} # PostgreSQL 连接的示例 -# url: jdbc:oracle:thin:@127.0.0.1:1521:xe # Oracle 连接的示例 -# url: jdbc:sqlserver://127.0.0.1:1433;DatabaseName=${spring.datasource.dynamic.datasource.master.name} # SQLServer 连接的示例 + url: jdbc:mysql://39.107.87.6:3306/${spring.datasource.dynamic.datasource.master.name}?allowMultiQueries=true&useUnicode=true&useSSL=false&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&autoReconnect=true&nullCatalogMeansCurrent=true # MySQL Connector/J 8.X 连接的示例 + # url: jdbc:mysql://127.0.0.1:3306/${spring.datasource.dynamic.datasource.master.name}?useSSL=false&allowPublicKeyRetrieval=true&useUnicode=true&characterEncoding=UTF-8&serverTimezone=CTT # MySQL Connector/J 5.X 连接的示例 + # url: jdbc:postgresql://127.0.0.1:5432/${spring.datasource.dynamic.datasource.slave.name} # PostgreSQL 连接的示例 + # url: jdbc:oracle:thin:@127.0.0.1:1521:xe # Oracle 连接的示例 + # url: jdbc:sqlserver://127.0.0.1:1433;DatabaseName=${spring.datasource.dynamic.datasource.master.name} # SQLServer 连接的示例 username: root - password: 123456 -# username: sa -# password: JSm:g(*%lU4ZAkz06cd52KqT3)i1?H7W + password: Root@xingyu123 + # username: sa + # password: JSm:g(*%lU4ZAkz06cd52KqT3)i1?H7W slave: # 模拟从库,可根据自己需要修改 name: ruoyi-vue-pro - url: jdbc:mysql://127.0.0.1:3306/${spring.datasource.dynamic.datasource.slave.name}?allowMultiQueries=true&useUnicode=true&useSSL=false&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&autoReconnect=true&nullCatalogMeansCurrent=true # MySQL Connector/J 8.X 连接的示例 -# url: jdbc:mysql://127.0.0.1:3306/${spring.datasource.dynamic.datasource.slave.name}?useSSL=false&allowPublicKeyRetrieval=true&useUnicode=true&characterEncoding=UTF-8&serverTimezone=CTT # MySQL Connector/J 5.X 连接的示例 -# url: jdbc:postgresql://127.0.0.1:5432/${spring.datasource.dynamic.datasource.slave.name} # PostgreSQL 连接的示例 -# url: jdbc:oracle:thin:@127.0.0.1:1521:xe # Oracle 连接的示例 -# url: jdbc:sqlserver://127.0.0.1:1433;DatabaseName=${spring.datasource.dynamic.datasource.slave.name} # SQLServer 连接的示例 + url: jdbc:mysql://39.107.87.6:3306/${spring.datasource.dynamic.datasource.slave.name}?allowMultiQueries=true&useUnicode=true&useSSL=false&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&autoReconnect=true&nullCatalogMeansCurrent=true # MySQL Connector/J 8.X 连接的示例 + # url: jdbc:mysql://127.0.0.1:3306/${spring.datasource.dynamic.datasource.slave.name}?useSSL=false&allowPublicKeyRetrieval=true&useUnicode=true&characterEncoding=UTF-8&serverTimezone=CTT # MySQL Connector/J 5.X 连接的示例 + # url: jdbc:postgresql://127.0.0.1:5432/${spring.datasource.dynamic.datasource.slave.name} # PostgreSQL 连接的示例 + # url: jdbc:oracle:thin:@127.0.0.1:1521:xe # Oracle 连接的示例 + # url: jdbc:sqlserver://127.0.0.1:1433;DatabaseName=${spring.datasource.dynamic.datasource.slave.name} # SQLServer 连接的示例 username: root - password: 123456 -# username: sa -# password: JSm:g(*%lU4ZAkz06cd52KqT3)i1?H7W + password: Root@xingyu123 +# username: sa +# password: JSm:g(*%lU4ZAkz06cd52KqT3)i1?H7W # Redis 配置。Redisson 默认的配置足够使用,一般不需要进行调优 redis: - host: 127.0.0.1 # 地址 + host: 39.107.87.6 # 地址 port: 6379 # 端口 - database: 0 # 数据库索引 -# password: 123456 # 密码,建议生产环境开启 + database: 4 # 数据库索引 + password: xingyu # 密码,建议生产环境开启 jasypt: encryptor: diff --git a/yudao-ui-admin-vue3/src/config/axios/index.ts b/yudao-ui-admin-vue3/src/config/axios/index.ts index 14bd90bad4..8396105957 100644 --- a/yudao-ui-admin-vue3/src/config/axios/index.ts +++ b/yudao-ui-admin-vue3/src/config/axios/index.ts @@ -172,6 +172,7 @@ const handleAuthorized = () => { isRelogin.show = true ElNotification.error(t('sys.api.timeoutMessage')) } + location.href = '/' return Promise.reject(t('sys.api.timeoutMessage')) } export { service } From 85e21092b85ed72f29de70800c45053f85435502 Mon Sep 17 00:00:00 2001 From: xingyu Date: Tue, 2 Aug 2022 12:49:41 +0000 Subject: [PATCH 044/135] =?UTF-8?q?=E5=88=A0=E9=99=A4=E6=96=87=E4=BB=B6=20?= =?UTF-8?q?yudao-server/src/main/resources/application-local.yaml?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/main/resources/application-local.yaml | 240 ------------------ 1 file changed, 240 deletions(-) delete mode 100644 yudao-server/src/main/resources/application-local.yaml diff --git a/yudao-server/src/main/resources/application-local.yaml b/yudao-server/src/main/resources/application-local.yaml deleted file mode 100644 index 1cfcdf2a2e..0000000000 --- a/yudao-server/src/main/resources/application-local.yaml +++ /dev/null @@ -1,240 +0,0 @@ -server: - port: 48080 - ---- #################### 数据库相关配置 #################### - -spring: - # 数据源配置项 - autoconfigure: - exclude: - - com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceAutoConfigure # 排除 Druid 的自动配置,使用 dynamic-datasource-spring-boot-starter 配置多数据源 - - org.springframework.boot.autoconfigure.mongo.MongoAutoConfiguration # 排除积木报表带来的 MongoDB 的自动配置 - datasource: - druid: # Druid 【监控】相关的全局配置 - web-stat-filter: - enabled: true - stat-view-servlet: - enabled: true - allow: # 设置白名单,不填则允许所有访问 - url-pattern: /druid/* - login-username: # 控制台管理用户名和密码 - login-password: - filter: - stat: - enabled: true - log-slow-sql: true # 慢 SQL 记录 - slow-sql-millis: 100 - merge-sql: true - wall: - config: - multi-statement-allow: true - dynamic: # 多数据源配置 - druid: # Druid 【连接池】相关的全局配置 - initial-size: 5 # 初始连接数 - min-idle: 10 # 最小连接池数量 - max-active: 20 # 最大连接池数量 - max-wait: 600000 # 配置获取连接等待超时的时间,单位:毫秒 - time-between-eviction-runs-millis: 60000 # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位:毫秒 - min-evictable-idle-time-millis: 300000 # 配置一个连接在池中最小生存的时间,单位:毫秒 - max-evictable-idle-time-millis: 900000 # 配置一个连接在池中最大生存的时间,单位:毫秒 - validation-query: SELECT 1 FROM DUAL # 配置检测连接是否有效 - test-while-idle: true - test-on-borrow: false - test-on-return: false - primary: master - datasource: - master: - name: ruoyi-vue-pro - url: jdbc:mysql://39.107.87.6:3306/${spring.datasource.dynamic.datasource.master.name}?allowMultiQueries=true&useUnicode=true&useSSL=false&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&autoReconnect=true&nullCatalogMeansCurrent=true # MySQL Connector/J 8.X 连接的示例 - # url: jdbc:mysql://127.0.0.1:3306/${spring.datasource.dynamic.datasource.master.name}?useSSL=false&allowPublicKeyRetrieval=true&useUnicode=true&characterEncoding=UTF-8&serverTimezone=CTT # MySQL Connector/J 5.X 连接的示例 - # url: jdbc:postgresql://127.0.0.1:5432/${spring.datasource.dynamic.datasource.slave.name} # PostgreSQL 连接的示例 - # url: jdbc:oracle:thin:@127.0.0.1:1521:xe # Oracle 连接的示例 - # url: jdbc:sqlserver://127.0.0.1:1433;DatabaseName=${spring.datasource.dynamic.datasource.master.name} # SQLServer 连接的示例 - username: root - password: Root@xingyu123 - # username: sa - # password: JSm:g(*%lU4ZAkz06cd52KqT3)i1?H7W - slave: # 模拟从库,可根据自己需要修改 - name: ruoyi-vue-pro - url: jdbc:mysql://39.107.87.6:3306/${spring.datasource.dynamic.datasource.slave.name}?allowMultiQueries=true&useUnicode=true&useSSL=false&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&autoReconnect=true&nullCatalogMeansCurrent=true # MySQL Connector/J 8.X 连接的示例 - # url: jdbc:mysql://127.0.0.1:3306/${spring.datasource.dynamic.datasource.slave.name}?useSSL=false&allowPublicKeyRetrieval=true&useUnicode=true&characterEncoding=UTF-8&serverTimezone=CTT # MySQL Connector/J 5.X 连接的示例 - # url: jdbc:postgresql://127.0.0.1:5432/${spring.datasource.dynamic.datasource.slave.name} # PostgreSQL 连接的示例 - # url: jdbc:oracle:thin:@127.0.0.1:1521:xe # Oracle 连接的示例 - # url: jdbc:sqlserver://127.0.0.1:1433;DatabaseName=${spring.datasource.dynamic.datasource.slave.name} # SQLServer 连接的示例 - username: root - password: Root@xingyu123 -# username: sa -# password: JSm:g(*%lU4ZAkz06cd52KqT3)i1?H7W - - # Redis 配置。Redisson 默认的配置足够使用,一般不需要进行调优 - redis: - host: 39.107.87.6 # 地址 - port: 6379 # 端口 - database: 4 # 数据库索引 - password: xingyu # 密码,建议生产环境开启 - -jasypt: - encryptor: - password: yuanma # 加解密的秘钥 - ---- #################### 定时任务相关配置 #################### - -# Quartz 配置项,对应 QuartzProperties 配置类 -spring: - quartz: - auto-startup: false # 本地开发环境,尽量不要开启 Job - scheduler-name: schedulerName # Scheduler 名字。默认为 schedulerName - job-store-type: jdbc # Job 存储器类型。默认为 memory 表示内存,可选 jdbc 使用数据库。 - wait-for-jobs-to-complete-on-shutdown: true # 应用关闭时,是否等待定时任务执行完成。默认为 false ,建议设置为 true - properties: # 添加 Quartz Scheduler 附加属性,更多可以看 http://www.quartz-scheduler.org/documentation/2.4.0-SNAPSHOT/configuration.html 文档 - org: - quartz: - # Scheduler 相关配置 - scheduler: - instanceName: schedulerName - instanceId: AUTO # 自动生成 instance ID - # JobStore 相关配置 - jobStore: - # JobStore 实现类。可见博客:https://blog.csdn.net/weixin_42458219/article/details/122247162 - class: org.springframework.scheduling.quartz.LocalDataSourceJobStore - isClustered: true # 是集群模式 - clusterCheckinInterval: 15000 # 集群检查频率,单位:毫秒。默认为 15000,即 15 秒 - misfireThreshold: 60000 # misfire 阀值,单位:毫秒。 - # 线程池相关配置 - threadPool: - threadCount: 25 # 线程池大小。默认为 10 。 - threadPriority: 5 # 线程优先级 - class: org.quartz.simpl.SimpleThreadPool # 线程池类型 - jdbc: # 使用 JDBC 的 JobStore 的时候,JDBC 的配置 - initialize-schema: NEVER # 是否自动使用 SQL 初始化 Quartz 表结构。这里设置成 never ,我们手动创建表结构。 - ---- #################### 配置中心相关配置 #################### - -# Apollo 配置中心 -apollo: - bootstrap: - enabled: true # 设置 Apollo 在启动阶段生效 - eagerLoad: - enabled: true # 设置 Apollo 在日志初始化前生效,可以实现日志的动态级别配置 - jdbc: # 自定义的 JDBC 配置项,用于数据库的地址 - dao: cn.iocoder.yudao.module.infra.dal.mysql.config.ConfigDAOImpl - url: ${spring.datasource.dynamic.datasource.master.url} - username: ${spring.datasource.dynamic.datasource.master.username} - password: ${spring.datasource.dynamic.datasource.master.password} - ---- #################### 服务保障相关配置 #################### - -# Lock4j 配置项 -lock4j: - acquire-timeout: 3000 # 获取分布式锁超时时间,默认为 3000 毫秒 - expire: 30000 # 分布式锁的超时时间,默认为 30 毫秒 - -# Resilience4j 配置项 -resilience4j: - ratelimiter: - instances: - backendA: - limit-for-period: 1 # 每个周期内,允许的请求数。默认为 50 - limit-refresh-period: 60s # 每个周期的时长,单位:微秒。默认为 500 - timeout-duration: 1s # 被限流时,阻塞等待的时长,单位:微秒。默认为 5s - register-health-indicator: true # 是否注册到健康监测 - ---- #################### 监控相关配置 #################### - -# Actuator 监控端点的配置项 -management: - endpoints: - web: - base-path: /actuator # Actuator 提供的 API 接口的根目录。默认为 /actuator - exposure: - include: '*' # 需要开放的端点。默认值只打开 health 和 info 两个端点。通过设置 * ,可以开放所有端点。 - -# Spring Boot Admin 配置项 -spring: - boot: - admin: - # Spring Boot Admin Client 客户端的相关配置 - client: - url: http://127.0.0.1:${server.port}/${spring.boot.admin.context-path} # 设置 Spring Boot Admin Server 地址 - instance: - service-host-type: IP # 注册实例时,优先使用 IP [IP, HOST_NAME, CANONICAL_HOST_NAME] - # Spring Boot Admin Server 服务端的相关配置 - context-path: /admin # 配置 Spring - -# 日志文件配置 -logging: - file: - name: ${user.home}/logs/${spring.application.name}.log # 日志文件名,全路径 - level: - # 配置自己写的 MyBatis Mapper 打印日志 - cn.iocoder.yudao.module.bpm.dal.mysql: debug - cn.iocoder.yudao.module.infra.dal.mysql: debug - cn.iocoder.yudao.module.pay.dal.mysql: debug - cn.iocoder.yudao.module.system.dal.mysql: debug - cn.iocoder.yudao.module.tool.dal.mysql: debug - cn.iocoder.yudao.module.member.dal.mysql: debug - ---- #################### 微信公众号、小程序相关配置 #################### -wx: - mp: # 公众号配置(必填),参见 https://github.com/Wechat-Group/WxJava/blob/develop/spring-boot-starters/wx-java-mp-spring-boot-starter/README.md 文档 - app-id: wx041349c6f39b268b - secret: 5abee519483bc9f8cb37ce280e814bd0 - # 存储配置,解决 AccessToken 的跨节点的共享 - config-storage: - type: RedisTemplate # 采用 RedisTemplate 操作 Redis,会自动从 Spring 中获取 - key-prefix: wx # Redis Key 的前缀 TODO 芋艿:解决下 Redis key 管理的配置 - http-client-type: HttpClient # 采用 HttpClient 请求微信公众号平台 - miniapp: # 小程序配置(必填),参见 https://github.com/Wechat-Group/WxJava/blob/develop/spring-boot-starters/wx-java-miniapp-spring-boot-starter/README.md 文档 - appid: wx63c280fe3248a3e7 - secret: 6f270509224a7ae1296bbf1c8cb97aed - config-storage: - type: RedisTemplate # 采用 RedisTemplate 操作 Redis,会自动从 Spring 中获取 - key-prefix: wa # Redis Key 的前缀 TODO 芋艿:解决下 Redis key 管理的配置 - http-client-type: HttpClient # 采用 HttpClient 请求微信公众号平台 - ---- #################### 芋道相关配置 #################### - -# 芋道配置项,设置当前项目所有自定义的配置 -yudao: - captcha: - enable: false # 本地环境,暂时关闭图片验证码,方便登录等接口的测试 - security: - mock-enable: true - xss: - enable: false - exclude-urls: # 如下两个 url,仅仅是为了演示,去掉配置也没关系 - - ${spring.boot.admin.context-path}/** # 不处理 Spring Boot Admin 的请求 - - ${management.endpoints.web.base-path}/** # 不处理 Actuator 的请求 - pay: - pay-notify-url: http://niubi.natapp1.cc/api/pay/order/notify - pay-return-url: http://niubi.natapp1.cc/api/pay/order/return - refund-notify-url: http://niubi.natapp1.cc/api/pay/refund/notify - access-log: # 访问日志的配置项 - enable: false - error-code: # 错误码相关配置项 - enable: false - demo: false # 关闭演示模式 - -justauth: - enabled: true - type: - DINGTALK: # 钉钉 - client-id: dingvrnreaje3yqvzhxg - client-secret: i8E6iZyDvZj51JIb0tYsYfVQYOks9Cq1lgryEjFRqC79P3iJcrxEwT6Qk2QvLrLI - ignore-check-redirect-uri: true - WECHAT_ENTERPRISE: # 企业微信 - client-id: wwd411c69a39ad2e54 - client-secret: 1wTb7hYxnpT2TUbIeHGXGo7T0odav1ic10mLdyyATOw - agent-id: 1000004 - ignore-check-redirect-uri: true - WECHAT_MINI_APP: # 微信小程序 - client-id: ${wx.miniapp.appid} - client-secret: ${wx.miniapp.secret} - ignore-check-redirect-uri: true - ignore-check-state: true # 微信小程序,不会使用到 state,所以不进行校验 - - cache: - type: REDIS - prefix: 'social_auth_state:' # 缓存前缀,目前只对 Redis 缓存生效,默认 JUSTAUTH::STATE:: - timeout: 24h # 超时时长,目前只对 Redis 缓存生效,默认 3 分钟 - From a8ea50a059289915b53319910e3c27c7e56c72e5 Mon Sep 17 00:00:00 2001 From: xingyu Date: Tue, 2 Aug 2022 20:58:08 +0800 Subject: [PATCH 045/135] update hutool 5.8.5 --- yudao-dependencies/pom.xml | 2 +- .../common/util/collection/ArrayUtils.java | 3 +- .../core/client/impl/AbstractPayClient.java | 5 +- .../src/main/resources/application-local.yaml | 240 ++++++++++++++++++ 4 files changed, 246 insertions(+), 4 deletions(-) create mode 100644 yudao-server/src/main/resources/application-local.yaml diff --git a/yudao-dependencies/pom.xml b/yudao-dependencies/pom.xml index 9bfaaadbd7..2e1d15f595 100644 --- a/yudao-dependencies/pom.xml +++ b/yudao-dependencies/pom.xml @@ -46,7 +46,7 @@ 3.0.4 1.18.20 1.4.1.Final - 5.7.22 + 5.8.5 3.1.1 2.2 1.0.5 diff --git a/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/collection/ArrayUtils.java b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/collection/ArrayUtils.java index 366f960084..4285b8f4c1 100644 --- a/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/collection/ArrayUtils.java +++ b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/collection/ArrayUtils.java @@ -1,6 +1,7 @@ package cn.iocoder.yudao.framework.common.util.collection; import cn.hutool.core.collection.CollectionUtil; +import cn.hutool.core.collection.IterUtil; import cn.hutool.core.util.ArrayUtil; import java.util.Collection; @@ -44,7 +45,7 @@ public class ArrayUtils { if (CollectionUtil.isEmpty(from)) { return (T[]) (new Object[0]); } - return ArrayUtil.toArray(from, (Class) CollectionUtil.getElementType(from.iterator())); + return ArrayUtil.toArray(from, (Class) IterUtil.getElementType(from.iterator())); } public static T get(T[] array, int index) { diff --git a/yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/AbstractPayClient.java b/yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/AbstractPayClient.java index 292b6cf01d..3253709c89 100644 --- a/yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/AbstractPayClient.java +++ b/yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/AbstractPayClient.java @@ -1,6 +1,5 @@ package cn.iocoder.yudao.framework.pay.core.client.impl; -import cn.hutool.extra.validation.ValidationUtil; import cn.iocoder.yudao.framework.pay.core.client.AbstractPayCodeMapping; import cn.iocoder.yudao.framework.pay.core.client.PayClient; import cn.iocoder.yudao.framework.pay.core.client.PayClientConfig; @@ -10,6 +9,8 @@ import cn.iocoder.yudao.framework.pay.core.client.dto.PayRefundUnifiedReqDTO; import cn.iocoder.yudao.framework.pay.core.client.dto.PayRefundUnifiedRespDTO; import lombok.extern.slf4j.Slf4j; +import javax.validation.Validation; + import static cn.iocoder.yudao.framework.common.util.json.JsonUtils.toJsonString; /** @@ -79,7 +80,7 @@ public abstract class AbstractPayClient implemen @Override public final PayCommonResult unifiedOrder(PayOrderUnifiedReqDTO reqDTO) { - ValidationUtil.validate(reqDTO); + Validation.buildDefaultValidatorFactory().getValidator().validate(reqDTO); // 执行短信发送 PayCommonResult result; try { diff --git a/yudao-server/src/main/resources/application-local.yaml b/yudao-server/src/main/resources/application-local.yaml new file mode 100644 index 0000000000..fb31aa3451 --- /dev/null +++ b/yudao-server/src/main/resources/application-local.yaml @@ -0,0 +1,240 @@ +server: + port: 48080 + +--- #################### 数据库相关配置 #################### + +spring: + # 数据源配置项 + autoconfigure: + exclude: + - com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceAutoConfigure # 排除 Druid 的自动配置,使用 dynamic-datasource-spring-boot-starter 配置多数据源 + - org.springframework.boot.autoconfigure.mongo.MongoAutoConfiguration # 排除积木报表带来的 MongoDB 的自动配置 + datasource: + druid: # Druid 【监控】相关的全局配置 + web-stat-filter: + enabled: true + stat-view-servlet: + enabled: true + allow: # 设置白名单,不填则允许所有访问 + url-pattern: /druid/* + login-username: # 控制台管理用户名和密码 + login-password: + filter: + stat: + enabled: true + log-slow-sql: true # 慢 SQL 记录 + slow-sql-millis: 100 + merge-sql: true + wall: + config: + multi-statement-allow: true + dynamic: # 多数据源配置 + druid: # Druid 【连接池】相关的全局配置 + initial-size: 5 # 初始连接数 + min-idle: 10 # 最小连接池数量 + max-active: 20 # 最大连接池数量 + max-wait: 600000 # 配置获取连接等待超时的时间,单位:毫秒 + time-between-eviction-runs-millis: 60000 # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位:毫秒 + min-evictable-idle-time-millis: 300000 # 配置一个连接在池中最小生存的时间,单位:毫秒 + max-evictable-idle-time-millis: 900000 # 配置一个连接在池中最大生存的时间,单位:毫秒 + validation-query: SELECT 1 FROM DUAL # 配置检测连接是否有效 + test-while-idle: true + test-on-borrow: false + test-on-return: false + primary: master + datasource: + master: + name: ruoyi-vue-pro + url: jdbc:mysql://127.0.0.1:3306/${spring.datasource.dynamic.datasource.master.name}?allowMultiQueries=true&useUnicode=true&useSSL=false&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&autoReconnect=true&nullCatalogMeansCurrent=true # MySQL Connector/J 8.X 连接的示例 + # url: jdbc:mysql://127.0.0.1:3306/${spring.datasource.dynamic.datasource.master.name}?useSSL=false&allowPublicKeyRetrieval=true&useUnicode=true&characterEncoding=UTF-8&serverTimezone=CTT # MySQL Connector/J 5.X 连接的示例 + # url: jdbc:postgresql://127.0.0.1:5432/${spring.datasource.dynamic.datasource.slave.name} # PostgreSQL 连接的示例 + # url: jdbc:oracle:thin:@127.0.0.1:1521:xe # Oracle 连接的示例 + # url: jdbc:sqlserver://127.0.0.1:1433;DatabaseName=${spring.datasource.dynamic.datasource.master.name} # SQLServer 连接的示例 + username: root + password: 123456 + # username: sa + # password: JSm:g(*%lU4ZAkz06cd52KqT3)i1?H7W + slave: # 模拟从库,可根据自己需要修改 + name: ruoyi-vue-pro + url: jdbc:mysql://127.0.0.1:3306/${spring.datasource.dynamic.datasource.slave.name}?allowMultiQueries=true&useUnicode=true&useSSL=false&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&autoReconnect=true&nullCatalogMeansCurrent=true # MySQL Connector/J 8.X 连接的示例 + # url: jdbc:mysql://127.0.0.1:3306/${spring.datasource.dynamic.datasource.slave.name}?useSSL=false&allowPublicKeyRetrieval=true&useUnicode=true&characterEncoding=UTF-8&serverTimezone=CTT # MySQL Connector/J 5.X 连接的示例 + # url: jdbc:postgresql://127.0.0.1:5432/${spring.datasource.dynamic.datasource.slave.name} # PostgreSQL 连接的示例 + # url: jdbc:oracle:thin:@127.0.0.1:1521:xe # Oracle 连接的示例 + # url: jdbc:sqlserver://127.0.0.1:1433;DatabaseName=${spring.datasource.dynamic.datasource.slave.name} # SQLServer 连接的示例 + username: root + password: 123456 + # username: sa + # password: JSm:g(*%lU4ZAkz06cd52KqT3)i1?H7W + + # Redis 配置。Redisson 默认的配置足够使用,一般不需要进行调优 + redis: + host: 127.0.0.1 # 地址 + port: 6379 # 端口 + database: 0 # 数据库索引 +# password: 123456 # 密码,建议生产环境开启 + +jasypt: + encryptor: + password: yuanma # 加解密的秘钥 + +--- #################### 定时任务相关配置 #################### + +# Quartz 配置项,对应 QuartzProperties 配置类 +spring: + quartz: + auto-startup: false # 本地开发环境,尽量不要开启 Job + scheduler-name: schedulerName # Scheduler 名字。默认为 schedulerName + job-store-type: jdbc # Job 存储器类型。默认为 memory 表示内存,可选 jdbc 使用数据库。 + wait-for-jobs-to-complete-on-shutdown: true # 应用关闭时,是否等待定时任务执行完成。默认为 false ,建议设置为 true + properties: # 添加 Quartz Scheduler 附加属性,更多可以看 http://www.quartz-scheduler.org/documentation/2.4.0-SNAPSHOT/configuration.html 文档 + org: + quartz: + # Scheduler 相关配置 + scheduler: + instanceName: schedulerName + instanceId: AUTO # 自动生成 instance ID + # JobStore 相关配置 + jobStore: + # JobStore 实现类。可见博客:https://blog.csdn.net/weixin_42458219/article/details/122247162 + class: org.springframework.scheduling.quartz.LocalDataSourceJobStore + isClustered: true # 是集群模式 + clusterCheckinInterval: 15000 # 集群检查频率,单位:毫秒。默认为 15000,即 15 秒 + misfireThreshold: 60000 # misfire 阀值,单位:毫秒。 + # 线程池相关配置 + threadPool: + threadCount: 25 # 线程池大小。默认为 10 。 + threadPriority: 5 # 线程优先级 + class: org.quartz.simpl.SimpleThreadPool # 线程池类型 + jdbc: # 使用 JDBC 的 JobStore 的时候,JDBC 的配置 + initialize-schema: NEVER # 是否自动使用 SQL 初始化 Quartz 表结构。这里设置成 never ,我们手动创建表结构。 + +--- #################### 配置中心相关配置 #################### + +# Apollo 配置中心 +apollo: + bootstrap: + enabled: true # 设置 Apollo 在启动阶段生效 + eagerLoad: + enabled: true # 设置 Apollo 在日志初始化前生效,可以实现日志的动态级别配置 + jdbc: # 自定义的 JDBC 配置项,用于数据库的地址 + dao: cn.iocoder.yudao.module.infra.dal.mysql.config.ConfigDAOImpl + url: ${spring.datasource.dynamic.datasource.master.url} + username: ${spring.datasource.dynamic.datasource.master.username} + password: ${spring.datasource.dynamic.datasource.master.password} + +--- #################### 服务保障相关配置 #################### + +# Lock4j 配置项 +lock4j: + acquire-timeout: 3000 # 获取分布式锁超时时间,默认为 3000 毫秒 + expire: 30000 # 分布式锁的超时时间,默认为 30 毫秒 + +# Resilience4j 配置项 +resilience4j: + ratelimiter: + instances: + backendA: + limit-for-period: 1 # 每个周期内,允许的请求数。默认为 50 + limit-refresh-period: 60s # 每个周期的时长,单位:微秒。默认为 500 + timeout-duration: 1s # 被限流时,阻塞等待的时长,单位:微秒。默认为 5s + register-health-indicator: true # 是否注册到健康监测 + +--- #################### 监控相关配置 #################### + +# Actuator 监控端点的配置项 +management: + endpoints: + web: + base-path: /actuator # Actuator 提供的 API 接口的根目录。默认为 /actuator + exposure: + include: '*' # 需要开放的端点。默认值只打开 health 和 info 两个端点。通过设置 * ,可以开放所有端点。 + +# Spring Boot Admin 配置项 +spring: + boot: + admin: + # Spring Boot Admin Client 客户端的相关配置 + client: + url: http://127.0.0.1:${server.port}/${spring.boot.admin.context-path} # 设置 Spring Boot Admin Server 地址 + instance: + service-host-type: IP # 注册实例时,优先使用 IP [IP, HOST_NAME, CANONICAL_HOST_NAME] + # Spring Boot Admin Server 服务端的相关配置 + context-path: /admin # 配置 Spring + +# 日志文件配置 +logging: + file: + name: ${user.home}/logs/${spring.application.name}.log # 日志文件名,全路径 + level: + # 配置自己写的 MyBatis Mapper 打印日志 + cn.iocoder.yudao.module.bpm.dal.mysql: debug + cn.iocoder.yudao.module.infra.dal.mysql: debug + cn.iocoder.yudao.module.pay.dal.mysql: debug + cn.iocoder.yudao.module.system.dal.mysql: debug + cn.iocoder.yudao.module.tool.dal.mysql: debug + cn.iocoder.yudao.module.member.dal.mysql: debug + +--- #################### 微信公众号、小程序相关配置 #################### +wx: + mp: # 公众号配置(必填),参见 https://github.com/Wechat-Group/WxJava/blob/develop/spring-boot-starters/wx-java-mp-spring-boot-starter/README.md 文档 + app-id: wx041349c6f39b268b + secret: 5abee519483bc9f8cb37ce280e814bd0 + # 存储配置,解决 AccessToken 的跨节点的共享 + config-storage: + type: RedisTemplate # 采用 RedisTemplate 操作 Redis,会自动从 Spring 中获取 + key-prefix: wx # Redis Key 的前缀 TODO 芋艿:解决下 Redis key 管理的配置 + http-client-type: HttpClient # 采用 HttpClient 请求微信公众号平台 + miniapp: # 小程序配置(必填),参见 https://github.com/Wechat-Group/WxJava/blob/develop/spring-boot-starters/wx-java-miniapp-spring-boot-starter/README.md 文档 + appid: wx63c280fe3248a3e7 + secret: 6f270509224a7ae1296bbf1c8cb97aed + config-storage: + type: RedisTemplate # 采用 RedisTemplate 操作 Redis,会自动从 Spring 中获取 + key-prefix: wa # Redis Key 的前缀 TODO 芋艿:解决下 Redis key 管理的配置 + http-client-type: HttpClient # 采用 HttpClient 请求微信公众号平台 + +--- #################### 芋道相关配置 #################### + +# 芋道配置项,设置当前项目所有自定义的配置 +yudao: + captcha: + enable: false # 本地环境,暂时关闭图片验证码,方便登录等接口的测试 + security: + mock-enable: true + xss: + enable: false + exclude-urls: # 如下两个 url,仅仅是为了演示,去掉配置也没关系 + - ${spring.boot.admin.context-path}/** # 不处理 Spring Boot Admin 的请求 + - ${management.endpoints.web.base-path}/** # 不处理 Actuator 的请求 + pay: + pay-notify-url: http://niubi.natapp1.cc/api/pay/order/notify + pay-return-url: http://niubi.natapp1.cc/api/pay/order/return + refund-notify-url: http://niubi.natapp1.cc/api/pay/refund/notify + access-log: # 访问日志的配置项 + enable: false + error-code: # 错误码相关配置项 + enable: false + demo: false # 关闭演示模式 + +justauth: + enabled: true + type: + DINGTALK: # 钉钉 + client-id: dingvrnreaje3yqvzhxg + client-secret: i8E6iZyDvZj51JIb0tYsYfVQYOks9Cq1lgryEjFRqC79P3iJcrxEwT6Qk2QvLrLI + ignore-check-redirect-uri: true + WECHAT_ENTERPRISE: # 企业微信 + client-id: wwd411c69a39ad2e54 + client-secret: 1wTb7hYxnpT2TUbIeHGXGo7T0odav1ic10mLdyyATOw + agent-id: 1000004 + ignore-check-redirect-uri: true + WECHAT_MINI_APP: # 微信小程序 + client-id: ${wx.miniapp.appid} + client-secret: ${wx.miniapp.secret} + ignore-check-redirect-uri: true + ignore-check-state: true # 微信小程序,不会使用到 state,所以不进行校验 + + cache: + type: REDIS + prefix: 'social_auth_state:' # 缓存前缀,目前只对 Redis 缓存生效,默认 JUSTAUTH::STATE:: + timeout: 24h # 超时时长,目前只对 Redis 缓存生效,默认 3 分钟 + From 2bf09cbfc2d69192039f70dcd5d24b6d87f6b039 Mon Sep 17 00:00:00 2001 From: xingyu Date: Tue, 2 Aug 2022 23:01:47 +0800 Subject: [PATCH 046/135] =?UTF-8?q?=E5=8D=87=E7=BA=A7=E9=83=A8=E5=88=86?= =?UTF-8?q?=E4=BE=9D=E8=B5=96=EF=BC=8C=E5=AD=98=E5=9C=A8=E9=AB=98=E5=8D=B1?= =?UTF-8?q?=E6=BC=8F=E6=B4=9E=E6=8A=A5=E9=94=99=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- yudao-dependencies/pom.xml | 10 +++++----- .../yudao-spring-boot-starter-biz-pay/pom.xml | 10 ++++++++-- .../yudao-spring-boot-starter-biz-weixin/pom.xml | 4 ++-- .../yudao-spring-boot-starter-captcha/pom.xml | 5 ----- 4 files changed, 15 insertions(+), 14 deletions(-) diff --git a/yudao-dependencies/pom.xml b/yudao-dependencies/pom.xml index 2e1d15f595..86b693affb 100644 --- a/yudao-dependencies/pom.xml +++ b/yudao-dependencies/pom.xml @@ -41,14 +41,14 @@ 0.1.16 4.0.0 - 6.7.0 + 6.7.2 3.0.4 1.18.20 1.4.1.Final 5.8.5 3.1.1 - 2.2 + 2.3 1.0.5 1.2.83 30.1.1-jre @@ -60,9 +60,9 @@ 1.3.0 8.2.2 - 4.5.25 - 2.1.0 - 3.1.471 + 4.6.0 + 2.2.1 + 3.1.561 1.2.7 1.4.0 1.5.2 diff --git a/yudao-framework/yudao-spring-boot-starter-biz-pay/pom.xml b/yudao-framework/yudao-spring-boot-starter-biz-pay/pom.xml index 4153c25c44..e6106b9d94 100644 --- a/yudao-framework/yudao-spring-boot-starter-biz-pay/pom.xml +++ b/yudao-framework/yudao-spring-boot-starter-biz-pay/pom.xml @@ -52,12 +52,18 @@ com.alipay.sdk alipay-sdk-java - 4.17.9.ALL + 4.31.72.ALL + + + org.bouncycastle + bcprov-jdk15on + + com.github.binarywang weixin-java-pay - 4.1.9.B + 4.3.8.B diff --git a/yudao-framework/yudao-spring-boot-starter-biz-weixin/pom.xml b/yudao-framework/yudao-spring-boot-starter-biz-weixin/pom.xml index 9572391db3..2dc2fe6881 100644 --- a/yudao-framework/yudao-spring-boot-starter-biz-weixin/pom.xml +++ b/yudao-framework/yudao-spring-boot-starter-biz-weixin/pom.xml @@ -35,12 +35,12 @@ com.github.binarywang wx-java-mp-spring-boot-starter - 4.3.4.B + 4.3.8.B com.github.binarywang wx-java-miniapp-spring-boot-starter - 4.3.4.B + 4.3.8.B diff --git a/yudao-framework/yudao-spring-boot-starter-captcha/pom.xml b/yudao-framework/yudao-spring-boot-starter-captcha/pom.xml index 7fc7eb00b8..cbdb3a100f 100644 --- a/yudao-framework/yudao-spring-boot-starter-captcha/pom.xml +++ b/yudao-framework/yudao-spring-boot-starter-captcha/pom.xml @@ -17,11 +17,6 @@ - - cn.iocoder.boot - yudao-common - - org.springframework.boot From 21cf9227236f32054d7f6071cb301ff777468999 Mon Sep 17 00:00:00 2001 From: xingyu Date: Wed, 3 Aug 2022 00:41:59 +0800 Subject: [PATCH 047/135] perf: refresh token && delete console --- .../src/api/system/user/profile/index.ts | 4 +- .../src/components/Verifition/src/Verify.vue | 3 - .../Verifition/src/Verify/VerifySlide.vue | 1 - yudao-ui-admin-vue3/src/config/axios/index.ts | 76 ++++++++++++++----- yudao-ui-admin-vue3/src/router/index.ts | 11 +-- .../views/Profile/components/UserAvatar.vue | 56 +++++++------- .../src/views/system/menu/index.vue | 1 - .../src/views/system/oauth2/client/index.vue | 2 +- .../src/views/system/role/index.vue | 5 +- .../src/views/system/tenantPackage/index.vue | 4 +- 10 files changed, 100 insertions(+), 63 deletions(-) diff --git a/yudao-ui-admin-vue3/src/api/system/user/profile/index.ts b/yudao-ui-admin-vue3/src/api/system/user/profile/index.ts index a5a24490f5..3eab59e014 100644 --- a/yudao-ui-admin-vue3/src/api/system/user/profile/index.ts +++ b/yudao-ui-admin-vue3/src/api/system/user/profile/index.ts @@ -24,6 +24,6 @@ export const updateUserPwdApi = (oldPassword: string, newPassword: string) => { } // 用户头像上传 -export const uploadAvatarApi = (params) => { - return request.upload({ url: '/system/user/profile/update-avatar', params }) +export const uploadAvatarApi = (data) => { + return request.upload({ url: '/system/user/profile/update-avatar', data: data }) } diff --git a/yudao-ui-admin-vue3/src/components/Verifition/src/Verify.vue b/yudao-ui-admin-vue3/src/components/Verifition/src/Verify.vue index 9fe0c54759..2e4af5ccee 100644 --- a/yudao-ui-admin-vue3/src/components/Verifition/src/Verify.vue +++ b/yudao-ui-admin-vue3/src/components/Verifition/src/Verify.vue @@ -102,7 +102,6 @@ export default { * @description 刷新 * */ const refresh = () => { - console.log(instance.value) if (instance.value.refresh) { instance.value.refresh() } @@ -271,7 +270,6 @@ export default { -moz-box-sizing: content-box; box-sizing: content-box; border: 1px solid #ddd; - -webkit-border-radius: 4px; } .verify-bar-area .verify-move-block { @@ -284,7 +282,6 @@ export default { -moz-box-sizing: content-box; box-sizing: content-box; box-shadow: 0 0 2px #888888; - -webkit-border-radius: 1px; } .verify-bar-area .verify-move-block:hover { diff --git a/yudao-ui-admin-vue3/src/components/Verifition/src/Verify/VerifySlide.vue b/yudao-ui-admin-vue3/src/components/Verifition/src/Verify/VerifySlide.vue index a31f4587f5..65136ff700 100644 --- a/yudao-ui-admin-vue3/src/components/Verifition/src/Verify/VerifySlide.vue +++ b/yudao-ui-admin-vue3/src/components/Verifition/src/Verify/VerifySlide.vue @@ -242,7 +242,6 @@ export default { //兼容移动端 var x = e.touches[0].pageX } - console.log(barArea) startLeft.value = Math.floor(x - barArea.value.getBoundingClientRect().left) startMoveTime.value = +new Date() //开始滑动的时间 if (isEnd.value == false) { diff --git a/yudao-ui-admin-vue3/src/config/axios/index.ts b/yudao-ui-admin-vue3/src/config/axios/index.ts index 8396105957..123a7fbe84 100644 --- a/yudao-ui-admin-vue3/src/config/axios/index.ts +++ b/yudao-ui-admin-vue3/src/config/axios/index.ts @@ -1,10 +1,11 @@ import axios, { AxiosInstance, AxiosRequestConfig, AxiosResponse, AxiosError } from 'axios' -import { ElMessage, ElNotification } from 'element-plus' +import { ElMessage, ElMessageBox, ElNotification } from 'element-plus' import qs from 'qs' import { config } from '@/config/axios/config' -import { getAccessToken, getTenantId, removeToken } from '@/utils/auth' +import { getAccessToken, getRefreshToken, getTenantId, removeToken, setToken } from '@/utils/auth' import errorCode from './errorCode' import { useI18n } from '@/hooks/web/useI18n' +import { resetRouter } from '@/router' const tenantEnable = import.meta.env.VITE_APP_TENANT_ENABLE const BASE_URL = import.meta.env.VITE_BASE_URL @@ -20,9 +21,9 @@ const ignoreMsgs = [ export const isRelogin = { show: false } // Axios 无感知刷新令牌,参考 https://www.dashingdog.cn/article/11 与 https://segmentfault.com/a/1190000020210980 实现 // 请求队列 -// const requestList = [] +let requestList: any[] = [] // 是否正在刷新中 -// const isRefreshToken = false +let isRefreshToken = false export const PATH_URL = base_url[import.meta.env.VITE_API_BASEPATH] @@ -91,6 +92,7 @@ service.interceptors.request.use( service.interceptors.response.use( async (response: AxiosResponse) => { const { data } = response + console.info(data) if (!data) { // 返回“[HTTP]请求没有返回值”; throw new Error() @@ -112,16 +114,38 @@ service.interceptors.response.use( return Promise.reject(msg) } else if (code === 401) { // 如果未认证,并且未进行刷新令牌,说明可能是访问令牌过期了 - return handleAuthorized() - // if (!isRefreshToken) { - // isRefreshToken = true - // // 1. 如果获取不到刷新令牌,则只能执行登出操作 - // if (!getRefreshToken()) { - // return handleAuthorized() - // } - // // 2. 进行刷新访问令牌 - // // TODO: 引入refreshToken会循环依赖报错 - // } + if (!isRefreshToken) { + isRefreshToken = true + // 1. 如果获取不到刷新令牌,则只能执行登出操作 + if (!getRefreshToken()) { + return handleAuthorized() + } + // 2. 进行刷新访问令牌 + try { + const refreshTokenRes = await refreshToken() + // 2.1 刷新成功,则回放队列的请求 + 当前请求 + setToken(refreshTokenRes.data) + requestList.forEach((cb: any) => cb()) + return service(response.config) + } catch (e) { + // 为什么需要 catch 异常呢?刷新失败时,请求因为 Promise.reject 触发异常。 + // 2.2 刷新失败,只回放队列的请求 + requestList.forEach((cb: any) => cb()) + // 提示是否要登出。即不回放当前请求!不然会形成递归 + return handleAuthorized() + } finally { + requestList = [] + isRefreshToken = false + } + } else { + // 添加到队列,等待刷新获取到新的令牌 + return new Promise((resolve) => { + requestList.push(() => { + ;(config as Recordable).headers.Authorization = 'Bearer ' + getAccessToken() // 让每个请求携带自定义token 请根据实际情况自行修改 + resolve(service(response.config)) + }) + }) + } } else if (code === 500) { ElMessage.error(t('sys.api.errMsg500')) return Promise.reject(new Error(msg)) @@ -165,14 +189,32 @@ service.interceptors.response.use( return Promise.reject(error) } ) + +const refreshToken = async () => { + return await service({ + url: '/system/auth/refresh-token?refreshToken=' + getRefreshToken(), + method: 'post' + }) +} const handleAuthorized = () => { const { t } = useI18n() if (!isRelogin.show) { - removeToken() isRelogin.show = true - ElNotification.error(t('sys.api.timeoutMessage')) + ElMessageBox.confirm(t('sys.api.timeoutMessage'), t('common.confirmTitle'), { + confirmButtonText: t('login.relogin'), + cancelButtonText: t('common.cancel'), + type: 'warning' + }) + .then(() => { + removeToken() + resetRouter() // 重置静态路由表 + isRelogin.show = false + location.href = '/' + }) + .catch(() => { + isRelogin.show = false + }) } - location.href = '/' return Promise.reject(t('sys.api.timeoutMessage')) } export { service } diff --git a/yudao-ui-admin-vue3/src/router/index.ts b/yudao-ui-admin-vue3/src/router/index.ts index 812ec4f7a5..022042eebe 100644 --- a/yudao-ui-admin-vue3/src/router/index.ts +++ b/yudao-ui-admin-vue3/src/router/index.ts @@ -10,6 +10,7 @@ import { createRouter, createWebHashHistory } from 'vue-router' import { usePermissionStoreWithOut } from '@/store/modules/permission' import { useDictStoreWithOut } from '@/store/modules/dict' import { listSimpleDictDataApi } from '@/api/system/dict/dict.data' +import { isRelogin } from '@/config/axios' const permissionStore = usePermissionStoreWithOut() @@ -48,14 +49,14 @@ router.beforeEach(async (to, from, next) => { next({ path: '/' }) } else { if (!dictStore.getIsSetDict) { + isRelogin.show = true // 获取所有字典 const res = await listSimpleDictDataApi() - if (res) { - dictStore.setDictMap(res) - dictStore.setIsSetDict(true) - } + dictStore.setDictMap(res) + dictStore.setIsSetDict(true) } if (permissionStore.getIsAddRouters) { + isRelogin.show = false next() return } @@ -77,7 +78,7 @@ router.beforeEach(async (to, from, next) => { if (whiteList.indexOf(to.path) !== -1) { next() } else { - next(`/login?redirect=${to.path}`) // 否则全部重定向到登录页 + next(`/login?redirect=${to.fullPath}`) // 否则全部重定向到登录页 } } }) diff --git a/yudao-ui-admin-vue3/src/views/Profile/components/UserAvatar.vue b/yudao-ui-admin-vue3/src/views/Profile/components/UserAvatar.vue index 4cdfb14840..b7a08de3a3 100644 --- a/yudao-ui-admin-vue3/src/views/Profile/components/UserAvatar.vue +++ b/yudao-ui-admin-vue3/src/views/Profile/components/UserAvatar.vue @@ -6,12 +6,12 @@ import { ElRow, ElCol, ElUpload, ElMessage, ElDialog } from 'element-plus' import { propTypes } from '@/utils/propTypes' import { uploadAvatarApi } from '@/api/system/user/profile' const cropper = ref() +const dialogVisible = ref(false) +const cropperVisible = ref(false) const props = defineProps({ img: propTypes.string.def('') }) -const state = reactive({ - dialogVisible: false, - cropperVisible: false, +const options = reactive({ dialogTitle: '编辑头像', options: { img: props.img, //裁剪图片的地址 @@ -27,8 +27,11 @@ const state = reactive({ }) /** 编辑头像 */ const editCropper = () => { - state.dialogVisible = true - state.cropperVisible = true + dialogVisible.value = true +} +// 打开弹出层结束时的回调 +const modalOpened = () => { + cropperVisible.value = true } /** 向左旋转 */ const rotateLeft = () => { @@ -44,7 +47,7 @@ const changeScale = (num: number) => { cropper.value.changeScale(num) } // 覆盖默认的上传行为 -const requestUpload = () => {} +const requestUpload: any = () => {} /** 上传预处理 */ const beforeUpload = (file: Blob) => { if (file.type.indexOf('image/') == -1) { @@ -54,64 +57,65 @@ const beforeUpload = (file: Blob) => { reader.readAsDataURL(file) reader.onload = () => { if (reader.result) { - state.options.img = reader.result as string + options.options.img = reader.result as string } } } } /** 上传图片 */ const uploadImg = () => { - cropper.value.getCropBlob((data) => { + cropper.value.getCropBlob((data: any) => { let formData = new FormData() formData.append('avatarfile', data) uploadAvatarApi(formData) }) } /** 实时预览 */ -const realTime = (data) => { - state.previews = data +const realTime = (data: any) => { + options.previews = data } watch( () => props.img, () => { if (props.img) { - state.options.img = props.img - state.previews.img = props.img - state.previews.url = props.img + options.options.img = props.img + options.previews.img = props.img + options.previews.url = props.img } } )