diff --git a/internal/api/web/index.html b/internal/api/web/index.html
index b9824a9..4f59b73 100644
--- a/internal/api/web/index.html
+++ b/internal/api/web/index.html
@@ -73,8 +73,10 @@ function fileDragEnd(e){e.currentTarget.classList.remove("dragging");document.qu
function folderDragOver(e,target){if(!e.dataTransfer?.types.includes('text/chfs-paths'))return;const f=lastItems.find(x=>(current?current+'/':'')+x.name===target);if(!f?.dir||!(f.mask||'').includes('W'))return;e.preventDefault();if(target===current||target===""||[...selected].some(p=>p===target||target.startsWith(p+'/')))return;e.dataTransfer.dropEffect="move";e.currentTarget.classList.add('drop-target')}
function folderDragLeave(e){e.currentTarget.classList.remove('drop-target')}
async function folderDrop(e,target){if(!e.dataTransfer?.types.includes('text/chfs-paths'))return;e.preventDefault();e.stopPropagation();e.currentTarget.classList.remove('drop-target');let paths=[];try{paths=JSON.parse(e.dataTransfer.getData('text/chfs-paths')||'[]')}catch{};const f=lastItems.find(x=>(current?current+'/':'')+x.name===target);if(!f?.dir||!paths.length)return;if(paths.some(p=>p===target||target.startsWith(p+'/')))return fail('不能移动到自身或子目录');const base=target.replace(/^\/+|\/+$/g,'');await runOperation('移动 '+paths.length+' 项',async()=>{let done=0,failed=[],renamed=[];for(const source of paths){const name=source.split('/').pop(),destination=base?base+'/'+name:name;try{const actual=await transferWithConflict(source,destination,false);if(actual!==destination)renamed.push(name+' → '+actual.split('/').pop());done++}catch(err){failed.push(name+': '+err.message)}}selected.clear();await refresh();if(failed.length||renamed.length)show('
移动完成 '+esc('成功 '+done+' 项,失败 '+failed.length+' 项'+(renamed.length?'。\n\n自动重命名:\n'+renamed.join('\n'):'')+(failed.length?'。\n\n失败:\n'+failed.join('\n'):''))+'
关闭
');else toast('已移动 '+done+' 项')})}
-function handleItemClick(e,p){if(window.matchMedia&&window.matchMedia('(max-width:700px)').matches){activateItem(p);return}selectItem(p,true,e)}
+function handleItemClick(e,p){if(!me.username){guestItemActions(p);return}if(window.matchMedia&&window.matchMedia('(max-width:700px)').matches){activateItem(p);return}selectItem(p,true,e)}
function activateItem(p){const f=lastItems.find(x=>(current?current+"/":"")+x.name===p);if(!f)return;if(f.dir&&(f.mask||"").includes("R"))openDir(p);else if((f.mask||"").includes("R"))previewFile(p)}
+function guestItemActions(p){const f=lastItems.find(x=>(current?current+"/":"")+x.name===p);if(!f||!(f.mask||"").includes("R")){toast("当前项目没有访问权限",true);return}if(f.dir){openDir(p);return}const url=new URL("/chfs/shared/"+encodeURI(p),location.href).href;let html=''+esc(f.name)+' 访客可以直接下载或复制分享链接。
下载 复制分享链接
';show(html)}
+async function guestCopyShare(url){try{await navigator.clipboard.writeText(url);toast("分享链接已复制");closeModal()}catch{show('分享链接
关闭
')}}
function toggleTile(p){selectItem(p,!selected.has(p))}
function openSelected(){if(selected.size!==1)return;const p=[...selected][0];if(searchMode){const f=searchItems.find(x=>x.path===p);if(f)openSearchResult(f);return}const f=lastItems.find(x=>(current?current+"/":"")+x.name===p);if(!f)return;if(f.dir&&(f.mask||"").includes("R"))openDir(p);else if((f.mask||"").includes("R"))previewFile(p)}
function toggleAll(v){const source=searchMode?searchItems:lastItems;source.forEach(f=>{const p=searchMode?f.path:(current?current+"/":"")+f.name;if(v)selected.add(p);else selected.delete(p)});searchMode?updateSelection():render(lastItems)}