完成布局
This commit is contained in:
@@ -50,13 +50,12 @@ provide('navigation', navigation)
|
||||
<template>
|
||||
<UApp>
|
||||
<NuxtLoadingIndicator />
|
||||
|
||||
<AppHeader />
|
||||
<UMain>
|
||||
<NuxtLayout>
|
||||
<NuxtPage />
|
||||
</NuxtLayout>
|
||||
</UMain>
|
||||
|
||||
<ClientOnly>
|
||||
<LazyUContentSearch
|
||||
:files="files"
|
||||
|
@@ -48,20 +48,20 @@
|
||||
<div>
|
||||
<NuxtLink
|
||||
to="/"
|
||||
class="flex items-center px-4 py-3 text-sm font-medium rounded-xl text-gray-700 dark:text-gray-300 hover:bg-gray-50 dark:hover:bg-gray-800 hover:shadow-sm transition-all duration-200"
|
||||
class="flex items-center px-4 py-2 text-sm font-medium rounded-lg text-gray-700 dark:text-gray-300 hover:bg-gray-50 dark:hover:bg-gray-800 hover:shadow-sm transition-all duration-200"
|
||||
:class="{
|
||||
'bg-blue-50 dark:bg-blue-900/20 text-blue-600 dark:text-blue-400 shadow-sm':
|
||||
$route.path === '/',
|
||||
}"
|
||||
>
|
||||
<Icon name="uim:house-user" class="text-primary mr-2" size="20" />
|
||||
<Icon name="lucide-home" class="text-primary mr-2" size="20" />
|
||||
站点首页
|
||||
</NuxtLink>
|
||||
</div>
|
||||
|
||||
|
||||
<!-- 分隔线 -->
|
||||
<div class="flex items-center px-6 p-1 ">
|
||||
<div class="flex items-center px-8 p-1 ">
|
||||
<ContentDirectory />
|
||||
</div>
|
||||
|
||||
|
@@ -3,6 +3,7 @@
|
||||
<UContentNavigation
|
||||
:navigation="directoryNavigation"
|
||||
highlight
|
||||
|
||||
color="primary"
|
||||
variant="pill"
|
||||
/>
|
||||
|
42
app/components/auth/login.vue
Normal file
42
app/components/auth/login.vue
Normal file
@@ -0,0 +1,42 @@
|
||||
<script setup lang="ts">
|
||||
const providers = ref([
|
||||
{
|
||||
label: 'Google',
|
||||
icon: 'i-simple-icons-google',
|
||||
color: 'neutral',
|
||||
variant: 'subtle'
|
||||
},
|
||||
{
|
||||
label: 'GitHub',
|
||||
icon: 'i-simple-icons-github',
|
||||
color: 'neutral',
|
||||
variant: 'subtle'
|
||||
}
|
||||
])
|
||||
const fields = ref([
|
||||
{
|
||||
name: 'email',
|
||||
type: 'text',
|
||||
label: 'Email'
|
||||
},
|
||||
{
|
||||
name: 'password',
|
||||
type: 'password',
|
||||
label: 'Password'
|
||||
}
|
||||
])
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<UAuthForm
|
||||
class="max-w-md"
|
||||
title="Login"
|
||||
description="Enter your credentials to access your account."
|
||||
icon="i-lucide-user"
|
||||
:fields="fields"
|
||||
:providers="providers"
|
||||
:separator="{
|
||||
icon: 'i-lucide-user'
|
||||
}"
|
||||
/>
|
||||
</template>
|
@@ -1,42 +1,57 @@
|
||||
<script setup lang="ts">
|
||||
import type { NuxtError } from '#app'
|
||||
import type { NuxtError } from "#app";
|
||||
|
||||
definePageMeta({
|
||||
layout: "default",
|
||||
});
|
||||
|
||||
defineProps<{
|
||||
error: NuxtError
|
||||
}>()
|
||||
error: NuxtError;
|
||||
}>();
|
||||
|
||||
useHead({
|
||||
htmlAttrs: {
|
||||
lang: 'en'
|
||||
}
|
||||
})
|
||||
lang: "zh-CN",
|
||||
},
|
||||
});
|
||||
|
||||
useSeoMeta({
|
||||
title: 'Page not found',
|
||||
description: 'We are sorry but this page could not be found.'
|
||||
})
|
||||
title: "Page not found",
|
||||
description: "We are sorry but this page could not be found.",
|
||||
});
|
||||
|
||||
const { data: navigation } = await useAsyncData('navigation', () => queryCollectionNavigation('docs'))
|
||||
const { data: files } = useLazyAsyncData('search', () => queryCollectionSearchSections('docs'), {
|
||||
server: false
|
||||
})
|
||||
const { data: navigation } = await useAsyncData("navigation", () =>
|
||||
queryCollectionNavigation("docs"),
|
||||
);
|
||||
const { data: files } = useLazyAsyncData(
|
||||
"search",
|
||||
() => queryCollectionSearchSections("docs"),
|
||||
{
|
||||
server: false,
|
||||
},
|
||||
);
|
||||
|
||||
provide('navigation', navigation)
|
||||
provide("navigation", navigation);
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<UApp>
|
||||
<AppHeader />
|
||||
|
||||
<UError :error="error" />
|
||||
<UError
|
||||
:error="error"
|
||||
:clear="{
|
||||
size: 'xl',
|
||||
icon: 'i-lucide-arrow-left',
|
||||
class: 'rounded-full',
|
||||
}"
|
||||
redirect="/"
|
||||
/>
|
||||
|
||||
<AppFooter />
|
||||
|
||||
<ClientOnly>
|
||||
<LazyUContentSearch
|
||||
:files="files"
|
||||
:navigation="navigation"
|
||||
/>
|
||||
<LazyUContentSearch :files="files" :navigation="navigation" />
|
||||
</ClientOnly>
|
||||
</UApp>
|
||||
</template>
|
||||
|
@@ -18,11 +18,52 @@ const pageFontSizeClass = computed(() => {
|
||||
return `text-${selectedFontSize.value}`
|
||||
})
|
||||
|
||||
const { data: page } = await useAsyncData(route.path, () => queryCollection('docs').path(route.path).first())
|
||||
if (!page.value) {
|
||||
throw createError({ statusCode: 404, statusMessage: 'Page not found', fatal: true })
|
||||
// 根据路由参数构建内容路径
|
||||
const path = computed(() => {
|
||||
const slug = route.params.slug;
|
||||
|
||||
// 处理 slug 参数
|
||||
if (!slug) {
|
||||
return '/'; // 如果没有 slug,返回根路径
|
||||
}
|
||||
|
||||
const pathValue = Array.isArray(slug) ? slug.join("/") : slug;
|
||||
|
||||
// 确保路径以 / 开头,不以 / 结尾
|
||||
const normalizedPath = `/${pathValue}`.replace(/\/+$/, ""); // 使用 /+ 匹配多个连续的斜杠
|
||||
|
||||
return normalizedPath;
|
||||
});
|
||||
|
||||
// URL 解码并验证路径
|
||||
const queryPath = computed(() => {
|
||||
try {
|
||||
return decodeURIComponent(path.value);
|
||||
} catch (error) {
|
||||
console.error('URL decode error:', error);
|
||||
return path.value; // 如果解码失败,返回原始路径
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
const { data: page } = await useAsyncData(
|
||||
`page-${route.path}`, // 使用更具体的 key
|
||||
() => queryCollection('docs').path(queryPath.value).first(),
|
||||
{
|
||||
default: () => null // 提供默认值
|
||||
}
|
||||
);
|
||||
|
||||
if (!page.value) {
|
||||
throw createError({
|
||||
statusCode: 404,
|
||||
statusMessage: '文档不存在',
|
||||
message: '当前页面不存在,请您检查路径是否正确',
|
||||
fatal: true
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
const { data: surround } = await useAsyncData(`${route.path}-surround`, () => {
|
||||
return queryCollectionItemSurroundings('docs', route.path, {
|
||||
fields: ['description']
|
||||
|
@@ -1,4 +1,8 @@
|
||||
<script setup lang="ts">
|
||||
definePageMeta({
|
||||
layout: 'default'
|
||||
})
|
||||
|
||||
const { data: page } = await useAsyncData('index', () => queryCollection('landing').path('/').first())
|
||||
if (!page.value) {
|
||||
throw createError({ statusCode: 404, statusMessage: 'Page not found', fatal: true })
|
||||
|
@@ -1,96 +0,0 @@
|
||||
<template>
|
||||
<div class="min-h-screen flex items-center justify-center bg-gray-50 dark:bg-gray-900 py-12 px-4 sm:px-6 lg:px-8">
|
||||
<div class="max-w-md w-full space-y-8">
|
||||
<div>
|
||||
<h2 class="mt-6 text-center text-3xl font-extrabold text-gray-900 dark:text-white">
|
||||
登录您的账户
|
||||
</h2>
|
||||
<p class="mt-2 text-center text-sm text-gray-600 dark:text-gray-300">
|
||||
或
|
||||
<NuxtLink to="/register" class="font-medium text-blue-600 hover:text-blue-500">
|
||||
创建新账户
|
||||
</NuxtLink>
|
||||
</p>
|
||||
</div>
|
||||
<form class="mt-8 space-y-6" @submit.prevent="handleLogin">
|
||||
<div class="rounded-md shadow-sm -space-y-px">
|
||||
<div>
|
||||
<label for="email" class="sr-only">邮箱地址</label>
|
||||
<input
|
||||
id="email"
|
||||
v-model="email"
|
||||
type="email"
|
||||
required
|
||||
class="appearance-none rounded-none relative block w-full px-3 py-2 border border-gray-300 placeholder-gray-500 text-gray-900 rounded-t-md focus:outline-none focus:ring-blue-500 focus:border-blue-500 focus:z-10 sm:text-sm"
|
||||
placeholder="邮箱地址"
|
||||
>
|
||||
</div>
|
||||
<div>
|
||||
<label for="password" class="sr-only">密码</label>
|
||||
<input
|
||||
id="password"
|
||||
v-model="password"
|
||||
type="password"
|
||||
required
|
||||
class="appearance-none rounded-none relative block w-full px-3 py-2 border border-gray-300 placeholder-gray-500 text-gray-900 rounded-b-md focus:outline-none focus:ring-blue-500 focus:border-blue-500 focus:z-10 sm:text-sm"
|
||||
placeholder="密码"
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="flex items-center justify-between">
|
||||
<div class="flex items-center">
|
||||
<input
|
||||
id="remember-me"
|
||||
v-model="rememberMe"
|
||||
type="checkbox"
|
||||
class="h-4 w-4 text-blue-600 focus:ring-blue-500 border-gray-300 rounded"
|
||||
>
|
||||
<label for="remember-me" class="ml-2 block text-sm text-gray-900 dark:text-gray-300">
|
||||
记住我
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div class="text-sm">
|
||||
<a href="#" class="font-medium text-blue-600 hover:text-blue-500">
|
||||
忘记密码?
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<button
|
||||
type="submit"
|
||||
class="group relative w-full flex justify-center py-2 px-4 border border-transparent text-sm font-medium rounded-md text-white bg-blue-600 hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500"
|
||||
>
|
||||
<span class="absolute left-0 inset-y-0 flex items-center pl-3">
|
||||
<svg class="h-5 w-5 text-blue-500 group-hover:text-blue-400" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor" aria-hidden="true">
|
||||
<path fill-rule="evenodd" d="M5 9V7a5 5 0 0110 0v2a2 2 0 012 2v5a2 2 0 01-2 2H5a2 2 0 01-2-2v-5a2 2 0 012-2zm8-2v2H7V7a3 3 0 016 0z" clip-rule="evenodd" />
|
||||
</svg>
|
||||
</span>
|
||||
登录
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
const email = ref('')
|
||||
const password = ref('')
|
||||
const rememberMe = ref(false)
|
||||
|
||||
const handleLogin = () => {
|
||||
// TODO: Implement actual login logic
|
||||
console.log('Login attempt:', { email: email.value, password: password.value, rememberMe: rememberMe.value })
|
||||
|
||||
// For demo purposes, redirect to home
|
||||
navigateTo('/')
|
||||
}
|
||||
|
||||
useSeoMeta({
|
||||
title: '登录 - Easy Docs',
|
||||
description: '登录您的 Easy Docs 账户'
|
||||
})
|
||||
</script>
|
@@ -1,2 +0,0 @@
|
||||
title: Getting Started
|
||||
icon: false
|
2
content/1.简单文档/.navigation.yml
Normal file
2
content/1.简单文档/.navigation.yml
Normal file
@@ -0,0 +1,2 @@
|
||||
title: 简单文档
|
||||
icon: i-lucide-book-open
|
@@ -1 +1,2 @@
|
||||
title: Essentials
|
||||
icon: i-lucide-book-open
|
2
content/3.getting-started/.navigation.yml
Normal file
2
content/3.getting-started/.navigation.yml
Normal file
@@ -0,0 +1,2 @@
|
||||
title: Getting Started
|
||||
icon: i-lucide-book-open
|
86
content/3.getting-started/1.index.md
Normal file
86
content/3.getting-started/1.index.md
Normal file
@@ -0,0 +1,86 @@
|
||||
---
|
||||
title: Introduction
|
||||
description: Welcome to Nuxt UI Pro documentation template.
|
||||
navigation:
|
||||
icon: i-lucide-house
|
||||
---
|
||||
|
||||
This template is a ready-to-use documentation template made with [Nuxt UI Pro](https://ui.nuxt.com/pro), a collection of premium components built on top of [Nuxt UI](https://ui.nuxt.com) to create beautiful & responsive Nuxt applications in minutes.
|
||||
|
||||
There are already many websites based on this template:
|
||||
|
||||
::card-group
|
||||
:::card
|
||||
---
|
||||
icon: i-simple-icons-nuxtdotjs
|
||||
target: _blank
|
||||
title: Nuxt
|
||||
to: https://nuxt.com
|
||||
---
|
||||
The Nuxt website
|
||||
:::
|
||||
|
||||
:::card
|
||||
---
|
||||
icon: i-simple-icons-nuxtdotjs
|
||||
target: _blank
|
||||
title: Nuxt UI
|
||||
to: https://ui.nuxt.com
|
||||
---
|
||||
The documentation of `@nuxt/ui` and `@nuxt/ui-pro`
|
||||
:::
|
||||
|
||||
:::card
|
||||
---
|
||||
icon: i-simple-icons-nuxtdotjs
|
||||
target: _blank
|
||||
title: Nuxt Image
|
||||
to: https://image.nuxt.com
|
||||
---
|
||||
The documentation of `@nuxt/image`
|
||||
:::
|
||||
|
||||
:::card
|
||||
---
|
||||
icon: i-simple-icons-nuxtdotjs
|
||||
target: _blank
|
||||
title: Nuxt Content
|
||||
to: https://content.nuxt.com
|
||||
---
|
||||
The documentation of `@nuxt/content`
|
||||
:::
|
||||
|
||||
:::card
|
||||
---
|
||||
icon: i-simple-icons-nuxtdotjs
|
||||
target: _blank
|
||||
title: Nuxt Devtools
|
||||
to: https://devtools.nuxt.com
|
||||
---
|
||||
The documentation of `@nuxt/devtools`
|
||||
:::
|
||||
|
||||
:::card
|
||||
---
|
||||
icon: i-simple-icons-nuxtdotjs
|
||||
target: _blank
|
||||
title: Nuxt Hub
|
||||
to: https://hub.nuxt.com
|
||||
---
|
||||
The best place to manage your projects, environments and variables.
|
||||
:::
|
||||
::
|
||||
|
||||
## Key Features
|
||||
|
||||
This template includes a range of features designed to streamline documentation management:
|
||||
|
||||
- **Powered by** [**Nuxt 3**](https://nuxt.com): Utilizes the latest Nuxt framework for optimal performance.
|
||||
- **Built with** [**Nuxt UI**](https://ui.nuxt.com) **and** [**Nuxt UI Pro**](https://ui.nuxt.com/pro): Integrates a comprehensive suite of UI components.
|
||||
- [**MDC Syntax**](https://content.nuxt.com/usage/markdown) **via** [**Nuxt Content**](https://content.nuxt.com): Supports Markdown with component integration for dynamic content.
|
||||
- [**Nuxt Studio**](https://content.nuxt.com/docs/studio) **Compatible**: Offers integration with Nuxt Studio for content editing.
|
||||
- **Auto-generated Sidebar Navigation**: Automatically generates navigation from content structure.
|
||||
- **Full-Text Search**: Includes built-in search functionality for content discovery.
|
||||
- **Optimized Typography**: Features refined typography for enhanced readability.
|
||||
- **Dark Mode**: Offers dark mode support for user preference.
|
||||
- **Extensive Functionality**: Explore the template to fully appreciate its capabilities.
|
29
content/3.getting-started/2.installation.md
Normal file
29
content/3.getting-started/2.installation.md
Normal file
@@ -0,0 +1,29 @@
|
||||
---
|
||||
title: Installation
|
||||
description: Get started with Nuxt UI Pro documentation template.
|
||||
navigation:
|
||||
icon: i-lucide-download
|
||||
---
|
||||
|
||||
::tip{target="_blank" to="https://content.nuxt.com/templates/docs"}
|
||||
Use this template on Nuxt Studio and start your documentation in seconds.
|
||||
::
|
||||
|
||||
## Quick Start
|
||||
|
||||
You can start a fresh new project with:
|
||||
|
||||
```bash [Terminal]
|
||||
npx nuxi init -t github:nuxt-ui-pro/docs
|
||||
```
|
||||
|
||||
or create a new repository from GitHub:
|
||||
|
||||
1. Open <https://github.com/nuxt-ui-pro/docs>
|
||||
2. Click on `Use this template` button
|
||||
3. Enter repository name and click on `Create repository from template` button
|
||||
4. Clone your new repository
|
||||
5. Install dependencies with your favorite package manager
|
||||
6. Start development server
|
||||
|
||||
That's it! You can now start writing your documentation in the [`content/`](https://content.nuxt.com/usage/content-directory) directory 🚀
|
127
content/3.getting-started/3.usage.md
Normal file
127
content/3.getting-started/3.usage.md
Normal file
@@ -0,0 +1,127 @@
|
||||
---
|
||||
title: Usage
|
||||
description: Learn how to write and customize your documentation.
|
||||
navigation:
|
||||
icon: i-lucide-sliders
|
||||
---
|
||||
|
||||
This is only a basic example of what you can achieve with [Nuxt UI Pro](https://ui.nuxt.com/pro/guide), you can tweak it to match your needs. The template uses several Nuxt modules underneath like [`@nuxt/content`](https://content.nuxt.com) for the content and [`nuxt-og-image`](https://nuxtseo.com/og-image/getting-started/installation) for social previews.
|
||||
|
||||
::tip
|
||||
---
|
||||
target: _blank
|
||||
to: https://ui.nuxt.com/getting-started/installation/pro/nuxt
|
||||
---
|
||||
Learn more on how to take the most out of Nuxt UI Pro!
|
||||
::
|
||||
|
||||
## Writing content
|
||||
|
||||
You can just start writing `.md` or `.yml` files in the [`content/`](https://content.nuxt.com/usage/content-directory) directory to have your pages updated. The navigation will be automatically generated in the left aside and in the mobile menu. You will also be able to go through your content with full-text search.
|
||||
|
||||
## App Configuration
|
||||
|
||||
In addition to `@nuxt/ui-pro` configuration through the `app.config.ts`, this template lets you customize the `Header`, `Footer` and the `Table of contents` components.
|
||||
|
||||
### Header
|
||||
|
||||
```ts [app.config.ts]
|
||||
export default defineAppConfig({
|
||||
header: {
|
||||
title: '',
|
||||
to: '/',
|
||||
// Logo configuration
|
||||
logo: {
|
||||
alt: '',
|
||||
// Light mode
|
||||
light: '',
|
||||
// Dark mode
|
||||
dark: ''
|
||||
},
|
||||
// Show or hide the search bar
|
||||
search: true,
|
||||
// Show or hide the color mode button
|
||||
colorMode: true,
|
||||
// Customize links
|
||||
links: [{
|
||||
'icon': 'i-simple-icons-github',
|
||||
'to': 'https://github.com/nuxt-ui-pro/docs',
|
||||
'target': '_blank',
|
||||
'aria-label': 'GitHub'
|
||||
}]
|
||||
},
|
||||
})
|
||||
```
|
||||
|
||||
### Footer
|
||||
|
||||
```ts [app.config.ts]
|
||||
export default defineAppConfig({
|
||||
footer: {
|
||||
// Update bottom left credits
|
||||
credits: `Copyright © ${new Date().getFullYear()}`,
|
||||
// Show or hide the color mode button
|
||||
colorMode: false,
|
||||
// Customize links
|
||||
links: [{
|
||||
'icon': 'i-simple-icons-nuxtdotjs',
|
||||
'to': 'https://nuxt.com',
|
||||
'target': '_blank',
|
||||
'aria-label': 'Nuxt Website'
|
||||
}, {
|
||||
'icon': 'i-simple-icons-discord',
|
||||
'to': 'https://discord.com/invite/ps2h6QT',
|
||||
'target': '_blank',
|
||||
'aria-label': 'Nuxt UI on Discord'
|
||||
}, {
|
||||
'icon': 'i-simple-icons-x',
|
||||
'to': 'https://x.com/nuxt_js',
|
||||
'target': '_blank',
|
||||
'aria-label': 'Nuxt on X'
|
||||
}, {
|
||||
'icon': 'i-simple-icons-github',
|
||||
'to': 'https://github.com/nuxt/ui',
|
||||
'target': '_blank',
|
||||
'aria-label': 'Nuxt UI on GitHub'
|
||||
}]
|
||||
},
|
||||
})
|
||||
```
|
||||
|
||||
### Table of contents
|
||||
|
||||
```ts [app.config.ts]
|
||||
export default defineAppConfig({
|
||||
toc: {
|
||||
// Title of the main table of contents
|
||||
title: 'Table of Contents',
|
||||
// Customize links
|
||||
bottom: {
|
||||
// Title of the bottom table of contents
|
||||
title: 'Community',
|
||||
// URL of your repository content folder
|
||||
edit: 'https://github.com/nuxt-ui-pro/docs/edit/main/content',
|
||||
links: [{
|
||||
icon: 'i-lucide-star',
|
||||
label: 'Star on GitHub',
|
||||
to: 'https://github.com/nuxt/ui',
|
||||
target: '_blank'
|
||||
}, {
|
||||
icon: 'i-lucide-book-open',
|
||||
label: 'Nuxt UI Pro docs',
|
||||
to: 'https://ui.nuxt.com/getting-started/installation/pro/nuxt',
|
||||
target: '_blank'
|
||||
}, {
|
||||
icon: 'i-simple-icons-nuxtdotjs',
|
||||
label: 'Purchase a license',
|
||||
to: 'https://ui.nuxt.com/pro/purchase',
|
||||
target: '_blank'
|
||||
}]
|
||||
}
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
::tip{target="_blank" to="https://content.nuxt.com/docs/studio/config"}
|
||||
This template integrates with Nuxt Studio, providing a visual interface for editing your documentation - perfect for non-technical contributors.
|
||||
::
|
@@ -22,6 +22,12 @@ export default defineNuxtConfig({
|
||||
toc: {
|
||||
searchDepth: 1
|
||||
}
|
||||
},
|
||||
pathMeta: {
|
||||
slugifyOptions: {
|
||||
// Keep everything except invalid chars, this will preserve Chinese characters
|
||||
remove: /[$*+~()'"!\-=#?:@.]/g,
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
Reference in New Issue
Block a user