diff --git a/backend/src/main/java/com/xly/erp/common/response/PageResult.java b/backend/src/main/java/com/xly/erp/common/response/PageResult.java
new file mode 100644
index 0000000..ca77a39
--- /dev/null
+++ b/backend/src/main/java/com/xly/erp/common/response/PageResult.java
@@ -0,0 +1,76 @@
+package com.xly.erp.common.response;
+
+import java.io.Serializable;
+import java.util.List;
+
+/**
+ * 通用分页响应体(docs/04 § 1.4 / § 3.2 SSoT)。
+ *
+ *
REQ-USR-003 T1【本 REQ 新增公共契约】。分页接口统一返回 {@code Result>},
+ * 含当前页数据 {@code records}、真实总记录数 {@code total}、当前页号 {@code pageNum}
+ * (数据越界钳制后的实际页号)、每页条数 {@code pageSize}。后续分页 REQ 复用。
+ *
+ * @param 当前页元素类型
+ */
+public class PageResult implements Serializable {
+
+ private static final long serialVersionUID = 1L;
+
+ /** 当前页数据。 */
+ private List records;
+ /** 真实总记录数。 */
+ private long total;
+ /** 当前页号(数据越界钳制后的实际页号)。 */
+ private long pageNum;
+ /** 每页条数。 */
+ private long pageSize;
+
+ public PageResult() {
+ }
+
+ public PageResult(List records, long total, long pageNum, long pageSize) {
+ this.records = records;
+ this.total = total;
+ this.pageNum = pageNum;
+ this.pageSize = pageSize;
+ }
+
+ /**
+ * 静态工厂:从分页要素装配。
+ */
+ public static PageResult of(List records, long total, long pageNum, long pageSize) {
+ return new PageResult<>(records, total, pageNum, pageSize);
+ }
+
+ public List getRecords() {
+ return records;
+ }
+
+ public void setRecords(List records) {
+ this.records = records;
+ }
+
+ public long getTotal() {
+ return total;
+ }
+
+ public void setTotal(long total) {
+ this.total = total;
+ }
+
+ public long getPageNum() {
+ return pageNum;
+ }
+
+ public void setPageNum(long pageNum) {
+ this.pageNum = pageNum;
+ }
+
+ public long getPageSize() {
+ return pageSize;
+ }
+
+ public void setPageSize(long pageSize) {
+ this.pageSize = pageSize;
+ }
+}
diff --git a/backend/src/test/java/com/xly/erp/common/response/PageResultTest.java b/backend/src/test/java/com/xly/erp/common/response/PageResultTest.java
new file mode 100644
index 0000000..b64d146
--- /dev/null
+++ b/backend/src/test/java/com/xly/erp/common/response/PageResultTest.java
@@ -0,0 +1,34 @@
+package com.xly.erp.common.response;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+import java.util.List;
+import org.junit.jupiter.api.Test;
+
+/**
+ * REQ-USR-003 T1:通用分页响应体 PageResult。
+ *
+ * 验证四字段(records/total/pageNum/pageSize)装配读回一致,空 records 允许。
+ */
+class PageResultTest {
+
+ @Test
+ void ofAssemblesAllFields() {
+ List records = List.of("a", "b", "c");
+ PageResult page = PageResult.of(records, 23L, 2L, 10L);
+
+ assertThat(page.getRecords()).isEqualTo(records);
+ assertThat(page.getTotal()).isEqualTo(23L);
+ assertThat(page.getPageNum()).isEqualTo(2L);
+ assertThat(page.getPageSize()).isEqualTo(10L);
+ }
+
+ @Test
+ void emptyRecordsAllowed() {
+ PageResult page = PageResult.of(List.of(), 0L, 1L, 10L);
+
+ assertThat(page.getRecords()).isNotNull().isEmpty();
+ assertThat(page.getTotal()).isZero();
+ assertThat(page.getPageNum()).isEqualTo(1L);
+ }
+}