80 linux 系统操作

lishihuan大约 185 分钟

项目笔记

gitee 作为图床有个问题,图片大小不能 超过 1M

待整理:https://blog.csdn.net/qq_33683097/article/details/81230111open in new window ssm maven 工程目录以及环境搭建(对配置文件的介绍)

整理代表:ydxjApply 巡检保人事申请

接口开发:https://blog.csdn.net/diyangxia/article/details/64122387open in new window

https://oss.console.aliyun.com/bucket/oss-cn-shanghai/lishihuan/object?path=20210408%2Fopen in new window

https://blog.csdn.net/vivivi_lau/article/details/106501715open in new window

git: https://git-scm.com/book/zh/v2open in new window

​ 图形化工具:Source Tree,[TortoiseGit](# https://www.cnblogs.com/xiuxingzhe/p/9312929.htmlopen in new window)

https://www.cnblogs.com/tugenhua0707/p/4050072.htmlopen in new window

js 实现 复制图片到剪切板 https://blog.csdn.net/MICHAELKING1/article/details/89642497open in new window

js 模板:https://blog.csdn.net/qq_42943107/article/details/91045524open in new window

css 动画;https://zh.javascript.info/css-animations#guan-jian-zhen-dong-hua-keyframesopen in new window

css 实现 图文切换:https://www.cnblogs.com/cs-whut/p/13463928.htmlopen in new window (C:\Users\lishihuan\Desktop\html动画-待整理\CSS动画实例:图文切换.html)

layer 弹窗层 https://blog.csdn.net/qq_37335220/article/details/82024066open in new window

图片 都放到一起,通过定位来 显示 当中的 具体 图片,例如ztree 图标 (用到属性 background-position)

Collections3.extractToString 对 集合的处理

idea 设置svn代码忽略:https://blog.csdn.net/idongit/article/details/103079171open in new window

https://tool.lu/tinyimage/open in new window 在线压缩图片

java 待整理: ControllerAdvice 注解

待整理 Java使用 POI 操作Excelopen in new window

待整理 盒子模型:https://www.cnblogs.com/hellocd/p/10443237.htmlopen in new window

待整理: js 闭包 https://blog.csdn.net/weixin_39214481/article/details/86164785open in new window

待整理-java 导出word:https://www.jianshu.com/p/de58ab550157open in new window

https://blog.csdn.net/xm393392625/article/details/88795547open in new window 插入图片

var data =  eval('('+evt.data+')');
JSON.parse(itemStr);

跨域:https://blog.csdn.net/qq_30546099/article/details/71404574open in new window

不同域名之间共享localStorage/sessionStorage https://www.jianshu.com/p/8c4cee29d532open in new window (解决跨域场景)

netty websocket实现心跳和断线重连

https://www.cnblogs.com/chaizezhao/articles/5291608.htmlopen in new window

app开发;https://blog.csdn.net/lucy_100/article/details/49820393open in new window

待整理,CPMS 组织树 (TreeBean)

整理 图片放大器:<div ng-include="'modules/sys/picGiger.html'"></div> 如何实现 作为公共 模块的

待整理:坐标转换(java,js) 坐标获取位置信息

Notepad++ 临时备份文件路径: C:\Users\lishihuan\AppData\Roaming\Notepad++\backup\

快捷键:

  • Idea:

    • ctrl+shift+x 转为大写

    • ctrl+shift+y 转为小写

    • sql 美化器:ctrl+alt+

    • Ctrl+alt+v 补全等号左侧

    • Alt+Ctrl+T 快速 tyr/catch (选中代码后也可以使用快捷键,Alt+Shift+Z 快速tyr/catch)

    • new XXX(); @ + L 自动生成new的新对象

    • Ctrl +shift+ o 批量引出jar包和删除多余jar包

  • NotePad大小写转换open in new window

    • 小写转换大写 Ctrl + shift + U
    • 大写转换小写Ctrl + U
    • 复制当前行 Ctrl + D
    • 删除当前行 Ctrl +L (相当于剪切 + 删除行,并不是存粹的删除行)
  • MyEclipse :

    • Alt+Shift+L 代码等号右边自动补全

输入法英文间距太大 open in new window(全角和半角) shift+空格

坐标系

公司:
	谷歌地图:31.9344120986,117.2649120808	----> 和 腾讯和高德坐标偏移很小
	百度地图:31.9405040000,117.2714210000
	腾讯高德:31.9344119085,117.2649256012
	图吧地图:31.9378224285,117.2620342812
	谷歌地球:31.9364424285,117.2594242812   ---> 现在市面上 GPS都是用这个的
	北纬N31°56′11.19″ 东经E117°15′33.93″
坐标系说明
    WGS84坐标系	地球坐标系,国际通用坐标系  ---GPS
    GCJ02坐标系	火星坐标系,WGS84坐标系加密后的坐标系;Google国内地图、高德、QQ地图、腾讯地图 使用
    BD09坐标系	百度坐标系,GCJ02坐标系加密后的坐标系
注:
	谷歌地图API,高德地图API,腾讯地图API上取到的,都是GCJ-02坐标,他们三家都是通用的
	百度:BD-09坐标
	谷歌地球,google earth上取到的,是GPS坐标。而且是度分秒形式的经纬度坐标。在国内不允许使用。必须转换为GCJ-02坐标

11 数据库

shu据库:https://192.168.99.19:1158/emopen in new window

11.1

  • 命令运行 : sqlplus /nolog

  • 给system赋权 :grant sysdba to system;

sql文件导入导致plsql 等工具卡死,无法执行解决:

​ 1.cmd-->输入: conn sys/as sysdba

​ 2.输入密码 lishihuan

​ 3. sql>@'D:\aa.sql'; 执行后导入sql文件

oracle em 主机身份证明 输入的用户名和密码是 电脑端的,比如我的是 wangyilishihuna@163.com e9q......

11.1oracle 一些常用 语句

数据库创建一个用户

测试测试

/*(命令行运行: sqlplus /nolog  在SQL>提示符后面运行: conn /as sysdba  命令横提示Connected说明连接成功;)*/
--1.查询用户 (检查用户对象,导库的时候可以用来检测,目标用户是否存在)
select * from dba_users; 
--2.查询表控件本地存储位置
select name from v$datafile;
--3.创建表空间
create tablespace sdt_tyxxpt datafile 'D:\ORACLE\ORADATA\ORCL\sdt_tyxxpt.dbf' size 50m autoextend on next 50m maxsize 20480m extent management local; 
--说明:(create tablespace 表空间名称 datafile '数据文件的路径' size 大小 autoextend on ;  (autoextend 自增长)命令行输入)
--4.创建用户: 创建用户语法:create user 用户名 identified by 密码 default tablespace 用户默认使用哪一个表空间; 
create user sdt_tyxxpt identified by sdt_tyxxpt default tablespace sdt_tyxxpt temporary tablespace temp;
--5.给用户授予权限 
grant connect,resource,dba to sdt_tyxxpt;
--6.删除
--删除用户
drop user 用户名称 cascade;

--删除表空间
drop tablespace 表空间名称 including contents and datafiles cascade constraint;
-- 修改用户密码
alter user SDT_XJB identified by SDT_XJB;
--7.数据库em
https://localhost:1158/em;

删除用户失败,提示 ORA-01940 用户被使用在,所以需要先杀死进程

select username,sid,serial#,paddr from v$session where username='INVOICE'; alter system kill session '62,22594';

image-20210113095013789
image-20210113095013789

修改用户密码

alter user 用户名 identified by 新密码;

查询每个表的 数据量

select u.TABLE_NAME,u.NUM_ROWS from user_tables u order by u.NUM_ROWS desc

查看ORACLE表空间大小及所剩空间大小 (单位MB)

select a.tablespace_name,
       a.bytes / 1024 / 1024 "Sum MB",
       (a.bytes - b.bytes) / 1024 / 1024 "used MB",
       b.bytes / 1024 / 1024 "free MB",
       round(((a.bytes - b.bytes) / a.bytes) * 100, 2) "percent_used"
  from (select tablespace_name, sum(bytes) bytes
          from dba_data_files
         group by tablespace_name) a,
       (select tablespace_name, sum(bytes) bytes, max(bytes) largest
          from dba_free_space
         group by tablespace_name) b
 where a.tablespace_name = b.tablespace_name
 order by ((a.bytes - b.bytes) / a.bytes) desc;

SELECT UPPER(F.TABLESPACE_NAME) "表空间名",
       D.TOT_GROOTTE_MB "表空间大小(M)",
       D.TOT_GROOTTE_MB - F.TOTAL_BYTES "已使用空间(M)",
       TO_CHAR(ROUND((D.TOT_GROOTTE_MB - F.TOTAL_BYTES) / D.TOT_GROOTTE_MB * 100, 2),'990.99') "使用比",
       F.TOTAL_BYTES "空闲空间(M)",
       F.MAX_BYTES "最大块(M)"
  FROM (SELECT TABLESPACE_NAME,
               ROUND(SUM(BYTES) / (1024 * 1024), 2) TOTAL_BYTES,
               ROUND(MAX(BYTES) / (1024 * 1024), 2) MAX_BYTES
          FROM SYS.DBA_FREE_SPACE
         GROUP BY TABLESPACE_NAME) F,
       (SELECT DD.TABLESPACE_NAME,
               ROUND(SUM(DD.BYTES) / (1024 * 1024), 2) TOT_GROOTTE_MB
          FROM SYS.DBA_DATA_FILES DD
         GROUP BY DD.TABLESPACE_NAME) D
 WHERE D.TABLESPACE_NAME = F.TABLESPACE_NAME
 ORDER BY 4 DESC;

查询用户下的所有表

select t.* from user_tables t;

select * from all_tab_comments;--查询所有用户的表,视图等。
select * from user_tab_comments;--查询本用户的表,视图等。
select * from all_col_comments;--查询所有用户的表的列名和注释。
select * from user_col_comments;--查询本用户的表的列名和注释。
select * from all_tab_columns;--查询所有用户的表的列名等信息。
select * from user_tab_columns;--查询本用户的表的列名等信息。

/*
    ORACLE下有三个视图
        DBA_TABLES 拥有DBA角色的用户可以查看系统中的所有表
        USER_TABLES 登录数据库的当前用户拥有的所有表
        ALL_TABLES 登录数据库的当前用户有权限查看的所有表
 */

查询空表

select * from user_tables where num_rows=0;
select username,default_tablespace from user_users;,查询当前用户下的表空间

修改表空间

-- 如果是 迁移表,针对需要 修改表空间的场景,需要 分2步,1.修改表的 表空间  2.重建 索引 的 表空间
---- 1.讲表 ACT_RU_JOB 的表空间修改为   SDT_XJB
alter table ACT_RU_JOB move tablespace SDT_XJB;
---- 2. 重建 索引
select 'alter index '||index_name||' rebuild online;' from  user_indexes 
	where status <> 'VALID' and index_name not like'%$$' or tablespace_name ='SDT_IMOA';;
----- 本质执行 alter index 索引名称 rebuild online; 重建


-- 查询索引(用于检查是否有些 重构 索引 但是没有 讲表空间修改 好)
select tablespace_name,index_name,t.table_name,t.status from SYS.USER_INDEXES t;--(USER_INDEXES 查询索引信息的视图)
--批量修改(找到 索引 表空间为 SDT_IMOA 的所有索引 修改语句,将其 修改为 CPMS)
select 'alter index '||index_name||' rebuild tablespace CPMS;' from  user_indexes where tablespace_name ='SDT_IMOA';

--alter index 索引名称 rebuild online; --重建
--alter index 索引名称 rebuild tablespace 表空间; --修改表空间

获取 DDL 语句

SELECT DBMS_METADATA.GET_DDL('TABLE',u.table_name) FROM USER_TABLES u; 
SELECT DBMS_METADATA.GET_DDL('INDEX',u.index_name) FROM USER_INDEXES u; 

查询每个表数量

select t.table_name,t.num_rows from user_tables t;

主键、唯一性约束 、联合主键

对于除了主键还需要 其他字段做唯一性约束,(例如部门下管的行政区域,那么中间表需要 部门和行政区域合再一起做唯一性约束)

alter table zcz add constraints zcz_pk primary key (id); -- 主键
alter table zcz add constraints zcz_name_age primary key (name,age);--联合主键

--创建联合约束(下面该条sql的作用是name和age不能同时相等)
CREATE UNIQUE INDEX zcz_name_age ON zcz(NVL2(name,age,NULL),NVL2(name,name,NULL));

-- 创建unique唯一约束(不能存在 name+age相同的数据)
alter table table_name add constraint name_age_unique unique(name,age));

-- 给表添加 主键和联合约束
alter table BAS_C_LINE_RELEVANCE 
      add constraints PK_BAS_C_LINE_RELEVANCE primary key (id)
      add constraint ID_PID_UNIQUE unique(LINE_PID,LINE_ID);

查询库中的表名和表中记录数

SELECT T.TABLE_NAME, T.NUM_ROWS FROM USER_TABLES T;

表数据被删除,但是空间没被释放

truncate table  YDXJ_DW_DWJL_2018_08 DROP STORAGE;
alter TABLE YDXJ_DW_DWJL_2018_08 deallocate unused keep 1k;  

导入时报:ora-01659 表空间自增长的原因

select name from v$datafile;
alter database datafile 'D:\APP\LISHIHUAN\ORADATA\ORCL\SDT_XJB.DBF' autoextend on;

Oracle 取随机数(转)open in new window

--1、从表中随机取记录
     select * from (select * from staff order by dbms_random.random)      where rownum < 4  --表示从STAFF表中随机取3条记录
--2、产生随机数
        SELECT DBMS_RANDOM.RANDOM FROM DUAL;          --产生一个任意大小的随机数
        SELECT ABS(MOD(DBMS_RANDOM.RANDOM,100)) FROM DUAL;          --产生一个100以内的随机数
        SELECT TRUNC(100+900*dbms_random.value) FROM dual;          --产生一个100~1000之间的随机数
        SELECT dbms_random.value FROM dual;          --产生一个0~1之间的随机数
		SELECT dbms_random.value(10,20) FROM dual;          --产生一个10~20之间的随机数
        SELECT dbms_random.normal FROM dual;          --NORMAL函数返回服从正态分布的一组数。此正态分布标准偏差为1,期望值为0。这个函数返回的数值中有68%是介于-1与+1之间,95%介于-2与+2之间,99%介于-3与+3之间。

--3、产生随机字符串
	select dbms_random.string('P',20) from dual;          --第一个参数 P 表示 printable,即字符串由任意可打印字符构成          第二个参数表示返回字符串长度

--4、ceil( n )函数是返回大于或等于n的最小整数。
/*
DBMS_RANDOM.VALUE()是随机产生( 0,1 )之间的数。要产生两位的随机数,可以DBMS_RANDOM.VALUE()*100,这样产生( 0,100 )的随机数,当产生( 0,10)之间的数时,只要加上10就可以保证产生的数都是两位了。
*/
--ORACLE的PL/SQL提供了生成随机数和随机字符串的多种方式,罗列如下:
--1、小数( 0 ~ 1)
     select dbms_random.value from dual;
--2、指定范围内的小数 ( 0 ~ 100 )      
	select dbms_random.value(0,100) from dual
--3、指定范围内的整数 ( 0 ~ 100 )
     select trunc(dbms_random.value(0,100)) from dual
--4、长度为20的随机数字串
     select substr(cast(dbms_random.value as varchar2(38)),3,20) from dual
--5、正态分布的随机数
     select dbms_random.normal from dual
--6、随机字符串
     select dbms_random.string(opt, length) from dual
      --opt可取值如下:       'u','U'    :    大写字母       'l','L'    :    小写字母       'a','A'    :    大、小写字母       'x','X'    :    数字、大写字母       'p','P'    :    可打印字符
--7、随机日期
     select to_date(2454084+TRUNC(DBMS_RANDOM.VALUE(0,365)),'J') from dual
     通过下面的语句获得指定日期的基数
     select to_char(sysdate,'J') from dual
--8、生成GUID
     select sys_guid() from dual
--生成带分隔符(-)的GUID的自定义函数 
	create or replace function my_guid return varchar2 is     guid varchar(36);     temp varchar(32); begin     temp:=sys_guid();     guid:= substr(temp,1,8) || '-'          ||substr(temp,9,4) || '-'          ||substr(temp,13,4)|| '-'          ||substr(temp,17,4)|| '-'          ||substr(temp,21,12);     return guid; end;

11.2 数据库导入,导出

exp 导出 imp 导入 (EXP和IMP是客户端工具程序,它们既可以在客户端使用,也可以在服务端使用。EXP不会导出空表,可能会对存储过程有影响)

1.导出:exp sdt_imoa/sdt_imoa@192.168.10.228/yjdb2 file=d:\sdt_imoa_20180831.dmp   tables=(ydxj_dundian_%)   rows=n
    说明:	1.sdt_imoa/sdt_imoa  是用户名和密码   
           2.@192.168.10.228/yjdb2  对应连接数据库时的路径192.168.10.229:1521/yjdb
           3.tables=(BAS_TOWER_%,BAS_FROMPART_TYPE,BAS_TYPEFROM_REF)  指定导出表,支持模糊匹配
           4.rows=n 表示只要表结构,不要数据
    案例:将数据库中system用户与sys用户的表导出
   		exp system/manager@TEST file=d:\daochu.dmp owner=(system,sys)
   	案例:将数据库中的表table1中的字段filed1以"00"打头的数据导出
   		exp system/manager@TEST file=d:\daochu.dmp tables=(table1) query=\" where filed1 like '00%'\"
2.导入: imp sdt_tyxxpt/sdt_tyxxpt@61.191.56.150:1521/xjb  file=f:\sdt_imoa2018-08-31.dmp full=y  data_only=y full=y log=E:\20191127.log;
    说明:1.rows=n 只导表结构
         2.data_only=y 只导数据
         3.ignore=y只导入数据,不导入表结构(没有的表,创建并倒入数据,如果已经有的表,忽略创建的,但不忽略倒入)
         4. 日志输出 log
     案例: 将d:\daochu.dmp中的表table1 导入
 		imp system/manager@TEST  file=d:\daochu.dmp  tables=(table1)
	如果导入的表空间不同,导入数据会报错,那么可以先只导入表结构,然后通过imp  导入表数据
3.指定表空间导入,没测试过(针对全数据库导出,先需要导出特定的用户,fromuser=用户)
imp CPMS_INVO/CPMS_INVO@36.7.176.72:11521/xjb fromuser=invoice touser=CPMS_INVO  file=E:\invo_20191127.dmp  log=E:\20191127.log
fromuser指定dmp文件中要导出的用户,touser 准备导入表的 数据用户 

存在问题 EXP不会导出空表,可能会对存储过程有影响 https://www.2cto.com/database/201703/615378.htmlopen in new windowhttps://blog.csdn.net/whxlovexue/article/details/82378389open in new window

--1.在建好数据库后执行如下脚本:
	alter system set deferred_segment_creation=false;
--2:批量执行空表更新语句
    --A: 查询当前用户下的所有记录数为空的表
    select TABLE_NAME from user_tables t where t.NUM_ROWS = 0 or t.NUM_ROWS is null;
    --B:生成修改语句,将SEGMENT_CREATED 修改为YES
    select 'alter table '||table_name||' allocate extent;' from user_tables t where t.NUM_ROWS = 0 or t.NUM_ROWS is null;
--参考网址:https://blog.csdn.net/whxlovexue/article/details/82378389

imp/impdp 和 EXPDP和IMPDP时应该注意的事项:

  • EXP和IMP是客户端工具程序,它们既可以在客户端使用,也可以在服务端使用。
  • EXPDP和IMPDP是服务端的工具程序,他们只能在ORACLE服务端使用,不能在客户端使用。
  • IMP只适用于EXP导出的文件,不适用于EXPDP导出文件;IMPDP只适用于EXPDP导出的文件,而不适用于EXP导出文件。

expdp/impdp导出/导入数据 https://www.cnblogs.com/wanghongyun/p/6307652.htmlopen in new window

使用impdp命令,需要在oracle数据库服务器操作:
1.使用sqlplus或者Oracle客户端(PL/SQL) 链接到相应的Oracle数据库实例(进行下面第一,第二两步骤的操作)
    一、创建逻辑目录,该命令不会在操作系统创建真正的目录,最好以system等管理员创建。
    	创建:create directory dpdata1 as 'd:\temp';
    	修改:create or replace directory dpdata1 as 'E:\temp';
		删除:drop directory dpdata1;
    (查看服务器上若没有存在d:\temp目录,则手动新建,把dmp备份文件放到d:\temp目录下面)
    二、查看管理理员目录(同时查看操作系统是否存在,因为Oracle并不关心该目录是否存在,如果不存在,则出错)
    	select * from dba_directories;
2.导入数据库
--expdp导出数据
	expdp CCENSE/CCENSE@OracleDB directory = "dpdata1" dumpfile ="oracleExpdp.dmp" logfile = oracleExpdp20161103.log
--impdp导入数据
	impdp CCENSE/CCENSE@OracleDB directory="dpdata1" dumpfile="oracleExpdp.dmp" logfile = oracleImpdp20161103.log FULL=y;

/* 说明:CCENSE/CCENSE@OracleDB --->用户名/密码@数据库实例
        directory="在步骤一中创建的逻辑目录"
        dumpfile="需要导入/导出的dmp文件全称"
        logfile="日志文件"
        FULL=y;
*/
impdp CPMS_0309/CPMS_0309@127.0.0.1:1521/orcl directory = dpdata1 dumpfile =CPMS_0309.dmp logfile = CPMS_0309.log REMAP_SCHEMA=CPMS:CPMS_0309 remap_tablespace=CPMS:CPMS_0309
--  讲CPMS正式数据库的表导入到 CPMS_0309用户下,impdp可以指定 需要导入的表空间和用户
	REMAP_SCHEMA=CPMS:CPMS_0309 表示 由原来的 CPMS用户导入到CPMS_0309用户下,   remap_tablespace=CPMS:CPMS_0309表示 由原来的CPMS表空间导入到CPMS_0309表空间下

--其他SQL
--表空间[10G]和临时表空间[1G]
/*表空间*/
	SELECT t.tablespace_name, round(SUM(bytes / (1024 * 1024)), 0) ts_size 
	FROM dba_tablespaces t, dba_data_files d 
	WHERE t.tablespace_name = d.tablespace_name 
	GROUP BY t.tablespace_name;

/*临时表空间*/
	select tablespace_name,file_name,bytes/1024/1024 file_size,autoextensible from dba_temp_files;

-- 查看端口是否被占用
	netstat -aon|findstr "1522"

-- 查看监听状态,启动监听,关闭监听
	lsnrctl status LISTENER2
	lsnrctl start LISTENER2 
	lsnrctl stop LISTENER2

--访问地址
	linux sqlplus ccense/ccense@//localhost:1521/OracleDB;
	win sqlplus ccense/ccense@IP:1521/OracleDB;

11.52 数据库备份单个表

关键字 复制表、备份表

create table myTable_tmpe as select * from myTable ;
create table myTable_tmpe as select * from myTable  where 1=2;-- 只备份表结构,不复制表数据
create table sys_emp_1 as  select * from sys_emp@xjbdblink;-- 使用dblink	

11.53 oracle 函数

  • replace 替换
select replace('123123tech', '123') from dual; --返回 'tech'============将 字符串 123123tech中123 去掉  最终结果是tech
select replace('123tech123', '123') from dual; --返回 'tech'
select replace('222tech', '2', '3') from dual; --返回 '333tech'============将字符串 222tech  中的2 替换为 3 最终结果是 333tech
select replace('0000123', '0') from dual; --返回 '123'
select replace('0000123', '0', ' ') from dual; --返回 ' 123'
  • 分支

  • ceil() /ceiling() 向上取整

     ceil(1.2) = 2
    
  • floor () 向下取整

     floor(1.2) = 1
    
  • round() 四舍五入

11.54 开窗函数,排序取最新

【Oracle】OVER(PARTITION BY)函数用法open in new window 开窗函数 https://www.cnblogs.com/ruiser/p/5687238.htmlopen in new window

Oracle从8.1.6开始提供分析函数

11.55 取分组取第一条记录(关键字:取最新,取第一条数据,取最后一条)

最优方法:
 select *
          from (select USERID,
                       JD_GPS,
                       WD_GPS,
                       dwsj,
                       row_number() over(partition by USERID order by dwsj desc) mm
                  from ydxj_dw_dwjl_2016)
         where mm = 1 // 要排过序后 才能 取第一条,不能直接就用rownum = 1    这样取出的数据,和没排序的一样
方法2
select a.*
  from ydxj_dw_dwjl_2016 a
 where not exists (select 1
          from ydxj_dw_dwjl_2016 b
         where b.userid = a.userid             
           and b.dwsj > a.dwsj)

11.60 列转行

日期行转列

SELECT TO_DATE('2021-05-01', 'YYYY-MM-DD') + ROWNUM - 1 DT FROM DUAL
          CONNECT BY LEVEL <= (TO_DATE('2021-05-31', 'YYYY-MM-DD') - TO_DATE('2021-05-01', 'YYYY-MM-DD') + 1)

指定字符串 分割,转行

SELECT  REGEXP_SUBSTR('1,2,3', '[^,]+', 1, LEVEL) NAME
FROM dual
CONNECT BY LEVEL <= REGEXP_COUNT('1,2,3', '[^,]+')

案例:

工作票接地线表每个 条记录 多个接地线直接用逗号相连,现在要获取 当前工作票 选用的所以的接地线 思路:先讲数据行转列,然后再列转行,使用in

image-20210602194206941
image-20210602194206941
-- 先将 指定 工作票的接地线全部查询出来,然后逗号相连
with jdx_use_temp as
 (select wm_concat(t.groundwire_no) jdx_code
    from PLAN_WORK_TICKET_GROUNDWIRE t
   where del_flag = 0
     and ticket_id = 'd439b3cd225c4667a550f172844a397a')
select *
  from jdx_device t
 where t.code in
       (SELECT REGEXP_SUBSTR(jdx_code, '[^,]+', 1, LEVEL) NAME  -- 列转行,使用in
          FROM jdx_use_temp
        CONNECT BY LEVEL <= REGEXP_COUNT(jdx_code, '[^,]+'))

使用< foreach collection="lineIds.split(',')" item="lineId" index="index" separator=", "> 目前最优,对数据格式没有过多要求

 <select id="findLineByIds" resultMap="lineVOMap">
        select t.id,
           t.tower_pmsid,
           t.line_id,
           t.tower_name,
           t.tower_no,
           l.line_name
      from BAS_C_TOWER t,bas_c_line l
      where t.line_id=l.id
          <if test="lineIds != null and lineIds != ''">
            AND t.LINE_ID in (
              <foreach collection="lineIds.split(',')" item="lineId" index="index" separator=", ">
                    #{lineId}
                </foreach>
            )
        </if>
        <if test="towerIds != null and towerIds != ''">
            AND t.LINE_ID in (
                select distinct line_id from bas_c_tower where id in (
                    <foreach collection="towerIds.split(',')" item="towerId" index="index" separator=", ">
                        #{towerId}
                    </foreach>
                 )
            )
        </if>
        order by  t.line_id, t.tower_no
    </select>

11.61 行转列

  • wm_concat 实现行转列(存在限定,拼接超过4000后异常)
select t.office_id,
       wm_concat(t.area_id) areaIds, --replace(wm_concat(area_id),',','|')  通过 replace替换成需要的连接字符串
       wm_concat(to_char(a.name)) as areaNames-- 对于中文可能会出现 转义
  from ZHCG_OFFICE_MANAGE_AREA t, sys_area a
 where t.del_flag = '0'
   and a.del_flag = '0'
   and t.area_id = a.id
 group by office_id
  • xmlagg

wm_concat ---函数实现字段合并 将返回的多条数据,,合并到一起,行转列,但是存在一个问题,拼接超过4000后异常

1.select XMLAGG(XMLELEMENT(E, name || ',')).EXTRACT('//text()').getclobval() as names from sys_user 但是好像不能使用分组函数

  1. xmlagg(xmlparse(content 拼接字段 || ','wellformed) order by 排序字段).getclobval()

案例:

SELECT rtrim(xmlagg(xmlparse(content u.emp_name || ',' wellformed) ) .getclobval(), ',') userNames,

rtrim(xmlagg(xmlparse(content p.emp_id || ',' wellformed) ) .getclobval(), ',') userIds,

​ p.RULE_ID

from PROJ_BASE_ATTENDANCE_PERSON p

left join sys_emp u on u.id=p.emp_id

group by p.RULE_ID

注: rtrim(字段, ',') 去掉右边最后一个逗号

通过xmlagg讲数据转为clob ,也会存在字符缓存去

限定长度

dbms_lob.substr( substr(rtrim(xmlagg(xmlparse(content a.idopen in new window || ',' wellformed)) .getclobval(),',') ,0,200))

  • 使用REGEXP_SUBSTR
--1.
SELECT REGEXP_SUBSTR ('1,2,3', '[^,]+', 1,rownum)
from dual connect by rownum<=LENGTH ('1,2,3') - LENGTH (regexp_replace('1,2,3', ',', ''))+1;


-- 2.
select REGEXP_SUBSTR(t.rolecode, '[^,]+', 1, l) type
  from (select '1,2' rolecode from dual) t,
       (SELECT LEVEL l FROM DUAL CONNECT BY LEVEL <= 100) b
 WHERE l <= LENGTH(t.rolecode) - LENGTH(REPLACE(rolecode, ',')) + 1

案例场景: 前端传递一个逗号拼接的字符串,sql中需要用in

 select pe.emp_id from SYS_EMP_POST_EMP pe 
 where pe.position_id in (
         SELECT REGEXP_SUBSTR (${positionIds}, '[^,]+', 1,rownum)
		   from dual connect by rownum <![CDATA[ <= ]]> LENGTH (${positionIds}) - LENGTH (regexp_replace(${positionIds}, ',', ''))+1
 	)   
 	
 	
--'26438E087E604071886C69BC39B8A176,4358B8B6E93F4119847FF73766B72733'

11.65 ORACLE WITH AS 用法

ORACLE WITH AS 用法open in new window

with as优点 (相当于 创建一个临时表,然后后面可以直接调用 ) 增加了sql的易读性,如果构造了多个子查询,结构会更清晰; 更重要的是:“一次分析,多次使用”,这也是为什么会提供性能的地方,达到了“少读”的目标;

with e as (select * from scott.emp e where e.empno=7499)-- 相当于创建一个临时表
select * from e;


with
     e as (select * from scott.emp),
     d as (select * from scott.dept)
select * from e, d where e.deptno = d.deptno;

11.70 resultMap

resultMap可以实现将查询结果映射为复杂类型的pojo,比如在查询结果映射对象中包括pojo和list实现一对一查询和一对多查询

<resultMap type="cn.semdo.modules.projjl.entity.ProjJlEngineer" id="projJlEngineerMap">  
    <id column="ID" property="id"/>  
    <id column="engineerName" property="engineerName"/>  

    <collection property="projJlPositionList" ofType="cn.semdo.modules.projjl.entity.ProjJlPosition" column="engineerId">  
        <id column="positionId" property="id"/>  
        <id column="engineerId" property="engineerId"/>
        <id column="positionName" property="name"/>

    </collection>  
</resultMap>


<select id="projJlEngineerList" resultMap="projJlEngineerMap">
    SELECT 
    a.id,
    a.engineer_Name as engineerName,
    p.id AS "positionId",
    p.engineer_id AS "engineerId",
    p.name AS "positionName"
    FROM proj_jl_engineer a 
    left join PROJ_JL_POSITION p on p.engineer_id = a.id
</select>
<!--column不做限制,可以为任意表的字段,而property须为type 定义的pojo属性-->
<resultMap id="唯一的标识" type="映射的pojo对象">
  <id column="表的主键字段,或者可以为查询语句中的别名字段" jdbcType="字段类型" property="映射pojo对象的主键属性" />
  <result column="表的一个字段(可以为任意表的一个字段)" jdbcType="字段类型" property="映射到pojo对象的一个属性(须为type定义的pojo对象中的一个属性)"/>
  <association property="pojo的一个对象属性" javaType="pojo关联的pojo对象">
    <id column="关联pojo对象对应表的主键字段" jdbcType="字段类型" property="关联pojo对象的主席属性"/>
    <result  column="任意表的字段" jdbcType="字段类型" property="关联pojo对象的属性"/>
  </association>
  <!-- 集合中的property须为oftype定义的pojo对象的属性-->
  <collection property="pojo的集合属性" ofType="集合中的pojo对象">
    <id column="集合中pojo对象对应的表的主键字段" jdbcType="字段类型" property="集合中pojo对象的主键属性" />
    <result column="可以为任意表的字段" jdbcType="字段类型" property="集合中的pojo对象的属性" />  
  </collection>
</resultMap>

11.80 特殊字符

  • 大于、小于 <![CDATA[ <= ]]>

11.81 oracle 查询记录为空,返回默认值 --- 在创建任务单单号的时候的应用

场景: 查询时 如果查询到那么就用查询的结果,如果查询不到,那么就给定一个默认值

分2中情况

1.可能不存在返回值 ,即一条数据都没有:

案例 表 dsj_line_tower_relation 存放 线路表存在的线路和 GT表中实际的线路

select nvl(MAX(t.tower_line_id),'bf3c8dd107a04d918a1d7f59365ccc26') from dsj_line_tower_relation  t where line_id='bf3c8dd107a04d918a1d7f59365ccc26' --(使用max一定会有返回值,这样搭配 nvl 就可以实现返回值一定有结果)

传递我们指定的线路id,如果在****dsj_line_tower_relation**** 表中存在记录,那么就用查询的tower_line_id 否则,我们就返回我们传递的参数

img
img

查询时没有任何返回值,那么时不能用nvl() 来实现上面的效果

  1. 一定存在返回值,但是可能存在为空 select nvl(t.line_id,0) from ..................
img
img

11.90 存储过程

场景:每天根据 V_USER_WEIPAI 表(存放设备主人,GT,设备id,应该巡视次数)

https://blog.csdn.net/dwenxue/article/details/82257944open in new window 创建存储过程(带参数)

https://blog.csdn.net/qq_38974634/article/details/81141845open in new window

create or replace procedure PROC_WEIPAI_OP_EVERY_DAY as
 --以机代巡中 设备巡视 每天统计
    v_op_num NUMBER(10); -- 每天对应的 设备应拍次数(设置变量,下文中 会用到上面的查询结果)
    begin
      select nvl(max(OP_NUM), 3) into v_op_num from YDXJ_JOB_OP_NUM where trunc(OP_TIME) = trunc(SYSDATE); -- 每天对应的 设备应拍次数  赋值 (nvl(max(OP_NUM),0) 保证一定有值)
      DELETE FROM YDXJ_WEIPAI_OP_COUNT_DAY WHERE trunc(OP_TIME) = trunc(SYSDATE); -- 删除今天数据,防止 数据重复添加
      insert into ydxj_weipai_op_count_day (user_id, weipai_id, tower_id, op_time, should_op_num, op_num)
       select a.userid, a.WEIPAIRECORD_ID, a.tower_id, sysdate,
             v_op_num, -- 每个设备 应该巡视次数 (是上面语句中查询出来的数值)
             nvl(op_.op_num,0) --每个设备 实际巡视次数
        from V_USER_WEIPAI a
        left join (select count(op.opid) as op_num, WEIPAIRECORD_ID,op.OPUSERID---讲数据分组后 left join 会提高查询速度
                     from ydxj_job_op op
                    where trunc(OPTIME) = trunc(SYSDATE)
                      and op.WEIPAIRECORD_ID is not null
                    group by WEIPAIRECORD_ID,op.OPUSERID) op_
          on a.WEIPAIRECORD_ID = op_.WEIPAIRECORD_ID and op_.OPUSERID=a.userid;
      Commit;
    exception
  when others then
    raise;
    rollback;
end;

创建 能传递参数的 存储过程

 
create or replace procedure test_page(
    page_start in int,page_end in int,page_count out int,
    page_emps out sys_refcursor)
as
begin
    select count(*) into page_count from employees;    
    open page_emps for
        select * from 
               (select rownum rn,e.* from employees e
                 where rownum <= page_end)
        where rn >= page_start;
end test_page;      
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
 PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
 "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.lxj.mapper.EmployeeMapper">
 
	<select id="getEmpById" resultType="com.lxj.bean.Employee">
		select EMPLOYEE_ID id,LAST_NAME lastName,EMAIL email from employees 
        where EMPLOYEE_ID = #{id}
	</select>
	
	<!--  public void getEmpsByPage(); 
	      statementType="CALLABLE":调用存储过程,默认是PREPARED
			call 不能丢,否则识别不出
	-->
	<select id="getEmpsByPage" statementType="CALLABLE">
	    {call test_page(
	        #{start,mode=IN,jdbcType=INTEGER},
	        #{end,mode=IN,jdbcType=INTEGER},
	        #{count,mode=OUT,jdbcType=INTEGER},
	        #{emps,mode=OUT,jdbcType=CURSOR,javaType=ResultSet,resultMap=TestPge}
	    )}
	</select>
	<resultMap type="com.lxj.bean.Employee" id="TestPge">
	   <id column="EMPLOYEE_ID" property="id"/>
	   <result column="LAST_NAME" property="lastName"/>
	   <result column="EMAIL" property="email"/>
	</resultMap>
</mapper>

11.91 数据库定时器

https://blog.csdn.net/u012209894/article/details/80432102open in new window

image-20210107084208506
image-20210107084208506

查询数据库中的dblink select * from dba_db_links;

--使用:比如协同办公需要移动巡检中的线路表(bas_c_linedsa) sdt_tyxxpt.bas_c_line@SDT_TYXXPT_DBLINK
 create database link SDT_TYXXPT_DBLINK
  connect to sdt_tyxxpt identified by sdt_tyxxpt
     using '(DESCRIPTION =
      (ADDRESS_LIST =
       (ADDRESS = (PROTOCOL = TCP)(HOST = 192.168.10.225)(PORT = 1521))
      )
      (CONNECT_DATA =
       (SERVER = DEDICATED)
        (SID = yjdb2)
      )
    )';  
 create database link SDT_TYXXPT_DBLINK
  connect to sdt_tyxxpt identified by sdt_tyxxpt
     using '218.23.109.123:9522/yjdb'; 

19.110 oracle 自定义函数

参考https://blog.csdn.net/jumtre/article/details/38092067open in new window

--第一种不带参数:
create or replace function get_user 
return varchar2 is Result varchar2(50); --定义变量(返回值)
begin 
select username into Result from user_users; --into 赋值,不要忘了加分号结尾
return(Result); --返回值
end get_user;

--第二种带参:
create or replace function get_sal(empname in varchar2) 
return numbe is Result number; 
begin 
select sal into Result from emp where ename=empname; 
return(Result); 
end;

自定义函数验证是否为数字
https://blog.csdn.net/vincentlee_/article/details/15336557open in new window

CREATE OR REPLACE FUNCTION isnumeric(str IN VARCHAR2)
    RETURN NUMBER
IS
    v_str FLOAT;
BEGIN
    IF str IS NULL
    THEN
       RETURN 0;
    ELSE
       BEGIN
          SELECT TO_NUMBER (str)
            INTO v_str
            FROM DUAL;
       EXCEPTION	--异常
          WHEN INVALID_NUMBER
          THEN
             RETURN 0;
       END;
       RETURN 1;
    END IF;
END isnumeric;

经纬度距离计算

CREATE OR REPLACE FUNCTION F_DISTANCE (cx in number,cy in number,sx in number, sy in number) 
RETURN NUMBER
is
    d number;
    x number;
    y number;
    r number;
    pi number;
begin
  r:=6371229;--地球半径
  pi:=3.14159265358979323;--圆周率
  x:=(sx-cx)*pi*r*cos((sy+cy)/2*pi/180)/180;
  y:=(sy-cy)*pi*r/180;
  d:=SQRT(power(x,2)+power(y,2));
  D:=ROUND(D,2);
  RETURN d;
end ;

11.120 查询指定用户 表名+数据量+表备注

SELECT t.table_name, t.num_rows, f.comments 
FROM all_tables t
  INNER JOIN ( SELECT * FROM all_tab_comments WHERE OWNER = 'CPMS_DEV' ) f ON t.table_name = f.table_name 
WHERE t.OWNER = 'CPMS_DEV'

11.200

between xx and yy ;

11.210 oracle 对时间的处理

1. trunc

select trunc(sysdate,'HH24')-1/24  from dual; -- 当前时间前一个小时 并且小时取整 2021/4/30 13:00:00

日期行转列

SELECT TO_DATE('2021-05-01', 'YYYY-MM-DD') + ROWNUM - 1 DT FROM DUAL
          CONNECT BY LEVEL <= (TO_DATE('2021-05-31', 'YYYY-MM-DD') - TO_DATE('2021-05-01', 'YYYY-MM-DD') + 1)

12. MySql

注: java 程序配置 MySql数据库时需要注意

因为在mysql5中,jdbc的驱动是com.mysql.jdbc.Driver,
而mysql6以及以上是com.mysql.cj.jdbc.Driver

navicat使用open in new window

12.1 基本使用

  • cmd登陆:mysql -h 192.168.10.229 -p 9060 -uroot -pSemdo@123

    查看数据库的语句是SHOW DATABASES,查看数据库语法格式是:

SHOW DATABASES [LIKE '数据库名'];

mysql> SHOW DATABASES LIKE '%test%';
  • 创建用户
CREATE USER 'lishihuan'@'172.16.10.229' IDENTIFIED BY '123456';
  • 授权

  • 删除用户

 DROP USER 'lishihuan'@'172.16.10.229';
  • 查询建表语句
SHOW CREATE TABLE table_name;
  • 查询字段 属性
desc table_name;
  • 切换数据库
use sdt_xjb;
  • 删除表:DROP TABLE my_table;

  • 删除数据(分场景,如果全删,用 truncate)

    • 删除整表数据 truncate table my_table;
    • 删除部分数据delete from my_table where id='1';
  • 查询进程

show processlist;

12.20 内置函数

2.GREATEST()函数返回输入参数最大值

-- 查询'zt_time' , 'zy_time' , 'zn_time'中最大一个
SELECT
	GREATEST(zt_time, zy_time, zn_time)
FROM
	'XXX'

limit 取前多少条数据

 select * from dw.dwd_sdxs_job_op  limit  100;

空间函数,计算 坐标距离 (米)

计算地球两点之间的球面距离,单位为 米。传入的参数分别为X点的经度,X点的纬度,Y点的经度,Y点的纬度。

select st_distance_sphere(116.35620117, 39.939093, 116.4274406433, 39.9020987219);

12.30 创建函数

set global log_bin_trust_function_creators=1;

如果创建的是带参 函数,需要给参数指定 类型同时指定大小,否则会报下面的错误

1064 - You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ')

CREATE DEFINER = CURRENT_USER FUNCTION `simpleFun`(name VARCHAR(20))
	RETURNS varchar(30)
BEGIN
	#Routine body goes here...
	RETURN name;
END;

声明参数

drop function if exists hello;
-- a、b 都是函数的参数
create function hello(a varchar(20),b varchar(20)) returns varchar (255)
begin
    
    -- declare 声明参数,default:设置声明参数的默认值
    declare x varchar(255) default ' x  ';
    declare y varchar(255) default b;
    declare c varchar(255) default ' 2017-01-02  ';
    declare d varchar(255);
    -- set 给声明的参数赋值
    SET d = concat(x,a,b,y,c);
    return d;
end;

12.40 定义变量

# 定义变量
set @dt = now();
select date_add(@dt, interval 1 day); -- add 1 day
select date_add(@dt, interval 1 hour); -- add 1 hour


# 赋值
set @:= 1;
select @dt:= @dt+3; 
SELECT  @dt:=5;

12.50 with as (创建临时表)

如果查询 报没有登陆数据库,可以通过 use DATABASES; 相当于先登陆一个数据库,创建的临时表就在 这个数据库下

with ydxj_ttsh_temp as -- ydxj_ttsh_temp 相当于一张临时表
(select t.line1_tower_id
    from sdt_xjb.ydxj_ttsh t
 )
select * from ydxj_ttsh_temp;
  • 需要定义多个 临时表,可有用逗号相连, with xx as () , yy as ()
with temp1 as -- ydxj_ttsh_temp 相当于一张临时表
(select t.line1_tower_id
    from table_name1 t
 ), temp2 as (
 	select * from table_name2
 )
select * from temp1 p1
left join temp2 p2 on p1.id=p2.id;

12.60 组内排序

场景:要求显示每个部门年龄第二大的人

第一步,分组;第二步,组内按照年龄排序;第三步,组内排序后的数据加上序号

SELECT rownum, id, NAME, age, deptId, empno 
FROM
	(SELECT
		(@i := #变量Qi的值,同一个部门内累加,部门变化则从0开始计数
		CASE WHEN @deptId = deptId # 判断deptId是否发生变化
			THEN @i + 1 #没有发生变化则将排序加1
			ELSE 1 #发生变化则从1开始重新排序
		END) rownum,t_emp.*,
	( @deptId := deptId ) #将当前数据的部门号赋值给变量@deptId,即读取当前部门]的deptId号
	
FROM t_emp,
	( SELECT @i := 0) AS a #定义变量并赋初值
	
GROUP BY deptId, id 
ORDER BY deptId, age DESC # 年龄降序排列
) tb 
 WHERE rownum = 2 #年龄第几大,该处就写几

12.70 数据拉平,每条记录的上一条记录

查找每条巡视记录的上一次同类型的巡视

select op.opid,op.optime ,bb.pre_optime
from sdt_xjb.ydxj_job_op op
LEFT JOIN (
	SELECT aa.major, aa.opobjid, aa.op_type, aa.optime,max(bb.optime) as pre_optime FROM 
	sdt_xjb.ydxj_job_op aa 
	left join sdt_xjb.ydxj_job_op bb ON bb.major = aa.major 
		AND bb.opobjid = aa.opobjid -- 找到当前每条记录的 前一条 巡视记录
		AND bb.op_type = aa.op_type 
		AND bb.optime < aa.optime 
	group by aa.major, aa.opobjid, aa.op_type, aa.optime 
	) bb on  bb.major=op.major and bb.opobjid=op.opobjid   and   bb.optime= op.optime
use sdt_xjb;
with act_hi_actinst_temp as (  -- 创建临时表
	select ht.id_,ht.proc_inst_id_,ht.task_id_,act_id_,ht.act_name_,ht.start_time_,ht.end_time_,ht.duration_,ht.act_type_,
	ROW_NUMBER() over(partition by ht.proc_inst_id_ order by ht.start_time_ ) as order_num 
	from 		sdt_xjb.act_hi_actinst ht 
	where
		ht.act_type_ != 'exclusivegateway' 
		and ht.proc_inst_id_ in (
			select distinct t.proc_inst_id_
          from sdt_xjb.act_hi_actinst t
         where t.proc_def_id_ like '%record_upgrades%'
           and t.act_type_ != 'exclusivegateway'
           and  (date_format(t.start_time_, '%y-%m') = date_format(now(), '%y-%m')  or date_format(t.end_time_, '%y-%m') = date_format(now(), '%y-%m'))
		) 
)
select 
	t1.id_ as id,
	qx.id as record_id,-- 对应的缺陷id
	t1.order_num,
	t1.proc_inst_id_ as proc_inst_id ,    
	t1.act_type_ as node_type,
	t1.act_name_  as curr_node_name,-- 当前节点名称
	t2.act_name_ as next_node_name, -- 下个节点名称
	hd.userId as user_id,         
	hd.userName as user_name,       
	t1.start_time_,     
	t1.end_time_,       
	t1.duration_,       
	hd.remark as remark
from act_hi_actinst_temp t1
left join act_hi_actinst_temp t2 on t1.proc_inst_id_=t2.proc_inst_id_ and t1.order_num=t2.order_num-1  -- 自己关联自己,获取每步的下个节点
inner join sdt_xjb.ydxj_danger_record qx on qx.proc_ins_id=t1.proc_inst_id_
-- 查审批过程 执行人和 备注
left join (select t.act_inst_id_,
				max(case when t.name_='userId' then t.text_ else '' end) as userId,
				max(case when t.name_='current' then t.text_ else '' end) as userName,
				max(case when t.name_='remark' then t.text_ else '' end)  as remark
				from sdt_xjb.act_hi_detail t 
				group by t.act_inst_id_) hd
on hd.act_inst_id_=t1.id_

12.80 组内排序 开窗函数

-- 下例展示了按照property列分组对x列排名:
select x, y, dense_rank() over(partition by x order by y) as rank from int_t;

在MYSQL的最新版本MYSQL8已经支持了排名函数RANKDENSE_RANKROW_NUMBER。但是在就得版本中还不支持这些函数,只能自己实现。实现方法主要用到了条件判断语句(CASE WHENIF)和添加临时变量。

1. 排名分类

1.1 区别RANK,DENSE_RANK和ROW_NUMBER
  • RANK并列跳跃排名,并列即相同的值,相同的值保留重复名次,遇到下一个不同值时,跳跃到总共的排名。
  • DENSE_RANK并列连续排序,并列即相同的值,相同的值保留重复名次,遇到下一个不同值时,依然按照连续数字排名。
  • ROW_NUMBER连续排名,即使相同的值,依旧按照连续数字进行排名。

区别如图:

image-20210224090835726
image-20210224090835726
1.2 分组排名

将数据分组后排名,区别如图:

image-20210224090939521
image-20210224090939521

2. 准备数据

创建一张分数表,里面有字段:分数score,课程号course_id和学生号student_id。 执行如下SQL语句,进行导入数据。

create table score(
  student_id varchar(10),
  course_id varchar(10),
  score decimal(18,1)
);

insert into score values('01' , '01' , 80);
insert into score values('01' , '02' , 90);
insert into score values('01' , '03' , 99);
insert into score values('02' , '01' , 70);
insert into score values('02' , '02' , 60);
insert into score values('02' , '03' , 80);
insert into score values('03' , '01' , 80);
insert into score values('03' , '02' , 80);
insert into score values('03' , '03' , 80);
insert into score values('04' , '01' , 50);
insert into score values('04' , '02' , 30);
insert into score values('04' , '03' , 20);
insert into score values('05' , '01' , 76);
insert into score values('05' , '02' , 87);
insert into score values('06' , '01' , 31);
insert into score values('06' , '03' , 34);
insert into score values('07' , '02' , 89);
insert into score values('07' , '03' , 98);
insert into score values('08' , '02' , 89);
insert into score values('09' , '02' , 89);

查看数据:

image-20210224091534272
image-20210224091534272

3. 不分组排名

3.1 连续排名
  1. 使用ROW_NUMBER实现:
SELECT score,
ROW_NUMBER() OVER (ORDER BY score DESC) ranking
FROM score;
123
  1. 使用变量实现:
SELECT s.score, (@cur_rank := @cur_rank + 1) ranking
FROM score s, (SELECT @cur_rank := 0) r
ORDER BY score DESC;
123

结果如图:

image-20210224091602071
image-20210224091602071
3.2 并列跳跃排名
  1. 使用RANK实现:
SELECT course_id, score,
RANK() OVER(ORDER BY score DESC)
FROM score;
123
  1. 使用变量IF语句实现:
SELECT s.score,
@rank_counter := @rank_counter + 1,
IF(@pre_score = s.score, @cur_rank, @cur_rank := @rank_counter) ranking,
@pre_score := s.score
FROM score s, (SELECT @cur_rank :=0, @pre_score := NULL, @rank_counter := 0) r
ORDER BY s.score DESC;
123456
  1. 使用变量CASE语句实现:
SELECT s.score,
@rank_counter := @rank_counter + 1,
(
  CASE
  WHEN @pre_score = s.score THEN @cur_rank
  WHEN @pre_score := s.score THEN @cur_rank := @rank_counter
  END
) ranking
FROM score s, (SELECT @cur_rank :=0, @pre_score := NULL, @rank_counter := 0) r
ORDER BY s.score DESC;
12345678910

结果如图:

image-20210224091638096
image-20210224091638096
3.3 并列连续排名
  1. 使用DENSE_RANK实现:
SELECT course_id, score,
DENSE_RANK() OVER(ORDER BY score DESC) FROM score;
12
  1. 使用变量IF语句实现:
SELECT s.score,
IF(@pre_score = s.score, @cur_rank, @cur_rank := @cur_rank + 1) ranking,
@pre_score := s.score
FROM score s, (SELECT @cur_rank :=0, @pre_score = NULL) r
ORDER BY s.score DESC;
12345
  1. 使用变量CASE语句实现:
SELECT s.score,
(
  CASE
  WHEN @pre_score = s.score THEN @cur_rank
  WHEN @pre_score := s.score THEN @cur_rank := @cur_rank + 1
  END
) ranking
FROM score s, (SELECT @cur_rank :=0, @pre_score = NULL) r
ORDER BY s.score DESC;
123456789

结果如图:

image-20210224091715704
image-20210224091715704

4. 分组排名

4.1 分组连续排名
  1. 使用ROW_NUMBER实现:
SELECT course_id, score,
ROW_NUMBER() OVER (PARTITION BY course_id ORDER BY score DESC) ranking FROM score;
12
  1. 使用变量IF语句实现:
SELECT s.course_id, s.score,
IF(@pre_course_id = s.course_id, @cur_rank := @cur_rank + 1, @cur_rank := 1) ranking,
@pre_course_id := s.course_id
FROM score s, (SELECT @cur_rank := 0, @pre_course_id := NULL) r
ORDER BY course_id, score DESC;
4.2 分组并列跳跃排名
  1. 使用RANK实现:
SELECT course_id, score,
RANK() OVER(PARTITION BY course_id ORDER BY score DESC)
FROM score;
123
  1. 使用变量IF语句实现:
SELECT s.course_id, s.score,
IF(@pre_course_id = s.course_id,
   @rank_counter := @rank_counter + 1,
   @rank_counter := 1) temp1,
IF(@pre_course_id = s.course_id,
   IF(@pre_score = s.score, @cur_rank, @cur_rank := @rank_counter),
   @cur_rank := 1) ranking,
@pre_score := s.score temp2,
@pre_course_id := s.course_id temp3
FROM score s, (SELECT @cur_rank := 0, @pre_course_id := NULL, @pre_score := NULL, @rank_counter := 1)r
ORDER BY s.course_id, s.score DESC;
4.3 分组并列连续排名
  1. 使用DENSE_RANK实现:
SELECT course_id, score,
DENSE_RANK() OVER(PARTITION BY course_id ORDER BY score DESC)
FROM score;
123
  1. 使用变量IF语句实现:
SELECT s.course_id, s.score,
IF(@pre_course_id = s.course_id,
   IF(@pre_score = s.score, @cur_rank, @cur_rank := @cur_rank + 1),
   @cur_rank := 1) ranking,
@pre_score := s.score,
@pre_course_id := s.course_id
FROM score s, (SELECT @cur_rank :=0, @pre_score = NULL, @pre_course_id := NULL) r
ORDER BY course_id, score DESC;
12345678

可以将上述的IF条件提取出来:

SELECT s.course_id, s.score,
IF(@pre_score = s.score, @cur_rank, @cur_rank := @cur_rank + 1) temp1,
@pre_score := s.score temp2,
IF(@pre_course_id = s.course_id, @cur_rank, @cur_rank := 1) ranking,
@pre_course_id := s.course_id
FROM score s, (SELECT @cur_rank :=0, @pre_score = NULL, @pre_course_id := NULL) r
ORDER BY course_id, score DESC;

12.90 mysql 对时间处理

获取当前时间

select curdate(); -- 2021-03-02
select now();  -- 2021-03-02 11:52:56
-- 查看当天日期
select current_date(); -- 2021-03-03

-- 查看当天时间
select current_time(); -- 11:08:16

-- 查看当天时间日期
select current_timestamp();-- 2021-03-03 11:08:42

返回日期在本年的第几天,范围为1到366。

SELECT DAYOFYEAR('2008-02-03'); # 34

SELECT DAYOFYEAR(now()); # 137

SELECT DAYOFYEAR(sysdate()); # 137

TIMESTAMPDIFF: MySql计算两日期时间之间相差的天数,秒数,分钟数,周数,小时数

语法为: TIMESTAMPDIFF(unit,datetime_expr1,datetime_expr2);

返回日期或日期时间表达式 datetime_expr1 和datetime_expr2the 之间的整数差。

其中unit单位有如下几种,分别是:FRAC_SECOND (microseconds), SECOND, MINUTE, HOUR, DAY, WEEK, MONTH, QUARTER, YEAR 。 该参数具体释义如下: FRAC_SECOND 表示间隔是毫秒 SECOND 秒 MINUTE 分钟 HOUR 小时 DAY 天 WEEK 星期 MONTH 月 QUARTER 季度 YEAR 年

例如:
#计算两日期之间相差多少周
select timestampdiff(week,'2011-09-30','2015-05-04');
#计算两日期之间相差多少天
select timestampdiff(day,'2011-09-30','2015-05-04');
另外计算两日期或时间之间相差多少天还可以使用 to_days 函数,但是该函数不用于阳历出现(1582)前的值,原因是当日历改变时,遗失的日期不会被考虑在内。因此对于1582 年之前的日期(或许在其它地区为下一年 ), 该函数的结果实不可靠的。具体用法如:
to_days(end_time) - to_days(start_time);
  
#计算两日期/时间之间相差的秒数:
select timestampdiff(SECOND,'2011-09-30','2015-05-04');
另外还可以使用 MySql 内置函数 UNIX_TIMESTAMP 实现,如下:
SELECT UNIX_TIMESTAMP(end_time) - UNIX_TIMESTAMP(start_time); 
  
#计算两日期/时间之间相差的时分数: 
select timestampdiff(MINUTE,'2011-09-30','2015-05-04');
另外还可以如下实现:
SELECT SEC_TO_TIME(UNIX_TIMESTAMP(end_time) - UNIX_TIMESTAMP(start_time));

  1. 相差多少天 可以使用 to_days 函数 to_days(end_time) - to_days(start_time);

    或者使用 DATEDIFF 函数:SELECT DATEDIFF('2020-01-13','2018-10-01');

  2. 相差的秒数 可以使用 UNIX_TIMESTAMP 函数:SELECT UNIX_TIMESTAMP(end_time) - UNIX_TIMESTAMP(start_time);

  3. 相差分支数 可以使用 SEC_TO_TIME 函数:SELECT SEC_TO_TIME(UNIX_TIMESTAMP(end_time) - UNIX_TIMESTAMP(start_time));

  4. now() 函数返回的是当前时间的年月日时分秒,如:2008-12-29 16:25:46;

  5. CURDATE() 函数返回的是年月日信息: 如:2018-6-17

  6. **CURTIME()**函数返回的是当前时间的时分秒信息,如:22:50

  7. 格式化时间:包含年月日时分秒日期格式化成年月日日期,可以使用DATE(time)函数,如DATE(now()) 返回的是 2018-6-17

    ​ 说明:需要格式化时间并且还要求不改变date格式的就可以用 select DATE('2021-02-12 00:00:00')

    ​ 如果时间格式字符串 date_format(now(), '%Y%m%d')

  8. unix_timestamp(日期,format) 把日期转化为时间戳 到秒的

  9. CURDATE() 获取的时间虽然和DATE(now()) 看起来一样,但实际值不一样。

案例

1.查看当天日期
select current_date();

2、 查看当天时间
select current_time();

3、查看当天时间日期
select current_timestamp();

4、查询当天记录
select * from 表名 where to_days(时间字段名) = to_days(now());

5、查询昨天记录
select * from 表名 where to_days( now( ) ) – to_days( 时间字段名) <= 1

6、查询7天的记录
select * from 表名 where date_sub(curdate(), interval 7 day) <= date(时间字段名) 

7、查询近30天的记录
select * from 表名 where date_sub(curdate(), interval 30 day) <= date(时间字段名)

8、查询本月的记录
select * from 表名 where date_format( 时间字段名, '%y%m' ) = date_format( curdate( ) , '%y%m' )

9、查询上一月的记录
select * from 表名 where period_diff( date_format( now( ) , '%y%m' ) , date_format( 时间字段名, '%y%m' ) ) =1

10、查询本季度数据
select * from 表名 where quarter(create_date)=quarter(now());

11、查询上季度数据
select * from 表名 where quarter(create_date)=quarter(date_sub(now(),interval 1 quarter));

12、查询本年数据
select * from 表名  where year(create_date)=year(now());

13、查询上年数据
select * from 表名 where year(create_date)=year(date_sub(now(),interval 1 year));

14、查询当前这周的数据
select * from 表名 where yearweek(date_format(submittime,'%y-%m-%d')) = yearweek(now());


15、查询上周的数据
select * from 表名 where yearweek(date_format(submittime,'%y-%m-%d')) = yearweek(now())-1;


16、查询当前月份的数据
select * from 表名   where date_format(submittime,'%y-%m')=date_format(now(),'%y-%m')

17、查询距离当前现在6个月的数据
select name,submittime from enterprise where submittime between date_sub(now(),interval 6 month) and now();

Mysql 获取昨日、今日、明日凌晨时间 ,本月第一天,今年第一天

https://blog.csdn.net/qq_40058321/article/details/102224125open in new window

# 获取今日凌晨时间
UNIX_TIMESTAMP(CAST(SYSDATE()AS DATE))
# 获取昨日凌晨时间
UNIX_TIMESTAMP(CAST(SYSDATE()AS DATE) - INTERVAL 1 DAY)
# 获取明日凌晨时间
UNIX_TIMESTAMP(CAST(SYSDATE()AS DATE) + INTERVAL 1 DAY)
# 获取的是时间戳
 
# 时间戳转换成datetime, datetime也就是我们说的日期格式 年-月-日 时-分-秒
FROM_UNIXTIME();
# datetime转时间戳
UNIX_TIMESTAMP();
 
# 测试
SELECT FROM_UNIXTIME(UNIX_TIMESTAMP(CAST(SYSDATE()AS DATE))) 今日;-- 2019-10-06 00:00:00
SELECT FROM_UNIXTIME(UNIX_TIMESTAMP(CAST(SYSDATE()AS DATE) - INTERVAL 1 DAY)) 昨日;-- 2019-10-05 00:00:00
SELECT FROM_UNIXTIME(UNIX_TIMESTAMP(CAST(SYSDATE()AS DATE) + INTERVAL 1 DAY)) 明日;-- 2019-10-07 00:00:00 

# 本月第一天
select DATE_ADD(curdate(),interval -day(curdate())+1 day)
-- 今年第一天
SELECT DATE_FORMAT(DATE_SUB(CURDATE(),INTERVAL dayofyear(now())-1 DAY),'%Y-%m-%d') AS c_year
-- 去年第一天
SELECT DATE_FORMAT((DATE_SUB((DATE_SUB(NOW(),INTERVAL dayofyear(now())-1 DAY)),INTERVAL 1 YEAR)),'%Y-%m-%d') AS last_year

格式化日期 DATE_FORMAT

# DATE_FORMAT(datetime ,format)用法,转换日期格式
DATE_FORMAT('2019-10-07 00:00:00', '%Y-%c-%d');-- 2019-10-07

 
# 常用的:
# '%Y-%c-%d %H:%i:%S'  
#  年-月-日  时:分:秒
# '%Y-%c-%d'
#  年-月-日
# '%H:%i:%S'
#  时:分:秒

可以使用的格式有:

格式描述
%a缩写星期名
%b缩写月名
%c月,数值
%D带有英文前缀的月中的天
%d月的天,数值(00-31)
%e月的天,数值(0-31)
%f微秒
%H小时 (00-23)
%h小时 (01-12)
%I小时 (01-12)
%i分钟,数值(00-59)
%j年的天 (001-366)
%k小时 (0-23)
%l小时 (1-12)
%M月名
%m月,数值(00-12)
%pAM 或 PM
%r时间,12-小时(hh:mm:ss AM 或 PM)
%S秒(00-59)
%s秒(00-59)
%T时间, 24-小时 (hh:mm:ss)
%U周 (00-53) 星期日是一周的第一天
%u周 (00-53) 星期一是一周的第一天
%V周 (01-53) 星期日是一周的第一天,与 %X 使用
%v周 (01-53) 星期一是一周的第一天,与 %x 使用
%W星期名
%w周的天 (0=星期日, 6=星期六)
%X年,其中的星期日是周的第一天,4 位,与 %V 使用
%x年,其中的星期一是周的第一天,4 位,与 %v 使用
%Y年,4 位
%y年,2 位

eg:

SELECT
  id,
  DATE_FORMAT(create_time, '%Y-%c-%d %H:%i:%S')
FROM epc_mes_item
WHERE create_time = '2018-11-19 23:00:20';

SELECT
  id,
  DATE_FORMAT(create_time, '%Y-%c-%e')
FROM epc_mes_item
WHERE DATE_FORMAT(create_time, '%Y-%c-%d') >= '2018-11-19';

date_add 、DATE_SUB 固定时间加 天,小时

  • date_add
select date_add(日期, interval 1 day); 日期加天

select date_add(日期, interval 1 hour); 日期加小时

select date_add(日期, interval 1 minute); 日期加分

select date_add(日期, interval 1 second);日期加秒

select date_add(日期, interval 1 microsecond); 日期加微秒

select date_add(日期, interval 1 week); 日期加周

select date_add(日期, interval 1 month); 日期加月

select date_add(日期, interval 1 quarter); 日期加季度

select date_add(日期, interval 1 year); 日期加年
  • DATE_SUB
SELECT * FROM 表名 WHERE 时间字段>DATE_SUB(CURDATE(), INTERVAL 1 YEAR) 一年
SELECT * FROM 表名 WHERE 时间字段>DATE_SUB(CURDATE(), INTERVAL 1 WEEK)  一周
SELECT * FROM 表名 WHERE 时间字段 >DATE_SUB(CURDATE(), INTERVAL 3 MONTH) 三个月
1、当前日期
select DATE_SUB(curdate(), INTERVAL 0 DAY) ;
 
2、明天日期
select DATE_SUB(curdate(), INTERVAL -1 DAY) ;
 
3、昨天日期
select DATE_SUB(curdate(), INTERVAL 1 DAY) ;
 
4、前一个小时时间
select date_sub(now(), interval 1 hour);
 
5、后一个小时时间
select date_sub(now(), interval -1 hour);
 
6、前30分钟时间
select date_add(now(), interval -30 minute)
 
7、后30分钟时间
select date_add(now(), interval 30 minute)

使用按理:

select a.record_date, -- 获取今天凌晨
				date_add(a.record_date,INTERVAL -1 DAY ) as yesterday,-- 昨天	
				date_add(a.record_date,INTERVAL 1 DAY ) as tomorrow-- 明天	
from (select FROM_UNIXTIME(UNIX_TIMESTAMP(CAST(NOW()AS DATE))) record_date) a -- 获取今天凌晨
use sdt_xjb;
with record_date_temp as (-- 用来事先 定义好 当前凌晨,用于过滤时间
	select record_date,
		DATE_ADD(record_date,interval -day(record_date)+1 day) monthFirstDay,-- 今天对应的所在月第一天
		yesterday,-- 昨天	
		tomorrow-- 明天	
from(select a.record_date, -- 获取今天凌晨
				date_add(a.record_date,INTERVAL -1 DAY ) as yesterday,-- 昨天	
				date_add(a.record_date,INTERVAL 1 DAY ) as tomorrow-- 明天	
	from (select FROM_UNIXTIME(UNIX_TIMESTAMP(CAST(NOW()AS DATE))) record_date) a -- 获取今天凌晨
	) aa
)

select * from record_date_temp

12.100MySql 对小数的处理

  • round 函数,四舍五入
select round(12.34512,3) -- 12.345

15 Echarts

15.1 入门案例

  • 引入 echarts.js <script src="echarts.min.js"></script>
  • 创建dom 容器 <div id="main" style="width: 600px;height:400px;"></div>
  • 初始化echarts实例

标注了:x y x2 y2的距离

img
img
<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
        <title>ECharts</title>
        <!-- 引入 echarts.js -->
        <script src="echarts.min.js"></script>
    </head>
    <body>
        <!-- 为ECharts准备一个具备大小(宽高)的Dom 
            当前div容器,必须放到 js 前面,否在初始化找不到元素。(高度不能用百分比=========待定)
        -->
        <div id="main" style="width: 600px;height:400px;"></div>
        <script type="text/javascript">
        // 基于准备好的dom,初始化echarts实例
        var myChart = echarts.init(document.getElementById('main'));
        // 指定图表的配置项和数据
        var option = {
            title: {
                text: 'ECharts 入门示例'
            },
            tooltip: {},
            grid: {
                //"left":"auto",
                "containLabel": true,
                //显示坐标轴上的时间轴和刻度尺
                y2: 0,
                x2: 10,
                x: 7
            },
            legend: {
                data: ['销量']
            },
            xAxis: {
                data: ["衬衫", "羊毛衫", "雪纺衫", "裤子", "高跟鞋", "袜子"],
                label: {
                    normal: {
                        show: true //用来在柱形图中显示数值  在柱状图里面
                    }
                },
                itemStyle: { //=======用来在柱形图中显示数值  在柱状图上方
                    normal: {
                        color: '#8470FF',
                        //========设置图片颜色
                        label: {
                            show: true,
                            position: 'top',
                            textStyle: {
                                fontSize: 12
                            }
                        }
                    }
                },
                axisLabel: { //x轴文字显示,针对文字过长会间隔出现,这里可以强制全部出现,并可以设置文字倾斜度
                    interval: 0,
                    //0:全部显示,1:间隔为1显示对应类目,2:依次类推,(简单试一下就明白了,这样说是不是有点抽象) 
                    rotate: -30,
                    //倾斜显示,-:顺时针旋转,+或不写:逆时针旋转 
                }
            },
            yAxis: {},
            series: [{
                name: '销量',
                type: 'bar',
                data: [5, 20, 36, 10, 10, 20],
                //后期可以用ajax从后台获取数据,,
                /*axisLabel:{			//x轴文字倾斜
                    interval:0,
                    rotate:45,
                    margin:2,
                    textStyle:{
                        color:"#222"
                    }}, */
            }]
        };
        // 使用刚指定的配置项和数据显示图表。
        myChart.setOption(option);
            //定义单击事件
        pieChart.on("click", function (param){
            If(param.name=’销量’){
            top.$.jBox('iframe:${ctx}/video/videoAnalyseResult/list?eqClazzs='+eqType+'&nums=0',{title: '状态数据 ',width: window.innerWidth-360,height:window.innerHeight, top:20, buttons: { '关闭': true }});	//以弹窗的心事展示页面
            }
        }
        </script>
    </body>
</html>

15.2 案例2:包含后台数据处理

echarts+ajax动态获取后端数据 open in new window https://blog.csdn.net/u010452388/article/details/81877663open in new window

img
img
  • java 部分
List<YdxjDundianTowers> mapList = ydxjDundianTowersService.dundianCountByStationECharts(ydxjDundianTowers);  普通的查询list方法
		List<String>  stationName = new ArrayList<String>();  //YJ站 作为  X轴
		List<String> notStart = new ArrayList<String>();//未开始
		List<String> startIng = new ArrayList<String>();//蹲守中 
		List<String> endDundian = new ArrayList<String>();//终结
		for (YdxjDundianTowers b : mapList) {
			stationName.add(b.getStationName());
			notStart.add(b.getNotStart());
			startIng.add(b.getStartIng());
			endDundian.add(b.getEndDundian());
		}
		JSONObject json = new JSONObject();
		json.put("stationName", stationName);//YJ站
		json.put("notStart", notStart);//未开始
		json.put("startIng", startIng);//蹲守中 
		json.put("endDundian", endDundian);//终结
		model.addAttribute("mapList", json.toJSONString());
  • 前端
<body>
	<div id="chart" style="height:420px;width:100%;float: left;"></div>
	<%-- <div class="pagination">${page}</div> --%>
	<!-- Echart图表 -->
	<script src="${ctxStatic}/echarts/echarts-all.js" type="text/javascript"></script>
	<script src="${ctxStatic}/echarts/esl.js" type="text/javascript"></script>
	<script type="text/javascript">
		var myChart = echarts.init(document.getElementById('chart'));
		var chartDatas = ${mapList};
		var option = {
			 title : { text: 'YJ站分析柱状图'
				 },
		    tooltip : {
		        trigger: 'axis',
		        axisPointer : {            // 坐标轴指示器,坐标轴触发有效
		            type : 'shadow'        // 默认为直线,可选为:'line' | 'shadow'
		        }
		    },
		    legend: {
		        //data:['直接访问','邮件营销','联盟广告','视频广告','搜索引擎','百度','谷歌','必应','其他']
		       	data:['未开始','蹲守中','已终结']    //======================= 是对应 Y轴的name
		    },
		    grid: {
		        left: '3%',
		        right: '4%',
		        bottom: '3%',
		        containLabel: true
		    },
		    xAxis : [
		        {
		            type : 'category',
		       		data:chartDatas.stationName  //X 轴,,YJ站
		        }
		    ],
		    yAxis : [
		        {
		            type : 'value'
		        }
		    ],
		    series : [
		        {
		            name:'未开始',
		            type:'bar',
		            stack: 'YJ站',   //同一个  stack  会和合并在一起
		            data:chartDatas.notStart
		        },
		        {
		            name:'蹲守中',
		            type:'bar',
		            stack: 'YJ站',
		            data:chartDatas.startIng
		        },
		        {
		            name:'已终结',
		            type:'bar',
		            stack: 'YJ站',
		            data:chartDatas.endDundian
		        },
		        {
		            name:'已终结',
		            type:'bar',
		           // barWidth : 10,   //宽度
		            stack: 'YJ站',
		            data:chartDatas.endDundian,
		            markLine : {        //在柱状图中连线  能够开  趋势
 		                lineStyle: {
 		                    normal: {
 		                        type: 'dashed'
 		                    }
 		                },
 		                data : [
 		                    [{type : 'min'}, {type : 'max'}]
 		                ]
 		            }
		        },
		        
		    ]
		};
		myChart.setOption(option);
	</script>
</body>

15.3 案例3 :环状图

https://www.makeapie.com/editor.html?c=xtLpob3FIDopen in new window

效果图

image-20210511092321588
var  getvalue=[88];
option = {
    title: {
    text: getvalue+'分',
    textStyle: {
      color: '#28BCFE',
      fontSize: 40
    },
    subtext: '综合得分',
        subtextStyle: {
            color: '#666666',
            fontSize: 30
        },
	itemGap: 20,
    left: 'center',
    top: '43%'
	},
    tooltip: {// Tips 提示。点击 内容区域提示信息
        formatter: function (params) {
            return '<span style="color: #fff;">综合得分:'+ getvalue + '分</span>';
        }
    },
  angleAxis: {
    max: 100,
    clockwise: true, // 逆时针
    show: false// 隐藏刻度线
  },
  radiusAxis: {
        type: 'category',
        show: true,
        axisLabel: {
            show: false,
        },
        axisLine: {
            show: false,
        },
        axisTick: {
            show: false
        },
  },
  polar: {
    center: ['50%', '50%'],
    radius: '100%' //图形大小
  },
  series: [{
    type: 'bar',
    data: getvalue,
	showBackground: true,
	backgroundStyle: {
		color: '#BDEBFF',
	},
    coordinateSystem: 'polar',
    roundCap: true,
    barWidth: 30,
    itemStyle: {// 修改圆环 颜色,设置渐变色
        normal: {
        opacity: 1,
        color:  new echarts.graphic.LinearGradient(0, 0, 0, 1, [{
            offset: 0,
            color: '#25BFFF'
          }, {
            offset: 1,
            color: '#5284DE'
          }]),
        shadowBlur: 5,
        shadowColor: '#2A95F9',
    }
    },
  }]
};

15.10 用来设置Echatrs的自适应

window.onresize = function () {
	myChart.resize({width:window.innerWidth, height:window.innerHeight});
}

15.11 设置渐变色

series: [{
            type: 'bar',
            data: [, , xsl],
            coordinateSystem: 'polar',
            barMaxWidth: 23,
            z: 2,
            name: '巡视率',
            roundCap: true,
            itemStyle: {
              normal: {
                color: {
                  type: 'linear',
                  colorStops: [
                    // !! 在此添加想要的渐变过程色 !!
                    {
                      offset: 0,
                      color: '#436CF5'
                    },
                    {
                      offset: 1,
                      color: '#68A2F7'
                    }
                  ]
                },
              }
            },
            barGap: '-100%',
          }, {
            type: 'bar',
            data: [, , 100],
            z: 0,
            silent: true,
            coordinateSystem: 'polar',
            barMaxWidth: 23,
            name: 'C',
            roundCap: true,
            color: '#F1F3F8',
            barGap: '-100%',
          }],

15.50 初始化异常

echarts 无法获取属性“getAttribute”的值: 对象为 null 或未定义 错误解决方法

造成这种错误的原因是

echarts.js引用放在head中或者放在body中HTML代码的前面了,造成加载时阻塞后面的html。

解决方法就是将echarts.js的引用放在</body>之前就可以了

17 java

idea 修改 maven配置后,肯能出现 项目报错,重启,清楚缓存都不能正常编译,手动刷新maven

image-20210207150540404
image-20210207150540404

查找pom用的jar https://mvnrepository.com/open in new window

jar包冲突https://blog.csdn.net/noaman_wgs/article/details/81137893open in new window

17.1 事物

参考网址 : https://blog.csdn.net/zhou_java_hui/article/details/53302278open in new window

场景1: A类方法,调用B类b方法,如果b异常,想通过try catch 来自定义异常,不进行事物回滚

@Transactional(
			//propagation=Propagation.NESTED,
			propagation= Propagation.NESTED,
			rollbackFor={Exception.class}
	)
public void b(){
    // b方法
}

17.2 HttpClient4.x进行Get/Post请求并使用ResponseHandler处理响应

导包

<dependency>
    <groupId>org.apache.httpcomponents</groupId>
    <artifactId>httpclient</artifactId>
    <version>4.5.4</version>
</dependency>
<!--StringUtil-->
<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-lang3</artifactId>
    <version>${commons-lang3.version}</version>
</dependency>
<!--java.net-->
<dependency>
    <groupId>commons-net</groupId>
    <artifactId>commons-net</artifactId>
    <version>1.4.1</version>
</dependency>
<!--http客户端-->
<dependency>
    <groupId>org.apache.httpcomponents</groupId>
    <artifactId>httpclient</artifactId>
    <version>4.5.4</version>
</dependency>

17.3 Java获取 当前访问的服务路径

String url =  request.getRequestURL().toString();
String baseUrl =url.substring(0,url.indexOf("/a/"));

17.10java之 Timer 类的简单使用案例open in new window

Timer来讲就是一个调度器 ,类似于js中的 定时器setInterval


阻塞

public static void main(String[] args) {

        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        for (int i = 0; i < 3; i++) {
            try {
                Thread.sleep(5 * 1000); //设置暂停的时间 5 秒
                System.out.println(sdf.format(new Date()) + "--循环执行第" + (i+1) + "次");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

    }

17.100 file

场景:文件的导出

  • 以流的形式输出到浏览器导出文件
  • 指定盘符导出
// 1.指定盘符导出,简单格式
public static void excelTest0() throws IOException {
    //创建HSSFWorkbook对象  
    HSSFWorkbook wb = new HSSFWorkbook();  
    //创建HSSFSheet对象  
    HSSFSheet sheet = wb.createSheet("sheet0");  
    //创建HSSFRow对象  
    HSSFRow row = sheet.createRow(0);  
    //创建HSSFCell对象  
    HSSFCell cell=row.createCell(0);  
    //设置单元格的值  
    cell.setCellValue("单元格中的中文");  
    //输出Excel文件  
    FileOutputStream output=new FileOutputStream("d:\\workbook.xls");  
    wb.write(output);  
    output.flush();  
}


//2. B/S模式中采用的输出方式,而不是输出到本地指定的磁盘目录。该代码表示将details.xls的Excel文件通过应答实体(response)输出给请求的客户端浏览器,客户端可保存或直接打开。
public static String excelTest2(HttpServletRequest request,HttpServletResponse response) throws IOException{
		    //创建HSSFWorkbook对象  
    HSSFWorkbook wb = new HSSFWorkbook();  
    //创建HSSFSheet对象  
    HSSFSheet sheet = wb.createSheet("sheet0");  
    //创建HSSFRow对象  
    HSSFRow row = sheet.createRow(0);  
    //创建HSSFCell对象  
    HSSFCell cell=row.createCell(0);  
    //设置单元格的值  
    cell.setCellValue("单元格中的中文");  
	  
	//输出Excel文件  
    OutputStream output=response.getOutputStream();  
    response.reset();  
    response.setHeader("Content-disposition", "attachment; filename=details.xls");  
    response.setContentType("application/msexcel");          
    wb.write(output);  
    output.close();  
    return null;  
}

17.110 用map对数据进行分类统计

1)案例1.用一个字段作为统计条件(以设备名称)

业务场景:大批量的导入设备,要求导入的数据中设备名称不能重复,所以要对导入的所以数据进行判断,看是否有重复

Map<String, List<NvrDevice>> map=new HashMap<String, List<NvrDevice>>();//=========NvrDevice为要导入的对象,将对象放到map里面,同时将设备名称作为map的key

===========这样就会将同一个key的对象放到同一个map中的list对象里

===========map里面存放多条不同key组成的键值对,,一个key 是 nvrName 讲相同的key的NvrDevice 合并再一起,塞在list中

//用来判断导入的数据中'名称'是否存在重复
for (NvrDevice nvrDevice2 : nvrDeviceList) {
	if(!map.containsKey(nvrDevice2.getNvrName())){//============containsKey是用来判断某个key是否存在
		map.put(nvrDevice2.getNvrName(), new ArrayList<NvrDevice>());//=====不存在就新new一个map对象,并将此时的设备名称作为key存入。
	}
	map.get(nvrDevice2.getNvrName()).add(nvrDevice2);//==最后map存放的就是唯一key的list对象,而list对象中可能存再设备名称相同的NvrDevice对象
}
for (String nvrName : map.keySet()) {//======================以key来遍历map集合
	if(map.get(nvrName).size()>1){//=======================表示对于设备名称的存在多条
		for (NvrDevice nvrDevice3 : map.get(nvrName)) {
			nvrDevice3.setResult(nvrDevice3.getResult()+nvrName+"有重复的;");
		}
	}
}
///=========================================验证导入数据是否存在重复,============================================
List<String> nameList=new ArrayList<String>()
for(NvrDevice nvrDevice2 : nvrDeviceList){//遍历对象,取除name,如果list里面没有,那么就将name 放到list里面,如果有表示存在重复
	String name= nvrDevice2.getNvrName();
	if (names.contains(fileName)) {// Java中list集合ArrayList 中contains包含的使用
		//说明存在
	}
	nameList.add(name);
}

2)案例2:

业务场景:服务商领用备品备件--存在自己的库存中使用,最后登记已经使用的数量。(所以思路是:以服务商和备件名来统计,具有相同的服务商和备件分别统计出,出库的量和已经使用的量)

img
img

//gcywBpbjCkRecord是出库记录 以他为主表。将具有相同的服务商和备件的使用量放到对应的出库记录中(相应的出库记录中增加一个存放使用量的字段)

public String fwsStock(GcywBpbjCkRecord gcywBpbjCkRecord, Model model){
		//一。获取对应服务商--备件的出库量(通过服务商和备件这两个条件去分类统计库存量分别是多少)
		List<GcywBpbjCkRecord> listData=new ArrayList<GcywBpbjCkRecord>();//最后存放数据的,将具有相同服务商--备件的记录中的数据存放在其中一个
		List<GcywBpbjCkRecord> list=gcywBpbjCkRecordService.findList(gcywBpbjCkRecord);//获取所有的信息
		for (GcywBpbjCkRecord fws : list) {
			if(!mapFws.containsKey(fws.getBcampany())){//通过服务商来第一层统计
				mapFws.put(fws.getBcampany(), new HashMap<String, List<GcywBpbjCkRecord>>());
			}
			if(mapFws.containsKey(fws.getBcampany())){
				if(!mapFws.get(fws.getBcampany()).containsKey(fws.getBpbjId())){
					mapFws.get(fws.getBcampany()).put(fws.getBpbjId(), new ArrayList<GcywBpbjCkRecord>());
				}
				mapFws.get(fws.getBcampany()).get(fws.getBpbjId()).add(fws);
			}
		}
		for(String fwsName:mapFws.keySet()){
			for (String bpbjName : mapFws.get(fwsName).keySet()) {
				Double num=0.0;
				for (GcywBpbjCkRecord ckRecord : mapFws.get(fwsName).get(bpbjName)) {
					num+=ckRecord.getBpbjNum();//=========1.数据中农具有相同服务商--备件的对象都存放在一个map中,然后遍历,将出库量的记录累加
				}
                //============2。将统计后的数据赋值给list中的第一个对象,作为有效数据listData.add(mapFws.get(fwsName).get(bpbjName).get(0));
                mapFws.get(fwsName).get(bpbjName).get(0).setBpbjNum(num);
			}
		}
		System.out.println(listData);
		//二。从使用记录中获取对应服务商--备件使用的实际量
		List<GcywBpbjUseSituation> listData2=new ArrayList<GcywBpbjUseSituation>();
		Map<String,List<GcywBpbjUseSituation>> map2=new HashMap<String, List<GcywBpbjUseSituation>>();
		Map<String,Map<String,List<GcywBpbjUseSituation>>> mapFws2=new HashMap<String, Map<String,List<GcywBpbjUseSituation>>>();
		List<GcywBpbjUseSituation> list2 = gcywBpbjUseSituationService.findList(new GcywBpbjUseSituation());
		for (GcywBpbjUseSituation fws : list2) {
			if(!mapFws2.containsKey(fws.getFwsId())){
				mapFws2.put(fws.getFwsId(), new HashMap<String, List<GcywBpbjUseSituation>>());
			}
			if(mapFws2.containsKey(fws.getFwsId())){
				if(!mapFws2.get(fws.getFwsId()).containsKey(fws.getBpbjId())){
					mapFws2.get(fws.getFwsId()).put(fws.getBpbjId(), new ArrayList<GcywBpbjUseSituation>());
				}
				mapFws2.get(fws.getFwsId()).get(fws.getBpbjId()).add(fws);
			}
		}
		for(String fwsName:mapFws2.keySet()){
			for (String bpbjName : mapFws2.get(fwsName).keySet()) {
				Double num=0.0;
				for (GcywBpbjUseSituation gcywBpbjUse : mapFws2.get(fwsName).get(bpbjName)) {
					num+=gcywBpbjUse.getBpbjNumber();
				}
				mapFws2.get(fwsName).get(bpbjName).get(0).setBpbjNumber(num);
				listData2.add(mapFws2.get(fwsName).get(bpbjName).get(0));
			}
		}
	//三。用来整合上面的2个map集合,将实际使用量在写到对应的出库记录中
		Map<String,Map<String, GcywBpbjUseSituation>> maps=new HashMap<String, Map<String,GcywBpbjUseSituation>>();
		for (GcywBpbjUseSituation fws : listData2) {
			if(!maps.containsKey(fws.getFwsId())){
				maps.put(fws.getFwsId(), new HashMap<String, GcywBpbjUseSituation>());
			}
			if(maps.containsKey(fws.getFwsId())){
				if(!maps.get(fws.getFwsId()).containsKey(fws.getBpbjId())){
					maps.get(fws.getFwsId()).put(fws.getBpbjId(), fws);
				}
			}
		}
		for(GcywBpbjCkRecord ckRecord :listData){
			if(maps.containsKey(ckRecord.getBcampany())){
				if(maps.get(ckRecord.getBcampany()).containsKey(ckRecord.getBpbjId())){
					System.out.println(maps.get(ckRecord.getBcampany()).get(ckRecord.getBpbjId()).getBpbjNumber());
					ckRecord.setBpbjNumber(maps.get(ckRecord.getBcampany()).get(ckRecord.getBpbjId()).getBpbjNumber());
				}
			}
		}
		System.out.println(listData2);
		model.addAttribute("gcywBpbjCkRecord",gcywBpbjCkRecord);
		model.addAttribute("listData",listData);
		return "modules/gcyw/gcywBpbjFwsStock";
	}

java中Map遍历的四种方式open in new window

在java中所有的map都实现了Map接口,因此所有的Map(如HashMap, TreeMap, LinkedHashMap, Hashtable等)都可以用以下的方式去遍历。

方法一:在for循环中使用entries实现Map的遍历:

/**
* 最常见也是大多数情况下用的最多的,一般在键值对都需要使用
 */
Map <String,String>map = new HashMap<String,String>();
map.put("熊大", "棕色");
map.put("熊二", "黄色");
for(Map.Entry<String, String> entry : map.entrySet()){
    String mapKey = entry.getKey();
    String mapValue = entry.getValue();
    System.out.println(mapKey+":"+mapValue);
}

方法二:在for循环中遍历key或者values,一般适用于只需要map中的key或者value时使用,在性能上比使用entrySet较好;

Map <String,String>map = new HashMap<String,String>();
map.put("熊大", "棕色");
map.put("熊二", "黄色");
//key
for(String key : map.keySet()){
    System.out.println(key);
}
//value
for(String value : map.values()){
    System.out.println(value);
}

方法三:通过Iterator遍历;

Iterator<Entry<String, String>> entries = map.entrySet().iterator();
while(entries.hasNext()){
    Entry<String, String> entry = entries.next();
    String key = entry.getKey();
    String value = entry.getValue();
    System.out.println(key+":"+value);
}

方法四:通过键找值遍历,这种方式的效率比较低,因为本身从键取值是耗时的操作;

for(String key : map.keySet()){
    String value = map.get(key);
    System.out.println(key+":"+value);
}

17.120 生成json 文件

- 指定盘符生成json文件
- map对数据的 处理
	/**
	 根据 不同电压 等级,组装 地图需要的线路数据
		List<LineVO> lineList = findLineByIds(towerVO);
		查询出来的数据是利用resultMap  构成 线路--GT 结构(线路pojo对象 包含一个GT的List集合)
		遍历结果集: 利用map讲同一个电压等级下的线路合并到一起。最后再遍历这个map,生成不同电压等级下的 线路json文件
        	例如:35KV.json  
            [{
                "type": "Feature",
                "geometry": {
                  "type": "LineString",
                  "coordinates": [[118.5705817,31.00465868],[118.5715242,31.00233154],[118.5722901,31.00044132],......]
                },
                "properties": {
                  "ID":"ys500sdwsdsidjqsxian",
                 "NAME":"35kV吉泉线接地极",
                 "voltageGrade":"35kV"
                }
              }]	
	
	**/
	public String createLineFileForMap(TowerVO towerVO) throws Exception {
		String filePath = "";
		try {
			List<LineVO> lineList = findLineByIds(towerVO);
			filePath = SettingUtils.getCfgSettingByCodeForSelf("platform_address").getValue()+"/lineDataFor3DMap/data";// 指定导出文件
			/**
			 * json 格式中 第一层 线路组成的数组
			 *  每个线路对象 3个参数,第一个type 类型
			 *  第二个 坐标信息 geometry,又分为 2个对象,第一个是 type='LineString'类型 ,第二个是 坐标信息 [[],[],[]......]
			 *  第三个 属性信息properties
			 * 需要以每个不同 电压等级 创建一个 对于的JSON 文件,然后把 同一个电压等级下的线路组装在一起,再写入到该json文件中
			 */
			Map<String,JSONArray> voltageGradeMap=Maps.newHashMap();
			//JSONArray lineJsonList = new JSONArray();
			for (LineVO lineVO:lineList) {
				//============containsKey是用来判断某个key是否存在
				if(!voltageGradeMap.containsKey(lineVO.getVoltageGrade())){
					//=====不存在就新new一个map对象,并将此时的设备名称作为key存入。
					voltageGradeMap.put(lineVO.getVoltageGrade(), new JSONArray());
				}
				//1.组装第一层 type='Feature'
				JSONObject lineObject = new JSONObject();
				lineObject.put("type","Feature");//
				//2. 线路属性信息(计划存储,电压等级,线路id,线路名称)
				JSONObject linePropertiesObject = new JSONObject();
				linePropertiesObject.put("ID",lineVO.getLineId());// 线路id
				linePropertiesObject.put("NAME",lineVO.getLineName());
				linePropertiesObject.put("linePmsid",lineVO.getLinePmsid());
				linePropertiesObject.put("voltageGrade",lineVO.getVoltageGrade());
				lineObject.put("properties",linePropertiesObject);// 线路 属性 信息
				//3.坐标信息
				JSONArray coordinatesList = new JSONArray();
				for (TowerVO tower: lineVO.getTowerList()) {
					JSONArray towerPointList = new JSONArray();
					towerPointList.add(0,Float.parseFloat(tower.getLongitudeGps()));// 经度
					towerPointList.add(1,Float.parseFloat(tower.getLatitudeGps()));// 纬度
					coordinatesList.add(towerPointList);
				}
				// 组装 坐标信息
				JSONObject geometryObject = new JSONObject();
				geometryObject.put("type","LineString");
				geometryObject.put("coordinates",coordinatesList);
				lineObject.put("geometry",geometryObject);
				//lineJsonList.add(lineObject);
				voltageGradeMap.get(lineVO.getVoltageGrade()).add(lineObject);
			}
			System.out.println(voltageGradeMap);
			for(String key : voltageGradeMap.keySet()){
				JSONArray lineJsonList = voltageGradeMap.get(key);
				createJsonFile(lineJsonList,filePath+"/"+key+".json");
			}
			logger.info("##==三维地图生成不同电压等级下的线路JSON文件===="+"导出线路成功:"+filePath);
		} catch (Exception e) {
			e.printStackTrace();
			logger.error("##==三维地图生成不同电压等级下的线路JSON文件===="+"导出线路失败:"+e);
			throw new Exception("文件生成失败"+e);
		}
		System.out.println("线路JSON文件生成完成!");
		return filePath;
	}
	/**
	 * 将JSON数据格式化并保存到文件中
	 * @param jsonData 需要输出的json数
	 * @param filePath 输出的文件地址
	 * @return
	 */
	public static boolean createJsonFile(Object jsonData, String filePath) {
		String content = JSON.toJSONString(jsonData, SerializerFeature.PrettyFormat, SerializerFeature.WriteMapNullValue,
				SerializerFeature.WriteDateUseDateFormat);
		// 标记文件生成是否成功
		boolean flag = true;
		// 生成json格式文件
		try {
			// 保证创建一个新文件
			File file = new File(filePath);
			if (!file.getParentFile().exists()) { // 如果父目录不存在,创建父目录
				file.getParentFile().mkdirs();
			}
			if (file.exists()) { // 如果已存在,删除旧文件
				file.delete();
			}
			file.createNewFile();
			// 将格式化后的字符串写入文件
			Writer write = new OutputStreamWriter(new FileOutputStream(file), "UTF-8");
			write.write(content);
			write.flush();
			write.close();
		} catch (Exception e) {
			flag = false;
			e.printStackTrace();
		}
		return flag;
	}

17.125 java io

//获取指定的文件夹下的所有pdf 文件
	public static ArrayList<String> getFiles(String path) {//D:\myEclipse\apache-tomcat-7_myElipse\apache-tomcat-7.0.73\webapps\SDT_IMOA\//work/zip/20190424163926/LA-R-2019-012-万善昆-1000kV圩淮Ⅰ线
	    ArrayList<String> files = new ArrayList<String>(); 
	    File file = new File(path);
	    File[] tempList = file.listFiles();

	    for (int i = 0; i < tempList.length; i++) {
	        if (tempList[i].isFile()) {
	        	 String fileName = tempList[i].getName();//获取文件名
	        	
	        	 String fileType=fileName.substring(fileName.lastIndexOf(".")+1);//获取文件的后缀名
	        	 if("pdf".equals(fileType)||"PDF".equals(fileType)){
	        		 files.add(tempList[i].toString());
	        	 }
	        }
	        
	    }
	   System.out.print("文     件:" + files);
	    return files;
	}

17.126 Java IO 创建文件解决文件名重复问题

文件名在操作系统中不允许出现 / \ ” : | * ? < > 故将其以空替代

**注:**文件创建时需要注意

  • 名称特殊字符(例如 \ 会导致文件被当作文件夹截取 )
  • 文件名称重复
Pattern pattern = Pattern.compile("[\\s\\\\/:\\*\\?\\\"<>\\|]");
Matcher matcher = pattern.matcher(fileName);
fileName= matcher.replaceAll(""); // 将匹配到的非法字符以空替换

两个思路:

​ 1.定义一个全局变量Map,以文件名称为key,序号为value. 调用方法前,先初始化map,因为全局变量,防止历史对数据的影响。方法调用需要传递fileName,判断当前文件名对应的key是否存在,如果存在则value+1,并拼好名称,返回

​ 2.传递一个路径,判断文件是否存在,循环,直到文件名称没有重复返回

  • 方法1:
	/**
	 * 防止文件名称重复,导致java io 读写失败
	 * 考虑有些 是 添加到 压缩包中,所以无法通过 io 来验证是否存在
	 * @param filePath
	 * @param fileName
	 * @return
	 * List<String> fileNameList=new ArrayList<String>();// 防止文件名重复 导致 程序异常,故需对 每个 文件名进行判断
	 
	 */
	public static String getFileNameByList(List<String> fileNameList, String fileName){
		fileName = StringEscapeUtils.unescapeHtml(fileName);
		Matcher matcher = pattern.matcher(fileName);//判断是否存在特殊字符 做空字符串替换
		fileName= matcher.replaceAll(""); // 将匹配到的非法字符以空替换
		//文件名,如spring
		String name = fileName.substring(0,fileName.indexOf("."));
		//文件后缀,如.jpeg
		String suffix = fileName.substring(fileName.lastIndexOf("."));
		int i = 1;
		//若文件存在重命名
		while(fileNameList.contains(fileName)) {
			String newFilename = name+"("+i+")"+suffix;
			i++;
			fileName=newFilename;
		}
		return fileName;
	}
  • 方法2:
	// 防止文件名称重复,导致java io 读写失败
	public String getFileName(String fileName,String filePath){
		//源文件
		File descFile  = new File(filePath+ File.separator+fileName);
		int i = 1;
		//若文件存在重命名
		while(descFile .exists()) {
			String newFilename = fileName+"("+i+")";
			descFile = new File(filePath+ File.separator+newFilename);
			i++;
		}
		return fileName;
	}
package practice.IO;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
/**
 * @author 言曌
 * @date 2017/12/2 上午10:59
 */
public class Demo {
    /**
     * 将 /Users/liuyanzhao/Desktop/spring.jpeg 文件
     * 拷贝到 /Users/liuyanzhao/Desktop/io/中
     * 需要避免文件名重复覆盖的情况
     */
    public static void main(String args[]) throws IOException {
        //源文件
        File sourceFile = new File("/Users/liuyanzhao/Desktop/spring.jpeg");
        //文件的完整名称,如spring.jpeg
        String filename = sourceFile.getName();
        //文件名,如spring
        String name = filename.substring(0,filename.indexOf("."));
        //文件后缀,如.jpeg
        String suffix = filename.substring(filename.lastIndexOf("."));
        //目标文件
        File descFile = new File("/Users/liuyanzhao/Desktop/io"+File.separator+filename);
        int i = 1;
        //若文件存在重命名
        while(descFile.exists()) {
            String newFilename = name+"("+i+")"+suffix;
            String parentPath = descFile.getParent();
            descFile = new File(parentPath+ File.separator+newFilename);
            i++;
        }
        descFile.createNewFile();  //新建文件
        FileInputStream fin = new FileInputStream(sourceFile);
        FileOutputStream fout = new FileOutputStream(descFile);
        byte[] data = new byte[512];
        int rs = -1;
        while((rs=fin.read(data))>0) {
            fout.write(data,0,rs);
        }
        fout.close();
        fin.close();
    }
}

17.127 java 生成文件

--------------待整理:js分公司 附件上传

以流的形式传递到前端,执行下载,后端可有用重定向,这样可以 通过addMessage(redirectAttributes, "导出失败!"); 返回前端报错提示

https://blog.csdn.net/weixin_44176169/article/details/105320502open in new window (单文件,多文件上传 MultipartFile 、MultipartHttpServletRequest )

仿阿里云的写法,讲需要上传的附件,分为,“上传字符串”,“上传Byte数组”,“上传网络流”,"本地附件" https://help.aliyun.com/document_detail/84781.html?spm=a2c4g.11186623.6.961.5a7c16906I5hslopen in new window

// 填写网络流地址。
InputStream inputStream = new URL("https://www.aliyun.com/").openStream();

已流的形式 浏览器输出

指定盘符 生成本地文件

通过url 下载附件

public static String getRelativeFilePath(String fileName, String rootDirPath, String relativePath){
		//判断是否存在特殊字符 做空字符串替换
		Matcher matcher = pattern.matcher(fileName);
		//URLEncoder.encode(newFileName,"UTF-8");//针对中文乱码
		fileName= matcher.replaceAll(""); // 将匹配到的非法字符以空替换
		/**
		 * 判断附件上传,指定位置的文件夹是否存在
		 */
		File saveDirFile = new File(rootDirPath+File.separator+relativePath);//E:/CPMS/CPMS_FILES/CPMS_JSFGS/proj/20200426/lihuan
		if (!saveDirFile.exists()) {//不存在指定文件夹 先创建
			saveDirFile.mkdirs();
		}
		return relativePath+File.separator+fileName;// 文件的相对路径(用于返回结果)
	}


	/**
	 *  将url 资源 下载到本地,并返回 相对路径
	 *  调用者 在使用时需要 自己补上 rul前缀 Global.getConfig("towerViewImg")+filePath
	 * @param URL
	 * @param rootDirPath :文件上传根目录 E:/CPMS/CPMS_FILES/CPMS_JSFGS
	 * @param relativePath:文件所在 文件夹相对路径 /proj/20200426/lihuan
	 * @return
	 * @throws Exception
	 */
	public static String uploadFileByURL(String URL,String rootDirPath,String relativePath) throws Exception {
		//文件名
		String fileName=URL.substring(URL.lastIndexOf("/")+1);
		String relativeFilePath=getRelativeFilePath(fileName,rootDirPath,relativePath);// 获取相对路径,用于  返回给 前端

		java.net.URL url = new URL(URL);
		HttpURLConnection urlCon = (HttpURLConnection) url.openConnection();
		urlCon.setConnectTimeout(6000);
		urlCon.setReadTimeout(6000);
		int code = urlCon.getResponseCode();
		if (code != HttpURLConnection.HTTP_OK) {
			throw new Exception("文件读取失败");
		}

		//读文件流
		DataInputStream in = new DataInputStream(urlCon.getInputStream());
		DataOutputStream out = new DataOutputStream(new FileOutputStream(rootDirPath+File.separator+relativeFilePath));
		byte[] buffer = new byte[2048];
		int count = 0;
		while ((count = in.read(buffer)) > 0) {
			out.write(buffer, 0, count);
		}
		out.close();
		in.close();
		relativeFilePath = relativeFilePath.replaceAll("\\\\", "/");
		return "/" + relativeFilePath;
	}
  • 打包下载( 通过url 下载文件 案例是 通过 oss需要整理成 普通url)

    不生成 本地文件,直接以流的形式输出

public static void downForZipAsFlowByOSS(HttpServletRequest req, HttpServletResponse response,List<String> fileUrlList, String fileName ){
		// 创建临时文件
		File zipFile = null;
		try {
			//临时文件名称
			zipFile = File.createTempFile("downZipTemp", ".zip");
			FileOutputStream f = new FileOutputStream(zipFile);
			/**
			 * 作用是为任何OutputStream产生校验和
			 * 第一个参数是制定产生校验和的输出流,第二个参数是指定Checksum的类型 (Adler32(较快)和CRC32两种)
			 */
			CheckedOutputStream csum = new CheckedOutputStream(f, new Adler32());
			// 用于将数据压缩成Zip文件格式
			ZipOutputStream zos = new ZipOutputStream(csum);
			AliOssClient aliOssClient= createAliOssClient();
			OSS ossClient = aliOssClient.getOssClient();
			String bucket_domain_url = SettingUtils.getCfgSettingByCode("BUCKET_DOMAIN_URL").getValue();
			for (String ossFile : fileUrlList) {
				// 路径前面 加 ‘/’ 会导致下载失败,所以需要 判断然后剔除掉多余的 /
				ossFile = getRelativeFilePthByOSS(ossFile);
				// 获取Object,返回结果为OSSObject对象
				OSSObject ossObject = ossClient.getObject(aliOssClient.getBucketName(),ossFile);//bucket_domain_url
				// 读去Object内容 返回
				InputStream inputStream = ossObject.getObjectContent();
				// 对于每一个要被存放到压缩包的文件,都必须调用ZipOutputStream对象的putNextEntry()方法,确保压缩包里面文件不同名
				String name=ossFile.substring(ossFile.lastIndexOf("/")+1);
				zos.putNextEntry(new ZipEntry(name));
				int bytesRead = 0;
				// 向压缩文件中输出数据
				while ((bytesRead = inputStream.read()) != -1) {
					zos.write(bytesRead);
				}
				inputStream.close();
				zos.closeEntry(); // 当前文件写完,定位为写入下一条项目
			}
			zos.close();
			String header = req.getHeader("User-Agent").toUpperCase();
			if (header.contains("MSIE") || header.contains("TRIDENT") || header.contains("EDGE")) {
				fileName = URLEncoder.encode(fileName, "utf-8");
				//IE下载文件名空格变+号问题
				fileName = fileName.replace("+", "%20");
			} else {
				fileName = new String(fileName.getBytes(), "ISO8859-1");
			}
			response.reset();
			response.setContentType("text/plain");
			response.setContentType("application/octet-stream; charset=utf-8");
			response.setHeader("Location", fileName);
			response.setHeader("Cache-Control", "max-age=0");
			response.setHeader("Content-Disposition", "attachment; filename=" + fileName);
			FileInputStream fis = new FileInputStream(zipFile);
			BufferedInputStream buff = new BufferedInputStream(fis);
			BufferedOutputStream out = new BufferedOutputStream(response.getOutputStream());
			byte[] car = new byte[1024];
			int l = 0;
			while (l < zipFile.length()) {
				int j = buff.read(car, 0, 1024);
				l += j;
				out.write(car, 0, j);
			}
			// 关闭流
			fis.close();
			buff.close();
			out.close();
			ossClient.shutdown();
			// 删除临时文件
			zipFile.delete();
		} catch (IOException e1) {
			e1.printStackTrace();
		}catch (Exception e) {
			e.printStackTrace();
		}

	}
  • 导出word

17.140 java 对数字的处理

场景:excel 导入时,会出现导入某些,可能会是文本或者数字,这样就会出现,如果是数字那么会被转成科学计数法

//验证是否为数字,如果是数字类型的防止数字被转为科学计数法类型
public static String switchNum(String str){
	Boolean strResult = str.matches("-?[0-9]+.?[0-9]*[Ee]?[+-]?\\d+");    
 	if(strResult == true) {//说明是数字
		return (new BigDecimal(str)).toString();//将科学计数法转为数字
 	}
 	return str;
}
public static void main(String[] args) {
// String num="9999999999.222222";
// String num2="10";
// String num3="9.999999999222221E9";
// String num4="xxxxxx";
// System.out.println(switchNum(num));
// System.out.println(switchNum(num2));
// System.out.println(switchNum(num3));
// System.out.println(switchNum(num4));
}
  • 加减乘除算法

DoubleUtilopen in new window

package cn.semdo.common.utils;
 
import java.io.Serializable;
import java.math.BigDecimal;
import java.math.RoundingMode;
 
/**
 * 精确计算 double and float
 * Created by lxk on 2017/9/27
 */
public class DoubleUtil implements Serializable {
    private static final long serialVersionUID = -3345205828566485102L;
    // 默认除法运算精度
    private static final Integer DEF_DIV_SCALE = 2;
 
    /**
     * 提供精确的加法运算。
     *
     * @param value1 被加数
     * @param value2 加数
     * @return 两个参数的和
     */
    public static Double add(Double value1, Double value2) {
        BigDecimal b1 = new BigDecimal(Double.toString(value1));
        BigDecimal b2 = new BigDecimal(Double.toString(value2));
        return b1.add(b2).doubleValue();
    }
 
    /**
     * 提供精确的减法运算。
     *
     * @param value1 被减数
     * @param value2 减数
     * @return 两个参数的差
     */
    public static double sub(Double value1, Double value2) {
        BigDecimal b1 = new BigDecimal(Double.toString(value1));
        BigDecimal b2 = new BigDecimal(Double.toString(value2));
        return b1.subtract(b2).doubleValue();
    }
 
    /**
     * 提供精确的乘法运算。
     *
     * @param value1 被乘数
     * @param value2 乘数
     * @return 两个参数的积
     */
    public static Double mul(Double value1, Double value2) {
        BigDecimal b1 = new BigDecimal(Double.toString(value1));
        BigDecimal b2 = new BigDecimal(Double.toString(value2));
        return b1.multiply(b2).doubleValue();
    }
 
    /**
     * 提供(相对)精确的除法运算,当发生除不尽的情况时, 精确到小数点以后10位,以后的数字四舍五入。
     *
     * @param dividend 被除数
     * @param divisor  除数
     * @return 两个参数的商
     */
    public static Double divide(Double dividend, Double divisor) {
        return divide(dividend, divisor, DEF_DIV_SCALE);
    }
 
    /**
     * 提供(相对)精确的除法运算。 当发生除不尽的情况时,由scale参数指定精度,以后的数字四舍五入。
     *
     * @param dividend 被除数
     * @param divisor  除数
     * @param scale    表示表示需要精确到小数点以后几位。
     * @return 两个参数的商
     */
    public static Double divide(Double dividend, Double divisor, Integer scale) {
        if (scale < 0) {
            throw new IllegalArgumentException("The scale must be a positive integer or zero");
        }
        BigDecimal b1 = new BigDecimal(Double.toString(dividend));
        BigDecimal b2 = new BigDecimal(Double.toString(divisor));
        return b1.divide(b2, scale, RoundingMode.HALF_UP).doubleValue();
    }
 
    /**
     * 提供指定数值的(精确)小数位四舍五入处理。
     *
     * @param value 需要四舍五入的数字
     * @param scale 小数点后保留几位
     * @return 四舍五入后的结果
     */
    public static double round(double value, int scale) {
        if (scale < 0) {
            throw new IllegalArgumentException("The scale must be a positive integer or zero");
        }
        BigDecimal b = new BigDecimal(Double.toString(value));
        BigDecimal one = new BigDecimal("1");
        return b.divide(one, scale, RoundingMode.HALF_UP).doubleValue();
    }
	//================自定义:double类型数据转为Sting ,计算返回String类型================================
    /**
     * 提供精确的加法运算。
     *
     * @param value1 被加数
     * @param value2 加数
     * @return 两个参数的和
     */
    public static String addByStr(String value1, String value2) {
    	if(StringUtils.isEmpty(value1)){//如果传递的未null 则会报空指针异常
    		value1="0";
    	}
    	if(StringUtils.isEmpty(value2)){
    		value2="0";
    	}
        BigDecimal b1 = new BigDecimal(value1);
        BigDecimal b2 = new BigDecimal(value2);
        return b1.add(b2).toString();
    }
    /**
     * 提供精确的乘法运算。
     *
     * @param value1 被乘数
     * @param value2 乘数
     * @return 两个参数的积
     */
    public static String mulByStr(String value1, String value2) {
    	if(StringUtils.isEmpty(value1)){//如果传递的未null 则会报空指针异常
    		value1="0";
    	}
    	if(StringUtils.isEmpty(value2)){
    		value2="0";
    	}
        BigDecimal b1 = new BigDecimal(value1);
        BigDecimal b2 = new BigDecimal(value2);
        return b1.multiply(b2).toString();
    }
//=========================验证是否为数字,如果是数字类型的防止数字被转为科学计数法类型======================================
    //考虑 科学计数法的使用,将数据转为 String原样输出
  	public static String switchNum(String str){
  		//Boolean strResult = str.matches("-?[0-9]+.?[0-9]*[Ee]?[+-]?\\d+");
  		Boolean strResult = str.matches("[\\+\\-]?[\\d]+([\\.][\\d]*)?([Ee][+-]?[\\d]+)?"); 
  		 if(strResult == true) {//说明是数字
  			return (new BigDecimal(str)).toString();
  		 }
  		 return str;
  	}
   /* public static void main(String[] args) {
		String num="9999999999.222222";
		String num2="10";
		String num3="9.999999999222221E9";
		BigDecimal b2 = new BigDecimal(num3);
		System.out.println(b2.toString()+"//======================");
		
		
		System.out.println(Double.valueOf(num));
		System.out.println(DoubleUtil.addByStr(num,num2));
		System.out.println(DoubleUtil.mulByStr(num,num2));
		System.out.println("//========================================");
		System.out.println(DoubleUtil.addByStr(num3,num2));
		System.out.println(DoubleUtil.mulByStr(num3,num2));
		
	}*/
}

17.200 获取项目路径

获取项目本地决定路径到tomcat下的wabapp下对应的项目下:request.getServletContext().getRealPath("/")

17.210 转义和反转义

转义和反转义(在做文件导入的时候可能会用到,可能需要阻止其转义,例如 ± ,可能需要原样保存到数据库中 )

  • 在页面中用htmlEscape="false" 来转义展示
<form:input path="rwdName" htmlEscape="false" maxlength="100" />
  • StringEscapeUtils.unescapeHtml 或者HtmlUtils.htmlUnescape

导包: import org.apache.commons.lang3.StringEscapeUtils;

//导包:  import org.apache.commons.lang3.StringEscapeUtils;
public static void main(String[] args) {     
	  String s = "<pre class=\"brush: java;\">";  
	  System.out.println(StringEscapeUtils.escapeHtml(s));  =========&lt;pre class=&quot;brush: java;&quot;&gt;
	          
	   String u = "<pre class=\"brush: java;\">";  
	   System.out.println(StringEscapeUtils.unescapeHtml(u));  =======<pre class="brush: java;">	
} 
//StringEscapeUtils.unescapeHtml(u)方法写在实体类中的对应的set方法中 
 public void setName(String name) {
           this.name = StringEscapeUtils.unescapeHtml(name);
}  
  • HtmlUtils.htmlUnescape
import org.springframework.web.util.HtmlUtils;
HtmlUtils.htmlUnescape()  //将数据库中已经转义的还原。 例如:&plusmn; 转为需要的 ±

17.220 java 包含

  • List.contains();
public static void main(String[] args){
    List<String>list = new ArrayList<String>();
    list.add("草莓");  //向列表中添加数据
    list.add("香蕉");  //向列表中添加数据
    list.add("菠萝");  //向列表中添加数据
    for(int i=0;i<list.size();i++){  //通过循环输出列表中的内容
    System.out.println(i+":"+list.get(i));
  }
  String o = "苹果";
  System.out.println("list对象中是否包含元素"+o+":"+list.contains(o));  //判断字符串中是否包含指定字符串对象
}

17.230 linux 系统下部署 jdk

https://blog.csdn.net/qq_34021712/article/details/69816837open in new window

https://blog.csdn.net/sxdtzhaoxinguo/article/details/43731677open in new window

1.下载linux下jdk安装包jdk-7u67-linux-i586.tar.gz 2.安装步骤 第一步:创建文件夹

mkdir /usr/local/java

第二步:将下载jdk安装包,上传到该目录下 第三步:解压缩

cd /usr/local/java   #进入目录
tar -zxvf jdk-7u67-linux-i586.tar.gz #解压缩
rm -rf jdk-7u67-linux-i586.tar.gz  #解压缩之后删掉,节省空间
ls -l #查看一下

第四步:备份环境变量文件

cd /etc 
cp profile profile_bak  #如果出错误了,还可以恢复

第五步:复制路径到环境变量中 路径为:/usr/local/java/jdk1.7.0_67

编辑profile文件

# 进入编辑默认
vi /etc/profile
# 输入 i
i
# 保存或取消
esc退出  :wq 确认  q! 取消

在profile文件的末尾加入如下命令:

JAVA_HOME=/usr/local/java/jdk1.7.0_67
JRE_HOME=$JAVA_HOME/jre
PATH=$PATH:$JAVA_HOME/bin:$JRE_HOME/bin
CLASSPATH=:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar:$JRE_HOME/lib
export JAVA_HOME JRE_HOME PATH CLASSPATH

3.测试安装是否成功 先使用命令 source /etc/profile 更新一下 再使用

java -version

17.240 cmd 命令模式下 查询进程和杀死进程

netstat -aon|findstr 5037

tasklist|findstr 21096

taskkill /f /t /im adb.exe
image-20210322172145307
image-20210322172145307

17.250 java 连接数据库

springboot mysql连接 https://blog.csdn.net/weixin_33901995/article/details/113326874open in new window

spring 项目 mysql 连接超时问题

https://blog.csdn.net/u013378306/article/details/80035912open in new window

spring boot项目

注意 本文针对springboot 1.3.5版本,不同版本配置会有差别

注意: 此处单为是毫秒 ms

spring boot 如果不设置spring.datasource.type,默认是使用tomcat-jdbc连接池

  • 使用tomcat-jdbc在application.properties
#验证连接的有效性  此处已定要设为true,不然 time-between-eviction-runs-millis 不起作用
  
spring.datasource.test-while-idle=true  
  
#获取连接时候验证,如果无效,则生成新的连接使用,会影响性能  (此处设为true最为保险,但是为影响性能)
spring.datasource.test-on-borrow=true  
  
  
spring.datasource.validation-query=SELECT 1 FROM DUAL  
  
#空闲连接回收的时间间隔,与test-while-idle一起使用,设置5分钟  
spring.datasource.time-between-eviction-runs-millis=300000  
  
#连接池空闲连接的有效时间 ,设置30分钟  
spring.datasource.min-evictable-idle-time-millis=1800000  

具体参数配置参看https://blog.csdn.net/u013378306/article/details/78085366open in new window

  • 使用druid

注意: 此处单为是毫秒 ms

pom.xml

<dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>1.0.23</version>
        </dependency>

application.properties

#druid datasouce database settings begin
spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/spring_boot?characterEncoding=utf-8
spring.datasource.username=root
spring.datasource.password=123456
 
# 下面为连接池的补充设置,应用到上面所有数据源中
# 初始化大小,最小,最大
spring.datasource.initialSize=5
spring.datasource.minIdle=5
spring.datasource.maxActive=20
# 配置获取连接等待超时的时间
spring.datasource.maxWait=60000
# 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
spring.datasource.timeBetweenEvictionRunsMillis=60000
# 配置一个连接在池中最小生存的时间,单位是毫秒
spring.datasource.minEvictableIdleTimeMillis=300000
spring.datasource.validationQuery=SELECT 1 FROM DUAL
<!-- 空闲时检测,此处已定要设为true,不然 timeBetweenEvictionRunsMillis不起作用-->
spring.datasource.testWhileIdle=true
#获取连接时候验证,如果无效,则生成新的连接使用,会影响性能  (此处设为true最为保险,但是为影响性能)
spring.datasource.testOnBorrow=false
<!-- 返回给线程池时检测连接有效性 -->
spring.datasource.testOnReturn=false
# 打开PSCache,并且指定每个连接上PSCache的大小
spring.datasource.poolPreparedStatements=true
spring.datasource.maxPoolPreparedStatementPerConnectionSize=20
# 配置监控统计拦截的filters,去掉后监控界面sql无法统计,'wall'用于防火墙
spring.datasource.filters=stat,wall,log4j
# 通过connectProperties属性来打开mergeSql功能;慢SQL记录
spring.datasource.connectionProperties=druid.stat.mergeSql=true;druid.stat.slowSqlMillis=5000
# 合并多个DruidDataSource的监控数据
spring.datasource.useGlobalDataSourceStat=true
#druid datasouce database settings end

17.270 JAVA中json转Map,jsonArray转List集合,List集合转json

https://blog.csdn.net/weixin_33446857/article/details/79171122open in new window

import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
 
 
import org.apache.commons.lang.StringUtils;
import org.zgr.pack.entity.test.TestJsonToList;
 
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
 
 
public class Util {
	    //json字符串转换为MAP
		public static Map jsonStrToMap(String s) {
			Map map = new HashMap();
			//注意这里JSONObject引入的是net.sf.json
			net.sf.json.JSONObject json = net.sf.json.JSONObject.fromObject(s);
			Iterator keys = json.keys();
			while (keys.hasNext()) {
				String key = (String) keys.next();
				String value = json.get(key).toString();
				if (value.startsWith("{") && value.endsWith("}")) {
					map.put(key, jsonStrToMap(value));
				} else {
					map.put(key, value);
				}
 
			}
			return map;
		}
		
		// 将jsonArray字符串转换成List集合
		public static List jsonToList(String json, Class beanClass) {
			if (!StringUtils.isBlank(json)) {
				//这里的JSONObject引入的是 com.alibaba.fastjson.JSONObject;
				return JSONObject.parseArray(json, beanClass);
			} else {
				return null;
			}
		}
		
		//List集合转换为json
		public static JSON listToJson(List list) {
			JSON json=(JSON) JSON.toJSON(list);
			return json;
		}
		
		
		public static void main(String[] args) {
			
			System.out.println("---------------------json字符串转换为MAP---------------------");
			JSONObject jsonObject=new JSONObject();
			jsonObject.put("abc", 123);
			jsonObject.put("def", 456);
			System.out.println("A==========json====="+jsonObject);
			Map map=Util.jsonStrToMap(jsonObject.toString());
			System.out.println("B==========def======"+map.get("def"));
			
			
			System.out.println("---------------------将jsonArray字符串转换成List集合---------------------");
			String str="[{\"year\":\"2015\",\"month\":10,\"count\":47},{\"year\":2017,\"month\":12,\"count\":4}]";
			//这里需要指定泛型,我们建立一个实体类TestJsonToList
			List<TestJsonToList> list=Util.jsonToList(str, TestJsonToList.class);
			System.out.println("C==========取list第二个元素的year====="+list.get(1).getYear());
			
			
			System.out.println("---------------------将list集合转换成json---------------------");
			//这里的JSONObject引入的是 com.alibaba.fastjson.JSONObject;
			JSON json=Util.listToJson(list);
			System.out.println("D==========json====="+json);
		}
}

实体类

public class TestJsonToList {
	private String year;      //年
    private String month;     //月
    private String count;     //数据
	public String getMonth() {
		return month;
	}
	public void setMonth(String month) {
		this.month = month;
	}
	public String getYear() {
		return year;
	}
	public void setYear(String year) {
		this.year = year;
	}
	public String getCount() {
		return count;
	}
	public void setCount(String count) {
		this.count = count;
	}
	
    //构造方法
    public TestJsonToList(String year, String month, String count) {  
        this.year = year;  
        this.month = month;  
        this.count = count;  
    }  
    //默认构造方法
    public TestJsonToList() {  
      
    }  
}

json转List集合,和List集合转json时需要注意,使用的是阿里的fastJson.jar包,不要引错了,Maven项目对应引入:

 <dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>fastjson</artifactId>
    <version>1.2.8</version>
</dependency>

17.290 maven jar 冲突

https://blog.csdn.net/loongshawn/article/details/50831890open in new window

项目jar包冲突,需要找到冲突的源在哪个依赖,然后过滤掉这个依赖即可。接下来进入本地的工程目录,执行以下命令,获取依赖树:

​ 项目根目录下执行 mvn dependency:tree

<!-- OSS Java SDK -->
<dependency>
    <groupId>com.aliyun.oss</groupId>
    <artifactId>aliyun-sdk-oss</artifactId>
    <version>2.2.0</version>        
    <exclusions> <!-- 过滤掉 aliyun-sdk-oss.jar中冲突 httpclient.jar -->
        <exclusion>
        	<groupId>org.apache.httpcomponents</groupId> 
        	<artifactId>httpclient</artifactId>                    
        </exclusion> 
    </exclusions> 
</dependency>   

19.300 阿里云OSS

待整理:阿里云OSS附件上传 https://blog.csdn.net/z1c5809145294zv/article/details/108344155open in new window

https://aliyun_portal_storage.oss.aliyuncs.com/oss_api/oss_javahtml/index.html

https://blog.csdn.net/u014559227/article/details/70888249open in new window

https://blog.csdn.net/linlin_0904/article/details/84583676open in new window

https://blog.csdn.net/fangside/article/details/113767360open in new window //简单完整案例

https://blog.csdn.net/weixin_39507514/article/details/90799073open in new window base64

https://blog.csdn.net/yuanyuan5201/article/details/109292046open in new window oss压缩下载

  • 需要注意的是。上传的文件名中不能有 + 号,否则无法访问 ;
  • 路径不能有反斜杠,正确的 形式 proj/202104/xx.txt ,OSS会自动创建 文件夹 proj和202104
	private static String BUCKETNAME="lishihuan";// Buket名称
	private static String ACCESSKEYID="LTAI5t75a7pjcLnuhY4pPVyK";//AccessKey ID
	private static String ACCESSKEYSECRET="NZIXJbkW7V2necehbaGVZHh9G0IrOj";//AccessKey Secret
	private static String ENDPOINT="https://oss-cn-shanghai.aliyuncs.com";// 域名
	private static String BUCKET_DOMAIN_URL="https://lishihuan.oss-cn-shanghai.aliyuncs.com";// EndPoint(地域节点)

需要5个参数,endpoint,accessKeyId,accessKeySecret 三个用来连接OssClient客户端。bucketName 域名是用来上传数据 BUCKET_DOMAIN_URL

OSS client = new OSSClientBuilder().build(this.endpoint,this.accessKeyId,this.accessKeySecret);// 创建连接
/**
* bucketUrl 相对路径+文件名 ( proj/202104/xx.txt)
*/
client.putObject(this.bucketName, bucketUrl, new File(fileRootPath));// 上传 文件
client.shutdown();

//前端访问
String url = BUCKET_DOMAIN_URL+"/"+bucketUrl;

17.310 java 对集合的处理

整理 Collections3.java

2. 前端处理 后端方回的list集合

var listJson=${fns:toJson(list)};

19.html

height: calc(100% - 73px);

元素 常用到的几个 单词

  • wrap: 容器
  • popup:弹出
  • Popover:弹窗窗口
  • content:内容
  • title: 标题

开发常用的几个css

/**
 放置一些  公共样式
 */
/*公共样式*/
.popup_window {
    padding: 0;
    margin: 0;
    width: 100%;
}

/*弹窗样式*/
.popup_window{
    color: #FFFFFF;
    height:100%;
}
/* 弹窗主色调 */
.popup_window_background{
    color: #FFFFFF;
    /*background: rgba(60, 61, 115, 0.3);*//* rgba(0,56,114,0.8); */
    box-shadow: 0px 0px 15px 0px rgba(24, 249, 234, 0.25);
}
/*隐藏*/
.none {
    display: none;
}
.pr{
    position: relative;
    /*display: flex*/
}
.pa{
    position: absolute;
}
/*辅助开发*/
.bk{
    border: 1px solid #ccc;
    box-sizing: border-box;
}
/*重要属性,设置元素padding 等属性 也可以保证 元素不超出父容器*/
.bs{
    box-sizing: border-box;
}
/*居中*/
.ty_50{
    top: 50%;
    position: absolute;
    transform:translateY(-50%)
}
/*居中 不能 对行内元素使用,例如 display: inline-block;*/
.div_text_jz{
    display: flex;
    align-items: center;
}
/*对行内元素 垂直居中*/
.div_text_jz2{
    display: inline-flex;
    align-items: center;
}
/*搭配  div_text_jz  用于水平居中*/
.jc_c{
    justify-content: center;
}
/* 竖向排列并居中*/
.vertical_pl{
    display: flex;
    flex-direction: column;
    justify-content: space-between;
    align-items: center;
}
/*盒子模型中两端对其*/
.jc_sb{
    justify-content:space-between;
}
/* 右对齐*/
.align_right{
    display: flex;
    align-items: center;
    justify-content: flex-end;
}
/* 自动换行 并且垂直居中*/
.flex_auto{
    display: flex;
    flex-flow: row wrap;
    align-items: center;
}
/* 水平居中*/
.ta-c{
    text-align: center;
}
/*光标*/
.cursor_pointer{
    cursor:pointer;/*光标样式-小手*/
}
.cursor_default{
    cursor:default;/*光标样式 指针*/
}
/*超长*/
.overlength{
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.overlength1{
    display:block;
    text-overflow: ellipsis;
    white-space: nowrap;
}
/*块元素转  行内块元素*/
.dib{
    display:inline-block;
    vertical-align:top
}
.di{
    display:inline;
}
.fl{
    float: left;
}
/*弹窗内容部分*/
/*内容部分中,标题  */
.content_title{
    color: #FFFFFF;
}
.content_color{
    color:#4FF0FD;
}
/*搭配  display: inline-block*/
.f0{
    font-size: 0;/*子元素 用 display: inline-block; 会导致 元素之间 存在空隙 所以设置  font-size: 0*/
}
/*高亮颜色*/
.highlight_font{
    color: #4deaf8;
}

.h25{
    line-height: 25px;
    height: 25px;
}
.h30{
    line-height: 30px;
    height: 30px;
}

.f18{ font-size: 18px; }.f20{font-size: 20px;}.f22{ font-size: 22px; }.f25{font-size: 25px;}.f30{font-size: 30px;}.f35{font-size: 35px;}

.pl20{
    padding-left: 20px;
    box-sizing: border-box;
}
.p20{
    padding: 20px;
}
.wh100{
    width: 100%;
    height: 100%;
}
.left_top_005{
    background: url(../map/3DmapImages/tower/tower_left_f_005.png) no-repeat center;
    background-size: 100%100%;
    width:762px;
    height:150px;
}
.left_top_005_ls{
    background: url(../map/3DmapImages/tower/tower_left_f_005_ls.png) no-repeat center;
    background-size: 100%100%;
    width:762px;
    height:150px;
}

.main_background {
    background-color: rgb(52, 106, 181, 0.8);
    color: #FFFFFF !important;
    box-shadow: 0px 0px 15px 0px rgba(24, 249, 234, 0.25);
}
.div_button{
    box-shadow: 0 0 10px #4a90d8 inset, 0px 0px 30px rgb(0,153,184);
    font-family: Microsoft YaHei;
    font-size: 1.2em;
    font-weight: 600;
    text-align: center;
    display: flex;
    align-items: center;
    justify-content: center;
    box-sizing: border-box;
    cursor: pointer;
    height: 100%;
    color: #f5f5f5;
    border: 1px solid #2f4aa1;
    background: #0e3056;
}
.zdy_button:hover  {
    transform: scale(1.1);
    transition: all 0.6s;
}
.zdy_button:active {
    opacity: 0.1;
    transform: scale(1.1);
}
.div_button:hover  {
    transform: scale(1.1);
    transition: all 0.6s;
}
.div_button:active {
    opacity: 0.1;
    transform: scale(1.1);
}
/*文字两端 对其,,在父容器上*/
.justify {
    justify-content: space-between;
    display: inline-flex;
    align-items: center;
}
.hidden{
    display: none;
}


/*自定义滚动条*/
.resultHtml{
    overflow: auto;
}
.resultHtml::-webkit-scrollbar { /*滚动条整体样式*/
    width: 4px; /*高宽分别对应横竖滚动条的尺寸*/
    height: 4px;
}

.resultHtml::-webkit-scrollbar-thumb { /*滚动条里面小方块*/
    border-radius: 10px;
    -webkit-box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.2);
    background: #535353;
}

.resultHtml::-webkit-scrollbar-track { /*滚动条里面轨道*/
    -webkit-box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.2);
    border-radius: 10px;
    background: #EDEDED;
}
/* 自定义弹出层*/
.popup_wrap{
    height: 200px;
    width: 150px;
    box-shadow: 0 0 10px #4a90d8 inset, 0px 0px 30px rgb(0,153,184);
    font-family: Microsoft YaHei;
    font-size: 1.2em;
    font-weight: 600;
    text-align: center;
    display: flex;
    align-items: center;
    justify-content: center;
    box-sizing: border-box;
    cursor: pointer;
    background: rgb(0,0,0,0.8);
    color: #f4f4f4;
    border-radius: 5px;
    opacity: 0;
    left: 0px;
    top: 0px;
    padding: 10px;
    z-index: 999;
}
.popup_wrap .item{
    padding: 5px 0;
    transition: all 0.6s;
    display: flex;
    align-items: center;
    justify-content: center;
}
.popup_wrap .item:hover{
    color: #13c3e3;
    background: #0e3056;
    /*transform: scale(1.1);*/
}
.popup_wrap .item.check{
    color: #13c3e3;
    background: #0e3056;
    /*transform: scale(1.1);*/
}
.popup_icon{
    padding-right: 10px;
}
/* HTML中解决双击会选中文本的问题*/
.html_wrap{
    -webkit-user-select: none;
    -moz-user-select: none;
    -ms-user-select: none;
    user-select: none;
}


/* 标签*/
.right_label_wrap{
    position: absolute;
    padding: 3px 6px;
    border: 1px solid #cca4e3;
    border-radius: 5px;
    background-color: rgb(87, 189, 77,0.4);
    /*box-shadow: 0 0 10px #4a90d8 inset, 0px 0px 30px rgb(0,153,184);*/
    box-shadow: 0px 5px 5px #888888;
    display: flex;
    align-items: center;
    box-sizing: border-box;
    color: #f5f5f5;
}
/* 动画 可以 作为 图片按钮 */
.img_button:hover{
    transform: scale(1.1);
    transition: all 0.6s;
}
.img_button:active{
    animation-name: example;
    animation-duration: 4s;
}
@keyframes example {
    0%   {opacity: 0;}
    25%  {opacity: 1;}
    50%  {opacity: 0.4;}
    100% {opacity: 1;}
}
/* 响应式 Web 设计 - 网格视图*/
* {
    box-sizing: border-box;
}
.row:after {
    content: "";
    clear: both;
    display: block;
}
[class*="col-"] {
    float: left;
}
.col-1 {width: 8.33%;}
.col-2 {width: 16.66%;}
.col-3 {width: 25%;}
.col-4 {width: 33.33%;}
.col-5 {width: 41.66%;}
.col-6 {width: 50%;}
.col-7 {width: 58.33%;}
.col-8 {width: 66.66%;}
.col-9 {width: 75%;}
.col-10 {width: 83.33%;}
.col-11 {width: 91.66%;}
.col-12 {width: 100%;}
/* 自定义 table 搭配 上面的 网格视图*/
.table_row {
    margin: 10px 0 0 0;
    background: rgba(3, 135, 188, 0.2);
    display: flex;
    align-items: center;
}
.table_col {
    height: 50px;
    line-height: 50px;
    font-size: 20px;
    font-family: Source Han Sans CN;
    font-weight: bold;
    color: #B8EAFF;
    text-align: center;
    padding: 0 10px;
    cursor: default;
    overflow: hidden;
    text-overflow: ellipsis;
    display: block;
}
.table_row:hover{
    /*transform: scale(1.1);*/
    background: rgba(3, 135, 188, 0.6);
}
.table_title {
    height: 73px;
    font-size: 25px;
    font-family: Source Han Sans CN;
    font-weight: bold;
    color: #B8EAFF;
    /* margin-bottom: 10px; */
}

/* 自定义 input 设置为 透明 ,去掉边框 */
.zdy_input{
    width: 90px;
    height: 100%;
    font-size: 1.2vh;
    font-weight: 400;
    color: #f5f5f5 !important;
    margin: 0px !important;
    /*border: 1px solid #2f4aa1 !important;*/
    border: none !important;
    box-sizing: border-box;
    background: none !important;
}


.plf5{padding-left:5px;padding-right:5px;}
.plf10{padding-left:10px;padding-right:10px;}
.plf15{padding-left:15px;padding-right:15px;}
.plf20{padding-left:20px;padding-right:20px;}
.br10{border-radius: 10px;}

案例:居中

image-20201028193829196
image-20201028193829196
/*使用 display: flex;   
	说明:display: flex实现块转行内元素 (不用使用display:inline-block 属性实现,因为需要父节点字体大小为0))
		然后使用  align-items: center; justify-content: center 实现垂直,水平居中
*/
<div class="box_background_style"><!--box_background_style 背景图片 -->
    <div class="div_text_jz bs cursor_pointer">
        <div class="div_text_jz jc_c" style="width: 80%;height: 100%;">天气情况</div>
        <div class="div_text_jz jc_c" style="width: 20%;height: 100%;">
            <img src="${ctxStatic}/dvp3D/imgs/ionic_002.png" >
        </div>
    </div>
</div>
<style>
.box_background_style{
    background: url(${ctxStatic}/dvp3D/imgs/ionic_001.png) no-repeat center;
    background-size: 100% 100%;
    width: 258px;
    height: 84px;
}
</style>

案例: 获取鼠标图片放大

<!DOCTYPE html>
<html>
	<head>
		<meta charset="UTF-8">
		<title></title>
		<style type="text/css">
			div{/*默认图片样式*/
				width: 300px;
				height: 300px;
				border: #000 solid 1px;
				margin: 50px auto;
				overflow: hidden;
			}
			div img{/* 动画 延迟*/
				cursor: pointer;/**/
				transition: all 0.6s;/*动画*/
			}
			div img:hover{/* 获取光标 放大1.4倍*/
				transform: scale(1.4);
			}
		</style>
	</head>
	<body>
		<div>
			<img src="img/focus.png" />
		</div>
	</body>
</html>

19.1中元素居中

  • 利用相对定位
parentElement{
	position:relative;
}
childElement{
	position: absolute;
	top: 50%;
	transform: translateY(-50%);
}
baseline默认。元素放置在父元素的基线上。
sub垂直对齐文本的下标。
super垂直对齐文本的上标
top把元素的顶端与行中最高元素的顶端对齐
text-top把元素的顶端与父元素字体的顶端对齐
middle把此元素放置在父元素的中部。
bottom把元素的顶端与行中最低的元素的顶端对齐。
text-bottom把元素的底端与父元素字体的底端对齐。
length
%使用 "line-height" 属性的百分比值来排列此元素。允许使用负值。
inherit规定应该从父元素继承 vertical-align 属性的值。

可以控制图片、文字等行内元素在行内的垂直方向上的对齐方式

如何使用vetical-align使块级元素垂直居中?

以下面为例:

<body>
	<div class="wrapper">    
		<div class="content">some content</div>  
	</div>
</body>

1、为父容器wrapper设置高度

html,body{
	height:100%
}
.wrapper{
	height:100%
}

2、使content容器变为行内元素

.content{  display:inline-block;}

3、利用before伪元素在content容器之前构造一个空内容的inline-block

.wrapper:before{  content:"";  display:inline-block;  height:100%;  vertical-align:middle;}

此时,整个页面只有一行,其中有两个inline-block,让空内容行内上下对齐

4、为content容器添加vetical-align属性

.content{
	vetical-align:middle;
}

这样,块级元素在浏览器中始终都是垂直对齐的

19.2几种居中的方法总结

  • 元素 竖排,并且居中
  1. ​ display: flex;
  2. ​ flex-direction: column;
  3. ​ justify-content: space-between;
  4. ​ align-items: center;
  • 1.vertical-align: middle

  • 2.position: absolute;top: 50%;transform: translateY(-50%),

  • 3.height,line-height

  • 4.不设置高度,通过padding 将内容撑起来

    1. 父:display: flex;子:align-self: center; (垂直居中) align-items: center;(水平居中)

    在父节点上添加 注:display: inline-flex; inline-flex对 行类块元素使用,替代 display: inline-block块转行;display: flex;对块元素使用

    display: flex;定义下的子元素 默认水平排列

	align-items: center;/*默认水平排列,如果想竖向排列 还需加 flex-direction: column;*/
    justify-content: center;/*子元素水平居中*/
    display: inline-flex;/*inline-flex对 行类块元素使用;display: flex;对块元素使用*/
  • 子项使用 margin:auto

需要注意,text-align: center; 正对 文本,在快元素是不支持的,比如div中子div 水平居中,如果子项

<!-- 场景1 使用 text-align: center; 那么需要将 子项div 转为行内元素(或行内块元素) --> 
<style>
    .f_div{
        text-align: center;
        border: 1px solid #ccc;
        width: 100%;
        height: 320px;
        top: 40px;
    }
    .z_div{
        width: 300px;
        background: red;
        height: 100%;
        /* margin: auto; */
        border: 1px solid #ccc;
        display: inline-block;
    }
    
</style>

<div class="f_div" id="map_xunjian_count" style=" ">
    <div class="z_div">div水平居中</div>
</div>
<!-- 场景2 子项div 不转为 行内元素,则 需要使用 --> 
<style>
    .f_div{
        /*text-align: center; 取除,对 块元素不起作用 */
        border: 1px solid #ccc;
        width: 100%;
        height: 320px;
        top: 40px;
    }
    .z_div{
        width: 300px;
        background: red;
        height: 100%;
        margin: auto;
        border: 1px solid #ccc;
        /*display: inline-block;*/
    }
    
</style>

<div class="f_div" id="map_xunjian_count" style=" ">
    <div class="z_div">div水平居中</div>
</div>

案例 img标签在div中水平垂直居中

  • 第一种方式: text-align:center; vertical-align:middle;
<style>
    div{
        text-align: center;
        vertical-align:middle;width: 400px;
        height: 400px;
        border: 1px solid #000;
    }
    img{vertical-align: middle}
    span{height: 100%;vertical-align: middle;display: inline-block}
</style>
<div style="">
    <span></span>
    <img src="ad-pic.png" alt="" style="border: 1px solid #000;">
</div>
  • 第二种
<div  style="position: relative;padding: 8px 8px 8px 50px;">
		<img src="img/kaoqin.png" alt="" style="height: 20px;position: absolute;top: 50%;transform: translateY(-50%);left: 16px;">
		<span style="">到位情况:</span><span>未到位到位沃尔沃欸范围划分骗我呢覅普无不佩服违法未u符合我二号</span>
</div>
img
img

注: 第二种方法,待定,父节点下的img 不应该设置 top: 50%;transform: translateY(-50%); 而是 内容高度和图片高度设置一致,然后由padding 将内容撑起,其中父节点也不设置 height,line-height

最优

img
img
<div style="position: relative;padding: 16px 0 16px 50px;font-size: 25px;">
<img src="/TPCloud/static/map/3DmapImages/ionic001.png"  style="width:40px;left: 0px;position: absolute;">
	<div class="dib">GT信息</div>
</div>
  • 第三种 使用 height,line-height
<div  style="border: 1px solid #ccc;text-align: center;width: 50px;height: 50px;line-height: 48px;border-radius: 50%;">内容</div>

第四种方式 :不设置高度,通过padding 将内容撑起来

img
img
.item {
  margin: -1px;/*上图中出现的左右测的边线 可以通过,margin:-1px隐藏再容器中*/
  padding: 16px;
  border: 1px solid #ddd;
}
/* 超长字符的处理,white-space: nowrap; 是用省略号代替,white-space: inherit; 不显示,自动可以强制换行*/
.item-content p {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
  • 第五种: 父节点设置display:flex; 子节点设置 align-self: center 属性(目前最优)

19.4 盒子模型 display: flex;

垂直居中

水平居中

两端对齐

从上到下,单行 排列

设置 文字 靠右

display: flex;
justify-content: flex-end;

flex-flow: row wrap;

display: flex;
            flex-flow: row wrap;
            align-items: center;

19.3 使用 position:absolute 下的水平居中

场景在地图开发中添加的标题 需要 使用相对定位 脱离文档流

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width">
  <title>JS Bin</title>
  <style>
  .con{
      width:200px;
      height:200px;
      background:#ccc;
      position:relative;
    }
  </style>
</head>
<body>
<div class="con">
  <div class="abs"></div>
</div>
</body>
</html>

css 实现: 2种 方式 ,第一种使用 margin:0 auto; 第二种使用 transform:translate(-50%);

/*
	场景1:核心在于  left:0; right:0; margin:0 auto;
*/
.abs{
  width:40px;
  height:20px;
  background:steelblue;
  position:absolute;
  bottom:0;
  left:0;/**/
  right:0;
  margin:0 auto;
}
/*
	场景2:核心在于 left:50%; transform:translate(-50%);
*/
.abs{
  width:40px;
  height:20px;
  background:steelblue;
  position:absolute;
  bottom:0;
  left:50%;
  transform:translate(-50%);
}

案例 :图片+多行文字 布局

image-20201123192717342
image-20201123192717342
<style>
	.menu_div{
        width: 300px;
        color: #ffffff;
        -webkit-border-radius: 15px !important;
        padding: 0px 14px 0px 120px;
	}
	.meun_div_img{
	  width: 32%;
      position: absolute;
      top: 50%;
      transform: translateY(-50%);
      left: 8px;
	}
	.meun_div_a{
	 	color: #18eaf9;
          vertical-align: bottom;
          font-size: 40px !important;
          font-family: 'electronicFont';
	}
</style>
<div class="bs pr main_background menu_div">
  <img src="/CPMS/static/map/arcgis4.x/images/left_meun/ionic_left_menu_002.png" class="meun_div_img"/>
  <div class="overlength" style="font-size: 25px; padding: 10% 0px; width: 100%" >
    <div style="padding-bottom: 10px">今日在建工程数</div>
    <div style="text-align: center">
      <a class="meun_div_a" >0</a>
      <span style="font-size: 20px">(项)</span>
    </div>
  </div>
</div>

19.6 案例 (需要完善,很多class属性没记录下来)

<div class="searchBox" style="padding:30px 20px;">
	<p class="inBox top00" style="width: 70%;display: inline-block;">
		<i class="icon ion-ios-search placeholder-icon"></i>
		<input style="background: #EEEEEE;color:#000000;height: 40px;border-radius: 22px;" ng-change="changeSearch()" ng-model="inputSearch"                 type="text" placeholder="请输入关键字..." />
	</p>
	<button class="button button-clear button-primary" style="color: #0CABA4;position: absolute;top: 50%;transform: translateY(-50%);right: 		10px;" ng-click="modal.remove()">取消</button>
</div>	
img
img

19.7 HTML行内元素、块状元素、行内块状元素的区别open in new window (行转块)

HTML可以将元素分类方式分为行内元素、块状元素和行内块状元素三种。这三者是可以互相转换的,使用display属性能够将三者任意转换:

  • display:inline;转换为行内元素

    特点:

    • m没有宽和高;
    • 元素和其他元素共占一行;
  • display:block;转换为块状元素

    块级元素的特点是:可以给元素设置宽高,元素独占一行;

  • display:inline-block;转换为行内块状元素

使用display:inline-block 会出现2个问题

  1. 错位

解决

.dib{
  	display:inline-block;
    vertical-align:top;
  }

2.换行,2个div中间出现空隙,导致换行(display:inline-block表示行内块元素,后面自带空格字符)

解决:在父系上加font-size:0 注:一定是在 父 节点上加 font-size:0px

对于 table:每个tr存在间隙 用 border-spacing:0;

添加padding,添加边框等 导致 超出父容器 处理

/*元素添加padding,为了防止超出父容器,添加box-sizing: border-box; 属性*/
.p20{
	padding: 20px;
	box-sizing: border-box;
}

19.8 html 常用的一些属性

  • div 内的文本不能换行 可能 white-space: normal;

  • 固定底部 (定位最下面)position: fixed

  • 透明度

    • opacity设置颜色然后透明度(但是会导致文字也模糊了) background-color: #658fce; opacity: 0.8;
  • background: rgba(0, 0, 0, 0.5)

.main_background{
        background-color:rgb(52, 106, 181,0.6);
        color: #FFFFFF !important;
        box-shadow: 0px 0px 15px 0px rgba(24, 249, 234, 0.25);
}
  • align 控制元素位置
    • left 左对齐内容。
    • right 右对齐内容。
    • center 居中对齐内容。
    • justify 对行进行伸展,这样每行都可以有相等的长度(就像在报纸和杂志中)。
  • text-align:center; 水平居中
  • vertical-align:middle; 垂直居中 ( vertical-align: bottom; 可使div 中的文字 底部靠齐)
  • 文字的间距 .divcss5
  • 行间距(行高)line-height:30px
  • 去掉边框 style="border: medium none;" 或者style="border:none;"
  • 元素的显示和隐藏
<div  id="ceshi" style="display:none;"></div>		---元素被隐藏
在js方法中 $("#ceshi").show();					---影藏的元素显示出来
 			$("#tianjiaHtml").show();
			$("#hiddenHtml").css("display","none")
$("#btnSubmit").removeAttr("disabled"); --------取消某个属性  对于disabled  属性  一但使用 对应的控件是无法通过  设置属性attr("disabled","flase");来取消的
display:none或visibility:hidden
visibility:hidden可以隐藏某个元素,但隐藏的元素仍需占用与未隐藏之前一样的空间。也就是说,该元素虽然被隐藏了,但仍然会影响布局

显示:style="display:block"或者 $('#div_1').show();
隐藏:style="display:none"或者$('#div_2').hide();
  • title 信息提示
<tr title="${task.rwdName}&#13;${task.office.name}&#13;${task.substation.name}">  <!--注:  &#13;是用来换行-->
  • 删除按钮,那么可以("#....").empty() 或者是.html(" ")--------删除的是标签的内容 ,,如果要删除标签用("#...").remove(); $(this).next("label").remove();

  • transform 旋转、缩放、倾斜、移动,变形 CSS3中的变形处理

https://blog.csdn.net/qq_40542728/article/details/81979163open in new window

https://developer.mozilla.org/zh-CN/docs/Web/CSS/transformopen in new window

transform的scale缩放属性,搭配 transform-origin属性 可进行页面适配,同样的还有zoom属性

暂时没做总结

于这个属性搭配的 transform-origin

  • 注: 页面中 元素位置移动可以通过 append 将指定的元素 迁移到 指定的位置

    ​ 例:A元素下有一个 div 想将 这个div迁移到 B元素下,直接(B).append((B).append((A).children())

transform: translate3d(0px, 0px, 0px) scale(1);/* 定义元素位置和 大小*/
  • 设置渐变色
background: radial-gradient(rgb(5 243 251) 12%,rgb(21 67 77)80%);
background: -webkit-gradient(linear,0 0,0 bottom, from(rgba(255,140,17,0.7)),to(#ff8c11));

background: linear-gradient(8deg,rgb(15,229,236,0.1) 20%,rgb(11 232 232 / 80%) 82%,rgb(15,229,236,0.2) );//
/* 一条竖线*/
border-right: 10px solid;
border-image: linear-gradient(rgb(21 67 77),rgb(5 243 251),rgb(21 67 77))1 10 1;
  • 圆角 radius
border-top-right-radius: 5px;
border-top-left-radius: 5px;

border-radius: 5px;
  • 指针(光标)
<html>
<body>
  <p>请把鼠标移动到单词上,可以看到鼠标指针发生变化:</p>
  <span style="cursor:auto">光标</span><br />
  <span style="cursor:crosshair">十字</span><br />
  <span style="cursor:default">指针</span><br />
  <span style="cursor:pointer">小手</span><br />
  <span style="cursor:move">移动</span><br />
  <span style="cursor:e-resize">左右拉</span><br />
  <span style="cursor:ne-resize">对角拉</span><br />
  <span style="cursor:nw-resize">对角拉</span><br />
  <span style="cursor:n-resize">上下拉</span><br />
  <span style="cursor:se-resize">对角拉</span><br />
  <span style="cursor:sw-resize">对角拉</span><br />
  <span style="cursor:s-resize">上下拉</span><br />
  <span style="cursor:w-resize">左右拉</span><br />
  <span style="cursor:text">光标</span><br />
  <span style="cursor:wait">等待</span><br />
  <span style="cursor:help">问好</span>
</body>
</html>
  • 阴影 box-shadow
box-shadow: 0px 0px 15px 0px rgba(24, 249, 234, 0.4);
box-shadow: 0 0 10px #178236 inset, 0px 0px 30px rgb(0,153,184);
  • css选中器
  <div class="f1 f1_1"></div>
  <!-- 
  	.f1.f1_1{} 表示 当前元素 有class='f1 f1_1'  <div class="f1 f1_1"></div>
  	.f1 .f1_1{} 中间有个空格,表示 class="f1" 下一个子元素 有个class="f1_1"  <div class="f1"> <div class="f1_1"></div></div>
  -->
  • calc
height: calc(100% - 165px);
  • 标题使用时用 font-weight: 900; 设置还是不够粗 ,可以设置字体
font-family: Arial, Helvetica, sans-serif;/* 字体会显得粗*/ 

蘋果儷細宋:Apple LiSung Light

Windows的一些:

新細明體:PMingLiU

細明體:MingLiU

標楷體:DFKai-SB

黑体:SimHei

新宋体:NSimSun

仿宋:FangSong

楷体:KaiTi

仿宋_GB2312:FangSong_GB2312

楷体_GB2312:KaiTi_GB2312

微軟正黑體:Microsoft JhengHei

微软雅黑体:Microsoft YaHei

装Office会生出来的一些:

隶书:LiSu

幼圆:YouYuan

华文细黑:STXihei

华文楷体:STKaiti

华文宋体:STSong

华文中宋:STZhongsong

华文仿宋:STFangsong

方正舒体:FZShuTi

方正姚体:FZYaoti

华文彩云:STCaiyun

华文琥珀:STHupo

华文隶书:STLiti

华文行楷:STXingkai

华文新魏:STXinwei

font-family,好看常用的字体

转载自http://www.zreading.cn/ican/2014/10/css-font-family/open in new window

例1(小米米官网):font-family: "Arial","Microsoft YaHei","黑体","宋体",sans-serif;

例2(淘宝技术研发中心):font: 12px/1.5 Tahoma,Helvetica,Arial,'宋体',sans-serif;

例3(加网 ):font: 14px/1.5 'Microsoft YaHei',arial,tahoma,\5b8b\4f53,sans-serif;

例4(淘宝UED):font: 12px/1 Tahoma,Helvetica,Arial,"\5b8b\4f53",sans-serif;

例5(一淘UX):font-family: Helvetica, 'Hiragino Sans GB', 'Microsoft Yahei', '微软雅黑', Arial, sans-serif;

@font-face {
    font-family: 'electronicFont';
    src: url("${ctxStatic}/map/arcgis4.x/images_new/LESLIEB_.TTF");
}

19.9 案例

img
img
<div style="bottom:0px;position:fixed;height: 62px;z-index: 2147483647;padding: 7px;width: 100%;background-color: #FAFAFA;" ng-show="!!shareImgFlag">
	<div  style="width:33.333333333%;position:relative;;float:left;text-align: center;">
		<img src="img/ionic0022.png" width="30" height="30">
		<div style="text-align: center;">分享</div>
	</div>
	<div  style="width:33.333333333%;position:relative;;float:left;text-align: center;">
		<img src="img/ionic0023.png" width="30" height="30">
		<div style="text-align: center;">全选</div>
	</div>
	<div  style="width:33.333333333%;position:relative;;float:left;text-align: center;">
		<img src="img/ionic0020.png" width="30" height="30">
		<div style="text-align: center;">取消</div>
	</div>
</div>

19.10 html 定位

https://www.cnblogs.com/theWayToAce/p/5264436.htmlopen in new window

关于html中的定位(相对定位和绝对定位) position: relative; 和 position:absolute;

relative是根据父元素定位的.absolute则会找他的父元素,直到找到一个position属性不是static的父元素,可能是它的上一层,也可能是好几层,如果都没有定义position属性的话,那将根据body定位.还有一个区别是:relative的元素,不管你怎么改变top或是left,他原来的那一块div的位置还是存在着的,会占着那边.如果有人挤掉了那一块,那他的位置也会改变.如果是absolute的话,他就不占位置了,除非自己所定位的父元素产生改变,不然就不会改变.

例1:将d2放在d1的有上角 (绝对定位,将元素放在指定位置)

#d1{position:relative;}
#d2 {position: absolute;left: 30px;top: 20px;}

<div id="d1">
	<div id="d2"></div>
</div>

例2:在页面指定中增加一个图标(图片) 绝对定位

img{
	position:absolute;right:5%;top:5%;z-index:1;
	opacity:0.5;/*设置图片的透明度*/
}
  1. 浮动定位 float: left; 和float:right;

在div中设置几个元素,实现并排安放在指定位置

<div >
	<div style="width: 60%; float: left;">消息标题</div>
	<div style="width : 40%; float: left;">消息内容</div>
</div>

19.11 表单控件

  • 滑块控件 <input type="range" id="myRange">

    img
    img
  • 只读

    • 文本框等只读 readOnly="true"

    • 下拉选,时间选择插件 设置 disabled="true" 表单在提交时要将,disabled移除掉,,否则对应字段数据无效$("#status").removeAttr("disabled", true);

19.12 鼠标悬停事件

鼠标悬停图片放大(利用css方法)

<style type="text/css">
   img{  
		cursor: pointer;  
		transition: all 0.6s;  
	}  
	img:hover{  
		transition: all 1s ease 0s;  
		transform: scale(1.6);/*放大的倍数,所以在元素上要有图片的尺寸大小 。如:style="height:100px;width:100px;" */
	}
</style>

鼠标悬停修改图片src

.choose-menu:hover{
    backgroud-position:0 40px;
    transition:background-position 0.3s;
    content: url('${ctxStatic}/map/images/dmap/ionic020.png');
}
.choose-menu:visited{
    backgroud-position:0 0;
    transition:background-position 0.3s;
    content: url('${ctxStatic}/map/images/dmap/ionic020_1.png');
}

案例:动画效果 鼠标放到图片中 显示 标签

动画效果,通过 设置opacity 透明度,或高度、宽度 来达到隐藏显示效果,再加上 transition:1s; 添加点动态效果

.waterDiv{/*子项 先隐藏*/
    /*opacity是不透明度*/
    opacity: 0;/*先隐藏获取光标 显示*/
    width:0;
    height: 0;
    /*transition写在这里才是.yuan5常有的属性,无论出现还是消失都会有动画的效果*/
    transition:1s;
    overflow:hidden;/*如果圆圈中的数字超过区域就隐藏*/
}
.borderDiv:hover .waterDiv{
    /*如果将transition写在这里的话,只有当鼠标悬停在.yuan4上的时候才会有效果,
         当鼠标移出.yuan2的区域时,因为不出发hover的条件,所以消失的时候就没有变化效果了,
         结果就是瞬间消失*/
    opacity: 1;
    width:20px;
    height: 20px;
}
img
img

案例:关闭按钮,初始,隐藏,active 后 右移 显示,动画效果


.search-wrapper .close {
    position: absolute;
    z-index: 1;
    top:24px;
    right:20px;
    width:25px;
    height:25px;
    cursor: pointer;
    -webkit-transform: rotate(-180deg);
    -moz-transform: rotate(-180deg);
    transform: rotate(-180deg);
    -webkit-transition: all .3s cubic-bezier(0.285, -0.450, 0.935, 0.110);
    -moz-transition: all .3s cubic-bezier(0.285, -0.450, 0.935, 0.110);
    transition: all .3s cubic-bezier(0.285, -0.450, 0.935, 0.110);
    -webkit-transition-delay: 0.2s;
    -moz-transition-delay: 0.2s;
    transition-delay: 0.2s;
    opacity: 0;
}
.search-wrapper.active .close {
    right:-50px;
    -webkit-transform: rotate(45deg);
    -moz-transform: rotate(45deg);
    transform: rotate(45deg);
    -webkit-transition: all .6s cubic-bezier(0.000, 0.105, 0.035, 1.570);
    -moz-transition: all .6s cubic-bezier(0.000, 0.105, 0.035, 1.570);
    transition: all .6s cubic-bezier(0.000, 0.105, 0.035, 1.570);
    -webkit-transition-delay: 0.5s;
    -moz-transition-delay: 0.5s;
    transition-delay: 0.5s;
    opacity: 1;
}

19.13动画:淡入,淡出

https://www.cnblogs.com/shark1100913/p/6266548.htmlopen in new window

https://www.html.cn/doc/css3/animations/index.htmlopen in new window

https://www.html.cn/doc/css3/transition/index.htmopen in new window

https://www.html.cn/doc/jquery/animate/open in new window

css 动画 点击按钮 实现 显示隐藏

.turn_page:active{
            animation-name: example;
            animation-duration: 4s;
        }
        @keyframes example {
            0%   {opacity: 0;}
            25%  {opacity: 1;}
            50%  {opacity: 0.4;}
            100% {opacity: 1;}
        }

fadeOut() 方法使用淡出效果来隐藏被选元素,假如该元素是隐藏的。

fadeIn() 方法使用淡入效果来显示被选元素

$(selector).fadeOut(speed,callback)

speed可选。规定元素从可见到隐藏的速度。默认为 "normal"。

可能的值:

毫秒 (比如 1500)

"slow"

"normal"

"fast"

在设置速度的情况下,元素从可见到隐藏的过程中,会逐渐地改变其透明度(这样会创造淡出效果)。

案例:container.find('.result-container').fadeOut(100, function(){$(this).empty();});

  • transition: 设置动画,会和slideDown等一下jQuery 动画冲突,导致动画不生效

    //解决思路
    var $_element= $(".popup_div_temp").find(".popup_son_div");// popup_son_div
    $_element.hide();
    animationLoadHtml($_element);
    
    /**
    * 动画加载 元素
    *  针对  元素设置transition属性,和slideDown等一下jQuery 动画冲突,导致动画不生效 的场景
    * 动态加载的dom 对象,使用前 需要 先将其隐藏  $_element.hide();  然后获取高度、宽度,然后 使用动画 加载出
    * @param $_element :jQuery 对象 ($("#id"))
    */
    function animationLoadHtml($_element){
        var width = $_element.width();
        var height = $_element.height();
        $_element.css("height","0px");// 先将宽和高 设置为0 然后动态加载
        $_element.css("width","0px");
        $_element.show();
        $_element.animate({
            height:height+'px',
            width:width+'px',
            opacity:"1"
        },1000);
    }
    

    做动画常用到的几个 属性:放大,延迟

    transform: scale(1.2);
    transform-origin:left bottom;//把基准点修改为元素的左下角
    transition: all 0.6s;
    transition: all .5s cubic-bezier(0.000, 0.105, 0.035, 1.570); /*曲线*/
    transition-delay: 0.2s;/*延迟*/
    

    案例: 滚动,延迟,旋转,曲线

    -webkit-transform: rotate(-180deg);
        -moz-transform: rotate(-180deg);
        transform: rotate(-180deg);
        -webkit-transition: all .3s cubic-bezier(0.285, -0.450, 0.935, 0.110);
        -moz-transition: all .3s cubic-bezier(0.285, -0.450, 0.935, 0.110);
        transition: all .3s cubic-bezier(0.285, -0.450, 0.935, 0.110);
        -webkit-transition-delay: 0.2s;
        -moz-transition-delay: 0.2s;
        transition-delay: 0.2s;
    
    
    
    
    
    /* 从左移到 右边*/
    .search-wrapper .input-holder .search-icon {
        width: 50px;
        height:50px;
        opacity: 1;
        border-radius:6px;
        background: #FFF;
        padding:0px;
        outline:none;
        position: relative;
        z-index: 2;
        float:right;
        cursor: pointer;
        transform: translate(-200px, 0px);/*初始 放在 最左侧*/
    
        -webkit-transition: all .6s cubic-bezier(0.285, -0.450, 0.935, 0.110);
        -moz-transition: all .6s cubic-bezier(0.285, -0.450, 0.935, 0.110);
        transition: all .6s cubic-bezier(0.285, -0.450, 0.935, 0.110);
    }
    .search-wrapper.active .input-holder .search-icon {
        transform: translate(0, 0px);
        -webkit-transition: all .6s cubic-bezier(0.285, -0.450, 0.935, 0.110);
        -moz-transition: all .6s cubic-bezier(0.285, -0.450, 0.935, 0.110);
        transition: all .6s cubic-bezier(0.285, -0.450, 0.935, 0.110);
        -webkit-transition-delay: 0.2s;
        -moz-transition-delay: 0.2s;
    }
    

    html 修改图片src 动画

    function viewImg() {
        imgSrc = urlArr[nowIndex];
        var $this_ = $("#popup_detail_content_html_img");
        // 动画添加 src
        $this_.animate(
            {opacity:'toggle'},
            "slow",
            null,
            function(){
                $this_.attr("src",imgSrc);
                $this_.animate({opacity:'toggle'},"slow");
            }
        );
    

    19.19图片作为按钮& 光标悬停

    /* 按钮单击 效果*/
    .title_button_img:hover{
    	transform: scale(1.1);
    	transition: all 0.6s;
    }
    /* 单击 */
    .title_button_img:active {
        opacity: 0.1;
        transform: scale(1.1);
        transition: all 0.6s;
    }
    

19.20 html部分知识

设置表格使表格的宽度上下自动对齐
td, th {
	display: table-cell;
	vertical-align: inherit;--------------vertical-align:属性设置元素的垂直对齐方式。inherit从父元素继承
}

8)表格中的 colspan 属性规定单元格可横跨的列数。
<tr>
	<td class="tit">编码设备:</td>
	<td colspan="3">
		<form:input path="deviceIds"/>
	</td>
</tr>
在用表格时,可以直接指定宽度 来优化
<th width="70%">消息标题</th>
<th width="30%" >消息时间</th>

19.25 自定义滚动条

对应 父容器 需要添加 属性 overflow: auto;和高度宽度 超出父容器部分隐藏,显示 滚动条

  • 场景1 :使用过,但是没测试过x轴上的滚动样式
/*如果使用百分比,则需要定义父节点宽度,高度,如果父节点高度和宽度也是使用百分比,那么需要找到爷爷节点,设置高度、宽度,总知,一定要定义父节点高宽,不能通过子元素把父节点撑起来而获取的高度、宽度*/
.scroll_zdy {
	width: 100px;
	height: 100px;  
	overflow: auto; 
}
.scroll_zdy::-webkit-scrollbar {/*滚动条整体样式*/
    width: 4px;     /*Y轴滚动条 尺寸   如果想实现 不出现滚动条并且 可以滚动 设置宽度为0*/
    height: 4px;/* 水平滚动条 */
}
.scroll_zdy::-webkit-scrollbar-thumb {/*滚动条里面小方块*/
    border-radius: 10px;
    -webkit-box-shadow: inset 0 0 5px rgba(0,0,0,0.2);
    background: #535353;
}
.scroll_zdy::-webkit-scrollbar-track {/*滚动条里面轨道*/
    -webkit-box-shadow: inset 0 0 5px rgba(0,0,0,0.2);
    border-radius: 10px;
    background: #EDEDED;
}

说明:滚动条组成部分

  1. ::-webkit-scrollbar 滚动条整体部分

  2. ::-webkit-scrollbar-thumb 滚动条里面的小方块,能向上向下移动(或向左向右移动)

  3. ::-webkit-scrollbar-track 滚动条的轨道(里面装有Thumb)

  4. ::-webkit-scrollbar-button 滚动条的轨道的两端按钮,由于通过点击微调小方块的位置。

  5. ::-webkit-scrollbar-track-piece 内层轨道,滚动条中间部分

  6. ::-webkit-scrollbar-corner 边角,即垂直滚动条和水平滚动条相交的地方

  7. ::-webkit-resizer 两个滚动条的交汇处上用于拖动调整元素大小的小控件

img
img

其他设置项:

:horizontal      //horizontal伪类适用于任何水平方向上的滚动条 

:vertical        //vertical伪类适用于任何垂直方向的滚动条 

:decrement      //decrement伪类适用于按钮和轨道碎片。表示递减的按钮或轨道碎片,例如可以使区域向上或者向右移动的区域和按钮 

:increment      //increment伪类适用于按钮和轨道碎片。表示递增的按钮或轨道碎片,例如可以使区域向下或者向左移动的区域和按钮 

:start         //start伪类适用于按钮和轨道碎片。表示对象(按钮 轨道碎片)是否放在滑块的前面 

:end       //end伪类适用于按钮和轨道碎片。表示对象(按钮 轨道碎片)是否放在滑块的后面 

:double-button //double-button伪类适用于按钮和轨道碎片。判断轨道结束的位置是否是一对按钮。也就是轨道碎片紧挨着一对在一起的按钮。 

:single-button //single-button伪类适用于按钮和轨道碎片。判断轨道结束的位置是否是一个按钮。也就是轨道碎片紧挨着一个单独的按钮。 

:no-button  //no-button伪类表示轨道结束的位置没有按钮。 

:corner-present  //corner-present伪类表示滚动条的角落是否存在。 

:window-inactive  //适用于所有滚动条,表示包含滚动条的区域,焦点不在该窗口的时候。 

::-webkit-scrollbar-track-piece:start { 
	/*滚动条上半边或左半边*/ 
} 
::-webkit-scrollbar-thumb:window-inactive { 
	/*当焦点不在当前区域滑块的状态*/ 
} 
::-webkit-scrollbar-button:horizontal:decrement:hover {>  
	/*当鼠标在水平滚动条下面的按钮上的状态*/ 
}
滚动条的设置
1. ::-webkit-scrollbar 滚动条整体部分,可以设置宽度等
2. ::-webkit-scrollbar-button 滚动条两端的按钮
3. ::-webkit-scrollbar-track  外层轨道
4. ::-webkit-scrollbar-track-piece  内层滚动槽
5. ::-webkit-scrollbar-thumb 滚动的滑块
6. ::-webkit-scrollbar-corner 边角
7. ::-webkit-resizer 定义右下角拖动块的样式
image-20201126094257366
image-20201126094257366
::-webkit-scrollbar :滚动条整体部分,其中的属性: width,height,background,border等。

::-webkit-scrollbar-button :滚动条两端的按钮。可以用display:none让其不显示,也可以添加背景图片,颜色改变显示效果。

::-webkit-scrollbar-track :外层轨道。可以用display:none让其不显示,也可以添加背景图片,颜色改变显示效果。

::-webkit-scrollbar-track-piece :内层轨道,具体区别看下面gif图,需要注意的就是它会覆盖第三个属性的样式。

::-webkit-scrollbar-thumb :滚动条里面可以拖动的那部分

::-webkit-scrollbar-corner :边角,两个滚动条交汇处

::-webkit-resizer :两个滚动条交汇处用于拖动调整元素大小的小控件(基本用不上)
image-20201126094403133
image-20201126094403133

案例


<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8">
    <title>标题</title>
    <style>
        div {
            width: 100px;
            height: 300px;
            border: 2px solid red;
            overflow-x: scroll;
            overflow-y: scroll;
        }

        /* 设置滚动条的样式 */
        ::-webkit-scrollbar {
        width:12px;
        background-color: aqua;
        }

        /* 滚动槽 */
        ::-webkit-scrollbar-track {
        border-radius:10px;
        }

        /* 滚动条滑块 */
        ::-webkit-scrollbar-thumb {
        border-radius:10px;
        background:black;
        }


    </style>

    </script>
</head>
<body>

<div id="div1">
    请选择Webkit内核的浏览器才可以正常的看到滚动条的变化。小天地,大世界是一个Web前端的技术博客。 主要是关于HTML 5,CSS 3,JavaScript,JQuery等。除此之外,还包含一些PHP语言等的实用例子。请选择Webkit内核的浏览器才可以正常的看到滚动条的变化。小天地,大世界是一个Web前端的技术博客。 主要是关于HTML 5,CSS 3,
    JavaScript,JQuery等。除此之外,还包含一些PHP语言等的实用例子。请选择Webkit内核的浏览器才可以正常的看到滚动条的变化。小天地,大世界是一个Web前端的技术博客。 主要是关于HTML 5,CSS 3,JavaScript,JQuery等。除此之外,还包含一些PHP语言等的实用例子。请选择Webkit内核的浏览器才可以正常的看到滚动条的变化。
    小天地,大世界是一个Web前端的技术博客。 主要是关于HTML 5,CSS 3,JavaScript,JQuery等。除此之外,还包含一些PHP语言等的实用例子。请选择Webkit内核的浏览器才可以正常的看到滚动条的变化。小天地,大世界是一个Web前端的技术博客。 主要是关于HTML 5,CSS 3,JavaScript,JQuery等。除此之外,还包含一些PHP语言等的
    实用例子。请选择Webkit内核的浏览器才可以正常的看到滚动条的变化。小天地,大世界是一个Web前端的技术博客。 主要是关于HTML 5,CSS 3,JavaScript,JQuery等。除此之外,还包含一些PHP语言等的实用例子。请选择Webkit内核的浏览器才可以正常的看到滚动条的变化。小天地,大世界是一个Web前端的技术博客。 主要是关于HTML 5,CSS 3,JavaScript,JQuery等。除此之外,还
    包含一些PHP语言等的实用例子。请选择Webkit内核的浏览器才可以正常的看到滚动条的变化。小天地,大世界是一个Web前端的技术博客。 主要是关于HTML 5,CSS 3,JavaScript,JQuery等。除此之外,还
    包含一些PHP语言等的实用例子。请选择Webkit内核的浏览器才可以正常的看到滚动条的变化。小天地,大世界是一个Web前端的技术博客。 主要是关于
    HTML 5,CSS 3,JavaScript,JQuery等。除此之外,还包含一些PHP语言等的实用例子。请选择Webkit内核的浏览器才可以正常的看到滚动条的变化。
    小天地,大世界是一个Web前端的技术博客。 主要是关于HTML 5,CSS 3,JavaScript,JQuery等。除此之外,还包含一些PHP语言等的实用例子。请选择Webkit内核的浏览器才可以正常的看到滚动条的变化。
    小天地,大世界是一个Web前端的技术博客。 主要是关于请选择Webkit内核的浏览器才可以正常的看到滚动条的变化。请选择Webkit内核的浏览器才可以正常的看到滚动条的变化。
    小天地,大世界是一个Web前端的技术博客。 主要是关于
    HTML 5,CSS 3,JavaScript,JQuery等。除此之外,还
     包含一些PHP语言等的实用例子。
    小天地,大世界是一个Web前端的技术博客。 主要是关于
    HTML 5,CSS 3,JavaScript,JQuery等。除此之外,还
     包含一些PHP语言等的实用例子。
    HTML 5,CSS 3,JavaScript,JQuery等。除此之外,还
     包含一些PHP语言等的实用例子。
</div>

</body>
</html>

使用总结

<div class="scroll_zdy"><!--设置 滚动条,需要定义高度和宽度 -->
	<div id="scroll_content" class="scroll" style="transform: translate3d(0px, -43px, 0px) scale(1);"><!-用于后面可能涉及的 位置移动,翻页等 -->
		<div>内容</div>
		<div>内容</div>
		<div>内容</div>
	</div>
</div>	
<!-- 使用说明 父节点 定义宽高,可有出现滚动条,但是 在 父节点和 内容区域中 又添加一个div 是考虑,如果有场景需要自动翻页,那么 就需要动 这个id="scroll_content" 的位置,通过设置其位置,来实现 移动和翻页  -->

19.30 背景图片 background-image

CSS让DIV按照背景图片的比例缩放,并让背景图片填充整个元素(转)

background-size: 100% auto; 
background-repeat: no-repeat; 
background-image: url(../images/aaa.png); 
background: url(/CPMS/static/images/screen/changeimage/搜索框.png) no-repeat center;
background-size:100%100%;/*可以让 背景图片完全填充*/
background-size:cover;/*自动填充,比 background-size:100%100%; 更合理*/

说明: background:url(图片) no-repeat right center不明白是什么意思,百度以后学习到了,在此记载知识点;

这一行代码其实是背景图定义形式的简写 完整形式是:

background-image:url(图片); background-repeat:no-repeat; background-position:right center

right center是设置图片的初始位置,right是在水平方向上贴容器或浏览器页面的右侧,center是在垂直方向上居中,这两个的顺序是先定义水平位置,再定义垂直位置;

案例:

.right_popup{
    background: url(../map/3DmapImages/ionic_bg_006_02.png) no-repeat center;
    background-size: 100%100%;
    width:621px;
    height:893px;
}

案例:背景图片不重复,在水平方向靠近容器的右侧,在垂直方向距离容器上方14px

background:url(../images/top_ico.png) no-repeat right 14px;

<li> 标签是用于定义列表项目。这行代码意思是每一列包含的背景图片是top_ico.png,图片不重复,靠近列表容器的右侧,距离列表容器上方20px;

.top_menu li { float:left; background:url(../images/top_ico.png) no-repeat right 20px;

背景:【背景图片链接】【平铺方式(无平铺)】【距左边边距(数值或left或百分比)】【距顶端边距(数值或top或百分比)】

background:url(../images/nav_bg.png) no-repeat -20px -150px;

案例图片作为 按钮

.HomeButton .home {
    padding: 2px;
    width: 30px;
    height: 30px;
    background-color: #666;
    background-color: rgba(102,102,102,0.80);
    -webkit-user-select: none;
    -moz-user-select: none;
    -ms-user-select: none;
    /* user-select: none; */
    cursor: pointer;
    -webkit-border-radius: 5px;
    -moz-border-radius: 5px;
    -o-border-radius: 5px;
    border-radius: 5px;
    background-image: url(../dijit/images/home.png);
    background-position: center center;
    background-repeat: no-repeat;
}
.HomeButton .home:hover {
    background-color: #333;
    background-color: rgba(102,102,102,0.90);
}

.HomeButton .home:active {
	background-color: #ccc;
	background-color: rgba(102,102,102,0.60);
}

.HomeButton .loading {
	background-image: url("../dijit/images/home-spinner.gif");
}

19.40 遮罩效果

参考网址:https://www.cnblogs.com/aspx-net/archive/2011/03/11/1981071.htmlopen in new window

在页面内先定义好需要显示的DIV和遮罩层的CSS,然后用在onclick事件时,通过JS去控制两个DIV的样式:display='block' or display='none'.就可以实现DIV的显示和隐藏。注意两个DIV的z-index,显示在最上面的DIV的z-index一定要比遮罩层的z-index大。

思路: 在父页面和弹出层中 添加一层,铺满 父页面,设置 透明度,设置颜色,即为 遮罩层,通过对遮罩层的显示和隐藏从而达到,这种遮罩效果

<!DOCTYPE html>
 <html>
<head>
<title>DIV CSS遮罩层</title>
<script language="javascript" type="text/javascript">
		function showdiv() {            
            document.getElementById("bg").style.display ="block";
            document.getElementById("show").style.display ="block";
        }
		function hidediv() {
            document.getElementById("bg").style.display ='none';
            document.getElementById("show").style.display ='none';
        }
</script>
<style type="text/css">
     #bg{ 
        display:none;
        position:absolute;
        top:0%;left:0%;width:100%;
        height:100%;
        background-color:black;
        z-index:1001;
        -moz-opacity:0.7;
        opacity:.70;
        filter:alpha(opacity=70);
    }
    #show{display:none;
        position:absolute;top:25%;left:22%;
        width:53%;height:
        49%;padding:8px;
        border:8pxsolid#E8E9F7;
        background-color:white;z-index:1002; 
        overflow: auto;
    }
</style>
</head>
<body>
<input id="btnshow" type="button" value="Show" onclick="showdiv();"/>
<div id="bg"></div>    <!-- 遮罩层  -->
<div id="show">测试
    <input id="btnclose" type="button" value="Close" onclick="hidediv();"/>
</div>
</body>
</html>

19.41css-图片闪烁效果

按钮 点击效果

/* 动画 可以 作为 图片按钮 */
.img_button:hover{
    transform: scale(1.1);
    transition: all 0.6s;
}
.img_button:active{
    animation-name: example;
    animation-duration: 4s;
}
@keyframes example {
    0%   {opacity: 0;}
    25%  {opacity: 1;}
    50%  {opacity: 0.4;}
    100% {opacity: 1;}
}

css-图片闪烁效果

<!DOCTYPE html>
<html>
<head>
    <meta http-equiv="content-type" content="text/html;charset=utf-8"/>
    <title>呼吸灯</title>
    <style type="text/css">
    /* css代码 */
    .breath_light {
    /*width: 300px;  */                                  /* 宽度 */
    /*height: 300px; */                                   /* 高度 */
    /*border:#666 1px solid;*/
    /*border-radius:50%;*/
    opacity: 0.1;                                   /* 不透明度 */
    overflow: hidden;                               /* 溢出隐藏 */
    background:#FF3;                            /* 背景色 */
   /* margin: 25% auto; */                              /* 外边距 */
  
    /* IE10、Firefox and Opera,IE9以及更早的版本不支持 */
    animation-name: breath;                         /* 动画名称 */
    animation-duration: 700ms;                         /* 动画时长3秒 */
    animation-timing-function: ease-in-out;         /* 动画速度曲线:以低速开始和结束 */
    animation-iteration-count: infinite;            /* 播放次数:无限 */
 
    /* Safari and Chrome */
    -webkit-animation-name: breath;                 /* 动画名称 */
    -webkit-animation-duration: 700ms;                 /* 动画时长3秒 */
    -webkit-animation-timing-function: ease-in-out; /* 动画速度曲线:以低速开始和结束 */
    -webkit-animation-iteration-count: infinite;    /* 播放次数:无限 */
}
 
@keyframes breath {
    from { opacity: 0.1; }                          /* 动画开始时的不透明度 */
    50%  { opacity:   1; }                          /* 动画50% 时的不透明度 */
    to   { opacity: 0.1; }                          /* 动画结束时的不透明度 */    
}
 
@-webkit-keyframes breath {
    from { opacity: 0.1; }                          /* 动画开始时的不透明度 */
    50%  { opacity:   1; }                          /* 动画50% 时的不透明度 */
    to   { opacity: 0.1; }                          /* 动画结束时的不透明度 */
}
    </style>
</head>
<body>
    <div  title="呼吸灯">
        <img class="breath_light" src="../img/guihui.jpg" style="height: 60px;width: 60px;" />
    </div>
</body>
</html>

19.42使用CSS实现按钮点击波纹效果

主要借助::after伪类及CSS3中的transform和transition属性:

<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.7/css/bootstrap.min.css">

<div class="container text-center">
        <button class="btn btn-default ripple btn-lg">Button</button>
        <button class="btn btn-default ripple btn-lg">Button with very long content</button>
</div>
<!--实现1 -->
<style>
.ripple {
    position: relative;
    //隐藏溢出的径向渐变背景
    overflow: hidden;
}

.ripple:after {
    content: "";
    display: block;
    position: absolute;
    width: 100%;
    height: 100%;
    top: 0;
    left: 0;
    pointer-events: none;
    //设置径向渐变
    background-image: radial-gradient(circle, #666 10%, transparent 10.01%);
    background-repeat: no-repeat;
    background-position: 50%;
    transform: scale(10, 10);
    opacity: 0;
    transition: transform .3s, opacity .5s;
}

.ripple:active:after {
    transform: scale(0, 0);
    opacity: .3;
    //设置初始状态
    transition: 0s;
}

</style>
<!-- 实现2-->
<style>
.ripple {
    position: relative;
    //此处不需要设置overflow:hidden,因为after元素需要溢出显示
}
.ripple:focus{
    outline: none;
}

.ripple:after {
    content: "";
    display: block;
    position: absolute;
    //扩大伪类元素4个方向各10px
    top: -10px;
    left: -10px;
    right: -10px;
    bottom: -10px;
    pointer-events: none;
    background-color: #333;
    background-repeat: no-repeat;
    background-position: 50%;
    opacity: 0;
    transition: all .3s;
}

.ripple:active:after {
    opacity: .3;
    //设置初始状态
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
    transition: 0s;
}


</style>

19.50 Table

设置时 宽度设置不了 ,,老是挤下个元素(强制换行)

设置属性 tyle="WORD-WRAP: break-word" 如果还是不换行 那么再设置 宽度: <td style="WORD-WRAP: break-word" width="500">

<div style="font-size: 11px;color:#868686;white-space:normal;word-wrap:break-word;word-break:break-all;" ></div>

table 设置隔行不同色

table tr:nth-child(odd){background: #ccc;}/*奇数行背景*/
table tr:nth-child(even){background: #ccc;}/*偶数行背景*/

19.55 超长字符(限定文字长度)

限定字符串长度列表展示数据太长 可以用省略号“......”(隐藏信息) 限定长度(限定字符串长度)

用法 :自定义标签${fns:abbr(字段,14)} 案例:<td title="${task.rwdName}">${fns:abbr(task.rwdName,15)}</td>

自定义标签: -----------------------------------------------------------参考5.案例四

自定义标签

<function>
	<description>缩写字符串,超过最大宽度用“...”表示</description>
	<name>abbr</name>
	<function-class>cn.semdo.common.utils.StringUtils</function-class>
	<function-signature>java.lang.String abbr(java.lang.String, int)</function-signature>
	<example>${fns:abbr(str,length)}</example>  
</function>

对应app上也有 {{item.fxbxStr|limitTo:20}}

css 控制,超出容器 用省略号

p {
	width:90%;
	overflow:hidden;/* 滚动条隐藏 */
	white-space:nowrap;/*规定段落中的文本不进行换行*/
	text-overflow:ellipsis;/*属性规定当文本溢出包含元素时发生的事情*/
}

19.60 自定义输入框样式


.style2 {
		  border: 1px solid #cccccc;
		  display: inline-block;
		  height: 20px;
		  padding: 4px 6px;
		  margin-bottom: 10px;
		  font-size: 14px;
		  line-height: 20px;
		  color: #555555;
		  vertical-align: middle;
		  -webkit-border-radius: 4px;
		     -moz-border-radius: 4px;
		          border-radius: 4px;
		}

19.250 文件竖向排版

方法一:使用 换行标签 <br>

方法二:设置文字外框DIV的宽度,让文本自动换行

方法三:设置CSS属性样式 writing-mode:tb-rl

19.260 辅助开发,给div添加 边框导致换行

/* 辅助开发,定位边框*/
.bk{
    border: 1px solid #ccc;
    box-sizing: border-box;/*定义边框内收 ,防止 超出父容器*/
}

19.270 table 最好定义 <thead> <tbody> 来区分 内容和标题

场景:table 如果内容为空会导致 标题 跑到内容的区域

<table id="period_table" style="height: 285px;">
    <thead>/*标题*/
        <tr style="height: 48px;">
            <th style="width: 20%;" >项目</th>
            <th style="width: 28%;" >上次检测</th>
        </tr>
    </thead>
    <tbody>
        <c:forEach items="${data.periodJsonArr}" var="periodJson" varStatus="indexItem">
            <tr style="height: 58px;" id="period_${indexItem.index}" class="need_hover">
                <td>${periodJson.period_name}</td>
                <td>${periodJson.period_time}</td>
            </tr>
        </c:forEach>
    </tbody>
</table>
image-20200915170754721
image-20200915170754721

19.280

19.290 进度条

<progress id="myProgress" value="75" max="100"></progress>

19.300 tab

<style>
	/*tab页切换*/
    .tabMenuBox{
        font-size: 24px;
        padding: 20px;
        color: #fff;
    }
    .tabMenuBox ul li {
        text-align: center;
        line-height: 35px;
    }
    /*默认*/
    .tabLi {
        width: 25%;
        float: left;
        border-bottom-style: solid;
        border-width: 2px;
        border-color: #74b7b4;
    }
    /*激活*/
    .tabActive {
        border-color: #fff;
    }
    li {
        list-style: none;
    }
</style>
<script>
	//点击tab 清除历史选中的tab页
    function  tabSwitch(type){
        $(".clearfix li").each(function(i){
            $(this).removeClass('tabActive');
        });
        $("#listType"+type).addClass("tabActive");
    }
</script>

<div class="tabMenuBox">
    <ul class="clearfix">
        <li id="listType1" class="tabLi tabActive" onclick="tabSwitch('1')"><span>tab1</span></li>
        <li id="listType2" class="tabLi" onclick="tabSwitch('2')"><span>tab2</span></li>
        <li id="listType3" class="tabLi" onclick="tabSwitch('3')"><span>tab3</span></li>
        <li id="listType4" class="tabLi" onclick="tabSwitch('4')"><span>tab4</span></li>
    </ul>
</div>
  • 横向tab + 滚动
image-20210407085712920
image-20210407085712920
<div class="top-pos">
    <div id="gesturesButton" class="bq-head" >
        <img src="modules/dsj/img/zk.png" height="7px;"><!-- 上滑,下滑按钮 -->
    </div>
    <!-- 表头tab,支持横向滚动 -->
    <ion-scroll id="head_tab" zooming="true" direction="x"  class="head_container">
        <div class="head_li tabActive" ng-click="tabSwitch('gttz',$event)">GT台账</div>
        <div class="head_li" ng-click="tabSwitch('tqqk',$event)">天气情况</div>
        <div class="head_li" ng-click="tabSwitch('jksk',$event)">交跨/三跨</div>
        <div class="head_li" ng-click="tabSwitch('wrjxs',$event)">无人机巡视</div>
        <div class="head_li" ng-click="tabSwitch(1,$event)">线路信息</div>
        <div class="head_li" ng-click="tabSwitch(1,$event)">线路信息</div>
        <div class="head_li" ng-click="tabSwitch(1,$event)">线路信息</div>
        <div class="head_li" ng-click="tabSwitch(1,$event)">线路信息</div>
        <div class="head_li" ng-click="tabSwitch(1,$event)">线路信息</div>
        <div class="head_li" ng-click="tabSwitch(1,$event)">线路信息</div>
        <div class="head_li" ng-click="tabSwitch(1,$event)">线路信息</div>
    </ion-scroll>
</div>

<style>
    .top-pos {
        /*  position: absolute;
        top: 0px; */
        width: 100%;
        z-index: 99999998;
    }
    .head_container{
        width: 100%;
        overflow-x: scroll;
        overflow-y: hidden;
        white-space: nowrap;
        background-color: #fff;
        padding: 0 10px;
        box-sizing: border-box;
    }
    .head_li {
        width: 73px !important;
        margin: auto;
        display: inline-flex;
        align-items: center;
        justify-content: center;
        font-size: 12px;
        font-weight: 400;
        color: #8C8C8C;
        flex-shrink: 0;
        height: 32px;
    }

    .tabActive {
        border-bottom: 1.5px #2094FF solid;
        color: #000000;
    }
</style>
<script>
	//点击tab 清除历史选中的tab页
	$scope.tabSwitch=function(type,$event){
        $(".head_li").each(function(i){
            $(this).removeClass('tabActive');
        });
        if($event==undefined){
        	$(".head_li").eq(0).addClass("tabActive");
        }
        $($event.target).addClass("tabActive");
        $event.stopPropagation();
      }
</script>

19.341 子元素横向排列,超过父容器宽度不换行纯css方法

  • inline-block方法
ul{
  white-space:nowrap;
  font-size:0;
}
li{
  display:inline-block;
}
  • flex方法
ul{
  display:flex;
}
li{
  flex-shrink:0;
}

19.310 响应式布局

思路是 讲页面宽度 分层 12分

<html>
    </head>
        <style>/*响应式布局*/
            * {
                box-sizing: border-box;
            }
            .row:after {
                content: "";
                clear: both;
                display: block;
            }
            [class*="col-"] {
                float: left;
            }
            .col-1 {width: 8.33%;}
            .col-2 {width: 16.66%;}
            .col-3 {width: 25%;}
            .col-4 {width: 33.33%;}
            .col-5 {width: 41.66%;}
            .col-6 {width: 50%;}
            .col-7 {width: 58.33%;}
            .col-8 {width: 66.66%;}
            .col-9 {width: 75%;}
            .col-10 {width: 83.33%;}
            .col-11 {width: 91.66%;}
            .col-12 {width: 100%;}

        </style>
    </head>
<body>

    <div class="row">
        <div class="col-3">第一块</div>
        <div class="col-9">第二块</div>
    </div>
</body>
</html>

CSS3 @media 查询open in new window

@media only screen and (min-width: 600px) {
    /* For tablets: */
    .col-m-12 {width: 8.33%;}
    .col-m-2 {width: 16.66%;}
}
@media only screen and (min-width: 768px) {
    /* For desktop: */
    .col-1 {width: 8.33%;}
    .col-2 {width: 16.66%;}

}
@media screen and (min-device-width: 1440px) and (max-device-width: 1680px){
	.col-1 {width: 8.33%;}
    .col-2 {width: 16.66%;}
}

19.瀑布流

https://www.jb51.net/html5/691874.htmlopen in new window

案例1.**JS 实现瀑布流 [JS 实现瀑布流.html](D:\java编程\笔记\html\图片展示&瀑布流\自定义瀑布流\JS 实现瀑布流.html) **

思路分析

  • 瀑布流布局的特点是等宽不等高。
  • 为了让最后一行的差距最小,从第二行开始,需要将图片放在第一行最矮的图片下面,以此类推。
  • 父元素设置为相对定位,图片所在元素设置为绝对定位。然后通过设置 top 值和 left 值定位每个元素。
<!DOCTYPE html>
<html>
<head>
    <style>
		
        .box {
            width: 100%;
            position:relative;
        }
        .item {
            position: absolute;
        }
        .item img{
            width: 100%;
            height:100%;
        }
    </style>
</head>
<body>
<div class="box">
    <div class="item">
        <img  src="./1.jpg" alt="" />
    </div>
    <div class="item">
        <img  src="./2.jpg" alt="" />
    </div>
    <div class="item">
        <img  src="./3.jpg" alt="" />
    </div>
    <div class="item">
        <img  src="./4.jpg" alt="" />
    </div>
    <div class="item">
        <img  src="./5.jpg" alt="" />
    </div>
    <div class="item">
        <img  src="./6.jpg" alt="" />
    </div>
    <div class="item">
        <img  src="./7.jpg" alt="" />
    </div>
    <div class="item">
        <img  src="./8.jpg" alt="" />
    </div>
    <div class="item">
        <img  src="./9.jpg" alt="" />
    </div>
    <div class="item">
        <img  src="./10.jpg" alt="" />
    </div>
    <div class="item">
        <img  src="./11.jpg" alt="" />
    </div>
    <div class="item">
        <img  src="./12.jpg" alt="" />
    </div>
</div>
</body>
<script src="jquery.min.js"></script>
<script>
    function waterFall() {
        // 1 确定图片的宽度 - 滚动条宽度
        var pageWidth = getClient().width-8;
        var columns = 3; //3列
        var itemWidth = parseInt(pageWidth/columns); //得到item的宽度
        $(".item").width(itemWidth); //设置到item的宽度
        var arr = [];
        $(".box .item").each(function(i){
            var height = $(this).find("img").height();
            if (i < columns) {
                // 2 第一行按序布局
                $(this).css({
                    top:0,
                    left:(itemWidth) * i+20*i,
                });
                //将行高push到数组
                arr.push(height);
            } else {
                // 其他行
                // 3 找到数组中最小高度  和 它的索引
                var minHeight = arr[0];
                var index = 0;
                for (var j = 0; j < arr.length; j++) {
                    if (minHeight > arr[j]) {
                        minHeight = arr[j];
                        index = j;
                    }
                }
                // 4 设置下一行的第一个盒子位置
                // top值就是最小列的高度
                $(this).css({
                    top:arr[index]+30,//设置30的距离
                    left:$(".box .item").eq(index).css("left")
                });

                // 5 修改最小列的高度
                // 最小列的高度 = 当前自己的高度 + 拼接过来的高度
                arr[index] = arr[index] + height+30;//设置30的距离
            }
        });
    }
    //clientWidth 处理兼容性
    function getClient() {
        return {
            width: window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth,
            height: window.innerHeight || document.documentElement.clientHeight || document.body.clientHeight
        }
    }
    // 页面尺寸改变时实时触发
    window.onresize = function() {
        //重新定义瀑布流
        waterFall();
    };
    //初始化
    window.onload = function(){
        //实现瀑布流
        waterFall();
    }
</script>
</html>

案例2. column 多行布局实现瀑布流

思路分析: column多行布局实现瀑布流.html

column 实现瀑布流主要依赖两个属性。 一个是 column-count 属性,是分为多少列。 一个是 column-gap 属性,是设置列与列之间的距离。

​ column-width 属性 ,设置列宽

案例1和2 合理 长度不会超出父容器

<!DOCTYPE html>
<html>
<head>
    <style>
        .box {
            margin: 10px;
            column-count: 3;
            column-gap: 10px;
            /*column-width: 250px;  列的宽度 */
        }
        .item {
            margin-bottom: 10px;
        }
        .item img{
            width: 100%;
            height:100%;
        }
    </style>
</head>
<body>
<div class="box">
    <div class="item">
        <img  src="./1.jpg" alt="" />
    </div>
    <div class="item">
        <img  src="./2.jpg" alt="" />
    </div>
    <div class="item">
        <img  src="./3.jpg" alt="" />
    </div>
    <div class="item">
        <img  src="./4.jpg" alt="" />
    </div>
    <div class="item">
        <img  src="./5.jpg" alt="" />
    </div>
    <div class="item">
        <img  src="./6.jpg" alt="" />
    </div>
    <div class="item">
        <img  src="./7.jpg" alt="" />
    </div>
    <div class="item">
        <img  src="./8.jpg" alt="" />
    </div>
    <div class="item">
        <img  src="./9.jpg" alt="" />
    </div>
    <div class="item">
        <img  src="./10.jpg" alt="" />
    </div>
    <div class="item">
        <img  src="./11.jpg" alt="" />
    </div>
    <div class="item">
        <img  src="./12.jpg" alt="" />
    </div>
</div>
</body>
也可以直接设置 每列的宽度 
.container {
		column-width: 250px;/* 列的宽度 */
		column-gap: 5px; /* 列的间距 */
	}

flex 弹性布局实现瀑布流

思路分析: index2.html

flex 实现瀑布流需要将最外层元素设置为 display: flex,即横向排列。然后通过设置 flex-flow:column wrap 使其换行。设置 height: 100vh 填充屏幕的高度,来容纳子元素。每一列的宽度可用 calc 函数来设置,即 width: calc(100%/3 - 20px)。分成等宽的 3 列减掉左右两遍的 margin 距离。

注:横向排列 需要定义 容器高度,这样存在问题,图片过多,会超出容器

<!DOCTYPE html>
<html>
<head>
	<meta charset="utf-8" />
	<title>flex 弹性布局实现瀑布流</title>
    <style>
		body{
			width:920px;
			border: 1px solid #ccc;
			box-sizing: border-box;
		}
        .box {
	          display: flex;  
          flex-flow:column wrap;
          height: 100vh;
        }
        .item {
            margin: 10px;
            width: calc(100%/3 - 20px);
        }
        .item img{
            width: 100%;
            height:100%;
        }
		
    </style>
</head>
<body>
<div class="box">
    <div class="item">
        <img  src="./1.jpg" alt="" />
    </div>
    <div class="item">
        <img  src="./2.jpg" alt="" />
    </div>
    <div class="item">
        <img  src="./3.jpg" alt="" />
    </div>
    <div class="item">
        <img  src="./4.jpg" alt="" />
    </div>
    <div class="item">
        <img  src="./5.jpg" alt="" />
    </div>
    <div class="item">
        <img  src="./6.jpg" alt="" />
    </div>
    <div class="item">
        <img  src="./7.jpg" alt="" />
    </div>
    <div class="item">
        <img  src="./8.jpg" alt="" />
    </div>
    <div class="item">
        <img  src="./9.jpg" alt="" />
    </div>
    <div class="item">
        <img  src="./10.jpg" alt="" />
    </div>
    <div class="item">
        <img  src="./11.jpg" alt="" />
    </div>
    <div class="item">
        <img  src="./12.jpg" alt="" />
    </div>
</div>
</body>

19.340 用div 创建一个梯形

<div style=" width: 300px;height: 40px;z-index: 10;position: absolute;left: 50%;transform: translate(-50%);" >
    <div style="" class="map_title_content ">
    	监造项目
    </div>
</div>

<style>
	.map_title_content {
            width: 100%;
            height: 100%;
            justify-content: center;
            display: flex;
            align-items: center;
            position: relative;
            color: white;
            color: #FFFF00;
            font-size: 18px;
        }
        .map_title_content::before {
            content: '';
            position: absolute;
            top: 0;
            right: 0;
            bottom: 0;
            left: 0;
            z-index: -1;
            background: #58a;
            transform: perspective(20px) rotateX(-5deg);
            background: -webkit-gradient(linear,0 0,0 bottom, from(rgb(168, 180, 171,0.5)),to(rgb(168, 180, 171,0.8)));
        }
</style>

19.341 标题

效果一: 利用背景图属性渐变色控制画线颜色,通过背景图大小属性设置线条的粗细,文字盒子设置背景覆盖部分线条

image-20210506202132635
image-20210506202132635
<template>
	  <div class="notice">
        <span class="notice_content">
          公告
        </span>
      </div>
</template>
<style>
	.notice {
  position: relative;
  margin: 15px auto 15px;
  width: 100px;
  background-image: linear-gradient(90deg, #fff, #333 50%, #fff);
  background-size: 100% 1px;
  background-position: 50%;
  background-repeat: no-repeat;
  text-align: center;
  
}
.notice_content {
    font-size: 12px;
    color: #333;
    padding: 0 6px;
    background-color: #fff;
  }
</style>

效果二:

image-20210506203731306
image-20210506203731306
<div class="div-line"></div>
<style>
.div-line {
    margin: 0 auto;
    height: 2px;
    width: 100%;
    background: radial-gradient(#1E89A2 12%, white 80%);
}
</style>

效果三:文字光晕

.span1 {
    box-sizing: border-box;
    color: rgb(172, 29, 16);
    max-width: 100%;
    overflow-wrap: break-word;
    text-shadow: 2px 2px 10px rgb(0, 112, 192);
}

19.342 渐变色

文字渐变色 https://blog.csdn.net/ayiewu460246/article/details/101789904open in new window

background-image: -webkit-linear-gradient(top, #a80b02, #ff3b30); //设置颜色与渐变方向
  background-clip: text;
  -webkit-background-clip: text; //主要用于剪掉文字以外的区域。
  -webkit-text-fill-color: transparent;//设置文本的填充颜色。
  font-family: Arial, Helvetica, sans-serif;
background: linear-gradient(to right, #04adca, #b1c2c2);
    -webkit-background-clip: text;
    color: transparent;
    font-family: Arial, Helvetica, sans-serif;

19.343 html5+css3简单边框发光效果

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
        body
        {
            margin: 0;
            padding: 0;

           display: flex;
            justify-content:center;       
            align-items:center;
            min-height:100vh;
            background: #060c21;
            font-family: 'Poppins', sans-serif;
        }
        .box{

            position: relative;
            width: 300px;
            height: 400px;
            display: flex;
            justify-content: center;
            align-items: center;
            background: #060c21;
        }
        /*一个溢出的盒子作为边框,添加背景后形成光源效果*/
        .box::before {
                     content: '';
                     position: absolute;
                     top:-2px;
                     left: -2px;
                     right: -2px;
                     bottom: -2px;
                     background: #FFFFFF;
                     z-index: -1;/*元素堆叠顺序*/
            
        }
        /*另一个溢出的盒子,模糊形成光晕效果*/
        .box::after {
            content: '';
            position: absolute;
            top: -2px;
            left: -2px;
            right: -2px;
            bottom: -2px;
            background: #FFFFFF;
            z-index: -2;
            /*添加模糊滤镜*/
            filter: blur(40px);
        }
        .box::before,
        .box::after{
            /*三色渐变,中间为背景色,融入背景*/
            background: linear-gradient(235deg,#89ff00,#060c21,#00bcd4);
        }
        .content {
            padding: 20px;
            box-sizing: border-box;
            color: #fff;
        }
    </style>
</head>
<body>
<div class="box">
    <div class="content">
        <h1>黑洞</h1>
         <p>
             黑洞是现代广义相对论中,宇宙空间内存在的一种天体。黑洞的引力很大,使得视界内的逃逸速度大于光速。
             “黑洞是时空曲率大到光都无法从其事件视界逃脱的天体”。
             如果将大量物质集中于空间一点,其周围会产生奇异的现象,即在质点周围存在一个界面——“视界”一旦进入这个界面,
             即使光也无法逃脱。这种“不可思议的天体”被美国物理学家约翰·阿奇博尔德·惠勒命名为“黑洞”。
         </p>

    </div>
</div>
</body>
</html>

19.

19.350 弹窗背景

/*白底 作为 图例统计*/
.title_background{
	background-color: rgb(215, 221, 221,0.84);
}
.title_background div:hover {
	background-color:#568080;
}


/*蓝底 一般作为 底部 菜单*/
.main_background {
    background-color: rgb(52, 106, 181, 0.8);
    color: #FFFFFF !important;
    box-shadow: 0px 0px 15px 0px rgba(24, 249, 234, 0.25);
    border-top-right-radius: 8px;
    border-top-left-radius: 8px;
}

/* 透明黑 */
.loginmain {
    background: rgba(0,0,0,.5);
    width: 540px;
    height: 300px;
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
    margin: auto;
    box-shadow: -15px 15px 15px rgba(6,17,47,.7);
    z-index: 99999;
}

CSS3中的变形处理——transform功能(旋转、缩放、倾斜、移动)

CSS3中的变形处理

参考网址: https://blog.csdn.net/qq_40542728/article/details/81979163open in new window

1 transform属性
在CSS3中,可以利用transform功能实现文字或图像的旋转、缩放、倾斜、移动这4中类型的变形处理。

(1)浏览器支持

到目前为止:Safari3.1以上、Chrome8以上、Firefox4以上、Opera10以上浏览器支持该属性。 

2 旋转
使用rotate方法,在参数中加入角度值,角度值后面跟表示角度单位的“deg”文字即可,旋转方向为顺时针方向。

transform:rotate(45deg);

3 缩放 
使用scale方法来实现文字或图像的缩放处理,在参数中指定缩放倍率。

transform:scale(0.5);//缩小一半

(1)可以分别指定元素的水平方向的放大倍率与垂直方向的放大倍率

transform:scale(0.5,2);//水平方向缩小一半,垂直方向放大一倍。

4 倾斜 
使用skew方法实现文字或图像的倾斜处理,在参数中分别指定水平方向上的倾斜角度与垂直方向上的倾斜角度。

transform:skew(30deg,30deg)//水平方向上倾斜30度,垂直方向上倾斜30度。

(1)只使用一个参数,省略另一个参数

这种情况下视为只在水平方向上进行倾斜,垂直方向上不倾斜。

transform:skew(30deg);

5 移动
使用translate方法来移动文字或图像,在参数中分别指定水平方向上的移动距离与垂直方向上的移动距离。

transform:translate(50px,50px);// 水平方向上移动50px,垂直方向上移动50px

(1)只使用一个参数,省略另一个参数

这种情况下视为只在水平方向上移动,垂直方向上不移动。

transform:translate(50px);

6 对一个元素使用多种变形的方法
transform:translate(150px,200px) rotate(45deg) scale(1.5);

7 指定变形的基准点
在使用transform方法进行文字或图像变形的时候,是以元素的中心点为基准点进行变形的。

transform-origin属性
使用该属性,可以改变变形的基准点。

transform:rotate(45deg);

transform-origin:left bottom;//把基准点修改为元素的左下角

(1)指定属性值

基准点在元素水平方向上的位置:left、center、right

基准点在元素垂直方向上的位置:top、center、bottom

8 3D变形功能
(1)旋转

分别使用rotateX方法、rotateY方法、rotateZ方法使元素围绕X轴、Y轴、Z轴旋转,在参数中加入角度值,角度值后面跟表示角度单位的deg文字即可,旋转方向为顺时针旋转。

transform:rotateX(45deg);

transform:rotateY(45deg);

transform:rotateZ(45deg);

transform:rotateX(45deg) rotateY(45deg) rotateZ(45deg);

transform:scale(0.5) rotateY(45deg) rotateZ(45deg);

(2)缩放

分别使用scaleX方法、scaleY方法、scaleZ方法使元素按X轴、Y轴、Z轴进行缩放,在参数中指定缩放倍率。

transform:scaleX(0.5);

transform:scaleY(1);

transform:scaleZ(2);

transform:scaleX(0.5)scaleY(1);

transform:scale(0.5) rotateY(45deg);

(3)倾斜

分别使用skewX方法、skewY方法使元素在X轴、Y轴上进行顺时针方向倾斜(无skewZ方法),在参数中指定倾斜的角度

transform:skewX(45deg);

transform:skewY(45deg);

(4)移动

分别使用translateX方法、translateY方法、translateZ方法、使元素在X轴、Y轴、Z轴方向上进行移动,在参数中加入移动距离。

transform:translateX(50px);

transform:translateY(50px);

transform:translateZ(50px);

案例

img
img
.popu_window_pointer {
    top: -8px;
    left: -3px;
    position: absolute;
    background: rgba(0,56,114,0.8);
    width: 20px;
    height: 20px;
    transform: skew(30deg,30deg);/* 倾斜  在参数中分别指定水平方向上的倾斜角度与垂直方向上的倾斜角度*/
}

19.360 css引入图片相对路径

image-20201219095123934
image-20201219095123934

19.370 自定义样式 一些案例

自定义标签,按钮

61)标签
<span  id="1" class="labelSpan labelS" style="border-color:#cca4e3">开心 </span>
.labelS {
		    padding: 5px 10px;
		    margin-right: 10px;
		    margin-bottom: 5px;
		    border: 1px solid;
		    border-radius: 5px;
		    float: left;
		    cursor: pointer;
		    background-color: rgba(0, 0, 0, 0);
		}
img
img

19.380 锚点

页面点击事件触发点
<div class="item-nav fl click_light cur" data_type="rmhd">
 
<div class="cont-info-wrap mb80" id="rmhd">
    需要跳转到的页面位置
</div>

<style>
    // 锚点 实现代码段:
    $('.click_light').on('click',function(){
        var type = $(this).attr("data_type");
        window.location.href = '#' + type;
    });
</style>

19.390 dom 操作

  • prepend:追加

    $("#parent").prepend(html);// 给父节点添加 子节点(追加在最后)

  • prepend

    $("#parent").prepend(html);// 给父节点添加 子节点(追加在最前)

  • prependTo

    $("#sonDom").prepend("#parent");// 讲dom元素 迁移到 parent节点下(作为其第一个子元素)

19.400 div横向排列+滚动条显示

.container{
    width: 100%;
    overflow-x: scroll;
    overflow-y: hidden;
    white-space: nowrap;
}
.container .item{
    display:inline-block;
    box-sizing: border-box;
    width:33%;
}

19.410 文字左右排列

image-20210406182754376
image-20210406182754376

<div class="detail_li justify" >
    <span class="">导线</span>
    <span class="">#211-#214</span>
</div>
<div class="detail_li justify" >
    <span class="">地线</span>
    <span class="">#211-#214</span>
</div>
<div class="detail_li justify" >
    <span class="">金具</span>
    <span class="">12</span>
</div>


<style>
	.detail_li {
    border: 1px #F5F5F5 solid;
    width: 49%;
    padding: 10px;
    margin-bottom: 10px;
    border-radius: 7px;
}
    /*两端对齐*/
			.justify {
	            justify-content: space-between;
			    display: inline-flex;
			    align-items: center;
			}
</style>

19.430 web 设置 浏览器 图标

image-20210507152743369
image-20210507152743369
<head>
	<title>集控中心</title>
    <link rel="shortcut icon" href="${fns:getCfgSettingByCode('platform_ioc').fileValueUrl}" type="image/x-icon" /><!-- 浏览器头部 图标--> 
	<meta name="decorator" content="default"/>
</head>	

19.440 HTML中解决双击会选中文本的问题

在父节点中 添加属性

/* HTML中解决双击会选中文本的问题*/
.html_wrap{
    -webkit-user-select: none;
    -moz-user-select: none;
    -ms-user-select: none;
    user-select: none;
}

19.450 浏览器全屏

  • 注:定时器非常耗性能,所以 页面出现ztree,并且异步加载数据的时候,切换全屏,会出现明显的卡顿
/**
 *
 *  全屏 切换
 * @type {boolean}
 */
var fullScreenFlag = false;// 全屏切换
function switchFullScreen(){
    if(!fullScreenFlag){
        requestFullScreen();// 整个网页
        fullScreenFlag = true;
    }else{
        fullScreenFlag = false;
        exitFull();
    }
    switchFullScreenStyle();// 涉及到样式的修改
};
function requestFullScreen() {
    var element=document.documentElement;
    // 判断各种浏览器,找到正确的方法
    var requestMethod = element.requestFullScreen || //W3C
        element.webkitRequestFullScreen ||    //Chrome等
        element.mozRequestFullScreen || //FireFox
        element.msRequestFullScreen; //IE11
    if (requestMethod) {
        requestMethod.call(element);
    }
    else if (typeof window.ActiveXObject !== "undefined") {//for Internet Explorer
        var wscript = new ActiveXObject("WScript.Shell");
        if (wscript !== null) {
            wscript.SendKeys("{F11}");
        }
    }
}
//退出全屏 判断浏览器种类
function exitFull() {
    // 判断各种浏览器,找到正确的方法
    var exitMethod = document.exitFullscreen || //W3C
        document.mozCancelFullScreen ||    //Chrome等
        document.webkitExitFullscreen || //FireFox
        document.webkitExitFullscreen; //IE11
    if (exitMethod) {
        exitMethod.call(document);
    }
    else if (typeof window.ActiveXObject !== "undefined") {//for Internet Explorer
        var wscript = new ActiveXObject("WScript.Shell");
        if (wscript !== null) {
            wscript.SendKeys("{F11}");
        }
    }
}
/*监听 f11*/
$(document).on('keydown', function (e){
    var e = event || window.event || arguments.callee.caller.arguments[0];
    if(e && e.keyCode == 122){//捕捉F11键盘动作
        e.preventDefault();  //阻止F11默认动作
        var el = document.documentElement;
        var rfs = el.requestFullScreen || el.webkitRequestFullScreen || el.mozRequestFullScreen || el.msRequestFullScreen;//定义不同浏览器的全屏API      //执行全屏
        if (typeof rfs != "undefined" && rfs) {
            rfs.call(el);
        }else if(typeof window.ActiveXObject != "undefined"){
            var wscript = new ActiveXObject("WScript.Shell");
            if (wscript!=null) {
                wscript.SendKeys("{F11}");
            }
        }
        //监听不同浏览器的全屏事件,并件执行相应的代码
        document.addEventListener("webkitfullscreenchange", function() {//
            if (document.webkitIsFullScreen) {
                //全屏后要执行的代码
                fullScreenFlag = true;
            }else{
                //退出全屏后执行的代码
                fullScreenFlag = false;
            }
            switchFullScreenStyle();
        }, false);

        document.addEventListener("fullscreenchange", function() {
            if (document.fullscreen) {
                //全屏后执行的代码
                fullScreenFlag = true;
            }else{
                //退出全屏后要执行的代码
                fullScreenFlag = false;
            }
            switchFullScreenStyle();
        }, false);

        document.addEventListener("mozfullscreenchange", function() {
            if (document.mozFullScreen) {
                //全屏后要执行的代码
                fullScreenFlag = true;
            }else{
                //退出全屏后要执行的代码
                fullScreenFlag = false;
            }
            switchFullScreenStyle();
        }, false);
        document.addEventListener("msfullscreenchange", function() {
            if (document.msFullscreenElement) {
                //全屏后要执行的代码
                fullScreenFlag = true;
            }else{
                //退出全屏后要执行的代码
                fullScreenFlag = false;
            }
            switchFullScreenStyle();
        }, false)
    }
});


// 全屏 切换 样式修改
var switchFullScreenStyle=function(){
    if(!fullScreenFlag){
        $("#quanping").attr("title","全屏显示");
        $("#quanping").find("img").eq(0).attr("src","/XJB/static/images/jkzx/qp_icon.png");
    }else{
        $("#quanping").attr("title","退出全屏");
        $("#quanping").find("img").eq(0).attr("src","/XJB/static/images/jkzx/colse_qp_icon.png")
    }
}

19.460 class

if($(this_).hasClass("desc")){

}
$(this_).toggleClass("asc");

19.470 css 常用属性

圆角

border-radius: 6px; (可以使方形变为圆形  ) 
-webkit-border-radius: 35px;   
border-top-right-radius: 8px; border-top-left-radius: 8px;(上面左右2个角)
border-bottom-right-radius:8px;
	
border-radius: 8px;(这个边框都加圆角)

19.500 时间控件& 下拉选 的 小三角图标

style='-webkit-appearance: none;' 这个是取消时间控件的小三角图标

去掉背景色和图标一片空白,如果不好看 可以加上 下划线 border-bottom: 1px solid #000 !important; 或者将背景色改为background-color:#FAFAFA;

.dateInput {  //androd 端去掉背景色
	background-color:transparent;  
	FILTER: alpha(opacity=0); /*androd*/  
	/*appearance:none;*/  /*下拉框去掉右侧图标*/  
	-moz-appearance:none;  -webkit-appearance:none; /*下拉框去掉右侧图标*/ 
}

19.510 浏览器适配

@media

/*@media screen*/
@media (min-width: 1024px){

} /*>=1024的设备*/
@media (min-device-width: 1100px) {

} /*>=1024的设备*/
@media (min-device-width: 1280px) {

}
@media (min-device-width: 1366px) {

}
@media (min-device-width: 1440px) {

}
/*主要针对  电脑 使用 150% 的分辨率下*/
@media screen and (min-device-width: 800px) and (max-device-width: 1440px){}
@media screen and (min-device-width: 1440px) and (max-device-width: 1680px){}
@media (min-device-width: 1920px){}

22JavaScript和jQuery相关知识

开发常用到的

<meta name="viewport" content="width=device-width, initial-scale=1">
<!-- 引入 jQuery Mobile 样式 -->
<link rel="stylesheet" href="http://code.jquery.com/mobile/1.4.5/jquery.mobile-1.4.5.min.css">
<!-- 引入 jQuery 库 -->
<script src="http://code.jquery.com/jquery-1.11.3.min.js"></script>
<!-- 引入 jQuery Mobile 库 -->
<script src="http://code.jquery.com/mobile/1.4.5/jquery.mobile-1.4.5.min.js"></script>

22.1 使用html5缓存数据,通信

缓存都存在跨域问题,如果想解决跨域,可以考虑 使用通讯,例如 1.window.postMessage,2.基于netty搭建websocket

https://blog.csdn.net/zerocher/article/details/72822108open in new window

https://blog.csdn.net/tang_yi_/article/details/79401280open in new window

  • localStorage ttps://www.jianshu.com/p/8c4cee29d532 (解决跨域场景)
//将数组转成字符串存到页面缓存
var appUser=[{Ids: "1,2", Names: "李,林"},{Ids: "1,2", Names: "周,吴"}];
window.localStorage["appUser"] = JSON.stringify(appUser);
//读取页面缓存转成数组
var appUser = JSON.parse(window.localStorage["appUser"]);
console.log(appUser);

从配置文件中取参数

${fns:getConfig("dpSockecService")}

22.2 js监听页面点击事件open in new window

    <!-- 第三种方式-->
    <button id="btn" onclick="threeFn()">点我</button>
    <script type="text/javascript">
        var btn = document.getElementById("btn");

        // 第一种 通过点击事件
        btn.onclick = function(){
            alert("这是第一种点击方式");
        }

        // 第二种 监听点击事件
        btn.addEventListener('click', function(){
            alert("这是第二中点击方式");
        })

        // 第三种 通过方法响应点击事件
        function threeFn(){
            alert("这是第三种点击方式");
        }
    </script>
// 监听页面单击事件
jQuery(document).click(function (event){
    if (event.target.id == "shade"){
        // 业务
    }
});

22.2常用方法

  • toggleClass class属性切换
$("p").toggleClass("main");
  • 光标悬停,光标移除
<div id="bottomFilter1"  onclick="_mapFilter(1);" onmouseover="showPopupMenu()">光标悬停</div>
<div id="bottomFilter1"  onclick="_mapFilter(1);" onmouseleave="hidePopupMenu()">光标移除</div>
  • 遍历
// 元素遍历
$(selector).each(function(index,element))
// 数组遍历
 $.each(arr,function(i,j){
    console.log(i,j);
})
  • 鼠标

    鼠标移除:onmouseleave

    获取鼠标:onmouseover="showSearch(event);"

  • jQuery添加元素的方法

    • before() - 在被选元素之前插入内容
    • after() - 在被选元素之后插入内容
    • prepend() - 在被选元素的开头插入内容
    • append() - 在被选元素的结尾插入内容

22.10 js 中利用枚举

var typeEmum= {
        "startGc":'${ctx}/ownerScreen/dp/jgStatisticsList',
        "stopGc": "http://192.168.10.228:18999/XJB_AHSBD/a/fiveFDP/xjbDataGet/getTowerWeatherDP",
        "userNum": "http://192.168.10.228:18999/XJB_AHSBD/a/fiveFDP/xjbDataGet/getTowerWeatherDP"
    }
    // 使用
typeEmum[type];

22.190 js 获取浏览器高度

https://www.jb51.net/article/44519.htmopen in new window

  • window.screen.height 和 window.screen.width 屏幕分辨率的高,宽

  • window.innerHeight和window.innerWidth得到窗口的高度和宽度 , 针对iframe,获取到的是当前iframe 对应的 高度,宽度

22.195 js获取元素, 设置元素属性

var html = document.getElementsByTagName('html')[0];
var dl_second_nav=document.getElementsByClassName("dl-second-nav")[0];
var J_NavContent=document.getElementById("J_NavContent");
html.style.height = 2500+'px';
//alert(dl_second_nav.style.height);
dl_second_nav.style.height=2400+'px';
J_NavContent.style.height=2400+'px';

22.200 el从map中获取数据

{"a":{"a1":1,"a2":3537},"b":{"b1":1,"b2":3537}}
//前端el 解析: 获取a1对应的value ${data["a"]["a1"]}

22.201 js 动画,文字横向循环滚动

function f() {
    //根据id获取所对应的div,document意思是去整个html文档中找,getElementById是根据ID
    var tag = document.getElementById('i1')
    //拿到div中的文本,注意innertext方法没有括弧
    var content = tag.innerText
    //获取它这个字符串的第一个文字
    var z =content.charAt(0)
    //获取这个文本除第一个字以外的文本,用substring给它起始位置
    var  l = content.substring(1,content.length)
    //把第一个字符放到最后一位拼接起来
    var new_content = l+z
    //用新生成new_content把div中的文本替换掉
    tag.innerText = new_content
}
//setInterval是个定时器,第一个参数是要执行的内容,第二个参数是执行间隔,单位为毫秒
setInterval('f()',300);

动画,逐字添加 单词

<!DOCTYPE html>
<html style="font-size:14px">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" id="view1" content="width=device-width, initial-scale=1, maximum-scale=3.0, user-scalable=yes" />
    <title>网页缩放</title>
	<script>
		var text = "Hello how are you?";
		function typeText() {
			var i = 0;
			var interval = setInterval(function () {
				var parag = document.getElementById("theParagraph");
				parag.innerText = text.substr(0, i);
				if (text.length == i)
					clearInterval(interval);
				i++;
			}, 200)
		}
</script>
</head>
<body>
    <p id="theParagraph"></p>
    <button id="typeButton" onclick="typeText()" style="padding:5px">单击</button>
</body>
</html>

22.210 js定时器


var guiJiPolyColortimer = setInterval(function () {
            console.log("定时器");
        }, 600);


 if (guiJiPolyColortimer != null) {
            clearInterval(guiJiPolyColortimer);
        }       

小结:textContent、innerText、innerHTML的区别和差异

目前遇到的场景:

2020-09-10 14:06:34
有个时间格式的字符串如果用 document.getElementById('i1').innerText 会剔除 时间中的空格

1 、textContent属性可以获取指定节点的文本及其后代节点中文本内容,也包括<script><style>元素中的内容;

innerText也是获取指定节点的文本及其后代节点中文本内容,但不能获取<script><style>元素中的内容。

innerHTML是获取HTML文本结构内容。

2、textContent会获取display:none的节点的文本;而innerText好像会感知到节点是否呈现一样,不作返回。

也就是说,textContent能够获取元素的所有子节点上的文本,不管这个节点是否呈现;而innerText只返回呈现到页面上的文本。

3、要注意设置文本时被替换的可不只是文本了;这时textContent 、innerText属性相当于innerHTML属性,会把指定节点下的所有子节点也一并替换掉。

4、由于 innerText 受 CSS 样式的影响,它会触发重排(reflow),但 textContent 不会。

22.220 延迟,定时器


setTimeout(function () {// 延迟
    var num=Math.floor(Math.random()*10+1);
    console.log(num)
},600);


var refUserIdsCheckFlag=false;//作为入住人员 下拉选数据是否获取到到的标识,,因为初始化时需要对其进行默认选中操作
var mSiFunc6=setInterval(function(){// 定时器
    if(refUserIdsCheckFlag){//人员下拉选数据全部获取到后 在执行默认选择功能
        $scope.refUserIdsCheck();//初始化时 对 入住人员复选框 默认选中
        clearInterval(mSiFunc6);
    }
},100);

22.221 随机数/uuid

  • 随机数
Math.floor(Math.random() * (max- min) + min);// 不含max  

var num=Math.floor(Math.random()*10+1);// 1-10

//奇偶判断
if(num%2 ==0){
    // 偶数
}else{
    // 奇数
}    


  • uuid
//1.用于生成uuid
function S4() {
	return (((1+Math.random())*0x10000)|0).toString(16).substring(1);
}
function guid() {
	return (S4()+S4()+"-"+S4()+"-"+S4()+"-"+S4()+"-"+S4()+S4()+S4());
}
// 调用
var uuid = "cms"+guid();

//2. 利用时间
var uuid = "cms"+mydate.getDay()+mydate.getHours()+mydate.getMinutes()+mydate.getSeconds()+mydate.getMilliseconds()+Math.round(Math.random()*10000);

22.230 获取图片的实际 大小

// 图片地址
var img_url = '13643608813441.jpg'
// 创建对象
var img = new Image()
// 改变图片的src
img.src = img_url
// 判断是否有缓存
if(img.complete){
    // 打印
    alert('from:complete : width:'+img.width+',height:'+img.height)
}else{
    // 加载完成执行
    img.onload = function(){
        // 打印
        alert('width:'+img.width+',height:'+img.height)
    }
}

22.240图片放大的简单例子

场景1

<!DOCTYPE html>
<html lang="zh-cmn-Hans">
  <head>
    <meta http-equiv="Content-Language" content="zh-cn" />
    <meta http-equiv="Content-Type" content="text/html; charset=gb2312" />
    <title>用鼠标滚轮滚动控制图片的缩小放大</title>
    <script language="javascript">
      function bbimg(o) {
        console.log(event.wheelDelta);
        var zoom = parseInt(o.style.zoom, 10) || 100;
        zoom += event.wheelDelta / 12;
        if (zoom > 0) o.style.zoom = zoom + "%";
        return false;
      }
    </script>
  </head>
  <body>
    <p>将鼠标放在图片上,点击一下,然后滚动鼠标滚轮试试看</p>
    <p>
      <img border="0" src="https://gitee.com/mylishihuan/image/raw/master/img/20200914161940.jpg" onmousewheel="return bbimg(this)" />
    </p>
  </body>
</html>

场景2:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <title>移动缩放图片</title>
  </head>
  <body>
    <style>
      #log {
        position: fixed;
        top: 0;
        right: 0;
        width: 200px;
        background: #eee;
        color: #333;
        padding: 5px;
      }
    </style>
    <div id="log"></div>
    <script>
      function log() {
        document.getElementById("log").innerHTML =
          document.getElementById("log").innerHTML +
          "<br>" +
          [].join.call(arguments, ",");
      }
    </script>

    <style>
      * {
        margin: 0;
        padding: 0;
      }
      body {
        background: #333;
      }
      #box {
        position: relative;
        overflow: hidden;
        margin: 50px auto;
        border: 1px solid #fff;
        background: #fff;
      }
      #box img {
        position: absolute;
      }
    </style>
      <!-- 需要注意,如果没有实现效果,可能是 box,img标签需要把width,height属性写入到 元素上,不能写在css文件中-->
    <div id="box" style="width: 500px; height: 500px;">
      <img src="http://cdn.iknow.bdimg.com/static/common/pkg/common_z_63fa369.png" style="width: 827px; height: 262px;"/>
    </div>

    <script>
      evnt = function (event) {
            var evn = event,
            eventDoc, doc, body,
            button = evn.button
            evn.target = evn.target || evn.srcElement;

        // Calculate pageX/Y if missing and clientX/Y available
        if (evn.pageX == null && evn.clientX != null) {
            eventDoc = evn.target.ownerDocument || document;
            doc = eventDoc.documentElement;
            body = eventDoc.body;

            evn.pageX = evn.clientX + (doc && doc.scrollLeft || body && body.scrollLeft || 0) - (doc && doc.clientLeft || body && body.clientLeft || 0);
            evn.pageY = evn.clientY + (doc && doc.scrollTop || body && body.scrollTop || 0) - (doc && doc.clientTop || body && body.clientTop || 0);
        }

        if (!evn.preventDefault) {
            evn.preventDefault = function() {
                this.returnValue = false;
            }
        }

        if (!evn.stopPropagation) {
            evn.stopPropagation = function() {
                this.cancelBubble = true;
            }
        }

        if (evn.which == null && (evn.charCode != null || evn.keyCode != null)) {
            evn.which = evn.charCode != null ? evn.charCode : evn.keyCode;
        }

        // Add which for click: 1 === left; 2 === middle; 3 === right
        // Note: button is not normalized, so don't use it
        if (!evn.which && button !== undefined) {
            evn.which = (button & 1 ? 1 : (button & 2 ? 3 : (button & 4 ? 2 : 0)));
        }
        return evn
    };

    function getOffset(o) {
        var left = 0,
            top = 0;
        while (o != null && o != document.body) {
            top += o.offsetTop;
            left += o.offsetLeft;
            o = o.offsetParent;
        }
        return {
            left: left,
            top: top
        };
    }

      (function() {
            var d = document,
                bind = function(b, a, c) {
                    b.addEventListener ? b.addEventListener(a, function(event) {
                        c.call(b, evnt(event));
                    }, false) : b.attachEvent("on" + a, function(event) {
                        c.call(b, evnt(window.event));
                    });
                },
                on = function(b, o) {
                    for (var a in o) {
                        bind(b, a, o[a]);
                    }
                };

            var isRun,
                startX,
                startY,
                endX,
                endY,
                rX,
                rY,
                bgX = 0,
                bgY = 0,
                $b = d.getElementById("box");
            ww = parseInt($b.style.width),
            wh = parseInt($b.style.height),
            i = $b.getElementsByTagName('img')[0],
            img = i.style,
            imgw = parseInt(img.width),
            imgh = parseInt(img.height),
            scaleSize = 1;

            function rs() {
                var w, h;
                //以完全显示图片为基准,如果改为>,则为以铺满屏幕为基准
                if (ww / wh < imgw / imgh) {
                    w = ww;
                    h = imgh * ww / imgw;
                    bgX = 0;
                    bgY = -(h - wh) / 2;
                    scaleSize = ww / imgw; //初始比率
                } else {
                    w = imgw * wh / imgh;
                    h = wh;
                    bgX = -(w - ww) / 2;
                    bgY = 0;
                    scaleSize = wh / imgh;
                }
                img.width = w + "px";
                img.height = h + "px";
                img.left = bgX + "px";
                img.top = bgY + "px";
            }
            rs();
            /* Init */
            on(d, {
                "mousedown": function(e) {

                    //按中建快速还原大小
                    if (e.which === 2) {
                        rs();
                    }
                    if (e.which === 1 && e.target && (e.target === i || e.target === $b)) {
                        isRun = true;
                        startX = e.pageX;
                        startY = e.pageY;

                        e.preventDefault();
                    }
                },
                "mouseup": function(e) {
                    if (e.which !== 1) {
                        return;
                    }

                    img.cursor = "default";
                    isRun = false;
                     if(typeof(rX)!=="undefined")//这个判断原作没有,去掉该判断会出现单击后,放大缩小不是鼠标位置的情况;处理加载后就点击的情况;即rX是undefined          
                    {
                        bgX = rX;
                        bgY = rY;
                    }

                    e.preventDefault();
                },
                "mousemove": function(e) {
                    //
                    if (e.which !== 1) {
                        return;
                    }
                    if (isRun) {
                        e.preventDefault();
                        img.cursor = "move";
                        endX = e.pageX;
                        endY = e.pageY;
                        rX = bgX + endX - startX;
                        rY = bgY + endY - startY;

                        img.left = rX + "px";
                        img.top = rY + "px";
                    }
                },
                "mousewheel": function(e) {
                    //以鼠标为中心缩放,同时进行位置调整
                    var deltaY = 0;
                    var x = e.pageX;
                    var y = e.pageY;

                    e.preventDefault();

                    if (e.target && (e.target === i)) {

                        var l = getOffset($b);
                        x = x - l.left;
                        y = y - l.top;

                        var p = (e.wheelDelta) / 1200;
                        var ns = scaleSize;
                        ns += p;
                        ns = ns < 0.1 ? 0.1 : (ns > 5 ? 5 : ns); //可以缩小到0.1,放大到5倍

                        //计算位置,以鼠标所在位置为中心
                        //以每个点的x、y位置,计算其相对于图片的位置,再计算其相对放大后的图片的位置
                        bgX = bgX - (x - bgX) * (ns - scaleSize) / (scaleSize);
                        bgY = bgY - (y - bgY) * (ns - scaleSize) / (scaleSize);
                        scaleSize = ns; //更新倍率

                        img.width = imgw * ns + "px";
                        img.height = imgh * ns + "px";
                        img.top = bgY + "px";
                        img.left = bgX + "px";
                    }
                }
            });

        })();
    </script>
  </body>
</html>

22.250 语音播报

<script type="text/javascript">
    // 语音播报
    var audio;
    voiceadiomethod=function(text) {
        if(!voiceRecognitionFlag){
            //layui.layer.msg("语音播报已关闭.......");
            return;
        }
        if (text && text != '') {

            if (audio) {
                try {
                    document.body.removeChild(audio);// 移除 音频控件
                } catch (e) {
                    console.log("无需移除:"+e)
                }
            }
            text = encodeURIComponent(text);
            var address = "https://tts.baidu.com/text2audio?lan=zh&pdt=301&vol=9&per=0&cuid=baike&ctp=1&tex=" + text;
            // 如果浏览器支持,可以设置autoplay,但是不能兼容所有浏览器
            audio = document.createElement('audio');
            audio.id = "aaron";
            audio.autoplay = true;
            audio.preload = true;
            audio.controls = true;
            audio.src = address;
            audio.addEventListener('ended', function () {
                // 设置则播放完后移除audio的dom对象
                document.body.removeChild(audio);
            }, false);
            audio.addEventListener('error', function () {
                document.body.removeChild(audio);
                console.log('合成出错url:' + address + '\nAudio错误码:' + audio.error.code);
            }, false);
            audio.loop = false;
            audio.volume = 1;
            // 在body元素下apppend音频控件
            document.body.append(audio);
        }
    }
    // 移除语音播报
    removeAudio=function(){
        if (audio) {
            try {
                document.body.removeChild(audio);// 移除 音频控件
            } catch (e) {
                console.log("无需移除:"+e)
            }
        }
    }
</script>

22.160 iframe

  • scrolling="no" 禁用滚动条
  • 父页面调用子页面的 方法 window.frames["ifrom_name"].methodsChild();
  • 取iframe 页面高度,定义样式
<script>
    //父页面调用子页面的 方法
    function findMore() {
        // 调用子页面 findMore 方法
        window.frames["window_popup_iframe"].findMore();
        // 如果上面的方法报错,则用下面这个
         document.getElementById("taskContent").contentWindow.findMore();// 调用子页面方法
        document.getElementById("taskContent").contentWindow.document.getElementById('dundianId').value=id;// 给子页面赋值
       
        
        
    }
    // 取iframe 页面高度,定义样式
    function changeIframeStyle(){
        var Scale = document.querySelector("iframe").offsetParent;// 正常应该是下面的写法,但是目前还不知道,为什么有时不行
    	var Scale = document.querySelector("iframe").contentDocument.querySelector("body");
    	Scale.style.transform = "scale("+ zoomScale +",1)";
    }  
    // ifame 给父页面赋值
    parent.document.getElementById('f_id').value = 'xxxxxxx';
    

    
</script>

<iframe id="window_popup_iframe" name="window_popup_iframe"  width="1780" height="1216" frameborder="no" scrolling="no" border="0"
	src="/CPMS/a/ownerScreen/dp/jgStatisticsList?type=startGc"  marginwidth="0" marginheight="0" allowtransparency="yes" 
	style="overflow: auto !important;" >
</iframe>



js和jquery给iframe src赋值的3种方法open in new window

  • 方法一

这是最常用的js给iframe src赋值的方法,代码如下:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>iframe src赋值的方法</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
</head>
<body>
<iframe frameborder="1" id="barframe" ></iframe>
</body>
</html>
<script type="text/javascript">
document.getElementById("barframe").src = "http://localhost/EXAMPLE/iframe/example.html";
</script>
  • 方法二

通过js创建一个iframe元素,然后再给该元素src赋值,代码如下:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>iframe src赋值的方法</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
</head>
<body>
</body>
</html>
<script type="text/javascript">
var myIframe = document.createElement('iframe');
myIframe.src = 'http://localhost/EXAMPLE/iframe/example.html';
document.body.appendChild(myIframe);

/**
	 var myIframe = document.createElement('iframe');
        myIframe.src = '${ctx}/map3D/map3DPopup?pmisid=12M00000035386353';
        myIframe.id = 'towerPopFrame';
        myIframe.width = $("#tower_pop_wrap").width();
        myIframe.height = $("#tower_pop_wrap").height();
        document.getElementById("tower_pop_wrap").appendChild(myIframe);

*/

</script>

最后一句 document.body.appendChild(myIframe); 是表示在 body 里添加刚定义的 myIframe 这个控件。

我们也可以把该iframe添加到某一个div容器里,写法如下:document.getElementById("div1").appendChild(myIframe); , div1是该div容器的id 。

  • 方法三

上面两个方法都是用js来实现的,其实我们也可以用jquery来实现,代码如下:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>iframe src赋值的方法</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<script src="http://www.webkaka.com/script/jquery-1.4.2.min.js" type="text/javascript"></script>
<script>
$(document).ready(function() {
  $('#barframe').attr('src', 'http://localhost/EXAMPLE/iframe/example.html');
});
</script>
</head>
<body>
<iframe frameborder="1" id="barframe"></iframe>
</body>
</html>

特别注意,上述jquery代码不能缺少 $(document).ready(); ,否则iframe src赋值失败,除非把jquery的代码放在 <iframe ... 的html代码后面。此外,还需要在 <head></head> 里引用 jquery.js 文件

案例:

<div id="tower_pop" class="tower_pop hide" style="width: 40%;height: 100%;overflow: hidden;top: 0px;right: 0px;position: absolute;" >
        <div id="tower_pop_wrap" style="width:100%;height: 100%;border: 1px #f10707 solid;"></div>
</div>
<script type="text/javascript">
   showTowerPopup=function(){
    if($("#tower_pop").hasClass("hide")){// 显示
        $("#tower_pop").removeClass("hide");
        var myIframe = document.createElement('iframe');
        myIframe.src = '${ctx}/map3D/map3DPopup?pmisid=12M00000035386353';
        myIframe.id = 'towerPopFrame';
        myIframe.width = $("#tower_pop_wrap").width();
        myIframe.height = $("#tower_pop_wrap").height();
        document.getElementById("tower_pop_wrap").appendChild(myIframe);
    }else{//隐藏
        $("#tower_pop").addClass("hide");
        $("#tower_pop_wrap").empty();
    }
} 
</script>

iframe 设置高度

可以不用通过jq 来自定义高度,直接通过 width="100%" height="100%" 来保证高度100%

                <iframe id="mainFrame" name="mainFrame" src="${ctx}/jkzx/jkzxModule/mainContent" style="" scrolling="yes" frameborder="no" width="100%" height="100%"></iframe>htmL

iframe 父页页面

  • iframe获取父页面元素:

    • JavaScript: $(window.parent.document.getElementById("元素id"))

    • jquery: $("#元素id", parent.document)

  • 父页面获取iframe页面元素(iframe加载完之后再获取里面的元素):

    • JavaScript:window.frames["iframeId"].document.getElementById("元素id")

      document.getElementById("iframeId").contentWindow.document.getElementById("元素id")

    • jquery: $("#元素id", document.frames("iframeId").document) 如果报错 就用下面这个

      $('#iframeId').contents().find("#元素id")[0]

  • iframe获取父页面函数方法: 先通过window.parent获取到父元素,在调用该对象上的方法

    • JavaScript: window.parent.funcName()

    • jquery: $(window.parent)[0].funcName()

  • 父页面获取iframe页面函数方法: 先获取到子页面的window对象,然后在调用

window.onload = function() {
  var ifra = document.getElementById("ifra");
  ifra.contentWindow.funcName();
}

监听iframe 页面加载完成事件

$(document).ready(function() {
            var iframe = document.getElementById("mainFrame");
            if (iframe.attachEvent) {
                iframe.attachEvent("onload", function() {
                    //iframe加载完成后你需要进行的操作
                    alert("加载完成")
                });
            } else {
                iframe.onload = function () {
                    //iframe加载完成后你需要进行的操作
                    alert("加载完成2222")
                };
            }
        })
;

案例:tab切换,iframe修改 src

<style>
	.header{
            font-family: Microsoft YaHei;
            font-size: 1.3em;
            font-weight: 800;
            height: 40px;
            width: 100%;
            display: flex;
            align-items:center;
            justify-content:center;
            padding: 10px 0;
        }
        .header_wrap{
            display: flex;
            align-items: center;
            justify-content: center;
            border-radius: 25px;
            background: #012445;
            border: 1px solid #104c8b;
        }
        .header .tab{
            color: #6f7886;
            cursor: pointer;
            padding: 8px 30px;
            border-radius: 25px;
            animation-delay:1s;
            -webkit-animation-delay:2s; /* Safari 和 Chrome */
        }
        .header .tab.check{
            color: #333;
            background: #eee;
            box-shadow: 0px 1px 2px rgba(0,0,0,0.2);
            /*background: linear-gradient(to bottom, #eeeff9 0%,#3399ff 100%);*/
        }
</style>

<%-- 头部--%>
    <div class="header">
        <div class="header_wrap">
            <div id="pic_detail" class="tab check" style="" onclick="switchTab(this,'pic_detail');">图像</div>
            <div id="list_detail" class="tab" onclick="switchTab(this,'list_detail');" >详情</div>
        </div>
    </div>
 var urlType={
            'pic_detail':'${ctx}/trans/trans/transPictureOnlyNew?isCj=${isCj}&equipid=${equipid}&rtime=${rtime}&jkzx=${jkzx}',
            'list_detail':'${ctx}/trans/trans/transPictureDetail?isCj=${isCj}&equipid=${equipid}&rtime=${rtime}&jkzx=${jkzx}',
        }
        var tabType = 'pic_detail';// 默认查询图片
        // tab 切换
        function switchTab(this_,id){
            tabType = id;
            $(".tab").removeClass("check");
            $(this_).addClass("check");
            loading("数据加载中,请稍等.....");
            $("#mainFrame").attr("src",urlType[tabType]);
        }

22.170 js 获取服务器域名、ip、端口

var pathName=window.document.location.pathname;
    var curWwwPath=window.document.location.href;
    var pos=curWwwPath.indexOf(pathName);
    var prefixUrl=curWwwPath.substring(0,pos);
    console.log("pathName:"+pathName);
    console.log("curWwwPath:"+curWwwPath);
    console.log("pos:"+pos);
    console.log("prefixUrl:"+prefixUrl);
    
    alert("location:"+window.location);//location:http://localhost:8080/CPMS/a/mapMake/mapMakeIndex
        alert("href: "+window.location.href);//href: http://localhost:8080/CPMS/a/mapMake/mapMakeIndex
        alert("protocol: "+window.location.protocol);//http:
        alert("host&port: "+window.location.host);//localhost:8080
        alert("port: "+window.location.port);//8080
        alert("hostname: "+window.location.hostname);//localhost
    
    
    
    
    

22.170 回车

<input id="search-input" type="text" class="search-input" placeholder="请输入关键字" style="font-size: 25px;"
                       autocomplete="off" onkeydown="keyDownSeach(event);"><%--onchange="inputSearch(this, event);"--%>
<button id="searchButton" class="search-icon" onclick="inputSearch(this, event);"><span></span></button>
<script>
    //回车触发搜素,搜素
    function keyDownSeach(e) {
        // 兼容FF和IE和Opera
        var theEvent = e || window.e;
        var code = theEvent.keyCode || theEvent.which || theEvent.charCode;
        if (code == 13) {
            $("#searchButton").click();
        }

    }
    
        // 搜索
    function inputSearch(evt) {
        //var inputSearch = $(obj).val().trim();
        var inputSearch = $("#search-input").val().trim();
        if (inputSearch == null || inputSearch == '' || inputSearch == undefined) {
            return;
        }
        $("#resultHtml").empty();// 清空,
        $('#resultHtml').fadeIn();//菜单栏 淡入
        resultHtmlForInputSearch(inputSearch,false);// 将方法迁移出来, 方便语音识别用到
    }
</script>           
                
                

22.180 移动鼠标拖动窗口

https://my.oschina.net/u/4383702/blog/3678751open in new window

拖动窗口.html

使用 jquery-ui.min.js 的 draggable 方法

<!doctype html>
<html lang="en">
	<head>
		<meta charset="utf-8">
		<script src='http://libs.baidu.com/jquery/1.7.2/jquery.min.js'></script>
		<script src="http://libs.baidu.com/jqueryui/1.9.0/jquery-ui.min.js "></script>
		<style>
			#draggable { width: 150px; height: 150px; padding: 0.5em; border:#AAA
			1px solid; background-color:#EEE; }
		</style>
	</head>
	<body>
		<div id="draggable"> 求拖走 </div>
		<script>
			$(function() {   
				$("#draggable").draggable({
					draggable: false
				});
			});
		</script>
	</body>

</html>

22.190 元素title 属性



<style>
	  #mytitle {
            position: absolute;
            color: black;
            max-width: 460px;
            font-size: 14px;
            line-height:29px;
            padding: 4px;
            background: white;
            border: solid 1px #e9f7f6;
            border-radius: 5px;
        }
</style>
<script>
 $(function () {
            var x = 10;
            var y = 20;
            var newtitle = '';
            $('.tityou').mouseover(function (e) {
                newtitle = this.title;
                this.title = '';
                if(newtitle!=""){
                    $('body').append('<div id="mytitle" >' + newtitle + '</div>');
                }
                $('#mytitle').css({
                    'left': (e.pageX + x + 'px'),
                    'top': (e.pageY + y - 80 + 'px')
                }).show();
            })
            .mouseout(function () {
                this.title = newtitle;
                $('#mytitle').remove();
            }) 
            
            .mousemove(function (e) {
                $('#mytitle').css({
                   'left': (e.pageX + x +10 + 'px'),
                    'top': (e.pageY + y - 60 + 'px'),
                    'font-size':29+'px'
                }).show();
            })
        });

</script>

22.200 d3 的使用---待整理

https://blog.csdn.net/mylovewanzi/article/details/99703445open in new window 利用 d3 自定义比例尺


22.210 My97DatePickeropen in new window 组件

https://blog.csdn.net/xiangff_csdn/article/details/78688506open in new window

<!--开始时间 -->
<input name="applyStart" id="applyStart" type="text"  class="input-medium Wdate required"
                           value="<fmt:formatDate value="${ydxjApply.applyStart}" pattern="yyyy-MM-dd"/>"
                           onclick="WdatePicker({dateFmt:'yyyy-MM-dd',isShowClear:true,maxDate:'#F{$dp.$D(\'applyEnd\')}',isShowClear:true,onpicked:pickedFunc});" />
<!--结束时间 -->
<input name="applyEnd" id="applyEnd" type="text"  class="input-medium Wdate required"
                           value="<fmt:formatDate value="${ydxjApply.applyEnd}" pattern="yyyy-MM-dd"/>"
                           onclick="WdatePicker({minDate:'#F{$dp.$D(\'applyStart\')}',dateFmt:'yyyy-MM-dd',isShowClear:true,onpicked:pickedFunc});"/>

<script type="text/javascript">
    /**
		自定义单击事件:
         	onpicked:pickedFunc
    		onpicked:function(){getRuleName();
    */
    
	 /*计算天数*/
        function datedifference(sDate1, sDate2) {//sDate1和sDate2是2006-12-18格式
            var dateSpan, tempDate, iDays;
            sDate1 = Date.parse(sDate1);
            sDate2 = Date.parse(sDate2);
            dateSpan = sDate2 - sDate1;
            dateSpan = Math.abs(dateSpan);
            iDays = Math.floor(dateSpan / (24 * 3600 * 1000));
            return iDays+1;
        }
        /* 计算 请假天数*/
        function pickedFunc() {
            var applyStart = $("#applyStart").val();
            var applyEnd = $("#applyEnd").val();
            if(applyStart!=null && applyStart!=''&& applyEnd!=null && applyEnd!=''){
                $("#applyDays").val(datedifference(applyEnd,applyStart));
            }
        }
</script>

a) 在发list页面 只展示用:<fmt:formatDate value="${planWorkTicket.timeFlow}" pattern="yyyy-MM-dd HH:mm:ss"/>

b) 在form页面 <input name="planStartDate" type="text" maxlength="20"

value="<fmt:formatDate value="${planWorkTicket.planStartDate}" pattern="yyyy-MM-dd HH:mm:ss"/>" onclick="WdatePicker({dateFmt:'yyyy-MM-dd HH:mm:ss',isShowClear:true});"/>

img
img
<!--list 页面时间段查询  -->
<form:input path="createDateStart" autocomplete="off" onclick="WdatePicker({dateFmt:'yyyy-MM-dd'});"  class="input-medium Wdate"/><form:input path="createDateEnd" autocomplete="off" onclick="WdatePicker({dateFmt:'yyyy-MM-dd'});"  class="input-medium Wdate"/>

<!--
    <if test="createDateStart != null and createDateStart != ''">
        AND to_char(a.create_date,'yyyy-MM-dd') <![CDATA[ >= ]]> #{createDateStart}
    </if>
    <if test="createDateEnd != null and createDateEnd != ''">
        AND to_char(a.create_date,'yyyy-MM-dd') <![CDATA[ <= ]]> #{createDateEnd}
    </if>
-->


  • 利用字符串拼接使用时间组件

var html='<tr class="tbTrJd tbTrJdTj" id="trJdTj'+index+'">'+
		'<td style="border:1px grey solid;text-align: center;"><input name="planWorkTicketGroundwireList['+num+'].startTime" id="startTime'+num+'" type="text" class="readOnlyInput"   							onclick="WdatePicker({dateFmt:\'yyyy-MM-dd\',maxDate:\'#F{$dp.$D(\\\'endTime'+num+'\\\')}\',isShowClear:true});"/></td>'+
		'<td style="border:1px grey solid;text-align: center;"><input name="planWorkTicketGroundwireList['+num+'].endTime" id="endTime'+num+'" style="font-size:14px; border: medium none;"  					onclick="WdatePicker({dateFmt:\'yyyy-MM-dd\',minDate:\'#F{$dp.$D(\\\'startTime'+num+'\\\')}\',isShowClear:true});"/></td>'+
		'</tr>'
注: maxDate:'#F{$dp.$D(\'txtEndDay\')}'    所以在拼接时 自带的格式中出现特殊字符的比如 '  \  等都需要转义才能保证其格式 

22.220 JQuery获取器中根据属性或属性值获得元素open in new window

1.获取页面p标签中属性有id的元素

$("p[id]")

2.根据属性值获得元素

$("input[name$='aaa']") 

获取的是name值中带有aaa的input元素的集合

3.[attribute!=value],匹配所有不含有指定的属性,或者属性不等于特定值的元素

$("input[name!='aaa']")

相当于排除input的name值等于aaa的元素,选择其他所有的元素

4.[attribute*=value],匹配给定的属性是以包含某些值的元素

$("input[name*='aaa']") 

,匹配的是input中name属性的值中包含aaa的元素,

5.[attribute^=value],匹配给定的属性是以某些值开始的元素

$("input[name^='aaa']") 

匹配input的name属性的值,是以aaa为开头的,符合这一个特征值得input元素

22.230 js map

map说明:

Mapopen in new window 是一个带键的数据项的集合,就像一个 Object 一样。 但是它们最大的差别是 Map 允许任何类型的键(key)。

它的方法和属性如下:

  • new Map() —— 创建 map。
  • map.set(key, value) —— 根据键存储值。
  • map.get(key) —— 根据键来返回值,如果 map 中不存在对应的 key,则返回 undefined
  • map.has(key) —— 如果 key 存在则返回 true,否则返回 false
  • map.delete(key) —— 删除指定键的值。
  • map.clear() —— 清空 map。
  • map.size —— 返回当前元素个数。
let map = new Map();

map.set('1', 'str1');   // 字符串键
map.set(1, 'num1');     // 数字键
map.set(true, 'bool1'); // 布尔值键

// 还记得普通的 Object 吗? 它会将键转化为字符串
// Map 则会保留键的类型,所以下面这两个结果不同:
alert( map.get(1)   ); // 'num1'
alert( map.get('1') ); // 'str1'

alert( map.size ); // 3

js 遍历map

  • 方式1
var typeMuenEnum={
            "tqqk":"天气情况",
            "gttz":"GT台账",
            "xltz":"线路台账",
            "sjtz":"设计图纸",
            "yhqx":"隐患/缺陷",//隐患/缺陷   有 tab 所以 不要加标题
            "jksk":"交跨/三跨",
            "rgxs":"人工巡视",// 人工巡视
            "wrjxs":"无人机巡视",//无人机巡视
            "wpxs":"微拍图片"
        }
// 方式一
for (var key in typeMuenEnum) {
       console.log(typeMuenEnum[key]);
}
  • 方式2
var map = new Map();
map.forEach(function(value){
  console.log("key",value)  //输出的是map中的value值

})

创建map对象(key 是string ,value 是数组对象)

jQuery.each(jdxJsonArr,function(index,item){
     if(jdxForTowerMap[item.towerId] == undefined){
         jdxForTowerMap[item.towerId] = [];
     }
     jdxForTowerMap[item.towerId].push(item);
});

将键值对放入map对象

map.set("key",value);// 可以直接覆盖 value
map.set("key1",value1)
map.set("key2",value2)

根据key获取map值

map.get(key)

.删除map指定对象

delete map[key]

map.delete(key)

22.340 js 拼接/ 模板字符串

1. 模板字符串

注:jsp 写法毕竟特殊 <div id="\${type}" > 需要在 $ 符号前加 反斜杠

let name = "小芳";
let age = 13;
//传统写法
let str1 = '名字' + name + '年龄' + age;
console.log(str1);//名字小芳年龄ma13
//使用模板字符串写法
let str2 = `名字${name}年龄${age}`;
console.log(str2);//名字小芳年龄13
// 多行 的拼接
var text = ` ${name},no matter what you do,
  I trust you.`;
20210127
20210127

2. 字符串拼接

'<td  onclick="updateBusiness(\'work_person_division\',\''+data.id+'\' , \'500\');">'+   //拼接多个字段
<input type="text"  value="'+data.workPersonDivisionList[i].workContent+'"/></td>';

html+="<input  name='"+'postionZdData_'+index+"' value='"+item.value+"' onclick='initPostionZd(\""+item.value+"\");' id='checkbox-999-"+item.value+"' />";

html+= "<div class='bottomFilter8_tl'  id='zd"+item.value+"' onclick='checkedZd(\""+item.value+"\",this,\"bottomFilter8\");'>"+
"<div class='mes_close'  onclick='removePushMesPopup(\"push_mes_popup_\""+mes_html_index+"\")'><i class='icono-crossCircle'></i></div>"+

22.350 复选框

  • 设置复选框大小 需要 同时设置height 和width 才会生效 <input type="checkbox" style="height: 20px; width: 20px;">

22.370 js 中 字符串和数值 的转换

// 字符串转 数字
parseFloat("123");




22.400 js计算坐标 之间的距离()

function toRad(d) {
    return d * Math.PI / 180;
}
function getDisance(lng1,lat1,lng2 , lat2) { //lat为纬度, lng为经度, 一定不要弄错
    var dis = 0;
    var radLat1 = toRad(lat1);
    var radLat2 = toRad(lat2);
    var deltaLat = radLat1 - radLat2;
    var deltaLng = toRad(lng1) - toRad(lng2);
    var dis = 2 * Math.asin(Math.sqrt(Math.pow(Math.sin(deltaLat / 2), 2) + Math.cos(radLat1) * Math.cos(radLat2) * Math.pow(Math.sin(deltaLng / 2), 2)));
    return dis * 6378137;
}
alert(  getDisance(119.84411419,29.98447129,119.84419419,29.98447129) );
var jdxForTowerMap={};// 分组 合并 将重叠的放一起
var cdItem = [];// 存储 被验证的重叠的 的对象,依次 比对,如果两两 重叠则 讲被比对象 放到 该数组中,后期 需要跳出 该对象的 比对
console.log(jdxJsonArr)
outer_loop:for (var i = 0; i < jdxJsonArr.length; i++) {
	var item= jdxJsonArr[i];
	if(cdItem.indexOf(item.id)!=-1){// 说明当前 对象 已经 和其他对象验证 重叠了,不用再去拿他 重新比较了
		continue outer_loop;// 跳出外循环 本下循环,执行下一次循环
	}
	if(jdxForTowerMap[i] == undefined){
		jdxForTowerMap[i] = [];
	}
	jdxForTowerMap[i].push(item);
	// 内层循环,比对 是否存在和当前 对象 距离很近的对象
	inner_loop:for (var j = i+1; j < jdxJsonArr.length-i-1; j++) {
		var item1= jdxJsonArr[j];
		var disance=getDisance(item.nowLongGps,item.nowLatGps,item1.nowLongGps,item1.nowLatGps);
		if(disance < 1){// 如果两点 之间 距离小于 10m ,则认为其是 重叠在一起,需要 归为一类,
			cdItem.push(item1.id);// 记录被比数值,下次循环 不用拿他再去 和其他对象比对了
			jdxForTowerMap[i].push(item1);
		}
	}
}

22.410 滚动条--滑块

基于Bootstrap的jQuery slider插件的使用bootstrap-slider.js

https://blog.csdn.net/u011127019/article/details/52992654open in new window

https://www.jq22.com/yanshi9075open in new window


###################
       HTML
###################

<input id="ex4" type="text" data-slider-min="-5" data-slider-max="20" data-slider-step="1" data-slider-value="-3" data-slider-orientation="vertical"/>

data-slider-orientation="vertical" 用来控制 滚动条的方向
###################
    JavaScript
###################

// With JQuery
$("#ex4").slider({
	reversed : true
});

// Without JQuery
var slider = new Slider("#ex4", {
	reversed : true
});

22.420 js 克隆

https://www.cnblogs.com/hubgit/p/6859910.htmlopen in new window

<!DOCTYPE html>
<html>

<head>
    <meta http-equiv="Content-type" content="text/html; charset=utf-8" />
    <title></title>
    <script src="http://lib.sinaapp.com/js/jquery/1.9.1/jquery-1.9.1.min.js"></script>
    <style>
    .left,
    .right {
        width: 300px;
        height: 120px;
    }
    
    .left div,
    .right div {
        width: 100px;
        height: 90px;
        padding: 5px;
        margin: 5px;
        float: left;
        border: 1px solid #ccc;
        background: #bbffaa;
    }
    </style>
</head>

<body>
    <h2>通过clone克隆元素</h2>
    <div class="left">
        <div class="aaron1">点击,clone浅拷贝</div>
        <div class="aaron2">点击,clone深拷贝,可以继续触发创建</div>
    </div>
    <script type="text/javascript">
        //只克隆节点
        //不克隆事件
        $(".aaron1").on('click', function() {
            $(".left").append( $(this).clone().css('color','red') )
        })
    </script>

    <script type="text/javascript">
        //克隆节点
        //克隆事件
        $(".aaron2").on('click', function() {
            console.log(1)
            $(".left").append( $(this).clone(true).css('color','blue') )
        })
    </script>
</body>

</html>

22.420 js 退出循环

  • break
  • continue: 跳出本次循环,执行下次循环
  • return

案例:双层循环

//loop_1用于对循环命名
 loop_1:for(var i=0;i<10;i++){
    loop_2:for(var j=0;j<5;j++){
         if(i==3 && j==4){
            break loop_1;//跳出循环loop_1
         }
     }
 }
 alert(i);//输出3

22.430 layer

  • 提示框
layer.msg('同上', {
  icon: 1,
  time: 2000 //2秒关闭(如果不配置,默认是3秒)
}, function(){
  //do something
});
  • 1) layer iframe 弹出窗,相对浏览器定位,可以用top.layer
var h = (window.innerHeight-10)+"px";
var w = (window.innerWidth/3*2)+"px";
top.layer.open({
		 type: 2, 
		 title: ['详情', 'font-size:18px;'],
		 area: [w, h],
		 offset: '80px',// 距离浏览器 顶部位置
		 anim: 0,
		 content: "${ctx}/msg/msgNewsInfo/formdetail2?id="+id 
//这里content是一个URL,如果你不想让iframe出现滚动条,你还可以content: ['http://sentsin.com', 'no']
	}); 

22.440 遍历,并返回值

getGraphicById=function(graphicsLayer,id){
    var return_graphic;
    var graphicArr = graphicsLayer.graphics;
    jQuery.each(graphicArr, function (index, graphic) {
        if (graphic.id == id) {
            return_graphic=graphic
            return true;
        }
    });
    return return_graphic;
}

22.450 Math函数

// 求2的开根号
function mySqrt(num){
		return Math.log(num)/Math.log(2);
}

22.500 ztree

zTree 收缩的两种方式

  • 方式1:对现有节点进行模糊匹配
var setting = {
            data: {
                simpleData: {enable: true,idKey: "id",pIdKey: "pId",rootPId: 0}
            },
            /*view: {
                expand:true,
                dblClickExpand: false,
                showLine: true
            },*/
            view: {
                fontCss: setFontCss_ztree ,
                showTitle :true
            },
            async:{enable:true,url:"${ctx}/map/dp/treeTowerData1?type=3",autoParam:["id=lineId","pId=officeId"]},
            callback:{
                onClick:function(event, treeId, treeNode){
                    var id = treeNode.id == '0' ? '' :treeNode.id;
                }
            }
        };
// 异步加载
function refreshTree(){
            $.getJSON("${ctx}/map/dp/treeLineData?type=1",function(data){///map/dp/treeLineData?type=1  ${ctx}/sys/office/treeData?type=6
                initZtree(data);
            });
        } 
var initZtree=function(data){
            tree = $.fn.zTree.init($("#tower_ztree"), setting, data);
            var nodes = tree.getNodesByParam("level", 0);
            for(var i=0; i<nodes.length; i++) {
                tree.expandNode(nodes[i], true, false, false);
            };
        };
        var searchtree = function(){
            var value = $("#search-input").val();
            var nodes = tree.getNodes();
            if (value == "") {
                refreshTree();
                return;
            }
            hideAllNode(nodes);
            var nodeList = tree.getNodesByParamFuzzy("name",value);
            updateNodes(nodeList);
        };
        //隐藏所有节点
        function hideAllNode(nodes){
            nodes = tree.transformToArray(nodes);
            for(var i=nodes.length-1; i>=0; i--) {
                tree.hideNode(nodes[i]);
            }
        }
        //更新节点状态
        function updateNodes(nodeList) {
            tree.showNodes(nodeList);
            for(var i=0, l=nodeList.length; i<l; i++) {
                //展开当前节点的父节点
                tree.showNode(nodeList[i].getParentNode());
                //显示展开符合条件节点的父节点
                while(nodeList[i].getParentNode()!=null){
                    tree.expandNode(nodeList[i].getParentNode(), true, false, false);
                    nodeList[i] = nodeList[i].getParentNode();
                    tree.showNode(nodeList[i].getParentNode());
                }
                //显示根节点
                tree.showNode(nodeList[i].getParentNode());
                //展开根节点
                tree.expandNode(nodeList[i].getParentNode(), true, false, false);
            }
        }

构造 ztree 熟结构PC端

	private String id;
	private String name;
	private String pId;
	private String iconSkin;
	private String isParent;// mybatis 不支持 boolen
	
	对应的sql
	SELECT t.id AS "id",
        t.tower_NAME AS "name",
        t.line_id AS "pId",
        'false' as "isParent"
    from bas_c_tower t

22.510 template.js模板引擎

js 模板引擎:https://aui.github.io/art-template/zh-cn/docs/installation.htmlopen in new window

https://www.cnblogs.com/w190/p/12890341.htmlopen in new window

<!DOCTYPE html>
<html>

	<head>
		<meta charset="UTF-8">
		<title>模板引擎</title>
		<script type="text/javascript" src="template.js"></script>
		<script type="text/html" id="resultTemplate">
			<h1>{{title}}</h1> {{each books as value i}}
			<div>{{value}}</div>
			{{/each}}
		</script>

		<script type="text/javascript">
			window.onload = function() {
				//模拟这个data数据是从服务器获取的数据
				//这个数据中有两个字段:一个是title,一个是books
				var data = { //data数据
					title: '四大名著图书信息',
					books: ['三国演义', '水浒传', '西游记', '红楼梦']
				};
				//template根据两个参数生成html片段保存在html里面
				//这里也就是把data数据保存到id为resultTemplate的template模板中去。
				var html = template("resultTemplate", data); //第一个参数是模板的id,第二个参数是data数据
				var container = document.querySelector("#container");
				container.innerHTML = html;
			}
		</script>

	</head>

	<body>
		<div id="container">

		</div>
	</body>

</html>

22.520 获取光标位置

var getScreen=function(event){
            var e = event || window.event;
            //return {'x':e.screenX,'y':e.screenY} // 相对于整个浏览器 而不是文档
            return {'x':e.pageX,'y':e.pageY}
        }

22.530 弹窗层

说明:

  • 页面 定义父容器 class='html_wrap'
  • 页面需要自定义 弹窗回调:popupCheck
  • 功能参考巡检保 jkzxModuleHomeView.jsp
image-20210512101200184
image-20210512101200184
  • css 部分
/* 自定义弹出层*/
.popup_wrap{
   /* height: 200px;
    width: 150px;*/
    box-shadow: 0 0 10px #4a90d8 inset, 0px 0px 30px rgb(0,153,184);
    font-family: Microsoft YaHei;
    font-size: 1.2em;
    font-weight: 600;
    text-align: center;
    display: flex;
    align-items: center;
    justify-content: center;
    box-sizing: border-box;
    cursor: pointer;
    background: rgb(0,0,0,0.8);
    color: #f4f4f4;
    border-radius: 5px;
    opacity: 0;
    left: 0px;
    top: 0px;
    padding: 10px;
}
.popup_wrap .item{
    padding: 5px 0;
    transition: all 0.6s;
    display: flex;
    align-items: center;
    justify-content: center;
}
.popup_wrap .item:hover{
    color: #13c3e3;
    background: #0e3056;
    /*transform: scale(1.1);*/
}
.popup_icon{
    padding-right: 10px;
}
  • js 部分
//================================================# 1.弹出层 #================================================
/**
    页面 定义父容器 class='html_wrap'
    页面需要自定义 弹窗回调:popupCheck
        功能参考 jkzxModuleHomeView.jsp
 */
/* 创建弹窗  */
var popover_width = 150;
var popover_height = 200;
var initPopupHTML = function(popupData,event,callback){
    var screen = getScreen(event);// 计算 鼠标位置
    if($(".popup_wrap").length>0){
        $(".popup_wrap").remove();
    }
    /* 弹出 先设置透明度为0 实现隐藏 ,然后用animate 设置 动画 从而 实现 弹窗的弹出*/
    var html =`<div id="popup_wrap" class="pa popup_wrap bs" style="left:${screen.x}px;top:${screen.y}px;width:${popover_width}px;height: ${popover_height}px">`+
                `<div class="resultHtml wh100 bs">`;
    jQuery.each(popupData, function (index, item) {
        var check=item.check==undefined?'':item.check;// 实现默认选中
        html+=      `<div id="${item.id}" title="${item.name}" class="item ${check}" onclick="popupCheck('${item.id}','${item.name}',${callback})">`;
        if(item.icon){
            html+=      `<img class="popup_icon zdy_popup_icon" title="" src="${item.icon}">`;// 预留 zdy_popup_icon 属性 供调用者 设置 自定义属性 样式
        }
        html+=`<div>${item.name}</div>`+
            `</div>`;
    });
    html+=`</div></div>`;
    $(".html_wrap").append(html);// html_wrap 整个页面 的 父容器
    // 设置高度(考虑如果数据太少 弹窗 显示不协调)
    if(popupData.length<=5){
        $(".popup_wrap").height(popupData.length*30+20);
    }

    openPopover(screen,event)// // 弹出 弹窗
}

/* 获取*/
var getScreen=function(event){
    var e = event || window.event;
    //return {'x':e.screenX,'y':e.screenY} // 相对于整个浏览器 而不是文档
    var popover_top=e.pageY+5;
    var popover_left=e.pageX+10;
    var window_width = $(".html_wrap").width();
    var window_height = $(".html_wrap").height();
    // 验证 是否 超出 父容器 右侧 用 弹窗 left(popover_left) + 弹窗宽度 popover_width 和 父容器 的宽度 比对
    if(popover_width+popover_left>=window_width){// 超出父容器,宽度 需要重新计算
        popover_left = window_width-popover_width-20;//用 父容器 宽度 - 弹窗宽度,在减去 一个padding =20
    }
    if(popover_height+popover_top>=window_height){// 超出父容器,高度 需要重新计算
        popover_top = window_height-popover_height+20;//用 父容器 宽度 - 弹窗宽度,在减去 一个padding =20
    }
    return {'x':popover_left,'y':popover_top}
}
// 弹出 弹窗
var openPopover = function(screen,event){
    event.stopPropagation();//用于定义 弹窗,点击其他区域 隐藏  弹窗,防止
    $(".html_wrap").addClass('popover-open');// 给 父元素 标记  ‘当前弹出窗口模式’
    // 需要 考虑,弹窗不能超出 父容器
    $("#popup_wrap").animate({
        //left:screen.x+'px',
        //top:screen.y+'px',
        opacity:"1"
    },600);
}


/* 关闭弹窗*/
var closePopover = function(){
    if($(".popup_wrap").length>0){
        $(".popup_wrap").remove();
        $(".html_wrap").removeClass('popover-open');// 为了实现 点击其他区域 关闭弹窗,对父节点 jkxz_div 定义 class 属性 popover-open 表示当前 弹窗激活
    }
}
function popupCheck(id,name,callback){
    closePopover();/* 关闭弹窗*/
    callback(id,name);
}
/* 弹出 默认选中*/
var resetCheckPopover = function(options,selectedId){
    jQuery.each(options, function (index, item) {
        if(selectedId==item.id){
            item.check='check';
        }else{
            item.check='';
        }

    });
}
/*
*   点击其他区域关闭弹窗
*       当前方法实现 的大前提,对于 openPopover 弹出层
*           需要使用 event.stopPropagation(); 阻止冒泡,否则 弹出还未谈起就被关闭
* */
$(document).click(function(){
    if($(".html_wrap").hasClass('popover-open')){
        closePopover();/* 关闭弹窗*/
    }
    // 调用 父页面 方法
    // 验证 父页面是否存在 弹窗 通过 是否存在 html_wrap 元素
    if($(".html_wrap", parent.document).length>0){
        // 父页面存在弹窗,,点击也需要关闭
        window.parent.closePopover();
    }
    // 验证子页面是否存在 弹窗
    if(document.getElementById("mainFrame") !=null && $('#mainFrame').contents().find(".html_wrap").length>0){
        // 子页面存在弹窗,,点击也需要关闭
        var ifra = document.getElementById("mainFrame");
        ifra.contentWindow.closePopover();
    }
});

  • 调用者


<script>
     var relativeUrlPath = '${ctxStatic}/images/jkzx/';
        var  pageSizeOptions = [
            {id:1,name:'一张',icon:relativeUrlPath+'small_icon/split_screen_1.png'},
            {id:4,name:'四张',icon:relativeUrlPath+'small_icon/split_screen_4.png'},
            {id:6,name:'六张',icon:relativeUrlPath+'small_icon/split_screen_6.png'},
            {id:9,name:'九张',icon:relativeUrlPath+'small_icon/split_screen_9.png'}
        ];
        /* 滚动时间*/
        var chooseTimeOptions = [
            {id:10,name:'10s'},
            {id:20,name:'20s'},
            {id:30,name:'30s'},
            {id:40,name:'40s'},
            {id:50,name:'50s'}
        ];
    
    
    
    
        var showPopover=function(type,event){
            var popupData=[];
            if(type=='officeType'){
                popupData=officeData
            }else if(type=='arrangeType'){
                popupData = pageSizeOptions;// 分屏
            }else if(type=='chooseType'){
                popupData = chooseTimeOptions;// 时间
            }
            initPopupHTML(popupData,event); /* 创建弹窗  */
        }


        function popupCheck(id,name){
            closePopover();/* 关闭弹窗*/
            alert('选择弹窗内容')
        }
</script>

22.540 Json对象与Json字符串的转化、JSON字符串与Java对象的转换open in new window(关键字:list转json )

参考:https://www.cnblogs.com/test-7/p/10144683.htmlopen in new window

JS中将后台model传过来的数据转换成JSON类型____ [ {key,value},{key,value},{key,value} ] 是list格式,如果在js中无法便利 那么就用下面的方法处理一下 (list页面遍历,list遍历,list遍历)

JAVA 中:model.addAttribute("datasJson", new Gson().toJson(mapList));

JS中:var data = eval(${datasJson });///用JSON.parse() 也可以转换

${fns:toJson(list)} JsonMapper.java 有一些将实体对象转为数组的方法

////可以用 标签遍历

一.Json对象与Json字符串的转化

1.jQuery插件支持的转换方式:
  $.parseJSON( jsonstr ); //jQuery.parseJSON(jsonstr),可以将json字符串转换成json对象
2.浏览器支持的转换方式(Firefox,chrome,opera,safari,ie9,ie8)等浏览器:
  JSON.stringify(obj)将JSON转为字符串。JSON.parse(string)将字符串转为JSON格式;
var a={"name":"tom","sex":"男","age":"24"}; 
var b='{"name":"Mike","sex":"女","age":"29"}'; 
var aToStr=JSON.stringify(a); 
var bToObj=JSON.parse(b); 
alert(typeof(aToStr));  //string 
alert(typeof(bToObj));//object

3.Javascript支持的转换方式: 
eval('(' + jsonstr + ')'); //可以将json字符串转换成json对象,注意需要在json字符外包裹一对小括号 
注:ie8(兼容模式),ie7和ie6也可以使用eval()将字符串转为JSON对象,但不推荐这些方式,这种方式不安全eval会执行json串中的表达式。

4.JSON官方的转换方式: 
http://www.json.org/提供了一个json.js,这样ie8(兼容模式),ie7和ie6就可以支持JSON对象以及其stringify()和parse()方法; 
可以在https://github.com/douglascrockford/JSON-js上获取到这个js,一般现在用json2.js。

二、JSON 字符串 与 java 对象的转换
1. 把java 对象列表转换为json对象数组,并转为字符串
    JSONArray array = JSONArray.fromObject(list);
    String jsonstr = array.toString();
2. 把java对象转换成json对象,并转化为字符串

  JSONObject object = JSONObject.fromObject(user);
  Log4jInit.ysulogger.debug(object.toString());
3.把JSON字符串转换为JAVA 对象数组
  JSONArray json = JSONArray.fromObject(userStr);//userStr是json字符串
  List<User> users= (List<User>)JSONArray.toCollection(json, User.class);
4.把JSON字符串转换为JAVA 对象
  JSONObject jsonobject = JSONObject.fromObject(jsonStr);
  User user= (User)JSONObject.toBean(object,User.class);

元素自定义属性

这种方式需要在自定义属性名前面加上data-

<div id="{{item.id}}" data-item="{{item}}" class="pic_check_box check" onclick="switchCheck(this);"></div>

<script>
var towerIdArr = [];// 被选中  towerid
var equipidArr = [];// 被选中 设备id
var filepathArr = [];// 被选中 选中图片id
$(".pic_check_box").each(function(){
    if($(this).hasClass("check")){// 选中
        var item = JSON.parse($(this).attr("data-item"));
        towerIdArr.push(item.towerId);
        equipidArr.push(item.equipid);
        filepathArr.push(item.filepath);
    }
});
</script>

22.560 js复制 文字和图片

参考: https://stackoverflow.com/questions/33175909/copy-image-to-clipboard/40547470#40547470open in new windowhttps://segmentfault.com/a/1190000015278418open in new window

使用clipboard.js,有两个限定

1.只复制目标节点的子节点,对于img标签,如果不额外包裹一层父元素,无法实现图片复制

2.只接受click事件,无法绑定其他事件。

方法1

<!DOCTYPE html>
<html>
 <head> 
  <title>复制</title> 
  <meta name="referrer" content="never" /> 
  <script src="https://cdn.jsdelivr.net/npm/clipboard@2/dist/clipboard.min.js"></script> 
  <script src="https://code.jquery.com/jquery-3.3.1.min.js"></script> 
 </head> 
 <body> 
  <div id="copyimg" class="copyable" style="height:100px;width:100px;"> 
   <img style="width:100%;height:100%;" src="http://172.16.10.244:2166/pic/20210525/86471603036765600_20210525T112046.jpg" alt="" /> 
  </div> 
  <div class="wechat-copy" onclick="copyImg('copyimg',event);"> 
   <button style="color:#FFFFFF;background-color: #263740">复制</button> 
  </div> 
  <script type="text/javascript">
   
    function SelectText(element) {
            var doc = document;
            if (doc.body.createTextRange) {
                var range = document.body.createTextRange();
                range.moveToElementText(element);
                range.select();
            } else if (window.getSelection) {
                var selection = window.getSelection();
                var range = document.createRange();
                range.selectNodeContents(element);
                selection.removeAllRanges();
                selection.addRange(range);
            }
        }
      // 方法一 监听 事件
        $(".copyable").click(function (e) {
            //Make the container Div contenteditable
            $(this).attr("contenteditable", true);
            //Select the image
			
            SelectText($(this).get(0));
            //Execute copy Command
            //Note: This will ONLY work directly inside a click listenner
            document.execCommand('copy');
            //Unselect the content
            window.getSelection().removeAllRanges();
            //Make the container Div uneditable again
            $(this).removeAttr("contenteditable");
            //Success!!
            alert("image copied!");
        });
      // 方法二 定义 onclick 事件,通过传递目标 元素 id
      function copyImg(id,event){
            $("#"+id).attr("contenteditable", true);
            //Select the image
            SelectText($("#"+id).get(0));
            //注意:这将只在点击侦听器中直接工作
            document.execCommand('copy');
            //取消选择的内容
            window.getSelection().removeAllRanges();
            //再次使容器Div不可编辑
            $("#"+id).removeAttr("contenteditable");
            //成功提示
            alertx("图片已复制到剪切板!");
        }
</script>   
 </body>
</html>

方法2

<!DOCTYPE html>
<html>
<head>
	<title>复制</title>
	 <meta name="referrer" content="never">
	<script src="https://cdn.jsdelivr.net/npm/clipboard@2/dist/clipboard.min.js"></script>
<script src="https://code.jquery.com/jquery-3.3.1.min.js"></script>

</head>
<body>
<div id='wechat-copy-main' style="opacity: 0">
<img class='img' src='https://tenfei04.cfp.cn/creative/vcg/veer/1600water/veer-308325838.jpg' style='width:50px;'><br/>
</div>
<br />
<span class="wechat-copy">
   <button style="color:#FFFFFF;background-color: #263740">复制</button>
</span>
<script type="text/javascript">
   
    $(".wechat-copy").click(function (t) {
        //$('.img').attr('src','https://tenfei04.cfp.cn/creative/vcg/veer/1600water/veer-308325838.jpg');
        var a = document.getElementById("wechat-copy-main");
        console.log(a);
        copyFunction(a, ".wechat-copy", "微信文案复制成功");
    });
    var copyFunction = function (t, a, i) {
		var e = new ClipboardJS(a, {
			target: function () {
				return console.log(t, a),
					t
			}
		});
		e.on("success", function (t) {
				alert('文案复制成功!');
				t.clearSelection()
		}),
		e.on("error", function (t) {
			console.log('复制失败');
				t.clearSelection()
		})
    };

</script>

</body>
</html>

22.570 jQuery动画

**使用animate 动画 ,如果设置的元素存在pading ,就算 将元素的width 设置为0 也不会 使元素空间释放出来,这里可以用 hide()来实现 隐藏并释放空间 **

自定义动画animate()

参考:https://www.w3school.com.cn/jquery/effect_animate.aspopen in new window

$(selector).animate(styles,speed,easing,callback)

animate() 方法执行 CSS 属性集的自定义动画。

该方法通过CSS样式将元素从一个状态改变为另一个状态。CSS属性值是逐渐改变的,这样就可以创建动画效果。

只有数字值可创建动画(比如 "margin:30px")。字符串值无法创建动画(比如 "background-color:red")。

**注释:**使用 "+=" 或 "-=" 来创建相对动画(relative animations)。

支持 使用 百分比 $("p").animate({width:"50%"});

参数描述
styles必需。规定产生动画效果的 CSS 样式和值。可能的 CSS 样式值(提供实例):**注释:**CSS 样式使用 DOM 名称(比如 "fontSize")来设置,而非 CSS 名称(比如 "font-size")、marginTop、paddingLeft........
speed可选。规定动画的速度。默认是 "normal"。可能的值:毫秒 (比如 1500)"slow""normal""fast"
easing可选。规定在不同的动画点中设置动画速度的 easing 函数。内置的 easing 函数:swinglinear扩展插件中提供更多 easing 函数。
callback可选。animate 函数执行完之后,要执行的函数。

参考:https://blog.csdn.net/a772116804/article/details/81909073open in new window

// animate():第一个参数:{width:200} 运动的值和属性 // 第二个-时间:默认400ms{},1000 //第三个-运动形式-两种:1.默认:swing(慢快慢) 2.linear(匀速) //第四个-回调函数 //$(this).animate({width:"300px",height:"300px"},2000,'linear',function(){alert(123)});

//stop():默认阻止当前运动,不阻止所有,stop(true) 阻止后续所有运动,stop(true,true) 当前运动立马完成 = finish()立即完成运动。

stop(true,true) 停止到最终的目标点

finish() 立即完成运动。

运动前加stop()可以清除运动队列(不总是重复)。(鼠标移入移除 mouseover、out)

$(this).stop().animate({width:'200px'},1000) //针对的是同一个元素上面的效果

jq animate动画详解

//动画延迟
.leftToRight{
    left:0;
}
$('.leftToRight').delay(800).animate({left:100px},"solw");
 
animated方法中没有封装transform属性
 
解决方案:
(1)css方法
 
$($sub).animate({},5000,function(){  
    $(this).css({'transform':'translateX(300px)'});  
})  
在动画函数的回调函数里执行。时间和效果就没了意义,毕竟函数是在动画完成之后才有调用
 
(2)addClass方法
可以通过addClass()方法来代替此动作: 
比如想旋转一个icon 
在css中加入一个class
Css代码
.add_transform{  
    transform:rotate(180deg);  
    -ms-transform:rotate(180deg);/* IE9 */  
    -moz-transform:rotate(180deg);/* Firefox */  
    -webkit-transform:rotate(180deg);/* Safari和Chrome */  
    -o-transform:rotate(180deg);/* Opera */  
    transition:all 0.5s ease-in-out;  
    -moz-transition:all 0.5s ease-in-out;/*Firefox 4 */  
    -webkit-transition:all 0.5s ease-in-out;/* Safari和Chrome */  
    -o-transition:all 0.5s ease-in-out;/* Opera */  
}  
 然后通过$(“选择器”).toggleClass(“.add_transform”);来使icon的旋转变为动画效果。
 
 <script>
//jQuery动画animate和scrollTop结合使用
$('li').click(function(){
    //$(document).scrollTop($(this).index()*viewHeight);
     var H = $(this).index()*viewHeight;
     var heiGht = $('#div1').offset().top;
     $('html,body').animate({scrollTop: H}, 1000);
  });
</script>
 
<body>
<script type="text/javascript" src="jquery-1.9.1.min.js"></script>
<style>
 #box { 
  width: 100px; 
  height: 100px; 
  background-color: red; 
 
  position:absolute; 
} 
 
#pox { 
  width: 100px; 
  height: 100px; 
  background-color: green; 
  position: absolute; 
  top: 200px; 
} 
</style>
</head>
<body>
	<input type="button" class="button" value="开始" />
	<input type="button" class="stop" value="停止" /> 
	    
	  <div id="box">box</div> 
	  <div id="pox">pox</div> 
<script type="text/javascript">
	 $(function () {   
	    $(".button").click(function () { 
	      $("#box").animate({ 
	        left: "300px"  //要想使用left top bottom right这种方向性的属性 先必须对"#box元素设置CSS 绝对定位 
	      }) 
	    })  
   
    //-------------------------------------同步动画  
    $(".button").click(function () { 
      $("#box").animate({ 
        width: "300px", 
        height: "200px", 
        opacity:0.5, //透明度为0.5 注:透明度的值在0-1之间 
        fontSize:"200px", //字体大小设为30px 
      }) //第一个参数:是一个对象,他是键值对的css 
    }) 
 
    //让指定元素左右移动
    $("#right").click(function(){
      $(".block").animate({left: '+50px'}, "slow");
    });
 
    $("#left").click(function(){
      $(".block").animate({left: '-50px'}, "slow");
    });
 
	//--------------------------------------列队动画,一个一个来 
    $(".button").click(function () { 
      $("#box").animate({ width: "300px"}, 1000, function(){ 
        $("#box").animate({height:"200px"},1000,function(){ 
          $("#box").animate({opacity:0.5},1000,function(){ 
            $("#box").animate({fontSize:"150px"},1000,function(){alert("完毕")}) 
          }); 
        }); 
      }); 
    }) 
 
	//在同一个元素的基础上,使用链式(队列)调用也可以实现列队动画 
 
    $(".button").click(function () { 
      $("#box") 
        .animate({ width: "300px" }, 1000) 
        .animate({ height: "200px" }, 1000) 
        .animate({ opacity: 0.5 }, 1000) 
        .animate({ fontSize: "150px" }, 1000, function () { alert("列队动画执行完毕")}) 
    }); 
	
	//那我们现在的需求是:不管你有几个元素,我都要他们依次实现列队动画效果。(测试了一下,只能用这种回调函数嵌套的方式来实现了) 
  
    $(".button").click(function () { 
      $("#box").animate({ width: "300px" }, 1000, function () { //box
        $("#pox").animate({ height: "200px" }, 1000, function () { //#pox
          $("#box").animate({ height: "200px"}, 1000, function () { 
            $("#pox").animate({ fontSize: "150px" }, 1000, function () { alert("列队动画执行完毕") }); 
          }) 
        }) 
      }) 
    }) 
	
	//那下面再来了解下,列队动画的停止 
      
    $(".button").click(function () { 
      $("#box")
      .animate({ left: "300px" },1000) 
      .animate({ bottom: "300px" }, 1000) 
      .animate({ width: "300px" }, 1000) 
      .animate({ height: "300px" }, 1000)                   
    }) 
  
    $(".stop").click(function () { 
     	$("#box").stop(true); // 加参数停止所有动画,不加停止当前 
    }) 
 
 //现在,我们想继续在.queue()方法后面再增加一个隐藏动画,这时发现居然无法实现。
/*这是.queue()特性导致的。
有两种方法可以解决这个问题,jQuery 的.queue()的回调函数可以传递一个参数,
这个参数是next 函数,在结尾处调用这个next()方法即可再链式执行列队动画。 
  */
    //链式编程实现队列动画 
    $(".button").click(function () { //四个动画 
      $("#box") 
        .slideUp(1000) 
        .slideDown(1000) 
        .queue(function (next) { //这个next是一个函数 
        $(this).css("background", "yellow"); 
        next();}) 
        .hide(1000); 
    }); 
  
    //顺序编程实现队列动画 我们看到使用顺序调用的列队,逐个执行,非常清晰 
    $(".button").click(function () { 
      $("#box").slideUp(1000); 
      $("#box").slideDown(1000); 
      $("#box").queue(function (next) { 
      	$(this).css("background", "yellow"); 
    	next(); }); 
      $("#box").hide(1000); 
    }); 
  });
	</script>
</body>

jQuery基础(动画篇 animate,显示隐藏,淡入淡出,下拉切换

https://www.cnblogs.com/mibear/p/6850440.htmlopen in new window

1.jQuery中隐藏元素的hide方法

$elem.hide()

让页面上的元素不可见,一般可以通过设置css的display为none属性。但是通过css直接修改是静态的布局,如果在代码执行的时候,一般是通过js控制元素的style属性,这里jQuery提供了一个快捷的方法.hide()来达到这个效果

搭配duration: 3000, 从而实现 动画效果

提供参数:

.hide( options ) 当提供hide方法一个参数时,.hide()就会成为一个动画方法。.hide()方法将会匹配元素的宽度,高度,以及不透明度,同时进行动画操作

 $("button:last").click(function() {
     $("#a2").hide({
         duration: 3000,
     })
});
2.jQuery中显示元素的show方法

hide是让元素显示到隐藏,show则是相反,让元素从隐藏到显示

  • show与hide方法是修改的display属性,通过是visibility属性布局需要通过css方法单独设置
  • 如果使用!important在你的样式中,比如display: none !important,如果你希望.show()方法正常工作,必须使用.css('display', 'block !important')重写样式
  • 如果让show与hide成为一个动画,那么默认执行动画会改变元素的高度,高度,透明度
3.jQuery中显示与隐藏切换toggle方法 (没有动画效果)

基本的操作:toggle();

这是最基本的操作,处理元素显示或者隐藏,因为不带参数,所以没有动画。通过改变CSS的display属性,匹配的元素将被立即显示或隐藏,没有动画。

  • 如果元素是最初显示,它会被隐藏
  • 如果隐藏的,它会显示出来

display属性将被储存并且需要的时候可以恢复。如果一个元素的display值为inline,然后是隐藏和显示,这个元素将再次显示inline

提供参数:.toggle( [duration ] [, complete ] )

同样的提供了时间、还有动画结束的回调。在参数对应的时间内,元素会发生显示/隐藏的改变,在改变的过程中会把元素的高、宽、不透明度进行一系列动画效果。这个元素其实就是show与hide的方法

 $("button:last").click(function() {
        $(".right").toggle(3000)
    });
4.jQuery中下拉动画slideDown

.slideDown():用滑动动画显示一个匹配元素

.slideDown()方法将给匹配元素的高度的动画,这会导致页面的下面部分滑下去,弥补了显示的方式

常见的操作,提供一个动画是时间,然后传递一个回调,用于知道动画是什么时候结束

.slideDown( [duration ] [, complete ] )

持续时间(duration)是以毫秒为单位的,数值越大,动画越慢,不是越快。字符串 'fast' 和 'slow' 分别代表200和600毫秒的延时。如果提供任何其他字符串,或者这个duration参数被省略,那么默认使用400 毫秒的延时。

具体使用:

$("ele").slideDown(1000, function() {
    //等待动画执行1秒后,执行别的动作....
});

注意事项:

  • 下拉动画是从无到有,所以一开始元素是需要先隐藏起来的,可以设置display:none
  • 如 果提供回调函数参数,callback会在动画完成的时候调用。将不同的动画串联在一起按顺序排列执行是非常有用的。这个回调函数不设置任何参数,但是 this会设成将要执行动画的那个DOM元素,如果多个元素一起做动画效果,那么要非常注意,回调函数会在每一个元素执行完动画后都执行一次,而不是这组 动画整体才执行一次

 $("button:last").click(function() {
            $("#a2").slideDown(3000,function(){
                alert('动画执行结束')
            })
        });

5.jQuery中上卷动画slideUp

最简单的使用:不带参数

$("elem").slideUp();

这个使用的含义就是:找到元素的高度,然后采用一个下滑动画让元素一直滑到隐藏,当高度为0的时候,也就是不可见的时,修改元素display 样式属性被设置为none。这样就能确保这个元素不会影响页面布局了

带参数:

.slideUp( [duration ] [, easing ] [, complete ] )

同样可以提供一个时间,然后可以使用一种过渡使用哪种缓动函数,jQuery默认就2种,可以通过下载插件支持。最后一个动画结束的回调方法。

因为动画是异步的,所以要在动画之后执行某些操作就必须要写到回调函数里面,这里要特别注意

  $("button:last").click(function() {
            $("#a2").slideUp(3000,function(){
                alert('动画执行结束')
            })
        });

6.jQuery中上卷下拉切换slideToggle

jQuery提供了一个便捷方法slideToggle用滑动动画显示或隐藏一个匹配元素

基本的操作:slideToggle();

这是最基本的操作,获取元素的高度,使这个元素的高度发生改变,从而让元素里的内容往下或往上滑。

提供参数:.slideToggle( [duration ] ,[ complete ] )

同样的提供了时间、还有动画结束的回调。在参数对应的时间内,元素会完成动画,然后出发回调函数

同时也提供了时间的快速定义,字符串 'fast' 和 'slow' 分别代表200和600毫秒的延时

注意:

  • display属性值保存在jQuery的数据缓存中,所以display可以方便以后可以恢复到其初始值
  • 当一个隐藏动画后,高度值达到0的时候,display 样式属性被设置为none,以确保该元素不再影响页面布局
   $("button").click(function() {
            $("#a1").slideToggle(3000)
        });

7.jQuery中淡出动画fadeOut

设置元素透明度为0,可以让元素不可见,透明度的参数是0~1之间的值,通过改变这个值可以让元素有一个透明度的效果。常见的淡入淡出动画正是这样的原理。

fadeOut()函数用于隐藏所有匹配的元素,并带有淡出的过渡动画效果

所谓"淡出"隐藏的,元素是隐藏状态不对作任何改变,元素是可见的,则将其隐藏。

.fadeOut( [duration ], [ complete ] )

通过不透明度的变化来实现所有匹配元素的淡出效果,并在动画完成后可选地触发一个回调函数。这个动画只调整元素的不透明度,也就是说所有匹配的元素的高度和宽度不会发生变化。

字符串 'fast' 和 'slow' 分别代表200和600毫秒的延时。如果提供任何其他字符串,或者这个duration参数被省略,那么默认使用400毫秒的延时

 $("p").fadeOut();

 $("p").fadeOut({
                duration: 1000
            });
 $("p").fadeOut(2000, function() {
                alert("隐藏完毕!");
            });

8.jQuery中淡入动画fadeIn

fadeOut是淡出效果,相反的还有淡入效果fadeIn,方法使用上两者都是一致的,只是结果相反

.fadeIn( [duration ], [ complete ] )

  • duration:指定过渡动画运行多长时间(毫秒数),默认值为400。该参数也可以为字符串"fast"(=200)或"slow"(=600)。
  • 元素显示完毕后需要执行的函数。函数内的this指向当前DOM元素。

fadeIn()函数用于显示所有匹配的元素,并带有淡入的过渡动画效果。

注意:

  • 淡入的动画原理:操作元素的不透明度从0%逐渐增加到100%
  • 如果元素本身是可见的,不对其作任何改变。如果元素是隐藏的,则使其可见

9.jQuery中淡入淡出切换fadeToggle

fadeToggle()函数用于切换所有匹配的元素,并带有淡入/淡出的过渡动画效果。之前也学过toggle、slideToggle 也是类似的处理方式

fadeToggle切换fadeOut与fadeIn效果,所谓"切换",即如果元素当前是可见的,则将其隐藏(淡出);如果元素当前是隐藏的,则使其显示(淡入)。

常用语法:.fadeToggle( [duration ] ,[ complete ] )

可选的 duration 参数规定效果的时长。它可以取以下值:"slow"、"fast" 或毫秒。 可选的 callback 参数是 fadeToggle完成后所执行的函数名称。

fadeToggle() 方法可以在 fadeIn() 与 fadeOut() 方法之间进行切换。如果元素已淡出,则 fadeToggle() 会向元素添加淡入效果。如果元素已淡入,则 fadeToggle() 会向元素添加淡出效果。 (和上面的方式一样)

10.jQuery中淡入效果fadeTo

淡入淡出fadeIn与fadeOut都是修改元素样式的opacity属性,但是他们都有个共同的特点,变化的区间要么是0,要么是1

fadeIn:淡入效果,内容显示,opacity是0到1 fadeOut:淡出效果,内容隐藏,opacity是1到0

如果要让元素保持动画效果,执行opacity = 0.5的效果时,要如何处理?

如果不考虑CSS3,我们用JS实现的话,基本就是通过定时器,在设定的时间内一点点的修改opacity的值,最终为0.5,原理虽说简单,但是总不如一键设置这么舒服,jQuery提供了fadeTo方法,可以让改变透明度一步到位

语法

.fadeTo( duration, opacity ,callback)

必需的 duration参数规定效果的时长。它可以取以下值:"slow"、"fast" 或毫秒。fadeTo() 方法中必需的 opacity 参数将淡入淡出效果设置为给定的不透明度(值介于 0 与 1 之间)。可选的 callback 参数是该函数完成后所执行的函数名称。

$("p").fadeTo("slow", 0.5);

$("p").fadeTo(1000, 0.2);
      
$("p").fadeTo(1000, 0.9, function() {
 alert('完成')
});

11.jQuery中toggle与slideToggle以及fadeToggle的比较

操作元素的显示和隐藏可以有几种方法。 例如:

  • 改变样式display为none
  • 设置位置高度为0
  • 设置透明度为0

都能达到这个目的,并且针对这样的处理jQuery都提供了各自的方法。show/hide、sildeDown/sildeUp、fadeIn/fadeOut。除此之外,还引入了toggle、sildeToggle以及fadeToggle切换方法

toggle、sildeToggle以及fadeToggle的区别:

  • toggle:切换显示与隐藏效果
  • sildeToggle:切换上下拉卷滚效果
  • fadeToggle:切换淡入淡出效果

当然细节上还是有更多的不同点:

toggle与slideToggle细节区别:

  • toggle:动态效果为从右至左。横向动作,toggle通过display来判断切换所有匹配元素的可见性
  • slideToggle:动态效果从下至上。竖向动作,slideToggle 通过高度变化来切换所有匹配元素的可见性

fadeToggle方法

  • fadeToggle() 方法在 fadeIn() 和 fadeOut() 方法之间切换。
  • 元素是淡出显示的,fadeToggle() 会使用淡入效果显示它们。
  • 元素是淡入显示的,fadeToggle() 会使用淡出效果显示它们。
  • 注释:隐藏的元素不会被完全显示(不再影响页面的布局)

12.jQuery中动画animate(上)

有些复杂的动画通过之前学到的几个动画函数是不能够实现,这时候就需要强大的animate方法了

操作一个元素执行3秒的淡入动画,对比一下2组动画设置的区别

语法:

.animate( properties ,[ duration ], [ easing ], [ complete ] )
.animate( properties, options )

.animate()方法允许我们在任意的数值的CSS属性上创建动画。2种语法使用,几乎差不多了,唯一必要的属性就是一组CSS属性键值对。这组属性和用于设置.css()方法的属性键值对类似,除了属性范围做了更多限制。第二个参数开始可以单独传递多个实参也可以合并成一个对象传递了

参数分解:properties:一个或多个css属性的键值对所构成的Object对象。要特别注意所有用于动画的属性必须是数字的,除非另有说明;这些属性如果不是数字的将不能使用基本的jQuery功能。比如常见的,border、margin、padding、width、height、font、left、top、right、bottom、wordSpacing等等这些都是能产生动画效果的。background-color很明显不可以,因为参数是red或者GBG这样的值,非常用插件,否则正常情况下是不能只用动画效果的。注意,CSS 样式使用 DOM 名称(比如 "fontSize")来设置,而非 CSS 名称(比如 "font-size")。

特别注意单位,属性值的单位像素(px),除非另有说明。单位em 和 %需要指定使用

.animate({
    left: 50,
    width: '50px' 
    opacity: 'show', 
    fontSize: "10em",
}, 500);

除了定义数值,每个属性能使用'show', 'hide', 和 'toggle'。这些快捷方式允许定制隐藏和显示动画用来控制元素的显示或隐藏

.animate({
    width: "toggle"
});

如果提供一个以+= 或 -=开始的值,那么目标值就是以这个属性的当前值加上或者减去给定的数字来计算的

.animate({
    left: '+=50px'
}, "slow");

duration时间

动画执行的时间,持续时间是以毫秒为单位的;值越大表示动画执行的越慢,不是越快。还可以提供'fast' 和 'slow'字符串,分别表示持续时间为200 和 600毫秒。

easing动画运动的算法

jQuery库中默认调用 swing。如果需要其他的动画算法,请查找相关的插件

complete回调

动画完成时执行的函数,这个可以保证当前动画确定完成后发会触发

 if (v == "1") {
            // 数值的单位默认是px
            $aaron.animate({
                width  :300,
                height :300
            });
        } else if (v == "2") {
            // 在现有高度的基础上增加100px
            $aaron.animate({
                 width  : "+=100px",
                 height : "+=100px"
            });
        } else if (v == "3") {
            $aaron.animate({
                fontSize: "5em"
            }, 2000, function() {
                alert("动画 fontSize执行完毕!");
            });
        } else if (v == "4") {
            //通过toggle参数切换高度
            $aaron.animate({
                width: "toggle"
            });
        }

13.jQuery中动画animate(下)

animate在执行动画中,如果需要观察动画的一些执行情况,或者在动画进行中的某一时刻进行一些其他处理,我们可以通过animate提供的第二种设置语法,传递一个对象参数,可以拿到动画执行状态一些通知

.animate( properties, options )

options参数

  • duration - 设置动画执行的时间
  • easing - 规定要使用的 easing 函数,过渡使用哪种缓动函数
  • step:规定每个动画的每一步完成之后要执行的函数
  • progress:每一次动画调用的时候会执行这个回调,就是一个进度的概念
  • complete:动画完成回调

其中最关键的一点就是:

如果多个元素执行动画,回调将在每个匹配的元素上执行一次,不是作为整个动画执行一次

列出常用的方式:

$('#elem').animate({
    width: 'toggle', 
    height: 'toggle'
  }, {
    duration: 5000,
    specialEasing: {
      width: 'linear',
      height: 'easeOutBounce'
    },
    complete: function() {
      $(this).after('<div>Animation complete.</div>');
    }
  });

14.jQuery中停止动画stop

动画在执行过程中是允许被暂停的,当一个元素调用.stop()方法,当前正在运行的动画(如果有的话)立即停止

语法:

.stop( [clearQueue ], [ jumpToEnd ] )
.stop( [queue ], [ clearQueue ] ,[ jumpToEnd ] )

stop还有几个可选的参数,简单来说可以这3种情况

  • .stop(); 停止当前动画,点击在暂停处继续开始
  • .stop(true); 如果同一元素调用多个动画方法,尚未被执行的动画被放置在元素的效果队列中。这些动画不会开始,直到第一个完成。当调用.stop()的时候,队列中的下一个动画立即开始。如果clearQueue参数提供true值,那么在队列中的动画其余被删除并永远不会运行
  • .stop(true,true); 当前动画将停止,但该元素上的 CSS 属性会被立刻修改成动画的目标值

简单的说:参考下面代码、

$("#aaron").animate({
    height: 300
}, 5000)
$("#aaron").animate({
    width: 300
}, 5000)
$("#aaron").animate({
    opacity: 0.6
}, 2000)
  • stop():只会停止第一个动画,第二个第三个继续
  • stop(true):停止第一个、第二个和第三个动画
  • stop(true ture):停止动画,直接跳到第一个动画的最终状态

15.jQuery中each方法的应用

jQuery中有个很重要的核心方法each,大部分jQuery方法在内部都会调用each,其主要的原因的就是jQuery的实例是一个元素合集

如下:找到所有的div,并且都设置样式,css只是一个方法,所以内部会调用each处理这个div的合集,给每个div都设置style属性

$('div').css(...)

jQuery的大部分方法都是针元素合集的操作,所以jQuery会提供$(selector).each()来遍历jQuery对象

.each只是处理jQuery对象的方法,jQuery还提供了一个通用的jQuery.each方法,用来处理对象和数组的遍历

语法

jQuery.each(array, callback )
jQuery.each( object, callback )

第一个参数传递的就是一个对象或者数组,第二个是回调函数

$.each(["Aaron", "慕课网"], function(index, value) {
  //index是索引,也就是数组的索引
  //value就是数组中的值了
});

each就是for循环方法的一个包装,内部就是通过for遍历数组与对象,通过回调函数返回内部迭代的一些参数,第一个参数是当前迭代成员在对象或数组中的索引值(从0开始计数),第二个参数是当前迭代成员(与this的引用相同

jQuery.each()函数还会根据每次调用函数callback的返回值来决定后续动作。如果返回值为false,则停止循环(相当于普通循环中的break);如果返回其他任何值,均表示继续执行下一个循环。

$.each(["Aaron", "慕课网"], function(index, value) {
    return false; //停止迭代
});

jQuery方法可以很方便的遍历一个数据,不需要考虑这个数据是对象还是数组

 // 遍历数组元素
            $.each(['Aaron', '慕课网'], function(i, item) {
                $aaron.append("索引=" + i + "; 元素=" + item);
            });

  $.each({
                name: "张三",
                age: 18
   }, function(property, value) {
                $aaron.append("属性名=" + property + "; 属性值=" + value);
   });

16.jQuery中查找数组中的索引inArray

在PHP有in_array()判断某个元素是否存在数组中,JavaScript却没有,但是jQuery封装了inArray()函数判断元素是否存在数组中。注意了:在ECMAScript5已经有数据的indexOf方法支持了,但是jQuery保持了版本向下兼容,所以封装了一个inArray方法

jQuery.inArray()函数用于在数组中搜索指定的值,并返回其索引值。如果数组中不存在该值,则返回 -1。

语法:

jQuery.inArray( value, array ,[ fromIndex ] )

用法非常简单,传递一个检测的目标值,然后传递原始的数组,可以通过fromIndex规定查找的起始值,默认数组是0开始

例如:在数组中查找值是5的索引

$.inArray(5,[1,2,3,4,5,6,7]) //返回对应的索引:4

注意:

如果要判断数组中是否存在指定值,你需要通过该函数的返回值不等于(或大于)-1来进行判断

 if (v == "1") {

            var index = $.inArray('Aaron',['test','Aaron', 'array','慕课网']);
     
            $aaron.text('Aaron的索引是: '+ index)
     
        } else if (v == "2") {
     
            //指定索引开始的位置
            var index = $.inArray('a',['a','b','c','d','a','c'],2);
     
            $aaron.text('a的索引是: '+ index)
        }

17.jQuery中去空格神器trim方法

页面中,通过input可以获取用户的输入值,例如常见的登录信息的提交处理。用户的输入不一定是标准的,输入一段密码:' 1123456 ",注意了: 密码的前后会留空,这可能是用户的无心的行为,但是密码确实又没错,针对这样的行为,开发者应该要判断输入值的前后是否有空白符、换行符、制表符这样明显的无意义的输入值。

jQuery.trim()函数用于去除字符串两端的空白字符

这个函数很简单,没有多余的参数用法

需要注意:

  • 移除字符串开始和结尾处的所有换行符,空格(包括连续的空格)和制表符(tab)
  • 如果这些空白字符在字符串中间时,它们将被保留,不会被移除

alert("值的长度:" + .trim(.trim(("#results2").val()).length)

18.jQuery中DOM元素的获取get方法

jQuery是一个合集对象,如果需要单独操作合集中的的某一个元素,可以通过.get()方法获取到

以下有3个a元素结构:

<a>1</a>
<a>2</a>
<a>3</a>

通过jQuery获取所有的a元素合集$("a"),如果想进一步在合集中找到第二2个dom元素单独处理,可以通过get方法

语法:

.get( [index ] )

注意2点

  • get方法是获取的dom对象,也就是通过document.getElementById获取的对象
  • get方法是从0开始索引

所以第二个a元素的查找: $(a).get(1)

负索引值参数

get方法还可以从后往前索引,传递一个负索引值,注意的负值的索引起始值是-1

同样是找到第二元素,可以传递 $(a).get(-2)

$aaron.get(1).style.color = "blue"
 $aaron.get(-1).style.color = "#8A2BE2"

19.jQuery中DOM元素的获取index方法

get方法是通过已知的索引在合集中找到对应的元素。如果反过来,已知元素如何在合集中找到对应的索引呢?

.index()方法,从匹配的元素中搜索给定元素的索引值,从0开始计数。

语法:参数接受一个jQuery或者dom对象作为查找的条件

.index() .index( selector ) .index( element )

  • 如果不传递任何参数给 .index() 方法,则返回值就是jQuery对象中第一个元素相对于它同辈元素的位置
  • 如果在一组元素上调用 .index() ,并且参数是一个DOM元素或jQuery对象, .index() 返回值就是传入的元素相对于原先集合的位置
  • 如果参数是一个选择器, .index() 返回值就是原先元素相对于选择器匹配元素的位置。如果找不到匹配的元素,则 .index() 返回 -1

简单来说:

<ul>
    <a></a>
    <li id="test1">1</li>
    <li id="test2">2</li>
    <li id="test3">3</li>
</ul>

$("li").index() 没有传递参数,反正的结果是1,它的意思是返回同辈的排列循序,第一个li之前有a元素,同辈元素是a开始为0,所以li的开始索引是1

如果要快速找到第二个li在列表中的索引,可以通过如下2种方式处理

$("li").index(document.getElementById("test2")) //结果:1
$("li").index($("#test2"))  //结果:1

571 jquery 动画 实例

图片切换 src

$(".TopImg").animate(
  {opacity:'toggle'},
  "slow",
  null,
  function(){
    $(".TopImg").attr("src","../images/2.jpg");
    $(".TopImg").animate({opacity:'toggle'},"slow");
  }
);

22.600 jQuery获取元素的宽度或高度的有几种情况:

1.使用width(),它只能获取当前元素的内容的宽度;

2.使用innerWidth(),它只能获取当前元素的内容的宽度+padding;

3.使用outerWidth(),它只能获取当前元素的内容的宽度+padding+border;

4,使用outerWidth(true),它只能获取当前元素的内容的宽度+padding+border+margin;

22.610 WdatePicker 日期插件

image-20210528092341738
image-20210528092341738
<div id="date" style="width:186px;height:176px;"></div>
<scripe>
WdatePicker({
    eCont:'date',
    startDate:'${device.rtime}',
    onpicked:function(dp){
        $("#rtime").val(dp.cal.getDateStr());
        window.location.replace("${ctx}/trans/trans/transPictureOnlyNew?equipid=${equipid}&rtime="+dp.cal.getDateStr());
    }
})
 </scripe>

22.620回车

 <input id="search-from-input" class="search-input" type="text" onkeydown="keyDownMenuSeach(event);" placeholder="请输入关键字..." autocomplete="off" >
                    <div id="search-from-button" class="search-input-button div_button" onclick="menuSeach();">查询</div>
 // $('#search-from-input').bind('keypress', function (event) {
        //     if (event.keyCode == "13") {
        //         $("#search-from-button").click();
        //     }
        // })
        //回车触发搜素,搜素
        function keyDownSeach(e) {
            // 兼容FF和IE和Opera
            var theEvent = e || window.e;
            var code = theEvent.keyCode || theEvent.which || theEvent.charCode;
            if (code == 13) {
                $("#search-from-button").click();
            }
        }

22.630 js 格式化时间

new Date(item.warnTime).format("yyyy-MM-dd hh:mm:ss")

44 ajax

参考网址https://blog.csdn.net/dreamstar613/article/details/61913970open in new window

说明:ajax 有时提交中文 到后台报错,是因为 Content-Type 和参数类型 没定义好 (目前app端遇到过)

​ contentType: "application/json;charset=utf-8", 提交json ,则参数使用JSON.stringify(pjDataArr) 抓我json ,同时 后端用 @RequestBody 来,注入参数

​ Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8', 表单提交

4.1 dataType返回类型

注:dataType:"json" 用这个类型需要,保证后台返回的数据是json 格式,或者返回数字 1、0 等,这个就是我们常用的形式,如果需要接收的是字符串那么类型需要改为dataType:"text"

4.2 ajax 发送list后台保存 案例

  • 前台ajax
function save(){
	var pjDataArr=new Array();
	var scoreFlag=true;
	$("#relativeBox1 .pjDiv").each(function(index,element){// (关键字:遍历元素,元素遍历)
				//$(this).children('input:eq(1)').css("background-color","rgba(30, 220, 206, 0.4)");
				var addData = {
						applyinfoid:$(this).children('input:eq(0)').val(),
						driverId:$(this).children('input:eq(1)').val(),
						carid:$(this).children('input:eq(2)').val(),
						score:$(this).children('input:eq(3)').val(),
						evaLabel:$(this).children('input:eq(4)').val(),
						evaLabelStr:$(this).children('input:eq(5)').val()
				}
				if(addData.score==null || addData.score==''){
					scoreFlag=false;
				}
				pjDataArr.push(addData);
			});
				console.log(pjDataArr);
			if(scoreFlag){
				loading('正在提交,请稍等...');
				$.ajax({
				    type: "POST",
				    url: "${ctx}/zhcg/zhcgApplyinfo/savePjData",
				    dataType: "json",
				    contentType:"application/json",
				    async:false,
				    data: JSON.stringify(pjDataArr),//JSON.stringify(obj2),
				    success: function(data) {
				    closeTip();
				    	alertx(data.flag);
				    	if(data.status==0){
				    		parent.window.location.reload();
				    	}
				    },
				    error: function() {
				    }
				});
			}else{
				alertx("请对驾驶员进行评价,再提交!")
			}
		}
  • 后端

前端使用 JSON.stringify(pjDataArr) 返回 json 字符串到后端 ,后端使用 @RequestBody 来注入参数

/**
	前端返回的是 json 字符串 (JSON.stringify(pjDataArr) )
	后端使用 @RequestBody  来注入参数
*/
@ResponseBody
@RequestMapping(value = "savePjData")
public ResVO<String>  savePjData(@RequestBody List<ZhcgApplyAvaluate> pjDataArr) {
    ResVO<String> res=new ResVO<String>();
    try {
        zhcgApplyinfoService.savePjData(pjDataArr);
    } catch (Exception e) {
        res.setFlag("评价失败!");
        res.setStatus("1");
        e.printStackTrace();
        return res;
    }
    res.setFlag("评价成功!");
    res.setStatus("0");
    return res;
}

4.3 保存对象点对象到后台去

var paramss={
			id:$scope.emp.id,
			userId:$rootScope.user.id,
			'sysEmpBase.jcTimeStr':item.sysEmpBase.jcTime,
			'sysEmpBase.postEvalTimeStr':item.sysEmpBase.postEvalTime
		};
$.ajax({
			type:"post",//post 请求用data
			url: $rootScope.serverUrl+'/sys/empsInfoSave',
			data:paramss,//如果不用原始的ajax ,传递这种对象里面塞对象,这个结构的数据,需要先序列化对象 $.param(paramss)
			success: function(data) {
				var res=data;
   				 if(res.status=='0'){
   					$ionicLoading.hide();
   			    	$cordovaToast.showShortBottom(data.flag);
   			    	$rootScope.back();
   				 }
			},error: function(data){
				$ionicLoading.hide();
			}
		});
//app 后台 不能用   @ResponseBody
@RequestMapping(value = "savePjData", method = RequestMethod.POST)
public ResponseEntity<ResVO<String>> savePjData(SysEmp emp,HttpServletRequest request,HttpServletResponse response)throws UnsupportedEncodingException {
		ResVO<String> res=new ResVO<String>();
		try{
			sysEmpService.savePjData(emp);
		} catch (Exception e) {
			res.setStatus("-1");
			res.setFlag("系统异常,请联系管理员");
			e.printStackTrace();
		}
		return new ResponseEntity<ResVO<String>>(res, HttpStatus.OK);
	}

4.4 $.param()的含义:序列化对象,返回字符串

var params = {a:300,b:300};
var str = $.param(params);
console.log(str);
	输出结果为:a=1900&b=1900

从前端 传递的参数中取指定 属性的 数据

//后台参数获取 
request.getParameter("XXXX");

4.5 前端传递 对象,包含 数组集合的处理 案例

  • 方法1:前端使用 JSON.stringify(paramss) ,后端使用 @RequestBody 来注入参数 [案例](#4.5.1 方法1)
  • 方法2:考虑需要使用 @ModelAttribute,来获取前台没有获取到的实体对象的其他数据。那么 前台不能使用JSON.stringify(xxx) ,将数据转为json字符串 [案例](#4.5.2 方法2)
  • 方法3:前端处理和方法2一样,后端对数组的处理使用 JSON.parseArray [案例](#4.5.3 方法3)

4.5.1 方法1

前端使用 JSON.stringify(paramss) ,后端使用 @RequestBody 来注入参数 。但是不是最优处理方法,因为无法搭配 @ModelAttribute 使用 get 方法,

var paramss={ 
			id:$scope.item.id,
			userId:$rootScope.user.id,//通过 封装的 $rootScope.http  ajax 方法传递到后台
			engineerId:item.engineerId,
			noticeNumber:item.noticeNumber,
			//projJlNoticeDetailListStr:JSON.stringify(projJlNoticeDetailList)
			projJlNoticeDetailList:projJlNoticeDetailList
		};
$.ajax({
			url: $rootScope.serverUrl+'/noticeInfo/applySave',
			data:JSON.stringify(paramss),
			 contentType:"application/json",//传递参数json字符串,对于后台接收参数
			type:"post",
			dataType:"json",
			async:false,
		 	success: function (data){
		 		var res = data;
				 $ionicLoading.hide();
				if(res.status=='0'){//保存成功
					$cordovaToast.showShortCenter('保存成功!');
					$rootScope.back();
				}else{
					$ionicPopup.alert({//暂不识别
						title: '保存失败,请重新提交!',
						okText:'确定' 
					});
				}
		 	},
		 	error: function (){
		 		 $ionicLoading.hide();
				$cordovaToast.showShortBottom("数据异常,请重试!");
		 	}
		});

4.5.2 方法2

考虑需要使用 @ModelAttribute,来获取前台没有获取到的实体对象的其他数据,,那么 前台不能使用JSON.stringify(xxx) ,将数据转为json字符串

  • 前端
var paramss={ 
			id:$scope.item.id,
			userId:$rootScope.user.id,//通过 封装的 $rootScope.http  ajax 方法传递到后台
			engineerId:item.engineerId,
			noticeNumber:item.noticeNumber,
			reason:item.reason,
			projJlNoticeDetailListStr:JSON.stringify(projJlNoticeDetailList)
		};
$.ajax({
			url: $rootScope.serverUrl+'/noticeInfo/applySave',
			data:paramss,
			contentType:"application/x-www-form-urlencoded",//这个要加,不然报错,发送数据流的类型,
			type:"post",
			dataType:"json",
			async:false,
		 	success: function (data){
		 		var res = data;
				 $ionicLoading.hide();
				if(res.status=='0'){//保存成功
					$cordovaToast.showShortCenter('保存成功!');
					$rootScope.back();
				}else{
					$ionicPopup.alert({//暂不识别
						title: '保存失败,请重新提交!',
						okText:'确定' 
					});
				}
		 	},
		 	error: function (){
		 		 $ionicLoading.hide();
				$cordovaToast.showShortBottom("数据异常,请重试!");
		 	}
		});
  • 后端
@RequestMapping(value = "applySave", method = RequestMethod.POST)
	public ResponseEntity<ResVO<String>> applySave(ProjJlNotice projJlNotice,HttpServletRequest request,HttpServletResponse response, Model model)throws UnsupportedEncodingException {
		ResVO<String> res=new ResVO<String>();
		try{//前端 无法直接传递 数组到 后端,故将 数组 转为json 然后由后台转换 为数组
			String json = request.getParameter("projJlNoticeDetailListStr");//如果不这样获取会出现 转义的情况
			List<ProjJlNoticeDetail> list=Lists.newArrayList();
			if(json!=null && !"".equals(json)){
				JSONArray jArray= JSONArray.fromObject(json);
				Collection collection = JSONArray.toCollection(jArray, ProjJlNoticeDetail.class);//引入net.sf.json包所需要的jar包支持
				Iterator it = collection.iterator();
				while (it.hasNext()) {
					ProjJlNoticeDetail bean= (ProjJlNoticeDetail) it.next();  
					list.add(bean);
				}
			}
			System.out.println(list);
			projJlNotice.setProjJlNoticeDetailList(list);
			projJlNoticeService.activitySave(projJlNotice);
			res.setStatus("0");
			res.setFlag("保存成功");
		} catch (Exception e) {
			e.printStackTrace();
			res.setStatus("-1");
			res.setFlag(e.getMessage());
		}
		return new ResponseEntity<ResVO<String>>(res, HttpStatus.OK);
	}

4.5.3 方法3 (最优)

  • 前端
var paramss={
					id:$scope.item.id,
					userId:$rootScope.user.id,
					comment:$scope.comment,
					materialGhRecordDetailListStr:JSON.stringify($scope.infoList),
					infoFlowImagePath:$scope.item.infoFlowImagePath,
					infoFlowRemark:$scope.item.infoFlowRemark,
					taskId:$scope.item.taskId
			};		
		$ionicLoading.show();
		$.ajax({
			url: $rootScope.serverUrl+'/materialGh/ghApplySave',
			data:paramss,
			type:"post",
			contentType:"application/x-www-form-urlencoded",
			dataType:"json",
			async:false,
		 	success: function (data){
		 		$ionicLoading.hide();
				var res = data;
				if(res.status=='0'){//保存成功
					$rootScope.layer.msg('保存成功!');
					locals.remove("flowData");
					$rootScope.back();
				}else{
					$ionicPopup.alert({//暂不识别
						title: '保存失败,请重新提交!',
						okText:'确定' });
				}
		 	},
		 	error: function (){
		 	}
		});

  • 后端
@ModelAttribute
	public MaterialHbRecord get(@RequestParam(required=false) String id) {
		MaterialHbRecord entity = null;
		if (StringUtils.isNotBlank(id)){
			entity = materialHbRecordService.get(id);
		}
		if (entity == null){
			entity = new MaterialHbRecord();
		}
		return entity;
	}
//领用物资审批保存(待审批)
	@RequestMapping(value = "ghApplySave", method = RequestMethod.POST)
	public ResponseEntity<ResVO<String>> ghApplySave(MaterialGhRecord materialGhRecord,String materialGhRecordDetailListStr,
HttpServletRequest request,HttpServletResponse response) {
		ResVO<String> res = new ResVO<String>();
		try {
			String materialGhRecordDetailList=request.getParameter("materialGhRecordDetailListStr");
			List<MaterialGhRecordDetail> dataList= JSON.parseArray(materialGhRecordDetailList,MaterialGhRecordDetail.class);
//引包 import com.alibaba.fastjson.JSON;
			materialGhRecord.setMaterialGhRecordDetailList(dataList);
			//拼接字符串
			materialGhRecordService.saveData(materialGhRecord);//pc能和app端公用保存方法
			res.setStatus("0");
		} catch (Exception e) {
			e.printStackTrace();
			res.setStatus("-1");
			res.setFlag( e.getMessage());
		}
		return new ResponseEntity<ResVO<String>>(res, HttpStatus.OK);
	}

44. 6 流的形式读取参数

var data={
        		objId:objId,
        		userid:$rootScope.user.id,
        		taskId:taskId        		
        };    
	    $.ajax({
			type: "POST",
			url:$rootScope.serverUrl+"/flowSign/signSave",
			contentType:"application/json;charset=utf-8",
			data:JSON.stringify(data), 
			dataType:'json',
			async: false,
			success: function(data) {
				
			}
		}); 
@RequestMapping(value = "signSave", method = RequestMethod.POST)
public ResponseEntity<ResVO<String>> signSave(HttpServletRequest request,HttpServletResponse response){
    ResVO<String> res = new ResVO<String>();
    StringBuilder sb = new StringBuilder();
String sbString="";
request.setCharacterEncoding("UTF-8");
   try(BufferedReader reader = request.getReader()) {
      char[] buff = new char[1024];
      int len;
      while((len = reader.read(buff)) != -1) {
         sb.append(buff,0, len);
    }
    sbString=sb.toString();
JSONObject jobject = JSONObject.fromObject(sbString);
     
  //电子签名图片保存的路径
  String userid = jobject.getString("userid");

  String objId = jobject.getString("objId");
  return new ResponseEntity<ResVO<String>>(res, HttpStatus.OK);
}

44.9 ajax 设置全局 header

对于 app 无法使用 UserUtils.getUser() 方法的解决 ,思路:在公共js中 对ajax 设置全局 header

$.ajaxSettings.beforeSend = function(xhr,request){//beforeSend方法用于在向服务器发送请求前添加一些处理函数
			let user =  locals.getObject("user");    // 获取用户信息
		    xhr.setRequestHeader('userId',user.id);//ajax中的setRequestHeader设置请求头
		}
/**
	 * 获取当前用户
	 * 
	 * @return 取不到返回 new User()
	 */
	public static User getUser() {
		if (RequestContextHolder.getRequestAttributes() != null) {
			HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
			String userId = request.getHeader("userId");// APP 访问,,通过ajax 的消息头找到 userId 去查询用户
			if(StringUtils.isEmpty(userId)){
				userId = request.getHeader("userid");
			}
			if (!StringUtils.isEmpty(userId)) {
				User user = get(userId);
				if (user != null) {
					return user;
				}
			} else {
				Principal principal = getPrincipal();
				if (principal != null) {
					User user = get(principal.getId());
					if (user != null) {
						return user;
					}
					user = new User();
					user.setCompany(getOfficeById(ROOT_OFFICE_ID));
					return user;
				}
			}
		}
		User user = new User();
		user.setCompany(getOfficeById(ROOT_OFFICE_ID));
		// 如果没有登录,则返回实例化空的User对象。
		return user;
	}

4.10 postman使用

1. 使用postman做压力测试

2.


60 JSON

60.1 解析

JSONObject jsonObject = JSONObject.fromObject(result);//将字符串转为JSON 对象
JSONObject rootjson = jsonObject.getJSONObject("ROOT");//

JSONArray infoDataJson = JsonTransformKeyUtil.transToArray(infoJson.getJSONArray("DATA"));// 实体对象 在 CPMS系统中
List<RiskDataVo> riskDataVoList = JSON.parseArray(riskDataJson.toString(),RiskDataVo.class);
List<RiskDataVo> riskDataVoList = JsonUtil.jsonToList(infoDataJson.toString(),new TypeReference<List<RiskDataVo>>(){});
<dependency>
  <groupId>com.alibaba</groupId>
  <artifactId>fastjson</artifactId>
  <version>1.2.9</version>
</dependency>

60.100 解析

var jsonObj={"name":"张三","age":"24","profession":"工程师"};       
console.log(jsonObj.name);
console.log(jsonObj[name]);// 这个写法,可以支持 key值自定义传参的形式          

63开发技巧

63.1. Fiddler

可以进行弱网测试,同时也可以进行抓包,需要设置代理网络,转到网络设置 高级 勾选手动代理,然后设置 主机和代理端口

1)限定网络img

2)抓包:手机发送请求,需要抓包,则手机要和电脑通个网段,然后 选择网络设置,手动代理,设置主机名和端口号(端口号是Fiddler配置的)

img
img

63.2. Fiddler抓取在夜神模拟器安装的软件的包

夜神模拟器wifi代理设置 https://blog.csdn.net/weixin_42670402/article/details/82997947open in new window

打开设置---长按已经连接的wifi记录--修改网络

img
img

主机名设置为当前电脑的ip,断开设置为Fiddler 设置的端口

image-20201121142026648
image-20201121142026648

63.3.eclips无法打开模拟器

打开eclipse的DDMS,点击reset adb,其实相当于重置adb,具体步骤如下:点击windows--show view--other--devices

img
img

63.4.手机调试:

谷歌:chrome://inspect/#devices

edge: edge://inspect/#devices

image-20200914144005221
image-20200914144005221

64工作流

工作流驳回,获取上一个节点的操作人

/**
**  获取上个节点的 操作人 
**   @param objId :业务表id
**   @param procInsId:流程id
**   @param  taskDefKey:流程标识(上个流程节点的流程标识)
**   @param defaultUserId:如果没有找到 指定的人,返回该字段,防止返回空数据*
**   @return
**/
public String getActMesByTaskDefKey(String objId,String procInsId,String taskDefKey,String defaultUserId){
//   List<Map<String, Object>> list = histoicFlowList(objId,procInsId);
//   Map<String, Object> map = Maps.newHashMap();
//   for (Map<String, Object> histoicFlow:list ) {
//    if(histoicFlow.get("taskDefKey").equals(taskDefKey)){
//      map.put(taskDefKey, histoicFlow);
//    }
//   }
   String userid=defaultUserId;
   List<HistoricActivityInstance> list = historyService
      .createHistoricActivityInstanceQuery()
      .processInstanceId(procInsId).activityId(taskDefKey)
      .orderByHistoricActivityInstanceStartTime().asc()
      .orderByHistoricActivityInstanceEndTime().asc().list();
   if(list!=null && list.size()>0 ){
     HistoricActivityInstance historicActivityInstance = list.get(list.size() - 1);
     if(historicActivityInstance!=null && !"".equals(historicActivityInstance)){
      return historicActivityInstance.getAssignee();
     }
   }
   return userid;
  }

待整理 获取连线名称

65 AngularJs

65.1 文本框 高度自适应

//创建一个指令:
.directive('autoHeight', function () {
  function autoHeight(elem) {
    elem.style.height = 'auto';
    elem.scrollTop = 0; //防抖动
    elem.style.height = elem.scrollHeight + 'px';
    elem.parentNode.style.height = elem.scrollHeight + 'px';
  }
  return {
    scope: {},
    link: function (scope, ele, attrs) {
      var oriEle = $(ele).get(0);
      $(oriEle).bind('keyup click', function (e) {
        $(oriEle).focus();
        autoHeight($(this).get(0));
      });
      var timer = setInterval(function () {
        if ($(oriEle).val()) {
          autoHeight(oriEle);
          clearInterval(timer);
        }
      }, 100);
    }
  };
});

AngularJs渲染完毕后执行指定操作 (针对ng-repeat定义的 )

<ul>
  <li ng-repeat="item in items" on-finish-render="callMethod()"> <!--可以直接用on-finish-render,不用callMethod方法   -->
      dummy Text
  </li>
</ul>
.directive('onFinishRender',['$timeout', '$parse', function ($timeout, $parse) {
    return {
        restrict: 'A',
        link: function (scope, element, attr) {
            if (scope.$last === true) {
                $timeout(function () {
                    scope.$emit('ngRepeatFinished'); //事件通知
                        var fun = $scope.$eval(attrs.onFinishRender);
                        if(fun && typeof(fun)=='function'){  
                            fun();  //回调函数
                        }  
                });
            }
        }
    }
}])
// 页面初始化加载事件
$scope.$on('ngRepeatFinished', function(ngRepeatFinishedEvent) {

 });

65.2 ng-repeat 限定循环次数

ng-repeat="item in items|limitTo:5"  

65.3 date时间转换

{{x.outtime | date:'yyyy-MM-dd hh:mm:ss'}}

AngularJs的controller中格式: (注意: controller需要注入$filter)

 var dateAsString = $filter('date')(item_date, "yyyy-MM-dd hh:mm:ss"); 

65.4 AngularJS实现HTML页面嵌套(嵌入页面)

场景: 有多个页面 需要 地图页面作为 底图,故 将地图改为 独立的页面,有自己的controller.js 和html 页面

image-20210111142942716
image-20210111142942716
  • main.html
 <!--main.html 主页面 -->
<body>
    <div class="ditu" ng-controller="mapLineDetailCtrl">
      <ng-include src="'modules/map/mapLineDetail.html'"></ng-include>
    </div>
    <div class="main">
        <!-- 主页面 -->
    </div>
</body>

说明:mapLineDetail.html 是 地图页面 mapLineDetailCtrl 是对于的 js 代码。

main.html 是主页面,和正常的的写法一样,在页面中引入 需要的 公共页面,同时 2个页面的参数可以互用,所以地图初始化需要的参数,在 跳转 main.html 是带入 ,即可保证实现

63.10 ng-repeat 遍历

说明: ng-repeat 遍历不能存在一样的数据,否则不能正常遍历

63.20 this,,$event


63.30 ionic 绑定手势

    // 页面初始化完成加载
    $timeout(function () {
    	$ionicGesture.on('dragstart',function(e){
            var ss = document.getElementById('tower_content')
            height0 = ss.offsetHeight;
        },angular.element(document.querySelector('#tower_content')))

        $ionicGesture.on('drag',function(e){
            let nowHeight = height0 - e.gesture.deltaY
            console.log('drag:'+nowHeight)
            if(nowHeight <= 600)
            $('#tower_content').css("height",nowHeight+"px");

        },angular.element(document.querySelector('#tower_content')))

        $ionicGesture.on('dragend',function(e){
            var ss = document.getElementById('tower_content')
            let height = ss.offsetHeight;
            console.log('dragend:'+height)
            if(height < 450){
                $('#tower_content').animate({height:'15em'})
            }
            if(height > 450){
                $('#tower_content').animate({height:'40em'})
            }
        },angular.element(document.querySelector('#tower_content')))
    }, 2000);

66 接口

百度接口 通过百度坐标获取当前位置详情

//通过坐标获取位置详情
http://api.map.baidu.com/geocoder/v2/?ak=rCTTTEXWsRNW3AlNvDbO2Bc5&location=31.940524127201048,117.27147584517168&output=json
//获取城市行政规划边界坐标点(用法查看 arcgis笔记中)
https://api.map.baidu.com/getscript  	

天气

http://apis.baidu.com/heweather/weather/free
https://lbs.amap.com/api/webservice/guide/api/weatherinfo/

http://restapi.amap.com/v3/weather/weatherInfo

70. node/npm

70.1 安装

1.下载open in new window 最好下载mis版本

安装教程:

2.安装成功,测试安装是否成功,运行CMD,分别输入node -vnpm -v 分别查看node和npm的版本号

3. 配置自定义的全局模块安装目录,在node.js安装目录下新建两个文件夹 node_global和node_cache,如图所示:

image-20210204092655887
image-20210204092655887

然后在cmd命令下执行如下两个命令:

npm config set prefix "D:\Program Files\nodejs\node_global"

npm config set cache "D:\Program Files\nodejs\node_cache"

4. 执行完后,配置环境变量,如下:

  • “环境变量” -> “系统变量”:新建一个变量名为 “NODE_PATH”, 值为**“D:\Program Files\nodejs**node_global\node_modules****”,如下图:

  • “环境变量” -> “用户变量”:编辑用户变量里的Path,将相应npm的路径(“C:\Users\用户名\AppData\Roaming\npm”)改为:“D:\Program Files\nodejs\node_global”,

5.测试

在cmd命令下执行 npm install webpack -g 安装webpack

70.2

# 使用淘宝 npm 地址
npm config set registry https://registry.npm.taobao.org

# 配置后可通过下面方式来验证是否成功
npm config get registry   或   npm info express

在GitHub官网,搜索gnvm,下载

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

放在node.js的安装目录下

在这里插入图片描述
在这里插入图片描述
# 然后打开cmd命令行窗口,输入:
gnvm update latest

使用安装gnvm 管理node 升级问题 https://blog.csdn.net/qq_41956139/article/details/105944608open in new window

一、新版本安装

以下操作需要管理员打开cmd

1.查看gnvm版本,验证是否安装成功

C:\WINDOWS\system32>gnvm version
Waring: config file C:\Program Files\nodejs\\.gnvmrc is not exist.
Notice: Config file C:\Program Files\nodejs\\.gnvmrc create success.
Current version 0.2.0 64 bit.
Copyright (C) 2014-2016 Kenshin Wang <kenshin@ksria.com>
See https://github.com/kenshin/gnvm for more information.
123456

2.配置gnvm

C:\WINDOWS\system32>gnvm config
Notice: config file path C:\Program Files\nodejs\\.gnvmrc
gnvm config registry is http://nodejs.org/dist/
gnvm config noderoot is C:\Program Files\nodejs\
gnvm config globalversion is 8.12.0
gnvm config latestversion is unknown
123456

3.查询node版本

C:\WINDOWS\system32>gnvm search 12.*.*
Search Node.js version rules [12.*.*] from http://nodejs.org/dist/index.json, please wait.
+--------------------------------------------------+
| No.   date         node ver    exec      npm ver |
+--------------------------------------------------+
  1     2020-04-28   12.16.3     x86 x64   6.14.4
  2     2020-04-08   12.16.2     x86 x64   6.14.4
  3     2020-02-14   12.16.1     x86 x64   6.13.4
  4     2020-02-11   12.16.0     x86 x64   6.13.4
  5     2020-02-05   12.15.0     x86 x64   6.13.4
  6     2020-01-07   12.14.1     x86 x64   6.13.4
  7     2019-12-16   12.14.0     x86 x64   6.13.4
  8     2019-11-19   12.13.1     x86 x64   6.12.1
  9     2019-10-21   12.13.0     x86 x64   6.12.0
  10    2019-10-11   12.12.0     x86 x64   6.11.3
  11    2019-10-01   12.11.1     x86 x64   6.11.3
  12    2019-09-25   12.11.0     x86 x64   6.11.3
  13    2019-09-04   12.10.0     x86 x64   6.10.3
  14    2019-08-26   12.9.1      x86 x64   6.10.2
  15    2019-08-20   12.9.0      x86 x64   6.10.2
  16    2019-08-15   12.8.1      x86 x64   6.10.2
  17    2019-08-06   12.8.0      x86 x64   6.10.2
  18    2019-07-23   12.7.0      x86 x64   6.10.0
  19    2019-07-03   12.6.0      x86 x64   6.9.0
  20    2019-06-26   12.5.0      x86 x64   6.9.0
  21    2019-06-04   12.4.0      x86 x64   6.9.0
  22    2019-05-22   12.3.1      x86 x64   6.9.0
  23    2019-05-21   12.3.0      x86 x64   6.9.0
  24    2019-05-07   12.2.0      x86 x64   6.9.0
  25    2019-04-29   12.1.0      x86 x64   6.9.0
  26    2019-04-23   12.0.0      x86 x64   6.9.0
+--------------------------------------------------+
1234567891011121314151617181920212223242526272829303132

4.安装指定版本node(本地安装)

C:\WINDOWS\system32>gnvm install 12.16.3
Start download Node.js versions [12.16.3].
12.16.3: 100% [==================================================>] 36s
--------
End download.
12345

5.查询本地所有的node版本

C:\WINDOWS\system32>gnvm ls
Notice: gnvm.exe root is C:\Program Files\nodejs\\
v12.16.3
123

当前使用的是哪一个版本,global就是哪个版本

6.下载

gnvm install 10.16.1

7. 使用本地已存在的某个node版本

gnvm use 10.16.1

8. 查询版本

gnvm node-version

80 linux 系统操作

linux 安装 telnet https://blog.csdn.net/doubleqinyan/article/details/80492421open in new window

https://blog.csdn.net/shun35/article/details/90701491open in new window

  • Xshell 控制台打印 时时日志
#在控制台打印 catalina.out 日志文件
tail -111f catalina.out

#实时的查看运行日志
tail -f xx.log
  • 修改文件
#查看
more nginx.conf	
#编辑
vi nginx.conf
#进入编辑
i

esc退出  :wq 确认  q! 取消
  • 移动文件,重命名
# 移动文件 mv 目标文件(可以用路径,也可以当前文件夹的文件)  目标目录
mv xx.txt /home/file
## 将 home/file1 下的xx.txt 文件,移动到 /home/file目录下
mv /home/file1/xx.txt /home/file

## 将文件test.txt重命名为wbk.txt:
$ mv test.txt wbk.txt
  • 查询java 服务
ps -ef|grep java
kill -9 xxx

sh 
./
  • 修改权限:chmod +x /usr/local/bin/wkhtmltopdf

  • 查询 centos 版本rpm -q centos-release


100 其他

100.1 PDM 备注列不显示

100.2 svn

.idea classes target *iml *.o *.lo *.la *.al .libs *.so *.so.[0-9]* *.a *.pyc *.pyo __pycache__ *.rej *~ #*# .#* .*.swp .DS_Store [Tt]humbs.db

MyEclipse 代码提交时,让svn忽略classpath、target、.project //https://blog.csdn.net/xiaojin21cen/article/details/83054820open in new window

Svn 设置文件忽略

100.3 idea 启动报错

Error running 'SdbdApplication':

Command line is too long. Shorten command line for SdbdApplication or also for Spring Boot default configuration.

image-20210429144413728
image-20210429144413728

链接

谷歌

超链接目标

超链接测试