Merge branch 'master' of bdgit.educoder.net:mwxbgi697/softegg

master
zhanglinhao 1 year ago
commit db3b54eac6

@ -1,23 +1,30 @@
.DS_Store
node_modules
/dist
# local env files
.env.local
.env.*.local
# Log files
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
lerna-debug.log*
node_modules
.DS_Store
dist
dist-ssr
coverage
*.local
/cypress/videos/
/cypress/screenshots/
# Editor directories and files
.vscode/*
!.vscode/extensions.json
.idea
.vscode
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?
*.tsbuildinfo

@ -1,43 +1,29 @@
## GoEasy Websocket Vue3 HelloWorld示例运行步骤
# walktofree
### 免费获取appkey
1. 访问[GoEasy官网](https://www.goeasy.io)进行注册
2. 登陆后,创建一个应用
3. 进入应用详情即可看到自己的appkey
This template should help get you started developing with Vue 3 in Vite.
### 替换appkey
打开main.js找到初始化GoEasy的地方将appkey替换成您应用的common key
## Recommended IDE Setup
### 运行步骤
[VSCode](https://code.visualstudio.com/) + [Volar](https://marketplace.visualstudio.com/items?itemName=Vue.volar) (and disable Vetur).
将目录切换到helloworld/web-vue3/
## Customize configuration
##### 安装依赖
node版本要求16及以上
```
npm ci
```
See [Vite Configuration Reference](https://vitejs.dev/config/).
##### 运行服务
## Project Setup
```
npm run serve
```sh
npm install
```
### Compile and Hot-Reload for Development
### 体验
建议可以同时运行在多个浏览器窗口,体验多个客户端之间互动。
```sh
npm run dev
```
### 体验服务端发送
可以用Postman或curl发送消息到GoEasy体验服务端发送消息到客户端。
### Compile and Minify for Production
````shell
curl -X POST https://rest-hz.goeasy.io/v2/pubsub/publish \
-H "Content-Type: application/json" \
-d "{
'appkey':'您的appkey',
'channel':'my_channel',
'content':'Hello, GoEasy!'
}"
````
```sh
npm run build
```

@ -0,0 +1,13 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<link rel="icon" href="/favicon.ico">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Vite App</title>
</head>
<body>
<div id="app"></div>
<script type="module" src="/src/main.js"></script>
</body>
</html>

@ -1,19 +1,8 @@
{
"compilerOptions": {
"target": "es5",
"module": "esnext",
"baseUrl": "./",
"moduleResolution": "node",
"paths": {
"@/*": [
"src/*"
]
},
"lib": [
"esnext",
"dom",
"dom.iterable",
"scripthost"
]
}
"@/*": ["./src/*"]
}
},
"exclude": ["node_modules", "dist"]
}

File diff suppressed because it is too large Load Diff

@ -1,25 +1,27 @@
{
"name": "web",
"version": "0.1.0",
"name": "walktofree",
"version": "0.0.0",
"private": true,
"type": "module",
"scripts": {
"serve": "vue-cli-service serve",
"build": "vue-cli-service build"
"dev": "vite",
"build": "vite build",
"preview": "vite preview"
},
"dependencies": {
"core-js": "^3.8.3",
"goeasy": "^2.12.4",
"vue": "^3.2.13",
"vue-router": "^4.0.3"
"@element-plus/icons-vue": "^2.3.1",
"@vuepic/vue-datepicker": "^8.6.0",
"axios": "^1.6.8",
"echarts": "^5.5.1",
"element-china-area-data": "^6.1.0",
"element-plus": "^2.7.3",
"sass": "^1.77.6",
"vue": "^3.4.27",
"vue-router": "^4.3.2"
},
"devDependencies": {
"@vue/cli-plugin-babel": "~5.0.0",
"@vue/cli-service": "~5.0.0"
},
"browserslist": [
"> 1%",
"last 2 versions",
"not dead",
"not ie 11"
]
"@vitejs/plugin-vue": "^5.0.4",
"@vue/cli-service": "^5.0.8",
"vite": "^5.2.8"
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.9 KiB

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 208 KiB

@ -17,4 +17,8 @@ export default {
text-align: center;
margin-top: 20px;
}
*{
padding: 0;
margin: 0;
}
</style>

@ -0,0 +1,140 @@
<template>
<div class="layout-container">
<div class="header" :style="{ backgroundColor: headerColor, height: headerHeight}">
<div class="header-content">
<div class="main-title">FreeToGo 自由同行-众包导游</div>
<h1 class="sub-title">{{ title }}</h1> <!-- 一级标题 -->
</div>
</div>
<!-- 导航栏使用 position: fixed 以确保它固定在页面的最左侧 -->
<nav class="navbar" :style="{ backgroundColor: headerColor, width: navWidth, position: 'fixed', top: '80px', height: 'calc(100vh - 80px)', left: '0' }">
<ul>
<li v-for="(link, index) in links" :key="index">
<router-link :to="link.path" class="nav-link">{{ link.name }}</router-link>
</li>
</ul>
</nav>
<!-- 内容区域使用 margin-left 来保证不被导航栏覆盖 -->
<div class="content" :style="{ marginLeft: navWidth, paddingTop: headerHeight }">
<slot></slot> <!-- 插槽用于插入不同页面的主体内容 -->
</div>
</div>
</template>
<script>
export default {
name: 'Layout',
props: {
title: {
type: String,
default: '页面标题'
},
links: {
type: Array,
default: () => []
},
headerColor: {
type: String,
default: 'gray' // CSS
},
navWidth: {
type: String,
default: '200px' //
},
headerHeight: {
type: String,
default: '80px' //
}
}
}
</script>
<style scoped>
:root {
--header-height: 80px;
--nav-width: 200px;
}
.layout-container {
display: flex;
flex-direction: column;
height: 100vh;
overflow: hidden;
}
.header {
position: fixed;
top: 0;
left: 0;
right: 0;
z-index: 10;
background-image: url('../data/picture/loginBackground.jpg'); /* 替换为标题栏背景图片的URL */
background-size: cover;
background-position: center;
background-repeat: no-repeat;
}
.header-content {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
height: var(--header-height);
}
.main-title {
margin: 0;
font-size: 24px;
color: black;
}
.sub-title {
margin: 0;
font-size: 16px;
color: black;
}
.navbar {
position: fixed;
top: var(--header-height);
left: 0;
bottom: 0;
width: var(--nav-width);
z-index: 5;
padding: 10px 0;
list-style-type: none;
overflow-y: auto;
background-image: url('../data/picture/loginBackground.jpg'); /* 替换为导航栏背景图片的URL */
background-size: cover;
background-position: center;
background-repeat: no-repeat;
}
.navbar li {
padding: 10px 0;
}
.nav-link {
color: white;
text-decoration: none;
display: block;
padding: 5px 15px;
transition: background-color 0.3s ease;
}
.nav-link:hover, .nav-link.router-link-active {
background-color: #333;
}
.content {
flex-grow: 1;
padding: 20px;
overflow-y: auto;
margin-left: var(--nav-width);
padding-top: var(--header-height);
background-image: url('../data/picture/mainBackground.jpg'); /* 替换为内容区域背景图片的URL */
background-size: cover;
background-position: center;
background-repeat: no-repeat;
}
</style>

@ -0,0 +1,118 @@
<template>
<div>
<div
ref="chinaMap"
style="height: 700px;border: solid 1px red;width: 100%;background: #ffffff;"
>
地图1
</div>
</div>
</template>
<script lang="ts" setup>
import * as echarts from 'echarts'
import chinaJSON from '../data/china.json'
import { onMounted, ref } from 'vue'
const chinaMap = ref()
onMounted(() => {
drawChina()
})
let regions = [
{
name: '新疆维吾尔自治区',
itemStyle: {
areaColor: '#374ba4',
opacity: 1,
},
},
{
name: '四川省',
itemStyle: {
areaColor: '#fe9b45',
opacity: 1,
},
},
{
name: '陕西省',
itemStyle: {
areaColor: '#fd691b',
opacity: 1,
},
},
{
name: '黑龙江省',
itemStyle: {
areaColor: '#ffc556',
opacity: 1,
},
},
]
let scatter = [
{ name: '云南', value: [102.710002, 25.045806, 9] },
]
function drawChina() {
var myChart = echarts.init(chinaMap.value)
echarts.registerMap('china', chinaJSON) //
var option = {
geo: {
map: 'china',
roam: true, //
zoom: 1, //
//
scaleLimit: {
min: 1, //
max: 2, //
},
//
center: [115.97, 29.71],
//
regions: regions,
itemStyle: {
areaColor: '#00ff00',
color: 'red',
borderColor: '#232652',
borderWidth: 2,
},
//
emphasis: {
itemStyle: {
areaColor: '#1af9e5',
color: '#fff',
},
},
},
//
series: {
type: 'effectScatter',
coordinateSystem: 'geo',
data: scatter,
showEffectOn: 'render',
rippleEffect: {
//
brushType: 'stroke', // 'stroke' 'fill'
},
hoverAnimation: true, // hover
label: {
//
normal: {
formatter: '{b}',
position: 'right',
show: true,
},
},
itemStyle: {
//normal emphasis
normal: {
color: '#ffffff', //
shadowBlur: 10,
shadowColor: 20,
fontSize: '12px',
},
},
zlevel: 1,
},
}
myChart.setOption(option)
}
</script>

@ -32,7 +32,7 @@ const gotoRegisterGuide = () => {
}
const isGuide = () => {
axios.get(`http://192.168.243.35:9000/users/isGuide?phone=${sessionStorage.getItem('phone')}`)
axios.get(`/serve/users/isGuide?phone=${sessionStorage.getItem('phone')}`)
.then(response => {
if (response.data == true){
router.push('/addServe')

@ -0,0 +1,126 @@
<template>
<div>
<div
ref="chinaMap"
style="height: 700px;border: solid 1px red;width: 100%;background: #b4b8b9;"
>
地图1
</div>
</div>
</template>
<script lang="ts" setup>
import * as echarts from 'echarts'
import chinaJSON from '../data/china.json'
import { onMounted, ref } from 'vue'
import axios from 'axios'
const chinaMap = ref()
let myChart: any = null
onMounted(() => {
fetchData()
})
async function fetchData() {
try {
const response = await axios.get('/serve/HeatMap/guideServiceHeatMapRegister')
const data = response.data
drawChina(data)
} catch (error) {
console.error('Failed to fetch data:', error)
}
}
function drawChina(provinceData: any) {
if (myChart) {
myChart.dispose() //
}
myChart = echarts.init(chinaMap.value)
echarts.registerMap('china', chinaJSON)
const regions = provinceData.map((item: any) => ({
name: item.name,
itemStyle: {
areaColor: getColorByPopulation(item.data),
opacity: 1,
},
}))
const option = {
geo: {
map: 'china',
roam: true, //
zoom: 1, //
//
scaleLimit: {
min: 1, //
max: 2, //
},
//
center: [115.97, 29.71],
//
regions: regions,
itemStyle: {
areaColor: '#28a7a3',
color: 'red',
borderColor: '#232652',
borderWidth: 2,
},
//
emphasis: {
itemStyle: {
areaColor: '#1af9e5',
color: '#fff',
},
},
},
//
series: {
type: 'effectScatter',
coordinateSystem: 'geo',
showEffectOn: 'render',
rippleEffect: {
//
brushType: 'stroke', // 'stroke' 'fill'
},
hoverAnimation: true, // hover
label: {
//
normal: {
formatter: '{b}',
position: 'right',
show: true,
},
},
itemStyle: {
//normal emphasis
normal: {
color: '#ffffff', //
shadowBlur: 10,
shadowColor: 20,
fontSize: '12px',
},
},
zlevel: 1,
},
}
myChart.setOption(option)
}
function getColorByPopulation(population: number): string {
//
const minPopulation = 0;
const maxPopulation = 10; // 1亿
const minColor = [173, 216, 230]; //
const maxColor = [255, 0, 0]; //
// 线
const ratio = (population - minPopulation) / (maxPopulation - minPopulation);
const r = Math.floor(minColor[0] + (maxColor[0] - minColor[0]) * ratio);
const g = Math.floor(minColor[1] + (maxColor[1] - minColor[1]) * ratio);
const b = Math.floor(minColor[2] + (maxColor[2] - minColor[2]) * ratio);
return `rgb(${r},${g},${b})`;
}
</script>

@ -0,0 +1,45 @@
<script setup lang="ts">
import { ref, watchEffect } from 'vue'
import { format } from 'date-fns'
const startDateValue = ref(format(new Date(), 'yyyy-MM-dd'))
const endDateValue = ref(format(new Date(), 'yyyy-MM-dd'))
watchEffect(() => {
console.log('startDateValue:', startDateValue.value)
console.log('endDateValue:', endDateValue.value)
})
</script>
<template>
<VueDatePicker
placeholder="请选择预计出发日期"
:min-date="new Date()"
format="yyyy-MM-dd"
v-model="startDateValue" />
<VueDatePicker
placeholder="请选择预计返回日期"
:min-date="new Date()"
format="yyyy-MM-dd"
v-model="endDateValue" />
</template>
<script setup lang="ts">
import { ref, watchEffect } from 'vue'
import { format } from 'date-fns'
const startDateValue = ref(format(new Date(), 'yyyy-MM-dd'))
const endDateValue = ref(format(new Date(), 'yyyy-MM-dd'))
watchEffect(() => {
console.log('startDateValue:', startDateValue.value)
console.log('endDateValue:', endDateValue.value)
})
</script>
<template>
<VueDatePicker
placeholder="请选择预计出发日期"
:min-date="new Date()"
format="yyyy-MM-dd"
v-model="startDateValue" />
<VueDatePicker
placeholder="请选择预计返回日期"
:min-date="new Date()"
format="yyyy-MM-dd"
v-model="endDateValue" />
</template>

@ -1,32 +1,76 @@
<script>
export default {
name: 'return',
methods: {
gotohome() {
this.$router.push('/home');
},
}
}
</script>
<template>
<div class="return">
<button class="return-button" @click="gotohome()"></button>
</div>
<div style="height:100vh;width:100%;">
<!-- 标题栏 -->
<div class="header" style="height: 11.11%;">
<h1>FreeToGo 自由同行-众包导游</h1>
</div>
<!-- 导航栏 -->
<aside class="sidebar" style="position: absolute; top: 11.11%; height: 88.89%;">
<!-- ...导航栏的其余部分... -->
</aside>
<!-- 主内容区域 -->
<div class="main-content" style="margin-left: 11.11%; height: 88.88%;">
<!-- 你的主要内容 -->
</div>
</div>
</template>
<style>.return-button {
/* 定义返回按钮的样式 */
position: fixed; /* 使按钮位置固定 */
top: 10px;
left: 10px;
margin: 0;
padding: 10px 20px;
border: none;
border-radius: 5px;
background-color: #ccc;
color: #333;
cursor: pointer;
.return-button:hover {
background-color: #aaaaaa;
}
} </style>
<script setup>
import { defineComponent, ref, onMounted, nextTick } from 'vue';
import { useRoute } from 'vue-router';
//
const links = ref([
{ to: '/home', text: '首页' },
{ to: '/mine', text: '个人信息' },
{ to: '/addDemand', text: '添加出行' },
{ to: '/order', text: '历史订单' },
]);
const route = useRoute();
const activeLink = ref(route.path);
onMounted(() => {
nextTick(() => {
activeLink.value = route.path;
});
});
function isActive(path) {
return path === activeLink.value;
}
</script>
<style scoped>
.header {
background-color: #13202d;
color: white;
text-align: center;
padding: 1rem;
/* ...其余样式... */
}
.sidebar {
background-color: #000000;
width: 11.11%; /* 根据页面布局调整 */
padding: 1rem;
overflow-y: auto;
/* ...其余样式... */
box-shadow: 2px 0 5px rgba(0, 0, 0, 0.2);
position: absolute;
left: 0;
}
/* ...其余样式... */
.main-content {
padding: 1rem;
overflow-y: auto;
position: absolute;
left: 11.11%; /* 导航栏宽度 */
width: 88.89%; /* 减去导航栏宽度 */
/* ...其余样式... */
}
</style>

File diff suppressed because one or more lines are too long

Binary file not shown.

After

Width:  |  Height:  |  Size: 223 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 406 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 208 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 266 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 923 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 188 KiB

@ -1,127 +1,167 @@
<template>
<div class="chat-container">
<div class="chat">
<h2 class="title">聊天室</h2>
<div class="chat-box">
<div v-for="(message, index) in messages" :key="index" class="message">
<span class="sender">{{ message.sender }}</span>
<span class="content">{{ message.content }}</span>
</div>
</div>
<div class="input">
<input type="text" v-model="newMessage" @keyup.enter="sendMessage" placeholder="输入消息...">
<button @click="sendMessage"></button>
</div>
<div style="height:100vh;width:100%;">
<el-container class="fullScreen">
<el-header class="header"><h1>FreeToGo 自由同行-众包导游</h1></el-header>
<el-container>
<el-aside width="200px" class="nav">
<ul>
<li>
<RouterLink to="/markdown" active-class="active">MD编辑器</RouterLink>
</li>
<li>
<RouterLink to="/tree" active-class="active">树状图</RouterLink>
</li>
<li>
<RouterLink to="/svg" active-class="active">SVG</RouterLink>
</li>
<li>
<RouterLink to="/todo" active-class="active">TodoMVC</RouterLink>
</li>
<li>
<RouterLink to="/list" active-class="active">动效列表</RouterLink>
</li>
<li>
<RouterLink to="/blur" active-class="active">模糊提示框</RouterLink>
</li>
</ul>
</el-aside>
<el-main>
<el-row :gutter="20">
<el-col :span="16">
<el-row>
<el-col :span="24">
<!-- 左边2/3的上容器 -->
<div class="container-style">上容器1</div>
</el-col>
</el-row>
<el-row>
<el-col :span="24">
<!-- 左边2/3的下容器 -->
<div class="container-style">下容器2</div>
</el-col>
</el-row>
</el-col>
<el-col :span="8">
<!-- 右边1/3的容器 -->
<div class="container-style">右边容器3</div>
</el-col>
</el-row>
</el-main>
</el-container>
</el-container>
</div>
</div>
<div><NavigationBar /></div>
</template>
<script>
import axios from 'axios';
import NavigationBar from '../components/NavigationBar.vue';
export default {
data() {
return {
messages: [],
newMessage: '',
};
},
components: {
NavigationBar
},
methods: {
async fetchMessages() {
try {
const response = await axios.get('http://example.com/messages');
this.messages = response.data;
} catch (error) {
console.error('Error fetching messages:', error);
}
},
async sendMessage() {
try {
await axios.post('http://example.com/messages', {
content: this.newMessage,
sender: 'Me', // You can replace 'Me' with the sender's name
});
this.newMessage = ''; // Clear the input field after sending
// You might want to fetch messages again here to update the UI with the latest messages
} catch (error) {
console.error('Error sending message:', error);
}
},
// WebSocket logic to receive messages
setupWebSocket() {
const ws = new WebSocket('ws://example.com/socket');
ws.onmessage = (event) => {
const message = JSON.parse(event.data);
this.messages.push(message);
};
},
},
created() {
this.fetchMessages(); // Fetch messages when the component is created
this.setupWebSocket(); // Setup WebSocket connection
},
};
</script>
<style>
.chat-container {
max-width: 600px;
margin: 0 auto;
*{
margin:0;
padding:0;
border:0
}
*, *:before, *:after {
box-sizing: border-box;
}
html, body {
margin: 0;
padding: 0;
height: 100%;
}
body{
margin: 0;
padding: 0;
border: 0;
}
a {
text-decoration: none;
color: inherit;
}
.header {
background-color: #13202d;
color: white;
text-align: center;
padding: 1rem;
display: flex;
justify-content: center;
align-items: center;
}
.chat {
border: 2px solid #ccc;
border-radius: 10px;
padding: 20px;
display: flex;
flex-direction: column;
height: 100%; /* Ensure the chat box takes up the entire height */
h1 {
font-size: 1.5rem;
}
.title {
margin-top: 0;
.nav {
background-color: #2b3642;
width: 100px;
height: 95vh;
margin: 0;
padding: 0;
}
.chat-box {
flex: 1; /* Allow the chat box to grow and take up remaining space */
max-height: 300px;
overflow-y: auto;
.nav ul {
padding: 1rem;
list-style-type: none;
}
.message {
margin-bottom: 10px;
.nav li {
margin-bottom: 1rem;
}
.input {
display: flex;
margin-top: 10px;
.nav li a {
display: block;
color: white;
padding: 0.5rem 1rem;
transition: background-color 0.3s;
}
.input input {
flex: 1;
padding: 8px;
border: 1px solid #ccc;
border-radius: 5px;
font-size: 16px;
.nav li a:hover, .active {
background-color: #8bb9ed;
}
.input button {
padding: 8px 15px;
border: none;
border-radius: 5px;
background-color: #007bff;
color: #fff;
font-size: 16px;
cursor: pointer;
margin-left: 10px;
.el-main {
padding: 1rem;
overflow-y: auto;
flex-grow: 1;
}
.input button:hover {
background-color: #0056b3;
@media (max-width: 768px) {
.el-aside {
width: 100%;
height: auto;
}
.nav ul {
flex-direction: column;
width: 100%;
}
.el-main {
margin-left: 0;
}
}
.fullScreen {
display: flex;
flex-direction: column;
height: 100vh;
overflow: hidden;
}
.el-container {
flex: 1;
display: flex;
flex-direction: row;
overflow: hidden;
padding: 0 !important;
}
.el-header, .el-aside, .el-main {
overflow-y: auto;
}
</style>

@ -1,75 +1,131 @@
<template>
<div class="return">
<button class="returnList" @click="returnList()"></button>
</div>
<div>
<h1>订单列表</h1>
<div
v-for="(list, index) in lists"
:key="lists.orderId"
class="order-box"
@click="goToOrderDetails(list.did)"
>
<p>目的地: {{ list.city }}</p>
<p>开始时间: {{ list.departureDate }}</p>
<p>结束时间: {{ list.endDate }}</p>
</div>
</div>
</template>
<script>
import axios from 'axios';
export default {
data() {
return {
phone: sessionStorage.getItem('phone') || '',
lists: [],
};
},
async created() {
//
axios.get(`http://192.168.243.35:9000/SendDemand/sendAllDemands?phone=${this.phone}`)
.then(response => {
this.lists = response.data
})
.catch(error => {
console.error('Error fetching user:', error);
});
},
methods: {
goToOrderDetails(orderId) {
this.$router.push({ name: 'OrderDetails', params: { orderId } });
},
returnList() {
this.$router.push('/mine');
}
}
};
</script>
<style scoped>
.order-box {
/* 样式代码,用于美化订单盒子 */
border: 1px solid #ccc;
padding: 10px;
margin-bottom: 10px;
<Layout :title="title" :links="computedLinks">
<div class="order-container">
<div
v-for="(list, index) in lists"
:key="list.orderId"
class="order-card"
@click="goToOrderDetails(list.did)"
>
<div class="order-header">
<h3>{{ list.city }}</h3>
</div>
<div class="order-body">
<p>开始时间: {{ list.departureDate }}</p>
<p>结束时间: {{ list.endDate }}</p>
</div>
<!-- 这里可以添加状态显示如果需要 -->
</div>
</div>
</Layout>
</template>
<script>
import axios from 'axios';
import Layout from '../components/Layout.vue';
export default {
components: {
Layout
},
data() {
return {
phone: sessionStorage.getItem('phone') || '',
lists: [],
title: '历史出行',
links: [{ name: '首页', path: '/home' }, { name: '个人信息', path: '/mine' }, { name: '添加出行', path: '/addDemandPage' },{ name: '历史出行', path: '/demandList' }],
user: {
},
};
},
computed: {
computedLinks() {
//
return this.user.membertype === true
? this.links.concat([{ name: '服务发布', path: '/addServe' },{ name: '导游记录', path: '/serverList' }])
: this.links.concat([{name:'注册导游',path:'/registerGuide'}]);
}
},
async created() {
//
axios.get(`/serve/users/getByPhone?phone=${this.phone}`)
.then(response => {
this.user = response.data
})
.catch(error => {
console.error('Error fetching user:', error);
});
axios.get(`/serve/SendDemand/sendAllDemands?phone=${this.phone}`)
.then(response => {
this.lists = response.data
})
.catch(error => {
console.error('Error fetching user:', error);
});
},
methods: {
goToOrderDetails(orderId) {
this.$router.push({ name: 'OrderDetails', params: { orderId } });
},
}
};
</script>
<style scoped>
/* 基本文本样式 */
.trip-info p {
margin: 8px 0;
font-size: 16px;
color: #333;
}
.returnList {
/* 定义返回按钮的样式 */
position: fixed; /* 使按钮位置固定 */
top: 10px;
left: 10px;
margin: 0;
padding: 10px 20px;
border: none;
border-radius: 5px;
background-color: #ccc;
color: #333;
cursor: pointer;
/* 订单容器样式 */
.order-container {
display: flex;
flex-wrap: wrap;
justify-content: center;
padding: 20px;
}
.returnList:hover {
background-color: #aaaaaa;
/* 订单卡片样式 */
.order-card {
border: 1px solid #eaeaea;
border-radius: 10px;
margin: 10px;
padding: 20px;
background-color: #fff;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
width: calc(33% - 40px);
cursor: pointer;
transition: transform 0.3s, box-shadow 0.3s;
}
.order-card:hover {
transform: translateY(-5px);
box-shadow: 0 5px 15px rgba(0, 0, 0, 0.2);
}
/* 订单头部和内容样式 */
.order-header h3 {
margin: 0 0 10px;
font-size: 20px;
color: #007BFF;
}
.order-body {
font-size: 14px;
}
/* 响应式设计 */
@media (max-width: 768px) {
.order-card {
width: calc(50% - 40px);
}
}
@media (max-width: 480px) {
.order-card {
width: 100%;
}
}
</style>

@ -1,15 +1,17 @@
<template>
<template>
<Layout :title="title" :links="computedLinks">
<div>
<h2>订单号: {{ orderId }}</h2>
<div v-for="(service, index) in services" :key="service.gid" class="service-box">
<div class="service-info">
<p class="nickname">{{ service.nickname }}</p>
<p class="end-date">{{ service.endDate }}</p>
<p class="nickname">导游姓名{{ service.nickname }}</p>
<p class="end-date">导游性别{{ service.endDate }}</p>
</div>
<button class="send-button" @click="sendServiceId(service.gid)"></button>
</div>
</div>
</div>
</Layout>
</template>
<style scoped>
@ -56,22 +58,39 @@
</style>
<script>
import axios from 'axios';
import axios from 'axios';
import Layout from '../components/Layout.vue';
export default {
props: ['orderId'],
data() {
return {
services: []
};
props: ['orderId'],
components: {
Layout,
},
data() {
return {
phone: sessionStorage.getItem('phone') || '',
services: [],
title: '匹配情况',
links: [{ name: '首页', path: '/home' }, { name: '个人信息', path: '/mine' }, { name: '添加出行', path: '/addDemandPage' },{ name: '历史出行', path: '/demandList' }],
user: {
},
};
},
computed: {
computedLinks() {
//
return this.user.membertype === true
? this.links.concat([{ name: '服务发布', path: '/addServe' },{ name: '导游记录', path: '/serverList' }])
: this.links.concat([{name:'注册导游',path:'/registerGuide'}]);
}
},
methods: {
async sendServiceId(gid) {
try {
// APIgiddidPOST
const orderIdAsInt = parseInt(this.orderId, 10);
const gidAsInt = parseInt(gid, 10);
const response = await axios.post('http://192.168.243.35:9000/DemandMatch/match', { did:orderIdAsInt,gid:gidAsInt});
const response = await axios.post('/serve/DemandMatch/match', { did:orderIdAsInt,gid:gidAsInt});
alert('已向导游发送确认信息');
} catch (error) {
console.error('Error sending service ID and order ID:', error);
@ -80,14 +99,14 @@ export default {
},
async created() {
//
axios.get(`http://192.168.243.35:9000/DemandMatch/register?did=${this.orderId}`)
axios.get(`/serve/DemandMatch/register?did=${this.orderId}`)
.then(response => {
this.services = response.data
})
.catch(error => {
console.error('Error fetching user:', error);
});
},
}
};
</script>

@ -1,84 +1,62 @@
<template>
<div class="item-manager">
<el-button type="primary" @click="add">Add Item</el-button>
<el-button type="danger" @click="onDelete">Delete Item</el-button>
<el-scrollbar class="custom-scrollbar" max-height="800px">
<div v-for="(item, index) in count" :key="index" class="item-container">
<p class="scrollbar-demo-item">{{ item }}</p>
</div>
<div v-for="review in reviews" :key="review.id" class="review-container">
<p class="scrollbar-demo-item">{{ review.content }}</p>
</div>
</el-scrollbar>
</div>
</template>
<style scoped>
.item-manager {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
margin: 20px;
}
.custom-scrollbar {
width: 100%; /* 根据需要调整滚动条容器的宽度 */
border-radius: 8px; /* 添加圆角 */
overflow: auto; /* 确保滚动条出现 */
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1); /* 添加阴影 */
}
.scrollbar-demo-item {
display: flex;
align-items: center;
justify-content: center;
height: 50px;
margin: 10px;
padding: 0 15px; /* 添加内边距 */
border-radius: 4px;
background: var(--el-color-primary-light-9);
color: var(--el-color-primary);
transition: background-color 0.3s ease; /* 添加背景色过渡效果 */
}
.item-container,
.review-container {
}
.custom-scrollbar::-webkit-scrollbar {
width: 10px;
}
.custom-scrollbar::-webkit-scrollbar-track {
background: #f1f1f1;
}
.custom-scrollbar::-webkit-scrollbar-thumb {
background: #888;
}
.custom-scrollbar::-webkit-scrollbar-thumb:hover {
background: #555;
}
</style>
<template>
<Layout :title="title" :links="computedLinks">
<div class="user-feedback">
<!-- 输入评价 -->
<div class="feedback-input">
<h2>行程评价</h2>
<form>
<textarea id="ebody" v-model.trim="evaluation.ebody" rows="4" cols="50"></textarea>
<button type="submit" @click="send"></button>
</form>
</div>
<el-space direction="vertical">
<el-row>
<el-text>星级评价</el-text>
<el-rate class="ml-1"
v-model="evaluation.satisfaction"
:texts="['oops', 'disappointed', 'normal', 'good', 'great']"
show-text
@change="handleRateChange"
clearable />
</el-row>
</el-space>
</div>
</Layout>
</template>
<script>
import axios from 'axios';
import Layout from '../components/Layout.vue';
export default {
props: ['orderId'],
components: {
Layout,
},
data() {
return {
ebody: '',
satisfaction:'',
did:'',
evaluation: {}, //
phone: sessionStorage.getItem('phone') || '',
title: '行程评价',
links: [{ name: '首页', path: '/home' }, { name: '个人信息', path: '/mine' }, { name: '添加出行', path: '/addDemandPage' },{ name: '历史出行', path: '/demandList' }],
user: {
},
};
},
computed: {
computedLinks() {
//
return this.user.membertype === true
? this.links.concat([{ name: '服务发布', path: '/addServe' },{ name: '导游记录', path: '/serverList' }])
: this.links.concat([{name:'注册导游',path:'/registerGuide'}]);
}
},
methods: {
send() {
axios.post('http://192.168.243.35:9000/evaluate/addEvaluation', {
axios.post('/serve/evaluate/addEvaluation', {
did: this.orderId,
satisfaction: this.evaluation.satisfaction,
ebody: this.evaluation.ebody,
@ -96,7 +74,14 @@ export default {
});
},
fetchEvaluation() {
axios.get(`http://192.168.243.35:9000/evaluate/getEvaluation?eid=${this.orderId}`)
axios.get(`/serve/users/getByPhone?phone=${this.phone}`)
.then(response => {
this.user = response.data
})
.catch(error => {
console.error('Error fetching user:', error);
});
axios.get(`/serve/evaluate/getEvaluation?eid=${this.orderId}`)
.then(response => {
this.evaluation = response.data;// evaluation
})

@ -1,146 +1,191 @@
<template>
<div class="home-page">
<div class="page-header">
<h1 class="page-title">首页</h1>
</div>
<div class="carousel-container">
<el-carousel :interval="4000" arrow="always" type="card">
<el-carousel-item
v-for="(item, index) in imagePaths"
:key="index"
:class="['carousel-item', index === Math.floor(imagePaths.length / 2) ? 'center-item' : '']"
>
<img :src="item" :alt="`Image ${index + 1}`" class="carousel-image">
</el-carousel-item>
</el-carousel>
</div>
<div class="search-container">
<input type="text" class="search-input" placeholder="世界这么大出去看看吧">
<button class="search-button" @click="gotoSearchPage()"></button>
</div>
<div class="return">
<button class="addDemand-button" @click="gotoAddDemandPage()"></button>
<isRegisterGuide />
</div>
</div>
<div><NavigationBar /></div>
</template>
<script>
import { ref } from 'vue';
import { useRouter } from 'vue-router';
import NavigationBar from '../components/NavigationBar.vue';
import isRegisterGuide from '../components/isRegisterGuide.vue';
<template>
<Layout :title="title" :links="computedLinks">
<!-- 将flex-direction改为row以实现水平排列 -->
<div class="main-content" :style="{ display: 'flex', flexDirection: 'row' }">
<div class="left-container" :style="{ flex: '3', height: 'calc(100vh - 20px)' }">
<h2>全国城市旅游热力图</h2>
<MapComponent></MapComponent>
</div>
<div class="right-container" :style="{ flex: '1', height: '100vh', marginLeft: '20px' }">
<h1>排行榜</h1>
<div class="ranking-container">
<div v-for="(item, index) in rankingList" :key="index" class="ranking-item">
<span class="ranking-number">{{ index + 1 }}.</span>
<span class="city-name">{{ item.city }}</span>
<span class="visitors-count">{{ item.visitors }}</span>
</div>
</div>
</div>
</div>
</Layout>
</template>
<script>
import Layout from '../components/Layout.vue'; //
import MapComponent from '../components/map.vue';
import axios from 'axios';
export default {
components: {
NavigationBar,
isRegisterGuide
},
setup() {
const imagePaths = ref([
'https://dimg04.c-ctrip.com/images/0102p12000828jmogCF2E_C_1600_1200.jpg',
'https://pic.kuaizhan.com/g3/b7/18/7a16-bad5-4d28-b5aa-571710c674cb36',
'https://img.shetu66.com/2023/07/11/1689058469100908.png'
]);
const router = useRouter();
//
function gotoSearchPage() {
router.push('/searchPage');
}
function gotoAddDemandPage() {
router.push('/addDemandPage');
}
return {
imagePaths,
gotoSearchPage,
gotoAddDemandPage
};
}
};
</script>
<style scoped>
.home-page {
display: flex;
flex-direction: column;
height: 100vh; /* 设置页面高度为视口高度 */
padding: 20px;
box-sizing: border-box;
}
.page-title {
margin: 0 0 20px; /* 为标题添加下边距,与轮播图分隔开 */
}
.carousel-container {
width: 100%;
/* 根据需要添加其他样式 */
}
.carousel-item {
/* 默认的轮播项样式 */
width: 80%; /* 假设默认宽度是80% */
margin: 0 auto; /* 水平居中 */
}
.center-item {
/* 居中的轮播项样式 */
width: 100%; /* 居中的项宽度为100% */
/* 可以添加其他样式,如高度、边框等 */
}
.carousel-image {
width: 100%; /* 图片宽度与轮播项宽度一致 */
height: auto; /* 保持图片比例 */
}
.search-container {
margin-top: 20px;
text-align: center; /* 让搜索框和按钮居中 */
}
.search-input {
padding: 10px;
border-radius: 4px;
border: 1px solid #ccc;
width: 300px; /* 可选,设置输入框宽度 */
}
.search-button {
padding: 10px 20px;
border-radius: 4px;
background-color: #4CAF50; /* 绿色背景 */
border: none;
color: white; /* 白色文字 */
text-align: center;
text-decoration: none;
display: inline-block;
font-size: 16px;
margin: 4px 2px;
cursor: pointer;
}
.addDemand-button {
/* 定义返回按钮的样式 */
position: fixed; /* 使按钮位置固定 */
top: 10px;
left: 10px;
margin: 0;
padding: 10px 20px;
border: none;
border-radius: 5px;
background-color: #ccc;
color: #333;
cursor: pointer;
}
.addDemand-button:hover {
background-color: #aaaaaa;
}
/* 可以添加更多样式来进一步美化 */
</style>
name: 'HomePage',
components: {
Layout,
MapComponent
},
data() {
return {
phone: sessionStorage.getItem('phone') || '',
title: '首页',
links: [{ name: '首页', path: '/home' }, { name: '个人信息', path: '/mine' }, { name: '添加出行', path: '/addDemandPage' },{ name: '历史出行', path: '/demandList' }],
user: {
},
rankingList: [
{ city: '广东', visitors: 3 },
{ city: '湖南', visitors: 2 },
// ...
],
};
},
computed: {
computedLinks() {
//
return this.user.membertype === true
? this.links.concat([{ name: '服务发布', path: '/addServe' },{ name: '导游记录', path: '/serverList' }])
: this.links.concat([{name:'注册导游',path:'/registerGuide'}]);
}
},
mounted() {
this.fetchUser(this.phone);
},
methods: {
fetchUser(phone) {
// API
axios.get(`/serve/users/getByPhone?phone=${phone}`)
.then(response => {
this.user = response.data
})
.catch(error => {
console.error('Error fetching user:', error);
});
},
}
}
</script>
<style scoped>
/* 整体页面样式 */
.main-content {
height: calc(100vh - 80px);
padding: 20px;
transition: background-color 0.3s; /* 过渡效果 */
background-color: rgba(255, 255, 255, 0.1);
}
/* 左侧容器样式 */
.left-container {
flex: 3;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
border-radius: 5px;
padding: 20px;
transition: box-shadow 0.3s, transform 0.3s; /* 过渡效果 */
background-color: rgba(255, 255, 255, 0.1);
}
/* 右侧容器样式 */
.right-container {
flex: 1;
margin-left: 20px;
background-color: rgba(255, 255, 255, 0.1);
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
border-radius: 5px;
padding: 20px;
transition: box-shadow 0.3s, transform 0.3s; /* 过渡效果 */
}
/* 排行榜容器样式 */
.ranking-container {
width: 100%;
border: 1px solid #666c6e;
border-radius: 5px;
padding: 10px;
background-color: #abd4ee;
transition: background-color 0.3s; /* 过渡效果 */
}
/* 排行榜项样式 */
.ranking-item {
display: flex;
align-items: center;
margin-bottom: 5px;
padding: 8px;
border-bottom: 1px solid #28a7a3;
transition: background-color 0.3s, transform 0.3s; /* 过渡效果 */
}
.ranking-item:hover {
background-color: #e0e2e3;
transform: scale(1.02); /* 放大效果 */
}
/* 排行榜序号样式 */
.ranking-number {
font-weight: bold;
margin-right: 5px;
color: #333;
transition: color 0.3s; /* 过渡效果 */
}
/* 城市名称样式 */
.city-name {
flex: 1;
font-size: 16px;
color: #555;
transition: color 0.3s; /* 过渡效果 */
}
/* 游客数量样式 */
.visitors-count {
margin-left: 5px;
color: #666;
transition: color 0.3s; /* 过渡效果 */
}
/* 标题样式 */
h1, h2 {
color: #333;
margin-bottom: 20px;
transition: color 0.3s; /* 过渡效果 */
}
/* 链接样式 */
.links {
display: flex;
justify-content: flex-end;
margin-bottom: 20px;
}
.link {
margin-left: 10px;
color: #007bff;
text-decoration: none;
transition: color 0.3s, transform 0.3s; /* 过渡效果 */
}
.link:hover {
color: #0056b3;
transform: scale(1.1); /* 放大效果 */
}
/* 页面滚动特效 */
.main-content.scrolled {
background-color: #e5e5e5; /* 滚动后的背景色 */
}
.left-container.scrolled,
.right-container.scrolled {
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2); /* 滚动后的阴影效果 */
transform: translateY(-10px); /* 滚动后的位移效果 */
}
/* 使用JavaScript监听滚动事件来添加.scrolled类 */
</style>

@ -1,91 +1,28 @@
<template>
<div class="login-container-bg">
<div class="login-header">
<h1>自由同行</h1>
</div>
<div class="login-container">
<h2>登录</h2>
<form @submit.prevent="login" class="login-form">
<el-icon><User /></el-icon>
<label for="phone">手机号</label>
<input type="text" id="phone" v-model="phone" class="input-field"placeholder="世界这么大出去看看吧">
<br>
<el-icon><Lock /></el-icon>
<label for="password">密码</label>
<input type="password" id="password" v-model="password" class="input-field"placeholder="世界这么大出去看看吧">
<br>
<button type="submit" class="submit-button">登录</button>
<button @click="goToRegister" class="register-button">注册</button>
</form>
</div>
<div class="background" ref="background"></div>
<div class="login-content" @mouseover="applyBlur" @mouseleave="removeBlur">
<div class="login-header">
<h1>登录</h1>
</div>
<div class="login-form">
<label for="phone">手机号:</label><br>
<input type="text" id="phone" v-model="phone" name="phone" class="input-field" placeholder="输入您的手机号"><br>
<label for="password">密码:</label><br>
<input type="password" id="password" v-model="password" name="password" class="input-field" placeholder="输入您的密码"><br>
<button class="submit-button" @click="login"></button>
</div>
<div class="register-link">
<p>没有账号? <a href="/register">现在注册</a></p>
</div>
</div>
</div>
</template>
<style scoped>
.login-header {
/* 根据需要调整标题的样式 */
text-align: center; /* 让标题居中对齐(如果水平宽度足够的话) */
margin-bottom: 20px; /* 根据需要调整标题与登录盒子之间的距离 */
}
.login-container-bg {
/* 为这个容器设置背景图片 */
background-image: url('../data/picture/loginBackground.webp');
background-size: cover;
background-position: center;
background-repeat: no-repeat;
height: 100vh; /* 根据需要设置高度,可以是视口高度 */
display: flex;
flex-direction: column; /* 如果需要垂直堆叠,默认如此 */
align-items: center; /* 垂直居中 */
justify-content: center; /* 水平居中 */
}
.login-header h1 {
color: #000000;
}
.login-form label {
color: white;
}
.login-container {
max-width: 400px;
margin: 0 auto;
padding: 20px;
border: 1px solid #000000;
border-radius: 5px;
text-align: center;
}
.input-field {
margin: 10px 0;
padding: 5px;
width: 100%;
}
.submit-button {
padding: 10px 20px;
background-color: #007bff;
color: #003f3f;
border: none;
border-radius: 5px;
cursor: pointer;
}
.register-button {
padding: 10px 20px;
background-color: #ff6347;
color: #003f3f;
border: none;
border-radius: 5px;
cursor: pointer;
}
</style>
<script>
import { login } from '../api/auth'
import axios from "axios";
export default {
export default {
data() {
return {
phone: '',
@ -93,11 +30,17 @@ export default {
}
},
methods: {
applyBlur() {
this.$refs.background.style.filter = 'blur(5px)';
},
removeBlur() {
this.$refs.background.style.filter = 'none';
},
login() {
console.log("手机号:", this.phone);
console.log("密码:", this.password);
axios.post('http://192.168.243.35:9000/Login/login', {
axios.post('/serve/Login/login', {
//
phone: this.phone,
password: this.password
@ -109,40 +52,107 @@ export default {
'Content-Type': 'application/json'
}
})
.then(response => {
if (response.data == 1) {
sessionStorage.setItem('phone', this.phone);
//
this.$router.push('/home');
}
else if (response.data == 2) {
alert('登录失败:账号或密码错误' );
}
else if(response.data == 3){
alert('登录失败:账号未注册');
}
else if(response.data == 6) {
alert('登录失败:未输入账号密码');
}
else if(response.data == 7) {
alert('登录失败:未输入账号');
}
else if(response.data == 8) {
alert('登录失败:未输入密码');
}
else {
alert('登录失败:未知原因');
}
})
.catch(error => {
console.error(error);
//
alert('登录失败:网络错误或服务器错误');
});
},
goToRegister() {
this.$router.push('/register'); //
}
}
.then(response => {
if (response.data == 1) {
sessionStorage.setItem('phone', this.phone);
//
this.$router.push('/home');
}
else if (response.data == 2) {
alert('登录失败:账号或密码错误' );
}
else if(response.data == 3){
alert('登录失败:账号未注册');
}
else if(response.data == 6) {
alert('登录失败:未输入账号密码');
}
else if(response.data == 7) {
alert('登录失败:未输入账号');
}
else if(response.data == 8) {
alert('登录失败:未输入密码');
}
else {
alert('登录失败:未知原因');
}
})
.catch(error => {
console.error(error);
//
alert('登录失败:网络错误或服务器错误');
});
},
},
};
</script>
<style>
.login-container {
position: relative;
}
.background {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-image: url('../data/picture/微信图片_20240629090627.jpg');
background-size: cover;
filter: blur(0);
transition: filter 0.5s;
}
.login-content {
position: relative;
z-index: 1;
width: 400px;
margin: 100px auto;
background-color: #fdfcfc;
border-radius: 5px;
box-shadow: 0 2px 4px rgb(0, 63, 63);
padding: 20px;
}
.login-header h1 {
text-align: center;
font-size: 2rem;
margin-bottom: 10px;
color: #000000;
}
.login-form {
margin-top: 20px;
display: inline-block;
}
.input-field {
margin: 10px 0;
padding: 10px;
width: 100%;
border: 1px solid #000000;
border-radius: 5px;
}
.submit-button {
padding: 10px 20px;
margin-top: 20px;
background-color: #007bff;
color: #fdfcfc;
border: none;
border-radius: 5px;
cursor: pointer;
}
.submit-button:hover {
background-color: #003f3f;
}
.register-link {
margin-top: 20px;
text-align: center;
color: #000000;
}
</script>
</style>

@ -1,145 +1,195 @@
<template>
<div class="register-container-wrapper">
<div class="register-container">
<h1>注册</h1>
<form @submit.prevent="register" class="register-form">
<label for="phone">手机号</label>
<input type="phone" id="phone" v-model="phone" class="input-field">
<br>
<label for="password">密码</label>
<input type="password" id="password" v-model="password" class="input-field">
<br>
<label for="name">姓名</label>
<input type="name" id="name" v-model="name" class="input-field">
<br>
<label for="IDcard">身份证号</label>
<input type="IDcard" id="IDcard" v-model="IDcard" class="input-field">
<br>
<label for="nickname">昵称</label>
<input type="nickname" id="nickname" v-model="nickname" class="input-field">
<br>
<button type="submit" class="submit-button">注册</button>
<button class="returnLogin-button" @click="gotoLogin()"></button>
</form>
</div>
</div>
</template>
<style scoped>
.register-container-wrapper {
/* 为这个容器设置背景图片 */
background-image: url('../data/picture/loginBackground.webp');
background-size: cover;
background-position: center;
background-repeat: no-repeat;
height: 100vh; /* 根据需要设置高度,可以是视口高度 */
display: flex;
justify-content: center;
align-items: center; /* 垂直居中 */
}
<div class="register-container">
<div class="background" ref="background"></div>
<div class="register-content" @mouseover="applyBlur" @mouseleave="removeBlur">
<div class="register-header">
<h1>注册</h1>
</div>
<div class="register-form">
<label for="phone" class="required-field">手机号:</label><br>
<input type="text" id="phone" v-model="phone" name="phone" class="input-field" placeholder="输入您的手机号"><br>
<label for="password" class="required-field">密码:</label><br>
<input type="password" id="password" v-model="password" name="password" class="input-field" placeholder="输入您的密码"><br>
<label for="confirmPassword" class="required-field">确认密码:</label>
<input type="password" id="confirmPassword" v-model="confirmPassword" name="confirmPassword" class="input-field" placeholder="确认您的密码">
<label for="name" class="required-field">姓名:</label><br>
<input type="text" id="name" v-model="name" name="name" class="input-field" placeholder="输入您的姓名"><br>
<label for="IDcard" class="required-field">身份证号:</label><br>
<input type="text" id="idNumber" v-model="IDcard" name="idNumber" class="input-field" placeholder="输入您的身份证号"><br>
<label for="nickname" class="required-field">昵称:</label><br>
<input type="text" id="nickname" v-model="nickname" name="nickname" class="input-field" placeholder="输入您的昵称"><br>
<label for="place">居住地:</label><br>
<el-cascader
placeholder="请选择"
:options="options"
v-model="selectedOptions"
@change="handleChange"
></el-cascader>
</div>
<div class="login-link">
<button class="submit-button" @click="register"></button>
<p>已有账号? <a href="/login">立即登录</a></p>
</div>
</div>
</div>
</template>
<style>
.required-field::after {
content: '*';
color: red;
margin-left: 5px; /* 根据需要调整间距 */
}
.register-container {
max-width: 400px;
margin: 0 auto;
padding: 30px;
border: 1px solid #000000;
position: relative;
}
.background {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-image: url('../data/picture/loginBackground.jpg');
background-size: cover;
filter: blur(0);
transition: filter 0.5s;
}
.register-content {
position: relative;
z-index: 1;
width: 400px;
margin: 100px auto;
background-color: #fdfcfc;
border-radius: 5px;
box-shadow: 0 2px 4px rgb(0, 63, 63);
padding: 20px;
}
.register-header h1 {
text-align: center;
font-size: 2rem;
margin-bottom: 10px;
color: #000000;
}
.register-form {
margin-top: 20px;
display: inline-block;
}
.input-field {
margin: 10px 0;
padding: 5px;
padding: 10px;
width: 100%;
border: 1px solid #000000;
border-radius: 5px;
}
.submit-button {
padding: 10px 20px;
background-color: #28a7a3;
color: #abd4ee;
margin-top: 20px;
background-color: #007bff;
color: #fff;
border: none;
border-radius: 5px;
cursor: pointer;
}
.returnLogin-button {
padding: 10px 20px;
background-color: #ff6347; /* 例如,设置为红色 */
color: white;
border: none;
border-radius: 5px;
cursor: pointer;
margin-top: 10px; /* 可以添加一些上边距来分隔按钮 */
}
.submit-button:hover {
background-color: #003f3f;
}
.login-link {
margin-top: 20px;
text-align: center;
color: #000000;
}
</style>
<script>
import { register } from '../api/auth'
import axios from "axios";
import { regionData } from 'element-china-area-data'
export default {
data() {
return {
phone: '',
password: '',
name:'',
nickname:'',
IDcard:''
name:'',
nickname:'',
IDcard:'',
confirmPassword: '',
email: '',
place: '',
passwordsMatch: false,
selectedOptions: [],
options: regionData
}
},
methods: {
methods:{
applyBlur() {
this.$refs.background.style.filter = 'blur(5px)';
},
removeBlur() {
this.$refs.background.style.filter = 'none';
},
register() {
console.log("", this.phone);
console.log("密码:", this.password);
console.log("姓名:",this.name);
console.log("身份证号:",this.IDcard);
console.log("昵称:",this.nickname);
axios.post(`http://192.168.243.35:9000/Login/register`, {
//
phone: this.phone,
password: this.password,
name:this.name,
IDCard:this.IDcard,
nickname:this.nickname
}, {
// cookie
withCredentials: true,
// JSON
headers: {
'Content-Type': 'application/json'
}
})
.then(response => {
if(response.data == 5){
alert("注册成功");
this.$router.push('/login');
}else if(response.data == 4){
alert("该账号已注册")
}else if(response.data == 9){
alert("身份证错误")
}else if (response.data == 11){
alert("手机号错误")
}else if (response.data == 12){
alert("密码过于简单请输入8位以上密码")
}else if (response.data == 13){
alert("请输入真实姓名")
}else{
alert("未知错误")
}
})
.catch(error => {
console.error(error)
//
alert("网络或服务器错误");
})
if (this.password !== this.confirmPassword) {
this.passwordsMatch = false;
alert('密码和确认密码不一致');
}
else if (this.password === this.confirmPassword){
console.log("手机号:", this.phone);
console.log("密码:", this.password);
console.log("姓名:",this.name);
console.log("身份证号:",this.IDcard);
console.log("昵称:",this.nickname);
console.log("居住地:",this.place);
axios.post(`/serve/Login/register`, {
//
phone: this.phone,
password: this.password,
name:this.name,
IDCard:this.IDcard,
nickname:this.nickname
}, {
// cookie
withCredentials: true,
// JSON
headers: {
'Content-Type': 'application/json'
}
})
.then(response => {
if(response.data == 5){
alert("注册成功");
this.$router.push('/login');
}else if(response.data == 4){
alert("该账号已注册")
}else if(response.data == 9){
alert("身份证错误")
}else if (response.data == 11){
alert("手机号错误")
}else if (response.data == 12){
alert("密码过于简单请输入8位以上密码")
}else if (response.data == 13){
alert("请输入真实姓名")
}else{
alert("未知错误")
}
})
.catch(error => {
console.error(error)
//
alert("网络或服务器错误");
})
}
},
gotoLogin(){
this.$router.push('/login');
},
handleChange(value, selectedData) {
console.log(value, selectedData);
}
}
}
</script>

@ -1,114 +1,223 @@
<script lang="ts" setup>
import { ref, onBeforeMount, watch, watchEffect } from 'vue'
import axios from 'axios'
import { ElSelect, ElOption } from 'element-plus'
import { AreaList } from '../components/types'
import { format, addDays } from 'date-fns'
import Return from '../components/return.vue'
const province = ref('')
const city = ref('')
const area = ref('')
const remark = ref('')
const provinceList = ref<AreaList[]>([])
const cityList = ref<AreaList[]>([])
const areaList = ref<AreaList[]>([])
const rangeValue = ref<string[]>([format(new Date(), 'yyyy-MM-dd'), format(addDays(new Date(), 1), 'yyyy-MM-dd')])
// JSON
const getProvinceList = async () => {
const res = await axios.get<AreaList[]>('https://yjy-oss-files.oss-cn-zhangjiakou.aliyuncs.com/tuxian/area.json')
provinceList.value = res.data
console.log(provinceList.value)
}
const publish = () => {
//
if(city.value!=''){
axios.post(`http://192.168.243.35:9000/SendDemand/register`,{phone:sessionStorage.getItem('phone') || '',city:city.value,time:rangeValue.value,remark:remark.value})
.then(response => {
alert("发布成功")
})
.catch(error => {
console.error('发布失败', error);
});}
else{
alert("请输入目的地")
}
<script lang="ts" setup>
import { ref, computed, onMounted, watch } from 'vue';
import axios from 'axios';
import { ElSelect, ElOption } from 'element-plus';
import { AreaList } from '../components/types';
import { format, addDays } from 'date-fns';
import Layout from '../components/Layout.vue';
// 使ref
const phone = ref(sessionStorage.getItem('phone') || '');
const title = '添加出行';
const links = ref([
{ name: '首页', path: '/home' },
{ name: '个人信息', path: '/mine' },
{ name: '添加出行', path: '/addDemandPage' },
{ name: '历史出行', path: '/demandList' }
]);
const user = ref({
membertype: false,
});
const guideGender = ref('');
const travelersCount = ref(1);
const province = ref('');
const city = ref('');
const area = ref('');
const remark = ref('');
const provinceList = ref<AreaList[]>([]);
const cityList = ref<AreaList[]>([]);
const areaList = ref<AreaList[]>([]);
const rangeValue = ref<string[]>([format(new Date(), 'yyyy-MM-dd'), format(addDays(new Date(), 1), 'yyyy-MM-dd')]);
//
const getProvinceList = async () => {
try {
const res = await axios.get<AreaList[]>('https://yjy-oss-files.oss-cn-zhangjiakou.aliyuncs.com/tuxian/area.json');
provinceList.value = res.data;
} catch (error) {
console.error('Error fetching province list:', error);
}
};
onBeforeMount(async()=>{
getProvinceList()
})
watchEffect(() => {
console.log('rangeValue:', rangeValue.value)
})
//
watch(province, (newValue, oldValue) => {
const matchedProvince = provinceList.value.find(item => item.name === newValue)
if (matchedProvince) {
cityList.value = matchedProvince.areaList
city.value = '' //
areaList.value = [] //
console.log(cityList.value)
}
})
//
watch(city, (newValue, oldValue) => {
const matchedCity = cityList.value.find(item => item.name === newValue)
if (matchedCity) {
areaList.value = matchedCity.areaList
area.value = '' //
console.log(areaList.value)
}
})
//
const publish = async () => {
if (city.value !== '') {
try {
const response = await axios.post(`/serve/SendDemand/register`, {
phone: phone.value,
city: city.value,
time: rangeValue.value,
remark: remark.value
});
alert("发布成功");
} catch (error) {
console.error('发布失败', error);
}
} else {
alert("请输入目的地");
}
};
//
onMounted(async () => {
await getProvinceList();
try {
const response = await axios.get(`/serve/users/getByPhone?phone=${phone.value}`);
if (response.data) {
user.value = response.data;
}
} catch (error) {
console.error('Error fetching user data:', error);
}
});
//
const computedLinks = computed(() => {
return user.value.membertype === true
? links.value.concat([{ name: '服务发布', path: '/addServe' }, { name: '导游记录', path: '/serverList' }])
: links.value.concat([{ name: '注册导游', path: '/registerGuide' }]);
});
// watcher
watch(province, (newValue, oldValue) => {
const matchedProvince = provinceList.value.find(item => item.name === newValue);
if (matchedProvince) {
cityList.value = matchedProvince.areaList;
city.value = ''; //
areaList.value = []; //
}
});
// watcher
watch(city, (newValue, oldValue) => {
const matchedCity = cityList.value.find(item => item.name === newValue);
if (matchedCity) {
areaList.value = matchedCity.areaList;
area.value = ''; //
}
});
</script>
<template>
<Layout :title="title" :links="computedLinks">
<h3>选择出行城市</h3>
<div class="city" style="display: flex; align-items: center;">
<p style="color: red;">*</p>
<el-select v-model="province" clearable placeholder="省份">
<el-option v-for="item in provinceList" :key="item.code" :label="item.name" :value="item.name" />
</el-select>
<el-select v-model="city" clearable placeholder="城市">
<el-option v-for="item in cityList" :key="item.code" :label="item.name" :value="item.name" />
</el-select>
</div>
<h3>选择出行时间</h3>
<div class="time-select">
<VueDatePicker
placeholder="请选择出行时间"
range
:min-date="new Date()"
format="yyyy-MM-dd"
:width="280"
v-model="rangeValue" />
</div>
<h3>期望导游性别</h3>
<div>
<el-select v-model="guideGender" placeholder="请选择">
<el-option label="男" value="male" />
<el-option label="女" value="female" />
</el-select>
</div>
<h3>出行人数</h3>
<div>
<label for="travelers-count"></label>
<input type="number" id="travelers-count" v-model.number="travelersCount"
placeholder="请输入出行人数" min="1" max="100" />
</div>
<h3>填写备注信息</h3>
<div>
<Return></Return>
<label for="user-input"></label>
<input type="text" id="remark" v-model="remark" placeholder="请输入备注信息">
</div>
<div><h1>发布出行规划</h1></div>
<div class="addDemand-container">
<div><h3>选择出行城市</h3></div>
<div style="display: flex;">
<p style="color: red;">*</p>
<el-select v-model="province" clearable placeholder="省份">
<el-option v-for="item in provinceList" :key="item.code" :label="item.name" :value="item.name" />
</el-select>
<el-select v-model="city" clearable placeholder="城市">
<el-option v-for="item in cityList" :key="item.code" :label="item.name" :value="item.name" />
</el-select>
</div>
<div><h3>选择出行时间</h3></div>
<div>
<VueDatePicker
placeholder="请选择出行时间"
range
:min-date="new Date()"
format="yyyy-MM-dd"
:width="280"
v-model="rangeValue" />
</div>
<div><h3>填写备注信息</h3></div>
<div>
<label for="user-input">备注信息:</label>
<input type="text" id="remark" v-model="remark" placeholder="">
</div>
<el-button type="primary" @click="publish"></el-button>
</div>
<el-button type="primary" @click="publish"></el-button>
</Layout>
</template>
<style>
.addDemand-container {
max-width: 400px;
margin: 0 auto;
padding: 30px;
border: 1px solid #000000;
border-radius: 5px;
text-align: center;
}
<style scoped>
body {
font-family: 'Helvetica Neue', Arial, sans-serif;
background: #f4f4f4;
color: #333;
margin: 0;
padding: 0;
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
}
/* Form container - removed to achieve elements centered */
.addDemand-container { /* Removed */
}
/* Update styles for form elements */
.el-select, input[type="number"], input[type="text"], .time-select, .city, .el-button {
width: 70%;
margin: 0 auto; /* Center the elements horizontally */
padding: 10px;
margin-bottom: 20px;
border: none;
border-radius: 4px;
background-color: #f9f9f9;
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.1);
transition: box-shadow 0.3s;
}
.el-select:hover, input[type="number"]:hover, input[type="text"]:hover, .time-select:hover, .city:hover, .el-button:hover {
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
}
.el-select:focus, input[type="number"]:focus, input[type="text"]:focus, .time-select:focus, .city:focus, .el-button:focus {
outline: none;
box-shadow: 0 0 0 2px rgba(0, 123, 255, 0.25);
}
/* Reset select inner border and styles */
.el-select .el-input__inner {
border: none;
background-color: #f9f9f9;
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.1);
}
/* Button styles */
.el-button {
width: 40%; /* Update button width */
padding: 15px;
font-size: 1em;
border: none;
border-radius: 4px;
background-image: linear-gradient(to right, #6a11cb 0%, #2575fc 100%); /* Change background color to blue gradient */
color: white;
transition: background-image 0.3s;
margin-top: 20px;
}
.el-button:hover {
background-image: linear-gradient(to right, #2575fc 0%, #6a11cb 100%);
}
/* Responsive design */
@media (max-width: 768px) {
.addDemand-container {
width: 90%;
padding: 20px;
}
}
</style>

@ -1,20 +1,32 @@
<script lang="ts" setup>
import { ref, onBeforeMount, watch, watchEffect } from 'vue'
import axios from 'axios'
import { ElSelect, ElOption } from 'element-plus'
import { AreaList } from '../components/types'
import { format, addDays } from 'date-fns'
import Return from '../components/return.vue'
<script lang="ts" setup>
import { ref, onMounted, watch, computed } from 'vue';
import axios, { AxiosError } from 'axios';
import { ElSelect, ElOption, ElButton } from 'element-plus';
import { AreaList } from '../components/types';
import { format, addDays } from 'date-fns';
import Layout from '../components/Layout.vue';
const province = ref('')
const city = ref('')
const area = ref('')
const remark = ref('')
const phone = ref(sessionStorage.getItem('phone') || '');
const title = '发布服务';
const links = ref([
{ name: '首页', path: '/home' },
{ name: '个人信息', path: '/mine' },
{ name: '添加出行', path: '/addDemandPage' },
{ name: '历史出行', path: '/demandList' }
]);
const user = ref({
membertype: true,
});
const provinceList = ref<AreaList[]>([])
const cityList = ref<AreaList[]>([])
const areaList = ref<AreaList[]>([])
const rangeValue = ref<string[]>([format(new Date(), 'yyyy-MM-dd'), format(addDays(new Date(), 1), 'yyyy-MM-dd')])
const province = ref('');
const city = ref('');
const area = ref('');
const remark = ref('');
const provinceList = ref<AreaList[]>([]);
const cityList = ref<AreaList[]>([]);
const areaList = ref<AreaList[]>([]);
const rangeValue = ref<string[]>([format(new Date(), 'yyyy-MM-dd'), format(addDays(new Date(), 1), 'yyyy-MM-dd')]);
// JSON
const getProvinceList = async () => {
@ -25,7 +37,7 @@ const getProvinceList = async () => {
const publish = () => {
//
if(city.value!=''){
axios.post(`http://192.168.243.35:9000/SendGuideService/register`,{phone:sessionStorage.getItem('phone') || '',city:city.value,time:rangeValue.value,remark:remark.value})
axios.post(`/serve/SendGuideService/register`,{phone:sessionStorage.getItem('phone') || '',city:city.value,time:rangeValue.value,remark:remark.value})
.then(response => {
alert("发布成功")
})
@ -36,84 +48,147 @@ const publish = () => {
alert("请输入目的地")
}
};
onBeforeMount(async()=>{
getProvinceList()
})
onMounted(async () => {
try {
await getProvinceList();
const response = await axios.get(`/serve/users/getByPhone?phone=${phone.value}`);
if (response.data) {
user.value = response.data;
}
} catch (error) {
console.error('Error fetching user or province list:', error);
//
}
});
//
const computedLinks = computed(() => {
return user.value.membertype === true
? links.value.concat([{ name: '服务发布', path: '/addServe' }, { name: '导游记录', path: '/serverList' }])
: links.value.concat([{ name: '注册导游', path: '/registerGuide' }]);
});
watch(province, (newValue, oldValue) => {
if (newValue) {
const matchedProvince = provinceList.value.find(item => item.name === newValue);
if (matchedProvince) {
cityList.value = matchedProvince.areaList;
city.value = ''; //
areaList.value = []; //
}
}
});
watchEffect(() => {
console.log('rangeValue:', rangeValue.value)
})
//
watch(province, (newValue, oldValue) => {
const matchedProvince = provinceList.value.find(item => item.name === newValue)
if (matchedProvince) {
cityList.value = matchedProvince.areaList
city.value = '' //
areaList.value = [] //
console.log(cityList.value)
}
})
//
watch(city, (newValue, oldValue) => {
const matchedCity = cityList.value.find(item => item.name === newValue)
if (matchedCity) {
areaList.value = matchedCity.areaList
area.value = '' //
console.log(areaList.value)
}
})
// watcher
watch(city, (newValue, oldValue) => {
if (newValue) {
const matchedCity = cityList.value.find(item => item.name === newValue);
if (matchedCity) {
areaList.value = matchedCity.areaList;
area.value = ''; //
}
}
});
</script>
<template>
<div>
<Return></Return>
</div>
<div><h1>导游服务</h1></div>
<div class="addServe-container">
<h3>选择导游城市</h3>
<div style="display: flex;">
<p style="color: red;">*</p>
<el-select v-model="province" clearable placeholder="省份">
<el-option v-for="item in provinceList" :key="item.code" :label="item.name" :value="item.name" />
</el-select>
<el-select v-model="city" clearable placeholder="城市">
<el-option v-for="item in cityList" :key="item.code" :label="item.name" :value="item.name" />
</el-select>
<!--<el-select v-model="area" clearable placeholder="Select">
<el-option v-for="item in areaList" :key="item.code" :label="item.name" :value="item.name" />
</el-select>-->
</div>
<h3>选择导游时间</h3>
<div>
<VueDatePicker
placeholder="请选择出行时间"
range
:min-date="new Date()"
format="yyyy-MM-dd"
:width="280"
v-model="rangeValue" />
</div>
<h3>添加备注信息</h3>
<div>
<label for="user-input">备注信息:</label>
<input type="text" id="remark" v-model="remark" placeholder="">
</div>
<el-button type="primary" @click="publish"style="margin-top: 20px;">发布</el-button>
</div>
<Layout :title="title" :links="computedLinks">
<h1>导游服务</h1>
<h3>选择导游城市</h3>
<div class="city" style="display: flex; align-items: center;">
<p style="color: red;">*</p>
<el-select v-model="province" clearable placeholder="省份">
<el-option v-for="item in provinceList" :key="item.code" :label="item.name" :value="item.name" />
</el-select>
<el-select v-model="city" clearable placeholder="城市">
<el-option v-for="item in cityList" :key="item.code" :label="item.name" :value="item.name" />
</el-select>
</div>
<h3>选择导游时间</h3>
<div class="time-select">
<VueDatePicker
placeholder="请选择出行时间"
range
:min-date="new Date()"
format="yyyy-MM-dd"
:width="280"
v-model="rangeValue" />
</div>
<h3>添加备注信息</h3>
<div>
<input type="text" v-model="remark" placeholder="请输入备注信息" />
</div>
<el-button type="primary" @click="publish"></el-button>
</Layout>
</template>
<style>
.addServe-container {
max-width: 400px;
margin: 0 auto;
padding: 30px;
border: 1px solid #000000;
border-radius: 5px;
text-align: center;
<style scoped>
/* 页面整体样式 */
body {
font-family: 'Arial', sans-serif;
background-color: #f5f5f5;
color: #333;
margin: 0;
padding: 0;
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
}
/* 标题样式 */
h1, h3 {
color: #333;
margin-left: 20px; /* 为标题添加左边距 */
}
h1 {
font-size: 24px;
text-align: center; /* 标题居中 */
margin-bottom: 20px;
}
h3 {
font-size: 18px;
margin-bottom: 10px;
}
/* 表单控件美化 */
.el-select, input[type="text"], .time-select, .el-button {
width: 70%;
margin: 0 auto; /* Center the elements horizontally */
padding: 10px;
margin-bottom: 20px;
border: none;
border-radius: 4px;
background-color: #f9f9f9;
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.1);
transition: box-shadow 0.3s;
}
/* 按钮样式 */
.el-button {
width: 40%; /* 按钮宽度 */
padding: 15px;
font-size: 1em;
border: none;
border-radius: 4px;
background-image: linear-gradient(to right, #6a11cb 0%, #2575fc 100%);
color: white;
transition: background-image 0.3s;
margin-top: 20px;
}
.el-button:hover {
background-image: linear-gradient(to right, #2575fc 0%, #6a11cb 100%);
}
/* 响应式设计 */
@media (max-width: 768px) {
.form-container {
width: 90%;
}
}
</style>

@ -1,4 +1,6 @@
<template>
<template>
<div><button class="back-button" @click="goBack"></button></div>
<div class="profile-edit">
<h2>修改个人信息</h2>
<form @submit.prevent="updateProfile">
@ -15,8 +17,8 @@
<input type="tel" id="phone" v-model="userInfo.phone" class="input-field">
</div>
<div>
<label for="password">密码</label>
<input type="password" id="password" v-model="userInfo.password" class="input-field">
<label for="password">个人简介</label>
<input type="text" id="brief" v-model="userInfo.brief" class="input-field">
</div>
<button type="submit">保存</button>
</form>
@ -24,17 +26,15 @@
</div>
</template>
<script>
<script>
import axios from 'axios';
export default {
data() {
return {
userInfo: {
nickname: '',
email: '',
phone: sessionStorage.getItem('phone') || '',
password: '',
},
message: '',
userInfo: { },
message: '',
phone:sessionStorage.getItem('phone') || '',
};
},
mounted() {
@ -43,42 +43,54 @@ export default {
methods: {
fetchUser(phone) {
// API
axios.get(`http://192.168.243.35:9000/users/getByPhone?phone=${phone}`)
axios.get(`/serve/users/getByPhone?phone=${phone}`)
.then(response => {
this.user = response.data
this.userInfo = response.data
})
.catch(error => {
console.error('Error fetching user:', error);
});
},
updateProfile() {
//
//
//
updateProfile() {
//
axios.post(`/serve/users/Pupdate`,{user:this.userInfo})
.then(response => {
})
.catch(error => {
console.error('Error updating nickname:', error);
});
this.message = '个人信息更新成功!';
//
this.userInfo = {
nickname: '',
email: '',
phone: '',
password: '',
};
//
//
//
setTimeout(() => {
this.message = '';
}, 2000);
//
// this.message = '';
},
}, 2000);
},
goBack(){
this.$router.push('/mine')
}
},
};
</script>
<style scoped>
<style scoped>
.back-button {
/* 这里是自定义按钮的样式 */
display: inline-block;
padding: 10px 20px;
font-size: 16px;
color: white;
background-color: #55aa00; /* 蓝色背景 */
border: none;
border-radius: 4px;
cursor: pointer;
margin-bottom: 20px; /* 底部留一些空间 */
position: absolute; /* 绝对定位以将其放置在左上角 */
top: 10px; /* 距离顶部的距离 */
left: 10px; /* 距离左侧的距离 */
}
.profile-edit {
max-width: 400px;
margin: 0 auto;

@ -1,4 +1,5 @@
<template>
<template>
<Layout :title="title" :links="computedLinks">
<div>订单号: {{ orderId }}</div>
<div v-for="(service, index) in services" :key="service.gid" class="service-box">
<p>{{ service.nickname }}</p>
@ -6,25 +7,43 @@
<!-- 添加一个按钮并绑定 click 事件处理器 sendServiceId -->
<button @click="sendServiceId(service.gid)"></button>
</div>
</Layout>
</template>
<script>
import axios from 'axios';
import axios from 'axios';
import Layout from '../components/Layout.vue';
export default {
props: ['orderId'],
data() {
return {
services: []
};
props: ['orderId'],
components: {
Layout,
},
data() {
return {
phone: sessionStorage.getItem('phone') || '',
services: [],
title: '导游申请',
links: [{ name: '首页', path: '/home' }, { name: '个人信息', path: '/mine' }, { name: '添加出行', path: '/addDemandPage' },{ name: '历史出行', path: '/demandList' }],
user: {
},
};
},
computed: {
computedLinks() {
//
return this.user.membertype === true
? this.links.concat([{ name: '服务发布', path: '/addServe' },{ name: '导游记录', path: '/serverList' }])
: this.links.concat([{name:'注册导游',path:'/registerGuide'}]);
}
},
methods: {
async sendServiceId(gid) {
try {
// APIgiddidPOST
const orderIdAsInt = parseInt(this.orderId, 10);
const gidAsInt = parseInt(gid, 10);
const response = await axios.post('http://192.168.243.35:9000/DemandMatch/confirmed', { did:orderIdAsInt,gid:gidAsInt});
const response = await axios.post('/serve/DemandMatch/confirmed', { did:orderIdAsInt,gid:gidAsInt});
alert('已同意');
} catch (error) {
console.error('Error sending service ID and order ID:', error);
@ -33,7 +52,7 @@ export default {
},
async created() {
//
axios.get(`http://192.168.243.35:9000/DemandMatch/confirmedPage?did=${this.orderId}`)
axios.get(`/serve/DemandMatch/confirmedPage?did=${this.orderId}`)
.then(response => {
this.services = response.data
})

@ -1,84 +1,156 @@
<template>
<div class="profile">
<h2>个人主页</h2>
<div v-if="showNicknameInput">
<label for="nickname">昵称</label>
<input type="nickname" id="nickname" v-model="nickname" class="input-field">
<button @click="updateNickname"></button>
</div>
<div v-else>
<p>昵称{{ user.nickname }}</p>
<button @click="toggleNicknameInput"></button>
</div>
<div v-if="showEmailInput">
<label for="email">邮箱</label>
<input type="email" id="email" v-model="email" class="input-field">
<button @click="updateEmail"></button>
</div>
<div v-else>
<p>邮箱{{ user.email }}</p>
<button @click="toggleEmailInput"></button>
</div>
<div v-if="showPhoneInput">
<label for="PhoneNumber">手机号</label>
<input type="phone" id="phone" v-model="phone" class="input-field">
<button @click="updatePhone"></button>
</div>
<div v-else>
<p>手机号{{ user.phone }}</p>
<button @click="togglePhoneInput"></button>
</div>
<div><button @click="gotoDemandList"></button></div>
<div v-if="user.membertype"><button @click="gotoServerList"></button></div>
<div><button @click="gotoLogin">退</button></div>
<div><NavigationBar /></div>
</div>
<Layout :title="title" :links="computedLinks">
<Layout :title="title" :links="computedLinks">
<div class="profile-container">
<div class="profile-background">
</div>
<div class="profile-content">
<h2>个人信息</h2>
<div class="form-group">
<label>昵称</label>
<div class="form-controls">
<input v-if="showNicknameInput" type="text" v-model="nickname" class="input-field editable-input">
<p v-else class="info-text">{{ user.nickname }}</p>
<button @click="showNicknameInput ? updateNickname() : toggleNicknameInput()" class="button">{{ showNicknameInput ? '保存' : '更换' }}</button>
</div>
</div>
<div class="form-group">
<label>邮箱</label>
<div class="form-controls">
<input v-if="showEmailInput" type="email" v-model="email" class="input-field editable-input">
<p v-else class="info-text">{{ user.email }}</p>
<button @click="showEmailInput ? updateEmail() : toggleEmailInput()" class="button">{{ showEmailInput ? '保存' : '更换' }}</button>
</div>
</div>
<div class="form-group">
<label>手机号</label>
<div class="form-controls">
<input v-if="showPhoneInput" type="tel" v-model="phone" class="input-field editable-input">
<p v-else class="info-text">{{ user.phone }}</p>
<button @click="showPhoneInput ? updatePhone() : togglePhoneInput()" class="button">{{ showPhoneInput ? '保存' : '更换' }}</button>
</div>
</div>
<div class="action-buttons">
<button @click="gotoLogin" class="button">退出登陆</button>
</div>
<div><NavigationBar /></div>
</div>
</div>
</Layout>
</Layout>
</template>
<style scoped>
/* 在这里添加样式 */
.profile h2 {
text-align: center;
margin-bottom: 20px;
}
.profile p {
margin-bottom: 10px;
font-size: 16px;
}
.editable-input {
width: 200px; /* 设置一个具体的宽度 */
margin: 0 auto; /* 上下外边距为0左右外边距自动以在父容器中居中 */
}
.form-group {
display: flex;
align-items: center;
margin-bottom: 15px; /* 调整组之间的间距 */
}
.form-group label {
flex: 0 0 100px; /* 固定标签宽度,可根据需要调整 */
}
.form-controls {
display: flex;
flex: 1;
justify-content: center; /* 使输入框和按钮之间有空间 */
align-items: center; /* 垂直居中 */
}
.form-controls .info-text {
flex: 1; /* 输入框或文本占据剩余空间 */
margin-right: 10px; /* 与按钮之间的间距 */
}
input[type="text"], textarea {
width: 100%;
padding: 8px;
margin-bottom: 5px;
border: 1px solid #ccc;
border-radius: 3px;
}
button {
padding: 10px 20px;
background-color: #28a7a3;
color: white;
border: none;
border-radius: 7px;
cursor: pointer;
}
button:hover {
background-color: #28a7a3;
}
label {
display: block;
margin-bottom: 5px;
}
</style>
<script>
import axios from 'axios';
import NavigationBar from '../components/NavigationBar.vue';
import Layout from '../components/Layout.vue';
export default {
name: 'MinePage',
components: {
Layout
},
data() {
return {
user: {},
nickname:'',
showNicknameInput: false,
phone: sessionStorage.getItem('phone') || '',
title: '个人信息',
links: [{ name: '首页', path: '/home' }, { name: '个人信息', path: '/mine' }, { name: '添加出行', path: '/addDemandPage' },{ name: '历史出行', path: '/demandList' }],
user: {
},
nickname:'',
showNicknameInput: false,
email: '',
showEmailInput: false,
phone:sessionStorage.getItem('phone') || '',
showPhoneInput: false,
idcard: '',
createtime: '',
status: 0,
reputation:60,
};
},
components: {
NavigationBar
status: 0,
reputation:60,
};
},
computed: {
computedLinks() {
//
return this.user.membertype === true
? this.links.concat([{ name: '服务发布', path: '/addServe' },{ name: '导游记录', path: '/serveList' }])
: this.links.concat([{name:'注册导游',path:'/registerGuide'}]);
}
},
mounted() {
this.fetchUser(this.phone);
},
methods: {
fetchUser(phone) {
// API
axios.get(`http://192.168.243.35:9000/users/getByPhone?phone=${phone}`)
axios.get(`/serve/users/getByPhone?phone=${phone}`)
.then(response => {
this.user = response.data
})
@ -93,7 +165,7 @@ export default {
},
updateNickname(){
this.user.nickname = this.nickname;
axios.post(`http://192.168.243.35:9000/users/Pupdate`,{user:this.user})
axios.post(`/serve/users/Pupdate`,{user:this.user})
.then(response => {
this.user.nickname = this.nickname;
this.toggleNicknameInput(); //
@ -109,7 +181,7 @@ export default {
updateEmail() {
//
this.user.email = this.email;
axios.post(`http://192.168.243.35:9000/users/Pupdate`,{user:this.user})
axios.post(`/serve/users/Pupdate`,{user:this.user})
.then(response => {
this.user.email = this.email;
this.toggleEmailInput(); //
@ -124,7 +196,7 @@ export default {
},
updatePhone(){
this.user.phone = this.phone;
axios.post(`http://192.168.243.35:9000/users/Pupdate`,{user:this.user})
axios.post(`/serve/users/Pupdate`,{user:this.user})
.then(response => {
sessionStorage.setItem('phone', this.phone);
this.user.phone = this.phone;
@ -134,17 +206,20 @@ export default {
console.error('Error updating phone:', error);
});
},
gotoChangeInfomation(){
this.$router.push('/changeInformation');
},
gotohome() {
this.$router.push('/home');
this.$router.push('/home');
},
gotomessage() {
this.$router.push('/message');
this.$router.push('/message');
},
gotoDemandList() {
this.$router.push('/demandlist');
this.$router.push('/demandlist');
},
gotoServerList() {
this.$router.push('/serverlist');
this.$router.push('/serverlist');
},
gotoLogin() {
this.$router.push('/login');

@ -1,124 +1,200 @@
<template>
<div class="return">
<button class="returnList" @click="returnList()"></button>
</div>
<h1>订单</h1>
<div class="order-details">
<h2>订单详情</h2>
<p>目的地: {{ list.city }}</p>
<p>开始时间: {{ list.departureDate }}</p>
<p>结束时间: {{ list.endDate }}</p>
<p>创建时间: {{ list.createTime }}</p>
<p>备注: {{ list.message }}</p>
<p>当前状态:
<span v-if="list.status === 0"></span>
<span v-else-if="list.status === 1">匹配中</span>
<span v-else-if="list.status === 2">匹配成功</span>
<span v-else-if="list.status === 3">已完成</span>
<span v-else></span>
</p>
<div v-if="list.status === 0">
<div><button @click="goToMatchDetail(orderId)"></button></div>
<div><button @click="goToDemandMatched(orderId)"></button></div>
<div><button @click="cancelTrip(orderId)"></button></div>
</div>
<div v-if="list.status === 1">
<div><button @click="goToMatchDetail(orderId)"></button></div>
<div><button @click="goToDemandMatched(orderId)"></button></div>
<div><button @click="cancelTrip(orderId)"></button></div>
</div>
<div v-if="list.status === 2">
<div><button @click="cancel(orderId)"></button></div>
<div><button @click="over(orderId)"></button></div>
</div>
<div><button v-if="list.status === 3" @click="goToEvaluateTrip(orderId)"></button></div>
<div><button v-if="list.status === 3" @click="deleteOrder(orderId)"></button></div>
</div>
</template>
<Layout :title="title" :links="computedLinks">
<div class="form-container">
<form class="order-form">
<div class="content-section">
<h1><i class="fas fa-map-marker-alt"></i> 订单详情</h1>
<p class="trip-info">目的地: {{ list.city }}</p>
<p class="trip-info">开始时间: {{ list.departureDate }}</p>
<p class="trip-info">结束时间: {{ list.endDate }}</p>
<p class="trip-info">创建时间: {{ list.createTime }}</p>
<p class="trip-info">订单号: {{ list.did }}</p>
<p class="trip-info">备注: {{ list.message }}</p>
<p class="status-info">
当前状态:
<span v-if="list.status === 0" class="matching"></span>
<span v-else-if="list.status === 1" class="processing">处理中</span> <!-- 修改了状态文本以区分状态1 -->
<span v-else-if="list.status === 2" class="success">匹配成功</span>
<span v-else-if="list.status === 3" class="completed">已完成</span>
<span v-else class="unknown">未知状态</span>
</p>
<style scoped>
.returnList {
/* 定义返回按钮的样式 */
position: fixed; /* 使按钮位置固定 */
top: 10px;
left: 10px;
margin: 0;
padding: 10px 20px;
border: none;
border-radius: 5px;
background-color: #ccc;
color: #333;
cursor: pointer;
}
.returnList:hover {
background-color: #aaaaaa;
}
<div v-if="list.status === 0 || list.status === 1">
<button class="action-button" @click="goToMatchDetail(orderId)"></button>
<button class="action-button" @click="goToDemandMatched(orderId)"></button>
<button class="action-button cancel-button" @click="cancelTrip(orderId)"></button>
</div>
<div v-if="list.status === 2">
<button class="action-button cancel-button" @click="cancel(orderId)"></button>
<button class="action-button complete-button" @click="over(orderId)"></button>
</div>
.order-details {
<div v-if="list.status === 3">
<button class="action-button" @click="goToEvaluateTrip(orderId)"></button>
<button class="action-button cancel-button" @click="deleteOrder(orderId)"></button>
</div>
</div>
</form>
</div>
</Layout>
</template>
<style scoped>
/* 基本布局和间距 */
.content-section {
display: flex;
flex-direction: column;
align-items: flex-start;
padding: 20px;
background-color: #f5f5f5; /* 浅灰色背景 */
border-radius: 10px;
box-shadow: 0 2px 5px rgba(0, 0, 0, 0.1); /* 阴影效果 */
align-items: flex-start;
border: 1px solid #ddd;
border-radius: 8px;
display: flex;
justify-content: center;
align-items: center;
min-height: 100vh;
line-height: 1.6;
}
.order-details h2 {
margin-bottom: 20px; /* 增加标题与内容之间的间距 */
.trip-info {
margin-bottom: 15px;
}
.order-details p {
margin-bottom: 10px; /* 增加段落之间的间距 */
}
/* 标题和图标样式 */
h1 {
font-size: 36px; /* or any size you prefer */
}
.order-details button {
margin-right: 10px; /* 增加按钮之间的间距 */
padding: 10px 20px;
/* 按钮样式 */
.action-button {
background-color: #007bff;
border: none;
border-radius: 5px;
color: white;
padding: 10px 20px;
text-align: center;
text-decoration: none;
display: inline-block;
font-size: 16px;
margin: 4px 2px;
cursor: pointer;
border-radius: 4px;
transition: background-color 0.3s;
}
.action-button:hover {
background-color: #0056b3;
}
.cancel-button, .delete-button {
background-color: #dc3545;
}
.cancel-button:hover, .delete-button:hover {
background-color: #c82333;
}
.complete-button {
background-color: #28a745;
}
.complete-button:hover {
background-color: #218838;
}
/* 状态文本样式 */
.status-info span {
margin-right: 15px;
padding: 5px 10px;
border-radius: 4px;
}
.order-details button:hover {
background-color: #ddd; /* 按钮点击时的背景色 */
.matching {
background-color: #ffc107;
color: #212529;
}
/* 根据状态为按钮添加不同的样式 */
.order-details button.cancel {
background-color: #f44336; /* 红色背景,表示取消操作 */
.processing {
background-color: #007bff;
color: white;
}
.order-details button.over {
background-color: #4CAF50; /* 绿色背景,表示完成操作 */
.success {
background-color: #28a745;
color: white;
}
.completed {
background-color: #17a2b8;
color: white;
}
.unknown {
background-color: #6c757d;
color: white;
}
/* 放大字体 */
.content-section, .trip-info, .status-info span, .action-button {
font-size: 18px;
}
.content-section {
display: flex;
flex-direction: column;
justify-content: flex-start; /* align items at the start (top) */
align-items: center;
min-height: 100vh;
line-height: 1.6;
}
.form-container {
width: 50%;
margin: 0 auto; /* Center the container horizontally */
background-color: #fff; /* White background color */
padding: 20px; /* Add some padding around the form */
}
.order-form {
width: 100%; /* Make the form occupy 100% of the container's width */
}
</style>
<script>
import axios from 'axios';
import Layout from '../components/Layout.vue';
export default {
props: ['orderId'],
components: {
Layout,
},
data() {
return {
phone: sessionStorage.getItem('phone') || '',
list: [],
};
},
return {
phone: sessionStorage.getItem('phone') || '',
list: [],
title: '订单详情',
links: [{ name: '首页', path: '/home' }, { name: '个人信息', path: '/mine' }, { name: '添加出行', path: '/addDemandPage' },{ name: '历史出行', path: '/demandList' }],
user: {
},
};
},
computed: {
computedLinks() {
//
return this.user.membertype === true
? this.links.concat([{ name: '服务发布', path: '/addServe' },{ name: '导游记录', path: '/serverList' }])
: this.links.concat([{name:'注册导游',path:'/registerGuide'}]);
}
},
async created() {
//
axios.get(`http://192.168.243.35:9000/SendDemand/demand?did=${this.orderId}`)
axios.get(`/serve/SendDemand/demand?did=${this.orderId}`)
.then(response => {
this.list = response.data
})
.catch(error => {
console.error('Error fetching user:', error);
});
},
},
methods: {
goToMatchDetail(orderId) {
this.$router.push({ name: 'MatchDetail', params: { orderId } });
@ -131,7 +207,7 @@ export default {
},
cancel(orderId) {
const did = parseInt(this.orderId, 10);
axios.post(`http://192.168.243.35:9000/DemandMatch/refuse`,{did:did})
axios.post(`/serve/DemandMatch/refuse`,{did:did})
.then(response => {
if(response.data == 1){
alert('取消成功');
@ -144,7 +220,7 @@ export default {
},
cancelTrip(orderId) {
const did = parseInt(this.orderId, 10);
axios.post(`http://192.168.243.35:9000/demands/delbyid`,{did:did})
axios.post(`/serve/demands/delbyid`,{did:did})
.then(response => {
if(response.data == 1){
alert('取消成功');
@ -157,7 +233,7 @@ export default {
},
over(orderId) {
const did = parseInt(this.orderId, 10);
axios.post(`http://192.168.243.35:9000/DemandMatch/finish`,{did:did})
axios.post(`/serve/DemandMatch/finish`,{did:did})
.then(response => {
if(response.data == 1){
location.reload();
@ -169,7 +245,7 @@ export default {
},
deleteOrder(orderId) {
const did = parseInt(this.orderId, 10);
axios.post(`http://192.168.243.35:9000/DemandMatch/delete`,{did:did})
axios.post(`/serve/DemandMatch/delete`,{did:did})
.then(response => {
if(response.data == 1){
alert('删除成功');

@ -1,79 +1,220 @@
<template>
<div>
<Return></Return>
</div>
<div>
<h1>平台导游资格申请</h1>
<form @submit.prevent="submitForm">
<div>
<label for="experience">有无相关经历:</label>
<input type="radio" id="has-experience-yes" value="true" v-model="registerToGuide.re" required>
<label for="has-experience-yes"></label>
<input type="radio" id="has-experience-no" value="false" v-model="registerToGuide.re">
<label for="has-experience-no"></label>
</div>
<div>
<label for="rsd">居住地区:</label>
<input type="text" id="rsd" v-model="registerToGuide.rsd">
</div>
<div>
<label for="familiar-area">熟悉区域:</label>
<textarea id="familiar-area" v-model="registerToGuide.fa"></textarea>
</div>
<div>
<label for="syns">个人简介:</label>
<textarea id="syns" v-model="registerToGuide.syns"></textarea>
</div>
<button @click="Submit()"></button>
</form>
</div>
</template>
<script>
<template>
<Layout :title="title" class="title" :links="computedLinks">
<div class="container">
<div class="form-group">
<label for="experience">有无相关经历:</label>
<!-- 单选按钮组使用flex布局在同一行显示并居中 -->
<div class="radio-group">
<div class="radio-label">
<input type="radio" id="has-experience-yes" value="true" v-model="registerToGuide.re" required>
<label for="has-experience-yes"></label>
</div>
<div class="radio-label">
<input type="radio" id="has-experience-no" value="false" v-model="registerToGuide.re">
<label for="has-experience-no"></label>
</div>
</div>
</div>
<div class="form-group">
<label for="rsd">居住地区:</label>
<input type="text" id="rsd" v-model="registerToGuide.rsd">
</div>
<div class="form-group">
<label for="familiar-area">熟悉区域:</label>
<textarea id="familiar-area" v-model="registerToGuide.fa"></textarea>
</div>
<div class="form-group">
<label for="syns">个人简介:</label>
<textarea id="syns" v-model="registerToGuide.syns"></textarea>
</div>
<button @click="Submit()"></button>
</div>
</Layout>
</template>
<script>
import axios from 'axios';
import Return from '../components/return.vue'
export default {
data() {
return{
registerToGuide:{
uid:0,
re: '',
rsd: '',
fa: '',
syns: '',
},
};
},
methods:{
Submit(){
axios.get(`http://192.168.243.35:9000/users/getUid?phone=${sessionStorage.getItem('phone')}`)
.then(response => {
this.registerToGuide.uid = response.data
axios.post(`http://192.168.243.35:9000/users/registerToGuide`,{registerToGuide:this.registerToGuide})
.then(response => {
if(response.data == 1){
alert("申请成功!")
this.$router.push('/addServe')
}else{
alert("申请未通过!")
}
})
.catch(error => {
console.error('Error fetching user:', error);
});
})
.catch(error => {
console.error('Error fetching user:', error);
});
}
import Layout from '../components/Layout.vue'
export default {
name: 'ApplyGuide',
data() {
return {
phone: sessionStorage.getItem('phone') || '',
title: '导游资格申请',
links: [{ name: '首页', path: '/home' }, { name: '个人信息', path: '/mine' }, { name: '添加出行', path: '/addDemandPage' }, { name: '历史出行', path: '/demandList' }],
user: {
role: 'member',
},
registerToGuide: {
uid: 0,
re: '',
rsd: '',
fa: '',
syns: '',
},
};
},
computed: {
computedLinks() {
return this.user.role === 'admin'
? this.links.concat([{ name: '服务发布', path: '/addServe' }, { name: '导游记录', path: '/serveList' }])
: this.links.concat([{ name: '注册导游', path: '/registerGuide' }]);
},
},
mounted() {
this.fetchUser(this.phone);
},
methods: {
fetchUser(phone) {
axios.get(`/serve/users/getByPhone?phone=${phone}`)
.then(response => {
this.user = response.data;
})
.catch(error => {
console.error('Error fetching user:', error);
});
},
Submit() {
axios.get(`/serve/users/getUid?phone=${this.phone}`)
.then(response => {
this.registerToGuide.uid = response.data;
axios.post(`/serve/users/registerToGuide`, { registerToGuide: this.registerToGuide })
.then(response => {
if (response.data == 1) {
alert("申请成功!");
this.$router.push('/addServe');
} else {
alert("申请未通过!");
}
})
.catch(error => {
console.error('Error posting registration:', error);
});
})
.catch(error => {
console.error('Error fetching user UID:', error);
});
},
},
components:{
Return,
components: {
Layout,
},
};
</script>
};
</script>
<style scoped>
.container {
background-color: rgba(255, 255, 255, 0.2);
}
/* 页面基础样式 */
body {
font-family: 'Arial', sans-serif;
background-color: #f5f5f5;
color: #333;
margin: 0;
padding: 0;
height: 100vh;
display: flex;
justify-content: center;
align-items: center;
}
/* 表单容器样式 */
form {
width: 100%;
height: 90vh;
<style scoped>
/* 添加你的样式 */
padding: 20px;
background: white;
border-radius: 8px;
box-shadow: 0 2px 20px rgba(0, 0, 0, 0.1);
box-sizing: border-box;
display: flex;
flex-direction: column;
align-items: center;
}
/* 表单组样式 */
.form-group {
width: 100%;
margin-bottom: 20px;
}
/* 单选按钮组样式 */
.radio-group {
display: flex;
align-items: center;
justify-content: space-between; /* 使得单选按钮平均分布在父元素中 */
width: 10%;
margin: 0 auto;
}
/* 单选按钮样式 */
.radio-label {
display: flex;
align-items: center;
margin-right: 15px; /* 单选按钮之间的间距 */
}
input[type="radio"] {
margin-right: 8px;
}
/* 输入框、文本区域样式 */
input[type="text"],
textarea {
width: 60%;
padding: 10px;
margin-bottom: 20px;
border: 1px solid #ccc;
border-radius: 4px;
font-size: 16px;
box-sizing: border-box;
margin-top: 5px; /* 调整输入框与标题的间距 */
}
/* 按钮样式 */
button {
width: 30%;
padding: 10px;
background-color: #007bff;
color: white;
border: none;
border-radius: 5px;
font-size: 18px;
cursor: pointer;
transition: background-color 0.3s ease;
margin-top: 20px;
background-image: linear-gradient(to right, #6a11cb 0%, #2575fc 100%);
}
button:hover {
background-image: linear-gradient(to right, #6a11cb 0%, #2575fc 100%);
}
label {
font-weight: bold; /* 标题加粗 */
font-size: 18px; /* 放大标题字体 */
margin-bottom: 10px; /* 标题与输入框之间的间距 */
}
/* 表单组样式调整 */
.form-group {
display: flex;
flex-direction: column;/* 标题和输入框左对齐 */
align-items: center;
width: 100%;
margin-bottom: 20px;
}
/* 单选按钮组样式调整 */
.radio-group {
width: 40%; /* 根据需要调整宽度 */
justify-content: space-around; /* 单选按钮均匀分布 */
}
/* 悬停效果、选中效果和错误信息样式保持不变 */
</style>

@ -1,7 +1,5 @@
<template>
<div class="return">
<button class="returnList" @click="returnList()"></button>
</div>
<Layout :title="title" :links="computedLinks">
<h1>订单</h1>
<div class="server-details">
<h2>订单详情</h2>
@ -35,7 +33,8 @@
<div>
<button v-if="list.status === 3" @click="deleteOrder(serverId)"></button>
</div>
</div>
</div>
</Layout>
</template>
<style scoped>
@ -60,18 +59,41 @@
<script>
import axios from 'axios';
import Layout from '../components/Layout.vue'
export default {
props: ['serverId'],
components: {
Layout,
},
data() {
return {
phone: sessionStorage.getItem('phone') || '',
list: [],
};
},
return {
phone: sessionStorage.getItem('phone') || '',
list: [],
title: '订单详情',
links: [{ name: '首页', path: '/home' }, { name: '个人信息', path: '/mine' }, { name: '添加出行', path: '/addDemandPage' },{ name: '历史出行', path: '/demandList' }],
user: {
},
};
},
computed: {
computedLinks() {
//
return this.user.membertype === true
? this.links.concat([{ name: '服务发布', path: '/addServe' },{ name: '导游记录', path: '/serverList' }])
: this.links.concat([{name:'注册导游',path:'/registerGuide'}]);
}
},
async created() {
//
axios.get(`http://192.168.243.35:9000/guideService/findbyid?gid=${this.serverId}`)
//
axios.get(`/serve/users/getByPhone?phone=${this.phone}`)
.then(response => {
this.user = response.data
})
.catch(error => {
console.error('Error fetching user:', error);
});
axios.get(`/serve/guideService/findbyid?gid=${this.serverId}`)
.then(response => {
this.list = response.data
})
@ -88,7 +110,7 @@ export default {
},
cancel(serverId) {
const gid = parseInt(this.serverId, 10);
axios.post(`http://192.168.243.35:9000/GuideMatch/refuse`,{gid:gid})
axios.post(`/serve/GuideMatch/refuse`,{gid:gid})
.then(response => {
if(response.data == 1){
alert('取消成功');
@ -101,7 +123,7 @@ export default {
},
cancelTrip(serverId) {
const gid = parseInt(this.serverId, 10);
axios.post(`http://192.168.243.35:9000/guideService/delbyid`,{gid:gid})
axios.post(`/serve/guideService/delbyid`,{gid:gid})
.then(response => {
if(response.data == 1){
alert('取消成功');
@ -114,7 +136,7 @@ export default {
},
deleteOrder(serverId) {
const gid = parseInt(this.serverId, 10);
axios.post(`http://192.168.243.35:9000/GuideMatch/delete`,{gid:gid})
axios.post(`/serve/GuideMatch/delete`,{gid:gid})
.then(response => {
if(response.data == 1){
alert('删除成功');
@ -125,9 +147,7 @@ export default {
console.error('Error fetching user:', error);
});
},
returnList() {
this.$router.push('/serverList');
}
}
};
</script>

@ -1,75 +1,128 @@
<template>
<div class="return">
<button class="returnList" @click="returnList()"></button>
</div>
<div>
<h1>订单列表</h1>
<Layout :title="title" :links="computedLinks">
<div class="order-container">
<div
v-for="(list, index) in lists"
:key="list.gid"
class="order-box"
class="order-card"
@click="goToServerDetails(list.gid)"
>
<p>目的地: {{ list.city }}</p>
<p>开始时间: {{ list.departureDate }}</p>
<p>结束时间: {{ list.endDate }}</p>
</div>
</div>
</template>
<div class="order-header">
<h3>{{ list.city }}</h3>
</div>
<div class="order-body">
<p>开始时间: {{ list.departureDate }}</p>
<p>结束时间: {{ list.endDate }}</p>
</div>
</div>
</div>
</Layout>
</template>
<script>
import axios from 'axios';
import Layout from '../components/Layout.vue';
export default {
components: {
Layout
},
data() {
return {
phone: sessionStorage.getItem('phone') || '',
lists: [],
lists: [],
title: '导游记录',
links: [{ name: '首页', path: '/home' }, { name: '个人信息', path: '/mine' }, { name: '添加出行', path: '/addDemandPage' },{ name: '历史出行', path: '/demandList' }],
user: {
},
};
},
async created() {
//
axios.get(`http://192.168.243.35:9000/SendGuideService/sendAllGuideService?phone=${this.phone}`)
.then(response => {
this.lists = response.data
})
.catch(error => {
console.error('Error fetching user:', error);
});
},
methods: {
async created() {
//
try {
const response = await axios.get(`/serve/SendGuideService/sendAllGuideService?phone=${this.phone}`);
this.lists = response.data;
} catch (error) {
console.error('Error fetching guide services:', error.response || error.message);
}
try {
const response = await axios.get(`/serve/users/getByPhone?phone=${this.phone}`);
this.user = response.data;
} catch (error) {
console.error('Error fetching user data:', error.response || error.message);
}
},
computed: {
computedLinks() {
//
return this.user.membertype === true
? this.links.concat([{ name: '服务发布', path: '/addServe' },{ name: '导游记录', path: '/serverList' }])
: this.links.concat([{name:'注册导游',path:'/registerGuide'}]);
}
},
methods: {
goToServerDetails(serverId) {
this.$router.push({ name: 'ServerDetail', params: { serverId } });
},
returnList() {
this.$router.push('/mine');
}
}
}
};
</script>
<style scoped>
.order-box {
/* 样式代码,用于美化订单盒子 */
border: 1px solid #ccc;
padding: 10px;
margin-bottom: 10px;
.trip-info p {
margin: 8px 0;
font-size: 16px;
color: #333;
}
/* 订单容器样式 */
.order-container {
display: flex;
flex-wrap: wrap;
justify-content: center;
padding: 20px;
}
/* 订单卡片样式 */
.order-card {
border: 1px solid #eaeaea;
border-radius: 10px;
margin: 10px;
padding: 20px;
background-color: #fff;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
width: calc(33% - 40px);
cursor: pointer;
transition: transform 0.3s, box-shadow 0.3s;
}
.order-card:hover {
transform: translateY(-5px);
box-shadow: 0 5px 15px rgba(0, 0, 0, 0.2);
}
/* 订单头部和内容样式 */
.order-header h3 {
margin: 0 0 10px;
font-size: 20px;
color: #007BFF;
}
.order-body {
font-size: 14px;
}
.returnList {
/* 定义返回按钮的样式 */
position: fixed; /* 使按钮位置固定 */
top: 10px;
left: 10px;
margin: 0;
padding: 10px 20px;
border: none;
border-radius: 5px;
background-color: #ccc;
color: #333;
cursor: pointer;
/* 响应式设计 */
@media (max-width: 768px) {
.order-card {
width: calc(50% - 40px);
}
}
.returnList:hover {
background-color: #aaaaaa;
@media (max-width: 480px) {
.order-card {
width: 100%;
}
}
</style>

@ -1,4 +1,8 @@
<template>
<template>
<Layout :title="title" :links="computedLinks">
<div class="back-button-container">
<button @click="goBack"></button>
</div>
<div>订单号: {{ serverId }}</div>
<div v-for="(service, index) in services" :key="service.gid" class="service-box">
<p>目的地:{{ service.city }}</p>
@ -7,25 +11,36 @@
<!-- 添加一个按钮并绑定 click 事件处理器 sendServiceId -->
<button @click="sendServiceId(service.did)"></button>
</div>
</Layout>
</template>
<script>
import axios from 'axios';
import Layout from '../components/Layout.vue';
export default {
props: ['serverId'],
props: ['serverId'],
components: {
Layout
},
data() {
return {
services: []
services: [],
phone: sessionStorage.getItem('phone') || '',
lists: [],
title: '导游记录',
links: [{ name: '首页', path: '/home' }, { name: '个人信息', path: '/mine' }, { name: '添加出行', path: '/addDemandPage' },{ name: '历史出行', path: '/demandList' }],
user: {
},
};
},
methods: {
async sendServiceId(did) {
async sendServiceId(did) {
try {
// APIgiddidPOST
const serverIdAsInt = parseInt(this.serverId, 10);
const didAsInt = parseInt(did, 10);
const response = await axios.post('http://192.168.243.35:9000/GuideMatch/match', { gid:serverIdAsInt,did:didAsInt});
const response = await axios.post('/serve/GuideMatch/match', { gid:serverIdAsInt,did:didAsInt});
alert('已向游客发送确认信息');
} catch (error) {
console.error('Error sending service ID and order ID:', error);
@ -33,8 +48,16 @@ export default {
}
},
async created() {
//
axios.get(`http://192.168.243.35:9000/GuideMatch/register?gid=${this.serverId}`)
//
axios.get(`/serve/users/getByPhone?phone=${this.phone}`)
.then(response => {
this.user = response.data
})
.catch(error => {
console.error('Error fetching user:', error);
});
axios.get(`/serve/GuideMatch/register?gid=${this.serverId}`)
.then(response => {
this.services = response.data
})
@ -46,7 +69,11 @@ export default {
</script>
<style scoped>
/* 样式代码,定义 .service-box 的样式 */
.back-button-container {
position: absolute;
top: 10px; /* 根据需要调整 */
left: 10px; /* 根据需要调整 */
}
/* 为按钮添加一些样式 */

@ -1,4 +1,5 @@
<template>
<template>
<Layout :title="title" :links="computedLinks">
<div>订单号: {{ serverId }}</div>
<div v-for="(service, index) in services" :key="service.gid" class="service-box">
<p>目的地:{{ service.city }}</p>
@ -7,16 +8,26 @@
<!-- 添加一个按钮并绑定 click 事件处理器 sendServiceId -->
<button @click="sendServiceId(service.did)"></button>
</div>
</Layout>
</template>
<script>
import axios from 'axios';
import Layout from '../components/Layout.vue';
export default {
props: ['serverId'],
props: ['serverId'],
components: {
Layout,
},
data() {
return {
services: []
services: [],
phone: sessionStorage.getItem('phone') || '',
title: '首页',
links: [{ name: '首页', path: '/home' }, { name: '个人信息', path: '/mine' }, { name: '添加出行', path: '/addDemandPage' },{ name: '历史出行', path: '/demandList' }],
user: {
},
};
},
methods: {
@ -25,16 +36,32 @@ export default {
// APIgiddidPOST
const serverIdAsInt = parseInt(this.serverId, 10);
const didAsInt = parseInt(did, 10);
const response = await axios.post('http://192.168.243.35:9000/GuideMatch/confirmed', { gid:serverIdAsInt,did:didAsInt});
const response = await axios.post('/serve/GuideMatch/confirmed', { gid:serverIdAsInt,did:didAsInt});
alert('已接单');
} catch (error) {
console.error('Error sending service ID and order ID:', error);
}
}
},
computed: {
computedLinks() {
//
return this.user.membertype === true
? this.links.concat([{ name: '服务发布', path: '/addServe' },{ name: '导游记录', path: '/serverList' }])
: this.links.concat([{name:'注册导游',path:'/registerGuide'}]);
}
},
async created() {
//
axios.get(`http://192.168.243.35:9000/GuideMatch/register?gid=${this.serverId}`)
axios.get(`/serve/users/getByPhone?phone=${this.phone}`)
.then(response => {
this.user = response.data
})
.catch(error => {
console.error('Error fetching user:', error);
});
axios.get(`/serve/GuideMatch/register?gid=${this.serverId}`)
.then(response => {
this.services = response.data
})

@ -0,0 +1,103 @@
<template>
<div class="user-feedback">
<!-- 输入评价 -->
<div class="feedback-input">
<h2>意见反馈</h2>
<form>
<textarea id="ebody" v-model.trim="ebody" rows="4" cols="50" placeholder="在这里输入您的使用意见"></textarea>
<button type="submit" @click="send"></button>
</form>
</div>
<el-space direction="vertical">
<el-row>
<el-text>星级评价</el-text>
<el-rate class="ml-1"
v-model="satisfaction"
:texts="['oops', 'disappointed', 'normal', 'good', 'great']"
show-text
@change="handleRateChange"
clearable />
</el-row>
</el-space>
</div>
</template>
<script>
import axios from 'axios';
export default {
data() {
return {
user: {},
eid: '',
ebody: '',
satisfaction:'',
};
},
methods: {
send() {
axios.post('http://106.52.218.118:8081/evaluate/addEvaluation', {
eid : 1,
satisfaction :this.satisfaction,
ebody :this.ebody,
}, {
// cookie
withCredentials: true,
// JSON
headers: {
'Content-Type': 'application/json'
}
})
},
handleRateChange(){
this.satisfaction = satisfaction; //
}
}
};
</script>
<style scoped>
.user-feedback {
max-width: 600px;
margin: 0 auto;
}
.feedback-input {
margin-bottom: 20px;
}
textarea {
width: 100%;
padding: 8px;
font-size: 16px;
border: 1px solid #28a7a3;
border-radius: 4px;
margin-bottom: 10px;
}
button {
padding: 8px 16px;
font-size: 16px;
border: none;
border-radius: 4px;
background-color: #007bff;
color: #003f3f;
cursor: pointer;
}
.submitted-feedback {
border-top: 1px solid #a6cfee;
padding-top: 20px;
}
.feedback-item {
background-color: #abd4ee;
border: 1px solid #c2f1fb;
border-radius: 4px;
padding: 10px;
}
.feedback-item p {
margin: 0;
}
</style>

@ -3,17 +3,12 @@ import Login from '../pages/Login.vue';
import Register from '../pages/Register.vue';
import Home from '../pages/HomePage.vue';
import Mine from '../pages/mine.vue';
import SearchPage from '../pages/searchPage.vue';
import Test from '../pages/test.vue'
import Communication from '../pages/Communication.vue'
import Pay from '../pages/Pay.vue';
import AddDemand from '../pages/addDemand.vue';
import DemandList from '../pages/DemandList.vue';
import Evaluation from '../pages/Evaluation.vue';
import SecurityVerification from '../pages/SecurityVerification.vue';
import RegisterGuide from '../pages/registerGuide.vue';
import AddServe from '../pages/addServe.vue';
import EvaluationList from '../pages/EvaluationList.vue';
import Order from '../pages/order.vue';
import MatchDetail from'../pages/DemandMatch.vue'
import ChangeInformation from'../pages/changeInformation.vue'
@ -29,17 +24,12 @@ const routes = [
{ path: '/register', component: Register },
{ path: '/home', component: Home },
{ path: '/mine', component: Mine },
{ path: '/searchPage', component: SearchPage },
{ path: '/addDemandPage', component: AddDemand },
{ path: '/test', component: Test },
{ path: '/message', component: Communication },
{ path: '/pay', component:Pay},
{ path: '/demandlist', name: 'DemandList', component:DemandList},
{ path: '/evaluation/:orderId',name: 'Evaluation', component:Evaluation,props: (route) => ({ orderId: route.params.orderId })},
{ path: '/SecurityVerification', component:SecurityVerification},
{ path: '/registerGuide', component:RegisterGuide},
{ path:'/addServe', component:AddServe},
{ path: '/evaluationList', component:EvaluationList},
{ path: '/order/:orderId', name: 'OrderDetails', component: Order, props: (route) => ({ orderId: route.params.orderId })},
{ path: '/MatchDetail/:orderId', name: 'MatchDetail',component: MatchDetail,props: (route) => ({ orderId: route.params.orderId })},
{ path: '/changeInformation', component:ChangeInformation},

@ -0,0 +1,25 @@
import { fileURLToPath, URL } from 'node:url'
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
// https://vitejs.dev/config/
export default defineConfig({
plugins: [
vue(),
],
resolve: {
alias: {
'@': fileURLToPath(new URL('./src', import.meta.url))
}
},
server: {
proxy: {
'/serve': {
target: 'http://192.168.205.145:8080', // 替换为您要代理到的目标地址
changeOrigin: true, // 允许跨域
rewrite: (path) => path.replace(/^\/serve/, '') // 重写路径
}
}
}
})
Loading…
Cancel
Save