前端智能旅行项目:Vue3 + TS +cozeAI技术精要

1,249 阅读2分钟

[NexTravel]是一款基于 Vue3+TypeScript 的旅行社交应用,灵感来源于小红书与马蜂窝的混合形态。项目聚焦三大核心场景:

  • 用户系统:JWT鉴权登录 + 个人主页动态管理
  • 内容社区:图文瀑布流 + 地点标记交互
  • 智能搜索:集成 CozeAI 实现自然语言旅行咨询

欢迎查看:项目地址

一、工程化基石:代码规范与协作

1. 代码风格统一方案

  • ESLint:静态代码检查工具

    npm install eslint @typescript-eslint/parser @typescript-eslint/eslint-plugin -D
    

    配置 .eslintrc.js

    module.exports = {
      parser: 'vue-eslint-parser',
      plugins: ['@typescript-eslint'],
      rules: {
        'no-unused-vars': 'error', // 杜绝无用变量
        'vue/multi-word-component-names': 'off' // 允许单文件组件名
      }
    }
    
  • Prettier:自动化代码格式化

    npm install prettier eslint-config-prettier -D
    

    配置 .prettierrc

    {
      "semi": false,
      "singleQuote": true,
      "trailingComma": "none"
    }
    

2. Git 提交规范

.husky/pre-commit 添加自动化处理:

#!/bin/sh
npx lint-staged

配置 lint-staged

{
  "src/**/*.{ts,vue}": [
    "eslint --fix",
    "prettier --write"
  ]
}

二、原子化样式革命:TailwindCSS 深度应用

1. 快速接入流程

npm install -D tailwindcss postcss autoprefixer
npx tailwindcss init -p

配置 tailwind.config.js

module.exports = {
  content: ['./index.html', './src/**/*.{vue,ts}'],
  theme: {
    extend: {
      spacing: {
        '15': '3.75rem' // 自定义间距值
      }
    }
  }
}

2. 实战样式方案

<template>
  <div class="flex flex-col gap-4 p-6">
    <h2 class="text-2xl font-bold text-primary">热门景点</h2>
    <div class="grid grid-cols-2 md:grid-cols-4 gap-4">
      <div 
        v-for="item in list"
        class="bg-white rounded-lg shadow-md hover:shadow-lg transition-shadow"
      >
        <img 
          :src="item.image" 
          class="w-full h-40 object-cover rounded-t-lg"
        >
      </div>
    </div>
  </div>
</template>

三、移动端组件库:Vant 高效集成

1. 自动导入配置

// vite.config.ts
import Components from 'unplugin-vue-components/vite'
import { VantResolver } from '@vant/auto-import-resolver'

export default defineConfig({
  plugins: [
    Components({
      resolvers: [VantResolver()]
    })
  ]
})

2. 典型组件应用

<template>
  <van-popup v-model:show="showPicker" position="bottom">
    <van-picker
      :columns="cities"
      @confirm="handleConfirm"
    />
  </van-popup>
</template>

<script setup lang="ts">
const cities = [
  { text: '北京', value: '110000' },
  { text: '上海', value: '310000' }
]
const showPicker = ref(false)

const handleConfirm = ({ selectedOptions }) => {
  console.log('选中值:', selectedOptions[0].value)
}
</script>

性能优化点

  • 编译时自动导入组件,减少打包体积
  • 配合 vant/es 按需引入样式文件

四、智能交互核心:CozeAI 接入方案

1. API 服务封装

// src/api/coze.ts
import axios from 'axios'

interface Message {
  role: 'user' | 'assistant'
  content: string
}

export const chatWithAI = async (messages: Message[]) => {
  const { data } = await axios.post('https://api.coze.cn/v2/chat', {
    bot_id: import.meta.env.VITE_COZE_BOT_ID,
    messages
  }, {
    headers: {
      Authorization: `Bearer ${import.meta.env.VITE_COZE_KEY}`
    }
  })
  return data.choices[0].message.content
}

2. 前端交互实现

<template>
  <div class="chat-container">
    <div v-for="(msg, index) in messages" :key="index">
      <div :class="['message-bubble', msg.role]">
        {{ msg.content }}
      </div>
    </div>
    <van-field 
      v-model="inputMsg"
      @keyup.enter="handleSend"
    />
  </div>
</template>

<script setup lang="ts">
const messages = ref<Message[]>([])
const inputMsg = ref('')

const handleSend = async () => {
  messages.value.push({ role: 'user', content: inputMsg.value })
  const reply = await chatWithAI(messages.value)
  messages.value.push({ role: 'assistant', content: reply })
  inputMsg.value = ''
}
</script>

关键技术点

  • 环境变量管理:通过 .env 文件保护敏感信息
  • 流式响应处理:使用 fetch + ReadableStream 实现实时对话效果

五、项目质量保障体系

1. 类型安全策略

// src/types/city.ts
export interface City {
  code: string
  name: string
  pinyin: string
  latitude: number
  longitude: number
}

// 组件props验证
defineProps<{
  cities: City[]
  defaultCode?: string
}>()

2. 性能优化指标

  • 图片懒加载:<img v-lazy="url"> 减少首屏压力
  • 组件缓存:<keep-alive> 保留非活跃组件状态
  • 虚拟列表:长列表场景下使用 vue-virtual-scroller
image.png