diff --git a/sop-admin/sop-admin-backend/src/main/java/com/gitee/sop/adminbackend/common/jackson/DateConverterProperties.java b/sop-admin/sop-admin-backend/src/main/java/com/gitee/sop/adminbackend/common/jackson/DateConverterProperties.java new file mode 100644 index 00000000..735909ba --- /dev/null +++ b/sop-admin/sop-admin-backend/src/main/java/com/gitee/sop/adminbackend/common/jackson/DateConverterProperties.java @@ -0,0 +1,41 @@ +package com.gitee.sop.adminbackend.common.jackson; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; + +import java.util.Locale; +import java.util.TimeZone; + +/** + * 日期序列化配置类 + */ +@Data +@ConfigurationProperties(prefix = "jackson") +public class DateConverterProperties { + + /** + * Date/LocalDateTime 格式化 + */ + private String dateTimeFormat = "yyyy-MM-dd HH:mm:ss"; + + /** + * localDate 格式化 + */ + private String localDateFormat = "yyyy-MM-dd"; + + /** + * localTime 格式化 + */ + private String localTimeFormat = "HH:mm:ss"; + + /** + * 时区, 默认 GMT+8 + */ + private TimeZone timeZone = TimeZone.getTimeZone("GMT+8"); + + /** + * 地区, 默认 zh_CN + */ + private Locale locale = Locale.CHINA; + +} diff --git a/sop-admin/sop-admin-backend/src/main/java/com/gitee/sop/adminbackend/common/jackson/JacksonDateConverterConfig.java b/sop-admin/sop-admin-backend/src/main/java/com/gitee/sop/adminbackend/common/jackson/JacksonDateConverterConfig.java new file mode 100644 index 00000000..379045b6 --- /dev/null +++ b/sop-admin/sop-admin-backend/src/main/java/com/gitee/sop/adminbackend/common/jackson/JacksonDateConverterConfig.java @@ -0,0 +1,147 @@ +package com.gitee.sop.adminbackend.common.jackson; + +import com.fasterxml.jackson.databind.SerializationFeature; +import com.fasterxml.jackson.databind.deser.std.DateDeserializers; +import com.fasterxml.jackson.databind.ser.std.DateSerializer; +import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateDeserializer; +import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer; +import com.fasterxml.jackson.datatype.jsr310.deser.LocalTimeDeserializer; +import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateSerializer; +import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer; +import com.fasterxml.jackson.datatype.jsr310.ser.LocalTimeSerializer; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.autoconfigure.jackson.Jackson2ObjectMapperBuilderCustomizer; +import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.core.convert.converter.Converter; + +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.time.LocalTime; +import java.time.format.DateTimeFormatter; +import java.util.Date; + +/** + * 基于Jackson的日期格式配置 + */ +@Slf4j +@Configuration +@EnableConfigurationProperties(DateConverterProperties.class) +public class JacksonDateConverterConfig { + + @Autowired + private DateConverterProperties props; + + @Bean + public Jackson2ObjectMapperBuilderCustomizer jackson2ObjectMapperBuilderCustomizer() { + log.info("@================= 初始化jackson日期序列化 ==================@"); + log.info("Locale : 【{}】", props.getLocale()); + log.info("TimeZone : 【{}】", props.getTimeZone().getDisplayName()); + log.info("Date : 【{}】", props.getDateTimeFormat()); + log.info("LocalDateTime : 【{}】", props.getDateTimeFormat()); + log.info("LocalDate : 【{}】", props.getLocalDateFormat()); + log.info("LocalTime : 【{}】", props.getLocalTimeFormat()); + + final DateTimeFormatter dateTimeFormatter = this.ofPattern(props.getDateTimeFormat()); + final DateTimeFormatter localDateFormatter = this.ofPattern(props.getLocalDateFormat()); + final DateTimeFormatter localTimeFormatter = this.ofPattern(props.getLocalTimeFormat()); + final SimpleDateFormat simpleDateFormat = new SimpleDateFormat(props.getDateTimeFormat()); + + return builder -> { + builder.featuresToDisable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS) + // 地区 + .locale(props.getLocale()) + // 时区 + .timeZone(props.getTimeZone()); + // 序列化 + builder.serializerByType(LocalDateTime.class, new LocalDateTimeSerializer(dateTimeFormatter)) + .serializerByType(LocalDate.class, new LocalDateSerializer(localDateFormatter)) + .serializerByType(LocalTime.class, new LocalTimeSerializer(localTimeFormatter)) + .serializerByType(Date.class, new DateSerializer(false, simpleDateFormat)); + // 反序列化 + builder.deserializerByType(LocalDateTime.class, new LocalDateTimeDeserializer(dateTimeFormatter)) + .deserializerByType(LocalDate.class, new LocalDateDeserializer(localDateFormatter)) + .deserializerByType(LocalTime.class, new LocalTimeDeserializer(localTimeFormatter)) + .deserializerByType(Date.class, + new DateDeserializers.DateDeserializer(DateDeserializers.DateDeserializer.instance, + simpleDateFormat, props.getDateTimeFormat())); + }; + } + + + /** + * 根据字符串 获取 DateTimeFormatter + * + * @param pattern 日期格式字符串 + * @return DateTimeFormatter + */ + private DateTimeFormatter ofPattern(String pattern) { + return DateTimeFormatter.ofPattern(pattern); + } + + + /** + * LocalDate转换器,用于转换RequestParam和PathVariable参数 + */ + @Bean + public Converter localDateConverter() { + return new Converter() { + @Override + public LocalDate convert(String source) { + return LocalDate.parse(source, DateTimeFormatter.ofPattern(props.getLocalDateFormat())); + } + }; + } + + /** + * LocalDateTime转换器,用于转换RequestParam和PathVariable参数 + */ + @Bean + public Converter localDateTimeConverter() { + return new Converter() { + @Override + public LocalDateTime convert(String source) { + return LocalDateTime.parse(source, DateTimeFormatter.ofPattern(props.getDateTimeFormat())); + } + }; + } + + /** + * LocalTime转换器,用于转换RequestParam和PathVariable参数 + */ + @Bean + public Converter localTimeConverter() { + return new Converter() { + @Override + public LocalTime convert(String source) { + return LocalTime.parse(source, DateTimeFormatter.ofPattern(props.getLocalTimeFormat())); + } + }; + } + + /** + * Date转换器,用于转换RequestParam和PathVariable参数 + */ + @Bean + public Converter dateConverter() { + return new Converter() { + @Override + public Date convert(String source) { + final SimpleDateFormat simpleDateFormat = new SimpleDateFormat(props.getDateTimeFormat()); + + try { + return simpleDateFormat.parse(source); + } catch (ParseException e) { + log.error(">>>> init Converter String to Date error!", e); + throw new RuntimeException(e); + } + } + }; + } + +} + diff --git a/sop-admin/sop-admin-backend/src/main/java/com/gitee/sop/adminbackend/controller/isv/IsvInfoController.java b/sop-admin/sop-admin-backend/src/main/java/com/gitee/sop/adminbackend/controller/isv/IsvInfoController.java index 8114eb7b..b76c1e86 100644 --- a/sop-admin/sop-admin-backend/src/main/java/com/gitee/sop/adminbackend/controller/isv/IsvInfoController.java +++ b/sop-admin/sop-admin-backend/src/main/java/com/gitee/sop/adminbackend/controller/isv/IsvInfoController.java @@ -66,12 +66,12 @@ public class IsvInfoController { /** * 获取秘钥信息 * - * @param isvInfoId + * @param isvId * @return */ @GetMapping("/getKeys") - public Result getKeys(Long isvInfoId) { - IsvKeysDTO isvKeysDTO = isvInfoService.getKeys(isvInfoId); + public Result getKeys(Long isvId) { + IsvKeysDTO isvKeysDTO = isvInfoService.getKeys(isvId); return Result.ok(isvKeysDTO); } diff --git a/sop-admin/sop-admin-backend/src/main/java/com/gitee/sop/adminbackend/controller/isv/req/IsvInfoAddParam.java b/sop-admin/sop-admin-backend/src/main/java/com/gitee/sop/adminbackend/controller/isv/req/IsvInfoAddParam.java index 0349afbb..e2b8aa89 100644 --- a/sop-admin/sop-admin-backend/src/main/java/com/gitee/sop/adminbackend/controller/isv/req/IsvInfoAddParam.java +++ b/sop-admin/sop-admin-backend/src/main/java/com/gitee/sop/adminbackend/controller/isv/req/IsvInfoAddParam.java @@ -3,6 +3,8 @@ package com.gitee.sop.adminbackend.controller.isv.req; import lombok.Data; import org.hibernate.validator.constraints.Length; +import javax.validation.constraints.Max; +import javax.validation.constraints.Min; import javax.validation.constraints.NotNull; @@ -12,6 +14,13 @@ import javax.validation.constraints.NotNull; @Data public class IsvInfoAddParam { + /** + * 秘钥格式,1:PKCS8(JAVA适用),2:PKCS1(非JAVA适用) + */ + @Min(value = 1, message = "秘钥格式错误") + @Max(value = 2, message = "秘钥格式错误") + private Integer keyFormat; + /** * 1启用,2禁用 */ diff --git a/sop-admin/sop-admin-backend/src/main/java/com/gitee/sop/adminbackend/dao/entity/IsvKeys.java b/sop-admin/sop-admin-backend/src/main/java/com/gitee/sop/adminbackend/dao/entity/IsvKeys.java index 0a1626ff..265276a2 100644 --- a/sop-admin/sop-admin-backend/src/main/java/com/gitee/sop/adminbackend/dao/entity/IsvKeys.java +++ b/sop-admin/sop-admin-backend/src/main/java/com/gitee/sop/adminbackend/dao/entity/IsvKeys.java @@ -23,7 +23,7 @@ public class IsvKeys { /** * isv_info.id */ - private Long isvInfoId; + private Long isvId; /** * 秘钥格式,1:PKCS8(JAVA适用),2:PKCS1(非JAVA适用) diff --git a/sop-admin/sop-admin-backend/src/main/java/com/gitee/sop/adminbackend/dao/entity/PermIsvRole.java b/sop-admin/sop-admin-backend/src/main/java/com/gitee/sop/adminbackend/dao/entity/PermIsvRole.java index dbdae9d5..442bb676 100644 --- a/sop-admin/sop-admin-backend/src/main/java/com/gitee/sop/adminbackend/dao/entity/PermIsvRole.java +++ b/sop-admin/sop-admin-backend/src/main/java/com/gitee/sop/adminbackend/dao/entity/PermIsvRole.java @@ -24,7 +24,7 @@ public class PermIsvRole { /** * isv_info表id */ - private Long isvInfoId; + private Long isvId; /** * 角色code diff --git a/sop-admin/sop-admin-backend/src/main/java/com/gitee/sop/adminbackend/dao/mapper/IsvKeysMapper.java b/sop-admin/sop-admin-backend/src/main/java/com/gitee/sop/adminbackend/dao/mapper/IsvKeysMapper.java index 006a5fe4..c531b5b6 100644 --- a/sop-admin/sop-admin-backend/src/main/java/com/gitee/sop/adminbackend/dao/mapper/IsvKeysMapper.java +++ b/sop-admin/sop-admin-backend/src/main/java/com/gitee/sop/adminbackend/dao/mapper/IsvKeysMapper.java @@ -8,8 +8,8 @@ import com.gitee.sop.adminbackend.dao.entity.IsvKeys; */ public interface IsvKeysMapper extends BaseMapper { - default IsvKeys getByAppId(String appId) { - return this.get(IsvKeys::getAppId, appId); + default IsvKeys getByIsvInfoId(Long isvId) { + return this.get(IsvKeys::getIsvId, isvId); } } diff --git a/sop-admin/sop-admin-backend/src/main/java/com/gitee/sop/adminbackend/service/isv/IsvInfoService.java b/sop-admin/sop-admin-backend/src/main/java/com/gitee/sop/adminbackend/service/isv/IsvInfoService.java index f82319e2..471202fe 100644 --- a/sop-admin/sop-admin-backend/src/main/java/com/gitee/sop/adminbackend/service/isv/IsvInfoService.java +++ b/sop-admin/sop-admin-backend/src/main/java/com/gitee/sop/adminbackend/service/isv/IsvInfoService.java @@ -43,6 +43,12 @@ public class IsvInfoService implements LambdaService { return rsaTool.createKeys(); } + /** + * 添加ISV + * @param isvInfoAddDTO + * @return + * @throws Exception + */ @Transactional(rollbackFor = Exception.class) public long add(IsvInfoAddDTO isvInfoAddDTO) throws Exception { IsvInfo rec = CopyUtil.copyBean(isvInfoAddDTO, IsvInfo::new); @@ -53,25 +59,27 @@ public class IsvInfoService implements LambdaService { if (CollectionUtils.isNotEmpty(isvInfoAddDTO.getRoleCodes())) { this.saveIsvRole(rec, isvInfoAddDTO.getRoleCodes()); } - IsvKeysGenDTO isvKeysGenVO = this.createIsvKeys(); + // 生成秘钥 + RSATool.KeyFormat keyFormat = RSATool.KeyFormat.of(isvInfoAddDTO.getKeyFormat()); + IsvKeysGenDTO isvKeysGenVO = this.createIsvKeys(keyFormat); IsvKeys isvKeys = new IsvKeys(); - isvKeys.setIsvInfoId(rec.getId()); + isvKeys.setIsvId(rec.getId()); CopyUtil.copyPropertiesIgnoreNull(isvKeysGenVO, isvKeys); isvKeysService.save(isvKeys); return rec.getId(); } private void saveIsvRole(IsvInfo isvInfo, List roleCodeList) { - long isvInfoId = isvInfo.getId(); + Long isvId = isvInfo.getId(); permIsvRoleService.query() - .eq(PermIsvRole::getIsvInfoId, isvInfoId) + .eq(PermIsvRole::getIsvId, isvId) .delete(); List tobeSaveList = roleCodeList.stream() .map(roleCode -> { PermIsvRole rec = new PermIsvRole(); - rec.setIsvInfoId(isvInfoId); + rec.setIsvId(isvId); rec.setRoleCode(roleCode); return rec; }) @@ -88,10 +96,10 @@ public class IsvInfoService implements LambdaService { // } } - private IsvKeysGenDTO createIsvKeys() throws Exception { + private IsvKeysGenDTO createIsvKeys(RSATool.KeyFormat keyFormat) throws Exception { IsvKeysGenDTO isvKeysGenDTO = new IsvKeysGenDTO(); - RSATool.KeyStore keyStoreIsv = this.createKeys(RSATool.KeyFormat.PKCS8); + RSATool.KeyStore keyStoreIsv = this.createKeys(keyFormat); isvKeysGenDTO.setPublicKeyIsv(keyStoreIsv.getPublicKey()); isvKeysGenDTO.setPrivateKeyIsv(keyStoreIsv.getPrivateKey()); @@ -100,8 +108,8 @@ public class IsvInfoService implements LambdaService { return isvKeysGenDTO; } - public IsvKeysDTO getKeys(Long isvInfoId) { - IsvKeys isvKeys = isvKeysService.get(IsvKeys::getIsvInfoId, isvInfoId); + public IsvKeysDTO getKeys(Long isvId) { + IsvKeys isvKeys = isvKeysService.get(IsvKeys::getIsvId, isvId); return CopyUtil.copyBean(isvKeys, IsvKeysDTO::new); } diff --git a/sop-admin/sop-admin-backend/src/main/java/com/gitee/sop/adminbackend/service/isv/dto/IsvInfoAddDTO.java b/sop-admin/sop-admin-backend/src/main/java/com/gitee/sop/adminbackend/service/isv/dto/IsvInfoAddDTO.java index 1af3c347..82021092 100644 --- a/sop-admin/sop-admin-backend/src/main/java/com/gitee/sop/adminbackend/service/isv/dto/IsvInfoAddDTO.java +++ b/sop-admin/sop-admin-backend/src/main/java/com/gitee/sop/adminbackend/service/isv/dto/IsvInfoAddDTO.java @@ -3,6 +3,8 @@ package com.gitee.sop.adminbackend.service.isv.dto; import lombok.Data; import org.hibernate.validator.constraints.Length; +import javax.validation.constraints.Max; +import javax.validation.constraints.Min; import javax.validation.constraints.NotNull; import java.util.List; @@ -13,6 +15,13 @@ import java.util.List; @Data public class IsvInfoAddDTO { + /** + * 秘钥格式,1:PKCS8(JAVA适用),2:PKCS1(非JAVA适用) + */ + @Min(value = 1, message = "秘钥格式错误") + @Max(value = 2, message = "秘钥格式错误") + private Integer keyFormat; + /** * 1启用,2禁用 */ diff --git a/sop-admin/sop-admin-frontend/src/model/enums/index.ts b/sop-admin/sop-admin-frontend/src/model/enums/index.ts index 4f876df6..36acdbf1 100644 --- a/sop-admin/sop-admin-frontend/src/model/enums/index.ts +++ b/sop-admin/sop-admin-frontend/src/model/enums/index.ts @@ -2,3 +2,8 @@ export enum StatusEnum { ENABLE = 1, DISABLE = 2 } + +export enum KeyFormatEnum { + PKCS8 = 1, + PKCS1 = 2 +} diff --git a/sop-admin/sop-admin-frontend/src/views/isv/list/index.ts b/sop-admin/sop-admin-frontend/src/views/isv/list/index.ts index d24e1bbc..bd4fd6b8 100644 --- a/sop-admin/sop-admin-frontend/src/views/isv/list/index.ts +++ b/sop-admin/sop-admin-frontend/src/views/isv/list/index.ts @@ -1,13 +1,14 @@ -import { computed, ref } from "vue"; +import { computed, type Ref, ref } from "vue"; import { type ButtonsCallBackParams, type FieldValues, + type OptionsRow, type PageInfo, type PlusColumn, useTable } from "plus-pro-components"; import { ElMessage } from "element-plus"; -import { StatusEnum } from "@/model/enums"; +import { KeyFormatEnum, StatusEnum } from "@/model/enums"; import { api } from "@/api/isvList"; const isAdd = ref(false); @@ -66,7 +67,7 @@ export const tableColumns: PlusColumn[] = [ { label: "AppID", prop: "appId", - width: 230 + width: 250 }, { label: "秘钥", @@ -76,7 +77,7 @@ export const tableColumns: PlusColumn[] = [ { label: "角色", prop: "roleNames", - width: 120 + width: 200 }, { label: "状态", @@ -102,11 +103,13 @@ export const tableColumns: PlusColumn[] = [ }, { label: "添加时间", - prop: "addTime" + prop: "addTime", + width: 160 }, { label: "修改时间", - prop: "updateTime" + prop: "updateTime", + width: 160 } ]; // 表格按钮定义 @@ -165,52 +168,82 @@ export const dlgTitle = ref(""); // 表单值 const editFormDataGen = () => { return { - id: "", - appId: "", - status: "", - remark: "", - addTime: "", - updateTime: "" + id: 0, + status: StatusEnum.ENABLE, + keyFormat: KeyFormatEnum.PKCS8, + remark: "" }; }; export const editFormData = ref(editFormDataGen()); -export const editFormRules = { - id: [{ required: true, message: "请输入id" }], - appId: [{ required: true, message: "请输入appKey" }], - status: [{ required: true, message: "请输入1启用,2禁用" }] +export const editFormRules = {}; + +// options推荐写法 +// 1. 定义一个 `ref`数组 +const roleList: Ref = ref([]); +// 2. 异步函数获取到值赋值到 `ref` +const loadRole = async () => { + // }; +loadRole(); // 表单内容 export const editFormColumns: PlusColumn[] = [ - { - label: "id", - prop: "id", - valueType: "copy" - }, { label: "AppID", prop: "appId", - valueType: "copy" + valueType: "copy", + fieldProps: { + disabled: true, + placeholder: "自动生成" + } }, { - label: "1启用,2禁用", + label: "秘钥格式", + prop: "keyFormat", + valueType: "radio", + options: [ + { + label: "PKCS8(Java适用)", + value: KeyFormatEnum.PKCS8 + }, + { + label: "PKCS1(非Java适用)", + value: KeyFormatEnum.PKCS1 + } + ] + }, + { + label: "角色", + prop: "roleCodes", + valueType: "checkbox", + // options推荐写法 + // 3. 用 computed 返回 ref 的 value + options: computed(() => roleList.value) + }, + { + label: "状态", prop: "status", - valueType: "copy" + valueType: "radio", + options: [ + { + label: "启用", + value: StatusEnum.ENABLE + }, + { + label: "禁用", + value: StatusEnum.DISABLE + } + ] }, { label: "备注", prop: "remark", - valueType: "copy" - }, - { - label: "addTime", - prop: "addTime", - valueType: "copy" - }, - { - label: "updateTime", - prop: "updateTime", - valueType: "copy" + valueType: "textarea", + fieldProps: { + maxlength: 300, + showWordLimit: true, + autosize: { minRows: 2, maxRows: 4 } + } } ]; diff --git a/sop-admin/sop-admin-frontend/src/views/isv/list/showKeys.ts b/sop-admin/sop-admin-frontend/src/views/isv/list/showKeys.ts index 0d79d003..eae748aa 100644 --- a/sop-admin/sop-admin-frontend/src/views/isv/list/showKeys.ts +++ b/sop-admin/sop-admin-frontend/src/views/isv/list/showKeys.ts @@ -77,7 +77,7 @@ export const showKeysFormColumns: PlusFormGroupRow[] = [ export const viewKeys = (row: any) => { const params = { - isvInfoId: row.id + isvId: row.id }; api.viewKeys(params).then(resp => { showKeysFormData.value = resp.data; diff --git a/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/api/isv/IsvApi.java b/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/api/isv/IsvApi.java index 0c28b150..36d5cbae 100644 --- a/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/api/isv/IsvApi.java +++ b/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/api/isv/IsvApi.java @@ -271,14 +271,14 @@ public class IsvApi { void saveIsvRole(IsvInfo isvInfo, List roleCodeList) { Query query = new Query(); - long isvInfoId = isvInfo.getId(); - query.eq("isv_id", isvInfoId); + Long isvId = isvInfo.getId(); + query.eq("isv_id", isvId); permIsvRoleMapper.deleteByQuery(query); List tobeSaveList = roleCodeList.stream() .map(roleCode -> { PermIsvRole rec = new PermIsvRole(); - rec.setIsvId(isvInfoId); + rec.setIsvId(isvId); rec.setRoleCode(roleCode); return rec; })