feat: basic ui
This commit is contained in:
parent
096d8aa231
commit
e3e1a28462
8
.vscode/settings.json
vendored
Normal file
8
.vscode/settings.json
vendored
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
{
|
||||||
|
"files.associations": {
|
||||||
|
"*.css": "tailwindcss"
|
||||||
|
},
|
||||||
|
"editor.quickSuggestions": {
|
||||||
|
"strings": "on"
|
||||||
|
}
|
||||||
|
}
|
8
app.config.ts
Normal file
8
app.config.ts
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
export default defineAppConfig({
|
||||||
|
ui: {
|
||||||
|
colors: {
|
||||||
|
primary: "indigo",
|
||||||
|
neutral: "neutral",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
11
app.vue
11
app.vue
@ -1,6 +1,9 @@
|
|||||||
<template>
|
<template>
|
||||||
<div>
|
<UApp>
|
||||||
<NuxtRouteAnnouncer />
|
<div class="w-full h-screen">
|
||||||
<NuxtWelcome />
|
<NuxtLayout>
|
||||||
</div>
|
<NuxtPage />
|
||||||
|
</NuxtLayout>
|
||||||
|
</div>
|
||||||
|
</UApp>
|
||||||
</template>
|
</template>
|
||||||
|
9
assets/css/main.css
Normal file
9
assets/css/main.css
Normal 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;
|
||||||
|
}
|
BIN
assets/image/pattern/ai_glow.png
Normal file
BIN
assets/image/pattern/ai_glow.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 81 KiB |
BIN
assets/image/pattern/mesh-7.png
Normal file
BIN
assets/image/pattern/mesh-7.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 87 KiB |
38
components/ChatBotMessage.vue
Normal file
38
components/ChatBotMessage.vue
Normal 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>
|
17
components/ChatUserMessage.vue
Normal file
17
components/ChatUserMessage.vue
Normal 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>
|
51
components/PopularInquiries.vue
Normal file
51
components/PopularInquiries.vue
Normal 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
18
layouts/default.vue
Normal 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>
|
@ -1,5 +1,12 @@
|
|||||||
|
import tailwindcss from "@tailwindcss/vite";
|
||||||
|
|
||||||
// https://nuxt.com/docs/api/configuration/nuxt-config
|
// https://nuxt.com/docs/api/configuration/nuxt-config
|
||||||
export default defineNuxtConfig({
|
export default defineNuxtConfig({
|
||||||
compatibilityDate: '2024-11-01',
|
compatibilityDate: "2024-11-01",
|
||||||
devtools: { enabled: true }
|
devtools: { enabled: true },
|
||||||
})
|
modules: ["@nuxt/ui"],
|
||||||
|
css: ["~/assets/css/main.css"],
|
||||||
|
vite: {
|
||||||
|
plugins: [tailwindcss()],
|
||||||
|
},
|
||||||
|
});
|
||||||
|
@ -10,9 +10,14 @@
|
|||||||
"postinstall": "nuxt prepare"
|
"postinstall": "nuxt prepare"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@tailwindcss/vite": "^4.0.14",
|
||||||
"nuxt": "^3.16.0",
|
"nuxt": "^3.16.0",
|
||||||
|
"tailwindcss": "^4.0.14",
|
||||||
"vue": "^3.5.13",
|
"vue": "^3.5.13",
|
||||||
"vue-router": "^4.5.0"
|
"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
78
pages/index.vue
Normal 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 Agent、AI-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
1377
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
1
types/index.ts
Normal file
1
types/index.ts
Normal file
@ -0,0 +1 @@
|
|||||||
|
export type VisitorRole = "stu" | "tea" | "fans";
|
Loading…
Reference in New Issue
Block a user