forked from EduCraft/curriculum-project-hub
style(admin-web): apply Prettier formatting
Run `prettier --write .` across all source files. Changes are purely formatting: trailing commas, line wrapping at 120 chars, import reordering, and CSS whitespace. No logic changes. Verified with `prettier --check .` and `svelte-check` (0 errors, 0 warnings).
This commit is contained in:
@@ -11,9 +11,7 @@
|
||||
import { toastError, toastSuccess } from '$lib/toast';
|
||||
|
||||
let orgSlug = $derived(page.params.slug ?? '');
|
||||
let org = $derived(
|
||||
$session.me?.organizations.find((o) => o.slug === orgSlug) as OrgMembership | undefined
|
||||
);
|
||||
let org = $derived($session.me?.organizations.find((o) => o.slug === orgSlug) as OrgMembership | undefined);
|
||||
|
||||
let settings = $state<{ membersCanCreateProjects: boolean } | null>(null);
|
||||
let usage = $state<Awaited<ReturnType<typeof api.usage>> | null>(null);
|
||||
@@ -82,15 +80,9 @@
|
||||
|
||||
<div class="saas-card-pad sm:col-span-2">
|
||||
<p class="saas-section-title mb-1">项目自助创建策略</p>
|
||||
<p class="saas-muted mb-4">
|
||||
开启后,普通老师可在飞书群自助创建项目;关闭后仅所有者与管理员可建。
|
||||
</p>
|
||||
<p class="saas-muted mb-4">开启后,普通老师可在飞书群自助创建项目;关闭后仅所有者与管理员可建。</p>
|
||||
<div class="flex items-center gap-3 border border-surface-300 bg-surface-100 px-4 py-3">
|
||||
<SwitchControl
|
||||
checked={settings.membersCanCreateProjects}
|
||||
disabled={saving}
|
||||
onchange={setMembersCanCreate}
|
||||
/>
|
||||
<SwitchControl checked={settings.membersCanCreateProjects} disabled={saving} onchange={setMembersCanCreate} />
|
||||
<div>
|
||||
<div class="text-sm font-medium text-surface-900">允许成员自助创建项目</div>
|
||||
<div class="text-xs text-surface-600">普通成员在飞书群中自助建项</div>
|
||||
@@ -139,9 +131,7 @@
|
||||
<tr>
|
||||
<td class="font-medium">{p.projectName}</td>
|
||||
<td class="tabular-nums">{fmtNum(p.runCount)}</td>
|
||||
<td class="tabular-nums text-surface-600"
|
||||
>{fmtNum(p.inputTokens)} / {fmtNum(p.outputTokens)}</td
|
||||
>
|
||||
<td class="tabular-nums text-surface-600">{fmtNum(p.inputTokens)} / {fmtNum(p.outputTokens)}</td>
|
||||
<td class="tabular-nums">{fmtCost(p.costUsd)}</td>
|
||||
</tr>
|
||||
{/each}
|
||||
|
||||
@@ -158,12 +158,7 @@
|
||||
</div>
|
||||
<div>
|
||||
<Label.Root class="saas-label" for="verification-token">Verification Token(可选)</Label.Root>
|
||||
<input
|
||||
id="verification-token"
|
||||
class="saas-input"
|
||||
type="password"
|
||||
bind:value={verificationToken}
|
||||
/>
|
||||
<input id="verification-token" class="saas-input" type="password" bind:value={verificationToken} />
|
||||
</div>
|
||||
<div>
|
||||
<Label.Root class="saas-label" for="encrypt-key">Encrypt Key(可选)</Label.Root>
|
||||
|
||||
@@ -43,11 +43,9 @@
|
||||
const m = await api.addMember(slug, {
|
||||
feishuOpenId: newOpenId.trim(),
|
||||
role: newRole,
|
||||
...(newName.trim() ? { displayName: newName.trim() } : {})
|
||||
...(newName.trim() ? { displayName: newName.trim() } : {}),
|
||||
});
|
||||
members = [...members, m].sort(
|
||||
(a, b) => a.role.localeCompare(b.role) || a.createdAt.localeCompare(b.createdAt)
|
||||
);
|
||||
members = [...members, m].sort((a, b) => a.role.localeCompare(b.role) || a.createdAt.localeCompare(b.createdAt));
|
||||
newOpenId = '';
|
||||
newName = '';
|
||||
toastSuccess('成员已添加');
|
||||
@@ -128,11 +126,11 @@
|
||||
<td>
|
||||
<div class="flex items-center gap-2.5">
|
||||
{#if m.avatarUrl}
|
||||
<img src={m.avatarUrl} alt="" class="h-7 w-7 border border-surface-300 object-cover" />
|
||||
{:else}
|
||||
<div
|
||||
class="flex h-7 w-7 items-center justify-center border border-primary-300 bg-primary-100 text-xs font-semibold text-primary-800"
|
||||
>
|
||||
<img src={m.avatarUrl} alt="" class="h-7 w-7 border border-surface-300 object-cover" />
|
||||
{:else}
|
||||
<div
|
||||
class="flex h-7 w-7 items-center justify-center border border-primary-300 bg-primary-100 text-xs font-semibold text-primary-800"
|
||||
>
|
||||
{m.displayName.slice(0, 1)}
|
||||
</div>
|
||||
{/if}
|
||||
@@ -140,7 +138,7 @@
|
||||
</div>
|
||||
</td>
|
||||
<td class="font-mono text-xs text-surface-700">{m.feishuOpenId}</td>
|
||||
<td class="min-w-[9rem]">
|
||||
<td class="min-w-36">
|
||||
<SelectField
|
||||
items={roleItems}
|
||||
value={m.role}
|
||||
@@ -151,7 +149,7 @@
|
||||
</td>
|
||||
<td class="text-surface-700">{fmtDate(m.createdAt)}</td>
|
||||
<td class="text-right">
|
||||
<button class="saas-btn-danger !py-1 text-sm" onclick={() => revoke(m)}>移除</button>
|
||||
<button class="saas-btn-danger py-1! text-sm" onclick={() => revoke(m)}>移除</button>
|
||||
</td>
|
||||
</tr>
|
||||
{/each}
|
||||
|
||||
@@ -42,7 +42,7 @@
|
||||
try {
|
||||
await api.createFolder(slug, {
|
||||
name: folderName.trim(),
|
||||
...(folderParent ? { parentId: folderParent } : {})
|
||||
...(folderParent ? { parentId: folderParent } : {}),
|
||||
});
|
||||
folderName = '';
|
||||
folderParent = '';
|
||||
@@ -59,7 +59,7 @@
|
||||
try {
|
||||
const res = await api.createProject(slug, {
|
||||
name: projectName.trim(),
|
||||
...(projectFolder ? { folderId: projectFolder } : {})
|
||||
...(projectFolder ? { folderId: projectFolder } : {}),
|
||||
});
|
||||
projectName = '';
|
||||
projectFolder = '';
|
||||
@@ -85,10 +85,7 @@
|
||||
|
||||
function folderItems() {
|
||||
if (!data) return [{ value: '', label: '(根)' }];
|
||||
return [
|
||||
{ value: '', label: '(根)' },
|
||||
...data.folders.map((f) => ({ value: f.id, label: folderPath(f) }))
|
||||
];
|
||||
return [{ value: '', label: '(根)' }, ...data.folders.map((f) => ({ value: f.id, label: folderPath(f) }))];
|
||||
}
|
||||
|
||||
$effect(() => {
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
type TeamAccessEntry,
|
||||
type TeamRow,
|
||||
type SessionSummary,
|
||||
type ExplorerData
|
||||
type ExplorerData,
|
||||
} from '$lib/api';
|
||||
import { fmtDate, permissionRoleLabel } from '$lib/format';
|
||||
import { PERMISSION_ROLES, PERMISSION_ROLE_LABELS } from '$lib/constants';
|
||||
@@ -43,7 +43,7 @@
|
||||
api.teamAccess(slug, projectId),
|
||||
api.sessions(slug, projectId),
|
||||
api.teams(slug),
|
||||
api.explorer(slug)
|
||||
api.explorer(slug),
|
||||
]);
|
||||
proj = p;
|
||||
access = a.access;
|
||||
@@ -128,17 +128,11 @@
|
||||
function folderItems() {
|
||||
const items = [{ value: '', label: '(根)' }];
|
||||
if (!explorer) return items;
|
||||
return [
|
||||
...items,
|
||||
...explorer.folders.map((f) => ({ value: f.id, label: f.name }))
|
||||
];
|
||||
return [...items, ...explorer.folders.map((f) => ({ value: f.id, label: f.name }))];
|
||||
}
|
||||
|
||||
function teamItems() {
|
||||
return [
|
||||
{ value: '', label: '选择团队…' },
|
||||
...teams.map((t) => ({ value: t.id, label: `${t.name}(${t.slug})` }))
|
||||
];
|
||||
return [{ value: '', label: '选择团队…' }, ...teams.map((t) => ({ value: t.id, label: `${t.name}(${t.slug})` }))];
|
||||
}
|
||||
|
||||
$effect(() => {
|
||||
@@ -152,7 +146,10 @@
|
||||
<ErrorBanner message={error} onretry={load} />
|
||||
{:else if proj}
|
||||
<div class="mb-2">
|
||||
<a href={`/admin/org/${slug}/projects`} class="inline-flex items-center gap-1 text-sm text-surface-700 hover:text-primary-600">
|
||||
<a
|
||||
href={`/admin/org/${slug}/projects`}
|
||||
class="inline-flex items-center gap-1 text-sm text-surface-700 hover:text-primary-600"
|
||||
>
|
||||
← 返回项目列表
|
||||
</a>
|
||||
</div>
|
||||
@@ -160,11 +157,11 @@
|
||||
{@const detail = proj}
|
||||
<PageHeader title={detail.name} description={`项目是权限边界;通过团队授予 ${roleChain}。`}>
|
||||
{#snippet actions()}
|
||||
<button class="saas-btn-secondary !py-1.5 text-sm" onclick={rename}>重命名</button>
|
||||
<button class="saas-btn-secondary py-1.5! text-sm" onclick={rename}>重命名</button>
|
||||
{#if detail.binding}
|
||||
<button class="saas-btn-secondary !py-1.5 text-sm" onclick={archiveBinding}>解绑飞书群</button>
|
||||
<button class="saas-btn-secondary py-1.5! text-sm" onclick={archiveBinding}>解绑飞书群</button>
|
||||
{/if}
|
||||
<button class="saas-btn-danger !py-1.5 text-sm" onclick={archiveProject}>归档</button>
|
||||
<button class="saas-btn-danger py-1.5! text-sm" onclick={archiveProject}>归档</button>
|
||||
{/snippet}
|
||||
</PageHeader>
|
||||
|
||||
@@ -204,7 +201,7 @@
|
||||
|
||||
{#if explorer}
|
||||
<div class="mt-5 flex flex-wrap items-end gap-2 border-t border-surface-100 pt-4">
|
||||
<div class="min-w-[12rem] flex-1">
|
||||
<div class="min-w-48 flex-1">
|
||||
<p class="saas-label">移动到文件夹</p>
|
||||
<SelectField items={folderItems()} bind:value={moveFolder} />
|
||||
</div>
|
||||
@@ -242,7 +239,7 @@
|
||||
<td class="font-mono text-xs">/{g.teamSlug}</td>
|
||||
<td><span class="saas-badge-primary">{permissionRoleLabel(g.role)}</span></td>
|
||||
<td class="text-right">
|
||||
<button class="saas-btn-danger !py-1 text-xs" onclick={() => revoke(g)}>撤销</button>
|
||||
<button class="saas-btn-danger py-1! text-xs" onclick={() => revoke(g)}>撤销</button>
|
||||
</td>
|
||||
</tr>
|
||||
{/each}
|
||||
|
||||
@@ -62,7 +62,7 @@
|
||||
saving = true;
|
||||
const body: { baseUrl: string; authToken: string; anthropicApiKey?: string } = {
|
||||
baseUrl: url,
|
||||
authToken: token
|
||||
authToken: token,
|
||||
};
|
||||
const key = anthropicApiKey.trim();
|
||||
if (key !== '') body.anthropicApiKey = key;
|
||||
@@ -122,10 +122,7 @@
|
||||
<td class="text-surface-600">{fmtDate(row.updatedAt)}</td>
|
||||
<td>
|
||||
{#if row.mode === 'BYOK'}
|
||||
<button
|
||||
class="saas-btn-ghost !px-2 !py-1 text-xs"
|
||||
onclick={() => startRotate(row)}>轮换</button
|
||||
>
|
||||
<button class="saas-btn-ghost px-2! py-1! text-xs" onclick={() => startRotate(row)}>轮换</button>
|
||||
{:else}
|
||||
<span class="text-xs text-surface-500">平台管理</span>
|
||||
{/if}
|
||||
@@ -146,21 +143,11 @@
|
||||
<div class="grid gap-5">
|
||||
<div>
|
||||
<Label.Root class="saas-label" for="provider-id">供应方 ID</Label.Root>
|
||||
<input
|
||||
id="provider-id"
|
||||
class="saas-input font-mono text-sm"
|
||||
bind:value={providerId}
|
||||
placeholder="openrouter"
|
||||
/>
|
||||
<input id="provider-id" class="saas-input font-mono text-sm" bind:value={providerId} placeholder="openrouter" />
|
||||
</div>
|
||||
<div>
|
||||
<Label.Root class="saas-label" for="base-url">接口地址</Label.Root>
|
||||
<input
|
||||
id="base-url"
|
||||
class="saas-input"
|
||||
placeholder="https://openrouter.ai/api"
|
||||
bind:value={baseUrl}
|
||||
/>
|
||||
<input id="base-url" class="saas-input" placeholder="https://openrouter.ai/api" bind:value={baseUrl} />
|
||||
</div>
|
||||
<div>
|
||||
<Label.Root class="saas-label" for="auth-token">访问令牌</Label.Root>
|
||||
|
||||
@@ -52,7 +52,7 @@
|
||||
await api.createTeam(slug, {
|
||||
slug: teamSlug,
|
||||
name: newName.trim(),
|
||||
...(newDesc.trim() ? { description: newDesc.trim() } : {})
|
||||
...(newDesc.trim() ? { description: newDesc.trim() } : {}),
|
||||
});
|
||||
newSlug = '';
|
||||
newName = '';
|
||||
@@ -165,10 +165,10 @@
|
||||
<span class="font-mono text-xs text-surface-600">/{t.slug}</span>
|
||||
<span class="saas-badge-neutral">{t.memberCount} 成员</span>
|
||||
<div class="ml-auto flex flex-wrap gap-2">
|
||||
<Collapsible.Trigger class="saas-btn-secondary !py-1.5 text-sm">
|
||||
<Collapsible.Trigger class="saas-btn-secondary py-1.5! text-sm">
|
||||
{expandedId === t.id ? '收起' : '管理成员'}
|
||||
</Collapsible.Trigger>
|
||||
<button type="button" class="saas-btn-danger !py-1.5 text-sm" onclick={() => archiveTeam(t)}>
|
||||
<button type="button" class="saas-btn-danger py-1.5! text-sm" onclick={() => archiveTeam(t)}>
|
||||
归档
|
||||
</button>
|
||||
</div>
|
||||
@@ -213,7 +213,7 @@
|
||||
<td class="font-mono text-xs">{m.feishuOpenId}</td>
|
||||
<td class="text-surface-700">{fmtDate(m.createdAt)}</td>
|
||||
<td class="text-right">
|
||||
<button class="saas-btn-danger !py-1 text-xs" onclick={() => revokeMember(t, m)}>
|
||||
<button class="saas-btn-danger py-1! text-xs" onclick={() => revokeMember(t, m)}>
|
||||
移除
|
||||
</button>
|
||||
</td>
|
||||
|
||||
Reference in New Issue
Block a user