FirstBlog
Tags: css, javascript, html
Published: 2022-08-03 14:18:00

### 

```java
/**
 * @author John Smith <john.smith@example.com>
*/
package l2f.gameserver.model;

public abstract strictfp class L2Char extends L2Object {
  public static final Short ERROR = 0x0001;

  public void moveTo(int x, int y, int z) {
    _ai = null;
    log("Should not be called");
    if (1 > 5) { // wtf!?
      return;
    }
  }
}
```

```javascript
let clipboard = new Clipboard(".copy-btn");

// 复制成功失败的提示
clipboard.on("success", (e) => {
  $(e.trigger).fadeOut(() => {
    $(e.trigger)
      .siblings(".success-svg")
      .fadeIn(() => {
        setTimeout(() => {
          $(e.trigger)
            .siblings(".success-svg")
            .fadeOut(() => {
              $(e.trigger).fadeIn();
            });
        }, 2000);
      });
  });
});
clipboard.on("error", () => {
  console.log(e);
});
```

### 刚开始的代码

```js
let clipboard = new Clipboard(".copy-btn");

// 复制成功失败的提示
clipboard.on("success", (e) => {
  $(e.trigger).fadeOut(() => {
    $(e.trigger)
      .siblings(".success-svg")
      .fadeIn(() => {
        setTimeout(() => {
          $(e.trigger)
            .siblings(".success-svg")
            .fadeOut(() => {
              $(e.trigger).fadeIn();
            });
        }, 2000);
      });
  });
});
clipboard.on("error", () => {
  console.log(e);
});
```
### 加入以下代码

> document.activeElement.blur();

```js
let clipboard = new Clipboard(".copy-btn");

// 复制成功失败的提示
clipboard.on("success", (e) => {
  document.activeElement.blur();
  $(e.trigger).fadeOut(() => {
    $(e.trigger)
      .siblings(".success-svg")
      .fadeIn(() => {
        setTimeout(() => {
          $(e.trigger)
            .siblings(".success-svg")
            .fadeOut(() => {
              $(e.trigger).fadeIn();
            });
        }, 2000);
      });
  });
});
clipboard.on("error", () => {
  console.log(e);
});
```

```js
const res = await fetch(jsonService)
match (res) {
  when ({ status: 200, headers: { 'Content-Length': s } }):
    console.log(`size is ${s}`);
  when ({ status: 404 }):
    console.log('JSON not found');
  when ({ status }) if (status >= 400): do {
    throw new RequestError(res);
  }
};
```

学习网站
- http://www.imooc.com/code/387
- http://www.imooc.com/wiki/Javascriptbase/whatsjs.html

## 一、基础知识

### 1. js 位置与执行顺序
> 放在head部分
最常用的方式是在页面中head部分放置script元素，浏览器解析head部分就会执行这个代码，然后才解析页面的其余部分。
放在body部分
JavaScript代码在网页读取到该语句的时候就会执行。

> 注意: javascript作为一种脚本语言可以放在html页面中任何位置，但是浏览器解释html时是按先后顺序的，所以前面的script就先被执行。比如进行页面显示初始化的js必须放在head里面，因为初始化都要求提前进行（如给页面body设置css等）；而如果是通过事件调用执行的function那么对位置没什么要求的。

### 2. 如何使用DOM进行简单操作。
```js
document.write("hello")
document.getElementById("p1").style.color="blue"
```

### 3. confirm 消息对话框

confirm(str);

str：在消息对话框中要显示的文本
返回值: Boolean值

当用户点击"确定"按钮时，返回true
当用户点击"取消"按钮时，返回false
```js
var mymessage = confirm("你喜欢JavaScript吗?");
if (mymessage == true) {
  document.write("很好,加油!");
} else {
  document.write("JS功能强大，要学习噢!");
}
```

### 4. prompt 消息对话框
prompt(str1, str2);

str1: 要显示在消息对话框中的文本，不可修改
str2：文本框中的内容，可以修改

1. 点击确定按钮，文本框中的内容将作为函数返回值
2. 点击取消按钮，将返回null

```js
var myname=prompt("请输入你的姓名:");
if(myname!=null)
  {   alert("你好"+myname); }
else
  {  alert("你好 my friend.");  }
```

### 5. 打开新窗口（window.open）
open() 方法可以查找一个已经存在或者新建的浏览器窗口。

window.open([URL], [窗口名称], [参数字符串])

URL：可选参数，在窗口中要显示网页的网址或路径。如果省略这个参数，或者它的值是空字符串，那么窗口就不显示任何文档。
窗口名称：可选参数，被打开窗口的名称。
    1. 该名称由字母、数字和下划线字符组成。
    2. "_top"、"_blank"、"_self"具有特殊意义的名称。
       _blank：在新窗口显示目标网页
       _self：在当前窗口显示目标网页
       _top：框架网页中在上部窗口中显示目标网页
    3. 相同 name 的窗口只能创建一个，要想创建多个窗口则 name 不能相同。
    4. name 不能包含有空格。
参数字符串：可选参数，设置窗口参数，各参数用逗号隔开。

![image.png](http://120.77.211.22:7521/pictures/20220531_8560_image.png)

```js
<script type="text/javascript"> 
    window.open('http://www.imooc.com','_blank','width=300,height=200,menubar=no,toolbar=no, status=no,scrollbars=yes')
</script>
```

### 6. 关闭窗口（window.close）

```js
window.close();   //关闭本窗口

<窗口对象>.close();   //关闭指定的窗口

<script type="text/javascript">
   var mywin=window.open('http://www.imooc.com'); //将新打的窗口对象，存储在变量mywin中
   mywin.close();
</script>
```

### 7. 窗口练习
```html
<!DOCTYPE html>
<html>
 <head>
  <title> new document </title>  
  <meta http-equiv="Content-Type" content="text/html; charset=gbk"/>   
  <script type="text/javascript">  
  
    function openWindow() {
        var ifOpen;
        ifOpen = confirm("是否打开")
        
        if (ifOpen == true) {
            
            var urlconfirm = prompt("确定打开的网址","http://www.imooc.com/")
            
            if (urlconfirm)
            {
                window.open(urlconfirm, "_blank", 'width=400, height=500, menubar=yes, toolbar=yes')
            }
            
        }
    }

  </script> 
 </head> 
 <body> 
	  <input type="button" value="新窗口打开网站" onclick="openWindow()" /> 
 </body>
</html>
```

### 8. 认识DOM
> 文档对象模型DOM（Document Object Model）定义访问和处理HTML文档的标准方法。DOM 将HTML文档呈现为带有元素、属性和文本的树结构（节点树）。

<img src="http://120.77.211.22:7521/pictures/20220531_1252_image.png" width=50%>

将HTML代码分解为DOM节点层次图:

<img src="http://120.77.211.22:7521/pictures/20220531_6333_image.png" width=50%>

HTML文档可以说由节点构成的集合，三种常见的DOM节点:

1. 元素节点：上图中《html》、《body》、《p》等都是元素节点，即标签。

2. 文本节点:向用户展示的内容，如《li》...《/li》中的JavaScript、DOM、CSS等文本。

3. 属性节点:元素属性，如《a》标签的链接属性href="http://www.imooc.com"。

```
<a href="http://www.imooc.com">JavaScript DOM</a>
```
<img src="http://120.77.211.22:7521/pictures/20220531_9878_image.png" width=50%>

### 9. 事件
<img src="http://120.77.211.22:7521/pictures/20220603_9261_image.png">


### 10. classList类名操作

```html
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
    <style>
        .bg {
            background-color: black;
        }
    </style>
</head>

<body>
    <div class="one two"></div>
    <button> 开关灯</button>
    <script>
        // classList 返回元素的类名
        var div = document.querySelector('div');
        // console.log(div.classList[1]);
        // 1. 添加类名  是在后面追加类名不会覆盖以前的类名 注意前面不需要加.
        div.classList.add('three');
        // 2. 删除类名
        div.classList.remove('one');
        // 3. 切换类
        var btn = document.querySelector('button');
        btn.addEventListener('click', function() {
            document.body.classList.toggle('bg');
        })
    </script>
</body>

</html>
```


- 什么是对象

JavaScript 中的所有事物都是对象，如:字符串、数值、数组、函数等，每个对象带有属性和方法。

对象的属性：反映该对象某些特定的性质的，如：字符串的长度、图像的长宽等；

对象的方法：能够在对象上执行的动作。例如，表单的“提交”(Submit)，时间的“获取”(getYear)等；

JavaScript 提供多个内建对象，比如 String、Date、Array 等等，使用对象前先定义，如下使用数组对象：

```js
  var objectName =new Array();//使用new关键字定义对象
或者
  var objectName =[];
```

### 11. Date对象
```js
var d = new Date(2012, 10, 1);  //2012年10月1日
var d = new Date('Oct 1, 2012'); //2012年10月1日
```

Date对象中处理时间和日期的常用方法：

![image.png](http://120.77.211.22:7521/pictures/20220603_3555_image.png)

get/setTime() 返回/设置时间，单位毫秒数，计算从 1970 年 1 月 1 日零时到日期对象所指的日期的毫秒数。

将目前日期对象的时间推迟1小时
```js
mydate.setTime(mydate.getTime() + 60 * 60 * 1000);
```
### 12. String 字符串对象
```js
toUpperCase();
toLowerCase()
```

charAt() 方法可返回指定位置的字符。返回的字符是长度为 1 的字符串。

```js
stringObject.charAt(index)
```
> 如果参数 index 不在 0 与 string.length-1 之间，该方法将返回一个空字符串。

**返回指定的字符串首次出现的位置**
indexOf() 方法可返回某个指定的字符串值在字符串中首次出现的位置。
```js
stringObject.indexOf(substring, startpos)
```
![image.png](http://120.77.211.22:7521/pictures/20220603_7855_image.png)

**说明：**
1. 该方法将从头到尾地检索字符串 stringObject，看它是否含有子串 substring。

2. 可选参数，从stringObject的startpos位置开始查找substring，如果没有此参数将从stringObject的开始位置查找。

3. 如果找到一个 substring，则返回 substring 的第一次出现的位置。stringObject 中的字符位置是从 0 开始的。

**注意：**
1. indexOf() 方法区分大小写。

2. 如果要检索的字符串值没有出现，则该方法返回 -1

```js
<script type="text/javascript">
  var str="I love JavaScript!"
  document.write(str.indexOf("I") + "<br />");
  document.write(str.indexOf("v") + "<br />");
  document.write(str.indexOf("v",8));
</script>
```

```js
0
4
9
```

**字符串分割split()**

> split() 方法将字符串分割为字符串数组，并返回此数组。

![image.png](http://120.77.211.22:7521/pictures/20220603_7708_image.png)

**注意：**如果把空字符串 ("") 用作 separator，那么 stringObject 中的每个字符之间都会被分割。

```js
var mystr = "www.imooc.com";
document.write(mystr.split("")+"<br>");
document.write(mystr.split("", 5));
```
运行结果
```js
w,w,w,.,i,m,o,o,c,.,c,o,m
w,w,w,.,i
```

**提取字符串substring()**

> stringObject.substring(startPos,stopPos) 
**注意：**如果 startPos 比 stopPos 大，那么该方法在提取子串之前会先交换这两个参数。

```js
<script type="text/javascript">
  var mystr="I love JavaScript";
  document.write(mystr.substring(7));
  document.write(mystr.substring(2,6));
</script>
```

```js
JavaScript
love
```

**提取指定数目的字符substr()**

substr() 方法从字符串中提取从 startPos位置开始的指定数目的字符串。
> stringObject.substr(startPos,length)

**注意：**
1. 如果参数startPos是负数，从字符串的尾部开始算起的位置。也就是说，-1 指字符串中最后一个字符，-2 指倒数第二个字符，以此类推。

2. 如果startPos为负数且绝对值大于字符串长度，startPos为0。

```js
<script type="text/javascript">
  var mystr="I love JavaScript!";
  document.write(mystr.substr(7));
  document.write(mystr.substr(2,4));
  document.write(mystr.substr(-2,4));
</script>
```

```js
JavaScript!
love
t!
```

### 13. Math对象
**注意：**
Math 对象是一个固有的对象，无需创建它，直接把 Math 作为对象使用就可以调用其所有属性和方法。这是它与Date,String对象的区别。

Math 对象属性

![image.png](http://120.77.211.22:7521/pictures/20220603_5556_image.png)

Math 对象方法

![image.png](http://120.77.211.22:7521/pictures/20220603_1494_image.png)

**向上取整ceil()**
**向下取整floor()**
**四舍五入round()**

> 注意：

1. 返回与 x 最接近的整数。

2. 对于 0.5，该方法将进行上舍入。(5.5 将舍入为 6)

3. 如果 x 与两侧整数同等接近，则结果接近 +∞方向的数字值 。(如 -5.5 将舍入为 -5; -5.52 将舍入为 -6)

### 14. Array 数组对象

![image.png](http://120.77.211.22:7521/pictures/20220603_6801_image.png)

**数组连接concat()**
**指定分隔符连接数组元素join(分隔符)**
**选定元素slice()**

**数组排序sort()**

```js
var myarr = new Array("80","16","50","6","100","1");
document.write(myarr.sort());
document.write(myarr.sort(sortNum));
```

运行结果

```js
1,100,16,50,6,80
1,6,16,50,80,100
```

**注意** 冒泡排序引起的排序失败
```js
var ayyar1 = [13, 4, 77, 1, 7]
array1.reverse();
console.log(array1);

array1.reverse(function(a, b){
	return a - b; // 升序
	return b - a; // 降序
})
```



#### 判断是否为数组的两种方法
```js
	var array1 = [1, 2, 3];
	console.log(array1 instanceof Array );
	console.log(Array.isArray(array1))
```

### 15. window对象
**计时器**

![image.png](http://120.77.211.22:7521/pictures/20220603_7271_image.png)

```js
<script type="text/javascript">
        var i = 0;
	var timer;
	timer = setInterval(() => {
	document.write(i);
	document.write("<br>");
	i++;
	if (i === 5) {
		clearInterval(timer);
	}
	}, 500);
</script>
```

### 16. Location对象 
location对象属性图示:

location 对象方法:
![image.png](http://120.77.211.22:7521/pictures/20220603_8986_image.png)

![image.png](http://120.77.211.22:7521/pictures/20220603_6415_image.png)

### 17. Navigator对象

Navigator 对象包含有关浏览器的信息，通常用于检测浏览器与操作系统的版本。

**对象属性:**

![image.png](http://120.77.211.22:7521/pictures/20220603_5205_image.png)

```js
<script type="text/javascript">
   var browser=navigator.appName;
   var b_version=navigator.appVersion;
   document.write("Browser name"+browser);
   document.write("<br>");
   document.write("Browser version"+b_version);
</script>
```

### 18. userAgent

返回用户代理头的字符串表示(就是包括浏览器版本信息等的字符串)
> navigator.userAgent

![image.png](http://120.77.211.22:7521/pictures/20220603_4971_image.png)

### 19. screen对象
> window.screen.属性

![image.png](http://120.77.211.22:7521/pictures/20220603_4341_image.png)


### 20. 窗口大小

#### 获得浏览器窗口的尺寸（浏览器的视口，不包括工具栏和滚动条）的方法:

```js
var w= document.documentElement.clientWidth
      || document.body.clientWidth;
var h= document.documentElement.clientHeight
      || document.body.clientHeight;
```

#### scrollHeight和scrollWidth，获取网页内容高度和宽度。

一、针对IE、Opera:

scrollHeight 是网页内容实际高度，可以小于 clientHeight。

二、针对NS、FF:

scrollHeight 是网页内容高度，不过最小值是 clientHeight。也就是说网页内容实际高度小于 clientHeight 时，scrollHeight 返回 clientHeight 。

```js
var w=document.documentElement.scrollWidth
   || document.body.scrollWidth;
var h=document.documentElement.scrollHeight
   || document.body.scrollHeight;
```

#### offsetHeight和offsetWidth，获取网页内容高度和宽度(包括滚动条等边线，会随窗口的显示大小改变)。

offsetHeight = clientHeight + 滚动条 + 边框

```js
var w= document.documentElement.offsetWidth
    || document.body.offsetWidth;
var h= document.documentElement.offsetHeight
    || document.body.offsetHeight;
```

#### 网页卷去的距离与偏移量

**scrollLeft:** 设置或获取位于给定对象左边界与窗口中目前可见内容的最左端之间的距离 ，即左边灰色的内容。

**scrollTop:** 设置或获取位于对象最顶端与窗口中可见内容的最顶端之间的距离 ，即上边灰色的内容。

**offsetLeft:** 获取指定对象相对于版面或由 offsetParent 属性指定的父坐标的计算左侧位置 。

**offsetTop:** 获取指定对象相对于版面或由 offsetParent 属性指定的父坐标的计算顶端位置 。

![image.png](http://120.77.211.22:7521/pictures/20220610_4863_image.png)



## 二、JavaScript 面试
### 1. js 0.1+0.2为什么不等于0.3
> 原因在于在JS中采用的IEEE 754的双精度标准，计算机内部存储数据的编码的时候，0.1在计算机内部根本就不是精确的0.1，而是一个有舍入误差的0.1。当代码被编译或解释后，0.1已经被四舍五入成一个与之很接近的计算机内部数字，以至于计算还没开始，一个很小的舍入错误就已经产生了。这也就是 0.1 + 0.2 不等于0.3 的原因。
### 2. let和const区别
> let与const都是只在声明所在的块级作用域内有效。let声明的变量可以改变，值和类型都可以改变，没有限制。const声明的变量不得改变值，这意味着，const一旦声明变量，就必须立即初始化，不能留到以后赋值。

### 2. mouseenter和mouseover的区别

- 鼠标元素移动到元素上时都会触发
- mouseover经过自身盒子会触发，经过子盒子还会触发，mouseenter只会经过自身盒子时触发，因为mouseenter不会冒泡
- 跟mouseenter搭配鼠标离开mouseleave，同样不会冒泡。

### 3. 基本类型保存在栈中，引用类型保存在堆中

### 4. js基本数据类型

> 在ES5的时候，我们认知的数据类型确实是 6种：Number、String、Boolean、undefined、object、Null、BigInt

> ES6 中新增了一种 Symbol 。这种类型的对象永不相等，即始创建的时候传入相同的值，可以解决属性名冲突的问题，做为标记。

### 5. CSS权重顺序
> !important > 行内样式 > ID选择器 > 属性选择器(class) > 元素选择器(标签) 

```js
const store = createStore({
  state: {
    count: 1
  },
  mutations: {
    increment (state) {
      // mutate state
      state.count++
    }
  }
})
```

```java
import com.baomidou.mybatisplus.core.exceptions.MybatisPlusException;
import com.baomidou.mybatisplus.core.toolkit.StringPool;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.generator.AutoGenerator;
import com.baomidou.mybatisplus.generator.InjectionConfig;
import com.baomidou.mybatisplus.generator.config.*;
import com.baomidou.mybatisplus.generator.config.po.TableInfo;
import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy;
import com.baomidou.mybatisplus.generator.engine.FreemarkerTemplateEngine;

import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;

// 演示例子，执行 main 方法控制台输入模块表名回车自动生成对应项目目录中
public class CodeGenerator {

    /**
     * <p>
     * 读取控制台内容
     * </p>
     */
    public static String scanner(String tip) {
        Scanner scanner = new Scanner(System.in);
        StringBuilder help = new StringBuilder();
        help.append("请输入" + tip + "：");
        System.out.println(help.toString());
        if (scanner.hasNext()) {
            String ipt = scanner.next();
            if (StringUtils.isNotEmpty(ipt)) {
                return ipt;
            }
        }
        throw new MybatisPlusException("请输入正确的" + tip + "！");
    }

    public static void main(String[] args) {
        // 代码生成器
        AutoGenerator mpg = new AutoGenerator();

        // 全局配置
        GlobalConfig gc = new GlobalConfig();
        String projectPath = System.getProperty("user.dir");
        gc.setOutputDir(projectPath + "/src/main/java");
//        gc.setOutputDir("D:\\test");
        gc.setAuthor("LJF");
        gc.setOpen(false);
        // gc.setSwagger2(true); 实体属性 Swagger2 注解
        gc.setServiceName("%sService");
        mpg.setGlobalConfig(gc);

        // 数据源配置
        DataSourceConfig dsc = new DataSourceConfig();
        dsc.setUrl("jdbc:mysql://localhost:3306/vueblog?serverTimezone=Hongkong?characterEncoding=utf8&serverTimezone=GMT%2B8");
        // dsc.setSchemaName("public");
        dsc.setDriverName("com.mysql.cj.jdbc.Driver");
        dsc.setUsername("root");
        dsc.setPassword("123456");
        mpg.setDataSource(dsc);

        // 包配置
        PackageConfig pc = new PackageConfig();
        pc.setModuleName(null);
        pc.setParent("com.wind.vueblog");
        mpg.setPackageInfo(pc);

        // 自定义配置
        InjectionConfig cfg = new InjectionConfig() {
            @Override
            public void initMap() {
                // to do nothing
            }
        };

        // 如果模板引擎是 freemarker
        String templatePath = "/templates/mapper.xml.ftl";
        // 如果模板引擎是 velocity
        // String templatePath = "/templates/mapper.xml.vm";

        // 自定义输出配置
        List<FileOutConfig> focList = new ArrayList<>();
        // 自定义配置会被优先输出
        focList.add(new FileOutConfig(templatePath) {
            @Override
            public String outputFile(TableInfo tableInfo) {
                // 自定义输出文件名 ， 如果你 Entity 设置了前后缀、此处注意 xml 的名称会跟着发生变化！！
                return projectPath + "/src/main/resources/mapper/"
                        + "/" + tableInfo.getEntityName() + "Mapper" + StringPool.DOT_XML;
            }
        });

        cfg.setFileOutConfigList(focList);
        mpg.setCfg(cfg);

        // 配置模板
        TemplateConfig templateConfig = new TemplateConfig();

        templateConfig.setXml(null);
        mpg.setTemplate(templateConfig);

        // 策略配置
        StrategyConfig strategy = new StrategyConfig();
        strategy.setNaming(NamingStrategy.underline_to_camel);
        strategy.setColumnNaming(NamingStrategy.underline_to_camel);
        strategy.setEntityLombokModel(true);
        strategy.setRestControllerStyle(true);
        strategy.setInclude(scanner("表名，多个英文逗号分割").split(","));
        strategy.setControllerMappingHyphenStyle(true);
        strategy.setTablePrefix("m_");
        mpg.setStrategy(strategy);
        mpg.setTemplateEngine(new FreemarkerTemplateEngine());
        mpg.execute();
    }
}
```

```java
import com.baomidou.mybatisplus.core.exceptions.MybatisPlusException;
import com.baomidou.mybatisplus.core.toolkit.StringPool;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.generator.AutoGenerator;
import com.baomidou.mybatisplus.generator.InjectionConfig;
import com.baomidou.mybatisplus.generator.config.*;
import com.baomidou.mybatisplus.generator.config.po.TableInfo;
import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy;
import com.baomidou.mybatisplus.generator.engine.FreemarkerTemplateEngine;

import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;

// 演示例子，执行 main 方法控制台输入模块表名回车自动生成对应项目目录中
public class CodeGenerator {

    /**
     * <p>
     * 读取控制台内容
     * </p>
     */
    public static String scanner(String tip) {
        Scanner scanner = new Scanner(System.in);
        StringBuilder help = new StringBuilder();
        help.append("请输入" + tip + "：");
        System.out.println(help.toString());
        if (scanner.hasNext()) {
            String ipt = scanner.next();
            if (StringUtils.isNotEmpty(ipt)) {
                return ipt;
            }
        }
        throw new MybatisPlusException("请输入正确的" + tip + "！");
    }

    public static void main(String[] args) {
        // 代码生成器
        AutoGenerator mpg = new AutoGenerator();

        // 全局配置
        GlobalConfig gc = new GlobalConfig();
        String projectPath = System.getProperty("user.dir");
        gc.setOutputDir(projectPath + "/src/main/java");
//        gc.setOutputDir("D:\\test");
        gc.setAuthor("LJF");
        gc.setOpen(false);
        // gc.setSwagger2(true); 实体属性 Swagger2 注解
        gc.setServiceName("%sService");
        mpg.setGlobalConfig(gc);

        // 数据源配置
        DataSourceConfig dsc = new DataSourceConfig();
        dsc.setUrl("jdbc:mysql://localhost:3306/vueblog?serverTimezone=Hongkong?characterEncoding=utf8&serverTimezone=GMT%2B8");
        // dsc.setSchemaName("public");
        dsc.setDriverName("com.mysql.cj.jdbc.Driver");
        dsc.setUsername("root");
        dsc.setPassword("123456");
        mpg.setDataSource(dsc);

        // 包配置
        PackageConfig pc = new PackageConfig();
        pc.setModuleName(null);
        pc.setParent("com.wind.vueblog");
        mpg.setPackageInfo(pc);

        // 自定义配置
        InjectionConfig cfg = new InjectionConfig() {
            @Override
            public void initMap() {
                // to do nothing
            }
        };

        // 如果模板引擎是 freemarker
        String templatePath = "/templates/mapper.xml.ftl";
        // 如果模板引擎是 velocity
        // String templatePath = "/templates/mapper.xml.vm";

        // 自定义输出配置
        List<FileOutConfig> focList = new ArrayList<>();
        // 自定义配置会被优先输出
        focList.add(new FileOutConfig(templatePath) {
            @Override
            public String outputFile(TableInfo tableInfo) {
                // 自定义输出文件名 ， 如果你 Entity 设置了前后缀、此处注意 xml 的名称会跟着发生变化！！
                return projectPath + "/src/main/resources/mapper/"
                        + "/" + tableInfo.getEntityName() + "Mapper" + StringPool.DOT_XML;
            }
        });

        cfg.setFileOutConfigList(focList);
        mpg.setCfg(cfg);

        // 配置模板
        TemplateConfig templateConfig = new TemplateConfig();

        templateConfig.setXml(null);
        mpg.setTemplate(templateConfig);

        // 策略配置
        StrategyConfig strategy = new StrategyConfig();
        strategy.setNaming(NamingStrategy.underline_to_camel);
        strategy.setColumnNaming(NamingStrategy.underline_to_camel);
        strategy.setEntityLombokModel(true);
        strategy.setRestControllerStyle(true);
        strategy.setInclude(scanner("表名，多个英文逗号分割").split(","));
        strategy.setControllerMappingHyphenStyle(true);
        strategy.setTablePrefix("m_");
        mpg.setStrategy(strategy);
        mpg.setTemplateEngine(new FreemarkerTemplateEngine());
        mpg.execute();
    }
}
```

```js
document.documentElement.style.setProperty(
  "--rotate-180deg",
  "rotate(-180deg)"
);

```