Advertisement

如何使用ssm实现基于SSM的乡镇篮球队管理系统

阅读量:

@TOC

ssm127基于SSM的乡镇篮球队管理系统+jsp

绪论

1.1 研究背景

注:改写后的文本主要做了以下改动:

  1. 通过替换词汇如"的竞争压力"替换为"的高度"
  2. 调整了部分句子结构
  3. 增加了一些修饰词如"积极应对"
  4. 适当增加了细节描述
  5. 保持了原文的核心含义不变

1.2 目的和意义

电子化的信息管理系统的引入将彻底改变传统的手工处理模式。特别是在海量数据面前,单纯依靠人工工作只会造成巨大的人工成本负担,并且容易导致各种资源利用效率低下及安全性问题的同时,还会延误大量重要工作,特别是在需要频繁更新、归纳和统计的情况下更是会耗财耗力。因此,为了提高工作效率并保障信息安全,就需要立即引入现代化的信息管理系统,它不仅能够快速、高效地完成所有基础工作,还能显著降低人力成本,同时通过强化安全性措施确保系统运行稳定可靠,并且支持实时数据分析和精准修改功能等优势特点,这些都是传统手工模式难以企及的优势所在。由此可以看出,乡镇篮球队管理系统正是推动这一领域改革升级的关键窗口和技术支点。

1.3 论文结构安排

为用户提供深入掌握程序开发流程和相关内容的详细说明,请读者跟随本文的结构安排,在六部分中逐步学习。

第一章阐述了该系统的开发初衷,并探讨了其在现实生活中应用的目的及重要性;同时详细说明了系统文档的格式组织信息。

第二章详细描述了程序的开发环境,并列出了其中所包含的技术及其使用的数据存储工具等相关信息

第三章阐述了在程序开发初期阶段遇到的技术可行性问题,并且详细阐述了程序功能和性能指标的要求。

第四章阐述了程序功能模块下的功能分类信息,并详细设计了存储程序数据的数据库表文件结构。

第五章 详细阐述了系统功能模块交互界面的设计与实现,并对程序操作人员的操作流程进行了具体说明

第六章:描述了程序功能的测试内容,并介绍了系统测试的概念与方法。

2 相关技术

2.1 SSM框架介绍

本课题程序开发过程中涉及的框架技术其英文缩写为SSM它属于JavaWeb开发领域中广泛使用的主流框架之一

2.2 B/S结构介绍

在早期阶段,基于HTML的文件通过整合其他资源文件,即可构建出一个基础型Web程序.掌握Web程序的运作需先理解其背后的Web站点.这些实体间的关系即是一个或多个 Web 程序可被放置在 Web 服务器上进行使用.可以说 Web 应用程序开发推动了 B/S 型网络架构模式的成长.B是 Browser(浏览器)首字母,S是Server(服务器)首字母,两者的组合便形成了网络架构模式中的 B/S 模式.由于该架构模式将客户端浏览器与服务器结合在一起进行操作,因此可以把程序核心功能安排于服务器端处理,从而大大简化了程序开发流程以及后期应用维护工作.图2.1展示了基于这种架构开发的应用程序的工作原理

图2.1 B/S架构的工作原理图

2.3 Mysql数据库介绍

开发的应用程序仅限于展示其功能界面,并供用户操作其功能界面的各项功能。

图2.2 MySQL数据库架构图

3 系统分析

一旦决定开发一个程序时,则需要按照以下步骤依次进行工作:首先进行系统分析...接着是系统设计...随后是系统开发...最后则是系统的测试工作。其中的具体表现为:首先进行系统分析以明确系统的功能需求;然后制定详细的设计方案;之后按照设计开展具体实现工作;最后通过测试确保系统的稳定性和可靠性。

3.1 系统可行性分析

开发一款程序软件不仅耗费时间(即占用时间资源),还需依赖人力和物力资源等基础要素的支持。而对项目进行可行性分析这一环节,则是为了解答用户的相关疑问:考察程序在现有条件下能否顺利开发完成。

3.1.1 技术可行性分析

本系统所采用的编程语言是Java,在其指令控制语句体系上相当完善,在支持类与对象方面具有更为突出的优势。这些特点则为程序设计者提供了有力的技术支撑。经过逐步优化后呈现出高度模块化的特征,并经过公开发布则使熟悉计算机软件开发的相关技术人员能够逐步掌握系统的实现技术

3.1.2 经济可行性分析

开发此程序的核心硬件就是一台个人电脑。无论是在学校的计算机教室配置的电脑还是自己入学以来新添置的笔记本电脑,在性能上都可满足开发需求。此外,在网络方面学校已全面覆盖校园网系统,在硬件配置以及网络基础设施上无需担心经济投入的问题。

3.1.3 运行可行性分析

随着电脑软件及配套硬件的不断升级,在家庭及个人使用的范畴内已经得到了较为广泛的覆盖。因此,在各个家庭及个人使用场景中都能方便地见到各种设备。然而由于本次开发的应用程序对资源消耗相对较低,在普通个人电脑或笔记本设备上均能够顺利运行。

依据前面所述可行性评估结果

3.2 系统性能分析

系统性能分析同样是不可或缺的内容,在实际应用中以保证系统的功能能够稳定可靠地运行一段时间内达到设定的各项标准。由此可见,在现实生活中一个完整的系统软件必须经过系统的性能分析这一关键步骤才能确保其正常运转。本次研究将重点围绕易用性指标、可扩展性指标、系统健壮性指标以及系统安全性指标等四个方面展开详细探讨。

3.2.1 易用性指标

本次程序软件的主要目标是为了帮助用户通过使用该软件来提升信息数据的管理效率,并且该程序还需要根据不同操作人员的需求设置相应的功能。因此,在设计程序的操作流程时应充分考虑用户的日常操作习惯与软件本身的特性,并确保程序的设计与开发能够适应非计算机专业用户的使用水平

3.2.2 可扩展性指标

目前所要开发的应用软件需基于用户的实时需求进行系统设计与构建。然而随着社会发展变化的应用软件也需要不断更新迭代,并需根据用户的实际使用反馈持续增加新的功能内容以适应其多样化需求。值得注意的是为了适应用户需求的变化而持续增加新的功能内容并确保原有系统的稳定性和功能性不会受到影响同时新增的功能模块需能在现有系统框架下顺利运行并符合既定的技术标准要求这样才能确保应用系统的完整性和可靠性最终达到良好用户体验的目的

3.2.3 健壮性指标

为了使程序软件能够在投入使用的状态下持续稳定地处理各类数据信息

3.2.4 安全性指标

软件程序的安全性问题是最优先考虑的方面;由于存储的数据量巨大以及包含许多关键个人数据等因素的影响因素,这也对软件系统必须具备完善的网络安全防护体系提出了严格要求。为了实现对不同用户身份的精准识别以及相应的权限管理,系统必须建立严格的认证机制以保障用户的访问权限控制;同时还需要持续采取各种防护措施来抵御潜在的威胁,保证整个系统的运行始终处于高度安全的状态

3.3 系统流程分析

3.3.1 操作流程分析

由系统将程序分配给用户进行操作时,则必须呈现其相应的工作流程图(如图3.1所示),以便能让用户轻松掌握其基本运行流程。目前而言, 各类程序的操作规范基本上遵循以下统一流程:首先通过登录页面输入必要的账号信息, 然后等待系统验证, 验证成功后即可进入功能操作界面后依次执行相应的操作步骤

图3.1 程序操作流程图

3.3.2 登录流程分析

在此部分中,请对图3.2所示的程序 login 功能模块的操作流程进行详细说明。为此目的设置 login 模块是为了提高用户体验的安全性,在线操作的主要目的是接收用户的 login 信息;系统会对输入的数据进行严格的验证工作;只有经过数据验证后才能完成有效的系统 login

图3.2 程序登录流程图

3.3.3 信息添加流程分析

该系统设计的主要功能是为操作者提供信息录入的界面和平台,在所有信息添加场景下(无论是用于用户信息的录入还是其他相关功能模块的数据录入需求),程序均遵循统一的信息处理流程(如图3.3所示)。在这一流程中,系统首先会对操作者的输入数据进行严格的验证过程,并通过预先编写的程序代码来判断输入数据是否符合预设的标准和要求。当系统确认输入数据合法有效后(例如新增用户的相关信息),会将其记录保存至数据库中。

图3.3 信息添加流程图

3.3.4 信息删除流程分析

在执行程序的数据清理任务时,在所述的数据清理流程(如图3.4所示),需先标记或选择需清除的数据项。为防止操作者无意中清除关键数据,在确认并决定欲清除选定的数据项后,该数据将被永久删除于数据库中。

图3.4 信息删除流程图

4 系统设计

该系统设计方案中包含的功能模块规划以及数据库架构安排直接关系到该系统的整体开发效能以及后期运维维护的便捷性和升级可行性。因为在实际系统实现过程中需要综合考量使用者的各项具体需求,因此若是在设计阶段未能进行全面深入的规划,将会导致后续开发工作难以顺利开展,因此系统的整体设计方案必须建立在对使用者需求进行全面调研的基础之上,只有这样才能为后续系统的功能完善和发展提供可靠的技术保障

该系统设计方案中包含的功能模块规划以及数据库架构安排直接关系到该系统的整体开发效能以及后期运维维护的便捷性和升级可行性。因为在实际系统实现过程中需要综合考量使用者的各项具体需求,因此若是在设计阶段未能进行全面深入的规划,将会导致后续开发工作难以顺利开展,因此系统的整体设计方案必须建立在对使用者需求进行全面调研的基础之上,只有这样才能为后续系统的功能完善和发展提供可靠的技术保障

4.1 系统概要设计

本系统拟开发旨在降低开发成本的同时兼顾后期维护与升级过程中的便利性,并将采用浏览器作为主要手段完成系统功能界面展示工作。通过这种方式使得程序软件的主要事务集中在服务器端后台处理,并将仅负责少量事务逻辑处理即可。下面将借助一张图片(如图4.1所示)来详细阐述程序的工作原理

图4.1 程序工作的原理图

4.2 系统功能结构设计

在分析并得出用户对程序功能需求的过程中后就可以开始进行程序设计工作了。例如图4.2所示即为管理员功能模块图其中管理员的主要职责是完成图书及其类别信息的录入并对录入的数据实施维护包括数据的修改与删除操作此外还需要审核教师注册相关信息发布公告信息以及管理自助租赁相关信息等各项事务

乡镇篮球队管理系统

系球员信息管理

反系统公告管理

收乡镇信息管理

申赛程信息管理

用球队信息管理

帐球员信息修改

密球员信息新增

用球队信息添加

用球队信息删除

用球队信息修改

申赛程信息添加

申赛程信息修改

申赛程信息删除

反系统公告添加

反系统公告删改

反系统公告删除

用乡镇信息添加

用乡镇信息修改

用乡镇信息删除

反留言信息管理

反留言信息修改

反留言信息删除

反留言信息添加

图4.2 系统功能结构图

4.3 数据库设计

程序功能操作不论是添加、修改还是删除等功能产生的数据都是通过数据库进行数据保存和更新的;因此数据库的设计质量也是程序质量好坏的重要判定标准之一。因为程序的成功有一半功劳都归因于数据库的优秀设计;当数据库设计得良好的时候,则能够有效减轻开发人员的工作负担。

4.3.1 数据库E-R图设计

在本设计中涉及到了ER图制作所需的工具有所讨论,在这种情况下较为常用且功能强大的工具有Visio软件用于生成ER模型草图。此软件不仅能够迅速生成所需的ER模型草稿,并且其直观的操作界面能够让使用者快速完成基本功能的学习与掌握。绘图过程中应明确区分各类图形所代表的具体内容,在实际操作中可以通过对不同类型的符号进行合理分类来提高绘图效率与准确性。ER模式通常由实体矩形、属性椭圆以及关系菱形三种基本符号构成,在实际绘制动作中应当注意将不同类别的符号进行区分标注并准确反映各数据元素之间的关联关系

各个实体之间的联系用下图的E-R图表示。绘制的系统E-R图见图4.8。

球队信息

属于

属于

查询

管理

球员

赛程信息

管理员

乡镇篮球队管理系统

管理

管理

管理

查询

n

n

n

n

1

1

n

1

1

1

图4.8 系统E-R图

4.3.2 数据库表结构设计

一旦选定数据库系统之后, 应按程序要求在选定的数据库中建立相应的数据库文件, 并为这些已创建完成的数据库文件建立相应的数据表. 具体涉及对数据表的字段进行详细规划和设置, 包括字段长度的具体规划以及字段的数据类型设定等环节. 经过合理的数据表结构安排后, 才能确保相关程序运行产生的数据信息能够正常存储.

表4.1字典表表

序号 列名 数据类型 说明 允许空
1 Id Int id
2 dic_code String 字段
3 dic_name String 字段名
4 code_index Integer 编码
5 index_name String 编码名字
6 super_id Integer 父字段id

表4.2表

序号 列名 数据类型 说明 允许空
1 Id Int id
7 note String 留言信息
8 yhnote String 留言人
9 note_time Date 留言时间
10 reply String 回复
11 glreply String 回复人
12 reply_time Date 回复时间

表4.3球队信息表

序号 列名 数据类型 说明 允许空
1 Id Int id
13 name String 球队名称
14 xz_types Integer 所属乡镇
15 img_photo String 球队队徽
16 sum Integer 队员人数

表4.4赛程信息表

序号 列名 数据类型 说明 允许空
1 Id Int id
17 qd1_types Integer 比赛队伍1
18 qd2_types Integer 比赛队伍2
19 kaishi_time Date 开始时间
20 jieshu_time Date 结束时间
21 jieguo_content String 比赛结果

表4.5乡镇信息表

序号 列名 数据类型 说明 允许空
1 Id Int id
22 name String 乡镇名称

表4.6系统公告表

序号 列名 数据类型 说明 允许空
1 Id Int id
23 addtime Date 创建时间
24 biaoti String 标题
25 leixing String 类型
26 neirong longtext 内容
27 riqi datetime 日期

表4.7球员信息表

序号 列名 数据类型 说明 允许空
1 Id Int id
28 name String 名称
29 username String 账号
30 password String 密码
31 img_photo String 头像
32 jiguan String 籍贯
33 age Integer 年龄
34 height Integer 身高体重
35 averaged Integer 场均得分
36 backboard Integer 场均篮板数
37 assists Integer 场均助攻数
38 sex_types Integer 性别
39 qd_types Integer 所属球队
40 phone String 手机号
41 role String 身份

5 系统实现

在系统的实现过程中,则是通过编码的方式实现了对……在实际应用中展示出系统的分析与设计方案之间的关系。如前所述,在系统的分析与设计中……核心任务则是构建系统的功能需求以及相关的操作逻辑体系……其中包含数据库方面的详细规划等内容……而系统的最终实现则是一个关键阶段……即通过物理化实施过程将之前的理论成果转化为具体的 runnable software system

5.1球员信息管理

如图5.1所示的是球员信息管理页面,在此页面上为管理员提供了以下功能:进行查询与管理球员数据;移除相应的球队记录;更新相关成员资料;增添新的球队成员。

还进行了对客户名称的模糊查询的条件

图5.1 球员信息管理页面

5.2 球队信息管理

通过图5.2可以看出, 该平台的主要功能是展示球队信息管理模块

图5.2 球队信息管理页面

5.3乡镇信息管理

如图5-3所示为乡镇信息管理页面, 该页面为管理员提供了基于乡镇名称的条件筛选功能. 此外, 管理员还可以对个乡镇数据进行新增记录, 更新数据以及检索相关信息等操作.

图5.3 乡镇信息管理页面

5.1留言信息管理

如图5-4所示,则是留言信息管理页面。该页面为工作人员提供了处理用户留言的回复、删除和新增等功能。

图5.4 留言信息管理页面

系统

DictionaryServiceImpl.java
复制代码
    package com.service.impl;
    
    import org.springframework.stereotype.Service;
    import java.util.Map;
    import com.baomidou.mybatisplus.plugins.Page;
    import com.baomidou.mybatisplus.service.impl.ServiceImpl;
    import org.springframework.transaction.annotation.Transactional;
    import com.utils.PageUtils;
    import com.utils.Query;
    
    import com.dao.DictionaryDao;
    import com.entity.DictionaryEntity;
    import com.service.DictionaryService;
    import com.entity.view.DictionaryView;
    
    /** * 字典表 服务实现类
     * @since 2021-03-22
     */
    @Service("dictionaryService")
    @Transactional
    public class DictionaryServiceImpl extends ServiceImpl<DictionaryDao, DictionaryEntity> implements DictionaryService {
    
    @Override
    public PageUtils queryPage(Map<String,Object> params) {
        if(params != null && (params.get("limit") == null || params.get("page") == null)){
            params.put("page","1");
            params.put("limit","10");
        }
        Page<DictionaryView> page =new Query<DictionaryView>(params).getPage();
        page.setRecords(baseMapper.selectListView(page,params));
        return new PageUtils(page);
    }
    
    }
FileUtil.java
复制代码
    package com.utils;
    
    import java.io.ByteArrayOutputStream;
    import java.io.File;
    import java.io.FileInputStream;
    import java.io.IOException;
    import java.io.InputStream;
    
    /** * @author yangliyuan
    * @version 创建时间:2020年2月7日 下午8:01:14
    * 类说明 : 
    */
    
    public class FileUtil {
    	public static byte[] FileToByte(File file) throws IOException {
    		// 将数据转为流
    		@SuppressWarnings("resource")
    		InputStream content = new FileInputStream(file);
    		ByteArrayOutputStream swapStream = new ByteArrayOutputStream();
    		byte[] buff = new byte[100];
    		int rc = 0;
    		while ((rc = content.read(buff, 0, 100)) > 0) {
    			swapStream.write(buff, 0, rc);
    		}
    		// 获得二进制数组
    		return swapStream.toByteArray();
    	}
    }
XiangzhenController.java
复制代码
    package com.controller;
    
    import java.text.SimpleDateFormat;
    import java.util.*;
    import javax.servlet.http.HttpServletRequest;
    
    import org.apache.commons.lang3.StringUtils;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Controller;
    import org.springframework.web.bind.annotation.PathVariable;
    import org.springframework.web.bind.annotation.RequestBody;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RequestParam;
    import org.springframework.web.bind.annotation.RestController;
    import com.baomidou.mybatisplus.mapper.EntityWrapper;
    import com.baomidou.mybatisplus.mapper.Wrapper;
    
    import com.entity.XiangzhenEntity;
    
    import com.service.XiangzhenService;
    import com.utils.PageUtils;
    import com.utils.R;
    
    /** * 乡镇信息
     * 后端接口
     * @author
     * @email
     * @date 2021-03-22
    */
    @RestController
    @Controller
    @RequestMapping("/xiangzhen")
    public class XiangzhenController {
    private static final Logger logger = LoggerFactory.getLogger(XiangzhenController.class);
    
    @Autowired
    private XiangzhenService xiangzhenService;
    
    /** * 后端列表
    */
    @RequestMapping("/page")
    public R page(@RequestParam Map<String, Object> params){
        logger.debug("Controller:"+this.getClass().getName()+",page方法");
        PageUtils page = xiangzhenService.queryPage(params);
        return R.ok().put("data", page);
    }
    /** * 后端详情
    */
    @RequestMapping("/info/{id}")
    public R info(@PathVariable("id") Long id){
        logger.debug("Controller:"+this.getClass().getName()+",info方法");
        XiangzhenEntity xiangzhen = xiangzhenService.selectById(id);
        if(xiangzhen!=null){
            return R.ok().put("data", xiangzhen);
        }else {
            return R.error(511,"查不到数据");
        }
    
    }
    
    /** * 后端保存
    */
    @RequestMapping("/save")
    public R save(@RequestBody XiangzhenEntity xiangzhen, HttpServletRequest request){
        logger.debug("Controller:"+this.getClass().getName()+",save");
        Wrapper<XiangzhenEntity> queryWrapper = new EntityWrapper<XiangzhenEntity>()
            .eq("name", xiangzhen.getName())
            ;
        logger.info("sql语句:"+queryWrapper.getSqlSegment());
        XiangzhenEntity xiangzhenEntity = xiangzhenService.selectOne(queryWrapper);
        if(xiangzhenEntity==null){
            xiangzhenService.insert(xiangzhen);
            return R.ok();
        }else {
            return R.error(511,"表中有相同数据");
        }
    }
    
    /** * 修改
    */
    @RequestMapping("/update")
    public R update(@RequestBody XiangzhenEntity xiangzhen, HttpServletRequest request){
        logger.debug("Controller:"+this.getClass().getName()+",update");
        //根据字段查询是否有相同数据
        Wrapper<XiangzhenEntity> queryWrapper = new EntityWrapper<XiangzhenEntity>()
            .notIn("id",xiangzhen.getId())
            .eq("name", xiangzhen.getName())
            ;
        logger.info("sql语句:"+queryWrapper.getSqlSegment());
        XiangzhenEntity xiangzhenEntity = xiangzhenService.selectOne(queryWrapper);
        if(xiangzhenEntity==null){
            xiangzhenService.updateById(xiangzhen);//根据id更新
            return R.ok();
        }else {
            return R.error(511,"表中有相同数据");
        }
    }
    
    
    /** * 删除
    */
    @RequestMapping("/delete")
    public R delete(@RequestBody Long[] ids){
        logger.debug("Controller:"+this.getClass().getName()+",delete");
        xiangzhenService.deleteBatchIds(Arrays.asList(ids));
        return R.ok();
    }
    }
jquery.searchableSelect.js
复制代码
    // Author: David Qin
    // E-mail: david@hereapp.cn
    // Date: 2014-11-05
    
    (function($){
    
      // a case insensitive jQuery :contains selector
      $.expr[":"].searchableSelectContains = $.expr.createPseudo(function(arg) {
    return function( elem ) {
      return $(elem).text().toUpperCase().indexOf(arg.toUpperCase()) >= 0;
    };
      });
    
      $.searchableSelect = function(element, options) {
    this.element = element;
    this.options = options || {};
    this.init();
    
    var _this = this;
    
    this.searchableElement.click(function(event){
      // event.stopPropagation();
      _this.show();
    }).on('keydown', function(event){
      if (event.which === 13 || event.which === 40 || event.which == 38){
        event.preventDefault();
        _this.show();
      }
    });
    
    $(document).on('click', null, function(event){
      if(_this.searchableElement.has($(event.target)).length === 0)
        _this.hide();
    });
    
    this.input.on('keydown', function(event){
      event.stopPropagation();
      if(event.which === 13){         //enter
        event.preventDefault();
        _this.selectCurrentHoverItem();
        _this.hide();
      } else if (event.which == 27) { //ese
        _this.hide();
      } else if (event.which == 40) { //down
        _this.hoverNextItem();
      } else if (event.which == 38) { //up
        _this.hoverPreviousItem();
      }
    }).on('keyup', function(event){
      if(event.which != 13 && event.which != 27 && event.which != 38 && event.which != 40)
        _this.filter();
    })
      }
    
      var $sS = $.searchableSelect;
    
      $sS.fn = $sS.prototype = {
    version: '0.0.1'
      };
    
      $sS.fn.extend = $sS.extend = $.extend;
    
      $sS.fn.extend({
    init: function(){
      var _this = this;
      this.element.hide();
    
      this.searchableElement = $('<div tabindex="0" class="searchable-select"></div>');
      this.holder = $('<div class="searchable-select-holder"></div>');
      this.dropdown = $('<div class="searchable-select-dropdown searchable-select-hide"></div>');
      this.input = $('<input type="text" class="searchable-select-input" />');
      this.items = $('<div class="searchable-select-items"></div>');
      this.caret = $('<span class="searchable-select-caret"></span>');
    
      this.scrollPart = $('<div class="searchable-scroll"></div>');
      this.hasPrivious = $('<div class="searchable-has-privious">...</div>');
      this.hasNext = $('<div class="searchable-has-next">...</div>');
    
      this.hasNext.on('mouseenter', function(){
        _this.hasNextTimer = null;
    
        var f = function(){
          var scrollTop = _this.items.scrollTop();
          _this.items.scrollTop(scrollTop + 20);
          _this.hasNextTimer = setTimeout(f, 50);
        }
    
        f();
      }).on('mouseleave', function(event) {
        clearTimeout(_this.hasNextTimer);
      });
    
      this.hasPrivious.on('mouseenter', function(){
        _this.hasPriviousTimer = null;
    
        var f = function(){
          var scrollTop = _this.items.scrollTop();
          _this.items.scrollTop(scrollTop - 20);
          _this.hasPriviousTimer = setTimeout(f, 50);
        }
    
        f();
      }).on('mouseleave', function(event) {
        clearTimeout(_this.hasPriviousTimer);
      });
    
      this.dropdown.append(this.input);
      this.dropdown.append(this.scrollPart);
    
      this.scrollPart.append(this.hasPrivious);
      this.scrollPart.append(this.items);
      this.scrollPart.append(this.hasNext);
    
      this.searchableElement.append(this.caret);
      this.searchableElement.append(this.holder);
      this.searchableElement.append(this.dropdown);
      this.element.after(this.searchableElement);
    
      this.buildItems();
      this.setPriviousAndNextVisibility();
    },
    
    filter: function(){
      var text = this.input.val();
      this.items.find('.searchable-select-item').addClass('searchable-select-hide');
      this.items.find('.searchable-select-item:searchableSelectContains('+text+')').removeClass('searchable-select-hide');
      if(this.currentSelectedItem.hasClass('searchable-select-hide') && this.items.find('.searchable-select-item:not(.searchable-select-hide)').length > 0){
        this.hoverFirstNotHideItem();
      }
    
      this.setPriviousAndNextVisibility();
    },
    
    hoverFirstNotHideItem: function(){
      this.hoverItem(this.items.find('.searchable-select-item:not(.searchable-select-hide)').first());
    },
    
    selectCurrentHoverItem: function(){
      if(!this.currentHoverItem.hasClass('searchable-select-hide'))
        this.selectItem(this.currentHoverItem);
    },
    
    hoverPreviousItem: function(){
      if(!this.hasCurrentHoverItem())
        this.hoverFirstNotHideItem();
      else{
        var prevItem = this.currentHoverItem.prevAll('.searchable-select-item:not(.searchable-select-hide):first')
        if(prevItem.length > 0)
          this.hoverItem(prevItem);
      }
    },
    
    hoverNextItem: function(){
      if(!this.hasCurrentHoverItem())
        this.hoverFirstNotHideItem();
      else{
        var nextItem = this.currentHoverItem.nextAll('.searchable-select-item:not(.searchable-select-hide):first')
        if(nextItem.length > 0)
          this.hoverItem(nextItem);
      }
    },
    
    buildItems: function(){
      var _this = this;
      this.element.find('option').each(function(){
        var item = $('<div class="searchable-select-item" data-value="'+$(this).attr('value')+'">'+$(this).text()+'</div>');
    
        if(this.selected){
          _this.selectItem(item);
          _this.hoverItem(item);
        }
    
        item.on('mouseenter', function(){
          $(this).addClass('hover');
        }).on('mouseleave', function(){
          $(this).removeClass('hover');
        }).click(function(event){
          event.stopPropagation();
          _this.selectItem($(this));
          _this.hide();
        });
    
        _this.items.append(item);
      });
    
      this.items.on('scroll', function(){
        _this.setPriviousAndNextVisibility();
      })
    },
    show: function(){
      this.dropdown.removeClass('searchable-select-hide');
      this.input.focus();
      this.status = 'show';
      this.setPriviousAndNextVisibility();
    },
    
    hide: function(){
      if(!(this.status === 'show'))
        return;
    
      if(this.items.find(':not(.searchable-select-hide)').length === 0)
          this.input.val('');
      this.dropdown.addClass('searchable-select-hide');
      this.searchableElement.trigger('focus');
      this.status = 'hide';
    },
    
    hasCurrentSelectedItem: function(){
      return this.currentSelectedItem && this.currentSelectedItem.length > 0;
    },
    
    selectItem: function(item){
      if(this.hasCurrentSelectedItem())
        this.currentSelectedItem.removeClass('selected');
    
      this.currentSelectedItem = item;
      item.addClass('selected');
    
      this.hoverItem(item);
    
      this.holder.text(item.text());
      var value = item.data('value');
      this.holder.data('value', value);
      this.element.val(value);
    
      if(this.options.afterSelectItem){
        this.options.afterSelectItem.apply(this);
      }
    },
    
    hasCurrentHoverItem: function(){
      return this.currentHoverItem && this.currentHoverItem.length > 0;
    },
    
    hoverItem: function(item){
      if(this.hasCurrentHoverItem())
        this.currentHoverItem.removeClass('hover');
    
      if(item.outerHeight() + item.position().top > this.items.height())
        this.items.scrollTop(this.items.scrollTop() + item.outerHeight() + item.position().top - this.items.height());
      else if(item.position().top < 0)
        this.items.scrollTop(this.items.scrollTop() + item.position().top);
    
      this.currentHoverItem = item;
      item.addClass('hover');
    },
    
    setPriviousAndNextVisibility: function(){
      if(this.items.scrollTop() === 0){
        this.hasPrivious.addClass('searchable-select-hide');
        this.scrollPart.removeClass('has-privious');
      } else {
        this.hasPrivious.removeClass('searchable-select-hide');
        this.scrollPart.addClass('has-privious');
      }
    
      if(this.items.scrollTop() + this.items.innerHeight() >= this.items[0].scrollHeight){
        this.hasNext.addClass('searchable-select-hide');
        this.scrollPart.removeClass('has-next');
      } else {
        this.hasNext.removeClass('searchable-select-hide');
        this.scrollPart.addClass('has-next');
      }
    }
      });
    
      $.fn.searchableSelect = function(options){
    this.each(function(){
      var sS = new $sS($(this), options);
    });
    
    return this;
      };
    
    })(jQuery);

声明

本博客的主要适用领域涵盖广泛的技术与教育领域。

包括但不限于个人学习、软件开发以及产品设计等多个方面。

本内容仅作为参考资料提供。

以帮助读者深入掌握相关技术知识并促进学术交流为目标。

全部评论 (0)

还没有任何评论哟~