forked from EduCraft/curriculum-project-hub
Merge branch 'chore/role-label-zh'
This commit is contained in:
@@ -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,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> {
|
||||||
|
|||||||
@@ -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>
|
||||||
|
|
||||||
|
|||||||
@@ -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: "可管理",
|
||||||
|
};
|
||||||
Reference in New Issue
Block a user