PageSourceSearch

https://kdcrassvet03.ru/kubcms-front/v5/master/s/c-FilesActualizator-hMiNwRrH.js

js kdcrassvet03.ru collected 2026-09-28 09:09:22 UTC 45,853 bytes, 26 lines download raw bytes

1import{cn as I,aR as H,bq as O,cC as ce,cD as fe,cE as pe,cx as w,eg as M,aU as K,a_ as $,bl as Pe,cy as b,ej as G,c9 as Y,ca as V,br as Re,cb as Ee,aV as u,b2 as C,b3 as l,b1 as a,b6 as o,bg as i,aW as f,bh as g,bR as s,bt as q,c1 as se,bm as me,bn as le,bc as j}from"./c-index-C7aDQtMU.js";import{e as Q,c as ge,d as ye,b as _e,k as he,l as ve}from"./c-el-form-item-lGG0C5Mp.js";import{E as J}from"./c-el-pagination-Cw8uBw8d.js";import{E as N,a as B}from"./c-el-table-column-CQPKwBzb.js";import"./c-el-checkbox-yCtUXoWo.js";import{l as oe,E as Se}from"./e-front-BYMFT9Ax.js";import{S as Te}from"./c-SitesSelector-D8pJ-hs-.js";import{d as Fe}from"./c-debounce-C9zzGgaU.js";import{E as ke}from"./c-index-BVAx5QAs.js";/* empty css                     */import{f as be}from"./c-common-Fsnd349q.js";import{S as $e}from"./c-StandardListWrapper-XFfB7TYH.js";import{o as Ie}from"./c-orderBy-DeVN7W4v.js";import"./c-merge-B_kft1BI.js";import"./c-isArrayLikeObject-B68eDwjp.js";import"./c-map-D11rV1oF.js";import"./c-_baseMap-Cu2k9MJB.js";import"./c-el-select-v2-D6a1IT9B.js";import"./c-el-virtual-list-B1kIuwhn.js";import"./c-FrontendInterfaces-CP3Br6r3.js";import"./c-_baseOrderBy-DHaiweXL.js";async function ie(e,t){var T;const L={};t.value&&(L["If-None-Match"]=t.value);const P=await I.get(e,{headers:L,validateStatus:R=>R===200||R===304});return P.status===304?null:(t.value=((T=P.headers)==null?void 0:T.etag)??null,P.data)}const ze={value:null},De=async()=>ie("admin/files-actualizator/normalize/status",ze),X=()=>{ze.value=null},Ue=async e=>{await I.post("admin/files-actualizator/normalize/mode",{mode:e})},Ae=async e=>{const{data:t}=await I.post(`admin/files-actualizator/normalize/approve/${e}`);return t},we=async e=>{await I.post(`admin/files-actualizator/normalize/reject/${e}`)},Me=async()=>{const{data:e}=await I.delete("admin/files-actualizator/normalize/tasks");return e},Ce={value:null},Ne=async()=>ie("admin/files-actualizator/cleanup/status",Ce),Z=()=>{Ce.value=null},Be=async()=>{const{data:e}=await I.post("admin/files-actualizator/cleanup/rescan");return e},Ve=async e=>{const{data:t}=await I.post(`admin/files-actualizator/cleanup/delete/${e}`);return t},je=async e=>{const{data:t}=await I.post(`admin/files-actualizator/cleanup/force-delete/${e}`);return t},qe=async e=>{const{data:t}=await I.get("admin/files-actualizator/list",{params:e});return t},Oe=async()=>{const{data:e}=await I.get("admin/files-actualizator/list/extensions");return e},ee=async()=>{const{data:e}=await I.get("admin/files-actualizator/list/retention-stats");return e},We=async e=>{await I.post(`admin/files-actualizator/list/soft-delete/${e}`)},xe=async e=>{const{data:t}=await I.post(`admin/files-actualizator/list/restore/${e}`);return t},Ge=async e=>{const{data:t}=await I.post(`admin/files-actualizator/list/force-delete/${e}`);return t},He=async e=>{await I.post(`admin/files-actualizator/list/retry-s3/${e}`)},Le={value:null},Ye=async()=>ie("admin/materials-cleanup/stats",Le),ue=()=>{Le.value=null},de=async()=>{await I.post("admin/materials-cleanup/rescan")},Ke=async(e,t)=>{const{data:L}=await I.post(`admin/materials-cleanup/cleanup/${e}`,{mode:t});return L},Qe="https://782329.selcdn.ru/leonardo/",Je=H({components:{SitesSelector:Te,ElCard:Q,ElTable:B,ElTableColumn:N,ElTag:M,ElButton:w,ElInput:pe,ElSelect:fe,ElOption:ce,ElPagination:J,ElTooltip:O},setup(){const e=$([]),t=$([]),L=$(null),P=$(!1),T=$(null),R=$(null),_=$(null),z=$({total:0,currentPage:1,perPage:30,lastPage:1}),y=Pe({q:"",siteId:null,extension:"",deleted:"all",currentPage:1,perPage:30,sortProp:"id",sortOrder:"descending"});async function h(){P.value=!0;try{const p={...y,siteId:y.siteId||void 0,q:y.q||void 0,extension:y.extension||void 0},A=await qe(p);e.value=A.items,z.value=A.meta}catch{b.error("Ошибка загрузки списка файлов")}finally{P.value=!1}}const S=Fe(h,400);K(async()=>{var W;const[,p,A]=await Promise.all([h(),Oe(),ee()]);t.value=p,L.value=A,(W=oe)==null||W.close()});function v(){y.currentPage=1,S()}function m(p){y.currentPage=p,h()}function F(p){y.perPage=p,y.currentPage=1,h()}function n({prop:p,order:A}){y.sortProp=p||"id",y.sortOrder=A==="ascending"?"ascending":"descending",y.currentPage=1,h()}async function E(p){try{await G.confirm(`Пометить файл к удалению?
2
3${p.path}
4
5Файл станет недоступен по публичной ссылке. Физически (все версии S3) будет удалён через 2 месяца.`,"Удалить файл",{confirmButtonText:"Пометить",cancelButtonText:"Отмена",type:"warning"})}catch{return}try{await We(p.id),b.success("Файл помечен к удалению и скрыт в S3"),await h()}catch{b.error("Ошибка при удалении")}}async function U(p){R.value=p.id;try{const A=await xe(p.id);b.success(A.s3Restored?"Файл восстановлен":"Пометка снята (S3 delete marker не найден)"),await h()}catch{b.error("Ошибка при восстановлении")}finally{R.value=null}}async function c(p){try{await G.confirm(`Удалить все версии файла из S3 немедленно?
6
7${p.path}
8
9Это действие необратимо.`,"Удалить окончательно",{confirmButtonText:"Удалить",cancelButtonText:"Отмена",type:"error"})}catch{return}T.value=p.id;try{const A=await Ge(p.id);b.success(`Удалено версий: ${A.purgedVersions}`),L.value=await ee(),await h()}catch{b.error("Ошибка при удалении")}finally{T.value=null}}async function d(p){_.value=p.id;try{await He(p.id),b.success("Ошибка сброшена — файл снова в автоматике retention"),L.value=await ee(),await h()}catch{b.error("Ошибка при сбросе")}finally{_.value=null}}function r(p){return p?p.startsWith("http")?p:Qe+(p.startsWith("/")?p.slice(1):p):""}
9function k(p){return p?new Date(p).toLocaleString("ru-RU"):"—"}function D(p){return p>=1073741824?(p/1073741824).toFixed(1)+" ГБ":p>=1048576?(p/1048576).toFixed(1)+" МБ":p>=1024?(p/1024).toFixed(1)+" КБ":p+" Б"}return{items:e,extensions:t,retentionStats:L,loading:P,forcingId:T,restoringId:R,retryingId:_,meta:z,filters:y,onFilterChange:v,onPageChange:m,onSizeChange:F,onSortChange:n,onSoftDelete:E,onRestore:U,onForceDelete:c,onRetryS3:d,buildFileUrl:r,formatDate:k,formatSize:D}}}),Xe={class:"flex flex-wrap gap-3 items-center"},Ze={key:0,class:"ml-auto flex gap-2 text-sm text-gray-500 flex-wrap"},et={class:"show-of"},tt={class:"text-xs text-gray-500"},at={key:0,class:"text-xs"},nt=["href"],st={key:1,class:"text-xs font-mono break-all text-gray-400 line-through"},lt={key:0,class:"text-xs break-all"},ot={key:1,class:"text-xs text-gray-300"},it={class:"text-xs"},rt={class:"text-xs"},ut={class:"text-xs"},dt={key:0,class:"flex gap-1 justify-center flex-wrap"},ct={key:1,class:"flex gap-1 justify-center"},ft={key:2,class:"flex gap-1 justify-center"},pt={key:3,class:"text-xs text-gray-400"};function mt(e,t,L,P,T,R){const _=pe,z=V("SitesSelector"),y=ce,h=fe,S=M,v=N,m=M,F=O,n=w,E=B,U=J,c=Q,d=Ee;return Re((u(),C(c,null,{header:l(()=>[a("div",Xe,[i(_,{modelValue:e.filters.q,"onUpdate:modelValue":t[0]||(t[0]=r=>e.filters.q=r),placeholder:"Поиск по пути или названию",clearable:"",style:{width:"260px"},onInput:e.onFilterChange},null,8,["modelValue","onInput"]),i(z,{modelValue:e.filters.siteId,"onUpdate:modelValue":[t[1]||(t[1]=r=>e.filters.siteId=r),e.onFilterChange],mode:"all",style:{width:"240px"}},null,8,["modelValue","onUpdate:modelValue"]),i(h,{modelValue:e.filters.extension,"onUpdate:modelValue":t[2]||(t[2]=r=>e.filters.extension=r),placeholder:"Расширение",clearable:"",style:{width:"140px"},filterable:!0,onChange:e.onFilterChange},{default:l(()=>[(u(!0),f(q,null,se(e.extensions,r=>(u(),C(y,{key:r,label:r.length>50?`.${r.slice(0,47)}…`:`.${r}`,value:r},null,8,["label","value"]))),128))]),_:1},8,["modelValue","onChange"]),i(h,{modelValue:e.filters.deleted,"onUpdate:modelValue":t[3]||(t[3]=r=>e.filters.deleted=r),style:{width:"200px"},onChange:e.onFilterChange},{default:l(()=>[i(y,{label:"Все",value:"all"}),i(y,{label:"Активные",value:"none"}),i(y,{label:"Помечены к удалению",value:"soft"}),i(y,{label:"Физически удалены",value:"real"}),i(y,{label:"С ошибками S3",value:"error"},{default:l(()=>[t[4]||(t[4]=a("span",null,"С ошибками S3",-1)),e.retentionStats&&e.retentionStats.withErrors>0?(u(),C(S,{key:0,type:"danger",size:"small",class:"ml-1"},{default:l(()=>[s(o(e.retentionStats.withErrors),1)]),_:1})):g("",!0)]),_:1})]),_:1},8,["modelValue","onChange"]),e.retentionStats?(u(),f("div",Ze,[e.retentionStats.pendingSoftDelete>0?(u(),C(S,{key:0,type:"info",effect:"plain",size:"small"},{default:l(()=>[s(" Ждут скрытия в S3: "+o(e.retentionStats.pendingSoftDelete),1)]),_:1})):g("",!0),e.retentionStats.scheduled>0?(u(),C(S,{key:1,type:"warning",effect:"plain",size:"small"},{default:l(()=>[s(" Скрыты, ждут purge: "+o(e.retentionStats.scheduled),1)]),_:1})):g("",!0),e.retentionStats.expired>0?(u(),C(S,{key:2,type:"danger",effect:"plain",size:"small"},{default:l(()=>[s(" Просрочены: "+o(e.retentionStats.expired),1)]),_:1})):g("",!0),e.retentionStats.withErrors>0?(u(),C(S,{key:3,type:"danger",effect:"dark",size:"small"},{default:l(()=>[s(" Ошибки S3: "+o(e.retentionStats.withErrors),1)]),_:1})):g("",!0)])):g("",!0)])]),default:l(()=>[a("p",et,"Показано "+o(e.items.length)+" из "+o(e.meta.total),1),i(E,{data:e.items,border:!0,style:{width:"100%"},onSortChange:e.onSortChange},{default:l(()=>[i(v,{prop:"id",label:"ID",width:"100",sortable:"custom"}),i(v,{label:"Сайт",width:"200"},{default:l(({row:r})=>[a("span",tt,o(r.site_id),1),r.site_name?(u(),f("div",at,o(r.site_name),1)):g("",!0)]),_:1}),i(v,{label:"Файл","min-width":"260"},{default:l(({row:r})=>[!r.soft_deleted_at&&!r.real_deleted_at?(u(),f("a",{key:0,href:e.buildFileUrl(r.path),target:"_blank",class:"text-xs font-mono break-all text-blue-600 hover:underline"},o(r.path),9,nt)):(u(),f("span",st,o(r.path),1))]),_:1}),i(v,{label:"Название","min-width":"160"},{default:l(({row:r})=>
9[r.title?(u(),f("span",lt,o(r.title),1)):(u(),f("span",ot,"—"))]),_:1}),i(v,{prop:"extension",label:"Ext",width:"90",sortable:"custom"},{default:l(({row:r})=>[a("span",it,o(r.extension?`.${r.extension}`:"—"),1)]),_:1}),i(v,{prop:"size",label:"Размер",width:"200",sortable:"custom",align:"right"},{default:l(({row:r})=>[a("span",rt,o(r.size?e.formatSize(r.size):"—"),1)]),_:1}),i(v,{prop:"created_at",label:"Создан",width:"230",sortable:"custom"},{default:l(({row:r})=>[a("span",ut,o(e.formatDate(r.created_at)),1)]),_:1}),i(v,{label:"Статус",width:"260"},{default:l(({row:r})=>[a("div",null,[r.real_deleted_at?(u(),C(m,{key:0,type:"danger",size:"small",effect:"plain"},{default:l(()=>[...t[5]||(t[5]=[s("Удалён",-1)])]),_:1})):r.soft_deleted_at?(u(),C(m,{key:1,type:"warning",size:"small",effect:"plain"},{default:l(()=>[s(" К удалению "+o(e.formatDate(r.soft_deleted_at)),1)]),_:2},1024)):(u(),C(m,{key:2,type:"success",size:"small",effect:"plain"},{default:l(()=>[...t[6]||(t[6]=[s("Активен",-1)])]),_:1}))]),r.s3_error?(u(),C(F,{key:0,content:r.s3_error,placement:"top","show-after":200},{default:l(()=>[i(m,{type:"danger",size:"small",effect:"dark",class:"mt-1 cursor-pointer",style:{"max-width":"230px",overflow:"hidden","text-overflow":"ellipsis","white-space":"nowrap"}},{default:l(()=>[...t[7]||(t[7]=[s(" Ошибка S3 ",-1)])]),_:1})]),_:1},8,["content"])):g("",!0)]),_:1}),i(v,{fixed:"right",label:"Действия",width:"300",align:"center"},{default:l(({row:r})=>[r.s3_error&&!r.real_deleted_at?(u(),f("div",dt,[i(F,{content:"Сбросить ошибку — файл снова попадёт в автоматику retention"},{default:l(()=>[i(n,{type:"primary",size:"small",loading:e.retryingId===r.id,onClick:k=>e.onRetryS3(r)},{default:l(()=>[...t[8]||(t[8]=[s(" Повторить ",-1)])]),_:1},8,["loading","onClick"])]),_:2},1024),i(n,{type:"success",size:"small",loading:e.restoringId===r.id,onClick:k=>e.onRestore(r)},{default:l(()=>[...t[9]||(t[9]=[s(" Восстановить ",-1)])]),_:1},8,["loading","onClick"])])):!r.soft_deleted_at&&!r.real_deleted_at?(u(),f("div",ct,[i(n,{type:"warning",size:"small",onClick:k=>e.onSoftDelete(r)},{default:l(()=>[...t[10]||(t[10]=[s("Удалить",-1)])]),_:1},8,["onClick"])])):r.soft_deleted_at&&!r.real_deleted_at?(u(),f("div",ft,[i(n,{type:"success",size:"small",loading:e.restoringId===r.id,onClick:k=>e.onRestore(r)},{default:l(()=>[...t[11]||(t[11]=[s(" Восстановить ",-1)])]),_:1},8,["loading","onClick"]),i(F,{content:"Удалить все версии из S3 немедленно"},{default:l(()=>[i(n,{type:"danger",size:"small",loading:e.forcingId===r.id,onClick:k=>e.onForceDelete(r)},{default:l(()=>[...t[12]||(t[12]=[s(" Удалить навсегда ",-1)])]),_:1},8,["loading","onClick"])]),_:2},1024)])):(u(),f("span",pt,"—"))]),_:1})]),_:1},8,["data","onSortChange"]),e.meta.total>0?(u(),C(U,{key:0,class:"mt-3","current-page":e.filters.currentPage,"page-size":e.filters.perPage,total:e.meta.total,layout:"prev, pager, next, sizes, total","page-sizes":[15,30,50,100],onCurrentChange:e.onPageChange,onSizeChange:e.onSizeChange},null,8,["current-page","page-size","total","onCurrentChange","onSizeChange"])):g("",!0)]),_:1})),[[d,e.loading]])}const gt=Y(Je,[["render",mt]]),yt=3e3,te=15,_t=["sourcePath","newPath","status"],ht=H({components:{StandardListWrapper:$e,ElTable:B,ElTableColumn:N,ElTag:M,ElButton:w,ElPopover:ke,ElRadioGroup:ye,ElRadioButton:ge},setup(){const e=$({running:!1,mode:"semi",lastActivity:null,tasks:[],counts:{pending:0,done:0,rejected:0,error:0}}),t=$(""),L=$(1),P=$(!1),T=$("semi");let R=null,_=!1;const z=j(()=>be(e.value.tasks,_t,t.value)),y=j(()=>{const c=(L.value-1)*te;return Ie(z.value,["createdAt"],["desc"]).slice(c,c+te)});me(t,()=>{L.value=1});async function h(){var c;try{const d=await De();d&&(e.value=d,T.value=d.mode),_||(_=!0,(c=oe)==null||c.close())}catch{}}K(async()=>{P.value=!0,await h(),P.value=!1,R=setInterval(h,yt)}),le(()=>{R&&clearInterval(R)});async function S(c){try{await Ue(c),b.success(`Режим: ${c==="semi"?"Полуавтомат":"Автопилот"}`)}catch{b.error("Не удалось сменить режим")}}async function v(c){var d,r;try{await Ae(c.taskId),b.success("Файл перенесён"),X(),await h()}catch(k){b.error(((r=(d=k==null?void 0:k.response)==null?void 0:d.data)==null?void 0:r.error)||"Ошибка при переносе файла")}}async function m(c){try{await we(c.taskId),X(),await h()}catch{b.error("Не удалось отклонить задачу")}}async function F(){try{const{cleared:c}=await Me();b.success(`Очищено ${c} записей`),X(),await h()}catch{b.error("Ошибка при очистке")}}function n(c){return{pending:"warning",done:"success",rejected:"info",error:"danger"}[c]??"info"}function E(c){return{pending:"Ожидает",done:"Выполнено",rejected:"Отклонено",error:"Ошибка",approved:"Одобрено"}[c]??c}
9function U(c){return new Date(c).toLocaleString("ru-RU")}return{status:e,q:t,currentPage:L,loading:P,mode:T,perPage:te,cpFiltered:z,filteredAndPaginatedCurrentPage:y,onModeChange:S,onApprove:v,onReject:m,onClearCompleted:F,statusTagType:n,statusLabel:E,formatDate:U}}}),vt={class:"flex items-center gap-3"},St={class:"flex items-center gap-3"},kt={class:"flex gap-2"},bt={class:"text-xs font-mono leading-tight"},$t={class:"line-through text-gray-400 break-all"},zt={class:"text-green-700 break-all"},Ct={class:"flex flex-wrap gap-1"},Lt={key:0},Pt={class:"text-xs"},Rt={key:0,class:"flex gap-1"},Et={key:1,class:"text-xs text-red-500 break-all"},Tt={key:2},Ft={class:"text-xs font-mono max-h-48 overflow-y-auto"};function It(e,t,L,P,T,R){const _=M,z=ge,y=ye,h=w,S=N,v=ke,m=B,F=V("StandardListWrapper");return u(),C(F,{q:e.q,"onUpdate:q":t[1]||(t[1]=n=>e.q=n),currentPage:e.currentPage,"onUpdate:currentPage":t[2]||(t[2]=n=>e.currentPage=n),loading:e.loading,allLength:e.cpFiltered.length,filteredLength:e.cpFiltered.length,perPage:e.perPage},{beforeSearchRowSlot:l(()=>[a("div",vt,[i(_,{type:e.status.running?"success":"info",effect:"dark"},{default:l(()=>[s(o(e.status.running?"Запущена":"Остановлена"),1)]),_:1},8,["type"]),i(y,{modelValue:e.mode,"onUpdate:modelValue":t[0]||(t[0]=n=>e.mode=n),size:"small",onChange:e.onModeChange},{default:l(()=>[i(z,{label:"semi"},{default:l(()=>[...t[3]||(t[3]=[s("Полуавтомат",-1)])]),_:1}),i(z,{label:"auto"},{default:l(()=>[...t[4]||(t[4]=[s("Автопилот",-1)])]),_:1})]),_:1},8,["modelValue","onChange"])])]),searchRowSlot:l(()=>[a("div",St,[a("div",kt,[i(_,{type:"warning",effect:"plain"},{default:l(()=>[s("Ожидают: "+o(e.status.counts.pending),1)]),_:1}),i(_,{type:"success",effect:"plain"},{default:l(()=>[s("Выполнено: "+o(e.status.counts.done),1)]),_:1}),i(_,{type:"info",effect:"plain"},{default:l(()=>[s("Отклонено: "+o(e.status.counts.rejected),1)]),_:1}),e.status.counts.error?(u(),C(_,{key:0,type:"danger",effect:"plain"},{default:l(()=>[s("Ошибок: "+o(e.status.counts.error),1)]),_:1})):g("",!0)]),e.status.counts.done>0||e.status.counts.rejected>0?(u(),C(h,{key:0,size:"small",onClick:e.onClearCompleted},{default:l(()=>[...t[5]||(t[5]=[s(" Очистить выполненные ",-1)])]),_:1},8,["onClick"])):g("",!0)])]),default:l(()=>[i(m,{data:e.filteredAndPaginatedCurrentPage,border:!0,style:{width:"100%"}},{default:l(()=>[i(S,{label:"Статус",width:"110"},{default:l(({row:n})=>[i(_,{type:e.statusTagType(n.status),size:"small",effect:"plain"},{default:l(()=>[s(o(e.statusLabel(n.status)),1)]),_:2},1032,["type"])]),_:1}),i(S,{label:"Сайт",width:"80"},{default:l(({row:n})=>[s(o(n.siteId),1)]),_:1}),i(S,{label:"Файл (откуда → куда)","min-width":"320"},{default:l(({row:n})=>[a("div",bt,[a("div",$t,o(n.sourcePath),1),a("div",zt,"→ "+o(n.newPath),1)])]),_:1}),i(S,{label:"Найдено в","min-width":"200"},{default:l(({row:n})=>[a("div",Ct,[(u(!0),f(q,null,se(n.foundIn,(E,U)=>(u(),C(_,{key:U,size:"small",type:"info",effect:"plain"},{default:l(()=>[s(o(E.table)+"."+o(E.column)+" #"+o(E.rowId)+" ",1),E.occurrences>1?(u(),f("span",Lt,"("+o(E.occurrences)+"×)",1)):g("",!0)]),_:2},1024))),128))])]),_:1}),i(S,{label:"Создана",width:"140"},{default:l(({row:n})=>[a("span",Pt,o(e.formatDate(n.createdAt)),1)]),_:1}),i(S,{fixed:"right",label:"Действия",width:"200"},{default:l(({row:n})=>[n.status==="pending"?(u(),f("div",Rt,[i(h,{type:"success",size:"small",onClick:E=>e.onApprove(n)},{default:l(()=>[...t[6]||(t[6]=[s("ОК",-1)])]),_:1},8,["onClick"]),i(h,{type:"default",size:"small",onClick:E=>e.onReject(n)},{default:l(()=>[...t[7]||(t[7]=[s("Отклонить",-1)])]),_:1},8,["onClick"])])):n.status==="error"?(u(),f("div",Et,o(n.errorMessage),1)):n.log.length>0?(u(),f("div",Tt,[i(v,{placement:"left",width:400,trigger:"click"},{reference:l(()=>[i(h,{size:"small",type:"text"},{default:l(()=>[...t[8]||(t[8]=[s("Лог",-1)])]),_:1})]),default:l(()=>[a("div",Ft,[(u(!0),f(q,null,se(n.log,(E,U)=>(u(),f("div",{key:U},o(E),1))),128))])]),_:2},1024)])):g("",!0)]),_:1})]),_:1},8,["data"])]),_:1},8,["q","currentPage","loading","allLength","filteredLength","perPage"])}const Dt=Y(ht,[["render",It]]),Ut=3e3,ae=15,At=["siteName","siteId"],wt=H({components:{StandardListWrapper:$e,ElTable:B,ElTableColumn:N,ElTag:M,ElButton:w,ElTooltip:O},setup(){const e=$({running:!1,lastActivity:null,sites:[],totalFiles:0,totalSizeBytes:0,storageCost:{perMonth:0,perYear:0,sizeGb:0}}),t=$(""),L=$(1),P=$(!1),T=$(!1),R=$(null),_=$(null);let z=null,y=!1;const h=j(()=>be(e.value.sites,At,t.value)),S=j(()=>{const c=(L.value-1)*ae;return h.value.slice(c,c+ae)});me(t,()=>{L.value=1});async function v(){var c;try{const d=await Ne();d&&(e.value=d),y||(y=!0,(c=oe)==null||c.close())}catch{}}K(async()=>{P.value=!0,await v(),P.value=!1,z=setInterval(v,Ut)}),le(()=>{z&&clearInterval(z)});async function m(){T.value=!0;try{await Be(),Z(),await v(),b.success("Список обновлён")}catch{b.error("Ошибка при сканировании")}finally{T.value=!1}}async function F(c){var d,r;try{await G.confirm(`Пометить ${c.activeFiles.toLocaleStr
9ing("ru-RU")} файлов сайта "${c.siteName}" (${U(c.totalSizeBytes)}) к удалению?
10
11Файлы будут скрыты в S3 процессом cleanup. Физически удалятся через 2 месяца.`,"Подтвердите удаление",{confirmButtonText:"Да, пометить",cancelButtonText:"Отмена",type:"warning"})}catch{return}R.value=c.siteId,_.value="soft";try{const k=await Ve(c.siteId);b.success(`Помечено к удалению: ${k.marked} файлов. S3 обработает процесс cleanup.`),Z(),await v()}catch(k){b.error(((r=(d=k==null?void 0:k.response)==null?void 0:d.data)==null?void 0:r.error)||"Ошибка")}finally{R.value=null,_.value=null}}async function n(c){var d,r;try{await G.confirm(`Безвозвратно удалить ВСЕ файлы сайта "${c.siteName}" (${c.softDeletedFiles} файлов)?
12
13Retention процесс удалит все версии из S3. Восстановление будет невозможно.`,"Удалить навсегда",{confirmButtonText:"Удалить безвозвратно",cancelButtonText:"Отмена",type:"error"})}catch{return}R.value=c.siteId,_.value="force";try{const k=await je(c.siteId);b.success(`${k.marked} файлов передано retention процессу для полного удаления.`),Z(),await v()}catch(k){b.error(((r=(d=k==null?void 0:k.response)==null?void 0:d.data)==null?void 0:r.error)||"Ошибка")}finally{R.value=null,_.value=null}}function E(c){return new Date(c).toLocaleString("ru-RU")}function U(c){return c>=1073741824?(c/1073741824).toFixed(1)+" ГБ":c>=1048576?(c/1048576).toFixed(1)+" МБ":c>=1024?(c/1024).toFixed(1)+" КБ":c+" Б"}return{status:e,q:t,currentPage:L,loading:P,rescanning:T,actionId:R,actionType:_,perPage:ae,cpFiltered:h,filteredAndPaginatedCurrentPage:S,onRescan:m,onMarkForDeletion:F,onForceDelete:n,formatDate:E,formatSize:U}}}),Mt={class:"flex items-center gap-3"},Nt={key:0,class:"flex items-center gap-3 text-sm text-gray-600 flex-wrap"},Bt={key:0,class:"text-orange-600"},Vt={class:"text-xs"},jt={class:"text-orange-600"},qt={class:"text-xs text-gray-400"},Ot={key:0},Wt={key:1},xt={key:2},Gt={class:"text-xs text-gray-400 ml-1"},Ht={key:3,class:"mt-1"},Yt={class:"flex gap-1 justify-center flex-wrap"};function Kt(e,t,L,P,T,R){const _=M,z=w,y=N,h=O,S=B,v=V("StandardListWrapper");return u(),C(v,{q:e.q,"onUpdate:q":t[0]||(t[0]=m=>e.q=m),currentPage:e.currentPage,"onUpdate:currentPage":t[1]||(t[1]=m=>e.currentPage=m),loading:e.loading,allLength:e.cpFiltered.length,filteredLength:e.cpFiltered.length,perPage:e.perPage},{beforeSearchRowSlot:l(()=>[a("div",Mt,[i(_,{type:e.status.running?"success":"info",effect:"dark"},{default:l(()=>[s(o(e.status.running?"Сканирование активно":"Остановлено"),1)]),_:1},8,["type"]),i(z,{size:"small",loading:e.rescanning,onClick:e.onRescan},{default:l(()=>[...t[2]||(t[2]=[s(" Пересканировать ",-1)])]),_:1},8,["loading","onClick"])])]),searchRowSlot:l(()=>[e.status.sites.length>0?(u(),f("div",Nt,[a("span",null,[t[3]||(t[3]=s("Удал. Сайтов: ",-1)),a("strong",null,o(e.status.sites.length),1)]),a("span",null,[t[4]||(t[4]=s("Файлов: ",-1)),a("strong",null,o(e.status.totalFiles.toLocaleString("ru-RU")),1)]),a("span",null,[t[5]||(t[5]=s("Размер: ",-1)),a("strong",null,o(e.formatSize(e.status.totalSizeBytes)),1)]),e.status.storageCost?(u(),f("span",Bt,[t[6]||(t[6]=s(" Стоимость: ",-1)),a("strong",null,o(e.status.storageCost.perMonth)+" ₽/мес",1),s(" ("+o(e.status.storageCost.perYear)+" ₽/год) ",1)])):g("",!0)])):g("",!0)]),default:l(()=>[i(S,{data:e.filteredAndPaginatedCurrentPage,border:!0,style:{width:"100%"}},{default:l(()=>[i(y,{prop:"siteId",label:"ID",width:"80"}),i(y,{prop:"siteName",label:"Сайт","min-width":"180"}),i(y,{label:"Удалён",width:"140"},{default:l(({row:m})=>[s(o(e.formatDate(m.deletedAt)),1)]),_:1}),i(y,{label:"Файлов",width:"100",align:"right"},{default:l(({row:m})=>
13[s(o(m.totalFiles.toLocaleString("ru-RU")),1)]),_:1}),i(y,{label:"Размер",width:"110",align:"right"},{default:l(({row:m})=>[a("strong",null,o(e.formatSize(m.totalSizeBytes)),1)]),_:1}),i(y,{label:"Стоимость",width:"160",align:"right"},{default:l(({row:m})=>[a("div",Vt,[a("strong",jt,o(m.storageCostPerMonth)+" ₽/мес",1)]),a("div",qt,o(m.storageCostPerYear)+" ₽/год",1)]),_:1}),i(y,{label:"Статус",width:"220"},{default:l(({row:m})=>[m.activeFiles>0&&m.softDeletedFiles===0?(u(),f("div",Ot,[i(_,{type:"info",size:"small",effect:"plain"},{default:l(()=>[...t[7]||(t[7]=[s("Не помечено",-1)])]),_:1})])):m.activeFiles===0&&m.softDeletedFiles>0?(u(),f("div",Wt,[i(_,{type:"warning",size:"small",effect:"plain"},{default:l(()=>[s(" Все помечены ("+o(m.softDeletedFiles)+") ",1)]),_:2},1024)])):(u(),f("div",xt,[i(_,{type:"warning",size:"small",effect:"plain"},{default:l(()=>[s(o(m.softDeletedFiles)+" помечено ",1)]),_:2},1024),a("span",Gt,"/ "+o(m.activeFiles)+" активно",1)])),m.errorsCount>0?(u(),f("div",Ht,[i(_,{type:"danger",size:"small",effect:"dark"},{default:l(()=>[s(o(m.errorsCount)+" с ошибками S3 ",1)]),_:2},1024)])):g("",!0)]),_:1}),i(y,{fixed:"right",label:"Действия",width:"280",align:"center"},{default:l(({row:m})=>[a("div",Yt,[m.activeFiles>0?(u(),C(z,{key:0,type:"warning",size:"small",loading:e.actionId===m.siteId&&e.actionType==="soft",onClick:F=>e.onMarkForDeletion(m)},{default:l(()=>[...t[8]||(t[8]=[s(" Удалить файлы ",-1)])]),_:1},8,["loading","onClick"])):g("",!0),m.softDeletedFiles>0?(u(),C(h,{key:1,content:"Сдвигает дату удаления, retention процесс удалит все версии из S3"},{default:l(()=>[i(z,{type:"danger",size:"small",loading:e.actionId===m.siteId&&e.actionType==="force",onClick:F=>e.onForceDelete(m)},{default:l(()=>[...t[9]||(t[9]=[s(" Удалить навсегда ",-1)])]),_:1},8,["loading","onClick"])]),_:2},1024)):g("",!0)])]),_:1})]),_:1},8,["data"])]),_:1},8,["q","currentPage","loading","allLength","filteredLength","perPage"])}const Qt=Y(wt,[["render",Kt]]),ne=20,Jt=5e3,Xt={sites:null,calculatedAt:null,calculating:!1,startedAt:null},Zt=H({name:"MaterialsCleanup",components:{ElTable:B,ElTableColumn:N,ElTag:M,ElButton:w,ElPagination:J,ElEmpty:Se,ElAlert:_e,ElTooltip:O},setup(){const e=$({...Xt}),t=$(!1),L=$(1),P=$(null),T=$(null),R=ne;let _=null;const z=j(()=>(e.value.sites??[]).reduce((d,r)=>d+r.deleted.total.bytes,0)),y=j(()=>(e.value.sites??[]).reduce((d,r)=>d+r.all.total.bytes,0)),h=j(()=>
13{if(!e.value.sites)return[];const d=(L.value-1)*ne;return e.value.sites.slice(d,d+ne)});async function S(){try{const d=await Ye();d!==null&&(e.value=d)}catch{}}K(async()=>{await S(),_=setInterval(S,Jt)}),le(()=>{_&&clearInterval(_)});async function v(){var d;t.value=!0;try{await de(),ue(),await S(),b.info("Пересчёт запущен. Данные обновятся автоматически.")}catch(r){((d=r==null?void 0:r.response)==null?void 0:d.status)===409?b.warning("Пересчёт уже идёт"):b.error("Ошибка запуска пересчёта")}finally{t.value=!1}}async function m(d,r){var W,re;const k=r==="all",D=k?d.all:d.deleted,p=[];D.contents.count&&p.push(`Материалы: ${D.contents.count.toLocaleString("ru-RU")}`),D.blocks.count&&p.push(`Блоки: ${D.blocks.count.toLocaleString("ru-RU")}`),D.sections.count&&p.push(`Секции: ${D.sections.count.toLocaleString("ru-RU")}`),D.revisions.count&&p.push(`Ревизии: ${D.revisions.count.toLocaleString("ru-RU")}`),D.formResults.count&&p.push(`Заявки: ${D.formResults.count.toLocaleString("ru-RU")}`),D.attachments.count&&p.push(`Вложения S3: ${D.attachments.count.toLocaleString("ru-RU")}`);const A=k?`Будет удалено ВСЁ содержимое сайта "${d.siteName}".
14Останется только запись сайта и пользователь.
15
16ЭТО ДЕЙСТВИЕ НЕОБРАТИМО!
17
18${p.join(`
19`)}
20
21Освобождается: ${E(D.total.bytes)}`:`Будет удалено (удалённые${d.siteStatus==="active"?" > 1 мес":""}):
22
23${p.join(`
24`)}
25
26Освобождается: ${E(D.total.bytes)}`;try{await G.confirm(A,k?`Полная очистка: ${d.siteName}`:`Удаление устаревших: ${d.siteName}`,{confirmButtonText:k?"Удалить всё":"Удалить",cancelButtonText:"Отмена",type:k?"error":"warning"})}catch{return}P.value=d.siteId,T.value=r;try{const x=await Ke(d.siteId,r);b.success(`Удалено записей: ${x.total.toLocaleString("ru-RU")}`),ue(),de().catch(()=>{}),await S()}catch(x){b.error(((re=(W=x==null?void 0:x.response)==null?void 0:W.data)==null?void 0:re.error)||"Ошибка при очистке")}finally{P.value=null,T.value=null}}function F(d){return d==="active"?"success":d==="deleted"?"danger":"warning"}function n(d){return d==="active"?"Активный":d==="deleted"?"Удалён":"Неактивный"}function E(d){return d>=1073741824?(d/1073741824).toFixed(1)+" ГБ":d>=1048576?(d/1048576).toFixed(1)+" МБ":d>=1024?(d/1024).toFixed(1)+" КБ":d+" Б"}function U(d){return new Date(d).toLocaleDateString("ru-RU")}function c(d){return new Date(d).toLocaleString("ru-RU")}return{state:e,rescanning:t,currentPage:L,actionId:P,actionMode:T,perPage:R,grandTotalDeleted:z,grandTotalAll:y,paginatedRows:h,onRescan:v,onCleanup:m,statusTagType:F,statusLabel:n,formatSize:E,formatDate:U,formatDateTime:c}}}),ea={class:"flex items-center gap-3 mb-4 flex-wrap"},ta={key:0,class:"text-sm text-gray-500"},aa={key:1,class:"text-sm text-gray-500"},na={class:"text-sm text-gray-500"},sa={key:0,class:"text-sm text-orange-600"},la={key:1,class:"text-sm text-red-600"},oa={key:0},ia={key:0},ra={class:"flex items-center gap-2"},ua={class:"font-medium"},da={class:"text-xs text-gray-400"},ca={key:0,class:"text-xs text-gray-400 mt-1"},fa={class:"text-sm font-semibold text-orange-600 mb-1"},pa={class:"text-gray-500 font-normal"},ma={class:"text-xs text-gray-500 space-y-0.5"},ga={key:0},ya={class:"text-gray-400"},_a={key:1},ha={class:"text-gray-400"},va={key:2},Sa={class:"text-gray-400"},ka={key:3},ba={class:"text-gray-400"},$a={key:4},za={class:"text-gray-400"},Ca={key:5},La={class:"text-gray-400"},Pa={key:1,class:"text-xs text-gray-400"},Ra={class:"text-sm font-semibold text-red-600 mb-1"},Ea={class:"text-gray-500 font-normal"},Ta={class:"text-xs text-gray-500 space-y-0.5"},Fa={key:0},Ia={class:"text-gray-400"},Da={key:1},Ua={class:"text-gray-400"},Aa={key:2},wa={class:"text-gray-400"},Ma={key:3},Na={class:"text-gray-400"},Ba={key:4},Va={class:"text-gray-400"},ja={key:5},qa={class:"text-gray-400"},Oa={key:1,class:"text-xs text-gray-400"},Wa={class:"flex flex-col gap-1 items-center"},xa={key:4,class:"flex justify-center mt-4"};function Ga(e,t,L,P,T,R){const _=M,z=w,y=O,h=Se,S=_e,v=N,m=B,F=J;return u(),f("div",null,[a("div",ea,[i(_,{type:e.state.calculating?"warning":e.state.sites?"success":"info",effect:"dark"},{default:l(()=>[s(o(e.state.calculating?"Идёт подсчёт...":e.state.sites?"Данные актуальны":"Данных нет"),
261)]),_:1},8,["type"]),e.state.calculatedAt?(u(),f("span",ta,[t[1]||(t[1]=s(" Рассчитано: ",-1)),a("strong",null,o(e.formatDateTime(e.state.calculatedAt)),1)])):e.state.calculating&&e.state.startedAt?(u(),f("span",aa," Считается с: "+o(e.formatDateTime(e.state.startedAt)),1)):g("",!0),i(y,{content:e.state.calculating?"Подсчёт уже идёт, старые данные отображаются":"Запустить пересчёт"},{default:l(()=>[i(z,{size:"small",loading:e.rescanning,disabled:e.state.calculating,onClick:e.onRescan},{default:l(()=>[...t[2]||(t[2]=[s(" Пересчитать ",-1)])]),_:1},8,["loading","disabled","onClick"])]),_:1},8,["content"]),e.state.sites&&e.state.sites.length>0?(u(),f(q,{key:2},[t[6]||(t[6]=a("span",{class:"text-sm text-gray-400"},"|",-1)),a("span",na,[t[3]||(t[3]=s(" Сайтов с данными: ",-1)),a("strong",null,o(e.state.sites.length),1)]),e.grandTotalDeleted>0?(u(),f("span",sa,[t[4]||(t[4]=s(" Устаревших: ",-1)),a("strong",null,o(e.formatSize(e.grandTotalDeleted)),1)])):g("",!0),e.grandTotalAll>0?(u(),f("span",la,[t[5]||(t[5]=s(" При полной очистке: ",-1)),a("strong",null,o(e.formatSize(e.grandTotalAll)),1)])):g("",!0)],64)):g("",!0)]),!e.state.sites&&!e.state.calculating?(u(),C(h,{key:0,description:"Нет данных. Нажмите «Пересчитать» для запуска подсчёта."})):g("",!0),e.state.calculating&&!e.state.sites?(u(),C(S,{key:1,title:"Идёт подсчёт данных",type:"warning",closable:!1,class:"mb-4"},{default:l(()=>[t[7]||(t[7]=s(" Первый подсчёт может занять несколько минут. Страница обновится автоматически. ",-1)),e.state.startedAt?(u(),f("span",oa,"Начато: "+o(e.formatDateTime(e.state.startedAt)),1)):g("",!0)]),_:1})):g("",!0),e.state.calculating&&e.state.sites?(u(),C(S,{key:2,title:"Идёт пересчёт — отображаются предыдущие данные",type:"warning",closable:!1,class:"mb-4"},{default:l(()=>[e.state.startedAt?(u(),f("span",ia,"Пересчёт начат: "+o(e.formatDateTime(e.state.startedAt))+". ",1)):g("",!0),t[8]||(t[8]=s(" Таблица обновится когда подсчёт завершится. ",-1))]),_:1})):g("",!0),e.state.sites&&e.state.sites.length>0?(u(),C(m,{key:3,data:e.paginatedRows,border:!0,style:{width:"100%"}},{default:l(()=>[i(v,{label:"Сайт","min-width":"200"},{default:l(({row:n})=>[a("div",ra,[a("span",ua,o(n.siteName||"—"),1),a("span",da,"#"+o(n.siteId),1)]),i(_,{type:e.statusTagType(n.siteStatus),size:"small",class:"mt-1"},{default:l(()=>[s(o(e.statusLabel(n.siteStatus)),1)]),_:2},1032,["type"]),n.deletedAt?(u(),f("div",ca," Удалён: "+o(e.formatDate(n.deletedAt)),1)):g("",!0)]),_:1}),i(v,{label:"Устаревших записей","min-width":"260"},{default:l(({row:n})=>[n.deleted.total.count>0?(u(),f(q,{key:0},[a("div",fa,[s(o(e.formatSize(n.deleted.total.bytes))+" ",1),a("span",pa," ("+o(n.deleted.total.count.toLocaleString("ru-RU"))+" записей) ",1)]),a("div",ma,[n.deleted.contents.count?(u(),f("div",ga,[s(" Материалы: "+o(n.deleted.contents.count.toLocaleString("ru-RU"))+" ",1),a("span",ya,"("+o(e.formatSize(n.deleted.contents.bytes))+")",1)])):g("",!0),n.deleted.blocks.count?(u(),f("div",_a,[s(" Блоки: "+o(n.deleted.blocks.count.toLocaleString("ru-RU"))+" ",1),a("span",ha,"("+o(e.formatSize(n.deleted.blocks.bytes))+")",1)])):g("",!0),n.deleted.sections.count?(u(),f("div",va,[s(" Секции: "+o(n.deleted.sections.count.toLocaleString("ru-RU"))+" ",1),a("span",Sa,"("+o(e.formatSize(n.deleted.sections.bytes))+")",1)])):g("",!0),n.deleted.revisions.count?(u(),f("div",ka,[s(" Ревизии: "+o(n.deleted.revisions.count.toLocaleString("ru-RU"))+" ",1),a("span",ba,"("+o(e.formatSize(n.deleted.revisions.bytes))+")",1)])):g("",!0),n.deleted.formResults.count?(u(),f("div",$a,[s(" Заявки: "+o(n.deleted.formResults.count.toLocaleString("ru-RU"))+" ",1),a("span",za,"("+o(e.formatSize(n.deleted.formResults.b
26ytes))+")",1)])):g("",!0),n.deleted.attachments.count?(u(),f("div",Ca,[s(" Вложения S3: "+o(n.deleted.attachments.count.toLocaleString("ru-RU"))+" ",1),a("span",La,"("+o(e.formatSize(n.deleted.attachments.bytes))+")",1)])):g("",!0)])],64)):(u(),f("span",Pa,"—"))]),_:1}),i(v,{label:"При полной очистке","min-width":"220"},{default:l(({row:n})=>[n.siteStatus!=="active"&&n.all.total.count>0?(u(),f(q,{key:0},[a("div",Ra,[s(o(e.formatSize(n.all.total.bytes))+" ",1),a("span",Ea," ("+o(n.all.total.count.toLocaleString("ru-RU"))+" записей) ",1)]),a("div",Ta,[n.all.contents.count?(u(),f("div",Fa,[s(" Материалы: "+o(n.all.contents.count.toLocaleString("ru-RU"))+" ",1),a("span",Ia,"("+o(e.formatSize(n.all.contents.bytes))+")",1)])):g("",!0),n.all.blocks.count?(u(),f("div",Da,[s(" Блоки: "+o(n.all.blocks.count.toLocaleString("ru-RU"))+" ",1),a("span",Ua,"("+o(e.formatSize(n.all.blocks.bytes))+")",1)])):g("",!0),n.all.sections.count?(u(),f("div",Aa,[s(" Секции: "+o(n.all.sections.count.toLocaleString("ru-RU"))+" ",1),a("span",wa,"("+o(e.formatSize(n.all.sections.bytes))+")",1)])):g("",!0),n.all.revisions.count?(u(),f("div",Ma,[s(" Ревизии: "+o(n.all.revisions.count.toLocaleString("ru-RU"))+" ",1),a("span",Na,"("+o(e.formatSize(n.all.revisions.bytes))+")",1)])):g("",!0),n.all.formResults.count?(u(),f("div",Ba,[s(" Заявки: "+o(n.all.formResults.count.toLocaleString("ru-RU"))+" ",1),a("span",Va,"("+o(e.formatSize(n.all.formResults.bytes))+")",1)])):g("",!0),n.all.attachments.count?(u(),f("div",ja,[s(" Вложения S3: "+o(n.all.attachments.count.toLocaleString("ru-RU"))+" ",1),a("span",qa,"("+o(e.formatSize(n.all.attachments.bytes))+")",1)])):g("",!0)])],64)):(u(),f("span",Oa,"—"))]),_:1}),i(v,{fixed:"right",label:"Действия",width:"220",align:"center"},{default:l(({row:n})=>[a("div",Wa,[n.deleted.total.count>0?(u(),C(z,{key:0,type:"warning",size:"small",loading:e.actionId===n.siteId&&e.actionMode==="deleted",onClick:E=>e.onCleanup(n,"deleted")},{default:l(()=>[s(o(n.siteStatus==="active"?"Удалить устаревшие (>1 мес)":"Удалить устаревшие"),1)]),_:2},1032,["loading","onClick"])):g("",!0),n.siteStatus!=="active"&&n.all.total.count>0?(u(),C(z,{key:1,type:"danger",size:"small",loading:e.actionId===n.siteId&&e.actionMode==="all",onClick:E=>e.onCleanup(n,"all")},{default:l(()=>[...t[9]||(t[9]=[s(" Очистить всё ",-1)])]),_:1},8,["loading","onClick"])):g("",!0)])]),_:1})]),_:1},8,["data"])):g("",!0),e.state.sites&&e.state.sites.length>e.perPage?(u(),f("div",xa,[i(F,{"current-page":e.currentPage,"onUpdate:currentPage":t[0]||(t[0]=n=>e.currentPage=n),"page-size":e.perPage,total:e.state.sites.length,layout:"prev, pager, next",background:""},null,8,["current-page","page-size","total"])])):g("",!0)])}
26const Ha=Y(Zt,[["render",Ga]]),Ya=H({components:{FilesAll:gt,FilesNormalize:Dt,FilesCleanup:Qt,MaterialsCleanup:Ha,ElCard:Q,ElButton:w,ElTabs:ve,ElTabPane:he},setup(){return{activeTab:$("all"),showHelp:$(!1)}}}),Ka={class:"p-4"},Qa={class:"flex items-center justify-between mb-4"};function Ja(e,t,L,P,T,R){const _=w,z=Q,y=V("FilesAll"),h=he,S=V("FilesNormalize"),v=V("FilesCleanup"),m=V("MaterialsCleanup"),F=ve;return u(),f("div",Ka,[a("div",Qa,[t[2]||(t[2]=a("h2",{class:"text-xl font-semibold"},"Файлы S3",-1)),i(_,{type:"info",text:"",size:"small",onClick:t[0]||(t[0]=n=>e.showHelp=!e.showHelp)},{default:l(()=>[s(o(e.showHelp?"Скрыть справку":"Справка"),1)]),_:1})]),e.showHelp?(u(),C(z,{key:0,class:"mb-4",shadow:"never"},{default:l(()=>[...t[3]||(t[3]=[a("div",{class:"text-sm leading-relaxed space-y-3"},[a("h3",{class:"font-semibold text-base"},"Как работает система управления файлами S3"),a("div",null,[a("strong",null,'Вкладка "Все файлы"'),s(" — просмотр и управление записями таблицы attachments. Серверная пагинация с фильтрами по сайту, расширению, названию, статусу удаления. "),a("ul",{class:"list-disc ml-4 mt-1"},[a("li",null,[a("strong",null,"Удалить"),s(" — помечает файл к удалению ("),a("code",null,"soft_deleted_at"),s("), скрывает в S3 (создаёт delete marker). Файл больше не доступен по URL, но версии в S3 сохраняются 2 месяца.")]),a("li",null,[a("strong",null,"Восстановить"),s(" — снимает пометку, удаляет delete marker в S3. Файл снова доступен по URL. Используйте когда клиент пожаловался на пропавший файл.")]),a("li",null,[a("strong",null,"Удалить навсегда"),s(" — безвозвратно удаляет все версии из S3. Восстановление невозможно.")])])]),a("div",null,[a("strong",null,'Вкладка "Перенос файлов"'),s(" — нормализация: находит случаи когда сайт А использует файлы из папки сайта Б (обычно после клонирования). Копирует файл в правильную папку, обновляет все ссылки в БД. "),a("br"),s("Два режима: "),a("em",null,"Полуавтомат"),s(" — ручное одобрение каждого переноса, "),a("em",null,"Автопилот"),s(" — автоматическое выполнение. ")]),a("div",null,[a("strong",null,'Вкладка "Очистка удалённых сайтов"'),s(" — список сайтов помеченных как удалённые, у которых ещё остались файлы в S3. "),a("ul",{class:"list-disc ml-4 mt-1"},[a("li",null,[a("strong",null,"Удалить файлы"),s(" — помечает все файлы сайта в БД. Процесс "),a("code",null,"files:retention"),s(" скроет их в S3 в фоне (создаст delete markers). Через 2 месяца он же удалит физически.")]),a("li",null,[a("strong",null,"Удалить навсегда"),s(" — сдвигает дату удаления на 3 месяца назад. Процесс "),a("code",null,"files:retention"),s(" подхватит и удалит все S3 версии.")])]),s(" Стоимость хранения рассчитана по тарифу Selectel: 2,33 руб/ГБ/мес. ")]),a("div",null,[a("strong",null,'Вкладка "Очистка материалов"'),s(" — удаление записей БД (материалы, блоки, секции, ревизии, заявки с форм, вложения) по сайтам. "),a("ul",{class:"list-disc ml-4 mt-1"},[a("li",null,[a("strong",null,"Активный сайт"),s(" — только записи с "),a("c
26ode",null,"deleted_at"),s(" старше 1 месяца.")]),a("li",null,[a("strong",null,"Неактивный/удалённый сайт"),s(" — два варианта: удалить только устаревшие записи ("),a("code",null,"deleted_at IS NOT NULL"),s("), либо очистить всё — остаётся только сайт и прикреплённый пользователь.")]),a("li",null,[s("Вложения удаляются только физически удалённые из S3 ("),a("code",null,"real_deleted_at IS NOT NULL"),s(").")]),a("li",null,[s("Размер рассчитывается через "),a("code",null,"pg_column_size"),s(" — показывает сколько МБ освободится в PostgreSQL.")])])]),a("div",null,[a("strong",null,"Фоновые процессы (Docker)"),a("ul",{class:"list-disc ml-4 mt-1"},[a("li",null,[a("code",null,"files:normalize"),s(" (порт 3011) — сканирует сайты, находит чужие файлы")]),a("li",null,[a("code",null,"files:cleanup"),s(" (порт 3012) — каждый час обновляет список удалённых сайтов с файлами (только инвентаризация, без S3 операций)")]),a("li",null,[a("code",null,"files:retention"),s(" (порт 3013) — каждые 30 секунд: создаёт S3 delete markers (скрывает файлы) и удаляет просроченные (все версии)")])]),s(" Все процессы устойчивы к падению: обрабатывают пофайлово, при перезапуске продолжают. Результаты отправляются в Telegram (#files_retention). ")]),a("div",null,[a("strong",null,"Жизненный цикл файла"),a("ol",{class:"list-decimal ml-4 mt-1"},[a("li",null,"Файл активен — доступен по URL"),a("li",null,[a("code",null,"soft_deleted_at"),s(" — помечен в БД")]),a("li",null,[a("code",null,"s3_soft_deleted_at"),s(" — S3 delete marker создан, файл скрыт по URL. Можно восстановить.")]),a("li",null,[s("Через 2 мес (или принудительно) — "),a("code",null,"real_deleted_at"),s(", все S3 версии удалены. Безвозвратно.")])])])],-1)])]),_:1})):g("",!0),i(F,{modelValue:e.activeTab,"onUpdate:modelValue":t[1]||(t[1]=n=>e.activeTab=n)},{default:l(()=>[i(h,{label:"Все файлы",name:"all"},{default:l(()=>[i(y)]),_:1}),i(h,{label:"Перенос файлов",name:"normalize"},{default:l(()=>[i(S)]),_:1}),i(h,{label:"Очистка удалённых сайтов",name:"cleanup"},{default:l(()=>[i(v)]),_:1}),i(h,{label:"Очистка материалов",name:"materials"},{default:l(()=>[i(m)]),_:1})]),_:1},8,["modelValue"])])}const Sn=Y(Ya,[["render",Ja]]);export{Sn as default};

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.