@@ -73,6 +73,7 @@ export default function Profile() {
7373 const [ showCreateModal , setShowCreateModal ] = useState ( false ) ;
7474 const [ newCollectionName , setNewCollectionName ] = useState ( "" ) ;
7575 const [ showDropdown , setShowDropdown ] = useState ( false ) ;
76+ const [ syncing , setSyncing ] = useState < string | null > ( null ) ;
7677 const dropdownRef = useRef < HTMLDivElement > ( null ) ;
7778
7879 // Close dropdown on click outside
@@ -173,6 +174,31 @@ export default function Profile() {
173174
174175 const downloadedBooks : Book [ ] = [ ] ;
175176
177+ const handleSync = async ( type : "full" | "incremental" ) => {
178+ const title = type === "full" ? "全量更新" : "增量更新" ;
179+ const message =
180+ type === "full"
181+ ? "扫描所有本地书籍,新增数据库不存在的,标记已删除的,重新抓取所有现有书籍的元数据。"
182+ : "仅扫描新数据,现有数据不做处理。" ;
183+
184+ if ( ! window . confirm ( `${ title } \n\n${ message } \n\n确认开始更新吗?` ) ) {
185+ return ;
186+ }
187+
188+ setSyncing ( type ) ;
189+ try {
190+ const { getApiClient } = await import ( "@bookdock/api-client" ) ;
191+ const api = getApiClient ( ) ;
192+ const res = await api . syncBooks ( type ) ;
193+ alert ( res . data ?. message || `${ type === "full" ? "全量" : "增量" } 更新成功` ) ;
194+ } catch ( e : any ) {
195+ alert ( e ?. response ?. data ?. message || "同步失败" ) ;
196+ } finally {
197+ setSyncing ( null ) ;
198+ setShowDropdown ( false ) ;
199+ }
200+ } ;
201+
176202 const handleCreateCollection = useCallback ( async ( ) => {
177203 if ( ! newCollectionName . trim ( ) ) return ;
178204 try {
@@ -479,6 +505,22 @@ export default function Profile() {
479505 < Plus className = "w-4 h-4" />
480506 < span > 新建书单</ span >
481507 </ button >
508+ < button
509+ onClick = { ( ) => { handleSync ( "incremental" ) ; setShowDropdown ( false ) ; } }
510+ disabled = { ! ! syncing }
511+ className = "w-full flex items-center gap-2 px-4 py-2.5 text-sm text-gray-700 dark:text-gray-200 hover:bg-gray-50 dark:hover:bg-gray-700 transition-colors disabled:opacity-50"
512+ >
513+ < Plus className = "w-4 h-4" />
514+ < span > 增量更新</ span >
515+ </ button >
516+ < button
517+ onClick = { ( ) => { handleSync ( "full" ) ; setShowDropdown ( false ) ; } }
518+ disabled = { ! ! syncing }
519+ className = "w-full flex items-center gap-2 px-4 py-2.5 text-sm text-gray-700 dark:text-gray-200 hover:bg-gray-50 dark:hover:bg-gray-700 transition-colors disabled:opacity-50"
520+ >
521+ < RefreshCw className = "w-4 h-4" />
522+ < span > 全量更新</ span >
523+ </ button >
482524 < Link
483525 to = "/membership"
484526 onClick = { ( ) => setShowDropdown ( false ) }
0 commit comments