Files
zsglpt/static/app/assets/ScreenshotsPage-7CRd3Hlo.js
yuyx 7007f5f6f5 feat: 完成 Passkey 能力与前后台加载优化
更新说明:\n1. 新增用户端与管理员端 Passkey 登录/注册/设备管理(最多3台,支持设备备注、删除设备)。\n2. 修复 Passkey 注册与登录流程中的浏览器/证书/CSRF相关问题,增强错误提示。\n3. 前台登录页改为独立入口,首屏仅加载必要资源,其他页面按需加载。\n4. 系统配置页改为静默获取金山文档状态,避免首屏阻塞,并优化状态展示为“检测中/已登录/未登录/异常”。\n5. 补充后端接口与页面渲染适配,修复多入口下样式依赖注入问题。\n6. 同步更新前后台构建产物与相关静态资源。
2026-02-15 23:51:46 +08:00

2 lines
7.2 KiB
JavaScript

import{E as G}from"./el-button-DWxIvzz-.js";import{n as J,o as K,m as Q,p as L}from"./el-overlay-C_JJBVfE.js";import{E as X}from"./el-pagination-BY1uI-wO.js";import"./el-select-B0VMg2td.js";import{p as P,a as s}from"./http-CdvgQxJu.js";import{E as Y}from"./el-card-DfVpO1U5.js";import{_ as Z}from"./style-CEbARg1o.js";import{g as f,h as ee,i as te,c as k,s as i,o as u,k as r,j as x,q as p,x as w,F as S,l as ae,a4 as ne,t as E}from"./vendor-vue-DxN60LNb.js";import"./vendor-axios-B9ygI19o.js";async function oe(m={}){const{data:l}=await P.get("/screenshots",{params:m});return l}async function re(m){const{data:l}=await P.delete(`/screenshots/${encodeURIComponent(m)}`);return l}async function se(){const{data:m}=await P.post("/screenshots/clear",{});return m}const ie={class:"panel-head"},le={class:"panel-actions"},ce={key:1,class:"grid"},de=["src","alt","onError","onClick"],ue={class:"shot-body"},pe=["title"],fe={class:"shot-meta app-muted"},me={class:"shot-actions"},ve={key:2,class:"pagination"},ge={class:"page-hint app-muted"},we={class:"preview"},ye=["src","alt"],_=24,he={__name:"ScreenshotsPage",setup(m){const l=f(!1),y=f([]),c=f(1),d=f(0),A=ee(()=>Math.max(1,Math.ceil((d.value||0)/_))),v=f(!1),B=f(""),T=f("");function b(t){return`/screenshots/${encodeURIComponent(t)}`}function R(t){return`/screenshots/thumb/${encodeURIComponent(t)}`}async function C(){l.value=!0;try{const t={limit:_,offset:(c.value-1)*_},e=await oe(t),a=Array.isArray(e)?e:Array.isArray(e?.items)?e.items:[],o=Array.isArray(e)?a.length:Number(e?.total??a.length);y.value=a,d.value=Number.isFinite(o)?Math.max(0,o):a.length}catch(t){t?.response?.status===401&&(window.location.href="/login"),y.value=[],d.value=0}finally{l.value=!1}}async function V(t){c.value=t,await C()}function z(t){T.value=t.display_name||t.filename||"截图预览",B.value=b(t.filename),v.value=!0}function M(t,e){const a=t?.target;a&&a.dataset.fullLoaded!=="1"&&(a.dataset.fullLoaded="1",a.src=b(e.filename))}function I(t){return new Promise((e,a)=>{t.toBlob(o=>o?e(o):a(new Error("toBlob_failed")),"image/png")})}async function N(t){if(!t)throw new Error("no_image");(!t.complete||t.naturalWidth<=0)&&(typeof t.decode=="function"?await t.decode():await new Promise((o,g)=>{t.addEventListener("load",o,{once:!0}),t.addEventListener("error",g,{once:!0})}));const e=document.createElement("canvas");e.width=t.naturalWidth,e.height=t.naturalHeight;const a=e.getContext("2d");if(!a)throw new Error("no_canvas");return a.drawImage(t,0,0),await I(e)}async function j(t){if(!t)throw new Error("no_blob");if(t.type==="image/png")return t;if(typeof createImageBitmap=="function"){const a=await createImageBitmap(t),o=document.createElement("canvas");o.width=a.width,o.height=a.height;const g=o.getContext("2d");if(!g)throw new Error("no_canvas");return g.drawImage(a,0,0),await I(o)}const e=URL.createObjectURL(t);try{const a=new Image;return a.src=e,typeof a.decode=="function"&&await a.decode(),await N(a)}finally{URL.revokeObjectURL(e)}}async function U(t){const e=await fetch(t,{credentials:"include",cache:"no-store"});if(!e.ok)throw new Error("fetch_failed");const a=await e.blob();if(!(e.headers.get("Content-Type")||a.type||"").startsWith("image/"))throw new Error("not_image");return await j(a)}async function D(){try{await L.confirm("确定要清空全部截图吗?","清空截图",{confirmButtonText:"清空",cancelButtonText:"取消",type:"warning"})}catch{return}try{const t=await se();if(t?.success){s.success(`已清空(删除 ${t?.deleted||0} 张)`),y.value=[],d.value=0,c.value=1,v.value=!1;return}s.error(t?.error||"操作失败")}catch(t){const e=t?.response?.data;s.error(e?.error||"操作失败")}}async function F(t){try{await L.confirm(`确定要删除截图「${t.display_name||t.filename}」吗?`,"删除截图",{confirmButtonText:"删除",cancelButtonText:"取消",type:"warning"})}catch{return}try{const e=await re(t.filename);if(e?.success){B.value.includes(encodeURIComponent(t.filename))&&(v.value=!1),c.value>1&&y.value.length<=1&&(c.value-=1),await C(),s.success("已删除");return}s.error(e?.error||"删除失败")}catch(e){const a=e?.response?.data;s.error(a?.error||"删除失败")}}async function O(t){const e=b(t.filename);if(!navigator.clipboard||typeof navigator.clipboard.write!="function"||typeof window.ClipboardItem>"u"){s.warning("当前环境不支持复制图片(建议使用 Chrome/Edge 并通过 HTTPS 访问);可用“下载”。");return}try{try{await navigator.clipboard.write([new ClipboardItem({"image/png":U(e)})])}catch{const a=await U(e);await navigator.clipboard.write([new ClipboardItem({"image/png":a})])}s.success("图片已复制到剪贴板")}catch{try{if(navigator.clipboard&&typeof navigator.clipboard.writeText=="function"){await navigator.clipboard.writeText(`${window.location.origin}${e}`),s.warning("复制图片失败,已复制图片链接(可直接粘贴到浏览器打开)");return}}catch{}s.warning("复制图片失败:请确认允许剪贴板权限;可用“下载”。")}}function W(t){const e=document.createElement("a");e.href=b(t.filename),e.download=t.display_name||t.filename,document.body.appendChild(e),e.click(),e.remove()}return te(C),(t,e)=>{const a=G,o=J,g=K,$=Y,H=X,q=Q;return u(),k($,{shadow:"never",class:"panel","body-style":{padding:"14px"}},{default:i(()=>[r("div",ie,[e[5]||(e[5]=r("div",{class:"panel-title"},"截图管理",-1)),r("div",le,[p(a,{loading:l.value,onClick:C},{default:i(()=>[...e[3]||(e[3]=[w("刷新",-1)])]),_:1},8,["loading"]),p(a,{type:"danger",plain:"",disabled:d.value===0,onClick:D},{default:i(()=>[...e[4]||(e[4]=[w("清空全部",-1)])]),_:1},8,["disabled"])])]),l.value?(u(),k(o,{key:0,rows:6,animated:""})):(u(),x(S,{key:1},[d.value===0?(u(),k(g,{key:0,description:"暂无截图"})):(u(),x("div",ce,[(u(!0),x(S,null,ne(y.value,n=>(u(),k($,{key:n.filename,shadow:"never",class:"shot-card","body-style":{padding:"0"}},{default:i(()=>[r("img",{class:"shot-img",src:R(n.filename),alt:n.display_name||n.filename,loading:"lazy",onError:h=>M(h,n),onClick:h=>z(n)},null,40,de),r("div",ue,[r("div",{class:"shot-name",title:n.display_name||n.filename},E(n.display_name||n.filename),9,pe),r("div",fe,E(n.created||""),1),r("div",me,[p(a,{size:"small",text:"",type:"primary",onClick:h=>O(n)},{default:i(()=>[...e[6]||(e[6]=[w("复制图片",-1)])]),_:1},8,["onClick"]),p(a,{size:"small",text:"",onClick:h=>W(n)},{default:i(()=>[...e[7]||(e[7]=[w("下载",-1)])]),_:1},8,["onClick"]),p(a,{size:"small",text:"",type:"danger",onClick:h=>F(n)},{default:i(()=>[...e[8]||(e[8]=[w("删除",-1)])]),_:1},8,["onClick"])])])]),_:2},1024))),128))])),d.value>_?(u(),x("div",ve,[p(H,{"current-page":c.value,"onUpdate:currentPage":e[0]||(e[0]=n=>c.value=n),"page-size":_,total:d.value,layout:"prev, pager, next, jumper, ->, total",onCurrentChange:V},null,8,["current-page","total"]),r("div",ge,"第 "+E(c.value)+" / "+E(A.value)+" 页",1)])):ae("",!0)],64)),p(q,{modelValue:v.value,"onUpdate:modelValue":e[2]||(e[2]=n=>v.value=n),title:T.value,width:"min(920px, 94vw)"},{footer:i(()=>[p(a,{onClick:e[1]||(e[1]=n=>v.value=!1)},{default:i(()=>[...e[9]||(e[9]=[w("关闭",-1)])]),_:1})]),default:i(()=>[r("div",we,[r("img",{src:B.value,alt:T.value,class:"preview-img"},null,8,ye)])]),_:1},8,["modelValue","title"])]),_:1})}}},Ie=Z(he,[["__scopeId","data-v-07cdff63"]]);export{Ie as default};