SSM架构项目实战(CRM)

news2024/11/16 15:55:47

开始时间:7月17日

技术架构

(一)Web开发4层开发

  1. 视图层(view):展示数据,跟用户交互。《html,css,js,jquery,bootstrap(ext|easyUI),jsp》
  2. 控制层(controller):控制业务处理流程(接受请求,接受参数,封装参数,调用业务层,响应数据)。《SpringMVC,servlet,struts1,struts2,webwork》
  3. 业务层(service):处理业务逻辑(处理业务的步骤以及操作的原子性)。《javase(工作流:activiti | JBPM)》
  4. 持久层(Dao或Mapper):操作数据库。《传统jdbc,MyBatis,hibernate,ibatis》
  5. 整合层:粘合各层框架,维护类资源(ioc),维护数据库资源(aop)。《Spring,ejb,corba》 

 教学目的

(二)综合应用:

        学编程,就要学以致用,否则学得再熟练也没有

(三)教学方式:26天(线下),打算20天做完。

        做web项目开发(完全模拟企业开发),包装2到3年的开发经验。

(四)教学目的:

  1. 对软件公司和软件开发有一定的了解
  2. 了解CRM项目的核心业务
  3. 能够独立完成CRM项目核心业务的开发
  4. 对前期所学技术进行回顾,熟练,加深和扩展
  5. 掌握互联网基础课:linux,redis,git

(五)软件公司的组织结构:

下面部门都和程序员相关

研发部:程序员,美工(前端,设计图片),DBA(数据库调优员)

测试部:测试工程师(测试每个版本,找出bug,记录bug,国内大多数都是黑盒测试,只看功能,不看代码,而白盒都看)

产品部:了解软件市场和业务(提需求)

实施部:部署服务器,了解软硬件服务器(兼职性)

运维部:懂服务器(一般在机房隔壁办公)

市场部:重要!负责去拉项目来做(工资高,有提成,找程序员做标书)

其他:人力部和财务部和程序员关系不大

软件开发周期

(六)软件开发生命周期

1--

招标:政府和金融机构等,需要做哪些项目后,会发布招标(工期,投入等)

投标: 市场部做标书,和程序员沟通。然后投给招标

甲方:招标方

乙方:投标方

2--可行性分析:------------------------------ 可行性分析报告

技术总监或者架构师负责

技术(本公司技术能不能匹配要求)

经济(是否还需招程序员,招哪些层次的程序员)

(如果中标了,而可行性较低,可以转给外包公司(所以说,中标稳赚不赔))

3----需求分析:--------------------------------《需求文档》

产品经理进行分析,需要和客户沟通(需求调研,有可能和程序员一起去)

项目原型(美工做,完成通用的一些业务功能模块页面):去需要调研时,都是带项目原型去和客户沟通的(给客户看静态的页面,确定是否是这些需求),容易确定需求。

确定需求之后,写好需求文档,还需双方签字,才能进行开发。

4----分析与设计:

负责人是架构师或者项目经理,就相当于盖一个房子,里面负责设计图纸的建筑师。而这时候负责搬砖的工人还没有招进来,就相当于程序员,所以说程序员是“码农

5----架构设计:整体性设计(服务器,选用技术)-----------------------------------------架构师

物理架构设计:项目将来运行所在的硬件服务器,用的硬盘

        应用服务器:(Tomcat(免费,中小企业使用),weblogic(收费,功能强大,支持javaee:13种协议),websphere(ibm,收费),jboss(redhat公司,收费),resin(微软))

        数据库服务器:mysql(小巧灵活,免费),oracle(笨重,收费),DB2,sqlservet,达梦

逻辑架构设计:代码分层 

技术选型:java,.net (微软) ,框架

6----项目设计:项目经理负责 -------------项目设计文档

        物理模型设计(项目经理设计):哪些表,哪些字段,字符的类型和长度,以及表和表之间的关系。工具:powerdesigner ----.pdm(能转换成表sql语句)

        逻辑模型设计(实际中,由程序员自己写):哪些类,哪些属性和方法,方法的参数和返回值,以及类和类之间的关系。 工具:rationnal rose---pdl

        界面设计:企业级应用(朴素,用户群体固定,并发数有限),互联网应用(炫酷)

        算法设计:复杂业务,企业级应用不特别在意算法设计,而互联网应用会经常涉及(高并发)

7--搭建开发环境:项目经理搭建

        创建项目,添加jar包,添加配置文件,添加静态页面,添加公共类以及其他资源;能够正常启动运行

8-----编码实现:HR开始忙起来,去面试程序员。-----------注释文档

9-----测试:并不是完全开发完项目才开始测试,而是开发和测试同步进行,一般每周都会提交一个版本交给测试部测试,测试找到bug,放在bug记录平台,程序员再去修改自己的bug。----测试用例-----------------测试用例

10-----试运行:实施部帮客户或者客户找人去买对应性能的服务器。运行大概一周,没问题就可以去上线了。程序员开始逐渐转到下一个项目你 -----------使用手册

11------上线:--------实施文档

12----运维:软件周期一般最长在5年,就要下架了(随着使用,系统会变慢) --------运维手册

13----文档编纂:包含在整个开发过程,例如;需求文档,项目设计文档,可行性分析文档和注释文档。

servlet,jsp(jspl) springMVC

CRM项目的核心业务

CRM项目的简介:Customer Relationship Management 客户关系管理系统

类别为企业级应用,传统应用。给销售或者贸易型公司使用,在市场,销售,服务各个环节中维护客户关系。

CRM项目的宗旨:增加新客户,留住老客户,把已有客户转化成忠诚客户。

CRM是一类项目,每种行业,需要的CRM的实现都不一样,因为业务不一样,本CRM是给一个大型的进出口贸易公司来使用的,做大宗商品的进出口贸易;商品受管制

CRM项目的核心业务:

系统管理功能:不是直接处理业务数据,为了保证业务管理的功能正常安全运行而设计的功能。例如:登录功能,安全退出,登录验证(给超级管理员,系统管理员用的)

业务管理功能:处理业务数据

                市场活动:市场部,设计市场活动营销活动

                线索:销售部(初级销售),增加线索

                客户和联系人:销售部(高级销售),有效地区分和跟踪客户和联系人

                交易:销售部(高级销售),更好地区分和统计交易的各个阶段

                销售回放:客户部,妥善安排销售回访。主动提醒(防止客户忘记)

                统计图表:管理层用,统计交易表中各个阶段数据量。

CRM-物理模型设计

系统管理功能表:

tbl_user  用户表

tbl_dic_type 数据字典类型表

tbl_dic_value 数据字典值

业务管理功能相关表:

tbl_activity 市场活动表

tbl_activeity_remark 市场活动备注表

tbl_clue_activity_relation 线索和市场活动的关联关系表

tbl_clue 线索表

tbl_clue_remark 线索备注表

tbl_customer 客户表

tbl_customer_remark 客户备注表

tbl_contacts  联系人表

tbl_contacts_remark 联系人备注表

tbl_contacts_activity_relation 联系人和市场活动的关联关系表

tbl_tran 交易表

tbl_tran_history 交易历史表

tbl_tran_remark 交易备注表

tbl_task 任务表

主键字段

在表中,如果有一组字段能够唯一确认一条记录,则可以把它们设计成表的主键。推荐使用一个字段做主键,而且推荐使用没有业务含义的字段做主键。比如:id等。主键字段的类型和长度由主键值的生成方式来决定:

  1. 自增:借助数据库自身主键生成机制。数值类型,长度由数据量来决定(企业中,一般不用,底层实现用到了锁,高并发时,运行效率低,但开发效率高)
  2. assigned(手动):程序员手动生成主键值,唯一非空,算法。hi/low:数值型,长度由数据量决定。UUID:字符串,长度固定为32位(企业常用,效率高,适合多线程场景,没有加锁)
  3. 共享主键:由另一张表的类型和长度决定,例如:一个人的信息表,和驾照表。驾照表的id就引用一个人的id就行
  4. 联合主键:由多个字段的类型和长度来决定的

外键字段

用来确定表和表之间的关系

一(主表)对多(父表):

一张表A中的一条记录可以对应另一张表B中的多条记录;而另一张表B中的一条记录只能对应一张表A中的一个记录。例如:学生表(子表)和班级表(父表),一般多的那张表引用一的那个表的主键

添加记录:先添加父表记录,才能添加子表记录

删除记录:先删除子表记录,才能删除父表记录

内连接([inner] join on :外键不能为空):查询所有符合条件的数据,并且要求结果在两张表都有对应的

左外连接(left login on)(外键可以为空,按需求选择左还是右):查询左侧表中所有符合条件的数据,即使在右表中没有对应的数据,右外连接则相反(right login on)

*如果外键不能为空,优先使用内连接

*如果外键能为空,按需求选择左右外连接

一对一:

一张表A中的一条记录可以对应另一张表B中的一条记录;而另一张表B中的一条记录对应另一张表A中的一个记录。例如:个人信息表和驾照表,可以使用共享主键(不经常用)

添加记录:先添加先产生的表的记录,后再添加后产生的表的记录

删除记录:先删除后后产生的表记录,在删除先产生的表记录

查询数据:无需进行连接查询

一般都是用:唯一外键。

 多对多:

一张表A中的一条记录可以对应另一张表B中的多条记录;而另一张表B中的一条记录对应另一张表A中的多个记录。例如:学生表和课程表。

添加记录:先添加父表记录,再添加子表记录(中间表)

删除记录:先删除子表(中间表)记录,再删除父表记录。

查询记录:可能会进行关联查询

借助中间表来维护关系

关于日期和时间的字段

java

        Date

数据库

        date:只有日期

        time:只有时间

        datetime:日期和时间

基于以上格式转换问题,都直接按照字符串处理:

  1. char(10)yyyy-MM-dd
  2. char(19)yyyy-MM-dd HH:mm:ss

导入表sql,物理模型设计完成。

搭建开发环境

创建项目,创建工程:crm

设置编码格式:统一UTF-8

添加jar包依赖:需求文档上有(不需要背)

添加配置文件:不需要背,前期搭建环境时,需要用而已。

添加静态页面:防止非法访问,造成的恶意破坏,一般都把页面放在WEB-INF下 

        合理的项目文件目录:

  1.         

         生成的Tomcat服务器项目文件目录:

编码开发顺序:先做系统管理功能,后做业务管理功能。

做模块功能必须走的流程:

  1. 分析需求:
  2. 分析与设计:
  3. 编码实现
  4. 测试

 登录功能的实现

1.流程图

2.写代码,先写底层,再写高层(高层调用底层)

一个资源目录,创建一个controller进行响应

同步请求:页面全局刷新

异步请求:全局或者局部刷新都可以,存在两个刷新方式时,只能用异步请求。

一个表,对应的一个service,一个对象

mybatis逆向工程

简介:根据表生成mapper层三层部分代码:实体类,mapper接口,映射文件

创建工程:crm-mybatis-generator

添加插件:

<!--myBatis逆向工程插件-->
    <plugin>
	<groupId>org.mybatis.generator</groupId>
	<artifactId>mybatis-generator-maven-plugin</artifactId>
	<version>1.3.2</version>
	<configuration>
	    <verbose>true</verbose>
	    <overwrite>true</overwrite>
	</configuration>
    </plugin>

需要配置:

数据库连接信息

代码保存的目录

表的信息

运行mybatis的逆向工程,根据指定的表

选择器.attr(“属性值名”);//用来获取哪些值不是true或者false的属性的值

选择器.prop("属性名");//用来获取值是true/false 的属性值

选择器.click(function(){})//给指定的元素添加事件

选择器.click();//给指定的元素上模拟发生一次点击事件

把控制层(controller)处理好的数据传到视图层(jsp),使用作用域传递;

四大作用域:

pageContext:同页面内传参数,用来在同一个页面不同标签之间传递数据

request:在同一个请求之间传输数据。(请求完成后,会消失(不能重定向))

session:同一个浏览器,不同请求之间传递数据(服务器停止前,都有效)

application:所有用户共享的数据,而且长久频繁使用的数据。

实现点击回车,确认登录功能:

			//给整个登录窗口添加键盘按下事件-------------实现点击回车,自动登录
			$(window).keydown(function (e){
				//判断是否按键为回车键,,是,则提交登录请求,否则不做响应
				if(e.keyCode===13){//回车的Ascall码为13
					$("#loginBtn").click()
				}
			})

记住密码:

                //如果需要记住密码,则往外写Cookie
                if("true".equals(isRemember)){//选择记住密码
                    System.out.println("到了!!");
                    //账号
                    Cookie cookie1 = new Cookie("loginAct", user.getLoginAct());
                    cookie1.setMaxAge(10*24*60*60);//设置声明周期,10天后自动删除
                    response.addCookie(cookie1);
                    //密码
                    Cookie cookie2 = new Cookie("loginPwd", user.getLoginPwd());
                    cookie2.setMaxAge(10*24*60*60);//设置声明周期,10天后自动删除
                    response.addCookie(cookie2);
                }else{//选择不记住密码
                    //把没有过期cookie删除,不能直接删除客户端的Cookie,通过覆盖,设置生命周期,来达到同样效果
                    Cookie cookie1 = new Cookie("loginAct", "1");
                    cookie1.setMaxAge(0);
                    response.addCookie(cookie1);
                    Cookie cookie2 = new Cookie("loginPwd", "1");
                    cookie2.setMaxAge(0);
                    response.addCookie(cookie2);
                }

通过判断和记录Cookie记录

实现思路:每次登录,判断是否需要记住密码,如果需要,则写Cookie。而且把用户的账号和密码保存在Cookie里面

                下次登录,判断该用户有没有Cookie,没有,则不填,有,则填写Cookie值,即自动填写账号和密码,

页面获取Cookie的方法:

安全退出:

P38集

业务页面的登录验证功能

借助SpringMVC的拦截器HandlerInterceptor实现验证功能

前期映射路径命名规则有利于拦截器使用: 

 1--写拦截类

public class LoginInterceptor implements HandlerInterceptor {
    //访问目标资源前,执行
    @Override
    public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o) throws Exception {
        //验证用户是否处于登录状态
        HttpSession session = httpServletRequest.getSession();//获取session对象
        User user = (User) session.getAttribute(Contants.SESSION_USER);
        if(user==null){//未登录,跳转到登录页面
            //重定向--需要加项目的名称(这里不是MVC框架范围,视图解析器不起作用,不帮忙加前后缀)
            httpServletResponse.sendRedirect(httpServletRequest.getContextPath());//手动重定向,url必须加项目的名称,httpServletRequest.getContextPath()=="/crm"
            return false;
        }else{//已登录,放行资源
            return true;
        }

    }
    @Override
    public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception {

    }

    @Override
    public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception {

    }
}

 2--配置拦截器

    <!-- 配置拦截器(拦截controller请求) -->
    <mvc:interceptors>
        <mvc:interceptor>
<!--  "/settings/*":只表示settings下的一层子目录进行拦截,  "/settings/**": 表示settings的所有多层子目录都进行拦截       -->
            <mvc:mapping path="/settings/**"/>
            <mvc:mapping path="/workbench/**"/>
            <!-- 配置排除拦截的请求(登录相关),排除的优先级高 -->
            <mvc:exclude-mapping path="/settings/qx/user/toLogin.do"/>
            <mvc:exclude-mapping path="/settings/qx/user/login.do"/>
<!--        不需要加这个,因为没有用到全局拦截“/**”    <mvc:exclude-mapping path="/"/>-->
            <!-- 拦截器类 -->
            <bean class="online.sumu.crm.settings.web.interceptor.LoginInterceptor"/>
        </mvc:interceptor>
    </mvc:interceptors>

页面切割技术

一个页面,可以由多个页面组成

技术1:<frameset>和<frame>(重标签,性能低) 

<frameset>: 用来切割页面,只能按行或者列来切

<frame>: 显示页面,每一个<frame>标签就是一个独立的浏览器窗口

技术2:<div>和<iframe> (轻量标签,性能高) 

<div> : 用来切割页面,即和之前用div一样就行

<iframe> :显示页面

市场活动

1--创建(先实现创建模块,在做删改查)

模态窗口:模拟的窗口,不是真实弹出来的,本质上是div,通过设置z-index大小来实现;

                初始时,z-index初始参数小于0,不显示;需要显示时,设置大于0,即可1显示

借助bootstrap框架来控制z-index的大小

方式1--通过框架的标签的属性date-toggle="modal“ :触发显示模态窗口,date-target=”模态窗口的id“ :指定显示某个模态窗口。

方式2--通过js函数控制

方式3-- 通过标签的属性data-dismiss=”“,通过点击添加了属性data-dismiss=”“的按钮,来关闭当前的模态窗口

模态窗口有利于获取要处理的数据

显示市场活动页面

p49

清空form表单里面所有输入框内容

//清空表单.get[0].reset(),, .get(0)为获取表单的全部DOM对象

$("#createActivityForm").get[0].reset()

日历功能的实现:

满足这两个特定,说明有插件,现成的功能的直接cv就行

  1. 实现起来比较复杂
  2. 更业务无关

日历插件:bootstrap-datetimepicker

 前端插使用步骤:

  1. 下载开发包
  2. 拷贝到webapp目录下        
  3. 引入开发包到使用页面上
  4. 创建容器:<input type="text">组件运行结果为字符串
  5. 当容器加载之后,对容器调用工具函数(传参数)

引入css和js等依赖资源,先引入被依赖的资源    

$(function(){}) :为入口函数,只有页面其他资源加载完后,才执行

 

 

 分页查询功能的实现

  1.  查询的时候,能分开为一个独立方法,就分开为独立方法(service层),这样更灵活。
  2. 涉及多个表的增删改时,最好放在service层的一个方法执行,且controller层只调用service一次,保证操作都在一个事务内,可以把全部操作回滚,保持原子性和数据一致性。而不是在controller层调用多次service方法。

P63

 在指定的标签中,显示jsp页面片段:

$("#tBody").html(html语句)//覆盖显示

$("#tBody").text(文本)//覆盖,只能添加文本

$("#tBody").append(html语句)//在尾部追加显示

$("#tBody").after(html语句)//追加显示

$("#tBody").before(html语句)//追加显示

分页插件:bs_pagination

使用步骤:

  1. 引入开发包bs_pagination
  2. 创建容器<div></div>
  3. 当容器加载完后,对容器调用工具函数(注意:要容器加载完后,再调用函数,否则失效)

P74

给页面中元素添加事件方式有:

1--使用元素的事件属性:onxxx=“函数名()”//例如:οnclick=“ 函数名()”(一般不用,不易维护)

2--使用jquery对象:选择器.xxx(function(){   //js语句 }) (只能为固有元素添加事件)

3--使用jquery的on函数:父选择器.on('事件类型名称','添加事件元素名的判定依据',function()){  //js语句  };(不但能给固有元素添加事件,也能给动态生成的元素添加事件)

(父元素:必须时固有元素,可以是直接父元素,也可以是间接父元素)

(事件类型:跟事件数据属性和事件函数意义对应)

(子元素:目标元素,跟父选择器构成一个父子选择器)

注意:使用使用jquery对象判定事件时,对于用在动态元素上,事件可能会失效,而固有元素则没问题

P85

js的截取字符串函数:

 js求长度:

 

 ajax向后台发送请求时,通过data提交参数,data的数据格式有三种格式:

第一种:json对象

data:{

        k1:v1,

        k2:v2,

        ……

}

*优势:操作简单

*劣势:不能向后台提交一个参数名对应多个参数值的数据。否则会覆盖,只能提交字符串。

data:{

        id:v1,

        id:v2,

        ……}//后台只能获取最后一个id的值

第二种:字符串型

data:k1=v1&k2:v2$……

*优势:可以向后台提交一个参数名对应多个参数值的数据

*劣势:需要拼接字符串,操作麻烦,只能提交字符串。

第三种:FormData对象

优势:不但能提交字符串数,还能提交二进制数据

劣势:操作更复杂

封装参数原则规范:

 导出市场活动(导出Excel文件)

 关键技术准备:

(一)使用java生产Excel文件:iText(收费,功能强大),Apache-poi(免费)

关于办公文档插件使用的基本思想:把办公文档的所有元素封装成普通的java类,程序员通过操作这些类达到操作办公文档的目的。

最基础的办公文档类:

  1. Excel文件-----HSSFWorkbook对象
  2. 页------HSSFSheet对象
  3. 行-------HSSFRow对象
  4. 列-------HSSFCell对象
  5. 样式-----HSSFCellStyle

使用Apache-poi生成excel文件:

1--添加依赖

        <!-- Excel文档依赖包  poi依赖-->
        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi</artifactId>
            <version>3.15</version>
        </dependency>

 2--使用封装类

  1. Excel文件-----HSSFWorkbook对象
  2. 页------HSSFSheet对象
  3. 行-------HSSFRow对象
  4. 列-------HSSFCell对象
  5. 样式-----HSSFCellStyle

(二)文件下载:

web技术,涉及前后台技术

//所有的文件下载请求,只能发同步请求

//所有的文件下载请求,只能发同步请求
window.location.href = "workbench/activity/exportAllActivity.do"//同步请求

//浏览器收到响应数据后,默认情况下,直接在显示窗口打开响应信息

//即使打不开,也会调用其他应用程序打开,只有实在打不开,才回激活下载

//可以设置响应头信息,使浏览器默认直接下载。

//设置响应头,是浏览器默认直接下载响应信息,且设置文件名为myStudent.xsl
response.addHeader("Content-Disposition","attachment;filename=ActivityList.xls");

P108

导入市场活动

技术准备:

文件上传:

前端上传文件三要素:

(一)选择文件选择按钮,type值为“file”

(二)form表单提交方式,method值为“post”

请求方式只能用:post

get:参数通过请求头提交到后台,参数放在url后边;只能向后台提交文本数据;对参数长度有限制;数据不安全;效率高;自动将得到的数据放在缓存(重复访问,用缓存,不需发新请求)。

post:参数通过请求体提交到后台,即能提交文件数据,又能够提交二进制数据(图片,视频等);理论上对参数长度没有限制;相对更安全;效率相对较低。

(三)form表单提交编码格式,enctype值为“mutipart/form-data”

根据HTTP协议的规定,浏览器每次向后台提交参数,都会对参数进行统一编码;默认采用的的编码格式为urlencode,这种编码格式只能为文本数据进行编码;所以文件上传的表单编码格式只能用ultipart/form-data。

使用java解析excel文件: iText,apache-poi(这里工具对于excel文件操作都是双向的)

  1. Excel文件-----HSSFWorkbook对象
  2. 页------HSSFSheet对象
  3. 行-------HSSFRow对象
  4. 列-------HSSFCell对象
  5. 样式不提供解析

 文件上传同步和异步都行

 p125

要注意的时,用mvc框架接受页面传来的文件,需要去mvc核心配置文件配置文件上传解析器才能正常使用MultipartFile类

文件上传,如果需要用到文件里面的数据,则文件格式一定要跟用户约定好

技术上的问题解决不了,可以在业务上选择更好的方案

js获取文件名中的后缀子串(全部转成小写):

let fileType = activityFile.substr(activityFile.lastIndexOf(".")+1).toLocaleLowerCase()

jquery对象转DOM对象

&("#id").[0]  或者 &("#id").get(0)

 用ajax上传文件:

                //发送请求----
                //FormData是ajax提供的接口,可以模拟键值对向后台提交参数
                //FormData不但能提交文本数据,还是提交二进制数据
                let formData = new FormData();
                //把文件数据放在formData中的键值对中
                formData.append("activityFile",File)//key要和后台获取文件的参数名对应
                $.ajax({
                    url:"workbench/activity/importActivity.do",
                    data:formData,//
                    type:"post",//上传文件,必须为post
                    processData:false,//设置ajax向后台提交参数前,是否把参数统一转为字符串,true--是,默认为true,当上传文件时,要设置为false
                    contentType:false,//设置ajax向后台提交参数之前,是否把参数统一按urlencoded编码,默认为true,上传文件时,要设置为false,等同于form表单上的enctype=“mutipart/form-data”设置
                    dataType:"json",
                    success:function (data) {
                        if (data.code=="1"){//导入成功
                            alert("成功导入:"+data.retData+"条记录!")
                            //关闭模态窗口
                            $("#importActivityModal").modal("hide")
                            //刷新页面
                            queryActivityByConditionForPage(1, $("#page").bs_pagination('getOption', 'rowsPerPage'))
                        }else{//导入成功
                            //提示信息
                            alert(data.message)
                            //模态窗口不关闭
                            $("#importActivityModal").modal("show")
                        }
                    }
                })

使用标签保存数据(以便在需要的时候能够获取这些数据)

给标签添加属性:

  1.  如果时表单组件标签,优先使用value属性,只有value不方便使用时,使用自定义属性(随便在标签上,定义属性名和属性值);
  2. 如果不是表单组件标签,不推荐是使用value,推荐使用自定义属性;

 获取属性值:

  1. 如果获取表单组件标签的value属性值时,可以用:dom对象.value或者jquery.val();
  2.  如果是自定义的属性,不管是什么标签,只能用:jquery对象.attr('属性名');

P 130

el表达式在js中使用:

//获取表单数据
let activityId = '${activity.id}'//el表达式在js使用,用''括起来,否则浏览器识别为变量

把页面片段动态地显示在页面:5种方法

选择器.append(html):追加显示在指定标签的内部的后面

选择器.text(字符串):覆盖显示在标签内部

选择器.html(html):覆盖显示在标签内部

选择器.after(html):追加显示在指定标签的外部的后面(同级标签)

 选择器.before(html):追加显示在指定标签的外部的前面(同级标签)

给元素扩展属性

        html页面是可拓展的标记语句,可以给指定的标签任意扩展属性,只要属性名名称不重复即可。且有扩展有两个主要目的;

使用标签保存数据:

  1.  如果时表单组件标签,优先使用value属性,只有value不方便使用时,使用自定义属性(随便在标签上,定义属性名和属性值);
  2. 如果不是表单组件标签,不推荐是使用value,推荐使用自定义属性;

定位标签:

        优先考虑id属性,其次考虑name属性,只有id和name属性都不方便使用时,才考虑使用自定义属性。

dom对象转jquery对象

$("#remarkDivList").on('click',"a[name='deleteA']",function () {
	//收集参数( this是dom对象,要放在$()转为jquery对象 )---自定义属性
	let id = $(this).attr('remarkId')}

删除页面指定的元素

//刷新页面(删除元素)
$("#div_"+id).remove()//从页面中移除对应元素

P135--P158还没看

P158

统计图表:以更专业,更形象的形式展示系统中的数据。

销售漏斗图:展示商品销售数据,销售业绩

---------------------------------------- 2022/7/25转去学MyBatis Plus先--------------------------------

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

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

相关文章

代码随想录算法训练营第三十五天 | 两维贪心、重叠区间

860.柠檬水找零 文档讲解&#xff1a;代码随想录 (programmercarl.com) 视频讲解&#xff1a;贪心算法&#xff0c;看上去复杂&#xff0c;其实逻辑都是固定的&#xff01;LeetCode&#xff1a;860.柠檬水找零_哔哩哔哩_bilibili 状态&#xff1a;能直接做出来。 思路 只需要维…

【java-04】深入浅出多态、内部类、常用API

主要内容 多态 内部类 常用API 1 多态 1.1 面向对象三大特征 ? 封装 , 继承 , 多态 1.2 什么是多态 ? 一个对象在不同时刻体现出来的不同形态 举例 : 一只猫对象 我们可以说猫就是猫 : Cat cat new Cat();我们也可以说猫是动物 : Animal cat new Cat();这里对象在不…

知识推理——CNN模型总结

记录一下我看过的利用CNN实现知识推理的论文。 最后修改时间&#xff1a;2023.05.08 目录 1.ConvE 1.1.解决的问题 1.2.优势 1.3.贡献与创新点 1.4.方法 1.4.1 为什么用二维卷积&#xff0c;而不是一维卷积&#xff1f; 1.4.2.ConvE具体实现 1.ConvE 论文&#xff1a…

聊聊我在阿里第一年375晋升的心得

前言 思来想去&#xff0c;觉得这个事情除了领导赏识大佬抬爱之外&#xff0c;还是挺不容易的&#xff0c;主观认为有一定的参考价值&#xff0c;然后也是复盘一下&#xff0c;继续完善自己。 绩效 首先晋升的条件就是要有个好绩效&#xff0c;那么我们就先基于绩效这个维度…

基于`IRIS`列存储,我们能做什么

文章目录 基于IRIS列存储&#xff0c;我们能做什么简介使用场景如何使用列存储什么情况下使用列储存统计数据数量count计算字段平均值avg计算字段和sum 列存储与行存储区别总结 基于IRIS列存储&#xff0c;我们能做什么 简介 列存储是一种数据存储方式&#xff0c;与传统的行…

Win11-RTX4060安装Pytorch-GPU干货避坑指南

文章目录 1、版本要和pytorch官网对应&#xff0c;CUDA11.8及其对应版本的cudnn2、CUDA Toolkit安装出现自动重启3、Python版本4、配置永久国内镜像源5、要在激活的虚拟环境里安装pytorch6、进入python后检查是否gpu配置成功7、在虚拟环境中启动jupyter notebook8、conda中inst…

【Docker】5、Dockerfile 自定义镜像(镜像结构、Dockerfile 语法、把 Java 项目弄成镜像)

目录 零、学习内容一、镜像结构二、Dockerfile四、基于 java:8-alpine 构建自己的 Java 项目镜像 零、学习内容 镜像结构Dockerfile 语法构建 Java 项目 ① 之前使用的镜像都是 DockerHub 官方提供的 ② 开发者需要将自己的微服务制作为镜像 一、镜像结构 镜像是由应用程序及其…

【新星计划-2023】什么是ARP?详解它的“解析过程”与“ARP表”。

一、什么是ARP ARP&#xff08;地址解析协议&#xff09;英文全称“Address Resolution Protocol”&#xff0c;是根据IP地址获取物理地址的一个TCP/IP协议。主机发送信息时将包含目标IP地址的ARP请求广播到局域网络上的所有主机&#xff0c;并接收返回消息&#xff0c;以此确…

ConcurrentHashMap实现原理

1. 哈希表 1.1 介绍 哈希表是一种key-value存储数据的结构&#xff0c;根据key即可查到对应的value。 如果所有的键是整数&#xff0c;我们可用简单的无序数组来表示&#xff0c;键作为数组索引&#xff0c;值即为对应的值 1.2 链式哈希表 链式哈希表本质由一组链表构成。每…

用MacBook实操:docker本地部署mysql+php+nginx坏境

大家好&#xff0c;我拿出我的macbook,带着大家实操用docker部署mysqlphpnginx环境。 之前的小白实操搭建Nginx1.2.0PHP7.0MySQL5.7Thinkphp5项目&#xff0c;看这篇就够了&#xff0c;欢迎阅读。 之前的是服务器上配置环境&#xff0c;现在在mac本地搭建全栈开发环境。 目录…

LiveData详解(实战+源码+粘性事件解决方案)

1. 简介 LiveData 是一种可观察的数据存储器类。与常规的可观察类不同&#xff0c;LiveData 具有生命周期感知能力&#xff0c;意指它遵循其他应用组件&#xff08;如 activity、fragment 或 service&#xff09;的生命周期。这种感知能力可确保 LiveData 仅更新处于活跃生命周…

mysql查询之子查询

0. 概念 SQL语句中嵌套SELECT语句&#xff0c;称为嵌套查询&#xff0c;又叫子查询。 查询可以基于一个表或多个表。子查询可以添加到SELECT、UPDATE和DELETE中&#xff0c;而且可以进行多层嵌套。子查询常用操作符有 ANY(SOME)&#xff0c;ALL、IN、EXISTS。也可以使用比较运…

Codeforces Round 872 (Div. 2) A-C

Start&#xff1a;May/08/2023 20:05UTC8 Length&#xff1a;02:00 这次总该上分了吧 A LuoTianyi and the Palindrome String 1 s, 256 MB x8531 都一样是-1&#xff0c;普通回文是size()-1 #include<bits/stdc.h> using namespace std; #define int long long #def…

架构-软件工程模块-1

概述 这一模块选择题的分值比较多&#xff0c;案例题和论文也有能用上的地方。主要知识点会特殊标注或说明。 软件开发生命周期 软件工程三要素&#xff1a;方法、工具、过程。不会直接考&#xff0c;但可帮助记忆理解。 传统软件生命周期方法学分为&#xff1a;&#xff08;选…

使用sharding-scaling和sharding-proxy做分库分表数据迁移

背景&#xff1a; 现在有一个有一张表被分成了两张表&#xff0c;t_score1 ,t_score2&#xff0c;但后期数据量激增&#xff0c;两张表不能满足业务需求&#xff0c;扩张为2个库每个库2张表&#xff0c;即数据库 ds_0下有t_score1 ,t_score2 &#xff0c;数据库ds1下有t_score1…

浏览器插件的使用

善于使用浏览器插件&#xff0c;能起到高效上网的作用。 Microsoft Edge 是全球广受欢迎的浏览器&#xff0c;浏览器本身具有快速、简单和轻量级的特点。一流的性能系统和访问速度极大提升您的浏览体验。 对于浏览器的用户来说&#xff0c;安装一些实用的插件&#xff0c;能让…

Navicat设置Oracle数据库主键自增1的方法步骤

一、 创建如下表 Oracle数据库不同于Mysql、Sql Server数据库&#xff0c;Oracle数据库主键自增不能在建表时直接设置&#xff0c;而是需要通过序列和触发器进行设置&#xff01; 二、创建序列 1 2 3 4 5 6create sequence SEQ_DEVICEDATAINFO start with 1 …

iOS可视化动态绘制连通图

上篇博客《iOS可视化动态绘制八种排序过程》可视化了一下一些排序的过程&#xff0c;本篇博客就来聊聊图的东西。在之前的博客中详细的讲过图的相关内容&#xff0c;比如《图的物理存储结构与深搜、广搜》。当然之前写的程序是比较抽象的。上篇博客我们以可视化的方式看了一下各…

数据库(Sql server语言)(一)

例题&#xff1a;&#xff08;不介绍创建和插入&#xff09; star表 ●查询每个组合的名称及其成员个数 select g.name,count(*) 成员个数 from star s,stargroup g where s.gid g.gid group by g.name 如果不写where s.gidg,gid会出现成员个数重复 ●查询身高最高的团…

UG NX二次开发(C#)-建模-反向片体(SheetBody)的法向矢量

文章目录 1、前言2、在UG NX中构建一个片体3、在UG NX中查看片体的法向矢量4、采用UFun函数来实现法向反向5、代码实现6、测试效果1、前言 在UG NX中,一张曲面获取其所属的片体(SheetBody)对象,其在构建时有默认的法向矢量,有时处于功能的需求,比如加工时工件的材料去除方…