“mitao”
2026-02-14 d0d5b3d82bf8b2a416a92dd817f22f4ec3fc2d64
feat(app):个人中心、消息通知接口
12个文件已添加
15个文件已修改
623 ■■■■■ 已修改文件
xp-robotaxi-account-boot/src/main/java/com/xiaopeng/account/controller/SysGroupMenuController.java 35 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-account-boot/src/main/java/com/xiaopeng/account/controller/XpOperationsUserController.java 14 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-account-boot/src/main/java/com/xiaopeng/account/controller/XpOperationsUserNotificationController.java 50 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-account-boot/src/main/java/com/xiaopeng/account/mapper/XpOperationsUserNotificationMapper.java 13 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-account-boot/src/main/java/com/xiaopeng/account/model/dto/XpOperationsUserDTO.java 47 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-account-boot/src/main/java/com/xiaopeng/account/model/query/XpOperationsUserNotificationPageQuery.java 19 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-account-boot/src/main/java/com/xiaopeng/account/model/vo/SysGroupDetailVO.java 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-account-boot/src/main/java/com/xiaopeng/account/service/IXpOperationsUserNotificationService.java 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-account-boot/src/main/java/com/xiaopeng/account/service/IXpOperationsUserService.java 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-account-boot/src/main/java/com/xiaopeng/account/service/impl/SysGroupServiceImpl.java 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-account-boot/src/main/java/com/xiaopeng/account/service/impl/XpOperationsUserNotificationServiceImpl.java 30 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-account-boot/src/main/java/com/xiaopeng/account/service/impl/XpOperationsUserServiceImpl.java 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-account-boot/src/main/resources/mapper/account/XpOperationsUserNotificationMapper.xml 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-api/src/main/java/com/xiaopeng/api/factory/account/SysGroupMenuClientFallbackFactory.java 31 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-api/src/main/java/com/xiaopeng/api/feignClient/account/SysGroupMenuClient.java 29 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-api/src/main/java/com/xiaopeng/api/model/operation/XpAppVersion.java 41 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-api/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-operation-boot/src/main/java/com/xiaopeng/operation/controller/XpAgreementController.java 19 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-operation-boot/src/main/java/com/xiaopeng/operation/controller/XpAppVersionController.java 41 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-operation-boot/src/main/java/com/xiaopeng/operation/controller/XpSystemSettingController.java 19 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-operation-boot/src/main/java/com/xiaopeng/operation/mapper/XpAppVersionMapper.java 14 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-operation-boot/src/main/java/com/xiaopeng/operation/service/IXpAppVersionService.java 20 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-operation-boot/src/main/java/com/xiaopeng/operation/service/impl/SysMenuServiceImpl.java 78 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-operation-boot/src/main/java/com/xiaopeng/operation/service/impl/XpAppVersionServiceImpl.java 43 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-operation-boot/src/main/java/com/xiaopeng/operation/vo/XpAgreementVo.java 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-operation-boot/src/main/java/com/xiaopeng/operation/vo/XpAppVersionVO.java 28 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-operation-boot/src/main/resources/mapper/operation/XpAppVersionMapper.xml 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-account-boot/src/main/java/com/xiaopeng/account/controller/SysGroupMenuController.java
New file
@@ -0,0 +1,35 @@
package com.xiaopeng.account.controller;
import com.xiaopeng.account.service.ISysGroupMenuService;
import com.xiaopeng.common.core.domain.R;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.List;
/**
 * 权限组菜单关联 Controller
 */
@Slf4j
@RestController
@RequestMapping("")
@Api(tags = "权限组菜单管理")
public class SysGroupMenuController {
    @Autowired
    private ISysGroupMenuService sysGroupMenuService;
    /**
     * 根据权限组ID查询菜单ID列表(内部接口)
     */
    @PostMapping("/groupMenu/selectMenuIdsByGroupId")
    @ApiOperation(value = "根据权限组ID查询菜单ID列表", tags = {"内部接口"})
    public R<List<Long>> selectMenuIdsByGroupId(@RequestParam("groupId") Long groupId) {
        log.info("查询权限组菜单ID列表, groupId={}", groupId);
        List<Long> menuIds = sysGroupMenuService.selectMenuIdsByGroupId(groupId);
        return R.ok(menuIds);
    }
}
xp-robotaxi-account-boot/src/main/java/com/xiaopeng/account/controller/XpOperationsUserController.java
@@ -2,6 +2,7 @@
import com.xiaopeng.account.mapper.XpOperationsRoleMapper;
import com.xiaopeng.account.model.dto.XpOperationsUserDTO;
import com.xiaopeng.account.model.query.XpOperationsUserPageQuery;
import com.xiaopeng.account.service.IXpOperationsUserService;
import com.xiaopeng.api.dto.account.XpOperationsUserQueryDTO;
@@ -16,6 +17,7 @@
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.*;
import javax.validation.Valid;
import java.util.ArrayList;
import java.util.List;
@@ -130,4 +132,16 @@
        return R.ok(profile);
    }
    /**
     * 运维APP-个人中心-证件上传
     * @param dto
     * @return
     */
    @ApiOperation(value = "个人中心-证件上传", tags = {"运维APP-个人中心"})
    @PostMapping("/api/v1/saveCertificate")
    public R<?> saveCertificate(@Valid @RequestBody XpOperationsUserDTO dto){
        xpOperationsUserService.saveCertificate(dto);
        return R.ok();
    }
}
xp-robotaxi-account-boot/src/main/java/com/xiaopeng/account/controller/XpOperationsUserNotificationController.java
@@ -1,9 +1,17 @@
package com.xiaopeng.account.controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.stereotype.Controller;
import com.xiaopeng.account.model.query.XpOperationsUserNotificationPageQuery;
import com.xiaopeng.account.service.IXpOperationsUserNotificationService;
import com.xiaopeng.api.model.account.XpOperationsUserNotification;
import com.xiaopeng.common.core.domain.R;
import com.xiaopeng.common.core.web.page.PageInfo;
import com.xiaopeng.common.security.service.TokenService;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
/**
 * <p>
@@ -13,8 +21,38 @@
 * @author mitao
 * @since 2026-02-03
 */
@Controller
@RequestMapping("/xp-operations-user-notification")
@Slf4j
@RestController
public class XpOperationsUserNotificationController {
    @Autowired
    private IXpOperationsUserNotificationService notificationService;
    @Autowired
    private TokenService tokenService;
    /**
     * 根据当前登录用户获取通知分页列表(运维APP接口)
     */
    @PostMapping("/api/v1/notification/list")
    @ApiOperation(value = "获取通知分页列表", tags = {"运维APP-消息通知"})
    public R<PageInfo<XpOperationsUserNotification>> getNotificationList(
            @RequestBody XpOperationsUserNotificationPageQuery query) {
        log.info("查询通知分页列表, pageNum={}, pageSize={}",
            query.getPageNum(), query.getPageSize());
        // 从Token中获取当前登录用户ID
        Long currentUserId = tokenService.getLoginOperationUser().getId();
        query.setOperationsUserId(currentUserId);
        // 查询分页列表
        PageInfo<XpOperationsUserNotification> pageInfo =
            notificationService.selectNotificationPageByUserId(query);
        log.info("查询通知分页列表成功, userId={}, total={}",
            currentUserId, pageInfo.getTotal());
        return R.ok(pageInfo);
    }
}
xp-robotaxi-account-boot/src/main/java/com/xiaopeng/account/mapper/XpOperationsUserNotificationMapper.java
@@ -1,7 +1,10 @@
package com.xiaopeng.account.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.xiaopeng.account.model.query.XpOperationsUserNotificationPageQuery;
import com.xiaopeng.api.model.account.XpOperationsUserNotification;
import org.apache.ibatis.annotations.Param;
/**
 * <p>
@@ -13,4 +16,14 @@
 */
public interface XpOperationsUserNotificationMapper extends BaseMapper<XpOperationsUserNotification> {
    /**
     * 分页查询用户通知列表
     * @param page 分页对象
     * @param query 查询条件
     * @return 通知分页列表
     */
    Page<XpOperationsUserNotification> selectNotificationPageByUserId(
        Page<XpOperationsUserNotification> page,
        @Param("query") XpOperationsUserNotificationPageQuery query
    );
}
xp-robotaxi-account-boot/src/main/java/com/xiaopeng/account/model/dto/XpOperationsUserDTO.java
New file
@@ -0,0 +1,47 @@
package com.xiaopeng.account.model.dto;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
/**
 * @author MiTao
 * @date 2026-02-14 19:27
 *
 */
@Data
@ApiModel(value = "运维人员数据传输对象")
public class XpOperationsUserDTO {
    @ApiModelProperty(value = "ID")
    @NotNull(message = "id不能为空")
    private Long id;
    @NotBlank(message = "身份证正面不能为空")
    @ApiModelProperty(value = "身份证正面", notes = "格式:{\"id\":\"1\",\"name\":\"头像.jpg\",\"url\":\"\n" +
            "https://pss.bdstatic.com/static/superman/img/topnav/newfanyi-da0cea8f7e.png\"}")
    private String idCardFront;
    @NotBlank(message = "身份证背面不能为空")
    @ApiModelProperty(value = "身份证背面", notes = "格式:{\\\"id\\\":\\\"1\\\",\\\"name\\\":\\\"头像.jpg\\\",\\\"url\\\":\\\"\\n\" +\n" +
            "            \"https://pss.bdstatic.com/static/superman/img/topnav/newfanyi-da0cea8f7e.png\\\"}")
    private String idCardBack;
    @NotBlank(message = "驾驶证正面不能为空")
    @ApiModelProperty(value = "驾驶证正面",notes =  "格式:{\\\"id\\\":\\\"1\\\",\\\"name\\\":\\\"头像.jpg\\\",\\\"url\\\":\\\"\\n\" +\n" +
            "            \"https://pss.bdstatic.com/static/superman/img/topnav/newfanyi-da0cea8f7e.png\\\"}")
    private String driverLicense;
    @NotBlank(message = "无犯罪记录证明不能为空")
    @ApiModelProperty(value = "无犯罪记录",notes =  "格式:{\\\"id\\\":\\\"1\\\",\\\"name\\\":\\\"头像.jpg\\\",\\\"url\\\":\\\"\\n\" +\n" +
            "            \"https://pss.bdstatic.com/static/superman/img/topnav/newfanyi-da0cea8f7e.png\\\"}")
    private String certificateOfNoCriminalRecord;
    @NotBlank(message = "培训结业证不能为空")
    @ApiModelProperty(value = "培训结业证", notes = "格式:{\\\"id\\\":\\\"1\\\",\\\"name\\\":\\\"头像.jpg\\\",\\\"url\\\":\\\"\\n\" +\n" +
            "            \"https://pss.bdstatic.com/static/superman/img/topnav/newfanyi-da0cea8f7e.png\\\"}")
    private String trainingGraduationCertificate;
}
xp-robotaxi-account-boot/src/main/java/com/xiaopeng/account/model/query/XpOperationsUserNotificationPageQuery.java
New file
@@ -0,0 +1,19 @@
package com.xiaopeng.account.model.query;
import com.xiaopeng.common.core.web.page.BasePage;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
 * 运维人员通知分页查询条件
 */
@Data
@EqualsAndHashCode(callSuper = true)
@ApiModel("运维人员通知分页查询条件")
public class XpOperationsUserNotificationPageQuery extends BasePage {
    @ApiModelProperty(value = "运维人员ID(由后端自动填充,前端无需传递)")
    private Long operationsUserId;
}
xp-robotaxi-account-boot/src/main/java/com/xiaopeng/account/model/vo/SysGroupDetailVO.java
@@ -29,4 +29,7 @@
    @ApiModelProperty(value = "菜单列表")
    private List<SysMenuVO> menus;
    @ApiModelProperty(value = "菜单列表")
    private List<Long> menuIds;
}
xp-robotaxi-account-boot/src/main/java/com/xiaopeng/account/service/IXpOperationsUserNotificationService.java
@@ -1,7 +1,9 @@
package com.xiaopeng.account.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.xiaopeng.account.model.query.XpOperationsUserNotificationPageQuery;
import com.xiaopeng.api.model.account.XpOperationsUserNotification;
import com.xiaopeng.common.core.web.page.PageInfo;
/**
 * <p>
@@ -13,4 +15,12 @@
 */
public interface IXpOperationsUserNotificationService extends IService<XpOperationsUserNotification> {
    /**
     * 分页查询用户通知列表
     * @param query 查询条件
     * @return 通知分页列表
     */
    PageInfo<XpOperationsUserNotification> selectNotificationPageByUserId(
        XpOperationsUserNotificationPageQuery query
    );
}
xp-robotaxi-account-boot/src/main/java/com/xiaopeng/account/service/IXpOperationsUserService.java
@@ -1,12 +1,14 @@
package com.xiaopeng.account.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.xiaopeng.account.model.dto.XpOperationsUserDTO;
import com.xiaopeng.account.model.query.XpOperationsUserPageQuery;
import com.xiaopeng.api.model.account.XpOperationsUser;
import com.xiaopeng.api.vo.account.XpOperationsUserProfileVO;
import com.xiaopeng.api.vo.account.XpOperationsUserWithRoleVO;
import com.xiaopeng.common.core.web.page.PageInfo;
import javax.validation.Valid;
import java.util.List;
/**
@@ -39,4 +41,10 @@
     * @return 个人中心首页信息
     */
    XpOperationsUserProfileVO getUserProfile(Long userId);
    /**
     *
     * @param dto
     */
    void saveCertificate(@Valid XpOperationsUserDTO dto);
}
xp-robotaxi-account-boot/src/main/java/com/xiaopeng/account/service/impl/SysGroupServiceImpl.java
@@ -137,8 +137,10 @@
                List<SysMenu> menus = result.getData();
                // 构建菜单树
                vo.setMenus(buildMenuTree(menus));
                vo.setMenuIds(menus.stream().map(SysMenu::getId).collect(Collectors.toList()));
            } else {
                vo.setMenus(new ArrayList<>());
                vo.setMenuIds(new ArrayList<>());
            }
        } catch (Exception e) {
            log.error("获取菜单列表失败: {}", e.getMessage());
xp-robotaxi-account-boot/src/main/java/com/xiaopeng/account/service/impl/XpOperationsUserNotificationServiceImpl.java
@@ -1,9 +1,12 @@
package com.xiaopeng.account.service.impl;
import com.xiaopeng.account.mapper.XpOperationsUserNotificationMapper;
import com.xiaopeng.account.service.IXpOperationsUserNotificationService;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xiaopeng.account.mapper.XpOperationsUserNotificationMapper;
import com.xiaopeng.account.model.query.XpOperationsUserNotificationPageQuery;
import com.xiaopeng.account.service.IXpOperationsUserNotificationService;
import com.xiaopeng.api.model.account.XpOperationsUserNotification;
import com.xiaopeng.common.core.web.page.PageInfo;
import org.springframework.stereotype.Service;
/**
@@ -17,4 +20,27 @@
@Service
public class XpOperationsUserNotificationServiceImpl extends ServiceImpl<XpOperationsUserNotificationMapper, XpOperationsUserNotification> implements IXpOperationsUserNotificationService {
    @Override
    public PageInfo<XpOperationsUserNotification> selectNotificationPageByUserId(
            XpOperationsUserNotificationPageQuery query) {
        // 创建分页对象
        Page<XpOperationsUserNotification> page = new Page<>(
            query.getPageNum(),
            query.getPageSize()
        );
        // 执行分页查询
        Page<XpOperationsUserNotification> resultPage = baseMapper.selectNotificationPageByUserId(
            page,
            query
        );
        // 封装分页结果
        PageInfo<XpOperationsUserNotification> pageInfo = new PageInfo<>();
        pageInfo.setRecords(resultPage.getRecords());
        pageInfo.setTotal(resultPage.getTotal());
        return pageInfo;
    }
}
xp-robotaxi-account-boot/src/main/java/com/xiaopeng/account/service/impl/XpOperationsUserServiceImpl.java
@@ -1,8 +1,10 @@
package com.xiaopeng.account.service.impl;
import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.xiaopeng.account.mapper.XpOperationsRoleMapper;
import com.xiaopeng.account.mapper.XpOperationsUserMapper;
import com.xiaopeng.account.model.dto.XpOperationsUserDTO;
import com.xiaopeng.account.model.query.XpOperationsUserPageQuery;
import com.xiaopeng.account.service.IXpOperationsUserService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
@@ -149,4 +151,10 @@
        return vo;
    }
    @Override
    public void saveCertificate(XpOperationsUserDTO dto) {
        XpOperationsUser xpOperationsUser = BeanUtil.copyProperties(dto, XpOperationsUser.class);
        updateById(xpOperationsUser);
    }
}
xp-robotaxi-account-boot/src/main/resources/mapper/account/XpOperationsUserNotificationMapper.xml
@@ -7,4 +7,15 @@
        id, notification_type, notification_content, operations_user_id, data_id, is_deleted, create_time, update_time, create_by, update_by
    </sql>
    <!-- 分页查询用户通知列表 -->
    <select id="selectNotificationPageByUserId"
            resultType="com.xiaopeng.api.model.account.XpOperationsUserNotification">
        SELECT
            <include refid="Base_Column_List"/>
        FROM xp_operations_user_notification
        WHERE operations_user_id = #{query.operationsUserId}
          AND is_deleted = 0
        ORDER BY create_time DESC
    </select>
</mapper>
xp-robotaxi-api/src/main/java/com/xiaopeng/api/factory/account/SysGroupMenuClientFallbackFactory.java
New file
@@ -0,0 +1,31 @@
package com.xiaopeng.api.factory.account;
import com.xiaopeng.api.feignClient.account.SysGroupMenuClient;
import com.xiaopeng.common.core.domain.R;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.openfeign.FallbackFactory;
import org.springframework.stereotype.Component;
import java.util.Collections;
import java.util.List;
/**
 * 权限组菜单关联服务降级工厂
 */
@Slf4j
@Component
public class SysGroupMenuClientFallbackFactory implements FallbackFactory<SysGroupMenuClient> {
    @Override
    public SysGroupMenuClient create(Throwable cause) {
        return new SysGroupMenuClient() {
            @Override
            public R<List<Long>> selectMenuIdsByGroupId(Long groupId) {
                log.error("调用权限组菜单服务失败, groupId={}, 异常: {}",
                    groupId, cause.getMessage(), cause);
                // 降级策略: 返回空列表
                return R.ok(Collections.emptyList());
            }
        };
    }
}
xp-robotaxi-api/src/main/java/com/xiaopeng/api/feignClient/account/SysGroupMenuClient.java
New file
@@ -0,0 +1,29 @@
package com.xiaopeng.api.feignClient.account;
import com.xiaopeng.api.factory.account.SysGroupMenuClientFallbackFactory;
import com.xiaopeng.common.core.domain.R;
import com.xiaopeng.common.core.dto.ServiceNameConstantsEnum;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import java.util.List;
/**
 * 权限组菜单关联 Feign 客户端
 */
@FeignClient(
    contextId = "SysGroupMenuClient",
    value = ServiceNameConstantsEnum.XP_ACCOUNT_SERVICE,
    fallbackFactory = SysGroupMenuClientFallbackFactory.class
)
public interface SysGroupMenuClient {
    /**
     * 根据权限组ID查询菜单ID列表
     * @param groupId 权限组ID
     * @return 菜单ID列表
     */
    @PostMapping("/groupMenu/selectMenuIdsByGroupId")
    R<List<Long>> selectMenuIdsByGroupId(@RequestParam("groupId") Long groupId);
}
xp-robotaxi-api/src/main/java/com/xiaopeng/api/model/operation/XpAppVersion.java
New file
@@ -0,0 +1,41 @@
package com.xiaopeng.api.model.operation;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.xiaopeng.common.core.web.domain.BaseModel;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
 * App版本管理实体类
 *
 * @author mitao
 * @since 2026-02-14
 */
@Data
@EqualsAndHashCode(callSuper = false)
@TableName("xp_app_version")
@ApiModel(value = "XpAppVersion对象", description = "app版本管理")
public class XpAppVersion extends BaseModel {
    private static final long serialVersionUID = 1L;
    @ApiModelProperty(value = "自增id")
    @TableId(value = "id", type = IdType.AUTO)
    private Long id;
    @ApiModelProperty(value = "安卓软件包")
    private String androidFile;
    @ApiModelProperty(value = "ios软件包")
    private String iosFile;
    @ApiModelProperty(value = "软件版本号")
    private String version;
    @ApiModelProperty(value = "更新说明")
    private String updateDescription;
}
xp-robotaxi-api/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
@@ -28,4 +28,5 @@
com.xiaopeng.api.factory.automaticPilot.OrderMissionClientFallbackFactory
com.xiaopeng.api.factory.maintenance.XpCheckLocationClientFallbackFactory
com.xiaopeng.api.factory.automaticPilot.OrderMissionClientFallbackFactory
com.xiaopeng.api.factory.maintenance.XpClockInClientFallbackFactory
com.xiaopeng.api.factory.maintenance.XpClockInClientFallbackFactory
com.xiaopeng.api.factory.account.SysGroupMenuClientFallbackFactory
xp-robotaxi-operation-boot/src/main/java/com/xiaopeng/operation/controller/XpAgreementController.java
@@ -2,24 +2,19 @@
import com.xiaopeng.common.core.domain.R;
import com.xiaopeng.common.core.web.controller.BaseController;
import com.xiaopeng.common.core.web.domain.AjaxResult;
import com.xiaopeng.operation.service.XpAgreementService;
import com.xiaopeng.operation.vo.XpAgreementVo;
import com.xiaopeng.operation.vo.XpBannerListVo;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
@Slf4j
@RestController
@RequestMapping("/base/v1/mini-program")
@Api(tags = "协议模块")
public class XpAgreementController extends BaseController {
    private final XpAgreementService xpAgreementService;
@@ -29,21 +24,23 @@
    }
    @ApiOperation(value = "获取协议",tags = {"小程序-首页"},response = XpAgreementVo.class)
    @GetMapping("/privacy/content/{type}")
    @GetMapping("/base/v1/mini-program/privacy/content/{type}")
    public R<XpAgreementVo> getContent(@PathVariable Integer type) {
        return R.ok(xpAgreementService.getContentByType(type));
    }
    @ApiOperation(value = "获取协议所有",tags = {"小程序-首页所有"},response = XpAgreementVo.class)
    @GetMapping("/privacy/contentAll")
    @GetMapping("/base/v1/mini-program/privacy/contentAll")
    public R<List<XpAgreementVo>> contentAll() {
        return R.ok(xpAgreementService.getContentByTypeAll());
    }
    @ApiOperation(value = "获取协议/隐私政策",tags = {"运维APP-个人中心"},response = XpAgreementVo.class)
    @GetMapping("/base/v1/privacy/content/{type}")
    public R<XpAgreementVo> getAppContent(@ApiParam(name = "type", value = "类型 1=用户服务协议 2=平台隐私政策 ") @PathVariable Integer type) {
        return R.ok(xpAgreementService.getContentByType(type));
    }
}
xp-robotaxi-operation-boot/src/main/java/com/xiaopeng/operation/controller/XpAppVersionController.java
New file
@@ -0,0 +1,41 @@
package com.xiaopeng.operation.controller;
import com.xiaopeng.common.core.domain.R;
import com.xiaopeng.operation.service.IXpAppVersionService;
import com.xiaopeng.operation.vo.XpAppVersionVO;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
 * App版本管理 Controller
 *
 * @author mitao
 * @since 2026-02-14
 */
@Slf4j
@RestController
@RequestMapping("")
@Api(tags = "App版本管理")
public class XpAppVersionController {
    private final IXpAppVersionService appVersionService;
    public XpAppVersionController(IXpAppVersionService appVersionService) {
        this.appVersionService = appVersionService;
    }
    /**
     * 获取App最新版本(运维APP接口)
     */
    @GetMapping("/api/v1/app/version/latest")
    @ApiOperation(value = "获取App最新版本", tags = {"运维APP-版本管理"})
    public R<XpAppVersionVO> getLatestVersion() {
        log.info("查询App最新版本");
        XpAppVersionVO vo = appVersionService.getLatestVersion();
        return R.ok(vo);
    }
}
xp-robotaxi-operation-boot/src/main/java/com/xiaopeng/operation/controller/XpSystemSettingController.java
@@ -1,6 +1,5 @@
package com.xiaopeng.operation.controller;
import com.xiaopeng.api.model.operation.SysOperLog;
import com.xiaopeng.common.core.constant.CacheConstants;
import com.xiaopeng.common.core.domain.R;
import com.xiaopeng.common.core.web.controller.BaseController;
@@ -8,14 +7,12 @@
import com.xiaopeng.common.redis.service.RedisService;
import com.xiaopeng.operation.service.XpSystemSettingService;
import com.xiaopeng.operation.vo.CustomerServicePhoneVo;
import com.xiaopeng.operation.vo.XpBannerListVo;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.bind.annotation.*;
import java.util.List;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@Slf4j
@RestController
@@ -64,4 +61,14 @@
        return R.ok(xpSystemSettingService.getOrderFinishTime());
    }
    @GetMapping("/base/v1/support/phone")
    @ApiOperation(value = "获取客服电话", tags = {"运维APP-个人中心"}, response = String.class)
    public R<CustomerServicePhoneVo> getCustomerPhone() {
        Object customerServicePhone = redisService.getCacheObject(CacheConstants.CUSTOMER_SERVICE_PHONE);
        if (customerServicePhone != null) {
            return R.ok(new CustomerServicePhoneVo(customerServicePhone.toString()));
        } else {
            return R.ok(new CustomerServicePhoneVo(xpSystemSettingService.getCustomerServicePhone()));
        }
    }
}
xp-robotaxi-operation-boot/src/main/java/com/xiaopeng/operation/mapper/XpAppVersionMapper.java
New file
@@ -0,0 +1,14 @@
package com.xiaopeng.operation.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.xiaopeng.api.model.operation.XpAppVersion;
/**
 * App版本管理 Mapper 接口
 *
 * @author mitao
 * @since 2026-02-14
 */
public interface XpAppVersionMapper extends BaseMapper<XpAppVersion> {
}
xp-robotaxi-operation-boot/src/main/java/com/xiaopeng/operation/service/IXpAppVersionService.java
New file
@@ -0,0 +1,20 @@
package com.xiaopeng.operation.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.xiaopeng.api.model.operation.XpAppVersion;
import com.xiaopeng.operation.vo.XpAppVersionVO;
/**
 * App版本管理 服务接口
 *
 * @author mitao
 * @since 2026-02-14
 */
public interface IXpAppVersionService extends IService<XpAppVersion> {
    /**
     * 获取最新版本信息
     * @return 最新版本信息
     */
    XpAppVersionVO getLatestVersion();
}
xp-robotaxi-operation-boot/src/main/java/com/xiaopeng/operation/service/impl/SysMenuServiceImpl.java
@@ -1,9 +1,18 @@
package com.xiaopeng.operation.service.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xiaopeng.api.feignClient.account.SysGroupMenuClient;
import com.xiaopeng.api.feignClient.account.SysRoleClient;
import com.xiaopeng.api.feignClient.account.SysUserRoleClient;
import com.xiaopeng.api.model.account.SysRole;
import com.xiaopeng.api.model.account.SysUserRole;
import com.xiaopeng.api.model.operation.SysMenu;
import com.xiaopeng.common.core.domain.R;
import com.xiaopeng.common.security.service.TokenService;
import com.xiaopeng.operation.mapper.SysMenuMapper;
import com.xiaopeng.operation.service.ISysMenuService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.*;
@@ -17,8 +26,21 @@
 * @author mitao
 * @since 2026-02-03
 */
@Slf4j
@Service
public class SysMenuServiceImpl extends ServiceImpl<SysMenuMapper, SysMenu> implements ISysMenuService {
    @Autowired
    private TokenService tokenService;
    @Autowired
    private SysUserRoleClient sysUserRoleClient;
    @Autowired
    private SysRoleClient sysRoleClient;
    @Autowired
    private SysGroupMenuClient sysGroupMenuClient;
    /**
     * 根据菜单ID列表查询菜单列表
@@ -105,7 +127,61 @@
    @Override
    public List<SysMenu> getPermission() {
        try {
            // 1. 获取当前登录用户ID
            Long userId = tokenService.getLoginUser().getUserid();
            if (userId == null) {
                log.warn("获取当前登录用户ID失败");
                return Collections.emptyList();
            }
        return Collections.emptyList();
            // 2. 查询用户角色关联
            R<SysUserRole> userRoleResult = sysUserRoleClient.selectSysUserRoleByUserId(userId);
            if (userRoleResult == null || userRoleResult.getCode() != 200 || userRoleResult.getData() == null) {
                log.warn("查询用户角色关联失败, userId={}", userId);
                return Collections.emptyList();
            }
            Long roleId = userRoleResult.getData().getRoleId();
            if (roleId == null) {
                log.warn("用户未关联角色, userId={}", userId);
                return Collections.emptyList();
            }
            // 3. 查询角色信息
            R<SysRole> roleResult = sysRoleClient.getRoleById(roleId);
            if (roleResult == null || roleResult.getCode() != 200 || roleResult.getData() == null) {
                log.warn("查询角色信息失败, roleId={}", roleId);
                return Collections.emptyList();
            }
            Long groupId = roleResult.getData().getGroupId();
            if (groupId == null) {
                log.warn("角色未关联权限组, roleId={}", roleId);
                return Collections.emptyList();
            }
            // 4. 查询权限组关联的菜单ID列表
            R<List<Long>> menuIdsResult = sysGroupMenuClient.selectMenuIdsByGroupId(groupId);
            if (menuIdsResult == null || menuIdsResult.getCode() != 200 || menuIdsResult.getData() == null) {
                log.warn("查询权限组菜单ID列表失败, groupId={}", groupId);
                return Collections.emptyList();
            }
            List<Long> menuIds = menuIdsResult.getData();
            if (menuIds.isEmpty()) {
                log.info("权限组未关联菜单, groupId={}", groupId);
                return Collections.emptyList();
            }
            // 5. 查询菜单详情
            List<SysMenu> menus = this.listByIds(menuIds);
            log.info("查询用户权限菜单成功, userId={}, menuCount={}", userId, menus.size());
            return menus;
        } catch (Exception e) {
            log.error("查询用户权限菜单异常", e);
            return Collections.emptyList();
        }
    }
}
xp-robotaxi-operation-boot/src/main/java/com/xiaopeng/operation/service/impl/XpAppVersionServiceImpl.java
New file
@@ -0,0 +1,43 @@
package com.xiaopeng.operation.service.impl;
import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xiaopeng.api.model.operation.XpAppVersion;
import com.xiaopeng.common.core.exception.ServiceException;
import com.xiaopeng.operation.mapper.XpAppVersionMapper;
import com.xiaopeng.operation.service.IXpAppVersionService;
import com.xiaopeng.operation.vo.XpAppVersionVO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import java.util.Objects;
/**
 * App版本管理 服务实现类
 *
 * @author mitao
 * @since 2026-02-14
 */
@Slf4j
@Service
public class XpAppVersionServiceImpl extends ServiceImpl<XpAppVersionMapper, XpAppVersion> implements IXpAppVersionService {
    @Override
    public XpAppVersionVO getLatestVersion() {
        // 查询最新版本(按ID倒序,取第一条)
        XpAppVersion latestVersion = this.lambdaQuery()
                .orderByDesc(XpAppVersion::getId)
                .last("LIMIT 1")
                .one();
        if (Objects.isNull(latestVersion)) {
            log.warn("未找到App版本信息");
            throw new ServiceException("App版本信息不存在");
        }
        // 转换为 VO
        XpAppVersionVO vo = BeanUtil.copyProperties(latestVersion, XpAppVersionVO.class);
        log.info("获取最新App版本成功, version={}", vo.getVersion());
        return vo;
    }
}
xp-robotaxi-operation-boot/src/main/java/com/xiaopeng/operation/vo/XpAgreementVo.java
@@ -10,7 +10,7 @@
    @ApiModelProperty(value = "id")
    private Long id;
    @ApiModelProperty(value = "类型")
    @ApiModelProperty(value = "类型 1=用户服务协议 2=平台隐私政策 3=敏感个人信息处理情况说明 4=向第三方提供个人信息情况的说明 5=乘车须知 6=计费规则说明")
    private Integer type;
    @ApiModelProperty(value = "内容")
xp-robotaxi-operation-boot/src/main/java/com/xiaopeng/operation/vo/XpAppVersionVO.java
New file
@@ -0,0 +1,28 @@
package com.xiaopeng.operation.vo;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
/**
 * App版本信息 VO
 *
 * @author mitao
 * @since 2026-02-14
 */
@Data
@ApiModel("App版本信息")
public class XpAppVersionVO {
    @ApiModelProperty(value = "软件版本号")
    private String version;
    @ApiModelProperty(value = "安卓软件包")
    private String androidFile;
    @ApiModelProperty(value = "ios软件包")
    private String iosFile;
    @ApiModelProperty(value = "更新说明")
    private String updateDescription;
}
xp-robotaxi-operation-boot/src/main/resources/mapper/operation/XpAppVersionMapper.xml
New file
@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.xiaopeng.operation.mapper.XpAppVersionMapper">
</mapper>