diff --git a/src/main/java/com/yunhai/notice/common/interceptor/MobiAccessInterceptor.java b/src/main/java/com/yunhai/notice/common/interceptor/MobiAccessInterceptor.java
new file mode 100644
index 0000000..62c3e70
--- /dev/null
+++ b/src/main/java/com/yunhai/notice/common/interceptor/MobiAccessInterceptor.java
@@ -0,0 +1,34 @@
+package com.yunhai.notice.common.interceptor;
+
+import com.yunhai.platform.auth.BoaUserContext;
+import com.yunhai.platform.auth.UserContextHolder;
+import org.springframework.web.servlet.HandlerInterceptor;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+/**
+ * 移动端 /mobiapi 访问拦截(口径 = 登录即可访问)。
+ *
不做访问级别判级——移动端主体含学生(旧 SUPER/BUREAU/SCHOOL/NONE 判级照抄会全 403)。
+ * token 解析、401+40101 信封与 pre-token 豁免由平台 SDK {@code LoginUserInterceptor} 承担
+ * (tokenSurfaces 缺省 /mobiapi);本拦截器是业务侧兜底:SDK 之后的任何 /mobiapi 业务请求,
+ * 身份上下文为空即 401,防止依赖链路变化时出现"匿名可达的业务端点"。
+ */
+public class MobiAccessInterceptor implements HandlerInterceptor {
+
+ @Override
+ public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
+ if (UserContextHolder.get() == null && BoaUserContext.get() == null) {
+ try {
+ response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
+ response.setContentType("application/json;charset=UTF-8");
+ response.getWriter().write(
+ "{\"code\":40101,\"msg\":\"未登录或登录已过期\",\"data\":null}");
+ } catch (Exception ignored) {
+ // 响应已提交等场景:状态码已设置,写体失败不掩盖原始语义
+ }
+ return false;
+ }
+ return true;
+ }
+}
diff --git a/src/main/java/com/yunhai/notice/config/Config.java b/src/main/java/com/yunhai/notice/config/Config.java
index 6375822..d76204d 100644
--- a/src/main/java/com/yunhai/notice/config/Config.java
+++ b/src/main/java/com/yunhai/notice/config/Config.java
@@ -1,11 +1,14 @@
package com.yunhai.notice.config;
/**
- * 全局路径常量。与 UserBase 一致:API 统一挂在 /{platform}/ 之下(platform = api / manage / mobiapi)。
+ * 全局路径常量(三层接口面,闭集):/api PC 管理端(CAS)、/mobiapi 移动端(token)、/oapi 开放接口(应用签名)。
+ * 其余前缀(如旧 /manage、/{platform} 通配)一律 404(方案 §4.1 路径闭集)。
*/
public enum Config {
Inst;
- public static final String API_PATH = "/{platform}"; // manage / api / mobiapi,前面有/后面无/,拼接子路径时用"/"分隔
+ // 末尾不带斜杠:各控制器用 API_PATH + "/xxx/" 拼路径,若这里带尾斜杠会拼出字面双斜杠而 404
+ public static final String API_PATH = "/api"; // PC 管理端(CAS 会话)
+ public static final String MOBI_API_PATH = "/mobiapi"; // 移动端(平台 Bearer token)
public static final String OPEN_API_PATH = "/oapi";
}
diff --git a/src/main/java/com/yunhai/notice/config/MobiWebMvcConfig.java b/src/main/java/com/yunhai/notice/config/MobiWebMvcConfig.java
new file mode 100644
index 0000000..7db0935
--- /dev/null
+++ b/src/main/java/com/yunhai/notice/config/MobiWebMvcConfig.java
@@ -0,0 +1,27 @@
+package com.yunhai.notice.config;
+
+import com.yunhai.notice.common.interceptor.MobiAccessInterceptor;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.core.Ordered;
+import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
+import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
+
+/**
+ * 移动端 /mobiapi 拦截装配。
+ * {@code LOWEST_PRECEDENCE} 保证本配置器在 SDK 的 {@code YhAuthWebMvcConfigurer}
+ * (无 @Order)之后注册,登录态解析先于本兜底拦截执行。
+ * 排除 {@code /mobiapi/auth/**}:其中 login/bind/exchange 是 SDK 定义的 pre-token 端点
+ * ({@code LoginUserInterceptor.PRE_TOKEN_ENDPOINTS}),设计上匿名可达——它们是登录链本身,
+ * 不是"业务免登录端点";logout/jsapiSignature 仍由 SDK 按 token 强制。业务端点无任何白名单。
+ */
+@Configuration
+public class MobiWebMvcConfig implements WebMvcConfigurer {
+
+ @Override
+ public void addInterceptors(InterceptorRegistry registry) {
+ registry.addInterceptor(new MobiAccessInterceptor())
+ .addPathPatterns("/mobiapi/**")
+ .excludePathPatterns("/mobiapi/auth/**")
+ .order(Ordered.LOWEST_PRECEDENCE);
+ }
+}
diff --git a/src/main/java/com/yunhai/notice/controller/mobiapi/BaseMobiController.java b/src/main/java/com/yunhai/notice/controller/mobiapi/BaseMobiController.java
new file mode 100644
index 0000000..1bd4f90
--- /dev/null
+++ b/src/main/java/com/yunhai/notice/controller/mobiapi/BaseMobiController.java
@@ -0,0 +1,85 @@
+package com.yunhai.notice.controller.mobiapi;
+
+import com.yunhai.notice.config.Config;
+import com.yunhai.notice.model.notice.UpFileResultVo;
+import com.yunhai.notice.service.IFileService;
+import com.yunhai.notice.service.IUserCenterService;
+import com.yunhai.platform.utils.model.BoaUser;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
+import org.springframework.web.multipart.MultipartFile;
+
+import javax.servlet.http.HttpServletResponse;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * 平台代理域移动端接口(/mobiapi/base/,token 身份)。
+ * 端点从 {@code controller.api.BaseApiController} 按移动端需要迁出,业务逻辑仍在
+ * {@link IUserCenterService} / {@link IFileService},本控制器仅"取参 → 调 Service → 返回";
+ * 管理端专用端点留在 api/ 面,本期不删。
+ * 出入参口径与 api 侧一致(路径名沿用旧移动端 base/FilePreview|FileDown 调用形状;
+ * 文件预览/下载在 api 侧实际位于 FileController 的 file/Down|Preview,此处对齐其
+ * IFileService 签名)。登出不在此暴露——SDK 已提供 {@code POST /mobiapi/auth/logout}。
+ */
+@RestController
+@RequestMapping(value = Config.MOBI_API_PATH + "/base/")
+public class BaseMobiController {
+
+ @Autowired
+ private IUserCenterService userCenterService;
+
+ @Autowired
+ private IFileService fileService;
+
+ /** 获取当前登录用户信息(token 链注入)。 */
+ @GetMapping("GetUserInfo")
+ public BoaUser getUserInfo(BoaUser authUserWithDept) {
+ return authUserWithDept;
+ }
+
+ /** 获取当前用户已授权的模块列表(移动端仅用于发布权限判定)。 */
+ @GetMapping("GetUserMod")
+ public List