diff --git a/src/main/java/com/gxwebsoft/app/entity/AppTicket.java b/src/main/java/com/gxwebsoft/app/entity/AppTicket.java index 1d62783..a4aa64d 100644 --- a/src/main/java/com/gxwebsoft/app/entity/AppTicket.java +++ b/src/main/java/com/gxwebsoft/app/entity/AppTicket.java @@ -4,6 +4,10 @@ import com.baomidou.mybatisplus.annotation.IdType; import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableName; import com.fasterxml.jackson.annotation.JsonFormat; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import com.gxwebsoft.common.core.config.JsonArrayToStringDeserializer; +import com.gxwebsoft.common.core.config.JsonStringToArraySerializer; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; import lombok.EqualsAndHashCode; @@ -53,6 +57,8 @@ public class AppTicket implements Serializable { private String status; @Schema(description = "附件JSON数组") + @JsonDeserialize(using = JsonArrayToStringDeserializer.class) + @JsonSerialize(using = JsonStringToArraySerializer.class) private String attachments; @Schema(description = "提交人用户ID") diff --git a/src/main/java/com/gxwebsoft/app/entity/AppTicketReply.java b/src/main/java/com/gxwebsoft/app/entity/AppTicketReply.java index fb13ca9..2633d94 100644 --- a/src/main/java/com/gxwebsoft/app/entity/AppTicketReply.java +++ b/src/main/java/com/gxwebsoft/app/entity/AppTicketReply.java @@ -4,6 +4,10 @@ import com.baomidou.mybatisplus.annotation.IdType; import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableName; import com.fasterxml.jackson.annotation.JsonFormat; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import com.gxwebsoft.common.core.config.JsonArrayToStringDeserializer; +import com.gxwebsoft.common.core.config.JsonStringToArraySerializer; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; import lombok.EqualsAndHashCode; @@ -35,6 +39,8 @@ public class AppTicketReply implements Serializable { private String content; @Schema(description = "附件JSON数组") + @JsonDeserialize(using = JsonArrayToStringDeserializer.class) + @JsonSerialize(using = JsonStringToArraySerializer.class) private String attachments; @Schema(description = "回复人用户ID") diff --git a/src/main/java/com/gxwebsoft/cms/mapper/xml/CmsWebsiteMapper.xml b/src/main/java/com/gxwebsoft/cms/mapper/xml/CmsWebsiteMapper.xml index 865bb37..fb17bb1 100644 --- a/src/main/java/com/gxwebsoft/cms/mapper/xml/CmsWebsiteMapper.xml +++ b/src/main/java/com/gxwebsoft/cms/mapper/xml/CmsWebsiteMapper.xml @@ -435,7 +435,7 @@ a.user_id = #{param.memberUserId} OR a.website_id IN ( SELECT au.website_id FROM app_user au - WHERE au.user_id = #{param.memberUserId} AND au.deleted = 0 + WHERE au.user_id = #{param.memberUserId} ) ) diff --git a/src/main/java/com/gxwebsoft/common/core/config/JsonArrayToStringDeserializer.java b/src/main/java/com/gxwebsoft/common/core/config/JsonArrayToStringDeserializer.java new file mode 100644 index 0000000..dbb4989 --- /dev/null +++ b/src/main/java/com/gxwebsoft/common/core/config/JsonArrayToStringDeserializer.java @@ -0,0 +1,57 @@ +package com.gxwebsoft.common.core.config; + +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.core.JsonToken; +import com.fasterxml.jackson.databind.DeserializationContext; +import com.fasterxml.jackson.databind.JsonDeserializer; +import com.fasterxml.jackson.databind.ObjectMapper; +import lombok.extern.slf4j.Slf4j; + +import java.io.IOException; +import java.util.List; + +/** + * JSON 数组 ↔ String 反序列化器 + *

+ * 数据库字段存储的是 JSON 字符串(如 ["url1","url2"]), + * 前端传来的是 JSON 数组;此反序列化器把两种形式都正确处理为 String 存库。 + * + * @author WebSoft + * @since 2026-03-30 + */ +@Slf4j +public class JsonArrayToStringDeserializer extends JsonDeserializer { + + private static final ObjectMapper MAPPER = new ObjectMapper(); + + @Override + public String deserialize(JsonParser p, DeserializationContext ctxt) throws IOException { + // 如果前端传的已经是字符串,直接返回 + if (p.currentToken() == JsonToken.VALUE_STRING) { + String text = p.getText(); + if (text == null || text.trim().isEmpty()) { + return null; + } + return text; + } + // 如果前端传的是数组,序列化成 JSON 字符串 + if (p.currentToken() == JsonToken.START_ARRAY) { + List list = MAPPER.readValue(p, MAPPER.getTypeFactory() + .constructCollectionType(List.class, String.class)); + if (list == null || list.isEmpty()) { + return null; + } + return MAPPER.writeValueAsString(list); + } + // null + if (p.currentToken() == JsonToken.VALUE_NULL) { + return null; + } + return p.getValueAsString(); + } + + @Override + public String getNullValue(DeserializationContext ctxt) { + return null; + } +} diff --git a/src/main/java/com/gxwebsoft/common/core/config/JsonStringToArraySerializer.java b/src/main/java/com/gxwebsoft/common/core/config/JsonStringToArraySerializer.java new file mode 100644 index 0000000..b42390d --- /dev/null +++ b/src/main/java/com/gxwebsoft/common/core/config/JsonStringToArraySerializer.java @@ -0,0 +1,45 @@ +package com.gxwebsoft.common.core.config; + +import com.fasterxml.jackson.core.JsonGenerator; +import com.fasterxml.jackson.databind.JsonSerializer; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.SerializerProvider; +import lombok.extern.slf4j.Slf4j; + +import java.io.IOException; +import java.util.Collections; +import java.util.List; + +/** + * JSON 字符串 → 数组 序列化器 + *

+ * 数据库中 attachments 存储为 JSON 字符串,响应给前端时自动转成数组。 + * + * @author WebSoft + * @since 2026-03-30 + */ +@Slf4j +public class JsonStringToArraySerializer extends JsonSerializer { + + private static final ObjectMapper MAPPER = new ObjectMapper(); + + @Override + public void serialize(String value, JsonGenerator gen, SerializerProvider serializers) throws IOException { + if (value == null || value.trim().isEmpty()) { + gen.writeStartArray(); + gen.writeEndArray(); + return; + } + try { + List list = MAPPER.readValue(value, + MAPPER.getTypeFactory().constructCollectionType(List.class, String.class)); + gen.writeObject(list); + } catch (Exception e) { + // 解析失败(非JSON格式)就把原始字符串包成单元素数组 + log.warn("attachments 字段不是合法 JSON 数组,原样包装: {}", value); + gen.writeStartArray(); + gen.writeString(value); + gen.writeEndArray(); + } + } +}