forked from bai/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:
@@ -18,7 +18,7 @@ async function request(method: string, url: string, body?: unknown): Promise<unk
|
||||
method,
|
||||
credentials: 'same-origin',
|
||||
headers: body !== undefined ? { 'content-type': 'application/json' } : undefined,
|
||||
body: body !== undefined ? JSON.stringify(body) : undefined
|
||||
body: body !== undefined ? JSON.stringify(body) : undefined,
|
||||
};
|
||||
const res = await fetch(url, init);
|
||||
const text = await res.text();
|
||||
@@ -194,7 +194,11 @@ export const api = {
|
||||
me: () => get('/api/me') as Promise<MeResponse>,
|
||||
logout: () => post('/auth/logout'),
|
||||
|
||||
org: (slug: string) => get(orgBase(slug)) as Promise<{ organization: { id: string; slug: string; name: string; status: string }; actorRole: string }>,
|
||||
org: (slug: string) =>
|
||||
get(orgBase(slug)) as Promise<{
|
||||
organization: { id: string; slug: string; name: string; status: string };
|
||||
actorRole: string;
|
||||
}>,
|
||||
settings: (slug: string) => get(`${orgBase(slug)}/settings`) as Promise<{ membersCanCreateProjects: boolean }>,
|
||||
setSettings: (slug: string, body: { membersCanCreateProjects: boolean }) =>
|
||||
patch(`${orgBase(slug)}/settings`, body) as Promise<{ membersCanCreateProjects: boolean }>,
|
||||
@@ -202,18 +206,15 @@ export const api = {
|
||||
members: (slug: string) => get(`${orgBase(slug)}/members`) as Promise<{ members: OrgMember[] }>,
|
||||
addMember: (slug: string, body: { feishuOpenId: string; displayName?: string; role: string }) =>
|
||||
post(`${orgBase(slug)}/members`, body) as Promise<OrgMember>,
|
||||
setMemberRole: (slug: string, userId: string, role: string) =>
|
||||
patch(`${orgBase(slug)}/members/${userId}`, { role }),
|
||||
revokeMember: (slug: string, userId: string) =>
|
||||
post(`${orgBase(slug)}/members/${userId}/revoke`),
|
||||
setMemberRole: (slug: string, userId: string, role: string) => patch(`${orgBase(slug)}/members/${userId}`, { role }),
|
||||
revokeMember: (slug: string, userId: string) => post(`${orgBase(slug)}/members/${userId}/revoke`),
|
||||
|
||||
teams: (slug: string) => get(`${orgBase(slug)}/teams`) as Promise<{ teams: TeamRow[] }>,
|
||||
createTeam: (slug: string, body: { slug: string; name: string; description?: string }) =>
|
||||
post(`${orgBase(slug)}/teams`, body) as Promise<TeamRow>,
|
||||
updateTeam: (slug: string, teamId: string, body: { name?: string; description?: string | null }) =>
|
||||
patch(`${orgBase(slug)}/teams/${teamId}`, body) as Promise<TeamRow>,
|
||||
archiveTeam: (slug: string, teamId: string) =>
|
||||
post(`${orgBase(slug)}/teams/${teamId}/archive`),
|
||||
archiveTeam: (slug: string, teamId: string) => post(`${orgBase(slug)}/teams/${teamId}/archive`),
|
||||
teamMembers: (slug: string, teamId: string) =>
|
||||
get(`${orgBase(slug)}/teams/${teamId}/members`) as Promise<{ members: TeamMemberRow[] }>,
|
||||
addTeamMember: (slug: string, teamId: string, body: { userId?: string; feishuOpenId?: string }) =>
|
||||
@@ -223,23 +224,30 @@ export const api = {
|
||||
|
||||
explorer: (slug: string) => get(`${orgBase(slug)}/explorer`) as Promise<ExplorerData>,
|
||||
createFolder: (slug: string, body: { name: string; parentId?: string; sortKey?: string }) =>
|
||||
post(`${orgBase(slug)}/folders`, body) as Promise<{ id: string; name: string; parentId: string | null; sortKey: string }>,
|
||||
post(`${orgBase(slug)}/folders`, body) as Promise<{
|
||||
id: string;
|
||||
name: string;
|
||||
parentId: string | null;
|
||||
sortKey: string;
|
||||
}>,
|
||||
renameFolder: (slug: string, folderId: string, body: { name?: string; sortKey?: string; parentId?: string | null }) =>
|
||||
patch(`${orgBase(slug)}/folders/${folderId}`, body) as Promise<{ id: string; name: string; parentId: string | null; sortKey: string }>,
|
||||
patch(`${orgBase(slug)}/folders/${folderId}`, body) as Promise<{
|
||||
id: string;
|
||||
name: string;
|
||||
parentId: string | null;
|
||||
sortKey: string;
|
||||
}>,
|
||||
archiveFolder: (slug: string, folderId: string) =>
|
||||
post(`${orgBase(slug)}/folders/${folderId}/archive`) as Promise<{ archived: true; folderId: string }>,
|
||||
createProject: (slug: string, body: { name: string; folderId?: string }) =>
|
||||
post(`${orgBase(slug)}/projects`, body) as Promise<{ id: string; name: string }>,
|
||||
project: (slug: string, projectId: string) =>
|
||||
get(`${orgBase(slug)}/projects/${projectId}`) as Promise<ProjectDetail>,
|
||||
project: (slug: string, projectId: string) => get(`${orgBase(slug)}/projects/${projectId}`) as Promise<ProjectDetail>,
|
||||
renameProject: (slug: string, projectId: string, name: string) =>
|
||||
patch(`${orgBase(slug)}/projects/${projectId}`, { name }),
|
||||
moveProject: (slug: string, projectId: string, folderId: string | null) =>
|
||||
patch(`${orgBase(slug)}/projects/${projectId}/folder`, { folderId }),
|
||||
archiveProject: (slug: string, projectId: string) =>
|
||||
post(`${orgBase(slug)}/projects/${projectId}/archive`),
|
||||
archiveBinding: (slug: string, projectId: string) =>
|
||||
post(`${orgBase(slug)}/projects/${projectId}/binding/archive`),
|
||||
archiveProject: (slug: string, projectId: string) => post(`${orgBase(slug)}/projects/${projectId}/archive`),
|
||||
archiveBinding: (slug: string, projectId: string) => post(`${orgBase(slug)}/projects/${projectId}/binding/archive`),
|
||||
|
||||
teamAccess: (slug: string, projectId: string) =>
|
||||
get(`${orgBase(slug)}/projects/${projectId}/team-access`) as Promise<{ access: TeamAccessEntry[] }>,
|
||||
@@ -249,7 +257,9 @@ export const api = {
|
||||
del(`${orgBase(slug)}/projects/${projectId}/team-access/${teamId}`),
|
||||
|
||||
sessions: (slug: string, projectId: string, limit?: number) =>
|
||||
get(`${orgBase(slug)}/projects/${projectId}/sessions${limit !== undefined ? `?limit=${limit}` : ''}`) as Promise<{ sessions: SessionSummary[] }>,
|
||||
get(`${orgBase(slug)}/projects/${projectId}/sessions${limit !== undefined ? `?limit=${limit}` : ''}`) as Promise<{
|
||||
sessions: SessionSummary[];
|
||||
}>,
|
||||
usage: (slug: string, params?: { from?: string; to?: string; folderId?: string }) => {
|
||||
const q = new URLSearchParams();
|
||||
if (params?.from) q.set('from', params.from);
|
||||
@@ -286,5 +296,5 @@ export const api = {
|
||||
},
|
||||
) => put(`${orgBase(slug)}/feishu-application-connection`, body) as Promise<FeishuApplicationConnection>,
|
||||
disableFeishuApplication: (slug: string) =>
|
||||
del(`${orgBase(slug)}/feishu-application-connection`) as Promise<FeishuApplicationConnection>
|
||||
del(`${orgBase(slug)}/feishu-application-connection`) as Promise<FeishuApplicationConnection>,
|
||||
};
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
checked = $bindable(false),
|
||||
disabled = false,
|
||||
class: className = '',
|
||||
onchange
|
||||
onchange,
|
||||
}: {
|
||||
checked?: boolean;
|
||||
disabled?: boolean;
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
let {
|
||||
title = '暂无数据',
|
||||
description,
|
||||
action
|
||||
action,
|
||||
}: {
|
||||
title?: string;
|
||||
description?: string;
|
||||
@@ -13,7 +13,9 @@
|
||||
</script>
|
||||
|
||||
<div class="saas-empty">
|
||||
<div class="mb-1 flex h-12 w-12 items-center justify-center border border-surface-300 bg-surface-100 text-surface-600">
|
||||
<div
|
||||
class="mb-1 flex h-12 w-12 items-center justify-center border border-surface-300 bg-surface-100 text-surface-600"
|
||||
>
|
||||
<svg class="h-6 w-6" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" d="M3.75 6.75h16.5M3.75 12h16.5m-16.5 5.25H12" />
|
||||
</svg>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<script lang="ts">
|
||||
let {
|
||||
message,
|
||||
onretry
|
||||
onretry,
|
||||
}: {
|
||||
message: string;
|
||||
onretry?: () => void;
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
folder,
|
||||
folders,
|
||||
projects,
|
||||
slug
|
||||
slug,
|
||||
}: {
|
||||
folder: ExplorerFolder;
|
||||
folders: ExplorerFolder[];
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
folders,
|
||||
projects,
|
||||
parentId,
|
||||
slug
|
||||
slug,
|
||||
}: {
|
||||
folders: ExplorerFolder[];
|
||||
projects: {
|
||||
|
||||
@@ -2,16 +2,16 @@
|
||||
/** Inline nav icons for the admin shell. */
|
||||
let {
|
||||
name,
|
||||
class: className = 'h-4 w-4'
|
||||
class: className = 'h-4 w-4',
|
||||
}: {
|
||||
name:
|
||||
| 'overview'
|
||||
| 'members'
|
||||
| 'teams'
|
||||
| 'projects'
|
||||
| 'provider'
|
||||
| 'feishu'
|
||||
| 'menu'
|
||||
| 'provider'
|
||||
| 'feishu'
|
||||
| 'menu'
|
||||
| 'logout'
|
||||
| 'org'
|
||||
| 'chevron'
|
||||
@@ -24,7 +24,11 @@
|
||||
|
||||
{#if name === 'overview'}
|
||||
<svg class={className} viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" d="M3 12l9-9 9 9M5 10v9a1 1 0 001 1h3v-5h6v5h3a1 1 0 001-1v-9" />
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
d="M3 12l9-9 9 9M5 10v9a1 1 0 001 1h3v-5h6v5h3a1 1 0 001-1v-9"
|
||||
/>
|
||||
</svg>
|
||||
{:else if name === 'members'}
|
||||
<svg class={className} viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75">
|
||||
@@ -52,8 +56,16 @@
|
||||
</svg>
|
||||
{:else if name === 'provider'}
|
||||
<svg class={className} viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" d="M13.19 8.688a4.5 4.5 0 016.364 6.364l-3.182 3.182a4.5 4.5 0 01-6.364-6.364" />
|
||||
<path stroke-linecap="round" stroke-linejoin="round" d="M10.81 15.312a4.5 4.5 0 01-6.364-6.364l3.182-3.182a4.5 4.5 0 016.364 6.364" />
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
d="M13.19 8.688a4.5 4.5 0 016.364 6.364l-3.182 3.182a4.5 4.5 0 01-6.364-6.364"
|
||||
/>
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
d="M10.81 15.312a4.5 4.5 0 01-6.364-6.364l3.182-3.182a4.5 4.5 0 016.364 6.364"
|
||||
/>
|
||||
</svg>
|
||||
{:else if name === 'feishu'}
|
||||
<svg class={className} viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75">
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
open = $bindable(false),
|
||||
title,
|
||||
children,
|
||||
onclose
|
||||
onclose,
|
||||
}: {
|
||||
open?: boolean;
|
||||
title: string;
|
||||
@@ -26,7 +26,7 @@
|
||||
<Dialog.Content class="saas-modal">
|
||||
<div class="mb-4 flex items-start justify-between gap-3">
|
||||
<Dialog.Title class="text-lg font-semibold text-surface-900">{title}</Dialog.Title>
|
||||
<Dialog.Close class="saas-btn-ghost !px-2 !py-1 text-surface-600" aria-label="关闭">
|
||||
<Dialog.Close class="saas-btn-ghost px-2! py-1! text-surface-600" aria-label="关闭">
|
||||
<svg class="h-5 w-5" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" d="M6 18L18 6M6 6l12 12" />
|
||||
</svg>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
let {
|
||||
title,
|
||||
description,
|
||||
actions
|
||||
actions,
|
||||
}: {
|
||||
title: string;
|
||||
description?: string;
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
class: className = '',
|
||||
disabled = false,
|
||||
placeholder = '请选择…',
|
||||
onchange
|
||||
onchange,
|
||||
}: {
|
||||
items: SelectItem[];
|
||||
value?: string;
|
||||
@@ -51,12 +51,7 @@
|
||||
<Select.Content class="saas-select-content" sideOffset={6} collisionPadding={8}>
|
||||
<Select.Viewport class="p-1">
|
||||
{#each items as item (item.value)}
|
||||
<Select.Item
|
||||
class="saas-select-item"
|
||||
value={item.value}
|
||||
label={item.label}
|
||||
disabled={item.disabled}
|
||||
>
|
||||
<Select.Item class="saas-select-item" value={item.value} label={item.label} disabled={item.disabled}>
|
||||
{#snippet children({ selected })}
|
||||
<span class="min-w-0 flex-1 truncate">{item.label}</span>
|
||||
{#if selected}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
let {
|
||||
label,
|
||||
value,
|
||||
hint
|
||||
hint,
|
||||
}: {
|
||||
label: string;
|
||||
value: string;
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
checked = $bindable(false),
|
||||
disabled = false,
|
||||
class: className = '',
|
||||
onchange
|
||||
onchange,
|
||||
}: {
|
||||
checked?: boolean;
|
||||
disabled?: boolean;
|
||||
|
||||
@@ -4,15 +4,16 @@
|
||||
const kindClass: Record<string, string> = {
|
||||
info: 'border-surface-200 bg-surface-50 text-surface-800',
|
||||
success: 'border-success-200 bg-success-50 text-success-800',
|
||||
error: 'border-error-200 bg-error-50 text-error-800'
|
||||
error: 'border-error-200 bg-error-50 text-error-800',
|
||||
};
|
||||
</script>
|
||||
|
||||
<div class="pointer-events-none fixed inset-x-0 top-0 z-[100] flex flex-col items-end gap-2 p-4">
|
||||
<div class="pointer-events-none fixed inset-x-0 top-0 z-100 flex flex-col items-end gap-2 p-4">
|
||||
{#each $toasts as t (t.id)}
|
||||
<div
|
||||
class="pointer-events-auto flex max-w-sm items-start gap-3 border px-4 py-3 text-sm shadow-[4px_4px_0_rgb(15_23_42_/_0.12)] {kindClass[t.kind] ??
|
||||
kindClass.info}"
|
||||
class="pointer-events-auto flex max-w-sm items-start gap-3 border px-4 py-3 text-sm shadow-[4px_4px_0_rgb(15_23_42/0.12)] {kindClass[
|
||||
t.kind
|
||||
] ?? kindClass.info}"
|
||||
role="status"
|
||||
>
|
||||
<p class="min-w-0 flex-1">{t.message}</p>
|
||||
|
||||
@@ -15,7 +15,7 @@ export const TOOL_OPTIONS: ToolOption[] = [
|
||||
{ id: 'send_file', label: '发送文件(飞书)', group: '飞书' },
|
||||
{ id: 'feishu_read_context', label: '读飞书上下文', group: '飞书' },
|
||||
{ id: 'feishu_download_resource', label: '下载飞书资源', group: '飞书' },
|
||||
{ id: 'request_approval', label: '请求审批', group: '飞书' }
|
||||
{ id: 'request_approval', label: '请求审批', group: '飞书' },
|
||||
];
|
||||
|
||||
/** 组织成员角色(接口枚举保持英文,界面用 orgRoleLabel) */
|
||||
@@ -25,7 +25,7 @@ export type OrgRole = (typeof ORG_ROLES)[number];
|
||||
export const ORG_ROLE_LABELS: Record<OrgRole, string> = {
|
||||
OWNER: '所有者',
|
||||
ADMIN: '管理员',
|
||||
MEMBER: '成员'
|
||||
MEMBER: '成员',
|
||||
};
|
||||
|
||||
/** 项目团队授权角色(接口枚举保持英文,界面用 permissionRoleLabel) */
|
||||
@@ -35,5 +35,5 @@ export type PermissionRole = (typeof PERMISSION_ROLES)[number];
|
||||
export const PERMISSION_ROLE_LABELS: Record<PermissionRole, string> = {
|
||||
READ: '只读',
|
||||
EDIT: '编辑',
|
||||
MANAGE: '管理'
|
||||
MANAGE: '管理',
|
||||
};
|
||||
|
||||
@@ -1,9 +1,4 @@
|
||||
import {
|
||||
ORG_ROLE_LABELS,
|
||||
PERMISSION_ROLE_LABELS,
|
||||
type OrgRole,
|
||||
type PermissionRole
|
||||
} from './constants';
|
||||
import { ORG_ROLE_LABELS, PERMISSION_ROLE_LABELS, type OrgRole, type PermissionRole } from './constants';
|
||||
|
||||
export function fmtDate(iso: string): string {
|
||||
if (!iso) return '—';
|
||||
@@ -14,7 +9,7 @@ export function fmtDate(iso: string): string {
|
||||
month: 'short',
|
||||
day: '2-digit',
|
||||
hour: '2-digit',
|
||||
minute: '2-digit'
|
||||
minute: '2-digit',
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ interface SessionState {
|
||||
export const session = writable<SessionState>({
|
||||
loading: true,
|
||||
me: null,
|
||||
error: null
|
||||
error: null,
|
||||
});
|
||||
|
||||
export async function loadSession(): Promise<void> {
|
||||
@@ -27,7 +27,7 @@ export async function loadSession(): Promise<void> {
|
||||
session.set({
|
||||
loading: false,
|
||||
me: null,
|
||||
error: err instanceof Error ? err.message : String(err)
|
||||
error: err instanceof Error ? err.message : String(err),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user