feat: 添加视频源管理页,支持修改路径与启用状态 (#369)
This commit is contained in:
@@ -4,6 +4,7 @@
|
||||
import UserIcon from '@lucide/svelte/icons/user';
|
||||
import HeartIcon from '@lucide/svelte/icons/heart';
|
||||
import FolderIcon from '@lucide/svelte/icons/folder';
|
||||
import DatabaseIcon from '@lucide/svelte/icons/database';
|
||||
import * as Sidebar from '$lib/components/ui/sidebar/index.js';
|
||||
import { useSidebar } from '$lib/components/ui/sidebar/context.svelte.js';
|
||||
import {
|
||||
@@ -183,6 +184,24 @@
|
||||
<!-- 固定在底部的菜单选项 -->
|
||||
<div class="border-border mt-auto border-t pt-4">
|
||||
<Sidebar.Menu class="space-y-1">
|
||||
<Sidebar.MenuItem>
|
||||
<Sidebar.MenuButton>
|
||||
<a
|
||||
href="/video-sources"
|
||||
class="hover:bg-accent/50 text-foreground flex w-full cursor-pointer items-center justify-between rounded-lg px-3 py-2.5 font-medium transition-all duration-200"
|
||||
onclick={() => {
|
||||
if (sidebar.isMobile) {
|
||||
sidebar.setOpenMobile(false);
|
||||
}
|
||||
}}
|
||||
>
|
||||
<div class="flex flex-1 items-center gap-3">
|
||||
<DatabaseIcon class="text-muted-foreground h-4 w-4" />
|
||||
<span class="text-sm">视频源管理</span>
|
||||
</div>
|
||||
</a>
|
||||
</Sidebar.MenuButton>
|
||||
</Sidebar.MenuItem>
|
||||
<Sidebar.MenuItem>
|
||||
<Sidebar.MenuButton>
|
||||
<a
|
||||
|
||||
7
web/src/lib/components/ui/switch/index.ts
Normal file
7
web/src/lib/components/ui/switch/index.ts
Normal file
@@ -0,0 +1,7 @@
|
||||
import Root from './switch.svelte';
|
||||
|
||||
export {
|
||||
Root,
|
||||
//
|
||||
Root as Switch
|
||||
};
|
||||
29
web/src/lib/components/ui/switch/switch.svelte
Normal file
29
web/src/lib/components/ui/switch/switch.svelte
Normal file
@@ -0,0 +1,29 @@
|
||||
<script lang="ts">
|
||||
import { Switch as SwitchPrimitive } from 'bits-ui';
|
||||
import { cn, type WithoutChildrenOrChild } from '$lib/utils.js';
|
||||
|
||||
let {
|
||||
ref = $bindable(null),
|
||||
class: className,
|
||||
checked = $bindable(false),
|
||||
...restProps
|
||||
}: WithoutChildrenOrChild<SwitchPrimitive.RootProps> = $props();
|
||||
</script>
|
||||
|
||||
<SwitchPrimitive.Root
|
||||
bind:ref
|
||||
bind:checked
|
||||
data-slot="switch"
|
||||
class={cn(
|
||||
'data-[state=checked]:bg-primary data-[state=unchecked]:bg-input focus-visible:border-ring focus-visible:ring-ring/50 dark:data-[state=unchecked]:bg-input/80 peer inline-flex h-[1.15rem] w-8 shrink-0 items-center rounded-full border border-transparent shadow-xs transition-all outline-none focus-visible:ring-[3px] disabled:cursor-not-allowed disabled:opacity-50',
|
||||
className
|
||||
)}
|
||||
{...restProps}
|
||||
>
|
||||
<SwitchPrimitive.Thumb
|
||||
data-slot="switch-thumb"
|
||||
class={cn(
|
||||
'bg-background dark:data-[state=unchecked]:bg-foreground dark:data-[state=checked]:bg-primary-foreground pointer-events-none block size-4 rounded-full ring-0 transition-transform data-[state=checked]:translate-x-[calc(100%-2px)] data-[state=unchecked]:translate-x-0'
|
||||
)}
|
||||
/>
|
||||
</SwitchPrimitive.Root>
|
||||
28
web/src/lib/components/ui/table/index.ts
Normal file
28
web/src/lib/components/ui/table/index.ts
Normal file
@@ -0,0 +1,28 @@
|
||||
import Root from './table.svelte';
|
||||
import Body from './table-body.svelte';
|
||||
import Caption from './table-caption.svelte';
|
||||
import Cell from './table-cell.svelte';
|
||||
import Footer from './table-footer.svelte';
|
||||
import Head from './table-head.svelte';
|
||||
import Header from './table-header.svelte';
|
||||
import Row from './table-row.svelte';
|
||||
|
||||
export {
|
||||
Root,
|
||||
Body,
|
||||
Caption,
|
||||
Cell,
|
||||
Footer,
|
||||
Head,
|
||||
Header,
|
||||
Row,
|
||||
//
|
||||
Root as Table,
|
||||
Body as TableBody,
|
||||
Caption as TableCaption,
|
||||
Cell as TableCell,
|
||||
Footer as TableFooter,
|
||||
Head as TableHead,
|
||||
Header as TableHeader,
|
||||
Row as TableRow
|
||||
};
|
||||
20
web/src/lib/components/ui/table/table-body.svelte
Normal file
20
web/src/lib/components/ui/table/table-body.svelte
Normal file
@@ -0,0 +1,20 @@
|
||||
<script lang="ts">
|
||||
import { cn, type WithElementRef } from '$lib/utils.js';
|
||||
import type { HTMLAttributes } from 'svelte/elements';
|
||||
|
||||
let {
|
||||
ref = $bindable(null),
|
||||
class: className,
|
||||
children,
|
||||
...restProps
|
||||
}: WithElementRef<HTMLAttributes<HTMLTableSectionElement>> = $props();
|
||||
</script>
|
||||
|
||||
<tbody
|
||||
bind:this={ref}
|
||||
data-slot="table-body"
|
||||
class={cn('[&_tr:last-child]:border-0', className)}
|
||||
{...restProps}
|
||||
>
|
||||
{@render children?.()}
|
||||
</tbody>
|
||||
20
web/src/lib/components/ui/table/table-caption.svelte
Normal file
20
web/src/lib/components/ui/table/table-caption.svelte
Normal file
@@ -0,0 +1,20 @@
|
||||
<script lang="ts">
|
||||
import { cn, type WithElementRef } from '$lib/utils.js';
|
||||
import type { HTMLAttributes } from 'svelte/elements';
|
||||
|
||||
let {
|
||||
ref = $bindable(null),
|
||||
class: className,
|
||||
children,
|
||||
...restProps
|
||||
}: WithElementRef<HTMLAttributes<HTMLElement>> = $props();
|
||||
</script>
|
||||
|
||||
<caption
|
||||
bind:this={ref}
|
||||
data-slot="table-caption"
|
||||
class={cn('text-muted-foreground mt-4 text-sm', className)}
|
||||
{...restProps}
|
||||
>
|
||||
{@render children?.()}
|
||||
</caption>
|
||||
20
web/src/lib/components/ui/table/table-cell.svelte
Normal file
20
web/src/lib/components/ui/table/table-cell.svelte
Normal file
@@ -0,0 +1,20 @@
|
||||
<script lang="ts">
|
||||
import { cn, type WithElementRef } from '$lib/utils.js';
|
||||
import type { HTMLTdAttributes } from 'svelte/elements';
|
||||
|
||||
let {
|
||||
ref = $bindable(null),
|
||||
class: className,
|
||||
children,
|
||||
...restProps
|
||||
}: WithElementRef<HTMLTdAttributes> = $props();
|
||||
</script>
|
||||
|
||||
<td
|
||||
bind:this={ref}
|
||||
data-slot="table-cell"
|
||||
class={cn('p-2 align-middle whitespace-nowrap [&:has([role=checkbox])]:pr-0', className)}
|
||||
{...restProps}
|
||||
>
|
||||
{@render children?.()}
|
||||
</td>
|
||||
20
web/src/lib/components/ui/table/table-footer.svelte
Normal file
20
web/src/lib/components/ui/table/table-footer.svelte
Normal file
@@ -0,0 +1,20 @@
|
||||
<script lang="ts">
|
||||
import { cn, type WithElementRef } from '$lib/utils.js';
|
||||
import type { HTMLAttributes } from 'svelte/elements';
|
||||
|
||||
let {
|
||||
ref = $bindable(null),
|
||||
class: className,
|
||||
children,
|
||||
...restProps
|
||||
}: WithElementRef<HTMLAttributes<HTMLTableSectionElement>> = $props();
|
||||
</script>
|
||||
|
||||
<tfoot
|
||||
bind:this={ref}
|
||||
data-slot="table-footer"
|
||||
class={cn('bg-muted/50 border-t font-medium [&>tr]:last:border-b-0', className)}
|
||||
{...restProps}
|
||||
>
|
||||
{@render children?.()}
|
||||
</tfoot>
|
||||
23
web/src/lib/components/ui/table/table-head.svelte
Normal file
23
web/src/lib/components/ui/table/table-head.svelte
Normal file
@@ -0,0 +1,23 @@
|
||||
<script lang="ts">
|
||||
import { cn, type WithElementRef } from '$lib/utils.js';
|
||||
import type { HTMLThAttributes } from 'svelte/elements';
|
||||
|
||||
let {
|
||||
ref = $bindable(null),
|
||||
class: className,
|
||||
children,
|
||||
...restProps
|
||||
}: WithElementRef<HTMLThAttributes> = $props();
|
||||
</script>
|
||||
|
||||
<th
|
||||
bind:this={ref}
|
||||
data-slot="table-head"
|
||||
class={cn(
|
||||
'text-foreground h-10 px-2 text-left align-middle font-medium whitespace-nowrap [&:has([role=checkbox])]:pr-0',
|
||||
className
|
||||
)}
|
||||
{...restProps}
|
||||
>
|
||||
{@render children?.()}
|
||||
</th>
|
||||
20
web/src/lib/components/ui/table/table-header.svelte
Normal file
20
web/src/lib/components/ui/table/table-header.svelte
Normal file
@@ -0,0 +1,20 @@
|
||||
<script lang="ts">
|
||||
import { cn, type WithElementRef } from '$lib/utils.js';
|
||||
import type { HTMLAttributes } from 'svelte/elements';
|
||||
|
||||
let {
|
||||
ref = $bindable(null),
|
||||
class: className,
|
||||
children,
|
||||
...restProps
|
||||
}: WithElementRef<HTMLAttributes<HTMLTableSectionElement>> = $props();
|
||||
</script>
|
||||
|
||||
<thead
|
||||
bind:this={ref}
|
||||
data-slot="table-header"
|
||||
class={cn('[&_tr]:border-b', className)}
|
||||
{...restProps}
|
||||
>
|
||||
{@render children?.()}
|
||||
</thead>
|
||||
23
web/src/lib/components/ui/table/table-row.svelte
Normal file
23
web/src/lib/components/ui/table/table-row.svelte
Normal file
@@ -0,0 +1,23 @@
|
||||
<script lang="ts">
|
||||
import { cn, type WithElementRef } from '$lib/utils.js';
|
||||
import type { HTMLAttributes } from 'svelte/elements';
|
||||
|
||||
let {
|
||||
ref = $bindable(null),
|
||||
class: className,
|
||||
children,
|
||||
...restProps
|
||||
}: WithElementRef<HTMLAttributes<HTMLTableRowElement>> = $props();
|
||||
</script>
|
||||
|
||||
<tr
|
||||
bind:this={ref}
|
||||
data-slot="table-row"
|
||||
class={cn(
|
||||
'hover:bg-muted/50 data-[state=selected]:bg-muted border-b transition-colors',
|
||||
className
|
||||
)}
|
||||
{...restProps}
|
||||
>
|
||||
{@render children?.()}
|
||||
</tr>
|
||||
22
web/src/lib/components/ui/table/table.svelte
Normal file
22
web/src/lib/components/ui/table/table.svelte
Normal file
@@ -0,0 +1,22 @@
|
||||
<script lang="ts">
|
||||
import type { HTMLTableAttributes } from 'svelte/elements';
|
||||
import { cn, type WithElementRef } from '$lib/utils.js';
|
||||
|
||||
let {
|
||||
ref = $bindable(null),
|
||||
class: className,
|
||||
children,
|
||||
...restProps
|
||||
}: WithElementRef<HTMLTableAttributes> = $props();
|
||||
</script>
|
||||
|
||||
<div data-slot="table-container" class="relative w-full overflow-x-auto">
|
||||
<table
|
||||
bind:this={ref}
|
||||
data-slot="table"
|
||||
class={cn('w-full caption-bottom text-sm', className)}
|
||||
{...restProps}
|
||||
>
|
||||
{@render children?.()}
|
||||
</table>
|
||||
</div>
|
||||
Reference in New Issue
Block a user