commit
33c1d32b24
9 changed files with 302 additions and 0 deletions
-
7README.md
-
13index.html
-
20package.json
-
1public/vite.svg
-
165src/App.vue
-
1src/assets/vue.svg
-
9src/main.js
-
79src/style.css
-
7vite.config.js
@ -0,0 +1,7 @@ |
|||
# Vue 3 + Vite |
|||
|
|||
This template should help get you started developing with Vue 3 in Vite. The template uses Vue 3 `<script setup>` SFCs, check out the [script setup docs](https://v3.vuejs.org/api/sfc-script-setup.html#sfc-script-setup) to learn more. |
|||
|
|||
## Recommended IDE Setup |
|||
|
|||
- [VS Code](https://code.visualstudio.com/) + [Vue - Official](https://marketplace.visualstudio.com/items?itemName=Vue.volar) (previously Volar) and disable Vetur |
|||
@ -0,0 +1,13 @@ |
|||
<!doctype html> |
|||
<html lang="en"> |
|||
<head> |
|||
<meta charset="UTF-8" /> |
|||
<link rel="icon" type="image/svg+xml" href="/vite.svg" /> |
|||
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> |
|||
<title>Vite + Vue</title> |
|||
</head> |
|||
<body> |
|||
<div id="app"></div> |
|||
<script type="module" src="/src/main.js"></script> |
|||
</body> |
|||
</html> |
|||
@ -0,0 +1,20 @@ |
|||
{ |
|||
"name": "chatgpt-demo", |
|||
"private": true, |
|||
"version": "0.0.0", |
|||
"type": "module", |
|||
"scripts": { |
|||
"dev": "vite", |
|||
"build": "vite build", |
|||
"preview": "vite preview" |
|||
}, |
|||
"dependencies": { |
|||
"element-plus": "^2.8.7", |
|||
"vue": "^3.4.21" |
|||
}, |
|||
"devDependencies": { |
|||
"@vitejs/plugin-vue": "^5.0.4", |
|||
"axios": "^1.7.7", |
|||
"vite": "^5.2.0" |
|||
} |
|||
} |
|||
@ -0,0 +1 @@ |
|||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="iconify iconify--logos" width="31.88" height="32" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 257"><defs><linearGradient id="IconifyId1813088fe1fbc01fb466" x1="-.828%" x2="57.636%" y1="7.652%" y2="78.411%"><stop offset="0%" stop-color="#41D1FF"></stop><stop offset="100%" stop-color="#BD34FE"></stop></linearGradient><linearGradient id="IconifyId1813088fe1fbc01fb467" x1="43.376%" x2="50.316%" y1="2.242%" y2="89.03%"><stop offset="0%" stop-color="#FFEA83"></stop><stop offset="8.333%" stop-color="#FFDD35"></stop><stop offset="100%" stop-color="#FFA800"></stop></linearGradient></defs><path fill="url(#IconifyId1813088fe1fbc01fb466)" d="M255.153 37.938L134.897 252.976c-2.483 4.44-8.862 4.466-11.382.048L.875 37.958c-2.746-4.814 1.371-10.646 6.827-9.67l120.385 21.517a6.537 6.537 0 0 0 2.322-.004l117.867-21.483c5.438-.991 9.574 4.796 6.877 9.62Z"></path><path fill="url(#IconifyId1813088fe1fbc01fb467)" d="M185.432.063L96.44 17.501a3.268 3.268 0 0 0-2.634 3.014l-5.474 92.456a3.268 3.268 0 0 0 3.997 3.378l24.777-5.718c2.318-.535 4.413 1.507 3.936 3.838l-7.361 36.047c-.495 2.426 1.782 4.5 4.151 3.78l15.304-4.649c2.372-.72 4.652 1.36 4.15 3.788l-11.698 56.621c-.732 3.542 3.979 5.473 5.943 2.437l1.313-2.028l72.516-144.72c1.215-2.423-.88-5.186-3.54-4.672l-25.505 4.922c-2.396.462-4.435-1.77-3.759-4.114l16.646-57.705c.677-2.35-1.37-4.583-3.769-4.113Z"></path></svg> |
|||
@ -0,0 +1,165 @@ |
|||
|
|||
|
|||
<template> |
|||
|
|||
<el-row :gutter="20"> |
|||
<el-col :span="16"> |
|||
|
|||
<el-table :data="tableData" stripe style="width: 100%"> |
|||
<el-table-column prop="bookingNumber" label="#" /> |
|||
<el-table-column prop="name" label="Name" /> |
|||
<el-table-column prop="date" label="Date" /> |
|||
<el-table-column prop="from" label="From" /> |
|||
<el-table-column prop="to" label="To" /> |
|||
<el-table-column prop="bookingStatus" label="Status" > |
|||
<template #default="scope"> |
|||
{{ scope.row.bookingStatus === "CONFIRMED" ? "✅" : "❌"}} |
|||
</template> |
|||
</el-table-column> |
|||
<el-table-column prop="bookingClass" label="Booking class" /> |
|||
<el-table-column label="Operations" fixed="right" width="180" > |
|||
<template #default="scope"> |
|||
<el-button size="small" |
|||
type="primary"> |
|||
更改预定 |
|||
</el-button> |
|||
<el-button |
|||
size="small" |
|||
type="danger"> |
|||
退订 |
|||
</el-button> |
|||
</template> |
|||
</el-table-column> |
|||
</el-table> |
|||
</el-col> |
|||
|
|||
<el-col :span="8" style="background-color: aliceblue;"> |
|||
<div style="height: 500px;overflow: scroll"> |
|||
<el-timeline style="max-width: 100%"> |
|||
<el-timeline-item |
|||
v-for="(activity, index) in activities" |
|||
:key="index" |
|||
:icon="activity.icon" |
|||
:type="activity.type" |
|||
:color="activity.color" |
|||
:size="activity.size" |
|||
:hollow="activity.hollow" |
|||
:timestamp="activity.timestamp" |
|||
> |
|||
{{ activity.content }} |
|||
</el-timeline-item> |
|||
</el-timeline> |
|||
</div> |
|||
<div id="container"> |
|||
<div id="chat"> |
|||
<el-input |
|||
v-model="msg" |
|||
input-style="width: 100%;height:50px" |
|||
:rows="2" |
|||
type="text" |
|||
placeholder="Please input" |
|||
@keydown.enter="sendMsg();" |
|||
/> |
|||
<el-button @click="sendMsg()">发送</el-button> |
|||
</div> |
|||
</div> |
|||
</el-col> |
|||
</el-row> |
|||
|
|||
</template> |
|||
<script lang="ts"> |
|||
import { MoreFilled } from '@element-plus/icons-vue' |
|||
import {ref, onMounted} from "vue"; |
|||
import axios from 'axios'//引入axios |
|||
|
|||
export default { |
|||
setup() { |
|||
const activities = ref([ |
|||
{ |
|||
content: '⭐欢迎来到图灵航空✈!请问有什么可以帮您的?', |
|||
timestamp: new Date().toLocaleDateString() + " " + new Date().toLocaleTimeString(), |
|||
color: '#0bbd87', |
|||
}, |
|||
]); |
|||
const msg = ref(''); |
|||
const tableData = ref([]); |
|||
let count = 2; |
|||
let eventSource; |
|||
|
|||
const sendMsg = () => { |
|||
if (eventSource) { |
|||
eventSource.close(); |
|||
} |
|||
|
|||
activities.value.push( |
|||
{ |
|||
content: `你:${msg.value}`, |
|||
timestamp: new Date().toLocaleDateString() + " " + new Date().toLocaleTimeString(), |
|||
size: 'large', |
|||
type: 'primary', |
|||
icon: MoreFilled, |
|||
}, |
|||
); |
|||
|
|||
activities.value.push( |
|||
{ |
|||
content: 'waiting...', |
|||
timestamp: new Date().toLocaleDateString() + " " + new Date().toLocaleTimeString(), |
|||
color: '#0bbd87', |
|||
}, |
|||
); |
|||
|
|||
// sse: 服务端推送 Server-Sent Events |
|||
eventSource = new EventSource(`http://localhost:8080/ai/generateStreamAsString?message=${msg.value}`); |
|||
msg.value=''; |
|||
eventSource.onmessage = (event) => { |
|||
if (event.data === '[complete]') { |
|||
count = count + 2; |
|||
eventSource.close(); |
|||
getBookings(); // 每次对话完后刷新列表 |
|||
return; |
|||
} |
|||
activities.value[count].content += event.data; |
|||
}; |
|||
eventSource.onopen = (event) => { |
|||
activities.value[count].content = ''; |
|||
}; |
|||
}; |
|||
|
|||
const getBookings = () => { |
|||
axios.get('http://localhost:8080/booking/list') |
|||
.then((response) => { |
|||
debugger; |
|||
tableData.value = response.data; |
|||
}) |
|||
.catch((error) => { |
|||
console.error(error); |
|||
}); |
|||
}; |
|||
|
|||
// Use onMounted to call getBookings when the component is mounted |
|||
onMounted(() => { |
|||
getBookings(); |
|||
}); |
|||
|
|||
return { |
|||
activities, |
|||
msg, |
|||
tableData, |
|||
sendMsg, |
|||
getBookings, |
|||
}; |
|||
}, |
|||
}; |
|||
</script> |
|||
<style scoped> |
|||
* { |
|||
margin: 0; |
|||
padding: 0; |
|||
} |
|||
#chat button{ |
|||
position: absolute; |
|||
margin-left: -60px; |
|||
margin-top: 19px; |
|||
} |
|||
</style> |
|||
@ -0,0 +1 @@ |
|||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="iconify iconify--logos" width="37.07" height="36" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 198"><path fill="#41B883" d="M204.8 0H256L128 220.8L0 0h97.92L128 51.2L157.44 0h47.36Z"></path><path fill="#41B883" d="m0 0l128 220.8L256 0h-51.2L128 132.48L50.56 0H0Z"></path><path fill="#35495E" d="M50.56 0L128 133.12L204.8 0h-47.36L128 51.2L97.92 0H50.56Z"></path></svg> |
|||
@ -0,0 +1,9 @@ |
|||
import { createApp } from 'vue' |
|||
//import './style.css'
|
|||
import App from './App.vue' |
|||
import ElementPlus from 'element-plus' //全局引入
|
|||
import 'element-plus/dist/index.css' |
|||
|
|||
const app=createApp(App); |
|||
app.use(ElementPlus) |
|||
app.mount('#app') |
|||
@ -0,0 +1,79 @@ |
|||
:root { |
|||
font-family: Inter, system-ui, Avenir, Helvetica, Arial, sans-serif; |
|||
line-height: 1.5; |
|||
font-weight: 400; |
|||
|
|||
color-scheme: light dark; |
|||
color: rgba(255, 255, 255, 0.87); |
|||
background-color: #242424; |
|||
|
|||
font-synthesis: none; |
|||
text-rendering: optimizeLegibility; |
|||
-webkit-font-smoothing: antialiased; |
|||
-moz-osx-font-smoothing: grayscale; |
|||
} |
|||
|
|||
a { |
|||
font-weight: 500; |
|||
color: #646cff; |
|||
text-decoration: inherit; |
|||
} |
|||
a:hover { |
|||
color: #535bf2; |
|||
} |
|||
|
|||
body { |
|||
margin: 0; |
|||
display: flex; |
|||
place-items: center; |
|||
min-width: 320px; |
|||
min-height: 100vh; |
|||
} |
|||
|
|||
h1 { |
|||
font-size: 3.2em; |
|||
line-height: 1.1; |
|||
} |
|||
|
|||
button { |
|||
border-radius: 8px; |
|||
border: 1px solid transparent; |
|||
padding: 0.6em 1.2em; |
|||
font-size: 1em; |
|||
font-weight: 500; |
|||
font-family: inherit; |
|||
background-color: #1a1a1a; |
|||
cursor: pointer; |
|||
transition: border-color 0.25s; |
|||
} |
|||
button:hover { |
|||
border-color: #646cff; |
|||
} |
|||
button:focus, |
|||
button:focus-visible { |
|||
outline: 4px auto -webkit-focus-ring-color; |
|||
} |
|||
|
|||
.card { |
|||
padding: 2em; |
|||
} |
|||
|
|||
#app { |
|||
max-width: 1280px; |
|||
margin: 0 auto; |
|||
padding: 2rem; |
|||
text-align: center; |
|||
} |
|||
|
|||
@media (prefers-color-scheme: light) { |
|||
:root { |
|||
color: #213547; |
|||
background-color: #ffffff; |
|||
} |
|||
a:hover { |
|||
color: #747bff; |
|||
} |
|||
button { |
|||
background-color: #f9f9f9; |
|||
} |
|||
} |
|||
@ -0,0 +1,7 @@ |
|||
import { defineConfig } from 'vite' |
|||
import vue from '@vitejs/plugin-vue' |
|||
|
|||
// https://vitejs.dev/config/
|
|||
export default defineConfig({ |
|||
plugins: [vue()], |
|||
}) |
|||
Write
Preview
Loading…
Cancel
Save
Reference in new issue