基于Spring Boot的楚雄旅游景区门票售卖系统设计与实现
**技术说明:**本文围绕《基于Spring Boot的楚雄旅游景区门票售卖系统设计与实现》进行技术和设计过程整理,重点关注需求分析、系统架构、数据建模、功能实现和测试验证等内容。内容用于软件工程和信息系统设计复盘,不涉及商业推广或服务宣传。
摘要
伴随着国内经济的发展,人们对生活水平的要求明显提高,对美好实物的需求日益增长,云南旅游行业迎来了新的发展机遇。然而,传统的旅游景区门票售卖模式存在有些弊端,如游客购票需长时间排队,信息获取不全面,景区管理面临游客流量难控等问题,在一定程度上制约了楚雄旅游业的进一步发展。为提升楚雄旅游业的竞争力和游客体验,设计并实现基于Springboot的楚雄旅游景区门票售卖系统迫在眉睫。本系统以Java语言为基础,采用SpringBoot框架构建后端服务,借助MySQL数据库进行数据的存储和管理数据,利用Idea进行代码的开发和调试。系统包括用户端与管理端员两大模块。用户端,可以进行登录,管理个人信息;可以浏览景区介绍、景区图片及票价等信息,方便用户预订门票,该系统允许用户实时查看和撤销订单,同时也允许用户随时调整订单的当前状态。在管理员端上,你可以对所有的用户实施管理,并查阅和修改有关景区的信息,查看订单状态,通过数据分析了解用户对那些景区更为偏爱,合理管理库存,并及时发布新闻资讯。
该系统的实现,可以解决景点信息分散、购票退订繁琐、景区管理效率低等问题,实现了门票的在线预订与支付、实时库存管理等功能,提升了游客体验,助力景区科学管理,推动了旅游行业信息化发展。
关键词:信息管理系统;Springboot框架;MySQL数据库
Abstract
With the development of the domestic economy, people's requirements for living standards have been significantly improved, and the demand for beautiful goods is growing day by day. Yunnan's tourism industry has ushered in new opportunities for development. However, there are some drawbacks in the traditional ticket sales mode of tourist attractions, such as the long queue for tourists to purchase tickets, incomplete information acquisition, and difficult control of tourist flow in the management of scenic spots, which restrict the further development of Chuxiong's tourism industry to a certain extent. In order to improve the competitiveness of Chuxiong's tourism industry and tourists' experience, it is urgent to design and implement the ticket sales system of Chuxiong's tourist attractions based on Springboot. This system is based on Java language, uses SpringBoot framework to build back-end services, uses MySQL database for data storage and management, and uses Idea for code development and debugging. The system includes two modules: client and manager. The client side can log in and manage personal information; You can browse the introduction of scenic spots, scenic pictures and ticket prices and other information, convenient for users to book tickets, the system allows users to view and cancel orders in real time, but also allows users to adjust the current status of the order at any time. On the administrator side, you can manage all users, check and modify information about scenic spots, view order status, understand which scenic spots users prefer through data analysis, manage inventory reasonably, and release news information in a timely manner.
The implementation of the system can solve the problems of scattered information of scenic spots, complicated ticket purchase and cancellation, low management efficiency of scenic spots, realize the online booking and payment of tickets, real-time inventory management and other functions, improve the tourist experience, help the scientific management of scenic spots, and promote the development of tourism industry information.
Keywords:Information management system; Springboot framework; MySQL database
第1章 绪论
1.1 研究背景
在现代信息科技的迅猛进展的当下,互联网与多个行业的联系越来越紧密,旅游行业也正在经历一场数字化的转型。楚雄,作为一个拥有丰富自然景观和人文历史资源的旅游地点,其旅游市场规模不断扩大,为了满足游客对于旅游服务的便捷性和高效性。传统的门票销售模式主要依赖人工售票窗口,这种方式并不能适应时代的发展,特别是在旅游的高峰期,游客购票时需姚长时间排队等候,浪费了游客大量的观光时间,同时也对景区的管理造成了一定的负担,容易导致游客体验不佳1。同时,人工售票也很难实现精准的数据分析和有效的资源调配,不利于景区的长远发展。在这样的背景下,基于Springboot框架开发楚雄旅游景区门票售卖系统有了出现的必要。系统凭借Springboot框架凭借其简洁的配置、很快的开发速度和部署的便利性,可以有效地建立一个稳定、可靠且功能齐全的楚雄景区门票销售系统,实现门票在线预订、支付、订单管理等一系列自动化流程,提升景区运营效率,优化游客旅游体验,推动楚雄的旅游行业走向数字化和智能化,以更有效地满足现代旅游市场的各种需求和竞争压力。
1.2 研究意义
1.2.1 理论意义
在这个科技飞速进步以及经济快速发展的时代,旅游门票管理系统开发的技术也在不断地更新和进步。基于Spring Boot的楚雄旅游景区门票售卖系统选题对于技术领域的理论研究有着多方面重要意义,Spring Boot框架作为当前主流的后端框架具有高效、易操作、便捷等特征减少用户在Java开发过程中时间投入和精力投入。深入开展本选题研究,能够进一步挖掘Spring Boot框架在处理复杂业务时的潜力,探索其在数据处理、安全机制、架构设计等多方面的深度应用,从而深化对该框架及其相关技术了解,如数据库连接、依赖注入、Web开发组件整合等的理解与应用,为其在更广泛软件开发场景中的拓展与创新提供理论依据与实践经验,推动这些技术在整个软件开发领域持续演进2。
旅游业的数字化转型已成为推动旅游行业现代化升级的核心路径。本研究侧重于研究信息技术与旅游服务深度融合,以楚雄旅游景区票务系统为实践载体,通过整合在线购票、票务管理、交易安全等数字化功能模块,构建覆盖网络通信、数据库管理与信息安全的技术体系,探索智慧旅游场景下的创新应用模式。该实践不仅验证了数字技术在提升景区运营效率、优化游客体验方面的显著成效,更为区域旅游信息化建设提供了技术方案与理论参考,对加速旅游产业数字化进程、对行业创新生态具有意义。
从软件开发的角度来看,这个系统的工程实践,确实可以为技术体系的演变提供一种新的参考范式。在整个开发的过程中,涉及的环节有很多,包括需求的分析、系统的设计、测试以及部署等等。这些环节所用的技术方法和策略,实际上是能够为软件开发的理论和方法的完善,提供一些实际的依据和依据的实例。比如说,针对旅游景区的业务特点,我们可以进行系统架构的设计,目的是为了实现高可用性和可扩展性,这个设计的过程是需要细致的考虑和反复的推敲的。另外,在多用户并发访问的场景下,我们也需要对系统的性能进行优化,这种优化的方式和策略,都是我们在实践中积累下来的经验。所有这些实践经验,都能够在某种程度上丰富我们软件开发的知识体系,同时,也能够为后续类似的项目开发,提供一些有益的参考和借鉴,尽管这些参考和借鉴并不是绝对的,但总归是有一定的帮助的3。
1.2.2 实践意义
在实践层面,该门票售卖系统为楚雄旅游景区带来诸多显著效益。系统上线后,门票销售和预约流程实现自动化处理,原本繁琐的人工售票、登记、统计等工作被高效的计算机程序所取代,极大地减少了人工操作环节,提升景区人员安排的效率,使得景区可以将更多精力投入到为游客服务与景区建设等核心业务中4。
对于游客而言,在线购票和预约服务的提供彻底改变了传统旅游购票模式。游客无需再花费大量时间在景区现场排队购票,只需在手机或电脑上轻点几下,即可随时随地完成门票预订,并能提前规划行程。这种便捷性极大地优化了游客体验,增强了游客对景区的满意度与好感度,有利于景区树立良好口碑,吸引更多潜在游客。
鉴于景区正在进行数字化转型,该系统已经变成了推动旅游行业走向数字化和智能化的核心战略。借助系统的数据分析功能,景区能够精准掌握游客流量、购票偏好、消费习惯等信息,进而合理分配景区资源,如根据游客流量预测合理安排工作人员、调配旅游设施等,有效降低运营成本,提高资源利用率,实现景区管理的现代化与精细化5。
最后,在激烈的旅游市场竞争中,一个具备便捷、高效购票服务的景区无疑更具吸引力。本系统的应用能够吸引更多游客选择楚雄旅游景区,随着游客数量的增加,景区知名度也将随之提升,进一步增强其在旅游市场中的竞争力,促进景区可持续发展并带动当地旅游经济繁荣。
1.3 发展现状
1.3.1 国外发展现状
外国的系统也为用户提供了定制化的购票选项。系统具有较高的安全性,能有效地防范各种攻击手段。该国外的系统能够依据游客的购票历史和游客的偏好,为游客门推荐最适合的旅游景点和旅游套餐。以及提供地区的地址方便游客规划旅游路线,该系统还通过建立了数据库进行数据备份和恢复机制,以确保游客在数据丢失或被非法访问的情况下,可以通过该系统能过帮助用户迅速恢复数据,从而维护游客权益和系统的稳定运行。通过对旅游景区票务销售系统中的信息进行加密处理,可以有效地防止游客利用系统获取自己想要的信息或者是获得不合法的利益。关于数据隐私的保护,存在着严格的条款和手段。为了确保游客的个人资料和支付的安全性,景区的门票销售系统经常使用尖端的加密方法和安全协议,以避免数据的外泄和不当使用同时系统正在逐步实现跨平台整合,将门票售卖与社交媒体、旅游平台等进行深度融合,为游客提供更加便捷和全面的服务13。通过建立合作伙伴关系,国外景区门票售卖系统能够与景区、酒店、交通等产业链上下游企业实现资源共享和数据互通,共同努力以提高服务的品质和增强客户的满意程度。
1.3.2 国内研究现状
在国内移动支付的普及,为旅游门票售卖系统的为用户提供了数字化服务 6。比如国内门票系统已全面支持在线预订和移动支付功能,游客可通过手机应用、微信公众号等渠道快速完成购票,通过线上购票来缓解景区现场排长队购票现象。国内的系统界面设计注重简洁直观,注重优化布局、图标和文字引导提升操作效率,通过跨平台整合,部分系统已实现与社交媒体、旅游平台的深度融合,同时与酒店、交通等产业深度绑定,推动旅游服务生态化发展。但还有少部分系统仍存在界面层级复杂、功能跳转繁琐等问题,整体安全防护仍存在漏洞风险。需重点解决在线退改签功能不完善、支付流程稳定性不足以及界面视觉协调性等问题,以用来全面提升服务质量和系统可靠性。由于系统的技术水平、用户体验、市场推广等方面存在不足,部分系统可能仍处于试点或初步应用阶段,同时旅游企业和景点的合作与交流不足7,导致尚未能形成一个完整的体系。
1.3.3 研究内容
在我们对基于Spring Boot的景区门票售卖系统进行了一番深入的探讨和研究之后,可以说我们对于国内外在这一领域所取得的成果与不足之处,已经有了一个比较清晰的认识。想真正解决当前存在的一些问题,并推动这个系统的进一步发展,需要明确一些具体的研究内容。本研究包括框架分析、系统功能模块分析、应用效果分析具体如下:
-
系统采用Spring Boot架构作为后端,帮助用户管理、门票管理、支付处理等模块进行数据整合。
-
系统功能模块包含以下核心部分:用户管理模块包括注册、登录及权限分级控制;景区管理模块支持景点信息维护、门票价格动态调整及库存实时查看,帮助管理员进行人员分配和门票的管理;数据分析模块为管理员提供数据帮助管理员进行分析,为管理员战神销售趋势、用户行为数据及反馈统计,为运营决策提供多维数据支撑。
3.应用效果:该系统是一个具有实际应用价值的项目。该系统可以提升了游客的购票体验,也可以为景区管理提供了高效的数据支持。通过技术创新和优化,该系统有望成为旅游行业数字化转型的推力。
第2章 关键技术简介
2.1 Java语言
Java的核心之一为面向对象编程,通过使用new关键字来构建对象。Java借鉴了C++的面向对象的编程优势,还抛弃了C++中指针等概念。Java语言本身还具有良好的可移植性、安全性以及易于维护让它众多开发者的首选,虽然 C++提供了多继承的功能,而Java仅支持单一继承。但是Java语言本身功能强大,而且操作简便,受到了经验丰富的程序员和程序爱好者的高度评价。Java语言,作为OOP编程语言的典型代表,成功地融合了面向对象的编程理念。在Spring的核心组件IOC控制反转中,引入了依赖注入DI的思想,为Java为程序员提供了一个优雅的平台,使其能够进行复杂的链式编程,并支持多线程、网络编程、反射、克隆和序列化等多种编程概念。对于初学者来说,Java可以分为Javase、JavaEE和JavaME三种类型。只有在坚实的Javase基础上,他们才能进一步研究偏向企业开发的JavaEE。值得注意的是,JavaME在过去主要用于移动端开发,但现在已经变得越来越少。目前,基于Java技术的Web开发技术研究代表了Web技术开发领域的最新趋势。它不仅为人们提供一种方便、高效的信息交流手段,更重要的是能够提高人们的工作效率和质量,使工作变得更加轻松、快捷。鉴于当前Web技术研究中不断涌现的挑战,Web技术的设计方式也需要寻求新的创新和突破。
2.2 SpringBoot框架
SpringBoot是一个以Java为基础开发的开放源代码框架,其主要目的是为了简化Spring应用程序的初步构建和开发流程。该平台支持多种编程语言,可以在不同操作系统下部署。该应用程序秉持"约定优于配置"的设计理念,通过提供丰富的默认配置选项和自动化配置机制,使得开发人员能够迅速构建出具有独立运行能力和生产级别的Spring应用。SpringBoot整合了众多常用的开发库和框架,如Spring MVC用于构建Web应用的RESTful服务,Spring Data方便与各种数据库进行交互等8。该框架内部集成了Tomcat、Jetty等Web存储设备,用户无需进行繁琐的部署设置就能轻松启动。通过对客户端进行简单修改就可以完成所有功能。开发团队只需要集中精力于实现业务逻辑,这大大简化了复杂的配置流程,并显著提升了开发的效率。此外,它的丰富插件和扩展功能可以满足各种规模和场景的应用开发要求,在开发需求方面,无论是小型项目的迅速迭代,还是大型企业级应用的构建,SpringBoot都起到了关键作用并提现出来出了卓越的适应性和稳定性,在当今的Java开发领域占据着极为重要的地位。
2.3 MySQL数据库
MySQL作为现在主流的关系型数据库管理系统,可以进行跨平台运行,可以在Windows、Linux、Unix等操作系统上稳定运行,适用于不同环境下的应用开发。该系统遵循标准SQL语法规范,支持数据库创建、表结构设计及数据增删改查操作。在性能方面,MySQL能有效处理高并发数据请求,满足企业级应用的高负载需求。其提供包括文本、数值、日期时间在内的多种数据类型,适配不同业务场景的数据存储要求。通过事务处理机制保障数据操作的原子性和一致性,结合数据备份与恢复功能,确保系统数据安全可靠。MySQL拥有活跃开放的社区支持,开发者可以从中方便地获取技术文档、问题解决方案以及各种插件和工具,不断拓展其功能边界,在众多互联网应用、企业信息系统等领域都有着极为广泛的应用10。
2.4 Idea开发工具
IntelliJ是IDEA的全称,是一个很受欢迎的开发工具,主要用于Java的开发。与Eclipse IntelliJ相比,IDEA在多个方面具有明显的优势。例如,当我们更改一个类的名称时,之前对应的其他层的类名也会自动进行相应的修改。另外,还可以将一些复杂的操作用简单的方法去实现。Springboot在Web开发方面表现出色,特别适用于Restful的前端和后端独立编码,支持正则表达式。它能够把代码中所有数据进行统一管理,可以将其保存到数据库里。它也还能够整合众多的页面模板引擎组件,如Thymeleaf、FreeMaker等,为Web项目的开发提供便利。IDEA是JetBrains公司的一个子公司,其界面设计与Android studio等类似。特别适合于快速开发程序。它还具有丰富的编辑控件和自定义属性。IDEA提供了强大的快捷键功能。比如用户只需按下Ctrl+F,就可以通过搜索类名、JS方法名称和变量名来迅速定位。而按Ctrl+E则可以打开之前打开的文件。不满足Java定义规范的变量会被特别标记,这是为了提醒开发者进行修改。另外还有一个很重要的选项就是打断点。IDEA的断点功能便捷,在执行程序时,开发者还可以选择在Debug模式下运行,这为开发者带来了诸多的便捷。
2.5 B/S架构
在web技术还未受到足够的关注并被广泛应用于日常生活中之前,许多现有的系统在设计上主要还是使用C/S开发模式。这种开发模式具有可以在单机或局域网环境中运行的特点,可以避免了受到病毒干扰的风险,是由于该架构具有良好的扩展性以及灵活性等优点,使得该架构可以广泛应用于不同领域的系统当中,但是也存在一个不太友善的问题,那就是当系统在运行过程中发现程序存在BUG时,就必须重新部署其客户端,尤其是在大量客户端的部署情况下,这样的工作量是非常巨大的。如果要使其正常运行,就必须重新对系统进行配置和升级等工作,这可能会给用户带来较大的工作量,以及造成巨大的资源浪费。为了应对程序更新可能导致的大量工作,我们采用了一个与C/S模式不同的B/S设计模式,该模式以浏览器作为其客户端。简化了系统的开发流程,提高了用户友好性,还为后续的系统维护提供了便利。使用这种结构时,只需在计算机上安装数据库和一些常用的浏览器即可。数据库由服务器端提供的数据来存储和管理的。浏览器能够与多个数据库建立信息链接,实现多种功能。B/S架构是直接可用的,并且在使用过程中,B/S架构大大降低了工作维护的需求。通过这种结构也能使用户快速方便的访问到相关的数据。基于B/S架构的软件确保了所有数据库之间的独立性,从而实现了极高的安全性。另外由于数据库本身就是一个分布式的管理系统,所以在对它的管理上也更加简单方便。基于B/S架构,我们可以看到系统正在处理的各种业务,并为管理层提供及时的决策支持,这有助于减少企业可能遭受的损失。B/S架构的核心特性在于其集中化的管理方式。当用户通过系统产生数据时,这些信息可以被储存到系统的数据库中,从而便于未来的使用,满足人们各种不同的需求。

图2-1 B/S模式三层结构图
第3章 系统分析
3.1 可行性分析
3.1.1 经济可行性
开发基于Spring Boot的楚雄旅游景区门票售卖
从经济角度看,该系统具有相当高的实用性。考虑到开发的成本,我们选择了开源的Spring Boot框架、MySQL数据库和Vue.js的前端架构,用来降低软件开放成本。确实是如此。开发团队主要是集中在技术人力成本上,而这些技术的广泛应用使得相关的开发人员相对来说比较容易招聘,人力成本也算是比较可控的。在运营方面,一旦系统建成之后,能够显著提高门票的销售效率,这样就能减少人工售票窗口的设置以及人力的投入,长期看来,可能会降低运营的成本。通过线上售票的方式,还能够拓展客源,增加门票的收入,例如吸引更多的外地游客提前进行预订,这也是一个不错的想法。此外,系统也可以整合一些旅游周边产品的销售,比如门票销售、景区的评价等等,开辟新的盈利渠道,为景区带来更多的经济收益。因此,从经济层面来看,这个系统的开发与运营是切实可行的,确实具有良好的投资回报率。
3.1.2 技术可行性
该系统的技术方案具备坚实的可行性。该系统的后端使用了Spring Boot框架,这大大简化了基于Java的企业级应用开发过程,它具备快速构建、易于部署和高效运行的优点,能方便地整合各种后端服务与资源11。景区门票系统采用业界主流技术方案实现开发和运维。使用MySQL数据库凭借数据库的处理能力和架构,精准管理游客资料、票务订单及库存动态数据。前端采用Vue.js渐进式框架构建响应式界面,支持用户完成余票查询、在线预定门票和移动支付等交互操作。后端实验Java语言,利用跨平台特性和Spring生态体系保障了系统在多环境下的稳定运行。整套技术栈拥有丰富的开发者社区资源,开发人员可快速在期中获取问题解决方案,降低开发风险。
3.1.3 操作可行性
此门票售卖系统在操作层面具有良好的可行性。对于游客而言,系统界面设计基于Vue.js构建,采用简洁直观的布局与流程,游客仅需通过常见的浏览器或手机应用即可轻松访问。操作流程遵循常规的线上购物模式,如注册登录、查询门票、选择日期与数量、填写个人信息、完成支付等步骤,简单易懂,即使是对计算机操作不太熟悉的游客也能快速上手12。对于景区管理人员,系统基于Spring Boot开发的后台管理界面同样简洁易用,功能模块划分清晰,如景区信息管理、订单处理、用户管理等,管理员能够方便地进行数据录入、信息修改、订单审核等日常操作,无需复杂的培训即可胜任。并且系统提供了详细的操作指南与帮助文档,无论是游客在购票过程中还是管理员在后台操作时遇到问题,都能及时获取帮助,确保系统在实际使用过程中能够被各方顺利操作,发挥其应有的功能与价值。
3.2 需求分析
在旅游行业发展的当下,传统的楚雄旅游景区门票售卖面临着一系列问题,需要重新打造数字化体系与时俱进构建基于Springboot的现代化门票售卖系统。围绕着用户与管理员两类主要角色进行贴合实际的展开。
对于用户来说,系统需要为用户提供便捷注册登录功能,确保用户能轻松进入平台。个人信息管理模块需要为用户可自主更新联系方式与密码,保障账户安全。景区浏览功能需要为用户进行全方位展示景区介绍、图片及票价,为用户挑选目的地提供充分信息。门票预订应支持在线选日期、时段与票种,完成便捷预订。订单管理需要为方便用户查看、取消未支付订单,获取电子票并跟踪状态。评价和反馈功能让用户在游览后分享体验,促进景区服务提升。消息通知需要及时推送订单确认等关键信息,支付管理需要为用户实现快速支付。
从管理员角度,用户管理权限需要可查看所有用户列表,执行禁用、启用操作维护秩序。景区管理能添加、编辑、删除景区信息,保证信息准确时效。订单管理可以查看所有订单状态,公正处理退款。评论审核保证评论真实适当。数据分析需要帮助管理者依据销售数据做出合理安排。库存管理需要确保用户能随时买到喜欢景区门票。新闻资讯管理需要发布活动公告、优惠信息。
3.2.1 功能需求分析
在Springboot的楚雄旅游景区门票售卖系统之中,它需要贴合实际同时满足用户和管理员不同的使用需求。用户有注册登录、个人信息管理、景区浏览门票预订、订单管理、评价反馈、消息通知、支付管理等操作,可以满足了游客在购票及旅游过程中的大部分需求。管理员有用户管理、景区管理、订单管理、评论审核、数据分析、库存管理、新闻资讯管理等功能。
1.用户功能
注册登录:用户注册账号,注册完成后通过输入账号和对应的密码直接登录。
个人信息管理:用户可以对自己的信息进行自己信息的查看和对错误信息进行修改,当填写的信息需要变更的时候可以自行修改,忘记密码时联系过来了进行密码等信息的修改。
景区浏览:用户可以通过查看景区介绍、图片展示及票价信息了解当地景区情况,并可以让用户实际情况自主选择自己喜欢旅游目的地。
门票预订:用户可以通过门票预定提前购买喜欢景区门票,规划旅游时间。
订单管理:用户可以通过订单管理查看订单状态,对于不需要订单可以取消订单,方便用户修改订单状态。
评价与反馈:用户通过评论和反馈能够对对游玩过景区进行打分和分享旅游心得。
消息通知:通过信息通知系统会向用户发送订单是否确认、支付成功、以及退订等通知。
支付管理:用户可以通过支付管理进行支付,在支付完成后可以选择退票。
2.管理员功能
用户管理:管理员可以通过用户管理查看用户详细信息对应需要修改密码的用户管理员可以为其修改用户的信息。
景区管理:管理员通过景区管理可以进行添加之前没有的景区信息、删除多余的景区信息、以及修改有误的景区信息。
订单管理:管理员可以根据用户的订单状态以及用户的意愿,给用户进行退款处理。
评论审核:管理员可以查看用户评论的内容,对有些不文明的评论和不符合实际情况的抹黑进行删除处理也可以对用户的评论进行回复。
数据分析:管理员通过不同票种的销售情况,并根据销售情况进行分析做出合理的营销策略转变。
库存管理:管理员可以根据实际情况进行对库存门票的增加删修改查询以及删除,合理的规划库存情况。
新闻资讯管理:管理员可以实时修改进行新闻资讯的修改删除对于库存过多的门票推出合理的活动,以方便用户可以第一时间查看门票优惠的相关信息。
3.2.2 系统用例分析
(1)用户用例分析
用户具有注册登录、个人信息管理、景区信息浏览、门票预定、评价与反馈、订单管理、消息通知支付管理等功能。

图3-1 用户用例图
(2)管理员用例分析
管理员具有用户管理、景区管理、订单管理、评论管理、数据分析、库存管理、新闻资讯管理等功能。

图3-2 管理员用例图
第4章 系统设计
4.1 系统结构设计
在前端使用Html编程语言来展示基础内容,并使用CSS编程语言对网页进行格式排版优化,在后端使用Servlet处理浏览器发送的各种请求,调用业务逻辑层函数来实现功能。该系统使用Struts2框架来连接Java代码和MySQL数据库采用面向对象的方法来操作数据库连接,使用Struts2的配置文件,实现实体类与数据库表之间的映射关系和MySQL数据库自动生成的目的。基于Springboot的楚雄旅游景区门票售卖系统网站的技术层次图如图4-1所示:
图4-1 网站技术层次图
4.2 系统模块设计
本基于Springboot的楚雄旅游景区门票售卖系统主要围绕用户和管理员两类角色构建了多个核心功能模块,如图4-2所示。用户可以在前台查看楚雄旅游景区景点的信息以及进行门票的购买,系统管理员可以对各种资源信息进行相应的操作。可以为用户提供便捷的购票体验,帮助力管理员高效管理景区票务相关事务。
系统围绕用户需求构建了完整的功能体系。作为服务的入口,注册和登录是必要的。对于那些尚未注册的用户,他们首先需要完成注册程序。只有在完成注册后,他们才能登录。对于已经注册或注册的用户,他们可以直接登录,并在登录后对个人信息进行修改和完善。此外,他们还可以浏览景区,并在看到自己喜欢的景区时预订门票进行支付。一旦支付完成,他们还可以修改订单,并在订单中进行相应的修改,成功后会有消息通知。
对管理员来说,在系统中管理员可以对用户需要查看和修改的用户信息就行查看修改审核。对景区管理模块管理员可以根据实际添加未有的景区信息、修改有误的景区信息或删除多余的景区信息,对于订单管理模块管理员可以管理所有订单状态,参考用户的意愿进行合理的退款请求,对于评论管理管理员可以对用户评论进行回复以及对用户不合理不文明的评论进行删除,对于数据分析模块管理员可以通过系统统计的销售数据,做出库存合理的安排规划,以提高管理员的效率。对于库存模块管理员可以合理管理景区内门票的库存,及时补货。对于对于新闻资讯管理模块管理员可以修改发布活动公告、优惠信息,让用户能够及时看到优惠信息。
这些模块相互协作,共同构成了楚雄旅游景区门票售卖系统,可以满足了用户和管理员在不同层面的需求。

图4-2 系统功能模块图
4.3 详细设计
4.3.1 用户模块
(1)注册
用户注册功能为游客提供创建个人账户的数字化服务。注册者需填写真实有效的手机号码或电子邮箱作为主账号,并设置包含字母、数字及特殊字符的安全密码。系统会实时校验账号唯一性及格式合规性,同时支持用户自定义便于记忆的专属昵称。完成注册流程后,用户可通过认证信息登录楚雄旅游景区票务系统,进行景区门票在线选购、订单状态查询、电子票核验等全流程服务,系统将为每位用户建立独立档案以保障交易安全与数据隐私。用户注册程序流程如图4-3所示。

图4-3 用户注册程序流程图
(2)登录
登录功能允许已注册用户在输入对应的账号和密码时进入系统。系统会将用户输入的账号和密码与数据库存储的信息进行比对。若两者相同,用户就能成功登录,并进入系统界面,可使用各种服务,如浏览景区、预订门票、查看订单等;若信息错误,系统会给予相应提示,保障系统安全,避免非法用户进入。用户登录程序流程如图4-4所示。

图4-4 用户登录程序流程图
(3)个人信息管理
用户登录系统后,可以进入个人信息管理模块。在此模块中,用户可对自己的资料进行修改和完善。可以根据提示更新联系方式,无论是手机号码的变更还是电子邮箱的修改,都可及时操作以确保用户信息的时效性。对于密码,用户可根据自身需求和安全考虑进行修改,设置更符合个性化的密码,方便用户记忆。个人信息修改程序流程图如图4-5所示。

图4-5 个人信息修改程序流程图
(4)景区浏览
当用户想要选择旅游目的地时,可进入景区浏览模块。系统会以图文并茂的形式详细展示各个景区的信息。不仅有精美的风景图片呈现景区的独特风貌,还会有详细的文字介绍,包括景区的历史文化、特色景点、设施服务等。同时,明确标注各景区的票价信息,使用户能一目了然。用户可以通过滚动浏览、点击详情等操作,全面了解不同景区,从而轻松选择出心仪的旅游目的地。景区浏览程序流程图如图4-6所示。

图4-6 景区浏览程序流程图
(5)门票预订
在确定旅游目的地后,用户可进入门票预订模块进行操作。用户首先在线选择计划游览的日期和时段,系统会实时显示相应的可预订情况。接着,用户根据自身需求选择合适的票种,如成人票、儿童票等。确认所选信息无误后,按照提示点击预订按钮,系统会自动根据进行库存进行比对。若库存还有,则预订成功,用户可以根据提示进行后续的支付流程;若库存不足,系统会提示用户重新选择或调整预订信息。门票预订程序流程图如图4-7所示。

图4-7 门票预订程序流程图
(6)订单管理
用户的订单管理模块为用户提供了全方位的订单相关的服务。用户可以通过订单管理查看自己提交的订单信息,如订单的编号、预订的景区门票信息、订单本身的状态、订单的金额、支付订单。同时,用户可对没有进行支付的订单进行取消操作,也可查看已支付订单的状态,确保其能顺利完成整个旅游行程安排,还能查看和获取电子票,便于快速入园。如支付订单程序流程图如图4-8所示。

图4-8 支付订单程序流程图
4.3.2 管理员
(1)用户管理
管理员进入用户管理模块后,可查看系统内所有用户的详细列表,包含注册的手机号、电子邮箱、用户名等信息。当发现有违规用户时,管理员能迅速执行禁用操作,限制该用户对系统的访问;若用户问题解决,也可及时启用其账号。同时,对于新注册用户,管理员可审核其信息的真实性和完整性,确保社区秩序良好,为所有用户营造安全、可靠的使用环境。用户信息修改程序流程图如图4-9所示。

图4-9 用户信息修改程序流程图
(2)景区管理
管理员在景区管理模块可全面掌控景区信息。对于新开发或未录入的景区,管理员能为这些景区详细详细信息,若信息有变更,管理员可随时编辑更新,保证信息的时效性。当景区不再运营时,管理员则可将其删除,避免给用户造成误导。添加景区程序流程图如图4-10所示。

图4-10 添加景区程序流程图
(3)订单管理
管理员通过订单管理模块可以查看所有订单状态。系统为管理员提供实时更新订单的状态。当有用户提出退款请求时,管理员会详细审核订单情况,包括购票信息、游玩情况等,确保退款交易公正透明。同时,管理员还可对订单数据进行统计分析,了解销售趋势,为景区运营策略的调整提供有力依据。订单修改程序流程图如图4-11所示。

图4-11 订单修改程序流程图
(4)数据分析
管理员通过数据分析查看景区那些门票受游客欢迎,那些门票需要添加更多库存,通过数据分析还可以知到那些景区需要加派人手,那些景区服务员多而游客少,也可以看出不同年龄段的人喜欢去哪里旅游,不同性别的人喜欢去哪里旅游。数据分析流程图如图4-12所示。

图4-12 数据分析流程图
(5)库存管理
管理员可通过该模块对各景区的门票库存数量进行实时监控和管理。系统会根据票种和状态进行详细的商品统计,帮助管理员清晰了解每种门票的库存情况。当库存数量很少的时候,管理员可以及时进行库存补充,保证游客随时买到自己喜欢景区的门票。当库存多的时候管理员也可以通过发布公告鼓励游客消费减轻库存压力。库存修改程序流程图如图4-13所示。

图4-13 库存修改程序流程图
4.4 数据库设计
4.4.1 数据库概念结构设计
数据库设计是在一个特定的环境,为了满足有效地数据处理和数据存储等一系列要求,需要建立一个优质的与本系统对应的数据库模型。在进行数据库的重新设计时,我们需要根据用户的具体需求,在指定的数据库管理系统上构建和规划整个数据库流程,这也是软件开发中的核心技术之一。在数据库领域中,一般是把使用数据库的各类系统统称为数据库应用系统。
在基于Spring Boot的楚雄旅游景区门票售卖系统里,用户是整个系统的重要参与者,也是系统各项功能的主要使用者。因此,需要创建用户实体来存储与用户相关的详细信息。用户实体涵盖了用户的基本信息,如用户名、密码、姓名、性别、添加时间、权限、信息审核、备注、照片、联系方式等。用户信息实体属性图如图4-14所示。

图4-14 用户实体属性图
景区信息实体包含了景区编号、景区图片、景点名称、景区介绍、景区评论、景区位置、开放时间、备注、景点介绍等,这些信息能够帮助用户全面了解景点的情况,从而做出购票决策。景点信息实体属性图如图4-15所示。

图4-15 景区信息实体属性图
景区门票实体包含了编号、商品编号、景区名称、景区介绍、景区图片、门票价格、库存、开放时间、票种、用户名字、状态、备注等,门票实体属性图如图4-16所示。

图4-16 景区门票实体属性图
新闻通知实体包含新闻编号、新闻标题、新闻类别、新闻内容、点赞数、点击率、添加时间,是景区门票售卖系统的组成部分。公告信息实体属性图如图4-17所示。

图4-17 新闻通知实体类
订单实体包括编号、订单编号、总价格、用户编号、联系地址、联系电话、联系人、添加时间、订单状态,是景区门票售卖系统中的重要的组成部分。订单实体属性图如图4-18所示。

图4-18 订单实体类
管理员实体包含管理员编号、管理员的用户名、管理员的密码、管理员信息的添加时间、管理员权限、状态,也是景区票务系统重要组成部分之一,主要负责管理管理员后台系统,管理员实体的创建用来储存和管理员相关的信息。管理员信息实体属性图如图4-19所示。

图4-19 管理员实体
评论实体包含了评论的基本信息,如评论内容、评论时间、评论者的用户名等,同时还会关联所评论的景点,以便用户能够清晰地了解每条评论对应的景点。评论信息实体属性图如图4-20所示。

图4-20 评论实体属性图
我的收藏实体包含了收藏编号、景区编号、用户名、景区名称、添加时间,同时还会关联所收藏的景点,以便用户能够快速查找喜欢的景点。我的收藏实体属性图如图4-21所示。

图4-21 我的收藏实体属性图
购物车实体包含了编号、用户编号、商品编号、商品数量,方便用户进行多张门票同时支付。购物车实体属性图如图4-22所示。

图4-22 购物车实体属性图
库存实体包含了编号、景区编号、景区名称、景区类别、门票价格、添加时间、库存数量、入库价格、入库数量、入库时间、备注,以便管理员能够快速进行库存管理。库存实体属性图如图4-23所示。

图4-23 库存实体属性图
本系统的总E-R图清晰地描绘了楚雄旅游景区门票售卖系统中各实体之间的关系。主要实体包括用户、景区信息、景区门票、订单、评价、库存、管理员、我个人的收藏、购物车以及新闻通知。用户与订单之间存在一对多关系,用户与景区信息是多对多关系,用户和景区门票也存在一对多关系,用户与我的收藏是一对多关系,用户与评论是一对多关系,用户与新闻通知是多对多关系,用户和购物车是一对一关系,管理员与用户是一对多关系,管理员和库存是一对多关系,管理员与新闻通知是一对多关系,管理员与订单是一对多关系,管理员与评论是一对多关系,管理员与景区信息是一对多关系。如图4-24所示。

图4-24 系统总E-R图
4.4.2 数据库逻辑结构设计
通过上面的分析,数据库表设计如下:
用户表记录了系统后台管理员的基本信息包括编号、用户名、密码、姓名、照片、性别、联系方式、备注、信息审核、限权、添加时间,用于系统的管理和维护操作。如图4-1所示。
表4-1 用户表
| 序号 | 字段名称 | 字段类型 | 大小 | 允许为空 | 最大长度 | 备注 |
|---|---|---|---|---|---|---|
| 1 | id | int | 11 | 否 | 50 | 编号 |
| 2 | yonghuming | varchar | 50 | 否 | 50 | 用户名 |
| 3 | mima | varchar | 50 | 否 | 50 | 密码 |
| 4 | xingming | varchar | 50 | 否 | 50 | 姓名 |
| 5 | zhaopian | varchar | 50 | 否 | 50 | 照片 |
| 6 7 8 9 10 11 | xingbie lianxifangshi beizhu xinxishenhe quanxian addtime | varchar varchar varchar varchar varchar timestamp | 50 50 500 10 10 8 | 否 否 否 否 否 否 | 50 50 500 10 10 8 | 性别 联系方式 备注 信息审核 限权 添加时间 |
新闻通知是对记录的是新闻编号、新闻标题、新闻类别、新闻内容、点赞数、点击率、添加时间这些字段进行存储。方便用户对应相关信息的获取。如图4-2所示。
表4-2 新闻通知表
| 序号 | 字段名称 | 字段类型 | 大小 | 允许为空 | 最大长度 | 备注 |
|---|---|---|---|---|---|---|
| 1 | id | int | 11 | 否 | 20 | 新闻编号 |
| 2 | biaoti | varchar | 50 | 否 | 300 | 新闻标题 |
| 3 | leibie | varchar | 50 | 否 | 50 | 新闻类别 |
| 4 | neirong | longtext | 8 | 否 | 8 | 新闻内容 |
| 5 | dianzanshu | int | 11 | 否 | 50 | 点赞数 |
| 6 | dianjilv | int | 11 | 否 | 11 | 点击率 |
| 7 | addtime | datetime | 8 | 否 | 8 | 添加时间 |
订单表记录的是对用户对门票购买的订单信息,字段包括编号、订单编号、总价格、用户编号联系地址、联系电话、联系人、添加时间、订单状态进行储存。方便用户进行订单管理。如图4-3所示。
表4-3 订单表
| 序号 | 字段名称 | 字段类型 | 大小 | 允许为空 | 最大长度 | 备注 |
|---|---|---|---|---|---|---|
| 1 | id | int | 11 | 否 | 11 | 编号 |
| 2 | dingdanbianhao | int | 20 | 是 | 20 | 订单编号 |
| 3 | zongjiage | int | 11 | 是 | 11 | 总价格 |
| 4 | yonghuid | int | 11 | 是 | 11 | 用户编号 |
| 5 | lianxidizhi | varchar | 50 | 是 | 50 | 联系地址 |
| 6 | lianxidianhua | varchar | 20 | 是 | 20 | 联系电话 |
| 7 | lianxiren | varchar | 20 | 是 | 20 | 联系人 |
| 8 | addtime | varchar | 255 | 是 | 255 | 添加时间 |
| 9 | zhuangtai | varchar | 255 | 否 | 255 | 订单状态 |
景区信息表是对存储各个景区的详细资料,包括了景区编号、景区名称、景区介绍、景区图片、景区评价、景区地址、景区开放时间、备注、景区添加时间,方便用户更好了解景区情况。如图4-4所示。
表4-4 景区信息表
| 序号 | 字段名称 | 字段类型 | 大小 | 允许为空 | 最大长度 | 备注 |
|---|---|---|---|---|---|---|
| 1 | id | int | 4 | 否 | 8 | 景区编号 |
| 2 | jingqumingcheng | varchar | 50 | 是 | 50 | 景区名称 |
| 3 | jingqujieshao | longtext | 8 | 否 | 8 | 景区介绍 |
| 4 | tupian | varchar | 50 | 否 | 50 | 景区图片 |
| 5 | pingjia | varchar | 50 | 否 | 50 | 景区评价 |
| 6 | dizhi | varchar | 50 | 是 | 50 | 景区地址 |
| 7 | kaifangshijian | datetime | 8 | 是 | 8 | 景区开放时间 |
| 8 | beizhu | varchar | 500 | 是 | 500 | 备注 |
| 9 | addtime | timestamp | 8 | 否 | 8 | 景区添加时间 |
景区门票表时对各个景区门票的详细资料进行存储包括字段有编号、商品编号、景区名称、景区介绍、景区图片、门票价格、库存开放时间、票种、用户名字、状态、备注、添加时间,方便用户更好了解景区门票情况。如图4-5所示。
表4-5 景区门票表
| 序号 | 字段名称 | 字段类型 | 大小 | 允许为空 | 最大长度 | 备注 |
|---|---|---|---|---|---|---|
| 1 | bianhao | int | 11 | 否 | 11 | 编号 |
| 2 | shanpinbianhao | varchar | 50 | 否 | 50 | 商品编号 |
| 3 | jingqumingcheng | varchar | 50 | 否 | 50 | 景区名称 |
| 4 | jingqujieshou | varchar | 50 | 否 | 50 | 景区介绍 |
| 5 | jingqutupian | varchar | 50 | 否 | 50 | 景区图片 |
| 6 | menpiaojiage | varchar | 50 | 否 | 50 | 门票价格 |
| 7 | kucun | varchar | 50 | 否 | 50 | 库存 |
| 8 | kaifangshijian | varchar | 50 | 否 | 50 | 开放时间 |
| 9 | pianzhong | varchar | 50 | 否 | 50 | 票种 |
| 10 | yonghuid | varchar | 50 | 否 | 50 | 用户名字 |
| 11 | zhuangtai | varchar | 50 | 否 | 50 | 状态 |
| 12 | beizhu | varchar | 500 | 否 | 500 | 备注 |
| 13 | addtime | timestamp | 8 | 否 | 8 | 添加时间 |
评论表是对各个景区游客评论的详细资料进行存储,包括有编号、用户名、评论内容、景区编号、评分、添加时间、回复,方便用户更好了解景区游客游玩情况。如图4-6所示。
表4-6 评论信息表
| 序号 | 字段名称 | 字段类型 | 大小 | 允许为空 | 最大长度 | 备注 |
|---|---|---|---|---|---|---|
| 1 | id | int | 11 | 否 | 11 | 编号 |
| 2 | yonghuming | varchar | 50 | 否 | 50 | 用户名 |
| 3 | pinglunneirong | varchar | 500 | 否 | 500 | 评论内容 |
| 4 | jingquid | varchar | 255 | 否 | 255 | 景区编号 |
| 5 | pingfen | varchar | 50 | 否 | 50 | 评分 |
| 6 | addtime | timestamp | 8 | 否 | 8 | 添加时间 |
| 7 | huifu | varchar | 500 | 否 | 500 | 回复 |
我的收藏表是对用户喜欢景区的资料进行存储,包括有编号、用户名、景区编号、景区名称、添加时间,方便用户更好了解和查找喜欢景区。如图4-7所示。
表4-7 我的收藏信息表
| 序号 | 字段名称 | 字段类型 | 大小 | 允许为空 | 最大长度 | 备注 |
|---|---|---|---|---|---|---|
| 1 | id | int | 11 | 否 | 11 | 编号 |
| 2 | yonghuming | varchar | 50 | 否 | 50 | 用户名 |
| 3 | jingqubianhao | varchar | 50 | 否 | 50 | 景区编号 |
| 4 | Jingqumingcheng | varchar | 50 | 否 | 50 | 景区名称 |
| 5 | addtime | timestamp | 8 | 否 | 8 | 添加时间 |
购物车表是的用户将要购买的门票信息进行存储,包括有编号、景区编号、用户编号、数量,方便用户更好了解和查找喜欢景区。如图4-8所示。
表4-8 购物车收藏信息表
| 序号 | 字段名称 | 字段类型 | 大小 | 允许为空 | 最大长度 | 备注 |
|---|---|---|---|---|---|---|
| 1 | id | int | 11 | 否 | 11 | 编号 |
| 2 | jingquid | int | 20 | 否 | 20 | 景区编号 |
| 3 | yonghuid | int | 20 | 否 | 20 | 用户编号 |
| 4 | shuliang | int | 20 | 否 | 20 | 数量 |
管理员用户表是的系统后台管理员的基本信息进行存储,包括有编号、用户名、密码、限权、添加时间,用于系统的管理和维护。如图4-9所示。
表4-9 管理员信息表
| 序号 | 字段名称 | 字段类型 | 大小 | 允许为空 | 最大长度 | 备注 |
|---|---|---|---|---|---|---|
| 1 | id | int | 11 | 否 | 11 | 编号 |
| 2 | yonghuming | varchar | 50 | 否 | 50 | 用户名 |
| 3 | mima | varchar | 50 | 否 | 50 | 密码 |
| 4 | zhuangtai | varchar | 10 | 否 | 10 | 状态 |
| 5 | xianquan | varchar | 10 | 否 | 10 | 限权 |
| 6 | addtime | timestamp | 8 | 否 | 8 | 添加时间 |
库存表是对用户可以购买的门票信息进行存储,包括有编号、景区编号、景区名称、景区类型、销售价格、库存数量入库价格、入库数量、入库时间、备注、添加时间,方便管理员更好管理景区库存。如图4-10所示。
表4-10 库存表信息表
| 序号 | 字段名称 | 字段类型 | 大小 | 允许为空 | 最大长度 | 备注 |
|---|---|---|---|---|---|---|
| 1 | id | int | 11 | 否 | 11 | 编号 |
| 2 | jingquid | varchar | 50 | 否 | 50 | 景区编号 |
| 3 | jingqumingcheng | varchar | 50 | 否 | 50 | 景区名称 |
| 4 | jingquleibie | varchar | 50 | 否 | 50 | 景区类别 |
| 5 | xiaoshoujiage | varchar | 50 | 否 | 50 | 销售价格 |
| 6 | kucunshuliang | varchar | 50 | 否 | 50 | 库存数量 |
| 7 | rukujiage | varchar | 50 | 否 | 50 | 入库价格 |
| 8 | rukushuliang | varchar | 50 | 否 | 50 | 入库数量 |
| 9 | rukushijian | date | 10 | 否 | 10 | 入库时间 |
| 10 | beizhu | varchar | 500 | 否 | 500 | 备注 |
| 11 | tianjiashijian | timestamp | 8 | 否 | 8 | 添加时间 |
4.5 界面设计
基于springboot楚雄旅游景区门票售卖系统的界面在设计上融合了当地特色景区,用轮播图展示楚雄景区特色美景,在界面上清楚的表明了用户可以使用的功能,在景区详细介绍界面,详细的接受了楚雄景区所在地、具体景色、开放时间,在个人信息管理界面可以快速修改用户信息,在门票预订界面可以快速进行门票预定,同样在支付和订单管理界面也是很简洁明了方便游客进行操作和选择自己喜欢的景区以及购买门票。在管理员界面,管理员对自己的功能也能一目了然,采用侧边栏导航,可快速切换用户管理、景区管理、订单处理等功能区域,数据表格展示清晰,操作按钮布局合理,方便管理员可以高效地进行各项管理工作,整体界面设计旨在提升系统的易用性和操作效率。
第5章 系统实现
5.1 数据库链接的实现
在这个系统里,采用了Spring Boot的数据库连接方法,通过连接MySQL数据库配置连接地址、端口、用户名以及密码等关键参数。采用JDBC或更高级的连接池技术建立稳定高效连接。在代码层面,利用相关持久层架构(例如MyBatis),我们编写数据访问对象(DAO)接口和SQL映射文件,从而实现了对数据库表增加、删除、修改和查询操作。这种方式确保了系统在操作时能与数据库流畅互动,安全且可靠地保存用户资料、订单信息、景点详情和门票库存等数据,为系统功能成功实施提供了坚实数据基础。
5.2 系统功能模块的实现
5.2.1 用户模块
(1)注册登录
用户使用基于Springboot平台的楚雄旅游景区门票销售系统进行需登录。若游客未进行账户注册,可以先注册,在登录过程中需输入对应的密码。

图5-1 用户登录

图5-2 用户登录核心代码
(2)个人信息管理
用户在基于Springboot的楚雄旅游景区门票售卖系统中进行个人信息管理时,登录后进入相应模块。可自主更新联系方式,如手机号、电子邮箱等,修改时系统会进行格式验证确保准确。也能更改登录密码,设置符合安全要求的新密码。还可完善个人基本信息,如昵称等。系统会对用户所做更改进行实时保存,并提供操作记录查询,方便用户知晓信息变更情况,全方位保障用户个人信息的安全性、准确性与个性化。
图5-3 用户前台用户信息界面

图5-4 用户模块核心代码

(3)景区浏览
用户在基于Springboot的楚雄旅游景区门票售卖系统中进行个人信息管理时,登录后进入相应模块。用户可以选择自己喜欢的景区进行浏览,可以看到对应景区介绍、图片、地址等信息。

图5-5 前台景区信息界面
图5-6 前台景区信息界面核心代码

(4)门票管理
用户可查看加入进行门票预定、购物车、支付,订单可评价以及退票。管理员能查看所有订单,处理退款退货,统计订单数据,分析销售趋势,以便调整运营策略,确保订单流程顺畅与业务数据清晰掌控。

图5-7 前台门票管理界面
图5-8 前台门票管理界面核心代码

(5)订单管理
用户的订单管理模块为用户提供了全方位的订单相关的服务。用户可以通过订单管理查看自己提交的订单信息,如订单的编号、预订的景区门票信息、订单本身的状态、订单的金额、支付订单。同时,用户可对没有进行支付的订单进行取消操作,也可查看已支付订单的状态,确保其能顺利完成整个旅游行程安排,还能查看和获取电子票,便于快速入园。
图5-9 前台订单管理界面


图5-10 前台订单界面关键代码
(6)评价与反馈
用户在游玩完某个景区之后,能够很轻松地进入一个评价与反馈的模块,这个模块其实就是一个地方,用户可以在这里对景区的各个方面进行一些评价,比如说景点的特色、服务的质量、环境的卫生等等,都是可以详细地进行评价的。用户还可以为景区打一个分数,同时留下文字的留言,分享一下自己的真实体验,或者说提出一些建议,甚至是反馈自己在游玩过程中遇到的问题。这个系统会将用户的评价和留言都进行收集和整理,管理员则可以在后台查看这些内容,进行审核。对于那些客观的、有价值的评价,管理员会选择保留,并展示在景区的详情页面上,供其他的游客进行参考;而对于一些不当的言论,管理员则会进行一定的处理。
图5-11 前台留言界面图5-12 评论前台核心代码


(7)消息通知
当用户在系统中进行操作时,如订单确认、支付成功等,系统向用户发送消息通知。用户能第一时间获取反馈信息。例如,当用户成功预订门票后,系统会立即发送订单确认消息,让用户安心。

图5-13 消息通知界面

图5-14 消息通知核心代码
(8)支付管理
在用户完成了门票的预订之后,就会进入到支付的环节。在这个环节中,用户只需简单地选择一个合适的支付方式,系统便会引导用户完成整个支付的流程。同时,系统会实时地查询支付的状态,如果支付成功的话,订单的状态会立即更新,并且向用户发送一个支付成功的消息通知;若是支付失败,那么也会明确告知用户失败的原因,并且提供一些解决的方案。此外,支付管理的功能还支持退款操作,当用户需要退票的时候,管理员审核通过之后,系统会按照原来的支付路径快速地将票款退还,确保用户的资金安全以及权益。。

图5-15 支付管理界面

图5-16 支付管理界面核心代码
5.2.2 管理员模块
(1)用户管理
管理员可通过后台用户管理模块查看用户的注册详细信息、在用户需要的情况下帮助用户修改信息、找回密码、注销账号,以及对用户信息进行审核,保证用户门票的安全性。

图5-17 用户后台管理界面

图5-18 用户后台管理界面核心代码
(2)景区管理
管理员在此模块录入景区名称、地址、简介、开放时间、门票价格等详细信息,并上传图片和视频资料展示景区特色。还可根据景区运营情况修改信息、调整门票价格及设置库存数量,保障景区信息及时更新与准确呈现,吸引游客预订。用户可以在前台查看景区名称、地址、简介、开放时间、门票价格等信息,可以对景区进行收藏和评论。
图5-19 景区信息管理界面


图5-20后台景区信息管理界面核心代码
(3)订单管理
管理员在楚雄旅游景区门票售卖系统中进行订单管理时,如果有退款的请求,管理员就可以根据一些规定来审核和处理这些请求,以确保交易的公正性,管理员还可以对订单的数据进行一些统计分析,能够掌握销售的趋势,这样一来,就可以为景区的营销和资源的调配提供一些数据上的支持。
图5-21 后台订单信息

图5-22 后台订单信息核心代码

(4)评论审核
管理员在楚雄旅游景区门票售卖系统的评价管理模块中,对用户提交的评价进行管理。管理员可以审核用户评论的内容,可以对有些不文明的评论进行处理和回复评论。
图5-23 后台留言管理界面


图5-24 评论后台核心代码
(5)数据分析
数据分析模块可以帮助管理员能帮助管理分析数据,让管理员知到那些景区的门票好卖并帮助管理员及时修改营销策略对于门票卖不出去的景区了进行打折处理以及减少景区管理人员,对于则门票销售好的地区增派人手,避免出现景区管理人员过少和过多的情况。
图5-25 商品统计(按票种统计)


图5-26 商品统计(按票种统计)核心代码
图5-27 商品统计(按状态统计)


图5-28 商品统计(按状态统计)核心代码
(6)库存管理
管理员所以随时看到各景区门票库存数量,通过景区门票的库存进行合理分析,以便及时进行库存补充与调整。确保每位游客都能买到喜欢景区的门票,同时也避免出现部分景区门票过多的问题。

图5-29 库存管理界面图5-30 库存管理核心代码

(7)新闻咨询管理
管理员可以新闻资讯管理对新闻信息进行编辑,对库存多且不好出售的门票并实时发布优惠信息让用户第一时间找到优惠信息,以及对景区设施维修等信息进行公布方便游客规划行程。
图5-31 后台新闻数据管理界面


图5-32 后台新闻数据管理界面核心代码
第6章 系统测试
6.1 测试目的
当开始进行系统的测试时,这意味着系统的编码已经达到了一个相对流畅的状态。我们需要对某些模块和功能进行深入的测试,这一步骤被称为系统测试。在程序的编写阶段,系统测试就是一个至关重要的环节。在软件开发的全过程中,进行系统测试是命脉所在的一环。程序开发的每一个阶段存在不同的需求,而每个需求各有特点。当程序开发者遇到复杂的逻辑时,他们的思维并不像预期中那么明确。在开发中,他们经常需要处理大量的代码,并不断地调整数据类型。如果程序开发过程中遇到了错误或者缺陷的话,那么就需要通过系统测试用例进行修改和完善,这样才能保证程序的正确性和可靠性。在进行系统测试的过程中,我们必须确保所有应当完成的任务都得到妥善处理,以确保程序开发从启动到完成都遵循。
6.2 测试用例设计
一个设计完整的软件在进行测试时,通常主要包括以下几个方面:
6.2.2测试步骤
(1)模块测试:此阶段主要针对软件的各个独立模块进行细致的检查与验证。其目的是检验编程过程中可能存在的错误或不足之处,确保每个模块的功能按规定工作。通过此过程可以及时发现并修正问题。
(2)系统测试:在完成模块独立的测试后,将这些模块整合起来进行全面的系统测试。这一步骤不仅检验了整个系统的功能是否按照设计要求正确实现,还会评估系统整体性能、稳定性等非功能性指标。此外,系统测试还有助于识别需求说明书中可能存在的缺陷或遗漏。
(3)验收测试:在此阶段,重点在于验证系统是否完全符合客户的业务需求,并确保所有预期功能均能正常使用。这一步对于保证客户满意度至关重要。
6.2.3测试内容
(1)测试首先要考虑其配置环境是否能够完成测试内容。软硬件配套设施是符合。
(2)系统数据库的能否正常连接,内容是否完整等。
(3)各个功能模块页面的是否能够正常运行,各功能是否能够实现并正常应用,数据调用是否正常。
6.3 测设过程
当用户试图登录时,他们需要键入自己的用户名、电话号码和密码。这些信息对于用户来说非常重要。当用户输入的信息满足或未满足系统的标准要求时,我们有必要将实际输出与预先设定的预测进行对比,以确定两者是否一致。用户登录用例测试如表6-1所示。
表6-1 用户注册登录测试用例表
| 所属模块 | 注册登录 |
|---|---|
| 测试点 | 登录 |
| 详细过程 | 1.进入系统主页; 2.输入用户名:user2和密码:123456,点击登录 |
| 预期结果 | 使用该数据可成功登录。 |
| 实际结果 | 使用该数据可成功登录。 |
该模块主要是测试管理员对旅游新增景区信息的添加测试,包括新增景区名称、地址、介绍、价格等信息。景区发布测试如表6-2所示。
表6-2 景区管理测试用例表
| 所属模块 | 景区管理 |
|---|---|
| 测试点 | 发布景区信息 |
| 详细过程 | 1.以管理员身份登录,进入系统后台; 2.点击景区信息,进入该模块; 3.点击"新增",输入景区信息; 4.点击"保存" |
| 预期结果 | 该条景区发布成功。 |
| 实际结果 | 该条景区发布成功。 |
订单管理的测试,主要是为了验证系统中与订单管理相关的功能,这些功能是否完整,是否准确。首先,测试人员要以用户的身份进入系统,也就是说,得先登录,然后再去景区门票的预订页面。在这个过程中,测试人员会挑选一些合适的景区,选择门票的类型,再决定一下日期和时段,最后点击预订按钮,接着进行支付,完成这一系列的操作。完成订单创建之后,接下来就要进入订单管理页面,查看一下订单的信息。订单管理测试如表6-3所示。
表6-3 订单管理测试用例表
| 所属模块 | 订单管理 |
|---|---|
| 测试点 | 订单创建与查看 |
| 详细过程 | 1. 以用户身份登录系统; 2. 进入景区门票预订页面,选择景区、门票类型、日期和时段,点击 "预订"; 3. 完成支付操作; 4. 进入订单管理页面查看生成的订单信息。 |
| 预期结果 | 当订单成功创建后,你可以在订单管理界面查看到订单相关的详细资料,这其中也包括了订单的编号、预订景区、门票信息、支付状态等。 |
| 实际结果 | 订单创建成功,在订单管理页面可查看相应订单信息。 |
新闻资讯管理测试,主要是为了检验那些管理员在系统后台进行新闻资讯相关操作的功能,这些功能是否完整,是否准确。首先,测试人员将以管理员的身份,也就说登录到系统中,然后再去新闻资讯管理模块。在这个模块里面,测试人员会进行新闻资讯的添加操作,也就是输入一些必要的信息,然后就进行保存。测试人员对已经添加的新闻资讯进行修改信息,然后保存。预期的结果是,这些新的新闻资讯能够成功添加,也就是说在列表里面能够看到它们,而对其所做的修改的信息也应该能够成功更新,这样才算是达到了预期的效果。
表6-4 新闻资讯管理测试用例表
| 所属模块 | 新闻资讯管理 |
|---|---|
| 测试点 | 新闻资讯的添加与修改 |
| 详细过程 | 1.用管理员身份登录系统,进入管理员系统后台; 2.进入新闻资讯管理模块; 3.点击"添加"按钮,输入想要添加的新闻相关信息比如新闻标题、内容、发布日期等信息; 4.进入已添加的新闻资讯列表,找到需要修改的新闻资讯,修改部分信息。 |
| 预期结果 | 新的新闻资讯成功添加,并且能在列表中看到;修改后的新闻资讯信息更新成功。 |
| 实际结果 | 新闻资讯添加成功并显示在列表中,修改操作后信息更新正确。 |
6.4 测试结论
本系统是基于Springboot框架设计并实现的,主要是为了楚雄旅游景区的门票售卖,构建了一个用户可以方便购票,同时景区管理也能高效进行的综合性平台。经过深入的研究和开发,系统在利用Springboot框架的优势方面做了不少努力,同时也整合了MySQL数据库、Vue等技术,达成了一些预期的功能目标。在用户端,用户可以进行从注册到登录,再到浏览景区,接着是门票的预订,之后是订单的管理,还有评价的反馈,最后是消息的接收,这一系列的操作都显得非常流畅,这样就极大地提升了用户的购票体验和旅游规划的便利性。而在管理员端,管理员可以在用户管理、景区信息的维护、订单的处理、评论的审核、数据的分析、库存的监控,还有新闻资讯的发布等多个方面发挥重要的作用。这样就有效增强了景区运营的科学性与精准性。系统经过了一些测试,其功能是比较完备的,性能也是比较稳定的,兼容性也算良好,安全性也得到了保证,能够满足楚雄旅游景区在这个数字化时代所需要的门票售卖与管理的需求。这个系统的成功上线,不仅推动了楚雄旅游业的信息化进程,促进了景区资源的合理配置与利用,同时也为游客提供了更优质的旅游服务,不仅提升了景区的知名度与竞争力,具有一定的应用价值和推广前景。
结论
本系统是基于Springboot框架设计并实现的,用于楚雄地区的旅游景区门票的售卖,是一个集用户购票和景区管理于一体的综合性平台。对各种技术的研究和开发,该系统发挥了Springboot的各项优势,还融合MySQL数据库和Vue等先进技术,实现了预定的功能目标。用户端的功能比较全面,注册登录开始、浏览景区、预订门票、管理订单、进行评价反馈以及接收消息等一系列功能,用户体验得到很大提升,购票和旅游规划的便利性也有显著改善。而管理员端则主要是在用户管理、景区信息维护、订单处理、评论审核、数据分析、库存监控、发布新闻资讯等方面发挥了重要作用,增强了景区运营科学性,当然也提高了精准性。经过系统测试,可以说功能是比较完备的,性能也相对稳定,兼容性良好,安全性也是可靠的,总体上满足了楚雄旅游景区在这个数字化时代对于门票售卖与管理的需求。这套系统的成功上线,不仅推动了楚雄旅游行业的信息化进程,还促进了景区资源的合理配置与利用,当然也为游客提供了更为优质的旅游服务。在提升景区知名度与竞争力的同时,系统的建设经验也为其他旅游景区的票务系统提供了某种参考与借鉴,具有一定的应用价值和推广前景。
参考文献
1杨晟.基于Spring Boot的景点售票管理系统的设计与实现J.信息记录材料,2024,25(06):128-130.DOI:10.16009/j.cnki.cn13-1295/tq.2024.06.043.
2齐云龙,唐玮强,姚连达.景点门票售票系统设计研究J.电子世界,2021,(01):63-64.DOI:10.19353/j.cnki.dzsj.2021.01.030.
3熊永平.基于SpringBoot框架应用开发技术的分析与研究J.电脑知识与技术,2019,15(36):76-77.DOI:10.14004/j.cnki.ckt.2019.4290.
4曹浩,黎杰,谢彬.基于SpringBoot+Vue的桂林龙胜各族自治县的旅游信息系统设计J.现代信息科技,2024,8(16):102-106.
5张驰.旅游景区电子售票系统的设计与实施D.电子科技大学,2014.
6张婷,陆洪丽,曹玉洁.面向时变大客流的景区售票系统资源调度研究J.工业工程与管理,2021,26(05):29-37.DOI:10.19495/j.cnki.1007-5429.2021.05.004.
7白立军.旅游景区电子门票管理系统设计与应用D.燕山大学,2013.
8陈庆勇.云南数字旅游产品开发与发展对策D.云南大学,2011.
9谭蜜.面向智慧旅游小镇的移动终端系统的设计与实现D.北京邮电大学,2020.DOI:10.26969/d.cnki.gbydu.2020.002335.
10孟思明.基于SpringBoot框架选购系统的设计与实现J.中国设备工程,2023,(11):94-95.
11李晟曈,刘哲,俞定国,等.基于Vue和SpringBoot的乡村文旅平台设计与实现J.现代计算机,2023,29(08):98-103.
12田海晴.基于SpringBoot和Vue框架的共享运营管理平台的设计与实现D.山东大学,2020.DOI:10.27272/d.cnki.gshdu.2020.004528.
13Mengdie G,Rui S,Shulin Y,et al.Research on copyright appointment registration microplatform system based on vueJ.MATEC Web of Conferences,2022,355
致谢
我要感谢我的指导老师耐心指导论文的写作,感谢我的朋友们,在我为了系统的功能优化而日夜奋战、疲惫不堪时,你们用温暖的陪伴和鼓励给予我力量。是你们在我遇到技术瓶颈,几近崩溃之时,让我重拾信心继续拼搏。
我也不会忘记我的家人,始终默默支持着我的学业与研究。当我为了数据库设计而绞尽脑汁时,是你们在生活上的悉心照料,使我无后顾之忧,得以全身心投入到系统开发与论文撰写中。还要感谢那些为我提供技术资料和开发工具的开源社区与学校资源。正是因为有了丰富的技术资源和便捷的开发环境,我才能够顺利地将楚雄旅游景区门票售卖系统从设想变为现实。在这篇论文的句号即将落下之际,我深知这不仅是我个人努力的成果,更是众多力量共同汇聚、相互作用的结晶。我将带着这份感恩,继续在未来的道路上砥砺前行,为科技与社会的发展贡献自己的力量。
附录
//(1)用户登录
<template>
<div id="myLogin">
<el-dialog title="登录" width="300px" center:visible.sync="isLogin">
<el-form:model="LoginUser":rules="rules" status-icon ref="ruleForm" class="demo-ruleForm">
<el-form-item prop="name">
<el-input prefix-icon="el-icon-user-solid" placeholder="请输入账号" v-model="LoginUser.name"></el-input>
</el-form-item>
<el-form-item prop="pass">
<el-input
prefix-icon="el-icon-view"
type="password"
placeholder="请输入密码"
v-model="LoginUser.pass"
></el-input>
</el-form-item>
<el-form-item prop="role">
<el-radio v-model='LoginUser.role' label='用户'>用户</el-radio>
</el-form-item>
<el-form-item style="margin-left: 0px" prop="code">
<div class="el-row" span="24">
<div class="el-col el-col-16">
<el-input
type="text"
maxlength="4"
placeholder="请输入验证码"
prefix-icon="el-icon-position"
v-model="LoginUser.code"
clearable
autocomplete="off"
></el-input>
</div>
<div class="el-col el-col-8">
<div class="login-code">
<span class="login-code-img" @click="changeCode">{{code}}</span>
</div>
</div>
</div>
</el-form-item>
<el-form-item>
<el-button size="medium" type="primary" @click="Login" style="width:100%;">登录</el-button>
</el-form-item>
</el-form>
</el-dialog>
</div>
</template>
<script>
import { mapActions } from "vuex";
export default {
name: "MyLogin",
data() {
return {
rules: {
name: [
{required: true, message: '请输入用户名', trigger: 'blur'}
],
pass: [
{required: true, message: '请输入密码', trigger: 'blur'}
],
code: { required: true,trigger: 'blur',validator: this.codeValidator },
},
LoginUser: {
name: "",
pass: "",
role:"用户"
},
code:'',
};
},
computed: {
isLogin: {
get() {
return this.$store.getters.getShowLogin;
},
set(val) {
this.$refs"ruleForm".resetFields();
this.setShowLogin(val);
}
}
},
created() {
this.initCode();
},
methods: {
codeValidator(rule,value,callback){
let res
if(!value) {
res = rule.required? new Error('请输入验证码信息'): undefined
} else {
const val = value.trim();
if(val!= this.code){
res = new Error("验证码信息不正确")
}
}
callback(res)
},
initCode(){
let code = Math.floor(Math.random()*(9999-1000))+1000;
this.code = code;
},
changeCode(){
this.initCode();
},
...mapActions("setUser", "setShowLogin"),
Login() {
let username=this.LoginUser.name;
let cx=this.LoginUser.role;
// 通过element自定义表单校验规则,校验用户输入的用户信息
this.$refs"ruleForm".validate(valid => {
//如果通过校验开始登录
if (valid) {
if (this.LoginUser.role === '用户') {
this.$axios.post("/api/front/loginyonghu", {
yonghuming: this.LoginUser.name,
mima: this.LoginUser.pass
})
.then(res => {
if (res.data.code === "0") {
this.isLogin = false;
let user = JSON.stringify(res.data.data);
localStorage.setItem("user", user);
this.setUser(res.data.data.user);
localStorage.setItem("username",username);
localStorage.setItem("cx", cx);
this.notifySucceed(res.data.msg);
this.$router.go(0)
} else {
this.$refs"ruleForm".resetFields();
this.notifyError(res.data.msg);
}
})
.catch(err => {
return Promise.reject(err);
});
}
} else {
return false;
}
});
}
}
};
</script>
//(2)前台用户首界面
<template>
<div class="home" id="home" name="home">
<div class="main-box">
<div class="banner-bottom" style="width:100%">
<div class="">
<h4 class="latest-text w3_latest_text">会员风彩</h4>
</div>
<section class="home_news">
<div class="container">
<div class="home_top">
<a href="news.html" class="more"></a>
</div>
<ul class="clearfix">
<li v-for="(item,index) in wbjxwtz1":key="item.id">
<router-link:to="`/xinwentongzhidetail/`+item.id" >
{{item.biaoti}}
</router-link>
</li>
</ul>
</div>
</section>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
import {mapActions} from "vuex";
export default {
data() {
return {
objssp: \[\],
objstx: \[\],
wbjxwtz1: \[\],
};
},
watch: {
'$route'(to, from) {
this.$router.go(0)
},
},
created() {
let user = localStorage.getItem("user");
if(user) {
this.userInfo = JSON.parse(localStorage.getItem("user"));
}
//loadsp1
//loadtx2
this.loadTablexw1(6, "站内新闻");
},
methods: {
...mapActions("setUser", "setShowLogin", "setShoppingCart"),
goUrl() {
window.location.href = 'http://localhost:9999'
},
//loadsphs
//loadtxhs
loadTablexw1(ns, lb) {
this.$axios
.get("/api/front/xinwentongzhi", {})
.then(res => {
let data = res.data.data;
let filteredData = \[\];
let tt = 0
data.forEach(item => {
if (item.leibie === lb) {
tt++;
if (tt <= ns) {
filteredData.push(item);
}
}
});
this.wbjxwtz1 = filteredData;
})
.catch(err => {
return Promise.reject(err);
});
},
}
};
//(3) 前台商品菜单
<template>
<div class="order">
<!-- 我的订单头部 -->
<div class="order-header">
<div class="order-header-content">
<p>
<i class="el-icon-s-order" style="font-size: 30px;color: #ff6700;"></i>
我的订单
</p>
</div>
</div>
<!-- 我的订单头部END -->
<!-- 我的订单主要内容 -->
<div class="order-content" v-if="orders.length>0">
<div class="content" v-for="(item,index) in orders":key="index">
<ul>
<!-- 我的订单表头 -->
<li class="order-info">
<div class="order-id">订单编号: {{ item.orderId }}</div>
<div class="order-time">订单时间: {{ item.createTime | dateFormat }}</div>
</li>
<li class="header">
<div class="pro-img"></div>
<div class="pro-name">商品名称</div>
<div class="pro-price">单价</div>
<div class="pro-num">数量</div>
<div class="pro-total">小计</div>
</li>
<!-- 我的订单表头END -->
<!-- 订单列表 -->
<li class="product-list" v-for="(shangpin,i) in item.shangpinList":key="i">
<div class="pro-img">
<router-link:to="{ path: '/gouwuche/details', query: {shangpinID:shangpin.id} }">
<img:src="`/api/`+shangpin.tupian"/>
</router-link>
</div>
<div class="pro-name">
<router-link
:to="{ path: '/goods/details', query: {shangpinID:shangpin.shangpinID} }"
>{{ shangpin.shangpinmingcheng }}
</router-link>
</div>
<div class="pro-price">{{ shangpin.jiage }}元</div>
<div class="pro-num">{{ shangpin.kucun }}</div>
<div class="pro-total pro-total-in">{{ shangpin.jiage * shangpin.kucun }}元</div>
</li>
</ul>
<div class="order-bar">
<div class="order-bar-left">
<span class="order-total">
共
<!-- <span class="order-total-num">{{item.totalNum}}</span> 件商品-->
<span
class="order-total-num">{{ item.shangpinList.reduce((sum, e) => sum + Number(e.kucun || 0), 0) }}</span> 件商品
</span>
<!-- <span class="order-total">订单状态:{{item.status}}</span>-->
</div>
<div class="order-bar-right">
<span>
<span class="total-price-title">合计:</span>
<span class="total-price">{{ item.totalPrice }}元</span>
</span>
<span style="margin-left: 20px">
<el-button
v-if="item.status === '待付款' ||item.status === '已取消' || item.status === '完成' || item.status === '已退款' || item.status === '已退货'"
type="danger" @click="del(item.id)">删除</el-button>
<el-button v-if="item.status === '待付款'" type="danger"
@click="changeStatus(item.id, '已取消')">取消</el-button>
<el-button v-if="item.status === '待付款'" type="primary"
@click="changeStatus(item.id, '待发货')">付款</el-button>
<el-button v-if="item.status === '待收货'" type="primary"
@click="changeStatus(item.id, '完成')">确认收货</el-button>
<el-button v-if="item.status === '待发货'" type="primary"
@click="changeStatus(item.id, '申请退款中')">退款</el-button>
<el-button v-if="item.status === '完成'" type="primary"
@click="changeStatus(item.id, '申请退货中')">退货</el-button>
</span>
</div>
<!-- 订单列表END -->
</div>
</div>
<div style="margin-top:-40px;"></div>
</div>
<!-- 我的订单主要内容END -->
<!-- 订单为空的时候显示的内容 -->
<div v-else class="order-empty">
<div class="empty">
<h2>您的订单还是空的!</h2>
<p>快去购物吧!</p>
</div>
</div>
<!-- 订单为空的时候显示的内容END -->
</div>
</template>
<script>
export default {
data() {
return {
orders: \[\], // 订单列表
total: \[\],// 每个订单的商品数量及总价列表
};
},
activated() {
// 获取订单数据
this.$axios
.get("/api/front/getUserOrder/" + this.$store.getters.getUser.id, {})
.then(res => {
debugger
if (res.data.code === "0") {
debugger
this.orders = res.data.data;
this.orders.forEach(item => {
item.totalNum = 0;
item.shangpinList.forEach(item2 => {
item.totalNum += item2.productNum
})
})
} else {
this.notifyError(res.data.msg);
}
})
.catch(err => {
return Promise.reject(err);
});
},
watch: {
// 通过订单信息,计算出每个订单的商品数量及总价
orders: function (val) {
let total = \[\];
for (let i = 0; i < val.length; i++) {
const element = vali;
let totalNum = 0;
let totalPrice = 0;
for (let j = 0; j < element.length; j++) {
const temp = elementj;
totalNum += temp.product_num;
totalPrice += temp.product_price * temp.product_num;
}
total.push({totalNum, totalPrice});
}
this.total = total;
}
},
methods: {
del(id) {
this.$axios
.delete('/api/front/deleteOrder/' + id, {})
.then(res => {
if (res.data.code === "0") {
location.reload();
} else {
this.notifyError(res.data.msg);
}
})
.catch(err => {
return Promise.reject(err);
});
},
changeStatus(id, status) {
this.$axios
.get('/api/front/orderStatus/' + id + '/' + status, {})
.then(res => {
if (res.data.code === "0") {
location.reload();
} else {
this.notifyError(res.data.msg);
}
})
.catch(err => {
return Promise.reject(err);
});
}
}
};
//(4) 前台购物车
<template>
<div class="shoppingCart">
<!-- 购物车头部 -->
<div class="cart-header">
<div class="cart-header-content">
<p>
<i class="el-icon-shopping-cart-full" style="color:#ff6700; font-weight: 600;"></i>
我的购物车
</p>
<span>温馨提示:产品是否购买成功,以最终下单为准哦,请尽快结算</span>
</div>
</div>
<!-- 购物车头部END -->
<!-- 购物车主要内容区 -->
<div class="content" v-if="getShoppingCart.length>0">
<ul>
<!-- 购物车表头 -->
<li class="header">
<div class="pro-check">
<el-checkbox v-model="isAllCheck">全选</el-checkbox>
</div>
<div class="pro-img"></div>
<div class="pro-name">商品名称</div>
<div class="pro-price">单价</div>
<div class="pro-num">数量</div>
<div class="pro-total">小计</div>
<div class="pro-action">操作</div>
</li>
<!-- 购物车表头END -->
<!-- 购物车列表 -->
<li class="product-list" v-for="(item,index) in getShoppingCart":key="item.id">
<div class="pro-check">
<el-checkbox:value="item.check" @change="checkChange($event,index)"></el-checkbox>
</div>
<div class="pro-img">
<router-link:to="{ path: '/goods/details', query: {shangpinID:item.shangpinId} }">
<img:src="`/api/`+item.shangpin.tupian" />
</router-link>
</div>
<div class="pro-name">
<router-link
:to="{ path: '/goods/details', query: {shangpinID:item.shangpinId} }"
>{{item.shangpin.shangpinmingcheng}}</router-link>
</div>
<div class="pro-price">{{item.shangpin.jiage}}元</div>
<div class="pro-num">
<el-input-number
size="small"
:value="item.num"
@change="handleChange($event,index,item)"
:min="1"
:max="item.shangpin.kucun"
></el-input-number>
</div>
<div class="pro-total pro-total-in">{{item.shangpin.jiage*item.num}}元</div>
<div class="pro-action">
<el-popover placement="right">
<p>确定删除吗?</p>
<div style="text-align: right; margin: 10px 0 0">
<el-button
type="primary"
size="mini"
@click="deleteItem($event,item.id)"
>确定</el-button>
</div>
<i class="el-icon-error" slot="reference" style="font-size: 18px;"></i>
</el-popover>
</div>
</li>
<!-- 购物车列表END -->
</ul>
<div style="height:20px;background-color: #f5f5f5"></div>
<!-- 购物车底部导航条 -->
<div class="cart-bar">
<div class="cart-bar-left">
<span>
<router-link to="/goods">继续购物</router-link>
</span>
<span class="sep">|</span>
<span class="cart-total">
共
<span class="cart-total-num">{{getNum}}</span> 件商品,已选择
<span class="cart-total-num">{{getCheckNum}}</span> 件
</span>
</div>
<div class="cart-bar-right">
<span>
<span class="total-price-title">合计:</span>
<span class="total-price">{{getTotalPrice}}元</span>
</span>
<router-link:to="getCheckNum > 0? '/confirmOrder': ''">
<div:class="getCheckNum > 0? 'btn-primary': 'btn-primary-disabled'">去结算</div>
</router-link>
</div>
</div>
<!-- 购物车底部导航条END -->
</div>
<!-- 购物车主要内容区END -->
<!-- 购物车为空的时候显示的内容 -->
<div v-else class="cart-empty">
<div class="empty">
<h2>您的购物车还是空的!</h2>
<p>快去购物吧!</p>
</div>
</div>
<!-- 购物车为空的时候显示的内容END -->
</div>
</template>
<script>
import { mapActions } from "vuex";
import { mapGetters } from "vuex";
export default {
data() {
return {};
},
created() {
this.$axios
.post("/api/front/getUserCart", {
userId: this.$store.getters.getUser.id
})
.then(res => {
debugger
if (res.data.code === "0") {
// 001 为成功, 更新vuex购物车状态
res.data.data.forEach(item=>{
item.check = false
})
this.setShoppingCart(res.data.data);
} else {
// 提示失败信息
this.notifyError(res.data.msg);
}
})
.catch(err => {
return Promise.reject(err);
});
},
methods: {
...mapActions("updateShoppingCart", "deleteShoppingCart", "checkAll","setShoppingCart"),
// 修改商品数量的时候调用该函数
handleChange(currentValue, key, value) {
// 当修改数量时,默认勾选
this.updateShoppingCart({ key: key, prop: "check", val: true });
// 向后端发起更新购物车的数据库信息请求
this.$axios
.post("/api/front/updateCart", {
id:value.id,
userId: this.$store.getters.getUser.id,
shangpinId: value.shangpinId,
num: currentValue
})
.then(res => {
switch (res.data.code) {
case "0":
// "001"代表更新成功
// 更新vuex状态
this.updateShoppingCart({
key: key,
prop: "num",
val: currentValue
});
// 提示更新成功信息
this.notifySucceed(res.data.msg);
break;
default:
// 提示更新失败信息
this.notifyError(res.data.msg);
}
})
.catch(err => {
return Promise.reject(err);
});
},
checkChange(val, key) {
// 更新vuex中购物车商品是否勾选的状态
this.updateShoppingCart({ key: key, prop: "check", val: val });
},
// 向后端发起删除购物车的数据库信息请求
deleteItem(e, id) {
this.$axios
.delete("/api/front/deleteCart/"+id, {
})
.then(res => {
switch (res.data.code) {
case "0":
// "001" 删除成功
// 更新vuex状态
this.deleteShoppingCart(id);
// 提示删除成功信息
this.notifySucceed(res.data.msg);
break;
default:
// 提示删除失败信息
this.notifyError(res.data.msg);
}
})
.catch(err => {
return Promise.reject(err);
});
}
},
computed: {
...mapGetters([
"getShoppingCart",
"getCheckNum",
"getTotalPrice",
"getNum"
]),
isAllCheck: {
get() {
return this.$store.getters.getIsAllCheck;
},
set(val) {
this.checkAll(val);
}
}
}
};
//(5) 前台景区信息界面
<div class="order">
<div class="order-header">
<div class="order-header-content">
<p>
<i class="el-icon-s-order" style="font-size: 30px;color: #ff6700;"></i>
景区信息
</p>
</div>
</div>
<div class="order-content">
<div class="content">
<el-form:inline="true":model="formInline" class="user-search">
<el-form-item>
<el-button size="small" type="primary" icon="el-icon-search" @click="search">搜索</el-button>
</el-form-item>
</el-form>
<ul>
<li class="header">
<div class='pro-img'> 景区编号</div>
<div class='pro-img'> 景区名称</div>
<div class='pro-img'> 图片</div>
<div class='pro-img'> 票价</div>
<div class='pro-img'> 地址</div>
</li>
<li class="product-list" v-for="item in jingquxinxi":key="item.id">
<router-link:to="`/jingquxinxidetail/`+item.id" >
<div class='pro-img'>{{item.jingqubianhao}}</div>
<div class='pro-img'>{{item.jingqumingcheng}}</div>
<div class='pro-img'>{{item.xiangqingjieshao}}</div>
<div class='pro-img'>{{item.tupian}}</div>
<div class='pro-img'>{{item.piaojia}}</div>
</router-link>
</li>
</ul>
<div class="order-bar">
</div>
</div>
<div style="margin-top:-40px;"></div>
</div>
</div>
//(6)前台景区详细信息界面
<div id="details">
<!-- 头部 -->
<div class="page-header">
<div class="title" style="font-size: 14px;">
<p>首页>> 景区信息列表 >> 景区信息详细 </p>
</div>
</div>
<div class="main">
<el-card shadow="hover" style="width: 560px; float:left">
<div class="block">
<div>
<img style="height:500px;width: 500px":src="`/api/`+jingquxinxidetail.tupian" />
</div>
</div>
</el-card>
<div class="content">
<table width="100%" border="0" align="center" cellpadding="3" cellspacing="1" class="newsline">
<tr><td width='22%' height=44>景区编号:</td><td width='39%' >{{jingquxinxidetail.jingqubianhao}}</td></tr>
<tr><td width='22%' height=44>景区名称:</td><td width='39%' >{{jingquxinxidetail.jingqumingcheng}}</td></tr>
<tr><td width='22%' height=44>票价:</td><td width='39%' >{{jingquxinxidetail.piaojia}}</td></tr>
<tr><td width='22%' height=44>地址:</td><td width='39%' >{{jingquxinxidetail.dizhi}}</td></tr>
<tr><td width='22%' height=44>开放日期:</td><td width='39%' >{{jingquxinxidetail.kaifangriqi}}</td></tr>
<tr><td width='22%' height=100>详情介绍:</td><td width='39%' height=100 ><div v-html="jingquxinxidetail.xiangqingjieshao" ></div></td></tr>
<tr><td width='22%' height=100>备注:</td><td width='39%' height=100 ><div v-html="jingquxinxidetail.beizhu" ></div></td></tr>
</table>
<div class="button">
<el-button class='shop-cart' @click='addCollect'>喜欢</el-button>
<el-button class='like' @click='handleEdit()'>我有话说</el-button>
</div>
</div>
<el-table size="small":data="pinglun" highlight-current-row v-loading="loading" border element-loading-text="拼命加载中" @selection-change="handleSelectionChange">
<el-table-column sortable prop="pingfen" label="评分"></el-table-column>
<el-table-column sortable prop="pinglunneirong" label="评论内容"></el-table-column>
<el-table-column sortable prop="pinglunren" label="评论人"></el-table-column>
<el-table-column sortable prop="huifu" label="回复"></el-table-column>
<el-table-column sortable prop="addtime" label="添加时间" width="160">
<template slot-scope="scope">
<div>{{scope.row.addtime|datePipe('yyyy-MM-dd hh:mm:ss')}}</div>
</template>
</el-table-column>
</el-table>
<el-dialog:title="title":visible.sync="editFormVisible" width="30%" @click="closeDialog">
<el-form label-width="120px":model="editForm":rules="rules" ref="editForm">
<el-form-item label="评论内容" prop="pinglunneirong"><el-input type="textarea" size="small" v-model="editForm.pinglunneirong" auto-complete="off" placeholder="请输入评论内容" style='width:100%'></el-input></el-form-item>
<el-form-item label="评分" prop="pingfen">
<el-radio v-model='editForm.pingfen' label='1'>1</el-radio>
<el-radio v-model='editForm.pingfen' label='2'>2</el-radio>
<el-radio v-model='editForm.pingfen' label='3'>3</el-radio>
<el-radio v-model='editForm.pingfen' label='4'>4</el-radio>
<el-radio v-model='editForm.pingfen' label='5'>5</el-radio>
</el-form-item>
<el-form-item label="表" prop="biao" style="display: none"><el-input size="small" v-model="editForm.biao" auto-complete="off" placeholder="请输入表" style='width:50%'></el-input></el-form-item>
<el-form-item label="表" prop="shujuid" style="display: none"><el-input size="small" v-model="editForm.shujuid" auto-complete="off" placeholder="请输入表" style='width:50%'></el-input></el-form-item>
<el-form-item label="评论人" prop="pinglunren"><el-input size="small" v-model="editForm.pinglunren" auto-complete="off" placeholder="请输入评论人" style='width:50%' disabled></el-input></el-form-item>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button size="small" @click="closeDialog">取消</el-button>
<el-button size="small" type="primary":loading="loading" class="title" @click="submitForm('editForm')">保存</el-button>
</div>
</el-dialog>
</div>
</div>
//(7)前台留言界面
<div id="container" style="width:80%;margin: 5px auto">
<el-row:gutter="20">
<el-col span="24">
<div class="comment">
<div class="comment-item">
<el-row v-for="item in comments":key="item.id" style="margin-top: 20px">
<table width="100%" border="0" align="center" cellpadding="0" cellspacing="1" class="newsline" >
<tr>
<td width="11" rowspan="3" valign="top" ></td>
<td width="85" rowspan="3" align="center" valign="middle">
<img width='70' height='70' src="../assets/img/1.gif" border=0 v-if="item.touxiang=='1'" />
<img width='70' height='70' src="../assets/img/2.gif" border=0 v-if="item.touxiang=='2'" />
<img width='70' height='70' src="../assets/img/3.gif" border=0 v-if="item.touxiang=='3'" />
<img width='70' height='70' src="../assets/img/4.gif" border=0 v-if="item.touxiang=='4'" />
<img width='70' height='70' src="../assets/img/5.gif" border=0 v-if="item.touxiang=='5'" />
</td>
<td height="20" colspan="2" align="left" valign="middle"> 留言于:{{item.addtime}} </td>
<td width="10" rowspan="3" valign="top" style="width: 10px"> </td>
</tr>
<tr>
<td width="491" height="78" align="left" valign="top"> {{item.biaoti}}</td>
<td width="573" align="left" valign="top"><p>管理员回复:{{item.huifu}} </p>
</td>
</tr>
<tr>
<td colspan="2" align="left" valign="middle" style="height: 25px"> 发布人:{{item.cheng}} </td>
</tr>
</table>
<table style="color: #888;padding-top: 30px; width:100%" v-for="child in item.children":key="child.id">
<tr>
<td width="130px" align="left" valign="top"> {{child.cheng}} 回复:</td>
<td width="" align="left" valign="top">{{child.biaoti}} </td>
<td width="280px" align="right" valign="top">回复时间:{{child.addtime | dateFormat}} </td>
</tr>
</table>
<table>
<tr>
<td width="573" align="left" valign="top">
我也来回个 <el-input type="text" style="width: 70%; display: inline-block" v-model="item.replayText"/>
<el-button type="primary" @click="reply(item.id, item.replayText)">回复</el-button>
</td>
</tr>
</table>
</el-row>
</div>
</div>
<div class="row">
<div class="col-md-8 col-md-offset-2">
<h2>留言</h2>
</div>
</div>
<div class="comment-item">
<el-row>
<el-input type="textarea" rows="3" v-model="comment.biaoti"></el-input>
</el-row>
<el-row>
<el-radio v-model='comment.touxiang' label='1'><img width='70' height='70' src="../assets/img/1.gif" border=0/></el-radio>
<el-radio v-model='comment.touxiang' label='2'><img width='70' height='70' src="../assets/img/2.gif" border=0/></el-radio>
<el-radio v-model='comment.touxiang' label='3'><img width='70' height='70' src="../assets/img/3.gif" border=0/></el-radio>
<el-radio v-model='comment.touxiang' label='4'><img width='70' height='70' src="../assets/img/4.gif" border=0/></el-radio>
<el-radio v-model='comment.touxiang' label='5'><img width='70' height='70' src="../assets/img/5.gif" border=0/></el-radio>
</el-row>
<el-row>
<el-button type="primary" @click="add()">发送</el-button>
</el-row>
</div>
</el-col>
</el-row>
</div>
//(8)用户前台用户信息界面
<div id="yonghulisttp" class="myList">
<ul>
<li v-for="item in list":key="item.id">
<el-popover placement="top">
<p>确定删除吗?</p>
<div style="text-align: right; margin: 10px 0 0">
<el-button type="primary" size="mini" @click="deleteCollect(item.id)">确定</el-button>
</div>
<i class="el-icon-close delete" slot="reference" v-show="isDelete"></i>
</el-popover>
<router-link:to="`/yonghudetail/`+item.id">
<img:src="`/api/`+item.zhaopian" alt />
<h2>{{item.xingming}}</h2>
</router-link>
</li>
<li v-show="isMore && list.length>=1" id="more">
<router-link:to="{ path: '/goods', query: {categoryId:categoryId} }">
浏览更多
<i class="el-icon-d-arrow-right"></i>
</router-link>
</li>
</ul>
</div>
</template>
<script>
export default {
name: "yonghulisttp",
props: "list", "isMore", "isDelete",
data() {
return {};
},
computed: {
categoryID: function() {
let categoryID = \[\];
if (this.list!= "") {
for (let i = 0; i < this.list.length; i++) {
const id = this.listi.categoryId;
if (!categoryID.includes(id)) {
categoryID.push(id);
}
}
}
return categoryID;
}
},
methods: {
deleteCollect(id) {
this.$axios
.delete("/api/front/deleteCollect/"+id, {
})
.then(res => {
switch (res.data.code) {
case "0":
// 删除成功
// 删除删除列表中的该商品信息
for (let i = 0; i < this.list.length; i++) {
const temp = this.listi;
if (temp.id == id) {
this.list.splice(i, 1);
}
}
// 提示删除成功信息
this.notifySucceed(res.data.msg);
break;
default:
// 提示删除失败信息
this.notifyError(res.data.msg);
}
})
.catch(err => {
return Promise.reject(err);
});
}
}
};
//(1)后台登录
<div class="login">
<div class="login-weaper">
<div class="layadmin-user-login-main" style="background: rgba(250,250,250,0.45);">
<div class="layadmin-user-login-box layadmin-user-login-header">
<h2>后台登录</h2>
<p>{{ getThemeConfig.globalTitle }}</p>
</div>
<el-form:model="ruleForm":rules="rules" ref="ruleForm"
class="layadmin-user-login-box layadmin-user-login-body layui-form">
<el-form-item class="layui-form-item" prop="username">
<el-input type="text"
:placeholder="$t('message.login.placeholder1')"
prefix-icon="el-icon-user"
v-model="ruleForm.username"
clearable
autocomplete="off" >
</el-input>
</el-form-item>
<el-form-item class="layui-form-item" prop="password">
<el-input type="password"
:placeholder="$t('message.login.placeholder2')"
prefix-icon="el-icon-lock"
v-model="ruleForm.password"
autocomplete="off"
:show-password="true" >
</el-input>
</el-form-item>
<el-form-item style="margin-left: 0px; " prop="role" >
<select name="cx" id="cx" style="width:100%; height:40px;border-radius: 5px; border: 0px;
border-color: #dcdfe6; padding-left: 5px;" v-model="ruleForm.role" >
<option value="管理员">管理员</option>
<option value="用户">用户</option>
</select>
</el-form-item>
<el-form-item class="layui-form-item" prop="code">
<div class="el-row" span="24">
<div class="el-col el-col-16">
<el-input type="text"
maxlength="4"
:placeholder="$t('message.login.placeholder3')"
prefix-icon="el-icon-position"
v-model="ruleForm.code"
clearable
autocomplete="off" ></el-input>
</div>
<div class="el-col el-col-8">
<div class="login-code">
<span class="login-code-img" @click="changeCode">{{code}}</span>
</div>
</div>
</div>
</el-form-item>
<el-form-item style="margin: 40px 0px 0">
<el-button type="primary" class="login-submit" @click="submitForm('ruleForm')":loading="submit.loading"><span>{{ $t('message.login.btnText') }}</span></el-button>
<!--yoxuzxhuxce-->
</el-form-item>
</el-form>
</div>
</div>
<div class="vue-particles">
<vue-particles color="#dedede" shapeType="star" linesColor="#dedede" hoverMode="grab" clickMode="push" style="height: 100%"></vue-particles>
</div>
</div>
//(2)后台管理员首界面
<el-card shadow="hover" > <table width="98%" border="0" align="center" cellpadding="0" cellspacing="0"> <tr> <td ><img src="./1.jpg" style="width: 80%; height: 60%;" > </td> </tr> </table></el-card>
//(3)后台订单信息
<div>
<!--列表-->
<el-table size="small":data="listData" highlight-current-row v-loading="loading" border
element-loading-text="拼命加载中" @selection-change="handleSelectionChange">
<el-table-column align="center" type="selection" width="60">
</el-table-column>
<el-table-column sortable prop="orderId" label="订单编号" width="200">
</el-table-column>
<el-table-column sortable prop="totalPrice" label="订单总价格" width="200">
</el-table-column>
<el-table-column sortable prop="createTime" label="创建时间" width="200">
</el-table-column>
<el-table-column sortable prop="status" label="订单状态" width="200">
</el-table-column>
<el-table-column align="center" label="操作" min-width="300">
<template slot-scope="scope">
<el-button v-if="scope.row.status === '待发货'" size="mini" type="primary"
v-on:click="changeStatus(scope.row.id, '待收货')">发货
</el-button>
<el-button v-if="scope.row.status === '申请退款中'" size="mini" type="primary"
v-on:click="changeStatus(scope.row.id, '已退款')">退款
</el-button>
<el-button v-if="scope.row.status === '申请退货中'" size="mini" type="primary"
v-on:click="changeStatus(scope.row.id, '已退货')">退货
</el-button>
<el-button size="mini" type="danger" @click="deleteDepartment(scope.$index, scope.row)">删除</el-button>
</template>
</el-table-column>
</el-table>
<!-- 分页组件 -->
<Pagination v-bind:child-msg="pageparm" @callFather="callFather"></Pagination>
</div>
//(4)景区信息管理界面
<div>
<div class="card">
<div class="card-header"><h4>景区信息列表</h4></div>
<div class="card-body">
<el-form:inline="true":model="formInline" class="form-inline" >
<el-form-item label=""><el-input size="small" v-model="formInline.jingqubianhao" placeholder="输入景区编号"></el-input></el-form-item>
<el-form-item label=""><el-input size="small" v-model="formInline.jingqumingcheng" placeholder="输入景区名称"></el-input></el-form-item>
<el-form-item label=""><el-input size="small" v-model="formInline.piaojia" placeholder="输入票价"></el-input></el-form-item>
<el-form-item><el-button size="small" class="btn btn-default" @click="search"><span class='el-icon-loading'></span>查找</el-button></el-form-item>
</el-form>
<div class="panel admin-panel">
<div class="padding border-bottom">
<button class="btn btn-danger m-r-5" type="button" style="float:right" onClick="window.print();" ><span class="el-icon-s-goods"></span> 打印</button>
<button class="btn btn-success m-r-5" style="float:right" @click="handleDeleteList()" v-if="userInfo.roles0 == 'guanliyuan'" ><span class="el-icon-delete"></span> 批量删除</button>
<button class="btn btn-warning m-r-5" style="float:right" @click="daochu()"><span class="el-icon-setting"></span> 导出excel</button>
<button class="btn btn-info m-r-5" style="float:right" @click="handleEdit()" ><span class="el-icon-star-on"></span>添加新数据</button>
</div>
<el-table class="table table-bordered table-hover":data="listData" highlight-current-row v-loading="loading" border element-loading-text="拼命加载中" @selection-change="handleSelectionChange">
<el-table-column align="center" type="selection" width="60"></el-table-column>
<el-table-column sortable prop="jingqubianhao" label="景区编号"></el-table-column>
<el-table-column sortable prop="jingqumingcheng" label="景区名称"></el-table-column>
<el-table-column align='center' prop='tupian' label='图片' width='100'><template slot-scope='scope'><el-image:src='scope.row.tupian' style='height:70px' v-if="scope.row.tupian"/><img src="../../../static/images/guanli.jpg" style='height:70px' v-else/></template></el-table-column>
<el-table-column sortable prop="piaojia" label="票价"></el-table-column>
<el-table-column sortable prop="dizhi" label="地址" ></el-table-column>
<el-table-column sortable prop="kaifangriqi" label="开放日期" width="220"></el-table-column>
<el-table-column align="center" label="操作" min-width="160" width="280px;">
<template slot-scope="scope">
<!--liangbuan-->
<!--zhixfuanniu-->
<el-button size="mini" type="info" @click="handleContent(scope.$index, scope.row)" v-if="userInfo.roles0 == 'guanliyuan'">内容设置</el-button>
<button class="btn btn-primary" @click="handleEdit(scope.$index, scope.row)" v-if="userInfo.roles0 == 'guanliyuan' " style="cursor:pointer"><i class="mdi mdi-delete-empty"></i>改</button>
<button class="btn btn-warning" @click="deleteJingquxinxi(scope.$index, scope.row)" v-if="userInfo.roles0 == 'guanliyuan' " style="cursor:pointer"><i class="mdi mdi-close"></i>删</button>
<button class='btn btn-info' @click="handleDetail(scope.$index, scope.row)"><i class='mdi mdi-arrow-expand-all'></i>详</button>
</template>
</el-table-column>
</el-table>
</div>
<Pagination v-bind:child-msg="pageparm" @callFather="callFather" ></Pagination>
<el-dialog:title="title":visible.sync="editFormVisible" width="30%" @click="closeDialog">
<el-form label-width="120px":model="editForm":rules="rules" ref="editForm">
<el-form-item label="景区编号" prop="jingqubianhao"><el-input size="small" v-model="editForm.jingqubianhao" auto-complete="off" placeholder="请输入景区编号" style='width:50%'></el-input></el-form-item>
<el-form-item label="景区名称" prop="jingqumingcheng"><el-input size="small" v-model="editForm.jingqumingcheng" auto-complete="off" placeholder="请输入景区名称" style='width:50%'></el-input></el-form-item>
<el-form-item label='图片' prop='tupian'><el-upload class='avatar-uploader' action='http://localhost:9999/files/upload':headers='headers':show-file-list='false':on-success='handleTupianSuccess':before-upload='beforeTupianUpload'><img v-if='editForm.tupian':src='editForm.tupian' class='avatar'><i v-else class='el-icon-plus avatar-uploader-icon'></i></el-upload></el-form-item>
<el-form-item label="票价" prop="piaojia"><el-input-number size="small" v-model="editForm.piaojia" auto-complete="off" placeholder="请输入票价" style='width:50%'></el-input-number></el-form-item>
<el-form-item label="地址" prop="dizhi"><el-input size="small" v-model="editForm.dizhi" auto-complete="off" placeholder="请输入地址" style='width:100%'></el-input></el-form-item>
<el-form-item label="开放日期" prop="kaifangriqi"><el-date-picker type="datetime" value-format="yyyy-MM-dd hh:mm:ss" size="small" v-model="editForm.kaifangriqi" style='width:50%'/></el-form-item>
<el-form-item label="备注" prop="beizhu"><el-input type="textarea" size="small" v-model="editForm.beizhu" auto-complete="off" placeholder="请输入备注" style='width:100%'></el-input></el-form-item>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button size="small" @click="closeDialog">取消</el-button>
<el-button size="small" type="primary":loading="loading" class="title" @click="submitForm('editForm')">保存</el-button>
</div>
</el-dialog>
<!--xiangxidhk-->
<!--zhixfudhk-->
</div>
</div>
</div>
<div class="markdown-container"> <div class="container"> <div class="title">副文本编辑器</div> <tinymce ref="editor" v-model="data.xiangqingjieshao":disabled="disabled" /> <row> <el-col:span="24" style="text-align: center;margin-top: 20px"> <el-button type="danger" @click="clear">清空内容</el-button> <el-button type="primary" @click="save">保存</el-button> <el-button type="primary" @click="back">返回</el-button> </el-col> </row> </div></div>
//(5)后台留言管理模块
<div> <el-form:inline="true":model="formInline" class="user-search"> <el-form-item label=""><el-input size="small" v-model="formInline.cheng" placeholder="输入用户名"></el-input></el-form-item> <el-form-item label=""><el-input size="small" v-model="formInline.biaoti" placeholder="留言"></el-input></el-form-item> <el-form-item> <el-button size="small" type="warning" icon="el-icon-search" @click="search">搜索</el-button> <el-button size="small" type="success" icon="el-icon-s-data" @click="daochu()" v-if="userInfo.roles0 == 'guanliyuan'">导出</el-button> <el-button size="small" type="danger" icon="el-icon-delete" @click="handleDeleteList()" v-if="userInfo.roles0 == 'guanliyuan'">批量删除</el-button> </el-form-item> <el-form-item> <el-upload class="upload-demo" style="float: left; padding-right: 10px;" action='http://localhost:9999/liuyanban/upload':headers='headers':show-file-list='false':on-success='handleDaoruSuccess':before-upload='beforeDaoruUpload' ><el-button size="small" type="info" icon="el-icon-sell" v-if="userInfo.roles0 == 'guanliyuan'">导入</el-button></el-upload> </el-form-item> </el-form> <el-table size="small":data="listData" highlight-current-row v-loading="loading" border element-loading-text="拼命加载中" @selection-change="handleSelectionChange"> <el-table-column align="center" type="selection" width="60"></el-table-column> <el-table-column sortable prop="cheng" label="用户名"></el-table-column><!-- <el-table-column sortable prop="cheng" label="昵称"></el-table-column>--> <!-- <el-table-column sortable prop="touxiang" label="头像"></el-table-column>--> <el-table-column sortable prop="biaoti" label="留言"></el-table-column><!-- <el-table-column sortable prop="neirong" label="内容"></el-table-column>--> <el-table-column sortable prop="huifu" label="回复"></el-table-column> <el-table-column sortable prop="addtime" label="类型" width="160"> <template slot-scope="scope"> <div v-if="scope.row.parent==0">主帖</div> <div v-else>回帖</div> </template> </el-table-column> <el-table-column sortable prop="addtime" label="添加时间" width="160"> <template slot-scope="scope"> <div>{{scope.row.addtime|datePipe('yyyy-MM-dd hh:mm:ss')}}</div> </template> </el-table-column> <el-table-column align="center" label="操作" min-width="160"> <template slot-scope="scope"> <el-button size="mini" type="success" @click="handleEditlb(scope.index, scope.row)" v-if="userInfo.roles\[0\] == 'guanliyuan'"\>回复\ \