Răsfoiți Sursa

commit 家族小程序

Hai Lin 2 săptămâni în urmă
părinte
comite
058f44ee25
24 a modificat fișierele cu 1566 adăugiri și 59 ștergeri
  1. 39 0
      .idea/MyBatisCodeHelperDatasource.xml
  2. 8 0
      .idea/inspectionProfiles/Project_Default.xml
  3. 181 3
      mirage-service/src/main/java/com/mirage/mirageservice/controller/FamilyController.java
  4. 21 40
      mirage-service/src/main/java/com/mirage/mirageservice/controller/WxController.java
  5. 77 0
      mirage-service/src/main/java/com/mirage/mirageservice/domain/FamilyConfigInfo.java
  6. 113 0
      mirage-service/src/main/java/com/mirage/mirageservice/domain/FamilyMemberPhotoAlbum.java
  7. 143 0
      mirage-service/src/main/java/com/mirage/mirageservice/domain/FamilyMoments.java
  8. 35 0
      mirage-service/src/main/java/com/mirage/mirageservice/enums/FamilyConfigEnum.java
  9. 2 0
      mirage-service/src/main/java/com/mirage/mirageservice/enums/FamilyRelationEnum.java
  10. 26 0
      mirage-service/src/main/java/com/mirage/mirageservice/mapper/mysql/FamilyConfigInfoMapper.java
  11. 27 0
      mirage-service/src/main/java/com/mirage/mirageservice/mapper/mysql/FamilyMemberPhotoAlbumMapper.java
  12. 26 0
      mirage-service/src/main/java/com/mirage/mirageservice/mapper/mysql/FamilyMomentsMapper.java
  13. 20 0
      mirage-service/src/main/java/com/mirage/mirageservice/meta/FamilyMomentsAndPublishInfo.java
  14. 5 0
      mirage-service/src/main/java/com/mirage/mirageservice/meta/MemberInfoRequest.java
  15. 3 0
      mirage-service/src/main/java/com/mirage/mirageservice/meta/MemberRelationRequest.java
  16. 16 0
      mirage-service/src/main/java/com/mirage/mirageservice/meta/MomentsContentInfo.java
  17. 23 0
      mirage-service/src/main/java/com/mirage/mirageservice/meta/MomentsMediaInfo.java
  18. 33 0
      mirage-service/src/main/java/com/mirage/mirageservice/meta/MomentsRequest.java
  19. 221 12
      mirage-service/src/main/java/com/mirage/mirageservice/service/FamilyService.java
  20. 26 0
      mirage-service/src/main/java/com/mirage/mirageservice/service/WechatService.java
  21. 116 0
      mirage-service/src/main/resources/com/mirage/mirageservice/mapper/mysql/FamilyConfigInfoMapper.xml
  22. 165 0
      mirage-service/src/main/resources/com/mirage/mirageservice/mapper/mysql/FamilyMemberPhotoAlbumMapper.xml
  23. 210 0
      mirage-service/src/main/resources/com/mirage/mirageservice/mapper/mysql/FamilyMomentsMapper.xml
  24. 30 4
      sql.sql

+ 39 - 0
.idea/MyBatisCodeHelperDatasource.xml

@@ -43,6 +43,19 @@
                 </TableGenerateConfig>
               </value>
             </entry>
+            <entry key="csqz-client:family_config_info">
+              <value>
+                <TableGenerateConfig>
+                  <option name="generatedKey" value="id" />
+                  <option name="javaModelName" value="FamilyConfigInfo" />
+                  <option name="moduleName" value="mirage-service" />
+                  <option name="mybatisplusIdType" value="AUTO" />
+                  <option name="sequenceColumn" value="" />
+                  <option name="sequenceId" value="" />
+                  <option name="useActualColumnName" value="false" />
+                </TableGenerateConfig>
+              </value>
+            </entry>
             <entry key="csqz-client:family_member_info">
               <value>
                 <TableGenerateConfig>
@@ -56,6 +69,32 @@
                 </TableGenerateConfig>
               </value>
             </entry>
+            <entry key="csqz-client:family_member_photo_album">
+              <value>
+                <TableGenerateConfig>
+                  <option name="generatedKey" value="id" />
+                  <option name="javaModelName" value="FamilyMemberPhotoAlbum" />
+                  <option name="moduleName" value="mirage-service" />
+                  <option name="mybatisplusIdType" value="AUTO" />
+                  <option name="sequenceColumn" value="" />
+                  <option name="sequenceId" value="" />
+                  <option name="useActualColumnName" value="false" />
+                </TableGenerateConfig>
+              </value>
+            </entry>
+            <entry key="csqz-client:family_moments">
+              <value>
+                <TableGenerateConfig>
+                  <option name="generatedKey" value="id" />
+                  <option name="javaModelName" value="FamilyMoments" />
+                  <option name="moduleName" value="mirage-service" />
+                  <option name="mybatisplusIdType" value="AUTO" />
+                  <option name="sequenceColumn" value="" />
+                  <option name="sequenceId" value="" />
+                  <option name="useActualColumnName" value="false" />
+                </TableGenerateConfig>
+              </value>
+            </entry>
             <entry key="csqz-client:family_relation_info">
               <value>
                 <TableGenerateConfig>

+ 8 - 0
.idea/inspectionProfiles/Project_Default.xml

@@ -0,0 +1,8 @@
+<component name="InspectionProjectProfileManager">
+  <profile version="1.0">
+    <option name="myName" value="Project Default" />
+    <inspection_tool class="AutoCloseableResource" enabled="true" level="WARNING" enabled_by_default="true">
+      <option name="METHOD_MATCHER_CONFIG" value="java.util.Formatter,format,java.io.Writer,append,com.google.common.base.Preconditions,checkNotNull,org.hibernate.Session,close,java.io.PrintWriter,printf,java.io.PrintStream,printf,com.github.pagehelper.page.PageMethod,startPage" />
+    </inspection_tool>
+  </profile>
+</component>

+ 181 - 3
mirage-service/src/main/java/com/mirage/mirageservice/controller/FamilyController.java

@@ -5,19 +5,24 @@ import com.mirage.core.annotation.Auth;
 import com.mirage.core.exception.AppRuntimeException;
 import com.mirage.core.meta.AppCode;
 import com.mirage.core.meta.AuthType;
-import com.mirage.mirageservice.domain.CsMinWechatUser;
-import com.mirage.mirageservice.domain.FamilyMemberInfo;
+import com.mirage.mirageservice.domain.*;
+import com.mirage.mirageservice.enums.FamilyConfigEnum;
 import com.mirage.mirageservice.enums.FamilyRelationEnum;
 import com.mirage.mirageservice.meta.AppContext;
+import com.mirage.mirageservice.meta.FamilyMomentsAndPublishInfo;
 import com.mirage.mirageservice.meta.MemberInfoRequest;
+import com.mirage.mirageservice.meta.MomentsRequest;
 import com.mirage.mirageservice.service.FamilyService;
+import com.mirage.mirageservice.service.WechatService;
 import lombok.extern.slf4j.Slf4j;
 import org.apache.commons.lang3.StringUtils;
 import org.springframework.web.bind.annotation.*;
 
 import javax.annotation.Resource;
+import java.util.Arrays;
 import java.util.List;
 import java.util.Map;
+import java.util.stream.Collectors;
 
 /**
  * Created by hzlinhai on 2025/10/21.
@@ -29,6 +34,8 @@ public class FamilyController {
 
     @Resource
     private FamilyService familyService;
+    @Resource
+    private WechatService wechatService;
 
     /**
      * 获取自己的亲属关系卡片信息.
@@ -52,6 +59,18 @@ public class FamilyController {
         return familyService.getMemberById(id);
     }
 
+    /**
+     * 根据名字搜索已有用户.
+     *
+     * @param name
+     * @return
+     */
+    @Auth(value = AuthType.COOKIES)
+    @RequestMapping(value = "/member/search", method = RequestMethod.GET)
+    public Object search(@RequestParam String name){
+        return familyService.getMemberInfoByName(name);
+    }
+
     /**
      * 1.微信小程序授权登陆后填写自己信息;
      * 2.填写名称后校验是否已有同名记录,此接口会返回所有同名者信息;
@@ -103,7 +122,7 @@ public class FamilyController {
         if(relationEnum == FamilyRelationEnum.SELF) {
             request.getMemberInfo().setUid(csMinWechatUser.getId());
             request.getMemberInfo().setPhone(csMinWechatUser.getPhone());
-        }else{ // 非SELF代表填写其他亲属
+        }else if(relationEnum != FamilyRelationEnum.OTHER){ // 非SELF代表填写其他亲属
             FamilyMemberInfo selfMemberInfo = familyService.getMemberByUid(csMinWechatUser.getId());
             if(null == selfMemberInfo){
                 throw new AppRuntimeException("请先填写自己信息再录入亲属信息");
@@ -127,4 +146,163 @@ public class FamilyController {
     public Object getUserFamilyTreeMember(@RequestParam(required = false) Integer generation){
         return familyService.getFamilyTree(AppContext.getUid(), generation);
     }
+
+    /**
+     * 上传个人相册内容
+     * @param memberPhotoAlbum, 上传自己相册mid可不填,上传别人mid填别人的member表中id
+     * @return
+     */
+    @Auth(value = AuthType.COOKIES)
+    @RequestMapping(value = "/member/uploadAlbum", method = RequestMethod.POST)
+    public Object uploadAlbum(@RequestBody FamilyMemberPhotoAlbum memberPhotoAlbum){
+        return familyService.uploadMemberAlbum(AppContext.getUid(), memberPhotoAlbum);
+    }
+
+    /**
+     * 获取用户相册内容.
+     *
+     * @param mid
+     * @param type 不传为全部,0:图片 1:视频
+     * @param pageSize
+     * @param pageIndex
+     * @return
+     */
+    @Auth(value = AuthType.COOKIES)
+    @RequestMapping(value = "/member/getAlbumList", method = RequestMethod.GET)
+    public Object getAlbumList(@RequestParam(required = false) Long mid,
+                               @RequestParam(required = false) Integer type,
+                               @RequestParam Integer pageSize,
+                               @RequestParam Integer pageIndex){
+        if(null == mid){
+            FamilyMemberInfo memberInfo = familyService.getMemberByUid(AppContext.getUid());
+            if(null == memberInfo){
+                throw new AppRuntimeException(AppCode.BAD_REQUEST);
+            }
+            mid = memberInfo.getId();
+        }
+        return familyService.getMemberPhotoAlbum(mid, type, pageSize, pageIndex);
+    }
+
+    /**
+     * 根据相册资源id删除.
+     *
+     * @param memberPhotoAlbum
+     * @return
+     */
+    @Auth(value = AuthType.COOKIES)
+    @RequestMapping(value = "/member/getAlbumList", method = RequestMethod.POST)
+    public Object deleteAlbumById(@RequestBody FamilyMemberPhotoAlbum memberPhotoAlbum){
+        if(null == memberPhotoAlbum || memberPhotoAlbum.getId() == null){
+            throw new AppRuntimeException(AppCode.BAD_REQUEST);
+        }
+        return familyService.deletePhotoAlbumById(memberPhotoAlbum.getId());
+    }
+
+    /**
+     * 发布家族圈消息.
+     *
+     * @param momentsRequest
+     * @return
+     */
+    @Auth(value = AuthType.COOKIES)
+    @RequestMapping(value = "/member/publishMoments", method = RequestMethod.POST)
+    public Object publishMoments(@RequestBody MomentsRequest momentsRequest){
+        if(null == momentsRequest.getType()
+                || null == momentsRequest.getVisibleType()
+                || null == momentsRequest.getContentInfo()){
+            throw new AppRuntimeException(AppCode.BAD_REQUEST);
+        }
+        FamilyMemberInfo memberInfo = familyService.getMemberByUid(AppContext.getUid());
+        if(null == memberInfo){
+            throw new AppRuntimeException(AppCode.BAD_REQUEST);
+        }
+        // 公告判断管理员,没有设置管理员全员可发
+        if(momentsRequest.getType() == 1) {
+            // 没有设置失效时间默认永久有效
+            if(null == momentsRequest.getExpireTime()){
+                momentsRequest.setExpireTime(-1L);
+            }
+            List<FamilyConfigInfo> configInfoList = wechatService.getConfig(FamilyConfigEnum.ADMIN_USER.getConfigKey());
+            if (null != configInfoList && !configInfoList.isEmpty()) {
+                FamilyConfigInfo configInfo = configInfoList.get(0);
+                if(null != configInfo && StringUtils.isNotBlank(configInfo.getConfigValue())) {
+                    List<Long> adminUidList = Arrays.stream(configInfo.getConfigValue().split(","))
+                            .filter(s -> s != null && !s.trim().isEmpty())
+                            .map(Long::parseLong)
+                            .collect(Collectors.toList());
+                    if(!adminUidList.contains(AppContext.getUid())){
+                        throw new AppRuntimeException(AppCode.FORBIDDEN);
+                    }
+                }
+            }
+        }
+        if(!checkVisibleLegitimacy(memberInfo, momentsRequest)){
+            throw new AppRuntimeException("部分可见设置错误!");
+        }
+        return familyService.addFamilyMoments(AppContext.getUid(), momentsRequest);
+    }
+
+    /**
+     * 删除家族圈消息(仅能删自己).
+     *
+     * @param familyMoments 传递id
+     * @return true or false
+     */
+    @Auth(value = AuthType.COOKIES)
+    @RequestMapping(value = "/member/deleteMoments", method = RequestMethod.POST)
+    public Object deleteMoments(@RequestBody FamilyMoments familyMoments){
+        if(null == familyMoments || null == familyMoments.getId()){
+            throw new AppRuntimeException(AppCode.BAD_REQUEST);
+        }
+        return familyService.deleteMoments(familyMoments.getId(), AppContext.getUid());
+    }
+
+
+    /**
+     * 获取家族圈信息
+     *
+     * @param lastId 分页游标,上一页最后一个id
+     * @param pageSize 每页多少条数据.
+     * @return 返回Map结构:announcement:置顶公告 moments:家族圈
+     */
+    @Auth(value = AuthType.COOKIES)
+    @RequestMapping(value = "/member/getMoments", method = RequestMethod.GET)
+    public Object getMoments(@RequestParam(required = false) Long lastId, @RequestParam Integer pageSize){
+        // 置顶公告
+        List<FamilyMomentsAndPublishInfo> announcementList = familyService.getFamilyAnnouncementList(AppContext.getUid());
+        // 家族圈信息
+        List<FamilyMomentsAndPublishInfo> moments = familyService.getUserMomentsList(AppContext.getUid(), lastId, pageSize);
+        Map<String, Object> result = Maps.newHashMap();
+        result.put("announcement", announcementList);
+        result.put("moments", moments);
+        return result;
+    }
+
+    /**
+     * 新家族圈消息提示.
+     * @return
+     */
+    @Auth(value = AuthType.COOKIES)
+    @RequestMapping(value = "/member/newsRedDot", method = RequestMethod.GET)
+    public Object newsRedDot(){
+        return familyService.newsRedDot(AppContext.getUid());
+    }
+
+    private boolean checkVisibleLegitimacy(FamilyMemberInfo memberInfo, MomentsRequest momentsRequest){
+        if(momentsRequest.getVisibleType() == 0){
+            return true;
+        }
+        // 可见范围:0:全员 1:支系堂派 2:聚落 3:家族内男性 4:出生地
+        if(momentsRequest.getVisibleType() == 1
+                && StringUtils.isBlank(memberInfo.getBranchFamilyHall())){
+            throw new AppRuntimeException("仅支持发布到自己设置的支系堂派!");
+        } else if (momentsRequest.getVisibleType() == 2
+                && StringUtils.isBlank(memberInfo.getClusterPlace())) {
+            throw new AppRuntimeException("仅支持发布到自己设置的聚落!");
+        } else if (momentsRequest.getVisibleType() == 4
+                && StringUtils.isBlank(memberInfo.getBirthPlace())) {
+            throw new AppRuntimeException("仅支持发布到自己设置的出生第!");
+        }
+        return true;
+    }
 }

+ 21 - 40
mirage-service/src/main/java/com/mirage/mirageservice/controller/WxController.java

@@ -2,9 +2,12 @@ package com.mirage.mirageservice.controller;
 
 import com.mirage.core.annotation.Auth;
 import com.mirage.core.exception.AppRuntimeException;
+import com.mirage.core.meta.AppCode;
 import com.mirage.core.meta.AuthType;
+import com.mirage.mirageservice.enums.FamilyConfigEnum;
 import com.mirage.mirageservice.enums.MinProgramConfigEnum;
 import com.mirage.mirageservice.service.UserService;
+import com.mirage.mirageservice.service.WechatService;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.web.bind.annotation.RequestMapping;
 import org.springframework.web.bind.annotation.RequestMethod;
@@ -23,6 +26,8 @@ public class WxController {
 
     @Resource
     private UserService userService;
+    @Resource
+    private WechatService wechatService;
 
     @Auth(value = AuthType.OPEN)
     @RequestMapping(value = "/health", method = RequestMethod.GET)
@@ -74,44 +79,20 @@ public class WxController {
         }
         return userService.getUserWxInfo(code, configEnum);
     }
-//
-//    @Auth(value = AuthType.COOKIES)
-//    @RequestMapping(value = "/user/bind", method = RequestMethod.POST)
-//    public Object bind(@RequestBody BindRequest bindRequest){
-//        if(null == bindRequest
-//                || null == bindRequest.getScanPageId()
-//                || StringUtils.isBlank(bindRequest.getStudentName())){
-//            throw new AppRuntimeException(AppCode.BAD_REQUEST);
-//        }
-//        String openId = AppContext.getUserInfo().getOpenId();
-//        if(StringUtils.isBlank(openId)){
-//            throw new AppRuntimeException(AppCode.UNAUTHORIZED);
-//        }
-//        bindRequest.setOpenId(openId);
-//        return userService.bind(bindRequest);
-//    }
-//
-//    @Auth(value = AuthType.COOKIES)
-//    @RequestMapping(value = "/user/unbind")
-//    public Object unbind(){
-//        String openId = AppContext.getUserInfo().getOpenId();
-//        if(StringUtils.isBlank(openId)){
-//            throw new AppRuntimeException(AppCode.UNAUTHORIZED);
-//        }
-//        return userService.unBind(openId);
-//    }
-//
-//    @Auth(value = AuthType.COOKIES)
-//    @RequestMapping(value = "/user/reports", method = RequestMethod.GET)
-//    public Object reportList(@RequestParam String openId,
-//                             @RequestParam(required = false, defaultValue = "1") Integer pageIndex,
-//                             @RequestParam(required = false, defaultValue = "10") Integer pageSize){
-//        return userService.reportList(openId, pageIndex, pageSize);
-//    }
-//
-//    @Auth(value = AuthType.COOKIES)
-//    @RequestMapping(value = "/user/report/{id}", method = RequestMethod.GET)
-//    public Object getReportDetail(@PathVariable Integer id){
-//        return userService.getReportDetail(id);
-//    }
+
+    /**
+     * 通用配置获取
+     * @param configKey (首页头图:CAROUSEL, 发起人专区:HONOR)
+     * @return 配置一小时缓存.
+     */
+    @Auth(value = AuthType.COOKIES)
+    @RequestMapping(value = "/config/getConfig", method = RequestMethod.GET)
+    public Object getConfigInfo(@RequestParam String configKey){
+        FamilyConfigEnum familyConfigEnum = FamilyConfigEnum.getByConfigKey(configKey);
+        if(null == familyConfigEnum){
+            throw new AppRuntimeException(AppCode.BAD_REQUEST);
+        }
+        return wechatService.getConfig(configKey);
+    }
+
 }

+ 77 - 0
mirage-service/src/main/java/com/mirage/mirageservice/domain/FamilyConfigInfo.java

@@ -0,0 +1,77 @@
+package com.mirage.mirageservice.domain;
+
+import java.util.Date;
+
+/** 
+* Created by hzlinhai on 2025/10/23. 
+*/
+/**
+ * 通用配置表
+ */
+public class FamilyConfigInfo {
+    private Long id;
+
+    /**
+    * 对应FamilyConfigEnum值
+    */
+    private String configKey;
+
+    /**
+    * 配置值,json,eg: {"imgUrl","xxx","clickUrl":"","content":""}
+    */
+    private String configValue;
+
+    private Integer isDeleted;
+
+    private Date gmtCreate;
+
+    private Date gmtModified;
+
+    public Long getId() {
+        return id;
+    }
+
+    public void setId(Long id) {
+        this.id = id;
+    }
+
+    public String getConfigKey() {
+        return configKey;
+    }
+
+    public void setConfigKey(String configKey) {
+        this.configKey = configKey;
+    }
+
+    public String getConfigValue() {
+        return configValue;
+    }
+
+    public void setConfigValue(String configValue) {
+        this.configValue = configValue;
+    }
+
+    public Integer getIsDeleted() {
+        return isDeleted;
+    }
+
+    public void setIsDeleted(Integer isDeleted) {
+        this.isDeleted = isDeleted;
+    }
+
+    public Date getGmtCreate() {
+        return gmtCreate;
+    }
+
+    public void setGmtCreate(Date gmtCreate) {
+        this.gmtCreate = gmtCreate;
+    }
+
+    public Date getGmtModified() {
+        return gmtModified;
+    }
+
+    public void setGmtModified(Date gmtModified) {
+        this.gmtModified = gmtModified;
+    }
+}

+ 113 - 0
mirage-service/src/main/java/com/mirage/mirageservice/domain/FamilyMemberPhotoAlbum.java

@@ -0,0 +1,113 @@
+package com.mirage.mirageservice.domain;
+
+import java.util.Date;
+
+/** 
+* Created by hzlinhai on 2025/10/23. 
+*/
+/**
+ * 个人相册表
+ */
+public class FamilyMemberPhotoAlbum {
+    private Long id;
+
+    /**
+    * 图片或者视频url
+    */
+    private String url;
+
+    /**
+    * 0:图片 1:视频
+    */
+    private Integer type;
+
+    /**
+    * 成员表id
+    */
+    private Long mid;
+
+    /**
+    * 用户表id
+    */
+    private Long uid;
+
+    private Date uploadTime;
+
+    private Integer isDeleted;
+
+    private Date gmtCreate;
+
+    private Date gmtModified;
+
+    public Long getId() {
+        return id;
+    }
+
+    public void setId(Long id) {
+        this.id = id;
+    }
+
+    public String getUrl() {
+        return url;
+    }
+
+    public void setUrl(String url) {
+        this.url = url;
+    }
+
+    public Integer getType() {
+        return type;
+    }
+
+    public void setType(Integer type) {
+        this.type = type;
+    }
+
+    public Long getMid() {
+        return mid;
+    }
+
+    public void setMid(Long mid) {
+        this.mid = mid;
+    }
+
+    public Long getUid() {
+        return uid;
+    }
+
+    public void setUid(Long uid) {
+        this.uid = uid;
+    }
+
+    public Date getUploadTime() {
+        return uploadTime;
+    }
+
+    public void setUploadTime(Date uploadTime) {
+        this.uploadTime = uploadTime;
+    }
+
+    public Integer getIsDeleted() {
+        return isDeleted;
+    }
+
+    public void setIsDeleted(Integer isDeleted) {
+        this.isDeleted = isDeleted;
+    }
+
+    public Date getGmtCreate() {
+        return gmtCreate;
+    }
+
+    public void setGmtCreate(Date gmtCreate) {
+        this.gmtCreate = gmtCreate;
+    }
+
+    public Date getGmtModified() {
+        return gmtModified;
+    }
+
+    public void setGmtModified(Date gmtModified) {
+        this.gmtModified = gmtModified;
+    }
+}

+ 143 - 0
mirage-service/src/main/java/com/mirage/mirageservice/domain/FamilyMoments.java

@@ -0,0 +1,143 @@
+package com.mirage.mirageservice.domain;
+
+import java.util.Date;
+
+/** 
+* Created by hzlinhai on 2025/10/23. 
+*/
+
+/**
+ * 家族圈
+ */
+public class FamilyMoments {
+    private Long id;
+
+    /**
+     * 0:普通消息 1:定置公告
+     */
+    private Integer type;
+
+    /**
+     * 发布人
+     */
+    private Long publishUid;
+
+    /**
+     * 发布时间
+     */
+    private Date publishTime;
+
+    /**
+     * 公告设置实效时间,长期有效填-1
+     */
+    private Long expireTime;
+
+    /**
+     * json,eg: {"text":"我是一条家族圈","media":[{"url":"","type":0,"order":0},{"url":"","type":1,"order":1}]}
+     */
+    private String content;
+
+    /**
+     * 可见范围:0:全员 1:支系堂派 2:聚落 3:家族内男性 4:出生地
+     */
+    private Integer visibleType;
+
+    /**
+     * 对应visible_type值
+     */
+    private String visibleValue;
+
+    private Integer isDeleted;
+
+    private Date gmtCreate;
+
+    private Date gmtModified;
+
+    public Long getId() {
+        return id;
+    }
+
+    public void setId(Long id) {
+        this.id = id;
+    }
+
+    public Integer getType() {
+        return type;
+    }
+
+    public void setType(Integer type) {
+        this.type = type;
+    }
+
+    public Long getPublishUid() {
+        return publishUid;
+    }
+
+    public void setPublishUid(Long publishUid) {
+        this.publishUid = publishUid;
+    }
+
+    public Date getPublishTime() {
+        return publishTime;
+    }
+
+    public void setPublishTime(Date publishTime) {
+        this.publishTime = publishTime;
+    }
+
+    public Long getExpireTime() {
+        return expireTime;
+    }
+
+    public void setExpireTime(Long expireTime) {
+        this.expireTime = expireTime;
+    }
+
+    public String getContent() {
+        return content;
+    }
+
+    public void setContent(String content) {
+        this.content = content;
+    }
+
+    public Integer getVisibleType() {
+        return visibleType;
+    }
+
+    public void setVisibleType(Integer visibleType) {
+        this.visibleType = visibleType;
+    }
+
+    public String getVisibleValue() {
+        return visibleValue;
+    }
+
+    public void setVisibleValue(String visibleValue) {
+        this.visibleValue = visibleValue;
+    }
+
+    public Integer getIsDeleted() {
+        return isDeleted;
+    }
+
+    public void setIsDeleted(Integer isDeleted) {
+        this.isDeleted = isDeleted;
+    }
+
+    public Date getGmtCreate() {
+        return gmtCreate;
+    }
+
+    public void setGmtCreate(Date gmtCreate) {
+        this.gmtCreate = gmtCreate;
+    }
+
+    public Date getGmtModified() {
+        return gmtModified;
+    }
+
+    public void setGmtModified(Date gmtModified) {
+        this.gmtModified = gmtModified;
+    }
+}

+ 35 - 0
mirage-service/src/main/java/com/mirage/mirageservice/enums/FamilyConfigEnum.java

@@ -0,0 +1,35 @@
+package com.mirage.mirageservice.enums;
+
+import lombok.Getter;
+
+/**
+ * Created by hzlinhai on 2025/10/23.
+ */
+@Getter
+public enum FamilyConfigEnum {
+
+    CAROUSEL("CAROUSEL", "轮播图配置Key"),
+
+    HONOR("HONOR", "发起人专区配置Key"),
+
+    ADMIN_USER("ADMIN_USER", "管理员列表");
+
+    private String configKey;
+
+    private String description;
+
+    FamilyConfigEnum(String configKey, String description){
+        this.configKey = configKey;
+        this.description = description;
+    }
+
+    public static FamilyConfigEnum getByConfigKey(String configKey){
+        FamilyConfigEnum[] familyConfigEnums = FamilyConfigEnum.values();
+        for(FamilyConfigEnum familyConfigEnum : familyConfigEnums){
+            if(familyConfigEnum.getConfigKey().equals(configKey)){
+                return familyConfigEnum;
+            }
+        }
+        return null;
+    }
+}

+ 2 - 0
mirage-service/src/main/java/com/mirage/mirageservice/enums/FamilyRelationEnum.java

@@ -8,6 +8,8 @@ import lombok.Getter;
 @Getter
 public enum FamilyRelationEnum {
 
+    OTHER(-1, "其他"),
+
     SELF(0, "自己"),
 
     FATHER(1, "父亲"),

+ 26 - 0
mirage-service/src/main/java/com/mirage/mirageservice/mapper/mysql/FamilyConfigInfoMapper.java

@@ -0,0 +1,26 @@
+package com.mirage.mirageservice.mapper.mysql;
+import org.apache.ibatis.annotations.Param;
+import java.util.List;
+
+import com.mirage.mirageservice.domain.FamilyConfigInfo;
+
+/** 
+* Created by hzlinhai on 2025/10/23. 
+*/
+public interface FamilyConfigInfoMapper {
+    int deleteByPrimaryKey(Long id);
+
+    int insert(FamilyConfigInfo record);
+
+    int insertSelective(FamilyConfigInfo record);
+
+    FamilyConfigInfo selectByPrimaryKey(Long id);
+
+    int updateByPrimaryKeySelective(FamilyConfigInfo record);
+
+    int updateByPrimaryKey(FamilyConfigInfo record);
+
+    List<FamilyConfigInfo> selectAllByConfigKeyAndIsDeletedOrderByGmtModified(@Param("configKey")String configKey,@Param("isDeleted")Integer isDeleted);
+
+
+}

+ 27 - 0
mirage-service/src/main/java/com/mirage/mirageservice/mapper/mysql/FamilyMemberPhotoAlbumMapper.java

@@ -0,0 +1,27 @@
+package com.mirage.mirageservice.mapper.mysql;
+import org.apache.ibatis.annotations.Param;
+import java.util.List;
+
+import com.mirage.mirageservice.domain.FamilyMemberPhotoAlbum;
+
+/** 
+* Created by hzlinhai on 2025/10/23. 
+*/
+public interface FamilyMemberPhotoAlbumMapper {
+    int deleteByPrimaryKey(Long id);
+
+    int insert(FamilyMemberPhotoAlbum record);
+
+    int insertSelective(FamilyMemberPhotoAlbum record);
+
+    FamilyMemberPhotoAlbum selectByPrimaryKey(Long id);
+
+    int updateByPrimaryKeySelective(FamilyMemberPhotoAlbum record);
+
+    int updateByPrimaryKey(FamilyMemberPhotoAlbum record);
+
+    List<FamilyMemberPhotoAlbum> selectAllByMidAndIsDeletedOrderByUploadTimeDesc(@Param("mid")Long mid,@Param("isDeleted")Integer isDeleted);
+
+    List<FamilyMemberPhotoAlbum> selectAllByMidAndTypeAndIsDeletedOrderByUploadTimeDesc(@Param("mid")Long mid,@Param("type")Integer type,@Param("isDeleted")Integer isDeleted);
+
+}

+ 26 - 0
mirage-service/src/main/java/com/mirage/mirageservice/mapper/mysql/FamilyMomentsMapper.java

@@ -0,0 +1,26 @@
+package com.mirage.mirageservice.mapper.mysql;
+import org.apache.ibatis.annotations.Param;
+import java.util.List;
+
+import com.mirage.mirageservice.domain.FamilyMoments;
+
+/**
+ * Created by hzlinhai on 2025/10/23.
+ */
+public interface FamilyMomentsMapper {
+    int deleteByPrimaryKey(Long id);
+
+    int insert(FamilyMoments record);
+
+    int insertSelective(FamilyMoments record);
+
+    FamilyMoments selectByPrimaryKey(Long id);
+
+    int updateByPrimaryKeySelective(FamilyMoments record);
+
+    int updateByPrimaryKey(FamilyMoments record);
+
+    List<FamilyMoments> selectAllByTypeAndExpireTimeGreaterThanOrExpireTimeAndIsDeletedAndVisibleTypeOrderByPublishTimeDesc(@Param("type")Integer type,@Param("minExpireTime")Long minExpireTime,@Param("expireTime")Long expireTime,@Param("isDeleted")Integer isDeleted,@Param("visibleType")Integer visibleType);
+
+    List<FamilyMoments> selectAllMoments(@Param("type")Integer type, @Param("isDeleted")Integer isDeleted, @Param("visibleType")Integer visibleType, @Param("id")Long id, @Param("pageSize")Integer pageSize);
+}

+ 20 - 0
mirage-service/src/main/java/com/mirage/mirageservice/meta/FamilyMomentsAndPublishInfo.java

@@ -0,0 +1,20 @@
+package com.mirage.mirageservice.meta;
+
+import com.mirage.mirageservice.domain.FamilyMemberInfo;
+import com.mirage.mirageservice.domain.FamilyMoments;
+import lombok.Data;
+
+/**
+ * Created by hzlinhai on 2025/10/23.
+ */
+@Data
+public class FamilyMomentsAndPublishInfo {
+
+    private FamilyMoments familyMoments;
+
+    private FamilyMemberInfo publishMemberInfo;
+
+    public FamilyMomentsAndPublishInfo(){}
+
+    public FamilyMomentsAndPublishInfo(FamilyMoments familyMoments, FamilyMemberInfo publishMemberInfo){}
+}

+ 5 - 0
mirage-service/src/main/java/com/mirage/mirageservice/meta/MemberInfoRequest.java

@@ -20,4 +20,9 @@ public class MemberInfoRequest {
     private MemberRelationRequest relationRequest;
 
     private FamilyMemberInfo memberInfo;
+
+    /**
+     * 如帮自己父亲填写父亲关系亲属时传递父亲的mid
+     */
+    private Long sourceMid;
 }

+ 3 - 0
mirage-service/src/main/java/com/mirage/mirageservice/meta/MemberRelationRequest.java

@@ -8,6 +8,9 @@ import lombok.Data;
 @Data
 public class MemberRelationRequest {
 
+    /**
+     *
+     */
     private Integer relationType;
 
     /**

+ 16 - 0
mirage-service/src/main/java/com/mirage/mirageservice/meta/MomentsContentInfo.java

@@ -0,0 +1,16 @@
+package com.mirage.mirageservice.meta;
+
+import lombok.Data;
+
+import java.util.List;
+
+/**
+ * Created by hzlinhai on 2025/10/23.
+ */
+@Data
+public class MomentsContentInfo {
+
+    private String text;
+
+    private List<MomentsMediaInfo> mediaList;
+}

+ 23 - 0
mirage-service/src/main/java/com/mirage/mirageservice/meta/MomentsMediaInfo.java

@@ -0,0 +1,23 @@
+package com.mirage.mirageservice.meta;
+
+import lombok.Data;
+
+/**
+ * Created by hzlinhai on 2025/10/23.
+ */
+@Data
+public class MomentsMediaInfo {
+
+    /**
+     * 链接
+     */
+    private String url;
+    /**
+     * 0:图片 1:视频
+     */
+    private Integer type;
+    /**
+     * 内容排序字段
+     */
+    private Integer order;
+}

+ 33 - 0
mirage-service/src/main/java/com/mirage/mirageservice/meta/MomentsRequest.java

@@ -0,0 +1,33 @@
+package com.mirage.mirageservice.meta;
+
+import lombok.Data;
+
+/**
+ * Created by hzlinhai on 2025/10/23.
+ */
+@Data
+public class MomentsRequest {
+
+    /**
+     * 0:普通消息 1:顶置公告
+     */
+    private Integer type;
+
+    /**
+     * 公告设置实效时间,长期有效填-1
+     */
+    private Long expireTime;
+    /**
+     * 可见范围:0:全员 1:支系堂派 2:聚落 3:家族内男性 4:出生地
+     */
+    private Integer visibleType;
+
+    /**
+     * 对应visible_type值
+     */
+    private String visibleValue;
+    /**
+     * 内容
+     */
+    private MomentsContentInfo contentInfo;
+}

+ 221 - 12
mirage-service/src/main/java/com/mirage/mirageservice/service/FamilyService.java

@@ -1,25 +1,28 @@
 package com.mirage.mirageservice.service;
 
+import com.github.pagehelper.PageHelper;
 import com.google.common.collect.Lists;
-import com.mirage.mirageservice.domain.CsMinWechatUser;
-import com.mirage.mirageservice.domain.FamilyMemberInfo;
-import com.mirage.mirageservice.domain.FamilyRelationInfo;
-import com.mirage.mirageservice.domain.FamilyTreeInfo;
+import com.mirage.core.meta.PageResultVo;
+import com.mirage.core.meta.PageUtil;
+import com.mirage.core.utils.GsonUtil;
+import com.mirage.mirageservice.domain.*;
 import com.mirage.mirageservice.enums.FamilyRelationEnum;
 import com.mirage.mirageservice.mapper.mysql.FamilyMemberInfoMapper;
+import com.mirage.mirageservice.mapper.mysql.FamilyMemberPhotoAlbumMapper;
+import com.mirage.mirageservice.mapper.mysql.FamilyMomentsMapper;
 import com.mirage.mirageservice.mapper.mysql.FamilyRelationInfoMapper;
-import com.mirage.mirageservice.meta.FamilyMemberInfoAndRelation;
-import com.mirage.mirageservice.meta.FamilyTreeResponse;
-import com.mirage.mirageservice.meta.MemberInfoRequest;
-import com.mirage.mirageservice.meta.SelfFamilyCardResponse;
+import com.mirage.mirageservice.meta.*;
 import lombok.extern.slf4j.Slf4j;
 import org.apache.commons.lang3.StringUtils;
+import org.springframework.data.redis.core.StringRedisTemplate;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 
 import javax.annotation.Resource;
 import java.util.Date;
+import java.util.LinkedList;
 import java.util.List;
+import java.util.Objects;
 import java.util.stream.Collectors;
 
 /**
@@ -29,10 +32,17 @@ import java.util.stream.Collectors;
 @Slf4j
 public class FamilyService {
 
+    private static final String REDIS_MOMENTS_LAST_ID = "redis_moments_last_id_";
+    @Resource
+    private StringRedisTemplate stringRedisTemplate;
     @Resource
     private FamilyMemberInfoMapper familyMemberInfoMapper;
     @Resource
     private FamilyRelationInfoMapper familyRelationInfoMapper;
+    @Resource
+    private FamilyMemberPhotoAlbumMapper familyMemberPhotoAlbumMapper;
+    @Resource
+    private FamilyMomentsMapper familyMomentsMapper;
 
     public SelfFamilyCardResponse getSelfFamilyMember(Long uid){
         SelfFamilyCardResponse familyCardResponse = new SelfFamilyCardResponse();
@@ -219,12 +229,14 @@ public class FamilyService {
             if(null == selfMemberInfo){
                 throw new Exception("请先填写自己信息再录入亲属信息");
             }
+            // 当帮其他人填写亲属信息时,替换此信息,关系表中关联用户非自己
+            Long operationMid = null == request.getSourceMid() ? selfMemberInfo.getId() : request.getSourceMid();
             // 保存亲属关系
             FamilyRelationInfo relationInfo = null;
             switch (relationEnum) {
                 case FATHER:
                     relationInfo = new FamilyRelationInfo();
-                    relationInfo.setChildMid(selfMemberInfo.getId());
+                    relationInfo.setChildMid(operationMid);
                     relationInfo.setParentMid(memberInfo.getId());
                     relationInfo.setRelationType(FamilyRelationEnum.FATHER.getType());
                     relationInfo.setSubRelationType(request.getRelationRequest().getSubRelationType());
@@ -233,7 +245,7 @@ public class FamilyService {
                     break;
                 case MATHER:
                     relationInfo = new FamilyRelationInfo();
-                    relationInfo.setChildMid(selfMemberInfo.getId());
+                    relationInfo.setChildMid(operationMid);
                     relationInfo.setParentMid(memberInfo.getId());
                     relationInfo.setRelationType(FamilyRelationEnum.MATHER.getType());
                     relationInfo.setSubRelationType(request.getRelationRequest().getSubRelationType());
@@ -252,7 +264,7 @@ public class FamilyService {
                 case DAUGHTER:
                     relationInfo = new FamilyRelationInfo();
                     relationInfo.setChildMid(memberInfo.getId());
-                    relationInfo.setParentMid(selfMemberInfo.getId());
+                    relationInfo.setParentMid(operationMid);
                     relationInfo.setRelationType(FamilyRelationEnum.FATHER.getType());
                     relationInfo.setSubRelationType(request.getRelationRequest().getSubRelationType());
                     relationInfo.setRelationValue(request.getRelationRequest().getRelationValue());
@@ -271,7 +283,7 @@ public class FamilyService {
                     break;
             }
             if(null != relationInfo) {
-                relationInfo.setSourceMid(selfMemberInfo.getId());
+                relationInfo.setSourceMid(operationMid);
                 relationInfo.setRelationStatus(request.getRelationRequest().getRelationStatus());
                 relationInfo.setCreateTime(new Date());
                 relationInfo.setModifiedTime(new Date());
@@ -284,4 +296,201 @@ public class FamilyService {
         }
         return memberInfo;
     }
+
+    public boolean uploadMemberAlbum(Long uid, FamilyMemberPhotoAlbum memberPhotoAlbum){
+        if(null == uid
+                || null == memberPhotoAlbum
+                || StringUtils.isBlank(memberPhotoAlbum.getUrl())){
+            return false;
+        }
+        // mid为空上传自己相册
+        if(null == memberPhotoAlbum.getMid()){
+            FamilyMemberInfo memberInfo = this.getMemberByUid(uid);
+            if(null == memberInfo){
+                return false;
+            }
+            memberPhotoAlbum.setMid(memberInfo.getId());
+        }
+        memberPhotoAlbum.setUid(uid);
+        memberPhotoAlbum.setGmtCreate(new Date());
+        memberPhotoAlbum.setGmtModified(new Date());
+        memberPhotoAlbum.setUploadTime(new Date());
+        memberPhotoAlbum.setIsDeleted(0);
+        familyMemberPhotoAlbumMapper.insertSelective(memberPhotoAlbum);
+        return true;
+    }
+
+    public PageResultVo<FamilyMemberPhotoAlbum> getMemberPhotoAlbum(Long mid, Integer type, Integer pageSize, Integer pageIndex){
+        if(null == mid){
+            return null;
+        }
+        PageHelper.startPage(pageIndex, pageSize);
+        return PageUtil.convertPageResult(familyMemberPhotoAlbumMapper.selectAllByMidAndTypeAndIsDeletedOrderByUploadTimeDesc(mid, type, 0));
+    }
+
+    public boolean deletePhotoAlbumById(Long id){
+        if(null == id){
+            return false;
+        }
+        FamilyMemberPhotoAlbum familyMemberPhotoAlbum = familyMemberPhotoAlbumMapper.selectByPrimaryKey(id);
+        if(null == familyMemberPhotoAlbum || familyMemberPhotoAlbum.getIsDeleted() == 1){
+            return true;
+        }
+        familyMemberPhotoAlbum.setIsDeleted(1);
+        familyMemberPhotoAlbum.setGmtModified(new Date());
+        familyMemberPhotoAlbumMapper.updateByPrimaryKeySelective(familyMemberPhotoAlbum);
+        return true;
+    }
+
+    public boolean addFamilyMoments(Long uid, MomentsRequest momentsRequest){
+        if(null == uid
+                || null == momentsRequest.getType()
+                || null == momentsRequest.getVisibleType()
+                || null == momentsRequest.getContentInfo()){
+            return false;
+        }
+        FamilyMemberInfo memberInfo = this.getMemberByUid(uid);
+        if(null == memberInfo){
+            return false;
+        }
+        // 可见范围:0:全员 1:支系堂派 2:聚落 3:家族内男性 4:出生地
+        FamilyMoments familyMoments = new FamilyMoments();
+        familyMoments.setType(momentsRequest.getType());
+        familyMoments.setExpireTime(momentsRequest.getExpireTime());
+        familyMoments.setContent(GsonUtil.toJson(momentsRequest.getContentInfo()));
+        familyMoments.setPublishUid(uid);
+        familyMoments.setPublishTime(new Date());
+        familyMoments.setVisibleType(momentsRequest.getVisibleType());
+        if(momentsRequest.getVisibleType() == 1){
+            familyMoments.setVisibleValue(memberInfo.getBranchFamilyHall());
+        } else if(momentsRequest.getVisibleType() == 2){
+            familyMoments.setVisibleValue(memberInfo.getClusterPlace());
+        } else if (momentsRequest.getVisibleType() == 3) {
+            familyMoments.setVisibleValue("1");
+        } else if (momentsRequest.getVisibleType() == 4) {
+            familyMoments.setVisibleValue(memberInfo.getBirthPlace());
+        }
+        familyMoments.setIsDeleted(0);
+        familyMoments.setGmtCreate(new Date());
+        familyMoments.setGmtModified(new Date());
+        familyMomentsMapper.insertSelective(familyMoments);
+        return true;
+    }
+
+    public boolean deleteMoments(Long id, Long uid){
+        if(null == id || null == uid){
+            return false;
+        }
+        FamilyMoments moments = familyMomentsMapper.selectByPrimaryKey(id);
+        if(null == moments || moments.getIsDeleted() == 1){
+            return true;
+        }
+        if(!Objects.equals(moments.getPublishUid(), uid)){
+            return false;
+        }
+        moments.setIsDeleted(1);
+        moments.setGmtModified(new Date());
+        familyMomentsMapper.updateByPrimaryKeySelective(moments);
+    }
+
+    public List<FamilyMomentsAndPublishInfo> getFamilyAnnouncementList(Long uid){
+        LinkedList<FamilyMomentsAndPublishInfo> result = Lists.newLinkedList();
+        List<FamilyMoments> familyMoments = familyMomentsMapper.selectAllByTypeAndExpireTimeGreaterThanOrExpireTimeAndIsDeletedAndVisibleTypeOrderByPublishTimeDesc(1, System.currentTimeMillis(), -1L, 0, null);
+        if(null == familyMoments || familyMoments.isEmpty()){
+            return result;
+        }
+        for(FamilyMoments moments : familyMoments){
+            FamilyMemberInfo memberInfo = familyMemberInfoMapper.selectByUid(moments.getPublishUid());
+            result.add(new FamilyMomentsAndPublishInfo(moments, memberInfo));
+        }
+        return result;
+    }
+
+    public List<FamilyMomentsAndPublishInfo> getUserMomentsList(Long uid, Long lastId, Integer pageSize){
+        FamilyMemberInfo memberInfo = familyMemberInfoMapper.selectByUid(uid);
+        if(null == memberInfo){
+            return null;
+        }
+        LinkedList<FamilyMomentsAndPublishInfo> result = Lists.newLinkedList();
+        List<FamilyMoments> familyMoments = familyMomentsMapper.selectAllMoments(0, 0, null, lastId, pageSize);
+        if(null == familyMoments || familyMoments.isEmpty()){
+            return null;
+        }
+        for(FamilyMoments moments : familyMoments){
+            if(moments.getVisibleType() == 0){
+                result.add(new FamilyMomentsAndPublishInfo(moments, memberInfo));
+                continue;
+            }
+            if(moments.getVisibleType() == 1
+                    && StringUtils.isNotBlank(memberInfo.getBranchFamilyHall())
+                    && memberInfo.getBranchFamilyHall().equals(moments.getVisibleValue())){
+                result.add(new FamilyMomentsAndPublishInfo(moments, memberInfo));
+            } else if(moments.getVisibleType() == 2
+                    && StringUtils.isNotBlank(memberInfo.getClusterPlace())
+                    && memberInfo.getClusterPlace().equals(moments.getVisibleValue())){
+                result.add(new FamilyMomentsAndPublishInfo(moments, memberInfo));
+            } else if (moments.getVisibleType() == 3
+                    && Integer.parseInt(moments.getVisibleValue()) == memberInfo.getSex()) {
+                result.add(new FamilyMomentsAndPublishInfo(moments, memberInfo));
+            } else if (moments.getVisibleType() == 4
+                    && StringUtils.isNotBlank(memberInfo.getBirthPlace())
+                    && (memberInfo.getBirthPlace().contains(moments.getVisibleValue())
+                    || memberInfo.getBirthPlace().equalsIgnoreCase(moments.getVisibleValue()))) {
+                result.add(new FamilyMomentsAndPublishInfo(moments, memberInfo));
+            }
+        }
+         // 最后一个id记录,用于红点提示
+        Long alreadyReadId = result.get(result.size() - 1).getFamilyMoments().getId();
+        stringRedisTemplate.boundValueOps(REDIS_MOMENTS_LAST_ID).set(String.valueOf(alreadyReadId));
+        return result;
+    }
+
+    /**
+     * 新家族圈消息提示.
+     *
+     * @param uid
+     * @return
+     */
+    public boolean newsRedDot(Long uid){
+        if(null == uid){
+            return false;
+        }
+        String cacheValue = stringRedisTemplate.boundValueOps(REDIS_MOMENTS_LAST_ID).get();
+        Long lastId = StringUtils.isBlank(cacheValue) ? null : Long.parseLong(cacheValue);
+        List<FamilyMoments> familyMoments = familyMomentsMapper.selectAllMoments(0, 0, null, lastId, 1000);
+        if(null == familyMoments || familyMoments.isEmpty()){
+            return false;
+        }
+        FamilyMemberInfo memberInfo = this.getMemberByUid(uid);
+        if(null == memberInfo){
+            return false;
+        }
+        for(FamilyMoments moments : familyMoments){
+            if(moments.getVisibleType() == 0){
+                return true;
+            }
+            if(moments.getVisibleType() == 1
+                    && StringUtils.isNotBlank(memberInfo.getBranchFamilyHall())
+                    && memberInfo.getBranchFamilyHall().equals(moments.getVisibleValue())){
+                return true;
+            } else if(moments.getVisibleType() == 2
+                    && StringUtils.isNotBlank(memberInfo.getClusterPlace())
+                    && memberInfo.getClusterPlace().equals(moments.getVisibleValue())){
+                return true;
+            } else if (moments.getVisibleType() == 3
+                    && Integer.parseInt(moments.getVisibleValue()) == memberInfo.getSex()) {
+                return true;
+            } else if (moments.getVisibleType() == 4
+                    && StringUtils.isNotBlank(memberInfo.getBirthPlace())
+                    && (memberInfo.getBirthPlace().contains(moments.getVisibleValue())
+                    || memberInfo.getBirthPlace().equalsIgnoreCase(moments.getVisibleValue()))) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+
 }
+
+

+ 26 - 0
mirage-service/src/main/java/com/mirage/mirageservice/service/WechatService.java

@@ -1,10 +1,13 @@
 package com.mirage.mirageservice.service;
 
 import com.google.gson.JsonObject;
+import com.google.gson.reflect.TypeToken;
 import com.mirage.core.utils.AppHttpClient;
 import com.mirage.core.utils.Constants;
 import com.mirage.core.utils.GsonUtil;
+import com.mirage.mirageservice.domain.FamilyConfigInfo;
 import com.mirage.mirageservice.enums.MinProgramConfigEnum;
+import com.mirage.mirageservice.mapper.mysql.FamilyConfigInfoMapper;
 import lombok.extern.slf4j.Slf4j;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.http.client.methods.HttpUriRequest;
@@ -14,6 +17,8 @@ import org.springframework.stereotype.Service;
 
 import javax.annotation.Resource;
 import java.io.IOException;
+import java.util.List;
+import java.util.concurrent.TimeUnit;
 
 /**
  * Created by hzlinhai on 2025/1/2.
@@ -23,8 +28,13 @@ import java.io.IOException;
 public class WechatService {
 
     private static final String REDIS_REQUEST_ACCESS_TOKEN_LOCK_KEY = "REDIS-requestAccessToken-lock";
+    private static final String REDIS_KEY_CONFIG_INFO = "redis_config_info_";
+    private static final Long REDIS_CONFIG_EXPIRE_TIME_CONFIG = 60*60*1000L;
     @Resource
     private StringRedisTemplate stringRedisTemplate;
+    @Resource
+    private FamilyConfigInfoMapper familyConfigInfoMapper;
+
 
     public String requestAccessToken(int retry, MinProgramConfigEnum programConfigEnum){
         if(retry > 3){
@@ -78,4 +88,20 @@ public class WechatService {
             return null;
         }
     }
+
+    public List<FamilyConfigInfo> getConfig(String configKey){
+        if(StringUtils.isBlank(configKey)){
+            return null;
+        }
+        String cacheValue = stringRedisTemplate.boundValueOps(REDIS_KEY_CONFIG_INFO+configKey).get();
+        if(StringUtils.isBlank(cacheValue)){
+            List<FamilyConfigInfo> configList = familyConfigInfoMapper.selectAllByConfigKeyAndIsDeletedOrderByGmtModified(configKey, 0);
+            if(null == configList){
+                return null;
+            }
+            stringRedisTemplate.boundValueOps(REDIS_KEY_CONFIG_INFO+configKey).set(GsonUtil.toJson(configList), REDIS_CONFIG_EXPIRE_TIME_CONFIG, TimeUnit.MICROSECONDS);
+            return configList;
+        }
+        return GsonUtil.fromJson(cacheValue, new TypeToken<List<FamilyConfigInfo>>() {}.getType());
+    }
 }

+ 116 - 0
mirage-service/src/main/resources/com/mirage/mirageservice/mapper/mysql/FamilyConfigInfoMapper.xml

@@ -0,0 +1,116 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.mirage.mirageservice.mapper.mysql.FamilyConfigInfoMapper">
+  <resultMap id="BaseResultMap" type="com.mirage.mirageservice.domain.FamilyConfigInfo">
+    <!--@mbg.generated-->
+    <!--@Table family_config_info-->
+    <id column="id" jdbcType="BIGINT" property="id" />
+    <result column="config_key" jdbcType="VARCHAR" property="configKey" />
+    <result column="config_value" jdbcType="LONGVARCHAR" property="configValue" />
+    <result column="is_deleted" jdbcType="INTEGER" property="isDeleted" />
+    <result column="gmt_create" jdbcType="TIMESTAMP" property="gmtCreate" />
+    <result column="gmt_modified" jdbcType="TIMESTAMP" property="gmtModified" />
+  </resultMap>
+  <sql id="Base_Column_List">
+    <!--@mbg.generated-->
+    id, config_key, config_value, is_deleted, gmt_create, gmt_modified
+  </sql>
+  <select id="selectByPrimaryKey" parameterType="java.lang.Long" resultMap="BaseResultMap">
+    <!--@mbg.generated-->
+    select 
+    <include refid="Base_Column_List" />
+    from family_config_info
+    where id = #{id,jdbcType=BIGINT}
+  </select>
+  <delete id="deleteByPrimaryKey" parameterType="java.lang.Long">
+    <!--@mbg.generated-->
+    delete from family_config_info
+    where id = #{id,jdbcType=BIGINT}
+  </delete>
+  <insert id="insert" keyColumn="id" keyProperty="id" parameterType="com.mirage.mirageservice.domain.FamilyConfigInfo" useGeneratedKeys="true">
+    <!--@mbg.generated-->
+    insert into family_config_info (config_key, config_value, is_deleted, 
+      gmt_create, gmt_modified)
+    values (#{configKey,jdbcType=VARCHAR}, #{configValue,jdbcType=LONGVARCHAR}, #{isDeleted,jdbcType=INTEGER}, 
+      #{gmtCreate,jdbcType=TIMESTAMP}, #{gmtModified,jdbcType=TIMESTAMP})
+  </insert>
+  <insert id="insertSelective" keyColumn="id" keyProperty="id" parameterType="com.mirage.mirageservice.domain.FamilyConfigInfo" useGeneratedKeys="true">
+    <!--@mbg.generated-->
+    insert into family_config_info
+    <trim prefix="(" suffix=")" suffixOverrides=",">
+      <if test="configKey != null">
+        config_key,
+      </if>
+      <if test="configValue != null">
+        config_value,
+      </if>
+      <if test="isDeleted != null">
+        is_deleted,
+      </if>
+      <if test="gmtCreate != null">
+        gmt_create,
+      </if>
+      <if test="gmtModified != null">
+        gmt_modified,
+      </if>
+    </trim>
+    <trim prefix="values (" suffix=")" suffixOverrides=",">
+      <if test="configKey != null">
+        #{configKey,jdbcType=VARCHAR},
+      </if>
+      <if test="configValue != null">
+        #{configValue,jdbcType=LONGVARCHAR},
+      </if>
+      <if test="isDeleted != null">
+        #{isDeleted,jdbcType=INTEGER},
+      </if>
+      <if test="gmtCreate != null">
+        #{gmtCreate,jdbcType=TIMESTAMP},
+      </if>
+      <if test="gmtModified != null">
+        #{gmtModified,jdbcType=TIMESTAMP},
+      </if>
+    </trim>
+  </insert>
+  <update id="updateByPrimaryKeySelective" parameterType="com.mirage.mirageservice.domain.FamilyConfigInfo">
+    <!--@mbg.generated-->
+    update family_config_info
+    <set>
+      <if test="configKey != null">
+        config_key = #{configKey,jdbcType=VARCHAR},
+      </if>
+      <if test="configValue != null">
+        config_value = #{configValue,jdbcType=LONGVARCHAR},
+      </if>
+      <if test="isDeleted != null">
+        is_deleted = #{isDeleted,jdbcType=INTEGER},
+      </if>
+      <if test="gmtCreate != null">
+        gmt_create = #{gmtCreate,jdbcType=TIMESTAMP},
+      </if>
+      <if test="gmtModified != null">
+        gmt_modified = #{gmtModified,jdbcType=TIMESTAMP},
+      </if>
+    </set>
+    where id = #{id,jdbcType=BIGINT}
+  </update>
+  <update id="updateByPrimaryKey" parameterType="com.mirage.mirageservice.domain.FamilyConfigInfo">
+    <!--@mbg.generated-->
+    update family_config_info
+    set config_key = #{configKey,jdbcType=VARCHAR},
+      config_value = #{configValue,jdbcType=LONGVARCHAR},
+      is_deleted = #{isDeleted,jdbcType=INTEGER},
+      gmt_create = #{gmtCreate,jdbcType=TIMESTAMP},
+      gmt_modified = #{gmtModified,jdbcType=TIMESTAMP}
+    where id = #{id,jdbcType=BIGINT}
+  </update>
+
+<!--auto generated by MybatisCodeHelper on 2025-10-23-->
+  <select id="selectAllByConfigKeyAndIsDeletedOrderByGmtModified" resultMap="BaseResultMap">
+        select
+        <include refid="Base_Column_List"/>
+        from family_config_info
+        where config_key=#{configKey,jdbcType=VARCHAR} and is_deleted=#{isDeleted,jdbcType=INTEGER} order by
+        gmt_modified asc
+    </select>
+</mapper>

+ 165 - 0
mirage-service/src/main/resources/com/mirage/mirageservice/mapper/mysql/FamilyMemberPhotoAlbumMapper.xml

@@ -0,0 +1,165 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.mirage.mirageservice.mapper.mysql.FamilyMemberPhotoAlbumMapper">
+  <resultMap id="BaseResultMap" type="com.mirage.mirageservice.domain.FamilyMemberPhotoAlbum">
+    <!--@mbg.generated-->
+    <!--@Table family_member_photo_album-->
+    <id column="id" jdbcType="BIGINT" property="id" />
+    <result column="url" jdbcType="VARCHAR" property="url" />
+    <result column="type" jdbcType="INTEGER" property="type" />
+    <result column="mid" jdbcType="BIGINT" property="mid" />
+    <result column="uid" jdbcType="BIGINT" property="uid" />
+    <result column="upload_time" jdbcType="TIMESTAMP" property="uploadTime" />
+    <result column="is_deleted" jdbcType="INTEGER" property="isDeleted" />
+    <result column="gmt_create" jdbcType="TIMESTAMP" property="gmtCreate" />
+    <result column="gmt_modified" jdbcType="TIMESTAMP" property="gmtModified" />
+  </resultMap>
+  <sql id="Base_Column_List">
+    <!--@mbg.generated-->
+    id, url, `type`, mid, `uid`, upload_time, is_deleted, gmt_create, gmt_modified
+  </sql>
+  <select id="selectByPrimaryKey" parameterType="java.lang.Long" resultMap="BaseResultMap">
+    <!--@mbg.generated-->
+    select 
+    <include refid="Base_Column_List" />
+    from family_member_photo_album
+    where id = #{id,jdbcType=BIGINT}
+  </select>
+  <delete id="deleteByPrimaryKey" parameterType="java.lang.Long">
+    <!--@mbg.generated-->
+    delete from family_member_photo_album
+    where id = #{id,jdbcType=BIGINT}
+  </delete>
+  <insert id="insert" keyColumn="id" keyProperty="id" parameterType="com.mirage.mirageservice.domain.FamilyMemberPhotoAlbum" useGeneratedKeys="true">
+    <!--@mbg.generated-->
+    insert into family_member_photo_album (url, `type`, mid, 
+      `uid`, upload_time, is_deleted, 
+      gmt_create, gmt_modified)
+    values (#{url,jdbcType=VARCHAR}, #{type,jdbcType=INTEGER}, #{mid,jdbcType=BIGINT}, 
+      #{uid,jdbcType=BIGINT}, #{uploadTime,jdbcType=TIMESTAMP}, #{isDeleted,jdbcType=INTEGER}, 
+      #{gmtCreate,jdbcType=TIMESTAMP}, #{gmtModified,jdbcType=TIMESTAMP})
+  </insert>
+  <insert id="insertSelective" keyColumn="id" keyProperty="id" parameterType="com.mirage.mirageservice.domain.FamilyMemberPhotoAlbum" useGeneratedKeys="true">
+    <!--@mbg.generated-->
+    insert into family_member_photo_album
+    <trim prefix="(" suffix=")" suffixOverrides=",">
+      <if test="url != null">
+        url,
+      </if>
+      <if test="type != null">
+        `type`,
+      </if>
+      <if test="mid != null">
+        mid,
+      </if>
+      <if test="uid != null">
+        `uid`,
+      </if>
+      <if test="uploadTime != null">
+        upload_time,
+      </if>
+      <if test="isDeleted != null">
+        is_deleted,
+      </if>
+      <if test="gmtCreate != null">
+        gmt_create,
+      </if>
+      <if test="gmtModified != null">
+        gmt_modified,
+      </if>
+    </trim>
+    <trim prefix="values (" suffix=")" suffixOverrides=",">
+      <if test="url != null">
+        #{url,jdbcType=VARCHAR},
+      </if>
+      <if test="type != null">
+        #{type,jdbcType=INTEGER},
+      </if>
+      <if test="mid != null">
+        #{mid,jdbcType=BIGINT},
+      </if>
+      <if test="uid != null">
+        #{uid,jdbcType=BIGINT},
+      </if>
+      <if test="uploadTime != null">
+        #{uploadTime,jdbcType=TIMESTAMP},
+      </if>
+      <if test="isDeleted != null">
+        #{isDeleted,jdbcType=INTEGER},
+      </if>
+      <if test="gmtCreate != null">
+        #{gmtCreate,jdbcType=TIMESTAMP},
+      </if>
+      <if test="gmtModified != null">
+        #{gmtModified,jdbcType=TIMESTAMP},
+      </if>
+    </trim>
+  </insert>
+  <update id="updateByPrimaryKeySelective" parameterType="com.mirage.mirageservice.domain.FamilyMemberPhotoAlbum">
+    <!--@mbg.generated-->
+    update family_member_photo_album
+    <set>
+      <if test="url != null">
+        url = #{url,jdbcType=VARCHAR},
+      </if>
+      <if test="type != null">
+        `type` = #{type,jdbcType=INTEGER},
+      </if>
+      <if test="mid != null">
+        mid = #{mid,jdbcType=BIGINT},
+      </if>
+      <if test="uid != null">
+        `uid` = #{uid,jdbcType=BIGINT},
+      </if>
+      <if test="uploadTime != null">
+        upload_time = #{uploadTime,jdbcType=TIMESTAMP},
+      </if>
+      <if test="isDeleted != null">
+        is_deleted = #{isDeleted,jdbcType=INTEGER},
+      </if>
+      <if test="gmtCreate != null">
+        gmt_create = #{gmtCreate,jdbcType=TIMESTAMP},
+      </if>
+      <if test="gmtModified != null">
+        gmt_modified = #{gmtModified,jdbcType=TIMESTAMP},
+      </if>
+    </set>
+    where id = #{id,jdbcType=BIGINT}
+  </update>
+  <update id="updateByPrimaryKey" parameterType="com.mirage.mirageservice.domain.FamilyMemberPhotoAlbum">
+    <!--@mbg.generated-->
+    update family_member_photo_album
+    set url = #{url,jdbcType=VARCHAR},
+      `type` = #{type,jdbcType=INTEGER},
+      mid = #{mid,jdbcType=BIGINT},
+      `uid` = #{uid,jdbcType=BIGINT},
+      upload_time = #{uploadTime,jdbcType=TIMESTAMP},
+      is_deleted = #{isDeleted,jdbcType=INTEGER},
+      gmt_create = #{gmtCreate,jdbcType=TIMESTAMP},
+      gmt_modified = #{gmtModified,jdbcType=TIMESTAMP}
+    where id = #{id,jdbcType=BIGINT}
+  </update>
+
+<!--auto generated by MybatisCodeHelper on 2025-10-23-->
+  <select id="selectAllByMidAndIsDeletedOrderByUploadTimeDesc" resultMap="BaseResultMap">
+        select
+        <include refid="Base_Column_List"/>
+        from family_member_photo_album
+        where mid=#{mid,jdbcType=BIGINT} and is_deleted=#{isDeleted,jdbcType=INTEGER} order by upload_time desc
+    </select>
+
+<!--auto generated by MybatisCodeHelper on 2025-10-23-->
+  <select id="selectAllByMidAndTypeAndIsDeletedOrderByUploadTimeDesc" resultMap="BaseResultMap">
+    select
+    <include refid="Base_Column_List"/>
+    from family_member_photo_album
+    <where>
+      mid=#{mid,jdbcType=BIGINT}
+      <if test="type != null">
+        and `type`=#{type,jdbcType=INTEGER}
+      </if>
+      and is_deleted=#{isDeleted,jdbcType=INTEGER}
+    </where>
+    order by upload_time desc
+  </select>
+</mapper>

+ 210 - 0
mirage-service/src/main/resources/com/mirage/mirageservice/mapper/mysql/FamilyMomentsMapper.xml

@@ -0,0 +1,210 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.mirage.mirageservice.mapper.mysql.FamilyMomentsMapper">
+  <resultMap id="BaseResultMap" type="com.mirage.mirageservice.domain.FamilyMoments">
+    <!--@mbg.generated-->
+    <!--@Table family_moments-->
+    <id column="id" jdbcType="BIGINT" property="id" />
+    <result column="type" jdbcType="INTEGER" property="type" />
+    <result column="publish_uid" jdbcType="BIGINT" property="publishUid" />
+    <result column="publish_time" jdbcType="TIMESTAMP" property="publishTime" />
+    <result column="expire_time" jdbcType="BIGINT" property="expireTime" />
+    <result column="content" jdbcType="LONGVARCHAR" property="content" />
+    <result column="visible_type" jdbcType="INTEGER" property="visibleType" />
+    <result column="visible_value" jdbcType="VARCHAR" property="visibleValue" />
+    <result column="is_deleted" jdbcType="INTEGER" property="isDeleted" />
+    <result column="gmt_create" jdbcType="TIMESTAMP" property="gmtCreate" />
+    <result column="gmt_modified" jdbcType="TIMESTAMP" property="gmtModified" />
+  </resultMap>
+  <sql id="Base_Column_List">
+    <!--@mbg.generated-->
+    id, `type`, publish_uid, publish_time, expire_time, content, visible_type, visible_value, 
+    is_deleted, gmt_create, gmt_modified
+  </sql>
+  <select id="selectByPrimaryKey" parameterType="java.lang.Long" resultMap="BaseResultMap">
+    <!--@mbg.generated-->
+    select 
+    <include refid="Base_Column_List" />
+    from family_moments
+    where id = #{id,jdbcType=BIGINT}
+  </select>
+  <delete id="deleteByPrimaryKey" parameterType="java.lang.Long">
+    <!--@mbg.generated-->
+    delete from family_moments
+    where id = #{id,jdbcType=BIGINT}
+  </delete>
+  <insert id="insert" keyColumn="id" keyProperty="id" parameterType="com.mirage.mirageservice.domain.FamilyMoments" useGeneratedKeys="true">
+    <!--@mbg.generated-->
+    insert into family_moments (`type`, publish_uid, publish_time, 
+      expire_time, content, visible_type, 
+      visible_value, is_deleted, gmt_create, 
+      gmt_modified)
+    values (#{type,jdbcType=INTEGER}, #{publishUid,jdbcType=BIGINT}, #{publishTime,jdbcType=TIMESTAMP}, 
+      #{expireTime,jdbcType=BIGINT}, #{content,jdbcType=LONGVARCHAR}, #{visibleType,jdbcType=INTEGER}, 
+      #{visibleValue,jdbcType=VARCHAR}, #{isDeleted,jdbcType=INTEGER}, #{gmtCreate,jdbcType=TIMESTAMP}, 
+      #{gmtModified,jdbcType=TIMESTAMP})
+  </insert>
+  <insert id="insertSelective" keyColumn="id" keyProperty="id" parameterType="com.mirage.mirageservice.domain.FamilyMoments" useGeneratedKeys="true">
+    <!--@mbg.generated-->
+    insert into family_moments
+    <trim prefix="(" suffix=")" suffixOverrides=",">
+      <if test="type != null">
+        `type`,
+      </if>
+      <if test="publishUid != null">
+        publish_uid,
+      </if>
+      <if test="publishTime != null">
+        publish_time,
+      </if>
+      <if test="expireTime != null">
+        expire_time,
+      </if>
+      <if test="content != null">
+        content,
+      </if>
+      <if test="visibleType != null">
+        visible_type,
+      </if>
+      <if test="visibleValue != null">
+        visible_value,
+      </if>
+      <if test="isDeleted != null">
+        is_deleted,
+      </if>
+      <if test="gmtCreate != null">
+        gmt_create,
+      </if>
+      <if test="gmtModified != null">
+        gmt_modified,
+      </if>
+    </trim>
+    <trim prefix="values (" suffix=")" suffixOverrides=",">
+      <if test="type != null">
+        #{type,jdbcType=INTEGER},
+      </if>
+      <if test="publishUid != null">
+        #{publishUid,jdbcType=BIGINT},
+      </if>
+      <if test="publishTime != null">
+        #{publishTime,jdbcType=TIMESTAMP},
+      </if>
+      <if test="expireTime != null">
+        #{expireTime,jdbcType=BIGINT},
+      </if>
+      <if test="content != null">
+        #{content,jdbcType=LONGVARCHAR},
+      </if>
+      <if test="visibleType != null">
+        #{visibleType,jdbcType=INTEGER},
+      </if>
+      <if test="visibleValue != null">
+        #{visibleValue,jdbcType=VARCHAR},
+      </if>
+      <if test="isDeleted != null">
+        #{isDeleted,jdbcType=INTEGER},
+      </if>
+      <if test="gmtCreate != null">
+        #{gmtCreate,jdbcType=TIMESTAMP},
+      </if>
+      <if test="gmtModified != null">
+        #{gmtModified,jdbcType=TIMESTAMP},
+      </if>
+    </trim>
+  </insert>
+  <update id="updateByPrimaryKeySelective" parameterType="com.mirage.mirageservice.domain.FamilyMoments">
+    <!--@mbg.generated-->
+    update family_moments
+    <set>
+      <if test="type != null">
+        `type` = #{type,jdbcType=INTEGER},
+      </if>
+      <if test="publishUid != null">
+        publish_uid = #{publishUid,jdbcType=BIGINT},
+      </if>
+      <if test="publishTime != null">
+        publish_time = #{publishTime,jdbcType=TIMESTAMP},
+      </if>
+      <if test="expireTime != null">
+        expire_time = #{expireTime,jdbcType=BIGINT},
+      </if>
+      <if test="content != null">
+        content = #{content,jdbcType=LONGVARCHAR},
+      </if>
+      <if test="visibleType != null">
+        visible_type = #{visibleType,jdbcType=INTEGER},
+      </if>
+      <if test="visibleValue != null">
+        visible_value = #{visibleValue,jdbcType=VARCHAR},
+      </if>
+      <if test="isDeleted != null">
+        is_deleted = #{isDeleted,jdbcType=INTEGER},
+      </if>
+      <if test="gmtCreate != null">
+        gmt_create = #{gmtCreate,jdbcType=TIMESTAMP},
+      </if>
+      <if test="gmtModified != null">
+        gmt_modified = #{gmtModified,jdbcType=TIMESTAMP},
+      </if>
+    </set>
+    where id = #{id,jdbcType=BIGINT}
+  </update>
+  <update id="updateByPrimaryKey" parameterType="com.mirage.mirageservice.domain.FamilyMoments">
+    <!--@mbg.generated-->
+    update family_moments
+    set `type` = #{type,jdbcType=INTEGER},
+      publish_uid = #{publishUid,jdbcType=BIGINT},
+      publish_time = #{publishTime,jdbcType=TIMESTAMP},
+      expire_time = #{expireTime,jdbcType=BIGINT},
+      content = #{content,jdbcType=LONGVARCHAR},
+      visible_type = #{visibleType,jdbcType=INTEGER},
+      visible_value = #{visibleValue,jdbcType=VARCHAR},
+      is_deleted = #{isDeleted,jdbcType=INTEGER},
+      gmt_create = #{gmtCreate,jdbcType=TIMESTAMP},
+      gmt_modified = #{gmtModified,jdbcType=TIMESTAMP}
+    where id = #{id,jdbcType=BIGINT}
+  </update>
+
+<!--auto generated by MybatisCodeHelper on 2025-10-23-->
+  <select id="selectAllByTypeAndExpireTimeGreaterThanOrExpireTimeAndIsDeletedAndVisibleTypeOrderByPublishTimeDesc"
+          resultMap="BaseResultMap">
+    select
+    <include refid="Base_Column_List"/>
+    from family_moments
+    <where>
+      <if test="type != null">
+        and `type`=#{type,jdbcType=INTEGER}
+      </if>
+      <if test="minExpireTime != null">
+        and expire_time <![CDATA[>]]> #{minExpireTime,jdbcType=BIGINT}
+      </if>
+      <if test="expireTime != null">
+        or expire_time=#{expireTime,jdbcType=BIGINT}
+      </if>
+      and is_deleted=#{isDeleted,jdbcType=INTEGER}
+      <if test="visibleType != null">
+        and visible_type=#{visibleType,jdbcType=INTEGER}
+      </if>
+    </where>
+    order by publish_time desc
+  </select>
+
+  <select id="selectAllMoments" resultMap="BaseResultMap">
+    select
+    <include refid="Base_Column_List"/>
+    from family_moments
+    <where>
+      <if test="type != null">
+        and `type`=#{type,jdbcType=INTEGER}
+      </if>
+      and is_deleted=#{isDeleted,jdbcType=INTEGER}
+      <if test="visibleType != null">
+        and visible_type=#{visibleType,jdbcType=INTEGER}
+      </if>
+      <if test="id != null">
+         and id <![CDATA[<]]> #{id,jdbcType=BIGINT}
+      </if>
+    </where>
+    order by id desc LIMIT #{pageSize,jdbcType=INTEGER}
+  </select>
+</mapper>

+ 30 - 4
sql.sql

@@ -35,11 +35,11 @@ CREATE TABLE `family_member_info` (
   `cluster_place` varchar(256) DEFAULT NULL COMMENT '聚落',
   `nation` varchar(128) DEFAULT NULL COMMENT '民族',
   `residential_address` varchar(1024) DEFAULT NULL COMMENT '居住地址',
-  `phone` varchar(128) NULL COMMENT '手机号',
+  `phone` varchar(128) DEFAULT NULL COMMENT '手机号',
   `mail` varchar(128) DEFAULT NULL COMMENT '邮箱地址',
   `wechat_account` varchar(256) DEFAULT NULL COMMENT '微信号',
   `head_img_url` varchar(512) DEFAULT NULL COMMENT '头像照片',
-  `Id_number` varchar(128) DEFAULT NULL COMMENT '身份证号',
+  `id_number` varchar(128) DEFAULT NULL COMMENT '身份证号',
   `occupation` text COMMENT '职业',
   `educational` text COMMENT '教育背景',
   `blood_type` varchar(32) DEFAULT NULL COMMENT '血型',
@@ -52,7 +52,7 @@ CREATE TABLE `family_member_info` (
   PRIMARY KEY (`id`),
   KEY `idx_name` (`name`),
   KEY `idx_uid` (`uid`)
-) ENGINE=InnoDB AUTO_INCREMENT=10 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='成员表';
+) ENGINE=InnoDB AUTO_INCREMENT=18 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='成员表'
 
 CREATE TABLE `family_relation_info` (
     `id` bigint NOT NULL AUTO_INCREMENT,
@@ -69,4 +69,30 @@ CREATE TABLE `family_relation_info` (
     PRIMARY KEY (`id`),
     KEY `idx_relation` (`parent_mid`,`child_mid`,`relation_type`),
     KEY `idx_spouse_relation` (`parent_mid`,`relation_type`,`relation_status`)
-) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci
+) ENGINE=InnoDB AUTO_INCREMENT=12 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
+
+CREATE TABLE `family_config_info` (
+      `id` bigint NOT NULL AUTO_INCREMENT,
+      `config_key` varchar(256) NOT NULL COMMENT '对应FamilyConfigEnum值',
+      `config_value` text NOT NULL COMMENT '配置值,json,eg: {"imgUrl","xxx","clickUrl":"","content":""}',
+      `is_deleted` int NOT NULL DEFAULT '0',
+      `gmt_create` timestamp NOT NULL,
+      `gmt_modified` timestamp NOT NULL,
+      PRIMARY KEY (`id`),
+      KEY `idx_key` (`config_key`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='通用配置表';
+
+CREATE TABLE `family_moments` (
+  `id` bigint NOT NULL AUTO_INCREMENT,
+  `type` int NOT NULL DEFAULT '0' COMMENT '0:普通消息 1:定置公告',
+  `publish_uid` bigint NOT NULL COMMENT '发布人',
+  `publish_time` timestamp NOT NULL COMMENT '发布时间',
+  `content` text NOT NULL COMMENT 'json,eg: {"text":"我是一条家族圈","media":[{"url":"","type":0,"order":0},{"url":"","type":1,"order":1}]} ',
+  `visible_type` int NOT NULL DEFAULT '0' COMMENT '可见范围:0:全员 1:支系堂派 2:聚落 3:家族内男性 4:出生地',
+  `visible_value` varchar(512) DEFAULT NULL COMMENT '对应visible_type值',
+  `is_deleted` int NOT NULL DEFAULT '0',
+  `gmt_create` timestamp NOT NULL,
+  `gmt_modified` timestamp NOT NULL,
+  PRIMARY KEY (`id`),
+  KEY `idx_publish_time` (`publish_time` DESC)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='家族圈';