This commit is contained in:
1 parent
32a87ebc61
commit
5f0a5ff820
7 files changed
+66
-445
No files matched your search
@@ -3,6 +3,8 @@
|
|||||||
import { page } from '$app/stores';
|
import { page } from '$app/stores';
|
||||||
import type { PageData } from './$types';
|
import type { PageData } from './$types';
|
||||||
import { confirmState } from '$lib/stores/confirm.svelte';
|
import { confirmState } from '$lib/stores/confirm.svelte';
|
||||||
|
import Button from '$lib/components/admin/Button.svelte';
|
||||||
|
import DataTable from '$lib/components/admin/DataTable.svelte';
|
||||||
let { data }: { data: PageData } = $props();
|
let { data }: { data: PageData } = $props();
|
||||||
|
|
||||||
let selectedIds = $state<string[]>([]);
|
let selectedIds = $state<string[]>([]);
|
||||||
@@ -21,9 +23,9 @@
|
|||||||
|
|
||||||
<div class="admin-page-header">
|
<div class="admin-page-header">
|
||||||
<h2>{$page.data.aliases?.page || '页面'}管理</h2>
|
<h2>{$page.data.aliases?.page || '页面'}管理</h2>
|
||||||
<a href={resolve('/admin/pages/new')} class="btn btn-primary"
|
<Button href={resolve('/admin/pages/new')} variant="primary">
|
||||||
>新建{$page.data.aliases?.page || '页面'}</a
|
新建{$page.data.aliases?.page || '页面'}
|
||||||
>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{#if data.pages.length > 0}
|
{#if data.pages.length > 0}
|
||||||
@@ -54,7 +56,7 @@
|
|||||||
{#each selectedIds as id (id)}
|
{#each selectedIds as id (id)}
|
||||||
<input type="hidden" name="ids" value={id} />
|
<input type="hidden" name="ids" value={id} />
|
||||||
{/each}
|
{/each}
|
||||||
<button type="submit" class="btn btn-danger btn-sm">批量删除</button>
|
<Button type="submit" variant="danger" size="sm">批量删除</Button>
|
||||||
</form>
|
</form>
|
||||||
{:else}
|
{:else}
|
||||||
<span class="selected-count empty">未选择项目</span>
|
<span class="selected-count empty">未选择项目</span>
|
||||||
@@ -62,13 +64,12 @@
|
|||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
<div class="table-container">
|
{#if data.pages.length === 0}
|
||||||
{#if data.pages.length === 0}
|
|
||||||
<div class="empty-state">
|
<div class="empty-state">
|
||||||
<p>还没有发布任何{$page.data.aliases?.page || '页面'}</p>
|
<p>还没有发布任何{$page.data.aliases?.page || '页面'}</p>
|
||||||
</div>
|
</div>
|
||||||
{:else}
|
{:else}
|
||||||
<table class="data-table">
|
<DataTable>
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th class="checkbox-col">
|
<th class="checkbox-col">
|
||||||
@@ -113,13 +114,9 @@
|
|||||||
stroke-width="2"
|
stroke-width="2"
|
||||||
stroke-linecap="round"
|
stroke-linecap="round"
|
||||||
stroke-linejoin="round"
|
stroke-linejoin="round"
|
||||||
><path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"
|
><path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"></path><polyline
|
||||||
></path><polyline points="15 3 21 3 21 9"></polyline><line
|
points="15 3 21 3 21 9"
|
||||||
x1="10"
|
></polyline><line x1="10" y1="14" x2="21" y2="3"></line></svg
|
||||||
y1="14"
|
|
||||||
x2="21"
|
|
||||||
y2="3"
|
|
||||||
></line></svg
|
|
||||||
>
|
>
|
||||||
</a>
|
</a>
|
||||||
</td>
|
</td>
|
||||||
@@ -129,9 +126,8 @@
|
|||||||
</tr>
|
</tr>
|
||||||
{/each}
|
{/each}
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</DataTable>
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
.admin-page-header {
|
.admin-page-header {
|
||||||
@@ -149,65 +145,6 @@
|
|||||||
color: var(--text-color);
|
color: var(--text-color);
|
||||||
}
|
}
|
||||||
|
|
||||||
.btn {
|
|
||||||
display: inline-block;
|
|
||||||
padding: 8px 18px;
|
|
||||||
text-decoration: none;
|
|
||||||
font-size: 0.95rem;
|
|
||||||
font-weight: 600;
|
|
||||||
transition: all 0.2s;
|
|
||||||
cursor: pointer;
|
|
||||||
border: 2px solid var(--text-color);
|
|
||||||
background-color: transparent;
|
|
||||||
color: var(--text-color);
|
|
||||||
font-family: inherit;
|
|
||||||
}
|
|
||||||
|
|
||||||
.btn-primary {
|
|
||||||
background-color: var(--text-color);
|
|
||||||
color: var(--bg-color, #ffffff);
|
|
||||||
}
|
|
||||||
|
|
||||||
.btn-primary:hover {
|
|
||||||
background-color: var(--accent-color, #419b38);
|
|
||||||
border-color: var(--accent-color, #419b38);
|
|
||||||
color: white;
|
|
||||||
}
|
|
||||||
|
|
||||||
.table-container {
|
|
||||||
background: transparent;
|
|
||||||
border: 2px solid var(--text-color);
|
|
||||||
overflow-x: auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
.data-table {
|
|
||||||
width: 100%;
|
|
||||||
border-collapse: collapse;
|
|
||||||
text-align: left;
|
|
||||||
}
|
|
||||||
|
|
||||||
.data-table th,
|
|
||||||
.data-table td {
|
|
||||||
padding: 10px 16px;
|
|
||||||
border-bottom: 1px solid var(--border-color, rgba(0, 0, 0, 0.08));
|
|
||||||
}
|
|
||||||
|
|
||||||
.data-table th {
|
|
||||||
background-color: transparent;
|
|
||||||
color: var(--text-color);
|
|
||||||
font-weight: 700;
|
|
||||||
font-size: 0.95rem;
|
|
||||||
border-bottom: 2px solid var(--text-color);
|
|
||||||
}
|
|
||||||
|
|
||||||
.data-table tr:last-child td {
|
|
||||||
border-bottom: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.data-table tbody tr:hover {
|
|
||||||
background-color: rgba(0, 0, 0, 0.02);
|
|
||||||
}
|
|
||||||
|
|
||||||
.preview-link {
|
.preview-link {
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
margin-left: 6px;
|
margin-left: 6px;
|
||||||
@@ -272,20 +209,4 @@
|
|||||||
text-decoration: underline;
|
text-decoration: underline;
|
||||||
text-underline-offset: 4px;
|
text-underline-offset: 4px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.btn-danger {
|
|
||||||
background-color: transparent;
|
|
||||||
color: #d9534f;
|
|
||||||
border-color: #d9534f;
|
|
||||||
}
|
|
||||||
|
|
||||||
.btn-danger:hover {
|
|
||||||
background-color: #d9534f;
|
|
||||||
color: white;
|
|
||||||
}
|
|
||||||
|
|
||||||
.btn-sm {
|
|
||||||
padding: 4px 12px;
|
|
||||||
font-size: 0.85rem;
|
|
||||||
}
|
|
||||||
</style>
|
</style>
|
||||||
@@ -4,6 +4,8 @@
|
|||||||
import type { PageData, ActionData } from './$types';
|
import type { PageData, ActionData } from './$types';
|
||||||
import MarkdownRenderer from '$lib/components/MarkdownRenderer.svelte';
|
import MarkdownRenderer from '$lib/components/MarkdownRenderer.svelte';
|
||||||
import TextInput from '$lib/components/admin/TextInput.svelte';
|
import TextInput from '$lib/components/admin/TextInput.svelte';
|
||||||
|
import Button from '$lib/components/admin/Button.svelte';
|
||||||
|
import Alert from '$lib/components/admin/Alert.svelte';
|
||||||
import { untrack } from 'svelte';
|
import { untrack } from 'svelte';
|
||||||
|
|
||||||
let { data, form }: { data: PageData; form: ActionData } = $props();
|
let { data, form }: { data: PageData; form: ActionData } = $props();
|
||||||
@@ -18,20 +20,20 @@
|
|||||||
<div class="admin-page-header">
|
<div class="admin-page-header">
|
||||||
<h2>编辑{$page.data.aliases?.page || '页面'}</h2>
|
<h2>编辑{$page.data.aliases?.page || '页面'}</h2>
|
||||||
<div class="header-actions">
|
<div class="header-actions">
|
||||||
<a
|
<Button
|
||||||
href={resolve('/[slug]', { slug: data.page.slug })}
|
href={resolve('/[slug]', { slug: data.page.slug })}
|
||||||
target="_blank"
|
target="_blank"
|
||||||
class="btn btn-secondary"
|
variant="secondary"
|
||||||
style="margin-right: 12px;">前台预览</a
|
style="margin-right: 12px;"
|
||||||
>
|
>
|
||||||
<a href={resolve('/admin/pages')} class="btn btn-secondary">← 返回</a>
|
前台预览
|
||||||
|
</Button>
|
||||||
|
<Button href={resolve('/admin/pages')} variant="secondary">← 返回</Button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{#if form?.error}
|
{#if form?.error}
|
||||||
<div class="error-alert">
|
<Alert message={form.error} />
|
||||||
{form.error}
|
|
||||||
</div>
|
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
<form action="?/update" method="POST" class="post-form">
|
<form action="?/update" method="POST" class="post-form">
|
||||||
@@ -88,7 +90,7 @@
|
|||||||
<div class="form-sidebar">
|
<div class="form-sidebar">
|
||||||
<div class="sidebar-box">
|
<div class="sidebar-box">
|
||||||
<h3>更新</h3>
|
<h3>更新</h3>
|
||||||
<button type="submit" class="btn btn-primary submit-btn">保存修改</button>
|
<Button type="submit" variant="primary" fullWidth class="submit-btn">保存修改</Button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="sidebar-box">
|
<div class="sidebar-box">
|
||||||
@@ -128,49 +130,6 @@
|
|||||||
align-items: center;
|
align-items: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.btn {
|
|
||||||
display: inline-block;
|
|
||||||
padding: 10px 20px;
|
|
||||||
text-decoration: none;
|
|
||||||
font-size: 0.95rem;
|
|
||||||
font-weight: 600;
|
|
||||||
transition: all 0.3s ease;
|
|
||||||
cursor: pointer;
|
|
||||||
border: 1px solid var(--text-color);
|
|
||||||
background-color: transparent;
|
|
||||||
color: var(--text-color);
|
|
||||||
font-family: inherit;
|
|
||||||
text-transform: uppercase;
|
|
||||||
letter-spacing: 1px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.btn-primary {
|
|
||||||
background-color: var(--text-color);
|
|
||||||
color: var(--bg-color, #ffffff);
|
|
||||||
width: 100%;
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.btn-primary:hover {
|
|
||||||
background-color: var(--accent-color, #419b38);
|
|
||||||
border-color: var(--accent-color, #419b38);
|
|
||||||
color: white;
|
|
||||||
}
|
|
||||||
|
|
||||||
.btn-secondary:hover {
|
|
||||||
border-color: var(--accent-color, #419b38);
|
|
||||||
color: var(--accent-color, #419b38);
|
|
||||||
}
|
|
||||||
|
|
||||||
.error-alert {
|
|
||||||
padding: 12px 16px;
|
|
||||||
background-color: transparent;
|
|
||||||
border-left: 4px solid #d9534f;
|
|
||||||
color: #d9534f;
|
|
||||||
margin-bottom: 30px;
|
|
||||||
font-weight: 600;
|
|
||||||
}
|
|
||||||
|
|
||||||
.editor-header {
|
.editor-header {
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
|
|||||||
@@ -4,6 +4,8 @@
|
|||||||
import type { ActionData } from './$types';
|
import type { ActionData } from './$types';
|
||||||
import MarkdownRenderer from '$lib/components/MarkdownRenderer.svelte';
|
import MarkdownRenderer from '$lib/components/MarkdownRenderer.svelte';
|
||||||
import TextInput from '$lib/components/admin/TextInput.svelte';
|
import TextInput from '$lib/components/admin/TextInput.svelte';
|
||||||
|
import Button from '$lib/components/admin/Button.svelte';
|
||||||
|
import Alert from '$lib/components/admin/Alert.svelte';
|
||||||
|
|
||||||
import { createSlugAutoHandler } from '$lib/utils/slugify';
|
import { createSlugAutoHandler } from '$lib/utils/slugify';
|
||||||
|
|
||||||
@@ -35,13 +37,11 @@
|
|||||||
|
|
||||||
<div class="admin-page-header">
|
<div class="admin-page-header">
|
||||||
<h2>新建独立{$page.data.aliases?.page || '页面'}</h2>
|
<h2>新建独立{$page.data.aliases?.page || '页面'}</h2>
|
||||||
<a href={resolve('/admin/pages')} class="btn btn-secondary">← 返回</a>
|
<Button href={resolve('/admin/pages')} variant="secondary">← 返回</Button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{#if form?.error}
|
{#if form?.error}
|
||||||
<div class="error-alert">
|
<Alert message={form.error} />
|
||||||
{form.error}
|
|
||||||
</div>
|
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
<form method="POST" class="post-form">
|
<form method="POST" class="post-form">
|
||||||
@@ -99,7 +99,7 @@
|
|||||||
<div class="form-sidebar">
|
<div class="form-sidebar">
|
||||||
<div class="sidebar-box">
|
<div class="sidebar-box">
|
||||||
<h3>发布</h3>
|
<h3>发布</h3>
|
||||||
<button type="submit" class="btn btn-primary submit-btn">发布</button>
|
<Button type="submit" variant="primary" fullWidth class="submit-btn">发布</Button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="sidebar-box">
|
<div class="sidebar-box">
|
||||||
@@ -145,49 +145,6 @@
|
|||||||
color: var(--text-color);
|
color: var(--text-color);
|
||||||
}
|
}
|
||||||
|
|
||||||
.btn {
|
|
||||||
display: inline-block;
|
|
||||||
padding: 10px 20px;
|
|
||||||
text-decoration: none;
|
|
||||||
font-size: 0.95rem;
|
|
||||||
font-weight: 600;
|
|
||||||
transition: all 0.3s ease;
|
|
||||||
cursor: pointer;
|
|
||||||
border: 1px solid var(--text-color);
|
|
||||||
background-color: transparent;
|
|
||||||
color: var(--text-color);
|
|
||||||
font-family: inherit;
|
|
||||||
text-transform: uppercase;
|
|
||||||
letter-spacing: 1px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.btn-primary {
|
|
||||||
background-color: var(--text-color);
|
|
||||||
color: var(--bg-color, #ffffff);
|
|
||||||
width: 100%;
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.btn-primary:hover {
|
|
||||||
background-color: var(--accent-color, #419b38);
|
|
||||||
border-color: var(--accent-color, #419b38);
|
|
||||||
color: white;
|
|
||||||
}
|
|
||||||
|
|
||||||
.btn-secondary:hover {
|
|
||||||
border-color: var(--accent-color, #419b38);
|
|
||||||
color: var(--accent-color, #419b38);
|
|
||||||
}
|
|
||||||
|
|
||||||
.error-alert {
|
|
||||||
padding: 12px 16px;
|
|
||||||
background-color: transparent;
|
|
||||||
border-left: 4px solid #d9534f;
|
|
||||||
color: #d9534f;
|
|
||||||
margin-bottom: 30px;
|
|
||||||
font-weight: 600;
|
|
||||||
}
|
|
||||||
|
|
||||||
.editor-header {
|
.editor-header {
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
|
|||||||
@@ -3,6 +3,8 @@
|
|||||||
import { page } from '$app/stores';
|
import { page } from '$app/stores';
|
||||||
import type { PageData } from './$types';
|
import type { PageData } from './$types';
|
||||||
import { confirmState } from '$lib/stores/confirm.svelte';
|
import { confirmState } from '$lib/stores/confirm.svelte';
|
||||||
|
import Button from '$lib/components/admin/Button.svelte';
|
||||||
|
import DataTable from '$lib/components/admin/DataTable.svelte';
|
||||||
let { data }: { data: PageData } = $props();
|
let { data }: { data: PageData } = $props();
|
||||||
|
|
||||||
let selectedIds = $state<string[]>([]);
|
let selectedIds = $state<string[]>([]);
|
||||||
@@ -21,9 +23,9 @@
|
|||||||
|
|
||||||
<div class="admin-page-header">
|
<div class="admin-page-header">
|
||||||
<h2>{$page.data.aliases?.post || '文章'}管理</h2>
|
<h2>{$page.data.aliases?.post || '文章'}管理</h2>
|
||||||
<a href={resolve('/admin/posts/new')} class="btn btn-primary"
|
<Button href={resolve('/admin/posts/new')} variant="primary">
|
||||||
>发布新{$page.data.aliases?.post || '文章'}</a
|
新建{$page.data.aliases?.post || '文章'}
|
||||||
>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{#if data.posts.length > 0}
|
{#if data.posts.length > 0}
|
||||||
@@ -54,7 +56,7 @@
|
|||||||
{#each selectedIds as id (id)}
|
{#each selectedIds as id (id)}
|
||||||
<input type="hidden" name="ids" value={id} />
|
<input type="hidden" name="ids" value={id} />
|
||||||
{/each}
|
{/each}
|
||||||
<button type="submit" class="btn btn-danger btn-sm">批量删除</button>
|
<Button type="submit" variant="danger" size="sm">批量删除</Button>
|
||||||
</form>
|
</form>
|
||||||
{:else}
|
{:else}
|
||||||
<span class="selected-count empty">未选择项目</span>
|
<span class="selected-count empty">未选择项目</span>
|
||||||
@@ -62,13 +64,12 @@
|
|||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
<div class="table-container">
|
{#if data.posts.length === 0}
|
||||||
{#if data.posts.length === 0}
|
|
||||||
<div class="empty-state">
|
<div class="empty-state">
|
||||||
<p>还没有发布任何{$page.data.aliases?.post || '文章'}</p>
|
<p>还没有发布任何{$page.data.aliases?.post || '文章'}</p>
|
||||||
</div>
|
</div>
|
||||||
{:else}
|
{:else}
|
||||||
<table class="data-table">
|
<DataTable>
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th class="checkbox-col">
|
<th class="checkbox-col">
|
||||||
@@ -87,12 +88,7 @@
|
|||||||
{#each data.posts as post (post.id || post)}
|
{#each data.posts as post (post.id || post)}
|
||||||
<tr>
|
<tr>
|
||||||
<td class="checkbox-col">
|
<td class="checkbox-col">
|
||||||
<input
|
<input type="checkbox" name="ids" value={post.id.toString()} bind:group={selectedIds} />
|
||||||
type="checkbox"
|
|
||||||
name="ids"
|
|
||||||
value={post.id.toString()}
|
|
||||||
bind:group={selectedIds}
|
|
||||||
/>
|
|
||||||
</td>
|
</td>
|
||||||
<td>{post.id}</td>
|
<td>{post.id}</td>
|
||||||
<td>
|
<td>
|
||||||
@@ -114,13 +110,9 @@
|
|||||||
stroke-width="2"
|
stroke-width="2"
|
||||||
stroke-linecap="round"
|
stroke-linecap="round"
|
||||||
stroke-linejoin="round"
|
stroke-linejoin="round"
|
||||||
><path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"
|
><path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"></path><polyline
|
||||||
></path><polyline points="15 3 21 3 21 9"></polyline><line
|
points="15 3 21 3 21 9"
|
||||||
x1="10"
|
></polyline><line x1="10" y1="14" x2="21" y2="3"></line></svg
|
||||||
y1="14"
|
|
||||||
x2="21"
|
|
||||||
y2="3"
|
|
||||||
></line></svg
|
|
||||||
>
|
>
|
||||||
</a>
|
</a>
|
||||||
</td>
|
</td>
|
||||||
@@ -132,9 +124,8 @@
|
|||||||
</tr>
|
</tr>
|
||||||
{/each}
|
{/each}
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</DataTable>
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
.admin-page-header {
|
.admin-page-header {
|
||||||
@@ -152,65 +143,6 @@
|
|||||||
color: var(--text-color);
|
color: var(--text-color);
|
||||||
}
|
}
|
||||||
|
|
||||||
.btn {
|
|
||||||
display: inline-block;
|
|
||||||
padding: 8px 18px;
|
|
||||||
text-decoration: none;
|
|
||||||
font-size: 0.95rem;
|
|
||||||
font-weight: 600;
|
|
||||||
transition: all 0.2s;
|
|
||||||
cursor: pointer;
|
|
||||||
border: 2px solid var(--text-color);
|
|
||||||
background-color: transparent;
|
|
||||||
color: var(--text-color);
|
|
||||||
font-family: inherit;
|
|
||||||
}
|
|
||||||
|
|
||||||
.btn-primary {
|
|
||||||
background-color: var(--text-color);
|
|
||||||
color: var(--bg-color, #ffffff);
|
|
||||||
}
|
|
||||||
|
|
||||||
.btn-primary:hover {
|
|
||||||
background-color: var(--accent-color, #419b38);
|
|
||||||
border-color: var(--accent-color, #419b38);
|
|
||||||
color: white;
|
|
||||||
}
|
|
||||||
|
|
||||||
.table-container {
|
|
||||||
background: transparent;
|
|
||||||
border: 2px solid var(--text-color);
|
|
||||||
overflow-x: auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
.data-table {
|
|
||||||
width: 100%;
|
|
||||||
border-collapse: collapse;
|
|
||||||
text-align: left;
|
|
||||||
}
|
|
||||||
|
|
||||||
.data-table th,
|
|
||||||
.data-table td {
|
|
||||||
padding: 10px 16px;
|
|
||||||
border-bottom: 1px solid var(--border-color, rgba(0, 0, 0, 0.08));
|
|
||||||
}
|
|
||||||
|
|
||||||
.data-table th {
|
|
||||||
background-color: transparent;
|
|
||||||
color: var(--text-color);
|
|
||||||
font-weight: 700;
|
|
||||||
font-size: 0.95rem;
|
|
||||||
border-bottom: 2px solid var(--text-color);
|
|
||||||
}
|
|
||||||
|
|
||||||
.data-table tr:last-child td {
|
|
||||||
border-bottom: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.data-table tbody tr:hover {
|
|
||||||
background-color: rgba(0, 0, 0, 0.02);
|
|
||||||
}
|
|
||||||
|
|
||||||
.preview-link {
|
.preview-link {
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
margin-left: 6px;
|
margin-left: 6px;
|
||||||
@@ -275,20 +207,4 @@
|
|||||||
text-decoration: underline;
|
text-decoration: underline;
|
||||||
text-underline-offset: 4px;
|
text-underline-offset: 4px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.btn-danger {
|
|
||||||
background-color: transparent;
|
|
||||||
color: #d9534f;
|
|
||||||
border-color: #d9534f;
|
|
||||||
}
|
|
||||||
|
|
||||||
.btn-danger:hover {
|
|
||||||
background-color: #d9534f;
|
|
||||||
color: white;
|
|
||||||
}
|
|
||||||
|
|
||||||
.btn-sm {
|
|
||||||
padding: 4px 12px;
|
|
||||||
font-size: 0.85rem;
|
|
||||||
}
|
|
||||||
</style>
|
</style>
|
||||||
@@ -10,6 +10,8 @@
|
|||||||
import SelectDropdown from '$lib/components/admin/SelectDropdown.svelte';
|
import SelectDropdown from '$lib/components/admin/SelectDropdown.svelte';
|
||||||
import { parseHugoMarkdown } from '$lib/hugoParser';
|
import { parseHugoMarkdown } from '$lib/hugoParser';
|
||||||
import TextInput from '$lib/components/admin/TextInput.svelte';
|
import TextInput from '$lib/components/admin/TextInput.svelte';
|
||||||
|
import Button from '$lib/components/admin/Button.svelte';
|
||||||
|
import Alert from '$lib/components/admin/Alert.svelte';
|
||||||
import { untrack } from 'svelte';
|
import { untrack } from 'svelte';
|
||||||
|
|
||||||
let { data, form }: { data: PageData; form: ActionData } = $props();
|
let { data, form }: { data: PageData; form: ActionData } = $props();
|
||||||
@@ -263,10 +265,10 @@
|
|||||||
<div class="admin-page-header">
|
<div class="admin-page-header">
|
||||||
<h2>编辑</h2>
|
<h2>编辑</h2>
|
||||||
<div class="header-actions">
|
<div class="header-actions">
|
||||||
<button type="button" class="btn btn-secondary" onclick={() => fileInput?.click()}
|
<Button type="button" variant="secondary" onclick={() => fileInput?.click()}>
|
||||||
>导入 Markdown</button
|
导入 Markdown
|
||||||
>
|
</Button>
|
||||||
<a href={resolve('/admin/posts')} class="btn btn-secondary">← 返回</a>
|
<Button href={resolve('/admin/posts')} variant="secondary">← 返回</Button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<input
|
<input
|
||||||
@@ -278,9 +280,7 @@
|
|||||||
/>
|
/>
|
||||||
|
|
||||||
{#if form?.error}
|
{#if form?.error}
|
||||||
<div class="error-alert">
|
<Alert message={form.error} />
|
||||||
{form.error}
|
|
||||||
</div>
|
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
<form method="POST" action="?/update" class="post-form">
|
<form method="POST" action="?/update" class="post-form">
|
||||||
@@ -488,7 +488,7 @@
|
|||||||
<div class="form-sidebar">
|
<div class="form-sidebar">
|
||||||
<div class="sidebar-box">
|
<div class="sidebar-box">
|
||||||
<h3>保存</h3>
|
<h3>保存</h3>
|
||||||
<button type="submit" class="btn btn-primary submit-btn">保存</button>
|
<Button type="submit" variant="primary" fullWidth class="submit-btn">保存</Button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<FeaturedImagePicker bind:cover adaptiveHeight previewable />
|
<FeaturedImagePicker bind:cover adaptiveHeight previewable />
|
||||||
@@ -632,60 +632,6 @@
|
|||||||
gap: 10px;
|
gap: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.header-actions .btn {
|
|
||||||
display: inline-flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
box-sizing: border-box;
|
|
||||||
min-height: 42px;
|
|
||||||
margin: 0;
|
|
||||||
line-height: 1;
|
|
||||||
white-space: nowrap;
|
|
||||||
}
|
|
||||||
|
|
||||||
.btn {
|
|
||||||
display: inline-block;
|
|
||||||
padding: 10px 20px;
|
|
||||||
text-decoration: none;
|
|
||||||
font-size: 0.95rem;
|
|
||||||
font-weight: 600;
|
|
||||||
transition: all 0.3s ease;
|
|
||||||
cursor: pointer;
|
|
||||||
border: 1px solid var(--text-color);
|
|
||||||
background-color: transparent;
|
|
||||||
color: var(--text-color);
|
|
||||||
font-family: inherit;
|
|
||||||
text-transform: uppercase;
|
|
||||||
letter-spacing: 1px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.btn-primary {
|
|
||||||
background-color: var(--text-color);
|
|
||||||
color: var(--bg-color, #ffffff);
|
|
||||||
width: 100%;
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.btn-primary:hover {
|
|
||||||
background-color: var(--accent-color, #419b38);
|
|
||||||
border-color: var(--accent-color, #419b38);
|
|
||||||
color: white;
|
|
||||||
}
|
|
||||||
|
|
||||||
.btn-secondary:hover {
|
|
||||||
border-color: var(--accent-color, #419b38);
|
|
||||||
color: var(--accent-color, #419b38);
|
|
||||||
}
|
|
||||||
|
|
||||||
.error-alert {
|
|
||||||
padding: 12px 16px;
|
|
||||||
background-color: transparent;
|
|
||||||
border-left: 4px solid #d9534f;
|
|
||||||
color: #d9534f;
|
|
||||||
margin-bottom: 30px;
|
|
||||||
font-weight: 600;
|
|
||||||
}
|
|
||||||
|
|
||||||
.editor-header {
|
.editor-header {
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
|
|||||||
@@ -10,6 +10,8 @@
|
|||||||
import SelectDropdown from '$lib/components/admin/SelectDropdown.svelte';
|
import SelectDropdown from '$lib/components/admin/SelectDropdown.svelte';
|
||||||
import { parseHugoMarkdown } from '$lib/hugoParser';
|
import { parseHugoMarkdown } from '$lib/hugoParser';
|
||||||
import TextInput from '$lib/components/admin/TextInput.svelte';
|
import TextInput from '$lib/components/admin/TextInput.svelte';
|
||||||
|
import Button from '$lib/components/admin/Button.svelte';
|
||||||
|
import Alert from '$lib/components/admin/Alert.svelte';
|
||||||
import { untrack } from 'svelte';
|
import { untrack } from 'svelte';
|
||||||
|
|
||||||
import { createSlugAutoHandler } from '$lib/utils/slugify';
|
import { createSlugAutoHandler } from '$lib/utils/slugify';
|
||||||
@@ -280,10 +282,10 @@
|
|||||||
<div class="admin-page-header">
|
<div class="admin-page-header">
|
||||||
<h2>新{$page.data.aliases?.post || '文章'}</h2>
|
<h2>新{$page.data.aliases?.post || '文章'}</h2>
|
||||||
<div class="header-actions">
|
<div class="header-actions">
|
||||||
<button type="button" class="btn btn-secondary" onclick={() => fileInput?.click()}
|
<Button type="button" variant="secondary" onclick={() => fileInput?.click()}>
|
||||||
>导入 Markdown</button
|
导入 Markdown
|
||||||
>
|
</Button>
|
||||||
<a href={resolve('/admin/posts')} class="btn btn-secondary">← 返回</a>
|
<Button href={resolve('/admin/posts')} variant="secondary">← 返回</Button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<input
|
<input
|
||||||
@@ -295,9 +297,7 @@
|
|||||||
/>
|
/>
|
||||||
|
|
||||||
{#if form?.error}
|
{#if form?.error}
|
||||||
<div class="error-alert">
|
<Alert message={form.error} />
|
||||||
{form.error}
|
|
||||||
</div>
|
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
<form method="POST" class="post-form">
|
<form method="POST" class="post-form">
|
||||||
@@ -505,9 +505,9 @@
|
|||||||
<div class="form-sidebar">
|
<div class="form-sidebar">
|
||||||
<div class="sidebar-box">
|
<div class="sidebar-box">
|
||||||
<h3>发布</h3>
|
<h3>发布</h3>
|
||||||
<button type="submit" class="btn btn-primary publish-btn"
|
<Button type="submit" variant="primary" fullWidth class="publish-btn">
|
||||||
>发布{$page.data.aliases?.post || '文章'}</button
|
发布{$page.data.aliases?.post || '文章'}
|
||||||
>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<FeaturedImagePicker bind:cover adaptiveHeight previewable />
|
<FeaturedImagePicker bind:cover adaptiveHeight previewable />
|
||||||
@@ -663,60 +663,6 @@
|
|||||||
gap: 10px;
|
gap: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.header-actions .btn {
|
|
||||||
display: inline-flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
box-sizing: border-box;
|
|
||||||
min-height: 42px;
|
|
||||||
margin: 0;
|
|
||||||
line-height: 1;
|
|
||||||
white-space: nowrap;
|
|
||||||
}
|
|
||||||
|
|
||||||
.btn {
|
|
||||||
display: inline-block;
|
|
||||||
padding: 10px 20px;
|
|
||||||
text-decoration: none;
|
|
||||||
font-size: 0.95rem;
|
|
||||||
font-weight: 600;
|
|
||||||
transition: all 0.3s ease;
|
|
||||||
cursor: pointer;
|
|
||||||
border: 1px solid var(--text-color);
|
|
||||||
background-color: transparent;
|
|
||||||
color: var(--text-color);
|
|
||||||
font-family: inherit;
|
|
||||||
text-transform: uppercase;
|
|
||||||
letter-spacing: 1px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.btn-primary {
|
|
||||||
background-color: var(--text-color);
|
|
||||||
color: var(--bg-color, #ffffff);
|
|
||||||
width: 100%;
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.btn-primary:hover {
|
|
||||||
background-color: var(--accent-color, #419b38);
|
|
||||||
border-color: var(--accent-color, #419b38);
|
|
||||||
color: white;
|
|
||||||
}
|
|
||||||
|
|
||||||
.btn-secondary:hover {
|
|
||||||
border-color: var(--accent-color, #419b38);
|
|
||||||
color: var(--accent-color, #419b38);
|
|
||||||
}
|
|
||||||
|
|
||||||
.error-alert {
|
|
||||||
padding: 12px 16px;
|
|
||||||
background-color: transparent;
|
|
||||||
border-left: 4px solid #d9534f;
|
|
||||||
color: #d9534f;
|
|
||||||
margin-bottom: 30px;
|
|
||||||
font-weight: 600;
|
|
||||||
}
|
|
||||||
|
|
||||||
.editor-header {
|
.editor-header {
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
|
|||||||
@@ -6,6 +6,7 @@
|
|||||||
import ImagePicker from '$lib/components/admin/FeaturedImagePicker.svelte';
|
import ImagePicker from '$lib/components/admin/FeaturedImagePicker.svelte';
|
||||||
import DatePicker from '$lib/components/admin/DatePicker.svelte';
|
import DatePicker from '$lib/components/admin/DatePicker.svelte';
|
||||||
import TextInput from '$lib/components/admin/TextInput.svelte';
|
import TextInput from '$lib/components/admin/TextInput.svelte';
|
||||||
|
import Button from '$lib/components/admin/Button.svelte';
|
||||||
import { untrack } from 'svelte';
|
import { untrack } from 'svelte';
|
||||||
|
|
||||||
let { data, form }: { data: PageData; form: ActionData } = $props();
|
let { data, form }: { data: PageData; form: ActionData } = $props();
|
||||||
@@ -98,7 +99,7 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="form-actions">
|
<div class="form-actions">
|
||||||
<button type="submit" class="btn btn-primary">保存</button>
|
<Button type="submit" variant="primary">保存</Button>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
@@ -175,7 +176,7 @@
|
|||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
<div class="form-actions">
|
<div class="form-actions">
|
||||||
<button type="submit" class="btn btn-primary">保存外观偏好</button>
|
<Button type="submit" variant="primary">保存外观偏好</Button>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
@@ -255,7 +256,7 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="form-actions">
|
<div class="form-actions">
|
||||||
<button type="submit" class="btn btn-primary">保存</button>
|
<Button type="submit" variant="primary">保存</Button>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
@@ -374,31 +375,6 @@
|
|||||||
justify-content: flex-end;
|
justify-content: flex-end;
|
||||||
}
|
}
|
||||||
|
|
||||||
.btn {
|
|
||||||
display: inline-block;
|
|
||||||
padding: 10px 24px;
|
|
||||||
text-decoration: none;
|
|
||||||
font-size: 0.95rem;
|
|
||||||
font-weight: 600;
|
|
||||||
transition: all 0.3s ease;
|
|
||||||
cursor: pointer;
|
|
||||||
border: 2px solid var(--text-color);
|
|
||||||
background-color: transparent;
|
|
||||||
color: var(--text-color);
|
|
||||||
font-family: inherit;
|
|
||||||
}
|
|
||||||
|
|
||||||
.btn-primary {
|
|
||||||
background-color: var(--text-color);
|
|
||||||
color: var(--bg-color, #ffffff);
|
|
||||||
}
|
|
||||||
|
|
||||||
.btn-primary:hover {
|
|
||||||
background-color: var(--accent-color, #419b38);
|
|
||||||
border-color: var(--accent-color, #419b38);
|
|
||||||
color: white;
|
|
||||||
}
|
|
||||||
|
|
||||||
.toggle-label {
|
.toggle-label {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
|||||||
Reference in new issue
Block a user