diff --git a/pigx-app-server/pigx-app-server-api/src/main/java/com/pig4cloud/pigx/app/api/dto/AppRoleTabbarDTO.java b/pigx-app-server/pigx-app-server-api/src/main/java/com/pig4cloud/pigx/app/api/dto/AppRoleTabbarDTO.java
new file mode 100644
index 000000000..84ad49d84
--- /dev/null
+++ b/pigx-app-server/pigx-app-server-api/src/main/java/com/pig4cloud/pigx/app/api/dto/AppRoleTabbarDTO.java
@@ -0,0 +1,38 @@
+package com.pig4cloud.pigx.app.api.dto;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import jakarta.validation.constraints.NotNull;
+import lombok.Data;
+
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * App 角色底部导航配置请求体。
+ *
+ * 后台保存某个系统角色可见的 App Tabbar 列表。公开 Tabbar 由 {@code app_tabbar.login_flag=0}
+ * 控制,不依赖这里的角色授权。
+ *
+ * @author lengleng
+ * @date 2026-05-09
+ */
+@Data
+@Schema(description = "App角色底部导航配置")
+public class AppRoleTabbarDTO implements Serializable {
+
+ private static final long serialVersionUID = 1L;
+
+ @NotNull(message = "角色ID不能为空")
+ @Schema(description = "系统角色ID")
+ private Long roleId;
+
+ /**
+ * 该角色可见的登录态 Tabbar ID 列表。
+ *
+ * 保存时采用覆盖语义,空列表表示清空该角色的 Tabbar 授权。
+ */
+ @Schema(description = "底部导航ID列表")
+ private List tabbarIds = new ArrayList<>();
+
+}
diff --git a/pigx-app-server/pigx-app-server-api/src/main/java/com/pig4cloud/pigx/app/api/dto/AppUserDTO.java b/pigx-app-server/pigx-app-server-api/src/main/java/com/pig4cloud/pigx/app/api/dto/AppUserDTO.java
deleted file mode 100644
index 70c8484f6..000000000
--- a/pigx-app-server/pigx-app-server-api/src/main/java/com/pig4cloud/pigx/app/api/dto/AppUserDTO.java
+++ /dev/null
@@ -1,30 +0,0 @@
-package com.pig4cloud.pigx.app.api.dto;
-
-import com.pig4cloud.pigx.app.api.entity.AppUser;
-import io.swagger.v3.oas.annotations.media.Schema;
-import lombok.Data;
-import lombok.EqualsAndHashCode;
-
-import java.util.List;
-
-@Data
-@Schema(description = "APP用户传输对象")
-@EqualsAndHashCode(callSuper = true)
-public class AppUserDTO extends AppUser {
-
- /**
- * 角色ID
- */
- @Schema(description = "角色id集合")
- private List role;
-
- /**
- * 新密码
- */
- @Schema(description = "新密码")
- private String newpassword1;
-
- @Schema(description = "验证码")
- private String mobileCode;
-
-}
diff --git a/pigx-app-server/pigx-app-server-api/src/main/java/com/pig4cloud/pigx/app/api/dto/AppUserInfo.java b/pigx-app-server/pigx-app-server-api/src/main/java/com/pig4cloud/pigx/app/api/dto/AppUserInfo.java
deleted file mode 100644
index 45ac2f48e..000000000
--- a/pigx-app-server/pigx-app-server-api/src/main/java/com/pig4cloud/pigx/app/api/dto/AppUserInfo.java
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- *
- * Copyright (c) 2018-2026, lengleng All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
- * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * Neither the name of the pig4cloud.com developer nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- * Author: lengleng (wangiegie@gmail.com)
- *
- */
-
-package com.pig4cloud.pigx.app.api.dto;
-
-import com.pig4cloud.pigx.app.api.entity.AppUser;
-import io.swagger.v3.oas.annotations.media.Schema;
-import lombok.Data;
-
-import java.io.Serializable;
-
-/**
- * @author lengleng
- * @date 2017/11/11
- */
-@Data
-@Schema(description = "用户信息")
-public class AppUserInfo implements Serializable {
-
- /**
- * 用户基本信息
- */
- @Schema(description = "用户基本信息")
- private AppUser appUser;
-
- /**
- * 权限标识集合
- */
- @Schema(description = "权限标识集合")
- private String[] permissions;
-
- /**
- * 角色集合
- */
- @Schema(description = "角色标识集合")
- private Long[] roles;
-
-}
diff --git a/pigx-app-server/pigx-app-server-api/src/main/java/com/pig4cloud/pigx/app/api/entity/AppArticleCollectEntity.java b/pigx-app-server/pigx-app-server-api/src/main/java/com/pig4cloud/pigx/app/api/entity/AppArticleCollectEntity.java
index dca6e2771..2e6c27813 100644
--- a/pigx-app-server/pigx-app-server-api/src/main/java/com/pig4cloud/pigx/app/api/entity/AppArticleCollectEntity.java
+++ b/pigx-app-server/pigx-app-server-api/src/main/java/com/pig4cloud/pigx/app/api/entity/AppArticleCollectEntity.java
@@ -22,66 +22,66 @@ import java.time.LocalDateTime;
@Schema(description = "文章收藏表")
public class AppArticleCollectEntity extends Model {
- /**
- * 主键
- */
- @TableId(type = IdType.ASSIGN_ID)
- @Schema(description = "主键")
- private Long id;
+ /**
+ * 主键
+ */
+ @TableId(type = IdType.ASSIGN_ID)
+ @Schema(description = "主键")
+ private Long id;
- /**
- * 用户ID
- */
- @Schema(description = "用户ID")
- private Long userId;
+ /**
+ * 用户ID
+ */
+ @Schema(description = "用户ID")
+ private Long userId;
- /**
- * 文章ID
- */
- @Schema(description = "文章ID")
- private Long articleId;
+ /**
+ * 文章ID
+ */
+ @Schema(description = "文章ID")
+ private Long articleId;
- /**
- * 文章标题
- */
- @TableField(exist = false)
- private String title;
+ /**
+ * 文章标题
+ */
+ @TableField(exist = false)
+ private String title;
- /**
- * 创建人
- */
- @TableField(fill = FieldFill.INSERT)
- @Schema(description = "创建人")
- private String createBy;
+ /**
+ * 创建人
+ */
+ @TableField(fill = FieldFill.INSERT)
+ @Schema(description = "创建人")
+ private String createBy;
- /**
- * 创建时间
- */
- @TableField(fill = FieldFill.INSERT)
- @Schema(description = "创建时间")
- private LocalDateTime createTime;
+ /**
+ * 创建时间
+ */
+ @TableField(fill = FieldFill.INSERT)
+ @Schema(description = "创建时间")
+ private LocalDateTime createTime;
- /**
- * 更新人
- */
- @TableField(fill = FieldFill.INSERT_UPDATE)
- @Schema(description = "更新人")
- private String updateBy;
+ /**
+ * 更新人
+ */
+ @TableField(fill = FieldFill.INSERT_UPDATE)
+ @Schema(description = "更新人")
+ private String updateBy;
- /**
- * 更新时间
- */
- @TableField(fill = FieldFill.INSERT_UPDATE)
- @Schema(description = "更新时间")
- private LocalDateTime updateTime;
+ /**
+ * 更新时间
+ */
+ @TableField(fill = FieldFill.INSERT_UPDATE)
+ @Schema(description = "更新时间")
+ private LocalDateTime updateTime;
- /**
- * 是否删除
- */
- @TableLogic
- @TableField(fill = FieldFill.INSERT)
- @Schema(description = "是否删除")
- private String delFlag;
+ /**
+ * 是否删除
+ */
+ @TableLogic
+ @TableField(fill = FieldFill.INSERT)
+ @Schema(description = "是否删除")
+ private String delFlag;
/**
* 图片
diff --git a/pigx-app-server/pigx-app-server-api/src/main/java/com/pig4cloud/pigx/app/api/entity/AppContactsEntity.java b/pigx-app-server/pigx-app-server-api/src/main/java/com/pig4cloud/pigx/app/api/entity/AppContactsEntity.java
new file mode 100644
index 000000000..99194ed07
--- /dev/null
+++ b/pigx-app-server/pigx-app-server-api/src/main/java/com/pig4cloud/pigx/app/api/entity/AppContactsEntity.java
@@ -0,0 +1,92 @@
+package com.pig4cloud.pigx.app.api.entity;
+
+import com.baomidou.mybatisplus.annotation.*;
+import com.baomidou.mybatisplus.extension.activerecord.Model;
+import com.pig4cloud.pigx.common.core.util.TenantTable;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+import java.time.LocalDateTime;
+
+/**
+ * 通讯录表
+ *
+ * @author pigx
+ * @date 2025-05-29 17:30:30
+ */
+@Data
+@TenantTable
+@TableName("app_contacts")
+@EqualsAndHashCode(callSuper = true)
+@Schema(description = "通讯录表")
+public class AppContactsEntity extends Model {
+
+
+ /**
+ * 主键
+ */
+ @TableId(type = IdType.ASSIGN_ID)
+ @Schema(description = "主键")
+ private Long id;
+
+ /**
+ * 联系人
+ */
+ @Schema(description = "联系人")
+ private String contactName;
+
+ /**
+ * 手机号
+ */
+ @Schema(description = "手机号")
+ private String contactPhone;
+
+ /**
+ * 备注
+ */
+ @Schema(description = "备注")
+ private String remark;
+
+ /**
+ * 创建人
+ */
+ @TableField(fill = FieldFill.INSERT)
+ @Schema(description = "创建人")
+ private String createBy;
+
+ /**
+ * 创建时间
+ */
+ @TableField(fill = FieldFill.INSERT)
+ @Schema(description = "创建时间")
+ private LocalDateTime createTime;
+
+ /**
+ * 修改人
+ */
+ @TableField(fill = FieldFill.INSERT_UPDATE)
+ @Schema(description = "修改人")
+ private String updateBy;
+
+ /**
+ * 修改时间
+ */
+ @TableField(fill = FieldFill.INSERT_UPDATE)
+ @Schema(description = "修改时间")
+ private LocalDateTime updateTime;
+
+ /**
+ * 删除标记
+ */
+ @TableLogic
+ @TableField(fill = FieldFill.INSERT)
+ @Schema(description = "删除标记")
+ private String delFlag;
+
+ /**
+ * 租户ID
+ */
+ @Schema(description = "租户ID")
+ private Long tenantId;
+}
\ No newline at end of file
diff --git a/pigx-app-server/pigx-app-server-api/src/main/java/com/pig4cloud/pigx/app/api/entity/AppPageEntity.java b/pigx-app-server/pigx-app-server-api/src/main/java/com/pig4cloud/pigx/app/api/entity/AppPageEntity.java
index 12c7eeffb..a217cccfb 100644
--- a/pigx-app-server/pigx-app-server-api/src/main/java/com/pig4cloud/pigx/app/api/entity/AppPageEntity.java
+++ b/pigx-app-server/pigx-app-server-api/src/main/java/com/pig4cloud/pigx/app/api/entity/AppPageEntity.java
@@ -6,11 +6,15 @@ import com.pig4cloud.pigx.common.core.util.TenantTable;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
+import lombok.experimental.FieldNameConstants;
import java.time.LocalDateTime;
/**
- * 页面
+ * App 装修页面实体。
+ *
+ * 仅对应 {@code app_page} 表,保存页面类型、页面名称和页面组件 JSON。
+ * 底部 Tabbar 已拆分到 {@code app_tabbar},不要再塞进 {@link #pageData}。
*
* @author lengleng
* @date 2023-06-08 11:19:23
@@ -18,6 +22,7 @@ import java.time.LocalDateTime;
@Data
@TenantTable
@TableName("app_page")
+@FieldNameConstants
@EqualsAndHashCode(callSuper = true)
@Schema(description = "页面")
public class AppPageEntity extends Model {
@@ -30,7 +35,7 @@ public class AppPageEntity extends Model {
private Long id;
/**
- * 页面类型
+ * 页面类型,对应 {@link com.pig4cloud.pigx.app.api.enums.PageTypeEnums}
*/
@Schema(description = "页面类型")
private Integer pageType;
@@ -42,7 +47,10 @@ public class AppPageEntity extends Model {
private String pageName;
/**
- * 页面数据
+ * 页面装修组件 JSON。
+ *
+ * 只保存页面内部组件,例如搜索、轮播、导航块、服务块等;
+ * 运行时需要 Tabbar 时由服务层聚合 {@code app_tabbar} 返回。
*/
@Schema(description = "页面数据")
private String pageData;
diff --git a/pigx-app-server/pigx-app-server-api/src/main/java/com/pig4cloud/pigx/app/api/entity/AppRole.java b/pigx-app-server/pigx-app-server-api/src/main/java/com/pig4cloud/pigx/app/api/entity/AppRole.java
deleted file mode 100644
index df89ff0be..000000000
--- a/pigx-app-server/pigx-app-server-api/src/main/java/com/pig4cloud/pigx/app/api/entity/AppRole.java
+++ /dev/null
@@ -1,107 +0,0 @@
-/*
- * Copyright (c) 2018-2026, lengleng All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
- * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * Neither the name of the pig4cloud.com developer nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- * Author: lengleng (wangiegie@gmail.com)
- */
-
-package com.pig4cloud.pigx.app.api.entity;
-
-import com.baomidou.mybatisplus.annotation.IdType;
-import com.baomidou.mybatisplus.annotation.TableId;
-import com.baomidou.mybatisplus.annotation.TableName;
-import com.baomidou.mybatisplus.extension.activerecord.Model;
-import com.pig4cloud.pigx.common.core.util.TenantTable;
-import io.swagger.v3.oas.annotations.media.Schema;
-import lombok.Data;
-import lombok.EqualsAndHashCode;
-
-import java.time.LocalDateTime;
-
-/**
- * app角色表
- *
- * @author aeizzz
- * @date 2022-12-07 09:52:03
- */
-@Data
-@TenantTable
-@TableName("app_role")
-@EqualsAndHashCode(callSuper = true)
-@Schema(description = "app角色表")
-public class AppRole extends Model {
-
- private static final long serialVersionUID = 1L;
-
- /**
- * roleId
- */
- @TableId(type = IdType.ASSIGN_ID)
- @Schema(description = "roleId")
- private Long roleId;
-
- /**
- * roleName
- */
- @Schema(description = "roleName")
- private String roleName;
-
- /**
- * roleCode
- */
- @Schema(description = "roleCode")
- private String roleCode;
-
- /**
- * roleDesc
- */
- @Schema(description = "roleDesc")
- private String roleDesc;
-
- /**
- * 创建人
- */
- @Schema(description = "创建人")
- private String createBy;
-
- /**
- * 修改人
- */
- @Schema(description = "修改人")
- private String updateBy;
-
- /**
- * createTime
- */
- @Schema(description = "createTime")
- private LocalDateTime createTime;
-
- /**
- * updateTime
- */
- @Schema(description = "updateTime")
- private LocalDateTime updateTime;
-
- /**
- * delFlag
- */
- @Schema(description = "delFlag")
- private String delFlag;
-
- /**
- * tenantId
- */
- @Schema(description = "tenantId", hidden = true)
- private Long tenantId;
-
-}
diff --git a/pigx-app-server/pigx-app-server-api/src/main/java/com/pig4cloud/pigx/app/api/entity/AppRoleTabbar.java b/pigx-app-server/pigx-app-server-api/src/main/java/com/pig4cloud/pigx/app/api/entity/AppRoleTabbar.java
new file mode 100644
index 000000000..35383abcb
--- /dev/null
+++ b/pigx-app-server/pigx-app-server-api/src/main/java/com/pig4cloud/pigx/app/api/entity/AppRoleTabbar.java
@@ -0,0 +1,37 @@
+package com.pig4cloud.pigx.app.api.entity;
+
+import com.baomidou.mybatisplus.annotation.TableName;
+import com.baomidou.mybatisplus.extension.activerecord.Model;
+import com.pig4cloud.pigx.common.core.util.TenantTable;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+/**
+ * App 角色底部导航关联实体,以 (role_id, tabbar_id, tenant_id) 为复合主键。
+ *
+ * 这里的 roleId 是系统角色 {@code sys_role.role_id}。运行时不会跨库查询 {@code sys_user_role},
+ * 而是从登录 token 的角色权限中解析 roleId,再回到本表查询可见 Tabbar。
+ *
+ * @author lengleng
+ * @date 2026-05-09
+ */
+@Data
+@TenantTable
+@TableName("app_role_tabbar")
+@EqualsAndHashCode(callSuper = true)
+@Schema(description = "App角色底部导航")
+public class AppRoleTabbar extends Model {
+
+ private static final long serialVersionUID = 1L;
+
+ @Schema(description = "系统角色ID")
+ private Long roleId;
+
+ @Schema(description = "底部导航ID")
+ private Long tabbarId;
+
+ @Schema(description = "租户ID", hidden = true)
+ private Long tenantId;
+
+}
diff --git a/pigx-app-server/pigx-app-server-api/src/main/java/com/pig4cloud/pigx/app/api/entity/AppSocialDetails.java b/pigx-app-server/pigx-app-server-api/src/main/java/com/pig4cloud/pigx/app/api/entity/AppSocialDetails.java
deleted file mode 100644
index c56e33c48..000000000
--- a/pigx-app-server/pigx-app-server-api/src/main/java/com/pig4cloud/pigx/app/api/entity/AppSocialDetails.java
+++ /dev/null
@@ -1,125 +0,0 @@
-/*
- * Copyright (c) 2018-2026, lengleng All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
- * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * Neither the name of the pig4cloud.com developer nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- * Author: lengleng (wangiegie@gmail.com)
- */
-
-package com.pig4cloud.pigx.app.api.entity;
-
-import com.baomidou.mybatisplus.annotation.*;
-import com.baomidou.mybatisplus.extension.activerecord.Model;
-import com.pig4cloud.pigx.common.core.util.ValidGroup;
-import com.pig4cloud.pigx.common.sensitive.annotation.Sensitive;
-import io.swagger.v3.oas.annotations.media.Schema;
-import jakarta.validation.constraints.NotBlank;
-import lombok.Data;
-import lombok.EqualsAndHashCode;
-
-import java.time.LocalDateTime;
-
-/**
- * app 社交账号登录
- */
-@Data
-@Schema(description = "第三方账号信息")
-@EqualsAndHashCode(callSuper = true)
-public class AppSocialDetails extends Model {
-
- private static final long serialVersionUID = 1L;
-
- /**
- * 主鍵
- */
- @TableId(type = IdType.ASSIGN_ID)
- @Schema(description = "主键")
- private Long id;
-
- /**
- * 类型
- */
- @NotBlank(message = "类型不能为空")
- @Schema(description = "账号类型")
- private String type;
-
- /**
- * 描述
- */
- @Schema(description = "描述")
- private String remark;
-
- /**
- * appid
- */
- @Sensitive(prefixNoMaskLen = 4, suffixNoMaskLen = 4)
- @NotBlank(message = "账号不能为空")
- @Schema(description = "appId")
- private String appId;
-
- /**
- * app_secret
- */
- @Sensitive(prefixNoMaskLen = 4, suffixNoMaskLen = 4)
- @NotBlank(message = "密钥不能为空", groups = { ValidGroup.Insert.class })
- @Schema(description = "app secret")
- private String appSecret;
-
- /**
- * 回调地址
- */
- @Schema(description = "回调地址")
- private String redirectUrl;
-
- /**
- * 拓展字段
- */
- @Schema(description = "拓展字段")
- private String ext;
-
- /**
- * 创建人
- */
- @TableField(fill = FieldFill.INSERT)
- @Schema(description = "创建人")
- private String createBy;
-
- /**
- * 修改人
- */
- @TableField(fill = FieldFill.UPDATE)
- @Schema(description = "修改人")
- private String updateBy;
-
- /**
- * 创建时间
- */
- @Schema(description = "创建时间")
- @TableField(fill = FieldFill.INSERT)
- private LocalDateTime createTime;
-
- /**
- * 更新时间
- */
- @Schema(description = "更新时间")
- @TableField(fill = FieldFill.UPDATE)
- private LocalDateTime updateTime;
-
- /**
- * 删除标记
- */
- @TableLogic
- @TableField(fill = FieldFill.INSERT)
- @Schema(description = "删除标记,1:已删除,0:正常")
- private String delFlag;
-
-}
diff --git a/pigx-app-server/pigx-app-server-api/src/main/java/com/pig4cloud/pigx/app/api/entity/AppTabbarEntity.java b/pigx-app-server/pigx-app-server-api/src/main/java/com/pig4cloud/pigx/app/api/entity/AppTabbarEntity.java
index 30725d18a..a9538de6b 100644
--- a/pigx-app-server/pigx-app-server-api/src/main/java/com/pig4cloud/pigx/app/api/entity/AppTabbarEntity.java
+++ b/pigx-app-server/pigx-app-server-api/src/main/java/com/pig4cloud/pigx/app/api/entity/AppTabbarEntity.java
@@ -12,7 +12,10 @@ import lombok.EqualsAndHashCode;
import java.time.LocalDateTime;
/**
- * 导航栏
+ * App 底部导航实体。
+ *
+ * 该表是移动端底部 Tabbar 的唯一数据源。图标字段保存 Wot UI 图标名,
+ * 运行时可见性由 {@link #loginFlag} 和 {@code app_role_tabbar} 共同决定。
*
* @author lengleng
* @date 2023-06-08 11:18:46
@@ -38,19 +41,25 @@ public class AppTabbarEntity extends Model {
private String name;
/**
- * 未选图标
+ * 选中态图标名。
+ *
+ * 保存 Wot UI 内置图标名称,例如 {@code home-fill}。
*/
- @Schema(description = "未选图标")
+ @Schema(description = "选中态图标名")
private String selected;
/**
- * 已选图标
+ * 未选中态图标名。
+ *
+ * 保存 Wot UI 内置图标名称,例如 {@code home}。
*/
- @Schema(description = "已选图标")
+ @Schema(description = "未选中态图标名")
private String unselected;
/**
- * 链接地址
+ * 跳转链接 JSON。
+ *
+ * 前端按装修链接结构解析,例如 {@code {"path":"/pages/index/index","type":"shop"}}。
*/
@Schema(description = "链接地址")
@JsonRawValue
@@ -63,6 +72,12 @@ public class AppTabbarEntity extends Model {
@Schema(description = "排序值")
private Integer sortOrder;
+ /**
+ * 是否需要登录,0=不需要登录也可见,1=登录后按角色授权可见。
+ */
+ @Schema(description = "是否需要登录,0=不需要登录也可见,1=登录后按角色授权可见")
+ private String loginFlag;
+
/**
* 创建人
*/
diff --git a/pigx-app-server/pigx-app-server-api/src/main/java/com/pig4cloud/pigx/app/api/entity/AppUser.java b/pigx-app-server/pigx-app-server-api/src/main/java/com/pig4cloud/pigx/app/api/entity/AppUser.java
deleted file mode 100644
index 98ea669e7..000000000
--- a/pigx-app-server/pigx-app-server-api/src/main/java/com/pig4cloud/pigx/app/api/entity/AppUser.java
+++ /dev/null
@@ -1,161 +0,0 @@
-/*
- * Copyright (c) 2018-2026, lengleng All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
- * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * Neither the name of the pig4cloud.com developer nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- * Author: lengleng (wangiegie@gmail.com)
- */
-
-package com.pig4cloud.pigx.app.api.entity;
-
-import com.baomidou.mybatisplus.annotation.*;
-import com.baomidou.mybatisplus.extension.activerecord.Model;
-import com.fasterxml.jackson.annotation.JsonIgnore;
-import com.pig4cloud.pigx.common.core.util.TenantTable;
-import io.swagger.v3.oas.annotations.media.Schema;
-import lombok.Data;
-import lombok.EqualsAndHashCode;
-
-import java.time.LocalDateTime;
-
-/**
- * app用户表
- *
- * @author aeizzz
- * @date 2022-12-07 09:52:03
- */
-@Data
-@TenantTable
-@TableName("app_user")
-@EqualsAndHashCode(callSuper = true)
-@Schema(description = "app用户表")
-public class AppUser extends Model {
-
- private static final long serialVersionUID = 1L;
-
- /**
- * userId
- */
- @TableId(type = IdType.ASSIGN_ID)
- @Schema(description = "userId")
- private Long userId;
-
- /**
- * 用户名
- */
- @Schema(description = "用户名")
- private String username;
-
- /**
- * 密码
- */
- @Schema(description = "密码")
- private String password;
-
- /**
- * 随机盐
- */
- @JsonIgnore
- @Schema(description = "随机盐")
- private String salt;
-
- /**
- * 手机号
- */
- @Schema(description = "手机号")
- private String phone;
-
- /**
- * 头像
- */
- @Schema(description = "头像")
- private String avatar;
-
- /**
- * 昵称
- */
- @Schema(description = "拓展字段:昵称")
- private String nickname;
-
- /**
- * 姓名
- */
- @Schema(description = "拓展字段:姓名")
- private String name;
-
- /**
- * 邮箱
- */
- @Schema(description = "拓展字段:邮箱")
- private String email;
-
- /**
- * 创建人
- */
- @Schema(description = "创建人")
- @TableField(fill = FieldFill.INSERT)
- private String createBy;
-
- /**
- * 修改人
- */
- @Schema(description = "修改人")
- @TableField(fill = FieldFill.UPDATE)
- private String updateBy;
-
- /**
- * 创建时间
- */
- @Schema(description = "创建时间")
- @TableField(fill = FieldFill.INSERT)
- private LocalDateTime createTime;
-
- /**
- * 修改时间
- */
- @Schema(description = "修改时间")
- @TableField(fill = FieldFill.UPDATE)
- private LocalDateTime updateTime;
-
- /**
- * 删除标记
- */
- @Schema(description = "删除标记,1:已删除,0:正常")
- @TableField(fill = FieldFill.INSERT)
- @TableLogic
- private String delFlag;
-
- /**
- * 所属租户
- */
- @Schema(description = "所属租户", hidden = true)
- private Long tenantId;
-
- /**
- * 最后一次密码修改时间
- */
- @Schema(description = "最后一次密码修改时间")
- private LocalDateTime lastModifiedTime;
-
- /**
- * 锁定标记
- */
- @Schema(description = "锁定标记")
- private String lockFlag;
-
- /**
- * 微信小程序登录openId
- */
- @Schema(description = "微信小程序登录openId")
- private String wxOpenid;
-
-}
diff --git a/pigx-app-server/pigx-app-server-api/src/main/java/com/pig4cloud/pigx/app/api/entity/AppUserRole.java b/pigx-app-server/pigx-app-server-api/src/main/java/com/pig4cloud/pigx/app/api/entity/AppUserRole.java
deleted file mode 100644
index d560c0731..000000000
--- a/pigx-app-server/pigx-app-server-api/src/main/java/com/pig4cloud/pigx/app/api/entity/AppUserRole.java
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * Copyright (c) 2018-2026, lengleng All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
- * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * Neither the name of the pig4cloud.com developer nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- * Author: lengleng (wangiegie@gmail.com)
- */
-
-package com.pig4cloud.pigx.app.api.entity;
-
-import com.baomidou.mybatisplus.annotation.IdType;
-import com.baomidou.mybatisplus.annotation.TableId;
-import com.baomidou.mybatisplus.annotation.TableName;
-import com.baomidou.mybatisplus.extension.activerecord.Model;
-import io.swagger.v3.oas.annotations.media.Schema;
-import lombok.Data;
-import lombok.EqualsAndHashCode;
-
-/**
- * 用户角色表
- *
- * @author aeizzz
- * @date 2022-12-07 09:52:03
- */
-@Data
-@TableName("app_user_role")
-@EqualsAndHashCode(callSuper = true)
-@Schema(description = "用户角色表")
-public class AppUserRole extends Model {
-
- private static final long serialVersionUID = 1L;
-
- /**
- * 用户ID
- */
- @TableId(type = IdType.ASSIGN_ID)
- @Schema(description = "用户ID")
- private Long userId;
-
- /**
- * 角色ID
- */
- @Schema(description = "角色ID")
- private Long roleId;
-
-}
diff --git a/pigx-app-server/pigx-app-server-api/src/main/java/com/pig4cloud/pigx/app/api/enums/PageTypeEnums.java b/pigx-app-server/pigx-app-server-api/src/main/java/com/pig4cloud/pigx/app/api/enums/PageTypeEnums.java
index 75339dbef..7f331b530 100644
--- a/pigx-app-server/pigx-app-server-api/src/main/java/com/pig4cloud/pigx/app/api/enums/PageTypeEnums.java
+++ b/pigx-app-server/pigx-app-server-api/src/main/java/com/pig4cloud/pigx/app/api/enums/PageTypeEnums.java
@@ -1,11 +1,18 @@
package com.pig4cloud.pigx.app.api.enums;
+import lombok.Getter;
+import lombok.RequiredArgsConstructor;
+
/**
- * 页面类型枚举
+ * App 装修页面类型枚举。
+ *
+ * 页面类型会写入 {@code app_page.page_type},后台保存装修页时根据该枚举回填页面名称。
*
* @author lengleng
* @date 2024/12/22
*/
+@Getter
+@RequiredArgsConstructor
public enum PageTypeEnums {
/**
* 首页
@@ -18,17 +25,23 @@ public enum PageTypeEnums {
/**
* 客服设置
*/
- SERVICE(3, "客服设置");
+ SERVICE(3, "客服设置"),
+ /**
+ * 工作台属性
+ */
+ WORKBENCH(4, "工作台");
+
+ /**
+ * 页面类型编码,和 app_page.page_type 对应。
+ */
private final Integer pageType;
+ /**
+ * 页面类型展示名称。
+ */
private final String name;
- PageTypeEnums(Integer pageType, String name) {
- this.pageType = pageType;
- this.name = name;
- }
-
/**
* 按类型获取名称
*
@@ -44,11 +57,4 @@ public enum PageTypeEnums {
return null;
}
- public Integer getPageType() {
- return pageType;
- }
-
- public String getName() {
- return name;
- }
}
diff --git a/pigx-app-server/pigx-app-server-api/src/main/java/com/pig4cloud/pigx/app/api/feign/RemoteAppUserService.java b/pigx-app-server/pigx-app-server-api/src/main/java/com/pig4cloud/pigx/app/api/feign/RemoteAppUserService.java
deleted file mode 100644
index 7605a9e56..000000000
--- a/pigx-app-server/pigx-app-server-api/src/main/java/com/pig4cloud/pigx/app/api/feign/RemoteAppUserService.java
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- *
- * Copyright (c) 2018-2026, lengleng All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
- * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * Neither the name of the pig4cloud.com developer nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- * Author: lengleng (wangiegie@gmail.com)
- *
- */
-
-package com.pig4cloud.pigx.app.api.feign;
-
-import com.pig4cloud.pigx.app.api.dto.AppUserInfo;
-import com.pig4cloud.pigx.common.core.constant.ServiceNameConstants;
-import com.pig4cloud.pigx.common.core.util.R;
-import com.pig4cloud.pigx.common.feign.annotation.NoToken;
-import org.springframework.cloud.openfeign.FeignClient;
-import org.springframework.web.bind.annotation.GetMapping;
-import org.springframework.web.bind.annotation.PathVariable;
-
-/**
- * @author lengleng
- * @date 2018/6/22
- */
-@FeignClient(contextId = "remoteAppUserService", value = ServiceNameConstants.APP_SERVER)
-public interface RemoteAppUserService {
-
- /**
- * 通过用户名查询用户、角色信息
- * @param username 用户名
- * @param from 调用标志
- * @return R
- */
- @NoToken
- @GetMapping("/appuser/info/{username}")
- R info(@PathVariable("username") String username);
-
- /**
- * 通过社交账号或手机号查询用户、角色信息
- * @param inStr appid@code
- * @param from 调用标志
- * @return
- */
- @NoToken
- @GetMapping("/appsocial/info/{inStr}")
- R social(@PathVariable("inStr") String inStr);
-
-
-}
diff --git a/pigx-app-server/pigx-app-server-api/src/main/java/com/pig4cloud/pigx/app/api/vo/AppDecorateVO.java b/pigx-app-server/pigx-app-server-api/src/main/java/com/pig4cloud/pigx/app/api/vo/AppDecorateVO.java
new file mode 100644
index 000000000..6f065558d
--- /dev/null
+++ b/pigx-app-server/pigx-app-server-api/src/main/java/com/pig4cloud/pigx/app/api/vo/AppDecorateVO.java
@@ -0,0 +1,102 @@
+package com.pig4cloud.pigx.app.api.vo;
+
+import com.pig4cloud.pigx.app.api.entity.AppPageEntity;
+import com.pig4cloud.pigx.app.api.entity.AppTabbarEntity;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+import org.springframework.beans.BeanUtils;
+
+import java.time.LocalDateTime;
+import java.util.List;
+
+/**
+ * APP 装修页聚合数据。
+ *
+ * 对外保持页面字段在顶层,额外追加 {@link #tabbar},避免把底部导航配置重新写回
+ * {@code app_page.page_data}。
+ *
+ * @author lengleng
+ */
+@Data
+@Schema(description = "APP 装修页聚合数据")
+public class AppDecorateVO {
+
+ /**
+ * 主键
+ */
+ @Schema(description = "主键")
+ private Long id;
+
+ /**
+ * 页面类型
+ */
+ @Schema(description = "页面类型")
+ private Integer pageType;
+
+ /**
+ * 页面名称
+ */
+ @Schema(description = "页面名称")
+ private String pageName;
+
+ /**
+ * 页面装修组件 JSON,不包含底部 Tabbar。
+ */
+ @Schema(description = "页面数据")
+ private String pageData;
+
+ /**
+ * 创建人
+ */
+ @Schema(description = "创建人")
+ private String createBy;
+
+ /**
+ * 创建时间
+ */
+ @Schema(description = "创建时间")
+ private LocalDateTime createTime;
+
+ /**
+ * 修改人
+ */
+ @Schema(description = "修改人")
+ private String updateBy;
+
+ /**
+ * 修改时间
+ */
+ @Schema(description = "修改时间")
+ private LocalDateTime updateTime;
+
+ /**
+ * 删除标记
+ */
+ @Schema(description = "删除标记")
+ private String delFlag;
+
+ /**
+ * 当前查询场景下可用的底部导航栏。
+ *
+ * 后台装修查询返回完整 Tabbar;App 运行时查询返回公开 Tabbar + 当前角色授权 Tabbar。
+ */
+ @Schema(description = "底部导航栏")
+ private List tabbar;
+
+ /**
+ * 根据页面实体和 Tabbar 列表构建装修聚合 VO。
+ *
+ * @param page 页面实体,可能为空
+ * @param tabbar Tabbar 列表
+ * @return 装修聚合数据
+ */
+ public static AppDecorateVO of(AppPageEntity page, List tabbar) {
+ AppDecorateVO vo = new AppDecorateVO();
+ if (page != null) {
+ BeanUtils.copyProperties(page, vo);
+ }
+ vo.setTabbar(tabbar);
+ return vo;
+ }
+
+}
diff --git a/pigx-app-server/pigx-app-server-api/src/main/java/com/pig4cloud/pigx/app/api/vo/AppRoleExcelVO.java b/pigx-app-server/pigx-app-server-api/src/main/java/com/pig4cloud/pigx/app/api/vo/AppRoleExcelVO.java
deleted file mode 100644
index e642897e0..000000000
--- a/pigx-app-server/pigx-app-server-api/src/main/java/com/pig4cloud/pigx/app/api/vo/AppRoleExcelVO.java
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * Copyright (c) 2018-2026, lengleng All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
- * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * Neither the name of the pig4cloud.com developer nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- * Author: lengleng (wangiegie@gmail.com)
- */
-
-package com.pig4cloud.pigx.app.api.vo;
-
-import cn.idev.excel.annotation.ExcelIgnore;
-import cn.idev.excel.annotation.ExcelProperty;
-import cn.idev.excel.annotation.write.style.ColumnWidth;
-import com.pig4cloud.pigx.common.excel.annotation.ExcelLine;
-import io.swagger.v3.oas.annotations.media.Schema;
-import lombok.Data;
-
-/**
- * @author lengleng
- * @date 2020/2/10
- */
-@Data
-@Schema(description = "前端角色展示对象")
-@ColumnWidth(30)
-public class AppRoleExcelVO {
-
- /**
- * 导入时候回显行号
- */
- @ExcelLine
- @ExcelIgnore
- private Long lineNum;
-
- /**
- * roleName
- */
- @ExcelProperty("角色名称")
- private String roleName;
-
- /**
- * roleCode
- */
- @ExcelProperty("角色标识")
- private String roleCode;
-
- /**
- * roleDesc
- */
- @ExcelProperty("角色描述")
- private String roleDesc;
-
-}
diff --git a/pigx-app-server/pigx-app-server-api/src/main/java/com/pig4cloud/pigx/app/api/vo/AppRoleVO.java b/pigx-app-server/pigx-app-server-api/src/main/java/com/pig4cloud/pigx/app/api/vo/AppRoleVO.java
deleted file mode 100644
index bc2b70ece..000000000
--- a/pigx-app-server/pigx-app-server-api/src/main/java/com/pig4cloud/pigx/app/api/vo/AppRoleVO.java
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Copyright (c) 2018-2026, lengleng All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
- * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * Neither the name of the pig4cloud.com developer nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- * Author: lengleng (wangiegie@gmail.com)
- */
-
-package com.pig4cloud.pigx.app.api.vo;
-
-import io.swagger.v3.oas.annotations.media.Schema;
-import lombok.Data;
-
-/**
- * @author lengleng
- * @date 2020/2/10
- */
-@Data
-@Schema(description = "前端角色展示对象")
-public class AppRoleVO {
-
- /**
- * 角色id
- */
- private Long roleId;
-
- /**
- * 菜单列表
- */
- private String menuIds;
-
-}
diff --git a/pigx-app-server/pigx-app-server-api/src/main/java/com/pig4cloud/pigx/app/api/vo/AppUserExcelVO.java b/pigx-app-server/pigx-app-server-api/src/main/java/com/pig4cloud/pigx/app/api/vo/AppUserExcelVO.java
deleted file mode 100644
index 6158f780b..000000000
--- a/pigx-app-server/pigx-app-server-api/src/main/java/com/pig4cloud/pigx/app/api/vo/AppUserExcelVO.java
+++ /dev/null
@@ -1,83 +0,0 @@
-package com.pig4cloud.pigx.app.api.vo;
-
-import cn.idev.excel.annotation.ExcelIgnore;
-import cn.idev.excel.annotation.ExcelProperty;
-import cn.idev.excel.annotation.write.style.ColumnWidth;
-import com.pig4cloud.pigx.common.excel.annotation.ExcelLine;
-import jakarta.validation.constraints.NotBlank;
-import lombok.Data;
-
-import java.time.LocalDateTime;
-
-@Data
-@ColumnWidth(30)
-public class AppUserExcelVO {
-
- /**
- * 导入时候回显行号
- */
- @ExcelLine
- @ExcelIgnore
- private Long lineNum;
-
- /**
- * 主键ID
- */
- @ExcelProperty("用户编号")
- private Long userId;
-
- /**
- * 用户名
- */
- @NotBlank(message = "用户名不能为空")
- @ExcelProperty("用户名")
- private String username;
-
- /**
- * 手机号
- */
- @NotBlank(message = "手机号不能为空")
- @ExcelProperty("手机号")
- private String phone;
-
- /**
- * 手机号
- */
- @NotBlank(message = "昵称不能为空")
- @ExcelProperty("昵称")
- private String nickname;
-
- /**
- * 手机号
- */
- @NotBlank(message = "姓名不能为空")
- @ExcelProperty("姓名")
- private String name;
-
- /**
- * 手机号
- */
- @NotBlank(message = "邮箱不能为空")
- @ExcelProperty("邮箱")
- private String email;
-
- /**
- * 角色列表
- */
- @NotBlank(message = "角色不能为空")
- @ExcelProperty("角色")
- private String roleNameList;
-
- /**
- * 锁定标记
- */
- @ExcelProperty("锁定标记,0:正常,9:已锁定")
- private String lockFlag;
-
- /**
- * 创建时间
- */
- @ExcelProperty(value = "创建时间")
- private LocalDateTime createTime;
-
-}
diff --git a/pigx-app-server/pigx-app-server-api/src/main/java/com/pig4cloud/pigx/app/api/vo/AppUserVO.java b/pigx-app-server/pigx-app-server-api/src/main/java/com/pig4cloud/pigx/app/api/vo/AppUserVO.java
deleted file mode 100644
index 14cc34223..000000000
--- a/pigx-app-server/pigx-app-server-api/src/main/java/com/pig4cloud/pigx/app/api/vo/AppUserVO.java
+++ /dev/null
@@ -1,101 +0,0 @@
-package com.pig4cloud.pigx.app.api.vo;
-
-import com.pig4cloud.pigx.app.api.entity.AppRole;
-import com.pig4cloud.pigx.common.sensitive.annotation.Sensitive;
-import com.pig4cloud.pigx.common.sensitive.core.SensitiveTypeEnum;
-import io.swagger.v3.oas.annotations.media.Schema;
-import lombok.Data;
-
-import java.io.Serializable;
-import java.time.LocalDateTime;
-import java.util.List;
-
-@Data
-public class AppUserVO implements Serializable {
-
- /**
- * 主键
- */
- @Schema(description = "主键")
- private Long userId;
-
- /**
- * 用户名
- */
- @Schema(description = "用户名")
- private String username;
-
- /**
- * 密码
- */
- @Schema(description = "密码")
- private String password;
-
- /**
- * 手机号
- */
- @Schema(description = "手机号")
- @Sensitive(type = SensitiveTypeEnum.MOBILE_PHONE)
- private String phone;
-
- /**
- * 头像
- */
- @Schema(description = "头像")
- private String avatar;
-
- /**
- * 昵称
- */
- @Schema(description = "拓展字段:昵称")
- private String nickname;
-
- /**
- * 姓名
- */
- @Schema(description = "拓展字段:姓名")
- private String name;
-
- /**
- * 邮箱
- */
- @Schema(description = "拓展字段:邮箱")
- private String email;
-
- /**
- * 创建时间
- */
- @Schema(description = "创建时间")
- private LocalDateTime createTime;
-
- /**
- * 删除标记
- */
- @Schema(description = "删除标记,1:已删除,0:正常")
- private String delFlag;
-
- /**
- * 所属租户
- */
- @Schema(description = "所属租户")
- private Long tenantId;
-
- /**
- * 最后一次密码修改时间
- */
- @Schema(description = "最后一次密码修改时间")
- private LocalDateTime lastModifiedTime;
-
- /**
- * 锁定标记
- */
- @Schema(description = "锁定标记")
- private String lockFlag;
-
- /**
- * 角色列表
- */
- @Schema(description = "拥有的角色列表")
- private List roleList;
-
-}
diff --git a/pigx-app-server/pigx-app-server-api/src/main/resources/META-INF/spring/org.springframework.cloud.openfeign.FeignClient.imports b/pigx-app-server/pigx-app-server-api/src/main/resources/META-INF/spring/org.springframework.cloud.openfeign.FeignClient.imports
deleted file mode 100644
index bff844c71..000000000
--- a/pigx-app-server/pigx-app-server-api/src/main/resources/META-INF/spring/org.springframework.cloud.openfeign.FeignClient.imports
+++ /dev/null
@@ -1 +0,0 @@
-com.pig4cloud.pigx.app.api.feign.RemoteAppUserService
diff --git a/pigx-app-server/pigx-app-server-biz/src/main/java/com/pig4cloud/pigx/app/controller/AppArticleController.java b/pigx-app-server/pigx-app-server-biz/src/main/java/com/pig4cloud/pigx/app/controller/AppArticleController.java
index 975182b00..5251bdbbf 100644
--- a/pigx-app-server/pigx-app-server-biz/src/main/java/com/pig4cloud/pigx/app/controller/AppArticleController.java
+++ b/pigx-app-server/pigx-app-server-biz/src/main/java/com/pig4cloud/pigx/app/controller/AppArticleController.java
@@ -36,10 +36,13 @@ public class AppArticleController {
private final AppArticleService appArticleService;
/**
- * 分页查询
+ * 分页查询文章资讯。
+ *
+ * 返回文章列表时会关联分类名称,供 App 资讯列表和后台管理复用。
+ *
* @param page 分页对象
* @param appArticle 文章资讯
- * @return
+ * @return 文章分页结果
*/
@Operation(summary = "分页查询", description = "分页查询")
@Inner(value = false)
@@ -49,9 +52,13 @@ public class AppArticleController {
}
/**
- * 通过id查询文章资讯
- * @param id id
- * @return R
+ * 查询文章详情。
+ *
+ * 会递增访问次数;如果传入 userId,则额外返回该用户是否收藏当前文章。
+ *
+ * @param id 文章 ID
+ * @param userId 用户 ID,可为空
+ * @return 文章详情
*/
@Inner(value = false)
@Operation(summary = "通过id查询", description = "通过id查询")
diff --git a/pigx-app-server/pigx-app-server-biz/src/main/java/com/pig4cloud/pigx/app/controller/AppContactsController.java b/pigx-app-server/pigx-app-server-biz/src/main/java/com/pig4cloud/pigx/app/controller/AppContactsController.java
new file mode 100644
index 000000000..e0ce7ccbb
--- /dev/null
+++ b/pigx-app-server/pigx-app-server-biz/src/main/java/com/pig4cloud/pigx/app/controller/AppContactsController.java
@@ -0,0 +1,122 @@
+package com.pig4cloud.pigx.app.controller;
+
+import cn.hutool.core.collection.CollUtil;
+import cn.hutool.core.util.ArrayUtil;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.pig4cloud.pigx.app.api.entity.AppContactsEntity;
+import com.pig4cloud.pigx.app.service.AppContactsService;
+import com.pig4cloud.pigx.common.core.util.R;
+import com.pig4cloud.pigx.common.excel.annotation.ResponseExcel;
+import com.pig4cloud.pigx.common.log.annotation.SysLog;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.security.SecurityRequirement;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import lombok.RequiredArgsConstructor;
+import org.springdoc.core.annotations.ParameterObject;
+import org.springframework.http.HttpHeaders;
+import com.pig4cloud.pigx.common.security.annotation.HasPermission;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.List;
+
+/**
+ * 通讯录表管理控制器
+ *
+ * @author lengleng
+ * @date 2025/05/29
+ */
+@RestController
+@RequiredArgsConstructor
+@RequestMapping("/appContacts")
+@Tag(description = "appContacts", name = "通讯录表管理")
+@SecurityRequirement(name = HttpHeaders.AUTHORIZATION)
+public class AppContactsController {
+
+ private final AppContactsService appContactsService;
+
+ /**
+ * 分页查询
+ *
+ * @param page 分页对象
+ * @param appContacts 通讯录表
+ * @return
+ */
+ @Operation(summary = "分页查询", description = "分页查询")
+ @GetMapping("/page")
+ @HasPermission("app_appContacts_view")
+ public R getAppContactsPage(@ParameterObject Page page, @ParameterObject AppContactsEntity appContacts) {
+ return R.ok(appContactsService.pageScope(page, appContacts));
+ }
+
+
+ /**
+ * 通过id查询通讯录表
+ *
+ * @param id id
+ * @return R
+ */
+ @Operation(summary = "通过id查询", description = "通过id查询")
+ @GetMapping("/{id}")
+ @HasPermission("app_appContacts_view")
+ public R getById(@PathVariable("id") Long id) {
+ return R.ok(appContactsService.getById(id));
+ }
+
+ /**
+ * 新增通讯录表
+ *
+ * @param appContacts 通讯录表
+ * @return R
+ */
+ @Operation(summary = "新增通讯录表", description = "新增通讯录表")
+ @SysLog("新增通讯录表")
+ @PostMapping
+ @HasPermission("app_appContacts_add")
+ public R save(@RequestBody AppContactsEntity appContacts) {
+ return R.ok(appContactsService.save(appContacts));
+ }
+
+ /**
+ * 修改通讯录表
+ *
+ * @param appContacts 通讯录表
+ * @return R
+ */
+ @Operation(summary = "修改通讯录表", description = "修改通讯录表")
+ @SysLog("修改通讯录表")
+ @PutMapping
+ @HasPermission("app_appContacts_edit")
+ public R updateById(@RequestBody AppContactsEntity appContacts) {
+ return R.ok(appContactsService.updateById(appContacts));
+ }
+
+ /**
+ * 通过id删除通讯录表
+ *
+ * @param ids id列表
+ * @return R
+ */
+ @Operation(summary = "通过id删除通讯录表", description = "通过id删除通讯录表")
+ @SysLog("通过id删除通讯录表")
+ @DeleteMapping
+ @HasPermission("app_appContacts_del")
+ public R removeById(@RequestBody Long[] ids) {
+ return R.ok(appContactsService.removeBatchByIds(CollUtil.toList(ids)));
+ }
+
+
+ /**
+ * 导出excel 表格
+ *
+ * @param appContacts 查询条件
+ * @param ids 导出指定ID
+ * @return excel 文件流
+ */
+ @ResponseExcel
+ @GetMapping("/export")
+ @HasPermission("app_appContacts_export")
+ public List export(AppContactsEntity appContacts, Long[] ids) {
+ return appContactsService.list(Wrappers.lambdaQuery(appContacts).in(ArrayUtil.isNotEmpty(ids), AppContactsEntity::getId, ids));
+ }
+}
\ No newline at end of file
diff --git a/pigx-app-server/pigx-app-server-biz/src/main/java/com/pig4cloud/pigx/app/controller/AppIndexController.java b/pigx-app-server/pigx-app-server-biz/src/main/java/com/pig4cloud/pigx/app/controller/AppIndexController.java
index 06371ea0a..f73540ce5 100644
--- a/pigx-app-server/pigx-app-server-biz/src/main/java/com/pig4cloud/pigx/app/controller/AppIndexController.java
+++ b/pigx-app-server/pigx-app-server-biz/src/main/java/com/pig4cloud/pigx/app/controller/AppIndexController.java
@@ -1,6 +1,5 @@
package com.pig4cloud.pigx.app.controller;
-import com.pig4cloud.pigx.app.api.entity.AppPageEntity;
import com.pig4cloud.pigx.app.service.AppIndexService;
import com.pig4cloud.pigx.common.core.util.R;
import com.pig4cloud.pigx.common.security.annotation.Inner;
@@ -14,10 +13,11 @@ import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
-import java.util.Map;
-
/**
- * app 首页控制
+ * App 运行时页面接口。
+ *
+ * 这里的接口主要给移动端调用,返回首页、装修页、底部 Tabbar 等运行时数据。
+ * 部分接口允许匿名访问,具体可见方法上的 {@link Inner} 配置。
*
* @author lengleng
* @date 2023/6/8
@@ -32,9 +32,11 @@ public class AppIndexController {
private final AppIndexService indexService;
/**
- * 获取主页配置
+ * 获取首页基础数据。
+ *
+ * 当前返回首页装修页记录和资讯列表,适合旧版首页一次性拉取基础内容。
*
- * @return {@link R }
+ * @return 首页页面数据和资讯列表
*/
@Inner(value = false)
@GetMapping("/index")
@@ -43,9 +45,11 @@ public class AppIndexController {
}
/**
- * 获取移动端appTabbar 配置
+ * 获取移动端底部导航配置。
+ *
+ * 未登录时只返回公开 Tabbar;登录后返回公开 Tabbar + 当前用户角色授权的 Tabbar。
*
- * @return {@link R }
+ * @return 当前访问身份可见的 Tabbar 列表
*/
@Inner(value = false)
@GetMapping("/config")
@@ -54,10 +58,12 @@ public class AppIndexController {
}
/**
- * 根据页面类型查询页面配置
+ * 获取指定页面类型的装修数据。
+ *
+ * 返回页面装修 JSON,同时聚合当前访问身份可见的 Tabbar,方便移动端一次请求完成页面渲染。
*
* @param pageType 页面类型
- * @return {@link R }
+ * @return 装修页聚合数据
*/
@Inner(value = false)
@GetMapping("/decorate")
@@ -65,4 +71,16 @@ public class AppIndexController {
return R.ok(indexService.decorate(pageType));
}
+ /**
+ * 获取工作台页面装修数据。
+ *
+ * 工作台内部按钮权限复用 B 端权限体系,这里不再按 App 专属菜单做二次过滤。
+ *
+ * @return 工作台页面数据
+ */
+ @GetMapping("/workbench")
+ public R workbench() {
+ return R.ok(indexService.workbench());
+ }
+
}
diff --git a/pigx-app-server/pigx-app-server-biz/src/main/java/com/pig4cloud/pigx/app/controller/AppMobileController.java b/pigx-app-server/pigx-app-server-biz/src/main/java/com/pig4cloud/pigx/app/controller/AppMobileController.java
index 8612179b9..6bd940248 100644
--- a/pigx-app-server/pigx-app-server-biz/src/main/java/com/pig4cloud/pigx/app/controller/AppMobileController.java
+++ b/pigx-app-server/pigx-app-server-biz/src/main/java/com/pig4cloud/pigx/app/controller/AppMobileController.java
@@ -30,6 +30,8 @@ import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
+ * App 手机验证码接口。
+ *
* @author lengleng
* @date 2018/11/14
*
@@ -44,6 +46,12 @@ public class AppMobileController {
private final AppMobileService appMobileService;
+ /**
+ * 发送 App 手机验证码。
+ *
+ * @param mobile 手机号
+ * @return 发送结果
+ */
@Inner(value = false)
@GetMapping("/{mobile}")
public R sendSmsCode(@PathVariable String mobile) {
diff --git a/pigx-app-server/pigx-app-server-biz/src/main/java/com/pig4cloud/pigx/app/controller/AppPageController.java b/pigx-app-server/pigx-app-server-biz/src/main/java/com/pig4cloud/pigx/app/controller/AppPageController.java
index 54370d79f..4d0511040 100644
--- a/pigx-app-server/pigx-app-server-biz/src/main/java/com/pig4cloud/pigx/app/controller/AppPageController.java
+++ b/pigx-app-server/pigx-app-server-biz/src/main/java/com/pig4cloud/pigx/app/controller/AppPageController.java
@@ -3,8 +3,11 @@ package com.pig4cloud.pigx.app.controller;
import cn.hutool.core.collection.CollUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.pig4cloud.pigx.app.api.entity.AppPageEntity;
+import com.pig4cloud.pigx.app.api.entity.AppTabbarEntity;
import com.pig4cloud.pigx.app.api.enums.PageTypeEnums;
+import com.pig4cloud.pigx.app.api.vo.AppDecorateVO;
import com.pig4cloud.pigx.app.service.AppPageService;
+import com.pig4cloud.pigx.app.service.AppTabbarService;
import com.pig4cloud.pigx.common.core.util.R;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.security.SecurityRequirement;
@@ -17,7 +20,10 @@ import org.springframework.web.bind.annotation.*;
import java.util.List;
/**
- * 页面管理
+ * App 装修页面后台管理接口。
+ *
+ * 页面表只保存页面装修组件 JSON,底部 Tabbar 由 {@code app_tabbar} 独立维护;
+ * 查询装修页时会聚合 Tabbar,便于后台预览。
*
* @author pig
* @date 2023-06-07 16:32:35
@@ -31,24 +37,35 @@ public class AppPageController {
private final AppPageService pageService;
+ private final AppTabbarService tabbarService;
+
/**
- * 查询文章资讯
+ * 按页面类型查询后台装修页配置。
+ *
+ * 返回结构保持页面字段在顶层,并额外携带完整 Tabbar 列表,用于后台装修预览和 Tabbar 设置区初始化。
*
- * @param pageType pageType
- * @return R
+ * @param pageType 页面类型,见 {@link PageTypeEnums}
+ * @return 页面装修数据和完整 Tabbar 列表
*/
@Operation(summary = "通过页面类型查询", description = "通过页面类型查询")
@GetMapping("/{pageType}")
- public R getByPageType(@PathVariable("pageType") Long pageType) {
- AppPageEntity appPage = pageService.getOne(Wrappers.lambdaQuery().eq(AppPageEntity::getPageType, pageType));
- return R.ok(appPage);
+ public R getByPageType(@PathVariable("pageType") Integer pageType) {
+ AppPageEntity appPage = pageService.getOne(Wrappers.lambdaQuery()
+ .eq(AppPageEntity::getPageType, pageType)
+ .orderByDesc(AppPageEntity::getCreateTime), false);
+ List tabbarList = tabbarService
+ .list(Wrappers.lambdaQuery().orderByAsc(AppTabbarEntity::getSortOrder).orderByAsc(AppTabbarEntity::getId));
+ return R.ok(AppDecorateVO.of(appPage, tabbarList));
}
/**
- * 更新
+ * 保存页面装修数据。
+ *
+ * 同一页面类型只保留一份最新配置;保存时先删除旧记录,再写入新记录。
+ * Tabbar 不随页面一起保存,需通过 {@link AppTabbarController} 单独维护。
*
* @param page 页面
- * @return {@link R }
+ * @return 保存结果
*/
@Operation(summary = "更新页面", description = "更新页面")
@PutMapping
@@ -58,7 +75,7 @@ public class AppPageController {
.list(Wrappers.lambdaQuery().eq(AppPageEntity::getPageType, page.getPageType()));
if (CollUtil.isNotEmpty(pageEntityList)) {
- // 删掉原来类型的页面数据
+ // app_page 按页面类型覆盖保存,避免同一页面类型存在多份装修数据。
pageService.removeByIds(pageEntityList.stream().map(AppPageEntity::getId).toList());
}
diff --git a/pigx-app-server/pigx-app-server-biz/src/main/java/com/pig4cloud/pigx/app/controller/AppRoleController.java b/pigx-app-server/pigx-app-server-biz/src/main/java/com/pig4cloud/pigx/app/controller/AppRoleController.java
deleted file mode 100644
index d4afe10be..000000000
--- a/pigx-app-server/pigx-app-server-biz/src/main/java/com/pig4cloud/pigx/app/controller/AppRoleController.java
+++ /dev/null
@@ -1,185 +0,0 @@
-/*
- * Copyright (c) 2018-2026, lengleng All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
- * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * Neither the name of the pig4cloud.com developer nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- * Author: lengleng (wangiegie@gmail.com)
- */
-
-package com.pig4cloud.pigx.app.controller;
-
-import cn.hutool.core.util.StrUtil;
-import com.baomidou.mybatisplus.core.toolkit.Wrappers;
-import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
-import com.pig4cloud.pigx.app.api.entity.AppRole;
-import com.pig4cloud.pigx.app.api.vo.AppRoleExcelVO;
-import com.pig4cloud.pigx.app.service.AppRoleService;
-import com.pig4cloud.pigx.common.core.util.R;
-import com.pig4cloud.pigx.common.excel.annotation.RequestExcel;
-import com.pig4cloud.pigx.common.excel.annotation.ResponseExcel;
-import com.pig4cloud.pigx.common.log.annotation.SysLog;
-import com.pig4cloud.pigx.common.security.annotation.HasPermission;
-import io.swagger.v3.oas.annotations.Operation;
-import io.swagger.v3.oas.annotations.security.SecurityRequirement;
-import io.swagger.v3.oas.annotations.tags.Tag;
-import lombok.RequiredArgsConstructor;
-import org.springframework.http.HttpHeaders;
-import org.springframework.validation.BindingResult;
-import org.springframework.web.bind.annotation.*;
-
-import java.util.List;
-
-/**
- * app角色表
- *
- * @author aeizzz
- * @date 2022-12-07 09:52:03
- */
-@RestController
-@RequiredArgsConstructor
-@RequestMapping("/approle")
-@Tag(description = "approle", name = "app角色表管理")
-@SecurityRequirement(name = HttpHeaders.AUTHORIZATION)
-public class AppRoleController {
-
- private final AppRoleService appRoleService;
-
- /**
- * 分页查询
- *
- * @param page 分页对象
- * @param appRole app角色表
- * @return
- */
- @Operation(summary = "分页查询", description = "分页查询")
- @GetMapping("/page")
- public R getAppRolePage(Page page, AppRole appRole) {
- return R.ok(appRoleService.page(page, Wrappers.lambdaQuery()
- .like(StrUtil.isNotBlank(appRole.getRoleName()), AppRole::getRoleName, appRole.getRoleName())));
- }
-
- /**
- * 查询全部角色
- *
- * @return
- */
- @Operation(summary = "查询全部", description = "查询全部")
- @GetMapping("/list")
- public R list() {
- return R.ok(appRoleService.list(Wrappers.emptyWrapper()));
- }
-
- /**
- * 通过id查询app角色表
- *
- * @param roleId id
- * @return R
- */
- @Operation(summary = "通过id查询", description = "通过id查询")
- @GetMapping("/{roleId}")
- public R getById(@PathVariable("roleId") Long roleId) {
- return R.ok(appRoleService.getById(roleId));
- }
-
- /**
- * 通过roleName查询app角色表
- *
- * @param roleName roleName
- * @return R
- */
- @Operation(summary = "通过id查询", description = "通过id查询")
- @GetMapping("/details/{roleName}")
- public R getByUserName(@PathVariable("roleName") String roleName) {
- return R.ok(appRoleService.getOne(Wrappers.lambdaQuery().eq(AppRole::getRoleName, roleName)));
- }
-
- /**
- * 通过roleCode查询app角色表
- *
- * @param roleCode roleCode
- * @return R
- */
- @Operation(summary = "通过roleCode查询", description = "通过roleCode查询")
- @GetMapping("/detailsByCode/{roleCode}")
- public R getByPhone(@PathVariable("roleCode") String roleCode) {
- return R.ok(appRoleService.getOne(Wrappers.lambdaQuery().eq(AppRole::getRoleCode, roleCode)));
- }
-
- /**
- * 新增app角色表
- *
- * @param appRole app角色表
- * @return R
- */
- @Operation(summary = "新增app角色表", description = "新增app角色表")
- @SysLog("新增app角色表")
- @PostMapping
- @HasPermission("app_approle_add")
- public R save(@RequestBody AppRole appRole) {
- return R.ok(appRoleService.save(appRole));
- }
-
- /**
- * 修改app角色表
- *
- * @param appRole app角色表
- * @return R
- */
- @Operation(summary = "修改app角色表", description = "修改app角色表")
- @SysLog("修改app角色表")
- @PutMapping
- @HasPermission("app_approle_edit")
- public R updateById(@RequestBody AppRole appRole) {
- return R.ok(appRoleService.updateById(appRole));
- }
-
- /**
- * 通过ids批量删除app角色表
- *
- * @param ids roleIds
- * @return R
- */
- @Operation(summary = "通过ids批量删除app角色表", description = "通过ids批量删除app角色表")
- @SysLog("通过ids批量删除app角色表")
- @DeleteMapping
- @HasPermission("app_approle_del")
- public R removeById(@RequestBody Long[] ids) {
- return R.ok(appRoleService.deleteRoleByIds(ids));
- }
-
- /**
- * 导出excel 表格
- *
- * @param appRole 查询条件
- * @return excel 文件流
- */
- @ResponseExcel
- @GetMapping("/export")
- @HasPermission("app_approle_export")
- public List export(AppRole appRole) {
- return appRoleService.list(Wrappers.query(appRole));
- }
-
- /**
- * 导入角色
- *
- * @param excelVOList 角色列表
- * @param bindingResult 错误信息列表
- * @return ok fail
- */
- @PostMapping("/import")
- @HasPermission("app_approle_export")
- public R importRole(@RequestExcel List excelVOList, BindingResult bindingResult) {
- return appRoleService.importRole(excelVOList, bindingResult);
- }
-
-}
diff --git a/pigx-app-server/pigx-app-server-biz/src/main/java/com/pig4cloud/pigx/app/controller/AppRoleTabbarController.java b/pigx-app-server/pigx-app-server-biz/src/main/java/com/pig4cloud/pigx/app/controller/AppRoleTabbarController.java
new file mode 100644
index 000000000..5a88bdbf8
--- /dev/null
+++ b/pigx-app-server/pigx-app-server-biz/src/main/java/com/pig4cloud/pigx/app/controller/AppRoleTabbarController.java
@@ -0,0 +1,105 @@
+package com.pig4cloud.pigx.app.controller;
+
+import cn.hutool.core.util.StrUtil;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.pig4cloud.pigx.admin.api.entity.SysRole;
+import com.pig4cloud.pigx.admin.api.feign.RemoteRoleService;
+import com.pig4cloud.pigx.app.api.dto.AppRoleTabbarDTO;
+import com.pig4cloud.pigx.app.api.entity.AppTabbarEntity;
+import com.pig4cloud.pigx.app.service.AppRoleTabbarService;
+import com.pig4cloud.pigx.app.service.AppTabbarService;
+import com.pig4cloud.pigx.common.core.util.R;
+import com.pig4cloud.pigx.common.security.annotation.HasPermission;
+import io.swagger.v3.oas.annotations.security.SecurityRequirement;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import jakarta.validation.Valid;
+import lombok.RequiredArgsConstructor;
+import org.springframework.http.HttpHeaders;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.List;
+
+/**
+ * App 角色底部导航授权管理接口。
+ *
+ * 该接口只维护「系统角色 -> App Tabbar」的授权关系。角色本身仍来自 upms 的 {@code sys_role},
+ * App 端运行时根据登录 token 中的角色 ID 读取 {@code app_role_tabbar},不跨库 join {@code sys_user_role}。
+ *
+ * @author lengleng
+ * @date 2026-05-09
+ */
+@RestController
+@RequiredArgsConstructor
+@RequestMapping("/role-tabbar")
+@Tag(description = "role-tabbar", name = "App角色底部导航授权")
+@SecurityRequirement(name = HttpHeaders.AUTHORIZATION)
+public class AppRoleTabbarController {
+
+ private final RemoteRoleService remoteRoleService;
+
+ private final AppTabbarService appTabbarService;
+
+ private final AppRoleTabbarService appRoleTabbarService;
+
+ /**
+ * 查询可授权的系统角色列表。
+ *
+ * 角色来源于 upms 远程接口,前端可按角色名称做轻量过滤,用于角色 Tabbar 授权页面。
+ *
+ * @param roleName 角色名称关键字,可为空
+ * @return 系统角色列表
+ */
+ @GetMapping("/roles")
+ @HasPermission("app_role_tabbar_view")
+ public R> roles(@RequestParam(required = false) String roleName) {
+ R> roles = remoteRoleService.getAllRole();
+ if (!roles.isOk() || roles.getData() == null || StrUtil.isBlank(roleName)) {
+ return roles;
+ }
+ return R.ok(roles.getData()
+ .stream()
+ .filter(role -> StrUtil.containsIgnoreCase(role.getRoleName(), roleName))
+ .toList());
+ }
+
+ /**
+ * 查询可授权的 App 底部导航列表。
+ *
+ * 返回完整 Tabbar 列表,公开 Tabbar 前端可固定勾选,登录可见 Tabbar 由角色授权控制。
+ *
+ * @return App Tabbar 列表
+ */
+ @GetMapping("/tabbar")
+ @HasPermission("app_role_tabbar_view")
+ public R> tabbars() {
+ return R.ok(appTabbarService.list(Wrappers.lambdaQuery()
+ .orderByAsc(AppTabbarEntity::getSortOrder)));
+ }
+
+ /**
+ * 查询指定角色已授权的 Tabbar ID。
+ *
+ * @param roleId 系统角色 ID
+ * @return 已授权的 Tabbar ID 列表
+ */
+ @GetMapping("/{roleId}")
+ @HasPermission("app_role_tabbar_view")
+ public R> roleTabbars(@PathVariable Long roleId) {
+ return R.ok(appRoleTabbarService.listTabbarIdsByRoleId(roleId));
+ }
+
+ /**
+ * 保存角色 Tabbar 授权。
+ *
+ * 保存采用覆盖语义:先清空该角色原有授权,再写入本次提交的 Tabbar ID 列表。
+ *
+ * @param dto 角色 Tabbar 授权请求
+ * @return 保存结果
+ */
+ @PutMapping
+ @HasPermission("app_role_tabbar_edit")
+ public R saveRoleTabbars(@Valid @RequestBody AppRoleTabbarDTO dto) {
+ return R.ok(appRoleTabbarService.saveRoleTabbars(dto));
+ }
+
+}
diff --git a/pigx-app-server/pigx-app-server-biz/src/main/java/com/pig4cloud/pigx/app/controller/AppSocialDetailsController.java b/pigx-app-server/pigx-app-server-biz/src/main/java/com/pig4cloud/pigx/app/controller/AppSocialDetailsController.java
deleted file mode 100644
index c3d207be7..000000000
--- a/pigx-app-server/pigx-app-server-biz/src/main/java/com/pig4cloud/pigx/app/controller/AppSocialDetailsController.java
+++ /dev/null
@@ -1,139 +0,0 @@
-/*
- * Copyright (c) 2018-2026, lengleng All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
- * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * Neither the name of the pig4cloud.com developer nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- * Author: lengleng (wangiegie@gmail.com)
- */
-
-package com.pig4cloud.pigx.app.controller;
-
-import cn.hutool.core.collection.CollUtil;
-import com.baomidou.mybatisplus.core.toolkit.Wrappers;
-import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
-import com.pig4cloud.pigx.app.api.entity.AppSocialDetails;
-import com.pig4cloud.pigx.app.service.AppSocialDetailsService;
-import com.pig4cloud.pigx.common.core.util.R;
-import com.pig4cloud.pigx.common.core.util.ValidGroup;
-import com.pig4cloud.pigx.common.excel.annotation.ResponseExcel;
-import com.pig4cloud.pigx.common.log.annotation.SysLog;
-import com.pig4cloud.pigx.common.security.annotation.HasPermission;
-import com.pig4cloud.pigx.common.security.annotation.Inner;
-import io.swagger.v3.oas.annotations.security.SecurityRequirement;
-import io.swagger.v3.oas.annotations.tags.Tag;
-import jakarta.validation.Valid;
-import lombok.AllArgsConstructor;
-import org.springframework.http.HttpHeaders;
-import org.springframework.validation.annotation.Validated;
-import org.springframework.web.bind.annotation.*;
-
-import java.util.List;
-
-@RestController
-@RequestMapping("/appsocial")
-@AllArgsConstructor
-@Tag(description = "social", name = "三方账号管理模块")
-@SecurityRequirement(name = HttpHeaders.AUTHORIZATION)
-public class AppSocialDetailsController {
-
- private final AppSocialDetailsService appSocialDetailsService;
-
- /**
- * 社交登录账户简单分页查询
- * @param page 分页对象
- * @param appSocialDetails 社交登录
- * @return
- */
- @GetMapping("/page")
- public R getSocialDetailsPage(Page page, AppSocialDetails appSocialDetails) {
- return R.ok(appSocialDetailsService.page(page, Wrappers.query(appSocialDetails)));
- }
-
- /**
- * 信息
- * @param id id
- * @return R
- */
- @GetMapping("/{id}")
- public R getinfo(@PathVariable("id") Long id) {
- return R.ok(appSocialDetailsService.getById(id));
- }
-
- /**
- * 保存
- * @param appSocialDetails
- * @return R
- */
- @SysLog("保存三方信息")
- @PostMapping
- @HasPermission("app_social_details_add")
- public R save(@Valid @RequestBody AppSocialDetails appSocialDetails) {
- return R.ok(appSocialDetailsService.save(appSocialDetails));
- }
-
- /**
- * 修改
- * @param appSocialDetails
- * @return R
- */
- @SysLog("修改三方信息")
- @PutMapping
- @HasPermission("app_social_details_edit")
- public R updateById(@Validated({ ValidGroup.Update.class }) @RequestBody AppSocialDetails appSocialDetails) {
- appSocialDetailsService.updateById(appSocialDetails);
- return R.ok(Boolean.TRUE);
- }
-
- /**
- * 删除
- * @param ids
- * @return R
- */
- @SysLog("删除三方信息")
- @DeleteMapping
- @HasPermission("app_social_details_del")
- public R removeById(@RequestBody Long[] ids) {
- return R.ok(appSocialDetailsService.removeBatchByIds(CollUtil.toList(ids)));
- }
-
- /**
- * 通过社交账号、手机号查询用户、角色信息
- * @param inStr appid@code
- * @return
- */
- @Inner
- @GetMapping("/info/{inStr}")
- public R getUserInfo(@PathVariable String inStr) {
- return R.ok(appSocialDetailsService.getUserInfo(inStr));
- }
-
- /**
- * 绑定社交账号
- * @param state 类型
- * @param code code
- * @return
- */
- @PostMapping("/bind")
- public R bindSocial(String state, String code) {
- return R.ok(appSocialDetailsService.bindSocial(state, code));
- }
-
- /**
- * 导出
- */
- @GetMapping("/export")
- @ResponseExcel
- public List export(AppSocialDetails appSocialDetails) {
- return appSocialDetailsService.list(Wrappers.query(appSocialDetails));
- }
-
-}
diff --git a/pigx-app-server/pigx-app-server-biz/src/main/java/com/pig4cloud/pigx/app/controller/AppTabbarController.java b/pigx-app-server/pigx-app-server-biz/src/main/java/com/pig4cloud/pigx/app/controller/AppTabbarController.java
index e80fcd4e0..888e3bed4 100644
--- a/pigx-app-server/pigx-app-server-biz/src/main/java/com/pig4cloud/pigx/app/controller/AppTabbarController.java
+++ b/pigx-app-server/pigx-app-server-biz/src/main/java/com/pig4cloud/pigx/app/controller/AppTabbarController.java
@@ -2,7 +2,9 @@ package com.pig4cloud.pigx.app.controller;
import cn.hutool.core.collection.CollUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.pig4cloud.pigx.app.api.entity.AppRoleTabbar;
import com.pig4cloud.pigx.app.api.entity.AppTabbarEntity;
+import com.pig4cloud.pigx.app.service.AppRoleTabbarService;
import com.pig4cloud.pigx.app.service.AppTabbarService;
import com.pig4cloud.pigx.common.core.util.R;
import io.swagger.v3.oas.annotations.Operation;
@@ -15,7 +17,10 @@ import org.springframework.web.bind.annotation.*;
import java.util.List;
/**
- * 底部导航
+ * App 底部导航后台管理接口。
+ *
+ * Tabbar 是移动端底部入口的数据源,图标字段保存 Wot UI 图标名;
+ * 是否登录可见由 {@code loginFlag} 控制,登录后再叠加角色授权。
*
* @author pig
* @date 2023-06-07 16:32:35
@@ -29,20 +34,40 @@ public class AppTabbarController {
private final AppTabbarService tabbarService;
+ private final AppRoleTabbarService roleTabbarService;
+
/**
- * 查询导航列表
+ * 查询全部底部导航。
+ *
+ * 后台维护页面使用完整列表;移动端运行时请走 {@code /app/index/config},
+ * 由运行时接口按公开/角色授权规则过滤。
*
- * @return R
+ * @return 完整 Tabbar 列表
*/
@Operation(summary = "查询导航列表", description = "查询导航列表")
@GetMapping("/list")
public R list() {
- return R.ok(tabbarService.list(Wrappers.lambdaQuery().orderByAsc(AppTabbarEntity::getSortOrder)));
+ return R.ok(tabbarService.list(
+ Wrappers.lambdaQuery().orderByAsc(AppTabbarEntity::getSortOrder).orderByAsc(AppTabbarEntity::getId)));
}
+ /**
+ * 批量保存底部导航。
+ *
+ * 前端提交的是当前完整 Tabbar 列表。这里会删除数据库中已不存在的 Tabbar,
+ * 并同步清理角色授权关系,避免 {@code app_role_tabbar} 残留无效 tabbar_id。
+ *
+ * @param tabbarEntityList 当前完整 Tabbar 配置
+ * @return 保存结果
+ */
@Operation(summary = "更新导航", description = "更新导航")
@PutMapping
public R update(@RequestBody List tabbarEntityList) {
+ tabbarEntityList.forEach(tabbar -> {
+ if (tabbar.getLoginFlag() == null) {
+ tabbar.setLoginFlag("1");
+ }
+ });
// 删除不在新增范围的导航菜单
List idList = tabbarService.list().stream().map(AppTabbarEntity::getId).toList();
List newIdList = tabbarEntityList.stream().map(AppTabbarEntity::getId).toList();
@@ -53,9 +78,10 @@ public class AppTabbarController {
// 如果有需要删除的菜单,则批量删除
if (CollUtil.isNotEmpty(idsToRemove)) {
tabbarService.removeBatchByIds(idsToRemove);
+ roleTabbarService.remove(Wrappers.lambdaQuery().in(AppRoleTabbar::getTabbarId, idsToRemove));
}
return R.ok(tabbarService.saveOrUpdateBatch(tabbarEntityList));
- }
+ }
}
diff --git a/pigx-app-server/pigx-app-server-biz/src/main/java/com/pig4cloud/pigx/app/controller/AppUserController.java b/pigx-app-server/pigx-app-server-biz/src/main/java/com/pig4cloud/pigx/app/controller/AppUserController.java
deleted file mode 100644
index a9e5f0cd7..000000000
--- a/pigx-app-server/pigx-app-server-biz/src/main/java/com/pig4cloud/pigx/app/controller/AppUserController.java
+++ /dev/null
@@ -1,215 +0,0 @@
-/*
- * Copyright (c) 2018-2026, lengleng All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
- * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * Neither the name of the pig4cloud.com developer nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- * Author: lengleng (wangiegie@gmail.com)
- */
-
-package com.pig4cloud.pigx.app.controller;
-
-import com.baomidou.mybatisplus.core.toolkit.Wrappers;
-import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
-import com.pig4cloud.pigx.app.api.dto.AppUserDTO;
-import com.pig4cloud.pigx.app.api.entity.AppUser;
-import com.pig4cloud.pigx.app.api.enums.AppErrorCodes;
-import com.pig4cloud.pigx.app.api.vo.AppUserExcelVO;
-import com.pig4cloud.pigx.app.service.AppUserService;
-import com.pig4cloud.pigx.common.core.constant.CommonConstants;
-import com.pig4cloud.pigx.common.core.constant.enums.UserTypeEnum;
-import com.pig4cloud.pigx.common.core.util.MsgUtils;
-import com.pig4cloud.pigx.common.core.util.R;
-import com.pig4cloud.pigx.common.excel.annotation.RequestExcel;
-import com.pig4cloud.pigx.common.excel.annotation.ResponseExcel;
-import com.pig4cloud.pigx.common.log.annotation.SysLog;
-import com.pig4cloud.pigx.common.security.annotation.HasPermission;
-import com.pig4cloud.pigx.common.security.annotation.Inner;
-import com.pig4cloud.pigx.common.security.util.SecurityUtils;
-import io.swagger.v3.oas.annotations.Operation;
-import io.swagger.v3.oas.annotations.security.SecurityRequirement;
-import io.swagger.v3.oas.annotations.tags.Tag;
-import jakarta.validation.Valid;
-import lombok.RequiredArgsConstructor;
-import org.springframework.http.HttpHeaders;
-import org.springframework.validation.BindingResult;
-import org.springframework.web.bind.annotation.*;
-
-import java.util.List;
-
-/**
- * app用户表
- *
- * @author aeizzz
- * @date 2022-12-07 09:52:03
- */
-@RestController
-@RequiredArgsConstructor
-@RequestMapping("/appuser")
-@Tag(description = "appuser", name = "app用户表管理")
-@SecurityRequirement(name = HttpHeaders.AUTHORIZATION)
-public class AppUserController {
-
- private final AppUserService appUserService;
-
- @Inner
- @GetMapping("/info/{username}")
- public R info(@PathVariable String username) {
- AppUser user = appUserService.getOne(Wrappers.query()
- .lambda()
- .eq(AppUser::getUsername, username)
- .or()
- .eq(AppUser::getPhone, username));
- if (user == null) {
- return R.failed(MsgUtils.getMessage(AppErrorCodes.APP_USER_USERINFO_EMPTY, username));
- }
- return R.ok(appUserService.findUserInfo(user));
- }
-
- /**
- * 获取当前用户全部信息
- *
- * @return 用户信息
- */
- @GetMapping(value = {"/info"})
- public R info() {
- String username = SecurityUtils.getUser().getUsername();
- AppUser user = appUserService.getOne(Wrappers.query().lambda().eq(AppUser::getUsername, username));
- if (user == null) {
- return R.failed(MsgUtils.getMessage(AppErrorCodes.APP_USER_QUERY_ERROR));
- }
- return R.ok(appUserService.findUserInfo(user));
- }
-
- /**
- * 分页查询
- *
- * @param page 分页对象
- * @param appUserDTO app用户表
- * @return
- */
- @Operation(summary = "分页查询", description = "分页查询")
- @GetMapping("/page")
- public R getAppUserPage(Page page, AppUserDTO appUserDTO) {
- return R.ok(appUserService.getUsersWithRolePage(page, appUserDTO));
- }
-
- /**
- * 通过id查询app用户表
- *
- * @param userId id
- * @return R
- */
- @Operation(summary = "通过id查询", description = "通过id查询")
- @GetMapping("/details/{userId}")
- public R getById(@PathVariable("userId") Long userId) {
- return R.ok(appUserService.selectUserVoById(userId));
- }
-
- /**
- * @return R
- */
- @Operation(summary = "通过userName查询", description = "通过userName查询")
- @GetMapping("/details")
- public R getByUserName(AppUser user) {
- AppUser one = appUserService.getOne(Wrappers.query(user), false);
- return R.ok(one == null ? null : CommonConstants.SUCCESS);
- }
-
- /**
- * 新增app用户表
- *
- * @param appUser app用户表
- * @return R
- */
- @Operation(summary = "新增app用户表", description = "新增app用户表")
- @SysLog("新增app用户表")
- @PostMapping
- @HasPermission("app_appuser_add")
- public R save(@RequestBody AppUserDTO appUser) {
- appUserService.saveUser(appUser);
- return R.ok();
- }
-
- /**
- * 修改app用户表
- *
- * @param appUser app用户表
- * @return R
- */
- @Operation(summary = "修改app用户表", description = "修改app用户表")
- @SysLog("修改app用户表")
- @PutMapping
- @HasPermission("app_appuser_edit")
- public R updateById(@RequestBody AppUserDTO appUser) {
- return R.ok(appUserService.updateUser(appUser));
- }
-
- /**
- * 通过id删除app用户表
- *
- * @param ids userIds
- * @return R
- */
- @Operation(summary = "通过ids删除app用户表", description = "通过ids删除app用户表")
- @SysLog("通过id删除app用户表")
- @DeleteMapping
- @HasPermission("app_appuser_del")
- public R removeById(@RequestBody Long[] ids) {
- return R.ok(appUserService.deleteAppUserByIds(ids));
- }
-
- /**
- * 导出excel 表格
- *
- * @param appUser 查询条件
- * @return excel 文件流
- */
- @ResponseExcel
- @GetMapping("/export")
- @HasPermission("app_appuser_export")
- public List export(AppUserDTO appUser) {
- return appUserService.listUser(appUser);
- }
-
- @SysLog("修改个人信息")
- @PutMapping("/edit")
- public R updateUserInfo(@Valid @RequestBody AppUserDTO userDto) {
- if (UserTypeEnum.TOC.getStatus().equals(SecurityUtils.getUser().getUserType())) {
- userDto.setUserId(SecurityUtils.getUser().getId());
- // TOC 以手机号为key
- userDto.setUsername(SecurityUtils.getUser().getUsername());
- }
- return appUserService.updateUserInfo(userDto);
- }
-
- /**
- * 导入用户
- *
- * @param excelVOList 用户列表
- * @param bindingResult 错误信息列表
- * @return R
- */
- @PostMapping("/import")
- @HasPermission("app_appuser_export")
- public R importUser(@RequestExcel List excelVOList, BindingResult bindingResult) {
- return appUserService.importUser(excelVOList, bindingResult);
- }
-
- @Operation(summary = "注册app用户表", description = "注册app用户表")
- @SysLog("注册app用户表")
- @Inner(value = false)
- @PostMapping("/register")
- public R register(@RequestBody AppUserDTO appUser) {
- return appUserService.registerAppUser(appUser);
- }
-
-}
diff --git a/pigx-app-server/pigx-app-server-biz/src/main/java/com/pig4cloud/pigx/app/controller/AppUserRoleController.java b/pigx-app-server/pigx-app-server-biz/src/main/java/com/pig4cloud/pigx/app/controller/AppUserRoleController.java
deleted file mode 100644
index b3f1693ab..000000000
--- a/pigx-app-server/pigx-app-server-biz/src/main/java/com/pig4cloud/pigx/app/controller/AppUserRoleController.java
+++ /dev/null
@@ -1,128 +0,0 @@
-/*
- * Copyright (c) 2018-2026, lengleng All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
- * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * Neither the name of the pig4cloud.com developer nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- * Author: lengleng (wangiegie@gmail.com)
- */
-
-package com.pig4cloud.pigx.app.controller;
-
-import com.baomidou.mybatisplus.core.toolkit.Wrappers;
-import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
-import com.pig4cloud.pigx.app.api.entity.AppUserRole;
-import com.pig4cloud.pigx.app.service.AppUserRoleService;
-import com.pig4cloud.pigx.common.core.util.R;
-import com.pig4cloud.pigx.common.excel.annotation.ResponseExcel;
-import com.pig4cloud.pigx.common.log.annotation.SysLog;
-import com.pig4cloud.pigx.common.security.annotation.HasPermission;
-import io.swagger.v3.oas.annotations.Operation;
-import io.swagger.v3.oas.annotations.security.SecurityRequirement;
-import io.swagger.v3.oas.annotations.tags.Tag;
-import lombok.RequiredArgsConstructor;
-import org.springframework.http.HttpHeaders;
-import org.springframework.web.bind.annotation.*;
-
-import java.util.List;
-
-/**
- * 用户角色表
- *
- * @author aeizzz
- * @date 2022-12-07 09:52:03
- */
-@RestController
-@RequiredArgsConstructor
-@RequestMapping("/appuserrole")
-@Tag(description = "appuserrole", name = "用户角色表管理")
-@SecurityRequirement(name = HttpHeaders.AUTHORIZATION)
-public class AppUserRoleController {
-
- private final AppUserRoleService appUserRoleService;
-
- /**
- * 分页查询
- * @param page 分页对象
- * @param appUserRole 用户角色表
- * @return
- */
- @Operation(summary = "分页查询", description = "分页查询")
- @GetMapping("/page")
- @HasPermission("app_appuserrole_view")
- public R getAppUserRolePage(Page page, AppUserRole appUserRole) {
- return R.ok(appUserRoleService.page(page, Wrappers.query(appUserRole)));
- }
-
- /**
- * 通过id查询用户角色表
- * @param userId id
- * @return R
- */
- @Operation(summary = "通过id查询", description = "通过id查询")
- @GetMapping("/{userId}")
- @HasPermission("app_appuserrole_view")
- public R getById(@PathVariable("userId") Long userId) {
- return R.ok(appUserRoleService.getById(userId));
- }
-
- /**
- * 新增用户角色表
- * @param appUserRole 用户角色表
- * @return R
- */
- @Operation(summary = "新增用户角色表", description = "新增用户角色表")
- @SysLog("新增用户角色表")
- @PostMapping
- @HasPermission("app_appuserrole_add")
- public R save(@RequestBody AppUserRole appUserRole) {
- return R.ok(appUserRoleService.save(appUserRole));
- }
-
- /**
- * 修改用户角色表
- * @param appUserRole 用户角色表
- * @return R
- */
- @Operation(summary = "修改用户角色表", description = "修改用户角色表")
- @SysLog("修改用户角色表")
- @PutMapping
- @HasPermission("app_appuserrole_edit")
- public R updateById(@RequestBody AppUserRole appUserRole) {
- return R.ok(appUserRoleService.updateById(appUserRole));
- }
-
- /**
- * 通过id删除用户角色表
- * @param userId id
- * @return R
- */
- @Operation(summary = "通过id删除用户角色表", description = "通过id删除用户角色表")
- @SysLog("通过id删除用户角色表")
- @DeleteMapping("/{userId}")
- @HasPermission("app_appuserrole_del")
- public R removeById(@PathVariable Long userId) {
- return R.ok(appUserRoleService.removeById(userId));
- }
-
- /**
- * 导出excel 表格
- * @param appUserRole 查询条件
- * @return excel 文件流
- */
- @ResponseExcel
- @GetMapping("/export")
- @HasPermission("app_appuserrole_export")
- public List export(AppUserRole appUserRole) {
- return appUserRoleService.list(Wrappers.query(appUserRole));
- }
-
-}
diff --git a/pigx-app-server/pigx-app-server-biz/src/main/java/com/pig4cloud/pigx/app/handler/AbstractLoginHandler.java b/pigx-app-server/pigx-app-server-biz/src/main/java/com/pig4cloud/pigx/app/handler/AbstractLoginHandler.java
deleted file mode 100644
index fd2503be8..000000000
--- a/pigx-app-server/pigx-app-server-biz/src/main/java/com/pig4cloud/pigx/app/handler/AbstractLoginHandler.java
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Copyright (c) 2018-2026, lengleng All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
- * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * Neither the name of the pig4cloud.com developer nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- * Author: lengleng (wangiegie@gmail.com)
- */
-
-package com.pig4cloud.pigx.app.handler;
-
-import com.pig4cloud.pigx.app.api.dto.AppUserInfo;
-
-/**
- * @author lengleng
- * @date 2018/11/18
- */
-public abstract class AbstractLoginHandler implements LoginHandler {
-
- /***
- * 数据合法性校验
- * @param loginStr 通过用户传入获取唯一标识
- * @return 默认不校验
- */
- @Override
- public Boolean check(String loginStr) {
- return true;
- }
-
- /**
- * 处理方法
- * @param loginStr 登录参数
- * @return
- */
- @Override
- public AppUserInfo handle(String loginStr) {
- if (!check(loginStr)) {
- return null;
- }
-
- String identify = identify(loginStr);
- return info(identify);
- }
-
-}
diff --git a/pigx-app-server/pigx-app-server-biz/src/main/java/com/pig4cloud/pigx/app/handler/LoginHandler.java b/pigx-app-server/pigx-app-server-biz/src/main/java/com/pig4cloud/pigx/app/handler/LoginHandler.java
deleted file mode 100644
index e9716b7ab..000000000
--- a/pigx-app-server/pigx-app-server-biz/src/main/java/com/pig4cloud/pigx/app/handler/LoginHandler.java
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * Copyright (c) 2018-2026, lengleng All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
- * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * Neither the name of the pig4cloud.com developer nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- * Author: lengleng (wangiegie@gmail.com)
- */
-
-package com.pig4cloud.pigx.app.handler;
-
-import com.pig4cloud.pigx.app.api.dto.AppUserInfo;
-import com.pig4cloud.pigx.app.api.entity.AppUser;
-
-/**
- * @author lengleng
- * @date 2018/11/18
- *
- * 登录处理器
- */
-public interface LoginHandler {
-
- /***
- * 数据合法性校验
- * @param loginStr 通过用户传入获取唯一标识
- * @return
- */
- Boolean check(String loginStr);
-
- /**
- * 通过用户传入获取唯一标识
- * @param loginStr
- * @return
- */
- String identify(String loginStr);
-
- /**
- * 通过openId 获取用户信息
- * @param identify
- * @return
- */
- AppUserInfo info(String identify);
-
- /**
- * 处理方法
- * @param loginStr 登录参数
- * @return
- */
- AppUserInfo handle(String loginStr);
-
- /**
- * 绑定逻辑
- * @param user 用户实体
- * @param identify 渠道返回唯一标识
- * @return
- */
- default Boolean bind(AppUser user, String identify) {
- return false;
- }
-
-}
diff --git a/pigx-app-server/pigx-app-server-biz/src/main/java/com/pig4cloud/pigx/app/handler/MiniAppLoginHandler.java b/pigx-app-server/pigx-app-server-biz/src/main/java/com/pig4cloud/pigx/app/handler/MiniAppLoginHandler.java
deleted file mode 100644
index 737518a1e..000000000
--- a/pigx-app-server/pigx-app-server-biz/src/main/java/com/pig4cloud/pigx/app/handler/MiniAppLoginHandler.java
+++ /dev/null
@@ -1,122 +0,0 @@
-/*
- * Copyright (c) 2018-2026, lengleng All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
- * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * Neither the name of the pig4cloud.com developer nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- * Author: lengleng (wangiegie@gmail.com)
- */
-
-package com.pig4cloud.pigx.app.handler;
-
-import cn.hutool.http.HttpUtil;
-import cn.hutool.json.JSONUtil;
-import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
-import com.baomidou.mybatisplus.core.toolkit.Wrappers;
-import com.pig4cloud.pigx.app.api.dto.AppUserInfo;
-import com.pig4cloud.pigx.app.api.entity.AppSocialDetails;
-import com.pig4cloud.pigx.app.api.entity.AppUser;
-import com.pig4cloud.pigx.app.mapper.AppSocialDetailsMapper;
-import com.pig4cloud.pigx.app.service.AppUserService;
-import com.pig4cloud.pigx.common.core.constant.SecurityConstants;
-import com.pig4cloud.pigx.common.core.constant.enums.LoginTypeEnum;
-import com.pig4cloud.pigx.common.core.exception.CheckedException;
-import lombok.AllArgsConstructor;
-import lombok.extern.slf4j.Slf4j;
-import org.springframework.stereotype.Component;
-
-import java.util.Objects;
-
-/**
- * @author lengleng
- * @date 2019年11月02日
- *
- * 微信小程序
- */
-@Slf4j
-@Component("APP-MINI")
-@AllArgsConstructor
-public class MiniAppLoginHandler extends AbstractLoginHandler {
-
- private final AppUserService appUserService;
-
- private final AppSocialDetailsMapper appSocialDetailsMapper;
-
- /**
- * 小程序登录传入code
- *
- * 通过code 调用qq 获取唯一标识
- *
- * @param code
- * @return
- */
- @Override
- public String identify(String code) {
- AppSocialDetails condition = new AppSocialDetails();
- condition.setType(LoginTypeEnum.MINI_APP.getType());
- AppSocialDetails socialDetails = appSocialDetailsMapper.selectOne(new QueryWrapper<>(condition));
-
- String url = String.format(SecurityConstants.MINI_APP_AUTHORIZATION_CODE_URL, socialDetails.getAppId(),
- socialDetails.getAppSecret(), code);
- String result = HttpUtil.get(url);
- log.debug("微信小程序响应报文:{}", result);
-
- if (JSONUtil.parseObj(result).containsKey("openid")) {
- return JSONUtil.parseObj(result).get("openid").toString();
- } else {
- log.error("微信小程序登录失败:{}", result);
- throw new CheckedException("微信小程序登录失败");
- }
- }
-
- /**
- * openId 获取用户信息
- *
- * @param openId
- * @return
- */
- @Override
- public AppUserInfo info(String openId) {
- AppUser user = appUserService.getOne(Wrappers.query().lambda().eq(AppUser::getWxOpenid, openId));
-
- // 未注册用户自动注册
- if (Objects.isNull(user)) {
- log.info("微信小程序未绑定:{},创建新的用户", openId);
- AppUser appUser = new AppUser();
- appUser.setWxOpenid(openId);
- appUser.setUsername(openId);
- appUser.setCreateBy(openId);
- appUser.setUpdateBy(openId);
- appUserService.saveOrUpdate(appUser);
-
- AppUserInfo appUserDTO = new AppUserInfo();
- appUserDTO.setAppUser(appUser);
- return appUserDTO;
- }
-
- return appUserService.findUserInfo(user);
- }
-
- /**
- * 绑定逻辑
- *
- * @param user 用户实体
- * @param identify 渠道返回唯一标识
- * @return
- */
- @Override
- public Boolean bind(AppUser user, String identify) {
- user.setWxOpenid(identify);
- appUserService.updateById(user);
- return true;
- }
-
-}
diff --git a/pigx-app-server/pigx-app-server-biz/src/main/java/com/pig4cloud/pigx/app/handler/SmsLoginHandler.java b/pigx-app-server/pigx-app-server-biz/src/main/java/com/pig4cloud/pigx/app/handler/SmsLoginHandler.java
deleted file mode 100644
index 2b4e26a50..000000000
--- a/pigx-app-server/pigx-app-server-biz/src/main/java/com/pig4cloud/pigx/app/handler/SmsLoginHandler.java
+++ /dev/null
@@ -1,93 +0,0 @@
-/*
- * Copyright (c) 2018-2026, lengleng All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
- * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * Neither the name of the pig4cloud.com developer nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- * Author: lengleng (wangiegie@gmail.com)
- */
-
-package com.pig4cloud.pigx.app.handler;
-
-import com.baomidou.mybatisplus.core.toolkit.Wrappers;
-import com.pig4cloud.pigx.app.api.dto.AppUserInfo;
-import com.pig4cloud.pigx.app.api.entity.AppUser;
-import com.pig4cloud.pigx.app.mapper.AppUserMapper;
-import com.pig4cloud.pigx.app.service.AppUserService;
-import lombok.AllArgsConstructor;
-import lombok.extern.slf4j.Slf4j;
-import org.springframework.stereotype.Component;
-
-import java.util.Objects;
-
-/**
- * @author lengleng
- * @date 2018/11/18
- */
-@Slf4j
-@Component("APP-SMS")
-@AllArgsConstructor
-public class SmsLoginHandler extends AbstractLoginHandler {
-
- private final AppUserService appUserService;
-
- /**
- * 验证码登录传入为手机号 不用不处理
- * @param mobile
- * @return
- */
- @Override
- public String identify(String mobile) {
- return mobile;
- }
-
- /**
- * 通过mobile 获取用户信息
- * @param identify
- * @return
- */
- @Override
- public AppUserInfo info(String identify) {
- AppUser user = appUserService.getOne(Wrappers.query().lambda().eq(AppUser::getPhone, identify));
-
- // 未注册用户自动注册
- if (Objects.isNull(user)) {
- log.info("手机号未注册:{}", identify);
- AppUser appUser = new AppUser();
- appUser.setUsername(identify);
- appUser.setPhone(identify);
- appUser.setCreateBy(identify);
- appUser.setUpdateBy(identify);
- appUserService.save(appUser);
- AppUserInfo appUserDTO = new AppUserInfo();
- appUserDTO.setAppUser(appUser);
- return appUserDTO;
- }
-
- // 返回用户信息
- return appUserService.findUserInfo(user);
- }
-
-
- /**
- * 绑定逻辑
- * @param user 用户实体
- * @param identify 渠道返回唯一标识
- * @return
- */
- @Override
- public Boolean bind(AppUser user, String identify) {
- user.setPhone(identify);
- appUserService.updateById(user);
- return true;
- }
-
-}
diff --git a/pigx-app-server/pigx-app-server-biz/src/main/java/com/pig4cloud/pigx/app/mapper/AppArticleCategoryMapper.java b/pigx-app-server/pigx-app-server-biz/src/main/java/com/pig4cloud/pigx/app/mapper/AppArticleCategoryMapper.java
index 21b54b96a..d34cf4488 100644
--- a/pigx-app-server/pigx-app-server-biz/src/main/java/com/pig4cloud/pigx/app/mapper/AppArticleCategoryMapper.java
+++ b/pigx-app-server/pigx-app-server-biz/src/main/java/com/pig4cloud/pigx/app/mapper/AppArticleCategoryMapper.java
@@ -4,6 +4,9 @@ import com.pig4cloud.pigx.app.api.entity.AppArticleCategoryEntity;
import com.pig4cloud.pigx.common.data.datascope.PigxBaseMapper;
import org.apache.ibatis.annotations.Mapper;
+/**
+ * 文章分类 Mapper。
+ */
@Mapper
public interface AppArticleCategoryMapper extends PigxBaseMapper {
diff --git a/pigx-app-server/pigx-app-server-biz/src/main/java/com/pig4cloud/pigx/app/mapper/AppArticleCollectMapper.java b/pigx-app-server/pigx-app-server-biz/src/main/java/com/pig4cloud/pigx/app/mapper/AppArticleCollectMapper.java
index 38ac31ff4..1dab63c7c 100644
--- a/pigx-app-server/pigx-app-server-biz/src/main/java/com/pig4cloud/pigx/app/mapper/AppArticleCollectMapper.java
+++ b/pigx-app-server/pigx-app-server-biz/src/main/java/com/pig4cloud/pigx/app/mapper/AppArticleCollectMapper.java
@@ -4,6 +4,9 @@ import com.pig4cloud.pigx.app.api.entity.AppArticleCollectEntity;
import com.pig4cloud.pigx.common.data.datascope.PigxBaseMapper;
import org.apache.ibatis.annotations.Mapper;
+/**
+ * 文章收藏 Mapper。
+ */
@Mapper
public interface AppArticleCollectMapper extends PigxBaseMapper {
diff --git a/pigx-app-server/pigx-app-server-biz/src/main/java/com/pig4cloud/pigx/app/mapper/AppArticleMapper.java b/pigx-app-server/pigx-app-server-biz/src/main/java/com/pig4cloud/pigx/app/mapper/AppArticleMapper.java
index f8306c1f5..61803e94a 100644
--- a/pigx-app-server/pigx-app-server-biz/src/main/java/com/pig4cloud/pigx/app/mapper/AppArticleMapper.java
+++ b/pigx-app-server/pigx-app-server-biz/src/main/java/com/pig4cloud/pigx/app/mapper/AppArticleMapper.java
@@ -4,6 +4,9 @@ import com.pig4cloud.pigx.app.api.entity.AppArticleEntity;
import com.pig4cloud.pigx.common.data.datascope.PigxBaseMapper;
import org.apache.ibatis.annotations.Mapper;
+/**
+ * 文章资讯 Mapper。
+ */
@Mapper
public interface AppArticleMapper extends PigxBaseMapper {
diff --git a/pigx-app-server/pigx-app-server-biz/src/main/java/com/pig4cloud/pigx/app/mapper/AppContactsMapper.java b/pigx-app-server/pigx-app-server-biz/src/main/java/com/pig4cloud/pigx/app/mapper/AppContactsMapper.java
new file mode 100644
index 000000000..0ff8a798d
--- /dev/null
+++ b/pigx-app-server/pigx-app-server-biz/src/main/java/com/pig4cloud/pigx/app/mapper/AppContactsMapper.java
@@ -0,0 +1,16 @@
+package com.pig4cloud.pigx.app.mapper;
+
+import com.pig4cloud.pigx.app.api.entity.AppContactsEntity;
+import com.pig4cloud.pigx.common.data.datascope.PigxBaseMapper;
+import org.apache.ibatis.annotations.Mapper;
+
+/**
+ * 通讯录 Mapper。
+ *
+ * 继承 {@link PigxBaseMapper} 后可配合数据权限插件执行范围查询。
+ */
+@Mapper
+public interface AppContactsMapper extends PigxBaseMapper {
+
+
+}
diff --git a/pigx-app-server/pigx-app-server-biz/src/main/java/com/pig4cloud/pigx/app/mapper/AppPageMapper.java b/pigx-app-server/pigx-app-server-biz/src/main/java/com/pig4cloud/pigx/app/mapper/AppPageMapper.java
index cad423d1d..407d872ea 100644
--- a/pigx-app-server/pigx-app-server-biz/src/main/java/com/pig4cloud/pigx/app/mapper/AppPageMapper.java
+++ b/pigx-app-server/pigx-app-server-biz/src/main/java/com/pig4cloud/pigx/app/mapper/AppPageMapper.java
@@ -4,6 +4,9 @@ import com.pig4cloud.pigx.app.api.entity.AppPageEntity;
import com.pig4cloud.pigx.common.data.datascope.PigxBaseMapper;
import org.apache.ibatis.annotations.Mapper;
+/**
+ * App 装修页面 Mapper。
+ */
@Mapper
public interface AppPageMapper extends PigxBaseMapper {
diff --git a/pigx-app-server/pigx-app-server-biz/src/main/java/com/pig4cloud/pigx/app/mapper/AppRoleMapper.java b/pigx-app-server/pigx-app-server-biz/src/main/java/com/pig4cloud/pigx/app/mapper/AppRoleMapper.java
deleted file mode 100644
index 4c1bbaa47..000000000
--- a/pigx-app-server/pigx-app-server-biz/src/main/java/com/pig4cloud/pigx/app/mapper/AppRoleMapper.java
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Copyright (c) 2018-2026, lengleng All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
- * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * Neither the name of the pig4cloud.com developer nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- * Author: lengleng (wangiegie@gmail.com)
- */
-
-package com.pig4cloud.pigx.app.mapper;
-
-import com.pig4cloud.pigx.app.api.entity.AppRole;
-import com.pig4cloud.pigx.common.data.datascope.PigxBaseMapper;
-import org.apache.ibatis.annotations.Mapper;
-
-import java.util.List;
-
-/**
- * app角色表
- *
- * @author aeizzz
- * @date 2022-12-07 09:52:03
- */
-@Mapper
-public interface AppRoleMapper extends PigxBaseMapper {
-
- List listRolesByUserId(Long userId);
-
-}
diff --git a/pigx-app-server/pigx-app-server-biz/src/main/java/com/pig4cloud/pigx/app/mapper/AppRoleTabbarMapper.java b/pigx-app-server/pigx-app-server-biz/src/main/java/com/pig4cloud/pigx/app/mapper/AppRoleTabbarMapper.java
new file mode 100644
index 000000000..8cfb71656
--- /dev/null
+++ b/pigx-app-server/pigx-app-server-biz/src/main/java/com/pig4cloud/pigx/app/mapper/AppRoleTabbarMapper.java
@@ -0,0 +1,16 @@
+package com.pig4cloud.pigx.app.mapper;
+
+import com.pig4cloud.pigx.app.api.entity.AppRoleTabbar;
+import com.pig4cloud.pigx.common.data.datascope.PigxBaseMapper;
+import org.apache.ibatis.annotations.Mapper;
+
+/**
+ * App 角色底部导航 Mapper。
+ *
+ * @author lengleng
+ * @date 2026-05-09
+ */
+@Mapper
+public interface AppRoleTabbarMapper extends PigxBaseMapper {
+
+}
diff --git a/pigx-app-server/pigx-app-server-biz/src/main/java/com/pig4cloud/pigx/app/mapper/AppSocialDetailsMapper.java b/pigx-app-server/pigx-app-server-biz/src/main/java/com/pig4cloud/pigx/app/mapper/AppSocialDetailsMapper.java
deleted file mode 100644
index c5db03aa8..000000000
--- a/pigx-app-server/pigx-app-server-biz/src/main/java/com/pig4cloud/pigx/app/mapper/AppSocialDetailsMapper.java
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Copyright (c) 2018-2026, lengleng All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
- * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * Neither the name of the pig4cloud.com developer nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- * Author: lengleng (wangiegie@gmail.com)
- */
-
-package com.pig4cloud.pigx.app.mapper;
-
-import com.pig4cloud.pigx.app.api.entity.AppSocialDetails;
-import com.pig4cloud.pigx.common.data.datascope.PigxBaseMapper;
-import org.apache.ibatis.annotations.Mapper;
-
-/**
- * 系统社交登录账号表
- *
- * @author lengleng
- * @date 2018-08-16 21:30:41
- */
-@Mapper
-public interface AppSocialDetailsMapper extends PigxBaseMapper {
-
-}
diff --git a/pigx-app-server/pigx-app-server-biz/src/main/java/com/pig4cloud/pigx/app/mapper/AppTabbarMapper.java b/pigx-app-server/pigx-app-server-biz/src/main/java/com/pig4cloud/pigx/app/mapper/AppTabbarMapper.java
index 774177178..b4b0296bb 100644
--- a/pigx-app-server/pigx-app-server-biz/src/main/java/com/pig4cloud/pigx/app/mapper/AppTabbarMapper.java
+++ b/pigx-app-server/pigx-app-server-biz/src/main/java/com/pig4cloud/pigx/app/mapper/AppTabbarMapper.java
@@ -4,6 +4,9 @@ import com.pig4cloud.pigx.app.api.entity.AppTabbarEntity;
import com.pig4cloud.pigx.common.data.datascope.PigxBaseMapper;
import org.apache.ibatis.annotations.Mapper;
+/**
+ * App 底部导航 Mapper。
+ */
@Mapper
public interface AppTabbarMapper extends PigxBaseMapper {
diff --git a/pigx-app-server/pigx-app-server-biz/src/main/java/com/pig4cloud/pigx/app/mapper/AppUserMapper.java b/pigx-app-server/pigx-app-server-biz/src/main/java/com/pig4cloud/pigx/app/mapper/AppUserMapper.java
deleted file mode 100644
index 4a1284aa9..000000000
--- a/pigx-app-server/pigx-app-server-biz/src/main/java/com/pig4cloud/pigx/app/mapper/AppUserMapper.java
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * Copyright (c) 2018-2026, lengleng All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
- * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * Neither the name of the pig4cloud.com developer nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- * Author: lengleng (wangiegie@gmail.com)
- */
-
-package com.pig4cloud.pigx.app.mapper;
-
-import com.baomidou.mybatisplus.core.metadata.IPage;
-import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
-import com.pig4cloud.pigx.app.api.dto.AppUserDTO;
-import com.pig4cloud.pigx.app.api.entity.AppUser;
-import com.pig4cloud.pigx.app.api.vo.AppUserVO;
-import com.pig4cloud.pigx.common.data.datascope.PigxBaseMapper;
-import org.apache.ibatis.annotations.Mapper;
-import org.apache.ibatis.annotations.Param;
-
-/**
- * app用户表
- *
- * @author aeizzz
- * @date 2022-12-07 09:52:03
- */
-@Mapper
-public interface AppUserMapper extends PigxBaseMapper {
-
- IPage getUserVosPage(Page page, @Param("query") AppUserDTO appUserDTO);
-
- AppUserVO getUserVoById(Long userId);
-
-}
diff --git a/pigx-app-server/pigx-app-server-biz/src/main/java/com/pig4cloud/pigx/app/mapper/AppUserRoleMapper.java b/pigx-app-server/pigx-app-server-biz/src/main/java/com/pig4cloud/pigx/app/mapper/AppUserRoleMapper.java
deleted file mode 100644
index e3a7445f1..000000000
--- a/pigx-app-server/pigx-app-server-biz/src/main/java/com/pig4cloud/pigx/app/mapper/AppUserRoleMapper.java
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Copyright (c) 2018-2026, lengleng All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
- * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * Neither the name of the pig4cloud.com developer nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- * Author: lengleng (wangiegie@gmail.com)
- */
-
-package com.pig4cloud.pigx.app.mapper;
-
-import com.pig4cloud.pigx.app.api.entity.AppUserRole;
-import com.pig4cloud.pigx.common.data.datascope.PigxBaseMapper;
-import org.apache.ibatis.annotations.Mapper;
-
-/**
- * 用户角色表
- *
- * @author aeizzz
- * @date 2022-12-07 09:52:03
- */
-@Mapper
-public interface AppUserRoleMapper extends PigxBaseMapper {
-
-}
diff --git a/pigx-app-server/pigx-app-server-biz/src/main/java/com/pig4cloud/pigx/app/service/AppArticleCategoryService.java b/pigx-app-server/pigx-app-server-biz/src/main/java/com/pig4cloud/pigx/app/service/AppArticleCategoryService.java
index 73cfb8caa..b2e9c79e5 100644
--- a/pigx-app-server/pigx-app-server-biz/src/main/java/com/pig4cloud/pigx/app/service/AppArticleCategoryService.java
+++ b/pigx-app-server/pigx-app-server-biz/src/main/java/com/pig4cloud/pigx/app/service/AppArticleCategoryService.java
@@ -3,6 +3,9 @@ package com.pig4cloud.pigx.app.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.pig4cloud.pigx.app.api.entity.AppArticleCategoryEntity;
+/**
+ * 文章分类基础服务。
+ */
public interface AppArticleCategoryService extends IService {
}
diff --git a/pigx-app-server/pigx-app-server-biz/src/main/java/com/pig4cloud/pigx/app/service/AppArticleCollectService.java b/pigx-app-server/pigx-app-server-biz/src/main/java/com/pig4cloud/pigx/app/service/AppArticleCollectService.java
index ec0afba12..d3146cfb6 100644
--- a/pigx-app-server/pigx-app-server-biz/src/main/java/com/pig4cloud/pigx/app/service/AppArticleCollectService.java
+++ b/pigx-app-server/pigx-app-server-biz/src/main/java/com/pig4cloud/pigx/app/service/AppArticleCollectService.java
@@ -3,8 +3,19 @@ package com.pig4cloud.pigx.app.service;
import com.github.yulichang.base.MPJBaseService;
import com.pig4cloud.pigx.app.api.entity.AppArticleCollectEntity;
+/**
+ * 文章收藏服务。
+ *
+ * 收藏记录以当前登录用户为维度保存,同一用户对同一文章只允许收藏一次。
+ */
public interface AppArticleCollectService extends MPJBaseService {
+ /**
+ * 保存当前用户的文章收藏。
+ *
+ * @param appArticleCollect 收藏请求,需包含文章 ID
+ * @return true=保存成功,false=已收藏或未保存
+ */
Boolean saveArticleCollect(AppArticleCollectEntity appArticleCollect);
}
diff --git a/pigx-app-server/pigx-app-server-biz/src/main/java/com/pig4cloud/pigx/app/service/AppContactsService.java b/pigx-app-server/pigx-app-server-biz/src/main/java/com/pig4cloud/pigx/app/service/AppContactsService.java
new file mode 100644
index 000000000..21412734e
--- /dev/null
+++ b/pigx-app-server/pigx-app-server-biz/src/main/java/com/pig4cloud/pigx/app/service/AppContactsService.java
@@ -0,0 +1,23 @@
+package com.pig4cloud.pigx.app.service;
+
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.pig4cloud.pigx.app.api.entity.AppContactsEntity;
+
+/**
+ * 应用联系人服务接口
+ *
+ * @author lengleng
+ * @date 2025/05/29
+ */
+public interface AppContactsService extends IService {
+
+ /**
+ * 根据应用联系人实体获取分页范围
+ *
+ * @param page 分页对象
+ * @param contactsEntity 应用联系人实体
+ * @return 分页范围对象
+ */
+ Page pageScope(Page page, AppContactsEntity contactsEntity);
+}
\ No newline at end of file
diff --git a/pigx-app-server/pigx-app-server-biz/src/main/java/com/pig4cloud/pigx/app/service/AppIndexService.java b/pigx-app-server/pigx-app-server-biz/src/main/java/com/pig4cloud/pigx/app/service/AppIndexService.java
index 2cb203221..55f556846 100644
--- a/pigx-app-server/pigx-app-server-biz/src/main/java/com/pig4cloud/pigx/app/service/AppIndexService.java
+++ b/pigx-app-server/pigx-app-server-biz/src/main/java/com/pig4cloud/pigx/app/service/AppIndexService.java
@@ -1,11 +1,15 @@
package com.pig4cloud.pigx.app.service;
import com.pig4cloud.pigx.app.api.entity.AppPageEntity;
+import com.pig4cloud.pigx.app.api.vo.AppDecorateVO;
import java.util.Map;
/**
- * app 页面控制
+ * App 运行时页面服务。
+ *
+ * 负责给移动端聚合首页、装修页、工作台和 Tabbar 配置;
+ * 后台装修管理接口不直接走这里。
*
* @author lengleng
* @date 2023/6/8
@@ -13,21 +17,33 @@ import java.util.Map;
public interface AppIndexService {
/**
- * 首页
+ * 获取首页基础数据。
+ *
+ * @return 首页页面记录和资讯列表
*/
Map index();
/**
- * 配置
- * @return Map
+ * 获取运行时配置。
+ *
+ * @return 当前访问身份可见的 Tabbar 等配置
*/
Map config();
/**
- * 装修
- * @param id 装修ID
- * @return Map
+ * 获取指定页面类型的装修页聚合数据。
+ *
+ * @param id 页面类型
+ * @return 装修页聚合数据
*/
- AppPageEntity decorate(Integer id);
+ AppDecorateVO decorate(Integer id);
+ /**
+ * 返回工作台页面实体对象。
+ *
+ * 工作台按钮权限由 B 端 permission 控制,这里只返回页面装修数据。
+ *
+ * @return 工作台页面实体对象
+ */
+ AppPageEntity workbench();
}
diff --git a/pigx-app-server/pigx-app-server-biz/src/main/java/com/pig4cloud/pigx/app/service/AppPageService.java b/pigx-app-server/pigx-app-server-biz/src/main/java/com/pig4cloud/pigx/app/service/AppPageService.java
index 5d58d1d61..a883aa549 100644
--- a/pigx-app-server/pigx-app-server-biz/src/main/java/com/pig4cloud/pigx/app/service/AppPageService.java
+++ b/pigx-app-server/pigx-app-server-biz/src/main/java/com/pig4cloud/pigx/app/service/AppPageService.java
@@ -3,6 +3,12 @@ package com.pig4cloud.pigx.app.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.pig4cloud.pigx.app.api.entity.AppPageEntity;
+/**
+ * App 装修页面基础服务。
+ *
+ * 页面组件 JSON 保存在 {@link AppPageEntity#getPageData()},
+ * 底部 Tabbar 不保存在页面 JSON 中。
+ */
public interface AppPageService extends IService {
}
diff --git a/pigx-app-server/pigx-app-server-biz/src/main/java/com/pig4cloud/pigx/app/service/AppRoleService.java b/pigx-app-server/pigx-app-server-biz/src/main/java/com/pig4cloud/pigx/app/service/AppRoleService.java
deleted file mode 100644
index 755faa03a..000000000
--- a/pigx-app-server/pigx-app-server-biz/src/main/java/com/pig4cloud/pigx/app/service/AppRoleService.java
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * Copyright (c) 2018-2026, lengleng All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
- * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * Neither the name of the pig4cloud.com developer nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- * Author: lengleng (wangiegie@gmail.com)
- */
-
-package com.pig4cloud.pigx.app.service;
-
-import com.baomidou.mybatisplus.extension.service.IService;
-import com.pig4cloud.pigx.app.api.entity.AppRole;
-import com.pig4cloud.pigx.app.api.vo.AppRoleExcelVO;
-import com.pig4cloud.pigx.common.core.util.R;
-import org.springframework.validation.BindingResult;
-
-import java.util.List;
-
-/**
- * app角色表
- *
- * @author aeizzz
- * @date 2022-12-07 09:52:03
- */
-public interface AppRoleService extends IService {
-
- List findRolesByUserId(Long userId);
-
- /**
- * 删除用户的同时,把role_menu关系删除
- * @param ids RoleIds
- */
- Boolean deleteRoleByIds(Long[] ids);
-
- R importRole(List excelVOList, BindingResult bindingResult);
-
-}
diff --git a/pigx-app-server/pigx-app-server-biz/src/main/java/com/pig4cloud/pigx/app/service/AppRoleTabbarService.java b/pigx-app-server/pigx-app-server-biz/src/main/java/com/pig4cloud/pigx/app/service/AppRoleTabbarService.java
new file mode 100644
index 000000000..bbf3ab9e7
--- /dev/null
+++ b/pigx-app-server/pigx-app-server-biz/src/main/java/com/pig4cloud/pigx/app/service/AppRoleTabbarService.java
@@ -0,0 +1,40 @@
+package com.pig4cloud.pigx.app.service;
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.pig4cloud.pigx.app.api.dto.AppRoleTabbarDTO;
+import com.pig4cloud.pigx.app.api.entity.AppRoleTabbar;
+
+import java.util.List;
+
+/**
+ * App 角色底部导航服务,管理系统角色与 App 底部导航的授权关系。
+ *
+ * @author lengleng
+ */
+public interface AppRoleTabbarService extends IService {
+
+ /**
+ * 查询指定角色已授权的底部导航 ID 列表。
+ *
+ * @param roleId 系统角色 ID
+ * @return 底部导航 ID 列表
+ */
+ List listTabbarIdsByRoleId(Long roleId);
+
+ /**
+ * 查询指定角色列表已授权的底部导航 ID 列表。
+ *
+ * @param roleIds 系统角色 ID 列表
+ * @return 底部导航 ID 列表
+ */
+ List listTabbarIdsByRoleIds(List roleIds);
+
+ /**
+ * 保存角色底部导航授权。
+ *
+ * @param dto 角色底部导航配置
+ * @return 操作结果
+ */
+ Boolean saveRoleTabbars(AppRoleTabbarDTO dto);
+
+}
diff --git a/pigx-app-server/pigx-app-server-biz/src/main/java/com/pig4cloud/pigx/app/service/AppSocialDetailsService.java b/pigx-app-server/pigx-app-server-biz/src/main/java/com/pig4cloud/pigx/app/service/AppSocialDetailsService.java
deleted file mode 100644
index cd9d142af..000000000
--- a/pigx-app-server/pigx-app-server-biz/src/main/java/com/pig4cloud/pigx/app/service/AppSocialDetailsService.java
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * Copyright (c) 2018-2026, lengleng All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
- * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * Neither the name of the pig4cloud.com developer nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- * Author: lengleng (wangiegie@gmail.com)
- */
-
-package com.pig4cloud.pigx.app.service;
-
-import com.baomidou.mybatisplus.extension.service.IService;
-import com.pig4cloud.pigx.app.api.dto.AppUserInfo;
-import com.pig4cloud.pigx.app.api.entity.AppSocialDetails;
-
-/**
- * 系统社交登录账号表
- *
- * @author lengleng
- * @date 2018-08-16 21:30:41
- */
-public interface AppSocialDetailsService extends IService {
-
- /**
- * 绑定社交账号
- * @param state 类型
- * @param code code
- * @return
- */
- Boolean bindSocial(String state, String code);
-
- /**
- * 根据入参查询用户信息
- * @param inStr
- * @return
- */
- AppUserInfo getUserInfo(String inStr);
-
-}
diff --git a/pigx-app-server/pigx-app-server-biz/src/main/java/com/pig4cloud/pigx/app/service/AppTabbarService.java b/pigx-app-server/pigx-app-server-biz/src/main/java/com/pig4cloud/pigx/app/service/AppTabbarService.java
index bdfbce6aa..2d14dcdf1 100644
--- a/pigx-app-server/pigx-app-server-biz/src/main/java/com/pig4cloud/pigx/app/service/AppTabbarService.java
+++ b/pigx-app-server/pigx-app-server-biz/src/main/java/com/pig4cloud/pigx/app/service/AppTabbarService.java
@@ -3,6 +3,9 @@ package com.pig4cloud.pigx.app.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.pig4cloud.pigx.app.api.entity.AppTabbarEntity;
+/**
+ * App 底部导航基础服务。
+ */
public interface AppTabbarService extends IService {
}
diff --git a/pigx-app-server/pigx-app-server-biz/src/main/java/com/pig4cloud/pigx/app/service/AppUserRoleService.java b/pigx-app-server/pigx-app-server-biz/src/main/java/com/pig4cloud/pigx/app/service/AppUserRoleService.java
deleted file mode 100644
index 13c7b85af..000000000
--- a/pigx-app-server/pigx-app-server-biz/src/main/java/com/pig4cloud/pigx/app/service/AppUserRoleService.java
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Copyright (c) 2018-2026, lengleng All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
- * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * Neither the name of the pig4cloud.com developer nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- * Author: lengleng (wangiegie@gmail.com)
- */
-
-package com.pig4cloud.pigx.app.service;
-
-import com.baomidou.mybatisplus.extension.service.IService;
-import com.pig4cloud.pigx.app.api.entity.AppUserRole;
-
-/**
- * 用户角色表
- *
- * @author aeizzz
- * @date 2022-12-07 09:52:03
- */
-public interface AppUserRoleService extends IService {
-
-}
diff --git a/pigx-app-server/pigx-app-server-biz/src/main/java/com/pig4cloud/pigx/app/service/AppUserService.java b/pigx-app-server/pigx-app-server-biz/src/main/java/com/pig4cloud/pigx/app/service/AppUserService.java
deleted file mode 100644
index 2ddef6fcb..000000000
--- a/pigx-app-server/pigx-app-server-biz/src/main/java/com/pig4cloud/pigx/app/service/AppUserService.java
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * Copyright (c) 2018-2026, lengleng All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
- * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * Neither the name of the pig4cloud.com developer nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- * Author: lengleng (wangiegie@gmail.com)
- */
-
-package com.pig4cloud.pigx.app.service;
-
-import com.baomidou.mybatisplus.core.metadata.IPage;
-import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
-import com.baomidou.mybatisplus.extension.service.IService;
-import com.pig4cloud.pigx.app.api.dto.AppUserDTO;
-import com.pig4cloud.pigx.app.api.dto.AppUserInfo;
-import com.pig4cloud.pigx.app.api.entity.AppUser;
-import com.pig4cloud.pigx.app.api.vo.AppUserExcelVO;
-import com.pig4cloud.pigx.app.api.vo.AppUserVO;
-import com.pig4cloud.pigx.common.core.util.R;
-import org.springframework.validation.BindingResult;
-
-import java.util.List;
-
-/**
- * app用户表
- *
- * @author aeizzz
- * @date 2022-12-07 09:52:03
- */
-public interface AppUserService extends IService {
-
- Boolean updateUser(AppUserDTO appUser);
-
- Boolean saveUser(AppUserDTO appUser);
-
- List listUser(AppUserDTO appUser);
-
- IPage getUsersWithRolePage(Page page, AppUserDTO appUserDTO);
-
- AppUserInfo findUserInfo(AppUser user);
-
- R updateUserInfo(AppUserDTO userDto);
-
- AppUserVO selectUserVoById(Long userId);
-
- Boolean deleteAppUserByIds(Long[] ids);
-
- R importUser(List excelVOList, BindingResult bindingResult);
-
- R registerAppUser(AppUserDTO appUser);
-
-}
diff --git a/pigx-app-server/pigx-app-server-biz/src/main/java/com/pig4cloud/pigx/app/service/impl/AppArticleCollectServiceImpl.java b/pigx-app-server/pigx-app-server-biz/src/main/java/com/pig4cloud/pigx/app/service/impl/AppArticleCollectServiceImpl.java
index 6121a8016..376e857c5 100644
--- a/pigx-app-server/pigx-app-server-biz/src/main/java/com/pig4cloud/pigx/app/service/impl/AppArticleCollectServiceImpl.java
+++ b/pigx-app-server/pigx-app-server-biz/src/main/java/com/pig4cloud/pigx/app/service/impl/AppArticleCollectServiceImpl.java
@@ -9,7 +9,9 @@ import com.pig4cloud.pigx.common.security.util.SecurityUtils;
import org.springframework.stereotype.Service;
/**
- * 文章收藏表
+ * 文章收藏服务实现。
+ *
+ * 收藏归属当前登录用户,保存前会校验同一用户是否已经收藏过同一文章。
*
* @author pig
* @date 2023-06-16 14:33:41
@@ -18,6 +20,12 @@ import org.springframework.stereotype.Service;
public class AppArticleCollectServiceImpl extends ServiceImpl
implements AppArticleCollectService {
+ /**
+ * 保存当前登录用户的文章收藏。
+ *
+ * @param appArticleCollect 收藏请求,业务上只需要文章 ID,用户 ID 由登录态写入
+ * @return true=收藏成功,false=已经收藏
+ */
@Override
public Boolean saveArticleCollect(AppArticleCollectEntity appArticleCollect) {
Long id = SecurityUtils.getUser().getId();
diff --git a/pigx-app-server/pigx-app-server-biz/src/main/java/com/pig4cloud/pigx/app/service/impl/AppArticleServiceImpl.java b/pigx-app-server/pigx-app-server-biz/src/main/java/com/pig4cloud/pigx/app/service/impl/AppArticleServiceImpl.java
index 418056513..fb5fa67f5 100644
--- a/pigx-app-server/pigx-app-server-biz/src/main/java/com/pig4cloud/pigx/app/service/impl/AppArticleServiceImpl.java
+++ b/pigx-app-server/pigx-app-server-biz/src/main/java/com/pig4cloud/pigx/app/service/impl/AppArticleServiceImpl.java
@@ -17,7 +17,9 @@ import org.springframework.stereotype.Service;
import java.util.Objects;
/**
- * 文章资讯
+ * 文章资讯服务实现。
+ *
+ * 负责文章列表关联分类名称、文章详情访问次数递增,以及当前用户收藏状态补充。
*
* @author pig
* @date 2023-06-07 16:32:35
@@ -30,14 +32,19 @@ public class AppArticleServiceImpl extends ServiceImpl
+ * 如果传入用户 ID,会额外查询该用户是否已收藏当前文章。
+ * 阅读数更新使用当前 visit 值作为条件,降低并发覆盖风险。
+ *
+ * @param id 文章 ID
+ * @param userId 当前用户 ID,可为空
+ * @return 文章详情
*/
@Override
public AppArticleEntity getArticleAndIncrById(Long id, Long userId) {
AppArticleEntity appArticleEntity = baseMapper.selectById(id);
- // 查询是否收藏了
+ // 登录用户访问详情时,补充当前用户是否已收藏该文章。
if (Objects.nonNull(userId)) {
boolean exists = collectMapper.exists(Wrappers.lambdaQuery()//
.eq(AppArticleCollectEntity::getArticleId, appArticleEntity.getId())//
@@ -45,10 +52,9 @@ public class AppArticleServiceImpl extends ServiceImpllambdaQuery()
.eq(AppArticleEntity::getId, id)
@@ -57,10 +63,11 @@ public class AppArticleServiceImpl extends ServiceImpl
+ * 通讯录列表会结合系统数据权限,只返回当前登录用户可见范围内的数据。
+ *
+ * @author lengleng
+ * @date 2025/05/29
+ */
+@Service
+public class AppContactsServiceImpl extends ServiceImpl implements AppContactsService {
+ /**
+ * 根据查询条件分页查询通讯录,并应用数据权限范围。
+ *
+ * @param page 分页对象
+ * @param appContacts 应用联系人实体
+ * @return 分页范围对象
+ */
+ @Override
+ public Page pageScope(Page page, AppContactsEntity appContacts) {
+ LambdaQueryWrapper wrapper = Wrappers.lambdaQuery();
+ wrapper.like(StrUtil.isNotBlank(appContacts.getContactName()), AppContactsEntity::getContactName, appContacts.getContactName());
+ wrapper.like(StrUtil.isNotBlank(appContacts.getContactPhone()), AppContactsEntity::getContactPhone, appContacts.getContactPhone());
+
+ DataScope dataScope = new DataScope();
+ dataScope.setUsername(SecurityUtils.getUser().getUsername());
+ return baseMapper.selectPageByScope(page, wrapper, dataScope);
+ }
+}
diff --git a/pigx-app-server/pigx-app-server-biz/src/main/java/com/pig4cloud/pigx/app/service/impl/AppIndexServiceImpl.java b/pigx-app-server/pigx-app-server-biz/src/main/java/com/pig4cloud/pigx/app/service/impl/AppIndexServiceImpl.java
index 73e3831ed..fa9258b30 100644
--- a/pigx-app-server/pigx-app-server-biz/src/main/java/com/pig4cloud/pigx/app/service/impl/AppIndexServiceImpl.java
+++ b/pigx-app-server/pigx-app-server-biz/src/main/java/com/pig4cloud/pigx/app/service/impl/AppIndexServiceImpl.java
@@ -5,10 +5,14 @@ import com.pig4cloud.pigx.app.api.entity.AppArticleEntity;
import com.pig4cloud.pigx.app.api.entity.AppPageEntity;
import com.pig4cloud.pigx.app.api.entity.AppTabbarEntity;
import com.pig4cloud.pigx.app.api.enums.PageTypeEnums;
+import com.pig4cloud.pigx.app.api.vo.AppDecorateVO;
import com.pig4cloud.pigx.app.mapper.AppArticleMapper;
import com.pig4cloud.pigx.app.mapper.AppPageMapper;
import com.pig4cloud.pigx.app.mapper.AppTabbarMapper;
import com.pig4cloud.pigx.app.service.AppIndexService;
+import com.pig4cloud.pigx.app.service.AppRoleTabbarService;
+import com.pig4cloud.pigx.common.core.constant.CommonConstants;
+import com.pig4cloud.pigx.common.security.util.SecurityUtils;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
@@ -17,24 +21,33 @@ import java.util.List;
import java.util.Map;
/**
- * app 页面控制
+ * App首页服务实现类
+ * 实现AppIndexService接口,提供首页数据、导航栏配置以及页面配置等功能。
+ *
+ * 该实现面向移动端运行时:Tabbar 会按公开/登录角色授权规则过滤,
+ * 页面装修数据则保持原始组件 JSON,不在这里做页面组件级权限裁剪。
*
* @author lengleng
* @date 2023/6/8
*/
-
@Service
@RequiredArgsConstructor
public class AppIndexServiceImpl implements AppIndexService {
- private final AppArticleMapper appArticleMapper;
-
private final AppTabbarMapper appTabbarMapper;
private final AppPageMapper appPageMapper;
+ private final AppArticleMapper appArticleMapper;
+
+ private final AppRoleTabbarService appRoleTabbarService;
+
/**
- * 商城首页 首页数据
+ * 获取商城首页基础数据。
+ *
+ * 旧版首页接口返回首页装修页记录和资讯列表;新版装修页推荐使用 {@link #decorate(Integer)}。
+ *
+ * @return 首页页面数据和资讯列表
*/
@Override
public Map index() {
@@ -44,6 +57,7 @@ public class AppIndexServiceImpl implements AppIndexService {
.orderByDesc(AppPageEntity::getCreateTime),
false
);
+
List articleList = appArticleMapper
.selectList(Wrappers.lambdaQuery().orderByDesc(AppArticleEntity::getSort));
response.put("pages", appPageEntity);
@@ -52,29 +66,74 @@ public class AppIndexServiceImpl implements AppIndexService {
}
/**
- * 导航栏配置
+ * 获取运行时配置。
+ *
+ * 当前只包含 Tabbar,并按 {@link #listAuthorizedTabbar()} 的规则过滤。
*
- * @return Map
+ * @return 运行时配置集合
*/
@Override
public Map config() {
Map response = new LinkedHashMap<>();
- List tabbarEntityList = appTabbarMapper
- .selectList(Wrappers.lambdaQuery().orderByAsc(AppTabbarEntity::getSortOrder));
- response.put("tabbar", tabbarEntityList);
+ response.put("tabbar", listAuthorizedTabbar());
return response;
}
/**
- * 根据类型查询页面配置
+ * 根据页面类型获取最新装修页,并附加当前访问身份可见的 Tabbar。
*
* @param pageType 页面类型
- * @return {@link AppPageEntity }
+ * @return 装修页聚合数据
*/
@Override
- public AppPageEntity decorate(Integer pageType) {
- return appPageMapper.selectOne(Wrappers.lambdaQuery().eq(AppPageEntity::getPageType, pageType)
- .orderByDesc(AppPageEntity::getCreateTime), false);
+ public AppDecorateVO decorate(Integer pageType) {
+ AppPageEntity appPageEntity = appPageMapper.selectOne(
+ Wrappers.lambdaQuery()
+ .eq(AppPageEntity::getPageType, pageType)
+ .orderByDesc(AppPageEntity::getCreateTime),
+ false
+ );
+ return AppDecorateVO.of(appPageEntity, listAuthorizedTabbar());
}
+
+ /**
+ * 获取工作台页面数据。
+ *
+ * 工作台内部按钮权限复用系统菜单 permission,这里不再读取 App 专属菜单授权。
+ *
+ * @return 工作台页面实体
+ */
+ @Override
+ public AppPageEntity workbench() {
+ return appPageMapper.selectOne(
+ Wrappers.lambdaQuery()
+ .eq(AppPageEntity::getPageType, PageTypeEnums.WORKBENCH.getPageType())
+ .orderByDesc(AppPageEntity::getCreateTime),
+ false
+ );
+ }
+
+ /**
+ * 查询当前访问身份可见的 Tabbar。
+ *
+ * 匿名访问只返回 {@code loginFlag=0} 的公开 Tabbar;登录访问从 token authorities
+ * 解析角色 ID,再读取 {@code app_role_tabbar} 中授权的 Tabbar,避免跨库 join upms 的
+ * {@code sys_user_role}。
+ *
+ * @return 当前可见的 Tabbar 列表
+ */
+ private List listAuthorizedTabbar() {
+ List roleIds = SecurityUtils.getUser() == null ? List.of() : SecurityUtils.getRoleIds();
+ List tabbarIds = appRoleTabbarService.listTabbarIdsByRoleIds(roleIds);
+ return appTabbarMapper.selectList(Wrappers.lambdaQuery()
+ .and(wrapper -> {
+ wrapper.eq(AppTabbarEntity::getLoginFlag, CommonConstants.STATUS_NORMAL);
+ if (!tabbarIds.isEmpty()) {
+ wrapper.or().in(AppTabbarEntity::getId, tabbarIds);
+ }
+ })
+ .orderByAsc(AppTabbarEntity::getSortOrder)
+ .orderByAsc(AppTabbarEntity::getId));
+ }
}
diff --git a/pigx-app-server/pigx-app-server-biz/src/main/java/com/pig4cloud/pigx/app/service/impl/AppMobileServiceImpl.java b/pigx-app-server/pigx-app-server-biz/src/main/java/com/pig4cloud/pigx/app/service/impl/AppMobileServiceImpl.java
index 3a522ccc5..af31cf488 100644
--- a/pigx-app-server/pigx-app-server-biz/src/main/java/com/pig4cloud/pigx/app/service/impl/AppMobileServiceImpl.java
+++ b/pigx-app-server/pigx-app-server-biz/src/main/java/com/pig4cloud/pigx/app/service/impl/AppMobileServiceImpl.java
@@ -33,6 +33,11 @@ import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
/**
+ * App 手机验证码服务实现。
+ *
+ * 验证码按 {@code 验证码缓存前缀 + 登录类型 + 手机号} 写入 Redis,
+ * 过期时间使用统一安全常量配置。
+ *
* @author lengleng
* @date 2018/11/14
*
@@ -44,10 +49,13 @@ import org.springframework.stereotype.Service;
public class AppMobileServiceImpl implements AppMobileService {
/**
- * 发送手机验证码 TODO: 调用短信网关发送验证码,测试返回前端
+ * 发送手机验证码。
+ *
+ * 如果验证码仍在有效期内,则拒绝重复发送。当前实现只生成并缓存验证码,
+ * 后续接入短信网关时应在生成验证码后调用真实发送能力。
*
- * @param mobile mobile
- * @return code
+ * @param mobile 手机号
+ * @return true=生成成功,false=验证码未过期
*/
@Override
public R sendSmsCode(String mobile) {
diff --git a/pigx-app-server/pigx-app-server-biz/src/main/java/com/pig4cloud/pigx/app/service/impl/AppRoleServiceImpl.java b/pigx-app-server/pigx-app-server-biz/src/main/java/com/pig4cloud/pigx/app/service/impl/AppRoleServiceImpl.java
deleted file mode 100644
index 7d620e75d..000000000
--- a/pigx-app-server/pigx-app-server-biz/src/main/java/com/pig4cloud/pigx/app/service/impl/AppRoleServiceImpl.java
+++ /dev/null
@@ -1,124 +0,0 @@
-/*
- * Copyright (c) 2018-2026, lengleng All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
- * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * Neither the name of the pig4cloud.com developer nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- * Author: lengleng (wangiegie@gmail.com)
- */
-package com.pig4cloud.pigx.app.service.impl;
-
-import cn.hutool.core.collection.CollUtil;
-import com.baomidou.mybatisplus.core.toolkit.Wrappers;
-import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
-import com.pig4cloud.pigx.app.api.entity.AppPageEntity;
-import com.pig4cloud.pigx.app.api.entity.AppRole;
-import com.pig4cloud.pigx.app.api.enums.AppErrorCodes;
-import com.pig4cloud.pigx.app.api.enums.PageTypeEnums;
-import com.pig4cloud.pigx.app.api.vo.AppRoleExcelVO;
-import com.pig4cloud.pigx.app.mapper.AppPageMapper;
-import com.pig4cloud.pigx.app.mapper.AppRoleMapper;
-import com.pig4cloud.pigx.app.service.AppRoleService;
-import com.pig4cloud.pigx.common.core.util.MsgUtils;
-import com.pig4cloud.pigx.common.core.util.R;
-import com.pig4cloud.pigx.common.excel.vo.ErrorMessage;
-import lombok.RequiredArgsConstructor;
-import org.springframework.stereotype.Service;
-import org.springframework.validation.BindingResult;
-
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
-
-/**
- * APP角色服务实现类
- *
- * 提供对APP角色相关的业务操作实现。
- *
- * @author lengleng
- * @date 2025/05/29
- */
-@Service
-@RequiredArgsConstructor
-public class AppRoleServiceImpl extends ServiceImpl implements AppRoleService {
-
- private final AppPageMapper appPageMapper;
-
- private final AppRoleMapper appRoleMapper;
-
- @Override
- public List findRolesByUserId(Long userId) {
- return baseMapper.listRolesByUserId(userId);
- }
-
- /**
- * 删除用户的同时,把role_menu关系删除
- *
- * @param ids roleIds
- */
- @Override
- public Boolean deleteRoleByIds(Long[] ids) {
- this.removeBatchByIds(CollUtil.toList(ids));
- return Boolean.TRUE;
- }
-
- /**
- * 导入角色
- *
- * @param excelVOList
- * @param bindingResult
- * @return
- */
- @Override
- public R importRole(List excelVOList, BindingResult bindingResult) {
- // 通用校验获取失败的数据
- List errorMessageList = (List) bindingResult.getTarget();
-
- // 个性化校验逻辑
- List roleList = this.list();
-
- // 执行数据插入操作 组装 RoleDto
- for (AppRoleExcelVO excel : excelVOList) {
- Set errorMsg = new HashSet<>();
- // 检验角色名称或者角色编码是否存在
- boolean existRole = roleList.stream()
- .anyMatch(appRole -> excel.getRoleName().equals(appRole.getRoleName())
- || excel.getRoleCode().equals(appRole.getRoleCode()));
-
- if (existRole) {
- errorMsg.add(MsgUtils.getMessage(AppErrorCodes.APP_ROLE_NAMEORCODE_EXISTING, excel.getRoleName(),
- excel.getRoleCode()));
- }
-
- // 数据合法情况
- if (CollUtil.isEmpty(errorMsg)) {
- insertExcelRole(excel);
- } else {
- // 数据不合法情况
- errorMessageList.add(new ErrorMessage(excel.getLineNum(), errorMsg));
- }
- }
- if (CollUtil.isNotEmpty(errorMessageList)) {
- return R.failed(errorMessageList);
- }
- return R.ok();
-
- }
-
- private void insertExcelRole(AppRoleExcelVO excel) {
- AppRole appRole = new AppRole();
- appRole.setRoleName(excel.getRoleName());
- appRole.setRoleDesc(excel.getRoleDesc());
- appRole.setRoleCode(excel.getRoleCode());
- this.save(appRole);
- }
-
-}
diff --git a/pigx-app-server/pigx-app-server-biz/src/main/java/com/pig4cloud/pigx/app/service/impl/AppRoleTabbarServiceImpl.java b/pigx-app-server/pigx-app-server-biz/src/main/java/com/pig4cloud/pigx/app/service/impl/AppRoleTabbarServiceImpl.java
new file mode 100644
index 000000000..e0c8a56a7
--- /dev/null
+++ b/pigx-app-server/pigx-app-server-biz/src/main/java/com/pig4cloud/pigx/app/service/impl/AppRoleTabbarServiceImpl.java
@@ -0,0 +1,83 @@
+package com.pig4cloud.pigx.app.service.impl;
+
+import cn.hutool.core.collection.CollUtil;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.pig4cloud.pigx.app.api.dto.AppRoleTabbarDTO;
+import com.pig4cloud.pigx.app.api.entity.AppRoleTabbar;
+import com.pig4cloud.pigx.app.mapper.AppRoleTabbarMapper;
+import com.pig4cloud.pigx.app.service.AppRoleTabbarService;
+import lombok.RequiredArgsConstructor;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.util.List;
+import java.util.Objects;
+
+/**
+ * App 角色底部导航服务实现。
+ *
+ * 只访问 app-server 本库的 {@code app_role_tabbar}。运行时角色来源由 Spring Security
+ * token authorities 提供,避免 app-server 跨库 join upms 的用户角色表。
+ *
+ * @author lengleng
+ * @date 2026-05-09
+ */
+@Service
+@RequiredArgsConstructor
+public class AppRoleTabbarServiceImpl extends ServiceImpl
+ implements AppRoleTabbarService {
+
+ @Override
+ public List listTabbarIdsByRoleId(Long roleId) {
+ return roleId == null ? List.of() : listTabbarIdsByRoleIds(List.of(roleId));
+ }
+
+ /**
+ * 根据多个角色查询可见 Tabbar。
+ *
+ * 一个用户可能同时拥有多个角色,因此这里会先对角色 ID 去重,再对查询出的 Tabbar ID 去重。
+ *
+ * @param roleIds 系统角色 ID 列表
+ * @return 去重后的 Tabbar ID 列表
+ */
+ @Override
+ public List listTabbarIdsByRoleIds(List roleIds) {
+ if (CollUtil.isEmpty(roleIds)) {
+ return List.of();
+ }
+ List distinctRoleIds = roleIds.stream().filter(Objects::nonNull).distinct().toList();
+ if (CollUtil.isEmpty(distinctRoleIds)) {
+ return List.of();
+ }
+ return this.list(Wrappers.lambdaQuery().in(AppRoleTabbar::getRoleId, distinctRoleIds))
+ .stream()
+ .map(AppRoleTabbar::getTabbarId)
+ .filter(Objects::nonNull)
+ .distinct()
+ .toList();
+ }
+
+ @Override
+ @Transactional(rollbackFor = Exception.class)
+ public Boolean saveRoleTabbars(AppRoleTabbarDTO dto) {
+ // 覆盖保存:后台每次提交的是该角色完整授权结果,先删旧关系再写新关系。
+ this.remove(Wrappers.lambdaQuery().eq(AppRoleTabbar::getRoleId, dto.getRoleId()));
+ if (CollUtil.isEmpty(dto.getTabbarIds())) {
+ return Boolean.TRUE;
+ }
+ List records = dto.getTabbarIds()
+ .stream()
+ .filter(Objects::nonNull)
+ .distinct()
+ .map(tabbarId -> {
+ AppRoleTabbar roleTabbar = new AppRoleTabbar();
+ roleTabbar.setRoleId(dto.getRoleId());
+ roleTabbar.setTabbarId(tabbarId);
+ return roleTabbar;
+ })
+ .toList();
+ return this.saveBatch(records);
+ }
+
+}
diff --git a/pigx-app-server/pigx-app-server-biz/src/main/java/com/pig4cloud/pigx/app/service/impl/AppSocialDetailsServiceImpl.java b/pigx-app-server/pigx-app-server-biz/src/main/java/com/pig4cloud/pigx/app/service/impl/AppSocialDetailsServiceImpl.java
deleted file mode 100644
index 47b9bd033..000000000
--- a/pigx-app-server/pigx-app-server-biz/src/main/java/com/pig4cloud/pigx/app/service/impl/AppSocialDetailsServiceImpl.java
+++ /dev/null
@@ -1,86 +0,0 @@
-/*
- * Copyright (c) 2018-2026, lengleng All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
- * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * Neither the name of the pig4cloud.com developer nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- * Author: lengleng (wangiegie@gmail.com)
- */
-
-package com.pig4cloud.pigx.app.service.impl;
-
-import com.baomidou.mybatisplus.core.toolkit.StringPool;
-import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
-import com.pig4cloud.pigx.app.api.dto.AppUserInfo;
-import com.pig4cloud.pigx.app.api.entity.AppSocialDetails;
-import com.pig4cloud.pigx.app.api.entity.AppUser;
-import com.pig4cloud.pigx.app.handler.LoginHandler;
-import com.pig4cloud.pigx.app.mapper.AppSocialDetailsMapper;
-import com.pig4cloud.pigx.app.mapper.AppUserMapper;
-import com.pig4cloud.pigx.app.service.AppSocialDetailsService;
-import com.pig4cloud.pigx.common.core.constant.CacheConstants;
-import com.pig4cloud.pigx.common.security.util.SecurityUtils;
-import lombok.AllArgsConstructor;
-import lombok.extern.slf4j.Slf4j;
-import org.springframework.cache.CacheManager;
-import org.springframework.stereotype.Service;
-
-import java.util.Map;
-
-/**
- * @author lengleng
- * @date 2018年08月16日
- */
-@Slf4j
-@AllArgsConstructor
-@Service("appSocialDetailsService")
-public class AppSocialDetailsServiceImpl extends ServiceImpl
- implements AppSocialDetailsService {
-
- private final Map loginHandlerMap;
-
- private final CacheManager cacheManager;
-
- private final AppUserMapper appUserMapper;
-
- /**
- * 绑定社交账号
- * @param type type
- * @param code code
- * @return
- */
- @Override
- public Boolean bindSocial(String type, String code) {
- LoginHandler loginHandler = loginHandlerMap.get(type);
- // 绑定逻辑
- String identify = loginHandler.identify(code);
- AppUser user = appUserMapper.selectById(SecurityUtils.getUser().getId());
- loginHandler.bind(user, identify);
-
- // 更新緩存
- cacheManager.getCache(CacheConstants.USER_DETAILS_MINI).evict(user.getUsername());
- return Boolean.TRUE;
- }
-
- /**
- * 根据入参查询用户信息
- * @param inStr TYPE@code
- * @return
- */
- @Override
- public AppUserInfo getUserInfo(String inStr) {
- String[] inStrs = inStr.split(StringPool.AT);
- String type = inStrs[0];
- String loginStr = inStr.substring(type.length() + 1);
- return loginHandlerMap.get(type).handle(loginStr);
- }
-
-}
diff --git a/pigx-app-server/pigx-app-server-biz/src/main/java/com/pig4cloud/pigx/app/service/impl/AppUserRoleServiceImpl.java b/pigx-app-server/pigx-app-server-biz/src/main/java/com/pig4cloud/pigx/app/service/impl/AppUserRoleServiceImpl.java
deleted file mode 100644
index 0eeab146e..000000000
--- a/pigx-app-server/pigx-app-server-biz/src/main/java/com/pig4cloud/pigx/app/service/impl/AppUserRoleServiceImpl.java
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Copyright (c) 2018-2026, lengleng All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
- * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * Neither the name of the pig4cloud.com developer nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- * Author: lengleng (wangiegie@gmail.com)
- */
-package com.pig4cloud.pigx.app.service.impl;
-
-import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
-import com.pig4cloud.pigx.app.api.entity.AppUserRole;
-import com.pig4cloud.pigx.app.mapper.AppUserRoleMapper;
-import com.pig4cloud.pigx.app.service.AppUserRoleService;
-import org.springframework.stereotype.Service;
-
-/**
- * 用户角色表
- *
- * @author aeizzz
- * @date 2022-12-07 09:52:03
- */
-@Service
-public class AppUserRoleServiceImpl extends ServiceImpl implements AppUserRoleService {
-
-}
diff --git a/pigx-app-server/pigx-app-server-biz/src/main/java/com/pig4cloud/pigx/app/service/impl/AppUserServiceImpl.java b/pigx-app-server/pigx-app-server-biz/src/main/java/com/pig4cloud/pigx/app/service/impl/AppUserServiceImpl.java
deleted file mode 100644
index 1ecccb968..000000000
--- a/pigx-app-server/pigx-app-server-biz/src/main/java/com/pig4cloud/pigx/app/service/impl/AppUserServiceImpl.java
+++ /dev/null
@@ -1,409 +0,0 @@
-/*
- * Copyright (c) 2018-2026, lengleng All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
- * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * Neither the name of the pig4cloud.com developer nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- * Author: lengleng (wangiegie@gmail.com)
- */
-package com.pig4cloud.pigx.app.service.impl;
-
-import cn.hutool.core.collection.CollUtil;
-import cn.hutool.core.util.ArrayUtil;
-import cn.hutool.core.util.StrUtil;
-import com.baomidou.mybatisplus.core.metadata.IPage;
-import com.baomidou.mybatisplus.core.toolkit.StringPool;
-import com.baomidou.mybatisplus.core.toolkit.Wrappers;
-import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
-import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
-import com.pig4cloud.pigx.app.api.dto.AppUserDTO;
-import com.pig4cloud.pigx.app.api.dto.AppUserInfo;
-import com.pig4cloud.pigx.app.api.entity.AppRole;
-import com.pig4cloud.pigx.app.api.entity.AppUser;
-import com.pig4cloud.pigx.app.api.entity.AppUserRole;
-import com.pig4cloud.pigx.app.api.enums.AppErrorCodes;
-import com.pig4cloud.pigx.app.api.vo.AppUserExcelVO;
-import com.pig4cloud.pigx.app.api.vo.AppUserVO;
-import com.pig4cloud.pigx.app.mapper.AppUserMapper;
-import com.pig4cloud.pigx.app.service.AppRoleService;
-import com.pig4cloud.pigx.app.service.AppUserRoleService;
-import com.pig4cloud.pigx.app.service.AppUserService;
-import com.pig4cloud.pigx.common.core.constant.CacheConstants;
-import com.pig4cloud.pigx.common.core.constant.CommonConstants;
-import com.pig4cloud.pigx.common.core.constant.enums.LoginTypeEnum;
-import com.pig4cloud.pigx.common.core.constant.enums.UserTypeEnum;
-import com.pig4cloud.pigx.common.core.util.MsgUtils;
-import com.pig4cloud.pigx.common.core.util.R;
-import com.pig4cloud.pigx.common.data.cache.RedisUtils;
-import com.pig4cloud.pigx.common.excel.vo.ErrorMessage;
-import com.pig4cloud.pigx.common.security.service.PigxUser;
-import com.pig4cloud.pigx.common.security.util.SecurityUtils;
-import lombok.AllArgsConstructor;
-import lombok.extern.slf4j.Slf4j;
-import org.springframework.beans.BeanUtils;
-import org.springframework.cache.Cache;
-import org.springframework.cache.CacheManager;
-import org.springframework.cache.annotation.CacheEvict;
-import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
-import org.springframework.security.crypto.password.PasswordEncoder;
-import org.springframework.stereotype.Service;
-import org.springframework.validation.BindingResult;
-
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
-
-/**
- * app用户表服务实现类
- *
- * @author aeizzz
- * @date 2022-12-07 09:52:03
- */
-@Service
-@AllArgsConstructor
-@Slf4j
-public class AppUserServiceImpl extends ServiceImpl implements AppUserService {
-
- /**
- * 密码编码器,用于密码加密
- */
- private static final PasswordEncoder ENCODER = new BCryptPasswordEncoder();
-
- /**
- * 用户角色关联服务
- */
- private final AppUserRoleService appUserRoleService;
-
- /**
- * 角色服务
- */
- private final AppRoleService appRoleService;
-
- /**
- * 缓存管理器
- */
- private final CacheManager cacheManager;
-
-
- /**
- * 更新用户信息
- *
- * @param userDTO 用户数据传输对象
- * @return 更新结果
- */
- @Override
- @CacheEvict(value = CacheConstants.USER_DETAILS_MINI, key = "#userDTO.username")
- public Boolean updateUser(AppUserDTO userDTO) {
- // 创建用户实体并复制属性
- AppUser appUser = new AppUser();
- BeanUtils.copyProperties(userDTO, appUser);
-
- // 如果密码不为空,进行加密处理
- if (StrUtil.isNotBlank(userDTO.getPassword())) {
- appUser.setPassword(ENCODER.encode(userDTO.getPassword()));
- }
- // 更新用户基本信息
- this.updateById(appUser);
-
- // 删除用户与角色的关联关系
- appUserRoleService.remove(Wrappers.lambdaQuery().eq(AppUserRole::getUserId, appUser.getUserId()));
- // 重新建立用户与角色的关联关系
- userDTO.getRole().forEach(roleId -> {
- AppUserRole appUserRole = new AppUserRole();
- appUserRole.setRoleId(roleId);
- appUserRole.setUserId(userDTO.getUserId());
- appUserRole.insert();
- });
-
- // 清除以手机号为key的用户缓存
- AppUser appUserInfo = baseMapper.selectById(userDTO.getUserId());
- cacheManager.getCache(CacheConstants.USER_DETAILS_MINI).evict(appUserInfo.getPhone());
- return Boolean.TRUE;
- }
-
- /**
- * 新增用户
- *
- * @param userDTO 用户数据传输对象
- * @return 保存结果
- */
- @Override
- public Boolean saveUser(AppUserDTO userDTO) {
- // 创建用户实体并复制属性
- AppUser appUser = new AppUser();
- BeanUtils.copyProperties(userDTO, appUser);
- // 设置删除标志为正常状态
- appUser.setDelFlag(CommonConstants.STATUS_NORMAL);
- // 对密码进行加密
- appUser.setPassword(ENCODER.encode(userDTO.getPassword()));
- // 插入用户记录
- baseMapper.insert(appUser);
-
- // 如果角色列表不为空,建立用户与角色的关联关系
- if (CollUtil.isNotEmpty(userDTO.getRole())) {
- List userRoleList = userDTO.getRole().stream().map(roleId -> {
- AppUserRole userRole = new AppUserRole();
- userRole.setUserId(appUser.getUserId());
- userRole.setRoleId(roleId);
- return userRole;
- }).toList();
- // 批量保存用户角色关联
- appUserRoleService.saveBatch(userRoleList);
- }
- return Boolean.TRUE;
- }
-
- /**
- * 查询全部用户(用于Excel导出)
- *
- * @param appUser 查询条件
- * @return 用户Excel视图对象列表
- */
- @Override
- public List listUser(AppUserDTO appUser) {
- // 查询所有用户
- List appUsers = baseMapper.selectList(null);
- // 将用户实体转换为Excel视图对象
- List appUserExcelVOS = appUsers.stream().map(item -> {
- AppUserExcelVO appUserExcelVO = new AppUserExcelVO();
- BeanUtils.copyProperties(item, appUserExcelVO);
- return appUserExcelVO;
- }).toList();
- return appUserExcelVOS;
- }
-
- /**
- * 分页查询用户(包含角色信息)
- *
- * @param page 分页参数
- * @param appUserDTO 查询条件
- * @return 分页结果
- */
- @Override
- public IPage getUsersWithRolePage(Page page, AppUserDTO appUserDTO) {
- return baseMapper.getUserVosPage(page, appUserDTO);
- }
-
- /**
- * 查询用户详细信息(包含角色和权限)
- *
- * @param user 用户对象
- * @return 用户信息对象
- */
- @Override
- public AppUserInfo findUserInfo(AppUser user) {
- // 创建用户信息对象
- AppUserInfo info = new AppUserInfo();
- info.setAppUser(user);
-
- // 设置角色列表(ID数组)
- List roleIds = appRoleService.findRolesByUserId(user.getUserId())
- .stream()
- .map(AppRole::getRoleId)
- .toList();
- info.setRoles(ArrayUtil.toArray(roleIds, Long.class));
-
- // 设置权限列表(暂为空)
- Set permissions = new HashSet<>();
- info.setPermissions(ArrayUtil.toArray(permissions, String.class));
- return info;
- }
-
- /**
- * 更新用户个人信息
- *
- * @param userDTO 用户数据传输对象
- * @return 操作结果
- */
- @Override
- @CacheEvict(value = CacheConstants.USER_DETAILS_MINI, key = "#userDTO.username")
- public R updateUserInfo(AppUserDTO userDTO) {
- // 获取当前登录用户
- PigxUser user = SecurityUtils.getUser();
-
- // C端客户修改手机号需要验证短信验证码
- if (UserTypeEnum.TOC.getStatus().equals(user.getUserType()) && StrUtil.isNotBlank(userDTO.getPhone())) {
- // 构建验证码缓存key
- String key = CacheConstants.DEFAULT_CODE_KEY + LoginTypeEnum.APPSMS.getType() + StringPool.AT
- + userDTO.getPhone();
- // 获取缓存中的验证码
- String codeObj = RedisUtils.get(key);
-
- // 验证码不匹配,返回错误
- if (!userDTO.getMobileCode().equals(codeObj)) {
- return R.failed("验证码错误");
- }
- }
-
- // 更新密码(如果提供了新密码)
- if (StrUtil.isNotBlank(userDTO.getPassword())) {
- userDTO.setPassword(ENCODER.encode(userDTO.getPassword()));
- }
-
- // 获取原用户信息并更新
- AppUser appUser = baseMapper.selectById(userDTO.getUserId());
- BeanUtils.copyProperties(userDTO, appUser);
-
- // 清除以手机号为key的用户缓存
- cacheManager.getCache(CacheConstants.USER_DETAILS_MINI).evict(user.getPhone());
- return R.ok(this.updateById(appUser));
- }
-
- /**
- * 根据用户ID查询用户视图对象
- *
- * @param userId 用户ID
- * @return 用户视图对象
- */
- @Override
- public AppUserVO selectUserVoById(Long userId) {
- return baseMapper.getUserVoById(userId);
- }
-
- /**
- * 批量删除用户
- *
- * @param ids 用户ID数组
- * @return 删除结果
- */
- @Override
- public Boolean deleteAppUserByIds(Long[] ids) {
- // 获取缓存对象
- Cache cache = cacheManager.getCache(CacheConstants.USER_DETAILS_MINI);
- // 清除用户缓存
- for (AppUser appUser : baseMapper.selectByIds(CollUtil.toList(ids))) {
- cache.evict(appUser.getUsername());
- }
-
- // 删除用户角色关联关系
- this.appUserRoleService
- .remove(Wrappers.lambdaQuery().in(AppUserRole::getUserId, CollUtil.toList(ids)));
-
- // 删除用户记录
- this.removeBatchByIds(CollUtil.toList(ids));
-
- return Boolean.TRUE;
- }
-
- /**
- * 注册APP用户
- *
- * @param appUser 用户数据传输对象
- * @return 操作结果
- */
- @Override
- public R registerAppUser(AppUserDTO appUser) {
- // 检查手机号是否已被注册
- List appUserList = baseMapper
- .selectList(Wrappers.lambdaQuery().eq(AppUser::getPhone, appUser.getPhone()));
-
- if (CollUtil.isNotEmpty(appUserList)) {
- return R.failed("手机号已注册,请使用验证码直接登录");
- }
-
- // 验证短信验证码
- String key = CacheConstants.DEFAULT_CODE_KEY + LoginTypeEnum.APPSMS.getType() + StringPool.AT
- + appUser.getPhone();
- String codeObj = RedisUtils.get(key);
-
- if (!appUser.getMobileCode().equals(codeObj)) {
- return R.failed("验证码错误");
- }
-
- // 创建用户并保存
- AppUser app = new AppUser();
- BeanUtils.copyProperties(appUser, app);
- appUser.setUsername(app.getPhone()); // 默认使用手机号作为用户名
- appUser.setDelFlag(CommonConstants.STATUS_NORMAL);
- appUser.setPassword(ENCODER.encode(appUser.getPassword()));
- baseMapper.insert(appUser);
- return null;
- }
-
- /**
- * 导入用户(从Excel导入)
- *
- * @param excelVOList Excel数据列表
- * @param bindingResult 数据校验结果
- * @return 导入结果
- */
- @Override
- public R importUser(List excelVOList, BindingResult bindingResult) {
- // 获取通用校验失败的数据
- List errorMessageList = (List) bindingResult.getTarget();
-
- // 获取现有用户和角色列表,用于校验
- List userList = this.list();
- List roleList = appRoleService.list();
-
- // 遍历Excel数据进行处理
- for (AppUserExcelVO excel : excelVOList) {
- Set errorMsg = new HashSet<>();
-
- // 校验用户名是否已存在
- boolean exsitUserName = userList.stream()
- .anyMatch(sysUser -> excel.getUsername().equals(sysUser.getUsername()));
-
- if (exsitUserName) {
- errorMsg.add(MsgUtils.getMessage(AppErrorCodes.APP_USER_USERNAME_EXISTING, excel.getUsername()));
- }
-
- // 校验角色名称是否合法
- List roleNameList = StrUtil.split(excel.getRoleNameList(), StrUtil.COMMA);
- List roleCollList = roleList.stream()
- .filter(role -> roleNameList.stream().anyMatch(name -> role.getRoleName().equals(name)))
- .toList();
-
- if (roleCollList.size() != roleNameList.size()) {
- errorMsg.add(MsgUtils.getMessage(AppErrorCodes.APP_ROLE_ROLENAME_INEXISTENCE, excel.getRoleNameList()));
- }
-
- // 数据合法时执行插入
- if (CollUtil.isEmpty(errorMsg)) {
- insertExcelUser(excel, roleCollList);
- } else {
- // 记录不合法数据的错误信息
- errorMessageList.add(new ErrorMessage(excel.getLineNum(), errorMsg));
- }
- }
-
- // 存在错误信息时返回失败
- if (CollUtil.isNotEmpty(errorMessageList)) {
- return R.failed(errorMessageList);
- }
- return R.ok(null, MsgUtils.getMessage(AppErrorCodes.APP_USER_IMPORT_SUCCEED));
- }
-
- /**
- * 插入Excel导入的用户数据
- *
- * @param excel Excel用户数据
- * @param roleCollList 角色列表
- */
- private void insertExcelUser(AppUserExcelVO excel, List roleCollList) {
- // 创建用户DTO并设置基本信息
- AppUserDTO userDTO = new AppUserDTO();
- userDTO.setUsername(excel.getUsername());
- userDTO.setPhone(excel.getPhone());
- userDTO.setNickname(excel.getNickname());
- userDTO.setName(excel.getName());
- userDTO.setEmail(excel.getEmail());
- // 批量导入时初始密码设置为手机号
- userDTO.setPassword(userDTO.getPhone());
-
- // 获取角色ID列表
- List roleIdList = roleCollList.stream().map(AppRole::getRoleId).toList();
- userDTO.setRole(roleIdList);
-
- // 保存用户
- this.saveUser(userDTO);
- }
-}
diff --git a/pigx-app-server/pigx-app-server-biz/src/main/resources/mapper/AppContactsMapper.xml b/pigx-app-server/pigx-app-server-biz/src/main/resources/mapper/AppContactsMapper.xml
new file mode 100644
index 000000000..087737f2a
--- /dev/null
+++ b/pigx-app-server/pigx-app-server-biz/src/main/resources/mapper/AppContactsMapper.xml
@@ -0,0 +1,18 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/pigx-app-server/pigx-app-server-biz/src/main/resources/mapper/AppRoleMapper.xml b/pigx-app-server/pigx-app-server-biz/src/main/resources/mapper/AppRoleMapper.xml
deleted file mode 100644
index e00f6c9e0..000000000
--- a/pigx-app-server/pigx-app-server-biz/src/main/resources/mapper/AppRoleMapper.xml
+++ /dev/null
@@ -1,52 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- SELECT app_role.role_id,
- app_role.role_name,
- app_role.role_code,
- app_role.role_desc,
- app_role.create_time,
- app_role.update_time,
- app_role.del_flag
- FROM app_role,
- app_user_role
- WHERE app_role.role_id = app_user_role.role_id
- AND app_role.del_flag = '0'
- and app_user_role.user_id = #{userId}
-
-
diff --git a/pigx-app-server/pigx-app-server-biz/src/main/resources/mapper/AppTabbarMapper.xml b/pigx-app-server/pigx-app-server-biz/src/main/resources/mapper/AppTabbarMapper.xml
index 5b10e6e20..e6f7790c1 100644
--- a/pigx-app-server/pigx-app-server-biz/src/main/resources/mapper/AppTabbarMapper.xml
+++ b/pigx-app-server/pigx-app-server-biz/src/main/resources/mapper/AppTabbarMapper.xml
@@ -9,6 +9,8 @@
+
+
diff --git a/pigx-app-server/pigx-app-server-biz/src/main/resources/mapper/AppUserMapper.xml b/pigx-app-server/pigx-app-server-biz/src/main/resources/mapper/AppUserMapper.xml
deleted file mode 100644
index efbf1aec7..000000000
--- a/pigx-app-server/pigx-app-server-biz/src/main/resources/mapper/AppUserMapper.xml
+++ /dev/null
@@ -1,97 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- select
- u.user_id,
- u.username,
- u.password,
- u.phone,
- u.avatar,
- u.create_time,
- u.del_flag,
- u.lock_flag,
- u.tenant_id,
- u.nickname,
- u.name,
- u.email
- from app_user u
-
- u.del_flag = '0'
-
-
- AND u.username LIKE #{usernameLike}
-
-
-
-
-
- u.user_id,
- u.username,
- u.password,
- u.salt,
- u.phone,
- u.avatar,
- u.wx_openid,
- u.del_flag,
- u.lock_flag,
- u.tenant_id,
- u.nickname,
- u.name,
- u.email,
- u.create_by,
- u.create_time ucreate_time,
- u.update_time uupdate_time,
- r.role_id
-
-
-
- SELECT
-
- FROM
- app_user u
- LEFT JOIN app_user_role urole ON urole.user_id = u.user_id
- LEFT JOIN app_role r ON r.role_id = urole.role_id
- WHERE
- u.user_id = #{id}
-
-
diff --git a/pigx-app-server/pigx-app-server-biz/src/main/resources/mapper/AppUserRoleMapper.xml b/pigx-app-server/pigx-app-server-biz/src/main/resources/mapper/AppUserRoleMapper.xml
deleted file mode 100644
index 340e33883..000000000
--- a/pigx-app-server/pigx-app-server-biz/src/main/resources/mapper/AppUserRoleMapper.xml
+++ /dev/null
@@ -1,30 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-