Compare commits

..

81 Commits

Author SHA1 Message Date
zhanglinhao 547b61315e 最终ppt
2 years ago
zhanglinhao b6b7400b9b 更新ppt
2 years ago
zhanglinhao 91c51c5fbd 修改ppt
2 years ago
zhanglinhao bbc5dc4227 更新文档和ppt
2 years ago
zhanglinhao 89c2fba28a 最新后端代码
2 years ago
zhanglinhao bfa49ec0eb 修复后端代码
2 years ago
zhanglinhao 5fdb68fa9c 上传宣传视频
2 years ago
zhanglinhao db3b54eac6 Merge branch 'master' of bdgit.educoder.net:mwxbgi697/softegg
2 years ago
zcx bbba1c5420 最新版
2 years ago
zhanglinhao 79b858112b Merge branch 'master' of bdgit.educoder.net:mwxbgi697/softegg
2 years ago
zhanglinhao c5a815b054 更新后端代码
2 years ago
zcx 5a799f95c5 设计文档
2 years ago
zhanglinhao bb9bad6335 Merge branch 'master' of bdgit.educoder.net:mwxbgi697/softegg
2 years ago
zhanglinhao 02d678f8d8 更新ppt
2 years ago
zcx 92ff810b93 Merge branch 'master' of https://bdgit.educoder.net/mwxbgi697/softegg
2 years ago
zcx 52baa344c5 设计文档
2 years ago
zhanglinhao 1a0d65c725 Merge branch 'master' of bdgit.educoder.net:mwxbgi697/softegg
2 years ago
zhanglinhao f72a51e34f 修改ppt
2 years ago
房孝庭 fbadcc2cae Merge branch 'master' of https://bdgit.educoder.net/mwxbgi697/softegg
2 years ago
房孝庭 2ee3d6f894 修改两个自评报告
2 years ago
zhanglinhao 7e6e07eb0e 更新模型
2 years ago
房孝庭 4aebe6d916 修改软件设计规格说明书
2 years ago
zcx 759274239b 自评报告
2 years ago
zcx 2c6cf04da8 Merge branch 'master' of https://bdgit.educoder.net/mwxbgi697/softegg
2 years ago
zcx 5ebd78ff3c 个人自评报告
2 years ago
zhanglinhao 642dceb244 提交ppt
2 years ago
zhanglinhao bf6cbe7dae 改图
2 years ago
zhanglinhao 5ec51aafa9 上传海报
2 years ago
zhanglinhao 5ba00916b6 Merge branch 'master' of bdgit.educoder.net:mwxbgi697/softegg
2 years ago
zhanglinhao e2014de19e update
2 years ago
wuyifan 70ce44ad44 后端代码
2 years ago
wuyifan 04bdb19ec9 更新
2 years ago
wuyifan da67fe8884 回退
2 years ago
wuyifan 991b3c3b61 Revert "修改"
2 years ago
wuyifan 346e939e4f 修改
2 years ago
wuyifan 8299139603 代码修改
2 years ago
zhanglinhao 8b7bee7c1d 更新
2 years ago
zhanglinhao 510d8db779 更新自评报告
2 years ago
zhanglinhao f800550ada 更新自评报告
2 years ago
zhanglinhao 383a9111cd Merge branch 'master' of bdgit.educoder.net:mwxbgi697/softegg
2 years ago
zhanglinhao a2373dffb3 提交自评报告
2 years ago
房孝庭 d5bdc148e5 Merge branch 'master' of https://bdgit.educoder.net/mwxbgi697/softegg
2 years ago
房孝庭 79475227ad 1
2 years ago
wuyifan 7e69ad3848 后端代码补充
2 years ago
zhanglinhao 8fb4fbcccc 删除多余代码
2 years ago
zhanglinhao 8e77ed74cb Merge branch 'master' of bdgit.educoder.net:mwxbgi697/softegg
2 years ago
zhanglinhao 512de5ad7d 重命名文档
2 years ago
房孝庭 6d63961541 1
2 years ago
a3197878436@163.com 9eb3a3a341 1
2 years ago
a3197878436@163.com 0fa783bd1b 1
2 years ago
a3197878436@163.com 6c75e5562f 1
2 years ago
a3197878436@163.com 3cdd46dd80 1
2 years ago
a3197878436@163.com 28a36bb26c 1
2 years ago
a3197878436@163.com 93177199db 1
2 years ago
a3197878436@163.com 28c47a51ca 1
2 years ago
a3197878436@163.com 7feccda1d0 1
2 years ago
15616168609 1d900ab370 1
2 years ago
15616168609 a6db9c05d6 Merge branch 'master' of https://bdgit.educoder.net/mwxbgi697/softegg
2 years ago
15616168609 2d2aabcbc3 1
2 years ago
mafc2zqui 3420b94b0c ADD file via upload
2 years ago
mafc2zqui 3f53a7e490 ADD file via upload
2 years ago
“fangxiaoting” 830dfe5e4a 前端代码
2 years ago
“fangxiaoting” bef6b8433e Merge branch 'master' of https://bdgit.educoder.net/mwxbgi697/softegg
2 years ago
“fangxiaoting” a6cfa1b58f 1
2 years ago
“fangxiaoting” 11ca1b0560 1
2 years ago
“fangxiaoting” 459b1e2d9d 1
2 years ago
“fangxiaoting” b61e1370f7 1
2 years ago
mafc2zqui aa86338860 Add 前端
2 years ago
“fangxiaoting” 78c8592922 删除原代码
2 years ago
mafc2zqui 6cc844c2d6 ADD file via upload
2 years ago
zhanglinhao 49bf7c57d7 提交张林浩的代码
2 years ago
zhanglinhao ad3e007dfa 删除旧版本代码
2 years ago
zcx 98079dcf40 文档修改
2 years ago
mwxbgi697 80f92e6114 Delete 'src/后端/src/main/java/com/softegg/freetogo/UsersController.java'
2 years ago
mwxbgi697 9f984bcffb Delete 'src/后端/src/main/java/com/softegg/freetogo/Users.java'
2 years ago
mwxbgi697 191c450657 Delete 'src/后端/src/main/java/com/softegg/freetogo/UserServiceImpl.java'
2 years ago
mwxbgi697 fd52484673 Delete 'src/后端/src/main/java/com/softegg/freetogo/UsersRepository.java'
2 years ago
mwxbgi697 c3a76e62be Delete 'src/后端/src/main/java/com/softegg/freetogo/UsersService.java'
2 years ago
mwxbgi697 a35a1f82f7 Delete 'src/后端/src/main/java/com/softegg/freetogo/Login.zip'
2 years ago
mwxbgi697 1d75cfe581 Merge pull request '更新文档' (#7) from develop into master
2 years ago
mwxbgi697 f9889025cd Merge pull request '提交' (#6) from develop into master
2 years ago

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 MiB

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 475 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 270 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 945 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 210 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 574 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 64 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 730 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 74 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 39 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 543 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 632 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 745 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 41 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 174 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 760 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 64 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 31 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 445 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 40 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 217 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 41 KiB

@ -0,0 +1,13 @@
[*]
charset = utf-8
end_of_line = crlf
indent_size = 4
indent_style = space
insert_final_newline = false
tab_width = 4
[*.vue]
indent_size = 2
tab_width = 2
ij_vue_indent_children_of_top_level = template, script, style

@ -0,0 +1,30 @@
# 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
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?
*.tsbuildinfo

@ -0,0 +1,29 @@
# walktofree
This template should help get you started developing with Vue 3 in Vite.
## Recommended IDE Setup
[VSCode](https://code.visualstudio.com/) + [Volar](https://marketplace.visualstudio.com/items?itemName=Vue.volar) (and disable Vetur).
## Customize configuration
See [Vite Configuration Reference](https://vitejs.dev/config/).
## Project Setup
```sh
npm install
```
### Compile and Hot-Reload for Development
```sh
npm run dev
```
### Compile and Minify for Production
```sh
npm run build
```

@ -0,0 +1,5 @@
module.exports = {
presets: [
'@vue/cli-plugin-babel/preset'
]
}

@ -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>

@ -0,0 +1,8 @@
{
"compilerOptions": {
"paths": {
"@/*": ["./src/*"]
}
},
"exclude": ["node_modules", "dist"]
}

File diff suppressed because it is too large Load Diff

@ -0,0 +1,27 @@
{
"name": "walktofree",
"version": "0.0.0",
"private": true,
"type": "module",
"scripts": {
"dev": "vite",
"build": "vite build",
"preview": "vite preview"
},
"dependencies": {
"@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": {
"@vitejs/plugin-vue": "^5.0.4",
"@vue/cli-service": "^5.0.8",
"vite": "^5.2.8"
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

@ -0,0 +1,17 @@
<!DOCTYPE html>
<html lang="">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<link rel="icon" href="<%= BASE_URL %>favicon.ico">
<title><%= htmlWebpackPlugin.options.title %></title>
</head>
<body>
<noscript>
<strong>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
</noscript>
<div id="app"></div>
<!-- built files will be auto injected -->
</body>
</html>

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>

@ -1,6 +1,6 @@
import axios from 'axios'
const baseURL = 'https:106.52.218.118:12607'
const baseURL = 'http://192.168.243.35:9000'
export const login = (data) => {
return axios.post(`${baseURL}/Login/login`, data)

Before

Width:  |  Height:  |  Size: 276 B

After

Width:  |  Height:  |  Size: 276 B

@ -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>

@ -56,13 +56,12 @@
flex: 1;
border: none;
padding: 10px;
background-color: #ccc;
background-color: #d5d5d5;
color: #333;
cursor: pointer;
}
.footer-nav button:hover {
/* 按钮点击时的样式 */
background-color: #bbb;
.button-with-icon:hover {
background-color: #aaaaaa;
}
</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>

@ -0,0 +1,27 @@
<template>
<div>
<el-carousel :interval="4000" arrow="always">
<el-carousel-item v-for="(item, index) in imagePaths" :key="index">
<img :src="item" alt = "描述图像的文本">
</el-carousel-item>
</el-carousel>
</div>
</template>
<script>
import { ref } from 'vue';
export default {
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'
]);
return {
imagePaths
};
}
};
</script>

@ -32,7 +32,7 @@ const gotoRegisterGuide = () => {
}
const isGuide = () => {
axios.get(`http://106.52.218.118:8081/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,76 @@
<template>
<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>
<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

Before

Width:  |  Height:  |  Size: 787 KiB

After

Width:  |  Height:  |  Size: 787 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 223 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 406 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.4 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 208 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 MiB

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

@ -4,9 +4,14 @@ import router from './router';
import ElementPlus from 'element-plus';
import 'element-plus/theme-chalk/index.css';
import VueDatePicker from '@vuepic/vue-datepicker';
import '@vuepic/vue-datepicker/dist/main.css';
import '@vuepic/vue-datepicker/dist/main.css'
import * as ElementPlusIconsVue from '@element-plus/icons-vue'
const app = createApp(App);
for (const [key, component] of Object.entries(ElementPlusIconsVue)) {
app.component(key, component)
}
app.use(ElementPlus);
app.use(router);
app.component('VueDatePicker', VueDatePicker);

@ -0,0 +1,167 @@
<template>
<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>
</template>
<style>
*{
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;
}
h1 {
font-size: 1.5rem;
}
.nav {
background-color: #2b3642;
width: 100px;
height: 95vh;
margin: 0;
padding: 0;
}
.nav ul {
padding: 1rem;
list-style-type: none;
}
.nav li {
margin-bottom: 1rem;
}
.nav li a {
display: block;
color: white;
padding: 0.5rem 1rem;
transition: background-color 0.3s;
}
.nav li a:hover, .active {
background-color: #8bb9ed;
}
.el-main {
padding: 1rem;
overflow-y: auto;
flex-grow: 1;
}
@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>

@ -0,0 +1,131 @@
<template>
<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;
}
/* 订单容器样式 */
.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;
}
/* 响应式设计 */
@media (max-width: 768px) {
.order-card {
width: calc(50% - 40px);
}
}
@media (max-width: 480px) {
.order-card {
width: 100%;
}
}
</style>

@ -0,0 +1,112 @@
<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>
</div>
<button class="send-button" @click="sendServiceId(service.gid)"></button>
</div>
</div>
</Layout>
</template>
<style scoped>
/* 为按钮添加一些样式 */
.send-button {
display: block;
margin-left: auto; /* 将按钮推到右侧 */
margin-top: 10px; /* 顶部添加一些间距 */
padding: 5px 10px; /* 内边距 */
border: none; /* 移除边框 */
border-radius: 4px; /* 添加圆角 */
background-color: #4CAF50; /* 背景色 */
color: white; /* 文字颜色 */
cursor: pointer; /* 鼠标悬停时显示小手 */
transition: background-color 0.3s ease; /* 添加背景色过渡效果 */
}
.send-button:hover {
background-color: #45a049; /* 鼠标悬停时改变背景色 */
}
/* 为服务信息盒子添加样式 */
.service-box {
border: 1px solid #ccc;
padding: 15px;
margin-bottom: 15px;
background-color: #fff; /* 添加背景色 */
box-shadow: 0 2px 5px rgba(0, 0, 0, 0.1); /* 添加阴影效果 */
border-radius: 5px; /* 添加圆角 */
}
/* 为昵称和结束日期添加样式 */
.service-info {
display: flex;
justify-content: space-between; /* 内容两端对齐 */
align-items: center; /* 内容垂直居中 */
}
.nickname, .end-date {
margin: 0; /* 移除默认的外边距 */
}
</style>
<script>
import axios from 'axios';
import Layout from '../components/Layout.vue';
export default {
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('/serve/DemandMatch/match', { did:orderIdAsInt,gid:gidAsInt});
alert('已向导游发送确认信息');
} catch (error) {
console.error('Error sending service ID and order ID:', error);
}
}
},
async created() {
//
axios.get(`/serve/DemandMatch/register?did=${this.orderId}`)
.then(response => {
this.services = response.data
})
.catch(error => {
console.error('Error fetching user:', error);
});
}
};
</script>

@ -1,8 +1,9 @@
<template>
<Layout :title="title" :links="computedLinks">
<div class="user-feedback">
<!-- 输入评价 -->
<div class="feedback-input">
<h2>修改你的评价</h2>
<h2>行程评价</h2>
<form>
<textarea id="ebody" v-model.trim="evaluation.ebody" rows="4" cols="50"></textarea>
<button type="submit" @click="send"></button>
@ -20,27 +21,44 @@
</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:'',
ct:'',
eid: 1, // eid
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://106.52.218.118:8081/evaluate/editEvaluation', {
eid: this.eid, // eid
axios.post('/serve/evaluate/addEvaluation', {
did: this.orderId,
satisfaction: this.evaluation.satisfaction,
ct:this.evaluation.ct,
ebody: this.evaluation.ebody,
}, {
withCredentials: true,
@ -49,14 +67,21 @@ export default {
}
}).then(response => {
//
console.log('评价发送成功');
location.reload();
}).catch(error => {
//
console.error('评价发送失败', error);
});
},
fetchEvaluation() {
axios.get(`http://106.52.218.118:8081/evaluate/getEvaluation?eid=${this.eid}`)
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
})

@ -0,0 +1,94 @@
<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>
.scrollbar-demo-item {
display: flex;
align-items: center;
justify-content: center;
height: 50px;
margin: 10px;
text-align: center;
border-radius: 4px;
background: var(--el-color-primary-light-9);
color: var(--el-color-primary);
}
.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>
<script lang="ts" setup>
import { ref } from 'vue'
const count = ref(3)
const reviews = ref([
{ id: 1, content: 'Great product!' },
{ id: 2, content: 'Fast shipping!' },
{ id: 3, content: 'Excellent customer service!' }
])
const add = () => {
count.value++
}
const onDelete = () => {
if (count.value > 0) {
count.value--
}
}
</script>

@ -0,0 +1,191 @@
<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 {
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>

@ -0,0 +1,158 @@
<template>
<div class="login-container">
<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>
<script>
import axios from "axios";
export default {
data() {
return {
phone: '',
password: ''
}
},
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('/serve/Login/login', {
//
phone: this.phone,
password: this.password
}, {
// cookie
withCredentials: true,
// JSON
headers: {
'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('登录失败:网络错误或服务器错误');
});
},
},
};
</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;
}
</style>

@ -0,0 +1,195 @@
<template>
<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 {
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: 10px;
width: 100%;
border: 1px solid #000000;
border-radius: 5px;
}
.submit-button {
padding: 10px 20px;
margin-top: 20px;
background-color: #007bff;
color: #fff;
border: none;
border-radius: 5px;
cursor: pointer;
}
.submit-button:hover {
background-color: #003f3f;
}
.login-link {
margin-top: 20px;
text-align: center;
color: #000000;
}
</style>
<script>
import axios from "axios";
import { regionData } from 'element-china-area-data'
export default {
data() {
return {
phone: '',
password: '',
name:'',
nickname:'',
IDcard:'',
confirmPassword: '',
email: '',
place: '',
passwordsMatch: false,
selectedOptions: [],
options: regionData
}
},
methods:{
applyBlur() {
this.$refs.background.style.filter = 'blur(5px)';
},
removeBlur() {
this.$refs.background.style.filter = 'none';
},
register() {
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("网络或服务器错误");
})
}
},
handleChange(value, selectedData) {
console.log(value, selectedData);
}
}
}
</script>

@ -4,37 +4,37 @@
<!-- 身份证号验证 -->
<div class="verification-item">
<label for="idCard">身份证号</label>
<input type="text" id="idCard" v-model.trim="IDcard" placeholder="请输入身份证号">
<p v-if="IDcard !== ''" class="invalid-message"></p>
<input type="text" id="idCard" v-model.trim="idCard" placeholder="请输入身份证号">
<button @click="verifyIdCard" :disabled="loading">验证</button>
<p v-if="idCardValid" class="valid-message"></p>
<p v-else-if="idCard !== ''" class="invalid-message">请输入有效的身份证号</p>
</div>
<!-- 银行卡号验证 -->
<div class="verification-item">
<label for="name">姓名</label>
<input type="text" id="name" v-model.trim="name" placeholder="请输入姓名">
<p v-if="name !== ''" class="invalid-message"></p>
<label for="bankCard">银行卡号</label>
<input type="text" id="bankCard" v-model.trim="bankCard" placeholder="请输入银行卡号">
<button @click="verifyBankCard" :disabled="loading">验证</button>
<p v-if="bankCardValid" class="valid-message"></p>
<p v-else-if="bankCard !== ''" class="invalid-message">请输入有效的银行卡号</p>
</div>
<p v-if="error" class="error-message">{{ error }}</p>
</div>
<button @click="verify" :disabled="loading">验证</button>
<p v-if="idCardValid && nameValid" class="valid-message"></p>
</template>
<script>
export default {
data() {
return {
IDcard: '',
IDcardValid: false,
name: '',
nameValid: false,
idCard: '',
idCardValid: false,
bankCard: '',
bankCardValid: false,
loading: false,
error: ''
};
},
methods: {
verify() {
verifyIdCard() {
this.loading = true;
//
setTimeout(() => {
@ -48,7 +48,20 @@ export default {
this.loading = false;
}, 1000); // 1
},
verifyBankCard() {
this.loading = true;
//
setTimeout(() => {
if (/^\d{16,19}$/.test(this.bankCard)) {
this.bankCardValid = true;
this.error = '';
} else {
this.bankCardValid = false;
this.error = '请输入有效的银行卡号!';
}
this.loading = false;
}, 1000); // 1
}
}
};
</script>

@ -0,0 +1,223 @@
<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);
}
};
//
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>
<label for="user-input"></label>
<input type="text" id="remark" v-model="remark" placeholder="请输入备注信息">
</div>
<el-button type="primary" @click="publish"></el-button>
</Layout>
</template>
<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>

@ -0,0 +1,194 @@
<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 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 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(`/serve/SendGuideService/register`,{phone:sessionStorage.getItem('phone') || '',city:city.value,time:rangeValue.value,remark:remark.value})
.then(response => {
alert("发布成功")
})
.catch(error => {
console.error('发布失败', error);
});}
else{
alert("请输入目的地")
}
};
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 = []; //
}
}
});
// 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>
<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 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>

@ -0,0 +1,131 @@
<template>
<div><button class="back-button" @click="goBack"></button></div>
<div class="profile-edit">
<h2>修改个人信息</h2>
<form @submit.prevent="updateProfile">
<div>
<label for="nickname">昵称</label>
<input type="text" id="nickname" v-model="userInfo.nickname" class="input-field">
</div>
<div>
<label for="email">邮箱</label>
<input type="email" id="email" v-model="userInfo.email" class="input-field">
</div>
<div>
<label for="phone">手机号</label>
<input type="tel" id="phone" v-model="userInfo.phone" class="input-field">
</div>
<div>
<label for="password">个人简介</label>
<input type="text" id="brief" v-model="userInfo.brief" class="input-field">
</div>
<button type="submit">保存</button>
</form>
<div v-if="message" class="message">{{ message }}</div>
</div>
</template>
<script>
import axios from 'axios';
export default {
data() {
return {
userInfo: { },
message: '',
phone:sessionStorage.getItem('phone') || '',
};
},
mounted() {
this.fetchUser(this.phone);
},
methods: {
fetchUser(phone) {
// API
axios.get(`/serve/users/getByPhone?phone=${phone}`)
.then(response => {
this.userInfo = response.data
})
.catch(error => {
console.error('Error fetching user:', error);
});
},
updateProfile() {
//
axios.post(`/serve/users/Pupdate`,{user:this.userInfo})
.then(response => {
})
.catch(error => {
console.error('Error updating nickname:', error);
});
this.message = '个人信息更新成功!';
//
//
setTimeout(() => {
this.message = '';
}, 2000);
},
goBack(){
this.$router.push('/mine')
}
},
};
</script>
<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;
padding: 20px;
border: 1px solid #ddd;
border-radius: 5px;
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
}
.input-field {
margin-bottom: 10px;
padding: 5px;
border: 1px solid #ccc;
border-radius: 3px;
}
button {
display: inline-block;
padding: 5px 10px;
margin-top: 10px;
background-color: #4CAF50;
color: white;
border: none;
border-radius: 4px;
cursor: pointer;
transition: background-color 0.3s;
}
button:hover {
background-color: #45a049;
}
.message {
color: #333;
margin-top: 10px;
text-align: center;
}
</style>

@ -0,0 +1,248 @@
<script setup>
// request
import {
getBaseUrl,
requestUtil
} from '../../utils/requestUtil.js';
Page({
/**
* 页面的初始数据
*/
data: {
baseUrl: '',
cart:[],
address:{},
totalPrice:0,
totalNum:0
},
/**
* 生命周期函数--监听页面加载
*/
onLoad: function (options) {
const baseUrl=getBaseUrl();
this.setData({
baseUrl
})
},
/**
* 生命周期函数--监听页面显示
*/
onShow: function () {
console.log("show")
const address=wx.getStorageSync('address');
let cart=wx.getStorageSync('cart')||[];
//
cart=cart.filter(v=>v.checked);
let totalPrice=0;
let totalNum=0;
cart.forEach(v=>{
totalPrice+=v.num*v.price;
totalNum+=v.num;
})
this.setData({
cart,
address,
totalNum,
totalPrice
})
}
})
</script>
<template>
<!-- 收货地址 开始 -->
<view class="revice_address_row">
<view class="user_info">
<view class="user_info_item">{{address.provinceName+address.cityName+address.countyName}}</view>
<view class="user_info_item user_info_detail">{{address.detailInfo}}</view>
<text class="user_info_item" decode="{{true}}">{{address.userName}}&nbsp;&nbsp;{{address.telNumber}}</text>
</view>
</view>
<!-- 收货地址 结束 -->
<!-- 购物车清单 开始 -->
<view class="cart_content">
<view class="cart_main">
<view class="cart_item"
wx:for="{{cart}}"
wx:key="id"
>
<!-- 商品图片 开始 -->
<navigator class="cart_img_warp" url="/pages/product_detail/index?id={{item.id}}">
<image mode="widthFix" src="{{baseUrl+'/image/product/'+item.proPic}}"></image>
</navigator>
<!-- 商品图片 结束 -->
<!-- 商品信息 开始 -->
<view class="cart_info_warp">
<navigator url="/pages/product_detail/index?id={{item.id}}">
<view class="goods_name">{{item.name}}</view>
</navigator>
<view class="goods_price_warp">
<view class="goods_price">¥ {{item.price}}</view>
<view class="cart_num_tool">
<view class="goods_num">×{{item.num}}</view>
</view>
</view>
</view>
<!-- 商品信息 结束 -->
</view>
</view>
</view>
<!-- 购物车清单 结束 -->
<!-- 底部工具类 开始 -->
<view class="footer_tool">
<!-- 总价格 开始 -->
<view class="total_price_wrap">
<view class="total_price">
{{totalNum}}合计<text class="total_price_text" decode="{{true}}">&nbsp;¥ {{totalPrice}}</text>
</view>
</view>
<!-- 总价格 结束 -->
<!-- 结算 开始 -->
<view class="order_pay_wrap" bindtap="handlePay">
去付款
</view>
<!-- 结算 结束 -->
</view>
<!-- 底部工具类 结束 -->
</template>
<style scoped>
page{
padding-bottom: 70rpx;
}
.revice_address_row{
border-bottom: 1rpx dotted gray;
padding: 20rpx;
.user_info{
.user_info_item{
margin-top: 10rpx;
}
.user_info_detail{
font-size: 20px;
font-weight: bolder;
margin-bottom: 10rpx;
}
}
}
.cart_content{
background-color: #F5F5F5;
.cart_main{
padding: 2rpx 10rpx 10rpx 10rpx;
.cart_item{
display: flex;
background-color: white;
border-radius: 10px;
margin: 20rpx;
padding-right: 20rpx;
.cart_img_warp{
flex:2;
display: flex;
justify-content: center;
align-items: center;
margin: 20rpx;
border-radius: 10px;
background-color: #F5F5F5;
image{
width: 80%;
}
}
.cart_info_warp{
flex:4;
display: flex;
flex-direction: column;
justify-content: space-around;
navigator{
.goods_name{
font-weight: bolder;
display: -webkit-box;
overflow: hidden;
-webkit-box-orient: vertical;
-webkit-line-clamp: 2;
}
}
.goods_price_warp{
display: flex;
justify-content: space-between;
.goods_price{
color:var(--themeColor);
font-size:34rpx;
}
.cart_num_tool{
display: flex;
.goods_num{
display: flex;
justify-content: center;
align-items: center;
}
}
}
}
}
}
}
.footer_tool{
display: flex;
width: 100%;
height: 90rpx;
background-color: #fff;
border-top: 1px solid #ccc;
position: fixed;
bottom: 0;
left: 0;
padding-left: 30rpx;
.total_price_wrap{
flex:5;
display: flex;
align-items: center;
.total_price{
.total_price_text{
color:var(--themeColor);
font-size: 34rpx;
font-weight: bold;
}
}
}
.order_pay_wrap{
flex:3;
display: flex;
justify-content: center;
align-items: center;
background-image: linear-gradient(90deg,#FF740B,#FE6227);
margin: 10rpx;
color:#fff;
font-weight: 600;
font-size: 32rpx;
border-radius: 20px;
}
}
</style>

@ -1,4 +1,5 @@
<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,17 +7,35 @@
<!-- 添加一个按钮并绑定 click 事件处理器 sendServiceId -->
<button @click="sendServiceId(service.gid)"></button>
</div>
</Layout>
</template>
<script>
import axios from 'axios';
import Layout from '../components/Layout.vue';
export default {
props: ['orderId'],
components: {
Layout,
},
data() {
return {
services: []
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) {
@ -24,7 +43,7 @@ export default {
// 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
})

@ -0,0 +1,146 @@
<script setup>
</script>
<template>
<view class="order">
<!-- 背景图片 -->
<view class="background">
<image src="../../static/background/background.jfif"></image>
</view>
<!-- 订单列表 -->
<view class="order_item" v-for="(item,index) in orderList" :key="item.supplier_order_id" @click="navToOrderDetail(item.supplier_order_id)">
<view class="shop"> <!-- 商铺名称 -->
<image src="../../static/order-icon/shop.png"></image>
<view class="shop_name">{{item.super_user_name}}</view>
</view>
<view class="order_info"> <!-- 商铺信息 -->
<view>联系电话{{item.super_phone}}</view>
<view>联系地址{{item.super_address}}</view>
<view>订单时间{{item.supplier_order_createdate | formatDate}}</view>
<view v-if="orderList[index].supplier_goods_price">{{item.supplier_goods_price}}</view>
<view v-if="orderList[index].supplier_goods_amount">{{item.supplier_goods_amount}}</view>
</view>
<view class="line"></view> <!-- 分割线 -->
</view>
</view>
</template>```
```javascript
<script>
export default {
data() {
return {
//
orderList: [],
}
},
methods: {
//
async getOrder() {
const res = await this.$myRequest({
url: '/order/getOrderBySupplierId',
method: 'POST',
data: JSON.stringify({
supplier_id: uni.getStorageSync('supplier_id')
})
})
this.orderList = res.data.data
//
for(let i=0;i<this.orderList.length;i++) {
//
let res2 = await this.$myRequest({
url: '/order/getSingleOrderBySupplierGoodsId',
method: 'POST',
data: JSON.stringify({
supplier_order_id: this.orderList[i].supplier_order_id
})
})
//
let orderDetail = res2.data.data
let order_all_price = 0
let order_all_amount = 0
for(let j=0;j<orderDetail.length;j++) {
order_all_price = order_all_price + orderDetail[j].supplier_goods_price * orderDetail[j].supplier_goods_amount
order_all_amount = order_all_amount + orderDetail[j].supplier_goods_amount
}
this.orderList[i].supplier_goods_price = order_all_price
this.orderList[i].supplier_goods_amount = order_all_amount
}
},
//
navToOrderDetail(supplier_order_id) {
uni.navigateTo({
url: '/pages/order/order-detail?supplier_order_id='+supplier_order_id
})
},
//
onPullDownRefresh() {
setTimeout(()=>{
this.getOrder(()=>{
uni.stopPullDownRefresh()
})
}, 500)
}
},
//
onLoad() {
//
this.getOrder()
}
}
</script>
<style lang="scss">
.order {
.background { //
image {
position: fixed;
width: 100%;
height: 100%;
top: 0;
left: 0;
z-index: -1;
}
}
.order_item {
background-color: white;
.shop { //
display: flex;
padding: 10rpx 30rpx 0 30rpx;
image { //
padding: 5rpx 15rpx 0 0;
width: 60rpx;
height: 60rpx;
}
.shop_name { //
font-size: 45rpx;
line-height: 70rpx;
}
}
.order_info { //
color: #555555;
padding: 0 30rpx 10rpx 30rpx;
font-size: 35rpx;
line-height: 60rpx;
}
.line { // 线
width: 750rpx;
height: 8rpx;
background: #eee;
}
}
}
</style>

@ -0,0 +1,232 @@
<template>
<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 Layout from '../components/Layout.vue';
export default {
name: 'MinePage',
components: {
Layout
},
data() {
return {
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,
showPhoneInput: false,
idcard: '',
createtime: '',
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(`/serve/users/getByPhone?phone=${phone}`)
.then(response => {
this.user = response.data
})
.catch(error => {
console.error('Error fetching user:', error);
});
},
toggleNicknameInput(){
this.showNicknameInput = !this.showNicknameInput;
this.nickname = this.user.nickname;
},
updateNickname(){
this.user.nickname = this.nickname;
axios.post(`/serve/users/Pupdate`,{user:this.user})
.then(response => {
this.user.nickname = this.nickname;
this.toggleNicknameInput(); //
})
.catch(error => {
console.error('Error updating nickname:', error);
});
},
toggleEmailInput() {
this.showEmailInput = !this.showEmailInput;
this.email = this.user.email;//
},
updateEmail() {
//
this.user.email = this.email;
axios.post(`/serve/users/Pupdate`,{user:this.user})
.then(response => {
this.user.email = this.email;
this.toggleEmailInput(); //
})
.catch(error => {
console.error('Error updating email:', error);
});
},
togglePhoneInput(){
this.showPhoneInput = !this.showPhoneInput;
this.phone = this.user.phone;
},
updatePhone(){
this.user.phone = this.phone;
axios.post(`/serve/users/Pupdate`,{user:this.user})
.then(response => {
sessionStorage.setItem('phone', this.phone);
this.user.phone = this.phone;
this.togglePhoneInput(); //
})
.catch(error => {
console.error('Error updating phone:', error);
});
},
gotoChangeInfomation(){
this.$router.push('/changeInformation');
},
gotohome() {
this.$router.push('/home');
},
gotomessage() {
this.$router.push('/message');
},
gotoDemandList() {
this.$router.push('/demandlist');
},
gotoServerList() {
this.$router.push('/serverlist');
},
gotoLogin() {
this.$router.push('/login');
sessionStorage.setItem('phone', '');
},
}
};
</script>

@ -0,0 +1,264 @@
<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>
<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>
<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;
border: 1px solid #ddd;
border-radius: 8px;
display: flex;
justify-content: center;
align-items: center;
min-height: 100vh;
line-height: 1.6;
}
.trip-info {
margin-bottom: 15px;
}
/* 标题和图标样式 */
h1 {
font-size: 36px; /* or any size you prefer */
}
/* 按钮样式 */
.action-button {
background-color: #007bff;
border: none;
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;
}
.matching {
background-color: #ffc107;
color: #212529;
}
.processing {
background-color: #007bff;
color: white;
}
.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: [],
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/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 } });
},
goToDemandMatched(orderId) {
this.$router.push({ name: 'DemandMatched', params: { orderId } });
},
goToEvaluateTrip(orderId) {
this.$router.push({ name: 'Evaluation', params: { orderId } });
},
cancel(orderId) {
const did = parseInt(this.orderId, 10);
axios.post(`/serve/DemandMatch/refuse`,{did:did})
.then(response => {
if(response.data == 1){
alert('取消成功');
location.reload();
}
})
.catch(error => {
console.error('Error fetching user:', error);
});
},
cancelTrip(orderId) {
const did = parseInt(this.orderId, 10);
axios.post(`/serve/demands/delbyid`,{did:did})
.then(response => {
if(response.data == 1){
alert('取消成功');
this.$router.push('/demandlist');
}
})
.catch(error => {
console.error('Error fetching user:', error);
});
},
over(orderId) {
const did = parseInt(this.orderId, 10);
axios.post(`/serve/DemandMatch/finish`,{did:did})
.then(response => {
if(response.data == 1){
location.reload();
}
})
.catch(error => {
console.error('Error fetching user:', error);
});
},
deleteOrder(orderId) {
const did = parseInt(this.orderId, 10);
axios.post(`/serve/DemandMatch/delete`,{did:did})
.then(response => {
if(response.data == 1){
alert('删除成功');
this.$router.push('/demandlist');
}
})
.catch(error => {
console.error('Error fetching user:', error);
});
},
returnList() {
this.$router.push('/demandlist');
}
}
};
</script>

@ -0,0 +1,220 @@
<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 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: {
Layout,
},
};
</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;
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>

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save