[福游宝——AI智能旅游信息查询平台]全栈AI项目-阶段二:聊天咨询业务组件开发
简言
本项目旨在构建一个以AI智能体
为核心的福建省旅游信息查询系统,聚焦景点推荐、路线规划、交通天气查询等功能,为游客提供智能化、便捷化的旅游信息服务。项目采用前后端分离架构,前端基于Vite + TypeScript + Vue3技术栈,搭配轻量级移动端UI库Vant实现高效开发与响应式布局;后端采用SpringBoot框架构建RESTful API,通过MySQL进行数据存储与管理,将集成DeepSeekAI
实现自然语言处理与智能推荐能力。
项目地址
- gitCode平台:https://gitcode.com/Var_ya/varWisdomModelBody
脚手架明细表
前端:
技术 | 版本 | 官网地址 |
---|---|---|
Vite | ^6.2.0 | https://cn.vitejs.dev/ |
node.js | ^22.14.0 | https://nodejs.org/zh-cn |
npm | ^10.9.2 | https://www.npmjs.com/ |
vue-router | ^4.5.0 | https://router.vuejs.org/zh/ |
Vue3 | ^3.5.13 | https://vuejs.org/ |
Vant | ^4.9.18 | https://vant-ui.github.io/vant/#/zh-CN |
postcss | ^8.5.3 | https://github.com/cuth/postcss-pxtorem |
postcss-pxtorem | ^6.1.0 | |
待补充… |
当前进度预览
- 已完成聊天咨询页各个组件开发:
- 标题组件
- 默认问题组件
- 多模态类型布局组件
- 自定义加载组件
- 火车票查询组件
- 天气查询组件
- 旅游套餐查询组件
九、聊天咨询界面顶部布局
新增组件:
src\components\foreword\index.vue
修改页面:
src\page\home\index.vue
- 实现效果图
- foreword组件内容
<template>
<div class="main-header" >
<div class="main-header-left">
<p class="candy-text handwriting-effect "><span style="font-size: 18px;">🍃</span><i>Hi</i>~我是福游宝<span class="cute-bubble">🌱</span></p>
<p class="tip gradient-text cute-bubble">🌿你的专属旅游助手,可以帮助你规划行程和解答出游问题哦!</p>
</div>
<div class="main-headr-right">
<img src="@/assets/foreword.jpeg" alt="">
</div>
</div>
</template>
<script lang="ts">
</script>
<style lang="less" scoped>
.main-header{
display: grid;
grid-template-columns: repeat(2,1fr);
padding:30px 0;
img{
width:100%;
object-fit: fill;
border-radius: 50%;
overflow: hidden;
box-shadow: 1px 1px 0 #e8f5e9,
2px 2px 4px rgba(46, 204, 113, 0.3),
0 0 8px rgba(76, 175, 80, 0.3);
}
.name{
font-size: 20px;
color: #0f9380;
font-style: italic;
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
}
.tip{
font-weight: bold;
line-height: 2;
text-indent: 2em;
}
}
// 修改后的绿色主题可爱字体样式
.cute-text-base {
font-family: cursive;
font-weight: 600;
letter-spacing: 0.08em;
line-height: 1.4;
color: #28a745; // 主绿色
}
// 青苹果泡泡字
.cute-bubble {
.cute-text-base();
text-shadow:
1px 1px 0 #e8f5e9,
2px 2px 4px rgba(46, 204, 113, 0.3),
0 0 8px rgba(76, 175, 80, 0.3);
}
// 森林立体字
.candy-text {
.cute-text-base();
text-shadow:
0 1px 0 #e8f5e9,
0 2px 0 #c8e6c9,
0 3px 0 #a5d6a7,
0 4px 8px rgba(46, 204, 113, 0.4);
}
// 渐变绿叶效果
.gradient-text {
background: linear-gradient(45deg, #34d399, #10b981);
-webkit-background-clip: text;
background-clip: text;
-webkit-text-fill-color: transparent;
}
// 手写装饰线(改为青绿色)
.handwriting-effect::before {
background: repeating-linear-gradient(
90deg,
transparent,
transparent 3px,
#66bb6a 3px,
#66bb6a 6px
);
}
</style>
- 将foreword组件引入到聊天咨询页面
<template>
<!-- 标题栏 -->
<!-- <van-nav-bar
title=""
/> -->
<van-nav-bar title="福游宝" >
<template #right>
<van-icon name="ellipsis" size="18"/>
</template>
</van-nav-bar>
<div class="content">
<!-- 头部信息 -->
<foreWord></foreWord>
</div>
</template>
<script setup lang="ts">
import foreWord from"@/components/foreword/index.vue"
</script>
<style lang="less" scoped>
.content{
padding:0 15px;
}
</style>
十、默认问题区域布局
新增组件:
src\components\defaultQuestion\index.vue
修改页面:
src\page\home\index.vue
- 实现效果图
- defaultquestion组件内容
<!-- 默认问题 -->
<template>
<div class="default-question">
<div class="customer-service">
<img src="@/assets/kefu.png" alt="">
<p>福宝</p>
</div>
<div class="message-content">
<span class="message-tip">你可以这样问我</span>
<div class="message-list" v-for="(item,index) in 5" :key="index">
<img src="@/assets/message.png" alt="">
<p>你好</p>
</div>
</div>
<div class="change-question">
<img src="@/assets/change.png" alt="">
<span>换一换</span>
</div>
</div>
</template>
<script lang="ts">
</script>
<style lang="less" scoped>
.default-question{
.customer-service{
display: flex;
align-items: center;
img{
width:30px;
height: 30px;
object-fit: cover;
}
p{
font-size: 14px;
padding-left: 10px;
}
}
.message-content{
background: white;
border-radius: 10px;
border-top-left-radius: 0px;
margin-top: 20px;
padding:10px;
.message-tip{
display: inline-block;
margin: 10px 0px ;
font-size: 14px;
}
.message-list{
display: flex;
align-items: center;
padding:4px 7px;
border-radius: 10px;
background: #f3f8f9;
margin-bottom: 10px;
img{
width:25px;
height: 25px;
object-fit: cover;
}
p{
font-size: 14px;
padding-left: 10px;
}
}
}
.change-question{
margin-top: 10px;
background: #c0d5d0;
border-radius: 5px;
padding:5px;
display: inline-flex;
img{
width:20px;
height:20px;
object-fit: cover;
margin-right: 10px;
}
span{
font-size: 14px;
line-height: 20px;
color:white;
}
}
}
</style>
- defaultquestion组件引入聊天咨询页
<template>
<!-- 标题栏 -->
<!-- <van-nav-bar
title=""
/> -->
<van-nav-bar title="福游宝" >
<template #right>
<van-icon name="ellipsis" size="18"/>
</template>
</van-nav-bar>
<div class="content">
<!-- 头部信息 -->
<foreWord></foreWord>
<!-- 默认问题 -->
<defaultQuestion></defaultQuestion>
</div>
</template>
<script setup lang="ts">
import foreWord from"@/components/foreword/index.vue"
import defaultQuestion from "@/components/defaultQuestion/index.vue"
</script>
<style lang="less" scoped>
.content{
padding:0 15px;
}
</style>
十一、多模态类型对话布局
新增组件:
src\components\charmessage\inde.vue
修改页面:
src\page\home\index.vue
- 实现效果图
- vant图片组件引入
import { createApp } from 'vue'
// import './style.css'
import App from './App.vue'
// 动态改变字体大小
import "amfe-flexible"
// 引入路由实例
import router from"./router/index"
const app = createApp(App)
// 注入路由
app.use(router)
// vant组件样式
import 'vant/lib/index.css';
// vant组件
import { NavBar,Icon ,Button} from 'vant';
// 标题栏
app.use(NavBar);
//icon图标
app.use(Icon);
// 按钮
app.use(Button);
// 图片
import { Image as VanImage } from 'vant';
app.use(VanImage);
app.mount('#app')
- chatmessage组件内容
<!--AI聊天 -->
<template>
<div class="chat-message">
<div class="user-text-message">
<p>用户发送的问题</p>
</div>
<div class="user-image-message">
<!-- 用户发送图片,使用vant组件 -->
<van-image width="100px" height="100px" fit="cover" radius="5"
src="https://fastly.jsdelivr.net/npm/@vant/assets/cat.jpeg" />
</div>
<!-- AI回复的内容 -->
<!-- 文字内容 -->
<div class="ai-message">
<div class="customer-service">
<img src="@/assets/kefu.png" alt="">
<span> 福宝</span>
</div>
<p>
本项目旨在构建一个以AI智能体为核心的福建省旅游信息查询系统,聚焦景点推荐、路线规划、交通天气查询等功能,为游客提供智能化、便捷化的旅游信息服务。项目采用前后端分离架构,前端基于Vite + TypeScript + Vue3技术栈,搭配轻量级移动端UI库Vant实现高效开发与响应式布局;后端采用SpringBoot框架构建RESTful API,通过MySQL进行数据存储与管理,将集成DeepSeekAI实现自然语言处理与智能推荐能力。
</p>
</div>
</div>
</template>
<script lang="ts">
</script>
<style lang="less" scoped>
.chat-message {
display: flex;
// 上下排序
flex-direction: column;
margin-bottom: 10px;
.user-text-message {
margin-top: 15px;
align-self: flex-end;
max-width: 70%;
opacity: 0;
transform: translateY(20px);
animation: fadeUp 0.2s ease-in-out forwards;
p {
font-size: 16px;
line-height: 1.5;
background: #15c998;
border-radius: 5px;
border-top-right-radius: 0px;
padding:5px;
color: white;
}
}
@keyframes fadeUp {
0%{
opacity: 0;
transform: translateY(20px);
}
100%{
opacity: 1;
transform: translateY(0px);
}
}
.user-image-message{
align-self: flex-end;
margin-top: 15px;
}
.ai-message{
margin-top: 15px;
.customer-service{
display: flex;
align-items: center;
margin-bottom: 10px;
img{
width:30px;
height: 30px;
object-fit: cover;
}
span{
font-size: 16px;
padding-left: 10px;
}
}
p{
padding:5px;
font-size: 16px;
line-height: 1.5;
background: white;
border-radius: 5px;
border-top-left-radius: 0px;
color: rgb(117, 114, 114);
}
}
}
</style>
- chatmessage组件引入到聊天咨询界面
<template>
<!-- 标题栏 -->
<!-- <van-nav-bar
title=""
/> -->
<van-nav-bar title="福游宝" >
<template #right>
<van-icon name="ellipsis" size="18"/>
</template>
</van-nav-bar>
<div class="content">
<!-- 头部信息 -->
<foreWord></foreWord>
<!-- 默认问题 -->
<defaultQuestion></defaultQuestion>
<!-- 聊天内容 -->
<chatMessage/>
</div>
</template>
<script setup lang="ts">
import foreWord from"@/components/foreword/index.vue"
import defaultQuestion from "@/components/defaultQuestion/index.vue"
import chatMessage from "@/components/charmessage/inde.vue"
</script>
<style lang="less" scoped>
.content{
padding:0 15px;
}
</style>
十二、自定义加载组件
新增组件:
src\components\loading\index.vue
修改页面 :
src\components\charmessage\inde.vue
- 实现效果图
- loading组件内容
<template>
<div class="shape-circle">
<span class="circle"></span>
<span class="circle"></span>
<span class="circle"></span>
</div>
</template>
<script lang="ts">
</script>
<style lang="less" scoped>
.shape-circle{
display: flex;
align-items: center;
.circle{
width:7px;
height: 7px;
border-radius: 50%;
background: #777a8d;
margin: 0 4px;
animation: colorChange 1s linear infinite;
}
/* 帧 */
@keyframes colorChange {
0%{
background-color: #ffcc00;
}
33%{
background-color: #ffcc00;
}
66.67%{
background-color: #ffcc00;
}
}
.circle:nth-child(1){
animation-delay: 0s;
}
.circle:nth-child(2){
animation-delay: 0.33s;
}
.circle:nth-child(3){
animation-delay: 0.67s;
}
}
</style>>
- chatmessage父组件引入loading组件
<!--AI聊天 -->
<template>
<!-- ... -->
<!-- AI回复的内容 -->
<div class="ai-message">
<div class="mark-text" >
<loading></loading>
</div>
</div>
</div>
</template>
<script setup lang="ts">
import loading from"@/components/loading/index.vue"
</script>
十三、火车票查询组件布局
新增组件:
src\components\trainticket\index.vue
修改页面:
src\components\charmessage\inde.vue
- 实现效果图
- trainticket组件内容
<!-- 车票查询 -->
<template>
<div class="train-ticket">
<div>
<p class="query-time">9:18</p>
<p class="station-name">泉州</p>
</div>
<div class="train-run-number">
<p>2小时2分</p>
<p>D6666</p>
</div>
<div>
<p class="query-time">10:20</p>
<p class="station-name">福州</p>
</div>
<div>
<p class="product-price">¥86</p>
</div>
</div>
<div class="train-ticket">
<div>
<p class="query-time">9:18</p>
<p class="station-name">泉州</p>
</div>
<div class="train-run-number">
<p>2小时2分</p>
<p>D6666</p>
</div>
<div>
<p class="query-time">10:20</p>
<p class="station-name">福州</p>
</div>
<div>
<p class="product-price">¥86</p>
</div>
</div>
</template>
<script setup lang="ts">
</script>
<style lang="less" scoped>
.train-ticket{
border-bottom: 1px solid rgb(228, 222, 222);
background: white;
display: flex;
align-items: center;
justify-content: space-around;
padding: 7px 0px;
.product-price{
color: #0a6f4d;
}
.query-time,.station-name{
font-weight: bold;
font-size: 12px;
}
.query-time{
font-size: 16px;
}
.train-run-number{
p{
font-size: 12px;
color: #9ca1a0;
}
}
}
</style>
- trainticket组件引入到chatmessage父组件中
<!--AI聊天 -->
<template>
<div class="chat-message">
<!-- AI回复的内容 -->
<div class="ai-message">
<!-- 头像 -->
<!-- 车票查询 -->
<trainTicket></trainTicket>
</div>
</div>
</template>
<script setup lang="ts">
import trainTicket from "@/components/trainticket/index.vue"
</script>
十四、天气查询组件布局
新增组件:
src\components\weather\index.vue
修改页面:
src\components\charmessage\inde.vue
- 实现效果图预览
- weather组件内容
<!-- 天气查询 -->
<template>
<div class="weather-content">
<div class="weather-item">
<!-- 日期 -->
<div class="day-time">05/26</div>
<!-- 状态 -->
<div class="day-weather">
<!--
src\assets\weather\qingtian.png
-->
<img src="../../assets/weather/qingtian.png" alt="">
<p>晴</p>
</div>
<!-- 摄氏度 -->
<div class="day-limit">10-20℃</div>
</div>
<div class="weather-item">
<!-- 日期 -->
<div class="day-time">05/26</div>
<!-- 状态 -->
<div class="day-weather">
<!--
src\assets\weather\qingtian.png
-->
<img src="../../assets/weather/qingtian.png" alt="">
<p>多云</p>
</div>
<!-- 摄氏度 -->
<div class="day-limit">10-20℃</div>
</div>
</div>
</template>
<script lang="ts">
</script>
<style lang="less" scoped>
.weather-content {
background: linear-gradient(to bottom left, #ffffff, #48adff);
margin-top: 10px;
margin-bottom: 10px;
font-size: 14px;
.weather-item{
display: flex;
align-items: center;
justify-content: space-around;
padding:7px 0px;
.day-time{
flex:1;
text-align: center;
}
.day-weather{
flex: 1;
display: flex;
align-items: center ;
img{
width:20px;
margin-right: 5px;
height: 20px;
}
p{
font-size: 14px;
}
}
.day-limit{
flex: 1;
}
}
}
</style>
- weather组件引入到chatmessage父组件中
<!--AI聊天 -->
<template>
<div class="chat-message">
<!-- AI回复的内容 -->
<!-- 天气查询 -->
<weather></weather>
</div>
</div>
</template>
<script setup lang="ts">
import weather from "@/components/weather/index.vue"
</script>
十五、搜索商品组件布局
新增组件:src\components\searchgood\index.vue
修改页面:src\components\charmessage\inde.vue
修改页面:index.html
- 实现效果图预览
- 全局样式写入
- index.html文件
<style>
/* 文本超过两行时,隐藏多余部分,并以省略号代替 */
.text-show{
overflow: hidden;
display: -webkit-box;
text-overflow: ellipsis;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
}
</style>
- searchgood组件内容
<!-- 搜索商品 -->
<template>
<div class="goods-content">
<p class="title">为您推荐以下相关的旅游套餐:</p>
<!-- 旅游套餐列表 -->
<div class="goods-list">
<!-- 单个商品 -->
<div class="goods-item">
<img src="../../assets/gu.jpg" alt="">
<p class="goods-title text-show ">2025厦门,鹭岛漫游×山海文艺:厦门五天四夜全攻略</p>
<p class="goods-price">¥1233.3</p>
</div>
<div class="goods-item">
<img src="../../assets/gu.jpg" alt="">
<p class="goods-title text-show ">2025厦门,鹭岛漫游×山海文艺:厦门五天四夜全攻略</p>
<p class="goods-price">¥1233.3</p>
</div>
<div class="goods-item">
<img src="../../assets/gu.jpg" alt="">
<p class="goods-title text-show ">2025厦门,鹭岛漫游×山海文艺:厦门五天四夜全攻略</p>
<p class="goods-price">¥1233.3</p>
</div>
</div>
</div>
</template>
<script setup lang="ts">
</script>
<style lang="less" scoped>
.goods-content{
padding-top: 2px;
padding-bottom: 2px;
background: white;
border-radius: 5px;
.title{
color:rgb(216, 166, 245);
font-weight: bold;
margin-top: 4px;
margin-left: 4px;
}
.goods-list{
display: flex;
// x轴溢出
overflow-x: auto;
margin: 5px 0px;
.goods-item{
padding:6px;
background: #f3f3f3;
border-radius: 4px;
display: flex;
// 垂直布局
flex-direction: column;
margin: 0 4px;
width: 33%;
flex-shrink: 0;
img{
width:100%;
border-radius: 4px;
height: 130px;
object-fit: cover;
margin-bottom: 4px;
}
.goods-title{
font-size: 16px;
font-weight: bold;
margin-bottom: 4px;
}
.goods-price{
margin-top:auto;
font-size: 14px;
color: red;
}
}
}
}
</style>
- searchgood组件引入到chatmessage父组件中
<!--AI聊天 -->
<template>
<div class="chat-message">
<!-- AI回复的内容 -->
<!-- 搜索商品 -->
<searchgood></searchgood>
</div>
</div>
</template>
<script setup lang="ts">
import searchgood from "@/components/searchgood/index.vue"
</script>