feat: basic ui

This commit is contained in:
Timothy Yin 2025-03-14 21:45:00 +08:00
parent 096d8aa231
commit e3e1a28462
Signed by: HoshinoSuzumi
GPG Key ID: 4052E565F04B122A
15 changed files with 1585 additions and 51 deletions

8
.vscode/settings.json vendored Normal file
View File

@ -0,0 +1,8 @@
{
"files.associations": {
"*.css": "tailwindcss"
},
"editor.quickSuggestions": {
"strings": "on"
}
}

8
app.config.ts Normal file
View File

@ -0,0 +1,8 @@
export default defineAppConfig({
ui: {
colors: {
primary: "indigo",
neutral: "neutral",
},
},
});

11
app.vue
View File

@ -1,6 +1,9 @@
<template>
<div>
<NuxtRouteAnnouncer />
<NuxtWelcome />
</div>
<UApp>
<div class="w-full h-screen">
<NuxtLayout>
<NuxtPage />
</NuxtLayout>
</div>
</UApp>
</template>

9
assets/css/main.css Normal file
View File

@ -0,0 +1,9 @@
@import "tailwindcss" theme(static);
@import "@nuxt/ui";
@theme static {
/* --default-font-family: Rubik, "Noto Sans SC", sans-serif; */
--font-sans: Rubik, "Noto Sans SC", sans-serif;
--font-mono: "Cascadia Code", "Fira Code", "Fira Mono", "Roboto Mono",
monospace;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 81 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 87 KiB

View File

@ -0,0 +1,38 @@
<script lang="ts" setup>
const props = defineProps({
message: {
type: String,
default: null,
},
name: {
type: String,
default: "AI 智慧校园",
},
icon: {
type: String,
default: "tabler:robot-face",
},
});
</script>
<template>
<div class="flex flex-col gap-2">
<div class="flex gap-1.5 items-center">
<div
class="w-7 h-7 rounded-lg border border-neutral-200 bg-white shadow-sm flex justify-center items-center dark:bg-neutral-700 dark:border-neutral-600"
>
<UIcon :name="icon" />
</div>
<span class="text-sm font-medium">{{ name }}</span>
</div>
<div class="rounded-lg bg-white/50 p-2 text-sm dark:bg-neutral-800/50">
<span v-if="message">{{ message }}</span>
<span v-else class="flex items-center gap-1.5">
<UIcon name="svg-spinners:3-dots-scale" class="text-lg -mt-0.5" />
<p class="text-xs">思考中</p>
</span>
</div>
</div>
</template>
<style scoped></style>

View File

@ -0,0 +1,17 @@
<script lang="ts" setup>
defineProps({
message: String,
});
</script>
<template>
<div class="flex flex-col items-end gap-2">
<div
class="rounded-2xl rounded-br-none bg-primary-400 px-3 py-2 text-sm w-fit text-white font-medium dark:bg-primary-500"
>
{{ message }}
</div>
</div>
</template>
<style scoped></style>

View File

@ -0,0 +1,51 @@
<script lang="ts" setup>
const props = defineProps({
inquiriesList: {
type: Array as PropType<
{ label: string; inquiries?: { question: string }[] }[]
>,
required: true,
},
});
const activeTab = ref("0");
</script>
<template>
<div v-if="props.inquiriesList.length">
<div
class="rounded-lg bg-white/50 shadow border border-neutral-50/50 dark:border-neutral-700 dark:bg-neutral-800/50 overflow-hidden"
>
<div>
<UTabs
v-model="activeTab"
:content="false"
:items="props.inquiriesList"
variant="link"
size="sm"
/>
</div>
<div
v-if="props.inquiriesList[Number(activeTab)].inquiries"
class="py-1.5 px-1.5 flex flex-col gap-1 max-h-36 overflow-y-auto"
>
<UButton
v-for="inquiry in props.inquiriesList[Number(activeTab)].inquiries"
variant="ghost"
color="neutral"
trailing-icon="tabler-arrow-right"
size="sm"
block
:key="inquiry.question"
>
{{ inquiry.question }}
</UButton>
</div>
<div v-else class="p-4 text-sm font-medium text-center text-neutral-500">
暂无数据
</div>
</div>
</div>
</template>
<style scoped></style>

18
layouts/default.vue Normal file
View File

@ -0,0 +1,18 @@
<script lang="ts" setup></script>
<template>
<div class="w-full h-full flex flex-col dark:bg-neutral-900/80">
<div
class="sticky top-0 w-full px-4 py-3 bg-white/30 backdrop-blur-2xl z-30 dark:bg-neutral-900/80"
>
<h1 class="font-medium">AI 智慧校园</h1>
</div>
<slot></slot>
</div>
</template>
<style>
body {
background-image: url("~/assets/image/pattern/mesh-7.png");
}
</style>

View File

@ -1,5 +1,12 @@
import tailwindcss from "@tailwindcss/vite";
// https://nuxt.com/docs/api/configuration/nuxt-config
export default defineNuxtConfig({
compatibilityDate: '2024-11-01',
devtools: { enabled: true }
})
compatibilityDate: "2024-11-01",
devtools: { enabled: true },
modules: ["@nuxt/ui"],
css: ["~/assets/css/main.css"],
vite: {
plugins: [tailwindcss()],
},
});

View File

@ -10,9 +10,14 @@
"postinstall": "nuxt prepare"
},
"dependencies": {
"@tailwindcss/vite": "^4.0.14",
"nuxt": "^3.16.0",
"tailwindcss": "^4.0.14",
"vue": "^3.5.13",
"vue-router": "^4.5.0"
},
"packageManager": "pnpm@9.15.3+sha512.1f79bc245a66eb0b07c5d4d83131240774642caaa86ef7d0434ab47c0d16f66b04e21e0c086eb61e62c77efc4d7f7ec071afad3796af64892fae66509173893a"
"packageManager": "pnpm@9.15.3+sha512.1f79bc245a66eb0b07c5d4d83131240774642caaa86ef7d0434ab47c0d16f66b04e21e0c086eb61e62c77efc4d7f7ec071afad3796af64892fae66509173893a",
"devDependencies": {
"@nuxt/ui": "^3.0.0"
}
}

78
pages/index.vue Normal file
View File

@ -0,0 +1,78 @@
<script lang="ts" setup>
const getPopularInquiriesByRole = () => {
return [
{
label: "新生入学",
inquiries: [
{
question: "新生报到时间",
},
{
question: "新生报到流程",
},
{
question: "如何到达学院",
},
{
question: "如何办理户口迁移",
},
{
question: "学院 VPN 使用方法",
},
],
},
{
label: "学校概况",
},
{
label: "学术学习",
},
{
label: "生活服务",
},
{
label: "就业辅导",
},
];
};
const inquiries = computed(() => getPopularInquiriesByRole());
</script>
<template>
<div>
<div class="p-4 h-full flex flex-col gap-4 mb-20">
<PopularInquiries :inquiries-list="inquiries" />
<ChatUserMessage message="眩生花是什么?" />
<ChatBotMessage
name="AI 辅导员"
message="眩生花是一家科技公司全称为重庆眩生花科技有限公司它专注于新一代人工智能技术的研发与应用包括AI大模型AIGC生成式人工智能AI AgentAI-First以及AGI通用人工智能等领域的创新解决方案公司的目标是通过这些先进技术为高等教育职业教育和基础教育等行业提供变革性的服务助力教育生态的重塑
眩生花秉承以人为本抱诚守真求实创新的价值观致力于成为AI教育时代的变革者推动教育方式的革新与进步"
/>
<ChatUserMessage message="这是前端测试示例消息" />
<ChatBotMessage name="AI 辅导员" />
</div>
<div
class="fixed inset-x-0 bottom-0 p-4 bg-white/90 rounded-t-2xl shadow-2xl dark:bg-neutral-800/90 backdrop-blur-2xl"
>
<img
src="~/assets/image/pattern/ai_glow.png"
class="absolute top-0 inset-x-0 opacity-50"
/>
<div class="w-full flex justify-between items-center gap-2">
<UInput placeholder="请输入问题" class="flex-1" size="xl" />
<UButton
color="primary"
variant="solid"
size="xl"
trailing-icon="tabler:send-2"
>提问</UButton
>
</div>
</div>
</div>
</template>
<style scoped></style>

1377
pnpm-lock.yaml generated

File diff suppressed because it is too large Load Diff

1
types/index.ts Normal file
View File

@ -0,0 +1 @@
export type VisitorRole = "stu" | "tea" | "fans";