mirror of
https://github.com/CorentinTh/it-tools.git
synced 2025-04-23 16:26:15 -04:00
chore: components base
This commit is contained in:
parent
64c92a661c
commit
25a8659786
13 changed files with 821 additions and 19 deletions
|
@ -16,9 +16,11 @@ const layout = computed(() => route?.meta?.layout ?? layouts.base)
|
|||
<template>
|
||||
<n-config-provider>
|
||||
<n-global-style />
|
||||
<component :is="layout">
|
||||
<router-view />
|
||||
</component>
|
||||
<n-message-provider placement="bottom">
|
||||
<component :is="layout">
|
||||
<router-view />
|
||||
</component>
|
||||
</n-message-provider>
|
||||
</n-config-provider>
|
||||
</template>
|
||||
|
||||
|
|
15
src/composable/copy.ts
Normal file
15
src/composable/copy.ts
Normal file
|
@ -0,0 +1,15 @@
|
|||
import { useClipboard } from '@vueuse/core';
|
||||
import { useMessage } from 'naive-ui';
|
||||
import type { Ref } from 'vue';
|
||||
|
||||
export function useCopy({ source, text = 'Copied to the clipboard' }: { source: Ref; text?: string }) {
|
||||
const { copy } = useClipboard({ source });
|
||||
const message = useMessage();
|
||||
|
||||
return {
|
||||
async copy() {
|
||||
await copy();
|
||||
message.success(text);
|
||||
},
|
||||
};
|
||||
}
|
|
@ -1,19 +1,85 @@
|
|||
<script lang="ts">
|
||||
export default {
|
||||
name: 'base-layout'
|
||||
}
|
||||
<script lang="ts" setup>
|
||||
import { NIcon } from 'naive-ui';
|
||||
import { h, ref, type Component } from 'vue';
|
||||
import { RouterLink, useRoute } from 'vue-router';
|
||||
import { User } from '@vicons/tabler'
|
||||
import { tools } from '@/tools';
|
||||
|
||||
const collapsed = ref(false)
|
||||
const activeKey = ref(null)
|
||||
const route = useRoute()
|
||||
|
||||
const makeLabel = (text: string, to: string) => () => h(RouterLink, { to }, { default: () => text })
|
||||
const makeIcon = (icon: Component) => () => h(NIcon, null, { default: () => h(icon) })
|
||||
|
||||
const menuOptions = tools.map(({ name, path, icon }) => ({
|
||||
label: makeLabel(name, path),
|
||||
key: name,
|
||||
icon: makeIcon(icon)
|
||||
}))
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="base-layout">
|
||||
<slot />
|
||||
</div>
|
||||
<n-layout has-sider>
|
||||
<n-layout-sider
|
||||
bordered
|
||||
collapse-mode="width"
|
||||
:collapsed-width="64"
|
||||
:width="240"
|
||||
:collapsed="collapsed"
|
||||
show-trigger
|
||||
@collapse="collapsed = true"
|
||||
@expand="collapsed = false"
|
||||
>
|
||||
<router-link
|
||||
to="/"
|
||||
style="text-decoration: none; color: grey; display: block; text-align: center; margin:25px 0; font-size: 25px;"
|
||||
>
|
||||
<strong>IT-Tools</strong>
|
||||
</router-link>
|
||||
|
||||
<n-menu
|
||||
:value="route.name"
|
||||
class="menu"
|
||||
:collapsed="collapsed"
|
||||
:collapsed-width="64"
|
||||
:collapsed-icon-size="22"
|
||||
:options="menuOptions"
|
||||
v-model:value="activeKey"
|
||||
/>
|
||||
</n-layout-sider>
|
||||
<n-layout class="content">
|
||||
<div class="bar-wrapper">
|
||||
<n-input />
|
||||
<n-button secondary circle>
|
||||
<n-icon size="large">
|
||||
<user />
|
||||
</n-icon>
|
||||
</n-button>
|
||||
</div>
|
||||
<slot />
|
||||
</n-layout>
|
||||
</n-layout>
|
||||
</template>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.base-layout {
|
||||
width: 100%;
|
||||
min-height: 100vh;
|
||||
background-color: #f4f6fa;
|
||||
.bar-wrapper {
|
||||
display: flex;
|
||||
& > *:not(:first-child) {
|
||||
margin-left: 15px;
|
||||
}
|
||||
& > :first-child {
|
||||
flex-grow: 1;
|
||||
}
|
||||
}
|
||||
|
||||
.content {
|
||||
background-color: #f1f5f9;
|
||||
::v-deep(.n-layout-scroll-container) {
|
||||
padding: 26px;
|
||||
}
|
||||
}
|
||||
.n-layout {
|
||||
height: 100vh;
|
||||
}
|
||||
</style>
|
|
@ -1,5 +1,7 @@
|
|||
import BaseLayout from './base.layout.vue';
|
||||
import ToolLayout from './tool.layout.vue';
|
||||
|
||||
export const layouts = {
|
||||
base: BaseLayout,
|
||||
toolLayout: ToolLayout,
|
||||
};
|
||||
|
|
68
src/layouts/tool.layout.vue
Normal file
68
src/layouts/tool.layout.vue
Normal file
|
@ -0,0 +1,68 @@
|
|||
<script lang="ts" setup>
|
||||
import { useRoute } from 'vue-router';
|
||||
import BaseLayout from './base.layout.vue';
|
||||
import { useHead } from '@vueuse/head'
|
||||
import type { HeadObject } from '@vueuse/head'
|
||||
import { reactive } from 'vue';
|
||||
|
||||
const route = useRoute()
|
||||
|
||||
const head = reactive<HeadObject>({
|
||||
title: `${route.meta.name} - IT Tools`,
|
||||
meta: [
|
||||
{
|
||||
name: 'description',
|
||||
content: route.meta.description
|
||||
},
|
||||
{
|
||||
name: 'keywords',
|
||||
content: route.meta.keywords
|
||||
}
|
||||
]
|
||||
})
|
||||
useHead(head)
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<base-layout>
|
||||
<div class="tool-layout">
|
||||
<div class="tool-header">
|
||||
<n-h1>{{ route.meta.name }}</n-h1>
|
||||
<div class="separator" />
|
||||
<div class="description">{{ route.meta.description }}</div>
|
||||
</div>
|
||||
|
||||
<slot />
|
||||
</div>
|
||||
</base-layout>
|
||||
</template>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.tool-layout {
|
||||
max-width: 700px;
|
||||
margin: 0 auto;
|
||||
box-sizing: border-box;
|
||||
|
||||
.tool-header {
|
||||
padding: 40px 0;
|
||||
.n-h1 {
|
||||
opacity: 0.9;
|
||||
font-size: 40px;
|
||||
font-weight: 400;
|
||||
margin: 0;
|
||||
}
|
||||
.separator {
|
||||
width: 200px;
|
||||
height: 2px;
|
||||
background: rgb(161, 161, 161);
|
||||
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
.description {
|
||||
margin: 0;
|
||||
|
||||
opacity: 0.7;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
|
@ -1,5 +1,6 @@
|
|||
import { createApp } from 'vue';
|
||||
import { createPinia } from 'pinia';
|
||||
import { createHead } from '@vueuse/head';
|
||||
|
||||
import { naive } from './plugins/naive.plugin';
|
||||
|
||||
|
@ -9,6 +10,7 @@ import router from './router';
|
|||
const app = createApp(App);
|
||||
|
||||
app.use(createPinia());
|
||||
app.use(createHead());
|
||||
app.use(router);
|
||||
app.use(naive);
|
||||
|
||||
|
|
|
@ -33,9 +33,19 @@ import {
|
|||
NP,
|
||||
NH2,
|
||||
NDropdown,
|
||||
NLayout,
|
||||
NLayoutSider,
|
||||
NMenu,
|
||||
NMessageProvider,
|
||||
NPageHeader,
|
||||
} from 'naive-ui';
|
||||
|
||||
const components = [
|
||||
NPageHeader,
|
||||
NMessageProvider,
|
||||
NLayout,
|
||||
NLayoutSider,
|
||||
NMenu,
|
||||
NDropdown,
|
||||
NH2,
|
||||
NP,
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
import { layouts } from './layouts/index';
|
||||
import { createRouter, createWebHistory } from 'vue-router';
|
||||
import HomePage from './pages/Home.page.vue';
|
||||
import { tools } from './tools';
|
||||
|
@ -10,7 +11,7 @@ const router = createRouter({
|
|||
name: 'home',
|
||||
component: HomePage,
|
||||
},
|
||||
...Object.values(tools).flat(),
|
||||
...tools.map(({ path, name, component, ...config }) => ({ path, name, component, meta: { isTool: true, layout: layouts.toolLayout, name, ...config } })),
|
||||
],
|
||||
});
|
||||
|
||||
|
|
|
@ -6,4 +6,11 @@ export interface ITool {
|
|||
description: string;
|
||||
keywords: string[];
|
||||
component: () => Promise<Component>;
|
||||
icon: Component;
|
||||
}
|
||||
|
||||
export interface ToolCategory {
|
||||
name: string;
|
||||
icon: Component;
|
||||
components: ITool[];
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import { tool as tokenGenerator } from './token-generator';
|
||||
import type { ToolCategory } from './Tool';
|
||||
|
||||
export const tools = {
|
||||
crypto: [tokenGenerator],
|
||||
};
|
||||
export const toolsByCategory: ToolCategory[] = [];
|
||||
|
||||
export const tools = toolsByCategory.flatMap(({ components }) => components);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue