基于SpringBoot vue3 的山西文旅网java网页设计与实现

news2024/10/8 11:59:51

博主介绍:专注于Java(springboot ssm springcloud等开发框架) vue  .net  php phython node.js    uniapp小程序 等诸多技术领域和毕业项目实战、企业信息化系统建设,从业十五余年开发设计教学工作
☆☆☆ 精彩专栏推荐订阅☆☆☆☆☆不然下次找不到哟
我的博客空间发布了1000+毕设题目 方便大家学习使用
感兴趣的可以先收藏起来,还有大家在毕设选题,项目以及论文编写等相关问题都可以给我留言咨询,希望帮助更多的人
更多项目地址 介绍  翰文编程-CSDN博客

系统实现预览

系统设计

4.1系统通用功能用例分析

系统的通用功能包括用户登录和密码修改,是三个角色共同需要使用的功能,用例分析如图4-1所示。

                                  

   4-1系统通用功能用例分析图

4.2 系统设计主要功能

本系统采用自上往下的方法开发实现,本课题要求实现一套山西文旅网,系统主要包括管理员模块和运营商、用户模块功能模块

 1运营商用例图如下所示:

4-2运营商用例图

2用户用例图如下所示:

4-3用户用例图

2管理员用例图如下所示:               

4-4管理员用例图

通过市场调研及咨询研究,可以按照用户的角色权限使不同用户角色看到不一样的信息界面。现根据需求阶段的分析,我们可以大致确定系统需要包含的功能如下图4-5所示:

 图4-5山西文旅网结构功能图

4.3 数据库设计

4.3.1 数据库设计规范

数据可设计要遵循职责分离原则,即在设计时应该要考虑系统独立性,即每个系统之间互不干预不能混乱数据表和系统关系。

数据库命名也要遵循一定规范,否则容易混淆,数据库字段名要尽量做到与表名类似。

4.3.2 E-R图

用户信息E-R图,如图4-6所示:

 图4-6用户信息E-R

运营商E-R图,如图4-7所示:

图4-7运营商E-R

景点信息E-R图如图4-8所示。

  图4-8景点信息E-R

酒店信息E-R图如图4-9所示。

图4-9酒店信息E-R

山西文旅网总体E-R图如图4-10所示。

图4-10山西文旅网总体E-R

4.3.3 数据表

本系统采用的是MySQL数据库存储数据,系统中使用到的主要数据表的具体展示部分如下所示。

4-1我的收藏

字段名称

类型

长度

字段说明

主键

默认值

id

bigint

主键

  主键

addtime

timestamp

创建时间

CURRENT_TIMESTAMP

refid

bigint

refid

tablename

varchar

200

表名

name

varchar

200

名称

picture

longtext

4294967295

图片

type

varchar

200

类型(1:收藏,21:赞,22:踩,31:竞拍参与,41:关注)

inteltype

varchar

200

推荐类型

remark

varchar

200

备注

userid

bigint

用户id

4-2用户

字段名称

类型

长度

字段说明

主键

默认值

id

bigint

主键

  主键

addtime

timestamp

创建时间

CURRENT_TIMESTAMP

yonghuzhanghao

varchar

200

用户账号

yonghumima

varchar

200

用户密码

yonghuxingming

varchar

200

用户姓名

touxiang

longtext

4294967295

头像

xingbie

varchar

200

性别

shoujihaoma

varchar

200

手机号码

4-3景点信息评论表

字段名称

类型

长度

字段说明

主键

默认值

id

bigint

主键

  主键

addtime

timestamp

创建时间

CURRENT_TIMESTAMP

refid

bigint

关联表id

userid

bigint

用户id

avatarurl

longtext

4294967295

头像

nickname

varchar

200

用户名

content

longtext

4294967295

评论内容

reply

longtext

4294967295

回复内容

4-4菜单

字段名称

类型

长度

字段说明

主键

默认值

id

bigint

主键

  主键

addtime

timestamp

创建时间

CURRENT_TIMESTAMP

menujson

longtext

4294967295

菜单

4-5管理员

字段名称

类型

长度

字段说明

主键

默认值

id

bigint

主键

  主键

addtime

timestamp

创建时间

CURRENT_TIMESTAMP

username

varchar

200

用户名

password

varchar

200

密码

role

varchar

200

角色

4-6配置文件

字段名称

类型

长度

字段说明

主键

默认值

id

bigint

主键

  主键

name

varchar

100

配置参数名称

value

varchar

100

配置参数值

4-7门票购买

字段名称

类型

长度

字段说明

主键

默认值

id

bigint

主键

  主键

addtime

timestamp

创建时间

CURRENT_TIMESTAMP

dingdanbianhao

varchar

200

订单编号

jingdianmingcheng

varchar

200

景点名称

menpiaojiage

double

门票价格

shuliang

int

数量

dingdanjine

double

订单金额

goumaishijian

datetime

购买时间

yonghuzhanghao

varchar

200

用户账号

yonghuxingming

varchar

200

用户姓名

shoujihaoma

varchar

200

手机号码

ispay

varchar

200

是否支付

yunyingshangzhanghao

varchar

200

运营商账号

yunyingshangxingming

varchar

200

运营商姓名

4-8旅游攻略

字段名称

类型

长度

字段说明

主键

默认值

id

bigint

主键

  主键

addtime

timestamp

创建时间

CURRENT_TIMESTAMP

gonglvemingcheng

varchar

200

攻略名称

gonglveleixing

varchar

200

攻略类型

tupian

longtext

4294967295

图片

qidian

varchar

200

起点

tujingluduan

varchar

200

途径路段

mudedi

varchar

200

目的地

chuxingfangshi

varchar

200

出行方式

meishituijian

longtext

4294967295

美食推荐

jingdiantuijian

longtext

4294967295

景点推荐

jiudiantuijian

longtext

4294967295

酒店推荐

gonglvexiangqing

longtext

4294967295

攻略详情

youwantianshu

varchar

200

游玩天数

yujifeiyong

varchar

200

预计费用

yonghuzhanghao

varchar

200

用户账号

storeupnum

int

收藏数量

sfsh

varchar

200

是否审核

shhf

longtext

4294967295

回复内容

4-9酒店预定

字段名称

类型

长度

字段说明

主键

默认值

id

bigint

主键

  主键

addtime

timestamp

创建时间

CURRENT_TIMESTAMP

fangjianmingcheng

varchar

200

房间名称

fangjianleixing

varchar

200

房间类型

jiudianleixing

varchar

200

酒店类型

fangjiandizhi

varchar

200

房间地址

yiwanjiage

double

一晚价格

yudingtianshu

int

预定天数

zongjia

varchar

200

总价

fuwudianhua

varchar

200

服务电话

yudingshijian

datetime

预定时间

yonghuzhanghao

varchar

200

用户账号

yonghuxingming

varchar

200

用户姓名

ispay

varchar

200

是否支付

sfsh

varchar

200

是否审核

shhf

longtext

4294967295

回复内容

yunyingshangzhanghao

varchar

200

运营商账号

yunyingshangxingming

varchar

200

运营商姓名

4-10酒店信息

字段名称

类型

长度

字段说明

主键

默认值

id

bigint

主键

  主键

addtime

timestamp

创建时间

CURRENT_TIMESTAMP

fangjianmingcheng

varchar

200

房间名称

jiudianleixing

varchar

200

酒店类型

fangjianleixing

varchar

200

房间类型

fangjiantupian

longtext

4294967295

房间图片

fangjiandizhi

varchar

200

房间地址

yiwanjiage

int

一晚价格

fuwudianhua

varchar

200

服务电话

fangneisheshi

longtext

4294967295

房内设施

storeupnum

int

收藏数量

fangjianzhuangtai

varchar

200

房间状态

yunyingshangzhanghao

varchar

200

运营商账号

yunyingshangxingming

varchar

200

运营商姓名

sfsh

varchar

200

是否审核

shhf

longtext

4294967295

回复内容

4-11酒店类型

字段名称

类型

长度

字段说明

主键

默认值

id

bigint

主键

  主键

addtime

timestamp

创建时间

CURRENT_TIMESTAMP

jiudianleixing

varchar

200

酒店类型

4-12景点信息

字段名称

类型

长度

字段说明

主键

默认值

id

bigint

主键

  主键

addtime

timestamp

创建时间

CURRENT_TIMESTAMP

jingdianmingcheng

varchar

200

景点名称

jingdiantupian

longtext

4294967295

景点图片

menpiaojiage

double

门票价格

shuliang

int

数量

jingdianleixing

varchar

200

景点类型

kaifangshijian

varchar

200

开放时间

luxiantuijian

longtext

4294967295

路线推荐

jingdianjieshao

longtext

4294967295

景点介绍

jingdiandizhi

varchar

200

景点地址

storeupnum

int

收藏数量

clicktime

datetime

最近点击时间

clicknum

int

点击次数

yunyingshangzhanghao

varchar

200

运营商账号

yunyingshangxingming

varchar

200

运营商姓名

sfsh

varchar

200

是否审核

shhf

longtext

4294967295

回复内容

4-13景点类型

字段名称

类型

长度

字段说明

主键

默认值

id

bigint

主键

  主键

addtime

timestamp

创建时间

CURRENT_TIMESTAMP

jingdianleixing

varchar

200

景点类型

4-14攻略类型

字段名称

类型

长度

字段说明

主键

默认值

id

bigint

主键

  主键

addtime

timestamp

创建时间

CURRENT_TIMESTAMP

gonglveleixing

varchar

200

攻略类型

4-15token表

字段名称

类型

长度

字段说明

主键

默认值

id

bigint

主键

  主键

userid

bigint

用户id

username

varchar

100

用户名

tablename

varchar

100

表名

role

varchar

100

角色

token

varchar

200

密码

addtime

timestamp

新增时间

CURRENT_TIMESTAMP

expiratedtime

timestamp

过期时间

CURRENT_TIMESTAMP

4-16运营商

字段名称

类型

长度

字段说明

主键

默认值

id

bigint

主键

  主键

addtime

timestamp

创建时间

CURRENT_TIMESTAMP

yunyingshangzhanghao

varchar

200

运营商账号

mima

varchar

200

密码

yunyingshangxingming

varchar

200

运营商姓名

touxiang

longtext

4294967295

头像

xingbie

varchar

200

性别

shoujihaoma

varchar

200

手机号码

sfsh

varchar

200

是否审核

shhf

longtext

4294967295

回复内容

4-17酒店信息评论表

字段名称

类型

长度

字段说明

主键

默认值

id

bigint

主键

  主键

addtime

timestamp

创建时间

CURRENT_TIMESTAMP

refid

bigint

关联表id

userid

bigint

用户id

avatarurl

longtext

4294967295

头像

nickname

varchar

200

用户名

content

longtext

4294967295

评论内容

reply

longtext

4294967295

回复内容

5 系统实现

5.1前台用户功能模块

游客打开系统的网址后,首先看到的就是首页界面。在这里,游客能够看到山西文旅网的导航条显示系统首页、旅游攻略、景点信息、酒店信息、个人中心等,如图5-1所示。

图5-1前台功能界面图

    

在注册流程中,用户在Vue前端填写必要信息(如用户名、密码等)并提交。前端将这些信息通过HTTP请求发送到Java后端。后端处理这些信息,检查用户名是否唯一,并将新用户数据存入MySQL数据库。完成后,后端向前端发送注册成功的确认,前端随后通知用户完成注册。这个过程实现了新用户的数据收集、验证和存储。如图5-2所示。

图5-2用户注册界面图

在登录流程中,用户首先在Vue前端界面输入用户名和密码。这些信息通过HTTP请求发送到Java后端。后端接收请求,通过与MySQL数据库交互验证用户凭证。如果认证成功,后端会返回给前端,允许用户访问系统。这个过程涵盖了从用户输入到系统验证和响应的全过程如图5-3所示。

图5-3用户登录界面图

代码


<template>
	<div>
		<div class="app-contain">
			<div class="list_search_view">
				<el-form :model="searchQuery" class="search_form" >
					<div class="search_view">
						<div class="search_label">
							运营商账号:
						</div>
						<div class="search_box">
							<el-input class="search_inp" v-model="searchQuery.yunyingshangzhanghao" placeholder="运营商账号"
								clearable>
							</el-input>
						</div>
					</div>
					<div class="search_view">
						<div class="search_label">
							审核状态:
						</div>
						<div class="search_box">
							<el-select
								class="search_sel"
								clearable
								v-model="searchQuery.sfsh" 
								placeholder="审核状态"
								>
								<el-option v-for="item in approvalLists" :label="item" :value="item"></el-option>
							</el-select>
						</div>
					</div>
					<div class="search_btn_view">
						<el-button class="search_btn" type="primary" @click="searchClick()" size="small">搜索</el-button>
					</div>
				</el-form>
				<br>
				<div class="btn_view">
					<el-button type="success" @click="addClick" v-if="btnAuth('yunyingshang','新增')">新增</el-button>
					<el-button  v-if=" btnAuth('yunyingshang','查看')" type="info"  :disabled="selRows.length==1?false:true" @click="infoClick(null)">详情</el-button>
					<el-button type="primary" :disabled="selRows.length==1?false:true" @click="editClick" v-if=" btnAuth('yunyingshang','修改')">修改</el-button>
					<el-button type="danger" :disabled="selRows.length?false:true" @click="delClick(null)"  v-if="btnAuth('yunyingshang','删除')">删除</el-button>
				</div>
			</div>
			<br>
			<el-table
				v-loading="listLoading"
				border 
				:stripe='true'
				@selection-change="handleSelectionChange" 
				ref="table"
				v-if="btnAuth('yunyingshang','查看')"
				:data="list"
				@row-click="listChange">
				<el-table-column :resizable='true' align="left" header-align="left" type="selection" width="55" />
				<el-table-column label="序号" width="70" :resizable='true' :sortable='true' align="left" header-align="left">
					<template #default="scope">{{ scope.$index + 1}}</template>
				</el-table-column>
				<el-table-column
					 :resizable='true' 
					 :sortable='true' 
					 align="left" 
					 header-align="left"
					label="运营商账号">
					<template #default="scope">
						{{scope.row.yunyingshangzhanghao}}
					</template>
				</el-table-column>
				<el-table-column
					 :resizable='true' 
					 :sortable='true' 
					 align="left" 
					 header-align="left"
					label="运营商姓名">
					<template #default="scope">
						{{scope.row.yunyingshangxingming}}
					</template>
				</el-table-column>
				<el-table-column label="头像" width="120" :resizable='true' :sortable='true' align="left" header-align="left">
					<template #default="scope">
						<div v-if="scope.row.touxiang">
							<el-image v-if="scope.row.touxiang.substring(0,4)=='http'" preview-teleported
								:preview-src-list="[scope.row.touxiang.split(',')[0]]"
								:src="scope.row.touxiang.split(',')[0]" style="width:100px;height:100px"></el-image>
							<el-image v-else preview-teleported
								:preview-src-list="[$config.url+scope.row.touxiang.split(',')[0]]"
								:src="$config.url+scope.row.touxiang.split(',')[0]" style="width:100px;height:100px">
							</el-image>
						</div>
						<div v-else>无图片</div>
					</template>
				</el-table-column>
				<el-table-column
					 :resizable='true' 
					 :sortable='true' 
					 align="left" 
					 header-align="left"
					label="性别">
					<template #default="scope">
						{{scope.row.xingbie}}
					</template>
				</el-table-column>
				<el-table-column
					 :resizable='true' 
					 :sortable='true' 
					 align="left" 
					 header-align="left"
					label="手机号码">
					<template #default="scope">
						{{scope.row.shoujihaoma}}
					</template>
				</el-table-column>
				<el-table-column label="审核回复" :resizable='true' :sortable='true' align="left" header-align="left">
					<template #default="scope">
						{{scope.row.shhf}}
					</template>
				</el-table-column>
				<el-table-column label="审核状态" :resizable='true' :sortable='true' align="left" header-align="left">
					<template #default="scope">
						<el-tag type="success" v-if="scope.row.sfsh=='是'">通过</el-tag>
						<el-tag type="danger" v-else-if="scope.row.sfsh=='否'">未通过</el-tag>
						<el-tag type="warning" v-else>待审核</el-tag>
					</template>
				</el-table-column>
				<el-table-column label="审核" v-if="btnAuth('yunyingshang','审核')" :resizable='true' :sortable='true' align="left" header-align="left">
					<template #default="scope">
						<el-button type="text" @click="approvalClick(scope.row)">审核</el-button>
					</template>
				</el-table-column>
				<el-table-column label="操作" width="300" :resizable='true' :sortable='true' align="left" header-align="left">
					<template #default="scope">
						<el-button type="info" v-if=" btnAuth('yunyingshang','查看')" @click="infoClick(scope.row.id)">详情</el-button>
					</template>
				</el-table-column>
			</el-table>
			<el-pagination 
				background
				:layout="layouts.join(',')"
				:total="total" 
				:page-size="listQuery.limit"
				prev-text="Prev"
				next-text="Next"
				:hide-on-single-page="false"
				:style='{"padding":"0","margin":"20px 0 0","whiteSpace":"nowrap","color":"#333","textAlign":"center","width":"100%","fontWeight":"500"}'
				@size-change="sizeChange"
				@current-change="currentChange" 
				@prev-click="prevClick"
				@next-click="nextClick"  />
		</div>
		<formModel ref="formRef" @formModelChange="formModelChange"></formModel>
		<Approval ref="approvalRef" :tableName="tableName" @shChange="searchClick()"></Approval>
	</div>
</template>
<script setup>
	import axios from 'axios'
	import {
		reactive,
		ref,
		getCurrentInstance,
		nextTick,
		onMounted,
		watch,
	} from 'vue'
	import {
		useRoute,
		useRouter
	} from 'vue-router'
	import {
		ElMessageBox
	} from 'element-plus'
	const context = getCurrentInstance()?.appContext.config.globalProperties;
	import formModel from './formModel.vue'
	
	//基础信息
	const tableName = 'yunyingshang'
	const formName = '运营商'
	const route = useRoute()
	//基础信息
	onMounted(()=>{
	})
	//列表数据
	const list = ref(null)
	const table = ref(null)
	const listQuery = ref({
		page: 1,
		limit: 20,
		sort: 'id',
		order: 'desc'
	})
	const searchQuery = ref({})
	const selRows = ref([])
	const listLoading = ref(false)
	const listChange = (row) =>{
		nextTick(()=>{
			table.value.clearSelection()
			table.value.toggleRowSelection(row)
		})
	}
	//列表
	const getList = () => {
		listLoading.value = true
		let params = JSON.parse(JSON.stringify(listQuery.value))
		params['sort'] = 'id'
		params['order'] = 'desc'
		if(searchQuery.value.yunyingshangzhanghao&&searchQuery.value.yunyingshangzhanghao!=''){
			params['yunyingshangzhanghao'] = '%' + searchQuery.value.yunyingshangzhanghao + '%'
		}
          if(searchQuery.value.sfsh && searchQuery.value.sfsh!=''){
            params['sfsh'] = searchQuery.value.sfsh
          }
          if(searchQuery.value.sfsh && searchQuery.value.sfsh!=''){
            params['sfsh'] = searchQuery.value.sfsh
          }
          if(searchQuery.value.sfsh && searchQuery.value.sfsh!=''){
            params['sfsh'] = searchQuery.value.sfsh
          }
          if(searchQuery.value.sfsh && searchQuery.value.sfsh!=''){
            params['sfsh'] = searchQuery.value.sfsh
          }
          if(searchQuery.value.sfsh && searchQuery.value.sfsh!=''){
            params['sfsh'] = searchQuery.value.sfsh
          }
          if(searchQuery.value.sfsh && searchQuery.value.sfsh!=''){
            params['sfsh'] = searchQuery.value.sfsh
          }
          if(searchQuery.value.sfsh && searchQuery.value.sfsh!=''){
            params['sfsh'] = searchQuery.value.sfsh
          }
          if(searchQuery.value.sfsh && searchQuery.value.sfsh!=''){
            params['sfsh'] = searchQuery.value.sfsh
          }
		context?.$http({
			url: `${tableName}/page`,
			method: 'get',
			params: params
		}).then(res => {
			listLoading.value = false
			list.value = res.data.data.list
			total.value = Number(res.data.data.total)
		})
	}
	//删
	const delClick = (id) => {
		let ids = ref([])
		if (id) {
			ids.value = [id]
		} else {
			if (selRows.value.length) {
				for (let x in selRows.value) {
					ids.value.push(selRows.value[x].id)
				}
			} else {
				return false
			}
		}
		ElMessageBox.confirm(`是否删除选中${formName}`, '提示', {
			confirmButtonText: '是',
			cancelButtonText: '否',
			type: 'warning',
		}).then(() => {
			context?.$http({
				url: `${tableName}/delete`,
				method: 'post',
				data: ids.value
			}).then(res => {
				context?.$toolUtil.message('删除成功', 'success',()=>{
					getList()
				})
			})
		})
	}
	//多选
	const handleSelectionChange = (e) => {
		selRows.value = e
	}
	//列表数据
	//分页
	const total = ref(0)
	const layouts = ref(["prev","pager","next"])
	const sizeChange = (size) => {
		listQuery.value.limit = size
		getList()
	}
	const currentChange = (page) => {
		listQuery.value.page = page
		getList()
	}
	const prevClick = () => {
		listQuery.value.page = listQuery.value.page - 1
		getList()
	}
	const nextClick = () => {
		listQuery.value.page = listQuery.value.page + 1
		getList()
	}
	//分页
	//权限验证
	const btnAuth = (e,a)=>{
		return context?.$toolUtil.isAuth(e,a)
	}
	//搜索
	const searchClick = () => {
		listQuery.value.page = 1
		getList()
	}
	//表单
	const formRef = ref(null)
	const formModelChange=()=>{
		searchClick()
	}
	const addClick = ()=>{
		formRef.value.init()
	}
	const editClick = ()=>{
		if(selRows.value.length){
			formRef.value.init(selRows.value[0].id,'edit')
		}
	}
	
	const infoClick = (id=null)=>{
		if(id){
			formRef.value.init(id,'info')
		}
		else if(selRows.value.length){
			formRef.value.init(selRows.value[0].id,'info')
		}
	}
	// 表单
	// 预览文件
	const preClick = (file) =>{
		if(!file){
			context?.$toolUtil.message('文件不存在','error')
		}
		window.open(context?.$config.url + file)
		// const a = document.createElement('a');
		// a.style.display = 'none';
		// a.setAttribute('target', '_blank');
		// file && a.setAttribute('download', file);
		// a.href = context?.$config.url + file;
		// document.body.appendChild(a);
		// a.click();
		// document.body.removeChild(a);
	}
	// 下载文件
	const download = (file) => {
		if(!file){
			context?.$toolUtil.message('文件不存在','error')
		}
		let arr = file.replace(new RegExp('file/', "g"), "")
		axios.get((location.href.split(context?.$config.name).length>1 ? location.href.split(context?.$config.name)[0] :'') + context?.$config.name + '/file/download?fileName=' + arr, {
			headers: {
				token: context?.$toolUtil.storageGet('Token')
			},
			responseType: "blob"
		}).then(({
			data
		}) => {
			const binaryData = [];
			binaryData.push(data);
			const objectUrl = window.URL.createObjectURL(new Blob(binaryData, {
				type: 'application/pdf;chartset=UTF-8'
			}))
			const a = document.createElement('a')
			a.href = objectUrl
			a.download = arr
			// a.click()
			// 下面这个写法兼容火狐
			a.dispatchEvent(new MouseEvent('click', {
				bubbles: true,
				cancelable: true,
				view: window
			}))
			window.URL.revokeObjectURL(data)
		})
	}

	//审核
	import Approval from '@/components/common/approval.vue'
	const approvalRef = ref(null)
	const approvalClick = (row) => {
		let params = {
			id:row.id,
			yunyingshangzhanghao: row.yunyingshangzhanghao,
			mima: row.mima,
			yunyingshangxingming: row.yunyingshangxingming,
			touxiang: row.touxiang,
			xingbie: row.xingbie,
			shoujihaoma: row.shoujihaoma,
			sfsh: row.sfsh,
			shhf: row.shhf,
		}
		nextTick(() => {
			approvalRef.value.approvalClick(params )
		})
	}

	//查询审核状态列表
	const approvalLists = ref([])
	//初始化
	const init = () => {
        approvalLists.value = "是,否,待审核".split(',');
		getList()
	}
	init()
</script>
<style lang="scss" scoped>
	
	// 操作盒子
	.list_search_view {
		margin: 0 0 20px;
		display: flex;
		justify-content: space-between;
		flex-wrap: wrap;
		// 搜索盒子
		.search_form {
			display: flex;
			align-items: center;
			order: 2;
			// 子盒子
			.search_view {
				margin: 0 10px 0 0;
				display: flex;
				align-items: center;
				// 搜索label
				.search_label {
					margin: 0 10px 0 0;
					color: #fff;
					background: none;
					font-weight: 500;
					display: inline-block;
					width: auto;
					font-size: 14px;
					line-height: 40px;
					text-align: right;
					min-width: 100px;
					height: 40px;
				}
				// 搜索item
				.search_box {
					display: inline-block;
					width: auto;
					// 输入框
					:deep(.search_inp) {
						border: 1px solid rgba(0, 0, 0, 0.1);
						border-radius: 4px;
						padding: 0 10px;
						color: #fff;
						background: rgba(0, 0, 0, 0.1);
						width: auto;
						line-height: 34px;
						box-sizing: border-box;
						//去掉默认样式
						.el-input__wrapper{
							border: none;
							box-shadow: none;
							background: none;
							border-radius: 0;
							height: 100%;
							padding: 0;
						}
						.is-focus {
							box-shadow: none !important;
						}
					}
					// 下拉框
					:deep(.search_sel) {
						border: 1px solid rgba(0, 0, 0, 0.1);
						border-radius: 4px;
						padding: 0 10px;
						color: #fff;
						background: rgba(0, 0, 0, 0.1);
						width: auto;
						line-height: 34px;
						box-sizing: border-box;
						//去掉默认样式
						.select-trigger{
							height: 100%;
							.el-input{
								height: 100%;
								.el-input__wrapper{
									border: none;
									box-shadow: none;
									background: none;
									border-radius: 0;
									height: 100%;
									padding: 0;
								}
								.is-focus {
									box-shadow: none !important;
								}
							}
						}
					}
				}
			}
			// 搜索按钮盒子
			.search_btn_view {
				width: 20%;
				display: flex;
				padding: 0 20px;
				// 搜索按钮
				.search_btn {
					border: 1px solid #357ebd;
					cursor: pointer;
					border-radius: 4px;
					padding: 0 24px;
					color: #fff;
					background: rgba(66, 139, 202, 0.45);
					width: auto;
					font-size: 14px;
					height: 36px;
				}
				// 搜索按钮-悬浮
				.search_btn:hover {
					border: 1px solid #357ebd;
					background: rgba(66, 139, 202, 0.45);
				}
			}
		}
		//头部按钮盒子
		.btn_view {
			margin: 0;
			display: flex;
			// 其他
			:deep(.el-button--default){
				border: 1px solid #ccc;
				cursor: pointer;
				border-radius: 3px;
				padding: 0 24px;
				margin: 0 10px 0 0;
				outline: none;
				color: #fff;
				background: rgba(222, 222, 222, 0.55);
				width: auto;
				font-size: 14px;
				height: 36px;
			}
			// 其他-悬浮
			:deep(.el-button--default:hover){
				background: rgba(222, 222, 222, 0.45);
			}
			// 新增
			:deep(.el-button--success){
				border: 1px solid #357ebd;
				cursor: pointer;
				border-radius: 3px;
				padding: 0 24px;
				margin: 0 10px 0 0;
				outline: none;
				color: #fff;
				background: rgba(66, 139, 202, 0.45);
				width: auto;
				font-size: 14px;
				height: 36px;
			}
			// 新增-悬浮
			:deep(.el-button--success:hover){
				background: rgba(66, 139, 202, 0.35);
			}
			// 修改
			:deep(.el-button--primary){
				border: 1px solid #4cae4c;
				cursor: pointer;
				border-radius: 3px;
				padding: 0 24px;
				margin: 0 10px 0 0;
				outline: none;
				color: #fff;
				background: rgba(92, 184, 92, 0.55);
				width: auto;
				font-size: 14px;
				height: 36px;
			}
			// 修改-悬浮
			:deep(.el-button--primary:hover){
				background: rgba(92, 184, 92, 0.45);
			}
			// 详情
			:deep(.el-button--info){
				border: 1px solid #46b8da;
				cursor: pointer;
				border-radius: 3px;
				padding: 0 24px;
				margin: 0 10px 0 0;
				outline: none;
				color: #fff;
				background: rgba(91, 192, 222, 0.45);
				width: auto;
				font-size: 14px;
				height: 36px;
			}
			// 详情-悬浮
			:deep(.el-button--info:hover){
				background: rgba(91, 192, 222, 0.35);
			}
			// 删除
			:deep(.el-button--danger){
				border: 1px solid #d43f3a;
				cursor: pointer;
				border-radius: 3px;
				padding: 0 24px;
				margin: 0 10px 0 0;
				outline: none;
				color: #fff;
				background: rgba(217, 83, 79, 0.55);
				width: auto;
				font-size: 14px;
				height: 36px;
			}
			// 删除-悬浮
			:deep(.el-button--danger:hover){
				background: rgba(217, 83, 79, 0.45);
			}
			// 统计
			:deep(.el-button--warning){
				border: 1px solid #eea236;
				cursor: pointer;
				border-radius: 3px;
				padding: 0 24px;
				margin: 0 10px 0 0;
				outline: none;
				color: #fff;
				background: rgba(240, 173, 78, 0.55);
				width: auto;
				font-size: 14px;
				height: 36px;
			}
			// 统计-悬浮
			:deep(.el-button--warning:hover){
				background: rgba(240, 173, 78, 0.45);
			}
		}
	}
	// 表格样式
	.el-table {
		border-radius: 0px;
		padding: 0;
		background: rgba(0, 0, 0, 0.25);
		width: 100%;
		border-color: rgba(254, 182, 203, 0.5);
		border-width: 1px 0 0 1px;
		border-style: solid;
		:deep(.el-table__header-wrapper) {
			thead {
				color: #fff;
				font-weight: 500;
				width: 100%;
				tr {
					background: rgba(0, 0, 0, 0.1);
					th {
						padding: 4px 0;
						background: none;
						border-color: rgba(254, 182, 203, 0.5);
						border-width: 0 0px 1px 0;
						border-style: solid;
						text-align: left;
						.cell {
							padding: 0 10px;
							word-wrap: normal;
							word-break: break-all;
							white-space: normal;
							font-weight: bold;
							display: inline-block;
							vertical-align: middle;
							width: 100%;
							line-height: 24px;
							position: relative;
							text-overflow: ellipsis;
						}
					}
				}
			}
		}
		:deep(.el-table__body-wrapper) {
			tbody {
				width: 100%;
				tr {
					background: none;
					td {
						padding: 6px 0;
						color: #eee;
						background: none;
						border-color: #d2d2d2;
						border-width: 0 0px 0px 0;
						border-style: solid;
						text-align: left;
						.cell {
							padding: 0 10px;
							overflow: hidden;
							word-break: break-all;
							white-space: normal;
							line-height: 24px;
							text-overflow: ellipsis;
							// 编辑
							.el-button--primary {
								border: 1px solid #d58512;
								cursor: pointer;
								border-radius: 4px;
								padding: 5px 10px;
								margin: 0 6px 6px 0;
								color: #fff;
								background: rgba(240, 173, 78, 0.45);
								width: auto;
								font-size: 12px;
								height: auto;
							}
							// 编辑-悬浮
							.el-button--primary:hover {
							}
							// 详情
							.el-button--info {
								border: 1px solid #357ebd;
								cursor: pointer;
								border-radius: 3px;
								padding: 5px 10px;
								margin: 0 6px 6px 0;
								color: #fff;
								background: rgba(66, 139, 202, 0.55);
								width: auto;
								font-size: 12px;
								height: auto;
							}
							// 详情-悬浮
							.el-button--info:hover {
							}
							// 删除
							.el-button--danger {
								border: 1px solid #ac2925;
								cursor: pointer;
								border-radius: 3px;
								padding: 5px 10px;
								margin: 0 6px 6px 0;
								color: #fff;
								background: rgba(217, 83, 79, 0.45);
								width: auto;
								font-size: 12px;
								height: auto;
							}
							// 删除-悬浮
							.el-button--danger:hover {
							}
							// 跨表
							.el-button--success {
								border: 1px solid #ccc;
								cursor: pointer;
								border-radius: 3px;
								padding: 5px 10px;
								margin: 0 6px 6px 0;
								color: #fff;
								background: rgba(222, 222, 222, 0.55);
								width: auto;
								font-size: 12px;
								height: 24px;
							}
							// 跨表-悬浮
							.el-button--success:hover {
							}
							// 操作
							.el-button--warning {
								border: 1px solid #4cae4c;
								cursor: pointer;
								border-radius: 3px;
								padding: 5px 10px;
								margin: 0 6px 6px 0;
								color: #fff;
								background: rgba(92, 184, 92, 0.55);
								width: auto;
								font-size: 12px;
								height: auto;
							}
							// 操作-悬浮
							.el-button--warning:hover {
							}
						}
					}
				}
				tr.el-table__row--striped {
					td {
						background: rgba(0, 0, 0, 0.10);
					}
				}
				tr:hover {
					td {
						padding: 6px 0;
						color: #fff;
						background: rgba(0, 0, 0, 0.10);
						border-color: #d2d2d2;
						border-width: 0 0px 0px 0;
						border-style: solid;
						text-align: left;
					}
				}
			}
		}
	}
	// 分页器
	.el-pagination {
		// 总页码
		:deep(.el-pagination__total) {
			margin: 0 10px 0 0;
			color: #666;
			font-weight: 400;
			display: inline-block;
			vertical-align: top;
			font-size: 13px;
			line-height: 28px;
			height: 28px;
		}
		// 上一页
		:deep(.btn-prev) {
			border: none;
			border-radius: 0px;
			padding: 0 5px;
			margin: 0 5px;
			color: #fff;
			background: none;
			display: inline-block;
			vertical-align: top;
			font-size: 13px;
			line-height: 26px;
			min-width: 35px;
			height: 26px;
		}
		// 下一页
		:deep(.btn-next) {
			border: none;
			border-radius: 0px;
			padding: 0 5px;
			margin: 0 5px;
			color: #fff;
			background: none;
			display: inline-block;
			vertical-align: top;
			font-size: 13px;
			line-height: 26px;
			min-width: 35px;
			height: 26px;
		}
		// 上一页禁用
		:deep(.btn-prev:disabled) {
			border: none;
			cursor: not-allowed;
			border-radius: 0px;
			padding: 0 5px;
			margin: 0 5px;
			color: #fff;
			background: none;
			display: inline-block;
			vertical-align: top;
			font-size: 13px;
			line-height: 26px;
			height: 26px;
		}
		// 下一页禁用
		:deep(.btn-next:disabled) {
			border: none;
			cursor: not-allowed;
			border-radius: 0px;
			padding: 0 5px;
			margin: 0 5px;
			color: #fff;
			background: none;
			display: inline-block;
			vertical-align: top;
			font-size: 13px;
			line-height: 26px;
			height: 26px;
		}
		// 页码
		:deep(.el-pager) {
			padding: 0;
			margin: 0;
			display: inline-block;
			vertical-align: top;
			// 数字
			.number {
				cursor: pointer;
				border: 1px solid rgba(255, 255, 255, 0.3);
				padding: 0 4px;
				margin: 0 5px;
				color: #fff;
				display: inline-block;
				vertical-align: top;
				font-size: 13px;
				line-height: 26px;
				border-radius: 0px;
				background: none;
				text-align: center;
				min-width: 30px;
				height: 26px;
			}
			// 数字悬浮
			.number:hover {
				cursor: pointer;
				border: 1px solid rgba(0, 0, 0, 0.05);
				padding: 0 4px;
				margin: 0 5px;
				color: #fff;
				display: inline-block;
				vertical-align: top;
				font-size: 13px;
				line-height: 26px;
				border-radius: 0px;
				background: rgba(0, 0, 0, 0.25);
				text-align: center;
				min-width: 30px;
				height: 26px;
			}
			// 选中
			.number.is-active {
				cursor: default;
				border: 1px solid rgba(0, 0, 0, 0.05);
				padding: 0 4px;
				margin: 0 5px;
				color: #fff;
				display: inline-block;
				vertical-align: top;
				font-size: 13px;
				line-height: 26px;
				border-radius: 0px;
				background: rgba(0, 0, 0, 0.25);
				text-align: center;
				min-width: 30px;
				height: 26px;
			}
		}
		// sizes
		:deep(.el-pagination__sizes) {
			display: inline-block;
			vertical-align: top;
			font-size: 13px;
			line-height: 28px;
			height: 28px;
			.el-select {
				border: 1px solid #DCDFE6;
				cursor: pointer;
				padding: 0;
				color: #606266;
				display: inline-block;
				font-size: 13px;
				line-height: 28px;
				border-radius: 3px;
				outline: 0;
				background: #FFF;
				width: 100%;
				text-align: center;
				height: 28px;
			}
		}
		// 跳页
		:deep(.el-pagination__jump) {
			margin: 0 0 0 24px;
			color: #606266;
			display: inline-block;
			vertical-align: top;
			font-size: 13px;
			line-height: 28px;
			height: 28px;
			// 输入框
			.el-input {
				border: 1px solid #DCDFE6;
				cursor: pointer;
				padding: 0 3px;
				color: #606266;
				display: inline-block;
				font-size: 14px;
				line-height: 28px;
				border-radius: 3px;
				outline: 0;
				background: #FFF;
				width: 100%;
				text-align: center;
				height: 28px;
				//去掉默认样式
				.el-input__wrapper{
					border: none;
					box-shadow: none;
					background: none;
					border-radius: 0;
					height: 100%;
					padding: 0;
				}
				.is-focus {
					box-shadow: none !important;
				}
			}
		}
	}
</style>

用户点击旅游攻略,在旅游攻略页面的搜索栏输入攻略名称、起点,进行搜索,然后可以查看目的地、出行方式、美食推荐、景点推荐、酒店推荐、游玩天数、预计费用、用户账号、收藏数量等信息,如有需要可以进行收藏等操作;如图5-4所示。 

图5-4旅游攻略界面图

用户点击景点信息,在景点信息页面的搜索栏输入景点名称,进行搜索,然后可以查看景点图片、门票价格、数量、景点类型、开放时间、景点地址、运营商账号、运营商姓名等信息如有需要可以点击购买、收藏等操作;如图5-5所示。  

图5-5景点信息界面图

用户点击个人中心,在个人中心页面可以修改个人信息、密码修改进行详细操作,可以对修改密码、酒店信息管理、旅游路线管理、我的收藏管理、景点信息管理进行详细操作如图5-6所示。

图5-6个人中心界面图

5.2 后台管理员功能模块

管理员登录,通过登录页面输入用户名、密码角色进行登录操作,如图5-7所示。

5-7管理员登录界面图

管理员登录进入山西文旅网可以查看首页、酒店信息管理、景点信息管理、旅游路线管理、管理员管理、运营商管理、用户管理等信息进行相应操作,如图5-8所示。

5-8管理员功能界面图

酒店信息功能在视图层(view层)进行交互,比如点击“新增”按钮或填写酒店信息表单。这些酒店信息动作被视图层捕获并作为请求发送给相应的控制器层(control1er层)。控制器接收到这些请求后,调用服务层(service层)以执行相关的业务逻辑,例如验证输入数据的有效性和与数据库的交互。服务层处理完这些逻辑后,进一步与数据访问对象层(DAO层)交互,后者负责具体的数据操作如搜索、新增、更新或删除酒店信息,并将操作结果返回给控制器。最终,控制器根据这些结果更新视图层,以便酒店信息功能可以看到最新的信息或相应的操作反馈。在酒店信息页面的输入栏中输入房间名称、房间类型、审核状态进行搜索,可以查看到酒店详细信息,并根据需要进行修改或者删除等操作;如图5-9所示。

图5-9酒店信息界面图

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2196295.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

项目完整开发的流程

流程 1.设计产品 2.写需求文档 2.1需求分析&#xff0c;后端设计数据库&#xff0c;建表&#xff0c;客户沟通&#xff0c;说完签字&#xff0c;留证据&#xff0c;防止后面扯皮&#xff0c;和防止后续变需求重新写业务 3.画原型图&#xff0c;也就是草图&#xff0c;初始的…

LeetCode讲解篇之2466. 统计构造好字符串的方案数

文章目录 题目描述题解思路题解代码题目链接 题目描述 题解思路 组成长度为i的字符串个数 组成长度为i - zero的字符串个数 组成长度为i - one的字符串个数 设数组f中i号元素的值为组成长度为i的字符串个数 则状态转移方程为f[i] f[i - zero] f[i - one]&#xff0c;其中需…

【unity进阶知识10】从零手搓一个UI管理器/UI框架,自带一个提示界面,还有自带DOTween动画效果

最终效果 文章目录 最终效果前言UI管理器1、新增UI面板层枚举2、初始化2.1、用代码创建画布2.2、用代码创建UI面板的父物体层2.3、代码添加EventSystem物体 3、ShowPanel显示面板方法4、HidePanel隐藏面板的方法5、CloseUI关闭界面的方法6、UI界面基类 测试调用优化绑定按钮事件…

C语言初步介绍(初学者,大学生)【上】

1.C语⾔是什么&#xff1f; ⼈和⼈交流使⽤的是⾃然语⾔&#xff0c;如&#xff1a;汉语、英语、⽇语 那⼈和计算机是怎么交流的呢&#xff1f;使⽤ 计算机语⾔ 。 ⽬前已知已经有上千种计算机语⾔&#xff0c;⼈们是通过计算机语⾔写的程序&#xff0c;给计算机下达指令&am…

【AIGC产品经理】面试7家,拿到2个offer,薪资中上水平

Hello&#xff0c;大家好&#xff0c;我是一名不知名的5年B端金融产品经验的产品经理&#xff0c;成功转行AI产品经理&#xff0c;前期面试了北京百度、阿里、理想汽车、百川智能、华为、OPPO等多家大厂面试&#xff0c;但是由于已定居成都&#xff0c;主动终止了后续需要线下的…

ubuntu 系统安装

使用VMware虚拟机上进行实现 官网下载地址&#xff1a; https://cn.ubuntu.com/download https://releases.ubuntu.com 操作系统手册&#xff1a; https://ubuntu.com/server/docs/ &#xff08;里面包含安装文档&#xff09; 安装指南&#xff08;详细&#xff09;&#xff1a…

一手信息:用ai怎么做短视频赚钱。

AI制作短视频赚钱的具体数据与分析如下&#xff1a; 数据展示 ​ 更多实操教程和AI绘画工具,可以扫描下方,免费获取 \1. 收入情况&#xff1a; - 有案例显示&#xff0c;通过AI生成历史解说视频&#xff0c;半年内可以赚取64万人民币。 - 另一个案例则是通过AI生成电影解说…

鸿蒙 Next 实战: 环境搭建

前言 作为独立开发者&#xff0c;如果我们错过了传统移动 App&#xff0c;和后起小程序的红利&#xff0c;那万物互联 AI 的应用开发就得抓住了。 虽然个人上架应用平台难易都差不多&#xff0c;但是鸿蒙生态当前正需要广大开发者参与&#xff0c;一旦上架&#xff0c;相比其…

AI绘画ComfyUI 完全入门:基本功能完全掌握!

前言 大家好&#xff0c;我是每天分享AI应用的萤火君&#xff01; 在AI绘画领域&#xff0c;Stable Diffusion 因其开源特性而受到广泛的关注和支持&#xff0c;背后聚拢了一大批的应用开发者和艺术创作者&#xff0c;是AI绘画领域当之无愧的王者。 目前使用 Stable Diffusi…

外国钞票面值检测系统源码分享

外国钞票面值检测系统源码分享 [一条龙教学YOLOV8标注好的数据集一键训练_70全套改进创新点发刊_Web前端展示] 1.研究背景与意义 项目参考AAAI Association for the Advancement of Artificial Intelligence 项目来源AACV Association for the Advancement of Computer Vis…

新版AndroidStudio log使用

从Android Studio Dophin开始&#xff0c;Android Studio中的默认展示了新版的logcat。新版的logcat色彩上是更加的好看了&#xff0c;不同的tag会有不同的颜色&#xff0c;不同level等级的log默认也有不同的颜色。log过滤修改的更简洁了&#xff0c;当然使用起来也更加复杂了。…

系统开发基础错题解析一【软考】

目录 前言1.开发模型1.1快速原型模型优点1.2敏捷统一模型1.3增量模型的优缺点1.4极限编程1.5螺旋模型 2.软件开发方法3.数据流图与数据字典3.1判定表3.2数据流图绘制3.3决策树 4.概要设计和详细设计5.内聚性6.耦合性 前言 本文专门用来记录本人在做软考中有关系统开发基础的错…

基于SpringBoot+Vue的宠物店管理系统

作者&#xff1a;计算机学姐 开发技术&#xff1a;SpringBoot、SSM、Vue、MySQL、JSP、ElementUI、Python、小程序等&#xff0c;“文末源码”。 专栏推荐&#xff1a;前后端分离项目源码、SpringBoot项目源码、Vue项目源码、SSM项目源码、微信小程序源码 精品专栏&#xff1a;…

0基础跟德姆(dom)一起学AI 机器学习03-线性回归

线性回归 线性回归介绍 【理解】举个栗子 假若有了身高和体重数据&#xff0c;来了播仔的身高&#xff0c;你能预测播仔体重吗? 这是一个回归问题&#xff0c;该如何求解呢? **思路**:先从已知身高X和体重Y中找规律&#xff0c;再预测 •数学问题&#xff1a;用一条线来拟…

【LeetCode】每日一题 2024_10_7 最低加油次数(堆、贪心)

前言 每天和你一起刷 LeetCode 每日一题~ 大家国庆节快乐呀~ LeetCode 启动&#xff01; 国庆最后一天&#xff0c;力扣还在加油站&#xff0c;怕不是国庆回家路上堵车了 题目&#xff1a;最低加油次数 代码与解题思路 func minRefuelStops(target int, startFuel int, st…

失业的程序员除了找工作,还有哪些赚钱的路子?零基础入门到精通,收藏这篇就够了_网络开发怎么赚钱

看到一个平台上的博主&#xff0c;目前在做独立开发者&#xff0c;开发了20多个网站&#xff0c;网站的类型主要是工具型和信息整理型&#xff0c;谷歌广告的收益一个月1万多。 目前他除了依靠谷歌广告的收入外&#xff0c;也在做自媒体&#xff0c;拓展这一块的收入&#xff…

41亿收购百年零部件巨头,「果链一哥」欲再造千亿规模新版图?

、 为了进一步拓展汽车业务版图&#xff0c;果链一哥立讯精密再次开启“买买买”模式。 日前&#xff0c;立讯精密发布公告称&#xff0c;计划以5.25亿欧元&#xff08;约41.3亿元人民币&#xff09;的价格收购Leoni AG&#xff08;以下简称“莱尼公司”&#xff09;50.1%股权…

打卡第五天 P3916 图的遍历

今天是我打卡第五天&#xff0c;做个普及/提高−题吧(#^.^#) 原题链接&#xff1a;图的遍历 - 洛谷 题目描述 给出 N 个点&#xff0c;M 条边的有向图&#xff0c;对于每个点 v&#xff0c;求 A(v)A(v) 表示从点 v 出发&#xff0c;能到达的编号最大的点。 输入格式 第 1 …

Golang反射解说

在Go语言中&#xff0c;反射&#xff08;Reflection&#xff09;是一种强大的机制&#xff0c;允许程序在运行时检查、修改和操作变量的类型信息。 反射主要用于处理那些在编译时无法确定类型的情况&#xff0c;比如处理接口类型的值、实现通用的函数等。 Go语言中反射的基本…

OpenAI 旧金山开发者大会发布五大创新功能 实时语音、视觉微调、模型蒸馏

在10月1日的 OpenAI 旧金山开发者大会&#xff08; DevDay&#xff09; 上 。OpenAI 公布了五项重大创新&#xff0c;其中“实时 API”&#xff08;Realtime API&#xff09;的新功能&#xff0c;使得开发者能够创建具有低延迟、AI 生成的语音响应功能的应用程序。尽管这一功能…