feat: 分页加载和用户编码

1. 前端List.jsx: 实现分页加载,每次50条,滚动到底部自动加载更多
2. 后端auth.py: 注册时自动生成用户编码(0001开始)
3. 模型schemas: 添加user_code字段
This commit is contained in:
龙大 2026-03-22 19:16:08 +08:00
parent ef638f18c4
commit 2c0056c827
4 changed files with 59 additions and 5 deletions

View File

@ -16,6 +16,7 @@ class User(Base):
# f99 系统字段 # f99 系统字段
f99_90_id = Column(String(36), primary_key=True, default=generate_uuid) f99_90_id = Column(String(36), primary_key=True, default=generate_uuid)
user_code = Column(String(10), unique=True, nullable=True, index=True) # 用户编码
f99_91_user_id = Column(String(36), unique=True, nullable=False, index=True) f99_91_user_id = Column(String(36), unique=True, nullable=False, index=True)
f01_01_name = Column(String(255), unique=True, nullable=False, index=True) # username f01_01_name = Column(String(255), unique=True, nullable=False, index=True) # username
email = Column(String(255), unique=True, nullable=True, index=True) email = Column(String(255), unique=True, nullable=True, index=True)

View File

@ -10,6 +10,20 @@ from app.schemas.schemas import Token, UserCreate, UserResponse
router = APIRouter(prefix="/api/auth", tags=["认证"]) router = APIRouter(prefix="/api/auth", tags=["认证"])
def generate_user_code(db):
"""生成用户编码从0001开始"""
# 查找最大的user_code
max_code = db.query(User.user_code).filter(User.user_code != None).order_by(User.user_code.desc()).first()
if max_code and max_code[0]:
try:
num = int(max_code[0]) + 1
return f"{num:04d}"
except:
pass
return "0001"
@router.post("/register", response_model=UserResponse) @router.post("/register", response_model=UserResponse)
def register(user_data: UserCreate, db: Session = Depends(get_db)): def register(user_data: UserCreate, db: Session = Depends(get_db)):
"""用户注册""" """用户注册"""
@ -35,7 +49,8 @@ def register(user_data: UserCreate, db: Session = Depends(get_db)):
hashed_password = get_password_hash(user_data.password) hashed_password = get_password_hash(user_data.password)
user = User( user = User(
f99_90_id=str(uuid.uuid4()), f99_90_id=str(uuid.uuid4()),
f99_91_user_id=str(uuid.uuid4()), # 生成唯一 user_id f99_91_user_id=str(uuid.uuid4()),
user_code=generate_user_code(db),
f01_01_name=user_data.f01_01_name, f01_01_name=user_data.f01_01_name,
email=user_data.email, email=user_data.email,
phone=user_data.phone, phone=user_data.phone,

View File

@ -37,6 +37,7 @@ class UserResponse(UserBase):
f99_90_id: str = Field(..., alias="id") f99_90_id: str = Field(..., alias="id")
f01_01_name: str = Field(..., alias="username") f01_01_name: str = Field(..., alias="username")
role: str role: str
user_code: Optional[str] = None
f99_92_created_at: Optional[datetime] = Field(None, alias="created_at") f99_92_created_at: Optional[datetime] = Field(None, alias="created_at")
f99_93_updated_at: Optional[datetime] = Field(None, alias="updated_at") f99_93_updated_at: Optional[datetime] = Field(None, alias="updated_at")

View File

@ -15,6 +15,9 @@ export default function List() {
const [key, setKey] = useState(0) const [key, setKey] = useState(0)
const [search, setSearch] = useState('') const [search, setSearch] = useState('')
const [isAdmin, setIsAdmin] = useState(false) const [isAdmin, setIsAdmin] = useState(false)
const [page, setPage] = useState(1)
const [hasMore, setHasMore] = useState(true)
const [initialLoad, setInitialLoad] = useState(true)
useEffect(() => { useEffect(() => {
// //
@ -46,7 +49,19 @@ export default function List() {
setFilter('') setFilter('')
setFilterType('') setFilterType('')
} }
fetchCollections() //
const handleScroll = () => {
if (loading || !hasMore) return
const scrollTop = window.scrollY || document.documentElement.scrollTop
const scrollHeight = document.documentElement.scrollHeight
const clientHeight = document.documentElement.clientHeight
if (scrollTop + clientHeight >= scrollHeight - 100) {
fetchCollections(true)
}
}
window.addEventListener('scroll', handleScroll)
return () => window.removeEventListener('scroll', handleScroll)
} }
handleHashChange() handleHashChange()
@ -59,11 +74,21 @@ export default function List() {
} }
}, []) }, [])
const fetchCollections = async () => { const fetchCollections = async (reset = false) => {
setLoading(true)
const token = localStorage.getItem('token') const token = localStorage.getItem('token')
const currentPage = reset ? 1 : page
try { try {
const res = await fetch('/api/collections?limit=100', { if (reset) {
setCollections([])
setPage(1)
setLoading(true)
setInitialLoad(true)
} else {
setLoading(true)
}
const res = await fetch(`/api/collections?page=${currentPage}&limit=50`, {
headers: token ? { 'Authorization': 'Bearer ' + token } : {} headers: token ? { 'Authorization': 'Bearer ' + token } : {}
}) })
@ -82,6 +107,18 @@ export default function List() {
list = list.items list = list.items
} }
//
if (reset) {
setCollections(list || [])
} else {
setCollections(prev => [...prev, ...(list || [])])
}
//
const receivedCount = list ? list.length : 0
setHasMore(receivedCount >= 50)
if (!initialLoad) setPage(prev => prev + 1)
// //
// IDURL // IDURL
if (userIdFilter) { if (userIdFilter) {