feat: 分页加载和用户编码
1. 前端List.jsx: 实现分页加载,每次50条,滚动到底部自动加载更多 2. 后端auth.py: 注册时自动生成用户编码(0001开始) 3. 模型schemas: 添加user_code字段
This commit is contained in:
parent
ef638f18c4
commit
2c0056c827
|
|
@ -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)
|
||||||
|
|
|
||||||
|
|
@ -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,
|
||||||
|
|
|
||||||
|
|
@ -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")
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
|
||||||
// 应用筛选条件
|
// 应用筛选条件
|
||||||
// 用户ID筛选(从URL获取)
|
// 用户ID筛选(从URL获取)
|
||||||
if (userIdFilter) {
|
if (userIdFilter) {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue