PageSourceSearch

https://task.com.tw/assets/SeoPermissions-DG9zSq04.js

js task.com.tw collected 2026-10-08 16:05:58 UTC 35,486 bytes, 1 lines download raw bytes

1import{j as e,P as W,au as re,T as de,X as xe,L as ge,by as me,a0 as pe,z as ue,bs as he,af as Se,aF as fe,ap as Pe,F as je,N as be,b0 as Re,dn as ve,r as h,a6 as Ne,t as P,bh as De}from"./vendor-react-Cek5_fI5.js";import{ao as H,aq as T,B as S,j as we,k as ke,l as ye,m as Ce,n as Ae,p as Me,y as $,z as V,A as K,E as Q,G as Y,L as se,I as te,F as G,bu as Ee,bw as Le,bx as Ie,by as Fe,bz as Oe,bA as _e,bB as Te,bC as Ue,b as Be,t as M,C as ze,d as $e}from"./index-DnYEcI1T.js";import{S as Ve}from"./SeoAdminLayout-Bgrt4li3.js";import{b as U,c as Ke,a as I}from"./seoEnums-Cxf0PcGh.js";import{C as Qe,a as Ge,b as He,c as Ye,d as Xe,e as qe}from"./command-DSkxGqmS.js";import"./vendor-charts-CdtAEet6.js";import"./vendor-export-Do0PDzts.js";const X="flex shrink-0 items-center gap-2 whitespace-nowrap rounded-md px-3 py-2 text-left text-sm transition-colors lg:w-full";function We({roles:t,isLoading:o,selection:c,onSelect:i,dirtyRoleIds:x,pendingCount:d,onCreateRole:n}){return e.jsx("div",{"data-loc":"client/src/pages/seo/sections/SeoRoleListPanel.tsx:34",className:"rounded-lg border bg-card p-2 lg:h-full",children:o?e.jsxs("div",{"data-loc":"client/src/pages/seo/sections/SeoRoleListPanel.tsx:36",className:"flex flex-col gap-2 p-1",children:[e.jsx(H,{"data-loc":"client/src/pages/seo/sections/SeoRoleListPanel.tsx:37",className:"h-9 w-full"}),e.jsx(H,{"data-loc":"client/src/pages/seo/sections/SeoRoleListPanel.tsx:38",className:"h-9 w-full"}),e.jsx(H,{"data-loc":"client/src/pages/seo/sections/SeoRoleListPanel.tsx:39",className:"h-9 w-full"})]}):e.jsxs("div",{"data-loc":"client/src/pages/seo/sections/SeoRoleListPanel.tsx:42",className:"flex items-center gap-1 overflow-x-auto pb-1 lg:flex-col lg:items-stretch lg:overflow-visible lg:pb-0",children:[t.map(g=>{const j=c.kind==="role"&&c.roleId===g.id,m=x.includes(g.id);return e.jsxs("button",{"data-loc":"client/src/pages/seo/sections/SeoRoleListPanel.tsx:47",type:"button",onClick:()=>i({kind:"role",roleId:g.id}),className:T(X,j?"bg-accent text-accent-foreground font-medium":"text-foreground hover:bg-muted"),children:[e.jsx("span",{"data-loc":"client/src/pages/seo/sections/SeoRoleListPanel.tsx:58",className:"min-w-0 max-w-[10rem] flex-1 truncate lg:max-w-none",children:g.name}),m&&e.jsx("span",{"data-loc":"client/src/pages/seo/sections/SeoRoleListPanel.tsx:62",className:"h-1.5 w-1.5 shrink-0 rounded-full bg-destructive"}),e.jsx("span",{"data-loc":"client/src/pages/seo/sections/SeoRoleListPanel.tsx:64",className:"shrink-0 text-xs tabular-nums opacity-70",children:g.memberCount})]},g.id)}),e.jsx("div",{"data-loc":"client/src/pages/seo/sections/SeoRoleListPanel.tsx:72",className:"mx-1 w-px shrink-0 self-stretch bg-border lg:mx-0 lg:my-1 lg:h-px lg:w-full"}),e.jsxs("button",{"data-loc":"client/src/pages/seo/sections/SeoRoleListPanel.tsx:74",type:"button",onClick:()=>i({kind:"pending"}),className:T(X,c.kind==="pending"?"bg-accent font-medium":"hover:bg-muted",d>0?"text-destructive":"text-muted-foreground"),children:[e.jsx("span",{"data-loc":"client/src/pages/seo/sections/SeoRoleListPanel.tsx:83",className:"min-w-0 flex-1 truncate",children:"尚未開通"}),e.jsx("span",{"data-loc":"client/src/pages/seo/sections/SeoRoleListPanel.tsx:84",className:"shrink-0 text-xs tabular-nums",children:d})]}),e.jsxs("button",{"data-loc":"client/src/pages/seo/sections/SeoRoleListPanel.tsx:87",type:"button",onClick:n,className:T(X,"justify-center gap-1 border border-dashed text-muted-foreground hover:bg-muted"),children:[e.jsx(W,{"data-loc":"client/src/pages/seo/sections/SeoRoleListPanel.tsx:95",className:"h-3.5 w-3.5"}),"新增角色"]})]})})}const ae=[{label:"總覽",keys:["dashboard","my-workload"]},{label:"客戶與內容",keys:["clients","articles"]},{label:"分析與監測",keys:["keyword-traffic","competitor-gap","brand-monitor"]},{label:"工具",keys:["site-tools","external-tools"]},{label:"系統",keys:["settings"]}],Je={dashboard:"全公司 SEO 成效總覽","my-workload":"自己負責的客戶與待辦",clients:"客戶資料、合約期間與收款狀態",articles:"文章排程、撰寫與上稿紀錄","keyword-traffic":"關鍵字排名與流量變化","competitor-gap":"對手有排名而我方沒有的關鍵字","brand-monitor":"品牌字在搜尋結果的露出狀況","site-tools":"自家網站的健檢與技術修正","external-tools":"外部查詢工具的入口",settings:"報表寄送、提醒週期與介接金鑰"},Ze={none:"bg-muted text-muted-foreground",view:"bg-secondary text-foreground ring-1 ring-border",edit:"bg-foreground text-background"};function es({levels:t,value:o,onChange:c}){return e.jsx("div",{"data-loc":"client/src/pages/seo/sections/SeoRoleDetailPanel.tsx:60",role:"group",className:"inline-flex shrink-0 overflow-hidden rounded-md border",children:t.map((i,x)=>{const d=o===i;return e.jsx("button",{"data-loc":"client/src/pages/seo/sections/SeoRoleDetailPanel.tsx:64",type:"button","aria-pressed":d,onClick:()=>c(i),className:T("px-3 py-1.5 text-xs font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring",x>0&&"border-l",d?Ze[i]:"bg-background text-muted-foreground hover:bg-muted/50"),children:Ke[i]},i)})})}function ss({role:t,levels:o,isDirty:c,isSaving:i,otherDirtyRoleNames:x,members:d,isMemberMutating:n,onChangeLevel:g,onBulkSet:j,onSave:m,onReset:k,onRename:F,onDelete:b,onCopyFrom:y,onAddMember:E,onRemoveMember:C}){const A=U.filter(r=>o[r.key]!=="none").length;return e.jsxs("div",{"data-loc":"client/src/pages/seo/sections/SeoRoleDetailPanel.tsx:106",className:"rounded-lg border bg-card",children:[e.jsxs("div",{"data-loc":"client/src/pages/seo/sections/SeoRoleDetailPanel.tsx:108",className:"flex flex-col gap-3 border-b px-6 py-4",children:[e.jsxs("div",{"data-loc":"client/src/pages/seo/sections/SeoRoleDetailPanel.tsx:109",className:"flex items-start justify-between gap-3",children:[e.jsxs("div",{"data-loc":"client/src/pages/seo/sections/SeoRoleDetailPanel.tsx:110",className:"min-w-0",children:[e.jsx("h2",{"data-loc":"client/src/pages/seo/sections/SeoRoleDetailPanel.tsx:111",className:"truncate text-lg font-semibold",children:t.name}),e.jsxs("p",{"data-loc":"client/src/pages/seo/sections/SeoRoleDetailPanel.tsx:112",className:"text-sm text-muted-foreground",children:[d.length," 位成員 · 開放 ",A," / ",U.length," 項功能"]})]}),e.jsxs("div",{"data-loc":"client/src/pages/seo/sections/SeoRoleDetailPanel.tsx:116",className:"flex shrink-0 items-center gap-1",children:[e.jsxs(S,{"data-loc":"client/src/pages/seo/sections/SeoRoleDetailPanel.tsx:117",variant:"ghost",size:"sm",className:"gap-1.5",onClick:F,children:[e.jsx(re,{"data-loc":"client/src/pages/seo/sections/SeoRoleDetailPanel.tsx:118",className:"h-4 w-4"}),"改名"]}),e.jsxs(S,{"data-loc":"client/src/pages/seo/sections/SeoRoleDetailPanel.tsx:121",variant:"ghost",size:"sm",className:"gap-1.5 text-destructive hover:text-destructive",onClick:b,children:[e.jsx(de,{"data-loc":"client/src/pages/seo/sections/SeoRoleDetailPanel.tsx:127",className:"h-4 w-4"}),"刪除"]})]})]}),e.jsxs("div",{"data-loc":"client/src/pages/seo/sections/SeoRoleDetailPanel.tsx:132",className:"flex flex-wrap gap-2",children:[e.jsx(S,{"data-loc":"client/src/pages/seo/sections/SeoRoleDetailPanel.tsx:133",variant:"outline",size:"sm",onClick:()=>j("edit"),children:"全部可編輯"}),e.jsx(S,{"data-loc":"client/src/pages/seo/sections/SeoRoleDetailPanel.tsx:136",variant:"outline",size:"sm",onClick:()=>j("view"),children:"全部僅檢視"}),e.jsx(S,{"data-loc":"client/src/pages/seo/sections/SeoRoleDetailPanel.tsx:139",variant:"outline",size:"sm",onClick:()=>j("none"),children:"全部關閉"}),e.jsx(S,{"data-loc":"client/src/pages/seo/sections/SeoRoleDetailPanel.tsx:142",variant:"outline",size:"sm",onClick:y,children:"複製其他角色的設定"})]})]}),e.jsx("div",{"data-loc":"client/src/pages/seo/sections/SeoRoleDetailPanel.tsx:149",className:"px-6",children:ae.map(r=>e.jsxs("div",{"data-loc":"client/src/pages/seo/sections/SeoRoleDetailPanel.tsx:151",children:[e.jsx("div",{"data-loc":"client/src/pages/seo/sections/SeoRoleDetailPanel.tsx:152",className:"pt-4 text-xs uppercase tracking-wider text-muted-foreground",children:r.label}
1),r.keys.map(v=>{const N=U.find(w=>w.key===v);if(!N)return null;const D=o[v],R=D==="none";return e.jsxs("div",{"data-loc":"client/src/pages/seo/sections/SeoRoleDetailPanel.tsx:161",className:"flex items-center gap-4 border-t py-3",children:[e.jsxs("div",{"data-loc":"client/src/pages/seo/sections/SeoRoleDetailPanel.tsx:162",className:"min-w-0 flex-1",children:[e.jsx("div",{"data-loc":"client/src/pages/seo/sections/SeoRoleDetailPanel.tsx:163",className:T("text-sm font-medium",R&&"text-muted-foreground"),children:N.label}),e.jsx("div",{"data-loc":"client/src/pages/seo/sections/SeoRoleDetailPanel.tsx:168",className:"text-xs text-muted-foreground",children:Je[v]})]}),e.jsx(es,{"data-loc":"client/src/pages/seo/sections/SeoRoleDetailPanel.tsx:172",levels:N.levels,value:D,onChange:w=>g(v,w)})]},v)})]},r.label))}),e.jsxs("div",{"data-loc":"client/src/pages/seo/sections/SeoRoleDetailPanel.tsx:185",className:"mt-2 border-t bg-muted/40 px-6 py-4",children:[e.jsx("div",{"data-loc":"client/src/pages/seo/sections/SeoRoleDetailPanel.tsx:186",className:"mb-3 text-xs uppercase tracking-wider text-muted-foreground",children:"成員"}),e.jsxs("div",{"data-loc":"client/src/pages/seo/sections/SeoRoleDetailPanel.tsx:187",className:"flex flex-wrap items-center gap-2",children:[d.length===0&&e.jsx("span",{"data-loc":"client/src/pages/seo/sections/SeoRoleDetailPanel.tsx:189",className:"text-sm text-muted-foreground",children:"還沒有人是這個角色。"}),d.map(r=>e.jsxs("div",{"data-loc":"client/src/pages/seo/sections/SeoRoleDetailPanel.tsx:192",className:"flex items-center gap-1.5 rounded-full border bg-background py-1 pl-1 pr-2 text-sm",children:[e.jsx("span",{"data-loc":"client/src/pages/seo/sections/SeoRoleDetailPanel.tsx:196",className:"flex h-6 w-6 items-center justify-center rounded-full bg-primary text-xs font-medium text-primary-foreground",children:(r.name||"?").charAt(0)}),e.jsx("span",{"data-loc":"client/src/pages/seo/sections/SeoRoleDetailPanel.tsx:199",children:r.name||`使用者 #${r.userId}`}),e.jsx("button",{"data-loc":"client/src/pages/seo/sections/SeoRoleDetailPanel.tsx:200",type:"button",onClick:()=>C(r.userId),disabled:n,"aria-label":`移除 ${r.name}`,className:"text-muted-foreground hover:text-destructive disabled:pointer-events-none disabled:opacity-50",children:e.jsx(xe,{"data-loc":"client/src/pages/seo/sections/SeoRoleDetailPanel.tsx:207",className:"h-3.5 w-3.5"})})]},r.userId)),e.jsxs("button",{"data-loc":"client/src/pages/seo/sections/SeoRoleDetailPanel.tsx:211",type:"button",onClick:E,disabled:n,className:"flex items-center gap-1 rounded-full border border-dashed px-3 py-1 text-sm text-muted-foreground transition-colors hover:border-foreground hover:text-foreground disabled:pointer-events-none disabled:opacity-50",children:[e.jsx(W,{"data-loc":"client/src/pages/seo/sections/SeoRoleDetailPanel.tsx:217",className:"h-3.5 w-3.5"}),"加入成員"]})]})]}),e.jsxs("div",{"data-loc":"client/src/pages/seo/sections/SeoRoleDetailPanel.tsx:224",className:"sticky bottom-16 flex items-center gap-3 rounded-b-lg border-t bg-card px-6 py-3 md:bottom-0",children:[e.jsx("div",{"data-loc":"client/src/pages/seo/sections/SeoRoleDetailPanel.tsx:225",className:"flex-1 text-sm",children:c?e.jsxs("span",{"data-loc":"client/src/pages/seo/sections/SeoRoleDetailPanel.tsx:227",className:"text-destructive",children:["有未儲存的變更",x.length>0&&`(另外${x.map(r=>`「${r}」`).join("")}也還沒存)`]}):x.length>0?e.jsxs("span",{"data-loc":"client/src/pages/seo/sections/SeoRoleDetailPanel.tsx:233",className:"text-muted-foreground",children:["已儲存",e.jsx("span",{"data-loc":"client/src/pages/seo/sections/SeoRoleDetailPanel.tsx:235",className:"text-destructive",children:`(另外${x.map(r=>`「${r}」`).join("")}還沒存)`})]}):e.jsx("span",{"data-loc":"client/src/pages/seo/sections/SeoRoleDetailPanel.tsx:240",className:"text-muted-foreground",children:"已儲存"})}),e.jsx(S,{"data-loc":"client/src/pages/seo/sections/SeoRoleDetailPanel.tsx:243",variant:"outline",size:"sm",onClick:k,disabled:!c||i,children:"還原"}),e.jsxs(S,{"data-loc":"client/src/pages/seo/sections/SeoRoleDetailPanel.tsx:246",size:"sm",onClick:m,disabled:!c||i,className:"gap-1.5",children:[i&&e.jsx(ge,{"data-loc":"client/src/pages/seo/sections/SeoRoleDetailPanel.tsx:247",className:"h-4 w-4 animate-spin"}
1),i?"儲存中…":"儲存"]})]})]})}function ts({members:t,roles:o,isAssigning:c,onAssign:i}){return e.jsxs("div",{"data-loc":"client/src/pages/seo/sections/SeoPendingMembersPanel.tsx:30",className:"flex h-full flex-col rounded-lg border bg-card",children:[e.jsxs("div",{"data-loc":"client/src/pages/seo/sections/SeoPendingMembersPanel.tsx:31",className:"border-b px-6 py-4",children:[e.jsx("h2",{"data-loc":"client/src/pages/seo/sections/SeoPendingMembersPanel.tsx:32",className:"text-lg font-semibold",children:"尚未開通"}),e.jsx("p",{"data-loc":"client/src/pages/seo/sections/SeoPendingMembersPanel.tsx:33",className:"mt-1 text-sm text-muted-foreground",children:"這些人已經是公司成員,但還沒有 SEO 角色,目前進不了 SEO 系統。指派角色後立刻生效。"})]}),e.jsx("div",{"data-loc":"client/src/pages/seo/sections/SeoPendingMembersPanel.tsx:38",className:"flex-1 overflow-y-auto px-6 py-4",children:t.length===0?e.jsxs("div",{"data-loc":"client/src/pages/seo/sections/SeoPendingMembersPanel.tsx:40",className:"flex flex-col items-center justify-center gap-3 py-16 text-center text-muted-foreground",children:[e.jsx(me,{"data-loc":"client/src/pages/seo/sections/SeoPendingMembersPanel.tsx:41",className:"h-8 w-8"}),e.jsx("p",{"data-loc":"client/src/pages/seo/sections/SeoPendingMembersPanel.tsx:42",className:"text-sm",children:"所有成員都已經指派角色。"})]}):e.jsx("div",{"data-loc":"client/src/pages/seo/sections/SeoPendingMembersPanel.tsx:45",className:"divide-y",children:t.map(x=>e.jsxs("div",{"data-loc":"client/src/pages/seo/sections/SeoPendingMembersPanel.tsx:47",className:"flex items-center justify-between gap-4 py-3",children:[e.jsxs("div",{"data-loc":"client/src/pages/seo/sections/SeoPendingMembersPanel.tsx:48",className:"min-w-0",children:[e.jsx("div",{"data-loc":"client/src/pages/seo/sections/SeoPendingMembersPanel.tsx:49",className:"truncate text-sm font-medium",children:x.name||`使用者 #${x.userId}`}),e.jsx("div",{"data-loc":"client/src/pages/seo/sections/SeoPendingMembersPanel.tsx:52",className:"truncate text-xs text-muted-foreground",children:x.email})]}),e.jsxs(we,{"data-loc":"client/src/pages/seo/sections/SeoPendingMembersPanel.tsx:54",disabled:c||o.length===0,onValueChange:d=>i(x.userId,Number(d)),children:[e.jsx(ke,{"data-loc":"client/src/pages/seo/sections/SeoPendingMembersPanel.tsx:58",className:"w-40 shrink-0",children:e.jsx(ye,{"data-loc":"client/src/pages/seo/sections/SeoPendingMembersPanel.tsx:59",placeholder:"指派角色"})}),e.jsx(Ce,{"data-loc":"client/src/pages/seo/sections/SeoPendingMembersPanel.tsx:61",children:o.map(d=>e.jsx(Ae,{"data-loc":"client/src/pages/seo/sections/SeoPendingMembersPanel.tsx:63",value:String(d.id),children:d.name},d.id))})]})]},x.userId))})})]})}const os={dashboard:ve,"my-workload":Re,clients:be,articles:je,"keyword-traffic":Pe,"competitor-gap":fe,"brand-monitor":Se,"site-tools":he,"external-tools":ue,settings:pe},as=Object.fromEntries(U.map(t=>[t.key,t.label])),q={};ae.forEach((t,o)=>{t.keys.forEach(c=>{q[c]=o})});function oe({children:t}){return e.jsxs("div",{"data-loc":"client/src/pages/seo/sections/SeoAccessPreviewPanel.tsx:61",className:"overflow-hidden rounded-lg border",children:[e.jsxs("div",{"data-loc":"client/src/pages/seo/sections/SeoAccessPreviewPanel.tsx:62",className:"flex items-center gap-2 border-b bg-card px-3 py-2.5",children:[e.jsx("div",{"data-loc":"client/src/pages/seo/sections/SeoAccessPreviewPanel.tsx:63",className:"h-4 w-4 shrink-0 rounded-sm bg-primary"}),e.jsx("span",{"data-loc":"client/src/pages/seo/sections/SeoAccessPreviewPanel.tsx:64",className:"text-xs font-medium tracking-wider text-muted-foreground",children:"SEO 系統"})]}),e.jsx("div",{"data-loc":"client/src/pages/seo/sections/SeoAccessPreviewPanel.tsx:68",className:"space-y-0.5 bg-card px-2 py-2",children:t})]})}function ls({selection:t,roleName:o,levels:c}
1){if(t.kind==="pending")return e.jsxs("div",{"data-loc":"client/src/pages/seo/sections/SeoAccessPreviewPanel.tsx:84",className:"space-y-3",children:[e.jsxs("div",{"data-loc":"client/src/pages/seo/sections/SeoAccessPreviewPanel.tsx:85",children:[e.jsx("p",{"data-loc":"client/src/pages/seo/sections/SeoAccessPreviewPanel.tsx:86",className:"text-[10px] font-semibold uppercase tracking-[0.2em] text-muted-foreground",children:"登入後會看到"}),e.jsx("p",{"data-loc":"client/src/pages/seo/sections/SeoAccessPreviewPanel.tsx:89",className:"mt-1 text-sm text-foreground",children:"尚未開通的成員,登入之後看到的樣子。"})]}),e.jsx(oe,{"data-loc":"client/src/pages/seo/sections/SeoAccessPreviewPanel.tsx:94",children:e.jsx("p",{"data-loc":"client/src/pages/seo/sections/SeoAccessPreviewPanel.tsx:95",className:"px-3 py-6 text-center text-xs text-muted-foreground",children:"(選單是空的)"})}),e.jsx("p",{"data-loc":"client/src/pages/seo/sections/SeoAccessPreviewPanel.tsx:100",className:"text-xs text-muted-foreground",children:"未開通的成員進不了 SEO 系統,連選單都不會出現。"})]});if(c===null)return null;const x=I.filter(n=>c[n]!=="none").length,d=I.filter(n=>c[n]==="edit").length;return e.jsxs("div",{"data-loc":"client/src/pages/seo/sections/SeoAccessPreviewPanel.tsx:116",className:"space-y-3",children:[e.jsxs("div",{"data-loc":"client/src/pages/seo/sections/SeoAccessPreviewPanel.tsx:117",children:[e.jsx("p",{"data-loc":"client/src/pages/seo/sections/SeoAccessPreviewPanel.tsx:118",className:"text-[10px] font-semibold uppercase tracking-[0.2em] text-muted-foreground",children:"登入後會看到"}),e.jsxs("p",{"data-loc":"client/src/pages/seo/sections/SeoAccessPreviewPanel.tsx:121",className:"mt-1 text-sm text-foreground",children:[e.jsx("span",{"data-loc":"client/src/pages/seo/sections/SeoAccessPreviewPanel.tsx:122",className:"font-semibold",children:o}),"的成員登入之後,左側選單長這樣。"]})]}),e.jsx(oe,{"data-loc":"client/src/pages/seo/sections/SeoAccessPreviewPanel.tsx:127",children:I.map((n,g)=>{const j=os[n],m=c[n],k=g>0&&q[n]!==q[I[g-1]];return e.jsxs("div",{"data-loc":"client/src/pages/seo/sections/SeoAccessPreviewPanel.tsx:134",children:[k&&e.jsx("div",{"data-loc":"client/src/pages/seo/sections/SeoAccessPreviewPanel.tsx:135",className:"my-1 border-t border-border/60"}),e.jsxs("div",{"data-loc":"client/src/pages/seo/sections/SeoAccessPreviewPanel.tsx:136",className:T("flex items-center gap-3 rounded-lg px-3 py-2 text-sm text-muted-foreground",m==="none"&&"opacity-40 line-through"),children:[e.jsx(j,{"data-loc":"client/src/pages/seo/sections/SeoAccessPreviewPanel.tsx:142",className:"h-4 w-4 shrink-0"}),e.jsx("span",{"data-loc":"client/src/pages/seo/sections/SeoAccessPreviewPanel.tsx:143",className:"flex-1",children:as[n]}),m==="edit"&&e.jsx(Me,{"data-loc":"client/src/pages/seo/sections/SeoAccessPreviewPanel.tsx:145",variant:"secondary",className:"text-[9px] tracking-wider",children:"可編輯"})]})]},n)})}),e.jsx("p",{"data-loc":"client/src/pages/seo/sections/SeoAccessPreviewPanel.tsx:155",className:"text-xs text-muted-foreground",children:"劃掉的項目不會出現在他的選單裡。"}),e.jsxs("p",{"data-loc":"client/src/pages/seo/sections/SeoAccessPreviewPanel.tsx:157",className:"text-xs text-muted-foreground",children:["看得到 ",e.jsx("span",{"data-loc":"client/src/pages/seo/sections/SeoAccessPreviewPanel.tsx:158",className:"font-medium text-foreground tabular-nums",children:x})," 項"," · ","其中 ",e.jsx("span",{"data-loc":"client/src/pages/seo/sections/SeoAccessPreviewPanel.tsx:160",className:"font-medium text-foreground tabular-nums",children:d})," 項可以動手改"]})]})}function ns({state:t,onClose:o,roles:c,members:i,onCreateRole:x,isCreating:d,onRenameRole:n,isRenaming:g,onDeleteRole:j,isDeleting:m,onAddMember:k,isAddingMember:F,onCopyFrom:b}){const[y,E]=h.useState(""),[C,A]=h.useState(""),[r,v]=h.useState("");h.useEffect(()=>{t.kind==="create"&&E(""),t.kind==="rename"&&A(t.role.name),t.kind==="addMember"&&v("")},[t]);const N=a=>{a||o()},D=()=>{const a=y.trim();if(!a){P.error("請輸入角色名稱");return}x(a)},R=()=>
1{if(t.kind!=="rename")return;const a=C.trim();if(!a){P.error("請輸入角色名稱");return}n(t.role.id,a)},w=h.useMemo(()=>{if(t.kind!=="addMember")return[];const a=r.trim().toLowerCase();return i.filter(L=>L.orgRole==="owner"||L.orgRole==="admin"||L.roleId===t.role.id?!1:a?L.name.toLowerCase().includes(a)||L.email.toLowerCase().includes(a):!0)},[t,i,r]),B=t.kind==="copyFrom"?c.filter(a=>a.id!==t.role.id):[];return e.jsxs(e.Fragment,{children:[e.jsx($,{"data-loc":"client/src/pages/seo/sections/SeoRoleDialogs.tsx:131",open:t.kind==="create",onOpenChange:N,children:e.jsxs(V,{"data-loc":"client/src/pages/seo/sections/SeoRoleDialogs.tsx:132",className:"sm:max-w-md max-h-[90vh] overflow-y-auto",children:[e.jsxs(K,{"data-loc":"client/src/pages/seo/sections/SeoRoleDialogs.tsx:133",children:[e.jsx(Q,{"data-loc":"client/src/pages/seo/sections/SeoRoleDialogs.tsx:134",children:"新增角色"}),e.jsx(Y,{"data-loc":"client/src/pages/seo/sections/SeoRoleDialogs.tsx:135",children:"建立後可在角色詳情設定這個角色能用哪些功能。"})]}),e.jsxs("div",{"data-loc":"client/src/pages/seo/sections/SeoRoleDialogs.tsx:137",className:"space-y-2",children:[e.jsx(se,{"data-loc":"client/src/pages/seo/sections/SeoRoleDialogs.tsx:138",children:"角色名稱"}),e.jsx(te,{"data-loc":"client/src/pages/seo/sections/SeoRoleDialogs.tsx:139",value:y,onChange:a=>E(a.target.value),placeholder:"例如:SEO 專員",onKeyDown:a=>{a.key==="Enter"&&D()},autoFocus:!0})]}),e.jsxs(G,{"data-loc":"client/src/pages/seo/sections/SeoRoleDialogs.tsx:149",children:[e.jsx(S,{"data-loc":"client/src/pages/seo/sections/SeoRoleDialogs.tsx:150",variant:"outline",onClick:o,children:"取消"}),e.jsx(S,{"data-loc":"client/src/pages/seo/sections/SeoRoleDialogs.tsx:153",onClick:D,disabled:d,children:d?"建立中...":"建立"})]})]})}),e.jsx($,{"data-loc":"client/src/pages/seo/sections/SeoRoleDialogs.tsx:161",open:t.kind==="rename",onOpenChange:N,children:e.jsxs(V,{"data-loc":"client/src/pages/seo/sections/SeoRoleDialogs.tsx:162",className:"sm:max-w-md max-h-[90vh] overflow-y-auto",children:[e.jsx(K,{"data-loc":"client/src/pages/seo/sections/SeoRoleDialogs.tsx:163",children:e.jsx(Q,{"data-loc":"client/src/pages/seo/sections/SeoRoleDialogs.tsx:164",children:"編輯角色名稱"})}),e.jsxs("div",{"data-loc":"client/src/pages/seo/sections/SeoRoleDialogs.tsx:166",className:"space-y-2",children:[e.jsx(se,{"data-loc":"client/src/pages/seo/sections/SeoRoleDialogs.tsx:167",children:"角色名稱"}),e.jsx(te,{"data-loc":"client/src/pages/seo/sections/SeoRoleDialogs.tsx:168",value:C,onChange:a=>A(a.target.value),onKeyDown:a=>{a.key==="Enter"&&R()},autoFocus:!0})]}),e.jsxs(G,{"data-loc":"client/src/pages/seo/sections/SeoRoleDialogs.tsx:177",children:[e.jsx(S,{"data-loc":"client/src/pages/seo/sections/SeoRoleDialogs.tsx:178",variant:"outline",onClick:o,children:"取消"}),e.jsx(S,{"data-loc":"client/src/pages/seo/sections/SeoRoleDialogs.tsx:181",onClick:R,disabled:g,children:g?"儲存中...":"儲存"})]})]})}),e.jsx(Ee,{"data-loc":"client/src/pages/seo/sections/SeoRoleDialogs.tsx:189",open:t.kind==="delete",onOpenChange:N,children:e.jsx(Le,{"data-loc":"client/src/pages/seo/sections/SeoRoleDialogs.tsx:190",children:t.kind==="delete"&&e.jsxs(e.Fragment,{children:[e.jsxs(Ie,{"data-loc":"client/src/pages/seo/sections/SeoRoleDialogs.tsx:193",children:[e.jsxs(Fe,{"data-loc":"client/src/pages/seo/sections/SeoRoleDialogs.tsx:194",children:["刪除角色「",t.role.name,"」?"]}),e.jsxs(Oe,{"data-loc":"client/src/pages/seo/sections/SeoRoleDialogs.tsx:195",children:["刪除後,原本使用這個角色的 ",t.role.memberCount," 位成員會變成未開通,需要重新指派角色才能繼續使用 SEO 系統。此動作無法復原。"]})]}),e.jsxs(_e,{"data-loc":"client/src/pages/seo/sections/SeoRoleDialogs.tsx:200",children:[e.jsx(Te,{"data-loc":"client/src/pages/seo/sections/SeoRoleDialogs.tsx:201",children:"取消"}),e.jsx(Ue,{"data-loc":"client/src/pages/seo/sections/SeoRoleDialogs.tsx:202",onClick:()=>j(t.role.id),disabled:m,className:"bg-destructive text-destructive-foreground hover:bg-destructive/90",children:m?"刪除中...":"確認刪除"})]})]})})}),e.jsx($,{"data-loc":"client/src/pages/seo/sections/SeoRoleDialogs.tsx:216",open:t.kind==="addMember",onOpenChange:N,children:e.jsxs(V,{"data-loc":"client/src/pages/seo/sections/SeoRoleDialogs.tsx:217",className:"sm:max-w-md max-h-[90vh] overflow-y-auto p-0",children:[e.jsxs(K,{"data-loc":"client/src/pages/seo/sections/SeoRoleDialogs.tsx:218",className:"px-6 pt-6",children:[e.jsxs(Q,{"data-loc":"client/src/pages/seo/sections/SeoRoleDialogs.tsx:219",children:["加入成員",t.kind==="addMember"?`到「${t.role.name}」`:""]}),e.jsx(Y,{"data-loc":"client/src/pages/seo/sections/SeoRoleDialogs.tsx:222",children:"點一列即加入,可重複加入多位。"})]}),e.jsxs(Qe,{"data-loc":"client/src/pages/seo/sections/SeoRoleDialogs.tsx:224",shouldFilter:!1,className:"px-2 pb-2",children:[e.jsx(Ge,{"data-loc":"client/src/pages/seo/sections/SeoRoleDialogs.tsx:225",placeholder:"搜尋姓å
1æˆ– Email",value:r,onValueChange:v}),e.jsxs(He,{"data-loc":"client/src/pages/seo/sections/SeoRoleDialogs.tsx:230",children:[e.jsx(Ye,{"data-loc":"client/src/pages/seo/sections/SeoRoleDialogs.tsx:231",children:"沒有可加入的成員"}),e.jsx(Xe,{"data-loc":"client/src/pages/seo/sections/SeoRoleDialogs.tsx:232",children:w.map(a=>e.jsxs(qe,{"data-loc":"client/src/pages/seo/sections/SeoRoleDialogs.tsx:234",value:String(a.userId),disabled:F,onSelect:()=>k(a.userId),children:[e.jsxs("div",{"data-loc":"client/src/pages/seo/sections/SeoRoleDialogs.tsx:240",className:"flex min-w-0 flex-1 flex-col",children:[e.jsx("span",{"data-loc":"client/src/pages/seo/sections/SeoRoleDialogs.tsx:241",className:"truncate text-sm font-medium",children:a.name||`使用者 #${a.userId}`}),e.jsx("span",{"data-loc":"client/src/pages/seo/sections/SeoRoleDialogs.tsx:244",className:"truncate text-xs text-muted-foreground",children:a.email})]}),a.roleName&&e.jsxs("span",{"data-loc":"client/src/pages/seo/sections/SeoRoleDialogs.tsx:247",className:"shrink-0 text-xs text-muted-foreground",children:["目前:",a.roleName]})]},a.userId))})]})]}),e.jsx(G,{"data-loc":"client/src/pages/seo/sections/SeoRoleDialogs.tsx:256",className:"px-6 pb-6",children:e.jsx(S,{"data-loc":"client/src/pages/seo/sections/SeoRoleDialogs.tsx:257",variant:"outline",onClick:o,children:"完成"})})]})}),e.jsx($,{"data-loc":"client/src/pages/seo/sections/SeoRoleDialogs.tsx:265",open:t.kind==="copyFrom",onOpenChange:N,children:e.jsxs(V,{"data-loc":"client/src/pages/seo/sections/SeoRoleDialogs.tsx:266",className:"sm:max-w-md max-h-[90vh] overflow-y-auto",children:[e.jsxs(K,{"data-loc":"client/src/pages/seo/sections/SeoRoleDialogs.tsx:267",children:[e.jsxs(Q,{"data-loc":"client/src/pages/seo/sections/SeoRoleDialogs.tsx:268",children:["複製其他角色的設定",t.kind==="copyFrom"?`到「${t.role.name}」`:""]}),e.jsx(Y,{"data-loc":"client/src/pages/seo/sections/SeoRoleDialogs.tsx:271",children:"選一個角色,把它目前的權限設定套用到這裡(草稿),仍需按「儲存」才會生效。"})]}),e.jsx("div",{"data-loc":"client/src/pages/seo/sections/SeoRoleDialogs.tsx:275",className:"flex flex-col gap-1",children:B.length===0?e.jsx("p",{"data-loc":"client/src/pages/seo/sections/SeoRoleDialogs.tsx:277",className:"py-4 text-center text-sm text-muted-foreground",children:"沒有其他角色可複製"}):B.map(a=>e.jsxs("button",{"data-loc":"client/src/pages/seo/sections/SeoRoleDialogs.tsx:280",type:"button",onClick:()=>b(a.id),className:"flex items-center gap-2 rounded-md px-3 py-2 text-left text-sm hover:bg-muted",children:[e.jsx(Ne,{"data-loc":"client/src/pages/seo/sections/SeoRoleDialogs.tsx:286",className:"h-3.5 w-3.5 shrink-0 text-muted-foreground"}),e.jsx("span",{"data-loc":"client/src/pages/seo/sections/SeoRoleDialogs.tsx:287",className:"flex-1 truncate",children:a.name})]},a.id))}),e.jsx(G,{"data-loc":"client/src/pages/seo/sections/SeoRoleDialogs.tsx:292",children:e.jsx(S,{"data-loc":"client/src/pages/seo/sections/SeoRoleDialogs.tsx:293",variant:"outline",onClick:o,children:"取消"})})]})})]})}function cs(){const{currentOrg:t}=Be(),o=t?.orgId??0,c=M.useUtils(),i=M.seo.permissions.listRoles.useQuery({orgId:o},{enabled:o>0}),x=M.seo.permissions.getMatrix.useQuery({orgId:o},{enabled:o>0}),d=M.seo.permissions.listMembers.useQuery({orgId:o},{enabled:o>0}),n=i.data??[],g=d.data??[],j=x.data??[],[m,k]=h.useState({kind:"pending"}),F=h.useRef(!1);h.useEffect(()=>{if(!i.isPending){if(!F.current&&n.length>0){F.current=!0,k({kind:"role",roleId:n[0].id});return}i.isFetching||m.kind==="role"&&!n.some(s=>s.id===m.roleId)&&k(n.length>0?{kind:"role",roleId:n[0].id}:{kind:"pending"})}},[n,i.isPending,i.isFetching,m]);const b=h.useMemo(()=>{const s={};for(const l of I)s[l]="none";return s},[]),y=h.useMemo(()=>{const s={};for(const l of n)s[l.id]={...b};for(const l of j)s[l.roleId]||(s[l.roleId]={...b}),s[l.roleId][l.featureKey]=l.level;return s},[n,j,b]),[E,C]=h.useState({}),A=s=>E[s]??y[s]??b,r=h.useMemo(()=>n.filter(s=>{const l=E[s.id];if(!l)return!1;const u=y[s.id]??b;return I.some(f=>l[f]!==u[f])}).map(s=>s.id),[n,E,y,b]),v=h.useMemo(()=>g.filter(s=>s.roleId===null&&s.orgRole!=="owner"&&s.orgRole!=="admin"),[g]),N=s=>g.filter(l=>l.roleId===s),[D,R]=h.useState({kind:"none"}),w=()=>R({kind:"none"}),[B,a]=h.useState(null),L=M.seo.permissions.createRole.useMutation({onSuccess:s=>{P.success("角色已新增"),c.seo.permissions.listRoles.invalidate({orgId:o}),w(),k({kind:"role",roleId:s.id})},onError:s=>P.error(s.message)}),J=M.seo.permissions.updateRole.useMutation({onSuccess:()=>
1{P.success("已更新角色名稱"),c.seo.permissions.listRoles.invalidate({orgId:o}),w()},onError:s=>P.error(s.message)}),Z=M.seo.permissions.deleteRole.useMutation({onSuccess:(s,l)=>{P.success("角色已刪除"),c.seo.permissions.listRoles.invalidate({orgId:o}),c.seo.permissions.getMatrix.invalidate({orgId:o}),c.seo.permissions.listMembers.invalidate({orgId:o}),c.seo.permissions.myAccess.invalidate({orgId:o}),C(u=>{if(!(l.roleId in u))return u;const f={...u};return delete f[l.roleId],f}),w()},onError:s=>P.error(s.message)}),O=M.seo.permissions.setMemberRole.useMutation({onSuccess:(s,l)=>{P.success(l.roleId===null?"已移除成員":"已加入成員"),c.seo.permissions.listMembers.invalidate({orgId:o}),c.seo.permissions.listRoles.invalidate({orgId:o})},onError:s=>P.error(s.message)}),ee=M.seo.permissions.updateMatrix.useMutation({onSuccess:()=>{P.success("已儲存"),c.seo.permissions.getMatrix.invalidate({orgId:o}),c.seo.permissions.myAccess.invalidate({orgId:o}),a(null)},onError:s=>{P.error(s.message),a(null)}}),le=(s,l,u)=>{C(f=>({...f,[s]:{...f[s]??y[s]??b,[l]:u}}))},ne=(s,l)=>{C(u=>{const _={...u[s]??y[s]??b};for(const z of U)_[z.key]=z.levels.includes(l)?l:z.levels[z.levels.length-1];return{...u,[s]:_}})},ce=s=>{a(s);const l=A(s),u=I.map(f=>({featureKey:f,level:l[f]}));ee.mutate({orgId:o,roleId:s,permissions:u})},ie=s=>{C(l=>{if(!(s in l))return l;const u={...l};return delete u[s],u})},p=m.kind==="role"?n.find(s=>s.id===m.roleId)??null:null;return e.jsxs("div",{"data-loc":"client/src/pages/seo/SeoPermissions.tsx:220",className:"flex flex-col gap-4 lg:grid lg:grid-cols-[212px_minmax(0,1fr)] lg:items-start xl:grid-cols-[212px_minmax(0,1fr)_296px]",children:[e.jsx("div",{"data-loc":"client/src/pages/seo/SeoPermissions.tsx:222",className:"lg:row-span-2 xl:row-span-1",children:e.jsx(We,{"data-loc":"client/src/pages/seo/SeoPermissions.tsx:223",roles:n,isLoading:i.isPending,selection:m,onSelect:k,dirtyRoleIds:r,pendingCount:v.length,onCreateRole:()=>R({kind:"create"})})}),e.jsx("div",{"data-loc":"client/src/pages/seo/SeoPermissions.tsx:235",className:"min-w-0",children:!i.isPending&&n.length===0?e.jsx(ze,{"data-loc":"client/src/pages/seo/SeoPermissions.tsx:237",children:e.jsx($e,{"data-loc":"client/src/pages/seo/SeoPermissions.tsx:238",className:"py-16",children:e.jsxs("div",{"data-loc":"client/src/pages/seo/SeoPermissions.tsx:239",className:"mx-auto flex max-w-md flex-col items-center gap-3 text-center",children:[e.jsx("div",{"data-loc":"client/src/pages/seo/SeoPermissions.tsx:240",className:"rounded-full bg-muted p-3",children:e.jsx(De,{"data-loc":"client/src/pages/seo/SeoPermissions.tsx:241",className:"h-8 w-8 text-muted-foreground"})}),e.jsx("h3",{"data-loc":"client/src/pages/seo/SeoPermissions.tsx:243",className:"text-lg font-semibold",children:"還沒有任何角色"}),e.jsx("p",{"data-loc":"client/src/pages/seo/SeoPermissions.tsx:244",className:"text-sm text-muted-foreground",children:"先新增第一個角色,再設定它能用哪些功能、指派成員。"}),e.jsxs(S,{"data-loc":"client/src/pages/seo/SeoPermissions.tsx:247",className:"mt-2",onClick:()=>R({kind:"create"}),children:[e.jsx(W,{"data-loc":"client/src/pages/seo/SeoPermissions.tsx:248",className:"mr-1 h-4 w-4"}),"新增角色"]})]})})}):m.kind==="pending"?e.jsx(ts,{"data-loc":"client/src/pages/seo/SeoPermissions.tsx:255",members:v,roles:n,isAssigning:O.isPending,onAssign:(s,l)=>O.mutate({orgId:o,userId:s,roleId:l})}):p?e.jsx(ss,{"data-loc":"client/src/pages/seo/SeoPermissions.tsx:262",role:p,levels:A(p.id),isDirty:r.includes(p.id),isSaving:ee.isPending&&B===p.id,otherDirtyRoleNames:n.filter(s=>s.id!==p.id&&r.includes(s.id)).map(s=>s.name),members:N(p.id),isMemberMutating:O.isPending,onChangeLevel:(s,l)=>le(p.id,s,l),onBulkSet:s=>ne(p.id,s),onSave:()=>ce(p.id),onReset:()=>ie(p.id),onRename:()=>R({kind:"rename",role:p}),onDelete:()=>R({kind:"delete",role:p}),onCopyFrom:()=>R({kind:"copyFrom",role:p}),onAddMember:()=>R({kind:"addMember",role:p}),onRemoveMember:s=>O.mutate({orgId:o,userId:s,roleId:null})}):null}),n.length>0&&e.jsx("div",{"data-loc":"client/src/pages/seo/SeoPermissions.tsx:287",className:"min-w-0 xl:sticky xl:top-4",children:e.jsx(ls,{"data-loc":"client/src/pages/seo/SeoPermissions.tsx:288",selection:m,roleName:p?.name??null,levels:p?A(p.id):null})}),e.jsx(ns,{"data-loc":"client/src/pages/seo/SeoPermissions.tsx:296",state:D,onClose:w,roles:n,members:g,onCreateRole:s=>L.mutate({orgId:o,name:s}),isCreating:L.isPending,onRenameRole:(s,l)=>J.mutate({orgId:o,roleId:s,name:l}),isRenaming:J.isPending,onDeleteRole:s=>Z.mutate({orgId:o,roleId:s}),isDeleting:Z.isPending,onAddMember:s=>{D.kind==="addMember"&&O.mutate({orgId:o,userId:s,roleId:D.role.id})},isAddingMember:O.isPending,onCopyFrom:s=>{if(D.kind!=="copyFrom")return;const l=D.role.id,u=A(s),f=n.find(_=>_.id===s)?.name??"";C(_=>({..._,[l]:{...u}})),w(),P.success(`已套用「${f}」的權限設定,記得按「儲存」`)}})]})}function us(){return e.jsx(Ve,{"data-loc":"client/src/pages/seo/SeoPermissions.tsx:328",title:"權限管理",subtitle:"設定角色、功能權限與成員指派",children:e.jsx(cs,{"data-loc":"client/src/pages/seo/SeoPermissions.tsx:329"})})}export{us 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.