Merge branch 'chore/role-label-zh'

This commit is contained in:
ymy
2026-07-27 15:57:42 +08:00
5 changed files with 21 additions and 7 deletions
+5 -4
View File
@@ -15,6 +15,7 @@
*/ */
import { api } from "./api.js"; import { api } from "./api.js";
import { toastOk, toastErr } from "./stores.js"; import { toastOk, toastErr } from "./stores.js";
import { ROLE_LABEL } from "./labels.js";
import type { Grant, MemberGroupSearchResult, NodeDetail, Role, UserSearchResult } from "./types.js"; import type { Grant, MemberGroupSearchResult, NodeDetail, Role, UserSearchResult } from "./types.js";
import Icon from "./Icon.svelte"; import Icon from "./Icon.svelte";
import Modal from "./Modal.svelte"; import Modal from "./Modal.svelte";
@@ -199,7 +200,7 @@
} }
async function revoke(g: Grant): Promise<void> { async function revoke(g: Grant): Promise<void> {
if (!confirm(`删除「${g.principalName ?? g.principalId}」的 ${g.role} 授权?`)) return; if (!confirm(`删除「${g.principalName ?? g.principalId}」的${ROLE_LABEL[g.role]}授权?`)) return;
try { try {
await api(`/database/api/nodes/${node.id}/grants/${encodeURIComponent(g.id)}`, { await api(`/database/api/nodes/${node.id}/grants/${encodeURIComponent(g.id)}`, {
method: "DELETE", method: "DELETE",
@@ -275,11 +276,11 @@
onchange={(e) => void changeRole(g, e.currentTarget.value as Role)} onchange={(e) => void changeRole(g, e.currentTarget.value as Role)}
> >
{#each ROLES as r (r)} {#each ROLES as r (r)}
<option value={r}>{r}</option> <option value={r}>{ROLE_LABEL[r]}</option>
{/each} {/each}
</select> </select>
{:else} {:else}
<span class="file-meta">{g.role}</span> <span class="file-meta">{ROLE_LABEL[g.role]}</span>
{/if} {/if}
</td> </td>
<td class="file-meta">{fmtDate(g.createdAt)}</td> <td class="file-meta">{fmtDate(g.createdAt)}</td>
@@ -351,7 +352,7 @@
<label class="form-label" for="grant-role">权限</label> <label class="form-label" for="grant-role">权限</label>
<select id="grant-role" class="select" bind:value={role}> <select id="grant-role" class="select" bind:value={role}>
{#each ROLES as r (r)} {#each ROLES as r (r)}
<option value={r}>{r}</option> <option value={r}>{ROLE_LABEL[r]}</option>
{/each} {/each}
</select> </select>
</div> </div>
@@ -2,6 +2,7 @@
import { api } from "./api.js"; import { api } from "./api.js";
import { currentNode, breadcrumb, bumpTree, clearSelectedFile } from "./browser.js"; import { currentNode, breadcrumb, bumpTree, clearSelectedFile } from "./browser.js";
import { toastOk, toastErr } from "./stores.js"; import { toastOk, toastErr } from "./stores.js";
import { ROLE_LABEL } from "./labels.js";
import OverviewPanel from "./OverviewPanel.svelte"; import OverviewPanel from "./OverviewPanel.svelte";
import FilesPanel from "./FilesPanel.svelte"; import FilesPanel from "./FilesPanel.svelte";
import GrantsPanel from "./GrantsPanel.svelte"; import GrantsPanel from "./GrantsPanel.svelte";
@@ -99,7 +100,7 @@
<div class="flex items-center gap-2 text-[17px] font-semibold text-ink"> <div class="flex items-center gap-2 text-[17px] font-semibold text-ink">
{node.name} {node.name}
<span class="tag">{node.kind === "PROJECT" ? "项目" : "文件夹"}</span> <span class="tag">{node.kind === "PROJECT" ? "项目" : "文件夹"}</span>
<span class="tag !border-line !text-ink-2">{node.role}</span> <span class="tag !border-line !text-ink-2">{ROLE_LABEL[node.role]}</span>
</div> </div>
<div class="flex gap-1.5"> <div class="flex gap-1.5">
{#if canEdit && node.kind === "FOLDER"} {#if canEdit && node.kind === "FOLDER"}
+2 -1
View File
@@ -2,6 +2,7 @@
import { api } from "./api.js"; import { api } from "./api.js";
import { toastOk, toastErr } from "./stores.js"; import { toastOk, toastErr } from "./stores.js";
import { currentNode } from "./browser.js"; import { currentNode } from "./browser.js";
import { ROLE_LABEL } from "./labels.js";
import type { ExportJob, NodeDetail } from "./types.js"; import type { ExportJob, NodeDetail } from "./types.js";
import Modal from "./Modal.svelte"; import Modal from "./Modal.svelte";
@@ -13,7 +14,7 @@
const canEdit = $derived(node.role === "MANAGE" || node.role === "EDIT"); const canEdit = $derived(node.role === "MANAGE" || node.role === "EDIT");
const canManage = $derived(node.role === "MANAGE"); const canManage = $derived(node.role === "MANAGE");
const roleLabel = $derived(node.role === "MANAGE" ? "可管理" : node.role === "EDIT" ? "可编辑" : "只读"); const roleLabel = $derived(ROLE_LABEL[node.role]);
/** 独立权限开关(仅 PROJECT;关闭时只继承父级权限,创建者除外)。 */ /** 独立权限开关(仅 PROJECT;关闭时只继承父级权限,创建者除外)。 */
async function toggleIndependent(): Promise<void> { async function toggleIndependent(): Promise<void> {
+2 -1
View File
@@ -3,6 +3,7 @@
import { api } from "./api.js"; import { api } from "./api.js";
import { expanded, currentNode, breadcrumb, toggleExpanded, treeVersion } from "./browser.js"; import { expanded, currentNode, breadcrumb, toggleExpanded, treeVersion } from "./browser.js";
import { toastErr } from "./stores.js"; import { toastErr } from "./stores.js";
import { ROLE_LABEL } from "./labels.js";
import type { BreadcrumbEntry, NodeChild, NodeDetail } from "./types.js"; import type { BreadcrumbEntry, NodeChild, NodeDetail } from "./types.js";
let { node, depth }: { node: NodeChild; depth: number } = $props(); let { node, depth }: { node: NodeChild; depth: number } = $props();
@@ -64,7 +65,7 @@
</span> </span>
<span class="truncate">{node.name}</span> <span class="truncate">{node.name}</span>
{#if node.role !== "MANAGE"} {#if node.role !== "MANAGE"}
<span class="ml-auto pr-1 font-mono text-[10px] text-ink-3">{node.role}</span> <span class="ml-auto pr-1 text-[10px] text-ink-3">{ROLE_LABEL[node.role]}</span>
{/if} {/if}
</div> </div>
+10
View File
@@ -0,0 +1,10 @@
/** 展示层文案(与 API 枚举值解耦;传参仍用英文枚举)。 */
import type { Role } from "./types.js";
/** 文件库权限级(契约 8.1 MANAGE>EDIT>VIEW)的中文展示名。 */
export const ROLE_LABEL: Record<Role, string> = {
VIEW: "只读",
EDIT: "可编辑",
MANAGE: "可管理",
};