代码拉取完成,页面将自动刷新
同步操作将从 石添/zide 强制同步,此操作会覆盖自 Fork 仓库以来所做的任何修改,且无法恢复!!!
确定后同步将在后台操作,完成时将刷新页面,请耐心等待。
SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;
-- ----------------------------
-- Table structure for ams_article
-- ----------------------------
DROP TABLE IF EXISTS `ams_article`;
CREATE TABLE `ams_article` (
`id` bigint NOT NULL AUTO_INCREMENT COMMENT '主键id',
`user_id` bigint NULL DEFAULT NULL COMMENT '用户id',
`category_id` bigint NULL DEFAULT NULL COMMENT '分类id',
`title` varchar(150) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '文章标题',
`main_img` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT '文章封面地址',
`summary` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '文章简介',
`content` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL COMMENT '文章内容',
`read_volume` bigint NULL DEFAULT 0 COMMENT '文章阅读量',
`collect_volume` bigint NULL DEFAULT 0 COMMENT '收藏数',
`like_volume` bigint NULL DEFAULT 0 COMMENT '点赞数',
`comment_volume` bigint NULL DEFAULT 0 COMMENT '评论数',
`top_status` int NULL DEFAULT 0 COMMENT '是否置顶 0否 1是',
`push_status` int NULL DEFAULT 0 COMMENT '是否发布 0:下架 1:发布',
`show_scope` int NULL DEFAULT 0 COMMENT '可见范围',
`push_type` int NULL DEFAULT 0 COMMENT '是否原创 0:原创 1:转载,2:翻译',
`original_url` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '转载地址',
`address` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '发布地址',
`create_time` datetime NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`update_time` datetime NULL DEFAULT NULL COMMENT '修改时间',
`carousel_status` int NULL DEFAULT 0 COMMENT '是否首页轮播',
`recom_status` int NULL DEFAULT 0 COMMENT '是否推荐',
`tag` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT '文章标签',
PRIMARY KEY (`id`) USING BTREE,
INDEX `user_id`(`user_id` ASC) USING BTREE,
FULLTEXT INDEX `title`(`title`) WITH PARSER `ngram`
) ENGINE = InnoDB AUTO_INCREMENT = 10 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '博客文章表' ROW_FORMAT = DYNAMIC;
-- ----------------------------
-- Records of ams_article
-- ----------------------------
INSERT INTO `ams_article` VALUES (1, 3, 8, '标题撒大大标题撒大大标helloworld题撒大大啊实打实大啊实打实大师', 'http://localhost:8128/img/article/20240501180023A002.png', '电风扇', '# 什么是TypeScript\r\n\r\nTypeScript于2012年10月由微软推出上线,始于JavaScript,看名字就知道TypeScript主要强调了类型,TypeScript在JaaScript基础上增加**类型系统**,JavaScript是一个弱类型语言,在编译期间声明的变量可以是任意类型,会导致运行时可能出现的类型错误,使用TypeScript之后可以指定变量类型,如果出现类型问题在编译期间就可以暴露出来,更容易查bug。\r\n最终TypScript又归于JavaScript,运行时其实还是将TypeScript转译成JavaScript执行,因为浏览器,node环境只能运行JavaScript。\r\n\r\n# 安装TypeScript\r\n\r\n首先确保您的电脑上安装了node,建议安装nodejs18以上版本。可点击链接进入[node下载地址](https://www.nodejs.com.cn/)。\r\nTypeScript需要编译为JavaScript文件执行,所以需要先安装TypeScript环境,可以将TypeScipt文件编译为JavaScript在浏览器或者node环境中运行。首先同时按下win + r键输入cmd唤起命令窗口\r\n**安装命令:**\r\n\r\n```shell\r\n# 全局安装typescript\r\nnpm install -g typescript\r\n```\r\n\r\n![image.png](http://localhost:8128/img/article/20240501180023A002.png)\r\n安装之后TypeScript的执行命令为tsc,比如想要查看TypeScript版本则可输入:\r\n\r\n```shell\r\ntsc -version\r\n```\r\n\r\n# HelloWorld\r\n\r\n## 创建文件\r\n\r\n写JavaScript时,文件后缀为.js。写TypeScript时文件后缀名为.ts。可以打开任意的编辑器整活,此处我使用VsCode开搞。以声明sting类型变量为例:\r\n\r\n```typescript\r\n// 变量title后边加上:string。指定为string类型,修改变量值时就只能是string类型\r\nlet title:string = \"Hello TypeScript\";\r\n\r\nconsole.log(title);\r\n```\r\n\r\n![image.png](http://localhost:8128/img/article/20240501180023A002.png)\r\n所以说ts声明变量的语法为:\r\n\r\n```javascript\r\n变量修饰符 变量名 : 数据类型 = 初始化值;\r\n如:var/let/const vag:number = 123;\r\n```\r\n\r\n## 编译\r\n\r\n将ts文件编译为js文件执行,使用tsc命令即可命令\r\n\r\n```shell\r\ntsc 01-hellosworld.ts\r\n```\r\n\r\n执行之后会在同级目录下生成一个同名的js文件\r\n![image.png](http://localhost:8128/img/article/20240501180023A002.png)\r\n\r\n## 执行\r\n\r\n使用node命令或者通过浏览器打开js文件来执行,如果使用node执行则使用nod命令:\r\n\r\n```shell\r\nnode 01-hellosworld.js\r\n```\r\n\r\n![image.png](http://localhost:8128/img/article/20240501180023A002.png)\r\n\r\n## 快速执行\r\n\r\n安装ts-node包实现快速运行ts,其实内部还是将ts转为js执行,底层逻辑不变,只是简化了开发人员操作。\r\n**安装命令:**\r\n\r\n```shell\r\nnpm install -g ts-node\r\n```\r\n\r\n**执行ts文件:**\r\n\r\n```shell\r\nts-node 01-hellosworld.ts\r\n```\r\n\r\n此时就不会再生成js文件啦。**但是执行的还是js哦,这是一定要记清楚的。**\r\n\r\n## 修改类型\r\n\r\n尝试将title修改为数字类型数据,如果在javascript中是可行的,类型可随意修改,在typescript中,如果修改数据类型在编译期就会报错\r\n![image.png](http://localhost:8128/img/article/20240501180023A002.png)\r\n那么忽略编辑器的报错,尝试运行会返回TSError错误,错误信息是编译TypeScript时出现问题。\r\n![image.png](http://localhost:8128/img/article/20240501180023A002.png)\r\n此处可以看出TypeScript相较于JavaScript对类型要求更严格,这也是很多开发人员吐槽的地方,以前写js\r\n随心所欲,随便定义一个变量,下边想怎么改都成,使用了ts之后只能修改值为对应类型的,好像添加了束缚,但我觉得这是好事:\r\n\r\n- 首先数据类型在逻辑处理中其实就应该输入同一个类型内的修改,严格来说是不可以将字符串类型修改为数字类型等,甚至是对象类型的数据。\r\n- 在复杂的业务处理中,甚至有时候都已经忘记了一个变量是什么类型的了😛。\r\n\r\n# TypeScript优势\r\n\r\nTypeScript包含JavaScript所有功能,同时又增加了类型系统,弥补了JavaScript弱类型的缺陷,那么为什么是缺陷呢?在ES6中JavaScript又推出了很多新的API,方便处理数据,这些api有的是字符串才能使用的,有的是数组才能使用的,有的是数字才能使用的,而JavaScript在编译时并不会检查当前变量是什么类型,能否使用调用的方法,在运行时就会出现错误。甚至会导致严重的线上bug。比如:\r\n\r\n```javascript\r\nlet arr = [1,2,3,4,5,6,7];\r\n\r\n// 将数组转为数字类型\r\narr = 1;\r\n// 调用filter方法,获取大于4的数据,此方法number类型肯定不能调用,但编译期并不会提示\r\nlet result = arr.filter(item => item > 4);\r\nconsole.log(result);\r\n\r\n```\r\n\r\n运行时就会出现TypeError即类型错误。\r\n![image.png](http://localhost:8128/img/article/20240501180023A002.png)\r\n以上错误在开发工作中比比皆是,不要妄图以为脑子好用能记住所有变量的数据类型,有时候你甚至不知道用户传过来的是什么类型的数据,所以在定义变量和方法参数时,设置明确的类型势在必行。\r\n\r\n# 数据类型\r\n\r\nTypeScript是JavaScript的扩充,所以包含JavaScript中的所有数据类型,同时又增加了若干个数据类型。下表列出TypeScript中所有的数据类型,不区分JS和TS,没有什么实际意义:\r\n\r\n| 数据类型 | 作用 |\r\n| ------------------ | ------------------------------------------------------------ |\r\n| number:数字类型 | 双精度 64 位浮点值。它可以用来表示整数和分数 |\r\n| string:字符串类型 | 描述字符或字符串,使用单引号(\')或双引号(\")来表示字符串类型。反引号(`)来定义多行文本和内嵌表达式。 |\r\n| boolean:布尔类型 | 表示逻辑值:true 和 false。 |\r\n| Object:对象 | 对象类型包括,数组、对象、函数 |\r\n| 元组 | 元组类型用来表示已知元素数量和类型的数组,各元素的类型不必相同,对应位置的类型需要相同。 |\r\n| enum:枚举 | 枚举类型用于定义数值集合。 |\r\n| any:任意类型 | 声明为 any 的变量可以赋予任意类型的值。 |\r\n| null | 表示对象值缺失。 |\r\n| undefined | 用于初始化变量为一个未定义的值 |\r\n| void | 用于标识方法返回值的类型,表示该方法没有返回值。 |\r\n| symbol | 用来声明唯一值,解决命名冲突问题 |\r\n| never | 其它类型(包括 null 和 undefined)的子类型,代表从不会出现的值。 |\r\n\r\n## number\r\n\r\n前端的JavaScript和TypeScript中没有整数和小数之分,数字类型统一使用number表示,可以使用各种进制实例化一个数字,写法如下:\r\n\r\n```typescript\r\n// 使用十进制表示\r\nlet num1: number = 6;\r\n// 十六进制\r\nlet num2: number = 0xf00d;\r\n// ES6 中的二进制表示法\r\nlet num3: number = 0b1010;\r\n// ES6 中的八进制表示法\r\nlet num4: number = 0o744;\r\n// 非数字\r\nlet num5: number = NaN;\r\n// 无穷值\r\nlet infinityNumber: number = Infinity;\r\n// 使用构造\r\nlet num1 : number = Number(1);\r\n// 使用JS中对象类型表示类型\r\nlet num2 : Number = 123;\r\n```\r\n\r\n其他数据类型都相同,可以使用构造方法初始化值,使用对象类型标识数据类型\r\n\r\n## string\r\n\r\n字符串可以通过单引号\'\'、双引号\"\"和模板字符串``创建\r\n\r\n```typescript\r\nlet s1 : string = \'单引号字符串\';\r\n\r\nlet s2 : string = \"双引号字符串\";\r\n\r\nlet s3 : string = `第一个${s1},第二个${s2}`;\r\n\r\nlet s4 : string = String(\"对象字符串\");\r\n```\r\n\r\n模板字符串可以使用${变量}方式引用变量\r\n\r\n## boolean\r\n\r\n布尔类型的值用来表示对【true】或者错【false】,在TypeScript中使用boolean表示:\r\n\r\n```typescript\r\nlet age : number = 123;\r\n\r\nlet username : string = \"username\";\r\n\r\nlet isMan : boolean = true;\r\n\r\n// 下方是错误的,new Boolean是对象类型\r\n// let isDog : boolean = new Boolean(true);\r\n\r\n// 可以直接使用Boolean()\r\nlet isDog : boolean = Boolean(true);\r\n```\r\n\r\n## 任意值\r\n\r\n可以通过使用any表示变量可以是任意类型数据,使用any效果和JavaScript相同,后期可以修改变量数据类型\r\n\r\n```typescript\r\n// any类型,初始值为string\r\nlet a1 : any = \"a1\";\r\n// 修改为number类型\r\na1 = 123;\r\n```\r\n\r\n## 类型推断\r\n\r\nTypeScript支持像JavaScript那样不显示声明数据类型,会根据赋值自动推断类型,后期则不可修改值为其他类型的数据\r\n\r\n```typescript\r\n// 类型自动推断为string\r\nlet username = \'张三\';\r\n// Type \'number\' is not assignable to type \'string\'\r\nusername = 123;\r\n```\r\n\r\n## null和undefined\r\n\r\nnull和undefined也可以被当做数据类型来定义\r\n\r\n```typescript\r\nlet nu : null = null;\r\n\r\nlet un : undefined = undefined;\r\n```\r\n\r\nnull是一个对象/变量的值为null,而undefined则表示该变量没有初始化。\r\n\r\n## void\r\n\r\nvoid为空值,是TypeScript中新增的数据类型,表示没有任何返回值的函数\r\n\r\n```typescript\r\nfunction say(): void {\r\n alert(\'我是张三\');\r\n}\r\n\r\nsay();\r\n```\r\n\r\n有些地方会比较,深究null、undefined、void区别,我认为并没有意义,null就是一个对象为空值,undefined就是没有初始值,void用来表示方法没有返回值,不要去描述变量。仅此而已不要再做无谓的深究!\r\n\r\n## 联合类型\r\n\r\n联合类型是该变量可以在声明的类型中随意匹配一个即可,比如年龄可以使用数字表示,也可以使用字符串表示,可以通过** | **符号分割多个类型\r\n\r\n```typescript\r\nlet age : number | string = \'十六\';\r\nage = 16;\r\n```\r\n\r\n如果使用联合类型表示一个变量,此时在操作变量时需要使用共有属性和方法,不能使用某一个类型特有的方法或属性,比如age可以为number或者string类型,number类型有toFixed方法,而string没有,number和string共有的操作有**toString**、**valueOf**方法。\r\n\r\n```typescript\r\nlet age : number | string = \'十六\'\r\nage = 16\r\n// 共有方法\r\nage.toString();\r\n// string有此方法,如果数字调用出现,Property \'length\' does not exist on type \'number\'\r\nage.length;\r\n```\r\n\r\n或者使用**typeof**判断类型之后使用\r\n\r\n```typescript\r\nlet age : number | string = 12\r\n\r\nif(typeof age === \'number\') {\r\n console.log(\"数字类型\")\r\n}\r\n\r\nif(typeof age === \'string\') {\r\n console.log(\"字符串类型\")\r\n}\r\n```\r\n\r\n## 数组\r\n\r\n```typescript\r\n// 通过类型[]方式指定,下例:数组中只允许有number类型数据\r\nlet a1 : number[] = [1,2,3,4];\r\n// 通过泛型指定,Array<类型>,下例:只允许有字符串\r\nlet nameArr : Array<string> = [\'大毛\',\'二毛\',\'小明\'];\r\n```\r\n\r\n## 元组\r\n\r\n元组和数组区别在于,元组中可以存在不同类型的数据。\r\n\r\n```typescript\r\n// 数据类型必须与索引一一匹配\r\nlet a1 : [number,string,number] = [1,\'a\',2];\r\n\r\n// 先声明,再赋值\r\nlet person1: [string, number];\r\nperson1 = [\'大毛\', 25];\r\n\r\n// 获取一项\r\nlet username : string = person1[0];\r\nlet age : number = person1[1];\r\n\r\n// 操作数据\r\nconsole.log(username.indexOf(\"大\"))\r\nconsole.log(age.toFixed(2));\r\n```\r\n\r\n添加越界元素时【元组本身2个元素长度,新增其他数据长度会增加,称为添加越界元素】,它的类型会被限制为元组中每个类型的联合类型:\r\n\r\n```typescript\r\n// 先声明,再赋值\r\nlet person1: [string, number] = [\'大毛\', 25];\r\n\r\nperson1.push(\"123\");\r\nperson1.push(123);\r\n\r\n// Argument of type \'boolean\' is not assignable to parameter of type \'string | number\'.\r\nperson1.push(true);\r\n```\r\n\r\n如果元组中存在可选值时可以在类型后添加?表示,如下\r\n\r\n```typescript\r\n// number类型的值可写可不写,添加?即可\r\nlet person1: [string, number?] = [\'大毛\'];\r\n```\r\n\r\n## 枚举\r\n\r\n枚举(Enum)类型用于取值被限定在一定范围内的场景,比如订单状态为未付款、待发货、待收货、待评价,性别限定为男、女、未知等。\r\n枚举成员会被赋值为从 0 开始递增的数字,同时也会对枚举值到枚举名进行反向映射:\r\n\r\n```typescript\r\nenum OrderStatus {NO_PAY, SHIPPED, RECEIVED, EVALUATED,REVIEWED};\r\n\r\n// 使用\r\nconsole.log(OrderStatus[\'NO_PAY\'] === 0);\r\nconsole.log(OrderStatus[\'SHIPPED\'] === 1);\r\nconsole.log(OrderStatus[\'RECEIVED\'] === 2);\r\n\r\nconsole.log(OrderStatus[0] === \'NO_PAY\');\r\nconsole.log(OrderStatus[1] === \'SHIPPED\');\r\nconsole.log(OrderStatus[2] === \'RECEIVED\');\r\n```\r\n\r\n你还可以通过手动赋值修改默认以0递增的数据\r\n\r\n```typescript\r\nenum OrderStatus {NO_PAY = 1, SHIPPED = 2, RECEIVED = 3, EVALUATED,REVIEWED};\r\n\r\n// 使用\r\nconsole.log(OrderStatus[\'NO_PAY\']);\r\nconsole.log(OrderStatus[\'SHIPPED\']);\r\nconsole.log(OrderStatus[\'RECEIVED\']);\r\nconsole.log(OrderStatus[\'EVALUATED\']);\r\nconsole.log(OrderStatus[\'REVIEWED\']);\r\n```\r\n\r\n## 函数\r\n\r\nTypeScript中声明函数可以在形式参数和返回值中指定数据类型。\r\n\r\n```typescript\r\n// 接收number类型参数,返回number类型参数\r\nfunction fun1(num1 : number,num2 : number) : number {\r\n\r\n return num1 + num2;\r\n}\r\nconsole.log(fun1(1,2));\r\n```\r\n\r\n也支持通过函数表达式【Function Expression】的方式声明函数\r\n\r\n```typescript\r\nlet fun2 = function(str1 : string,str2 : string) : string {\r\n\r\n return str1.concat(str2);\r\n}\r\n\r\nconsole.log(fun2(\'A\',\'B\'));\r\n```\r\n\r\n函数同样支持**可选参数**,当然可选参数必须在最后\r\n\r\n```typescript\r\nfunction buildName(firstName: string, lastName?: string) {\r\n if (lastName) {\r\n return firstName + \' \' + lastName;\r\n } else {\r\n return firstName;\r\n }\r\n}\r\nlet tomcat = buildName(\'Tom\', \'Cat\');\r\nlet tom = buildName(\'Tom\');\r\n```\r\n\r\n如果没有返回值,则可以使用**void**修饰返回值类型,无返回值时接收到的为**undefined**\r\n\r\n```typescript\r\nfunction fun1(firstName: string):void {\r\n console.log(firstName.toUpperCase());\r\n}\r\nlet result = fun1(\'Tom\');\r\nconsole.log(result);\r\n```\r\n\r\nES6中允许方法参数有默认值,**TypeScript 会将添加了默认值的参数识别为可选参数**:\r\n\r\n```typescript\r\nfunction buildName(firstName: string, lastName: string = \'Cat\') {\r\n return firstName + \' \' + lastName;\r\n}\r\nlet tomcat = buildName(\'Tom\', \'Cat\');\r\nlet tom = buildName(\'Tom\');\r\n```\r\n\r\n此时就不受「可选参数必须接在必需参数后面」的限制了:\r\n\r\n```typescript\r\nfunction buildName(firstName: string = \'Tom\', lastName: string) {\r\n return firstName + \' \' + lastName;\r\n}\r\nlet tomcat = buildName(\'Tom\', \'Cat\');\r\nlet cat = buildName(undefined, \'Cat\');\r\n```\r\n\r\nES6中可以使用 **...rest** 的方式获取函数中的剩余参数(rest 参数):\r\n\r\n```typescript\r\nfunction push(array, ...items) {\r\n items.forEach(function(item) {\r\n array.push(item);\r\n });\r\n}\r\n\r\nlet a: any[] = [];\r\npush(a, 1, 2, 3);\r\n```\r\n\r\n事实上,items 是一个数组。所以我们可以用数组的类型来定义它:\r\n\r\n```typescript\r\nfunction push(array: any[], ...items: any[]) {\r\n items.forEach(function(item) {\r\n array.push(item);\r\n });\r\n}\r\n\r\nlet a = [];\r\npush(a, 1, 2, 3);\r\n```\r\n\r\n注意,rest 参数只能是最后一个参数\r\n\r\n## 接口\r\n\r\n接口用来定义一种规范,具体的时候交由对象来做,举个生活中的例子我们购买商品按照消费者权益来说所有的商品都必须有售后保障,那么具体怎么实现售后,你是上门维修也好,直接换货也好,就有厂家自己实现。这个必须有售后就是规范,各个厂家就是一个一个具体的对象,交由对象实现就行了。\r\n程序中就是我们希望在程序内描述一个人,那么人的规范就是有名字、性别、年龄和一些行为这可以通过接口描述,具体是哪一个人,就交由对象来具体化【实例化】。\r\n\r\n```typescript\r\n// 接口定义抽象结构\r\ninterface Person {\r\n username: string;\r\n age: number;\r\n say():void;\r\n}\r\n// 对象具体实现\r\nlet tom: Person = {\r\n username: \'张三\',\r\n age: 25,\r\n say() : void {\r\n console.log(this.username)\r\n }\r\n};\r\n```\r\n\r\n### 可选属性\r\n\r\n有时认为一个对象的某个属性可有可无,可以使用可选属性\r\n\r\n```typescript\r\ninterface Person {\r\n name: string;\r\n age?: number;\r\n}\r\n\r\nlet p1: Person = {\r\n name: \'大毛\'\r\n};\r\nlet p2: Person = {\r\n name: \'小毛\',\r\n age: 25\r\n};\r\n```\r\n\r\n### 任意属性\r\n\r\n又是我们希望可以在对象中添加任意的属性:\r\n\r\n```typescript\r\ninterface Person {\r\n name: string;\r\n age?: number;\r\n [propName: string]: any;\r\n}\r\n\r\nlet tom: Person = {\r\n name: \'大毛\',\r\n gender: \'男\',\r\n};\r\n```\r\n\r\n任意属性的类型需要包含可选属性,否则编译报错,比如any包含number类型,如果将any换成string,则age可选属性就会报错\r\n\r\n### 只读属性\r\n\r\n有时候我们希望对象中的一些字段在创建的时候被赋值后就不可更改,那么可以用 readonly 定义只读属性:\r\n\r\n```typescript\r\ninterface IBook {\r\n readonly author: string;\r\n bookname: string;\r\n}\r\n\r\nlet book1: IBook = {\r\n author: \'小明\',\r\n bookname: \'TypeScript养成记\',\r\n};\r\n\r\nbook1.author = \'大毛\';\r\n```\r\n\r\n## 类\r\n\r\nES6中JavaScript引入了类的概念,类也是用来定义事物的抽象,交由对象具体实现,在面向对象的语言中,对于类我们应该熟知这么几个概念:\r\n\r\n- 类(Class):定义了一件事物的抽象特点,包含它的属性和方法\r\n- 对象(Object):类的实例,通过 new 生成\r\n- 面向对象(OOP)的三大特性:封装、继承、多态\r\n- 封装(Encapsulation):将对数据的操作细节隐藏起来,只暴露对外的接口。外界调用端不需要(也不可能)知道细节,就能通过对外提供的接口来访问该对象,同时也保证了外界无法任意更改对象内部的数据\r\n- 继承(Inheritance):子类继承父类,子类除了拥有父类的所有特性外,还有一些更具体的特性\r\n- 多态(Polymorphism):由继承而产生了相关的不同的类,对同一个方法可以有不同的响应。比如 Cat 和 Dog 都继承自 Animal,但是分别实现了自己的 eat 方法。此时针对某一个实例,我们无需了解它是 Cat 还是 Dog,就可以直接调用 eat 方法,程序会自动判断出来应该如何执行 eat\r\n- 存取器(getter & setter):用以改变属性的读取和赋值行为\r\n- 修饰符(Modifiers):修饰符是一些关键字,用于限定成员或类型的性质。比如 public 表示公有属性或方法\r\n- 抽象类(Abstract Class):抽象类是供其他类继承的基类,抽象类不允许被实例化。抽象类中的抽象方法必须在子类中被实现\r\n- 接口(Interfaces):不同类之间公有的属性或方法,可以抽象成一个接口。接口可以被类实现(implements)。一个类只能继承自另一个类,但是可以实现多个接口\r\n\r\n### TypeScript中的类\r\n\r\nTypeScript 可以使用三种访问修饰符(Access Modifiers),分别是 public、private 和 protected。\r\n\r\n- public 修饰的属性或方法是公有的,可以在任何地方被访问到,默认所有的属性和方法都是 public 的\r\n- private 修饰的属性或方法是私有的,不能在声明它的类的外部访问\r\n- protected 修饰的属性或方法是受保护的,它和 private 类似,区别是它在子类中也是允许被访问的\r\n\r\n比如创建一个动物类,实例化一个狗\r\n\r\n```typescript\r\nclass Animal {\r\n public name;\r\n public constructor(name:string) {\r\n this.name = name;\r\n }\r\n}\r\n\r\nlet a = new Animal(\'大黄\');\r\nconsole.log(a.name); // 大黄\r\na.name = \'小黑\';\r\nconsole.log(a.name); // 小黑\r\n```\r\n\r\n上述可以直接修改和获取数据,对于对象数据来说是不安全的,可以通过private或者protected提高安全性。\r\n\r\n### private修饰属性\r\n\r\n使用private修饰将属性私有化,属性只能在类内部直接调用,如果要修改数据和获取数据可以通过公开的方法获取\r\n\r\n```typescript\r\nclass Animal {\r\n private name;\r\n public constructor(name:string) {\r\n this.name = name;\r\n }\r\n\r\n public getName():string {\r\n return this.name;\r\n }\r\n\r\n public setName(name:string):string {\r\n return this.name = name;\r\n }\r\n}\r\n\r\nlet a = new Animal(\'大黄\');\r\nconsole.log(a.getName()); // 大黄\r\na.setName(\'小黑\');\r\nconsole.log(a.getName()); // 小黑\r\n```\r\n\r\n### protected修饰属性\r\n\r\n被private修饰,包括子类在内都不被允许访问,只有本类内部可以访问,如果希望子类可以访问则可以使用protected修饰\r\n\r\n```typescript\r\nclass Animal {\r\n protected name;\r\n public constructor(name:string) {\r\n this.name = name;\r\n }\r\n\r\n public getName():string {\r\n return this.name;\r\n }\r\n\r\n public setName(name:string):string {\r\n return this.name = name;\r\n }\r\n}\r\n\r\nclass Dog extends Animal {\r\n constructor(name:string) {\r\n super(name);\r\n // name属性被继承过来\r\n console.log(this.name);\r\n }\r\n}\r\n```\r\n\r\n### private修饰构造方法\r\n\r\n如果构造方法通过private修饰被私有化,则该类不能被实例化,也不能被继承\r\n\r\n```typescript\r\nclass Animal {\r\n protected name;\r\n // 私有化构造方法\r\n private constructor(name:string) {\r\n this.name = name;\r\n }\r\n\r\n public getName():string {\r\n return this.name;\r\n }\r\n\r\n public setName(name:string):string {\r\n return this.name = name;\r\n }\r\n}\r\n\r\n// 继承就会报错\r\n// Cannot extend a class \'Animal\'. Class constructor is marked as private\r\nclass Dog extends Animal {\r\n constructor(name:string) {\r\n super(name);\r\n // name属性被继承过来\r\n console.log(this.name);\r\n }\r\n}\r\n```\r\n\r\n### protected 修饰构造方法\r\n\r\n如果构造函数修饰为 protected 时,该类不能实例化\r\n\r\n```typescript\r\nclass Animal {\r\n protected name;\r\n // protected修饰\r\n protected constructor(name:string) {\r\n this.name = name;\r\n }\r\n\r\n public getName():string {\r\n return this.name;\r\n }\r\n\r\n public setName(name:string):string {\r\n return this.name = name;\r\n }\r\n}\r\n// 继承没毛病\r\nclass Dog extends Animal {\r\n constructor(name:string) {\r\n super(name);\r\n // name属性被继承过来\r\n console.log(this.name);\r\n }\r\n}\r\n// 实例化有问题\r\n// Constructor of class \'Animal\' is protected and only accessible within the class declaration\r\nlet a = new Animal(\'大黄\');\r\n```\r\n\r\n### 参数属性\r\n\r\n类中属性可以定义在构造方法上,等同于类中定义了属性\r\n\r\n```typescript\r\nclass Animal {\r\n // 参数属性\r\n public constructor(public name:string) {\r\n }\r\n}\r\n\r\nlet a = new Animal(\"大黄\");\r\nconsole.log(a.name)\r\n```\r\n\r\n### readonly\r\n\r\n只读属性关键字也可用于类中,只允许出现在属性声明或索引签名或构造函数中。\r\n\r\n```typescript\r\nclass Animal {\r\n // 只读属性\r\n readonly name;\r\n public constructor(name:string) {\r\n this.name = name;\r\n }\r\n}\r\n\r\nlet a = new Animal(\'大黄\');\r\nconsole.log(a.name);\r\n// 不可再次修改\r\na.name = \'小黑\';\r\n```\r\n\r\n注意如果 readonly 和其他访问修饰符同时存在的话,需要写在其后面。\r\n\r\n```typescript\r\nclass Animal {\r\n // public readonly name;\r\n public constructor(public readonly name:string) {\r\n // this.name = name;\r\n }\r\n}\r\n```\r\n\r\n### 抽象类\r\n\r\n抽象类不能被实例化,使用abstract修饰\r\n\r\n```typescript\r\nabstract class Animal {\r\n public name;\r\n public constructor(name:string) {\r\n this.name = name;\r\n }\r\n public abstract sayHi():any;\r\n}\r\n// Cannot create an instance of an abstract class.\r\nlet a = new Animal(\'大黄\');\r\n```\r\n\r\n抽象类中的抽象方法必须被子类实现,子类必须实现抽象类中的所有抽象方法,否则需要继续抽象下去:\r\n\r\n```typescript\r\nabstract class Animal {\r\n public name;\r\n public constructor(name:string) {\r\n this.name = name;\r\n }\r\n public abstract eat():any;\r\n}\r\n\r\nclass Cat extends Animal {\r\n public eat() {\r\n console.log(`${this.name} 在吃鱼.`);\r\n }\r\n}\r\n\r\nlet c = new Cat(\'小花\');\r\nc.eat();\r\n```\r\n\r\n如果没有实现所有抽象方法则继续报错:\r\n\r\n```typescript\r\nabstract class Animal {\r\n public name;\r\n public constructor(name:string) {\r\n this.name = name;\r\n }\r\n public abstract eat():any;\r\n public abstract sayHi():any;\r\n}\r\n\r\n// Non-abstract class \'Cat\' does not implement all abstract members of \'Animal\'\r\nclass Cat extends Animal {\r\n public eat() {\r\n console.log(`${this.name} 在吃鱼.`);\r\n }\r\n}\r\n```\r\n\r\n## 泛型\r\n\r\n泛型(Generics)是指在定义函数、接口或类的时候,不预先指定具体的类型,而在使用的时候再指定类型的一种特性。\r\n\r\n### 无泛型\r\n\r\n实现一个函数 createArray,它可以创建一个指定长度的数组,同时将每一项都填充一个默认值:\r\n\r\n```typescript\r\nfunction createArray(length: number, value: any): Array<any> {\r\n let result = [];\r\n for (let i = 0; i < length; i++) {\r\n result[i] = value;\r\n }\r\n return result;\r\n}\r\n\r\ncreateArray(3, \'x\'); // [\'x\', \'x\', \'x\']\r\n```\r\n\r\n此处使用any当做入参和Array<any>反参类型,编译不会报错,但是可能会造成类型不安全的问题,调用方法的用户可能瞎传数据,你的方法就报错啦。此时泛型就登场了,**解决参数类型安全问题**\r\n\r\n```typescript\r\nfunction createArray<T>(length: number, value: T): Array<T> {\r\n let result: T[] = [];\r\n for (let i = 0; i < length; i++) {\r\n result[i] = value;\r\n }\r\n return result;\r\n}\r\n\r\ncreateArray<string>(3, \'x\'); // [\'x\', \'x\', \'x\']\r\n```\r\n\r\n上例中,我们在函数名后添加了 <T>,其中 T 用来指代任意输入的类型,在后面的输入 value: T 和输出 Array<T> 中即可使用了。\r\n接着在调用的时候,可以指定它具体的类型为 string。当然,也可以不手动指定,而让类型推论自动推算出来:\r\n\r\n```typescript\r\nfunction createArray<T>(length: number, value: T): Array<T> {\r\n let result: T[] = [];\r\n for (let i = 0; i < length; i++) {\r\n result[i] = value;\r\n }\r\n return result;\r\n}\r\n\r\ncreateArray(3, \'x\'); // [\'x\', \'x\', \'x\']\r\n```\r\n\r\n### 多个类型参数\r\n\r\n定义泛型的时候,可以一次定义多个类型参数:\r\n\r\n```typescript\r\nfunction swap<T, U>(tuple: [T, U]): [U, T] {\r\n return [tuple[1], tuple[0]];\r\n}\r\n\r\nswap([7, \'seven\']); // [\'seven\', 7]\r\n```\r\n\r\n### 泛型约束\r\n\r\n在函数内部使用泛型变量的时候,由于事先不知道它是哪种类型,所以不能随意的操作它的属性或方法:\r\n\r\n```typescript\r\nfunction loggingIdentity<T>(arg: T): T {\r\n console.log(arg.length);\r\n return arg;\r\n}\r\n```\r\n\r\n上例中,泛型 T 不一定包含属性 length,所以编译的时候报错了。\r\n这时,我们可以对泛型进行约束,只允许这个函数传入那些包含 length 属性的变量。这就是泛型约束:\r\n\r\n```typescript\r\ninterface Lengthwise {\r\n length: number;\r\n}\r\n\r\nfunction loggingIdentity<T extends Lengthwise>(arg: T): T {\r\n console.log(arg.length);\r\n return arg;\r\n}\r\n```\r\n\r\n上例中,我们使用了 extends 约束了泛型 T 必须符合接口 Lengthwise 的形状,也就是必须包含 length 属性。\r\n此时如果调用 loggingIdentity 的时候,传入的 arg 不包含 length,那么在编译阶段就会报错了:\r\n\r\n```typescript\r\ninterface Lengthwise {\r\n length: number;\r\n}\r\n\r\nfunction loggingIdentity<T extends Lengthwise>(arg: T): T {\r\n console.log(arg.length);\r\n return arg;\r\n}\r\n\r\nloggingIdentity(7);\r\n```\r\n\r\n多个类型参数之间也可以互相约束:\r\n\r\n```typescript\r\nfunction copyFields<T extends U, U>(target: T, source: U): T {\r\n for (let id in source) {\r\n target[id] = (<T>source)[id];\r\n }\r\n return target;\r\n}\r\n\r\nlet x = { a: 1, b: 2, c: 3, d: 4 };\r\n\r\ncopyFields(x, { b: 10, d: 20 });\r\n```\r\n\r\n上例中,我们使用了两个类型参数,其中要求 T 继承 U,这样就保证了 U 上不会出现 T 中不存在的字段。\r\n\r\n### 泛型接口\r\n\r\n泛型也可以用来定义接口\r\n\r\n```typescript\r\ninterface CreateArrayFunc {\r\n <T>(length: number, value: T): Array<T>;\r\n}\r\n\r\nlet createArray: CreateArrayFunc;\r\ncreateArray = function<T>(length: number, value: T): Array<T> {\r\n let result: T[] = [];\r\n for (let i = 0; i < length; i++) {\r\n result[i] = value;\r\n }\r\n return result;\r\n}\r\n\r\ncreateArray(3, \'x\'); // [\'x\', \'x\', \'x\']\r\n```\r\n\r\n进一步,我们可以把泛型参数提前到接口名上:\r\n\r\n```typescript\r\ninterface CreateArrayFunc<T> {\r\n (length: number, value: T): Array<T>;\r\n}\r\n\r\nlet createArray: CreateArrayFunc<any>;\r\ncreateArray = function<T>(length: number, value: T): Array<T> {\r\n let result: T[] = [];\r\n for (let i = 0; i < length; i++) {\r\n result[i] = value;\r\n }\r\n return result;\r\n}\r\n\r\ncreateArray(3, \'x\'); // [\'x\', \'x\', \'x\']\r\n```\r\n\r\n注意,此时在使用泛型接口的时候,需要定义泛型的类型。\r\n\r\n### 泛型类\r\n\r\n与泛型接口类似,泛型也可以用于类的类型定义中:\r\n\r\n```typescript\r\nclass GenericNumber<T> {\r\n zeroValue: T;\r\n add: (x: T, y: T) => T;\r\n}\r\n\r\nlet myGenericNumber = new GenericNumber<number>();\r\nmyGenericNumber.zeroValue = 0;\r\nmyGenericNumber.add = function(x, y) { return x + y; };\r\n```\r\n\r\n### 泛型参数的默认类型\r\n\r\n在 TypeScript 2.3 以后,我们可以为泛型中的类型参数指定默认类型。当使用泛型时没有在代码中直接指定类型参数,从实际值参数中也无法推测出时,这个默认类型就会起作用。\r\n\r\n```typescript\r\nfunction createArray<T = string>(length: number, value: T): Array<T> {\r\n let result: T[] = [];\r\n for (let i = 0; i < length; i++) {\r\n result[i] = value;\r\n }\r\n return result;\r\n}\r\n```\r\n\r\n# 类型断言\r\n\r\n类型断言(Type Assertion)可以用来手动指定一个值的类型。语法为\r\n\r\n```typescript\r\n值 as 类型\r\n\r\n或\r\n \r\n<类型>值\r\n```\r\n\r\n在 tsx 语法(React 的 jsx 语法的 ts 版)中必须使用 **值 as 类型**。\r\n\r\n## 联合类型断言为一个具体类型\r\n\r\n前文介绍了支持联合类型,即一个变量可以是string类型也可以是number类型,只能访问该变量所有类型的共有属性和方法\r\n\r\n```typescript\r\nfunction fun1(args: string | number):number {\r\n // 将值断言为number类型\r\n let result = args as number;\r\n\r\n return result;\r\n}\r\n\r\nconsole.log(fun1(\"1\"))\r\n```\r\n\r\n## 将一个父类断言为更加具体的子类\r\n\r\n当类之间有继承关系时,类型断言也是很常见的:\r\n\r\n```typescript\r\nclass Animal {\r\n name: string;\r\n constructor(name:string) {\r\n this.name = name;\r\n }\r\n}\r\n\r\nclass Dog extends Animal {\r\n constructor(name:string) {\r\n super(name);\r\n }\r\n doorkeeper():void {\r\n console.log(this.name + \"在看家\")\r\n }\r\n}\r\nclass Cat extends Animal {\r\n constructor(name:string) {\r\n super(name);\r\n }\r\n catchMouse():void {\r\n console.log(this.name + \"在抓老鼠\")\r\n }\r\n}\r\n\r\n// 离家需要狗看门,也需要猫抓老鼠\r\nfunction leaveHome(animal: Animal) {\r\n let dog = animal as Dog;\r\n dog.doorkeeper();\r\n}\r\n\r\nleaveHome(new Dog(\'旺财\'));\r\n```\r\n\r\n上面的例子中,我们声明了函数 leaveHome,转为Dog类型,调用看门方法,离家时构建一个狗对象,调用它的看门方法即可。\r\n\r\n## 断言限制\r\n\r\n类型不可随意断言,比如Dog是Animal的一种,Adimal可以断言为Dog,Cat不是Dog的一种,Cat就不能断言为Dog。如下例子:\r\n\r\n```typescript\r\nclass Animal {\r\n name: string;\r\n constructor(name:string) {\r\n this.name = name;\r\n }\r\n}\r\n\r\nclass Dog extends Animal {\r\n constructor(name:string) {\r\n super(name);\r\n }\r\n doorkeeper():void {\r\n console.log(this.name + \"在看家\")\r\n }\r\n}\r\nclass Cat extends Animal {\r\n constructor(name:string) {\r\n super(name);\r\n }\r\n catchMouse():void {\r\n console.log(this.name + \"在抓老鼠\")\r\n }\r\n}\r\n\r\n// 离家需要狗看门\r\n// 如果传入类型为Cat,断言成Dog编译不会报错,但运行时就会报错\r\nfunction leaveHome(animal: Animal) {\r\n let dog = animal as Dog;\r\n dog.doorkeeper();\r\n}\r\n// 实例化一个Cat\r\nleaveHome(new Cat(\'小花\'));\r\n```\r\n\r\n可以使用**instanceof**判断类型后对数据进行断言:\r\n\r\n```typescript\r\nclass Animal {\r\n name: string;\r\n constructor(name:string) {\r\n this.name = name;\r\n }\r\n}\r\n\r\nclass Dog extends Animal {\r\n constructor(name:string) {\r\n super(name);\r\n }\r\n doorkeeper():void {\r\n console.log(this.name + \"在看家\")\r\n }\r\n}\r\nclass Cat extends Animal {\r\n constructor(name:string) {\r\n super(name);\r\n }\r\n catchMouse():void {\r\n console.log(this.name + \"在抓老鼠\")\r\n }\r\n}\r\n\r\n// 判断类型之后\r\nfunction leaveHome(animal: Animal) {\r\n if(animal instanceof Dog) {\r\n let dog = animal as Dog;\r\n dog.doorkeeper();\r\n }else if(animal instanceof Cat) {\r\n let cat = animal as Cat;\r\n cat.catchMouse();\r\n }\r\n}\r\n\r\nleaveHome(new Cat(\'小花\'));\r\n```\r\n\r\n# 类型别名\r\n\r\n类型别名用来给一个类型起个新名字。\r\n\r\n```typescript\r\ntype Name = string;\r\ntype NameResolver = () => string;\r\ntype NameOrResolver = Name | NameResolver;\r\nfunction getName(n: NameOrResolver): Name {\r\n if (typeof n === \'string\') {\r\n return n;\r\n } else {\r\n return n();\r\n }\r\n}\r\n```\r\n\r\n上例中,我们使用 type 创建类型别名。类型别名常用于联合类型,将多个类型封装进一个类型中', 32, 1, 2, 4, 0, 0, 0, 0, NULL, NULL, '2024-04-30 17:30:15', '2024-04-30 17:30:15', 0, 0, 'javascript,TypeScript');
INSERT INTO `ams_article` VALUES (2, 3, 8, '标题撒大大标题撒大大标helloworld题撒大大啊实打实大啊实打实大师', 'http://localhost:8128/img/article/20240501180023A002.png', '电风扇', '# 什么是TypeScript\r\n\r\nTypeScript于2012年10月由微软推出上线,始于JavaScript,看名字就知道TypeScript主要强调了类型,TypeScript在JaaScript基础上增加**类型系统**,JavaScript是一个弱类型语言,在编译期间声明的变量可以是任意类型,会导致运行时可能出现的类型错误,使用TypeScript之后可以指定变量类型,如果出现类型问题在编译期间就可以暴露出来,更容易查bug。\r\n最终TypScript又归于JavaScript,运行时其实还是将TypeScript转译成JavaScript执行,因为浏览器,node环境只能运行JavaScript。\r\n\r\n# 安装TypeScript\r\n\r\n首先确保您的电脑上安装了node,建议安装nodejs18以上版本。可点击链接进入[node下载地址](https://www.nodejs.com.cn/)。\r\nTypeScript需要编译为JavaScript文件执行,所以需要先安装TypeScript环境,可以将TypeScipt文件编译为JavaScript在浏览器或者node环境中运行。首先同时按下win + r键输入cmd唤起命令窗口\r\n**安装命令:**\r\n\r\n```shell\r\n# 全局安装typescript\r\nnpm install -g typescript\r\n```\r\n\r\n![image.png](http://localhost:8128/img/article/20240501180023A002.png)\r\n安装之后TypeScript的执行命令为tsc,比如想要查看TypeScript版本则可输入:\r\n\r\n```shell\r\ntsc -version\r\n```\r\n\r\n# HelloWorld\r\n\r\n## 创建文件\r\n\r\n写JavaScript时,文件后缀为.js。写TypeScript时文件后缀名为.ts。可以打开任意的编辑器整活,此处我使用VsCode开搞。以声明sting类型变量为例:\r\n\r\n```typescript\r\n// 变量title后边加上:string。指定为string类型,修改变量值时就只能是string类型\r\nlet title:string = \"Hello TypeScript\";\r\n\r\nconsole.log(title);\r\n```\r\n\r\n![image.png](http://localhost:8128/img/article/20240501180023A002.png)\r\n所以说ts声明变量的语法为:\r\n\r\n```javascript\r\n变量修饰符 变量名 : 数据类型 = 初始化值;\r\n如:var/let/const vag:number = 123;\r\n```\r\n\r\n## 编译\r\n\r\n将ts文件编译为js文件执行,使用tsc命令即可命令\r\n\r\n```shell\r\ntsc 01-hellosworld.ts\r\n```\r\n\r\n执行之后会在同级目录下生成一个同名的js文件\r\n![image.png](http://localhost:8128/img/article/20240501180023A002.png)\r\n\r\n## 执行\r\n\r\n使用node命令或者通过浏览器打开js文件来执行,如果使用node执行则使用nod命令:\r\n\r\n```shell\r\nnode 01-hellosworld.js\r\n```\r\n\r\n![image.png](http://localhost:8128/img/article/20240501180023A002.png)\r\n\r\n## 快速执行\r\n\r\n安装ts-node包实现快速运行ts,其实内部还是将ts转为js执行,底层逻辑不变,只是简化了开发人员操作。\r\n**安装命令:**\r\n\r\n```shell\r\nnpm install -g ts-node\r\n```\r\n\r\n**执行ts文件:**\r\n\r\n```shell\r\nts-node 01-hellosworld.ts\r\n```\r\n\r\n此时就不会再生成js文件啦。**但是执行的还是js哦,这是一定要记清楚的。**\r\n\r\n## 修改类型\r\n\r\n尝试将title修改为数字类型数据,如果在javascript中是可行的,类型可随意修改,在typescript中,如果修改数据类型在编译期就会报错\r\n![image.png](http://localhost:8128/img/article/20240501180023A002.png)\r\n那么忽略编辑器的报错,尝试运行会返回TSError错误,错误信息是编译TypeScript时出现问题。\r\n![image.png](http://localhost:8128/img/article/20240501180023A002.png)\r\n此处可以看出TypeScript相较于JavaScript对类型要求更严格,这也是很多开发人员吐槽的地方,以前写js\r\n随心所欲,随便定义一个变量,下边想怎么改都成,使用了ts之后只能修改值为对应类型的,好像添加了束缚,但我觉得这是好事:\r\n\r\n- 首先数据类型在逻辑处理中其实就应该输入同一个类型内的修改,严格来说是不可以将字符串类型修改为数字类型等,甚至是对象类型的数据。\r\n- 在复杂的业务处理中,甚至有时候都已经忘记了一个变量是什么类型的了😛。\r\n\r\n# TypeScript优势\r\n\r\nTypeScript包含JavaScript所有功能,同时又增加了类型系统,弥补了JavaScript弱类型的缺陷,那么为什么是缺陷呢?在ES6中JavaScript又推出了很多新的API,方便处理数据,这些api有的是字符串才能使用的,有的是数组才能使用的,有的是数字才能使用的,而JavaScript在编译时并不会检查当前变量是什么类型,能否使用调用的方法,在运行时就会出现错误。甚至会导致严重的线上bug。比如:\r\n\r\n```javascript\r\nlet arr = [1,2,3,4,5,6,7];\r\n\r\n// 将数组转为数字类型\r\narr = 1;\r\n// 调用filter方法,获取大于4的数据,此方法number类型肯定不能调用,但编译期并不会提示\r\nlet result = arr.filter(item => item > 4);\r\nconsole.log(result);\r\n\r\n```\r\n\r\n运行时就会出现TypeError即类型错误。\r\n![image.png](http://localhost:8128/img/article/20240501180023A002.png)\r\n以上错误在开发工作中比比皆是,不要妄图以为脑子好用能记住所有变量的数据类型,有时候你甚至不知道用户传过来的是什么类型的数据,所以在定义变量和方法参数时,设置明确的类型势在必行。\r\n\r\n# 数据类型\r\n\r\nTypeScript是JavaScript的扩充,所以包含JavaScript中的所有数据类型,同时又增加了若干个数据类型。下表列出TypeScript中所有的数据类型,不区分JS和TS,没有什么实际意义:\r\n\r\n| 数据类型 | 作用 |\r\n| ------------------ | ------------------------------------------------------------ |\r\n| number:数字类型 | 双精度 64 位浮点值。它可以用来表示整数和分数 |\r\n| string:字符串类型 | 描述字符或字符串,使用单引号(\')或双引号(\")来表示字符串类型。反引号(`)来定义多行文本和内嵌表达式。 |\r\n| boolean:布尔类型 | 表示逻辑值:true 和 false。 |\r\n| Object:对象 | 对象类型包括,数组、对象、函数 |\r\n| 元组 | 元组类型用来表示已知元素数量和类型的数组,各元素的类型不必相同,对应位置的类型需要相同。 |\r\n| enum:枚举 | 枚举类型用于定义数值集合。 |\r\n| any:任意类型 | 声明为 any 的变量可以赋予任意类型的值。 |\r\n| null | 表示对象值缺失。 |\r\n| undefined | 用于初始化变量为一个未定义的值 |\r\n| void | 用于标识方法返回值的类型,表示该方法没有返回值。 |\r\n| symbol | 用来声明唯一值,解决命名冲突问题 |\r\n| never | 其它类型(包括 null 和 undefined)的子类型,代表从不会出现的值。 |\r\n\r\n## number\r\n\r\n前端的JavaScript和TypeScript中没有整数和小数之分,数字类型统一使用number表示,可以使用各种进制实例化一个数字,写法如下:\r\n\r\n```typescript\r\n// 使用十进制表示\r\nlet num1: number = 6;\r\n// 十六进制\r\nlet num2: number = 0xf00d;\r\n// ES6 中的二进制表示法\r\nlet num3: number = 0b1010;\r\n// ES6 中的八进制表示法\r\nlet num4: number = 0o744;\r\n// 非数字\r\nlet num5: number = NaN;\r\n// 无穷值\r\nlet infinityNumber: number = Infinity;\r\n// 使用构造\r\nlet num1 : number = Number(1);\r\n// 使用JS中对象类型表示类型\r\nlet num2 : Number = 123;\r\n```\r\n\r\n其他数据类型都相同,可以使用构造方法初始化值,使用对象类型标识数据类型\r\n\r\n## string\r\n\r\n字符串可以通过单引号\'\'、双引号\"\"和模板字符串``创建\r\n\r\n```typescript\r\nlet s1 : string = \'单引号字符串\';\r\n\r\nlet s2 : string = \"双引号字符串\";\r\n\r\nlet s3 : string = `第一个${s1},第二个${s2}`;\r\n\r\nlet s4 : string = String(\"对象字符串\");\r\n```\r\n\r\n模板字符串可以使用${变量}方式引用变量\r\n\r\n## boolean\r\n\r\n布尔类型的值用来表示对【true】或者错【false】,在TypeScript中使用boolean表示:\r\n\r\n```typescript\r\nlet age : number = 123;\r\n\r\nlet username : string = \"username\";\r\n\r\nlet isMan : boolean = true;\r\n\r\n// 下方是错误的,new Boolean是对象类型\r\n// let isDog : boolean = new Boolean(true);\r\n\r\n// 可以直接使用Boolean()\r\nlet isDog : boolean = Boolean(true);\r\n```\r\n\r\n## 任意值\r\n\r\n可以通过使用any表示变量可以是任意类型数据,使用any效果和JavaScript相同,后期可以修改变量数据类型\r\n\r\n```typescript\r\n// any类型,初始值为string\r\nlet a1 : any = \"a1\";\r\n// 修改为number类型\r\na1 = 123;\r\n```\r\n\r\n## 类型推断\r\n\r\nTypeScript支持像JavaScript那样不显示声明数据类型,会根据赋值自动推断类型,后期则不可修改值为其他类型的数据\r\n\r\n```typescript\r\n// 类型自动推断为string\r\nlet username = \'张三\';\r\n// Type \'number\' is not assignable to type \'string\'\r\nusername = 123;\r\n```\r\n\r\n## null和undefined\r\n\r\nnull和undefined也可以被当做数据类型来定义\r\n\r\n```typescript\r\nlet nu : null = null;\r\n\r\nlet un : undefined = undefined;\r\n```\r\n\r\nnull是一个对象/变量的值为null,而undefined则表示该变量没有初始化。\r\n\r\n## void\r\n\r\nvoid为空值,是TypeScript中新增的数据类型,表示没有任何返回值的函数\r\n\r\n```typescript\r\nfunction say(): void {\r\n alert(\'我是张三\');\r\n}\r\n\r\nsay();\r\n```\r\n\r\n有些地方会比较,深究null、undefined、void区别,我认为并没有意义,null就是一个对象为空值,undefined就是没有初始值,void用来表示方法没有返回值,不要去描述变量。仅此而已不要再做无谓的深究!\r\n\r\n## 联合类型\r\n\r\n联合类型是该变量可以在声明的类型中随意匹配一个即可,比如年龄可以使用数字表示,也可以使用字符串表示,可以通过** | **符号分割多个类型\r\n\r\n```typescript\r\nlet age : number | string = \'十六\';\r\nage = 16;\r\n```\r\n\r\n如果使用联合类型表示一个变量,此时在操作变量时需要使用共有属性和方法,不能使用某一个类型特有的方法或属性,比如age可以为number或者string类型,number类型有toFixed方法,而string没有,number和string共有的操作有**toString**、**valueOf**方法。\r\n\r\n```typescript\r\nlet age : number | string = \'十六\'\r\nage = 16\r\n// 共有方法\r\nage.toString();\r\n// string有此方法,如果数字调用出现,Property \'length\' does not exist on type \'number\'\r\nage.length;\r\n```\r\n\r\n或者使用**typeof**判断类型之后使用\r\n\r\n```typescript\r\nlet age : number | string = 12\r\n\r\nif(typeof age === \'number\') {\r\n console.log(\"数字类型\")\r\n}\r\n\r\nif(typeof age === \'string\') {\r\n console.log(\"字符串类型\")\r\n}\r\n```\r\n\r\n## 数组\r\n\r\n```typescript\r\n// 通过类型[]方式指定,下例:数组中只允许有number类型数据\r\nlet a1 : number[] = [1,2,3,4];\r\n// 通过泛型指定,Array<类型>,下例:只允许有字符串\r\nlet nameArr : Array<string> = [\'大毛\',\'二毛\',\'小明\'];\r\n```\r\n\r\n## 元组\r\n\r\n元组和数组区别在于,元组中可以存在不同类型的数据。\r\n\r\n```typescript\r\n// 数据类型必须与索引一一匹配\r\nlet a1 : [number,string,number] = [1,\'a\',2];\r\n\r\n// 先声明,再赋值\r\nlet person1: [string, number];\r\nperson1 = [\'大毛\', 25];\r\n\r\n// 获取一项\r\nlet username : string = person1[0];\r\nlet age : number = person1[1];\r\n\r\n// 操作数据\r\nconsole.log(username.indexOf(\"大\"))\r\nconsole.log(age.toFixed(2));\r\n```\r\n\r\n添加越界元素时【元组本身2个元素长度,新增其他数据长度会增加,称为添加越界元素】,它的类型会被限制为元组中每个类型的联合类型:\r\n\r\n```typescript\r\n// 先声明,再赋值\r\nlet person1: [string, number] = [\'大毛\', 25];\r\n\r\nperson1.push(\"123\");\r\nperson1.push(123);\r\n\r\n// Argument of type \'boolean\' is not assignable to parameter of type \'string | number\'.\r\nperson1.push(true);\r\n```\r\n\r\n如果元组中存在可选值时可以在类型后添加?表示,如下\r\n\r\n```typescript\r\n// number类型的值可写可不写,添加?即可\r\nlet person1: [string, number?] = [\'大毛\'];\r\n```\r\n\r\n## 枚举\r\n\r\n枚举(Enum)类型用于取值被限定在一定范围内的场景,比如订单状态为未付款、待发货、待收货、待评价,性别限定为男、女、未知等。\r\n枚举成员会被赋值为从 0 开始递增的数字,同时也会对枚举值到枚举名进行反向映射:\r\n\r\n```typescript\r\nenum OrderStatus {NO_PAY, SHIPPED, RECEIVED, EVALUATED,REVIEWED};\r\n\r\n// 使用\r\nconsole.log(OrderStatus[\'NO_PAY\'] === 0);\r\nconsole.log(OrderStatus[\'SHIPPED\'] === 1);\r\nconsole.log(OrderStatus[\'RECEIVED\'] === 2);\r\n\r\nconsole.log(OrderStatus[0] === \'NO_PAY\');\r\nconsole.log(OrderStatus[1] === \'SHIPPED\');\r\nconsole.log(OrderStatus[2] === \'RECEIVED\');\r\n```\r\n\r\n你还可以通过手动赋值修改默认以0递增的数据\r\n\r\n```typescript\r\nenum OrderStatus {NO_PAY = 1, SHIPPED = 2, RECEIVED = 3, EVALUATED,REVIEWED};\r\n\r\n// 使用\r\nconsole.log(OrderStatus[\'NO_PAY\']);\r\nconsole.log(OrderStatus[\'SHIPPED\']);\r\nconsole.log(OrderStatus[\'RECEIVED\']);\r\nconsole.log(OrderStatus[\'EVALUATED\']);\r\nconsole.log(OrderStatus[\'REVIEWED\']);\r\n```\r\n\r\n## 函数\r\n\r\nTypeScript中声明函数可以在形式参数和返回值中指定数据类型。\r\n\r\n```typescript\r\n// 接收number类型参数,返回number类型参数\r\nfunction fun1(num1 : number,num2 : number) : number {\r\n\r\n return num1 + num2;\r\n}\r\nconsole.log(fun1(1,2));\r\n```\r\n\r\n也支持通过函数表达式【Function Expression】的方式声明函数\r\n\r\n```typescript\r\nlet fun2 = function(str1 : string,str2 : string) : string {\r\n\r\n return str1.concat(str2);\r\n}\r\n\r\nconsole.log(fun2(\'A\',\'B\'));\r\n```\r\n\r\n函数同样支持**可选参数**,当然可选参数必须在最后\r\n\r\n```typescript\r\nfunction buildName(firstName: string, lastName?: string) {\r\n if (lastName) {\r\n return firstName + \' \' + lastName;\r\n } else {\r\n return firstName;\r\n }\r\n}\r\nlet tomcat = buildName(\'Tom\', \'Cat\');\r\nlet tom = buildName(\'Tom\');\r\n```\r\n\r\n如果没有返回值,则可以使用**void**修饰返回值类型,无返回值时接收到的为**undefined**\r\n\r\n```typescript\r\nfunction fun1(firstName: string):void {\r\n console.log(firstName.toUpperCase());\r\n}\r\nlet result = fun1(\'Tom\');\r\nconsole.log(result);\r\n```\r\n\r\nES6中允许方法参数有默认值,**TypeScript 会将添加了默认值的参数识别为可选参数**:\r\n\r\n```typescript\r\nfunction buildName(firstName: string, lastName: string = \'Cat\') {\r\n return firstName + \' \' + lastName;\r\n}\r\nlet tomcat = buildName(\'Tom\', \'Cat\');\r\nlet tom = buildName(\'Tom\');\r\n```\r\n\r\n此时就不受「可选参数必须接在必需参数后面」的限制了:\r\n\r\n```typescript\r\nfunction buildName(firstName: string = \'Tom\', lastName: string) {\r\n return firstName + \' \' + lastName;\r\n}\r\nlet tomcat = buildName(\'Tom\', \'Cat\');\r\nlet cat = buildName(undefined, \'Cat\');\r\n```\r\n\r\nES6中可以使用 **...rest** 的方式获取函数中的剩余参数(rest 参数):\r\n\r\n```typescript\r\nfunction push(array, ...items) {\r\n items.forEach(function(item) {\r\n array.push(item);\r\n });\r\n}\r\n\r\nlet a: any[] = [];\r\npush(a, 1, 2, 3);\r\n```\r\n\r\n事实上,items 是一个数组。所以我们可以用数组的类型来定义它:\r\n\r\n```typescript\r\nfunction push(array: any[], ...items: any[]) {\r\n items.forEach(function(item) {\r\n array.push(item);\r\n });\r\n}\r\n\r\nlet a = [];\r\npush(a, 1, 2, 3);\r\n```\r\n\r\n注意,rest 参数只能是最后一个参数\r\n\r\n## 接口\r\n\r\n接口用来定义一种规范,具体的时候交由对象来做,举个生活中的例子我们购买商品按照消费者权益来说所有的商品都必须有售后保障,那么具体怎么实现售后,你是上门维修也好,直接换货也好,就有厂家自己实现。这个必须有售后就是规范,各个厂家就是一个一个具体的对象,交由对象实现就行了。\r\n程序中就是我们希望在程序内描述一个人,那么人的规范就是有名字、性别、年龄和一些行为这可以通过接口描述,具体是哪一个人,就交由对象来具体化【实例化】。\r\n\r\n```typescript\r\n// 接口定义抽象结构\r\ninterface Person {\r\n username: string;\r\n age: number;\r\n say():void;\r\n}\r\n// 对象具体实现\r\nlet tom: Person = {\r\n username: \'张三\',\r\n age: 25,\r\n say() : void {\r\n console.log(this.username)\r\n }\r\n};\r\n```\r\n\r\n### 可选属性\r\n\r\n有时认为一个对象的某个属性可有可无,可以使用可选属性\r\n\r\n```typescript\r\ninterface Person {\r\n name: string;\r\n age?: number;\r\n}\r\n\r\nlet p1: Person = {\r\n name: \'大毛\'\r\n};\r\nlet p2: Person = {\r\n name: \'小毛\',\r\n age: 25\r\n};\r\n```\r\n\r\n### 任意属性\r\n\r\n又是我们希望可以在对象中添加任意的属性:\r\n\r\n```typescript\r\ninterface Person {\r\n name: string;\r\n age?: number;\r\n [propName: string]: any;\r\n}\r\n\r\nlet tom: Person = {\r\n name: \'大毛\',\r\n gender: \'男\',\r\n};\r\n```\r\n\r\n任意属性的类型需要包含可选属性,否则编译报错,比如any包含number类型,如果将any换成string,则age可选属性就会报错\r\n\r\n### 只读属性\r\n\r\n有时候我们希望对象中的一些字段在创建的时候被赋值后就不可更改,那么可以用 readonly 定义只读属性:\r\n\r\n```typescript\r\ninterface IBook {\r\n readonly author: string;\r\n bookname: string;\r\n}\r\n\r\nlet book1: IBook = {\r\n author: \'小明\',\r\n bookname: \'TypeScript养成记\',\r\n};\r\n\r\nbook1.author = \'大毛\';\r\n```\r\n\r\n## 类\r\n\r\nES6中JavaScript引入了类的概念,类也是用来定义事物的抽象,交由对象具体实现,在面向对象的语言中,对于类我们应该熟知这么几个概念:\r\n\r\n- 类(Class):定义了一件事物的抽象特点,包含它的属性和方法\r\n- 对象(Object):类的实例,通过 new 生成\r\n- 面向对象(OOP)的三大特性:封装、继承、多态\r\n- 封装(Encapsulation):将对数据的操作细节隐藏起来,只暴露对外的接口。外界调用端不需要(也不可能)知道细节,就能通过对外提供的接口来访问该对象,同时也保证了外界无法任意更改对象内部的数据\r\n- 继承(Inheritance):子类继承父类,子类除了拥有父类的所有特性外,还有一些更具体的特性\r\n- 多态(Polymorphism):由继承而产生了相关的不同的类,对同一个方法可以有不同的响应。比如 Cat 和 Dog 都继承自 Animal,但是分别实现了自己的 eat 方法。此时针对某一个实例,我们无需了解它是 Cat 还是 Dog,就可以直接调用 eat 方法,程序会自动判断出来应该如何执行 eat\r\n- 存取器(getter & setter):用以改变属性的读取和赋值行为\r\n- 修饰符(Modifiers):修饰符是一些关键字,用于限定成员或类型的性质。比如 public 表示公有属性或方法\r\n- 抽象类(Abstract Class):抽象类是供其他类继承的基类,抽象类不允许被实例化。抽象类中的抽象方法必须在子类中被实现\r\n- 接口(Interfaces):不同类之间公有的属性或方法,可以抽象成一个接口。接口可以被类实现(implements)。一个类只能继承自另一个类,但是可以实现多个接口\r\n\r\n### TypeScript中的类\r\n\r\nTypeScript 可以使用三种访问修饰符(Access Modifiers),分别是 public、private 和 protected。\r\n\r\n- public 修饰的属性或方法是公有的,可以在任何地方被访问到,默认所有的属性和方法都是 public 的\r\n- private 修饰的属性或方法是私有的,不能在声明它的类的外部访问\r\n- protected 修饰的属性或方法是受保护的,它和 private 类似,区别是它在子类中也是允许被访问的\r\n\r\n比如创建一个动物类,实例化一个狗\r\n\r\n```typescript\r\nclass Animal {\r\n public name;\r\n public constructor(name:string) {\r\n this.name = name;\r\n }\r\n}\r\n\r\nlet a = new Animal(\'大黄\');\r\nconsole.log(a.name); // 大黄\r\na.name = \'小黑\';\r\nconsole.log(a.name); // 小黑\r\n```\r\n\r\n上述可以直接修改和获取数据,对于对象数据来说是不安全的,可以通过private或者protected提高安全性。\r\n\r\n### private修饰属性\r\n\r\n使用private修饰将属性私有化,属性只能在类内部直接调用,如果要修改数据和获取数据可以通过公开的方法获取\r\n\r\n```typescript\r\nclass Animal {\r\n private name;\r\n public constructor(name:string) {\r\n this.name = name;\r\n }\r\n\r\n public getName():string {\r\n return this.name;\r\n }\r\n\r\n public setName(name:string):string {\r\n return this.name = name;\r\n }\r\n}\r\n\r\nlet a = new Animal(\'大黄\');\r\nconsole.log(a.getName()); // 大黄\r\na.setName(\'小黑\');\r\nconsole.log(a.getName()); // 小黑\r\n```\r\n\r\n### protected修饰属性\r\n\r\n被private修饰,包括子类在内都不被允许访问,只有本类内部可以访问,如果希望子类可以访问则可以使用protected修饰\r\n\r\n```typescript\r\nclass Animal {\r\n protected name;\r\n public constructor(name:string) {\r\n this.name = name;\r\n }\r\n\r\n public getName():string {\r\n return this.name;\r\n }\r\n\r\n public setName(name:string):string {\r\n return this.name = name;\r\n }\r\n}\r\n\r\nclass Dog extends Animal {\r\n constructor(name:string) {\r\n super(name);\r\n // name属性被继承过来\r\n console.log(this.name);\r\n }\r\n}\r\n```\r\n\r\n### private修饰构造方法\r\n\r\n如果构造方法通过private修饰被私有化,则该类不能被实例化,也不能被继承\r\n\r\n```typescript\r\nclass Animal {\r\n protected name;\r\n // 私有化构造方法\r\n private constructor(name:string) {\r\n this.name = name;\r\n }\r\n\r\n public getName():string {\r\n return this.name;\r\n }\r\n\r\n public setName(name:string):string {\r\n return this.name = name;\r\n }\r\n}\r\n\r\n// 继承就会报错\r\n// Cannot extend a class \'Animal\'. Class constructor is marked as private\r\nclass Dog extends Animal {\r\n constructor(name:string) {\r\n super(name);\r\n // name属性被继承过来\r\n console.log(this.name);\r\n }\r\n}\r\n```\r\n\r\n### protected 修饰构造方法\r\n\r\n如果构造函数修饰为 protected 时,该类不能实例化\r\n\r\n```typescript\r\nclass Animal {\r\n protected name;\r\n // protected修饰\r\n protected constructor(name:string) {\r\n this.name = name;\r\n }\r\n\r\n public getName():string {\r\n return this.name;\r\n }\r\n\r\n public setName(name:string):string {\r\n return this.name = name;\r\n }\r\n}\r\n// 继承没毛病\r\nclass Dog extends Animal {\r\n constructor(name:string) {\r\n super(name);\r\n // name属性被继承过来\r\n console.log(this.name);\r\n }\r\n}\r\n// 实例化有问题\r\n// Constructor of class \'Animal\' is protected and only accessible within the class declaration\r\nlet a = new Animal(\'大黄\');\r\n```\r\n\r\n### 参数属性\r\n\r\n类中属性可以定义在构造方法上,等同于类中定义了属性\r\n\r\n```typescript\r\nclass Animal {\r\n // 参数属性\r\n public constructor(public name:string) {\r\n }\r\n}\r\n\r\nlet a = new Animal(\"大黄\");\r\nconsole.log(a.name)\r\n```\r\n\r\n### readonly\r\n\r\n只读属性关键字也可用于类中,只允许出现在属性声明或索引签名或构造函数中。\r\n\r\n```typescript\r\nclass Animal {\r\n // 只读属性\r\n readonly name;\r\n public constructor(name:string) {\r\n this.name = name;\r\n }\r\n}\r\n\r\nlet a = new Animal(\'大黄\');\r\nconsole.log(a.name);\r\n// 不可再次修改\r\na.name = \'小黑\';\r\n```\r\n\r\n注意如果 readonly 和其他访问修饰符同时存在的话,需要写在其后面。\r\n\r\n```typescript\r\nclass Animal {\r\n // public readonly name;\r\n public constructor(public readonly name:string) {\r\n // this.name = name;\r\n }\r\n}\r\n```\r\n\r\n### 抽象类\r\n\r\n抽象类不能被实例化,使用abstract修饰\r\n\r\n```typescript\r\nabstract class Animal {\r\n public name;\r\n public constructor(name:string) {\r\n this.name = name;\r\n }\r\n public abstract sayHi():any;\r\n}\r\n// Cannot create an instance of an abstract class.\r\nlet a = new Animal(\'大黄\');\r\n```\r\n\r\n抽象类中的抽象方法必须被子类实现,子类必须实现抽象类中的所有抽象方法,否则需要继续抽象下去:\r\n\r\n```typescript\r\nabstract class Animal {\r\n public name;\r\n public constructor(name:string) {\r\n this.name = name;\r\n }\r\n public abstract eat():any;\r\n}\r\n\r\nclass Cat extends Animal {\r\n public eat() {\r\n console.log(`${this.name} 在吃鱼.`);\r\n }\r\n}\r\n\r\nlet c = new Cat(\'小花\');\r\nc.eat();\r\n```\r\n\r\n如果没有实现所有抽象方法则继续报错:\r\n\r\n```typescript\r\nabstract class Animal {\r\n public name;\r\n public constructor(name:string) {\r\n this.name = name;\r\n }\r\n public abstract eat():any;\r\n public abstract sayHi():any;\r\n}\r\n\r\n// Non-abstract class \'Cat\' does not implement all abstract members of \'Animal\'\r\nclass Cat extends Animal {\r\n public eat() {\r\n console.log(`${this.name} 在吃鱼.`);\r\n }\r\n}\r\n```\r\n\r\n## 泛型\r\n\r\n泛型(Generics)是指在定义函数、接口或类的时候,不预先指定具体的类型,而在使用的时候再指定类型的一种特性。\r\n\r\n### 无泛型\r\n\r\n实现一个函数 createArray,它可以创建一个指定长度的数组,同时将每一项都填充一个默认值:\r\n\r\n```typescript\r\nfunction createArray(length: number, value: any): Array<any> {\r\n let result = [];\r\n for (let i = 0; i < length; i++) {\r\n result[i] = value;\r\n }\r\n return result;\r\n}\r\n\r\ncreateArray(3, \'x\'); // [\'x\', \'x\', \'x\']\r\n```\r\n\r\n此处使用any当做入参和Array<any>反参类型,编译不会报错,但是可能会造成类型不安全的问题,调用方法的用户可能瞎传数据,你的方法就报错啦。此时泛型就登场了,**解决参数类型安全问题**\r\n\r\n```typescript\r\nfunction createArray<T>(length: number, value: T): Array<T> {\r\n let result: T[] = [];\r\n for (let i = 0; i < length; i++) {\r\n result[i] = value;\r\n }\r\n return result;\r\n}\r\n\r\ncreateArray<string>(3, \'x\'); // [\'x\', \'x\', \'x\']\r\n```\r\n\r\n上例中,我们在函数名后添加了 <T>,其中 T 用来指代任意输入的类型,在后面的输入 value: T 和输出 Array<T> 中即可使用了。\r\n接着在调用的时候,可以指定它具体的类型为 string。当然,也可以不手动指定,而让类型推论自动推算出来:\r\n\r\n```typescript\r\nfunction createArray<T>(length: number, value: T): Array<T> {\r\n let result: T[] = [];\r\n for (let i = 0; i < length; i++) {\r\n result[i] = value;\r\n }\r\n return result;\r\n}\r\n\r\ncreateArray(3, \'x\'); // [\'x\', \'x\', \'x\']\r\n```\r\n\r\n### 多个类型参数\r\n\r\n定义泛型的时候,可以一次定义多个类型参数:\r\n\r\n```typescript\r\nfunction swap<T, U>(tuple: [T, U]): [U, T] {\r\n return [tuple[1], tuple[0]];\r\n}\r\n\r\nswap([7, \'seven\']); // [\'seven\', 7]\r\n```\r\n\r\n### 泛型约束\r\n\r\n在函数内部使用泛型变量的时候,由于事先不知道它是哪种类型,所以不能随意的操作它的属性或方法:\r\n\r\n```typescript\r\nfunction loggingIdentity<T>(arg: T): T {\r\n console.log(arg.length);\r\n return arg;\r\n}\r\n```\r\n\r\n上例中,泛型 T 不一定包含属性 length,所以编译的时候报错了。\r\n这时,我们可以对泛型进行约束,只允许这个函数传入那些包含 length 属性的变量。这就是泛型约束:\r\n\r\n```typescript\r\ninterface Lengthwise {\r\n length: number;\r\n}\r\n\r\nfunction loggingIdentity<T extends Lengthwise>(arg: T): T {\r\n console.log(arg.length);\r\n return arg;\r\n}\r\n```\r\n\r\n上例中,我们使用了 extends 约束了泛型 T 必须符合接口 Lengthwise 的形状,也就是必须包含 length 属性。\r\n此时如果调用 loggingIdentity 的时候,传入的 arg 不包含 length,那么在编译阶段就会报错了:\r\n\r\n```typescript\r\ninterface Lengthwise {\r\n length: number;\r\n}\r\n\r\nfunction loggingIdentity<T extends Lengthwise>(arg: T): T {\r\n console.log(arg.length);\r\n return arg;\r\n}\r\n\r\nloggingIdentity(7);\r\n```\r\n\r\n多个类型参数之间也可以互相约束:\r\n\r\n```typescript\r\nfunction copyFields<T extends U, U>(target: T, source: U): T {\r\n for (let id in source) {\r\n target[id] = (<T>source)[id];\r\n }\r\n return target;\r\n}\r\n\r\nlet x = { a: 1, b: 2, c: 3, d: 4 };\r\n\r\ncopyFields(x, { b: 10, d: 20 });\r\n```\r\n\r\n上例中,我们使用了两个类型参数,其中要求 T 继承 U,这样就保证了 U 上不会出现 T 中不存在的字段。\r\n\r\n### 泛型接口\r\n\r\n泛型也可以用来定义接口\r\n\r\n```typescript\r\ninterface CreateArrayFunc {\r\n <T>(length: number, value: T): Array<T>;\r\n}\r\n\r\nlet createArray: CreateArrayFunc;\r\ncreateArray = function<T>(length: number, value: T): Array<T> {\r\n let result: T[] = [];\r\n for (let i = 0; i < length; i++) {\r\n result[i] = value;\r\n }\r\n return result;\r\n}\r\n\r\ncreateArray(3, \'x\'); // [\'x\', \'x\', \'x\']\r\n```\r\n\r\n进一步,我们可以把泛型参数提前到接口名上:\r\n\r\n```typescript\r\ninterface CreateArrayFunc<T> {\r\n (length: number, value: T): Array<T>;\r\n}\r\n\r\nlet createArray: CreateArrayFunc<any>;\r\ncreateArray = function<T>(length: number, value: T): Array<T> {\r\n let result: T[] = [];\r\n for (let i = 0; i < length; i++) {\r\n result[i] = value;\r\n }\r\n return result;\r\n}\r\n\r\ncreateArray(3, \'x\'); // [\'x\', \'x\', \'x\']\r\n```\r\n\r\n注意,此时在使用泛型接口的时候,需要定义泛型的类型。\r\n\r\n### 泛型类\r\n\r\n与泛型接口类似,泛型也可以用于类的类型定义中:\r\n\r\n```typescript\r\nclass GenericNumber<T> {\r\n zeroValue: T;\r\n add: (x: T, y: T) => T;\r\n}\r\n\r\nlet myGenericNumber = new GenericNumber<number>();\r\nmyGenericNumber.zeroValue = 0;\r\nmyGenericNumber.add = function(x, y) { return x + y; };\r\n```\r\n\r\n### 泛型参数的默认类型\r\n\r\n在 TypeScript 2.3 以后,我们可以为泛型中的类型参数指定默认类型。当使用泛型时没有在代码中直接指定类型参数,从实际值参数中也无法推测出时,这个默认类型就会起作用。\r\n\r\n```typescript\r\nfunction createArray<T = string>(length: number, value: T): Array<T> {\r\n let result: T[] = [];\r\n for (let i = 0; i < length; i++) {\r\n result[i] = value;\r\n }\r\n return result;\r\n}\r\n```\r\n\r\n# 类型断言\r\n\r\n类型断言(Type Assertion)可以用来手动指定一个值的类型。语法为\r\n\r\n```typescript\r\n值 as 类型\r\n\r\n或\r\n \r\n<类型>值\r\n```\r\n\r\n在 tsx 语法(React 的 jsx 语法的 ts 版)中必须使用 **值 as 类型**。\r\n\r\n## 联合类型断言为一个具体类型\r\n\r\n前文介绍了支持联合类型,即一个变量可以是string类型也可以是number类型,只能访问该变量所有类型的共有属性和方法\r\n\r\n```typescript\r\nfunction fun1(args: string | number):number {\r\n // 将值断言为number类型\r\n let result = args as number;\r\n\r\n return result;\r\n}\r\n\r\nconsole.log(fun1(\"1\"))\r\n```\r\n\r\n## 将一个父类断言为更加具体的子类\r\n\r\n当类之间有继承关系时,类型断言也是很常见的:\r\n\r\n```typescript\r\nclass Animal {\r\n name: string;\r\n constructor(name:string) {\r\n this.name = name;\r\n }\r\n}\r\n\r\nclass Dog extends Animal {\r\n constructor(name:string) {\r\n super(name);\r\n }\r\n doorkeeper():void {\r\n console.log(this.name + \"在看家\")\r\n }\r\n}\r\nclass Cat extends Animal {\r\n constructor(name:string) {\r\n super(name);\r\n }\r\n catchMouse():void {\r\n console.log(this.name + \"在抓老鼠\")\r\n }\r\n}\r\n\r\n// 离家需要狗看门,也需要猫抓老鼠\r\nfunction leaveHome(animal: Animal) {\r\n let dog = animal as Dog;\r\n dog.doorkeeper();\r\n}\r\n\r\nleaveHome(new Dog(\'旺财\'));\r\n```\r\n\r\n上面的例子中,我们声明了函数 leaveHome,转为Dog类型,调用看门方法,离家时构建一个狗对象,调用它的看门方法即可。\r\n\r\n## 断言限制\r\n\r\n类型不可随意断言,比如Dog是Animal的一种,Adimal可以断言为Dog,Cat不是Dog的一种,Cat就不能断言为Dog。如下例子:\r\n\r\n```typescript\r\nclass Animal {\r\n name: string;\r\n constructor(name:string) {\r\n this.name = name;\r\n }\r\n}\r\n\r\nclass Dog extends Animal {\r\n constructor(name:string) {\r\n super(name);\r\n }\r\n doorkeeper():void {\r\n console.log(this.name + \"在看家\")\r\n }\r\n}\r\nclass Cat extends Animal {\r\n constructor(name:string) {\r\n super(name);\r\n }\r\n catchMouse():void {\r\n console.log(this.name + \"在抓老鼠\")\r\n }\r\n}\r\n\r\n// 离家需要狗看门\r\n// 如果传入类型为Cat,断言成Dog编译不会报错,但运行时就会报错\r\nfunction leaveHome(animal: Animal) {\r\n let dog = animal as Dog;\r\n dog.doorkeeper();\r\n}\r\n// 实例化一个Cat\r\nleaveHome(new Cat(\'小花\'));\r\n```\r\n\r\n可以使用**instanceof**判断类型后对数据进行断言:\r\n\r\n```typescript\r\nclass Animal {\r\n name: string;\r\n constructor(name:string) {\r\n this.name = name;\r\n }\r\n}\r\n\r\nclass Dog extends Animal {\r\n constructor(name:string) {\r\n super(name);\r\n }\r\n doorkeeper():void {\r\n console.log(this.name + \"在看家\")\r\n }\r\n}\r\nclass Cat extends Animal {\r\n constructor(name:string) {\r\n super(name);\r\n }\r\n catchMouse():void {\r\n console.log(this.name + \"在抓老鼠\")\r\n }\r\n}\r\n\r\n// 判断类型之后\r\nfunction leaveHome(animal: Animal) {\r\n if(animal instanceof Dog) {\r\n let dog = animal as Dog;\r\n dog.doorkeeper();\r\n }else if(animal instanceof Cat) {\r\n let cat = animal as Cat;\r\n cat.catchMouse();\r\n }\r\n}\r\n\r\nleaveHome(new Cat(\'小花\'));\r\n```\r\n\r\n# 类型别名\r\n\r\n类型别名用来给一个类型起个新名字。\r\n\r\n```typescript\r\ntype Name = string;\r\ntype NameResolver = () => string;\r\ntype NameOrResolver = Name | NameResolver;\r\nfunction getName(n: NameOrResolver): Name {\r\n if (typeof n === \'string\') {\r\n return n;\r\n } else {\r\n return n();\r\n }\r\n}\r\n```\r\n\r\n上例中,我们使用 type 创建类型别名。类型别名常用于联合类型,将多个类型封装进一个类型中', 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, '2024-05-01 17:59:27', '2024-05-01 17:59:27', 0, 0, 'javascript,TypeScript');
INSERT INTO `ams_article` VALUES (3, 3, 8, '标题撒大大标题撒大大标helloworld题撒大大啊实打实大啊实打实大师', 'http://localhost:8128/img/article/20240501180023A002.png', '电风扇', '# 什么是TypeScript\r\n\r\nTypeScript于2012年10月由微软推出上线,始于JavaScript,看名字就知道TypeScript主要强调了类型,TypeScript在JaaScript基础上增加**类型系统**,JavaScript是一个弱类型语言,在编译期间声明的变量可以是任意类型,会导致运行时可能出现的类型错误,使用TypeScript之后可以指定变量类型,如果出现类型问题在编译期间就可以暴露出来,更容易查bug。\r\n最终TypScript又归于JavaScript,运行时其实还是将TypeScript转译成JavaScript执行,因为浏览器,node环境只能运行JavaScript。\r\n\r\n# 安装TypeScript\r\n\r\n首先确保您的电脑上安装了node,建议安装nodejs18以上版本。可点击链接进入[node下载地址](https://www.nodejs.com.cn/)。\r\nTypeScript需要编译为JavaScript文件执行,所以需要先安装TypeScript环境,可以将TypeScipt文件编译为JavaScript在浏览器或者node环境中运行。首先同时按下win + r键输入cmd唤起命令窗口\r\n**安装命令:**\r\n\r\n```shell\r\n# 全局安装typescript\r\nnpm install -g typescript\r\n```\r\n\r\n![image.png](http://localhost:8128/img/article/20240501180023A002.png)\r\n安装之后TypeScript的执行命令为tsc,比如想要查看TypeScript版本则可输入:\r\n\r\n```shell\r\ntsc -version\r\n```\r\n\r\n# HelloWorld\r\n\r\n## 创建文件\r\n\r\n写JavaScript时,文件后缀为.js。写TypeScript时文件后缀名为.ts。可以打开任意的编辑器整活,此处我使用VsCode开搞。以声明sting类型变量为例:\r\n\r\n```typescript\r\n// 变量title后边加上:string。指定为string类型,修改变量值时就只能是string类型\r\nlet title:string = \"Hello TypeScript\";\r\n\r\nconsole.log(title);\r\n```\r\n\r\n![image.png](http://localhost:8128/img/article/20240501180023A002.png)\r\n所以说ts声明变量的语法为:\r\n\r\n```javascript\r\n变量修饰符 变量名 : 数据类型 = 初始化值;\r\n如:var/let/const vag:number = 123;\r\n```\r\n\r\n## 编译\r\n\r\n将ts文件编译为js文件执行,使用tsc命令即可命令\r\n\r\n```shell\r\ntsc 01-hellosworld.ts\r\n```\r\n\r\n执行之后会在同级目录下生成一个同名的js文件\r\n![image.png](http://localhost:8128/img/article/20240501180023A002.png)\r\n\r\n## 执行\r\n\r\n使用node命令或者通过浏览器打开js文件来执行,如果使用node执行则使用nod命令:\r\n\r\n```shell\r\nnode 01-hellosworld.js\r\n```\r\n\r\n![image.png](http://localhost:8128/img/article/20240501180023A002.png)\r\n\r\n## 快速执行\r\n\r\n安装ts-node包实现快速运行ts,其实内部还是将ts转为js执行,底层逻辑不变,只是简化了开发人员操作。\r\n**安装命令:**\r\n\r\n```shell\r\nnpm install -g ts-node\r\n```\r\n\r\n**执行ts文件:**\r\n\r\n```shell\r\nts-node 01-hellosworld.ts\r\n```\r\n\r\n此时就不会再生成js文件啦。**但是执行的还是js哦,这是一定要记清楚的。**\r\n\r\n## 修改类型\r\n\r\n尝试将title修改为数字类型数据,如果在javascript中是可行的,类型可随意修改,在typescript中,如果修改数据类型在编译期就会报错\r\n![image.png](http://localhost:8128/img/article/20240501180023A002.png)\r\n那么忽略编辑器的报错,尝试运行会返回TSError错误,错误信息是编译TypeScript时出现问题。\r\n![image.png](http://localhost:8128/img/article/20240501180023A002.png)\r\n此处可以看出TypeScript相较于JavaScript对类型要求更严格,这也是很多开发人员吐槽的地方,以前写js\r\n随心所欲,随便定义一个变量,下边想怎么改都成,使用了ts之后只能修改值为对应类型的,好像添加了束缚,但我觉得这是好事:\r\n\r\n- 首先数据类型在逻辑处理中其实就应该输入同一个类型内的修改,严格来说是不可以将字符串类型修改为数字类型等,甚至是对象类型的数据。\r\n- 在复杂的业务处理中,甚至有时候都已经忘记了一个变量是什么类型的了😛。\r\n\r\n# TypeScript优势\r\n\r\nTypeScript包含JavaScript所有功能,同时又增加了类型系统,弥补了JavaScript弱类型的缺陷,那么为什么是缺陷呢?在ES6中JavaScript又推出了很多新的API,方便处理数据,这些api有的是字符串才能使用的,有的是数组才能使用的,有的是数字才能使用的,而JavaScript在编译时并不会检查当前变量是什么类型,能否使用调用的方法,在运行时就会出现错误。甚至会导致严重的线上bug。比如:\r\n\r\n```javascript\r\nlet arr = [1,2,3,4,5,6,7];\r\n\r\n// 将数组转为数字类型\r\narr = 1;\r\n// 调用filter方法,获取大于4的数据,此方法number类型肯定不能调用,但编译期并不会提示\r\nlet result = arr.filter(item => item > 4);\r\nconsole.log(result);\r\n\r\n```\r\n\r\n运行时就会出现TypeError即类型错误。\r\n![image.png](http://localhost:8128/img/article/20240501180023A002.png)\r\n以上错误在开发工作中比比皆是,不要妄图以为脑子好用能记住所有变量的数据类型,有时候你甚至不知道用户传过来的是什么类型的数据,所以在定义变量和方法参数时,设置明确的类型势在必行。\r\n\r\n# 数据类型\r\n\r\nTypeScript是JavaScript的扩充,所以包含JavaScript中的所有数据类型,同时又增加了若干个数据类型。下表列出TypeScript中所有的数据类型,不区分JS和TS,没有什么实际意义:\r\n\r\n| 数据类型 | 作用 |\r\n| ------------------ | ------------------------------------------------------------ |\r\n| number:数字类型 | 双精度 64 位浮点值。它可以用来表示整数和分数 |\r\n| string:字符串类型 | 描述字符或字符串,使用单引号(\')或双引号(\")来表示字符串类型。反引号(`)来定义多行文本和内嵌表达式。 |\r\n| boolean:布尔类型 | 表示逻辑值:true 和 false。 |\r\n| Object:对象 | 对象类型包括,数组、对象、函数 |\r\n| 元组 | 元组类型用来表示已知元素数量和类型的数组,各元素的类型不必相同,对应位置的类型需要相同。 |\r\n| enum:枚举 | 枚举类型用于定义数值集合。 |\r\n| any:任意类型 | 声明为 any 的变量可以赋予任意类型的值。 |\r\n| null | 表示对象值缺失。 |\r\n| undefined | 用于初始化变量为一个未定义的值 |\r\n| void | 用于标识方法返回值的类型,表示该方法没有返回值。 |\r\n| symbol | 用来声明唯一值,解决命名冲突问题 |\r\n| never | 其它类型(包括 null 和 undefined)的子类型,代表从不会出现的值。 |\r\n\r\n## number\r\n\r\n前端的JavaScript和TypeScript中没有整数和小数之分,数字类型统一使用number表示,可以使用各种进制实例化一个数字,写法如下:\r\n\r\n```typescript\r\n// 使用十进制表示\r\nlet num1: number = 6;\r\n// 十六进制\r\nlet num2: number = 0xf00d;\r\n// ES6 中的二进制表示法\r\nlet num3: number = 0b1010;\r\n// ES6 中的八进制表示法\r\nlet num4: number = 0o744;\r\n// 非数字\r\nlet num5: number = NaN;\r\n// 无穷值\r\nlet infinityNumber: number = Infinity;\r\n// 使用构造\r\nlet num1 : number = Number(1);\r\n// 使用JS中对象类型表示类型\r\nlet num2 : Number = 123;\r\n```\r\n\r\n其他数据类型都相同,可以使用构造方法初始化值,使用对象类型标识数据类型\r\n\r\n## string\r\n\r\n字符串可以通过单引号\'\'、双引号\"\"和模板字符串``创建\r\n\r\n```typescript\r\nlet s1 : string = \'单引号字符串\';\r\n\r\nlet s2 : string = \"双引号字符串\";\r\n\r\nlet s3 : string = `第一个${s1},第二个${s2}`;\r\n\r\nlet s4 : string = String(\"对象字符串\");\r\n```\r\n\r\n模板字符串可以使用${变量}方式引用变量\r\n\r\n## boolean\r\n\r\n布尔类型的值用来表示对【true】或者错【false】,在TypeScript中使用boolean表示:\r\n\r\n```typescript\r\nlet age : number = 123;\r\n\r\nlet username : string = \"username\";\r\n\r\nlet isMan : boolean = true;\r\n\r\n// 下方是错误的,new Boolean是对象类型\r\n// let isDog : boolean = new Boolean(true);\r\n\r\n// 可以直接使用Boolean()\r\nlet isDog : boolean = Boolean(true);\r\n```\r\n\r\n## 任意值\r\n\r\n可以通过使用any表示变量可以是任意类型数据,使用any效果和JavaScript相同,后期可以修改变量数据类型\r\n\r\n```typescript\r\n// any类型,初始值为string\r\nlet a1 : any = \"a1\";\r\n// 修改为number类型\r\na1 = 123;\r\n```\r\n\r\n## 类型推断\r\n\r\nTypeScript支持像JavaScript那样不显示声明数据类型,会根据赋值自动推断类型,后期则不可修改值为其他类型的数据\r\n\r\n```typescript\r\n// 类型自动推断为string\r\nlet username = \'张三\';\r\n// Type \'number\' is not assignable to type \'string\'\r\nusername = 123;\r\n```\r\n\r\n## null和undefined\r\n\r\nnull和undefined也可以被当做数据类型来定义\r\n\r\n```typescript\r\nlet nu : null = null;\r\n\r\nlet un : undefined = undefined;\r\n```\r\n\r\nnull是一个对象/变量的值为null,而undefined则表示该变量没有初始化。\r\n\r\n## void\r\n\r\nvoid为空值,是TypeScript中新增的数据类型,表示没有任何返回值的函数\r\n\r\n```typescript\r\nfunction say(): void {\r\n alert(\'我是张三\');\r\n}\r\n\r\nsay();\r\n```\r\n\r\n有些地方会比较,深究null、undefined、void区别,我认为并没有意义,null就是一个对象为空值,undefined就是没有初始值,void用来表示方法没有返回值,不要去描述变量。仅此而已不要再做无谓的深究!\r\n\r\n## 联合类型\r\n\r\n联合类型是该变量可以在声明的类型中随意匹配一个即可,比如年龄可以使用数字表示,也可以使用字符串表示,可以通过** | **符号分割多个类型\r\n\r\n```typescript\r\nlet age : number | string = \'十六\';\r\nage = 16;\r\n```\r\n\r\n如果使用联合类型表示一个变量,此时在操作变量时需要使用共有属性和方法,不能使用某一个类型特有的方法或属性,比如age可以为number或者string类型,number类型有toFixed方法,而string没有,number和string共有的操作有**toString**、**valueOf**方法。\r\n\r\n```typescript\r\nlet age : number | string = \'十六\'\r\nage = 16\r\n// 共有方法\r\nage.toString();\r\n// string有此方法,如果数字调用出现,Property \'length\' does not exist on type \'number\'\r\nage.length;\r\n```\r\n\r\n或者使用**typeof**判断类型之后使用\r\n\r\n```typescript\r\nlet age : number | string = 12\r\n\r\nif(typeof age === \'number\') {\r\n console.log(\"数字类型\")\r\n}\r\n\r\nif(typeof age === \'string\') {\r\n console.log(\"字符串类型\")\r\n}\r\n```\r\n\r\n## 数组\r\n\r\n```typescript\r\n// 通过类型[]方式指定,下例:数组中只允许有number类型数据\r\nlet a1 : number[] = [1,2,3,4];\r\n// 通过泛型指定,Array<类型>,下例:只允许有字符串\r\nlet nameArr : Array<string> = [\'大毛\',\'二毛\',\'小明\'];\r\n```\r\n\r\n## 元组\r\n\r\n元组和数组区别在于,元组中可以存在不同类型的数据。\r\n\r\n```typescript\r\n// 数据类型必须与索引一一匹配\r\nlet a1 : [number,string,number] = [1,\'a\',2];\r\n\r\n// 先声明,再赋值\r\nlet person1: [string, number];\r\nperson1 = [\'大毛\', 25];\r\n\r\n// 获取一项\r\nlet username : string = person1[0];\r\nlet age : number = person1[1];\r\n\r\n// 操作数据\r\nconsole.log(username.indexOf(\"大\"))\r\nconsole.log(age.toFixed(2));\r\n```\r\n\r\n添加越界元素时【元组本身2个元素长度,新增其他数据长度会增加,称为添加越界元素】,它的类型会被限制为元组中每个类型的联合类型:\r\n\r\n```typescript\r\n// 先声明,再赋值\r\nlet person1: [string, number] = [\'大毛\', 25];\r\n\r\nperson1.push(\"123\");\r\nperson1.push(123);\r\n\r\n// Argument of type \'boolean\' is not assignable to parameter of type \'string | number\'.\r\nperson1.push(true);\r\n```\r\n\r\n如果元组中存在可选值时可以在类型后添加?表示,如下\r\n\r\n```typescript\r\n// number类型的值可写可不写,添加?即可\r\nlet person1: [string, number?] = [\'大毛\'];\r\n```\r\n\r\n## 枚举\r\n\r\n枚举(Enum)类型用于取值被限定在一定范围内的场景,比如订单状态为未付款、待发货、待收货、待评价,性别限定为男、女、未知等。\r\n枚举成员会被赋值为从 0 开始递增的数字,同时也会对枚举值到枚举名进行反向映射:\r\n\r\n```typescript\r\nenum OrderStatus {NO_PAY, SHIPPED, RECEIVED, EVALUATED,REVIEWED};\r\n\r\n// 使用\r\nconsole.log(OrderStatus[\'NO_PAY\'] === 0);\r\nconsole.log(OrderStatus[\'SHIPPED\'] === 1);\r\nconsole.log(OrderStatus[\'RECEIVED\'] === 2);\r\n\r\nconsole.log(OrderStatus[0] === \'NO_PAY\');\r\nconsole.log(OrderStatus[1] === \'SHIPPED\');\r\nconsole.log(OrderStatus[2] === \'RECEIVED\');\r\n```\r\n\r\n你还可以通过手动赋值修改默认以0递增的数据\r\n\r\n```typescript\r\nenum OrderStatus {NO_PAY = 1, SHIPPED = 2, RECEIVED = 3, EVALUATED,REVIEWED};\r\n\r\n// 使用\r\nconsole.log(OrderStatus[\'NO_PAY\']);\r\nconsole.log(OrderStatus[\'SHIPPED\']);\r\nconsole.log(OrderStatus[\'RECEIVED\']);\r\nconsole.log(OrderStatus[\'EVALUATED\']);\r\nconsole.log(OrderStatus[\'REVIEWED\']);\r\n```\r\n\r\n## 函数\r\n\r\nTypeScript中声明函数可以在形式参数和返回值中指定数据类型。\r\n\r\n```typescript\r\n// 接收number类型参数,返回number类型参数\r\nfunction fun1(num1 : number,num2 : number) : number {\r\n\r\n return num1 + num2;\r\n}\r\nconsole.log(fun1(1,2));\r\n```\r\n\r\n也支持通过函数表达式【Function Expression】的方式声明函数\r\n\r\n```typescript\r\nlet fun2 = function(str1 : string,str2 : string) : string {\r\n\r\n return str1.concat(str2);\r\n}\r\n\r\nconsole.log(fun2(\'A\',\'B\'));\r\n```\r\n\r\n函数同样支持**可选参数**,当然可选参数必须在最后\r\n\r\n```typescript\r\nfunction buildName(firstName: string, lastName?: string) {\r\n if (lastName) {\r\n return firstName + \' \' + lastName;\r\n } else {\r\n return firstName;\r\n }\r\n}\r\nlet tomcat = buildName(\'Tom\', \'Cat\');\r\nlet tom = buildName(\'Tom\');\r\n```\r\n\r\n如果没有返回值,则可以使用**void**修饰返回值类型,无返回值时接收到的为**undefined**\r\n\r\n```typescript\r\nfunction fun1(firstName: string):void {\r\n console.log(firstName.toUpperCase());\r\n}\r\nlet result = fun1(\'Tom\');\r\nconsole.log(result);\r\n```\r\n\r\nES6中允许方法参数有默认值,**TypeScript 会将添加了默认值的参数识别为可选参数**:\r\n\r\n```typescript\r\nfunction buildName(firstName: string, lastName: string = \'Cat\') {\r\n return firstName + \' \' + lastName;\r\n}\r\nlet tomcat = buildName(\'Tom\', \'Cat\');\r\nlet tom = buildName(\'Tom\');\r\n```\r\n\r\n此时就不受「可选参数必须接在必需参数后面」的限制了:\r\n\r\n```typescript\r\nfunction buildName(firstName: string = \'Tom\', lastName: string) {\r\n return firstName + \' \' + lastName;\r\n}\r\nlet tomcat = buildName(\'Tom\', \'Cat\');\r\nlet cat = buildName(undefined, \'Cat\');\r\n```\r\n\r\nES6中可以使用 **...rest** 的方式获取函数中的剩余参数(rest 参数):\r\n\r\n```typescript\r\nfunction push(array, ...items) {\r\n items.forEach(function(item) {\r\n array.push(item);\r\n });\r\n}\r\n\r\nlet a: any[] = [];\r\npush(a, 1, 2, 3);\r\n```\r\n\r\n事实上,items 是一个数组。所以我们可以用数组的类型来定义它:\r\n\r\n```typescript\r\nfunction push(array: any[], ...items: any[]) {\r\n items.forEach(function(item) {\r\n array.push(item);\r\n });\r\n}\r\n\r\nlet a = [];\r\npush(a, 1, 2, 3);\r\n```\r\n\r\n注意,rest 参数只能是最后一个参数\r\n\r\n## 接口\r\n\r\n接口用来定义一种规范,具体的时候交由对象来做,举个生活中的例子我们购买商品按照消费者权益来说所有的商品都必须有售后保障,那么具体怎么实现售后,你是上门维修也好,直接换货也好,就有厂家自己实现。这个必须有售后就是规范,各个厂家就是一个一个具体的对象,交由对象实现就行了。\r\n程序中就是我们希望在程序内描述一个人,那么人的规范就是有名字、性别、年龄和一些行为这可以通过接口描述,具体是哪一个人,就交由对象来具体化【实例化】。\r\n\r\n```typescript\r\n// 接口定义抽象结构\r\ninterface Person {\r\n username: string;\r\n age: number;\r\n say():void;\r\n}\r\n// 对象具体实现\r\nlet tom: Person = {\r\n username: \'张三\',\r\n age: 25,\r\n say() : void {\r\n console.log(this.username)\r\n }\r\n};\r\n```\r\n\r\n### 可选属性\r\n\r\n有时认为一个对象的某个属性可有可无,可以使用可选属性\r\n\r\n```typescript\r\ninterface Person {\r\n name: string;\r\n age?: number;\r\n}\r\n\r\nlet p1: Person = {\r\n name: \'大毛\'\r\n};\r\nlet p2: Person = {\r\n name: \'小毛\',\r\n age: 25\r\n};\r\n```\r\n\r\n### 任意属性\r\n\r\n又是我们希望可以在对象中添加任意的属性:\r\n\r\n```typescript\r\ninterface Person {\r\n name: string;\r\n age?: number;\r\n [propName: string]: any;\r\n}\r\n\r\nlet tom: Person = {\r\n name: \'大毛\',\r\n gender: \'男\',\r\n};\r\n```\r\n\r\n任意属性的类型需要包含可选属性,否则编译报错,比如any包含number类型,如果将any换成string,则age可选属性就会报错\r\n\r\n### 只读属性\r\n\r\n有时候我们希望对象中的一些字段在创建的时候被赋值后就不可更改,那么可以用 readonly 定义只读属性:\r\n\r\n```typescript\r\ninterface IBook {\r\n readonly author: string;\r\n bookname: string;\r\n}\r\n\r\nlet book1: IBook = {\r\n author: \'小明\',\r\n bookname: \'TypeScript养成记\',\r\n};\r\n\r\nbook1.author = \'大毛\';\r\n```\r\n\r\n## 类\r\n\r\nES6中JavaScript引入了类的概念,类也是用来定义事物的抽象,交由对象具体实现,在面向对象的语言中,对于类我们应该熟知这么几个概念:\r\n\r\n- 类(Class):定义了一件事物的抽象特点,包含它的属性和方法\r\n- 对象(Object):类的实例,通过 new 生成\r\n- 面向对象(OOP)的三大特性:封装、继承、多态\r\n- 封装(Encapsulation):将对数据的操作细节隐藏起来,只暴露对外的接口。外界调用端不需要(也不可能)知道细节,就能通过对外提供的接口来访问该对象,同时也保证了外界无法任意更改对象内部的数据\r\n- 继承(Inheritance):子类继承父类,子类除了拥有父类的所有特性外,还有一些更具体的特性\r\n- 多态(Polymorphism):由继承而产生了相关的不同的类,对同一个方法可以有不同的响应。比如 Cat 和 Dog 都继承自 Animal,但是分别实现了自己的 eat 方法。此时针对某一个实例,我们无需了解它是 Cat 还是 Dog,就可以直接调用 eat 方法,程序会自动判断出来应该如何执行 eat\r\n- 存取器(getter & setter):用以改变属性的读取和赋值行为\r\n- 修饰符(Modifiers):修饰符是一些关键字,用于限定成员或类型的性质。比如 public 表示公有属性或方法\r\n- 抽象类(Abstract Class):抽象类是供其他类继承的基类,抽象类不允许被实例化。抽象类中的抽象方法必须在子类中被实现\r\n- 接口(Interfaces):不同类之间公有的属性或方法,可以抽象成一个接口。接口可以被类实现(implements)。一个类只能继承自另一个类,但是可以实现多个接口\r\n\r\n### TypeScript中的类\r\n\r\nTypeScript 可以使用三种访问修饰符(Access Modifiers),分别是 public、private 和 protected。\r\n\r\n- public 修饰的属性或方法是公有的,可以在任何地方被访问到,默认所有的属性和方法都是 public 的\r\n- private 修饰的属性或方法是私有的,不能在声明它的类的外部访问\r\n- protected 修饰的属性或方法是受保护的,它和 private 类似,区别是它在子类中也是允许被访问的\r\n\r\n比如创建一个动物类,实例化一个狗\r\n\r\n```typescript\r\nclass Animal {\r\n public name;\r\n public constructor(name:string) {\r\n this.name = name;\r\n }\r\n}\r\n\r\nlet a = new Animal(\'大黄\');\r\nconsole.log(a.name); // 大黄\r\na.name = \'小黑\';\r\nconsole.log(a.name); // 小黑\r\n```\r\n\r\n上述可以直接修改和获取数据,对于对象数据来说是不安全的,可以通过private或者protected提高安全性。\r\n\r\n### private修饰属性\r\n\r\n使用private修饰将属性私有化,属性只能在类内部直接调用,如果要修改数据和获取数据可以通过公开的方法获取\r\n\r\n```typescript\r\nclass Animal {\r\n private name;\r\n public constructor(name:string) {\r\n this.name = name;\r\n }\r\n\r\n public getName():string {\r\n return this.name;\r\n }\r\n\r\n public setName(name:string):string {\r\n return this.name = name;\r\n }\r\n}\r\n\r\nlet a = new Animal(\'大黄\');\r\nconsole.log(a.getName()); // 大黄\r\na.setName(\'小黑\');\r\nconsole.log(a.getName()); // 小黑\r\n```\r\n\r\n### protected修饰属性\r\n\r\n被private修饰,包括子类在内都不被允许访问,只有本类内部可以访问,如果希望子类可以访问则可以使用protected修饰\r\n\r\n```typescript\r\nclass Animal {\r\n protected name;\r\n public constructor(name:string) {\r\n this.name = name;\r\n }\r\n\r\n public getName():string {\r\n return this.name;\r\n }\r\n\r\n public setName(name:string):string {\r\n return this.name = name;\r\n }\r\n}\r\n\r\nclass Dog extends Animal {\r\n constructor(name:string) {\r\n super(name);\r\n // name属性被继承过来\r\n console.log(this.name);\r\n }\r\n}\r\n```\r\n\r\n### private修饰构造方法\r\n\r\n如果构造方法通过private修饰被私有化,则该类不能被实例化,也不能被继承\r\n\r\n```typescript\r\nclass Animal {\r\n protected name;\r\n // 私有化构造方法\r\n private constructor(name:string) {\r\n this.name = name;\r\n }\r\n\r\n public getName():string {\r\n return this.name;\r\n }\r\n\r\n public setName(name:string):string {\r\n return this.name = name;\r\n }\r\n}\r\n\r\n// 继承就会报错\r\n// Cannot extend a class \'Animal\'. Class constructor is marked as private\r\nclass Dog extends Animal {\r\n constructor(name:string) {\r\n super(name);\r\n // name属性被继承过来\r\n console.log(this.name);\r\n }\r\n}\r\n```\r\n\r\n### protected 修饰构造方法\r\n\r\n如果构造函数修饰为 protected 时,该类不能实例化\r\n\r\n```typescript\r\nclass Animal {\r\n protected name;\r\n // protected修饰\r\n protected constructor(name:string) {\r\n this.name = name;\r\n }\r\n\r\n public getName():string {\r\n return this.name;\r\n }\r\n\r\n public setName(name:string):string {\r\n return this.name = name;\r\n }\r\n}\r\n// 继承没毛病\r\nclass Dog extends Animal {\r\n constructor(name:string) {\r\n super(name);\r\n // name属性被继承过来\r\n console.log(this.name);\r\n }\r\n}\r\n// 实例化有问题\r\n// Constructor of class \'Animal\' is protected and only accessible within the class declaration\r\nlet a = new Animal(\'大黄\');\r\n```\r\n\r\n### 参数属性\r\n\r\n类中属性可以定义在构造方法上,等同于类中定义了属性\r\n\r\n```typescript\r\nclass Animal {\r\n // 参数属性\r\n public constructor(public name:string) {\r\n }\r\n}\r\n\r\nlet a = new Animal(\"大黄\");\r\nconsole.log(a.name)\r\n```\r\n\r\n### readonly\r\n\r\n只读属性关键字也可用于类中,只允许出现在属性声明或索引签名或构造函数中。\r\n\r\n```typescript\r\nclass Animal {\r\n // 只读属性\r\n readonly name;\r\n public constructor(name:string) {\r\n this.name = name;\r\n }\r\n}\r\n\r\nlet a = new Animal(\'大黄\');\r\nconsole.log(a.name);\r\n// 不可再次修改\r\na.name = \'小黑\';\r\n```\r\n\r\n注意如果 readonly 和其他访问修饰符同时存在的话,需要写在其后面。\r\n\r\n```typescript\r\nclass Animal {\r\n // public readonly name;\r\n public constructor(public readonly name:string) {\r\n // this.name = name;\r\n }\r\n}\r\n```\r\n\r\n### 抽象类\r\n\r\n抽象类不能被实例化,使用abstract修饰\r\n\r\n```typescript\r\nabstract class Animal {\r\n public name;\r\n public constructor(name:string) {\r\n this.name = name;\r\n }\r\n public abstract sayHi():any;\r\n}\r\n// Cannot create an instance of an abstract class.\r\nlet a = new Animal(\'大黄\');\r\n```\r\n\r\n抽象类中的抽象方法必须被子类实现,子类必须实现抽象类中的所有抽象方法,否则需要继续抽象下去:\r\n\r\n```typescript\r\nabstract class Animal {\r\n public name;\r\n public constructor(name:string) {\r\n this.name = name;\r\n }\r\n public abstract eat():any;\r\n}\r\n\r\nclass Cat extends Animal {\r\n public eat() {\r\n console.log(`${this.name} 在吃鱼.`);\r\n }\r\n}\r\n\r\nlet c = new Cat(\'小花\');\r\nc.eat();\r\n```\r\n\r\n如果没有实现所有抽象方法则继续报错:\r\n\r\n```typescript\r\nabstract class Animal {\r\n public name;\r\n public constructor(name:string) {\r\n this.name = name;\r\n }\r\n public abstract eat():any;\r\n public abstract sayHi():any;\r\n}\r\n\r\n// Non-abstract class \'Cat\' does not implement all abstract members of \'Animal\'\r\nclass Cat extends Animal {\r\n public eat() {\r\n console.log(`${this.name} 在吃鱼.`);\r\n }\r\n}\r\n```\r\n\r\n## 泛型\r\n\r\n泛型(Generics)是指在定义函数、接口或类的时候,不预先指定具体的类型,而在使用的时候再指定类型的一种特性。\r\n\r\n### 无泛型\r\n\r\n实现一个函数 createArray,它可以创建一个指定长度的数组,同时将每一项都填充一个默认值:\r\n\r\n```typescript\r\nfunction createArray(length: number, value: any): Array<any> {\r\n let result = [];\r\n for (let i = 0; i < length; i++) {\r\n result[i] = value;\r\n }\r\n return result;\r\n}\r\n\r\ncreateArray(3, \'x\'); // [\'x\', \'x\', \'x\']\r\n```\r\n\r\n此处使用any当做入参和Array<any>反参类型,编译不会报错,但是可能会造成类型不安全的问题,调用方法的用户可能瞎传数据,你的方法就报错啦。此时泛型就登场了,**解决参数类型安全问题**\r\n\r\n```typescript\r\nfunction createArray<T>(length: number, value: T): Array<T> {\r\n let result: T[] = [];\r\n for (let i = 0; i < length; i++) {\r\n result[i] = value;\r\n }\r\n return result;\r\n}\r\n\r\ncreateArray<string>(3, \'x\'); // [\'x\', \'x\', \'x\']\r\n```\r\n\r\n上例中,我们在函数名后添加了 <T>,其中 T 用来指代任意输入的类型,在后面的输入 value: T 和输出 Array<T> 中即可使用了。\r\n接着在调用的时候,可以指定它具体的类型为 string。当然,也可以不手动指定,而让类型推论自动推算出来:\r\n\r\n```typescript\r\nfunction createArray<T>(length: number, value: T): Array<T> {\r\n let result: T[] = [];\r\n for (let i = 0; i < length; i++) {\r\n result[i] = value;\r\n }\r\n return result;\r\n}\r\n\r\ncreateArray(3, \'x\'); // [\'x\', \'x\', \'x\']\r\n```\r\n\r\n### 多个类型参数\r\n\r\n定义泛型的时候,可以一次定义多个类型参数:\r\n\r\n```typescript\r\nfunction swap<T, U>(tuple: [T, U]): [U, T] {\r\n return [tuple[1], tuple[0]];\r\n}\r\n\r\nswap([7, \'seven\']); // [\'seven\', 7]\r\n```\r\n\r\n### 泛型约束\r\n\r\n在函数内部使用泛型变量的时候,由于事先不知道它是哪种类型,所以不能随意的操作它的属性或方法:\r\n\r\n```typescript\r\nfunction loggingIdentity<T>(arg: T): T {\r\n console.log(arg.length);\r\n return arg;\r\n}\r\n```\r\n\r\n上例中,泛型 T 不一定包含属性 length,所以编译的时候报错了。\r\n这时,我们可以对泛型进行约束,只允许这个函数传入那些包含 length 属性的变量。这就是泛型约束:\r\n\r\n```typescript\r\ninterface Lengthwise {\r\n length: number;\r\n}\r\n\r\nfunction loggingIdentity<T extends Lengthwise>(arg: T): T {\r\n console.log(arg.length);\r\n return arg;\r\n}\r\n```\r\n\r\n上例中,我们使用了 extends 约束了泛型 T 必须符合接口 Lengthwise 的形状,也就是必须包含 length 属性。\r\n此时如果调用 loggingIdentity 的时候,传入的 arg 不包含 length,那么在编译阶段就会报错了:\r\n\r\n```typescript\r\ninterface Lengthwise {\r\n length: number;\r\n}\r\n\r\nfunction loggingIdentity<T extends Lengthwise>(arg: T): T {\r\n console.log(arg.length);\r\n return arg;\r\n}\r\n\r\nloggingIdentity(7);\r\n```\r\n\r\n多个类型参数之间也可以互相约束:\r\n\r\n```typescript\r\nfunction copyFields<T extends U, U>(target: T, source: U): T {\r\n for (let id in source) {\r\n target[id] = (<T>source)[id];\r\n }\r\n return target;\r\n}\r\n\r\nlet x = { a: 1, b: 2, c: 3, d: 4 };\r\n\r\ncopyFields(x, { b: 10, d: 20 });\r\n```\r\n\r\n上例中,我们使用了两个类型参数,其中要求 T 继承 U,这样就保证了 U 上不会出现 T 中不存在的字段。\r\n\r\n### 泛型接口\r\n\r\n泛型也可以用来定义接口\r\n\r\n```typescript\r\ninterface CreateArrayFunc {\r\n <T>(length: number, value: T): Array<T>;\r\n}\r\n\r\nlet createArray: CreateArrayFunc;\r\ncreateArray = function<T>(length: number, value: T): Array<T> {\r\n let result: T[] = [];\r\n for (let i = 0; i < length; i++) {\r\n result[i] = value;\r\n }\r\n return result;\r\n}\r\n\r\ncreateArray(3, \'x\'); // [\'x\', \'x\', \'x\']\r\n```\r\n\r\n进一步,我们可以把泛型参数提前到接口名上:\r\n\r\n```typescript\r\ninterface CreateArrayFunc<T> {\r\n (length: number, value: T): Array<T>;\r\n}\r\n\r\nlet createArray: CreateArrayFunc<any>;\r\ncreateArray = function<T>(length: number, value: T): Array<T> {\r\n let result: T[] = [];\r\n for (let i = 0; i < length; i++) {\r\n result[i] = value;\r\n }\r\n return result;\r\n}\r\n\r\ncreateArray(3, \'x\'); // [\'x\', \'x\', \'x\']\r\n```\r\n\r\n注意,此时在使用泛型接口的时候,需要定义泛型的类型。\r\n\r\n### 泛型类\r\n\r\n与泛型接口类似,泛型也可以用于类的类型定义中:\r\n\r\n```typescript\r\nclass GenericNumber<T> {\r\n zeroValue: T;\r\n add: (x: T, y: T) => T;\r\n}\r\n\r\nlet myGenericNumber = new GenericNumber<number>();\r\nmyGenericNumber.zeroValue = 0;\r\nmyGenericNumber.add = function(x, y) { return x + y; };\r\n```\r\n\r\n### 泛型参数的默认类型\r\n\r\n在 TypeScript 2.3 以后,我们可以为泛型中的类型参数指定默认类型。当使用泛型时没有在代码中直接指定类型参数,从实际值参数中也无法推测出时,这个默认类型就会起作用。\r\n\r\n```typescript\r\nfunction createArray<T = string>(length: number, value: T): Array<T> {\r\n let result: T[] = [];\r\n for (let i = 0; i < length; i++) {\r\n result[i] = value;\r\n }\r\n return result;\r\n}\r\n```\r\n\r\n# 类型断言\r\n\r\n类型断言(Type Assertion)可以用来手动指定一个值的类型。语法为\r\n\r\n```typescript\r\n值 as 类型\r\n\r\n或\r\n \r\n<类型>值\r\n```\r\n\r\n在 tsx 语法(React 的 jsx 语法的 ts 版)中必须使用 **值 as 类型**。\r\n\r\n## 联合类型断言为一个具体类型\r\n\r\n前文介绍了支持联合类型,即一个变量可以是string类型也可以是number类型,只能访问该变量所有类型的共有属性和方法\r\n\r\n```typescript\r\nfunction fun1(args: string | number):number {\r\n // 将值断言为number类型\r\n let result = args as number;\r\n\r\n return result;\r\n}\r\n\r\nconsole.log(fun1(\"1\"))\r\n```\r\n\r\n## 将一个父类断言为更加具体的子类\r\n\r\n当类之间有继承关系时,类型断言也是很常见的:\r\n\r\n```typescript\r\nclass Animal {\r\n name: string;\r\n constructor(name:string) {\r\n this.name = name;\r\n }\r\n}\r\n\r\nclass Dog extends Animal {\r\n constructor(name:string) {\r\n super(name);\r\n }\r\n doorkeeper():void {\r\n console.log(this.name + \"在看家\")\r\n }\r\n}\r\nclass Cat extends Animal {\r\n constructor(name:string) {\r\n super(name);\r\n }\r\n catchMouse():void {\r\n console.log(this.name + \"在抓老鼠\")\r\n }\r\n}\r\n\r\n// 离家需要狗看门,也需要猫抓老鼠\r\nfunction leaveHome(animal: Animal) {\r\n let dog = animal as Dog;\r\n dog.doorkeeper();\r\n}\r\n\r\nleaveHome(new Dog(\'旺财\'));\r\n```\r\n\r\n上面的例子中,我们声明了函数 leaveHome,转为Dog类型,调用看门方法,离家时构建一个狗对象,调用它的看门方法即可。\r\n\r\n## 断言限制\r\n\r\n类型不可随意断言,比如Dog是Animal的一种,Adimal可以断言为Dog,Cat不是Dog的一种,Cat就不能断言为Dog。如下例子:\r\n\r\n```typescript\r\nclass Animal {\r\n name: string;\r\n constructor(name:string) {\r\n this.name = name;\r\n }\r\n}\r\n\r\nclass Dog extends Animal {\r\n constructor(name:string) {\r\n super(name);\r\n }\r\n doorkeeper():void {\r\n console.log(this.name + \"在看家\")\r\n }\r\n}\r\nclass Cat extends Animal {\r\n constructor(name:string) {\r\n super(name);\r\n }\r\n catchMouse():void {\r\n console.log(this.name + \"在抓老鼠\")\r\n }\r\n}\r\n\r\n// 离家需要狗看门\r\n// 如果传入类型为Cat,断言成Dog编译不会报错,但运行时就会报错\r\nfunction leaveHome(animal: Animal) {\r\n let dog = animal as Dog;\r\n dog.doorkeeper();\r\n}\r\n// 实例化一个Cat\r\nleaveHome(new Cat(\'小花\'));\r\n```\r\n\r\n可以使用**instanceof**判断类型后对数据进行断言:\r\n\r\n```typescript\r\nclass Animal {\r\n name: string;\r\n constructor(name:string) {\r\n this.name = name;\r\n }\r\n}\r\n\r\nclass Dog extends Animal {\r\n constructor(name:string) {\r\n super(name);\r\n }\r\n doorkeeper():void {\r\n console.log(this.name + \"在看家\")\r\n }\r\n}\r\nclass Cat extends Animal {\r\n constructor(name:string) {\r\n super(name);\r\n }\r\n catchMouse():void {\r\n console.log(this.name + \"在抓老鼠\")\r\n }\r\n}\r\n\r\n// 判断类型之后\r\nfunction leaveHome(animal: Animal) {\r\n if(animal instanceof Dog) {\r\n let dog = animal as Dog;\r\n dog.doorkeeper();\r\n }else if(animal instanceof Cat) {\r\n let cat = animal as Cat;\r\n cat.catchMouse();\r\n }\r\n}\r\n\r\nleaveHome(new Cat(\'小花\'));\r\n```\r\n\r\n# 类型别名\r\n\r\n类型别名用来给一个类型起个新名字。\r\n\r\n```typescript\r\ntype Name = string;\r\ntype NameResolver = () => string;\r\ntype NameOrResolver = Name | NameResolver;\r\nfunction getName(n: NameOrResolver): Name {\r\n if (typeof n === \'string\') {\r\n return n;\r\n } else {\r\n return n();\r\n }\r\n}\r\n```\r\n\r\n上例中,我们使用 type 创建类型别名。类型别名常用于联合类型,将多个类型封装进一个类型中', 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, '2024-05-01 18:01:07', '2024-05-01 22:06:16', 0, 0, 'javascript,TypeScript');
INSERT INTO `ams_article` VALUES (4, 3, 8, '标题撒大大标题撒大大标helloworld题撒大大啊实打实大啊实打实大师', 'http://localhost:8128/img/article/20240501180023A002.png', 'dfdghggdfsgffdd', '# 什么是TypeScript\r\n\r\nTypeScript于2012年10月由微软推出上线,始于JavaScript,看名字就知道TypeScript主要强调了类型,TypeScript在JaaScript基础上增加**类型系统**,JavaScript是一个弱类型语言,在编译期间声明的变量可以是任意类型,会导致运行时可能出现的类型错误,使用TypeScript之后可以指定变量类型,如果出现类型问题在编译期间就可以暴露出来,更容易查bug。\r\n最终TypScript又归于JavaScript,运行时其实还是将TypeScript转译成JavaScript执行,因为浏览器,node环境只能运行JavaScript。\r\n\r\n# 安装TypeScript\r\n\r\n首先确保您的电脑上安装了node,建议安装nodejs18以上版本。可点击链接进入[node下载地址](https://www.nodejs.com.cn/)。\r\nTypeScript需要编译为JavaScript文件执行,所以需要先安装TypeScript环境,可以将TypeScipt文件编译为JavaScript在浏览器或者node环境中运行。首先同时按下win + r键输入cmd唤起命令窗口\r\n**安装命令:**\r\n\r\n```shell\r\n# 全局安装typescript\r\nnpm install -g typescript\r\n```\r\n\r\n![image.png](http://localhost:8128/img/article/20240501180023A002.png)\r\n安装之后TypeScript的执行命令为tsc,比如想要查看TypeScript版本则可输入:\r\n\r\n```shell\r\ntsc -version\r\n```\r\n\r\n# HelloWorld\r\n\r\n## 创建文件\r\n\r\n写JavaScript时,文件后缀为.js。写TypeScript时文件后缀名为.ts。可以打开任意的编辑器整活,此处我使用VsCode开搞。以声明sting类型变量为例:\r\n\r\n```typescript\r\n// 变量title后边加上:string。指定为string类型,修改变量值时就只能是string类型\r\nlet title:string = \"Hello TypeScript\";\r\n\r\nconsole.log(title);\r\n```\r\n\r\n![image.png](http://localhost:8128/img/article/20240501180023A002.png)\r\n所以说ts声明变量的语法为:\r\n\r\n```javascript\r\n变量修饰符 变量名 : 数据类型 = 初始化值;\r\n如:var/let/const vag:number = 123;\r\n```\r\n\r\n## 编译\r\n\r\n将ts文件编译为js文件执行,使用tsc命令即可命令\r\n\r\n```shell\r\ntsc 01-hellosworld.ts\r\n```\r\n\r\n执行之后会在同级目录下生成一个同名的js文件\r\n![image.png](http://localhost:8128/img/article/20240501180023A002.png)\r\n\r\n## 执行\r\n\r\n使用node命令或者通过浏览器打开js文件来执行,如果使用node执行则使用nod命令:\r\n\r\n```shell\r\nnode 01-hellosworld.js\r\n```\r\n\r\n![image.png](http://localhost:8128/img/article/20240501180023A002.png)\r\n\r\n## 快速执行\r\n\r\n安装ts-node包实现快速运行ts,其实内部还是将ts转为js执行,底层逻辑不变,只是简化了开发人员操作。\r\n**安装命令:**\r\n\r\n```shell\r\nnpm install -g ts-node\r\n```\r\n\r\n**执行ts文件:**\r\n\r\n```shell\r\nts-node 01-hellosworld.ts\r\n```\r\n\r\n此时就不会再生成js文件啦。**但是执行的还是js哦,这是一定要记清楚的。**\r\n\r\n## 修改类型\r\n\r\n尝试将title修改为数字类型数据,如果在javascript中是可行的,类型可随意修改,在typescript中,如果修改数据类型在编译期就会报错\r\n![image.png](http://localhost:8128/img/article/20240501180023A002.png)\r\n那么忽略编辑器的报错,尝试运行会返回TSError错误,错误信息是编译TypeScript时出现问题。\r\n![image.png](http://localhost:8128/img/article/20240501180023A002.png)\r\n此处可以看出TypeScript相较于JavaScript对类型要求更严格,这也是很多开发人员吐槽的地方,以前写js\r\n随心所欲,随便定义一个变量,下边想怎么改都成,使用了ts之后只能修改值为对应类型的,好像添加了束缚,但我觉得这是好事:\r\n\r\n- 首先数据类型在逻辑处理中其实就应该输入同一个类型内的修改,严格来说是不可以将字符串类型修改为数字类型等,甚至是对象类型的数据。\r\n- 在复杂的业务处理中,甚至有时候都已经忘记了一个变量是什么类型的了😛。\r\n\r\n# TypeScript优势\r\n\r\nTypeScript包含JavaScript所有功能,同时又增加了类型系统,弥补了JavaScript弱类型的缺陷,那么为什么是缺陷呢?在ES6中JavaScript又推出了很多新的API,方便处理数据,这些api有的是字符串才能使用的,有的是数组才能使用的,有的是数字才能使用的,而JavaScript在编译时并不会检查当前变量是什么类型,能否使用调用的方法,在运行时就会出现错误。甚至会导致严重的线上bug。比如:\r\n\r\n```javascript\r\nlet arr = [1,2,3,4,5,6,7];\r\n\r\n// 将数组转为数字类型\r\narr = 1;\r\n// 调用filter方法,获取大于4的数据,此方法number类型肯定不能调用,但编译期并不会提示\r\nlet result = arr.filter(item => item > 4);\r\nconsole.log(result);\r\n\r\n```\r\n\r\n运行时就会出现TypeError即类型错误。\r\n![image.png](http://localhost:8128/img/article/20240501180023A002.png)\r\n以上错误在开发工作中比比皆是,不要妄图以为脑子好用能记住所有变量的数据类型,有时候你甚至不知道用户传过来的是什么类型的数据,所以在定义变量和方法参数时,设置明确的类型势在必行。\r\n\r\n# 数据类型\r\n\r\nTypeScript是JavaScript的扩充,所以包含JavaScript中的所有数据类型,同时又增加了若干个数据类型。下表列出TypeScript中所有的数据类型,不区分JS和TS,没有什么实际意义:\r\n\r\n| 数据类型 | 作用 |\r\n| ------------------ | ------------------------------------------------------------ |\r\n| number:数字类型 | 双精度 64 位浮点值。它可以用来表示整数和分数 |\r\n| string:字符串类型 | 描述字符或字符串,使用单引号(\')或双引号(\")来表示字符串类型。反引号(`)来定义多行文本和内嵌表达式。 |\r\n| boolean:布尔类型 | 表示逻辑值:true 和 false。 |\r\n| Object:对象 | 对象类型包括,数组、对象、函数 |\r\n| 元组 | 元组类型用来表示已知元素数量和类型的数组,各元素的类型不必相同,对应位置的类型需要相同。 |\r\n| enum:枚举 | 枚举类型用于定义数值集合。 |\r\n| any:任意类型 | 声明为 any 的变量可以赋予任意类型的值。 |\r\n| null | 表示对象值缺失。 |\r\n| undefined | 用于初始化变量为一个未定义的值 |\r\n| void | 用于标识方法返回值的类型,表示该方法没有返回值。 |\r\n| symbol | 用来声明唯一值,解决命名冲突问题 |\r\n| never | 其它类型(包括 null 和 undefined)的子类型,代表从不会出现的值。 |\r\n\r\n## number\r\n\r\n前端的JavaScript和TypeScript中没有整数和小数之分,数字类型统一使用number表示,可以使用各种进制实例化一个数字,写法如下:\r\n\r\n```typescript\r\n// 使用十进制表示\r\nlet num1: number = 6;\r\n// 十六进制\r\nlet num2: number = 0xf00d;\r\n// ES6 中的二进制表示法\r\nlet num3: number = 0b1010;\r\n// ES6 中的八进制表示法\r\nlet num4: number = 0o744;\r\n// 非数字\r\nlet num5: number = NaN;\r\n// 无穷值\r\nlet infinityNumber: number = Infinity;\r\n// 使用构造\r\nlet num1 : number = Number(1);\r\n// 使用JS中对象类型表示类型\r\nlet num2 : Number = 123;\r\n```\r\n\r\n其他数据类型都相同,可以使用构造方法初始化值,使用对象类型标识数据类型\r\n\r\n## string\r\n\r\n字符串可以通过单引号\'\'、双引号\"\"和模板字符串``创建\r\n\r\n```typescript\r\nlet s1 : string = \'单引号字符串\';\r\n\r\nlet s2 : string = \"双引号字符串\";\r\n\r\nlet s3 : string = `第一个${s1},第二个${s2}`;\r\n\r\nlet s4 : string = String(\"对象字符串\");\r\n```\r\n\r\n模板字符串可以使用${变量}方式引用变量\r\n\r\n## boolean\r\n\r\n布尔类型的值用来表示对【true】或者错【false】,在TypeScript中使用boolean表示:\r\n\r\n```typescript\r\nlet age : number = 123;\r\n\r\nlet username : string = \"username\";\r\n\r\nlet isMan : boolean = true;\r\n\r\n// 下方是错误的,new Boolean是对象类型\r\n// let isDog : boolean = new Boolean(true);\r\n\r\n// 可以直接使用Boolean()\r\nlet isDog : boolean = Boolean(true);\r\n```\r\n\r\n## 任意值\r\n\r\n可以通过使用any表示变量可以是任意类型数据,使用any效果和JavaScript相同,后期可以修改变量数据类型\r\n\r\n```typescript\r\n// any类型,初始值为string\r\nlet a1 : any = \"a1\";\r\n// 修改为number类型\r\na1 = 123;\r\n```\r\n\r\n## 类型推断\r\n\r\nTypeScript支持像JavaScript那样不显示声明数据类型,会根据赋值自动推断类型,后期则不可修改值为其他类型的数据\r\n\r\n```typescript\r\n// 类型自动推断为string\r\nlet username = \'张三\';\r\n// Type \'number\' is not assignable to type \'string\'\r\nusername = 123;\r\n```\r\n\r\n## null和undefined\r\n\r\nnull和undefined也可以被当做数据类型来定义\r\n\r\n```typescript\r\nlet nu : null = null;\r\n\r\nlet un : undefined = undefined;\r\n```\r\n\r\nnull是一个对象/变量的值为null,而undefined则表示该变量没有初始化。\r\n\r\n## void\r\n\r\nvoid为空值,是TypeScript中新增的数据类型,表示没有任何返回值的函数\r\n\r\n```typescript\r\nfunction say(): void {\r\n alert(\'我是张三\');\r\n}\r\n\r\nsay();\r\n```\r\n\r\n有些地方会比较,深究null、undefined、void区别,我认为并没有意义,null就是一个对象为空值,undefined就是没有初始值,void用来表示方法没有返回值,不要去描述变量。仅此而已不要再做无谓的深究!\r\n\r\n## 联合类型\r\n\r\n联合类型是该变量可以在声明的类型中随意匹配一个即可,比如年龄可以使用数字表示,也可以使用字符串表示,可以通过** | **符号分割多个类型\r\n\r\n```typescript\r\nlet age : number | string = \'十六\';\r\nage = 16;\r\n```\r\n\r\n如果使用联合类型表示一个变量,此时在操作变量时需要使用共有属性和方法,不能使用某一个类型特有的方法或属性,比如age可以为number或者string类型,number类型有toFixed方法,而string没有,number和string共有的操作有**toString**、**valueOf**方法。\r\n\r\n```typescript\r\nlet age : number | string = \'十六\'\r\nage = 16\r\n// 共有方法\r\nage.toString();\r\n// string有此方法,如果数字调用出现,Property \'length\' does not exist on type \'number\'\r\nage.length;\r\n```\r\n\r\n或者使用**typeof**判断类型之后使用\r\n\r\n```typescript\r\nlet age : number | string = 12\r\n\r\nif(typeof age === \'number\') {\r\n console.log(\"数字类型\")\r\n}\r\n\r\nif(typeof age === \'string\') {\r\n console.log(\"字符串类型\")\r\n}\r\n```\r\n\r\n## 数组\r\n\r\n```typescript\r\n// 通过类型[]方式指定,下例:数组中只允许有number类型数据\r\nlet a1 : number[] = [1,2,3,4];\r\n// 通过泛型指定,Array<类型>,下例:只允许有字符串\r\nlet nameArr : Array<string> = [\'大毛\',\'二毛\',\'小明\'];\r\n```\r\n\r\n## 元组\r\n\r\n元组和数组区别在于,元组中可以存在不同类型的数据。\r\n\r\n```typescript\r\n// 数据类型必须与索引一一匹配\r\nlet a1 : [number,string,number] = [1,\'a\',2];\r\n\r\n// 先声明,再赋值\r\nlet person1: [string, number];\r\nperson1 = [\'大毛\', 25];\r\n\r\n// 获取一项\r\nlet username : string = person1[0];\r\nlet age : number = person1[1];\r\n\r\n// 操作数据\r\nconsole.log(username.indexOf(\"大\"))\r\nconsole.log(age.toFixed(2));\r\n```\r\n\r\n添加越界元素时【元组本身2个元素长度,新增其他数据长度会增加,称为添加越界元素】,它的类型会被限制为元组中每个类型的联合类型:\r\n\r\n```typescript\r\n// 先声明,再赋值\r\nlet person1: [string, number] = [\'大毛\', 25];\r\n\r\nperson1.push(\"123\");\r\nperson1.push(123);\r\n\r\n// Argument of type \'boolean\' is not assignable to parameter of type \'string | number\'.\r\nperson1.push(true);\r\n```\r\n\r\n如果元组中存在可选值时可以在类型后添加?表示,如下\r\n\r\n```typescript\r\n// number类型的值可写可不写,添加?即可\r\nlet person1: [string, number?] = [\'大毛\'];\r\n```\r\n\r\n## 枚举\r\n\r\n枚举(Enum)类型用于取值被限定在一定范围内的场景,比如订单状态为未付款、待发货、待收货、待评价,性别限定为男、女、未知等。\r\n枚举成员会被赋值为从 0 开始递增的数字,同时也会对枚举值到枚举名进行反向映射:\r\n\r\n```typescript\r\nenum OrderStatus {NO_PAY, SHIPPED, RECEIVED, EVALUATED,REVIEWED};\r\n\r\n// 使用\r\nconsole.log(OrderStatus[\'NO_PAY\'] === 0);\r\nconsole.log(OrderStatus[\'SHIPPED\'] === 1);\r\nconsole.log(OrderStatus[\'RECEIVED\'] === 2);\r\n\r\nconsole.log(OrderStatus[0] === \'NO_PAY\');\r\nconsole.log(OrderStatus[1] === \'SHIPPED\');\r\nconsole.log(OrderStatus[2] === \'RECEIVED\');\r\n```\r\n\r\n你还可以通过手动赋值修改默认以0递增的数据\r\n\r\n```typescript\r\nenum OrderStatus {NO_PAY = 1, SHIPPED = 2, RECEIVED = 3, EVALUATED,REVIEWED};\r\n\r\n// 使用\r\nconsole.log(OrderStatus[\'NO_PAY\']);\r\nconsole.log(OrderStatus[\'SHIPPED\']);\r\nconsole.log(OrderStatus[\'RECEIVED\']);\r\nconsole.log(OrderStatus[\'EVALUATED\']);\r\nconsole.log(OrderStatus[\'REVIEWED\']);\r\n```\r\n\r\n## 函数\r\n\r\nTypeScript中声明函数可以在形式参数和返回值中指定数据类型。\r\n\r\n```typescript\r\n// 接收number类型参数,返回number类型参数\r\nfunction fun1(num1 : number,num2 : number) : number {\r\n\r\n return num1 + num2;\r\n}\r\nconsole.log(fun1(1,2));\r\n```\r\n\r\n也支持通过函数表达式【Function Expression】的方式声明函数\r\n\r\n```typescript\r\nlet fun2 = function(str1 : string,str2 : string) : string {\r\n\r\n return str1.concat(str2);\r\n}\r\n\r\nconsole.log(fun2(\'A\',\'B\'));\r\n```\r\n\r\n函数同样支持**可选参数**,当然可选参数必须在最后\r\n\r\n```typescript\r\nfunction buildName(firstName: string, lastName?: string) {\r\n if (lastName) {\r\n return firstName + \' \' + lastName;\r\n } else {\r\n return firstName;\r\n }\r\n}\r\nlet tomcat = buildName(\'Tom\', \'Cat\');\r\nlet tom = buildName(\'Tom\');\r\n```\r\n\r\n如果没有返回值,则可以使用**void**修饰返回值类型,无返回值时接收到的为**undefined**\r\n\r\n```typescript\r\nfunction fun1(firstName: string):void {\r\n console.log(firstName.toUpperCase());\r\n}\r\nlet result = fun1(\'Tom\');\r\nconsole.log(result);\r\n```\r\n\r\nES6中允许方法参数有默认值,**TypeScript 会将添加了默认值的参数识别为可选参数**:\r\n\r\n```typescript\r\nfunction buildName(firstName: string, lastName: string = \'Cat\') {\r\n return firstName + \' \' + lastName;\r\n}\r\nlet tomcat = buildName(\'Tom\', \'Cat\');\r\nlet tom = buildName(\'Tom\');\r\n```\r\n\r\n此时就不受「可选参数必须接在必需参数后面」的限制了:\r\n\r\n```typescript\r\nfunction buildName(firstName: string = \'Tom\', lastName: string) {\r\n return firstName + \' \' + lastName;\r\n}\r\nlet tomcat = buildName(\'Tom\', \'Cat\');\r\nlet cat = buildName(undefined, \'Cat\');\r\n```\r\n\r\nES6中可以使用 **...rest** 的方式获取函数中的剩余参数(rest 参数):\r\n\r\n```typescript\r\nfunction push(array, ...items) {\r\n items.forEach(function(item) {\r\n array.push(item);\r\n });\r\n}\r\n\r\nlet a: any[] = [];\r\npush(a, 1, 2, 3);\r\n```\r\n\r\n事实上,items 是一个数组。所以我们可以用数组的类型来定义它:\r\n\r\n```typescript\r\nfunction push(array: any[], ...items: any[]) {\r\n items.forEach(function(item) {\r\n array.push(item);\r\n });\r\n}\r\n\r\nlet a = [];\r\npush(a, 1, 2, 3);\r\n```\r\n\r\n注意,rest 参数只能是最后一个参数\r\n\r\n## 接口\r\n\r\n接口用来定义一种规范,具体的时候交由对象来做,举个生活中的例子我们购买商品按照消费者权益来说所有的商品都必须有售后保障,那么具体怎么实现售后,你是上门维修也好,直接换货也好,就有厂家自己实现。这个必须有售后就是规范,各个厂家就是一个一个具体的对象,交由对象实现就行了。\r\n程序中就是我们希望在程序内描述一个人,那么人的规范就是有名字、性别、年龄和一些行为这可以通过接口描述,具体是哪一个人,就交由对象来具体化【实例化】。\r\n\r\n```typescript\r\n// 接口定义抽象结构\r\ninterface Person {\r\n username: string;\r\n age: number;\r\n say():void;\r\n}\r\n// 对象具体实现\r\nlet tom: Person = {\r\n username: \'张三\',\r\n age: 25,\r\n say() : void {\r\n console.log(this.username)\r\n }\r\n};\r\n```\r\n\r\n### 可选属性\r\n\r\n有时认为一个对象的某个属性可有可无,可以使用可选属性\r\n\r\n```typescript\r\ninterface Person {\r\n name: string;\r\n age?: number;\r\n}\r\n\r\nlet p1: Person = {\r\n name: \'大毛\'\r\n};\r\nlet p2: Person = {\r\n name: \'小毛\',\r\n age: 25\r\n};\r\n```\r\n\r\n### 任意属性\r\n\r\n又是我们希望可以在对象中添加任意的属性:\r\n\r\n```typescript\r\ninterface Person {\r\n name: string;\r\n age?: number;\r\n [propName: string]: any;\r\n}\r\n\r\nlet tom: Person = {\r\n name: \'大毛\',\r\n gender: \'男\',\r\n};\r\n```\r\n\r\n任意属性的类型需要包含可选属性,否则编译报错,比如any包含number类型,如果将any换成string,则age可选属性就会报错\r\n\r\n### 只读属性\r\n\r\n有时候我们希望对象中的一些字段在创建的时候被赋值后就不可更改,那么可以用 readonly 定义只读属性:\r\n\r\n```typescript\r\ninterface IBook {\r\n readonly author: string;\r\n bookname: string;\r\n}\r\n\r\nlet book1: IBook = {\r\n author: \'小明\',\r\n bookname: \'TypeScript养成记\',\r\n};\r\n\r\nbook1.author = \'大毛\';\r\n```\r\n\r\n## 类\r\n\r\nES6中JavaScript引入了类的概念,类也是用来定义事物的抽象,交由对象具体实现,在面向对象的语言中,对于类我们应该熟知这么几个概念:\r\n\r\n- 类(Class):定义了一件事物的抽象特点,包含它的属性和方法\r\n- 对象(Object):类的实例,通过 new 生成\r\n- 面向对象(OOP)的三大特性:封装、继承、多态\r\n- 封装(Encapsulation):将对数据的操作细节隐藏起来,只暴露对外的接口。外界调用端不需要(也不可能)知道细节,就能通过对外提供的接口来访问该对象,同时也保证了外界无法任意更改对象内部的数据\r\n- 继承(Inheritance):子类继承父类,子类除了拥有父类的所有特性外,还有一些更具体的特性\r\n- 多态(Polymorphism):由继承而产生了相关的不同的类,对同一个方法可以有不同的响应。比如 Cat 和 Dog 都继承自 Animal,但是分别实现了自己的 eat 方法。此时针对某一个实例,我们无需了解它是 Cat 还是 Dog,就可以直接调用 eat 方法,程序会自动判断出来应该如何执行 eat\r\n- 存取器(getter & setter):用以改变属性的读取和赋值行为\r\n- 修饰符(Modifiers):修饰符是一些关键字,用于限定成员或类型的性质。比如 public 表示公有属性或方法\r\n- 抽象类(Abstract Class):抽象类是供其他类继承的基类,抽象类不允许被实例化。抽象类中的抽象方法必须在子类中被实现\r\n- 接口(Interfaces):不同类之间公有的属性或方法,可以抽象成一个接口。接口可以被类实现(implements)。一个类只能继承自另一个类,但是可以实现多个接口\r\n\r\n### TypeScript中的类\r\n\r\nTypeScript 可以使用三种访问修饰符(Access Modifiers),分别是 public、private 和 protected。\r\n\r\n- public 修饰的属性或方法是公有的,可以在任何地方被访问到,默认所有的属性和方法都是 public 的\r\n- private 修饰的属性或方法是私有的,不能在声明它的类的外部访问\r\n- protected 修饰的属性或方法是受保护的,它和 private 类似,区别是它在子类中也是允许被访问的\r\n\r\n比如创建一个动物类,实例化一个狗\r\n\r\n```typescript\r\nclass Animal {\r\n public name;\r\n public constructor(name:string) {\r\n this.name = name;\r\n }\r\n}\r\n\r\nlet a = new Animal(\'大黄\');\r\nconsole.log(a.name); // 大黄\r\na.name = \'小黑\';\r\nconsole.log(a.name); // 小黑\r\n```\r\n\r\n上述可以直接修改和获取数据,对于对象数据来说是不安全的,可以通过private或者protected提高安全性。\r\n\r\n### private修饰属性\r\n\r\n使用private修饰将属性私有化,属性只能在类内部直接调用,如果要修改数据和获取数据可以通过公开的方法获取\r\n\r\n```typescript\r\nclass Animal {\r\n private name;\r\n public constructor(name:string) {\r\n this.name = name;\r\n }\r\n\r\n public getName():string {\r\n return this.name;\r\n }\r\n\r\n public setName(name:string):string {\r\n return this.name = name;\r\n }\r\n}\r\n\r\nlet a = new Animal(\'大黄\');\r\nconsole.log(a.getName()); // 大黄\r\na.setName(\'小黑\');\r\nconsole.log(a.getName()); // 小黑\r\n```\r\n\r\n### protected修饰属性\r\n\r\n被private修饰,包括子类在内都不被允许访问,只有本类内部可以访问,如果希望子类可以访问则可以使用protected修饰\r\n\r\n```typescript\r\nclass Animal {\r\n protected name;\r\n public constructor(name:string) {\r\n this.name = name;\r\n }\r\n\r\n public getName():string {\r\n return this.name;\r\n }\r\n\r\n public setName(name:string):string {\r\n return this.name = name;\r\n }\r\n}\r\n\r\nclass Dog extends Animal {\r\n constructor(name:string) {\r\n super(name);\r\n // name属性被继承过来\r\n console.log(this.name);\r\n }\r\n}\r\n```\r\n\r\n### private修饰构造方法\r\n\r\n如果构造方法通过private修饰被私有化,则该类不能被实例化,也不能被继承\r\n\r\n```typescript\r\nclass Animal {\r\n protected name;\r\n // 私有化构造方法\r\n private constructor(name:string) {\r\n this.name = name;\r\n }\r\n\r\n public getName():string {\r\n return this.name;\r\n }\r\n\r\n public setName(name:string):string {\r\n return this.name = name;\r\n }\r\n}\r\n\r\n// 继承就会报错\r\n// Cannot extend a class \'Animal\'. Class constructor is marked as private\r\nclass Dog extends Animal {\r\n constructor(name:string) {\r\n super(name);\r\n // name属性被继承过来\r\n console.log(this.name);\r\n }\r\n}\r\n```\r\n\r\n### protected 修饰构造方法\r\n\r\n如果构造函数修饰为 protected 时,该类不能实例化\r\n\r\n```typescript\r\nclass Animal {\r\n protected name;\r\n // protected修饰\r\n protected constructor(name:string) {\r\n this.name = name;\r\n }\r\n\r\n public getName():string {\r\n return this.name;\r\n }\r\n\r\n public setName(name:string):string {\r\n return this.name = name;\r\n }\r\n}\r\n// 继承没毛病\r\nclass Dog extends Animal {\r\n constructor(name:string) {\r\n super(name);\r\n // name属性被继承过来\r\n console.log(this.name);\r\n }\r\n}\r\n// 实例化有问题\r\n// Constructor of class \'Animal\' is protected and only accessible within the class declaration\r\nlet a = new Animal(\'大黄\');\r\n```\r\n\r\n### 参数属性\r\n\r\n类中属性可以定义在构造方法上,等同于类中定义了属性\r\n\r\n```typescript\r\nclass Animal {\r\n // 参数属性\r\n public constructor(public name:string) {\r\n }\r\n}\r\n\r\nlet a = new Animal(\"大黄\");\r\nconsole.log(a.name)\r\n```\r\n\r\n### readonly\r\n\r\n只读属性关键字也可用于类中,只允许出现在属性声明或索引签名或构造函数中。\r\n\r\n```typescript\r\nclass Animal {\r\n // 只读属性\r\n readonly name;\r\n public constructor(name:string) {\r\n this.name = name;\r\n }\r\n}\r\n\r\nlet a = new Animal(\'大黄\');\r\nconsole.log(a.name);\r\n// 不可再次修改\r\na.name = \'小黑\';\r\n```\r\n\r\n注意如果 readonly 和其他访问修饰符同时存在的话,需要写在其后面。\r\n\r\n```typescript\r\nclass Animal {\r\n // public readonly name;\r\n public constructor(public readonly name:string) {\r\n // this.name = name;\r\n }\r\n}\r\n```\r\n\r\n### 抽象类\r\n\r\n抽象类不能被实例化,使用abstract修饰\r\n\r\n```typescript\r\nabstract class Animal {\r\n public name;\r\n public constructor(name:string) {\r\n this.name = name;\r\n }\r\n public abstract sayHi():any;\r\n}\r\n// Cannot create an instance of an abstract class.\r\nlet a = new Animal(\'大黄\');\r\n```\r\n\r\n抽象类中的抽象方法必须被子类实现,子类必须实现抽象类中的所有抽象方法,否则需要继续抽象下去:\r\n\r\n```typescript\r\nabstract class Animal {\r\n public name;\r\n public constructor(name:string) {\r\n this.name = name;\r\n }\r\n public abstract eat():any;\r\n}\r\n\r\nclass Cat extends Animal {\r\n public eat() {\r\n console.log(`${this.name} 在吃鱼.`);\r\n }\r\n}\r\n\r\nlet c = new Cat(\'小花\');\r\nc.eat();\r\n```\r\n\r\n如果没有实现所有抽象方法则继续报错:\r\n\r\n```typescript\r\nabstract class Animal {\r\n public name;\r\n public constructor(name:string) {\r\n this.name = name;\r\n }\r\n public abstract eat():any;\r\n public abstract sayHi():any;\r\n}\r\n\r\n// Non-abstract class \'Cat\' does not implement all abstract members of \'Animal\'\r\nclass Cat extends Animal {\r\n public eat() {\r\n console.log(`${this.name} 在吃鱼.`);\r\n }\r\n}\r\n```\r\n\r\n## 泛型\r\n\r\n泛型(Generics)是指在定义函数、接口或类的时候,不预先指定具体的类型,而在使用的时候再指定类型的一种特性。\r\n\r\n### 无泛型\r\n\r\n实现一个函数 createArray,它可以创建一个指定长度的数组,同时将每一项都填充一个默认值:\r\n\r\n```typescript\r\nfunction createArray(length: number, value: any): Array<any> {\r\n let result = [];\r\n for (let i = 0; i < length; i++) {\r\n result[i] = value;\r\n }\r\n return result;\r\n}\r\n\r\ncreateArray(3, \'x\'); // [\'x\', \'x\', \'x\']\r\n```\r\n\r\n此处使用any当做入参和Array<any>反参类型,编译不会报错,但是可能会造成类型不安全的问题,调用方法的用户可能瞎传数据,你的方法就报错啦。此时泛型就登场了,**解决参数类型安全问题**\r\n\r\n```typescript\r\nfunction createArray<T>(length: number, value: T): Array<T> {\r\n let result: T[] = [];\r\n for (let i = 0; i < length; i++) {\r\n result[i] = value;\r\n }\r\n return result;\r\n}\r\n\r\ncreateArray<string>(3, \'x\'); // [\'x\', \'x\', \'x\']\r\n```\r\n\r\n上例中,我们在函数名后添加了 <T>,其中 T 用来指代任意输入的类型,在后面的输入 value: T 和输出 Array<T> 中即可使用了。\r\n接着在调用的时候,可以指定它具体的类型为 string。当然,也可以不手动指定,而让类型推论自动推算出来:\r\n\r\n```typescript\r\nfunction createArray<T>(length: number, value: T): Array<T> {\r\n let result: T[] = [];\r\n for (let i = 0; i < length; i++) {\r\n result[i] = value;\r\n }\r\n return result;\r\n}\r\n\r\ncreateArray(3, \'x\'); // [\'x\', \'x\', \'x\']\r\n```\r\n\r\n### 多个类型参数\r\n\r\n定义泛型的时候,可以一次定义多个类型参数:\r\n\r\n```typescript\r\nfunction swap<T, U>(tuple: [T, U]): [U, T] {\r\n return [tuple[1], tuple[0]];\r\n}\r\n\r\nswap([7, \'seven\']); // [\'seven\', 7]\r\n```\r\n\r\n### 泛型约束\r\n\r\n在函数内部使用泛型变量的时候,由于事先不知道它是哪种类型,所以不能随意的操作它的属性或方法:\r\n\r\n```typescript\r\nfunction loggingIdentity<T>(arg: T): T {\r\n console.log(arg.length);\r\n return arg;\r\n}\r\n```\r\n\r\n上例中,泛型 T 不一定包含属性 length,所以编译的时候报错了。\r\n这时,我们可以对泛型进行约束,只允许这个函数传入那些包含 length 属性的变量。这就是泛型约束:\r\n\r\n```typescript\r\ninterface Lengthwise {\r\n length: number;\r\n}\r\n\r\nfunction loggingIdentity<T extends Lengthwise>(arg: T): T {\r\n console.log(arg.length);\r\n return arg;\r\n}\r\n```\r\n\r\n上例中,我们使用了 extends 约束了泛型 T 必须符合接口 Lengthwise 的形状,也就是必须包含 length 属性。\r\n此时如果调用 loggingIdentity 的时候,传入的 arg 不包含 length,那么在编译阶段就会报错了:\r\n\r\n```typescript\r\ninterface Lengthwise {\r\n length: number;\r\n}\r\n\r\nfunction loggingIdentity<T extends Lengthwise>(arg: T): T {\r\n console.log(arg.length);\r\n return arg;\r\n}\r\n\r\nloggingIdentity(7);\r\n```\r\n\r\n多个类型参数之间也可以互相约束:\r\n\r\n```typescript\r\nfunction copyFields<T extends U, U>(target: T, source: U): T {\r\n for (let id in source) {\r\n target[id] = (<T>source)[id];\r\n }\r\n return target;\r\n}\r\n\r\nlet x = { a: 1, b: 2, c: 3, d: 4 };\r\n\r\ncopyFields(x, { b: 10, d: 20 });\r\n```\r\n\r\n上例中,我们使用了两个类型参数,其中要求 T 继承 U,这样就保证了 U 上不会出现 T 中不存在的字段。\r\n\r\n### 泛型接口\r\n\r\n泛型也可以用来定义接口\r\n\r\n```typescript\r\ninterface CreateArrayFunc {\r\n <T>(length: number, value: T): Array<T>;\r\n}\r\n\r\nlet createArray: CreateArrayFunc;\r\ncreateArray = function<T>(length: number, value: T): Array<T> {\r\n let result: T[] = [];\r\n for (let i = 0; i < length; i++) {\r\n result[i] = value;\r\n }\r\n return result;\r\n}\r\n\r\ncreateArray(3, \'x\'); // [\'x\', \'x\', \'x\']\r\n```\r\n\r\n进一步,我们可以把泛型参数提前到接口名上:\r\n\r\n```typescript\r\ninterface CreateArrayFunc<T> {\r\n (length: number, value: T): Array<T>;\r\n}\r\n\r\nlet createArray: CreateArrayFunc<any>;\r\ncreateArray = function<T>(length: number, value: T): Array<T> {\r\n let result: T[] = [];\r\n for (let i = 0; i < length; i++) {\r\n result[i] = value;\r\n }\r\n return result;\r\n}\r\n\r\ncreateArray(3, \'x\'); // [\'x\', \'x\', \'x\']\r\n```\r\n\r\n注意,此时在使用泛型接口的时候,需要定义泛型的类型。\r\n\r\n### 泛型类\r\n\r\n与泛型接口类似,泛型也可以用于类的类型定义中:\r\n\r\n```typescript\r\nclass GenericNumber<T> {\r\n zeroValue: T;\r\n add: (x: T, y: T) => T;\r\n}\r\n\r\nlet myGenericNumber = new GenericNumber<number>();\r\nmyGenericNumber.zeroValue = 0;\r\nmyGenericNumber.add = function(x, y) { return x + y; };\r\n```\r\n\r\n### 泛型参数的默认类型\r\n\r\n在 TypeScript 2.3 以后,我们可以为泛型中的类型参数指定默认类型。当使用泛型时没有在代码中直接指定类型参数,从实际值参数中也无法推测出时,这个默认类型就会起作用。\r\n\r\n```typescript\r\nfunction createArray<T = string>(length: number, value: T): Array<T> {\r\n let result: T[] = [];\r\n for (let i = 0; i < length; i++) {\r\n result[i] = value;\r\n }\r\n return result;\r\n}\r\n```\r\n\r\n# 类型断言\r\n\r\n类型断言(Type Assertion)可以用来手动指定一个值的类型。语法为\r\n\r\n```typescript\r\n值 as 类型\r\n\r\n或\r\n \r\n<类型>值\r\n```\r\n\r\n在 tsx 语法(React 的 jsx 语法的 ts 版)中必须使用 **值 as 类型**。\r\n\r\n## 联合类型断言为一个具体类型\r\n\r\n前文介绍了支持联合类型,即一个变量可以是string类型也可以是number类型,只能访问该变量所有类型的共有属性和方法\r\n\r\n```typescript\r\nfunction fun1(args: string | number):number {\r\n // 将值断言为number类型\r\n let result = args as number;\r\n\r\n return result;\r\n}\r\n\r\nconsole.log(fun1(\"1\"))\r\n```\r\n\r\n## 将一个父类断言为更加具体的子类\r\n\r\n当类之间有继承关系时,类型断言也是很常见的:\r\n\r\n```typescript\r\nclass Animal {\r\n name: string;\r\n constructor(name:string) {\r\n this.name = name;\r\n }\r\n}\r\n\r\nclass Dog extends Animal {\r\n constructor(name:string) {\r\n super(name);\r\n }\r\n doorkeeper():void {\r\n console.log(this.name + \"在看家\")\r\n }\r\n}\r\nclass Cat extends Animal {\r\n constructor(name:string) {\r\n super(name);\r\n }\r\n catchMouse():void {\r\n console.log(this.name + \"在抓老鼠\")\r\n }\r\n}\r\n\r\n// 离家需要狗看门,也需要猫抓老鼠\r\nfunction leaveHome(animal: Animal) {\r\n let dog = animal as Dog;\r\n dog.doorkeeper();\r\n}\r\n\r\nleaveHome(new Dog(\'旺财\'));\r\n```\r\n\r\n上面的例子中,我们声明了函数 leaveHome,转为Dog类型,调用看门方法,离家时构建一个狗对象,调用它的看门方法即可。\r\n\r\n## 断言限制\r\n\r\n类型不可随意断言,比如Dog是Animal的一种,Adimal可以断言为Dog,Cat不是Dog的一种,Cat就不能断言为Dog。如下例子:\r\n\r\n```typescript\r\nclass Animal {\r\n name: string;\r\n constructor(name:string) {\r\n this.name = name;\r\n }\r\n}\r\n\r\nclass Dog extends Animal {\r\n constructor(name:string) {\r\n super(name);\r\n }\r\n doorkeeper():void {\r\n console.log(this.name + \"在看家\")\r\n }\r\n}\r\nclass Cat extends Animal {\r\n constructor(name:string) {\r\n super(name);\r\n }\r\n catchMouse():void {\r\n console.log(this.name + \"在抓老鼠\")\r\n }\r\n}\r\n\r\n// 离家需要狗看门\r\n// 如果传入类型为Cat,断言成Dog编译不会报错,但运行时就会报错\r\nfunction leaveHome(animal: Animal) {\r\n let dog = animal as Dog;\r\n dog.doorkeeper();\r\n}\r\n// 实例化一个Cat\r\nleaveHome(new Cat(\'小花\'));\r\n```\r\n\r\n可以使用**instanceof**判断类型后对数据进行断言:\r\n\r\n```typescript\r\nclass Animal {\r\n name: string;\r\n constructor(name:string) {\r\n this.name = name;\r\n }\r\n}\r\n\r\nclass Dog extends Animal {\r\n constructor(name:string) {\r\n super(name);\r\n }\r\n doorkeeper():void {\r\n console.log(this.name + \"在看家\")\r\n }\r\n}\r\nclass Cat extends Animal {\r\n constructor(name:string) {\r\n super(name);\r\n }\r\n catchMouse():void {\r\n console.log(this.name + \"在抓老鼠\")\r\n }\r\n}\r\n\r\n// 判断类型之后\r\nfunction leaveHome(animal: Animal) {\r\n if(animal instanceof Dog) {\r\n let dog = animal as Dog;\r\n dog.doorkeeper();\r\n }else if(animal instanceof Cat) {\r\n let cat = animal as Cat;\r\n cat.catchMouse();\r\n }\r\n}\r\n\r\nleaveHome(new Cat(\'小花\'));\r\n```\r\n\r\n# 类型别名\r\n\r\n类型别名用来给一个类型起个新名字。\r\n\r\n```typescript\r\ntype Name = string;\r\ntype NameResolver = () => string;\r\ntype NameOrResolver = Name | NameResolver;\r\nfunction getName(n: NameOrResolver): Name {\r\n if (typeof n === \'string\') {\r\n return n;\r\n } else {\r\n return n();\r\n }\r\n}\r\n```\r\n\r\n上例中,我们使用 type 创建类型别名。类型别名常用于联合类型,将多个类型封装进一个类型中', 1, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, '2024-05-01 22:06:46', '2024-05-01 22:06:46', 0, 0, 'spring');
INSERT INTO `ams_article` VALUES (5, 3, 8, '标题撒大大标题撒大大标helloworld题撒大大啊实打实大啊实打实大师', 'http://localhost:8128/img/article/20240501180023A002.png', 'dfdghggdfsgffdd', '# 什么是TypeScript\r\n\r\nTypeScript于2012年10月由微软推出上线,始于JavaScript,看名字就知道TypeScript主要强调了类型,TypeScript在JaaScript基础上增加**类型系统**,JavaScript是一个弱类型语言,在编译期间声明的变量可以是任意类型,会导致运行时可能出现的类型错误,使用TypeScript之后可以指定变量类型,如果出现类型问题在编译期间就可以暴露出来,更容易查bug。\r\n最终TypScript又归于JavaScript,运行时其实还是将TypeScript转译成JavaScript执行,因为浏览器,node环境只能运行JavaScript。\r\n\r\n# 安装TypeScript\r\n\r\n首先确保您的电脑上安装了node,建议安装nodejs18以上版本。可点击链接进入[node下载地址](https://www.nodejs.com.cn/)。\r\nTypeScript需要编译为JavaScript文件执行,所以需要先安装TypeScript环境,可以将TypeScipt文件编译为JavaScript在浏览器或者node环境中运行。首先同时按下win + r键输入cmd唤起命令窗口\r\n**安装命令:**\r\n\r\n```shell\r\n# 全局安装typescript\r\nnpm install -g typescript\r\n```\r\n\r\n![image.png](http://localhost:8128/img/article/20240501180023A002.png)\r\n安装之后TypeScript的执行命令为tsc,比如想要查看TypeScript版本则可输入:\r\n\r\n```shell\r\ntsc -version\r\n```\r\n\r\n# HelloWorld\r\n\r\n## 创建文件\r\n\r\n写JavaScript时,文件后缀为.js。写TypeScript时文件后缀名为.ts。可以打开任意的编辑器整活,此处我使用VsCode开搞。以声明sting类型变量为例:\r\n\r\n```typescript\r\n// 变量title后边加上:string。指定为string类型,修改变量值时就只能是string类型\r\nlet title:string = \"Hello TypeScript\";\r\n\r\nconsole.log(title);\r\n```\r\n\r\n![image.png](http://localhost:8128/img/article/20240501180023A002.png)\r\n所以说ts声明变量的语法为:\r\n\r\n```javascript\r\n变量修饰符 变量名 : 数据类型 = 初始化值;\r\n如:var/let/const vag:number = 123;\r\n```\r\n\r\n## 编译\r\n\r\n将ts文件编译为js文件执行,使用tsc命令即可命令\r\n\r\n```shell\r\ntsc 01-hellosworld.ts\r\n```\r\n\r\n执行之后会在同级目录下生成一个同名的js文件\r\n![image.png](http://localhost:8128/img/article/20240501180023A002.png)\r\n\r\n## 执行\r\n\r\n使用node命令或者通过浏览器打开js文件来执行,如果使用node执行则使用nod命令:\r\n\r\n```shell\r\nnode 01-hellosworld.js\r\n```\r\n\r\n![image.png](http://localhost:8128/img/article/20240501180023A002.png)\r\n\r\n## 快速执行\r\n\r\n安装ts-node包实现快速运行ts,其实内部还是将ts转为js执行,底层逻辑不变,只是简化了开发人员操作。\r\n**安装命令:**\r\n\r\n```shell\r\nnpm install -g ts-node\r\n```\r\n\r\n**执行ts文件:**\r\n\r\n```shell\r\nts-node 01-hellosworld.ts\r\n```\r\n\r\n此时就不会再生成js文件啦。**但是执行的还是js哦,这是一定要记清楚的。**\r\n\r\n## 修改类型\r\n\r\n尝试将title修改为数字类型数据,如果在javascript中是可行的,类型可随意修改,在typescript中,如果修改数据类型在编译期就会报错\r\n![image.png](http://localhost:8128/img/article/20240501180023A002.png)\r\n那么忽略编辑器的报错,尝试运行会返回TSError错误,错误信息是编译TypeScript时出现问题。\r\n![image.png](http://localhost:8128/img/article/20240501180023A002.png)\r\n此处可以看出TypeScript相较于JavaScript对类型要求更严格,这也是很多开发人员吐槽的地方,以前写js\r\n随心所欲,随便定义一个变量,下边想怎么改都成,使用了ts之后只能修改值为对应类型的,好像添加了束缚,但我觉得这是好事:\r\n\r\n- 首先数据类型在逻辑处理中其实就应该输入同一个类型内的修改,严格来说是不可以将字符串类型修改为数字类型等,甚至是对象类型的数据。\r\n- 在复杂的业务处理中,甚至有时候都已经忘记了一个变量是什么类型的了😛。\r\n\r\n# TypeScript优势\r\n\r\nTypeScript包含JavaScript所有功能,同时又增加了类型系统,弥补了JavaScript弱类型的缺陷,那么为什么是缺陷呢?在ES6中JavaScript又推出了很多新的API,方便处理数据,这些api有的是字符串才能使用的,有的是数组才能使用的,有的是数字才能使用的,而JavaScript在编译时并不会检查当前变量是什么类型,能否使用调用的方法,在运行时就会出现错误。甚至会导致严重的线上bug。比如:\r\n\r\n```javascript\r\nlet arr = [1,2,3,4,5,6,7];\r\n\r\n// 将数组转为数字类型\r\narr = 1;\r\n// 调用filter方法,获取大于4的数据,此方法number类型肯定不能调用,但编译期并不会提示\r\nlet result = arr.filter(item => item > 4);\r\nconsole.log(result);\r\n\r\n```\r\n\r\n运行时就会出现TypeError即类型错误。\r\n![image.png](http://localhost:8128/img/article/20240501180023A002.png)\r\n以上错误在开发工作中比比皆是,不要妄图以为脑子好用能记住所有变量的数据类型,有时候你甚至不知道用户传过来的是什么类型的数据,所以在定义变量和方法参数时,设置明确的类型势在必行。\r\n\r\n# 数据类型\r\n\r\nTypeScript是JavaScript的扩充,所以包含JavaScript中的所有数据类型,同时又增加了若干个数据类型。下表列出TypeScript中所有的数据类型,不区分JS和TS,没有什么实际意义:\r\n\r\n| 数据类型 | 作用 |\r\n| ------------------ | ------------------------------------------------------------ |\r\n| number:数字类型 | 双精度 64 位浮点值。它可以用来表示整数和分数 |\r\n| string:字符串类型 | 描述字符或字符串,使用单引号(\')或双引号(\")来表示字符串类型。反引号(`)来定义多行文本和内嵌表达式。 |\r\n| boolean:布尔类型 | 表示逻辑值:true 和 false。 |\r\n| Object:对象 | 对象类型包括,数组、对象、函数 |\r\n| 元组 | 元组类型用来表示已知元素数量和类型的数组,各元素的类型不必相同,对应位置的类型需要相同。 |\r\n| enum:枚举 | 枚举类型用于定义数值集合。 |\r\n| any:任意类型 | 声明为 any 的变量可以赋予任意类型的值。 |\r\n| null | 表示对象值缺失。 |\r\n| undefined | 用于初始化变量为一个未定义的值 |\r\n| void | 用于标识方法返回值的类型,表示该方法没有返回值。 |\r\n| symbol | 用来声明唯一值,解决命名冲突问题 |\r\n| never | 其它类型(包括 null 和 undefined)的子类型,代表从不会出现的值。 |\r\n\r\n## number\r\n\r\n前端的JavaScript和TypeScript中没有整数和小数之分,数字类型统一使用number表示,可以使用各种进制实例化一个数字,写法如下:\r\n\r\n```typescript\r\n// 使用十进制表示\r\nlet num1: number = 6;\r\n// 十六进制\r\nlet num2: number = 0xf00d;\r\n// ES6 中的二进制表示法\r\nlet num3: number = 0b1010;\r\n// ES6 中的八进制表示法\r\nlet num4: number = 0o744;\r\n// 非数字\r\nlet num5: number = NaN;\r\n// 无穷值\r\nlet infinityNumber: number = Infinity;\r\n// 使用构造\r\nlet num1 : number = Number(1);\r\n// 使用JS中对象类型表示类型\r\nlet num2 : Number = 123;\r\n```\r\n\r\n其他数据类型都相同,可以使用构造方法初始化值,使用对象类型标识数据类型\r\n\r\n## string\r\n\r\n字符串可以通过单引号\'\'、双引号\"\"和模板字符串``创建\r\n\r\n```typescript\r\nlet s1 : string = \'单引号字符串\';\r\n\r\nlet s2 : string = \"双引号字符串\";\r\n\r\nlet s3 : string = `第一个${s1},第二个${s2}`;\r\n\r\nlet s4 : string = String(\"对象字符串\");\r\n```\r\n\r\n模板字符串可以使用${变量}方式引用变量\r\n\r\n## boolean\r\n\r\n布尔类型的值用来表示对【true】或者错【false】,在TypeScript中使用boolean表示:\r\n\r\n```typescript\r\nlet age : number = 123;\r\n\r\nlet username : string = \"username\";\r\n\r\nlet isMan : boolean = true;\r\n\r\n// 下方是错误的,new Boolean是对象类型\r\n// let isDog : boolean = new Boolean(true);\r\n\r\n// 可以直接使用Boolean()\r\nlet isDog : boolean = Boolean(true);\r\n```\r\n\r\n## 任意值\r\n\r\n可以通过使用any表示变量可以是任意类型数据,使用any效果和JavaScript相同,后期可以修改变量数据类型\r\n\r\n```typescript\r\n// any类型,初始值为string\r\nlet a1 : any = \"a1\";\r\n// 修改为number类型\r\na1 = 123;\r\n```\r\n\r\n## 类型推断\r\n\r\nTypeScript支持像JavaScript那样不显示声明数据类型,会根据赋值自动推断类型,后期则不可修改值为其他类型的数据\r\n\r\n```typescript\r\n// 类型自动推断为string\r\nlet username = \'张三\';\r\n// Type \'number\' is not assignable to type \'string\'\r\nusername = 123;\r\n```\r\n\r\n## null和undefined\r\n\r\nnull和undefined也可以被当做数据类型来定义\r\n\r\n```typescript\r\nlet nu : null = null;\r\n\r\nlet un : undefined = undefined;\r\n```\r\n\r\nnull是一个对象/变量的值为null,而undefined则表示该变量没有初始化。\r\n\r\n## void\r\n\r\nvoid为空值,是TypeScript中新增的数据类型,表示没有任何返回值的函数\r\n\r\n```typescript\r\nfunction say(): void {\r\n alert(\'我是张三\');\r\n}\r\n\r\nsay();\r\n```\r\n\r\n有些地方会比较,深究null、undefined、void区别,我认为并没有意义,null就是一个对象为空值,undefined就是没有初始值,void用来表示方法没有返回值,不要去描述变量。仅此而已不要再做无谓的深究!\r\n\r\n## 联合类型\r\n\r\n联合类型是该变量可以在声明的类型中随意匹配一个即可,比如年龄可以使用数字表示,也可以使用字符串表示,可以通过** | **符号分割多个类型\r\n\r\n```typescript\r\nlet age : number | string = \'十六\';\r\nage = 16;\r\n```\r\n\r\n如果使用联合类型表示一个变量,此时在操作变量时需要使用共有属性和方法,不能使用某一个类型特有的方法或属性,比如age可以为number或者string类型,number类型有toFixed方法,而string没有,number和string共有的操作有**toString**、**valueOf**方法。\r\n\r\n```typescript\r\nlet age : number | string = \'十六\'\r\nage = 16\r\n// 共有方法\r\nage.toString();\r\n// string有此方法,如果数字调用出现,Property \'length\' does not exist on type \'number\'\r\nage.length;\r\n```\r\n\r\n或者使用**typeof**判断类型之后使用\r\n\r\n```typescript\r\nlet age : number | string = 12\r\n\r\nif(typeof age === \'number\') {\r\n console.log(\"数字类型\")\r\n}\r\n\r\nif(typeof age === \'string\') {\r\n console.log(\"字符串类型\")\r\n}\r\n```\r\n\r\n## 数组\r\n\r\n```typescript\r\n// 通过类型[]方式指定,下例:数组中只允许有number类型数据\r\nlet a1 : number[] = [1,2,3,4];\r\n// 通过泛型指定,Array<类型>,下例:只允许有字符串\r\nlet nameArr : Array<string> = [\'大毛\',\'二毛\',\'小明\'];\r\n```\r\n\r\n## 元组\r\n\r\n元组和数组区别在于,元组中可以存在不同类型的数据。\r\n\r\n```typescript\r\n// 数据类型必须与索引一一匹配\r\nlet a1 : [number,string,number] = [1,\'a\',2];\r\n\r\n// 先声明,再赋值\r\nlet person1: [string, number];\r\nperson1 = [\'大毛\', 25];\r\n\r\n// 获取一项\r\nlet username : string = person1[0];\r\nlet age : number = person1[1];\r\n\r\n// 操作数据\r\nconsole.log(username.indexOf(\"大\"))\r\nconsole.log(age.toFixed(2));\r\n```\r\n\r\n添加越界元素时【元组本身2个元素长度,新增其他数据长度会增加,称为添加越界元素】,它的类型会被限制为元组中每个类型的联合类型:\r\n\r\n```typescript\r\n// 先声明,再赋值\r\nlet person1: [string, number] = [\'大毛\', 25];\r\n\r\nperson1.push(\"123\");\r\nperson1.push(123);\r\n\r\n// Argument of type \'boolean\' is not assignable to parameter of type \'string | number\'.\r\nperson1.push(true);\r\n```\r\n\r\n如果元组中存在可选值时可以在类型后添加?表示,如下\r\n\r\n```typescript\r\n// number类型的值可写可不写,添加?即可\r\nlet person1: [string, number?] = [\'大毛\'];\r\n```\r\n\r\n## 枚举\r\n\r\n枚举(Enum)类型用于取值被限定在一定范围内的场景,比如订单状态为未付款、待发货、待收货、待评价,性别限定为男、女、未知等。\r\n枚举成员会被赋值为从 0 开始递增的数字,同时也会对枚举值到枚举名进行反向映射:\r\n\r\n```typescript\r\nenum OrderStatus {NO_PAY, SHIPPED, RECEIVED, EVALUATED,REVIEWED};\r\n\r\n// 使用\r\nconsole.log(OrderStatus[\'NO_PAY\'] === 0);\r\nconsole.log(OrderStatus[\'SHIPPED\'] === 1);\r\nconsole.log(OrderStatus[\'RECEIVED\'] === 2);\r\n\r\nconsole.log(OrderStatus[0] === \'NO_PAY\');\r\nconsole.log(OrderStatus[1] === \'SHIPPED\');\r\nconsole.log(OrderStatus[2] === \'RECEIVED\');\r\n```\r\n\r\n你还可以通过手动赋值修改默认以0递增的数据\r\n\r\n```typescript\r\nenum OrderStatus {NO_PAY = 1, SHIPPED = 2, RECEIVED = 3, EVALUATED,REVIEWED};\r\n\r\n// 使用\r\nconsole.log(OrderStatus[\'NO_PAY\']);\r\nconsole.log(OrderStatus[\'SHIPPED\']);\r\nconsole.log(OrderStatus[\'RECEIVED\']);\r\nconsole.log(OrderStatus[\'EVALUATED\']);\r\nconsole.log(OrderStatus[\'REVIEWED\']);\r\n```\r\n\r\n## 函数\r\n\r\nTypeScript中声明函数可以在形式参数和返回值中指定数据类型。\r\n\r\n```typescript\r\n// 接收number类型参数,返回number类型参数\r\nfunction fun1(num1 : number,num2 : number) : number {\r\n\r\n return num1 + num2;\r\n}\r\nconsole.log(fun1(1,2));\r\n```\r\n\r\n也支持通过函数表达式【Function Expression】的方式声明函数\r\n\r\n```typescript\r\nlet fun2 = function(str1 : string,str2 : string) : string {\r\n\r\n return str1.concat(str2);\r\n}\r\n\r\nconsole.log(fun2(\'A\',\'B\'));\r\n```\r\n\r\n函数同样支持**可选参数**,当然可选参数必须在最后\r\n\r\n```typescript\r\nfunction buildName(firstName: string, lastName?: string) {\r\n if (lastName) {\r\n return firstName + \' \' + lastName;\r\n } else {\r\n return firstName;\r\n }\r\n}\r\nlet tomcat = buildName(\'Tom\', \'Cat\');\r\nlet tom = buildName(\'Tom\');\r\n```\r\n\r\n如果没有返回值,则可以使用**void**修饰返回值类型,无返回值时接收到的为**undefined**\r\n\r\n```typescript\r\nfunction fun1(firstName: string):void {\r\n console.log(firstName.toUpperCase());\r\n}\r\nlet result = fun1(\'Tom\');\r\nconsole.log(result);\r\n```\r\n\r\nES6中允许方法参数有默认值,**TypeScript 会将添加了默认值的参数识别为可选参数**:\r\n\r\n```typescript\r\nfunction buildName(firstName: string, lastName: string = \'Cat\') {\r\n return firstName + \' \' + lastName;\r\n}\r\nlet tomcat = buildName(\'Tom\', \'Cat\');\r\nlet tom = buildName(\'Tom\');\r\n```\r\n\r\n此时就不受「可选参数必须接在必需参数后面」的限制了:\r\n\r\n```typescript\r\nfunction buildName(firstName: string = \'Tom\', lastName: string) {\r\n return firstName + \' \' + lastName;\r\n}\r\nlet tomcat = buildName(\'Tom\', \'Cat\');\r\nlet cat = buildName(undefined, \'Cat\');\r\n```\r\n\r\nES6中可以使用 **...rest** 的方式获取函数中的剩余参数(rest 参数):\r\n\r\n```typescript\r\nfunction push(array, ...items) {\r\n items.forEach(function(item) {\r\n array.push(item);\r\n });\r\n}\r\n\r\nlet a: any[] = [];\r\npush(a, 1, 2, 3);\r\n```\r\n\r\n事实上,items 是一个数组。所以我们可以用数组的类型来定义它:\r\n\r\n```typescript\r\nfunction push(array: any[], ...items: any[]) {\r\n items.forEach(function(item) {\r\n array.push(item);\r\n });\r\n}\r\n\r\nlet a = [];\r\npush(a, 1, 2, 3);\r\n```\r\n\r\n注意,rest 参数只能是最后一个参数\r\n\r\n## 接口\r\n\r\n接口用来定义一种规范,具体的时候交由对象来做,举个生活中的例子我们购买商品按照消费者权益来说所有的商品都必须有售后保障,那么具体怎么实现售后,你是上门维修也好,直接换货也好,就有厂家自己实现。这个必须有售后就是规范,各个厂家就是一个一个具体的对象,交由对象实现就行了。\r\n程序中就是我们希望在程序内描述一个人,那么人的规范就是有名字、性别、年龄和一些行为这可以通过接口描述,具体是哪一个人,就交由对象来具体化【实例化】。\r\n\r\n```typescript\r\n// 接口定义抽象结构\r\ninterface Person {\r\n username: string;\r\n age: number;\r\n say():void;\r\n}\r\n// 对象具体实现\r\nlet tom: Person = {\r\n username: \'张三\',\r\n age: 25,\r\n say() : void {\r\n console.log(this.username)\r\n }\r\n};\r\n```\r\n\r\n### 可选属性\r\n\r\n有时认为一个对象的某个属性可有可无,可以使用可选属性\r\n\r\n```typescript\r\ninterface Person {\r\n name: string;\r\n age?: number;\r\n}\r\n\r\nlet p1: Person = {\r\n name: \'大毛\'\r\n};\r\nlet p2: Person = {\r\n name: \'小毛\',\r\n age: 25\r\n};\r\n```\r\n\r\n### 任意属性\r\n\r\n又是我们希望可以在对象中添加任意的属性:\r\n\r\n```typescript\r\ninterface Person {\r\n name: string;\r\n age?: number;\r\n [propName: string]: any;\r\n}\r\n\r\nlet tom: Person = {\r\n name: \'大毛\',\r\n gender: \'男\',\r\n};\r\n```\r\n\r\n任意属性的类型需要包含可选属性,否则编译报错,比如any包含number类型,如果将any换成string,则age可选属性就会报错\r\n\r\n### 只读属性\r\n\r\n有时候我们希望对象中的一些字段在创建的时候被赋值后就不可更改,那么可以用 readonly 定义只读属性:\r\n\r\n```typescript\r\ninterface IBook {\r\n readonly author: string;\r\n bookname: string;\r\n}\r\n\r\nlet book1: IBook = {\r\n author: \'小明\',\r\n bookname: \'TypeScript养成记\',\r\n};\r\n\r\nbook1.author = \'大毛\';\r\n```\r\n\r\n## 类\r\n\r\nES6中JavaScript引入了类的概念,类也是用来定义事物的抽象,交由对象具体实现,在面向对象的语言中,对于类我们应该熟知这么几个概念:\r\n\r\n- 类(Class):定义了一件事物的抽象特点,包含它的属性和方法\r\n- 对象(Object):类的实例,通过 new 生成\r\n- 面向对象(OOP)的三大特性:封装、继承、多态\r\n- 封装(Encapsulation):将对数据的操作细节隐藏起来,只暴露对外的接口。外界调用端不需要(也不可能)知道细节,就能通过对外提供的接口来访问该对象,同时也保证了外界无法任意更改对象内部的数据\r\n- 继承(Inheritance):子类继承父类,子类除了拥有父类的所有特性外,还有一些更具体的特性\r\n- 多态(Polymorphism):由继承而产生了相关的不同的类,对同一个方法可以有不同的响应。比如 Cat 和 Dog 都继承自 Animal,但是分别实现了自己的 eat 方法。此时针对某一个实例,我们无需了解它是 Cat 还是 Dog,就可以直接调用 eat 方法,程序会自动判断出来应该如何执行 eat\r\n- 存取器(getter & setter):用以改变属性的读取和赋值行为\r\n- 修饰符(Modifiers):修饰符是一些关键字,用于限定成员或类型的性质。比如 public 表示公有属性或方法\r\n- 抽象类(Abstract Class):抽象类是供其他类继承的基类,抽象类不允许被实例化。抽象类中的抽象方法必须在子类中被实现\r\n- 接口(Interfaces):不同类之间公有的属性或方法,可以抽象成一个接口。接口可以被类实现(implements)。一个类只能继承自另一个类,但是可以实现多个接口\r\n\r\n### TypeScript中的类\r\n\r\nTypeScript 可以使用三种访问修饰符(Access Modifiers),分别是 public、private 和 protected。\r\n\r\n- public 修饰的属性或方法是公有的,可以在任何地方被访问到,默认所有的属性和方法都是 public 的\r\n- private 修饰的属性或方法是私有的,不能在声明它的类的外部访问\r\n- protected 修饰的属性或方法是受保护的,它和 private 类似,区别是它在子类中也是允许被访问的\r\n\r\n比如创建一个动物类,实例化一个狗\r\n\r\n```typescript\r\nclass Animal {\r\n public name;\r\n public constructor(name:string) {\r\n this.name = name;\r\n }\r\n}\r\n\r\nlet a = new Animal(\'大黄\');\r\nconsole.log(a.name); // 大黄\r\na.name = \'小黑\';\r\nconsole.log(a.name); // 小黑\r\n```\r\n\r\n上述可以直接修改和获取数据,对于对象数据来说是不安全的,可以通过private或者protected提高安全性。\r\n\r\n### private修饰属性\r\n\r\n使用private修饰将属性私有化,属性只能在类内部直接调用,如果要修改数据和获取数据可以通过公开的方法获取\r\n\r\n```typescript\r\nclass Animal {\r\n private name;\r\n public constructor(name:string) {\r\n this.name = name;\r\n }\r\n\r\n public getName():string {\r\n return this.name;\r\n }\r\n\r\n public setName(name:string):string {\r\n return this.name = name;\r\n }\r\n}\r\n\r\nlet a = new Animal(\'大黄\');\r\nconsole.log(a.getName()); // 大黄\r\na.setName(\'小黑\');\r\nconsole.log(a.getName()); // 小黑\r\n```\r\n\r\n### protected修饰属性\r\n\r\n被private修饰,包括子类在内都不被允许访问,只有本类内部可以访问,如果希望子类可以访问则可以使用protected修饰\r\n\r\n```typescript\r\nclass Animal {\r\n protected name;\r\n public constructor(name:string) {\r\n this.name = name;\r\n }\r\n\r\n public getName():string {\r\n return this.name;\r\n }\r\n\r\n public setName(name:string):string {\r\n return this.name = name;\r\n }\r\n}\r\n\r\nclass Dog extends Animal {\r\n constructor(name:string) {\r\n super(name);\r\n // name属性被继承过来\r\n console.log(this.name);\r\n }\r\n}\r\n```\r\n\r\n### private修饰构造方法\r\n\r\n如果构造方法通过private修饰被私有化,则该类不能被实例化,也不能被继承\r\n\r\n```typescript\r\nclass Animal {\r\n protected name;\r\n // 私有化构造方法\r\n private constructor(name:string) {\r\n this.name = name;\r\n }\r\n\r\n public getName():string {\r\n return this.name;\r\n }\r\n\r\n public setName(name:string):string {\r\n return this.name = name;\r\n }\r\n}\r\n\r\n// 继承就会报错\r\n// Cannot extend a class \'Animal\'. Class constructor is marked as private\r\nclass Dog extends Animal {\r\n constructor(name:string) {\r\n super(name);\r\n // name属性被继承过来\r\n console.log(this.name);\r\n }\r\n}\r\n```\r\n\r\n### protected 修饰构造方法\r\n\r\n如果构造函数修饰为 protected 时,该类不能实例化\r\n\r\n```typescript\r\nclass Animal {\r\n protected name;\r\n // protected修饰\r\n protected constructor(name:string) {\r\n this.name = name;\r\n }\r\n\r\n public getName():string {\r\n return this.name;\r\n }\r\n\r\n public setName(name:string):string {\r\n return this.name = name;\r\n }\r\n}\r\n// 继承没毛病\r\nclass Dog extends Animal {\r\n constructor(name:string) {\r\n super(name);\r\n // name属性被继承过来\r\n console.log(this.name);\r\n }\r\n}\r\n// 实例化有问题\r\n// Constructor of class \'Animal\' is protected and only accessible within the class declaration\r\nlet a = new Animal(\'大黄\');\r\n```\r\n\r\n### 参数属性\r\n\r\n类中属性可以定义在构造方法上,等同于类中定义了属性\r\n\r\n```typescript\r\nclass Animal {\r\n // 参数属性\r\n public constructor(public name:string) {\r\n }\r\n}\r\n\r\nlet a = new Animal(\"大黄\");\r\nconsole.log(a.name)\r\n```\r\n\r\n### readonly\r\n\r\n只读属性关键字也可用于类中,只允许出现在属性声明或索引签名或构造函数中。\r\n\r\n```typescript\r\nclass Animal {\r\n // 只读属性\r\n readonly name;\r\n public constructor(name:string) {\r\n this.name = name;\r\n }\r\n}\r\n\r\nlet a = new Animal(\'大黄\');\r\nconsole.log(a.name);\r\n// 不可再次修改\r\na.name = \'小黑\';\r\n```\r\n\r\n注意如果 readonly 和其他访问修饰符同时存在的话,需要写在其后面。\r\n\r\n```typescript\r\nclass Animal {\r\n // public readonly name;\r\n public constructor(public readonly name:string) {\r\n // this.name = name;\r\n }\r\n}\r\n```\r\n\r\n### 抽象类\r\n\r\n抽象类不能被实例化,使用abstract修饰\r\n\r\n```typescript\r\nabstract class Animal {\r\n public name;\r\n public constructor(name:string) {\r\n this.name = name;\r\n }\r\n public abstract sayHi():any;\r\n}\r\n// Cannot create an instance of an abstract class.\r\nlet a = new Animal(\'大黄\');\r\n```\r\n\r\n抽象类中的抽象方法必须被子类实现,子类必须实现抽象类中的所有抽象方法,否则需要继续抽象下去:\r\n\r\n```typescript\r\nabstract class Animal {\r\n public name;\r\n public constructor(name:string) {\r\n this.name = name;\r\n }\r\n public abstract eat():any;\r\n}\r\n\r\nclass Cat extends Animal {\r\n public eat() {\r\n console.log(`${this.name} 在吃鱼.`);\r\n }\r\n}\r\n\r\nlet c = new Cat(\'小花\');\r\nc.eat();\r\n```\r\n\r\n如果没有实现所有抽象方法则继续报错:\r\n\r\n```typescript\r\nabstract class Animal {\r\n public name;\r\n public constructor(name:string) {\r\n this.name = name;\r\n }\r\n public abstract eat():any;\r\n public abstract sayHi():any;\r\n}\r\n\r\n// Non-abstract class \'Cat\' does not implement all abstract members of \'Animal\'\r\nclass Cat extends Animal {\r\n public eat() {\r\n console.log(`${this.name} 在吃鱼.`);\r\n }\r\n}\r\n```\r\n\r\n## 泛型\r\n\r\n泛型(Generics)是指在定义函数、接口或类的时候,不预先指定具体的类型,而在使用的时候再指定类型的一种特性。\r\n\r\n### 无泛型\r\n\r\n实现一个函数 createArray,它可以创建一个指定长度的数组,同时将每一项都填充一个默认值:\r\n\r\n```typescript\r\nfunction createArray(length: number, value: any): Array<any> {\r\n let result = [];\r\n for (let i = 0; i < length; i++) {\r\n result[i] = value;\r\n }\r\n return result;\r\n}\r\n\r\ncreateArray(3, \'x\'); // [\'x\', \'x\', \'x\']\r\n```\r\n\r\n此处使用any当做入参和Array<any>反参类型,编译不会报错,但是可能会造成类型不安全的问题,调用方法的用户可能瞎传数据,你的方法就报错啦。此时泛型就登场了,**解决参数类型安全问题**\r\n\r\n```typescript\r\nfunction createArray<T>(length: number, value: T): Array<T> {\r\n let result: T[] = [];\r\n for (let i = 0; i < length; i++) {\r\n result[i] = value;\r\n }\r\n return result;\r\n}\r\n\r\ncreateArray<string>(3, \'x\'); // [\'x\', \'x\', \'x\']\r\n```\r\n\r\n上例中,我们在函数名后添加了 <T>,其中 T 用来指代任意输入的类型,在后面的输入 value: T 和输出 Array<T> 中即可使用了。\r\n接着在调用的时候,可以指定它具体的类型为 string。当然,也可以不手动指定,而让类型推论自动推算出来:\r\n\r\n```typescript\r\nfunction createArray<T>(length: number, value: T): Array<T> {\r\n let result: T[] = [];\r\n for (let i = 0; i < length; i++) {\r\n result[i] = value;\r\n }\r\n return result;\r\n}\r\n\r\ncreateArray(3, \'x\'); // [\'x\', \'x\', \'x\']\r\n```\r\n\r\n### 多个类型参数\r\n\r\n定义泛型的时候,可以一次定义多个类型参数:\r\n\r\n```typescript\r\nfunction swap<T, U>(tuple: [T, U]): [U, T] {\r\n return [tuple[1], tuple[0]];\r\n}\r\n\r\nswap([7, \'seven\']); // [\'seven\', 7]\r\n```\r\n\r\n### 泛型约束\r\n\r\n在函数内部使用泛型变量的时候,由于事先不知道它是哪种类型,所以不能随意的操作它的属性或方法:\r\n\r\n```typescript\r\nfunction loggingIdentity<T>(arg: T): T {\r\n console.log(arg.length);\r\n return arg;\r\n}\r\n```\r\n\r\n上例中,泛型 T 不一定包含属性 length,所以编译的时候报错了。\r\n这时,我们可以对泛型进行约束,只允许这个函数传入那些包含 length 属性的变量。这就是泛型约束:\r\n\r\n```typescript\r\ninterface Lengthwise {\r\n length: number;\r\n}\r\n\r\nfunction loggingIdentity<T extends Lengthwise>(arg: T): T {\r\n console.log(arg.length);\r\n return arg;\r\n}\r\n```\r\n\r\n上例中,我们使用了 extends 约束了泛型 T 必须符合接口 Lengthwise 的形状,也就是必须包含 length 属性。\r\n此时如果调用 loggingIdentity 的时候,传入的 arg 不包含 length,那么在编译阶段就会报错了:\r\n\r\n```typescript\r\ninterface Lengthwise {\r\n length: number;\r\n}\r\n\r\nfunction loggingIdentity<T extends Lengthwise>(arg: T): T {\r\n console.log(arg.length);\r\n return arg;\r\n}\r\n\r\nloggingIdentity(7);\r\n```\r\n\r\n多个类型参数之间也可以互相约束:\r\n\r\n```typescript\r\nfunction copyFields<T extends U, U>(target: T, source: U): T {\r\n for (let id in source) {\r\n target[id] = (<T>source)[id];\r\n }\r\n return target;\r\n}\r\n\r\nlet x = { a: 1, b: 2, c: 3, d: 4 };\r\n\r\ncopyFields(x, { b: 10, d: 20 });\r\n```\r\n\r\n上例中,我们使用了两个类型参数,其中要求 T 继承 U,这样就保证了 U 上不会出现 T 中不存在的字段。\r\n\r\n### 泛型接口\r\n\r\n泛型也可以用来定义接口\r\n\r\n```typescript\r\ninterface CreateArrayFunc {\r\n <T>(length: number, value: T): Array<T>;\r\n}\r\n\r\nlet createArray: CreateArrayFunc;\r\ncreateArray = function<T>(length: number, value: T): Array<T> {\r\n let result: T[] = [];\r\n for (let i = 0; i < length; i++) {\r\n result[i] = value;\r\n }\r\n return result;\r\n}\r\n\r\ncreateArray(3, \'x\'); // [\'x\', \'x\', \'x\']\r\n```\r\n\r\n进一步,我们可以把泛型参数提前到接口名上:\r\n\r\n```typescript\r\ninterface CreateArrayFunc<T> {\r\n (length: number, value: T): Array<T>;\r\n}\r\n\r\nlet createArray: CreateArrayFunc<any>;\r\ncreateArray = function<T>(length: number, value: T): Array<T> {\r\n let result: T[] = [];\r\n for (let i = 0; i < length; i++) {\r\n result[i] = value;\r\n }\r\n return result;\r\n}\r\n\r\ncreateArray(3, \'x\'); // [\'x\', \'x\', \'x\']\r\n```\r\n\r\n注意,此时在使用泛型接口的时候,需要定义泛型的类型。\r\n\r\n### 泛型类\r\n\r\n与泛型接口类似,泛型也可以用于类的类型定义中:\r\n\r\n```typescript\r\nclass GenericNumber<T> {\r\n zeroValue: T;\r\n add: (x: T, y: T) => T;\r\n}\r\n\r\nlet myGenericNumber = new GenericNumber<number>();\r\nmyGenericNumber.zeroValue = 0;\r\nmyGenericNumber.add = function(x, y) { return x + y; };\r\n```\r\n\r\n### 泛型参数的默认类型\r\n\r\n在 TypeScript 2.3 以后,我们可以为泛型中的类型参数指定默认类型。当使用泛型时没有在代码中直接指定类型参数,从实际值参数中也无法推测出时,这个默认类型就会起作用。\r\n\r\n```typescript\r\nfunction createArray<T = string>(length: number, value: T): Array<T> {\r\n let result: T[] = [];\r\n for (let i = 0; i < length; i++) {\r\n result[i] = value;\r\n }\r\n return result;\r\n}\r\n```\r\n\r\n# 类型断言\r\n\r\n类型断言(Type Assertion)可以用来手动指定一个值的类型。语法为\r\n\r\n```typescript\r\n值 as 类型\r\n\r\n或\r\n \r\n<类型>值\r\n```\r\n\r\n在 tsx 语法(React 的 jsx 语法的 ts 版)中必须使用 **值 as 类型**。\r\n\r\n## 联合类型断言为一个具体类型\r\n\r\n前文介绍了支持联合类型,即一个变量可以是string类型也可以是number类型,只能访问该变量所有类型的共有属性和方法\r\n\r\n```typescript\r\nfunction fun1(args: string | number):number {\r\n // 将值断言为number类型\r\n let result = args as number;\r\n\r\n return result;\r\n}\r\n\r\nconsole.log(fun1(\"1\"))\r\n```\r\n\r\n## 将一个父类断言为更加具体的子类\r\n\r\n当类之间有继承关系时,类型断言也是很常见的:\r\n\r\n```typescript\r\nclass Animal {\r\n name: string;\r\n constructor(name:string) {\r\n this.name = name;\r\n }\r\n}\r\n\r\nclass Dog extends Animal {\r\n constructor(name:string) {\r\n super(name);\r\n }\r\n doorkeeper():void {\r\n console.log(this.name + \"在看家\")\r\n }\r\n}\r\nclass Cat extends Animal {\r\n constructor(name:string) {\r\n super(name);\r\n }\r\n catchMouse():void {\r\n console.log(this.name + \"在抓老鼠\")\r\n }\r\n}\r\n\r\n// 离家需要狗看门,也需要猫抓老鼠\r\nfunction leaveHome(animal: Animal) {\r\n let dog = animal as Dog;\r\n dog.doorkeeper();\r\n}\r\n\r\nleaveHome(new Dog(\'旺财\'));\r\n```\r\n\r\n上面的例子中,我们声明了函数 leaveHome,转为Dog类型,调用看门方法,离家时构建一个狗对象,调用它的看门方法即可。\r\n\r\n## 断言限制\r\n\r\n类型不可随意断言,比如Dog是Animal的一种,Adimal可以断言为Dog,Cat不是Dog的一种,Cat就不能断言为Dog。如下例子:\r\n\r\n```typescript\r\nclass Animal {\r\n name: string;\r\n constructor(name:string) {\r\n this.name = name;\r\n }\r\n}\r\n\r\nclass Dog extends Animal {\r\n constructor(name:string) {\r\n super(name);\r\n }\r\n doorkeeper():void {\r\n console.log(this.name + \"在看家\")\r\n }\r\n}\r\nclass Cat extends Animal {\r\n constructor(name:string) {\r\n super(name);\r\n }\r\n catchMouse():void {\r\n console.log(this.name + \"在抓老鼠\")\r\n }\r\n}\r\n\r\n// 离家需要狗看门\r\n// 如果传入类型为Cat,断言成Dog编译不会报错,但运行时就会报错\r\nfunction leaveHome(animal: Animal) {\r\n let dog = animal as Dog;\r\n dog.doorkeeper();\r\n}\r\n// 实例化一个Cat\r\nleaveHome(new Cat(\'小花\'));\r\n```\r\n\r\n可以使用**instanceof**判断类型后对数据进行断言:\r\n\r\n```typescript\r\nclass Animal {\r\n name: string;\r\n constructor(name:string) {\r\n this.name = name;\r\n }\r\n}\r\n\r\nclass Dog extends Animal {\r\n constructor(name:string) {\r\n super(name);\r\n }\r\n doorkeeper():void {\r\n console.log(this.name + \"在看家\")\r\n }\r\n}\r\nclass Cat extends Animal {\r\n constructor(name:string) {\r\n super(name);\r\n }\r\n catchMouse():void {\r\n console.log(this.name + \"在抓老鼠\")\r\n }\r\n}\r\n\r\n// 判断类型之后\r\nfunction leaveHome(animal: Animal) {\r\n if(animal instanceof Dog) {\r\n let dog = animal as Dog;\r\n dog.doorkeeper();\r\n }else if(animal instanceof Cat) {\r\n let cat = animal as Cat;\r\n cat.catchMouse();\r\n }\r\n}\r\n\r\nleaveHome(new Cat(\'小花\'));\r\n```\r\n\r\n# 类型别名\r\n\r\n类型别名用来给一个类型起个新名字。\r\n\r\n```typescript\r\ntype Name = string;\r\ntype NameResolver = () => string;\r\ntype NameOrResolver = Name | NameResolver;\r\nfunction getName(n: NameOrResolver): Name {\r\n if (typeof n === \'string\') {\r\n return n;\r\n } else {\r\n return n();\r\n }\r\n}\r\n```\r\n\r\n上例中,我们使用 type 创建类型别名。类型别名常用于联合类型,将多个类型封装进一个类型中', 2, 1, 1, 2, 0, 0, 0, 0, NULL, NULL, '2024-05-01 22:06:46', '2024-05-01 22:06:46', 0, 0, 'spring');
INSERT INTO `ams_article` VALUES (6, 3, 8, '标题撒大大标题撒大大标helloworld题撒大大啊实打实大啊实打实大师', 'http://localhost:8128/img/article/20240501180023A002.png', '电风扇', '# 什么是TypeScript\r\n\r\nTypeScript于2012年10月由微软推出上线,始于JavaScript,看名字就知道TypeScript主要强调了类型,TypeScript在JaaScript基础上增加**类型系统**,JavaScript是一个弱类型语言,在编译期间声明的变量可以是任意类型,会导致运行时可能出现的类型错误,使用TypeScript之后可以指定变量类型,如果出现类型问题在编译期间就可以暴露出来,更容易查bug。\r\n最终TypScript又归于JavaScript,运行时其实还是将TypeScript转译成JavaScript执行,因为浏览器,node环境只能运行JavaScript。\r\n\r\n# 安装TypeScript\r\n\r\n首先确保您的电脑上安装了node,建议安装nodejs18以上版本。可点击链接进入[node下载地址](https://www.nodejs.com.cn/)。\r\nTypeScript需要编译为JavaScript文件执行,所以需要先安装TypeScript环境,可以将TypeScipt文件编译为JavaScript在浏览器或者node环境中运行。首先同时按下win + r键输入cmd唤起命令窗口\r\n**安装命令:**\r\n\r\n```shell\r\n# 全局安装typescript\r\nnpm install -g typescript\r\n```\r\n\r\n![image.png](http://localhost:8128/img/article/20240501180023A002.png)\r\n安装之后TypeScript的执行命令为tsc,比如想要查看TypeScript版本则可输入:\r\n\r\n```shell\r\ntsc -version\r\n```\r\n\r\n# HelloWorld\r\n\r\n## 创建文件\r\n\r\n写JavaScript时,文件后缀为.js。写TypeScript时文件后缀名为.ts。可以打开任意的编辑器整活,此处我使用VsCode开搞。以声明sting类型变量为例:\r\n\r\n```typescript\r\n// 变量title后边加上:string。指定为string类型,修改变量值时就只能是string类型\r\nlet title:string = \"Hello TypeScript\";\r\n\r\nconsole.log(title);\r\n```\r\n\r\n![image.png](http://localhost:8128/img/article/20240501180023A002.png)\r\n所以说ts声明变量的语法为:\r\n\r\n```javascript\r\n变量修饰符 变量名 : 数据类型 = 初始化值;\r\n如:var/let/const vag:number = 123;\r\n```\r\n\r\n## 编译\r\n\r\n将ts文件编译为js文件执行,使用tsc命令即可命令\r\n\r\n```shell\r\ntsc 01-hellosworld.ts\r\n```\r\n\r\n执行之后会在同级目录下生成一个同名的js文件\r\n![image.png](http://localhost:8128/img/article/20240501180023A002.png)\r\n\r\n## 执行\r\n\r\n使用node命令或者通过浏览器打开js文件来执行,如果使用node执行则使用nod命令:\r\n\r\n```shell\r\nnode 01-hellosworld.js\r\n```\r\n\r\n![image.png](http://localhost:8128/img/article/20240501180023A002.png)\r\n\r\n## 快速执行\r\n\r\n安装ts-node包实现快速运行ts,其实内部还是将ts转为js执行,底层逻辑不变,只是简化了开发人员操作。\r\n**安装命令:**\r\n\r\n```shell\r\nnpm install -g ts-node\r\n```\r\n\r\n**执行ts文件:**\r\n\r\n```shell\r\nts-node 01-hellosworld.ts\r\n```\r\n\r\n此时就不会再生成js文件啦。**但是执行的还是js哦,这是一定要记清楚的。**\r\n\r\n## 修改类型\r\n\r\n尝试将title修改为数字类型数据,如果在javascript中是可行的,类型可随意修改,在typescript中,如果修改数据类型在编译期就会报错\r\n![image.png](http://localhost:8128/img/article/20240501180023A002.png)\r\n那么忽略编辑器的报错,尝试运行会返回TSError错误,错误信息是编译TypeScript时出现问题。\r\n![image.png](http://localhost:8128/img/article/20240501180023A002.png)\r\n此处可以看出TypeScript相较于JavaScript对类型要求更严格,这也是很多开发人员吐槽的地方,以前写js\r\n随心所欲,随便定义一个变量,下边想怎么改都成,使用了ts之后只能修改值为对应类型的,好像添加了束缚,但我觉得这是好事:\r\n\r\n- 首先数据类型在逻辑处理中其实就应该输入同一个类型内的修改,严格来说是不可以将字符串类型修改为数字类型等,甚至是对象类型的数据。\r\n- 在复杂的业务处理中,甚至有时候都已经忘记了一个变量是什么类型的了😛。\r\n\r\n# TypeScript优势\r\n\r\nTypeScript包含JavaScript所有功能,同时又增加了类型系统,弥补了JavaScript弱类型的缺陷,那么为什么是缺陷呢?在ES6中JavaScript又推出了很多新的API,方便处理数据,这些api有的是字符串才能使用的,有的是数组才能使用的,有的是数字才能使用的,而JavaScript在编译时并不会检查当前变量是什么类型,能否使用调用的方法,在运行时就会出现错误。甚至会导致严重的线上bug。比如:\r\n\r\n```javascript\r\nlet arr = [1,2,3,4,5,6,7];\r\n\r\n// 将数组转为数字类型\r\narr = 1;\r\n// 调用filter方法,获取大于4的数据,此方法number类型肯定不能调用,但编译期并不会提示\r\nlet result = arr.filter(item => item > 4);\r\nconsole.log(result);\r\n\r\n```\r\n\r\n运行时就会出现TypeError即类型错误。\r\n![image.png](http://localhost:8128/img/article/20240501180023A002.png)\r\n以上错误在开发工作中比比皆是,不要妄图以为脑子好用能记住所有变量的数据类型,有时候你甚至不知道用户传过来的是什么类型的数据,所以在定义变量和方法参数时,设置明确的类型势在必行。\r\n\r\n# 数据类型\r\n\r\nTypeScript是JavaScript的扩充,所以包含JavaScript中的所有数据类型,同时又增加了若干个数据类型。下表列出TypeScript中所有的数据类型,不区分JS和TS,没有什么实际意义:\r\n\r\n| 数据类型 | 作用 |\r\n| ------------------ | ------------------------------------------------------------ |\r\n| number:数字类型 | 双精度 64 位浮点值。它可以用来表示整数和分数 |\r\n| string:字符串类型 | 描述字符或字符串,使用单引号(\')或双引号(\")来表示字符串类型。反引号(`)来定义多行文本和内嵌表达式。 |\r\n| boolean:布尔类型 | 表示逻辑值:true 和 false。 |\r\n| Object:对象 | 对象类型包括,数组、对象、函数 |\r\n| 元组 | 元组类型用来表示已知元素数量和类型的数组,各元素的类型不必相同,对应位置的类型需要相同。 |\r\n| enum:枚举 | 枚举类型用于定义数值集合。 |\r\n| any:任意类型 | 声明为 any 的变量可以赋予任意类型的值。 |\r\n| null | 表示对象值缺失。 |\r\n| undefined | 用于初始化变量为一个未定义的值 |\r\n| void | 用于标识方法返回值的类型,表示该方法没有返回值。 |\r\n| symbol | 用来声明唯一值,解决命名冲突问题 |\r\n| never | 其它类型(包括 null 和 undefined)的子类型,代表从不会出现的值。 |\r\n\r\n## number\r\n\r\n前端的JavaScript和TypeScript中没有整数和小数之分,数字类型统一使用number表示,可以使用各种进制实例化一个数字,写法如下:\r\n\r\n```typescript\r\n// 使用十进制表示\r\nlet num1: number = 6;\r\n// 十六进制\r\nlet num2: number = 0xf00d;\r\n// ES6 中的二进制表示法\r\nlet num3: number = 0b1010;\r\n// ES6 中的八进制表示法\r\nlet num4: number = 0o744;\r\n// 非数字\r\nlet num5: number = NaN;\r\n// 无穷值\r\nlet infinityNumber: number = Infinity;\r\n// 使用构造\r\nlet num1 : number = Number(1);\r\n// 使用JS中对象类型表示类型\r\nlet num2 : Number = 123;\r\n```\r\n\r\n其他数据类型都相同,可以使用构造方法初始化值,使用对象类型标识数据类型\r\n\r\n## string\r\n\r\n字符串可以通过单引号\'\'、双引号\"\"和模板字符串``创建\r\n\r\n```typescript\r\nlet s1 : string = \'单引号字符串\';\r\n\r\nlet s2 : string = \"双引号字符串\";\r\n\r\nlet s3 : string = `第一个${s1},第二个${s2}`;\r\n\r\nlet s4 : string = String(\"对象字符串\");\r\n```\r\n\r\n模板字符串可以使用${变量}方式引用变量\r\n\r\n## boolean\r\n\r\n布尔类型的值用来表示对【true】或者错【false】,在TypeScript中使用boolean表示:\r\n\r\n```typescript\r\nlet age : number = 123;\r\n\r\nlet username : string = \"username\";\r\n\r\nlet isMan : boolean = true;\r\n\r\n// 下方是错误的,new Boolean是对象类型\r\n// let isDog : boolean = new Boolean(true);\r\n\r\n// 可以直接使用Boolean()\r\nlet isDog : boolean = Boolean(true);\r\n```\r\n\r\n## 任意值\r\n\r\n可以通过使用any表示变量可以是任意类型数据,使用any效果和JavaScript相同,后期可以修改变量数据类型\r\n\r\n```typescript\r\n// any类型,初始值为string\r\nlet a1 : any = \"a1\";\r\n// 修改为number类型\r\na1 = 123;\r\n```\r\n\r\n## 类型推断\r\n\r\nTypeScript支持像JavaScript那样不显示声明数据类型,会根据赋值自动推断类型,后期则不可修改值为其他类型的数据\r\n\r\n```typescript\r\n// 类型自动推断为string\r\nlet username = \'张三\';\r\n// Type \'number\' is not assignable to type \'string\'\r\nusername = 123;\r\n```\r\n\r\n## null和undefined\r\n\r\nnull和undefined也可以被当做数据类型来定义\r\n\r\n```typescript\r\nlet nu : null = null;\r\n\r\nlet un : undefined = undefined;\r\n```\r\n\r\nnull是一个对象/变量的值为null,而undefined则表示该变量没有初始化。\r\n\r\n## void\r\n\r\nvoid为空值,是TypeScript中新增的数据类型,表示没有任何返回值的函数\r\n\r\n```typescript\r\nfunction say(): void {\r\n alert(\'我是张三\');\r\n}\r\n\r\nsay();\r\n```\r\n\r\n有些地方会比较,深究null、undefined、void区别,我认为并没有意义,null就是一个对象为空值,undefined就是没有初始值,void用来表示方法没有返回值,不要去描述变量。仅此而已不要再做无谓的深究!\r\n\r\n## 联合类型\r\n\r\n联合类型是该变量可以在声明的类型中随意匹配一个即可,比如年龄可以使用数字表示,也可以使用字符串表示,可以通过** | **符号分割多个类型\r\n\r\n```typescript\r\nlet age : number | string = \'十六\';\r\nage = 16;\r\n```\r\n\r\n如果使用联合类型表示一个变量,此时在操作变量时需要使用共有属性和方法,不能使用某一个类型特有的方法或属性,比如age可以为number或者string类型,number类型有toFixed方法,而string没有,number和string共有的操作有**toString**、**valueOf**方法。\r\n\r\n```typescript\r\nlet age : number | string = \'十六\'\r\nage = 16\r\n// 共有方法\r\nage.toString();\r\n// string有此方法,如果数字调用出现,Property \'length\' does not exist on type \'number\'\r\nage.length;\r\n```\r\n\r\n或者使用**typeof**判断类型之后使用\r\n\r\n```typescript\r\nlet age : number | string = 12\r\n\r\nif(typeof age === \'number\') {\r\n console.log(\"数字类型\")\r\n}\r\n\r\nif(typeof age === \'string\') {\r\n console.log(\"字符串类型\")\r\n}\r\n```\r\n\r\n## 数组\r\n\r\n```typescript\r\n// 通过类型[]方式指定,下例:数组中只允许有number类型数据\r\nlet a1 : number[] = [1,2,3,4];\r\n// 通过泛型指定,Array<类型>,下例:只允许有字符串\r\nlet nameArr : Array<string> = [\'大毛\',\'二毛\',\'小明\'];\r\n```\r\n\r\n## 元组\r\n\r\n元组和数组区别在于,元组中可以存在不同类型的数据。\r\n\r\n```typescript\r\n// 数据类型必须与索引一一匹配\r\nlet a1 : [number,string,number] = [1,\'a\',2];\r\n\r\n// 先声明,再赋值\r\nlet person1: [string, number];\r\nperson1 = [\'大毛\', 25];\r\n\r\n// 获取一项\r\nlet username : string = person1[0];\r\nlet age : number = person1[1];\r\n\r\n// 操作数据\r\nconsole.log(username.indexOf(\"大\"))\r\nconsole.log(age.toFixed(2));\r\n```\r\n\r\n添加越界元素时【元组本身2个元素长度,新增其他数据长度会增加,称为添加越界元素】,它的类型会被限制为元组中每个类型的联合类型:\r\n\r\n```typescript\r\n// 先声明,再赋值\r\nlet person1: [string, number] = [\'大毛\', 25];\r\n\r\nperson1.push(\"123\");\r\nperson1.push(123);\r\n\r\n// Argument of type \'boolean\' is not assignable to parameter of type \'string | number\'.\r\nperson1.push(true);\r\n```\r\n\r\n如果元组中存在可选值时可以在类型后添加?表示,如下\r\n\r\n```typescript\r\n// number类型的值可写可不写,添加?即可\r\nlet person1: [string, number?] = [\'大毛\'];\r\n```\r\n\r\n## 枚举\r\n\r\n枚举(Enum)类型用于取值被限定在一定范围内的场景,比如订单状态为未付款、待发货、待收货、待评价,性别限定为男、女、未知等。\r\n枚举成员会被赋值为从 0 开始递增的数字,同时也会对枚举值到枚举名进行反向映射:\r\n\r\n```typescript\r\nenum OrderStatus {NO_PAY, SHIPPED, RECEIVED, EVALUATED,REVIEWED};\r\n\r\n// 使用\r\nconsole.log(OrderStatus[\'NO_PAY\'] === 0);\r\nconsole.log(OrderStatus[\'SHIPPED\'] === 1);\r\nconsole.log(OrderStatus[\'RECEIVED\'] === 2);\r\n\r\nconsole.log(OrderStatus[0] === \'NO_PAY\');\r\nconsole.log(OrderStatus[1] === \'SHIPPED\');\r\nconsole.log(OrderStatus[2] === \'RECEIVED\');\r\n```\r\n\r\n你还可以通过手动赋值修改默认以0递增的数据\r\n\r\n```typescript\r\nenum OrderStatus {NO_PAY = 1, SHIPPED = 2, RECEIVED = 3, EVALUATED,REVIEWED};\r\n\r\n// 使用\r\nconsole.log(OrderStatus[\'NO_PAY\']);\r\nconsole.log(OrderStatus[\'SHIPPED\']);\r\nconsole.log(OrderStatus[\'RECEIVED\']);\r\nconsole.log(OrderStatus[\'EVALUATED\']);\r\nconsole.log(OrderStatus[\'REVIEWED\']);\r\n```\r\n\r\n## 函数\r\n\r\nTypeScript中声明函数可以在形式参数和返回值中指定数据类型。\r\n\r\n```typescript\r\n// 接收number类型参数,返回number类型参数\r\nfunction fun1(num1 : number,num2 : number) : number {\r\n\r\n return num1 + num2;\r\n}\r\nconsole.log(fun1(1,2));\r\n```\r\n\r\n也支持通过函数表达式【Function Expression】的方式声明函数\r\n\r\n```typescript\r\nlet fun2 = function(str1 : string,str2 : string) : string {\r\n\r\n return str1.concat(str2);\r\n}\r\n\r\nconsole.log(fun2(\'A\',\'B\'));\r\n```\r\n\r\n函数同样支持**可选参数**,当然可选参数必须在最后\r\n\r\n```typescript\r\nfunction buildName(firstName: string, lastName?: string) {\r\n if (lastName) {\r\n return firstName + \' \' + lastName;\r\n } else {\r\n return firstName;\r\n }\r\n}\r\nlet tomcat = buildName(\'Tom\', \'Cat\');\r\nlet tom = buildName(\'Tom\');\r\n```\r\n\r\n如果没有返回值,则可以使用**void**修饰返回值类型,无返回值时接收到的为**undefined**\r\n\r\n```typescript\r\nfunction fun1(firstName: string):void {\r\n console.log(firstName.toUpperCase());\r\n}\r\nlet result = fun1(\'Tom\');\r\nconsole.log(result);\r\n```\r\n\r\nES6中允许方法参数有默认值,**TypeScript 会将添加了默认值的参数识别为可选参数**:\r\n\r\n```typescript\r\nfunction buildName(firstName: string, lastName: string = \'Cat\') {\r\n return firstName + \' \' + lastName;\r\n}\r\nlet tomcat = buildName(\'Tom\', \'Cat\');\r\nlet tom = buildName(\'Tom\');\r\n```\r\n\r\n此时就不受「可选参数必须接在必需参数后面」的限制了:\r\n\r\n```typescript\r\nfunction buildName(firstName: string = \'Tom\', lastName: string) {\r\n return firstName + \' \' + lastName;\r\n}\r\nlet tomcat = buildName(\'Tom\', \'Cat\');\r\nlet cat = buildName(undefined, \'Cat\');\r\n```\r\n\r\nES6中可以使用 **...rest** 的方式获取函数中的剩余参数(rest 参数):\r\n\r\n```typescript\r\nfunction push(array, ...items) {\r\n items.forEach(function(item) {\r\n array.push(item);\r\n });\r\n}\r\n\r\nlet a: any[] = [];\r\npush(a, 1, 2, 3);\r\n```\r\n\r\n事实上,items 是一个数组。所以我们可以用数组的类型来定义它:\r\n\r\n```typescript\r\nfunction push(array: any[], ...items: any[]) {\r\n items.forEach(function(item) {\r\n array.push(item);\r\n });\r\n}\r\n\r\nlet a = [];\r\npush(a, 1, 2, 3);\r\n```\r\n\r\n注意,rest 参数只能是最后一个参数\r\n\r\n## 接口\r\n\r\n接口用来定义一种规范,具体的时候交由对象来做,举个生活中的例子我们购买商品按照消费者权益来说所有的商品都必须有售后保障,那么具体怎么实现售后,你是上门维修也好,直接换货也好,就有厂家自己实现。这个必须有售后就是规范,各个厂家就是一个一个具体的对象,交由对象实现就行了。\r\n程序中就是我们希望在程序内描述一个人,那么人的规范就是有名字、性别、年龄和一些行为这可以通过接口描述,具体是哪一个人,就交由对象来具体化【实例化】。\r\n\r\n```typescript\r\n// 接口定义抽象结构\r\ninterface Person {\r\n username: string;\r\n age: number;\r\n say():void;\r\n}\r\n// 对象具体实现\r\nlet tom: Person = {\r\n username: \'张三\',\r\n age: 25,\r\n say() : void {\r\n console.log(this.username)\r\n }\r\n};\r\n```\r\n\r\n### 可选属性\r\n\r\n有时认为一个对象的某个属性可有可无,可以使用可选属性\r\n\r\n```typescript\r\ninterface Person {\r\n name: string;\r\n age?: number;\r\n}\r\n\r\nlet p1: Person = {\r\n name: \'大毛\'\r\n};\r\nlet p2: Person = {\r\n name: \'小毛\',\r\n age: 25\r\n};\r\n```\r\n\r\n### 任意属性\r\n\r\n又是我们希望可以在对象中添加任意的属性:\r\n\r\n```typescript\r\ninterface Person {\r\n name: string;\r\n age?: number;\r\n [propName: string]: any;\r\n}\r\n\r\nlet tom: Person = {\r\n name: \'大毛\',\r\n gender: \'男\',\r\n};\r\n```\r\n\r\n任意属性的类型需要包含可选属性,否则编译报错,比如any包含number类型,如果将any换成string,则age可选属性就会报错\r\n\r\n### 只读属性\r\n\r\n有时候我们希望对象中的一些字段在创建的时候被赋值后就不可更改,那么可以用 readonly 定义只读属性:\r\n\r\n```typescript\r\ninterface IBook {\r\n readonly author: string;\r\n bookname: string;\r\n}\r\n\r\nlet book1: IBook = {\r\n author: \'小明\',\r\n bookname: \'TypeScript养成记\',\r\n};\r\n\r\nbook1.author = \'大毛\';\r\n```\r\n\r\n## 类\r\n\r\nES6中JavaScript引入了类的概念,类也是用来定义事物的抽象,交由对象具体实现,在面向对象的语言中,对于类我们应该熟知这么几个概念:\r\n\r\n- 类(Class):定义了一件事物的抽象特点,包含它的属性和方法\r\n- 对象(Object):类的实例,通过 new 生成\r\n- 面向对象(OOP)的三大特性:封装、继承、多态\r\n- 封装(Encapsulation):将对数据的操作细节隐藏起来,只暴露对外的接口。外界调用端不需要(也不可能)知道细节,就能通过对外提供的接口来访问该对象,同时也保证了外界无法任意更改对象内部的数据\r\n- 继承(Inheritance):子类继承父类,子类除了拥有父类的所有特性外,还有一些更具体的特性\r\n- 多态(Polymorphism):由继承而产生了相关的不同的类,对同一个方法可以有不同的响应。比如 Cat 和 Dog 都继承自 Animal,但是分别实现了自己的 eat 方法。此时针对某一个实例,我们无需了解它是 Cat 还是 Dog,就可以直接调用 eat 方法,程序会自动判断出来应该如何执行 eat\r\n- 存取器(getter & setter):用以改变属性的读取和赋值行为\r\n- 修饰符(Modifiers):修饰符是一些关键字,用于限定成员或类型的性质。比如 public 表示公有属性或方法\r\n- 抽象类(Abstract Class):抽象类是供其他类继承的基类,抽象类不允许被实例化。抽象类中的抽象方法必须在子类中被实现\r\n- 接口(Interfaces):不同类之间公有的属性或方法,可以抽象成一个接口。接口可以被类实现(implements)。一个类只能继承自另一个类,但是可以实现多个接口\r\n\r\n### TypeScript中的类\r\n\r\nTypeScript 可以使用三种访问修饰符(Access Modifiers),分别是 public、private 和 protected。\r\n\r\n- public 修饰的属性或方法是公有的,可以在任何地方被访问到,默认所有的属性和方法都是 public 的\r\n- private 修饰的属性或方法是私有的,不能在声明它的类的外部访问\r\n- protected 修饰的属性或方法是受保护的,它和 private 类似,区别是它在子类中也是允许被访问的\r\n\r\n比如创建一个动物类,实例化一个狗\r\n\r\n```typescript\r\nclass Animal {\r\n public name;\r\n public constructor(name:string) {\r\n this.name = name;\r\n }\r\n}\r\n\r\nlet a = new Animal(\'大黄\');\r\nconsole.log(a.name); // 大黄\r\na.name = \'小黑\';\r\nconsole.log(a.name); // 小黑\r\n```\r\n\r\n上述可以直接修改和获取数据,对于对象数据来说是不安全的,可以通过private或者protected提高安全性。\r\n\r\n### private修饰属性\r\n\r\n使用private修饰将属性私有化,属性只能在类内部直接调用,如果要修改数据和获取数据可以通过公开的方法获取\r\n\r\n```typescript\r\nclass Animal {\r\n private name;\r\n public constructor(name:string) {\r\n this.name = name;\r\n }\r\n\r\n public getName():string {\r\n return this.name;\r\n }\r\n\r\n public setName(name:string):string {\r\n return this.name = name;\r\n }\r\n}\r\n\r\nlet a = new Animal(\'大黄\');\r\nconsole.log(a.getName()); // 大黄\r\na.setName(\'小黑\');\r\nconsole.log(a.getName()); // 小黑\r\n```\r\n\r\n### protected修饰属性\r\n\r\n被private修饰,包括子类在内都不被允许访问,只有本类内部可以访问,如果希望子类可以访问则可以使用protected修饰\r\n\r\n```typescript\r\nclass Animal {\r\n protected name;\r\n public constructor(name:string) {\r\n this.name = name;\r\n }\r\n\r\n public getName():string {\r\n return this.name;\r\n }\r\n\r\n public setName(name:string):string {\r\n return this.name = name;\r\n }\r\n}\r\n\r\nclass Dog extends Animal {\r\n constructor(name:string) {\r\n super(name);\r\n // name属性被继承过来\r\n console.log(this.name);\r\n }\r\n}\r\n```\r\n\r\n### private修饰构造方法\r\n\r\n如果构造方法通过private修饰被私有化,则该类不能被实例化,也不能被继承\r\n\r\n```typescript\r\nclass Animal {\r\n protected name;\r\n // 私有化构造方法\r\n private constructor(name:string) {\r\n this.name = name;\r\n }\r\n\r\n public getName():string {\r\n return this.name;\r\n }\r\n\r\n public setName(name:string):string {\r\n return this.name = name;\r\n }\r\n}\r\n\r\n// 继承就会报错\r\n// Cannot extend a class \'Animal\'. Class constructor is marked as private\r\nclass Dog extends Animal {\r\n constructor(name:string) {\r\n super(name);\r\n // name属性被继承过来\r\n console.log(this.name);\r\n }\r\n}\r\n```\r\n\r\n### protected 修饰构造方法\r\n\r\n如果构造函数修饰为 protected 时,该类不能实例化\r\n\r\n```typescript\r\nclass Animal {\r\n protected name;\r\n // protected修饰\r\n protected constructor(name:string) {\r\n this.name = name;\r\n }\r\n\r\n public getName():string {\r\n return this.name;\r\n }\r\n\r\n public setName(name:string):string {\r\n return this.name = name;\r\n }\r\n}\r\n// 继承没毛病\r\nclass Dog extends Animal {\r\n constructor(name:string) {\r\n super(name);\r\n // name属性被继承过来\r\n console.log(this.name);\r\n }\r\n}\r\n// 实例化有问题\r\n// Constructor of class \'Animal\' is protected and only accessible within the class declaration\r\nlet a = new Animal(\'大黄\');\r\n```\r\n\r\n### 参数属性\r\n\r\n类中属性可以定义在构造方法上,等同于类中定义了属性\r\n\r\n```typescript\r\nclass Animal {\r\n // 参数属性\r\n public constructor(public name:string) {\r\n }\r\n}\r\n\r\nlet a = new Animal(\"大黄\");\r\nconsole.log(a.name)\r\n```\r\n\r\n### readonly\r\n\r\n只读属性关键字也可用于类中,只允许出现在属性声明或索引签名或构造函数中。\r\n\r\n```typescript\r\nclass Animal {\r\n // 只读属性\r\n readonly name;\r\n public constructor(name:string) {\r\n this.name = name;\r\n }\r\n}\r\n\r\nlet a = new Animal(\'大黄\');\r\nconsole.log(a.name);\r\n// 不可再次修改\r\na.name = \'小黑\';\r\n```\r\n\r\n注意如果 readonly 和其他访问修饰符同时存在的话,需要写在其后面。\r\n\r\n```typescript\r\nclass Animal {\r\n // public readonly name;\r\n public constructor(public readonly name:string) {\r\n // this.name = name;\r\n }\r\n}\r\n```\r\n\r\n### 抽象类\r\n\r\n抽象类不能被实例化,使用abstract修饰\r\n\r\n```typescript\r\nabstract class Animal {\r\n public name;\r\n public constructor(name:string) {\r\n this.name = name;\r\n }\r\n public abstract sayHi():any;\r\n}\r\n// Cannot create an instance of an abstract class.\r\nlet a = new Animal(\'大黄\');\r\n```\r\n\r\n抽象类中的抽象方法必须被子类实现,子类必须实现抽象类中的所有抽象方法,否则需要继续抽象下去:\r\n\r\n```typescript\r\nabstract class Animal {\r\n public name;\r\n public constructor(name:string) {\r\n this.name = name;\r\n }\r\n public abstract eat():any;\r\n}\r\n\r\nclass Cat extends Animal {\r\n public eat() {\r\n console.log(`${this.name} 在吃鱼.`);\r\n }\r\n}\r\n\r\nlet c = new Cat(\'小花\');\r\nc.eat();\r\n```\r\n\r\n如果没有实现所有抽象方法则继续报错:\r\n\r\n```typescript\r\nabstract class Animal {\r\n public name;\r\n public constructor(name:string) {\r\n this.name = name;\r\n }\r\n public abstract eat():any;\r\n public abstract sayHi():any;\r\n}\r\n\r\n// Non-abstract class \'Cat\' does not implement all abstract members of \'Animal\'\r\nclass Cat extends Animal {\r\n public eat() {\r\n console.log(`${this.name} 在吃鱼.`);\r\n }\r\n}\r\n```\r\n\r\n## 泛型\r\n\r\n泛型(Generics)是指在定义函数、接口或类的时候,不预先指定具体的类型,而在使用的时候再指定类型的一种特性。\r\n\r\n### 无泛型\r\n\r\n实现一个函数 createArray,它可以创建一个指定长度的数组,同时将每一项都填充一个默认值:\r\n\r\n```typescript\r\nfunction createArray(length: number, value: any): Array<any> {\r\n let result = [];\r\n for (let i = 0; i < length; i++) {\r\n result[i] = value;\r\n }\r\n return result;\r\n}\r\n\r\ncreateArray(3, \'x\'); // [\'x\', \'x\', \'x\']\r\n```\r\n\r\n此处使用any当做入参和Array<any>反参类型,编译不会报错,但是可能会造成类型不安全的问题,调用方法的用户可能瞎传数据,你的方法就报错啦。此时泛型就登场了,**解决参数类型安全问题**\r\n\r\n```typescript\r\nfunction createArray<T>(length: number, value: T): Array<T> {\r\n let result: T[] = [];\r\n for (let i = 0; i < length; i++) {\r\n result[i] = value;\r\n }\r\n return result;\r\n}\r\n\r\ncreateArray<string>(3, \'x\'); // [\'x\', \'x\', \'x\']\r\n```\r\n\r\n上例中,我们在函数名后添加了 <T>,其中 T 用来指代任意输入的类型,在后面的输入 value: T 和输出 Array<T> 中即可使用了。\r\n接着在调用的时候,可以指定它具体的类型为 string。当然,也可以不手动指定,而让类型推论自动推算出来:\r\n\r\n```typescript\r\nfunction createArray<T>(length: number, value: T): Array<T> {\r\n let result: T[] = [];\r\n for (let i = 0; i < length; i++) {\r\n result[i] = value;\r\n }\r\n return result;\r\n}\r\n\r\ncreateArray(3, \'x\'); // [\'x\', \'x\', \'x\']\r\n```\r\n\r\n### 多个类型参数\r\n\r\n定义泛型的时候,可以一次定义多个类型参数:\r\n\r\n```typescript\r\nfunction swap<T, U>(tuple: [T, U]): [U, T] {\r\n return [tuple[1], tuple[0]];\r\n}\r\n\r\nswap([7, \'seven\']); // [\'seven\', 7]\r\n```\r\n\r\n### 泛型约束\r\n\r\n在函数内部使用泛型变量的时候,由于事先不知道它是哪种类型,所以不能随意的操作它的属性或方法:\r\n\r\n```typescript\r\nfunction loggingIdentity<T>(arg: T): T {\r\n console.log(arg.length);\r\n return arg;\r\n}\r\n```\r\n\r\n上例中,泛型 T 不一定包含属性 length,所以编译的时候报错了。\r\n这时,我们可以对泛型进行约束,只允许这个函数传入那些包含 length 属性的变量。这就是泛型约束:\r\n\r\n```typescript\r\ninterface Lengthwise {\r\n length: number;\r\n}\r\n\r\nfunction loggingIdentity<T extends Lengthwise>(arg: T): T {\r\n console.log(arg.length);\r\n return arg;\r\n}\r\n```\r\n\r\n上例中,我们使用了 extends 约束了泛型 T 必须符合接口 Lengthwise 的形状,也就是必须包含 length 属性。\r\n此时如果调用 loggingIdentity 的时候,传入的 arg 不包含 length,那么在编译阶段就会报错了:\r\n\r\n```typescript\r\ninterface Lengthwise {\r\n length: number;\r\n}\r\n\r\nfunction loggingIdentity<T extends Lengthwise>(arg: T): T {\r\n console.log(arg.length);\r\n return arg;\r\n}\r\n\r\nloggingIdentity(7);\r\n```\r\n\r\n多个类型参数之间也可以互相约束:\r\n\r\n```typescript\r\nfunction copyFields<T extends U, U>(target: T, source: U): T {\r\n for (let id in source) {\r\n target[id] = (<T>source)[id];\r\n }\r\n return target;\r\n}\r\n\r\nlet x = { a: 1, b: 2, c: 3, d: 4 };\r\n\r\ncopyFields(x, { b: 10, d: 20 });\r\n```\r\n\r\n上例中,我们使用了两个类型参数,其中要求 T 继承 U,这样就保证了 U 上不会出现 T 中不存在的字段。\r\n\r\n### 泛型接口\r\n\r\n泛型也可以用来定义接口\r\n\r\n```typescript\r\ninterface CreateArrayFunc {\r\n <T>(length: number, value: T): Array<T>;\r\n}\r\n\r\nlet createArray: CreateArrayFunc;\r\ncreateArray = function<T>(length: number, value: T): Array<T> {\r\n let result: T[] = [];\r\n for (let i = 0; i < length; i++) {\r\n result[i] = value;\r\n }\r\n return result;\r\n}\r\n\r\ncreateArray(3, \'x\'); // [\'x\', \'x\', \'x\']\r\n```\r\n\r\n进一步,我们可以把泛型参数提前到接口名上:\r\n\r\n```typescript\r\ninterface CreateArrayFunc<T> {\r\n (length: number, value: T): Array<T>;\r\n}\r\n\r\nlet createArray: CreateArrayFunc<any>;\r\ncreateArray = function<T>(length: number, value: T): Array<T> {\r\n let result: T[] = [];\r\n for (let i = 0; i < length; i++) {\r\n result[i] = value;\r\n }\r\n return result;\r\n}\r\n\r\ncreateArray(3, \'x\'); // [\'x\', \'x\', \'x\']\r\n```\r\n\r\n注意,此时在使用泛型接口的时候,需要定义泛型的类型。\r\n\r\n### 泛型类\r\n\r\n与泛型接口类似,泛型也可以用于类的类型定义中:\r\n\r\n```typescript\r\nclass GenericNumber<T> {\r\n zeroValue: T;\r\n add: (x: T, y: T) => T;\r\n}\r\n\r\nlet myGenericNumber = new GenericNumber<number>();\r\nmyGenericNumber.zeroValue = 0;\r\nmyGenericNumber.add = function(x, y) { return x + y; };\r\n```\r\n\r\n### 泛型参数的默认类型\r\n\r\n在 TypeScript 2.3 以后,我们可以为泛型中的类型参数指定默认类型。当使用泛型时没有在代码中直接指定类型参数,从实际值参数中也无法推测出时,这个默认类型就会起作用。\r\n\r\n```typescript\r\nfunction createArray<T = string>(length: number, value: T): Array<T> {\r\n let result: T[] = [];\r\n for (let i = 0; i < length; i++) {\r\n result[i] = value;\r\n }\r\n return result;\r\n}\r\n```\r\n\r\n# 类型断言\r\n\r\n类型断言(Type Assertion)可以用来手动指定一个值的类型。语法为\r\n\r\n```typescript\r\n值 as 类型\r\n\r\n或\r\n \r\n<类型>值\r\n```\r\n\r\n在 tsx 语法(React 的 jsx 语法的 ts 版)中必须使用 **值 as 类型**。\r\n\r\n## 联合类型断言为一个具体类型\r\n\r\n前文介绍了支持联合类型,即一个变量可以是string类型也可以是number类型,只能访问该变量所有类型的共有属性和方法\r\n\r\n```typescript\r\nfunction fun1(args: string | number):number {\r\n // 将值断言为number类型\r\n let result = args as number;\r\n\r\n return result;\r\n}\r\n\r\nconsole.log(fun1(\"1\"))\r\n```\r\n\r\n## 将一个父类断言为更加具体的子类\r\n\r\n当类之间有继承关系时,类型断言也是很常见的:\r\n\r\n```typescript\r\nclass Animal {\r\n name: string;\r\n constructor(name:string) {\r\n this.name = name;\r\n }\r\n}\r\n\r\nclass Dog extends Animal {\r\n constructor(name:string) {\r\n super(name);\r\n }\r\n doorkeeper():void {\r\n console.log(this.name + \"在看家\")\r\n }\r\n}\r\nclass Cat extends Animal {\r\n constructor(name:string) {\r\n super(name);\r\n }\r\n catchMouse():void {\r\n console.log(this.name + \"在抓老鼠\")\r\n }\r\n}\r\n\r\n// 离家需要狗看门,也需要猫抓老鼠\r\nfunction leaveHome(animal: Animal) {\r\n let dog = animal as Dog;\r\n dog.doorkeeper();\r\n}\r\n\r\nleaveHome(new Dog(\'旺财\'));\r\n```\r\n\r\n上面的例子中,我们声明了函数 leaveHome,转为Dog类型,调用看门方法,离家时构建一个狗对象,调用它的看门方法即可。\r\n\r\n## 断言限制\r\n\r\n类型不可随意断言,比如Dog是Animal的一种,Adimal可以断言为Dog,Cat不是Dog的一种,Cat就不能断言为Dog。如下例子:\r\n\r\n```typescript\r\nclass Animal {\r\n name: string;\r\n constructor(name:string) {\r\n this.name = name;\r\n }\r\n}\r\n\r\nclass Dog extends Animal {\r\n constructor(name:string) {\r\n super(name);\r\n }\r\n doorkeeper():void {\r\n console.log(this.name + \"在看家\")\r\n }\r\n}\r\nclass Cat extends Animal {\r\n constructor(name:string) {\r\n super(name);\r\n }\r\n catchMouse():void {\r\n console.log(this.name + \"在抓老鼠\")\r\n }\r\n}\r\n\r\n// 离家需要狗看门\r\n// 如果传入类型为Cat,断言成Dog编译不会报错,但运行时就会报错\r\nfunction leaveHome(animal: Animal) {\r\n let dog = animal as Dog;\r\n dog.doorkeeper();\r\n}\r\n// 实例化一个Cat\r\nleaveHome(new Cat(\'小花\'));\r\n```\r\n\r\n可以使用**instanceof**判断类型后对数据进行断言:\r\n\r\n```typescript\r\nclass Animal {\r\n name: string;\r\n constructor(name:string) {\r\n this.name = name;\r\n }\r\n}\r\n\r\nclass Dog extends Animal {\r\n constructor(name:string) {\r\n super(name);\r\n }\r\n doorkeeper():void {\r\n console.log(this.name + \"在看家\")\r\n }\r\n}\r\nclass Cat extends Animal {\r\n constructor(name:string) {\r\n super(name);\r\n }\r\n catchMouse():void {\r\n console.log(this.name + \"在抓老鼠\")\r\n }\r\n}\r\n\r\n// 判断类型之后\r\nfunction leaveHome(animal: Animal) {\r\n if(animal instanceof Dog) {\r\n let dog = animal as Dog;\r\n dog.doorkeeper();\r\n }else if(animal instanceof Cat) {\r\n let cat = animal as Cat;\r\n cat.catchMouse();\r\n }\r\n}\r\n\r\nleaveHome(new Cat(\'小花\'));\r\n```\r\n\r\n# 类型别名\r\n\r\n类型别名用来给一个类型起个新名字。\r\n\r\n```typescript\r\ntype Name = string;\r\ntype NameResolver = () => string;\r\ntype NameOrResolver = Name | NameResolver;\r\nfunction getName(n: NameOrResolver): Name {\r\n if (typeof n === \'string\') {\r\n return n;\r\n } else {\r\n return n();\r\n }\r\n}\r\n```\r\n\r\n上例中,我们使用 type 创建类型别名。类型别名常用于联合类型,将多个类型封装进一个类型中', 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, '2024-05-01 18:01:07', '2024-05-01 22:06:16', 0, 0, 'javascript,TypeScript');
INSERT INTO `ams_article` VALUES (7, 3, 8, '标题撒大大标题撒大大标helloworld题撒大大啊实打实大啊实打实大师', 'http://localhost:8128/img/article/20240501180023A002.png', '电风扇', '# 什么是TypeScript\r\n\r\nTypeScript于2012年10月由微软推出上线,始于JavaScript,看名字就知道TypeScript主要强调了类型,TypeScript在JaaScript基础上增加**类型系统**,JavaScript是一个弱类型语言,在编译期间声明的变量可以是任意类型,会导致运行时可能出现的类型错误,使用TypeScript之后可以指定变量类型,如果出现类型问题在编译期间就可以暴露出来,更容易查bug。\r\n最终TypScript又归于JavaScript,运行时其实还是将TypeScript转译成JavaScript执行,因为浏览器,node环境只能运行JavaScript。\r\n\r\n# 安装TypeScript\r\n\r\n首先确保您的电脑上安装了node,建议安装nodejs18以上版本。可点击链接进入[node下载地址](https://www.nodejs.com.cn/)。\r\nTypeScript需要编译为JavaScript文件执行,所以需要先安装TypeScript环境,可以将TypeScipt文件编译为JavaScript在浏览器或者node环境中运行。首先同时按下win + r键输入cmd唤起命令窗口\r\n**安装命令:**\r\n\r\n```shell\r\n# 全局安装typescript\r\nnpm install -g typescript\r\n```\r\n\r\n![image.png](http://localhost:8128/img/article/20240501180023A002.png)\r\n安装之后TypeScript的执行命令为tsc,比如想要查看TypeScript版本则可输入:\r\n\r\n```shell\r\ntsc -version\r\n```\r\n\r\n# HelloWorld\r\n\r\n## 创建文件\r\n\r\n写JavaScript时,文件后缀为.js。写TypeScript时文件后缀名为.ts。可以打开任意的编辑器整活,此处我使用VsCode开搞。以声明sting类型变量为例:\r\n\r\n```typescript\r\n// 变量title后边加上:string。指定为string类型,修改变量值时就只能是string类型\r\nlet title:string = \"Hello TypeScript\";\r\n\r\nconsole.log(title);\r\n```\r\n\r\n![image.png](http://localhost:8128/img/article/20240501180023A002.png)\r\n所以说ts声明变量的语法为:\r\n\r\n```javascript\r\n变量修饰符 变量名 : 数据类型 = 初始化值;\r\n如:var/let/const vag:number = 123;\r\n```\r\n\r\n## 编译\r\n\r\n将ts文件编译为js文件执行,使用tsc命令即可命令\r\n\r\n```shell\r\ntsc 01-hellosworld.ts\r\n```\r\n\r\n执行之后会在同级目录下生成一个同名的js文件\r\n![image.png](http://localhost:8128/img/article/20240501180023A002.png)\r\n\r\n## 执行\r\n\r\n使用node命令或者通过浏览器打开js文件来执行,如果使用node执行则使用nod命令:\r\n\r\n```shell\r\nnode 01-hellosworld.js\r\n```\r\n\r\n![image.png](http://localhost:8128/img/article/20240501180023A002.png)\r\n\r\n## 快速执行\r\n\r\n安装ts-node包实现快速运行ts,其实内部还是将ts转为js执行,底层逻辑不变,只是简化了开发人员操作。\r\n**安装命令:**\r\n\r\n```shell\r\nnpm install -g ts-node\r\n```\r\n\r\n**执行ts文件:**\r\n\r\n```shell\r\nts-node 01-hellosworld.ts\r\n```\r\n\r\n此时就不会再生成js文件啦。**但是执行的还是js哦,这是一定要记清楚的。**\r\n\r\n## 修改类型\r\n\r\n尝试将title修改为数字类型数据,如果在javascript中是可行的,类型可随意修改,在typescript中,如果修改数据类型在编译期就会报错\r\n![image.png](http://localhost:8128/img/article/20240501180023A002.png)\r\n那么忽略编辑器的报错,尝试运行会返回TSError错误,错误信息是编译TypeScript时出现问题。\r\n![image.png](http://localhost:8128/img/article/20240501180023A002.png)\r\n此处可以看出TypeScript相较于JavaScript对类型要求更严格,这也是很多开发人员吐槽的地方,以前写js\r\n随心所欲,随便定义一个变量,下边想怎么改都成,使用了ts之后只能修改值为对应类型的,好像添加了束缚,但我觉得这是好事:\r\n\r\n- 首先数据类型在逻辑处理中其实就应该输入同一个类型内的修改,严格来说是不可以将字符串类型修改为数字类型等,甚至是对象类型的数据。\r\n- 在复杂的业务处理中,甚至有时候都已经忘记了一个变量是什么类型的了😛。\r\n\r\n# TypeScript优势\r\n\r\nTypeScript包含JavaScript所有功能,同时又增加了类型系统,弥补了JavaScript弱类型的缺陷,那么为什么是缺陷呢?在ES6中JavaScript又推出了很多新的API,方便处理数据,这些api有的是字符串才能使用的,有的是数组才能使用的,有的是数字才能使用的,而JavaScript在编译时并不会检查当前变量是什么类型,能否使用调用的方法,在运行时就会出现错误。甚至会导致严重的线上bug。比如:\r\n\r\n```javascript\r\nlet arr = [1,2,3,4,5,6,7];\r\n\r\n// 将数组转为数字类型\r\narr = 1;\r\n// 调用filter方法,获取大于4的数据,此方法number类型肯定不能调用,但编译期并不会提示\r\nlet result = arr.filter(item => item > 4);\r\nconsole.log(result);\r\n\r\n```\r\n\r\n运行时就会出现TypeError即类型错误。\r\n![image.png](http://localhost:8128/img/article/20240501180023A002.png)\r\n以上错误在开发工作中比比皆是,不要妄图以为脑子好用能记住所有变量的数据类型,有时候你甚至不知道用户传过来的是什么类型的数据,所以在定义变量和方法参数时,设置明确的类型势在必行。\r\n\r\n# 数据类型\r\n\r\nTypeScript是JavaScript的扩充,所以包含JavaScript中的所有数据类型,同时又增加了若干个数据类型。下表列出TypeScript中所有的数据类型,不区分JS和TS,没有什么实际意义:\r\n\r\n| 数据类型 | 作用 |\r\n| ------------------ | ------------------------------------------------------------ |\r\n| number:数字类型 | 双精度 64 位浮点值。它可以用来表示整数和分数 |\r\n| string:字符串类型 | 描述字符或字符串,使用单引号(\')或双引号(\")来表示字符串类型。反引号(`)来定义多行文本和内嵌表达式。 |\r\n| boolean:布尔类型 | 表示逻辑值:true 和 false。 |\r\n| Object:对象 | 对象类型包括,数组、对象、函数 |\r\n| 元组 | 元组类型用来表示已知元素数量和类型的数组,各元素的类型不必相同,对应位置的类型需要相同。 |\r\n| enum:枚举 | 枚举类型用于定义数值集合。 |\r\n| any:任意类型 | 声明为 any 的变量可以赋予任意类型的值。 |\r\n| null | 表示对象值缺失。 |\r\n| undefined | 用于初始化变量为一个未定义的值 |\r\n| void | 用于标识方法返回值的类型,表示该方法没有返回值。 |\r\n| symbol | 用来声明唯一值,解决命名冲突问题 |\r\n| never | 其它类型(包括 null 和 undefined)的子类型,代表从不会出现的值。 |\r\n\r\n## number\r\n\r\n前端的JavaScript和TypeScript中没有整数和小数之分,数字类型统一使用number表示,可以使用各种进制实例化一个数字,写法如下:\r\n\r\n```typescript\r\n// 使用十进制表示\r\nlet num1: number = 6;\r\n// 十六进制\r\nlet num2: number = 0xf00d;\r\n// ES6 中的二进制表示法\r\nlet num3: number = 0b1010;\r\n// ES6 中的八进制表示法\r\nlet num4: number = 0o744;\r\n// 非数字\r\nlet num5: number = NaN;\r\n// 无穷值\r\nlet infinityNumber: number = Infinity;\r\n// 使用构造\r\nlet num1 : number = Number(1);\r\n// 使用JS中对象类型表示类型\r\nlet num2 : Number = 123;\r\n```\r\n\r\n其他数据类型都相同,可以使用构造方法初始化值,使用对象类型标识数据类型\r\n\r\n## string\r\n\r\n字符串可以通过单引号\'\'、双引号\"\"和模板字符串``创建\r\n\r\n```typescript\r\nlet s1 : string = \'单引号字符串\';\r\n\r\nlet s2 : string = \"双引号字符串\";\r\n\r\nlet s3 : string = `第一个${s1},第二个${s2}`;\r\n\r\nlet s4 : string = String(\"对象字符串\");\r\n```\r\n\r\n模板字符串可以使用${变量}方式引用变量\r\n\r\n## boolean\r\n\r\n布尔类型的值用来表示对【true】或者错【false】,在TypeScript中使用boolean表示:\r\n\r\n```typescript\r\nlet age : number = 123;\r\n\r\nlet username : string = \"username\";\r\n\r\nlet isMan : boolean = true;\r\n\r\n// 下方是错误的,new Boolean是对象类型\r\n// let isDog : boolean = new Boolean(true);\r\n\r\n// 可以直接使用Boolean()\r\nlet isDog : boolean = Boolean(true);\r\n```\r\n\r\n## 任意值\r\n\r\n可以通过使用any表示变量可以是任意类型数据,使用any效果和JavaScript相同,后期可以修改变量数据类型\r\n\r\n```typescript\r\n// any类型,初始值为string\r\nlet a1 : any = \"a1\";\r\n// 修改为number类型\r\na1 = 123;\r\n```\r\n\r\n## 类型推断\r\n\r\nTypeScript支持像JavaScript那样不显示声明数据类型,会根据赋值自动推断类型,后期则不可修改值为其他类型的数据\r\n\r\n```typescript\r\n// 类型自动推断为string\r\nlet username = \'张三\';\r\n// Type \'number\' is not assignable to type \'string\'\r\nusername = 123;\r\n```\r\n\r\n## null和undefined\r\n\r\nnull和undefined也可以被当做数据类型来定义\r\n\r\n```typescript\r\nlet nu : null = null;\r\n\r\nlet un : undefined = undefined;\r\n```\r\n\r\nnull是一个对象/变量的值为null,而undefined则表示该变量没有初始化。\r\n\r\n## void\r\n\r\nvoid为空值,是TypeScript中新增的数据类型,表示没有任何返回值的函数\r\n\r\n```typescript\r\nfunction say(): void {\r\n alert(\'我是张三\');\r\n}\r\n\r\nsay();\r\n```\r\n\r\n有些地方会比较,深究null、undefined、void区别,我认为并没有意义,null就是一个对象为空值,undefined就是没有初始值,void用来表示方法没有返回值,不要去描述变量。仅此而已不要再做无谓的深究!\r\n\r\n## 联合类型\r\n\r\n联合类型是该变量可以在声明的类型中随意匹配一个即可,比如年龄可以使用数字表示,也可以使用字符串表示,可以通过** | **符号分割多个类型\r\n\r\n```typescript\r\nlet age : number | string = \'十六\';\r\nage = 16;\r\n```\r\n\r\n如果使用联合类型表示一个变量,此时在操作变量时需要使用共有属性和方法,不能使用某一个类型特有的方法或属性,比如age可以为number或者string类型,number类型有toFixed方法,而string没有,number和string共有的操作有**toString**、**valueOf**方法。\r\n\r\n```typescript\r\nlet age : number | string = \'十六\'\r\nage = 16\r\n// 共有方法\r\nage.toString();\r\n// string有此方法,如果数字调用出现,Property \'length\' does not exist on type \'number\'\r\nage.length;\r\n```\r\n\r\n或者使用**typeof**判断类型之后使用\r\n\r\n```typescript\r\nlet age : number | string = 12\r\n\r\nif(typeof age === \'number\') {\r\n console.log(\"数字类型\")\r\n}\r\n\r\nif(typeof age === \'string\') {\r\n console.log(\"字符串类型\")\r\n}\r\n```\r\n\r\n## 数组\r\n\r\n```typescript\r\n// 通过类型[]方式指定,下例:数组中只允许有number类型数据\r\nlet a1 : number[] = [1,2,3,4];\r\n// 通过泛型指定,Array<类型>,下例:只允许有字符串\r\nlet nameArr : Array<string> = [\'大毛\',\'二毛\',\'小明\'];\r\n```\r\n\r\n## 元组\r\n\r\n元组和数组区别在于,元组中可以存在不同类型的数据。\r\n\r\n```typescript\r\n// 数据类型必须与索引一一匹配\r\nlet a1 : [number,string,number] = [1,\'a\',2];\r\n\r\n// 先声明,再赋值\r\nlet person1: [string, number];\r\nperson1 = [\'大毛\', 25];\r\n\r\n// 获取一项\r\nlet username : string = person1[0];\r\nlet age : number = person1[1];\r\n\r\n// 操作数据\r\nconsole.log(username.indexOf(\"大\"))\r\nconsole.log(age.toFixed(2));\r\n```\r\n\r\n添加越界元素时【元组本身2个元素长度,新增其他数据长度会增加,称为添加越界元素】,它的类型会被限制为元组中每个类型的联合类型:\r\n\r\n```typescript\r\n// 先声明,再赋值\r\nlet person1: [string, number] = [\'大毛\', 25];\r\n\r\nperson1.push(\"123\");\r\nperson1.push(123);\r\n\r\n// Argument of type \'boolean\' is not assignable to parameter of type \'string | number\'.\r\nperson1.push(true);\r\n```\r\n\r\n如果元组中存在可选值时可以在类型后添加?表示,如下\r\n\r\n```typescript\r\n// number类型的值可写可不写,添加?即可\r\nlet person1: [string, number?] = [\'大毛\'];\r\n```\r\n\r\n## 枚举\r\n\r\n枚举(Enum)类型用于取值被限定在一定范围内的场景,比如订单状态为未付款、待发货、待收货、待评价,性别限定为男、女、未知等。\r\n枚举成员会被赋值为从 0 开始递增的数字,同时也会对枚举值到枚举名进行反向映射:\r\n\r\n```typescript\r\nenum OrderStatus {NO_PAY, SHIPPED, RECEIVED, EVALUATED,REVIEWED};\r\n\r\n// 使用\r\nconsole.log(OrderStatus[\'NO_PAY\'] === 0);\r\nconsole.log(OrderStatus[\'SHIPPED\'] === 1);\r\nconsole.log(OrderStatus[\'RECEIVED\'] === 2);\r\n\r\nconsole.log(OrderStatus[0] === \'NO_PAY\');\r\nconsole.log(OrderStatus[1] === \'SHIPPED\');\r\nconsole.log(OrderStatus[2] === \'RECEIVED\');\r\n```\r\n\r\n你还可以通过手动赋值修改默认以0递增的数据\r\n\r\n```typescript\r\nenum OrderStatus {NO_PAY = 1, SHIPPED = 2, RECEIVED = 3, EVALUATED,REVIEWED};\r\n\r\n// 使用\r\nconsole.log(OrderStatus[\'NO_PAY\']);\r\nconsole.log(OrderStatus[\'SHIPPED\']);\r\nconsole.log(OrderStatus[\'RECEIVED\']);\r\nconsole.log(OrderStatus[\'EVALUATED\']);\r\nconsole.log(OrderStatus[\'REVIEWED\']);\r\n```\r\n\r\n## 函数\r\n\r\nTypeScript中声明函数可以在形式参数和返回值中指定数据类型。\r\n\r\n```typescript\r\n// 接收number类型参数,返回number类型参数\r\nfunction fun1(num1 : number,num2 : number) : number {\r\n\r\n return num1 + num2;\r\n}\r\nconsole.log(fun1(1,2));\r\n```\r\n\r\n也支持通过函数表达式【Function Expression】的方式声明函数\r\n\r\n```typescript\r\nlet fun2 = function(str1 : string,str2 : string) : string {\r\n\r\n return str1.concat(str2);\r\n}\r\n\r\nconsole.log(fun2(\'A\',\'B\'));\r\n```\r\n\r\n函数同样支持**可选参数**,当然可选参数必须在最后\r\n\r\n```typescript\r\nfunction buildName(firstName: string, lastName?: string) {\r\n if (lastName) {\r\n return firstName + \' \' + lastName;\r\n } else {\r\n return firstName;\r\n }\r\n}\r\nlet tomcat = buildName(\'Tom\', \'Cat\');\r\nlet tom = buildName(\'Tom\');\r\n```\r\n\r\n如果没有返回值,则可以使用**void**修饰返回值类型,无返回值时接收到的为**undefined**\r\n\r\n```typescript\r\nfunction fun1(firstName: string):void {\r\n console.log(firstName.toUpperCase());\r\n}\r\nlet result = fun1(\'Tom\');\r\nconsole.log(result);\r\n```\r\n\r\nES6中允许方法参数有默认值,**TypeScript 会将添加了默认值的参数识别为可选参数**:\r\n\r\n```typescript\r\nfunction buildName(firstName: string, lastName: string = \'Cat\') {\r\n return firstName + \' \' + lastName;\r\n}\r\nlet tomcat = buildName(\'Tom\', \'Cat\');\r\nlet tom = buildName(\'Tom\');\r\n```\r\n\r\n此时就不受「可选参数必须接在必需参数后面」的限制了:\r\n\r\n```typescript\r\nfunction buildName(firstName: string = \'Tom\', lastName: string) {\r\n return firstName + \' \' + lastName;\r\n}\r\nlet tomcat = buildName(\'Tom\', \'Cat\');\r\nlet cat = buildName(undefined, \'Cat\');\r\n```\r\n\r\nES6中可以使用 **...rest** 的方式获取函数中的剩余参数(rest 参数):\r\n\r\n```typescript\r\nfunction push(array, ...items) {\r\n items.forEach(function(item) {\r\n array.push(item);\r\n });\r\n}\r\n\r\nlet a: any[] = [];\r\npush(a, 1, 2, 3);\r\n```\r\n\r\n事实上,items 是一个数组。所以我们可以用数组的类型来定义它:\r\n\r\n```typescript\r\nfunction push(array: any[], ...items: any[]) {\r\n items.forEach(function(item) {\r\n array.push(item);\r\n });\r\n}\r\n\r\nlet a = [];\r\npush(a, 1, 2, 3);\r\n```\r\n\r\n注意,rest 参数只能是最后一个参数\r\n\r\n## 接口\r\n\r\n接口用来定义一种规范,具体的时候交由对象来做,举个生活中的例子我们购买商品按照消费者权益来说所有的商品都必须有售后保障,那么具体怎么实现售后,你是上门维修也好,直接换货也好,就有厂家自己实现。这个必须有售后就是规范,各个厂家就是一个一个具体的对象,交由对象实现就行了。\r\n程序中就是我们希望在程序内描述一个人,那么人的规范就是有名字、性别、年龄和一些行为这可以通过接口描述,具体是哪一个人,就交由对象来具体化【实例化】。\r\n\r\n```typescript\r\n// 接口定义抽象结构\r\ninterface Person {\r\n username: string;\r\n age: number;\r\n say():void;\r\n}\r\n// 对象具体实现\r\nlet tom: Person = {\r\n username: \'张三\',\r\n age: 25,\r\n say() : void {\r\n console.log(this.username)\r\n }\r\n};\r\n```\r\n\r\n### 可选属性\r\n\r\n有时认为一个对象的某个属性可有可无,可以使用可选属性\r\n\r\n```typescript\r\ninterface Person {\r\n name: string;\r\n age?: number;\r\n}\r\n\r\nlet p1: Person = {\r\n name: \'大毛\'\r\n};\r\nlet p2: Person = {\r\n name: \'小毛\',\r\n age: 25\r\n};\r\n```\r\n\r\n### 任意属性\r\n\r\n又是我们希望可以在对象中添加任意的属性:\r\n\r\n```typescript\r\ninterface Person {\r\n name: string;\r\n age?: number;\r\n [propName: string]: any;\r\n}\r\n\r\nlet tom: Person = {\r\n name: \'大毛\',\r\n gender: \'男\',\r\n};\r\n```\r\n\r\n任意属性的类型需要包含可选属性,否则编译报错,比如any包含number类型,如果将any换成string,则age可选属性就会报错\r\n\r\n### 只读属性\r\n\r\n有时候我们希望对象中的一些字段在创建的时候被赋值后就不可更改,那么可以用 readonly 定义只读属性:\r\n\r\n```typescript\r\ninterface IBook {\r\n readonly author: string;\r\n bookname: string;\r\n}\r\n\r\nlet book1: IBook = {\r\n author: \'小明\',\r\n bookname: \'TypeScript养成记\',\r\n};\r\n\r\nbook1.author = \'大毛\';\r\n```\r\n\r\n## 类\r\n\r\nES6中JavaScript引入了类的概念,类也是用来定义事物的抽象,交由对象具体实现,在面向对象的语言中,对于类我们应该熟知这么几个概念:\r\n\r\n- 类(Class):定义了一件事物的抽象特点,包含它的属性和方法\r\n- 对象(Object):类的实例,通过 new 生成\r\n- 面向对象(OOP)的三大特性:封装、继承、多态\r\n- 封装(Encapsulation):将对数据的操作细节隐藏起来,只暴露对外的接口。外界调用端不需要(也不可能)知道细节,就能通过对外提供的接口来访问该对象,同时也保证了外界无法任意更改对象内部的数据\r\n- 继承(Inheritance):子类继承父类,子类除了拥有父类的所有特性外,还有一些更具体的特性\r\n- 多态(Polymorphism):由继承而产生了相关的不同的类,对同一个方法可以有不同的响应。比如 Cat 和 Dog 都继承自 Animal,但是分别实现了自己的 eat 方法。此时针对某一个实例,我们无需了解它是 Cat 还是 Dog,就可以直接调用 eat 方法,程序会自动判断出来应该如何执行 eat\r\n- 存取器(getter & setter):用以改变属性的读取和赋值行为\r\n- 修饰符(Modifiers):修饰符是一些关键字,用于限定成员或类型的性质。比如 public 表示公有属性或方法\r\n- 抽象类(Abstract Class):抽象类是供其他类继承的基类,抽象类不允许被实例化。抽象类中的抽象方法必须在子类中被实现\r\n- 接口(Interfaces):不同类之间公有的属性或方法,可以抽象成一个接口。接口可以被类实现(implements)。一个类只能继承自另一个类,但是可以实现多个接口\r\n\r\n### TypeScript中的类\r\n\r\nTypeScript 可以使用三种访问修饰符(Access Modifiers),分别是 public、private 和 protected。\r\n\r\n- public 修饰的属性或方法是公有的,可以在任何地方被访问到,默认所有的属性和方法都是 public 的\r\n- private 修饰的属性或方法是私有的,不能在声明它的类的外部访问\r\n- protected 修饰的属性或方法是受保护的,它和 private 类似,区别是它在子类中也是允许被访问的\r\n\r\n比如创建一个动物类,实例化一个狗\r\n\r\n```typescript\r\nclass Animal {\r\n public name;\r\n public constructor(name:string) {\r\n this.name = name;\r\n }\r\n}\r\n\r\nlet a = new Animal(\'大黄\');\r\nconsole.log(a.name); // 大黄\r\na.name = \'小黑\';\r\nconsole.log(a.name); // 小黑\r\n```\r\n\r\n上述可以直接修改和获取数据,对于对象数据来说是不安全的,可以通过private或者protected提高安全性。\r\n\r\n### private修饰属性\r\n\r\n使用private修饰将属性私有化,属性只能在类内部直接调用,如果要修改数据和获取数据可以通过公开的方法获取\r\n\r\n```typescript\r\nclass Animal {\r\n private name;\r\n public constructor(name:string) {\r\n this.name = name;\r\n }\r\n\r\n public getName():string {\r\n return this.name;\r\n }\r\n\r\n public setName(name:string):string {\r\n return this.name = name;\r\n }\r\n}\r\n\r\nlet a = new Animal(\'大黄\');\r\nconsole.log(a.getName()); // 大黄\r\na.setName(\'小黑\');\r\nconsole.log(a.getName()); // 小黑\r\n```\r\n\r\n### protected修饰属性\r\n\r\n被private修饰,包括子类在内都不被允许访问,只有本类内部可以访问,如果希望子类可以访问则可以使用protected修饰\r\n\r\n```typescript\r\nclass Animal {\r\n protected name;\r\n public constructor(name:string) {\r\n this.name = name;\r\n }\r\n\r\n public getName():string {\r\n return this.name;\r\n }\r\n\r\n public setName(name:string):string {\r\n return this.name = name;\r\n }\r\n}\r\n\r\nclass Dog extends Animal {\r\n constructor(name:string) {\r\n super(name);\r\n // name属性被继承过来\r\n console.log(this.name);\r\n }\r\n}\r\n```\r\n\r\n### private修饰构造方法\r\n\r\n如果构造方法通过private修饰被私有化,则该类不能被实例化,也不能被继承\r\n\r\n```typescript\r\nclass Animal {\r\n protected name;\r\n // 私有化构造方法\r\n private constructor(name:string) {\r\n this.name = name;\r\n }\r\n\r\n public getName():string {\r\n return this.name;\r\n }\r\n\r\n public setName(name:string):string {\r\n return this.name = name;\r\n }\r\n}\r\n\r\n// 继承就会报错\r\n// Cannot extend a class \'Animal\'. Class constructor is marked as private\r\nclass Dog extends Animal {\r\n constructor(name:string) {\r\n super(name);\r\n // name属性被继承过来\r\n console.log(this.name);\r\n }\r\n}\r\n```\r\n\r\n### protected 修饰构造方法\r\n\r\n如果构造函数修饰为 protected 时,该类不能实例化\r\n\r\n```typescript\r\nclass Animal {\r\n protected name;\r\n // protected修饰\r\n protected constructor(name:string) {\r\n this.name = name;\r\n }\r\n\r\n public getName():string {\r\n return this.name;\r\n }\r\n\r\n public setName(name:string):string {\r\n return this.name = name;\r\n }\r\n}\r\n// 继承没毛病\r\nclass Dog extends Animal {\r\n constructor(name:string) {\r\n super(name);\r\n // name属性被继承过来\r\n console.log(this.name);\r\n }\r\n}\r\n// 实例化有问题\r\n// Constructor of class \'Animal\' is protected and only accessible within the class declaration\r\nlet a = new Animal(\'大黄\');\r\n```\r\n\r\n### 参数属性\r\n\r\n类中属性可以定义在构造方法上,等同于类中定义了属性\r\n\r\n```typescript\r\nclass Animal {\r\n // 参数属性\r\n public constructor(public name:string) {\r\n }\r\n}\r\n\r\nlet a = new Animal(\"大黄\");\r\nconsole.log(a.name)\r\n```\r\n\r\n### readonly\r\n\r\n只读属性关键字也可用于类中,只允许出现在属性声明或索引签名或构造函数中。\r\n\r\n```typescript\r\nclass Animal {\r\n // 只读属性\r\n readonly name;\r\n public constructor(name:string) {\r\n this.name = name;\r\n }\r\n}\r\n\r\nlet a = new Animal(\'大黄\');\r\nconsole.log(a.name);\r\n// 不可再次修改\r\na.name = \'小黑\';\r\n```\r\n\r\n注意如果 readonly 和其他访问修饰符同时存在的话,需要写在其后面。\r\n\r\n```typescript\r\nclass Animal {\r\n // public readonly name;\r\n public constructor(public readonly name:string) {\r\n // this.name = name;\r\n }\r\n}\r\n```\r\n\r\n### 抽象类\r\n\r\n抽象类不能被实例化,使用abstract修饰\r\n\r\n```typescript\r\nabstract class Animal {\r\n public name;\r\n public constructor(name:string) {\r\n this.name = name;\r\n }\r\n public abstract sayHi():any;\r\n}\r\n// Cannot create an instance of an abstract class.\r\nlet a = new Animal(\'大黄\');\r\n```\r\n\r\n抽象类中的抽象方法必须被子类实现,子类必须实现抽象类中的所有抽象方法,否则需要继续抽象下去:\r\n\r\n```typescript\r\nabstract class Animal {\r\n public name;\r\n public constructor(name:string) {\r\n this.name = name;\r\n }\r\n public abstract eat():any;\r\n}\r\n\r\nclass Cat extends Animal {\r\n public eat() {\r\n console.log(`${this.name} 在吃鱼.`);\r\n }\r\n}\r\n\r\nlet c = new Cat(\'小花\');\r\nc.eat();\r\n```\r\n\r\n如果没有实现所有抽象方法则继续报错:\r\n\r\n```typescript\r\nabstract class Animal {\r\n public name;\r\n public constructor(name:string) {\r\n this.name = name;\r\n }\r\n public abstract eat():any;\r\n public abstract sayHi():any;\r\n}\r\n\r\n// Non-abstract class \'Cat\' does not implement all abstract members of \'Animal\'\r\nclass Cat extends Animal {\r\n public eat() {\r\n console.log(`${this.name} 在吃鱼.`);\r\n }\r\n}\r\n```\r\n\r\n## 泛型\r\n\r\n泛型(Generics)是指在定义函数、接口或类的时候,不预先指定具体的类型,而在使用的时候再指定类型的一种特性。\r\n\r\n### 无泛型\r\n\r\n实现一个函数 createArray,它可以创建一个指定长度的数组,同时将每一项都填充一个默认值:\r\n\r\n```typescript\r\nfunction createArray(length: number, value: any): Array<any> {\r\n let result = [];\r\n for (let i = 0; i < length; i++) {\r\n result[i] = value;\r\n }\r\n return result;\r\n}\r\n\r\ncreateArray(3, \'x\'); // [\'x\', \'x\', \'x\']\r\n```\r\n\r\n此处使用any当做入参和Array<any>反参类型,编译不会报错,但是可能会造成类型不安全的问题,调用方法的用户可能瞎传数据,你的方法就报错啦。此时泛型就登场了,**解决参数类型安全问题**\r\n\r\n```typescript\r\nfunction createArray<T>(length: number, value: T): Array<T> {\r\n let result: T[] = [];\r\n for (let i = 0; i < length; i++) {\r\n result[i] = value;\r\n }\r\n return result;\r\n}\r\n\r\ncreateArray<string>(3, \'x\'); // [\'x\', \'x\', \'x\']\r\n```\r\n\r\n上例中,我们在函数名后添加了 <T>,其中 T 用来指代任意输入的类型,在后面的输入 value: T 和输出 Array<T> 中即可使用了。\r\n接着在调用的时候,可以指定它具体的类型为 string。当然,也可以不手动指定,而让类型推论自动推算出来:\r\n\r\n```typescript\r\nfunction createArray<T>(length: number, value: T): Array<T> {\r\n let result: T[] = [];\r\n for (let i = 0; i < length; i++) {\r\n result[i] = value;\r\n }\r\n return result;\r\n}\r\n\r\ncreateArray(3, \'x\'); // [\'x\', \'x\', \'x\']\r\n```\r\n\r\n### 多个类型参数\r\n\r\n定义泛型的时候,可以一次定义多个类型参数:\r\n\r\n```typescript\r\nfunction swap<T, U>(tuple: [T, U]): [U, T] {\r\n return [tuple[1], tuple[0]];\r\n}\r\n\r\nswap([7, \'seven\']); // [\'seven\', 7]\r\n```\r\n\r\n### 泛型约束\r\n\r\n在函数内部使用泛型变量的时候,由于事先不知道它是哪种类型,所以不能随意的操作它的属性或方法:\r\n\r\n```typescript\r\nfunction loggingIdentity<T>(arg: T): T {\r\n console.log(arg.length);\r\n return arg;\r\n}\r\n```\r\n\r\n上例中,泛型 T 不一定包含属性 length,所以编译的时候报错了。\r\n这时,我们可以对泛型进行约束,只允许这个函数传入那些包含 length 属性的变量。这就是泛型约束:\r\n\r\n```typescript\r\ninterface Lengthwise {\r\n length: number;\r\n}\r\n\r\nfunction loggingIdentity<T extends Lengthwise>(arg: T): T {\r\n console.log(arg.length);\r\n return arg;\r\n}\r\n```\r\n\r\n上例中,我们使用了 extends 约束了泛型 T 必须符合接口 Lengthwise 的形状,也就是必须包含 length 属性。\r\n此时如果调用 loggingIdentity 的时候,传入的 arg 不包含 length,那么在编译阶段就会报错了:\r\n\r\n```typescript\r\ninterface Lengthwise {\r\n length: number;\r\n}\r\n\r\nfunction loggingIdentity<T extends Lengthwise>(arg: T): T {\r\n console.log(arg.length);\r\n return arg;\r\n}\r\n\r\nloggingIdentity(7);\r\n```\r\n\r\n多个类型参数之间也可以互相约束:\r\n\r\n```typescript\r\nfunction copyFields<T extends U, U>(target: T, source: U): T {\r\n for (let id in source) {\r\n target[id] = (<T>source)[id];\r\n }\r\n return target;\r\n}\r\n\r\nlet x = { a: 1, b: 2, c: 3, d: 4 };\r\n\r\ncopyFields(x, { b: 10, d: 20 });\r\n```\r\n\r\n上例中,我们使用了两个类型参数,其中要求 T 继承 U,这样就保证了 U 上不会出现 T 中不存在的字段。\r\n\r\n### 泛型接口\r\n\r\n泛型也可以用来定义接口\r\n\r\n```typescript\r\ninterface CreateArrayFunc {\r\n <T>(length: number, value: T): Array<T>;\r\n}\r\n\r\nlet createArray: CreateArrayFunc;\r\ncreateArray = function<T>(length: number, value: T): Array<T> {\r\n let result: T[] = [];\r\n for (let i = 0; i < length; i++) {\r\n result[i] = value;\r\n }\r\n return result;\r\n}\r\n\r\ncreateArray(3, \'x\'); // [\'x\', \'x\', \'x\']\r\n```\r\n\r\n进一步,我们可以把泛型参数提前到接口名上:\r\n\r\n```typescript\r\ninterface CreateArrayFunc<T> {\r\n (length: number, value: T): Array<T>;\r\n}\r\n\r\nlet createArray: CreateArrayFunc<any>;\r\ncreateArray = function<T>(length: number, value: T): Array<T> {\r\n let result: T[] = [];\r\n for (let i = 0; i < length; i++) {\r\n result[i] = value;\r\n }\r\n return result;\r\n}\r\n\r\ncreateArray(3, \'x\'); // [\'x\', \'x\', \'x\']\r\n```\r\n\r\n注意,此时在使用泛型接口的时候,需要定义泛型的类型。\r\n\r\n### 泛型类\r\n\r\n与泛型接口类似,泛型也可以用于类的类型定义中:\r\n\r\n```typescript\r\nclass GenericNumber<T> {\r\n zeroValue: T;\r\n add: (x: T, y: T) => T;\r\n}\r\n\r\nlet myGenericNumber = new GenericNumber<number>();\r\nmyGenericNumber.zeroValue = 0;\r\nmyGenericNumber.add = function(x, y) { return x + y; };\r\n```\r\n\r\n### 泛型参数的默认类型\r\n\r\n在 TypeScript 2.3 以后,我们可以为泛型中的类型参数指定默认类型。当使用泛型时没有在代码中直接指定类型参数,从实际值参数中也无法推测出时,这个默认类型就会起作用。\r\n\r\n```typescript\r\nfunction createArray<T = string>(length: number, value: T): Array<T> {\r\n let result: T[] = [];\r\n for (let i = 0; i < length; i++) {\r\n result[i] = value;\r\n }\r\n return result;\r\n}\r\n```\r\n\r\n# 类型断言\r\n\r\n类型断言(Type Assertion)可以用来手动指定一个值的类型。语法为\r\n\r\n```typescript\r\n值 as 类型\r\n\r\n或\r\n \r\n<类型>值\r\n```\r\n\r\n在 tsx 语法(React 的 jsx 语法的 ts 版)中必须使用 **值 as 类型**。\r\n\r\n## 联合类型断言为一个具体类型\r\n\r\n前文介绍了支持联合类型,即一个变量可以是string类型也可以是number类型,只能访问该变量所有类型的共有属性和方法\r\n\r\n```typescript\r\nfunction fun1(args: string | number):number {\r\n // 将值断言为number类型\r\n let result = args as number;\r\n\r\n return result;\r\n}\r\n\r\nconsole.log(fun1(\"1\"))\r\n```\r\n\r\n## 将一个父类断言为更加具体的子类\r\n\r\n当类之间有继承关系时,类型断言也是很常见的:\r\n\r\n```typescript\r\nclass Animal {\r\n name: string;\r\n constructor(name:string) {\r\n this.name = name;\r\n }\r\n}\r\n\r\nclass Dog extends Animal {\r\n constructor(name:string) {\r\n super(name);\r\n }\r\n doorkeeper():void {\r\n console.log(this.name + \"在看家\")\r\n }\r\n}\r\nclass Cat extends Animal {\r\n constructor(name:string) {\r\n super(name);\r\n }\r\n catchMouse():void {\r\n console.log(this.name + \"在抓老鼠\")\r\n }\r\n}\r\n\r\n// 离家需要狗看门,也需要猫抓老鼠\r\nfunction leaveHome(animal: Animal) {\r\n let dog = animal as Dog;\r\n dog.doorkeeper();\r\n}\r\n\r\nleaveHome(new Dog(\'旺财\'));\r\n```\r\n\r\n上面的例子中,我们声明了函数 leaveHome,转为Dog类型,调用看门方法,离家时构建一个狗对象,调用它的看门方法即可。\r\n\r\n## 断言限制\r\n\r\n类型不可随意断言,比如Dog是Animal的一种,Adimal可以断言为Dog,Cat不是Dog的一种,Cat就不能断言为Dog。如下例子:\r\n\r\n```typescript\r\nclass Animal {\r\n name: string;\r\n constructor(name:string) {\r\n this.name = name;\r\n }\r\n}\r\n\r\nclass Dog extends Animal {\r\n constructor(name:string) {\r\n super(name);\r\n }\r\n doorkeeper():void {\r\n console.log(this.name + \"在看家\")\r\n }\r\n}\r\nclass Cat extends Animal {\r\n constructor(name:string) {\r\n super(name);\r\n }\r\n catchMouse():void {\r\n console.log(this.name + \"在抓老鼠\")\r\n }\r\n}\r\n\r\n// 离家需要狗看门\r\n// 如果传入类型为Cat,断言成Dog编译不会报错,但运行时就会报错\r\nfunction leaveHome(animal: Animal) {\r\n let dog = animal as Dog;\r\n dog.doorkeeper();\r\n}\r\n// 实例化一个Cat\r\nleaveHome(new Cat(\'小花\'));\r\n```\r\n\r\n可以使用**instanceof**判断类型后对数据进行断言:\r\n\r\n```typescript\r\nclass Animal {\r\n name: string;\r\n constructor(name:string) {\r\n this.name = name;\r\n }\r\n}\r\n\r\nclass Dog extends Animal {\r\n constructor(name:string) {\r\n super(name);\r\n }\r\n doorkeeper():void {\r\n console.log(this.name + \"在看家\")\r\n }\r\n}\r\nclass Cat extends Animal {\r\n constructor(name:string) {\r\n super(name);\r\n }\r\n catchMouse():void {\r\n console.log(this.name + \"在抓老鼠\")\r\n }\r\n}\r\n\r\n// 判断类型之后\r\nfunction leaveHome(animal: Animal) {\r\n if(animal instanceof Dog) {\r\n let dog = animal as Dog;\r\n dog.doorkeeper();\r\n }else if(animal instanceof Cat) {\r\n let cat = animal as Cat;\r\n cat.catchMouse();\r\n }\r\n}\r\n\r\nleaveHome(new Cat(\'小花\'));\r\n```\r\n\r\n# 类型别名\r\n\r\n类型别名用来给一个类型起个新名字。\r\n\r\n```typescript\r\ntype Name = string;\r\ntype NameResolver = () => string;\r\ntype NameOrResolver = Name | NameResolver;\r\nfunction getName(n: NameOrResolver): Name {\r\n if (typeof n === \'string\') {\r\n return n;\r\n } else {\r\n return n();\r\n }\r\n}\r\n```\r\n\r\n上例中,我们使用 type 创建类型别名。类型别名常用于联合类型,将多个类型封装进一个类型中', 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, '2024-05-01 18:01:07', '2024-05-01 22:06:16', 0, 0, 'javascript,TypeScript');
INSERT INTO `ams_article` VALUES (8, 3, 8, '标题撒大大标题撒大大标helloworld题撒大大啊实打实大啊实打实大师', 'http://localhost:8128/img/article/20240501180023A002.png', '电风扇', '# 什么是TypeScript\r\n\r\nTypeScript于2012年10月由微软推出上线,始于JavaScript,看名字就知道TypeScript主要强调了类型,TypeScript在JaaScript基础上增加**类型系统**,JavaScript是一个弱类型语言,在编译期间声明的变量可以是任意类型,会导致运行时可能出现的类型错误,使用TypeScript之后可以指定变量类型,如果出现类型问题在编译期间就可以暴露出来,更容易查bug。\r\n最终TypScript又归于JavaScript,运行时其实还是将TypeScript转译成JavaScript执行,因为浏览器,node环境只能运行JavaScript。\r\n\r\n# 安装TypeScript\r\n\r\n首先确保您的电脑上安装了node,建议安装nodejs18以上版本。可点击链接进入[node下载地址](https://www.nodejs.com.cn/)。\r\nTypeScript需要编译为JavaScript文件执行,所以需要先安装TypeScript环境,可以将TypeScipt文件编译为JavaScript在浏览器或者node环境中运行。首先同时按下win + r键输入cmd唤起命令窗口\r\n**安装命令:**\r\n\r\n```shell\r\n# 全局安装typescript\r\nnpm install -g typescript\r\n```\r\n\r\n![image.png](http://localhost:8128/img/article/20240501180023A002.png)\r\n安装之后TypeScript的执行命令为tsc,比如想要查看TypeScript版本则可输入:\r\n\r\n```shell\r\ntsc -version\r\n```\r\n\r\n# HelloWorld\r\n\r\n## 创建文件\r\n\r\n写JavaScript时,文件后缀为.js。写TypeScript时文件后缀名为.ts。可以打开任意的编辑器整活,此处我使用VsCode开搞。以声明sting类型变量为例:\r\n\r\n```typescript\r\n// 变量title后边加上:string。指定为string类型,修改变量值时就只能是string类型\r\nlet title:string = \"Hello TypeScript\";\r\n\r\nconsole.log(title);\r\n```\r\n\r\n![image.png](http://localhost:8128/img/article/20240501180023A002.png)\r\n所以说ts声明变量的语法为:\r\n\r\n```javascript\r\n变量修饰符 变量名 : 数据类型 = 初始化值;\r\n如:var/let/const vag:number = 123;\r\n```\r\n\r\n## 编译\r\n\r\n将ts文件编译为js文件执行,使用tsc命令即可命令\r\n\r\n```shell\r\ntsc 01-hellosworld.ts\r\n```\r\n\r\n执行之后会在同级目录下生成一个同名的js文件\r\n![image.png](http://localhost:8128/img/article/20240501180023A002.png)\r\n\r\n## 执行\r\n\r\n使用node命令或者通过浏览器打开js文件来执行,如果使用node执行则使用nod命令:\r\n\r\n```shell\r\nnode 01-hellosworld.js\r\n```\r\n\r\n![image.png](http://localhost:8128/img/article/20240501180023A002.png)\r\n\r\n## 快速执行\r\n\r\n安装ts-node包实现快速运行ts,其实内部还是将ts转为js执行,底层逻辑不变,只是简化了开发人员操作。\r\n**安装命令:**\r\n\r\n```shell\r\nnpm install -g ts-node\r\n```\r\n\r\n**执行ts文件:**\r\n\r\n```shell\r\nts-node 01-hellosworld.ts\r\n```\r\n\r\n此时就不会再生成js文件啦。**但是执行的还是js哦,这是一定要记清楚的。**\r\n\r\n## 修改类型\r\n\r\n尝试将title修改为数字类型数据,如果在javascript中是可行的,类型可随意修改,在typescript中,如果修改数据类型在编译期就会报错\r\n![image.png](http://localhost:8128/img/article/20240501180023A002.png)\r\n那么忽略编辑器的报错,尝试运行会返回TSError错误,错误信息是编译TypeScript时出现问题。\r\n![image.png](http://localhost:8128/img/article/20240501180023A002.png)\r\n此处可以看出TypeScript相较于JavaScript对类型要求更严格,这也是很多开发人员吐槽的地方,以前写js\r\n随心所欲,随便定义一个变量,下边想怎么改都成,使用了ts之后只能修改值为对应类型的,好像添加了束缚,但我觉得这是好事:\r\n\r\n- 首先数据类型在逻辑处理中其实就应该输入同一个类型内的修改,严格来说是不可以将字符串类型修改为数字类型等,甚至是对象类型的数据。\r\n- 在复杂的业务处理中,甚至有时候都已经忘记了一个变量是什么类型的了😛。\r\n\r\n# TypeScript优势\r\n\r\nTypeScript包含JavaScript所有功能,同时又增加了类型系统,弥补了JavaScript弱类型的缺陷,那么为什么是缺陷呢?在ES6中JavaScript又推出了很多新的API,方便处理数据,这些api有的是字符串才能使用的,有的是数组才能使用的,有的是数字才能使用的,而JavaScript在编译时并不会检查当前变量是什么类型,能否使用调用的方法,在运行时就会出现错误。甚至会导致严重的线上bug。比如:\r\n\r\n```javascript\r\nlet arr = [1,2,3,4,5,6,7];\r\n\r\n// 将数组转为数字类型\r\narr = 1;\r\n// 调用filter方法,获取大于4的数据,此方法number类型肯定不能调用,但编译期并不会提示\r\nlet result = arr.filter(item => item > 4);\r\nconsole.log(result);\r\n\r\n```\r\n\r\n运行时就会出现TypeError即类型错误。\r\n![image.png](http://localhost:8128/img/article/20240501180023A002.png)\r\n以上错误在开发工作中比比皆是,不要妄图以为脑子好用能记住所有变量的数据类型,有时候你甚至不知道用户传过来的是什么类型的数据,所以在定义变量和方法参数时,设置明确的类型势在必行。\r\n\r\n# 数据类型\r\n\r\nTypeScript是JavaScript的扩充,所以包含JavaScript中的所有数据类型,同时又增加了若干个数据类型。下表列出TypeScript中所有的数据类型,不区分JS和TS,没有什么实际意义:\r\n\r\n| 数据类型 | 作用 |\r\n| ------------------ | ------------------------------------------------------------ |\r\n| number:数字类型 | 双精度 64 位浮点值。它可以用来表示整数和分数 |\r\n| string:字符串类型 | 描述字符或字符串,使用单引号(\')或双引号(\")来表示字符串类型。反引号(`)来定义多行文本和内嵌表达式。 |\r\n| boolean:布尔类型 | 表示逻辑值:true 和 false。 |\r\n| Object:对象 | 对象类型包括,数组、对象、函数 |\r\n| 元组 | 元组类型用来表示已知元素数量和类型的数组,各元素的类型不必相同,对应位置的类型需要相同。 |\r\n| enum:枚举 | 枚举类型用于定义数值集合。 |\r\n| any:任意类型 | 声明为 any 的变量可以赋予任意类型的值。 |\r\n| null | 表示对象值缺失。 |\r\n| undefined | 用于初始化变量为一个未定义的值 |\r\n| void | 用于标识方法返回值的类型,表示该方法没有返回值。 |\r\n| symbol | 用来声明唯一值,解决命名冲突问题 |\r\n| never | 其它类型(包括 null 和 undefined)的子类型,代表从不会出现的值。 |\r\n\r\n## number\r\n\r\n前端的JavaScript和TypeScript中没有整数和小数之分,数字类型统一使用number表示,可以使用各种进制实例化一个数字,写法如下:\r\n\r\n```typescript\r\n// 使用十进制表示\r\nlet num1: number = 6;\r\n// 十六进制\r\nlet num2: number = 0xf00d;\r\n// ES6 中的二进制表示法\r\nlet num3: number = 0b1010;\r\n// ES6 中的八进制表示法\r\nlet num4: number = 0o744;\r\n// 非数字\r\nlet num5: number = NaN;\r\n// 无穷值\r\nlet infinityNumber: number = Infinity;\r\n// 使用构造\r\nlet num1 : number = Number(1);\r\n// 使用JS中对象类型表示类型\r\nlet num2 : Number = 123;\r\n```\r\n\r\n其他数据类型都相同,可以使用构造方法初始化值,使用对象类型标识数据类型\r\n\r\n## string\r\n\r\n字符串可以通过单引号\'\'、双引号\"\"和模板字符串``创建\r\n\r\n```typescript\r\nlet s1 : string = \'单引号字符串\';\r\n\r\nlet s2 : string = \"双引号字符串\";\r\n\r\nlet s3 : string = `第一个${s1},第二个${s2}`;\r\n\r\nlet s4 : string = String(\"对象字符串\");\r\n```\r\n\r\n模板字符串可以使用${变量}方式引用变量\r\n\r\n## boolean\r\n\r\n布尔类型的值用来表示对【true】或者错【false】,在TypeScript中使用boolean表示:\r\n\r\n```typescript\r\nlet age : number = 123;\r\n\r\nlet username : string = \"username\";\r\n\r\nlet isMan : boolean = true;\r\n\r\n// 下方是错误的,new Boolean是对象类型\r\n// let isDog : boolean = new Boolean(true);\r\n\r\n// 可以直接使用Boolean()\r\nlet isDog : boolean = Boolean(true);\r\n```\r\n\r\n## 任意值\r\n\r\n可以通过使用any表示变量可以是任意类型数据,使用any效果和JavaScript相同,后期可以修改变量数据类型\r\n\r\n```typescript\r\n// any类型,初始值为string\r\nlet a1 : any = \"a1\";\r\n// 修改为number类型\r\na1 = 123;\r\n```\r\n\r\n## 类型推断\r\n\r\nTypeScript支持像JavaScript那样不显示声明数据类型,会根据赋值自动推断类型,后期则不可修改值为其他类型的数据\r\n\r\n```typescript\r\n// 类型自动推断为string\r\nlet username = \'张三\';\r\n// Type \'number\' is not assignable to type \'string\'\r\nusername = 123;\r\n```\r\n\r\n## null和undefined\r\n\r\nnull和undefined也可以被当做数据类型来定义\r\n\r\n```typescript\r\nlet nu : null = null;\r\n\r\nlet un : undefined = undefined;\r\n```\r\n\r\nnull是一个对象/变量的值为null,而undefined则表示该变量没有初始化。\r\n\r\n## void\r\n\r\nvoid为空值,是TypeScript中新增的数据类型,表示没有任何返回值的函数\r\n\r\n```typescript\r\nfunction say(): void {\r\n alert(\'我是张三\');\r\n}\r\n\r\nsay();\r\n```\r\n\r\n有些地方会比较,深究null、undefined、void区别,我认为并没有意义,null就是一个对象为空值,undefined就是没有初始值,void用来表示方法没有返回值,不要去描述变量。仅此而已不要再做无谓的深究!\r\n\r\n## 联合类型\r\n\r\n联合类型是该变量可以在声明的类型中随意匹配一个即可,比如年龄可以使用数字表示,也可以使用字符串表示,可以通过** | **符号分割多个类型\r\n\r\n```typescript\r\nlet age : number | string = \'十六\';\r\nage = 16;\r\n```\r\n\r\n如果使用联合类型表示一个变量,此时在操作变量时需要使用共有属性和方法,不能使用某一个类型特有的方法或属性,比如age可以为number或者string类型,number类型有toFixed方法,而string没有,number和string共有的操作有**toString**、**valueOf**方法。\r\n\r\n```typescript\r\nlet age : number | string = \'十六\'\r\nage = 16\r\n// 共有方法\r\nage.toString();\r\n// string有此方法,如果数字调用出现,Property \'length\' does not exist on type \'number\'\r\nage.length;\r\n```\r\n\r\n或者使用**typeof**判断类型之后使用\r\n\r\n```typescript\r\nlet age : number | string = 12\r\n\r\nif(typeof age === \'number\') {\r\n console.log(\"数字类型\")\r\n}\r\n\r\nif(typeof age === \'string\') {\r\n console.log(\"字符串类型\")\r\n}\r\n```\r\n\r\n## 数组\r\n\r\n```typescript\r\n// 通过类型[]方式指定,下例:数组中只允许有number类型数据\r\nlet a1 : number[] = [1,2,3,4];\r\n// 通过泛型指定,Array<类型>,下例:只允许有字符串\r\nlet nameArr : Array<string> = [\'大毛\',\'二毛\',\'小明\'];\r\n```\r\n\r\n## 元组\r\n\r\n元组和数组区别在于,元组中可以存在不同类型的数据。\r\n\r\n```typescript\r\n// 数据类型必须与索引一一匹配\r\nlet a1 : [number,string,number] = [1,\'a\',2];\r\n\r\n// 先声明,再赋值\r\nlet person1: [string, number];\r\nperson1 = [\'大毛\', 25];\r\n\r\n// 获取一项\r\nlet username : string = person1[0];\r\nlet age : number = person1[1];\r\n\r\n// 操作数据\r\nconsole.log(username.indexOf(\"大\"))\r\nconsole.log(age.toFixed(2));\r\n```\r\n\r\n添加越界元素时【元组本身2个元素长度,新增其他数据长度会增加,称为添加越界元素】,它的类型会被限制为元组中每个类型的联合类型:\r\n\r\n```typescript\r\n// 先声明,再赋值\r\nlet person1: [string, number] = [\'大毛\', 25];\r\n\r\nperson1.push(\"123\");\r\nperson1.push(123);\r\n\r\n// Argument of type \'boolean\' is not assignable to parameter of type \'string | number\'.\r\nperson1.push(true);\r\n```\r\n\r\n如果元组中存在可选值时可以在类型后添加?表示,如下\r\n\r\n```typescript\r\n// number类型的值可写可不写,添加?即可\r\nlet person1: [string, number?] = [\'大毛\'];\r\n```\r\n\r\n## 枚举\r\n\r\n枚举(Enum)类型用于取值被限定在一定范围内的场景,比如订单状态为未付款、待发货、待收货、待评价,性别限定为男、女、未知等。\r\n枚举成员会被赋值为从 0 开始递增的数字,同时也会对枚举值到枚举名进行反向映射:\r\n\r\n```typescript\r\nenum OrderStatus {NO_PAY, SHIPPED, RECEIVED, EVALUATED,REVIEWED};\r\n\r\n// 使用\r\nconsole.log(OrderStatus[\'NO_PAY\'] === 0);\r\nconsole.log(OrderStatus[\'SHIPPED\'] === 1);\r\nconsole.log(OrderStatus[\'RECEIVED\'] === 2);\r\n\r\nconsole.log(OrderStatus[0] === \'NO_PAY\');\r\nconsole.log(OrderStatus[1] === \'SHIPPED\');\r\nconsole.log(OrderStatus[2] === \'RECEIVED\');\r\n```\r\n\r\n你还可以通过手动赋值修改默认以0递增的数据\r\n\r\n```typescript\r\nenum OrderStatus {NO_PAY = 1, SHIPPED = 2, RECEIVED = 3, EVALUATED,REVIEWED};\r\n\r\n// 使用\r\nconsole.log(OrderStatus[\'NO_PAY\']);\r\nconsole.log(OrderStatus[\'SHIPPED\']);\r\nconsole.log(OrderStatus[\'RECEIVED\']);\r\nconsole.log(OrderStatus[\'EVALUATED\']);\r\nconsole.log(OrderStatus[\'REVIEWED\']);\r\n```\r\n\r\n## 函数\r\n\r\nTypeScript中声明函数可以在形式参数和返回值中指定数据类型。\r\n\r\n```typescript\r\n// 接收number类型参数,返回number类型参数\r\nfunction fun1(num1 : number,num2 : number) : number {\r\n\r\n return num1 + num2;\r\n}\r\nconsole.log(fun1(1,2));\r\n```\r\n\r\n也支持通过函数表达式【Function Expression】的方式声明函数\r\n\r\n```typescript\r\nlet fun2 = function(str1 : string,str2 : string) : string {\r\n\r\n return str1.concat(str2);\r\n}\r\n\r\nconsole.log(fun2(\'A\',\'B\'));\r\n```\r\n\r\n函数同样支持**可选参数**,当然可选参数必须在最后\r\n\r\n```typescript\r\nfunction buildName(firstName: string, lastName?: string) {\r\n if (lastName) {\r\n return firstName + \' \' + lastName;\r\n } else {\r\n return firstName;\r\n }\r\n}\r\nlet tomcat = buildName(\'Tom\', \'Cat\');\r\nlet tom = buildName(\'Tom\');\r\n```\r\n\r\n如果没有返回值,则可以使用**void**修饰返回值类型,无返回值时接收到的为**undefined**\r\n\r\n```typescript\r\nfunction fun1(firstName: string):void {\r\n console.log(firstName.toUpperCase());\r\n}\r\nlet result = fun1(\'Tom\');\r\nconsole.log(result);\r\n```\r\n\r\nES6中允许方法参数有默认值,**TypeScript 会将添加了默认值的参数识别为可选参数**:\r\n\r\n```typescript\r\nfunction buildName(firstName: string, lastName: string = \'Cat\') {\r\n return firstName + \' \' + lastName;\r\n}\r\nlet tomcat = buildName(\'Tom\', \'Cat\');\r\nlet tom = buildName(\'Tom\');\r\n```\r\n\r\n此时就不受「可选参数必须接在必需参数后面」的限制了:\r\n\r\n```typescript\r\nfunction buildName(firstName: string = \'Tom\', lastName: string) {\r\n return firstName + \' \' + lastName;\r\n}\r\nlet tomcat = buildName(\'Tom\', \'Cat\');\r\nlet cat = buildName(undefined, \'Cat\');\r\n```\r\n\r\nES6中可以使用 **...rest** 的方式获取函数中的剩余参数(rest 参数):\r\n\r\n```typescript\r\nfunction push(array, ...items) {\r\n items.forEach(function(item) {\r\n array.push(item);\r\n });\r\n}\r\n\r\nlet a: any[] = [];\r\npush(a, 1, 2, 3);\r\n```\r\n\r\n事实上,items 是一个数组。所以我们可以用数组的类型来定义它:\r\n\r\n```typescript\r\nfunction push(array: any[], ...items: any[]) {\r\n items.forEach(function(item) {\r\n array.push(item);\r\n });\r\n}\r\n\r\nlet a = [];\r\npush(a, 1, 2, 3);\r\n```\r\n\r\n注意,rest 参数只能是最后一个参数\r\n\r\n## 接口\r\n\r\n接口用来定义一种规范,具体的时候交由对象来做,举个生活中的例子我们购买商品按照消费者权益来说所有的商品都必须有售后保障,那么具体怎么实现售后,你是上门维修也好,直接换货也好,就有厂家自己实现。这个必须有售后就是规范,各个厂家就是一个一个具体的对象,交由对象实现就行了。\r\n程序中就是我们希望在程序内描述一个人,那么人的规范就是有名字、性别、年龄和一些行为这可以通过接口描述,具体是哪一个人,就交由对象来具体化【实例化】。\r\n\r\n```typescript\r\n// 接口定义抽象结构\r\ninterface Person {\r\n username: string;\r\n age: number;\r\n say():void;\r\n}\r\n// 对象具体实现\r\nlet tom: Person = {\r\n username: \'张三\',\r\n age: 25,\r\n say() : void {\r\n console.log(this.username)\r\n }\r\n};\r\n```\r\n\r\n### 可选属性\r\n\r\n有时认为一个对象的某个属性可有可无,可以使用可选属性\r\n\r\n```typescript\r\ninterface Person {\r\n name: string;\r\n age?: number;\r\n}\r\n\r\nlet p1: Person = {\r\n name: \'大毛\'\r\n};\r\nlet p2: Person = {\r\n name: \'小毛\',\r\n age: 25\r\n};\r\n```\r\n\r\n### 任意属性\r\n\r\n又是我们希望可以在对象中添加任意的属性:\r\n\r\n```typescript\r\ninterface Person {\r\n name: string;\r\n age?: number;\r\n [propName: string]: any;\r\n}\r\n\r\nlet tom: Person = {\r\n name: \'大毛\',\r\n gender: \'男\',\r\n};\r\n```\r\n\r\n任意属性的类型需要包含可选属性,否则编译报错,比如any包含number类型,如果将any换成string,则age可选属性就会报错\r\n\r\n### 只读属性\r\n\r\n有时候我们希望对象中的一些字段在创建的时候被赋值后就不可更改,那么可以用 readonly 定义只读属性:\r\n\r\n```typescript\r\ninterface IBook {\r\n readonly author: string;\r\n bookname: string;\r\n}\r\n\r\nlet book1: IBook = {\r\n author: \'小明\',\r\n bookname: \'TypeScript养成记\',\r\n};\r\n\r\nbook1.author = \'大毛\';\r\n```\r\n\r\n## 类\r\n\r\nES6中JavaScript引入了类的概念,类也是用来定义事物的抽象,交由对象具体实现,在面向对象的语言中,对于类我们应该熟知这么几个概念:\r\n\r\n- 类(Class):定义了一件事物的抽象特点,包含它的属性和方法\r\n- 对象(Object):类的实例,通过 new 生成\r\n- 面向对象(OOP)的三大特性:封装、继承、多态\r\n- 封装(Encapsulation):将对数据的操作细节隐藏起来,只暴露对外的接口。外界调用端不需要(也不可能)知道细节,就能通过对外提供的接口来访问该对象,同时也保证了外界无法任意更改对象内部的数据\r\n- 继承(Inheritance):子类继承父类,子类除了拥有父类的所有特性外,还有一些更具体的特性\r\n- 多态(Polymorphism):由继承而产生了相关的不同的类,对同一个方法可以有不同的响应。比如 Cat 和 Dog 都继承自 Animal,但是分别实现了自己的 eat 方法。此时针对某一个实例,我们无需了解它是 Cat 还是 Dog,就可以直接调用 eat 方法,程序会自动判断出来应该如何执行 eat\r\n- 存取器(getter & setter):用以改变属性的读取和赋值行为\r\n- 修饰符(Modifiers):修饰符是一些关键字,用于限定成员或类型的性质。比如 public 表示公有属性或方法\r\n- 抽象类(Abstract Class):抽象类是供其他类继承的基类,抽象类不允许被实例化。抽象类中的抽象方法必须在子类中被实现\r\n- 接口(Interfaces):不同类之间公有的属性或方法,可以抽象成一个接口。接口可以被类实现(implements)。一个类只能继承自另一个类,但是可以实现多个接口\r\n\r\n### TypeScript中的类\r\n\r\nTypeScript 可以使用三种访问修饰符(Access Modifiers),分别是 public、private 和 protected。\r\n\r\n- public 修饰的属性或方法是公有的,可以在任何地方被访问到,默认所有的属性和方法都是 public 的\r\n- private 修饰的属性或方法是私有的,不能在声明它的类的外部访问\r\n- protected 修饰的属性或方法是受保护的,它和 private 类似,区别是它在子类中也是允许被访问的\r\n\r\n比如创建一个动物类,实例化一个狗\r\n\r\n```typescript\r\nclass Animal {\r\n public name;\r\n public constructor(name:string) {\r\n this.name = name;\r\n }\r\n}\r\n\r\nlet a = new Animal(\'大黄\');\r\nconsole.log(a.name); // 大黄\r\na.name = \'小黑\';\r\nconsole.log(a.name); // 小黑\r\n```\r\n\r\n上述可以直接修改和获取数据,对于对象数据来说是不安全的,可以通过private或者protected提高安全性。\r\n\r\n### private修饰属性\r\n\r\n使用private修饰将属性私有化,属性只能在类内部直接调用,如果要修改数据和获取数据可以通过公开的方法获取\r\n\r\n```typescript\r\nclass Animal {\r\n private name;\r\n public constructor(name:string) {\r\n this.name = name;\r\n }\r\n\r\n public getName():string {\r\n return this.name;\r\n }\r\n\r\n public setName(name:string):string {\r\n return this.name = name;\r\n }\r\n}\r\n\r\nlet a = new Animal(\'大黄\');\r\nconsole.log(a.getName()); // 大黄\r\na.setName(\'小黑\');\r\nconsole.log(a.getName()); // 小黑\r\n```\r\n\r\n### protected修饰属性\r\n\r\n被private修饰,包括子类在内都不被允许访问,只有本类内部可以访问,如果希望子类可以访问则可以使用protected修饰\r\n\r\n```typescript\r\nclass Animal {\r\n protected name;\r\n public constructor(name:string) {\r\n this.name = name;\r\n }\r\n\r\n public getName():string {\r\n return this.name;\r\n }\r\n\r\n public setName(name:string):string {\r\n return this.name = name;\r\n }\r\n}\r\n\r\nclass Dog extends Animal {\r\n constructor(name:string) {\r\n super(name);\r\n // name属性被继承过来\r\n console.log(this.name);\r\n }\r\n}\r\n```\r\n\r\n### private修饰构造方法\r\n\r\n如果构造方法通过private修饰被私有化,则该类不能被实例化,也不能被继承\r\n\r\n```typescript\r\nclass Animal {\r\n protected name;\r\n // 私有化构造方法\r\n private constructor(name:string) {\r\n this.name = name;\r\n }\r\n\r\n public getName():string {\r\n return this.name;\r\n }\r\n\r\n public setName(name:string):string {\r\n return this.name = name;\r\n }\r\n}\r\n\r\n// 继承就会报错\r\n// Cannot extend a class \'Animal\'. Class constructor is marked as private\r\nclass Dog extends Animal {\r\n constructor(name:string) {\r\n super(name);\r\n // name属性被继承过来\r\n console.log(this.name);\r\n }\r\n}\r\n```\r\n\r\n### protected 修饰构造方法\r\n\r\n如果构造函数修饰为 protected 时,该类不能实例化\r\n\r\n```typescript\r\nclass Animal {\r\n protected name;\r\n // protected修饰\r\n protected constructor(name:string) {\r\n this.name = name;\r\n }\r\n\r\n public getName():string {\r\n return this.name;\r\n }\r\n\r\n public setName(name:string):string {\r\n return this.name = name;\r\n }\r\n}\r\n// 继承没毛病\r\nclass Dog extends Animal {\r\n constructor(name:string) {\r\n super(name);\r\n // name属性被继承过来\r\n console.log(this.name);\r\n }\r\n}\r\n// 实例化有问题\r\n// Constructor of class \'Animal\' is protected and only accessible within the class declaration\r\nlet a = new Animal(\'大黄\');\r\n```\r\n\r\n### 参数属性\r\n\r\n类中属性可以定义在构造方法上,等同于类中定义了属性\r\n\r\n```typescript\r\nclass Animal {\r\n // 参数属性\r\n public constructor(public name:string) {\r\n }\r\n}\r\n\r\nlet a = new Animal(\"大黄\");\r\nconsole.log(a.name)\r\n```\r\n\r\n### readonly\r\n\r\n只读属性关键字也可用于类中,只允许出现在属性声明或索引签名或构造函数中。\r\n\r\n```typescript\r\nclass Animal {\r\n // 只读属性\r\n readonly name;\r\n public constructor(name:string) {\r\n this.name = name;\r\n }\r\n}\r\n\r\nlet a = new Animal(\'大黄\');\r\nconsole.log(a.name);\r\n// 不可再次修改\r\na.name = \'小黑\';\r\n```\r\n\r\n注意如果 readonly 和其他访问修饰符同时存在的话,需要写在其后面。\r\n\r\n```typescript\r\nclass Animal {\r\n // public readonly name;\r\n public constructor(public readonly name:string) {\r\n // this.name = name;\r\n }\r\n}\r\n```\r\n\r\n### 抽象类\r\n\r\n抽象类不能被实例化,使用abstract修饰\r\n\r\n```typescript\r\nabstract class Animal {\r\n public name;\r\n public constructor(name:string) {\r\n this.name = name;\r\n }\r\n public abstract sayHi():any;\r\n}\r\n// Cannot create an instance of an abstract class.\r\nlet a = new Animal(\'大黄\');\r\n```\r\n\r\n抽象类中的抽象方法必须被子类实现,子类必须实现抽象类中的所有抽象方法,否则需要继续抽象下去:\r\n\r\n```typescript\r\nabstract class Animal {\r\n public name;\r\n public constructor(name:string) {\r\n this.name = name;\r\n }\r\n public abstract eat():any;\r\n}\r\n\r\nclass Cat extends Animal {\r\n public eat() {\r\n console.log(`${this.name} 在吃鱼.`);\r\n }\r\n}\r\n\r\nlet c = new Cat(\'小花\');\r\nc.eat();\r\n```\r\n\r\n如果没有实现所有抽象方法则继续报错:\r\n\r\n```typescript\r\nabstract class Animal {\r\n public name;\r\n public constructor(name:string) {\r\n this.name = name;\r\n }\r\n public abstract eat():any;\r\n public abstract sayHi():any;\r\n}\r\n\r\n// Non-abstract class \'Cat\' does not implement all abstract members of \'Animal\'\r\nclass Cat extends Animal {\r\n public eat() {\r\n console.log(`${this.name} 在吃鱼.`);\r\n }\r\n}\r\n```\r\n\r\n## 泛型\r\n\r\n泛型(Generics)是指在定义函数、接口或类的时候,不预先指定具体的类型,而在使用的时候再指定类型的一种特性。\r\n\r\n### 无泛型\r\n\r\n实现一个函数 createArray,它可以创建一个指定长度的数组,同时将每一项都填充一个默认值:\r\n\r\n```typescript\r\nfunction createArray(length: number, value: any): Array<any> {\r\n let result = [];\r\n for (let i = 0; i < length; i++) {\r\n result[i] = value;\r\n }\r\n return result;\r\n}\r\n\r\ncreateArray(3, \'x\'); // [\'x\', \'x\', \'x\']\r\n```\r\n\r\n此处使用any当做入参和Array<any>反参类型,编译不会报错,但是可能会造成类型不安全的问题,调用方法的用户可能瞎传数据,你的方法就报错啦。此时泛型就登场了,**解决参数类型安全问题**\r\n\r\n```typescript\r\nfunction createArray<T>(length: number, value: T): Array<T> {\r\n let result: T[] = [];\r\n for (let i = 0; i < length; i++) {\r\n result[i] = value;\r\n }\r\n return result;\r\n}\r\n\r\ncreateArray<string>(3, \'x\'); // [\'x\', \'x\', \'x\']\r\n```\r\n\r\n上例中,我们在函数名后添加了 <T>,其中 T 用来指代任意输入的类型,在后面的输入 value: T 和输出 Array<T> 中即可使用了。\r\n接着在调用的时候,可以指定它具体的类型为 string。当然,也可以不手动指定,而让类型推论自动推算出来:\r\n\r\n```typescript\r\nfunction createArray<T>(length: number, value: T): Array<T> {\r\n let result: T[] = [];\r\n for (let i = 0; i < length; i++) {\r\n result[i] = value;\r\n }\r\n return result;\r\n}\r\n\r\ncreateArray(3, \'x\'); // [\'x\', \'x\', \'x\']\r\n```\r\n\r\n### 多个类型参数\r\n\r\n定义泛型的时候,可以一次定义多个类型参数:\r\n\r\n```typescript\r\nfunction swap<T, U>(tuple: [T, U]): [U, T] {\r\n return [tuple[1], tuple[0]];\r\n}\r\n\r\nswap([7, \'seven\']); // [\'seven\', 7]\r\n```\r\n\r\n### 泛型约束\r\n\r\n在函数内部使用泛型变量的时候,由于事先不知道它是哪种类型,所以不能随意的操作它的属性或方法:\r\n\r\n```typescript\r\nfunction loggingIdentity<T>(arg: T): T {\r\n console.log(arg.length);\r\n return arg;\r\n}\r\n```\r\n\r\n上例中,泛型 T 不一定包含属性 length,所以编译的时候报错了。\r\n这时,我们可以对泛型进行约束,只允许这个函数传入那些包含 length 属性的变量。这就是泛型约束:\r\n\r\n```typescript\r\ninterface Lengthwise {\r\n length: number;\r\n}\r\n\r\nfunction loggingIdentity<T extends Lengthwise>(arg: T): T {\r\n console.log(arg.length);\r\n return arg;\r\n}\r\n```\r\n\r\n上例中,我们使用了 extends 约束了泛型 T 必须符合接口 Lengthwise 的形状,也就是必须包含 length 属性。\r\n此时如果调用 loggingIdentity 的时候,传入的 arg 不包含 length,那么在编译阶段就会报错了:\r\n\r\n```typescript\r\ninterface Lengthwise {\r\n length: number;\r\n}\r\n\r\nfunction loggingIdentity<T extends Lengthwise>(arg: T): T {\r\n console.log(arg.length);\r\n return arg;\r\n}\r\n\r\nloggingIdentity(7);\r\n```\r\n\r\n多个类型参数之间也可以互相约束:\r\n\r\n```typescript\r\nfunction copyFields<T extends U, U>(target: T, source: U): T {\r\n for (let id in source) {\r\n target[id] = (<T>source)[id];\r\n }\r\n return target;\r\n}\r\n\r\nlet x = { a: 1, b: 2, c: 3, d: 4 };\r\n\r\ncopyFields(x, { b: 10, d: 20 });\r\n```\r\n\r\n上例中,我们使用了两个类型参数,其中要求 T 继承 U,这样就保证了 U 上不会出现 T 中不存在的字段。\r\n\r\n### 泛型接口\r\n\r\n泛型也可以用来定义接口\r\n\r\n```typescript\r\ninterface CreateArrayFunc {\r\n <T>(length: number, value: T): Array<T>;\r\n}\r\n\r\nlet createArray: CreateArrayFunc;\r\ncreateArray = function<T>(length: number, value: T): Array<T> {\r\n let result: T[] = [];\r\n for (let i = 0; i < length; i++) {\r\n result[i] = value;\r\n }\r\n return result;\r\n}\r\n\r\ncreateArray(3, \'x\'); // [\'x\', \'x\', \'x\']\r\n```\r\n\r\n进一步,我们可以把泛型参数提前到接口名上:\r\n\r\n```typescript\r\ninterface CreateArrayFunc<T> {\r\n (length: number, value: T): Array<T>;\r\n}\r\n\r\nlet createArray: CreateArrayFunc<any>;\r\ncreateArray = function<T>(length: number, value: T): Array<T> {\r\n let result: T[] = [];\r\n for (let i = 0; i < length; i++) {\r\n result[i] = value;\r\n }\r\n return result;\r\n}\r\n\r\ncreateArray(3, \'x\'); // [\'x\', \'x\', \'x\']\r\n```\r\n\r\n注意,此时在使用泛型接口的时候,需要定义泛型的类型。\r\n\r\n### 泛型类\r\n\r\n与泛型接口类似,泛型也可以用于类的类型定义中:\r\n\r\n```typescript\r\nclass GenericNumber<T> {\r\n zeroValue: T;\r\n add: (x: T, y: T) => T;\r\n}\r\n\r\nlet myGenericNumber = new GenericNumber<number>();\r\nmyGenericNumber.zeroValue = 0;\r\nmyGenericNumber.add = function(x, y) { return x + y; };\r\n```\r\n\r\n### 泛型参数的默认类型\r\n\r\n在 TypeScript 2.3 以后,我们可以为泛型中的类型参数指定默认类型。当使用泛型时没有在代码中直接指定类型参数,从实际值参数中也无法推测出时,这个默认类型就会起作用。\r\n\r\n```typescript\r\nfunction createArray<T = string>(length: number, value: T): Array<T> {\r\n let result: T[] = [];\r\n for (let i = 0; i < length; i++) {\r\n result[i] = value;\r\n }\r\n return result;\r\n}\r\n```\r\n\r\n# 类型断言\r\n\r\n类型断言(Type Assertion)可以用来手动指定一个值的类型。语法为\r\n\r\n```typescript\r\n值 as 类型\r\n\r\n或\r\n \r\n<类型>值\r\n```\r\n\r\n在 tsx 语法(React 的 jsx 语法的 ts 版)中必须使用 **值 as 类型**。\r\n\r\n## 联合类型断言为一个具体类型\r\n\r\n前文介绍了支持联合类型,即一个变量可以是string类型也可以是number类型,只能访问该变量所有类型的共有属性和方法\r\n\r\n```typescript\r\nfunction fun1(args: string | number):number {\r\n // 将值断言为number类型\r\n let result = args as number;\r\n\r\n return result;\r\n}\r\n\r\nconsole.log(fun1(\"1\"))\r\n```\r\n\r\n## 将一个父类断言为更加具体的子类\r\n\r\n当类之间有继承关系时,类型断言也是很常见的:\r\n\r\n```typescript\r\nclass Animal {\r\n name: string;\r\n constructor(name:string) {\r\n this.name = name;\r\n }\r\n}\r\n\r\nclass Dog extends Animal {\r\n constructor(name:string) {\r\n super(name);\r\n }\r\n doorkeeper():void {\r\n console.log(this.name + \"在看家\")\r\n }\r\n}\r\nclass Cat extends Animal {\r\n constructor(name:string) {\r\n super(name);\r\n }\r\n catchMouse():void {\r\n console.log(this.name + \"在抓老鼠\")\r\n }\r\n}\r\n\r\n// 离家需要狗看门,也需要猫抓老鼠\r\nfunction leaveHome(animal: Animal) {\r\n let dog = animal as Dog;\r\n dog.doorkeeper();\r\n}\r\n\r\nleaveHome(new Dog(\'旺财\'));\r\n```\r\n\r\n上面的例子中,我们声明了函数 leaveHome,转为Dog类型,调用看门方法,离家时构建一个狗对象,调用它的看门方法即可。\r\n\r\n## 断言限制\r\n\r\n类型不可随意断言,比如Dog是Animal的一种,Adimal可以断言为Dog,Cat不是Dog的一种,Cat就不能断言为Dog。如下例子:\r\n\r\n```typescript\r\nclass Animal {\r\n name: string;\r\n constructor(name:string) {\r\n this.name = name;\r\n }\r\n}\r\n\r\nclass Dog extends Animal {\r\n constructor(name:string) {\r\n super(name);\r\n }\r\n doorkeeper():void {\r\n console.log(this.name + \"在看家\")\r\n }\r\n}\r\nclass Cat extends Animal {\r\n constructor(name:string) {\r\n super(name);\r\n }\r\n catchMouse():void {\r\n console.log(this.name + \"在抓老鼠\")\r\n }\r\n}\r\n\r\n// 离家需要狗看门\r\n// 如果传入类型为Cat,断言成Dog编译不会报错,但运行时就会报错\r\nfunction leaveHome(animal: Animal) {\r\n let dog = animal as Dog;\r\n dog.doorkeeper();\r\n}\r\n// 实例化一个Cat\r\nleaveHome(new Cat(\'小花\'));\r\n```\r\n\r\n可以使用**instanceof**判断类型后对数据进行断言:\r\n\r\n```typescript\r\nclass Animal {\r\n name: string;\r\n constructor(name:string) {\r\n this.name = name;\r\n }\r\n}\r\n\r\nclass Dog extends Animal {\r\n constructor(name:string) {\r\n super(name);\r\n }\r\n doorkeeper():void {\r\n console.log(this.name + \"在看家\")\r\n }\r\n}\r\nclass Cat extends Animal {\r\n constructor(name:string) {\r\n super(name);\r\n }\r\n catchMouse():void {\r\n console.log(this.name + \"在抓老鼠\")\r\n }\r\n}\r\n\r\n// 判断类型之后\r\nfunction leaveHome(animal: Animal) {\r\n if(animal instanceof Dog) {\r\n let dog = animal as Dog;\r\n dog.doorkeeper();\r\n }else if(animal instanceof Cat) {\r\n let cat = animal as Cat;\r\n cat.catchMouse();\r\n }\r\n}\r\n\r\nleaveHome(new Cat(\'小花\'));\r\n```\r\n\r\n# 类型别名\r\n\r\n类型别名用来给一个类型起个新名字。\r\n\r\n```typescript\r\ntype Name = string;\r\ntype NameResolver = () => string;\r\ntype NameOrResolver = Name | NameResolver;\r\nfunction getName(n: NameOrResolver): Name {\r\n if (typeof n === \'string\') {\r\n return n;\r\n } else {\r\n return n();\r\n }\r\n}\r\n```\r\n\r\n上例中,我们使用 type 创建类型别名。类型别名常用于联合类型,将多个类型封装进一个类型中', 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, '2024-05-01 18:01:07', '2024-05-01 22:06:16', 0, 0, 'javascript,TypeScript');
INSERT INTO `ams_article` VALUES (9, 3, 8, '标题撒大大标题撒大大标helloworld题撒大大啊实打实大啊实打实大师', 'http://localhost:8128/img/article/20240501180023A002.png', '电风扇', '# 什么是TypeScript\r\n\r\nTypeScript于2012年10月由微软推出上线,始于JavaScript,看名字就知道TypeScript主要强调了类型,TypeScript在JaaScript基础上增加**类型系统**,JavaScript是一个弱类型语言,在编译期间声明的变量可以是任意类型,会导致运行时可能出现的类型错误,使用TypeScript之后可以指定变量类型,如果出现类型问题在编译期间就可以暴露出来,更容易查bug。\r\n最终TypScript又归于JavaScript,运行时其实还是将TypeScript转译成JavaScript执行,因为浏览器,node环境只能运行JavaScript。\r\n\r\n# 安装TypeScript\r\n\r\n首先确保您的电脑上安装了node,建议安装nodejs18以上版本。可点击链接进入[node下载地址](https://www.nodejs.com.cn/)。\r\nTypeScript需要编译为JavaScript文件执行,所以需要先安装TypeScript环境,可以将TypeScipt文件编译为JavaScript在浏览器或者node环境中运行。首先同时按下win + r键输入cmd唤起命令窗口\r\n**安装命令:**\r\n\r\n```shell\r\n# 全局安装typescript\r\nnpm install -g typescript\r\n```\r\n\r\n![image.png](http://localhost:8128/img/article/20240501180023A002.png)\r\n安装之后TypeScript的执行命令为tsc,比如想要查看TypeScript版本则可输入:\r\n\r\n```shell\r\ntsc -version\r\n```\r\n\r\n# HelloWorld\r\n\r\n## 创建文件\r\n\r\n写JavaScript时,文件后缀为.js。写TypeScript时文件后缀名为.ts。可以打开任意的编辑器整活,此处我使用VsCode开搞。以声明sting类型变量为例:\r\n\r\n```typescript\r\n// 变量title后边加上:string。指定为string类型,修改变量值时就只能是string类型\r\nlet title:string = \"Hello TypeScript\";\r\n\r\nconsole.log(title);\r\n```\r\n\r\n![image.png](http://localhost:8128/img/article/20240501180023A002.png)\r\n所以说ts声明变量的语法为:\r\n\r\n```javascript\r\n变量修饰符 变量名 : 数据类型 = 初始化值;\r\n如:var/let/const vag:number = 123;\r\n```\r\n\r\n## 编译\r\n\r\n将ts文件编译为js文件执行,使用tsc命令即可命令\r\n\r\n```shell\r\ntsc 01-hellosworld.ts\r\n```\r\n\r\n执行之后会在同级目录下生成一个同名的js文件\r\n![image.png](http://localhost:8128/img/article/20240501180023A002.png)\r\n\r\n## 执行\r\n\r\n使用node命令或者通过浏览器打开js文件来执行,如果使用node执行则使用nod命令:\r\n\r\n```shell\r\nnode 01-hellosworld.js\r\n```\r\n\r\n![image.png](http://localhost:8128/img/article/20240501180023A002.png)\r\n\r\n## 快速执行\r\n\r\n安装ts-node包实现快速运行ts,其实内部还是将ts转为js执行,底层逻辑不变,只是简化了开发人员操作。\r\n**安装命令:**\r\n\r\n```shell\r\nnpm install -g ts-node\r\n```\r\n\r\n**执行ts文件:**\r\n\r\n```shell\r\nts-node 01-hellosworld.ts\r\n```\r\n\r\n此时就不会再生成js文件啦。**但是执行的还是js哦,这是一定要记清楚的。**\r\n\r\n## 修改类型\r\n\r\n尝试将title修改为数字类型数据,如果在javascript中是可行的,类型可随意修改,在typescript中,如果修改数据类型在编译期就会报错\r\n![image.png](http://localhost:8128/img/article/20240501180023A002.png)\r\n那么忽略编辑器的报错,尝试运行会返回TSError错误,错误信息是编译TypeScript时出现问题。\r\n![image.png](http://localhost:8128/img/article/20240501180023A002.png)\r\n此处可以看出TypeScript相较于JavaScript对类型要求更严格,这也是很多开发人员吐槽的地方,以前写js\r\n随心所欲,随便定义一个变量,下边想怎么改都成,使用了ts之后只能修改值为对应类型的,好像添加了束缚,但我觉得这是好事:\r\n\r\n- 首先数据类型在逻辑处理中其实就应该输入同一个类型内的修改,严格来说是不可以将字符串类型修改为数字类型等,甚至是对象类型的数据。\r\n- 在复杂的业务处理中,甚至有时候都已经忘记了一个变量是什么类型的了😛。\r\n\r\n# TypeScript优势\r\n\r\nTypeScript包含JavaScript所有功能,同时又增加了类型系统,弥补了JavaScript弱类型的缺陷,那么为什么是缺陷呢?在ES6中JavaScript又推出了很多新的API,方便处理数据,这些api有的是字符串才能使用的,有的是数组才能使用的,有的是数字才能使用的,而JavaScript在编译时并不会检查当前变量是什么类型,能否使用调用的方法,在运行时就会出现错误。甚至会导致严重的线上bug。比如:\r\n\r\n```javascript\r\nlet arr = [1,2,3,4,5,6,7];\r\n\r\n// 将数组转为数字类型\r\narr = 1;\r\n// 调用filter方法,获取大于4的数据,此方法number类型肯定不能调用,但编译期并不会提示\r\nlet result = arr.filter(item => item > 4);\r\nconsole.log(result);\r\n\r\n```\r\n\r\n运行时就会出现TypeError即类型错误。\r\n![image.png](http://localhost:8128/img/article/20240501180023A002.png)\r\n以上错误在开发工作中比比皆是,不要妄图以为脑子好用能记住所有变量的数据类型,有时候你甚至不知道用户传过来的是什么类型的数据,所以在定义变量和方法参数时,设置明确的类型势在必行。\r\n\r\n# 数据类型\r\n\r\nTypeScript是JavaScript的扩充,所以包含JavaScript中的所有数据类型,同时又增加了若干个数据类型。下表列出TypeScript中所有的数据类型,不区分JS和TS,没有什么实际意义:\r\n\r\n| 数据类型 | 作用 |\r\n| ------------------ | ------------------------------------------------------------ |\r\n| number:数字类型 | 双精度 64 位浮点值。它可以用来表示整数和分数 |\r\n| string:字符串类型 | 描述字符或字符串,使用单引号(\')或双引号(\")来表示字符串类型。反引号(`)来定义多行文本和内嵌表达式。 |\r\n| boolean:布尔类型 | 表示逻辑值:true 和 false。 |\r\n| Object:对象 | 对象类型包括,数组、对象、函数 |\r\n| 元组 | 元组类型用来表示已知元素数量和类型的数组,各元素的类型不必相同,对应位置的类型需要相同。 |\r\n| enum:枚举 | 枚举类型用于定义数值集合。 |\r\n| any:任意类型 | 声明为 any 的变量可以赋予任意类型的值。 |\r\n| null | 表示对象值缺失。 |\r\n| undefined | 用于初始化变量为一个未定义的值 |\r\n| void | 用于标识方法返回值的类型,表示该方法没有返回值。 |\r\n| symbol | 用来声明唯一值,解决命名冲突问题 |\r\n| never | 其它类型(包括 null 和 undefined)的子类型,代表从不会出现的值。 |\r\n\r\n## number\r\n\r\n前端的JavaScript和TypeScript中没有整数和小数之分,数字类型统一使用number表示,可以使用各种进制实例化一个数字,写法如下:\r\n\r\n```typescript\r\n// 使用十进制表示\r\nlet num1: number = 6;\r\n// 十六进制\r\nlet num2: number = 0xf00d;\r\n// ES6 中的二进制表示法\r\nlet num3: number = 0b1010;\r\n// ES6 中的八进制表示法\r\nlet num4: number = 0o744;\r\n// 非数字\r\nlet num5: number = NaN;\r\n// 无穷值\r\nlet infinityNumber: number = Infinity;\r\n// 使用构造\r\nlet num1 : number = Number(1);\r\n// 使用JS中对象类型表示类型\r\nlet num2 : Number = 123;\r\n```\r\n\r\n其他数据类型都相同,可以使用构造方法初始化值,使用对象类型标识数据类型\r\n\r\n## string\r\n\r\n字符串可以通过单引号\'\'、双引号\"\"和模板字符串``创建\r\n\r\n```typescript\r\nlet s1 : string = \'单引号字符串\';\r\n\r\nlet s2 : string = \"双引号字符串\";\r\n\r\nlet s3 : string = `第一个${s1},第二个${s2}`;\r\n\r\nlet s4 : string = String(\"对象字符串\");\r\n```\r\n\r\n模板字符串可以使用${变量}方式引用变量\r\n\r\n## boolean\r\n\r\n布尔类型的值用来表示对【true】或者错【false】,在TypeScript中使用boolean表示:\r\n\r\n```typescript\r\nlet age : number = 123;\r\n\r\nlet username : string = \"username\";\r\n\r\nlet isMan : boolean = true;\r\n\r\n// 下方是错误的,new Boolean是对象类型\r\n// let isDog : boolean = new Boolean(true);\r\n\r\n// 可以直接使用Boolean()\r\nlet isDog : boolean = Boolean(true);\r\n```\r\n\r\n## 任意值\r\n\r\n可以通过使用any表示变量可以是任意类型数据,使用any效果和JavaScript相同,后期可以修改变量数据类型\r\n\r\n```typescript\r\n// any类型,初始值为string\r\nlet a1 : any = \"a1\";\r\n// 修改为number类型\r\na1 = 123;\r\n```\r\n\r\n## 类型推断\r\n\r\nTypeScript支持像JavaScript那样不显示声明数据类型,会根据赋值自动推断类型,后期则不可修改值为其他类型的数据\r\n\r\n```typescript\r\n// 类型自动推断为string\r\nlet username = \'张三\';\r\n// Type \'number\' is not assignable to type \'string\'\r\nusername = 123;\r\n```\r\n\r\n## null和undefined\r\n\r\nnull和undefined也可以被当做数据类型来定义\r\n\r\n```typescript\r\nlet nu : null = null;\r\n\r\nlet un : undefined = undefined;\r\n```\r\n\r\nnull是一个对象/变量的值为null,而undefined则表示该变量没有初始化。\r\n\r\n## void\r\n\r\nvoid为空值,是TypeScript中新增的数据类型,表示没有任何返回值的函数\r\n\r\n```typescript\r\nfunction say(): void {\r\n alert(\'我是张三\');\r\n}\r\n\r\nsay();\r\n```\r\n\r\n有些地方会比较,深究null、undefined、void区别,我认为并没有意义,null就是一个对象为空值,undefined就是没有初始值,void用来表示方法没有返回值,不要去描述变量。仅此而已不要再做无谓的深究!\r\n\r\n## 联合类型\r\n\r\n联合类型是该变量可以在声明的类型中随意匹配一个即可,比如年龄可以使用数字表示,也可以使用字符串表示,可以通过** | **符号分割多个类型\r\n\r\n```typescript\r\nlet age : number | string = \'十六\';\r\nage = 16;\r\n```\r\n\r\n如果使用联合类型表示一个变量,此时在操作变量时需要使用共有属性和方法,不能使用某一个类型特有的方法或属性,比如age可以为number或者string类型,number类型有toFixed方法,而string没有,number和string共有的操作有**toString**、**valueOf**方法。\r\n\r\n```typescript\r\nlet age : number | string = \'十六\'\r\nage = 16\r\n// 共有方法\r\nage.toString();\r\n// string有此方法,如果数字调用出现,Property \'length\' does not exist on type \'number\'\r\nage.length;\r\n```\r\n\r\n或者使用**typeof**判断类型之后使用\r\n\r\n```typescript\r\nlet age : number | string = 12\r\n\r\nif(typeof age === \'number\') {\r\n console.log(\"数字类型\")\r\n}\r\n\r\nif(typeof age === \'string\') {\r\n console.log(\"字符串类型\")\r\n}\r\n```\r\n\r\n## 数组\r\n\r\n```typescript\r\n// 通过类型[]方式指定,下例:数组中只允许有number类型数据\r\nlet a1 : number[] = [1,2,3,4];\r\n// 通过泛型指定,Array<类型>,下例:只允许有字符串\r\nlet nameArr : Array<string> = [\'大毛\',\'二毛\',\'小明\'];\r\n```\r\n\r\n## 元组\r\n\r\n元组和数组区别在于,元组中可以存在不同类型的数据。\r\n\r\n```typescript\r\n// 数据类型必须与索引一一匹配\r\nlet a1 : [number,string,number] = [1,\'a\',2];\r\n\r\n// 先声明,再赋值\r\nlet person1: [string, number];\r\nperson1 = [\'大毛\', 25];\r\n\r\n// 获取一项\r\nlet username : string = person1[0];\r\nlet age : number = person1[1];\r\n\r\n// 操作数据\r\nconsole.log(username.indexOf(\"大\"))\r\nconsole.log(age.toFixed(2));\r\n```\r\n\r\n添加越界元素时【元组本身2个元素长度,新增其他数据长度会增加,称为添加越界元素】,它的类型会被限制为元组中每个类型的联合类型:\r\n\r\n```typescript\r\n// 先声明,再赋值\r\nlet person1: [string, number] = [\'大毛\', 25];\r\n\r\nperson1.push(\"123\");\r\nperson1.push(123);\r\n\r\n// Argument of type \'boolean\' is not assignable to parameter of type \'string | number\'.\r\nperson1.push(true);\r\n```\r\n\r\n如果元组中存在可选值时可以在类型后添加?表示,如下\r\n\r\n```typescript\r\n// number类型的值可写可不写,添加?即可\r\nlet person1: [string, number?] = [\'大毛\'];\r\n```\r\n\r\n## 枚举\r\n\r\n枚举(Enum)类型用于取值被限定在一定范围内的场景,比如订单状态为未付款、待发货、待收货、待评价,性别限定为男、女、未知等。\r\n枚举成员会被赋值为从 0 开始递增的数字,同时也会对枚举值到枚举名进行反向映射:\r\n\r\n```typescript\r\nenum OrderStatus {NO_PAY, SHIPPED, RECEIVED, EVALUATED,REVIEWED};\r\n\r\n// 使用\r\nconsole.log(OrderStatus[\'NO_PAY\'] === 0);\r\nconsole.log(OrderStatus[\'SHIPPED\'] === 1);\r\nconsole.log(OrderStatus[\'RECEIVED\'] === 2);\r\n\r\nconsole.log(OrderStatus[0] === \'NO_PAY\');\r\nconsole.log(OrderStatus[1] === \'SHIPPED\');\r\nconsole.log(OrderStatus[2] === \'RECEIVED\');\r\n```\r\n\r\n你还可以通过手动赋值修改默认以0递增的数据\r\n\r\n```typescript\r\nenum OrderStatus {NO_PAY = 1, SHIPPED = 2, RECEIVED = 3, EVALUATED,REVIEWED};\r\n\r\n// 使用\r\nconsole.log(OrderStatus[\'NO_PAY\']);\r\nconsole.log(OrderStatus[\'SHIPPED\']);\r\nconsole.log(OrderStatus[\'RECEIVED\']);\r\nconsole.log(OrderStatus[\'EVALUATED\']);\r\nconsole.log(OrderStatus[\'REVIEWED\']);\r\n```\r\n\r\n## 函数\r\n\r\nTypeScript中声明函数可以在形式参数和返回值中指定数据类型。\r\n\r\n```typescript\r\n// 接收number类型参数,返回number类型参数\r\nfunction fun1(num1 : number,num2 : number) : number {\r\n\r\n return num1 + num2;\r\n}\r\nconsole.log(fun1(1,2));\r\n```\r\n\r\n也支持通过函数表达式【Function Expression】的方式声明函数\r\n\r\n```typescript\r\nlet fun2 = function(str1 : string,str2 : string) : string {\r\n\r\n return str1.concat(str2);\r\n}\r\n\r\nconsole.log(fun2(\'A\',\'B\'));\r\n```\r\n\r\n函数同样支持**可选参数**,当然可选参数必须在最后\r\n\r\n```typescript\r\nfunction buildName(firstName: string, lastName?: string) {\r\n if (lastName) {\r\n return firstName + \' \' + lastName;\r\n } else {\r\n return firstName;\r\n }\r\n}\r\nlet tomcat = buildName(\'Tom\', \'Cat\');\r\nlet tom = buildName(\'Tom\');\r\n```\r\n\r\n如果没有返回值,则可以使用**void**修饰返回值类型,无返回值时接收到的为**undefined**\r\n\r\n```typescript\r\nfunction fun1(firstName: string):void {\r\n console.log(firstName.toUpperCase());\r\n}\r\nlet result = fun1(\'Tom\');\r\nconsole.log(result);\r\n```\r\n\r\nES6中允许方法参数有默认值,**TypeScript 会将添加了默认值的参数识别为可选参数**:\r\n\r\n```typescript\r\nfunction buildName(firstName: string, lastName: string = \'Cat\') {\r\n return firstName + \' \' + lastName;\r\n}\r\nlet tomcat = buildName(\'Tom\', \'Cat\');\r\nlet tom = buildName(\'Tom\');\r\n```\r\n\r\n此时就不受「可选参数必须接在必需参数后面」的限制了:\r\n\r\n```typescript\r\nfunction buildName(firstName: string = \'Tom\', lastName: string) {\r\n return firstName + \' \' + lastName;\r\n}\r\nlet tomcat = buildName(\'Tom\', \'Cat\');\r\nlet cat = buildName(undefined, \'Cat\');\r\n```\r\n\r\nES6中可以使用 **...rest** 的方式获取函数中的剩余参数(rest 参数):\r\n\r\n```typescript\r\nfunction push(array, ...items) {\r\n items.forEach(function(item) {\r\n array.push(item);\r\n });\r\n}\r\n\r\nlet a: any[] = [];\r\npush(a, 1, 2, 3);\r\n```\r\n\r\n事实上,items 是一个数组。所以我们可以用数组的类型来定义它:\r\n\r\n```typescript\r\nfunction push(array: any[], ...items: any[]) {\r\n items.forEach(function(item) {\r\n array.push(item);\r\n });\r\n}\r\n\r\nlet a = [];\r\npush(a, 1, 2, 3);\r\n```\r\n\r\n注意,rest 参数只能是最后一个参数\r\n\r\n## 接口\r\n\r\n接口用来定义一种规范,具体的时候交由对象来做,举个生活中的例子我们购买商品按照消费者权益来说所有的商品都必须有售后保障,那么具体怎么实现售后,你是上门维修也好,直接换货也好,就有厂家自己实现。这个必须有售后就是规范,各个厂家就是一个一个具体的对象,交由对象实现就行了。\r\n程序中就是我们希望在程序内描述一个人,那么人的规范就是有名字、性别、年龄和一些行为这可以通过接口描述,具体是哪一个人,就交由对象来具体化【实例化】。\r\n\r\n```typescript\r\n// 接口定义抽象结构\r\ninterface Person {\r\n username: string;\r\n age: number;\r\n say():void;\r\n}\r\n// 对象具体实现\r\nlet tom: Person = {\r\n username: \'张三\',\r\n age: 25,\r\n say() : void {\r\n console.log(this.username)\r\n }\r\n};\r\n```\r\n\r\n### 可选属性\r\n\r\n有时认为一个对象的某个属性可有可无,可以使用可选属性\r\n\r\n```typescript\r\ninterface Person {\r\n name: string;\r\n age?: number;\r\n}\r\n\r\nlet p1: Person = {\r\n name: \'大毛\'\r\n};\r\nlet p2: Person = {\r\n name: \'小毛\',\r\n age: 25\r\n};\r\n```\r\n\r\n### 任意属性\r\n\r\n又是我们希望可以在对象中添加任意的属性:\r\n\r\n```typescript\r\ninterface Person {\r\n name: string;\r\n age?: number;\r\n [propName: string]: any;\r\n}\r\n\r\nlet tom: Person = {\r\n name: \'大毛\',\r\n gender: \'男\',\r\n};\r\n```\r\n\r\n任意属性的类型需要包含可选属性,否则编译报错,比如any包含number类型,如果将any换成string,则age可选属性就会报错\r\n\r\n### 只读属性\r\n\r\n有时候我们希望对象中的一些字段在创建的时候被赋值后就不可更改,那么可以用 readonly 定义只读属性:\r\n\r\n```typescript\r\ninterface IBook {\r\n readonly author: string;\r\n bookname: string;\r\n}\r\n\r\nlet book1: IBook = {\r\n author: \'小明\',\r\n bookname: \'TypeScript养成记\',\r\n};\r\n\r\nbook1.author = \'大毛\';\r\n```\r\n\r\n## 类\r\n\r\nES6中JavaScript引入了类的概念,类也是用来定义事物的抽象,交由对象具体实现,在面向对象的语言中,对于类我们应该熟知这么几个概念:\r\n\r\n- 类(Class):定义了一件事物的抽象特点,包含它的属性和方法\r\n- 对象(Object):类的实例,通过 new 生成\r\n- 面向对象(OOP)的三大特性:封装、继承、多态\r\n- 封装(Encapsulation):将对数据的操作细节隐藏起来,只暴露对外的接口。外界调用端不需要(也不可能)知道细节,就能通过对外提供的接口来访问该对象,同时也保证了外界无法任意更改对象内部的数据\r\n- 继承(Inheritance):子类继承父类,子类除了拥有父类的所有特性外,还有一些更具体的特性\r\n- 多态(Polymorphism):由继承而产生了相关的不同的类,对同一个方法可以有不同的响应。比如 Cat 和 Dog 都继承自 Animal,但是分别实现了自己的 eat 方法。此时针对某一个实例,我们无需了解它是 Cat 还是 Dog,就可以直接调用 eat 方法,程序会自动判断出来应该如何执行 eat\r\n- 存取器(getter & setter):用以改变属性的读取和赋值行为\r\n- 修饰符(Modifiers):修饰符是一些关键字,用于限定成员或类型的性质。比如 public 表示公有属性或方法\r\n- 抽象类(Abstract Class):抽象类是供其他类继承的基类,抽象类不允许被实例化。抽象类中的抽象方法必须在子类中被实现\r\n- 接口(Interfaces):不同类之间公有的属性或方法,可以抽象成一个接口。接口可以被类实现(implements)。一个类只能继承自另一个类,但是可以实现多个接口\r\n\r\n### TypeScript中的类\r\n\r\nTypeScript 可以使用三种访问修饰符(Access Modifiers),分别是 public、private 和 protected。\r\n\r\n- public 修饰的属性或方法是公有的,可以在任何地方被访问到,默认所有的属性和方法都是 public 的\r\n- private 修饰的属性或方法是私有的,不能在声明它的类的外部访问\r\n- protected 修饰的属性或方法是受保护的,它和 private 类似,区别是它在子类中也是允许被访问的\r\n\r\n比如创建一个动物类,实例化一个狗\r\n\r\n```typescript\r\nclass Animal {\r\n public name;\r\n public constructor(name:string) {\r\n this.name = name;\r\n }\r\n}\r\n\r\nlet a = new Animal(\'大黄\');\r\nconsole.log(a.name); // 大黄\r\na.name = \'小黑\';\r\nconsole.log(a.name); // 小黑\r\n```\r\n\r\n上述可以直接修改和获取数据,对于对象数据来说是不安全的,可以通过private或者protected提高安全性。\r\n\r\n### private修饰属性\r\n\r\n使用private修饰将属性私有化,属性只能在类内部直接调用,如果要修改数据和获取数据可以通过公开的方法获取\r\n\r\n```typescript\r\nclass Animal {\r\n private name;\r\n public constructor(name:string) {\r\n this.name = name;\r\n }\r\n\r\n public getName():string {\r\n return this.name;\r\n }\r\n\r\n public setName(name:string):string {\r\n return this.name = name;\r\n }\r\n}\r\n\r\nlet a = new Animal(\'大黄\');\r\nconsole.log(a.getName()); // 大黄\r\na.setName(\'小黑\');\r\nconsole.log(a.getName()); // 小黑\r\n```\r\n\r\n### protected修饰属性\r\n\r\n被private修饰,包括子类在内都不被允许访问,只有本类内部可以访问,如果希望子类可以访问则可以使用protected修饰\r\n\r\n```typescript\r\nclass Animal {\r\n protected name;\r\n public constructor(name:string) {\r\n this.name = name;\r\n }\r\n\r\n public getName():string {\r\n return this.name;\r\n }\r\n\r\n public setName(name:string):string {\r\n return this.name = name;\r\n }\r\n}\r\n\r\nclass Dog extends Animal {\r\n constructor(name:string) {\r\n super(name);\r\n // name属性被继承过来\r\n console.log(this.name);\r\n }\r\n}\r\n```\r\n\r\n### private修饰构造方法\r\n\r\n如果构造方法通过private修饰被私有化,则该类不能被实例化,也不能被继承\r\n\r\n```typescript\r\nclass Animal {\r\n protected name;\r\n // 私有化构造方法\r\n private constructor(name:string) {\r\n this.name = name;\r\n }\r\n\r\n public getName():string {\r\n return this.name;\r\n }\r\n\r\n public setName(name:string):string {\r\n return this.name = name;\r\n }\r\n}\r\n\r\n// 继承就会报错\r\n// Cannot extend a class \'Animal\'. Class constructor is marked as private\r\nclass Dog extends Animal {\r\n constructor(name:string) {\r\n super(name);\r\n // name属性被继承过来\r\n console.log(this.name);\r\n }\r\n}\r\n```\r\n\r\n### protected 修饰构造方法\r\n\r\n如果构造函数修饰为 protected 时,该类不能实例化\r\n\r\n```typescript\r\nclass Animal {\r\n protected name;\r\n // protected修饰\r\n protected constructor(name:string) {\r\n this.name = name;\r\n }\r\n\r\n public getName():string {\r\n return this.name;\r\n }\r\n\r\n public setName(name:string):string {\r\n return this.name = name;\r\n }\r\n}\r\n// 继承没毛病\r\nclass Dog extends Animal {\r\n constructor(name:string) {\r\n super(name);\r\n // name属性被继承过来\r\n console.log(this.name);\r\n }\r\n}\r\n// 实例化有问题\r\n// Constructor of class \'Animal\' is protected and only accessible within the class declaration\r\nlet a = new Animal(\'大黄\');\r\n```\r\n\r\n### 参数属性\r\n\r\n类中属性可以定义在构造方法上,等同于类中定义了属性\r\n\r\n```typescript\r\nclass Animal {\r\n // 参数属性\r\n public constructor(public name:string) {\r\n }\r\n}\r\n\r\nlet a = new Animal(\"大黄\");\r\nconsole.log(a.name)\r\n```\r\n\r\n### readonly\r\n\r\n只读属性关键字也可用于类中,只允许出现在属性声明或索引签名或构造函数中。\r\n\r\n```typescript\r\nclass Animal {\r\n // 只读属性\r\n readonly name;\r\n public constructor(name:string) {\r\n this.name = name;\r\n }\r\n}\r\n\r\nlet a = new Animal(\'大黄\');\r\nconsole.log(a.name);\r\n// 不可再次修改\r\na.name = \'小黑\';\r\n```\r\n\r\n注意如果 readonly 和其他访问修饰符同时存在的话,需要写在其后面。\r\n\r\n```typescript\r\nclass Animal {\r\n // public readonly name;\r\n public constructor(public readonly name:string) {\r\n // this.name = name;\r\n }\r\n}\r\n```\r\n\r\n### 抽象类\r\n\r\n抽象类不能被实例化,使用abstract修饰\r\n\r\n```typescript\r\nabstract class Animal {\r\n public name;\r\n public constructor(name:string) {\r\n this.name = name;\r\n }\r\n public abstract sayHi():any;\r\n}\r\n// Cannot create an instance of an abstract class.\r\nlet a = new Animal(\'大黄\');\r\n```\r\n\r\n抽象类中的抽象方法必须被子类实现,子类必须实现抽象类中的所有抽象方法,否则需要继续抽象下去:\r\n\r\n```typescript\r\nabstract class Animal {\r\n public name;\r\n public constructor(name:string) {\r\n this.name = name;\r\n }\r\n public abstract eat():any;\r\n}\r\n\r\nclass Cat extends Animal {\r\n public eat() {\r\n console.log(`${this.name} 在吃鱼.`);\r\n }\r\n}\r\n\r\nlet c = new Cat(\'小花\');\r\nc.eat();\r\n```\r\n\r\n如果没有实现所有抽象方法则继续报错:\r\n\r\n```typescript\r\nabstract class Animal {\r\n public name;\r\n public constructor(name:string) {\r\n this.name = name;\r\n }\r\n public abstract eat():any;\r\n public abstract sayHi():any;\r\n}\r\n\r\n// Non-abstract class \'Cat\' does not implement all abstract members of \'Animal\'\r\nclass Cat extends Animal {\r\n public eat() {\r\n console.log(`${this.name} 在吃鱼.`);\r\n }\r\n}\r\n```\r\n\r\n## 泛型\r\n\r\n泛型(Generics)是指在定义函数、接口或类的时候,不预先指定具体的类型,而在使用的时候再指定类型的一种特性。\r\n\r\n### 无泛型\r\n\r\n实现一个函数 createArray,它可以创建一个指定长度的数组,同时将每一项都填充一个默认值:\r\n\r\n```typescript\r\nfunction createArray(length: number, value: any): Array<any> {\r\n let result = [];\r\n for (let i = 0; i < length; i++) {\r\n result[i] = value;\r\n }\r\n return result;\r\n}\r\n\r\ncreateArray(3, \'x\'); // [\'x\', \'x\', \'x\']\r\n```\r\n\r\n此处使用any当做入参和Array<any>反参类型,编译不会报错,但是可能会造成类型不安全的问题,调用方法的用户可能瞎传数据,你的方法就报错啦。此时泛型就登场了,**解决参数类型安全问题**\r\n\r\n```typescript\r\nfunction createArray<T>(length: number, value: T): Array<T> {\r\n let result: T[] = [];\r\n for (let i = 0; i < length; i++) {\r\n result[i] = value;\r\n }\r\n return result;\r\n}\r\n\r\ncreateArray<string>(3, \'x\'); // [\'x\', \'x\', \'x\']\r\n```\r\n\r\n上例中,我们在函数名后添加了 <T>,其中 T 用来指代任意输入的类型,在后面的输入 value: T 和输出 Array<T> 中即可使用了。\r\n接着在调用的时候,可以指定它具体的类型为 string。当然,也可以不手动指定,而让类型推论自动推算出来:\r\n\r\n```typescript\r\nfunction createArray<T>(length: number, value: T): Array<T> {\r\n let result: T[] = [];\r\n for (let i = 0; i < length; i++) {\r\n result[i] = value;\r\n }\r\n return result;\r\n}\r\n\r\ncreateArray(3, \'x\'); // [\'x\', \'x\', \'x\']\r\n```\r\n\r\n### 多个类型参数\r\n\r\n定义泛型的时候,可以一次定义多个类型参数:\r\n\r\n```typescript\r\nfunction swap<T, U>(tuple: [T, U]): [U, T] {\r\n return [tuple[1], tuple[0]];\r\n}\r\n\r\nswap([7, \'seven\']); // [\'seven\', 7]\r\n```\r\n\r\n### 泛型约束\r\n\r\n在函数内部使用泛型变量的时候,由于事先不知道它是哪种类型,所以不能随意的操作它的属性或方法:\r\n\r\n```typescript\r\nfunction loggingIdentity<T>(arg: T): T {\r\n console.log(arg.length);\r\n return arg;\r\n}\r\n```\r\n\r\n上例中,泛型 T 不一定包含属性 length,所以编译的时候报错了。\r\n这时,我们可以对泛型进行约束,只允许这个函数传入那些包含 length 属性的变量。这就是泛型约束:\r\n\r\n```typescript\r\ninterface Lengthwise {\r\n length: number;\r\n}\r\n\r\nfunction loggingIdentity<T extends Lengthwise>(arg: T): T {\r\n console.log(arg.length);\r\n return arg;\r\n}\r\n```\r\n\r\n上例中,我们使用了 extends 约束了泛型 T 必须符合接口 Lengthwise 的形状,也就是必须包含 length 属性。\r\n此时如果调用 loggingIdentity 的时候,传入的 arg 不包含 length,那么在编译阶段就会报错了:\r\n\r\n```typescript\r\ninterface Lengthwise {\r\n length: number;\r\n}\r\n\r\nfunction loggingIdentity<T extends Lengthwise>(arg: T): T {\r\n console.log(arg.length);\r\n return arg;\r\n}\r\n\r\nloggingIdentity(7);\r\n```\r\n\r\n多个类型参数之间也可以互相约束:\r\n\r\n```typescript\r\nfunction copyFields<T extends U, U>(target: T, source: U): T {\r\n for (let id in source) {\r\n target[id] = (<T>source)[id];\r\n }\r\n return target;\r\n}\r\n\r\nlet x = { a: 1, b: 2, c: 3, d: 4 };\r\n\r\ncopyFields(x, { b: 10, d: 20 });\r\n```\r\n\r\n上例中,我们使用了两个类型参数,其中要求 T 继承 U,这样就保证了 U 上不会出现 T 中不存在的字段。\r\n\r\n### 泛型接口\r\n\r\n泛型也可以用来定义接口\r\n\r\n```typescript\r\ninterface CreateArrayFunc {\r\n <T>(length: number, value: T): Array<T>;\r\n}\r\n\r\nlet createArray: CreateArrayFunc;\r\ncreateArray = function<T>(length: number, value: T): Array<T> {\r\n let result: T[] = [];\r\n for (let i = 0; i < length; i++) {\r\n result[i] = value;\r\n }\r\n return result;\r\n}\r\n\r\ncreateArray(3, \'x\'); // [\'x\', \'x\', \'x\']\r\n```\r\n\r\n进一步,我们可以把泛型参数提前到接口名上:\r\n\r\n```typescript\r\ninterface CreateArrayFunc<T> {\r\n (length: number, value: T): Array<T>;\r\n}\r\n\r\nlet createArray: CreateArrayFunc<any>;\r\ncreateArray = function<T>(length: number, value: T): Array<T> {\r\n let result: T[] = [];\r\n for (let i = 0; i < length; i++) {\r\n result[i] = value;\r\n }\r\n return result;\r\n}\r\n\r\ncreateArray(3, \'x\'); // [\'x\', \'x\', \'x\']\r\n```\r\n\r\n注意,此时在使用泛型接口的时候,需要定义泛型的类型。\r\n\r\n### 泛型类\r\n\r\n与泛型接口类似,泛型也可以用于类的类型定义中:\r\n\r\n```typescript\r\nclass GenericNumber<T> {\r\n zeroValue: T;\r\n add: (x: T, y: T) => T;\r\n}\r\n\r\nlet myGenericNumber = new GenericNumber<number>();\r\nmyGenericNumber.zeroValue = 0;\r\nmyGenericNumber.add = function(x, y) { return x + y; };\r\n```\r\n\r\n### 泛型参数的默认类型\r\n\r\n在 TypeScript 2.3 以后,我们可以为泛型中的类型参数指定默认类型。当使用泛型时没有在代码中直接指定类型参数,从实际值参数中也无法推测出时,这个默认类型就会起作用。\r\n\r\n```typescript\r\nfunction createArray<T = string>(length: number, value: T): Array<T> {\r\n let result: T[] = [];\r\n for (let i = 0; i < length; i++) {\r\n result[i] = value;\r\n }\r\n return result;\r\n}\r\n```\r\n\r\n# 类型断言\r\n\r\n类型断言(Type Assertion)可以用来手动指定一个值的类型。语法为\r\n\r\n```typescript\r\n值 as 类型\r\n\r\n或\r\n \r\n<类型>值\r\n```\r\n\r\n在 tsx 语法(React 的 jsx 语法的 ts 版)中必须使用 **值 as 类型**。\r\n\r\n## 联合类型断言为一个具体类型\r\n\r\n前文介绍了支持联合类型,即一个变量可以是string类型也可以是number类型,只能访问该变量所有类型的共有属性和方法\r\n\r\n```typescript\r\nfunction fun1(args: string | number):number {\r\n // 将值断言为number类型\r\n let result = args as number;\r\n\r\n return result;\r\n}\r\n\r\nconsole.log(fun1(\"1\"))\r\n```\r\n\r\n## 将一个父类断言为更加具体的子类\r\n\r\n当类之间有继承关系时,类型断言也是很常见的:\r\n\r\n```typescript\r\nclass Animal {\r\n name: string;\r\n constructor(name:string) {\r\n this.name = name;\r\n }\r\n}\r\n\r\nclass Dog extends Animal {\r\n constructor(name:string) {\r\n super(name);\r\n }\r\n doorkeeper():void {\r\n console.log(this.name + \"在看家\")\r\n }\r\n}\r\nclass Cat extends Animal {\r\n constructor(name:string) {\r\n super(name);\r\n }\r\n catchMouse():void {\r\n console.log(this.name + \"在抓老鼠\")\r\n }\r\n}\r\n\r\n// 离家需要狗看门,也需要猫抓老鼠\r\nfunction leaveHome(animal: Animal) {\r\n let dog = animal as Dog;\r\n dog.doorkeeper();\r\n}\r\n\r\nleaveHome(new Dog(\'旺财\'));\r\n```\r\n\r\n上面的例子中,我们声明了函数 leaveHome,转为Dog类型,调用看门方法,离家时构建一个狗对象,调用它的看门方法即可。\r\n\r\n## 断言限制\r\n\r\n类型不可随意断言,比如Dog是Animal的一种,Adimal可以断言为Dog,Cat不是Dog的一种,Cat就不能断言为Dog。如下例子:\r\n\r\n```typescript\r\nclass Animal {\r\n name: string;\r\n constructor(name:string) {\r\n this.name = name;\r\n }\r\n}\r\n\r\nclass Dog extends Animal {\r\n constructor(name:string) {\r\n super(name);\r\n }\r\n doorkeeper():void {\r\n console.log(this.name + \"在看家\")\r\n }\r\n}\r\nclass Cat extends Animal {\r\n constructor(name:string) {\r\n super(name);\r\n }\r\n catchMouse():void {\r\n console.log(this.name + \"在抓老鼠\")\r\n }\r\n}\r\n\r\n// 离家需要狗看门\r\n// 如果传入类型为Cat,断言成Dog编译不会报错,但运行时就会报错\r\nfunction leaveHome(animal: Animal) {\r\n let dog = animal as Dog;\r\n dog.doorkeeper();\r\n}\r\n// 实例化一个Cat\r\nleaveHome(new Cat(\'小花\'));\r\n```\r\n\r\n可以使用**instanceof**判断类型后对数据进行断言:\r\n\r\n```typescript\r\nclass Animal {\r\n name: string;\r\n constructor(name:string) {\r\n this.name = name;\r\n }\r\n}\r\n\r\nclass Dog extends Animal {\r\n constructor(name:string) {\r\n super(name);\r\n }\r\n doorkeeper():void {\r\n console.log(this.name + \"在看家\")\r\n }\r\n}\r\nclass Cat extends Animal {\r\n constructor(name:string) {\r\n super(name);\r\n }\r\n catchMouse():void {\r\n console.log(this.name + \"在抓老鼠\")\r\n }\r\n}\r\n\r\n// 判断类型之后\r\nfunction leaveHome(animal: Animal) {\r\n if(animal instanceof Dog) {\r\n let dog = animal as Dog;\r\n dog.doorkeeper();\r\n }else if(animal instanceof Cat) {\r\n let cat = animal as Cat;\r\n cat.catchMouse();\r\n }\r\n}\r\n\r\nleaveHome(new Cat(\'小花\'));\r\n```\r\n\r\n# 类型别名\r\n\r\n类型别名用来给一个类型起个新名字。\r\n\r\n```typescript\r\ntype Name = string;\r\ntype NameResolver = () => string;\r\ntype NameOrResolver = Name | NameResolver;\r\nfunction getName(n: NameOrResolver): Name {\r\n if (typeof n === \'string\') {\r\n return n;\r\n } else {\r\n return n();\r\n }\r\n}\r\n```\r\n\r\n上例中,我们使用 type 创建类型别名。类型别名常用于联合类型,将多个类型封装进一个类型中', 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, '2024-05-01 18:01:07', '2024-05-01 22:06:16', 0, 0, 'javascript,TypeScript');
-- ----------------------------
-- Table structure for ams_article_tag
-- ----------------------------
DROP TABLE IF EXISTS `ams_article_tag`;
CREATE TABLE `ams_article_tag` (
`id` int NOT NULL AUTO_INCREMENT,
`article_id` int NOT NULL COMMENT '文章id',
`tag_id` int NOT NULL COMMENT '标签id',
PRIMARY KEY (`id`) USING BTREE,
UNIQUE INDEX `fk_article_tag_1`(`article_id` ASC, `tag_id` ASC) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '文章标签关联表' ROW_FORMAT = DYNAMIC;
-- ----------------------------
-- Records of ams_article_tag
-- ----------------------------
-- ----------------------------
-- Table structure for ams_category
-- ----------------------------
DROP TABLE IF EXISTS `ams_category`;
CREATE TABLE `ams_category` (
`id` bigint NOT NULL AUTO_INCREMENT COMMENT '主键id',
`parent_id` bigint NULL DEFAULT 0,
`name` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '分类名称',
`click_volume` int NULL DEFAULT 0,
`sorts` int NOT NULL COMMENT '排序',
`create_time` datetime NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`update_time` datetime NULL DEFAULT CURRENT_TIMESTAMP COMMENT '最后更新时间',
`icon` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '图标',
`status` int NULL DEFAULT 0 COMMENT '状态',
`deleted` int NULL DEFAULT 0 COMMENT '逻辑删除',
`creator` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT '创建者',
`updater` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT '更新者',
`remark` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT '备注',
PRIMARY KEY (`id`) USING BTREE,
INDEX `category_name`(`name` ASC) USING BTREE COMMENT '博客分类名称'
) ENGINE = InnoDB AUTO_INCREMENT = 14 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '文章分类表' ROW_FORMAT = DYNAMIC;
-- ----------------------------
-- Records of ams_category
-- ----------------------------
INSERT INTO `ams_category` VALUES (1, 0, 'Java', 0, 0, '2024-04-30 14:58:06', NULL, 'color', 0, 0, '', '', '');
INSERT INTO `ams_category` VALUES (2, 1, 'Java基础', 0, 0, '2024-04-30 15:02:06', NULL, '404', 0, 0, '', '', '');
INSERT INTO `ams_category` VALUES (3, 1, 'Maven', 0, 1, '2024-04-30 15:05:22', NULL, '404', 0, 0, '', '', '');
INSERT INTO `ams_category` VALUES (4, 1, 'SpringBoot', 0, 2, '2024-04-30 15:05:37', NULL, '404', 0, 0, '', '', '');
INSERT INTO `ams_category` VALUES (5, 1, 'MyBatis', 0, 0, '2024-04-30 15:05:58', NULL, '404', 0, 0, '', '', '');
INSERT INTO `ams_category` VALUES (6, 1, 'SpringCloud', 0, 0, '2024-04-30 15:06:10', NULL, '404', 0, 0, '', '', '');
INSERT INTO `ams_category` VALUES (7, 0, '前端', 0, 1, '2024-04-30 15:06:53', NULL, '404', 0, 0, '', '', '');
INSERT INTO `ams_category` VALUES (8, 7, 'JavaScript', 0, 0, '2024-04-30 15:11:26', NULL, '404', 0, 0, '', '', '');
INSERT INTO `ams_category` VALUES (9, 7, 'Vue', 0, 1, '2024-04-30 15:11:47', NULL, '404', 0, 0, '', '', '');
INSERT INTO `ams_category` VALUES (11, 7, '微信小程序', 0, 2, '2024-04-30 15:18:50', NULL, '404', 0, 0, '', '', '');
INSERT INTO `ams_category` VALUES (12, 7, 'uni-app', 0, 3, '2024-04-30 15:19:04', NULL, '404', 0, 0, '', '', '');
INSERT INTO `ams_category` VALUES (13, 0, '数据库', 0, 2, '2024-04-30 15:21:44', NULL, '404', 0, 0, '', '', '数据库技术栈');
-- ----------------------------
-- Table structure for ams_collect
-- ----------------------------
DROP TABLE IF EXISTS `ams_collect`;
CREATE TABLE `ams_collect` (
`id` bigint NOT NULL AUTO_INCREMENT COMMENT '主键',
`user_id` bigint NOT NULL COMMENT '用户id',
`article_id` bigint NOT NULL COMMENT '文章id',
`create_time` datetime NULL DEFAULT NULL COMMENT '收藏时间',
PRIMARY KEY (`id`) USING BTREE,
INDEX `idx_b_collect_user_id`(`user_id` ASC) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 5 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '文章收藏表' ROW_FORMAT = DYNAMIC;
-- ----------------------------
-- Records of ams_collect
-- ----------------------------
INSERT INTO `ams_collect` VALUES (3, 3, 1, '2024-05-08 15:36:55');
INSERT INTO `ams_collect` VALUES (4, 3, 5, '2024-05-08 20:27:09');
-- ----------------------------
-- Table structure for ams_comment
-- ----------------------------
DROP TABLE IF EXISTS `ams_comment`;
CREATE TABLE `ams_comment` (
`id` bigint NOT NULL AUTO_INCREMENT COMMENT 'ID',
`user_id` bigint NOT NULL COMMENT '评论人ID',
`article_id` bigint NOT NULL COMMENT '文章id',
`content` varchar(2000) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '内容',
`reply_user_id` bigint NULL DEFAULT NULL COMMENT '回复人id',
`parent_id` bigint NULL DEFAULT 0 COMMENT '父id',
`create_time` datetime NULL DEFAULT NULL COMMENT '评论时间',
`browser` varchar(30) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '',
`browser_version` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,
`systemOS` varchar(30) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '',
`system_version` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '',
`ip_address` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT 'ip地址',
PRIMARY KEY (`id`) USING BTREE,
INDEX `user_id`(`user_id` ASC) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 8 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '文章评论表' ROW_FORMAT = DYNAMIC;
-- ----------------------------
-- Records of ams_comment
-- ----------------------------
INSERT INTO `ams_comment` VALUES (1, 3, 1, 'adasdasd', NULL, 0, '2024-05-07 21:53:04', 'chrome', 'chrome 119.0.6045.160', NULL, NULL, NULL);
INSERT INTO `ams_comment` VALUES (2, 3, 1, '我的评论', NULL, 0, '2024-05-08 10:24:21', 'chrome', 'chrome 119.0.6045.160', '', '', '');
INSERT INTO `ams_comment` VALUES (3, 3, 1, '我的评论2', NULL, 0, '2024-05-08 10:27:19', 'chrome', 'chrome 119.0.6045.160', '', '', '');
INSERT INTO `ams_comment` VALUES (4, 3, 1, '不错的评论', 3, 3, '2024-05-08 10:35:48', 'chrome', 'chrome 119.0.6045.160', '', '', '');
INSERT INTO `ams_comment` VALUES (5, 3, 1, '这不错', 3, 3, '2024-05-08 10:36:00', 'chrome', 'chrome 119.0.6045.160', '', '', '');
INSERT INTO `ams_comment` VALUES (6, 3, 5, '沙发', NULL, 0, '2024-05-08 20:27:18', 'chrome', 'chrome 119.0.6045.160', '', '', '');
INSERT INTO `ams_comment` VALUES (7, 3, 5, '占位', NULL, 0, '2024-05-08 20:27:28', 'chrome', 'chrome 119.0.6045.160', '', '', '');
-- ----------------------------
-- Table structure for ams_like
-- ----------------------------
DROP TABLE IF EXISTS `ams_like`;
CREATE TABLE `ams_like` (
`id` bigint NOT NULL AUTO_INCREMENT COMMENT '主键',
`user_id` bigint NOT NULL COMMENT '用户id',
`article_id` bigint NOT NULL COMMENT '文章id',
`create_time` datetime NULL DEFAULT NULL COMMENT '点赞时间',
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 9 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '文章点赞表' ROW_FORMAT = DYNAMIC;
-- ----------------------------
-- Records of ams_like
-- ----------------------------
INSERT INTO `ams_like` VALUES (7, 3, 1, '2024-05-08 16:31:12');
INSERT INTO `ams_like` VALUES (8, 3, 5, '2024-05-08 20:27:07');
-- ----------------------------
-- Table structure for ams_tags
-- ----------------------------
DROP TABLE IF EXISTS `ams_tags`;
CREATE TABLE `ams_tags` (
`id` bigint NOT NULL AUTO_INCREMENT COMMENT '主键id',
`parent_id` bigint NULL DEFAULT 0 COMMENT '父标签',
`name` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '标签名称',
`click_volume` int NULL DEFAULT 0 COMMENT '点击量',
`sorts` int NOT NULL DEFAULT 0 COMMENT '排序',
`create_time` datetime NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`update_time` datetime NULL DEFAULT CURRENT_TIMESTAMP COMMENT '最后更新时间',
`creator` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT '创建者',
`updater` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT '更新者',
`deleted` int NULL DEFAULT 0 COMMENT '逻辑删除',
`remark` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT '备注',
`status` int NULL DEFAULT 0 COMMENT '状态',
PRIMARY KEY (`id`) USING BTREE,
INDEX `tag_name`(`name` ASC) USING BTREE COMMENT '博客标签名称'
) ENGINE = InnoDB AUTO_INCREMENT = 14 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '文章标签表' ROW_FORMAT = DYNAMIC;
-- ----------------------------
-- Records of ams_tags
-- ----------------------------
INSERT INTO `ams_tags` VALUES (1, 0, 'Java', 0, 0, '2024-04-30 16:10:24', NULL, '', '', 0, '', 0);
INSERT INTO `ams_tags` VALUES (2, 0, '前端', 0, 1, '2024-04-30 16:10:51', NULL, '', '', 0, '', 0);
INSERT INTO `ams_tags` VALUES (3, 0, '数据库', 0, 2, '2024-04-30 16:12:13', NULL, '', '', 0, '', 0);
INSERT INTO `ams_tags` VALUES (5, 1, 'Java基础', 0, 0, '2024-04-30 16:22:09', NULL, '', '', 0, '', 0);
INSERT INTO `ams_tags` VALUES (6, 1, 'spring', 0, 0, '2024-04-30 16:22:23', NULL, '', '', 0, '', 0);
INSERT INTO `ams_tags` VALUES (7, 1, 'springboot', 0, 0, '2024-04-30 16:22:28', NULL, '', '', 0, '', 0);
INSERT INTO `ams_tags` VALUES (8, 2, 'html', 0, 0, '2024-04-30 16:22:35', NULL, '', '', 0, '', 0);
INSERT INTO `ams_tags` VALUES (9, 2, 'css', 0, 0, '2024-04-30 16:22:42', NULL, '', '', 0, '', 0);
INSERT INTO `ams_tags` VALUES (10, 2, 'html5', 0, 0, '2024-04-30 16:22:48', NULL, '', '', 0, '', 0);
INSERT INTO `ams_tags` VALUES (11, 2, 'css3', 0, 0, '2024-04-30 16:22:54', NULL, '', '', 0, '', 0);
INSERT INTO `ams_tags` VALUES (12, 2, 'javascript', 0, 0, '2024-04-30 16:23:00', NULL, '', '', 0, '', 0);
INSERT INTO `ams_tags` VALUES (13, 2, 'TypeScript', 0, 0, '2024-04-30 16:23:11', NULL, '', '', 0, '', 0);
-- ----------------------------
-- Table structure for cms_banner
-- ----------------------------
DROP TABLE IF EXISTS `cms_banner`;
CREATE TABLE `cms_banner` (
`id` int NOT NULL AUTO_INCREMENT COMMENT '参数主键',
`show_page` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT '' COMMENT '显示页面',
`title` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT '' COMMENT '轮播图名称',
`url` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT '' COMMENT '轮播图链接地址',
`img_path` varchar(500) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT '' COMMENT '图片地址',
`creator` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT '' COMMENT '创建者',
`create_time` datetime NULL DEFAULT NULL COMMENT '创建时间',
`updater` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT '' COMMENT '更新者',
`update_time` datetime NULL DEFAULT NULL COMMENT '更新时间',
`remark` varchar(500) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '备注',
`status` int NULL DEFAULT 0 COMMENT '状态',
`deleted` int NULL DEFAULT 0 COMMENT '逻辑删除',
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 3 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci COMMENT = '轮播图管理' ROW_FORMAT = DYNAMIC;
-- ----------------------------
-- Records of cms_banner
-- ----------------------------
INSERT INTO `cms_banner` VALUES (1, 'home', 'banner1', '', 'http://localhost:8128/img/article/20240430111100A005.png', '', NULL, '', NULL, NULL, 0, 0);
INSERT INTO `cms_banner` VALUES (2, 'home', 'banner2', '', 'http://localhost:8128/img/article/20240430142050A007.jpg', '', NULL, '', NULL, NULL, 0, 0);
-- ----------------------------
-- Table structure for gen_table
-- ----------------------------
DROP TABLE IF EXISTS `gen_table`;
CREATE TABLE `gen_table` (
`table_id` bigint NOT NULL AUTO_INCREMENT COMMENT '编号',
`table_name` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT '' COMMENT '表名称',
`table_comment` varchar(500) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT '' COMMENT '表描述',
`sub_table_name` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '关联子表的表名',
`sub_table_fk_name` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '子表关联的外键名',
`class_name` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT '' COMMENT '实体类名称',
`tpl_category` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT 'crud' COMMENT '使用的模板(crud单表操作 tree树表操作)',
`tpl_web_type` varchar(30) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT '' COMMENT '前端模板类型(element-ui模版 element-plus模版)',
`package_name` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '生成包路径',
`module_name` varchar(30) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '生成模块名',
`business_name` varchar(30) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '生成业务名',
`function_name` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '生成功能名',
`function_author` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '生成功能作者',
`gen_type` char(1) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT '0' COMMENT '生成代码方式(0zip压缩包 1自定义路径)',
`gen_path` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT '/' COMMENT '生成路径(不填默认项目路径)',
`options` varchar(1000) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '其它生成选项',
`creator` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT '' COMMENT '创建者',
`create_time` datetime NULL DEFAULT NULL COMMENT '创建时间',
`updater` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT '' COMMENT '更新者',
`update_time` datetime NULL DEFAULT NULL COMMENT '更新时间',
`remark` varchar(500) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '备注',
PRIMARY KEY (`table_id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 117 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci COMMENT = '代码生成业务表' ROW_FORMAT = DYNAMIC;
-- ----------------------------
-- Records of gen_table
-- ----------------------------
INSERT INTO `gen_table` VALUES (104, 'ums_search_history', '搜索历史', NULL, NULL, 'UmsSearchHistory', 'crud', 'element-plus', 'com.xianying.system', 'system', 'history', '搜索历史', 'xianying', '0', '/', NULL, '', '2024-04-24 11:53:36', '', NULL, NULL);
INSERT INTO `gen_table` VALUES (105, 'ams_article', '博客文章表', NULL, NULL, 'AmsArticle', 'crud', 'element-plus', 'com.xianying.system', 'system', 'article', '博客文章', 'xianying', '0', '/', NULL, '', '2024-04-29 12:01:33', '', NULL, NULL);
INSERT INTO `gen_table` VALUES (106, 'ams_article_tag', '文章标签关联表', NULL, NULL, 'AmsArticleTag', 'crud', 'element-plus', 'com.xianying.system', 'system', 'tag', '文章标签关联', 'xianying', '0', '/', NULL, '', '2024-04-29 12:01:34', '', NULL, NULL);
INSERT INTO `gen_table` VALUES (107, 'ams_category', '文章分类表', NULL, NULL, 'AmsCategory', 'crud', 'element-plus', 'com.xianying.system', 'system', 'category', '文章分类', 'xianying', '0', '/', NULL, '', '2024-04-29 12:01:34', '', NULL, NULL);
INSERT INTO `gen_table` VALUES (108, 'ams_collect', '文章收藏表', NULL, NULL, 'AmsCollect', 'crud', 'element-plus', 'com.xianying.system', 'system', 'collect', '文章收藏', 'xianying', '0', '/', NULL, '', '2024-04-29 12:01:35', '', NULL, NULL);
INSERT INTO `gen_table` VALUES (109, 'ams_comment', '文章评论表', NULL, NULL, 'AmsComment', 'crud', 'element-plus', 'com.xianying.system', 'system', 'comment', '文章评论', 'xianying', '0', '/', NULL, '', '2024-04-29 12:01:35', '', NULL, NULL);
INSERT INTO `gen_table` VALUES (110, 'ams_tags', '文章标签表', NULL, NULL, 'AmsTags', 'crud', 'element-plus', 'com.xianying.system', 'system', 'tags', '文章标签', 'xianying', '0', '/', NULL, '', '2024-04-29 12:01:36', '', NULL, NULL);
INSERT INTO `gen_table` VALUES (111, 'cms_banner', '轮播图管理', NULL, NULL, 'CmsBanner', 'crud', 'element-plus', 'com.xianying.system', 'system', 'banner', '轮播图管理', 'xianying', '0', '/', NULL, '', '2024-05-06 16:17:29', '', NULL, NULL);
INSERT INTO `gen_table` VALUES (112, 'operate_support', '打赏支持表', NULL, NULL, 'OperateSupport', 'crud', 'element-plus', 'com.xianying.system', 'system', 'support', '打赏支持', 'xianying', '0', '/', NULL, '', '2024-05-07 16:22:00', '', NULL, NULL);
INSERT INTO `gen_table` VALUES (113, 'ams_like', '文章点赞表', NULL, NULL, 'AmsLike', 'crud', 'element-plus', 'com.xianying.system', 'system', 'like', '文章点赞', 'xianying', '0', '/', NULL, '', '2024-05-08 14:26:33', '', NULL, NULL);
INSERT INTO `gen_table` VALUES (114, 'video', '视频信息表', NULL, NULL, 'Video', 'crud', 'element-plus', 'com.xianying.system', 'system', 'video', '视频信息', 'xianying', '0', '/', NULL, '', '2024-05-08 15:51:46', '', NULL, NULL);
INSERT INTO `gen_table` VALUES (115, 'link_search', '搜索引擎表', NULL, NULL, 'LinkSearch', 'crud', 'element-plus', 'com.xianying.system', 'system', 'search', '搜索引擎', 'xianying', '0', '/', NULL, '', '2024-05-10 08:58:39', '', NULL, NULL);
INSERT INTO `gen_table` VALUES (116, 'link_web', '外链网站表', NULL, NULL, 'LinkWeb', 'crud', 'element-plus', 'com.xianying.system', 'system', 'web', '外链网站', 'xianying', '0', '/', NULL, '', '2024-05-10 08:58:40', '', NULL, NULL);
-- ----------------------------
-- Table structure for gen_table_column
-- ----------------------------
DROP TABLE IF EXISTS `gen_table_column`;
CREATE TABLE `gen_table_column` (
`column_id` bigint NOT NULL AUTO_INCREMENT COMMENT '编号',
`table_id` bigint NULL DEFAULT NULL COMMENT '归属表编号',
`column_name` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '列名称',
`column_comment` varchar(500) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '列描述',
`column_type` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '列类型',
`java_type` varchar(500) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT 'JAVA类型',
`java_field` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT 'JAVA字段名',
`is_pk` char(1) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '是否主键(1是)',
`is_increment` char(1) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '是否自增(1是)',
`is_required` char(1) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '是否必填(1是)',
`is_insert` char(1) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '是否为插入字段(1是)',
`is_edit` char(1) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '是否编辑字段(1是)',
`is_list` char(1) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '是否列表字段(1是)',
`is_query` char(1) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '是否查询字段(1是)',
`query_type` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT 'EQ' COMMENT '查询方式(等于、不等于、大于、小于、范围)',
`html_type` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '显示类型(文本框、文本域、下拉框、复选框、单选框、日期控件)',
`dict_type` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT '' COMMENT '字典类型',
`sort` int NULL DEFAULT NULL COMMENT '排序',
`creator` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT '' COMMENT '创建者',
`create_time` datetime NULL DEFAULT NULL COMMENT '创建时间',
`updater` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT '' COMMENT '更新者',
`update_time` datetime NULL DEFAULT NULL COMMENT '更新时间',
`remark` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '备注',
PRIMARY KEY (`column_id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 1434 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci COMMENT = '代码生成业务表字段' ROW_FORMAT = DYNAMIC;
-- ----------------------------
-- Records of gen_table_column
-- ----------------------------
INSERT INTO `gen_table_column` VALUES (1308, 104, 'id', NULL, 'bigint', 'Long', 'id', '1', '1', '0', '1', NULL, NULL, NULL, 'EQ', 'input', '', 1, '', '2024-04-24 11:53:36', '', NULL, NULL);
INSERT INTO `gen_table_column` VALUES (1309, 104, 'member_id', '用户id', 'bigint', 'Long', 'memberId', '0', '0', '1', '1', '1', '1', '1', 'EQ', 'input', '', 2, '', '2024-04-24 11:53:36', '', NULL, NULL);
INSERT INTO `gen_table_column` VALUES (1310, 104, 'keyword', '搜索内容', 'varchar(64)', 'String', 'keyword', '0', '0', '0', '1', '1', '1', '1', 'EQ', 'input', '', 3, '', '2024-04-24 11:53:36', '', NULL, NULL);
INSERT INTO `gen_table_column` VALUES (1311, 104, 'create_time', '创建时间', 'datetime', 'LocalDateTime', 'createTime', '0', '0', '0', '1', NULL, NULL, NULL, 'EQ', 'datetime', '', 4, '', '2024-04-24 11:53:36', '', NULL, NULL);
INSERT INTO `gen_table_column` VALUES (1312, 105, 'id', '主键id', 'bigint', 'Long', 'id', '1', '1', '0', '1', NULL, NULL, NULL, 'EQ', 'input', '', 1, '', '2024-04-29 12:01:33', '', NULL, NULL);
INSERT INTO `gen_table_column` VALUES (1313, 105, 'user_id', '用户id', 'varchar(150)', 'String', 'userId', '0', '0', '0', '1', '1', '1', '1', 'EQ', 'input', '', 2, '', '2024-04-29 12:01:33', '', NULL, NULL);
INSERT INTO `gen_table_column` VALUES (1314, 105, 'category_id', '分类id', 'bigint', 'Long', 'categoryId', '0', '0', '0', '1', '1', '1', '1', 'EQ', 'input', '', 3, '', '2024-04-29 12:01:33', '', NULL, NULL);
INSERT INTO `gen_table_column` VALUES (1315, 105, 'title', '文章标题', 'varchar(150)', 'String', 'title', '0', '0', '1', '1', '1', '1', '1', 'EQ', 'input', '', 4, '', '2024-04-29 12:01:34', '', NULL, NULL);
INSERT INTO `gen_table_column` VALUES (1316, 105, 'avatar', '文章封面地址', 'varchar(200)', 'String', 'avatar', '0', '0', '0', '1', '1', '1', '1', 'EQ', 'input', '', 5, '', '2024-04-29 12:01:34', '', NULL, NULL);
INSERT INTO `gen_table_column` VALUES (1317, 105, 'summary', '文章简介', 'varchar(255)', 'String', 'summary', '0', '0', '1', '1', '1', '1', '1', 'EQ', 'input', '', 6, '', '2024-04-29 12:01:34', '', NULL, NULL);
INSERT INTO `gen_table_column` VALUES (1318, 105, 'content', '文章内容 (最多两百字)', 'mediumtext', 'String', 'content', '0', '0', '0', '1', '1', '1', '1', 'EQ', 'editor', '', 7, '', '2024-04-29 12:01:34', '', NULL, NULL);
INSERT INTO `gen_table_column` VALUES (1319, 105, 'content_md', '文章内容md版', 'mediumtext', 'String', 'contentMd', '0', '0', '0', '1', '1', '1', '1', 'EQ', 'textarea', '', 8, '', '2024-04-29 12:01:34', '', NULL, NULL);
INSERT INTO `gen_table_column` VALUES (1320, 105, 'read_type', '阅读方式 0无需验证 1:评论阅读 2:点赞阅读 3:扫码阅读', 'int', 'Long', 'readType', '0', '0', '0', '1', '1', '1', '1', 'EQ', 'select', '', 9, '', '2024-04-29 12:01:34', '', NULL, NULL);
INSERT INTO `gen_table_column` VALUES (1321, 105, 'is_stick', '是否置顶 0否 1是', 'int', 'Long', 'isStick', '0', '0', '0', '1', '1', '1', '1', 'EQ', 'input', '', 10, '', '2024-04-29 12:01:34', '', NULL, NULL);
INSERT INTO `gen_table_column` VALUES (1322, 105, 'is_publish', '是否发布 0:下架 1:发布', 'int', 'Long', 'isPublish', '0', '0', '0', '1', '1', '1', '1', 'EQ', 'input', '', 11, '', '2024-04-29 12:01:34', '', NULL, NULL);
INSERT INTO `gen_table_column` VALUES (1323, 105, 'is_original', '是否原创 0:转载 1:原创', 'int', 'Long', 'isOriginal', '0', '0', '0', '1', '1', '1', '1', 'EQ', 'input', '', 12, '', '2024-04-29 12:01:34', '', NULL, NULL);
INSERT INTO `gen_table_column` VALUES (1324, 105, 'original_url', '转载地址', 'varchar(255)', 'String', 'originalUrl', '0', '0', '0', '1', '1', '1', '1', 'EQ', 'input', '', 13, '', '2024-04-29 12:01:34', '', NULL, NULL);
INSERT INTO `gen_table_column` VALUES (1325, 105, 'address', '发布地址', 'varchar(50)', 'String', 'address', '0', '0', '0', '1', '1', '1', '1', 'EQ', 'input', '', 14, '', '2024-04-29 12:01:34', '', NULL, NULL);
INSERT INTO `gen_table_column` VALUES (1326, 105, 'quantity', '文章阅读量', 'bigint', 'Long', 'quantity', '0', '0', '0', '1', '1', '1', '1', 'EQ', 'input', '', 15, '', '2024-04-29 12:01:34', '', NULL, NULL);
INSERT INTO `gen_table_column` VALUES (1327, 105, 'create_time', '创建时间', 'datetime', 'LocalDateTime', 'createTime', '0', '0', '0', '1', NULL, NULL, NULL, 'EQ', 'datetime', '', 16, '', '2024-04-29 12:01:34', '', NULL, NULL);
INSERT INTO `gen_table_column` VALUES (1328, 105, 'update_time', '修改时间', 'datetime', 'LocalDateTime', 'updateTime', '0', '0', '0', '1', '1', NULL, NULL, 'EQ', 'datetime', '', 17, '', '2024-04-29 12:01:34', '', NULL, NULL);
INSERT INTO `gen_table_column` VALUES (1329, 105, 'is_carousel', '是否首页轮播', 'int', 'Long', 'isCarousel', '0', '0', '0', '1', '1', '1', '1', 'EQ', 'input', '', 18, '', '2024-04-29 12:01:34', '', NULL, NULL);
INSERT INTO `gen_table_column` VALUES (1330, 105, 'is_recommend', '是否推荐', 'int', 'Long', 'isRecommend', '0', '0', '0', '1', '1', '1', '1', 'EQ', 'input', '', 19, '', '2024-04-29 12:01:34', '', NULL, NULL);
INSERT INTO `gen_table_column` VALUES (1331, 105, 'keywords', '关键词', 'varchar(200)', 'String', 'keywords', '0', '0', '0', '1', '1', '1', '1', 'EQ', 'input', '', 20, '', '2024-04-29 12:01:34', '', NULL, NULL);
INSERT INTO `gen_table_column` VALUES (1332, 106, 'id', NULL, 'int', 'Long', 'id', '1', '1', '0', '1', NULL, NULL, NULL, 'EQ', 'input', '', 1, '', '2024-04-29 12:01:34', '', NULL, NULL);
INSERT INTO `gen_table_column` VALUES (1333, 106, 'article_id', '文章id', 'int', 'Long', 'articleId', '0', '0', '1', '1', '1', '1', '1', 'EQ', 'input', '', 2, '', '2024-04-29 12:01:34', '', NULL, NULL);
INSERT INTO `gen_table_column` VALUES (1334, 106, 'tag_id', '标签id', 'int', 'Long', 'tagId', '0', '0', '1', '1', '1', '1', '1', 'EQ', 'input', '', 3, '', '2024-04-29 12:01:34', '', NULL, NULL);
INSERT INTO `gen_table_column` VALUES (1335, 107, 'id', '主键id', 'bigint', 'Long', 'id', '1', '1', '0', '1', NULL, NULL, NULL, 'EQ', 'input', '', 1, '', '2024-04-29 12:01:35', '', NULL, NULL);
INSERT INTO `gen_table_column` VALUES (1336, 107, 'name', '分类名称', 'varchar(32)', 'String', 'name', '0', '0', '1', '1', '1', '1', '1', 'LIKE', 'input', '', 2, '', '2024-04-29 12:01:35', '', NULL, NULL);
INSERT INTO `gen_table_column` VALUES (1337, 107, 'click_volume', NULL, 'int', 'Long', 'clickVolume', '0', '0', '0', '1', '1', '1', '1', 'EQ', 'input', '', 3, '', '2024-04-29 12:01:35', '', NULL, NULL);
INSERT INTO `gen_table_column` VALUES (1338, 107, 'sort', '排序', 'int', 'Long', 'sort', '0', '0', '1', '1', '1', '1', '1', 'EQ', 'input', '', 4, '', '2024-04-29 12:01:35', '', NULL, NULL);
INSERT INTO `gen_table_column` VALUES (1339, 107, 'create_time', '创建时间', 'datetime', 'LocalDateTime', 'createTime', '0', '0', '0', '1', NULL, NULL, NULL, 'EQ', 'datetime', '', 5, '', '2024-04-29 12:01:35', '', NULL, NULL);
INSERT INTO `gen_table_column` VALUES (1340, 107, 'update_time', '最后更新时间', 'datetime', 'LocalDateTime', 'updateTime', '0', '0', '0', '1', '1', NULL, NULL, 'EQ', 'datetime', '', 6, '', '2024-04-29 12:01:35', '', NULL, NULL);
INSERT INTO `gen_table_column` VALUES (1341, 107, 'icon', '图标', 'varchar(100)', 'String', 'icon', '0', '0', '0', '1', '1', '1', '1', 'EQ', 'input', '', 7, '', '2024-04-29 12:01:35', '', NULL, NULL);
INSERT INTO `gen_table_column` VALUES (1342, 108, 'id', '主键', 'int', 'Long', 'id', '1', '1', '0', '1', NULL, NULL, NULL, 'EQ', 'input', '', 1, '', '2024-04-29 12:01:35', '', NULL, NULL);
INSERT INTO `gen_table_column` VALUES (1343, 108, 'user_id', '用户id', 'varchar(100)', 'String', 'userId', '0', '0', '1', '1', '1', '1', '1', 'EQ', 'input', '', 2, '', '2024-04-29 12:01:35', '', NULL, NULL);
INSERT INTO `gen_table_column` VALUES (1344, 108, 'article_id', '文章id', 'bigint', 'Long', 'articleId', '0', '0', '1', '1', '1', '1', '1', 'EQ', 'input', '', 3, '', '2024-04-29 12:01:35', '', NULL, NULL);
INSERT INTO `gen_table_column` VALUES (1345, 108, 'create_time', '收藏时间', 'datetime', 'LocalDateTime', 'createTime', '0', '0', '0', '1', NULL, NULL, NULL, 'EQ', 'datetime', '', 4, '', '2024-04-29 12:01:35', '', NULL, NULL);
INSERT INTO `gen_table_column` VALUES (1346, 109, 'id', 'ID', 'bigint', 'Long', 'id', '1', '1', '0', '1', NULL, NULL, NULL, 'EQ', 'input', '', 1, '', '2024-04-29 12:01:35', '', NULL, NULL);
INSERT INTO `gen_table_column` VALUES (1347, 109, 'user_id', '评论人ID', 'varchar(150)', 'String', 'userId', '0', '0', '1', '1', '1', '1', '1', 'EQ', 'input', '', 2, '', '2024-04-29 12:01:35', '', NULL, NULL);
INSERT INTO `gen_table_column` VALUES (1348, 109, 'article_id', '文章id', 'bigint', 'Long', 'articleId', '0', '0', '1', '1', '1', '1', '1', 'EQ', 'input', '', 3, '', '2024-04-29 12:01:35', '', NULL, NULL);
INSERT INTO `gen_table_column` VALUES (1349, 109, 'content', '内容', 'varchar(400)', 'String', 'content', '0', '0', '1', '1', '1', '1', '1', 'EQ', 'editor', '', 4, '', '2024-04-29 12:01:35', '', NULL, NULL);
INSERT INTO `gen_table_column` VALUES (1350, 109, 'reply_user_id', '回复人id', 'varchar(150)', 'String', 'replyUserId', '0', '0', '0', '1', '1', '1', '1', 'EQ', 'input', '', 5, '', '2024-04-29 12:01:35', '', NULL, NULL);
INSERT INTO `gen_table_column` VALUES (1351, 109, 'parent_id', '父id', 'int', 'Long', 'parentId', '0', '0', '0', '1', '1', '1', '1', 'EQ', 'input', '', 6, '', '2024-04-29 12:01:35', '', NULL, NULL);
INSERT INTO `gen_table_column` VALUES (1352, 109, 'create_time', '评论时间', 'datetime', 'LocalDateTime', 'createTime', '0', '0', '0', '1', NULL, NULL, NULL, 'EQ', 'datetime', '', 7, '', '2024-04-29 12:01:35', '', NULL, NULL);
INSERT INTO `gen_table_column` VALUES (1353, 109, 'browser', NULL, 'varchar(30)', 'String', 'browser', '0', '0', '0', '1', '1', '1', '1', 'EQ', 'input', '', 8, '', '2024-04-29 12:01:35', '', NULL, NULL);
INSERT INTO `gen_table_column` VALUES (1354, 109, 'browser_version', NULL, 'varchar(100)', 'String', 'browserVersion', '0', '0', '0', '1', '1', '1', '1', 'EQ', 'input', '', 9, '', '2024-04-29 12:01:35', '', NULL, NULL);
INSERT INTO `gen_table_column` VALUES (1355, 109, 'system', NULL, 'varchar(30)', 'String', 'system', '0', '0', '0', '1', '1', '1', '1', 'EQ', 'input', '', 10, '', '2024-04-29 12:01:35', '', NULL, NULL);
INSERT INTO `gen_table_column` VALUES (1356, 109, 'system_version', NULL, 'varchar(100)', 'String', 'systemVersion', '0', '0', '0', '1', '1', '1', '1', 'EQ', 'input', '', 11, '', '2024-04-29 12:01:36', '', NULL, NULL);
INSERT INTO `gen_table_column` VALUES (1357, 109, 'ip_address', 'ip地址', 'varchar(100)', 'String', 'ipAddress', '0', '0', '0', '1', '1', '1', '1', 'EQ', 'input', '', 12, '', '2024-04-29 12:01:36', '', NULL, NULL);
INSERT INTO `gen_table_column` VALUES (1358, 110, 'id', '主键id', 'bigint', 'Long', 'id', '1', '1', '0', '1', NULL, NULL, NULL, 'EQ', 'input', '', 1, '', '2024-04-29 12:01:36', '', NULL, NULL);
INSERT INTO `gen_table_column` VALUES (1359, 110, 'name', '标签名称', 'varchar(32)', 'String', 'name', '0', '0', '1', '1', '1', '1', '1', 'LIKE', 'input', '', 2, '', '2024-04-29 12:01:36', '', NULL, NULL);
INSERT INTO `gen_table_column` VALUES (1360, 110, 'click_volume', NULL, 'int', 'Long', 'clickVolume', '0', '0', '0', '1', '1', '1', '1', 'EQ', 'input', '', 3, '', '2024-04-29 12:01:36', '', NULL, NULL);
INSERT INTO `gen_table_column` VALUES (1361, 110, 'sorts', '排序', 'int', 'Long', 'sorts', '0', '0', '1', '1', '1', '1', '1', 'EQ', 'input', '', 4, '', '2024-04-29 12:01:36', '', NULL, NULL);
INSERT INTO `gen_table_column` VALUES (1362, 110, 'create_time', '创建时间', 'datetime', 'LocalDateTime', 'createTime', '0', '0', '0', '1', NULL, NULL, NULL, 'EQ', 'datetime', '', 5, '', '2024-04-29 12:01:36', '', NULL, NULL);
INSERT INTO `gen_table_column` VALUES (1363, 110, 'update_time', '最后更新时间', 'datetime', 'LocalDateTime', 'updateTime', '0', '0', '0', '1', '1', NULL, NULL, 'EQ', 'datetime', '', 6, '', '2024-04-29 12:01:36', '', NULL, NULL);
INSERT INTO `gen_table_column` VALUES (1364, 111, 'id', '参数主键', 'int', 'Long', 'id', '1', '1', '0', '1', NULL, NULL, NULL, 'EQ', 'input', '', 1, '', '2024-05-06 16:17:29', '', NULL, NULL);
INSERT INTO `gen_table_column` VALUES (1365, 111, 'title', '轮播图名称', 'varchar(100)', 'String', 'title', '0', '0', '0', '1', '1', '1', '1', 'EQ', 'input', '', 2, '', '2024-05-06 16:17:29', '', NULL, NULL);
INSERT INTO `gen_table_column` VALUES (1366, 111, 'url', '轮播图链接地址', 'varchar(100)', 'String', 'url', '0', '0', '0', '1', '1', '1', '1', 'EQ', 'input', '', 3, '', '2024-05-06 16:17:29', '', NULL, NULL);
INSERT INTO `gen_table_column` VALUES (1367, 111, 'img_path', '图片地址', 'varchar(500)', 'String', 'imgPath', '0', '0', '0', '1', '1', '1', '1', 'EQ', 'textarea', '', 4, '', '2024-05-06 16:17:30', '', NULL, NULL);
INSERT INTO `gen_table_column` VALUES (1368, 111, 'creator', '创建者', 'varchar(64)', 'String', 'creator', '0', '0', '0', '1', NULL, NULL, NULL, 'EQ', 'input', '', 5, '', '2024-05-06 16:17:30', '', NULL, NULL);
INSERT INTO `gen_table_column` VALUES (1369, 111, 'create_time', '创建时间', 'datetime', 'LocalDateTime', 'createTime', '0', '0', '0', '1', NULL, NULL, NULL, 'EQ', 'datetime', '', 6, '', '2024-05-06 16:17:30', '', NULL, NULL);
INSERT INTO `gen_table_column` VALUES (1370, 111, 'updater', '更新者', 'varchar(64)', 'String', 'updater', '0', '0', '0', '1', '1', NULL, NULL, 'EQ', 'input', '', 7, '', '2024-05-06 16:17:30', '', NULL, NULL);
INSERT INTO `gen_table_column` VALUES (1371, 111, 'update_time', '更新时间', 'datetime', 'LocalDateTime', 'updateTime', '0', '0', '0', '1', '1', NULL, NULL, 'EQ', 'datetime', '', 8, '', '2024-05-06 16:17:30', '', NULL, NULL);
INSERT INTO `gen_table_column` VALUES (1372, 111, 'remark', '备注', 'varchar(500)', 'String', 'remark', '0', '0', '0', '1', '1', '1', NULL, 'EQ', 'textarea', '', 9, '', '2024-05-06 16:17:30', '', NULL, NULL);
INSERT INTO `gen_table_column` VALUES (1373, 111, 'status', '状态', 'int', 'Long', 'status', '0', '0', '0', '1', '1', '1', '1', 'EQ', 'radio', '', 10, '', '2024-05-06 16:17:30', '', NULL, NULL);
INSERT INTO `gen_table_column` VALUES (1374, 111, 'deleted', '逻辑删除', 'int', 'Long', 'deleted', '0', '0', '0', '1', NULL, NULL, NULL, 'EQ', 'input', '', 11, '', '2024-05-06 16:17:30', '', NULL, NULL);
INSERT INTO `gen_table_column` VALUES (1375, 112, 'id', '主键id', 'bigint', 'Long', 'id', '1', '1', '0', '1', NULL, NULL, NULL, 'EQ', 'input', '', 1, '', '2024-05-07 16:22:00', '', NULL, NULL);
INSERT INTO `gen_table_column` VALUES (1376, 112, 'title', '支持标题', 'varchar(150)', 'String', 'title', '0', '0', '1', '1', '1', '1', '1', 'EQ', 'input', '', 2, '', '2024-05-07 16:22:00', '', NULL, NULL);
INSERT INTO `gen_table_column` VALUES (1377, 112, 'er_code', '二维码地址', 'varchar(150)', 'String', 'erCode', '0', '0', '1', '1', '1', '1', '1', 'EQ', 'input', '', 3, '', '2024-05-07 16:22:00', '', NULL, NULL);
INSERT INTO `gen_table_column` VALUES (1378, 112, 'sorts', '排序', 'int', 'Long', 'sorts', '0', '0', '1', '1', '1', '1', '1', 'EQ', 'input', '', 4, '', '2024-05-07 16:22:00', '', NULL, NULL);
INSERT INTO `gen_table_column` VALUES (1379, 112, 'create_time', '创建时间', 'datetime', 'LocalDateTime', 'createTime', '0', '0', '0', '1', NULL, NULL, NULL, 'EQ', 'datetime', '', 5, '', '2024-05-07 16:22:00', '', NULL, NULL);
INSERT INTO `gen_table_column` VALUES (1380, 112, 'update_time', '最后更新时间', 'datetime', 'LocalDateTime', 'updateTime', '0', '0', '0', '1', '1', NULL, NULL, 'EQ', 'datetime', '', 6, '', '2024-05-07 16:22:00', '', NULL, NULL);
INSERT INTO `gen_table_column` VALUES (1381, 112, 'creator', '创建者', 'varchar(255)', 'String', 'creator', '0', '0', '0', '1', NULL, NULL, NULL, 'EQ', 'input', '', 7, '', '2024-05-07 16:22:00', '', NULL, NULL);
INSERT INTO `gen_table_column` VALUES (1382, 112, 'updater', '更新者', 'varchar(255)', 'String', 'updater', '0', '0', '0', '1', '1', NULL, NULL, 'EQ', 'input', '', 8, '', '2024-05-07 16:22:00', '', NULL, NULL);
INSERT INTO `gen_table_column` VALUES (1383, 112, 'deleted', '逻辑删除', 'int', 'Long', 'deleted', '0', '0', '0', '1', NULL, NULL, NULL, 'EQ', 'input', '', 9, '', '2024-05-07 16:22:00', '', NULL, NULL);
INSERT INTO `gen_table_column` VALUES (1384, 112, 'remark', '备注', 'varchar(255)', 'String', 'remark', '0', '0', '0', '1', '1', '1', NULL, 'EQ', 'input', '', 10, '', '2024-05-07 16:22:00', '', NULL, NULL);
INSERT INTO `gen_table_column` VALUES (1385, 112, 'status', '状态', 'int', 'Long', 'status', '0', '0', '0', '1', '1', '1', '1', 'EQ', 'radio', '', 11, '', '2024-05-07 16:22:00', '', NULL, NULL);
INSERT INTO `gen_table_column` VALUES (1386, 113, 'id', '主键', 'bigint', 'Long', 'id', '1', '1', '0', '1', NULL, NULL, NULL, 'EQ', 'input', '', 1, '', '2024-05-08 14:26:33', '', NULL, NULL);
INSERT INTO `gen_table_column` VALUES (1387, 113, 'user_id', '用户id', 'bigint', 'Long', 'userId', '0', '0', '1', '1', '1', '1', '1', 'EQ', 'input', '', 2, '', '2024-05-08 14:26:33', '', NULL, NULL);
INSERT INTO `gen_table_column` VALUES (1388, 113, 'article_id', '文章id', 'bigint', 'Long', 'articleId', '0', '0', '1', '1', '1', '1', '1', 'EQ', 'input', '', 3, '', '2024-05-08 14:26:33', '', NULL, NULL);
INSERT INTO `gen_table_column` VALUES (1389, 113, 'create_time', '点赞时间', 'datetime', 'LocalDateTime', 'createTime', '0', '0', '0', '1', NULL, NULL, NULL, 'EQ', 'datetime', '', 4, '', '2024-05-08 14:26:33', '', NULL, NULL);
INSERT INTO `gen_table_column` VALUES (1390, 114, 'id', '主键id', 'bigint', 'Long', 'id', '1', '1', '0', '1', NULL, NULL, NULL, 'EQ', 'input', '', 1, '', '2024-05-08 15:51:46', '', NULL, NULL);
INSERT INTO `gen_table_column` VALUES (1391, 114, 'user_id', '用户id', 'bigint', 'Long', 'userId', '0', '0', '0', '1', '1', '1', '1', 'EQ', 'input', '', 2, '', '2024-05-08 15:51:46', '', NULL, NULL);
INSERT INTO `gen_table_column` VALUES (1392, 114, 'category_id', '分类id', 'bigint', 'Long', 'categoryId', '0', '0', '0', '1', '1', '1', '1', 'EQ', 'input', '', 3, '', '2024-05-08 15:51:46', '', NULL, NULL);
INSERT INTO `gen_table_column` VALUES (1393, 114, 'title', '视频标题', 'varchar(150)', 'String', 'title', '0', '0', '1', '1', '1', '1', '1', 'EQ', 'input', '', 4, '', '2024-05-08 15:51:46', '', NULL, NULL);
INSERT INTO `gen_table_column` VALUES (1394, 114, 'main_img', '视频封面地址', 'varchar(200)', 'String', 'mainImg', '0', '0', '0', '1', '1', '1', '1', 'EQ', 'input', '', 5, '', '2024-05-08 15:51:46', '', NULL, NULL);
INSERT INTO `gen_table_column` VALUES (1395, 114, 'summary', '视频简介', 'varchar(255)', 'String', 'summary', '0', '0', '1', '1', '1', '1', '1', 'EQ', 'input', '', 6, '', '2024-05-08 15:51:46', '', NULL, NULL);
INSERT INTO `gen_table_column` VALUES (1396, 114, 'video_url', '视频地址', 'varchar(2000)', 'String', 'videoUrl', '0', '0', '0', '1', '1', '1', '1', 'EQ', 'textarea', '', 7, '', '2024-05-08 15:51:46', '', NULL, NULL);
INSERT INTO `gen_table_column` VALUES (1397, 114, 'read_volume', '播放量', 'bigint', 'Long', 'readVolume', '0', '0', '0', '1', '1', '1', '1', 'EQ', 'input', '', 8, '', '2024-05-08 15:51:46', '', NULL, NULL);
INSERT INTO `gen_table_column` VALUES (1398, 114, 'collect_volume', '收藏数', 'bigint', 'Long', 'collectVolume', '0', '0', '0', '1', '1', '1', '1', 'EQ', 'input', '', 9, '', '2024-05-08 15:51:46', '', NULL, NULL);
INSERT INTO `gen_table_column` VALUES (1399, 114, 'like_volume', '点赞数', 'bigint', 'Long', 'likeVolume', '0', '0', '0', '1', '1', '1', '1', 'EQ', 'input', '', 10, '', '2024-05-08 15:51:46', '', NULL, NULL);
INSERT INTO `gen_table_column` VALUES (1400, 114, 'comment_volume', '评论数', 'bigint', 'Long', 'commentVolume', '0', '0', '0', '1', '1', '1', '1', 'EQ', 'input', '', 11, '', '2024-05-08 15:51:46', '', NULL, NULL);
INSERT INTO `gen_table_column` VALUES (1401, 114, 'top_status', '是否置顶 0否 1是', 'int', 'Long', 'topStatus', '0', '0', '0', '1', '1', '1', '1', 'EQ', 'radio', '', 12, '', '2024-05-08 15:51:46', '', NULL, NULL);
INSERT INTO `gen_table_column` VALUES (1402, 114, 'push_status', '是否发布 0:下架 1:发布', 'int', 'Long', 'pushStatus', '0', '0', '0', '1', '1', '1', '1', 'EQ', 'radio', '', 13, '', '2024-05-08 15:51:46', '', NULL, NULL);
INSERT INTO `gen_table_column` VALUES (1403, 114, 'show_scope', '可见范围', 'int', 'Long', 'showScope', '0', '0', '0', '1', '1', '1', '1', 'EQ', 'input', '', 14, '', '2024-05-08 15:51:47', '', NULL, NULL);
INSERT INTO `gen_table_column` VALUES (1404, 114, 'push_type', '是否原创 0:原创 1:转载,2:翻译', 'int', 'Long', 'pushType', '0', '0', '0', '1', '1', '1', '1', 'EQ', 'select', '', 15, '', '2024-05-08 15:51:47', '', NULL, NULL);
INSERT INTO `gen_table_column` VALUES (1405, 114, 'original_url', '转载地址', 'varchar(255)', 'String', 'originalUrl', '0', '0', '0', '1', '1', '1', '1', 'EQ', 'input', '', 16, '', '2024-05-08 15:51:47', '', NULL, NULL);
INSERT INTO `gen_table_column` VALUES (1406, 114, 'create_time', '创建时间', 'datetime', 'LocalDateTime', 'createTime', '0', '0', '0', '1', NULL, NULL, NULL, 'EQ', 'datetime', '', 17, '', '2024-05-08 15:51:47', '', NULL, NULL);
INSERT INTO `gen_table_column` VALUES (1407, 114, 'update_time', '修改时间', 'datetime', 'LocalDateTime', 'updateTime', '0', '0', '0', '1', '1', NULL, NULL, 'EQ', 'datetime', '', 18, '', '2024-05-08 15:51:47', '', NULL, NULL);
INSERT INTO `gen_table_column` VALUES (1408, 114, 'recom_status', '是否推荐', 'int', 'Long', 'recomStatus', '0', '0', '0', '1', '1', '1', '1', 'EQ', 'radio', '', 19, '', '2024-05-08 15:51:47', '', NULL, NULL);
INSERT INTO `gen_table_column` VALUES (1409, 114, 'tag', '视频标签', 'varchar(200)', 'String', 'tag', '0', '0', '0', '1', '1', '1', '1', 'EQ', 'input', '', 20, '', '2024-05-08 15:51:47', '', NULL, NULL);
INSERT INTO `gen_table_column` VALUES (1410, 115, 'id', '主键', 'bigint', 'Long', 'id', '1', '1', '0', '1', NULL, NULL, NULL, 'EQ', 'input', '', 1, '', '2024-05-10 08:58:39', '', NULL, NULL);
INSERT INTO `gen_table_column` VALUES (1411, 115, 'title', '链接标题', 'varchar(150)', 'String', 'title', '0', '0', '1', '1', '1', '1', '1', 'EQ', 'input', '', 2, '', '2024-05-10 08:58:39', '', NULL, NULL);
INSERT INTO `gen_table_column` VALUES (1412, 115, 'base_url', '搜索地址', 'varchar(200)', 'String', 'baseUrl', '0', '0', '0', '1', '1', '1', '1', 'EQ', 'input', '', 3, '', '2024-05-10 08:58:39', '', NULL, NULL);
INSERT INTO `gen_table_column` VALUES (1413, 115, 'img', '图标', 'varchar(200)', 'String', 'img', '0', '0', '0', '1', '1', '1', '1', 'EQ', 'input', '', 4, '', '2024-05-10 08:58:39', '', NULL, NULL);
INSERT INTO `gen_table_column` VALUES (1414, 115, 'status', '状态(0正常 1停用)', 'int', 'Long', 'status', '0', '0', '0', '1', '1', '1', '1', 'EQ', 'radio', '', 5, '', '2024-05-10 08:58:39', '', NULL, NULL);
INSERT INTO `gen_table_column` VALUES (1415, 115, 'deleted', '删除标志(0代表存在 2代表删除)', 'int', 'Long', 'deleted', '0', '0', '0', '1', NULL, NULL, NULL, 'EQ', 'input', '', 6, '', '2024-05-10 08:58:40', '', NULL, NULL);
INSERT INTO `gen_table_column` VALUES (1416, 115, 'creator', '创建者', 'varchar(64)', 'String', 'creator', '0', '0', '0', '1', NULL, NULL, NULL, 'EQ', 'input', '', 7, '', '2024-05-10 08:58:40', '', NULL, NULL);
INSERT INTO `gen_table_column` VALUES (1417, 115, 'create_time', '创建时间', 'datetime', 'LocalDateTime', 'createTime', '0', '0', '0', '1', NULL, NULL, NULL, 'EQ', 'datetime', '', 8, '', '2024-05-10 08:58:40', '', NULL, NULL);
INSERT INTO `gen_table_column` VALUES (1418, 115, 'updater', '更新者', 'varchar(64)', 'String', 'updater', '0', '0', '0', '1', '1', NULL, NULL, 'EQ', 'input', '', 9, '', '2024-05-10 08:58:40', '', NULL, NULL);
INSERT INTO `gen_table_column` VALUES (1419, 115, 'update_time', '更新时间', 'datetime', 'LocalDateTime', 'updateTime', '0', '0', '0', '1', '1', NULL, NULL, 'EQ', 'datetime', '', 10, '', '2024-05-10 08:58:40', '', NULL, NULL);
INSERT INTO `gen_table_column` VALUES (1420, 115, 'remark', '备注', 'varchar(255)', 'String', 'remark', '0', '0', '0', '1', '1', '1', NULL, 'EQ', 'input', '', 11, '', '2024-05-10 08:58:40', '', NULL, NULL);
INSERT INTO `gen_table_column` VALUES (1421, 116, 'id', '主键', 'bigint', 'Long', 'id', '1', '1', '0', '1', NULL, NULL, NULL, 'EQ', 'input', '', 1, '', '2024-05-10 08:58:40', '', NULL, NULL);
INSERT INTO `gen_table_column` VALUES (1422, 116, 'title', '链接标题', 'varchar(150)', 'String', 'title', '0', '0', '1', '1', '1', '1', '1', 'EQ', 'input', '', 2, '', '2024-05-10 08:58:40', '', NULL, NULL);
INSERT INTO `gen_table_column` VALUES (1423, 116, 'href', '跳转地址', 'varchar(200)', 'String', 'href', '0', '0', '0', '1', '1', '1', '1', 'EQ', 'input', '', 3, '', '2024-05-10 08:58:40', '', NULL, NULL);
INSERT INTO `gen_table_column` VALUES (1424, 116, 'img', '图标', 'varchar(200)', 'String', 'img', '0', '0', '0', '1', '1', '1', '1', 'EQ', 'input', '', 4, '', '2024-05-10 08:58:40', '', NULL, NULL);
INSERT INTO `gen_table_column` VALUES (1425, 116, 'summary', '简介', 'varchar(255)', 'String', 'summary', '0', '0', '1', '1', '1', '1', '1', 'EQ', 'input', '', 5, '', '2024-05-10 08:58:40', '', NULL, NULL);
INSERT INTO `gen_table_column` VALUES (1426, 116, 'type', '类型', 'int', 'Long', 'type', '0', '0', '0', '1', '1', '1', '1', 'EQ', 'select', '', 6, '', '2024-05-10 08:58:40', '', NULL, NULL);
INSERT INTO `gen_table_column` VALUES (1427, 116, 'status', '部门状态(0正常 1停用)', 'int', 'Long', 'status', '0', '0', '0', '1', '1', '1', '1', 'EQ', 'radio', '', 7, '', '2024-05-10 08:58:40', '', NULL, NULL);
INSERT INTO `gen_table_column` VALUES (1428, 116, 'deleted', '删除标志(0代表存在 2代表删除)', 'int', 'Long', 'deleted', '0', '0', '0', '1', NULL, NULL, NULL, 'EQ', 'input', '', 8, '', '2024-05-10 08:58:40', '', NULL, NULL);
INSERT INTO `gen_table_column` VALUES (1429, 116, 'creator', '创建者', 'varchar(64)', 'String', 'creator', '0', '0', '0', '1', NULL, NULL, NULL, 'EQ', 'input', '', 9, '', '2024-05-10 08:58:40', '', NULL, NULL);
INSERT INTO `gen_table_column` VALUES (1430, 116, 'create_time', '创建时间', 'datetime', 'LocalDateTime', 'createTime', '0', '0', '0', '1', NULL, NULL, NULL, 'EQ', 'datetime', '', 10, '', '2024-05-10 08:58:40', '', NULL, NULL);
INSERT INTO `gen_table_column` VALUES (1431, 116, 'updater', '更新者', 'varchar(64)', 'String', 'updater', '0', '0', '0', '1', '1', NULL, NULL, 'EQ', 'input', '', 11, '', '2024-05-10 08:58:40', '', NULL, NULL);
INSERT INTO `gen_table_column` VALUES (1432, 116, 'update_time', '更新时间', 'datetime', 'LocalDateTime', 'updateTime', '0', '0', '0', '1', '1', NULL, NULL, 'EQ', 'datetime', '', 12, '', '2024-05-10 08:58:40', '', NULL, NULL);
INSERT INTO `gen_table_column` VALUES (1433, 116, 'remark', '备注', 'varchar(255)', 'String', 'remark', '0', '0', '0', '1', '1', '1', NULL, 'EQ', 'input', '', 13, '', '2024-05-10 08:58:40', '', NULL, NULL);
-- ----------------------------
-- Table structure for link_search
-- ----------------------------
DROP TABLE IF EXISTS `link_search`;
CREATE TABLE `link_search` (
`id` bigint NOT NULL AUTO_INCREMENT COMMENT '主键',
`title` varchar(150) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '链接标题',
`base_url` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT '搜索地址',
`img` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT '图标',
`status` int NULL DEFAULT 0 COMMENT '状态(0正常 1停用)',
`deleted` int NULL DEFAULT 0 COMMENT '删除标志(0代表存在 2代表删除)',
`creator` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT '' COMMENT '创建者',
`create_time` datetime NULL DEFAULT NULL COMMENT '创建时间',
`updater` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT '' COMMENT '更新者',
`update_time` datetime NULL DEFAULT NULL COMMENT '更新时间',
`remark` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT '' COMMENT '备注',
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 6 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '搜索引擎表' ROW_FORMAT = DYNAMIC;
-- ----------------------------
-- Records of link_search
-- ----------------------------
INSERT INTO `link_search` VALUES (1, '百度', 'https://www.baidu.com/s?ie=UTF-8&wd=', 'http://localhost:8128/img/link/search/20240510092407A001.png', 0, 0, '', NULL, '', NULL, '');
INSERT INTO `link_search` VALUES (2, '必应', 'https://cn.bing.com/search?q=', 'http://localhost:8128/img/link/search/20240510092846A001.png', 0, 0, '', NULL, '', NULL, '');
INSERT INTO `link_search` VALUES (3, 'Google', 'https://www.google.com/search?q=', 'http://localhost:8128/img/link/search/20240510092904A002.png', 0, 0, '', NULL, '', NULL, '');
INSERT INTO `link_search` VALUES (4, 'CSDN', 'https://so.csdn.net/so/search/all?q=', 'http://localhost:8128/img/link/search/20240510092919A003.png', 0, 0, '', NULL, '', NULL, '');
INSERT INTO `link_search` VALUES (5, '头条', 'https://so.toutiao.com/search?dvpf=pc&source=input&keyword=', 'http://localhost:8128/img/link/search/20240510092934A004.png', 0, 0, '', NULL, '', NULL, '');
-- ----------------------------
-- Table structure for link_web
-- ----------------------------
DROP TABLE IF EXISTS `link_web`;
CREATE TABLE `link_web` (
`id` bigint NOT NULL AUTO_INCREMENT COMMENT '主键',
`title` varchar(150) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '链接标题',
`href` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT '跳转地址',
`img` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT '图标',
`summary` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '简介',
`type` int NULL DEFAULT 0 COMMENT '类型',
`status` int NULL DEFAULT 0 COMMENT '部门状态(0正常 1停用)',
`deleted` int NULL DEFAULT 0 COMMENT '删除标志(0代表存在 2代表删除)',
`creator` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT '' COMMENT '创建者',
`create_time` datetime NULL DEFAULT NULL COMMENT '创建时间',
`updater` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT '' COMMENT '更新者',
`update_time` datetime NULL DEFAULT NULL COMMENT '更新时间',
`remark` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT '' COMMENT '备注',
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 32 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '外链网站表' ROW_FORMAT = DYNAMIC;
-- ----------------------------
-- Records of link_web
-- ----------------------------
INSERT INTO `link_web` VALUES (1, '秘搭写作猫', 'https://www.xiezuocat.com/', 'http://localhost:8128/img/link/web/20240510101806A004.png', '基于ChatGPT快速写作工作', 0, 0, 1, '', NULL, '', NULL, '');
INSERT INTO `link_web` VALUES (2, '秘搭写作猫', 'https://www.xiezuocat.com/', 'http://localhost:8128/img/link/web/20240510101806A004.png', '基于ChatGPT快速写作工作', 0, 0, 0, '', NULL, '', NULL, '');
INSERT INTO `link_web` VALUES (3, 'SQL生成器', 'https://www.agilebuilder.net/tools/app/sqlgen', 'http://localhost:8128/img/link/web/20240510102743A005.png', '', 0, 0, 0, '', NULL, '', NULL, '');
INSERT INTO `link_web` VALUES (4, '草料二维码', 'https://cli.im/', 'http://localhost:8128/img/link/web/20240510103550A006.png', '简单实用的二维码系统搭建平台', 0, 0, 0, '', NULL, '', NULL, '');
INSERT INTO `link_web` VALUES (5, '草料二维码', 'https://cli.im/', 'http://localhost:8128/img/link/web/20240510103550A006.png', '简单实用的二维码系统搭建平台', 0, 0, 1, '', NULL, '', NULL, '');
INSERT INTO `link_web` VALUES (6, '数据结构可视化', 'https://www.cs.usfca.edu/~galles/visualization/Algorithms.html', 'http://localhost:8128/img/link/web/20240510103816A007.png', '数据结构可视化网站', 0, 0, 0, '', NULL, '', NULL, '');
INSERT INTO `link_web` VALUES (7, 'Canva可画', 'https://www.canva.cn/', 'http://localhost:8128/img/link/web/20240510104249A008.png', '使用Canva可画,轻松创建并分享专业设计', 0, 0, 1, '', NULL, '', NULL, '');
INSERT INTO `link_web` VALUES (8, 'Canva可画', 'https://www.canva.cn/', 'http://localhost:8128/img/link/web/20240510104249A008.png', '使用Canva可画,轻松创建并分享专业设计', 0, 0, 1, '', NULL, '', NULL, '');
INSERT INTO `link_web` VALUES (9, 'Canva可画', 'https://www.canva.cn/', 'http://localhost:8128/img/link/web/20240510104249A008.png', '使用Canva可画,轻松创建并分享专业设计', 0, 0, 0, '', NULL, '', NULL, '');
INSERT INTO `link_web` VALUES (10, 'Vue3.js', 'https://cn.vuejs.org/guide/introduction.html', 'http://localhost:8128/img/link/web/20240510104437A009.png', '易学易用,性能出色,适用场景丰富的 Web 前端框架', 1, 0, 0, '', NULL, '', NULL, '');
INSERT INTO `link_web` VALUES (11, 'React', 'https://react.dev/', 'http://localhost:8128/img/link/web/20240510104609A010.png', '从组建构建用户页面', 1, 0, 0, '', NULL, '', NULL, '');
INSERT INTO `link_web` VALUES (12, 'Spring6文档', 'https://docs.spring.io/spring-framework/reference/index.html', 'http://localhost:8128/img/link/web/20240510110119A011.png', 'Spring6官方手册', 1, 0, 0, '', NULL, '', NULL, '');
INSERT INTO `link_web` VALUES (13, 'SpringBoot3', 'https://docs.spring.io/spring-boot/docs/current/reference/html/', 'http://localhost:8128/img/link/web/20240510110137A012.png', 'SpringBoot3官方手册', 1, 0, 0, '', NULL, '', NULL, 'SpringBoot3官方手册');
INSERT INTO `link_web` VALUES (14, 'SpringCloud', 'https://www.springcloud.cc/', 'http://localhost:8128/img/link/web/20240510110233A013.png', 'SpringCloud中文网', 1, 0, 0, '', NULL, '', NULL, '');
INSERT INTO `link_web` VALUES (15, 'redis中文网', 'https://redis.com.cn/', 'http://localhost:8128/img/link/web/20240510110742A014.png', '简单清晰免费的Redis中文手册', 1, 0, 0, '', NULL, '', NULL, '');
INSERT INTO `link_web` VALUES (16, 'Stack Overflow', 'https://stackoverflow.com/', 'http://localhost:8128/img/link/web/20240510111000A015.png', '全球技术问答社区', 2, 0, 0, '', NULL, '', NULL, '');
INSERT INTO `link_web` VALUES (17, 'CSDN', 'https://www.csdn.net/', 'http://localhost:8128/img/link/web/20240510111038A016.png', '成就1亿技术人中国技术社区', 2, 0, 0, '', NULL, '', NULL, '');
INSERT INTO `link_web` VALUES (18, '开源中国', 'https://www.oschina.net/', 'http://localhost:8128/img/link/web/20240510111402A017.png', '中国领先的技术社区', 2, 0, 0, '', NULL, '', NULL, '');
INSERT INTO `link_web` VALUES (19, '掘金', 'https://juejin.cn/', 'http://localhost:8128/img/link/web/20240510111447A018.png', '一个帮助开发者成长的社区', 2, 0, 0, '', NULL, '', NULL, '');
INSERT INTO `link_web` VALUES (20, '思否', 'https://segmentfault.com/', 'http://localhost:8128/img/link/web/20240510111532A019.png', '消除开发领域的知识不平等', 2, 0, 0, '', NULL, '', NULL, '');
INSERT INTO `link_web` VALUES (21, '菜鸟教程', 'https://www.runoob.com/', 'http://localhost:8128/img/link/web/20240510111820A020.png', '学的不仅仅是技术,而是梦想', 2, 0, 0, '', NULL, '', NULL, '');
INSERT INTO `link_web` VALUES (22, 'GitHub', 'https://github.com/', 'http://localhost:8128/img/link/web/20240510112309A021.png', '全球性代码资料库', 2, 0, 0, '', NULL, '', NULL, '');
INSERT INTO `link_web` VALUES (23, 'Gitee', 'https://gitee.com/stt0626', 'http://localhost:8128/img/link/web/20240510112505A022.png', '国内开源代码资料库', 2, 0, 0, '', NULL, '', NULL, '');
INSERT INTO `link_web` VALUES (24, '慕课网', 'https://www.imooc.com/', 'http://localhost:8128/img/link/web/20240510112621A023.png', '程序员的梦工厂', 2, 0, 0, '', NULL, '', NULL, '');
INSERT INTO `link_web` VALUES (25, '全历史', 'https://www.allhistory.com/', 'http://localhost:8128/img/link/web/20240510112828A024.png', 'AI知识图谱,数字化人文内容', 3, 0, 0, '', NULL, '', NULL, '');
INSERT INTO `link_web` VALUES (26, '藏书馆', 'https://www.zglibrary.com/', 'http://localhost:8128/img/link/web/20240510113703A025.png', '拥有主宰自己的力量', 3, 0, 0, '', NULL, '', NULL, '');
INSERT INTO `link_web` VALUES (27, '观沧海', 'https://www.ageeye.cn/', 'http://localhost:8128/img/link/web/20240510114045A026.png', '地图分享知识', 3, 0, 0, '', NULL, '', NULL, '');
INSERT INTO `link_web` VALUES (28, '二十四节气网', 'https://www.solarterm.cn/', 'http://localhost:8128/img/link/web/20240510114725A027.png', '中国人最诚挚朴素的自然智慧', 3, 0, 0, '', NULL, '', NULL, '');
INSERT INTO `link_web` VALUES (29, '汉程网', 'https://www.httpcn.com/', 'http://localhost:8128/img/link/web/20240510115837A029.png', '综合传统文化平台', 3, 0, 0, '', NULL, '', NULL, '');
INSERT INTO `link_web` VALUES (30, '古诗词网', 'https://www.56612.com/', 'http://localhost:8128/img/link/web/20240510120207A030.png', '共赏中华诗词、探寻文化基因、创造生活之美', 3, 0, 0, '', NULL, '', NULL, '');
INSERT INTO `link_web` VALUES (31, '阿里图标库', 'https://www.iconfont.cn/', 'http://localhost:8128/img/link/web/20240510152309A031.jpg', '国内最著名的图标搜索及管理平台,超2300万个图标下载', 0, 0, 0, '', NULL, '', NULL, '');
-- ----------------------------
-- Table structure for operate_support
-- ----------------------------
DROP TABLE IF EXISTS `operate_support`;
CREATE TABLE `operate_support` (
`id` bigint NOT NULL AUTO_INCREMENT COMMENT '主键id',
`title` varchar(150) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '支持标题',
`er_code` varchar(150) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '二维码地址',
`sorts` int NOT NULL DEFAULT 0 COMMENT '排序',
`create_time` datetime NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`update_time` datetime NULL DEFAULT CURRENT_TIMESTAMP COMMENT '最后更新时间',
`creator` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT '创建者',
`updater` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT '更新者',
`deleted` int NULL DEFAULT 0 COMMENT '逻辑删除',
`remark` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT '备注',
`status` int NULL DEFAULT 0 COMMENT '状态',
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 3 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '打赏支持表' ROW_FORMAT = DYNAMIC;
-- ----------------------------
-- Records of operate_support
-- ----------------------------
INSERT INTO `operate_support` VALUES (1, '微信', 'http://localhost:8128/img/operateSupport/20240507163543A001.jpg', 0, '2024-05-07 16:35:47', '2024-05-07 16:35:47', '', '', 0, '', 0);
INSERT INTO `operate_support` VALUES (2, '支付宝', 'http://localhost:8128/img/operateSupport/20240507163557A002.jpg', 1, '2024-05-07 16:35:59', '2024-05-07 16:35:59', '', '', 0, '', 0);
-- ----------------------------
-- Table structure for sys_config
-- ----------------------------
DROP TABLE IF EXISTS `sys_config`;
CREATE TABLE `sys_config` (
`config_id` int NOT NULL AUTO_INCREMENT COMMENT '参数主键',
`config_name` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT '' COMMENT '参数名称',
`config_key` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT '' COMMENT '参数键名',
`config_value` varchar(500) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT '' COMMENT '参数键值',
`config_type` char(1) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT 'N' COMMENT '系统内置(Y是 N否)',
`creator` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT '' COMMENT '创建者',
`create_time` datetime NULL DEFAULT NULL COMMENT '创建时间',
`updater` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT '' COMMENT '更新者',
`update_time` datetime NULL DEFAULT NULL COMMENT '更新时间',
`remark` varchar(500) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '备注',
`deleted` int NULL DEFAULT 0 COMMENT '逻辑删除',
PRIMARY KEY (`config_id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 101 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci COMMENT = '参数配置表' ROW_FORMAT = DYNAMIC;
-- ----------------------------
-- Records of sys_config
-- ----------------------------
INSERT INTO `sys_config` VALUES (1, '主框架页-默认皮肤样式名称', 'sys.index.skinName', 'skin-blue', 'Y', 'admin', '2024-02-25 16:38:43', '', NULL, '蓝色 skin-blue、绿色 skin-green、紫色 skin-purple、红色 skin-red、黄色 skin-yellow', 0);
INSERT INTO `sys_config` VALUES (2, '用户管理-账号初始密码', 'sys.user.initPassword', '123456', 'Y', 'admin', '2024-02-25 16:38:43', '', NULL, '初始化密码 123456', 0);
INSERT INTO `sys_config` VALUES (3, '主框架页-侧边栏主题', 'sys.index.sideTheme', 'theme-dark', 'Y', 'admin', '2024-02-25 16:38:43', '', NULL, '深色主题theme-dark,浅色主题theme-light', 0);
INSERT INTO `sys_config` VALUES (4, '账号自助-验证码开关', 'sys.account.captchaEnabled', 'true', 'Y', 'admin', '2024-02-25 16:38:43', '', NULL, '是否开启验证码功能(true开启,false关闭)', 0);
INSERT INTO `sys_config` VALUES (5, '账号自助-是否开启用户注册功能', 'sys.account.registerUser', 'false', 'Y', 'admin', '2024-02-25 16:38:43', '', NULL, '是否开启注册用户功能(true开启,false关闭)', 0);
INSERT INTO `sys_config` VALUES (6, '用户登录-黑名单列表', 'sys.login.blackIPList', '', 'Y', 'admin', '2024-02-25 16:38:43', '', NULL, '设置登录IP黑名单限制,多个匹配项以;分隔,支持匹配(*通配、网段)', 0);
-- ----------------------------
-- Table structure for sys_dept
-- ----------------------------
DROP TABLE IF EXISTS `sys_dept`;
CREATE TABLE `sys_dept` (
`dept_id` bigint NOT NULL AUTO_INCREMENT COMMENT '部门id',
`parent_id` bigint NULL DEFAULT 0 COMMENT '父部门id',
`ancestors` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT '' COMMENT '祖级列表',
`dept_name` varchar(30) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT '' COMMENT '部门名称',
`order_num` int NULL DEFAULT 0 COMMENT '显示顺序',
`leader` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '负责人',
`mobile` varchar(11) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '联系电话',
`email` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '邮箱',
`status` int NULL DEFAULT 0 COMMENT '部门状态(0正常 1停用)',
`deleted` int NULL DEFAULT 0 COMMENT '删除标志(0代表存在 2代表删除)',
`creator` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT '' COMMENT '创建者',
`create_time` datetime NULL DEFAULT NULL COMMENT '创建时间',
`updater` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT '' COMMENT '更新者',
`update_time` datetime NULL DEFAULT NULL COMMENT '更新时间',
`remark` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT '' COMMENT '备注',
PRIMARY KEY (`dept_id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 201 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci COMMENT = '部门表' ROW_FORMAT = DYNAMIC;
-- ----------------------------
-- Records of sys_dept
-- ----------------------------
INSERT INTO `sys_dept` VALUES (100, 0, '0', '自得其道', 0, '自得', '15888888888', 'xy@qq.com', 0, 0, 'admin', '2024-02-25 16:38:43', '', '2024-05-11 15:53:08', NULL);
INSERT INTO `sys_dept` VALUES (101, 100, '0,100', '深圳总公司', 1, '闲影', '15888888888', 'xy@qq.com', 0, 0, 'admin', '2024-02-25 16:38:43', '', '2024-03-19 17:27:19', NULL);
INSERT INTO `sys_dept` VALUES (102, 100, '0,100', '郑州分公司', 2, '闲影', '15888888888', 'xy@qq.com', 0, 0, 'admin', '2024-02-25 16:38:43', '', '2024-03-19 17:27:08', NULL);
INSERT INTO `sys_dept` VALUES (103, 101, '0,100,101', '研发部门', 1, '闲影', '15888888888', 'xy@qq.com', 0, 0, 'admin', '2024-02-25 16:38:43', '', '2024-03-19 17:27:55', NULL);
INSERT INTO `sys_dept` VALUES (104, 101, '0,100,101', '市场部门', 2, '闲影', '15888888888', 'xy@qq.com', 0, 0, 'admin', '2024-02-25 16:38:43', '', '2024-03-19 17:28:05', NULL);
INSERT INTO `sys_dept` VALUES (105, 101, '0,100,101', '测试部门', 3, '闲影', '15888888888', 'xy@qq.com', 0, 0, 'admin', '2024-02-25 16:38:43', '', '2024-03-19 17:28:13', NULL);
INSERT INTO `sys_dept` VALUES (106, 101, '0,100,101', '财务部门', 4, '闲影', '15888888888', 'xy@qq.com', 0, 0, 'admin', '2024-02-25 16:38:43', '', '2024-03-19 17:28:22', NULL);
INSERT INTO `sys_dept` VALUES (107, 101, '0,100,101', '运维部门', 5, '闲影', '15888888888', 'xy@qq.com', 0, 2, 'admin', '2024-02-25 16:38:43', '', '2024-03-19 17:28:30', NULL);
INSERT INTO `sys_dept` VALUES (108, 102, '0,100,102', '市场部门', 1, '闲影', '15888888888', 'xy@qq.com', 0, 0, 'admin', '2024-02-25 16:38:43', '', '2024-03-19 17:28:38', NULL);
INSERT INTO `sys_dept` VALUES (109, 102, '0,100,102', '财务部门', 2, '闲影', '15888888888', 'xy@qq.com', 0, 0, 'admin', '2024-02-25 16:38:43', '', '2024-03-19 17:28:46', NULL);
INSERT INTO `sys_dept` VALUES (200, 102, '0,100,102', '研发部门', 3, '孟怀', '16356524587', 'mh@163.com', 0, 0, '', '2024-03-19 17:31:20', '', '2024-03-20 09:30:35', NULL);
-- ----------------------------
-- Table structure for sys_dict_data
-- ----------------------------
DROP TABLE IF EXISTS `sys_dict_data`;
CREATE TABLE `sys_dict_data` (
`dict_code` bigint NOT NULL AUTO_INCREMENT COMMENT '字典编码',
`dict_sort` int NULL DEFAULT 0 COMMENT '字典排序',
`dict_label` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT '' COMMENT '字典标签',
`dict_value` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT '' COMMENT '字典键值',
`dict_type` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT '' COMMENT '字典类型',
`css_class` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '样式属性(其他样式扩展)',
`list_class` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '表格回显样式',
`is_default` char(1) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT 'N' COMMENT '是否默认(Y是 N否)',
`status` int NULL DEFAULT 0 COMMENT '状态(0正常 1停用)',
`creator` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT '' COMMENT '创建者',
`create_time` datetime NULL DEFAULT NULL COMMENT '创建时间',
`updater` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT '' COMMENT '更新者',
`update_time` datetime NULL DEFAULT NULL COMMENT '更新时间',
`remark` varchar(500) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '备注',
PRIMARY KEY (`dict_code`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 100 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci COMMENT = '字典数据表' ROW_FORMAT = DYNAMIC;
-- ----------------------------
-- Records of sys_dict_data
-- ----------------------------
INSERT INTO `sys_dict_data` VALUES (1, 1, '男', '0', 'sys_user_sex', '', '', 'Y', 0, 'admin', '2024-02-25 16:38:43', '', NULL, '性别男');
INSERT INTO `sys_dict_data` VALUES (2, 2, '女', '1', 'sys_user_sex', '', '', 'N', 0, 'admin', '2024-02-25 16:38:43', '', NULL, '性别女');
INSERT INTO `sys_dict_data` VALUES (3, 3, '未知', '2', 'sys_user_sex', '', '', 'N', 0, 'admin', '2024-02-25 16:38:43', '', NULL, '性别未知');
INSERT INTO `sys_dict_data` VALUES (4, 1, '显示', '0', 'sys_show_hide', '', 'primary', 'Y', 0, 'admin', '2024-02-25 16:38:43', '', NULL, '显示菜单');
INSERT INTO `sys_dict_data` VALUES (5, 2, '隐藏', '1', 'sys_show_hide', '', 'danger', 'N', 0, 'admin', '2024-02-25 16:38:43', '', NULL, '隐藏菜单');
INSERT INTO `sys_dict_data` VALUES (6, 1, '正常', '0', 'sys_normal_disable', '', 'primary', 'Y', 0, 'admin', '2024-02-25 16:38:43', '', NULL, '正常状态');
INSERT INTO `sys_dict_data` VALUES (7, 2, '停用', '1', 'sys_normal_disable', '', 'danger', 'N', 0, 'admin', '2024-02-25 16:38:43', '', NULL, '停用状态');
INSERT INTO `sys_dict_data` VALUES (8, 1, '正常', '0', 'sys_job_status', '', 'primary', 'Y', 0, 'admin', '2024-02-25 16:38:43', '', NULL, '正常状态');
INSERT INTO `sys_dict_data` VALUES (9, 2, '暂停', '1', 'sys_job_status', '', 'danger', 'N', 0, 'admin', '2024-02-25 16:38:43', '', NULL, '停用状态');
INSERT INTO `sys_dict_data` VALUES (10, 1, '默认', 'DEFAULT', 'sys_job_group', '', '', 'Y', 0, 'admin', '2024-02-25 16:38:43', '', NULL, '默认分组');
INSERT INTO `sys_dict_data` VALUES (11, 2, '系统', 'SYSTEM', 'sys_job_group', '', '', 'N', 0, 'admin', '2024-02-25 16:38:43', '', NULL, '系统分组');
INSERT INTO `sys_dict_data` VALUES (12, 1, '是', 'Y', 'sys_yes_no', '', 'primary', 'Y', 0, 'admin', '2024-02-25 16:38:43', '', NULL, '系统默认是');
INSERT INTO `sys_dict_data` VALUES (13, 2, '否', 'N', 'sys_yes_no', '', 'danger', 'N', 0, 'admin', '2024-02-25 16:38:43', '', NULL, '系统默认否');
INSERT INTO `sys_dict_data` VALUES (14, 1, '通知', '1', 'sys_notice_type', '', 'warning', 'Y', 0, 'admin', '2024-02-25 16:38:43', '', NULL, '通知');
INSERT INTO `sys_dict_data` VALUES (15, 2, '公告', '2', 'sys_notice_type', '', 'success', 'N', 0, 'admin', '2024-02-25 16:38:43', '', NULL, '公告');
INSERT INTO `sys_dict_data` VALUES (16, 1, '正常', '0', 'sys_notice_status', '', 'primary', 'Y', 0, 'admin', '2024-02-25 16:38:43', '', NULL, '正常状态');
INSERT INTO `sys_dict_data` VALUES (17, 2, '关闭', '1', 'sys_notice_status', '', 'danger', 'N', 0, 'admin', '2024-02-25 16:38:43', '', NULL, '关闭状态');
INSERT INTO `sys_dict_data` VALUES (18, 99, '其他', '0', 'sys_oper_type', '', 'info', 'N', 0, 'admin', '2024-02-25 16:38:43', '', NULL, '其他操作');
INSERT INTO `sys_dict_data` VALUES (19, 1, '新增', '1', 'sys_oper_type', '', 'info', 'N', 0, 'admin', '2024-02-25 16:38:43', '', NULL, '新增操作');
INSERT INTO `sys_dict_data` VALUES (20, 2, '修改', '2', 'sys_oper_type', '', 'info', 'N', 0, 'admin', '2024-02-25 16:38:43', '', NULL, '修改操作');
INSERT INTO `sys_dict_data` VALUES (21, 3, '删除', '3', 'sys_oper_type', '', 'danger', 'N', 0, 'admin', '2024-02-25 16:38:43', '', NULL, '删除操作');
INSERT INTO `sys_dict_data` VALUES (22, 4, '授权', '4', 'sys_oper_type', '', 'primary', 'N', 0, 'admin', '2024-02-25 16:38:43', '', NULL, '授权操作');
INSERT INTO `sys_dict_data` VALUES (23, 5, '导出', '5', 'sys_oper_type', '', 'warning', 'N', 0, 'admin', '2024-02-25 16:38:43', '', NULL, '导出操作');
INSERT INTO `sys_dict_data` VALUES (24, 6, '导入', '6', 'sys_oper_type', '', 'warning', 'N', 0, 'admin', '2024-02-25 16:38:43', '', NULL, '导入操作');
INSERT INTO `sys_dict_data` VALUES (25, 7, '强退', '7', 'sys_oper_type', '', 'danger', 'N', 0, 'admin', '2024-02-25 16:38:43', '', NULL, '强退操作');
INSERT INTO `sys_dict_data` VALUES (26, 8, '生成代码', '8', 'sys_oper_type', '', 'warning', 'N', 0, 'admin', '2024-02-25 16:38:43', '', NULL, '生成操作');
INSERT INTO `sys_dict_data` VALUES (27, 9, '清空数据', '9', 'sys_oper_type', '', 'danger', 'N', 0, 'admin', '2024-02-25 16:38:43', '', NULL, '清空操作');
INSERT INTO `sys_dict_data` VALUES (28, 1, '成功', '0', 'sys_common_status', '', 'primary', 'N', 0, 'admin', '2024-02-25 16:38:43', '', NULL, '正常状态');
INSERT INTO `sys_dict_data` VALUES (29, 2, '失败', '1', 'sys_common_status', '', 'danger', 'N', 0, 'admin', '2024-02-25 16:38:43', '', NULL, '停用状态');
-- ----------------------------
-- Table structure for sys_dict_type
-- ----------------------------
DROP TABLE IF EXISTS `sys_dict_type`;
CREATE TABLE `sys_dict_type` (
`dict_id` bigint NOT NULL AUTO_INCREMENT COMMENT '字典主键',
`dict_name` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT '' COMMENT '字典名称',
`dict_type` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT '' COMMENT '字典类型',
`status` int NULL DEFAULT 0 COMMENT '状态(0正常 1停用)',
`creator` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT '' COMMENT '创建者',
`create_time` datetime NULL DEFAULT NULL COMMENT '创建时间',
`updater` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT '' COMMENT '更新者',
`update_time` datetime NULL DEFAULT NULL COMMENT '更新时间',
`remark` varchar(500) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '备注',
PRIMARY KEY (`dict_id`) USING BTREE,
UNIQUE INDEX `dict_type`(`dict_type` ASC) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 101 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci COMMENT = '字典类型表' ROW_FORMAT = DYNAMIC;
-- ----------------------------
-- Records of sys_dict_type
-- ----------------------------
INSERT INTO `sys_dict_type` VALUES (1, '用户性别', 'sys_user_sex', 0, 'admin', '2024-02-25 16:38:43', '', '2024-03-20 10:19:13', '用户性别列表');
INSERT INTO `sys_dict_type` VALUES (2, '菜单状态', 'sys_show_hide', 0, 'admin', '2024-02-25 16:38:43', '', NULL, '菜单状态列表');
INSERT INTO `sys_dict_type` VALUES (3, '系统开关', 'sys_normal_disable', 0, 'admin', '2024-02-25 16:38:43', '', NULL, '系统开关列表');
INSERT INTO `sys_dict_type` VALUES (4, '任务状态', 'sys_job_status', 0, 'admin', '2024-02-25 16:38:43', '', NULL, '任务状态列表');
INSERT INTO `sys_dict_type` VALUES (5, '任务分组', 'sys_job_group', 0, 'admin', '2024-02-25 16:38:43', '', NULL, '任务分组列表');
INSERT INTO `sys_dict_type` VALUES (6, '系统是否', 'sys_yes_no', 0, 'admin', '2024-02-25 16:38:43', '', NULL, '系统是否列表');
INSERT INTO `sys_dict_type` VALUES (7, '通知类型', 'sys_notice_type', 0, 'admin', '2024-02-25 16:38:43', '', NULL, '通知类型列表');
INSERT INTO `sys_dict_type` VALUES (8, '通知状态', 'sys_notice_status', 0, 'admin', '2024-02-25 16:38:43', '', NULL, '通知状态列表');
INSERT INTO `sys_dict_type` VALUES (9, '操作类型', 'sys_oper_type', 0, 'admin', '2024-02-25 16:38:43', '', NULL, '操作类型列表');
INSERT INTO `sys_dict_type` VALUES (10, '系统状态', 'sys_common_status', 0, 'admin', '2024-02-25 16:38:43', '', NULL, '登录状态列表');
-- ----------------------------
-- Table structure for sys_job
-- ----------------------------
DROP TABLE IF EXISTS `sys_job`;
CREATE TABLE `sys_job` (
`job_id` bigint NOT NULL AUTO_INCREMENT COMMENT '任务ID',
`job_name` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL DEFAULT '' COMMENT '任务名称',
`job_group` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL DEFAULT 'DEFAULT' COMMENT '任务组名',
`invoke_target` varchar(500) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '调用目标字符串',
`cron_expression` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT '' COMMENT 'cron执行表达式',
`misfire_policy` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT '3' COMMENT '计划执行错误策略(1立即执行 2执行一次 3放弃执行)',
`concurrent` char(1) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT '1' COMMENT '是否并发执行(0允许 1禁止)',
`status` int NULL DEFAULT 0 COMMENT '状态(0正常 1暂停)',
`creator` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT '' COMMENT '创建者',
`create_time` datetime NULL DEFAULT NULL COMMENT '创建时间',
`updater` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT '' COMMENT '更新者',
`update_time` datetime NULL DEFAULT NULL COMMENT '更新时间',
`remark` varchar(500) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT '' COMMENT '备注信息',
`deleted` int NULL DEFAULT NULL COMMENT '逻辑删除',
PRIMARY KEY (`job_id`, `job_name`, `job_group`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 100 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci COMMENT = '定时任务调度表' ROW_FORMAT = DYNAMIC;
-- ----------------------------
-- Records of sys_job
-- ----------------------------
INSERT INTO `sys_job` VALUES (1, '系统默认(无参)', 'DEFAULT', 'ryTask.ryNoParams', '0/10 * * * * ?', '3', '1', 1, 'admin', '2024-02-25 16:38:43', '', '2024-03-20 12:16:47', '', 0);
INSERT INTO `sys_job` VALUES (2, '系统默认(有参)', 'DEFAULT', 'ryTask.ryParams(\'ry\')', '0/15 * * * * ?', '3', '1', 1, 'admin', '2024-02-25 16:38:43', '', NULL, '', 0);
INSERT INTO `sys_job` VALUES (3, '系统默认(多参)', 'DEFAULT', 'ryTask.ryMultipleParams(\'ry\', true, 2000L, 316.50D, 100)', '0/20 * * * * ?', '3', '1', 1, 'admin', '2024-02-25 16:38:43', '', NULL, '', 0);
-- ----------------------------
-- Table structure for sys_job_log
-- ----------------------------
DROP TABLE IF EXISTS `sys_job_log`;
CREATE TABLE `sys_job_log` (
`job_log_id` bigint NOT NULL AUTO_INCREMENT COMMENT '任务日志ID',
`job_name` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '任务名称',
`job_group` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '任务组名',
`invoke_target` varchar(500) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '调用目标字符串',
`job_message` varchar(500) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '日志信息',
`status` int NULL DEFAULT 0 COMMENT '执行状态(0正常 1失败)',
`exception_info` varchar(2000) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT '' COMMENT '异常信息',
`create_time` datetime NULL DEFAULT NULL COMMENT '创建时间',
`creator` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '创建者',
`update_time` datetime NULL DEFAULT NULL COMMENT '更新时间',
`updater` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '更新者',
`remark` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '备注',
PRIMARY KEY (`job_log_id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 2 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci COMMENT = '定时任务调度日志表' ROW_FORMAT = DYNAMIC;
-- ----------------------------
-- Records of sys_job_log
-- ----------------------------
INSERT INTO `sys_job_log` VALUES (1, '系统默认(无参)', 'DEFAULT', 'ryTask.ryNoParams', NULL, 0, '', NULL, NULL, NULL, NULL, NULL);
-- ----------------------------
-- Table structure for sys_logininfor
-- ----------------------------
DROP TABLE IF EXISTS `sys_logininfor`;
CREATE TABLE `sys_logininfor` (
`info_id` bigint NOT NULL AUTO_INCREMENT COMMENT '访问ID',
`username` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT '' COMMENT '用户账号',
`ipaddr` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT '' COMMENT '登录IP地址',
`login_location` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT '' COMMENT '登录地点',
`browser` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT '' COMMENT '浏览器类型',
`os` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT '' COMMENT '操作系统',
`status` int NULL DEFAULT 0 COMMENT '登录状态(0成功 1失败)',
`msg` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT '' COMMENT '提示消息',
`login_time` datetime NULL DEFAULT NULL COMMENT '访问时间',
`creator` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL,
`create_time` datetime NULL DEFAULT NULL,
`updater` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL,
`update_time` datetime NULL DEFAULT NULL,
`remark` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL,
PRIMARY KEY (`info_id`) USING BTREE,
INDEX `idx_sys_logininfor_s`(`status` ASC) USING BTREE,
INDEX `idx_sys_logininfor_lt`(`login_time` ASC) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 218 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci COMMENT = '系统访问记录' ROW_FORMAT = DYNAMIC;
-- ----------------------------
-- Records of sys_logininfor
-- ----------------------------
INSERT INTO `sys_logininfor` VALUES (100, 'admin', '127.0.0.1', '内网IP', 'Chrome 11', 'Windows 10', 0, '????', '2024-02-26 10:45:55', NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sys_logininfor` VALUES (101, 'admin', '127.0.0.1', '内网IP', 'Chrome 11', 'Windows 10', 0, '????', '2024-02-26 10:45:56', NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sys_logininfor` VALUES (102, 'admin', '127.0.0.1', '内网IP', 'Chrome 11', 'Windows 10', 0, '????', '2024-02-26 10:52:03', NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sys_logininfor` VALUES (103, 'admin', '127.0.0.1', '内网IP', 'Chrome 11', 'Windows 10', 0, '????', '2024-02-26 10:52:04', NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sys_logininfor` VALUES (104, 'admin', '127.0.0.1', '内网IP', 'Chrome 11', 'Windows 10', 0, '????', '2024-02-26 10:54:18', NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sys_logininfor` VALUES (105, 'admin', '127.0.0.1', '内网IP', 'Chrome 11', 'Windows 10', 0, '????', '2024-02-26 10:54:18', NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sys_logininfor` VALUES (106, 'admin', '127.0.0.1', '内网IP', 'Chrome 11', 'Windows 10', 0, '????', '2024-02-26 10:56:44', NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sys_logininfor` VALUES (107, 'admin', '127.0.0.1', '内网IP', 'Chrome 11', 'Windows 10', 0, '????', '2024-02-26 11:19:09', NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sys_logininfor` VALUES (108, 'admin', '127.0.0.1', '内网IP', 'Chrome 11', 'Windows 10', 0, '????', '2024-02-26 11:19:14', NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sys_logininfor` VALUES (109, NULL, '127.0.0.1', '内网IP', 'Chrome 11', 'Windows 10', 0, '????', '2024-02-27 09:57:36', NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sys_logininfor` VALUES (110, 'admin', '127.0.0.1', '内网IP', 'Chrome 11', 'Windows 10', 0, '????', '2024-02-27 09:57:38', NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sys_logininfor` VALUES (111, 'admin', '127.0.0.1', '内网IP', 'Chrome 11', 'Windows 10', 0, '????', '2024-02-27 09:57:43', NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sys_logininfor` VALUES (112, 'admin', '127.0.0.1', '内网IP', 'Chrome 11', 'Windows 10', 0, '????', '2024-02-27 09:58:37', NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sys_logininfor` VALUES (113, 'admin', '127.0.0.1', '内网IP', 'Chrome 11', 'Windows 10', 0, '登录成功', '2024-03-08 16:20:28', NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sys_logininfor` VALUES (114, 'admin', '127.0.0.1', '内网IP', 'Chrome 11', 'Windows 10', 0, '登录成功', '2024-03-11 09:53:29', NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sys_logininfor` VALUES (115, 'admin', '127.0.0.1', '内网IP', 'Chrome 11', 'Windows 10', 0, '登录成功', '2024-03-11 10:16:40', NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sys_logininfor` VALUES (116, 'admin', '127.0.0.1', '内网IP', 'Chrome 11', 'Windows 10', 0, '退出成功', '2024-03-12 12:10:59', NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sys_logininfor` VALUES (117, 'admin', '127.0.0.1', '内网IP', 'Chrome 11', 'Windows 10', 0, '登录成功', '2024-03-12 12:11:07', NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sys_logininfor` VALUES (118, 'admin', '127.0.0.1', '内网IP', 'Chrome 11', 'Windows 10', 0, '登录成功', '2024-03-18 09:30:07', NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sys_logininfor` VALUES (119, 'admin', '127.0.0.1', '内网IP', 'Chrome 11', 'Windows 10', 0, '退出成功', '2024-03-18 16:09:32', NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sys_logininfor` VALUES (120, 'admin', '127.0.0.1', '内网IP', 'Chrome 11', 'Windows 10', 0, '登录成功', '2024-03-18 16:09:36', NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sys_logininfor` VALUES (121, 'admin', '127.0.0.1', '内网IP', 'Chrome 11', 'Windows 10', 0, '登录成功', '2024-03-19 09:30:40', NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sys_logininfor` VALUES (122, 'admin', '127.0.0.1', '内网IP', 'Chrome 11', 'Windows 10', 0, '登录成功', '2024-03-19 09:54:55', NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sys_logininfor` VALUES (123, 'admin', '127.0.0.1', '内网IP', 'Chrome 11', 'Windows 10', 1, '用户不存在/密码错误', '2024-04-24 10:58:49', NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sys_logininfor` VALUES (124, 'admin', '127.0.0.1', '内网IP', 'Chrome 11', 'Windows 10', 1, '用户不存在/密码错误', '2024-04-24 10:59:02', NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sys_logininfor` VALUES (125, 'admin', '127.0.0.1', '内网IP', 'Chrome 11', 'Windows 10', 1, '用户不存在/密码错误', '2024-04-24 11:03:34', NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sys_logininfor` VALUES (126, 'admin', '127.0.0.1', '内网IP', 'Chrome 11', 'Windows 10', 1, '用户不存在/密码错误', '2024-04-24 11:03:42', NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sys_logininfor` VALUES (127, 'admin', '127.0.0.1', '内网IP', 'Chrome 11', 'Windows 10', 1, '用户不存在/密码错误', '2024-04-24 11:05:58', NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sys_logininfor` VALUES (128, 'admin', '127.0.0.1', '内网IP', 'Chrome 11', 'Windows 10', 1, '验证码已失效', '2024-04-24 11:09:27', NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sys_logininfor` VALUES (129, 'admin', '127.0.0.1', '内网IP', 'Chrome 11', 'Windows 10', 1, '密码输入错误5次,帐户锁定10分钟', '2024-04-24 11:09:30', NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sys_logininfor` VALUES (130, 'admin', '127.0.0.1', '内网IP', 'Chrome 11', 'Windows 10', 0, '登录成功', '2024-04-24 11:10:10', NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sys_logininfor` VALUES (131, 'admin', '127.0.0.1', '内网IP', 'Chrome 11', 'Windows 10', 0, '退出成功', '2024-04-24 11:50:07', NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sys_logininfor` VALUES (132, 'admin', '127.0.0.1', '内网IP', 'Chrome 11', 'Windows 10', 1, '用户不存在/密码错误', '2024-04-24 11:50:15', NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sys_logininfor` VALUES (133, 'admin', '127.0.0.1', '内网IP', 'Chrome 11', 'Windows 10', 1, '验证码错误', '2024-04-24 11:50:18', NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sys_logininfor` VALUES (134, 'admin', '127.0.0.1', '内网IP', 'Chrome 11', 'Windows 10', 0, '登录成功', '2024-04-24 11:50:23', NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sys_logininfor` VALUES (135, 'admin', '127.0.0.1', '内网IP', 'Chrome 11', 'Windows 10', 0, '登录成功', '2024-04-24 15:34:00', NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sys_logininfor` VALUES (136, 'admin', '127.0.0.1', '内网IP', 'Chrome 11', 'Windows 10', 0, '登录成功', '2024-04-24 15:50:29', NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sys_logininfor` VALUES (137, 'admin', '127.0.0.1', '内网IP', 'Chrome 11', 'Windows 10', 0, '登录成功', '2024-04-24 15:50:44', NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sys_logininfor` VALUES (138, 'admin', '127.0.0.1', '内网IP', 'Chrome 11', 'Windows 10', 0, '登录成功', '2024-04-24 15:50:46', NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sys_logininfor` VALUES (139, 'admin', '127.0.0.1', '内网IP', 'Chrome 11', 'Windows 10', 0, '登录成功', '2024-04-24 15:51:53', NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sys_logininfor` VALUES (140, 'admin', '127.0.0.1', '内网IP', 'Chrome 11', 'Windows 10', 0, '登录成功', '2024-04-24 15:53:45', NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sys_logininfor` VALUES (141, 'admin', '127.0.0.1', '内网IP', 'Chrome 11', 'Windows 10', 0, '登录成功', '2024-04-25 09:12:53', NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sys_logininfor` VALUES (142, 'admin', '127.0.0.1', '内网IP', 'Chrome 11', 'Windows 10', 0, '登录成功', '2024-04-25 09:16:19', NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sys_logininfor` VALUES (143, 'admin', '127.0.0.1', '内网IP', 'Chrome 11', 'Windows 10', 0, '登录成功', '2024-04-25 09:18:19', NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sys_logininfor` VALUES (144, 'admin', '127.0.0.1', '内网IP', 'Chrome 11', 'Windows 10', 0, '登录成功', '2024-04-25 09:22:01', NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sys_logininfor` VALUES (145, 'admin', '127.0.0.1', '内网IP', 'Chrome 11', 'Windows 10', 0, '登录成功', '2024-04-25 09:26:39', NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sys_logininfor` VALUES (146, 'admin', '127.0.0.1', '内网IP', 'Chrome 11', 'Windows 10', 0, '登录成功', '2024-04-25 09:33:59', NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sys_logininfor` VALUES (147, 'admin', '127.0.0.1', '内网IP', 'Chrome 11', 'Windows 10', 0, '登录成功', '2024-04-25 09:36:53', NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sys_logininfor` VALUES (148, 'admin', '127.0.0.1', '内网IP', 'Chrome 11', 'Windows 10', 1, '验证码已失效', '2024-04-25 09:47:00', NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sys_logininfor` VALUES (149, 'admin', '127.0.0.1', '内网IP', 'Chrome 11', 'Windows 10', 0, '登录成功', '2024-04-25 09:47:03', NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sys_logininfor` VALUES (150, 'admin', '127.0.0.1', '内网IP', 'Chrome 11', 'Windows 10', 0, '登录成功', '2024-04-25 11:18:25', NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sys_logininfor` VALUES (151, 'admin', '127.0.0.1', '内网IP', 'Chrome 11', 'Windows 10', 0, '登录成功', '2024-04-25 11:18:26', NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sys_logininfor` VALUES (152, 'admin', '127.0.0.1', '内网IP', 'Unknown', 'Unknown', 1, '验证码已失效', '2024-04-25 11:45:05', NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sys_logininfor` VALUES (153, 'admin', '127.0.0.1', '内网IP', 'Chrome 11', 'Windows 10', 0, '登录成功', '2024-04-25 11:45:18', NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sys_logininfor` VALUES (154, 'admin', '127.0.0.1', '内网IP', 'Chrome 11', 'Windows 10', 0, '登录成功', '2024-04-29 12:01:05', NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sys_logininfor` VALUES (155, 'admin', '127.0.0.1', '内网IP', 'Chrome 11', 'Windows 10', 0, '登录成功', '2024-04-29 12:09:18', NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sys_logininfor` VALUES (156, 'admin', '127.0.0.1', '内网IP', 'Chrome 11', 'Windows 10', 0, '登录成功', '2024-04-29 14:48:59', NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sys_logininfor` VALUES (157, 'admin', '127.0.0.1', '内网IP', 'Chrome 11', 'Windows 10', 0, '登录成功', '2024-04-29 15:11:19', NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sys_logininfor` VALUES (158, 'admin', '127.0.0.1', '内网IP', 'Chrome 11', 'Windows 10', 0, '登录成功', '2024-04-29 15:11:20', NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sys_logininfor` VALUES (159, 'admin', '127.0.0.1', '内网IP', 'Chrome 11', 'Windows 10', 0, '登录成功', '2024-04-29 17:32:17', NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sys_logininfor` VALUES (160, 'admin', '127.0.0.1', '内网IP', 'Chrome 11', 'Windows 10', 0, '登录成功', '2024-04-29 17:32:23', NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sys_logininfor` VALUES (161, 'admin', '127.0.0.1', '内网IP', 'Chrome 11', 'Windows 10', 0, '登录成功', '2024-04-29 17:35:08', NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sys_logininfor` VALUES (162, 'admin', '127.0.0.1', '内网IP', 'Chrome 11', 'Windows 10', 0, '登录成功', '2024-04-29 21:02:43', NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sys_logininfor` VALUES (163, 'admin', '127.0.0.1', '内网IP', 'Chrome 11', 'Windows 10', 0, '登录成功', '2024-04-29 21:32:48', NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sys_logininfor` VALUES (164, 'admin', '127.0.0.1', '内网IP', 'Chrome 11', 'Windows 10', 0, '登录成功', '2024-04-29 21:43:57', NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sys_logininfor` VALUES (165, 'admin', '127.0.0.1', '内网IP', 'Chrome 11', 'Windows 10', 0, '登录成功', '2024-04-29 22:32:05', NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sys_logininfor` VALUES (166, 'admin', '127.0.0.1', '内网IP', 'Chrome 11', 'Windows 10', 0, '登录成功', '2024-04-29 22:33:40', NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sys_logininfor` VALUES (167, 'admin', '127.0.0.1', '内网IP', 'Chrome 11', 'Windows 10', 0, '登录成功', '2024-04-29 22:34:09', NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sys_logininfor` VALUES (168, 'admin', '127.0.0.1', '内网IP', 'Chrome 11', 'Windows 10', 0, '登录成功', '2024-04-29 22:37:58', NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sys_logininfor` VALUES (169, 'admin', '127.0.0.1', '内网IP', 'Chrome 11', 'Windows 10', 0, '登录成功', '2024-04-29 22:43:49', NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sys_logininfor` VALUES (170, 'admin', '127.0.0.1', '内网IP', 'Chrome 11', 'Windows 10', 0, '登录成功', '2024-04-29 22:44:05', NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sys_logininfor` VALUES (171, 'admin', '127.0.0.1', '内网IP', 'Chrome 11', 'Windows 10', 0, '登录成功', '2024-04-29 22:44:52', NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sys_logininfor` VALUES (172, 'admin', '127.0.0.1', '内网IP', 'Chrome 11', 'Windows 10', 0, '登录成功', '2024-04-29 23:20:15', NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sys_logininfor` VALUES (173, 'admin', '127.0.0.1', '内网IP', 'Chrome 11', 'Windows 10', 0, '登录成功', '2024-04-30 09:18:21', NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sys_logininfor` VALUES (174, 'admin', '127.0.0.1', '内网IP', 'Chrome 11', 'Windows 10', 0, '登录成功', '2024-04-30 10:07:46', NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sys_logininfor` VALUES (175, 'admin', '127.0.0.1', '内网IP', 'Chrome 11', 'Windows 10', 0, '登录成功', '2024-04-30 10:15:45', NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sys_logininfor` VALUES (176, 'admin', '127.0.0.1', '内网IP', 'Chrome 11', 'Windows 10', 0, '登录成功', '2024-04-30 16:19:35', NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sys_logininfor` VALUES (177, 'admin', '127.0.0.1', '内网IP', 'Chrome 11', 'Windows 10', 0, '登录成功', '2024-04-30 16:19:36', NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sys_logininfor` VALUES (178, 'admin', '127.0.0.1', '内网IP', 'Chrome 11', 'Windows 10', 0, '登录成功', '2024-04-30 16:43:22', NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sys_logininfor` VALUES (179, 'admin', '127.0.0.1', '内网IP', 'Chrome 11', 'Windows 10', 0, '登录成功', '2024-04-30 16:43:23', NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sys_logininfor` VALUES (180, 'admin', '127.0.0.1', '内网IP', 'Chrome 11', 'Windows 10', 0, '登录成功', '2024-05-01 17:57:39', NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sys_logininfor` VALUES (181, 'admin', '127.0.0.1', '内网IP', 'Chrome 11', 'Windows 10', 1, '验证码错误', '2024-05-01 18:22:28', NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sys_logininfor` VALUES (182, 'admin', '127.0.0.1', '内网IP', 'Chrome 11', 'Windows 10', 0, '登录成功', '2024-05-01 18:22:32', NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sys_logininfor` VALUES (183, 'admin', '127.0.0.1', '内网IP', 'Chrome 11', 'Windows 10', 0, '登录成功', '2024-05-01 18:22:49', NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sys_logininfor` VALUES (184, 'admin', '127.0.0.1', '内网IP', 'Chrome 11', 'Windows 10', 0, '登录成功', '2024-05-01 21:16:56', NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sys_logininfor` VALUES (185, 'admin', '127.0.0.1', '内网IP', 'Chrome 11', 'Windows 10', 0, '登录成功', '2024-05-01 21:31:41', NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sys_logininfor` VALUES (186, 'admin', '127.0.0.1', '内网IP', 'Chrome 11', 'Windows 10', 0, '登录成功', '2024-05-06 09:24:12', NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sys_logininfor` VALUES (187, 'admin', '127.0.0.1', '内网IP', 'Chrome 11', 'Windows 10', 0, '登录成功', '2024-05-06 09:24:18', NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sys_logininfor` VALUES (188, 'admin', '127.0.0.1', '内网IP', 'Chrome 11', 'Windows 10', 0, '登录成功', '2024-05-06 11:33:23', NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sys_logininfor` VALUES (189, 'admin', '127.0.0.1', '内网IP', 'Chrome 11', 'Windows 10', 0, '登录成功', '2024-05-07 16:08:10', NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sys_logininfor` VALUES (190, 'admin', '127.0.0.1', '内网IP', 'Chrome 11', 'Windows 10', 0, '登录成功', '2024-05-07 16:08:16', NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sys_logininfor` VALUES (191, 'admin', '127.0.0.1', '内网IP', 'Chrome 11', 'Windows 10', 0, '登录成功', '2024-05-07 16:21:53', NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sys_logininfor` VALUES (192, 'admin', '127.0.0.1', '内网IP', 'Chrome 11', 'Windows 10', 1, '验证码已失效', '2024-05-10 08:58:11', NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sys_logininfor` VALUES (193, 'admin', '127.0.0.1', '内网IP', 'Chrome 11', 'Windows 10', 0, '登录成功', '2024-05-10 08:58:15', NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sys_logininfor` VALUES (194, 'admin', '127.0.0.1', '内网IP', 'Chrome 11', 'Windows 10', 1, '验证码错误', '2024-05-10 08:58:17', NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sys_logininfor` VALUES (195, 'admin', '127.0.0.1', '内网IP', 'Chrome 11', 'Windows 10', 0, '登录成功', '2024-05-10 08:58:20', NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sys_logininfor` VALUES (196, 'admin', '127.0.0.1', '内网IP', 'Chrome 11', 'Windows 10', 0, '登录成功', '2024-05-10 11:59:54', NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sys_logininfor` VALUES (197, 'admin', '127.0.0.1', '内网IP', 'Chrome 11', 'Windows 10', 0, '登录成功', '2024-05-10 20:53:31', NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sys_logininfor` VALUES (198, 'admin', '127.0.0.1', '内网IP', 'Chrome 11', 'Windows 10', 0, '登录成功', '2024-05-10 21:19:11', NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sys_logininfor` VALUES (199, 'admin', '127.0.0.1', '内网IP', 'Chrome 11', 'Windows 10', 0, '登录成功', '2024-05-10 21:27:04', NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sys_logininfor` VALUES (200, 'admin', '127.0.0.1', '内网IP', 'Chrome 11', 'Windows 10', 1, '验证码错误', '2024-05-10 21:27:26', NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sys_logininfor` VALUES (201, 'admin', '127.0.0.1', '内网IP', 'Chrome 11', 'Windows 10', 0, '登录成功', '2024-05-10 21:27:29', NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sys_logininfor` VALUES (202, 'admin', '127.0.0.1', '内网IP', 'Chrome 11', 'Windows 10', 0, '登录成功', '2024-05-10 21:38:06', NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sys_logininfor` VALUES (203, 'admin', '127.0.0.1', '内网IP', 'Chrome 11', 'Windows 10', 0, '登录成功', '2024-05-10 21:51:09', NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sys_logininfor` VALUES (204, 'admin', '127.0.0.1', '内网IP', 'Chrome 11', 'Windows 10', 0, '登录成功', '2024-05-10 21:51:23', NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sys_logininfor` VALUES (205, 'admin', '127.0.0.1', '内网IP', 'Chrome 11', 'Windows 10', 0, '登录成功', '2024-05-10 22:06:28', NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sys_logininfor` VALUES (206, 'admin', '127.0.0.1', '内网IP', 'Chrome 11', 'Windows 10', 0, '登录成功', '2024-05-10 22:06:41', NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sys_logininfor` VALUES (207, 'admin', '127.0.0.1', '内网IP', 'Chrome 11', 'Windows 10', 0, '登录成功', '2024-05-11 11:40:16', NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sys_logininfor` VALUES (208, 'admin', '127.0.0.1', '内网IP', 'Chrome 11', 'Windows 10', 0, '登录成功', '2024-05-11 11:44:58', NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sys_logininfor` VALUES (209, 'admin', '127.0.0.1', '内网IP', 'Chrome 11', 'Windows 10', 1, '验证码已失效', '2024-05-11 11:44:59', NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sys_logininfor` VALUES (210, 'admin', '127.0.0.1', '内网IP', 'Chrome 11', 'Windows 10', 0, '登录成功', '2024-05-11 11:45:02', NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sys_logininfor` VALUES (211, 'admin', '127.0.0.1', '内网IP', 'Chrome 11', 'Windows 10', 0, '登录成功', '2024-05-11 14:56:16', NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sys_logininfor` VALUES (212, 'admin', '127.0.0.1', '内网IP', 'Chrome 11', 'Windows 10', 1, '验证码已失效', '2024-05-11 14:56:32', NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sys_logininfor` VALUES (213, 'admin', '127.0.0.1', '内网IP', 'Chrome 11', 'Windows 10', 0, '登录成功', '2024-05-11 16:39:05', NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sys_logininfor` VALUES (214, 'admin', '127.0.0.1', '内网IP', 'Chrome 11', 'Windows 10', 0, '登录成功', '2024-05-13 14:36:40', NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sys_logininfor` VALUES (215, 'admin', '127.0.0.1', '内网IP', 'Chrome 11', 'Windows 10', 0, '登录成功', '2024-05-13 14:36:45', NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sys_logininfor` VALUES (216, 'admin', '127.0.0.1', '内网IP', 'Chrome 11', 'Windows 10', 0, '登录成功', '2024-05-13 14:36:51', NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sys_logininfor` VALUES (217, 'admin', '127.0.0.1', '内网IP', 'Chrome 11', 'Windows 10', 0, '登录成功', '2024-05-13 14:37:39', NULL, NULL, NULL, NULL, NULL);
-- ----------------------------
-- Table structure for sys_menu
-- ----------------------------
DROP TABLE IF EXISTS `sys_menu`;
CREATE TABLE `sys_menu` (
`menu_id` bigint NOT NULL AUTO_INCREMENT COMMENT '菜单ID',
`menu_name` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '菜单名称',
`parent_id` bigint NULL DEFAULT 0 COMMENT '父菜单ID',
`order_num` int NULL DEFAULT 0 COMMENT '显示顺序',
`path` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT '' COMMENT '路由地址',
`component` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '组件路径',
`query` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '路由参数',
`is_frame` int NULL DEFAULT 1 COMMENT '是否为外链(0是 1否)',
`is_cache` int NULL DEFAULT 0 COMMENT '是否缓存(0缓存 1不缓存)',
`menu_type` char(1) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT '' COMMENT '菜单类型(M目录 C菜单 F按钮)',
`visible` int NULL DEFAULT 0 COMMENT '菜单状态(0显示 1隐藏)',
`status` int NULL DEFAULT 0 COMMENT '菜单状态(0正常 1停用)',
`perms` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '权限标识',
`icon` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT '#' COMMENT '菜单图标',
`creator` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT '' COMMENT '创建者',
`create_time` datetime NULL DEFAULT NULL COMMENT '创建时间',
`updater` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT '' COMMENT '更新者',
`update_time` datetime NULL DEFAULT NULL COMMENT '更新时间',
`remark` varchar(500) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT '' COMMENT '备注',
`deleted` int NULL DEFAULT 0 COMMENT '逻辑删除',
PRIMARY KEY (`menu_id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 2024 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci COMMENT = '菜单权限表' ROW_FORMAT = DYNAMIC;
-- ----------------------------
-- Records of sys_menu
-- ----------------------------
INSERT INTO `sys_menu` VALUES (1, '系统管理', 0, 5, 'system', NULL, '', 1, 0, 'M', 0, 0, '', 'system', 'admin', '2024-02-25 16:38:43', '', '2024-03-11 17:01:53', '系统管理目录', 0);
INSERT INTO `sys_menu` VALUES (3, '系统工具', 0, 7, 'tool', NULL, '', 1, 0, 'M', 0, 0, '', 'tool', 'admin', '2024-02-25 16:38:43', '', '2024-03-11 17:02:06', '系统工具目录', 0);
INSERT INTO `sys_menu` VALUES (100, '用户管理', 1, 1, 'user', 'system/user/index', '', 1, 0, 'C', 0, 0, 'system:user:list', 'user', 'admin', '2024-02-25 16:38:43', '', NULL, '用户管理菜单', 0);
INSERT INTO `sys_menu` VALUES (101, '角色管理', 1, 2, 'role', 'system/role/index', '', 1, 0, 'C', 0, 0, 'system:role:list', 'peoples', 'admin', '2024-02-25 16:38:43', '', NULL, '角色管理菜单', 0);
INSERT INTO `sys_menu` VALUES (102, '菜单管理', 1, 3, 'menu', 'system/menu/index', '', 1, 0, 'C', 0, 0, 'system:menu:list', 'tree-table', 'admin', '2024-02-25 16:38:43', '', NULL, '菜单管理菜单', 0);
INSERT INTO `sys_menu` VALUES (103, '部门管理', 1, 4, 'dept', 'system/dept/index', '', 1, 0, 'C', 0, 0, 'system:dept:list', 'tree', 'admin', '2024-02-25 16:38:43', '', NULL, '部门管理菜单', 0);
INSERT INTO `sys_menu` VALUES (104, '岗位管理', 1, 5, 'post', 'system/post/index', '', 1, 0, 'C', 0, 0, 'system:post:list', 'post', 'admin', '2024-02-25 16:38:43', '', NULL, '岗位管理菜单', 0);
INSERT INTO `sys_menu` VALUES (105, '字典管理', 1, 6, 'dict', 'system/dict/index', '', 1, 0, 'C', 0, 0, 'system:dict:list', 'dict', 'admin', '2024-02-25 16:38:43', '', NULL, '字典管理菜单', 0);
INSERT INTO `sys_menu` VALUES (106, '参数设置', 1, 7, 'config', 'system/config/index', '', 1, 0, 'C', 0, 0, 'system:config:list', 'edit', 'admin', '2024-02-25 16:38:43', '', NULL, '参数设置菜单', 0);
INSERT INTO `sys_menu` VALUES (107, '通知公告', 1, 8, 'notice', 'system/notice/index', '', 1, 0, 'C', 0, 0, 'system:notice:list', 'message', 'admin', '2024-02-25 16:38:43', '', NULL, '通知公告菜单', 0);
INSERT INTO `sys_menu` VALUES (108, '日志管理', 1, 9, 'log', '', '', 1, 0, 'M', 0, 0, '', 'log', 'admin', '2024-02-25 16:38:43', '', NULL, '日志管理菜单', 0);
INSERT INTO `sys_menu` VALUES (116, '代码生成', 3, 2, 'gen', 'tool/gen/index', '', 1, 0, 'C', 0, 0, 'tool:gen:list', 'code', 'admin', '2024-02-25 16:38:43', '', NULL, '代码生成菜单', 0);
INSERT INTO `sys_menu` VALUES (500, '操作日志', 108, 1, 'operlog', 'monitor/operlog/index', '', 1, 0, 'C', 0, 0, 'monitor:operlog:list', 'form', 'admin', '2024-02-25 16:38:43', '', NULL, '操作日志菜单', 0);
INSERT INTO `sys_menu` VALUES (501, '登录日志', 108, 2, 'logininfor', 'monitor/logininfor/index', '', 1, 0, 'C', 0, 0, 'monitor:logininfor:list', 'logininfor', 'admin', '2024-02-25 16:38:43', '', NULL, '登录日志菜单', 0);
INSERT INTO `sys_menu` VALUES (1000, '用户查询', 100, 1, '', '', '', 1, 0, 'F', 0, 0, 'system:user:query', '#', 'admin', '2024-02-25 16:38:43', '', NULL, '', 0);
INSERT INTO `sys_menu` VALUES (1001, '用户新增', 100, 2, '', '', '', 1, 0, 'F', 0, 0, 'system:user:add', '#', 'admin', '2024-02-25 16:38:43', '', NULL, '', 0);
INSERT INTO `sys_menu` VALUES (1002, '用户修改', 100, 3, '', '', '', 1, 0, 'F', 0, 0, 'system:user:edit', '#', 'admin', '2024-02-25 16:38:43', '', NULL, '', 0);
INSERT INTO `sys_menu` VALUES (1003, '用户删除', 100, 4, '', '', '', 1, 0, 'F', 0, 0, 'system:user:remove', '#', 'admin', '2024-02-25 16:38:43', '', NULL, '', 0);
INSERT INTO `sys_menu` VALUES (1004, '用户导出', 100, 5, '', '', '', 1, 0, 'F', 0, 0, 'system:user:export', '#', 'admin', '2024-02-25 16:38:43', '', NULL, '', 0);
INSERT INTO `sys_menu` VALUES (1005, '用户导入', 100, 6, '', '', '', 1, 0, 'F', 0, 0, 'system:user:import', '#', 'admin', '2024-02-25 16:38:43', '', NULL, '', 0);
INSERT INTO `sys_menu` VALUES (1006, '重置密码', 100, 7, '', '', '', 1, 0, 'F', 0, 0, 'system:user:resetPwd', '#', 'admin', '2024-02-25 16:38:43', '', NULL, '', 0);
INSERT INTO `sys_menu` VALUES (1007, '角色查询', 101, 1, '', '', '', 1, 0, 'F', 0, 0, 'system:role:query', '#', 'admin', '2024-02-25 16:38:43', '', NULL, '', 0);
INSERT INTO `sys_menu` VALUES (1008, '角色新增', 101, 2, '', '', '', 1, 0, 'F', 0, 0, 'system:role:add', '#', 'admin', '2024-02-25 16:38:43', '', NULL, '', 0);
INSERT INTO `sys_menu` VALUES (1009, '角色修改', 101, 3, '', '', '', 1, 0, 'F', 0, 0, 'system:role:edit', '#', 'admin', '2024-02-25 16:38:43', '', NULL, '', 0);
INSERT INTO `sys_menu` VALUES (1010, '角色删除', 101, 4, '', '', '', 1, 0, 'F', 0, 0, 'system:role:remove', '#', 'admin', '2024-02-25 16:38:43', '', NULL, '', 0);
INSERT INTO `sys_menu` VALUES (1011, '角色导出', 101, 5, '', '', '', 1, 0, 'F', 0, 0, 'system:role:export', '#', 'admin', '2024-02-25 16:38:43', '', NULL, '', 0);
INSERT INTO `sys_menu` VALUES (1012, '菜单查询', 102, 1, '', '', '', 1, 0, 'F', 0, 0, 'system:menu:query', '#', 'admin', '2024-02-25 16:38:43', '', NULL, '', 0);
INSERT INTO `sys_menu` VALUES (1013, '菜单新增', 102, 2, '', '', '', 1, 0, 'F', 0, 0, 'system:menu:add', '#', 'admin', '2024-02-25 16:38:43', '', NULL, '', 0);
INSERT INTO `sys_menu` VALUES (1014, '菜单修改', 102, 3, '', '', '', 1, 0, 'F', 0, 0, 'system:menu:edit', '#', 'admin', '2024-02-25 16:38:43', '', NULL, '', 0);
INSERT INTO `sys_menu` VALUES (1015, '菜单删除', 102, 4, '', '', '', 1, 0, 'F', 0, 0, 'system:menu:remove', '#', 'admin', '2024-02-25 16:38:43', '', NULL, '', 0);
INSERT INTO `sys_menu` VALUES (1016, '部门查询', 103, 1, '', '', '', 1, 0, 'F', 0, 0, 'system:dept:query', '#', 'admin', '2024-02-25 16:38:43', '', NULL, '', 0);
INSERT INTO `sys_menu` VALUES (1017, '部门新增', 103, 2, '', '', '', 1, 0, 'F', 0, 0, 'system:dept:add', '#', 'admin', '2024-02-25 16:38:43', '', NULL, '', 0);
INSERT INTO `sys_menu` VALUES (1018, '部门修改', 103, 3, '', '', '', 1, 0, 'F', 0, 0, 'system:dept:edit', '#', 'admin', '2024-02-25 16:38:43', '', NULL, '', 0);
INSERT INTO `sys_menu` VALUES (1019, '部门删除', 103, 4, '', '', '', 1, 0, 'F', 0, 0, 'system:dept:remove', '#', 'admin', '2024-02-25 16:38:43', '', NULL, '', 0);
INSERT INTO `sys_menu` VALUES (1020, '岗位查询', 104, 1, '', '', '', 1, 0, 'F', 0, 0, 'system:post:query', '#', 'admin', '2024-02-25 16:38:43', '', NULL, '', 0);
INSERT INTO `sys_menu` VALUES (1021, '岗位新增', 104, 2, '', '', '', 1, 0, 'F', 0, 0, 'system:post:add', '#', 'admin', '2024-02-25 16:38:43', '', NULL, '', 0);
INSERT INTO `sys_menu` VALUES (1022, '岗位修改', 104, 3, '', '', '', 1, 0, 'F', 0, 0, 'system:post:edit', '#', 'admin', '2024-02-25 16:38:43', '', NULL, '', 0);
INSERT INTO `sys_menu` VALUES (1023, '岗位删除', 104, 4, '', '', '', 1, 0, 'F', 0, 0, 'system:post:remove', '#', 'admin', '2024-02-25 16:38:43', '', NULL, '', 0);
INSERT INTO `sys_menu` VALUES (1024, '岗位导出', 104, 5, '', '', '', 1, 0, 'F', 0, 0, 'system:post:export', '#', 'admin', '2024-02-25 16:38:43', '', NULL, '', 0);
INSERT INTO `sys_menu` VALUES (1025, '字典查询', 105, 1, '#', '', '', 1, 0, 'F', 0, 0, 'system:dict:query', '#', 'admin', '2024-02-25 16:38:43', '', NULL, '', 0);
INSERT INTO `sys_menu` VALUES (1026, '字典新增', 105, 2, '#', '', '', 1, 0, 'F', 0, 0, 'system:dict:add', '#', 'admin', '2024-02-25 16:38:43', '', NULL, '', 0);
INSERT INTO `sys_menu` VALUES (1027, '字典修改', 105, 3, '#', '', '', 1, 0, 'F', 0, 0, 'system:dict:edit', '#', 'admin', '2024-02-25 16:38:43', '', NULL, '', 0);
INSERT INTO `sys_menu` VALUES (1028, '字典删除', 105, 4, '#', '', '', 1, 0, 'F', 0, 0, 'system:dict:remove', '#', 'admin', '2024-02-25 16:38:43', '', NULL, '', 0);
INSERT INTO `sys_menu` VALUES (1029, '字典导出', 105, 5, '#', '', '', 1, 0, 'F', 0, 0, 'system:dict:export', '#', 'admin', '2024-02-25 16:38:43', '', NULL, '', 0);
INSERT INTO `sys_menu` VALUES (1030, '参数查询', 106, 1, '#', '', '', 1, 0, 'F', 0, 0, 'system:config:query', '#', 'admin', '2024-02-25 16:38:43', '', NULL, '', 0);
INSERT INTO `sys_menu` VALUES (1031, '参数新增', 106, 2, '#', '', '', 1, 0, 'F', 0, 0, 'system:config:add', '#', 'admin', '2024-02-25 16:38:43', '', NULL, '', 0);
INSERT INTO `sys_menu` VALUES (1032, '参数修改', 106, 3, '#', '', '', 1, 0, 'F', 0, 0, 'system:config:edit', '#', 'admin', '2024-02-25 16:38:43', '', NULL, '', 0);
INSERT INTO `sys_menu` VALUES (1033, '参数删除', 106, 4, '#', '', '', 1, 0, 'F', 0, 0, 'system:config:remove', '#', 'admin', '2024-02-25 16:38:43', '', NULL, '', 0);
INSERT INTO `sys_menu` VALUES (1034, '参数导出', 106, 5, '#', '', '', 1, 0, 'F', 0, 0, 'system:config:export', '#', 'admin', '2024-02-25 16:38:43', '', NULL, '', 0);
INSERT INTO `sys_menu` VALUES (1035, '公告查询', 107, 1, '#', '', '', 1, 0, 'F', 0, 0, 'system:notice:query', '#', 'admin', '2024-02-25 16:38:43', '', NULL, '', 0);
INSERT INTO `sys_menu` VALUES (1036, '公告新增', 107, 2, '#', '', '', 1, 0, 'F', 0, 0, 'system:notice:add', '#', 'admin', '2024-02-25 16:38:43', '', NULL, '', 0);
INSERT INTO `sys_menu` VALUES (1037, '公告修改', 107, 3, '#', '', '', 1, 0, 'F', 0, 0, 'system:notice:edit', '#', 'admin', '2024-02-25 16:38:43', '', NULL, '', 0);
INSERT INTO `sys_menu` VALUES (1038, '公告删除', 107, 4, '#', '', '', 1, 0, 'F', 0, 0, 'system:notice:remove', '#', 'admin', '2024-02-25 16:38:43', '', NULL, '', 0);
INSERT INTO `sys_menu` VALUES (1039, '操作查询', 500, 1, '#', '', '', 1, 0, 'F', 0, 0, 'monitor:operlog:query', '#', 'admin', '2024-02-25 16:38:43', '', NULL, '', 0);
INSERT INTO `sys_menu` VALUES (1040, '操作删除', 500, 2, '#', '', '', 1, 0, 'F', 0, 0, 'monitor:operlog:remove', '#', 'admin', '2024-02-25 16:38:43', '', NULL, '', 0);
INSERT INTO `sys_menu` VALUES (1041, '日志导出', 500, 3, '#', '', '', 1, 0, 'F', 0, 0, 'monitor:operlog:export', '#', 'admin', '2024-02-25 16:38:43', '', NULL, '', 0);
INSERT INTO `sys_menu` VALUES (1042, '登录查询', 501, 1, '#', '', '', 1, 0, 'F', 0, 0, 'monitor:logininfor:query', '#', 'admin', '2024-02-25 16:38:43', '', NULL, '', 0);
INSERT INTO `sys_menu` VALUES (1043, '登录删除', 501, 2, '#', '', '', 1, 0, 'F', 0, 0, 'monitor:logininfor:remove', '#', 'admin', '2024-02-25 16:38:43', '', NULL, '', 0);
INSERT INTO `sys_menu` VALUES (1044, '日志导出', 501, 3, '#', '', '', 1, 0, 'F', 0, 0, 'monitor:logininfor:export', '#', 'admin', '2024-02-25 16:38:43', '', NULL, '', 0);
INSERT INTO `sys_menu` VALUES (1045, '账户解锁', 501, 4, '#', '', '', 1, 0, 'F', 0, 0, 'monitor:logininfor:unlock', '#', 'admin', '2024-02-25 16:38:43', '', NULL, '', 0);
INSERT INTO `sys_menu` VALUES (1055, '生成查询', 116, 1, '#', '', '', 1, 0, 'F', 0, 0, 'tool:gen:query', '#', 'admin', '2024-02-25 16:38:43', '', NULL, '', 0);
INSERT INTO `sys_menu` VALUES (1056, '生成修改', 116, 2, '#', '', '', 1, 0, 'F', 0, 0, 'tool:gen:edit', '#', 'admin', '2024-02-25 16:38:43', '', NULL, '', 0);
INSERT INTO `sys_menu` VALUES (1057, '生成删除', 116, 3, '#', '', '', 1, 0, 'F', 0, 0, 'tool:gen:remove', '#', 'admin', '2024-02-25 16:38:43', '', NULL, '', 0);
INSERT INTO `sys_menu` VALUES (1058, '导入代码', 116, 4, '#', '', '', 1, 0, 'F', 0, 0, 'tool:gen:import', '#', 'admin', '2024-02-25 16:38:43', '', NULL, '', 0);
INSERT INTO `sys_menu` VALUES (1059, '预览代码', 116, 5, '#', '', '', 1, 0, 'F', 0, 0, 'tool:gen:preview', '#', 'admin', '2024-02-25 16:38:43', '', NULL, '', 0);
INSERT INTO `sys_menu` VALUES (1060, '生成代码', 116, 6, '#', '', '', 1, 0, 'F', 0, 0, 'tool:gen:code', '#', 'admin', '2024-02-25 16:38:43', '', NULL, '', 0);
INSERT INTO `sys_menu` VALUES (2014, '文章管理', 0, 0, 'article', NULL, NULL, 1, 0, 'M', 0, 0, NULL, 'documentation', '', '2024-04-29 14:30:37', '', NULL, '', 0);
INSERT INTO `sys_menu` VALUES (2015, '文章分类', 2014, 2, 'articleCategory', 'ams/category/index', NULL, 1, 0, 'C', 0, 0, 'ams:category:list', 'cascader', '', '2024-04-29 14:32:51', '', NULL, '', 0);
INSERT INTO `sys_menu` VALUES (2016, '文章标签', 2014, 3, 'articleTag', 'ams/tag/index', NULL, 1, 0, 'C', 0, 0, 'ams:tag:list', 'drag', '', '2024-04-29 14:33:55', '', NULL, '', 0);
INSERT INTO `sys_menu` VALUES (2017, '文章列表', 2014, 0, 'amsArticle', 'ams/article/index', NULL, 1, 0, 'C', 0, 0, 'ams:article:list', 'button', '', '2024-04-29 14:35:15', '', NULL, '', 0);
INSERT INTO `sys_menu` VALUES (2018, '编写文章', 2014, 1, 'amsEdit', 'ams/edit/index', NULL, 1, 0, 'C', 0, 0, 'ams:edit:list', 'edit', '', '2024-04-29 14:36:27', '', NULL, '', 0);
INSERT INTO `sys_menu` VALUES (2019, '运营设置', 0, 4, 'operate', NULL, NULL, 1, 0, 'M', 0, 0, NULL, 'education', '', '2024-05-07 16:10:27', '', NULL, '', 0);
INSERT INTO `sys_menu` VALUES (2020, '支持一下', 2019, 0, 'operateSupport', 'operate/support/index', NULL, 1, 0, 'C', 0, 0, 'operate:support:list', 'clipboard', '', '2024-05-07 16:13:38', '', NULL, '', 0);
INSERT INTO `sys_menu` VALUES (2021, '外链管理', 0, 3, 'link', NULL, NULL, 1, 0, 'M', 0, 0, NULL, 'international', '', '2024-05-10 09:05:06', '', NULL, '', 0);
INSERT INTO `sys_menu` VALUES (2022, '搜索引擎', 2021, 0, 'linkSearch', 'link/search/index', NULL, 1, 0, 'C', 0, 0, 'link:search:list', 'checkbox', '', '2024-05-10 09:06:16', '', NULL, '', 0);
INSERT INTO `sys_menu` VALUES (2023, '便捷网站', 2021, 1, 'linkWeb', 'link/web/index', NULL, 1, 0, 'C', 0, 0, 'link:web:list', 'color', '', '2024-05-10 09:07:06', '', NULL, '', 0);
-- ----------------------------
-- Table structure for sys_notice
-- ----------------------------
DROP TABLE IF EXISTS `sys_notice`;
CREATE TABLE `sys_notice` (
`notice_id` int NOT NULL AUTO_INCREMENT COMMENT '公告ID',
`notice_title` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '公告标题',
`notice_type` char(1) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '公告类型(1通知 2公告)',
`notice_content` longblob NULL COMMENT '公告内容',
`status` int NULL DEFAULT 0 COMMENT '公告状态(0正常 1关闭)',
`creator` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT '' COMMENT '创建者',
`create_time` datetime NULL DEFAULT NULL COMMENT '创建时间',
`updater` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT '' COMMENT '更新者',
`update_time` datetime NULL DEFAULT NULL COMMENT '更新时间',
`remark` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '备注',
PRIMARY KEY (`notice_id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 11 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci COMMENT = '通知公告表' ROW_FORMAT = DYNAMIC;
-- ----------------------------
-- Records of sys_notice
-- ----------------------------
INSERT INTO `sys_notice` VALUES (1, '温馨提醒', '2', 0x3C703EE696B0E78988E69CACE58685E5AEB93C2F703E, 0, 'admin', '2024-02-25 16:38:43', '', '2024-03-20 11:04:16', '管理员');
INSERT INTO `sys_notice` VALUES (2, '维护通', '1', 0x3C703EE7BBB4E68AA4E58685E5AEB93C2F703E, 0, 'admin', '2024-02-25 16:38:43', '', '2024-03-20 11:04:22', '管理员');
-- ----------------------------
-- Table structure for sys_oper_log
-- ----------------------------
DROP TABLE IF EXISTS `sys_oper_log`;
CREATE TABLE `sys_oper_log` (
`oper_id` bigint NOT NULL AUTO_INCREMENT COMMENT '日志主键',
`title` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT '' COMMENT '模块标题',
`business_type` int NULL DEFAULT 0 COMMENT '业务类型(0其它 1新增 2修改 3删除)',
`method` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT '' COMMENT '方法名称',
`request_method` varchar(10) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT '' COMMENT '请求方式',
`operator_type` int NULL DEFAULT 0 COMMENT '操作类别(0其它 1后台用户 2手机端用户)',
`oper_name` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT '' COMMENT '操作人员',
`dept_name` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT '' COMMENT '部门名称',
`oper_url` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT '' COMMENT '请求URL',
`oper_ip` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT '' COMMENT '主机地址',
`oper_location` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT '' COMMENT '操作地点',
`oper_param` varchar(2000) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT '' COMMENT '请求参数',
`json_result` varchar(2000) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT '' COMMENT '返回参数',
`status` int NULL DEFAULT 0 COMMENT '操作状态(0正常 1异常)',
`error_msg` varchar(2000) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT '' COMMENT '错误消息',
`oper_time` datetime NULL DEFAULT NULL COMMENT '操作时间',
`cost_time` bigint NULL DEFAULT 0 COMMENT '消耗时间',
`updater` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL,
`update_time` datetime NULL DEFAULT NULL,
`creator` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL,
`remark` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL,
`create_time` datetime NULL DEFAULT NULL,
PRIMARY KEY (`oper_id`) USING BTREE,
INDEX `idx_sys_oper_log_bt`(`business_type` ASC) USING BTREE,
INDEX `idx_sys_oper_log_s`(`status` ASC) USING BTREE,
INDEX `idx_sys_oper_log_ot`(`oper_time` ASC) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 250 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci COMMENT = '操作日志记录' ROW_FORMAT = DYNAMIC;
-- ----------------------------
-- Records of sys_oper_log
-- ----------------------------
INSERT INTO `sys_oper_log` VALUES (100, '菜单管理', 3, 'com.tongchen.system.controller.SysMenuController.remove()', 'DELETE', 1, 'admin', '研发部门', '/system/menu/4', '127.0.0.1', '内网IP', '{}', '{\"msg\":\"菜单已分配,不允许删除\",\"code\":601}', 0, NULL, '2024-03-11 15:43:51', 41, NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sys_oper_log` VALUES (101, '菜单管理', 1, 'com.tongchen.system.controller.SysMenuController.add()', 'POST', 1, 'admin', '研发部门', '/system/menu', '127.0.0.1', '内网IP', '{\"children\":[],\"createTime\":\"2024-03-11 15:48:59\",\"icon\":\"shopping\",\"isCache\":\"0\",\"isFrame\":\"1\",\"menuName\":\"商城管理\",\"menuType\":\"M\",\"orderNum\":4,\"params\":{},\"parentId\":0,\"path\":\"mall\",\"status\":0,\"visible\":0}', '{\"msg\":\"操作成功\",\"code\":200}', 0, NULL, '2024-03-11 15:49:00', 71, NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sys_oper_log` VALUES (102, '菜单管理', 1, 'com.tongchen.system.controller.SysMenuController.add()', 'POST', 1, 'admin', '研发部门', '/system/menu', '127.0.0.1', '内网IP', '{\"children\":[],\"component\":\"mall/product/index\",\"createTime\":\"2024-03-11 15:50:19\",\"icon\":\"phone\",\"isCache\":\"0\",\"isFrame\":\"1\",\"menuName\":\"商品管理\",\"menuType\":\"C\",\"orderNum\":0,\"params\":{},\"parentId\":2000,\"path\":\"mallProduct\",\"perms\":\"mall:product:list\",\"status\":0,\"visible\":0}', '{\"msg\":\"操作成功\",\"code\":200}', 0, NULL, '2024-03-11 15:50:20', 81, NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sys_oper_log` VALUES (103, '菜单管理', 2, 'com.tongchen.system.controller.SysMenuController.edit()', 'PUT', 1, 'admin', '研发部门', '/system/menu', '127.0.0.1', '内网IP', '{\"children\":[],\"createTime\":\"2024-03-11 15:48:59\",\"icon\":\"lock\",\"isCache\":\"0\",\"isFrame\":\"1\",\"menuId\":2000,\"menuName\":\"商品管理\",\"menuType\":\"M\",\"orderNum\":4,\"params\":{},\"parentId\":0,\"path\":\"product\",\"perms\":\"\",\"status\":0,\"visible\":0}', '{\"msg\":\"操作成功\",\"code\":200}', 0, NULL, '2024-03-11 15:56:53', 59, NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sys_oper_log` VALUES (104, '菜单管理', 2, 'com.tongchen.system.controller.SysMenuController.edit()', 'PUT', 1, 'admin', '研发部门', '/system/menu', '127.0.0.1', '内网IP', '{\"children\":[],\"component\":\"mall/product/index\",\"createTime\":\"2024-03-11 15:50:20\",\"icon\":\"phone\",\"isCache\":\"0\",\"isFrame\":\"1\",\"menuId\":2001,\"menuName\":\"商品列表\",\"menuType\":\"C\",\"orderNum\":0,\"params\":{},\"parentId\":2000,\"path\":\"mallProduct\",\"perms\":\"mall:product:list\",\"status\":0,\"visible\":0}', '{\"msg\":\"操作成功\",\"code\":200}', 0, NULL, '2024-03-11 15:57:10', 56, NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sys_oper_log` VALUES (105, '菜单管理', 2, 'com.tongchen.system.controller.SysMenuController.edit()', 'PUT', 1, 'admin', '研发部门', '/system/menu', '127.0.0.1', '内网IP', '{\"children\":[],\"component\":\"pms/product/index\",\"createTime\":\"2024-03-11 15:50:20\",\"icon\":\"phone\",\"isCache\":\"0\",\"isFrame\":\"1\",\"menuId\":2001,\"menuName\":\"商品列表\",\"menuType\":\"C\",\"orderNum\":0,\"params\":{},\"parentId\":2000,\"path\":\"pmsProduct\",\"perms\":\"pms:product:list\",\"status\":0,\"visible\":0}', '{\"msg\":\"操作成功\",\"code\":200}', 0, NULL, '2024-03-11 16:48:48', 59, NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sys_oper_log` VALUES (106, '菜单管理', 1, 'com.tongchen.system.controller.SysMenuController.add()', 'POST', 1, 'admin', '研发部门', '/system/menu', '127.0.0.1', '内网IP', '{\"children\":[],\"component\":\"pms/product/add\",\"createTime\":\"2024-03-11 16:49:24\",\"icon\":\"edit\",\"isCache\":\"0\",\"isFrame\":\"1\",\"menuName\":\"添加商品\",\"menuType\":\"C\",\"orderNum\":1,\"params\":{},\"parentId\":2000,\"path\":\"pmsAdd\",\"perms\":\"pms:product:add\",\"status\":0,\"visible\":0}', '{\"msg\":\"操作成功\",\"code\":200}', 0, NULL, '2024-03-11 16:49:25', 57, NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sys_oper_log` VALUES (107, '菜单管理', 1, 'com.tongchen.system.controller.SysMenuController.add()', 'POST', 1, 'admin', '研发部门', '/system/menu', '127.0.0.1', '内网IP', '{\"children\":[],\"component\":\"pms/productAttr/index\",\"createTime\":\"2024-03-11 16:50:35\",\"icon\":\"button\",\"isCache\":\"0\",\"isFrame\":\"1\",\"menuName\":\"商品类型\",\"menuType\":\"C\",\"orderNum\":2,\"params\":{},\"parentId\":2000,\"path\":\"productAttr\",\"perms\":\"pms:productAttr:list\",\"status\":0,\"visible\":0}', '{\"msg\":\"操作成功\",\"code\":200}', 0, NULL, '2024-03-11 16:50:36', 73, NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sys_oper_log` VALUES (108, '菜单管理', 1, 'com.tongchen.system.controller.SysMenuController.add()', 'POST', 1, 'admin', '研发部门', '/system/menu', '127.0.0.1', '内网IP', '{\"children\":[],\"createTime\":\"2024-03-11 16:51:39\",\"icon\":\"skill\",\"isCache\":\"0\",\"isFrame\":\"1\",\"menuName\":\"订单管理\",\"menuType\":\"M\",\"orderNum\":5,\"params\":{},\"parentId\":0,\"path\":\"oms\",\"status\":0,\"visible\":0}', '{\"msg\":\"操作成功\",\"code\":200}', 0, NULL, '2024-03-11 16:51:40', 55, NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sys_oper_log` VALUES (109, '菜单管理', 1, 'com.tongchen.system.controller.SysMenuController.add()', 'POST', 1, 'admin', '研发部门', '/system/menu', '127.0.0.1', '内网IP', '{\"children\":[],\"component\":\"oms/order/index\",\"createTime\":\"2024-03-11 16:53:07\",\"icon\":\"list\",\"isCache\":\"0\",\"isFrame\":\"1\",\"menuName\":\"订单列表\",\"menuType\":\"C\",\"orderNum\":0,\"params\":{},\"parentId\":2004,\"path\":\"omsOrder\",\"perms\":\"oms:order:list\",\"status\":0,\"visible\":0}', '{\"msg\":\"操作成功\",\"code\":200}', 0, NULL, '2024-03-11 16:53:08', 75, NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sys_oper_log` VALUES (110, '菜单管理', 1, 'com.tongchen.system.controller.SysMenuController.add()', 'POST', 1, 'admin', '研发部门', '/system/menu', '127.0.0.1', '内网IP', '{\"children\":[],\"component\":\"oms/order/setting\",\"createTime\":\"2024-03-11 16:58:05\",\"icon\":\"edit\",\"isCache\":\"0\",\"isFrame\":\"1\",\"menuName\":\"订单设置\",\"menuType\":\"C\",\"orderNum\":1,\"params\":{},\"parentId\":2004,\"path\":\"omsSetting\",\"perms\":\"oms:order:setting\",\"status\":0,\"visible\":0}', '{\"msg\":\"操作成功\",\"code\":200}', 0, NULL, '2024-03-11 16:58:06', 77, NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sys_oper_log` VALUES (111, '菜单管理', 1, 'com.tongchen.system.controller.SysMenuController.add()', 'POST', 1, 'admin', '研发部门', '/system/menu', '127.0.0.1', '内网IP', '{\"children\":[],\"createTime\":\"2024-03-11 16:59:31\",\"icon\":\"peoples\",\"isCache\":\"0\",\"isFrame\":\"1\",\"menuName\":\"客户管理\",\"menuType\":\"M\",\"orderNum\":0,\"params\":{},\"parentId\":0,\"path\":\"ums\",\"status\":0,\"visible\":0}', '{\"msg\":\"操作成功\",\"code\":200}', 0, NULL, '2024-03-11 16:59:32', 73, NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sys_oper_log` VALUES (112, '菜单管理', 1, 'com.tongchen.system.controller.SysMenuController.add()', 'POST', 1, 'admin', '研发部门', '/system/menu', '127.0.0.1', '内网IP', '{\"children\":[],\"component\":\"ums/member/index\",\"createTime\":\"2024-03-11 17:00:31\",\"icon\":\"list\",\"isCache\":\"0\",\"isFrame\":\"1\",\"menuName\":\"客户列表\",\"menuType\":\"C\",\"orderNum\":0,\"params\":{},\"parentId\":2007,\"path\":\"umsMember\",\"perms\":\"ums:member:list\",\"status\":0,\"visible\":0}', '{\"msg\":\"操作成功\",\"code\":200}', 0, NULL, '2024-03-11 17:00:32', 57, NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sys_oper_log` VALUES (113, '菜单管理', 1, 'com.tongchen.system.controller.SysMenuController.add()', 'POST', 1, 'admin', '研发部门', '/system/menu', '127.0.0.1', '内网IP', '{\"children\":[],\"component\":\"ums/level/index\",\"createTime\":\"2024-03-11 17:01:42\",\"icon\":\"star\",\"isCache\":\"0\",\"isFrame\":\"1\",\"menuName\":\"等级设置\",\"menuType\":\"C\",\"orderNum\":1,\"params\":{},\"parentId\":2007,\"path\":\"umsLevel\",\"perms\":\"ums:level:list\",\"status\":0,\"visible\":0}', '{\"msg\":\"操作成功\",\"code\":200}', 0, NULL, '2024-03-11 17:01:43', 80, NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sys_oper_log` VALUES (114, '菜单管理', 2, 'com.tongchen.system.controller.SysMenuController.edit()', 'PUT', 1, 'admin', '研发部门', '/system/menu', '127.0.0.1', '内网IP', '{\"children\":[],\"createTime\":\"2024-02-25 16:38:43\",\"icon\":\"system\",\"isCache\":\"0\",\"isFrame\":\"1\",\"menuId\":1,\"menuName\":\"系统管理\",\"menuType\":\"M\",\"orderNum\":5,\"params\":{},\"parentId\":0,\"path\":\"system\",\"perms\":\"\",\"query\":\"\",\"status\":0,\"visible\":0}', '{\"msg\":\"操作成功\",\"code\":200}', 0, NULL, '2024-03-11 17:01:54', 56, NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sys_oper_log` VALUES (115, '菜单管理', 2, 'com.tongchen.system.controller.SysMenuController.edit()', 'PUT', 1, 'admin', '研发部门', '/system/menu', '127.0.0.1', '内网IP', '{\"children\":[],\"createTime\":\"2024-02-25 16:38:43\",\"icon\":\"monitor\",\"isCache\":\"0\",\"isFrame\":\"1\",\"menuId\":2,\"menuName\":\"系统监控\",\"menuType\":\"M\",\"orderNum\":6,\"params\":{},\"parentId\":0,\"path\":\"monitor\",\"perms\":\"\",\"query\":\"\",\"status\":0,\"visible\":0}', '{\"msg\":\"操作成功\",\"code\":200}', 0, NULL, '2024-03-11 17:02:00', 55, NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sys_oper_log` VALUES (116, '菜单管理', 2, 'com.tongchen.system.controller.SysMenuController.edit()', 'PUT', 1, 'admin', '研发部门', '/system/menu', '127.0.0.1', '内网IP', '{\"children\":[],\"createTime\":\"2024-02-25 16:38:43\",\"icon\":\"tool\",\"isCache\":\"0\",\"isFrame\":\"1\",\"menuId\":3,\"menuName\":\"系统工具\",\"menuType\":\"M\",\"orderNum\":7,\"params\":{},\"parentId\":0,\"path\":\"tool\",\"perms\":\"\",\"query\":\"\",\"status\":0,\"visible\":0}', '{\"msg\":\"操作成功\",\"code\":200}', 0, NULL, '2024-03-11 17:02:06', 60, NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sys_oper_log` VALUES (117, '菜单管理', 2, 'com.tongchen.system.controller.SysMenuController.edit()', 'PUT', 1, 'admin', '研发部门', '/system/menu', '127.0.0.1', '内网IP', '{\"children\":[],\"createTime\":\"2024-03-11 15:48:59\",\"icon\":\"lock\",\"isCache\":\"0\",\"isFrame\":\"1\",\"menuId\":2000,\"menuName\":\"商品管理\",\"menuType\":\"M\",\"orderNum\":1,\"params\":{},\"parentId\":0,\"path\":\"product\",\"perms\":\"\",\"status\":0,\"visible\":0}', '{\"msg\":\"操作成功\",\"code\":200}', 0, NULL, '2024-03-11 17:02:15', 55, NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sys_oper_log` VALUES (118, '菜单管理', 2, 'com.tongchen.system.controller.SysMenuController.edit()', 'PUT', 1, 'admin', '研发部门', '/system/menu', '127.0.0.1', '内网IP', '{\"children\":[],\"createTime\":\"2024-03-11 16:51:40\",\"icon\":\"skill\",\"isCache\":\"0\",\"isFrame\":\"1\",\"menuId\":2004,\"menuName\":\"订单管理\",\"menuType\":\"M\",\"orderNum\":2,\"params\":{},\"parentId\":0,\"path\":\"oms\",\"perms\":\"\",\"status\":0,\"visible\":0}', '{\"msg\":\"操作成功\",\"code\":200}', 0, NULL, '2024-03-11 17:02:21', 54, NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sys_oper_log` VALUES (119, '菜单管理', 1, 'com.tongchen.system.controller.SysMenuController.add()', 'POST', 1, 'admin', '研发部门', '/system/menu', '127.0.0.1', '内网IP', '{\"children\":[],\"component\":\"bms/company/index\",\"createTime\":\"2024-03-11 17:04:01\",\"icon\":\"tree\",\"isCache\":\"0\",\"isFrame\":\"1\",\"menuName\":\"公司管理\",\"menuType\":\"M\",\"orderNum\":3,\"params\":{},\"parentId\":0,\"path\":\"bms\",\"perms\":\"bms:company:list\",\"status\":0,\"visible\":0}', '{\"msg\":\"操作成功\",\"code\":200}', 0, NULL, '2024-03-11 17:04:02', 72, NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sys_oper_log` VALUES (120, '菜单管理', 2, 'com.tongchen.system.controller.SysMenuController.edit()', 'PUT', 1, 'admin', '研发部门', '/system/menu', '127.0.0.1', '内网IP', '{\"children\":[],\"component\":\"\",\"createTime\":\"2024-03-11 17:04:02\",\"icon\":\"tree\",\"isCache\":\"0\",\"isFrame\":\"1\",\"menuId\":2010,\"menuName\":\"公司管理\",\"menuType\":\"M\",\"orderNum\":3,\"params\":{},\"parentId\":0,\"path\":\"bms\",\"perms\":\"\",\"status\":0,\"visible\":0}', '{\"msg\":\"操作成功\",\"code\":200}', 0, NULL, '2024-03-11 17:04:16', 56, NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sys_oper_log` VALUES (121, '菜单管理', 1, 'com.tongchen.system.controller.SysMenuController.add()', 'POST', 1, 'admin', '研发部门', '/system/menu', '127.0.0.1', '内网IP', '{\"children\":[],\"component\":\"bms/company/index\",\"createTime\":\"2024-03-11 17:05:37\",\"icon\":\"list\",\"isCache\":\"0\",\"isFrame\":\"1\",\"menuName\":\"公司列表\",\"menuType\":\"C\",\"orderNum\":0,\"params\":{},\"parentId\":2010,\"path\":\"bmsCompany\",\"perms\":\"bms:company:list\",\"status\":0,\"visible\":0}', '{\"msg\":\"操作成功\",\"code\":200}', 0, NULL, '2024-03-11 17:05:38', 74, NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sys_oper_log` VALUES (122, '菜单管理', 1, 'com.tongchen.system.controller.SysMenuController.add()', 'POST', 1, 'admin', '研发部门', '/system/menu', '127.0.0.1', '内网IP', '{\"children\":[],\"component\":\"pms/brand/index\",\"createTime\":\"2024-03-12 16:04:03\",\"icon\":\"table\",\"isCache\":\"0\",\"isFrame\":\"1\",\"menuName\":\"品牌管理\",\"menuType\":\"C\",\"orderNum\":3,\"params\":{},\"parentId\":2000,\"path\":\"pmsBrand\",\"perms\":\"pms:brand:list\",\"status\":0,\"visible\":0}', '{\"msg\":\"操作成功\",\"code\":200}', 0, NULL, '2024-03-12 16:04:04', 70, NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sys_oper_log` VALUES (123, '菜单管理', 2, 'com.tongchen.system.controller.SysMenuController.edit()', 'PUT', 1, 'admin', '研发部门', '/system/menu', '127.0.0.1', '内网IP', '{\"children\":[],\"component\":\"pms/productCategory/index\",\"createTime\":\"2024-03-11 16:50:36\",\"icon\":\"button\",\"isCache\":\"0\",\"isFrame\":\"1\",\"menuId\":2003,\"menuName\":\"商品分类\",\"menuType\":\"C\",\"orderNum\":2,\"params\":{},\"parentId\":2000,\"path\":\"productCategory\",\"perms\":\"pms:productCategory:list\",\"status\":0,\"visible\":0}', '{\"msg\":\"操作成功\",\"code\":200}', 0, NULL, '2024-03-14 15:26:48', 74, NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sys_oper_log` VALUES (124, '菜单管理', 1, 'com.tongchen.system.controller.SysMenuController.add()', 'POST', 1, 'admin', '研发部门', '/system/menu', '127.0.0.1', '内网IP', '{\"children\":[],\"component\":\"pms/product/update\",\"createTime\":\"2024-03-18 15:54:00\",\"icon\":\"edit\",\"isCache\":\"0\",\"isFrame\":\"1\",\"menuName\":\"修改商品\",\"menuType\":\"C\",\"orderNum\":4,\"params\":{},\"parentId\":2000,\"path\":\"pmsUpdate\",\"perms\":\"pms:product:update\",\"status\":0,\"visible\":1}', '{\"msg\":\"操作成功\",\"code\":200}', 0, NULL, '2024-03-18 15:53:59', 73, NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sys_oper_log` VALUES (125, '用户管理', 2, 'com.xianying.system.controller.SysUserController.changeStatus()', 'PUT', 1, 'admin', '研发部门', '/system/user/changeStatus', '127.0.0.1', '内网IP', '{\"admin\":true,\"params\":{},\"status\":1,\"userId\":1}', NULL, 1, '不允许操作超级管理员用户', '2024-03-19 15:39:22', 8, NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sys_oper_log` VALUES (126, '用户管理', 2, 'com.xianying.system.controller.SysUserController.changeStatus()', 'PUT', 1, 'admin', '研发部门', '/system/user/changeStatus', '127.0.0.1', '内网IP', '{\"admin\":false,\"params\":{},\"status\":1,\"userId\":2}', '{\"msg\":\"操作成功\",\"code\":200}', 0, NULL, '2024-03-19 15:39:29', 39, NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sys_oper_log` VALUES (127, '用户管理', 2, 'com.xianying.system.controller.SysUserController.changeStatus()', 'PUT', 1, 'admin', '研发部门', '/system/user/changeStatus', '127.0.0.1', '内网IP', '{\"admin\":false,\"params\":{},\"status\":0,\"userId\":2}', '{\"msg\":\"操作成功\",\"code\":200}', 0, NULL, '2024-03-19 15:39:31', 37, NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sys_oper_log` VALUES (128, '用户管理', 2, 'com.xianying.system.controller.SysUserController.changeStatus()', 'PUT', 1, 'admin', '研发部门', '/system/user/changeStatus', '127.0.0.1', '内网IP', '{\"admin\":false,\"params\":{},\"status\":0,\"userId\":2}', '{\"msg\":\"操作成功\",\"code\":200}', 0, NULL, '2024-03-19 15:42:33', 39, NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sys_oper_log` VALUES (129, '用户管理', 2, 'com.xianying.system.controller.SysUserController.changeStatus()', 'PUT', 1, 'admin', '研发部门', '/system/user/changeStatus', '127.0.0.1', '内网IP', '{\"admin\":false,\"params\":{},\"status\":0,\"userId\":2}', '{\"msg\":\"操作成功\",\"code\":200}', 0, NULL, '2024-03-19 15:42:47', 37, NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sys_oper_log` VALUES (130, '用户管理', 2, 'com.xianying.system.controller.SysUserController.changeStatus()', 'PUT', 1, 'admin', '研发部门', '/system/user/changeStatus', '127.0.0.1', '内网IP', '{\"admin\":false,\"params\":{},\"status\":1,\"userId\":2}', '{\"msg\":\"操作成功\",\"code\":200}', 0, NULL, '2024-03-19 15:43:53', 36, NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sys_oper_log` VALUES (131, '用户管理', 2, 'com.xianying.system.controller.SysUserController.changeStatus()', 'PUT', 1, 'admin', '研发部门', '/system/user/changeStatus', '127.0.0.1', '内网IP', '{\"admin\":false,\"params\":{},\"status\":0,\"userId\":2}', '{\"msg\":\"操作成功\",\"code\":200}', 0, NULL, '2024-03-19 15:43:59', 37, NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sys_oper_log` VALUES (132, '用户管理', 2, 'com.xianying.system.controller.SysUserController.changeStatus()', 'PUT', 1, 'admin', '研发部门', '/system/user/changeStatus', '127.0.0.1', '内网IP', '{\"admin\":false,\"params\":{},\"status\":0,\"userId\":2}', '{\"msg\":\"操作成功\",\"code\":200}', 0, NULL, '2024-03-19 15:44:31', 38, NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sys_oper_log` VALUES (133, '用户管理', 2, 'com.xianying.system.controller.SysUserController.changeStatus()', 'PUT', 1, 'admin', '研发部门', '/system/user/changeStatus', '127.0.0.1', '内网IP', '{\"admin\":false,\"params\":{},\"status\":0,\"userId\":2}', '{\"msg\":\"操作成功\",\"code\":200}', 0, NULL, '2024-03-19 15:44:55', 36, NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sys_oper_log` VALUES (134, '用户管理', 2, 'com.xianying.system.controller.SysUserController.changeStatus()', 'PUT', 1, 'admin', '研发部门', '/system/user/changeStatus', '127.0.0.1', '内网IP', '{\"admin\":false,\"params\":{},\"status\":0,\"userId\":2}', '{\"msg\":\"操作成功\",\"code\":200}', 0, NULL, '2024-03-19 15:45:21', 38, NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sys_oper_log` VALUES (135, '用户管理', 2, 'com.xianying.system.controller.SysUserController.changeStatus()', 'PUT', 1, 'admin', '研发部门', '/system/user/changeStatus', '127.0.0.1', '内网IP', '{\"admin\":false,\"params\":{},\"status\":0,\"userId\":2}', '{\"msg\":\"操作成功\",\"code\":200}', 0, NULL, '2024-03-19 15:47:25', 39, NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sys_oper_log` VALUES (136, '用户管理', 2, 'com.xianying.system.controller.SysUserController.changeStatus()', 'PUT', 1, 'admin', '研发部门', '/system/user/changeStatus', '127.0.0.1', '内网IP', '{\"admin\":false,\"status\":0,\"userId\":2}', '{\"msg\":\"操作成功\",\"code\":200}', 0, NULL, '2024-03-19 16:05:04', 89, NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sys_oper_log` VALUES (137, '用户管理', 2, 'com.xianying.system.controller.SysUserController.edit()', 'PUT', 1, 'admin', '研发部门', '/system/user', '127.0.0.1', '内网IP', '{\"admin\":false,\"avatar\":\"\",\"dept\":{\"ancestors\":\"0,100,101\",\"children\":[],\"deptId\":105,\"deptName\":\"测试部门\",\"leader\":\"若依\",\"orderNum\":3,\"params\":{},\"parentId\":101,\"status\":0},\"deptId\":105,\"email\":\"ry@qq.com\",\"mobile\":\"15666666666\",\"nickname\":\"若依\",\"postIds\":[3],\"roleIds\":[2],\"roles\":[{\"admin\":false,\"dataScope\":\"2\",\"deptCheckStrictly\":false,\"flag\":false,\"menuCheckStrictly\":false,\"params\":{},\"roleId\":2,\"roleKey\":\"common\",\"roleName\":\"普通角色\",\"roleSort\":2,\"status\":0}],\"sex\":1,\"status\":0,\"userId\":2,\"username\":\"ry\"}', '{\"msg\":\"操作成功\",\"code\":200}', 0, NULL, '2024-03-19 16:09:22', 422, NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sys_oper_log` VALUES (138, '用户管理', 2, 'com.xianying.system.controller.SysUserController.edit()', 'PUT', 1, 'admin', '研发部门', '/system/user', '127.0.0.1', '内网IP', '{\"admin\":false,\"avatar\":\"\",\"dept\":{\"ancestors\":\"0,100,101\",\"children\":[],\"deptId\":105,\"deptName\":\"测试部门\",\"leader\":\"若依\",\"orderNum\":3,\"params\":{},\"parentId\":101,\"status\":0},\"deptId\":105,\"email\":\"ry@qq.com\",\"mobile\":\"15666666666\",\"nickname\":\"若依\",\"postIds\":[3],\"roleIds\":[2],\"roles\":[{\"admin\":false,\"dataScope\":\"2\",\"deptCheckStrictly\":false,\"flag\":false,\"menuCheckStrictly\":false,\"params\":{},\"roleId\":2,\"roleKey\":\"common\",\"roleName\":\"普通角色\",\"roleSort\":2,\"status\":0}],\"sex\":1,\"status\":0,\"userId\":2,\"username\":\"ry\"}', '{\"msg\":\"操作成功\",\"code\":200}', 0, NULL, '2024-03-19 16:09:44', 317, NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sys_oper_log` VALUES (139, '用户管理', 2, 'com.xianying.system.controller.SysUserController.edit()', 'PUT', 1, 'admin', '研发部门', '/system/user', '127.0.0.1', '内网IP', '{\"admin\":false,\"avatar\":\"\",\"dept\":{\"ancestors\":\"0,100,101\",\"children\":[],\"deptId\":105,\"deptName\":\"测试部门\",\"leader\":\"若依\",\"orderNum\":3,\"params\":{},\"parentId\":101,\"status\":0},\"deptId\":105,\"email\":\"rysadasd@qq.com\",\"mobile\":\"16623254658\",\"nickname\":\"若依123456\",\"postIds\":[3],\"roleIds\":[2],\"roles\":[{\"admin\":false,\"dataScope\":\"2\",\"deptCheckStrictly\":false,\"flag\":false,\"menuCheckStrictly\":false,\"params\":{},\"roleId\":2,\"roleKey\":\"common\",\"roleName\":\"普通角色\",\"roleSort\":2,\"status\":0}],\"sex\":0,\"status\":0,\"userId\":2,\"username\":\"ry\"}', '{\"msg\":\"操作成功\",\"code\":200}', 0, NULL, '2024-03-19 16:11:26', 434, NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sys_oper_log` VALUES (140, '用户管理', 2, 'com.xianying.system.controller.SysUserController.edit()', 'PUT', 1, 'admin', '研发部门', '/system/user', '127.0.0.1', '内网IP', '{\"admin\":false,\"avatar\":\"\",\"dept\":{\"ancestors\":\"0,100,101\",\"children\":[],\"deptId\":105,\"deptName\":\"测试部门\",\"leader\":\"若依\",\"orderNum\":3,\"params\":{},\"parentId\":101,\"status\":0},\"deptId\":105,\"email\":\"xx@qq.com\",\"mobile\":\"16623254658\",\"nickname\":\"小贤\",\"postIds\":[3],\"remark\":\"测试员123\",\"roleIds\":[2],\"roles\":[{\"admin\":false,\"dataScope\":\"2\",\"deptCheckStrictly\":false,\"flag\":false,\"menuCheckStrictly\":false,\"params\":{},\"roleId\":2,\"roleKey\":\"common\",\"roleName\":\"普通角色\",\"roleSort\":2,\"status\":0}],\"sex\":0,\"status\":0,\"userId\":2,\"username\":\"ry\"}', '{\"msg\":\"操作成功\",\"code\":200}', 0, NULL, '2024-03-19 16:12:31', 396, NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sys_oper_log` VALUES (141, '用户管理', 1, 'com.xianying.system.controller.SysUserController.add()', 'POST', 1, 'admin', '研发部门', '/system/user', '127.0.0.1', '内网IP', '{\"admin\":false,\"deptId\":103,\"email\":\"123@qq.com\",\"mobile\":\"16653565847\",\"nickname\":\"孟怀\",\"postIds\":[1],\"remark\":\"123456\",\"roleIds\":[2],\"sex\":0,\"status\":0,\"username\":\"menghuai\"}', NULL, 1, '\r\n### Error updating database. Cause: java.sql.SQLIntegrityConstraintViolationException: Column \'user_id\' cannot be null\r\n### The error may exist in file [D:\\00-code\\02-self\\xianying\\xianying-module-system\\target\\classes\\mapper\\system\\SysUserPostMapper.xml]\r\n### The error may involve defaultParameterMap\r\n### The error occurred while setting parameters\r\n### SQL: insert into sys_user_post(user_id, post_id) values (?,?)\r\n### Cause: java.sql.SQLIntegrityConstraintViolationException: Column \'user_id\' cannot be null\n; Column \'user_id\' cannot be null', '2024-03-19 16:14:24', 363, NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sys_oper_log` VALUES (142, '用户管理', 1, 'com.xianying.system.controller.SysUserController.add()', 'POST', 1, 'admin', '研发部门', '/system/user', '127.0.0.1', '内网IP', '{\"admin\":false,\"deptId\":103,\"email\":\"123@qq.com\",\"mobile\":\"16653565847\",\"nickname\":\"孟怀\",\"postIds\":[1],\"remark\":\"123456\",\"roleIds\":[2],\"sex\":0,\"status\":0,\"userId\":101,\"username\":\"menghuai\"}', '{\"msg\":\"操作成功\",\"code\":200}', 0, NULL, '2024-03-19 16:17:13', 391, NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sys_oper_log` VALUES (143, '角色管理', 2, 'com.xianying.system.controller.SysRoleController.changeStatus()', 'PUT', 1, 'admin', '研发部门', '/system/role/changeStatus', '127.0.0.1', '内网IP', '{\"admin\":true,\"deptCheckStrictly\":false,\"flag\":false,\"menuCheckStrictly\":false,\"params\":{},\"roleId\":1,\"status\":1}', NULL, 1, '不允许操作超级管理员角色', '2024-03-19 16:23:23', 8, NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sys_oper_log` VALUES (144, '角色管理', 2, 'com.xianying.system.controller.SysRoleController.changeStatus()', 'PUT', 1, 'admin', '研发部门', '/system/role/changeStatus', '127.0.0.1', '内网IP', '{\"admin\":false,\"deptCheckStrictly\":false,\"flag\":false,\"menuCheckStrictly\":false,\"params\":{},\"roleId\":2,\"status\":1}', '{\"msg\":\"操作成功\",\"code\":200}', 0, NULL, '2024-03-19 16:23:29', 45, NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sys_oper_log` VALUES (145, '角色管理', 2, 'com.xianying.system.controller.SysRoleController.changeStatus()', 'PUT', 1, 'admin', '研发部门', '/system/role/changeStatus', '127.0.0.1', '内网IP', '{\"admin\":false,\"deptCheckStrictly\":false,\"flag\":false,\"menuCheckStrictly\":false,\"params\":{},\"roleId\":2,\"status\":0}', '{\"msg\":\"操作成功\",\"code\":200}', 0, NULL, '2024-03-19 16:23:34', 42, NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sys_oper_log` VALUES (146, '角色管理', 2, 'com.xianying.system.controller.SysRoleController.changeStatus()', 'PUT', 1, 'admin', '研发部门', '/system/role/changeStatus', '127.0.0.1', '内网IP', '{\"admin\":false,\"deptCheckStrictly\":false,\"flag\":false,\"menuCheckStrictly\":false,\"params\":{},\"roleId\":2,\"status\":0}', '{\"msg\":\"操作成功\",\"code\":200}', 0, NULL, '2024-03-19 16:24:59', 40, NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sys_oper_log` VALUES (147, '角色管理', 2, 'com.xianying.system.controller.SysRoleController.changeStatus()', 'PUT', 1, 'admin', '研发部门', '/system/role/changeStatus', '127.0.0.1', '内网IP', '{\"admin\":false,\"deptCheckStrictly\":false,\"menuCheckStrictly\":false,\"roleId\":2,\"status\":0}', '{\"msg\":\"操作成功\",\"code\":200}', 0, NULL, '2024-03-19 17:24:22', 52, NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sys_oper_log` VALUES (148, '部门管理', 2, 'com.xianying.system.controller.SysDeptController.edit()', 'PUT', 1, 'admin', '研发部门', '/system/dept', '127.0.0.1', '内网IP', '{\"ancestors\":\"0\",\"children\":[],\"deptId\":100,\"deptName\":\"闲影科技\",\"email\":\"xy@qq.com\",\"leader\":\"闲影\",\"mobile\":\"15888888888\",\"orderNum\":0,\"params\":{},\"parentId\":0,\"status\":0}', '{\"msg\":\"操作成功\",\"code\":200}', 0, NULL, '2024-03-19 17:26:44', 111, NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sys_oper_log` VALUES (149, '部门管理', 2, 'com.xianying.system.controller.SysDeptController.edit()', 'PUT', 1, 'admin', '研发部门', '/system/dept', '127.0.0.1', '内网IP', '{\"ancestors\":\"0,100\",\"children\":[],\"deptId\":102,\"deptName\":\"郑州分公司\",\"email\":\"xy@qq.com\",\"leader\":\"闲影\",\"mobile\":\"15888888888\",\"orderNum\":2,\"params\":{},\"parentId\":100,\"parentName\":\"闲影科技\",\"status\":0}', '{\"msg\":\"操作成功\",\"code\":200}', 0, NULL, '2024-03-19 17:27:08', 194, NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sys_oper_log` VALUES (150, '部门管理', 2, 'com.xianying.system.controller.SysDeptController.edit()', 'PUT', 1, 'admin', '研发部门', '/system/dept', '127.0.0.1', '内网IP', '{\"ancestors\":\"0,100\",\"children\":[],\"deptId\":101,\"deptName\":\"深圳总公司\",\"email\":\"xy@qq.com\",\"leader\":\"闲影\",\"mobile\":\"15888888888\",\"orderNum\":1,\"params\":{},\"parentId\":100,\"parentName\":\"闲影科技\",\"status\":0}', '{\"msg\":\"操作成功\",\"code\":200}', 0, NULL, '2024-03-19 17:27:19', 194, NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sys_oper_log` VALUES (151, '部门管理', 2, 'com.xianying.system.controller.SysDeptController.edit()', 'PUT', 1, 'admin', '研发部门', '/system/dept', '127.0.0.1', '内网IP', '{\"ancestors\":\"0,100,101\",\"children\":[],\"deptId\":103,\"deptName\":\"研发部门\",\"email\":\"xy@qq.com\",\"leader\":\"闲影\",\"mobile\":\"15888888888\",\"orderNum\":1,\"params\":{},\"parentId\":101,\"parentName\":\"深圳总公司\",\"status\":0}', '{\"msg\":\"操作成功\",\"code\":200}', 0, NULL, '2024-03-19 17:27:55', 171, NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sys_oper_log` VALUES (152, '部门管理', 2, 'com.xianying.system.controller.SysDeptController.edit()', 'PUT', 1, 'admin', '研发部门', '/system/dept', '127.0.0.1', '内网IP', '{\"ancestors\":\"0,100,101\",\"children\":[],\"deptId\":104,\"deptName\":\"市场部门\",\"email\":\"xy@qq.com\",\"leader\":\"闲影\",\"mobile\":\"15888888888\",\"orderNum\":2,\"params\":{},\"parentId\":101,\"parentName\":\"深圳总公司\",\"status\":0}', '{\"msg\":\"操作成功\",\"code\":200}', 0, NULL, '2024-03-19 17:28:05', 175, NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sys_oper_log` VALUES (153, '部门管理', 2, 'com.xianying.system.controller.SysDeptController.edit()', 'PUT', 1, 'admin', '研发部门', '/system/dept', '127.0.0.1', '内网IP', '{\"ancestors\":\"0,100,101\",\"children\":[],\"deptId\":105,\"deptName\":\"测试部门\",\"email\":\"xy@qq.com\",\"leader\":\"闲影\",\"mobile\":\"15888888888\",\"orderNum\":3,\"params\":{},\"parentId\":101,\"parentName\":\"深圳总公司\",\"status\":0}', '{\"msg\":\"操作成功\",\"code\":200}', 0, NULL, '2024-03-19 17:28:13', 168, NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sys_oper_log` VALUES (154, '部门管理', 2, 'com.xianying.system.controller.SysDeptController.edit()', 'PUT', 1, 'admin', '研发部门', '/system/dept', '127.0.0.1', '内网IP', '{\"ancestors\":\"0,100,101\",\"children\":[],\"deptId\":106,\"deptName\":\"财务部门\",\"email\":\"xy@qq.com\",\"leader\":\"闲影\",\"mobile\":\"15888888888\",\"orderNum\":4,\"params\":{},\"parentId\":101,\"parentName\":\"深圳总公司\",\"status\":0}', '{\"msg\":\"操作成功\",\"code\":200}', 0, NULL, '2024-03-19 17:28:22', 160, NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sys_oper_log` VALUES (155, '部门管理', 2, 'com.xianying.system.controller.SysDeptController.edit()', 'PUT', 1, 'admin', '研发部门', '/system/dept', '127.0.0.1', '内网IP', '{\"ancestors\":\"0,100,101\",\"children\":[],\"deptId\":107,\"deptName\":\"运维部门\",\"email\":\"xy@qq.com\",\"leader\":\"闲影\",\"mobile\":\"15888888888\",\"orderNum\":5,\"params\":{},\"parentId\":101,\"parentName\":\"深圳总公司\",\"status\":0}', '{\"msg\":\"操作成功\",\"code\":200}', 0, NULL, '2024-03-19 17:28:30', 165, NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sys_oper_log` VALUES (156, '部门管理', 2, 'com.xianying.system.controller.SysDeptController.edit()', 'PUT', 1, 'admin', '研发部门', '/system/dept', '127.0.0.1', '内网IP', '{\"ancestors\":\"0,100,102\",\"children\":[],\"deptId\":108,\"deptName\":\"市场部门\",\"email\":\"xy@qq.com\",\"leader\":\"闲影\",\"mobile\":\"15888888888\",\"orderNum\":1,\"params\":{},\"parentId\":102,\"parentName\":\"郑州分公司\",\"status\":0}', '{\"msg\":\"操作成功\",\"code\":200}', 0, NULL, '2024-03-19 17:28:38', 172, NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sys_oper_log` VALUES (157, '部门管理', 2, 'com.xianying.system.controller.SysDeptController.edit()', 'PUT', 1, 'admin', '研发部门', '/system/dept', '127.0.0.1', '内网IP', '{\"ancestors\":\"0,100,102\",\"children\":[],\"deptId\":109,\"deptName\":\"财务部门\",\"email\":\"xy@qq.com\",\"leader\":\"闲影\",\"mobile\":\"15888888888\",\"orderNum\":2,\"params\":{},\"parentId\":102,\"parentName\":\"郑州分公司\",\"status\":0}', '{\"msg\":\"操作成功\",\"code\":200}', 0, NULL, '2024-03-19 17:28:46', 169, NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sys_oper_log` VALUES (158, '部门管理', 1, 'com.xianying.system.controller.SysDeptController.add()', 'POST', 1, 'admin', '研发部门', '/system/dept', '127.0.0.1', '内网IP', '{\"ancestors\":\"0,100,102\",\"children\":[],\"createTime\":\"2024-03-19 17:31:20\",\"deptName\":\"研发部门\",\"email\":\"mh@163.com\",\"leader\":\"孟怀\",\"mobile\":\"16356524587\",\"orderNum\":3,\"params\":{},\"parentId\":102,\"status\":0}', '{\"msg\":\"操作成功\",\"code\":200}', 0, NULL, '2024-03-19 17:31:20', 106, NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sys_oper_log` VALUES (159, '部门管理', 2, 'com.xianying.system.controller.SysDeptController.edit()', 'PUT', 1, 'admin', '研发部门', '/system/dept', '127.0.0.1', '内网IP', '{\"ancestors\":\"0,100,102\",\"children\":[],\"deptId\":200,\"deptName\":\"研发部门\",\"email\":\"mh@163.com\",\"leader\":\"孟怀\",\"mobile\":\"16356524587\",\"orderNum\":3,\"params\":{},\"parentId\":102,\"parentName\":\"郑州分公司\",\"status\":1}', '{\"msg\":\"操作成功\",\"code\":200}', 0, NULL, '2024-03-19 17:31:27', 156, NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sys_oper_log` VALUES (160, '部门管理', 2, 'com.xianying.system.controller.SysDeptController.edit()', 'PUT', 1, 'admin', '研发部门', '/system/dept', '127.0.0.1', '内网IP', '{\"ancestors\":\"0,100,102\",\"children\":[],\"deptId\":200,\"deptName\":\"研发部门\",\"email\":\"mh@163.com\",\"leader\":\"孟怀\",\"mobile\":\"16356524587\",\"orderNum\":3,\"params\":{},\"parentId\":102,\"parentName\":\"郑州分公司\",\"status\":0}', '{\"msg\":\"操作成功\",\"code\":200}', 0, NULL, '2024-03-19 17:31:30', 195, NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sys_oper_log` VALUES (161, '部门管理', 2, 'com.xianying.system.controller.SysDeptController.edit()', 'PUT', 1, 'admin', '研发部门', '/system/dept', '127.0.0.1', '内网IP', '{\"ancestors\":\"0,100,102\",\"children\":[],\"deptId\":200,\"deptName\":\"研发部门\",\"email\":\"mh@163.com\",\"leader\":\"孟怀\",\"mobile\":\"16356524587\",\"orderNum\":3,\"params\":{},\"parentId\":102,\"parentName\":\"郑州分公司\",\"status\":0}', '{\"msg\":\"操作成功\",\"code\":200}', 0, NULL, '2024-03-20 09:24:18', 177, NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sys_oper_log` VALUES (162, '部门管理', 2, 'com.xianying.system.controller.SysDeptController.edit()', 'PUT', 1, 'admin', '研发部门', '/system/dept', '127.0.0.1', '内网IP', '{\"ancestors\":\"0,100,102\",\"children\":[],\"deptId\":200,\"deptName\":\"研发部门\",\"email\":\"mh@163.com\",\"leader\":\"孟怀\",\"mobile\":\"16356524587\",\"orderNum\":3,\"params\":{},\"parentId\":102,\"parentName\":\"郑州分公司\",\"status\":0}', '{\"msg\":\"操作成功\",\"code\":200}', 0, NULL, '2024-03-20 09:24:41', 171, NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sys_oper_log` VALUES (163, '部门管理', 2, 'com.xianying.system.controller.SysDeptController.edit()', 'PUT', 1, 'admin', '研发部门', '/system/dept', '127.0.0.1', '内网IP', '{\"ancestors\":\"0,100,102\",\"children\":[],\"deptId\":200,\"deptName\":\"研发部门\",\"email\":\"mh@163.com\",\"leader\":\"孟怀\",\"mobile\":\"16356524587\",\"orderNum\":3,\"params\":{},\"parentId\":102,\"parentName\":\"郑州分公司\",\"status\":0}', NULL, 1, 'Invalid bound statement (not found): com.xianying.system.mapper.SysDeptMapper.updateById', '2024-03-20 09:28:07', 96, NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sys_oper_log` VALUES (164, '部门管理', 2, 'com.xianying.system.controller.SysDeptController.edit()', 'PUT', 1, 'admin', '研发部门', '/system/dept', '127.0.0.1', '内网IP', '{\"ancestors\":\"0,100,102\",\"children\":[],\"deptId\":200,\"deptName\":\"研发部门\",\"email\":\"mh@163.com\",\"leader\":\"孟怀\",\"mobile\":\"16356524587\",\"orderNum\":3,\"params\":{},\"parentId\":102,\"parentName\":\"郑州分公司\",\"status\":0}', '{\"msg\":\"操作成功\",\"code\":200}', 0, NULL, '2024-03-20 09:29:36', 214, NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sys_oper_log` VALUES (165, '部门管理', 2, 'com.xianying.system.controller.SysDeptController.edit()', 'PUT', 1, 'admin', '研发部门', '/system/dept', '127.0.0.1', '内网IP', '{\"ancestors\":\"0,100,102\",\"children\":[],\"deptId\":200,\"deptName\":\"研发部门\",\"email\":\"mh@163.com\",\"leader\":\"孟怀\",\"mobile\":\"16356524587\",\"orderNum\":3,\"params\":{},\"parentId\":102,\"parentName\":\"郑州分公司\",\"status\":0}', '{\"msg\":\"操作成功\",\"code\":200}', 0, NULL, '2024-03-20 09:30:35', 219, NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sys_oper_log` VALUES (166, '部门管理', 3, 'com.xianying.system.controller.SysDeptController.remove()', 'DELETE', 1, 'admin', '研发部门', '/system/dept/107', '127.0.0.1', '内网IP', '{}', '{\"msg\":\"操作成功\",\"code\":200}', 0, NULL, '2024-03-20 09:49:21', 90, NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sys_oper_log` VALUES (167, '岗位管理', 1, 'com.xianying.system.controller.SysPostController.add()', 'POST', 1, 'admin', '研发部门', '/system/post', '127.0.0.1', '内网IP', '{\"createTime\":\"2024-03-20 09:49:45\",\"flag\":false,\"params\":{},\"postCode\":\"H5\",\"postId\":5,\"postName\":\"前端开发\",\"postSort\":5,\"status\":0}', '{\"msg\":\"操作成功\",\"code\":200}', 0, NULL, '2024-03-20 09:49:45', 85, NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sys_oper_log` VALUES (168, '岗位管理', 1, 'com.xianying.system.controller.SysPostController.add()', 'POST', 1, 'admin', '研发部门', '/system/post', '127.0.0.1', '内网IP', '{\"createTime\":\"2024-03-20 09:50:03\",\"flag\":false,\"params\":{},\"postCode\":\"J\",\"postId\":6,\"postName\":\"后端开发\",\"postSort\":0,\"status\":0}', '{\"msg\":\"操作成功\",\"code\":200}', 0, NULL, '2024-03-20 09:50:03', 83, NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sys_oper_log` VALUES (169, '字典类型', 2, 'com.xianying.system.controller.SysDictTypeController.edit()', 'PUT', 1, 'admin', '研发部门', '/system/dict/type', '127.0.0.1', '内网IP', '{\"createTime\":\"2024-02-25 16:38:43\",\"creator\":\"admin\",\"dictId\":1,\"dictName\":\"用户性别\",\"dictType\":\"sys_user_sex\",\"params\":{},\"remark\":\"用户性别列表\",\"status\":1,\"updater\":\"\"}', '{\"msg\":\"操作成功\",\"code\":200}', 0, NULL, '2024-03-20 10:19:09', 238, NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sys_oper_log` VALUES (170, '字典类型', 2, 'com.xianying.system.controller.SysDictTypeController.edit()', 'PUT', 1, 'admin', '研发部门', '/system/dict/type', '127.0.0.1', '内网IP', '{\"createTime\":\"2024-02-25 16:38:43\",\"creator\":\"admin\",\"dictId\":1,\"dictName\":\"用户性别\",\"dictType\":\"sys_user_sex\",\"params\":{},\"remark\":\"用户性别列表\",\"status\":0,\"updateTime\":\"2024-03-20 10:19:09\",\"updater\":\"\"}', '{\"msg\":\"操作成功\",\"code\":200}', 0, NULL, '2024-03-20 10:19:13', 217, NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sys_oper_log` VALUES (171, '字典类型', 1, 'com.xianying.system.controller.SysDictTypeController.add()', 'POST', 1, 'admin', '研发部门', '/system/dict/type', '127.0.0.1', '内网IP', '{\"createTime\":\"2024-03-20 10:20:05\",\"dictName\":\"测试字典\",\"dictType\":\"test_dict\",\"params\":{},\"remark\":\"测试字典123\",\"status\":0}', '{\"msg\":\"操作成功\",\"code\":200}', 0, NULL, '2024-03-20 10:20:05', 61, NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sys_oper_log` VALUES (172, '字典类型', 2, 'com.xianying.system.controller.SysDictTypeController.edit()', 'PUT', 1, 'admin', '研发部门', '/system/dict/type', '127.0.0.1', '内网IP', '{\"createTime\":\"2024-03-20 10:20:05\",\"creator\":\"\",\"dictId\":100,\"dictName\":\"测试字典\",\"dictType\":\"test_dict\",\"params\":{},\"remark\":\"测试字\",\"status\":0,\"updater\":\"\"}', '{\"msg\":\"操作成功\",\"code\":200}', 0, NULL, '2024-03-20 10:20:12', 196, NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sys_oper_log` VALUES (173, '字典类型', 3, 'com.xianying.system.controller.SysDictTypeController.remove()', 'DELETE', 1, 'admin', '研发部门', '/system/dict/type/100', '127.0.0.1', '内网IP', '{}', '{\"msg\":\"操作成功\",\"code\":200}', 0, NULL, '2024-03-20 10:20:15', 90, NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sys_oper_log` VALUES (174, '参数管理', 1, 'com.xianying.system.controller.SysConfigController.add()', 'POST', 1, 'admin', '研发部门', '/system/config', '127.0.0.1', '内网IP', '{\"configKey\":\"按时打算大萨达\",\"configName\":\"测试参数\",\"configType\":\"Y\",\"configValue\":\"按时打算大萨达\",\"createTime\":\"2024-03-20 10:46:17\",\"params\":{},\"remark\":\"大萨达大所\"}', '{\"msg\":\"操作成功\",\"code\":200}', 0, NULL, '2024-03-20 10:46:17', 74, NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sys_oper_log` VALUES (175, '参数管理', 2, 'com.xianying.system.controller.SysConfigController.edit()', 'PUT', 1, 'admin', '研发部门', '/system/config', '127.0.0.1', '内网IP', '{\"configId\":100,\"configKey\":\"按时打\",\"configName\":\"测试参\",\"configType\":\"Y\",\"configValue\":\"按\",\"createTime\":\"2024-03-20 10:46:17\",\"creator\":\"\",\"params\":{},\"remark\":\"大萨达大所\",\"updater\":\"\"}', '{\"msg\":\"操作成功\",\"code\":200}', 0, NULL, '2024-03-20 10:46:30', 86, NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sys_oper_log` VALUES (176, '参数管理', 3, 'com.xianying.system.controller.SysConfigController.remove()', 'DELETE', 1, 'admin', '研发部门', '/system/config/100', '127.0.0.1', '内网IP', '{}', NULL, 1, '内置参数【按时打】不能删除 ', '2024-03-20 10:46:32', 22, NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sys_oper_log` VALUES (177, '参数管理', 2, 'com.xianying.system.controller.SysConfigController.edit()', 'PUT', 1, 'admin', '研发部门', '/system/config', '127.0.0.1', '内网IP', '{\"configId\":100,\"configKey\":\"按时打\",\"configName\":\"测试参\",\"configType\":\"N\",\"configValue\":\"按\",\"createTime\":\"2024-03-20 10:46:17\",\"creator\":\"\",\"params\":{},\"remark\":\"大萨达大所\",\"updateTime\":\"2024-03-20 10:46:30\",\"updater\":\"\"}', '{\"msg\":\"操作成功\",\"code\":200}', 0, NULL, '2024-03-20 10:46:52', 78, NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sys_oper_log` VALUES (178, '参数管理', 3, 'com.xianying.system.controller.SysConfigController.remove()', 'DELETE', 1, 'admin', '研发部门', '/system/config/100', '127.0.0.1', '内网IP', '{}', '{\"msg\":\"操作成功\",\"code\":200}', 0, NULL, '2024-03-20 10:46:54', 61, NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sys_oper_log` VALUES (179, '通知公告', 2, 'com.xianying.system.controller.SysNoticeController.edit()', 'PUT', 1, 'admin', '研发部门', '/system/notice', '127.0.0.1', '内网IP', '{\"createTime\":\"2024-02-25 16:38:43\",\"creator\":\"admin\",\"noticeContent\":\"<p>新版本内容</p>\",\"noticeId\":1,\"noticeTitle\":\"温馨提醒\",\"noticeType\":\"2\",\"params\":{},\"remark\":\"管理员\",\"status\":0,\"updater\":\"\"}', '{\"msg\":\"操作成功\",\"code\":200}', 0, NULL, '2024-03-20 11:04:16', 69, NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sys_oper_log` VALUES (180, '通知公告', 2, 'com.xianying.system.controller.SysNoticeController.edit()', 'PUT', 1, 'admin', '研发部门', '/system/notice', '127.0.0.1', '内网IP', '{\"createTime\":\"2024-02-25 16:38:43\",\"creator\":\"admin\",\"noticeContent\":\"<p>维护内容</p>\",\"noticeId\":2,\"noticeTitle\":\"维护通\",\"noticeType\":\"1\",\"params\":{},\"remark\":\"管理员\",\"status\":0,\"updater\":\"\"}', '{\"msg\":\"操作成功\",\"code\":200}', 0, NULL, '2024-03-20 11:04:22', 40, NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sys_oper_log` VALUES (181, '通知公告', 1, 'com.xianying.system.controller.SysNoticeController.add()', 'POST', 1, 'admin', '研发部门', '/system/notice', '127.0.0.1', '内网IP', '{\"createTime\":\"2024-03-20 11:05:01\",\"noticeContent\":\"<p>阿三大叔大叔大叔大所所大阿三大叔大叔大叔大所</p>\",\"noticeTitle\":\"新公告\",\"noticeType\":\"2\",\"params\":{},\"status\":0}', '{\"msg\":\"操作成功\",\"code\":200}', 0, NULL, '2024-03-20 11:05:01', 43, NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sys_oper_log` VALUES (182, '通知公告', 3, 'com.xianying.system.controller.SysNoticeController.remove()', 'DELETE', 1, 'admin', '研发部门', '/system/notice/10', '127.0.0.1', '内网IP', '{}', '{\"msg\":\"操作成功\",\"code\":200}', 0, NULL, '2024-03-20 11:05:06', 41, NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sys_oper_log` VALUES (183, '定时任务', 2, 'com.xianying.job.controller.SysJobController.changeStatus()', 'PUT', 1, 'admin', '研发部门', '/monitor/job/changeStatus', '127.0.0.1', '内网IP', '{\"jobId\":1,\"misfirePolicy\":\"0\",\"params\":{},\"status\":0}', '{\"msg\":\"操作成功\",\"code\":200}', 0, NULL, '2024-03-20 12:16:44', 131, NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sys_oper_log` VALUES (184, '定时任务', 2, 'com.xianying.job.controller.SysJobController.changeStatus()', 'PUT', 1, 'admin', '研发部门', '/monitor/job/changeStatus', '127.0.0.1', '内网IP', '{\"jobId\":1,\"misfirePolicy\":\"0\",\"params\":{},\"status\":1}', '{\"msg\":\"操作成功\",\"code\":200}', 0, NULL, '2024-03-20 12:16:47', 117, NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sys_oper_log` VALUES (185, '角色管理', 1, 'com.xianying.system.controller.SysRoleController.add()', 'POST', 1, 'admin', '研发部门', '/system/role', '127.0.0.1', '内网IP', '{\"admin\":false,\"deptCheckStrictly\":true,\"deptIds\":[],\"menuCheckStrictly\":true,\"menuIds\":[2007,2008,2009,2000,2001,2002,2003,2012,2013,2004,2005,2006],\"roleId\":100,\"roleKey\":\"caiwu\",\"roleName\":\"财务\",\"roleSort\":2,\"status\":0}', '{\"msg\":\"操作成功\",\"code\":200}', 0, NULL, '2024-03-20 15:01:58', 199, NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sys_oper_log` VALUES (186, '用户管理', 4, 'com.xianying.system.controller.SysUserController.insertAuthRole()', 'PUT', 1, 'admin', '研发部门', '/system/user/authRole', '127.0.0.1', '内网IP', '{\"roleIds\":\"\",\"userId\":\"101\"}', '{\"msg\":\"操作成功\",\"code\":200}', 0, NULL, '2024-03-20 15:03:29', 98, NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sys_oper_log` VALUES (187, '角色管理', 4, 'com.xianying.system.controller.SysRoleController.selectAuthUserAll()', 'PUT', 1, 'admin', '研发部门', '/system/role/authUser/selectAll', '127.0.0.1', '内网IP', '{\"roleId\":\"100\",\"userIds\":\"1,2,101\"}', '{\"msg\":\"操作成功\",\"code\":200}', 0, NULL, '2024-03-20 15:32:58', 51, NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sys_oper_log` VALUES (188, '菜单管理', 3, 'com.xianying.system.controller.SysMenuController.remove()', 'DELETE', 1, 'admin', '研发部门', '/system/menu/2011', '127.0.0.1', '内网IP', '{}', '{\"msg\":\"操作成功\",\"code\":200}', 0, NULL, '2024-04-24 14:34:37', 101, NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sys_oper_log` VALUES (189, '菜单管理', 3, 'com.xianying.system.controller.SysMenuController.remove()', 'DELETE', 1, 'admin', '研发部门', '/system/menu/2010', '127.0.0.1', '内网IP', '{}', '{\"msg\":\"操作成功\",\"code\":200}', 0, NULL, '2024-04-24 14:34:40', 89, NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sys_oper_log` VALUES (190, '菜单管理', 3, 'com.xianying.system.controller.SysMenuController.remove()', 'DELETE', 1, 'admin', '研发部门', '/system/menu/2006', '127.0.0.1', '内网IP', '{}', '{\"msg\":\"菜单已分配,不允许删除\",\"code\":601}', 0, NULL, '2024-04-24 14:34:43', 38, NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sys_oper_log` VALUES (191, '角色管理', 3, 'com.xianying.system.controller.SysRoleController.remove()', 'DELETE', 1, 'admin', '研发部门', '/system/role/100', '127.0.0.1', '内网IP', '{}', NULL, 1, '财务已分配,不能删除', '2024-04-24 14:34:54', 95, NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sys_oper_log` VALUES (192, '用户管理', 3, 'com.xianying.system.controller.SysUserController.remove()', 'DELETE', 1, 'admin', '研发部门', '/system/user/101', '127.0.0.1', '内网IP', '{}', '{\"msg\":\"操作成功\",\"code\":200}', 0, NULL, '2024-04-24 14:35:02', 182, NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sys_oper_log` VALUES (193, '用户管理', 2, 'com.xianying.system.controller.SysUserController.edit()', 'PUT', 1, 'admin', '研发部门', '/system/user', '127.0.0.1', '内网IP', '{\"admin\":false,\"avatar\":\"\",\"dept\":{\"ancestors\":\"0,100,101\",\"children\":[],\"deptId\":105,\"deptName\":\"测试部门\",\"leader\":\"闲影\",\"orderNum\":3,\"params\":{},\"parentId\":101,\"status\":0},\"deptId\":105,\"email\":\"xx@qq.com\",\"mobile\":\"16623254658\",\"nickname\":\"小贤\",\"postIds\":[3],\"roleIds\":[2],\"roles\":[{\"admin\":false,\"dataScope\":\"2\",\"deptCheckStrictly\":false,\"flag\":false,\"menuCheckStrictly\":false,\"params\":{},\"roleId\":2,\"roleKey\":\"common\",\"roleName\":\"普通角色\",\"roleSort\":2,\"status\":0},{\"admin\":false,\"dataScope\":\"1\",\"deptCheckStrictly\":false,\"flag\":false,\"menuCheckStrictly\":false,\"params\":{},\"roleId\":100,\"roleKey\":\"caiwu\",\"roleName\":\"财务\",\"roleSort\":2,\"status\":0}],\"sex\":0,\"status\":0,\"userId\":2,\"username\":\"ry\"}', '{\"msg\":\"操作成功\",\"code\":200}', 0, NULL, '2024-04-24 14:35:08', 330, NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sys_oper_log` VALUES (194, '角色管理', 3, 'com.xianying.system.controller.SysRoleController.remove()', 'DELETE', 1, 'admin', '研发部门', '/system/role/100', '127.0.0.1', '内网IP', '{}', NULL, 1, '财务已分配,不能删除', '2024-04-24 14:35:15', 96, NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sys_oper_log` VALUES (195, '角色管理', 2, 'com.xianying.system.controller.SysRoleController.edit()', 'PUT', 1, 'admin', '研发部门', '/system/role', '127.0.0.1', '内网IP', '{\"admin\":false,\"dataScope\":\"1\",\"deptCheckStrictly\":true,\"menuCheckStrictly\":true,\"menuIds\":[],\"roleId\":100,\"roleKey\":\"caiwu\",\"roleName\":\"财务\",\"roleSort\":2,\"status\":0}', '{\"msg\":\"操作成功\",\"code\":200}', 0, NULL, '2024-04-24 14:35:21', 184, NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sys_oper_log` VALUES (196, '角色管理', 4, 'com.xianying.system.controller.SysRoleController.cancelAuthUser()', 'PUT', 1, 'admin', '研发部门', '/system/role/authUser/cancel', '127.0.0.1', '内网IP', '{\"roleId\":100,\"userId\":1}', '{\"msg\":\"操作成功\",\"code\":200}', 0, NULL, '2024-04-24 14:35:26', 43, NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sys_oper_log` VALUES (197, '角色管理', 3, 'com.xianying.system.controller.SysRoleController.remove()', 'DELETE', 1, 'admin', '研发部门', '/system/role/100', '127.0.0.1', '内网IP', '{}', '{\"msg\":\"操作成功\",\"code\":200}', 0, NULL, '2024-04-24 14:35:33', 211, NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sys_oper_log` VALUES (198, '菜单管理', 3, 'com.xianying.system.controller.SysMenuController.remove()', 'DELETE', 1, 'admin', '研发部门', '/system/menu/2006', '127.0.0.1', '内网IP', '{}', '{\"msg\":\"操作成功\",\"code\":200}', 0, NULL, '2024-04-24 14:35:37', 81, NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sys_oper_log` VALUES (199, '菜单管理', 3, 'com.xianying.system.controller.SysMenuController.remove()', 'DELETE', 1, 'admin', '研发部门', '/system/menu/2005', '127.0.0.1', '内网IP', '{}', '{\"msg\":\"操作成功\",\"code\":200}', 0, NULL, '2024-04-24 14:35:40', 78, NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sys_oper_log` VALUES (200, '菜单管理', 3, 'com.xianying.system.controller.SysMenuController.remove()', 'DELETE', 1, 'admin', '研发部门', '/system/menu/2004', '127.0.0.1', '内网IP', '{}', '{\"msg\":\"操作成功\",\"code\":200}', 0, NULL, '2024-04-24 14:35:43', 82, NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sys_oper_log` VALUES (201, '菜单管理', 3, 'com.xianying.system.controller.SysMenuController.remove()', 'DELETE', 1, 'admin', '研发部门', '/system/menu/2013', '127.0.0.1', '内网IP', '{}', '{\"msg\":\"操作成功\",\"code\":200}', 0, NULL, '2024-04-24 14:35:49', 80, NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sys_oper_log` VALUES (202, '菜单管理', 3, 'com.xianying.system.controller.SysMenuController.remove()', 'DELETE', 1, 'admin', '研发部门', '/system/menu/2012', '127.0.0.1', '内网IP', '{}', '{\"msg\":\"操作成功\",\"code\":200}', 0, NULL, '2024-04-24 14:35:51', 83, NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sys_oper_log` VALUES (203, '菜单管理', 3, 'com.xianying.system.controller.SysMenuController.remove()', 'DELETE', 1, 'admin', '研发部门', '/system/menu/2003', '127.0.0.1', '内网IP', '{}', '{\"msg\":\"操作成功\",\"code\":200}', 0, NULL, '2024-04-24 14:35:54', 82, NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sys_oper_log` VALUES (204, '菜单管理', 3, 'com.xianying.system.controller.SysMenuController.remove()', 'DELETE', 1, 'admin', '研发部门', '/system/menu/2002', '127.0.0.1', '内网IP', '{}', '{\"msg\":\"操作成功\",\"code\":200}', 0, NULL, '2024-04-24 14:35:57', 80, NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sys_oper_log` VALUES (205, '菜单管理', 3, 'com.xianying.system.controller.SysMenuController.remove()', 'DELETE', 1, 'admin', '研发部门', '/system/menu/2001', '127.0.0.1', '内网IP', '{}', '{\"msg\":\"操作成功\",\"code\":200}', 0, NULL, '2024-04-24 14:36:00', 86, NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sys_oper_log` VALUES (206, '菜单管理', 3, 'com.xianying.system.controller.SysMenuController.remove()', 'DELETE', 1, 'admin', '研发部门', '/system/menu/2000', '127.0.0.1', '内网IP', '{}', '{\"msg\":\"操作成功\",\"code\":200}', 0, NULL, '2024-04-24 14:36:03', 79, NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sys_oper_log` VALUES (207, '菜单管理', 3, 'com.xianying.system.controller.SysMenuController.remove()', 'DELETE', 1, 'admin', '研发部门', '/system/menu/2009', '127.0.0.1', '内网IP', '{}', '{\"msg\":\"操作成功\",\"code\":200}', 0, NULL, '2024-04-24 14:36:08', 81, NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sys_oper_log` VALUES (208, '菜单管理', 3, 'com.xianying.system.controller.SysMenuController.remove()', 'DELETE', 1, 'admin', '研发部门', '/system/menu/2008', '127.0.0.1', '内网IP', '{}', '{\"msg\":\"操作成功\",\"code\":200}', 0, NULL, '2024-04-24 14:36:10', 79, NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sys_oper_log` VALUES (209, '菜单管理', 3, 'com.xianying.system.controller.SysMenuController.remove()', 'DELETE', 1, 'admin', '研发部门', '/system/menu/2007', '127.0.0.1', '内网IP', '{}', '{\"msg\":\"操作成功\",\"code\":200}', 0, NULL, '2024-04-24 14:36:13', 87, NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sys_oper_log` VALUES (210, '角色管理', 1, 'com.xianying.system.controller.SysRoleController.add()', 'POST', 1, 'admin', NULL, '/system/role', '127.0.0.1', '内网IP', '{\"admin\":false,\"deptCheckStrictly\":true,\"deptIds\":[],\"menuCheckStrictly\":true,\"menuIds\":[],\"roleId\":101,\"roleKey\":\"test\",\"roleName\":\"测试角色\",\"roleSort\":1,\"status\":0}', '{\"msg\":\"操作成功\",\"code\":200}', 0, NULL, '2024-04-25 11:47:12', 173, NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sys_oper_log` VALUES (211, '角色管理', 3, 'com.xianying.system.controller.SysRoleController.remove()', 'DELETE', 1, 'admin', NULL, '/system/role/101', '127.0.0.1', '内网IP', '{}', '{\"msg\":\"操作成功\",\"code\":200}', 0, NULL, '2024-04-25 11:47:17', 245, NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sys_oper_log` VALUES (212, '菜单管理', 1, 'com.xianying.system.controller.SysMenuController.add()', 'POST', 1, 'admin', NULL, '/system/menu', '127.0.0.1', '内网IP', '{\"children\":[],\"createTime\":\"2024-04-29 14:30:37\",\"icon\":\"documentation\",\"isCache\":\"0\",\"isFrame\":\"1\",\"menuName\":\"文章管理\",\"menuType\":\"M\",\"orderNum\":0,\"params\":{},\"parentId\":0,\"path\":\"article\",\"status\":0,\"visible\":0}', '{\"msg\":\"操作成功\",\"code\":200}', 0, NULL, '2024-04-29 14:30:37', 83, NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sys_oper_log` VALUES (213, '菜单管理', 1, 'com.xianying.system.controller.SysMenuController.add()', 'POST', 1, 'admin', NULL, '/system/menu', '127.0.0.1', '内网IP', '{\"children\":[],\"component\":\"ams/category/index\",\"createTime\":\"2024-04-29 14:32:51\",\"icon\":\"cascader\",\"isCache\":\"0\",\"isFrame\":\"1\",\"menuName\":\"文章分类\",\"menuType\":\"C\",\"orderNum\":2,\"params\":{},\"parentId\":2014,\"path\":\"articleCategory\",\"perms\":\"ams:category:list\",\"status\":0,\"visible\":0}', '{\"msg\":\"操作成功\",\"code\":200}', 0, NULL, '2024-04-29 14:32:51', 90, NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sys_oper_log` VALUES (214, '菜单管理', 1, 'com.xianying.system.controller.SysMenuController.add()', 'POST', 1, 'admin', NULL, '/system/menu', '127.0.0.1', '内网IP', '{\"children\":[],\"component\":\"ams/tag/index\",\"createTime\":\"2024-04-29 14:33:55\",\"icon\":\"drag\",\"isCache\":\"0\",\"isFrame\":\"1\",\"menuName\":\"文章标签\",\"menuType\":\"C\",\"orderNum\":3,\"params\":{},\"parentId\":2014,\"path\":\"articleTag\",\"perms\":\"ams:tag:list\",\"status\":0,\"visible\":0}', '{\"msg\":\"操作成功\",\"code\":200}', 0, NULL, '2024-04-29 14:33:55', 136, NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sys_oper_log` VALUES (215, '菜单管理', 1, 'com.xianying.system.controller.SysMenuController.add()', 'POST', 1, 'admin', NULL, '/system/menu', '127.0.0.1', '内网IP', '{\"children\":[],\"component\":\"ams/article/index\",\"createTime\":\"2024-04-29 14:35:15\",\"icon\":\"button\",\"isCache\":\"0\",\"isFrame\":\"1\",\"menuName\":\"文章列表\",\"menuType\":\"C\",\"orderNum\":0,\"params\":{},\"parentId\":2014,\"path\":\"amsArticle\",\"perms\":\"ams:article:list\",\"status\":0,\"visible\":0}', '{\"msg\":\"操作成功\",\"code\":200}', 0, NULL, '2024-04-29 14:35:15', 91, NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sys_oper_log` VALUES (216, '菜单管理', 1, 'com.xianying.system.controller.SysMenuController.add()', 'POST', 1, 'admin', NULL, '/system/menu', '127.0.0.1', '内网IP', '{\"children\":[],\"component\":\"ams/edit/index\",\"createTime\":\"2024-04-29 14:36:27\",\"icon\":\"edit\",\"isCache\":\"0\",\"isFrame\":\"1\",\"menuName\":\"编写文章\",\"menuType\":\"C\",\"orderNum\":1,\"params\":{},\"parentId\":2014,\"path\":\"amsEdit\",\"perms\":\"ams:edit:list\",\"status\":0,\"visible\":0}', '{\"msg\":\"操作成功\",\"code\":200}', 0, NULL, '2024-04-29 14:36:27', 100, NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sys_oper_log` VALUES (217, '用户头像', 2, 'com.xianying.system.controller.SysProfileController.avatar()', 'POST', 1, 'admin', NULL, '/system/user/profile/avatar', '127.0.0.1', '内网IP', '', '{\"msg\":\"操作成功\",\"imgUrl\":\"/profile/avatar/2024/04/29/2024-04-22_15-35-10_20240429155413A001.png\",\"code\":200}', 0, NULL, '2024-04-29 15:54:32', 19245, NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sys_oper_log` VALUES (218, '用户头像', 2, 'com.xianying.system.controller.SysProfileController.avatar()', 'POST', 1, 'admin', NULL, '/system/user/profile/avatar', '127.0.0.1', '内网IP', '', '{\"msg\":\"操作成功\",\"imgUrl\":\"/profile/avatar/2024/04/29/2024-04-22_15-35-10_20240429155437A003.png\",\"code\":200}', 0, NULL, '2024-04-29 15:54:37', 48, NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sys_oper_log` VALUES (219, '用户头像', 2, 'com.xianying.system.controller.SysProfileController.avatar()', 'POST', 1, 'admin', NULL, '/system/user/profile/avatar', '127.0.0.1', '内网IP', '', '{\"msg\":\"操作成功\",\"imgUrl\":\"/profile/avatar/2024/04/29/2024-04-22_15-35-10_20240429155420A002.png\",\"code\":200}', 0, NULL, '2024-04-29 15:54:40', 19181, NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sys_oper_log` VALUES (220, '用户头像', 2, 'com.xianying.system.controller.SysProfileController.avatar()', 'POST', 1, 'admin', NULL, '/system/user/profile/avatar', '127.0.0.1', '内网IP', '', '{\"msg\":\"操作成功\",\"imgUrl\":\"/profile/avatar/2024/04/29/2024-04-22_15-35-10_20240429160002A001.png\",\"code\":200}', 0, NULL, '2024-04-29 16:00:02', 108, NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sys_oper_log` VALUES (221, '用户头像', 2, 'com.xianying.system.controller.SysProfileController.avatar()', 'POST', 1, 'admin', NULL, '/system/user/profile/avatar', '127.0.0.1', '内网IP', '', '{\"msg\":\"操作成功\",\"imgUrl\":\"http://localhost:8128/img/avatar/20240429211928A002.png\",\"code\":200}', 0, NULL, '2024-04-29 21:19:29', 61, NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sys_oper_log` VALUES (222, '用户头像', 2, 'com.xianying.system.controller.SysProfileController.avatar()', 'POST', 1, 'admin', NULL, '/system/user/profile/avatar', '127.0.0.1', '内网IP', '', '{\"msg\":\"操作成功\",\"code\":200,\"data\":\"http://localhost:8128/img/avatar/20240429212209A001.png\"}', 0, NULL, '2024-04-29 21:22:10', 113, NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sys_oper_log` VALUES (223, '菜单管理', 1, 'com.xianying.system.controller.SysMenuController.add()', 'POST', 1, 'admin', NULL, '/system/menu', '127.0.0.1', '内网IP', '{\"children\":[],\"createTime\":\"2024-05-07 16:10:27\",\"icon\":\"education\",\"isCache\":\"0\",\"isFrame\":\"1\",\"menuName\":\"运营设置\",\"menuType\":\"M\",\"orderNum\":4,\"params\":{},\"parentId\":0,\"path\":\"operate\",\"status\":0,\"visible\":0}', '{\"msg\":\"操作成功\",\"code\":200}', 0, NULL, '2024-05-07 16:10:27', 83, NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sys_oper_log` VALUES (224, '菜单管理', 1, 'com.xianying.system.controller.SysMenuController.add()', 'POST', 1, 'admin', NULL, '/system/menu', '127.0.0.1', '内网IP', '{\"children\":[],\"component\":\"operate/support/index\",\"createTime\":\"2024-05-07 16:13:37\",\"icon\":\"clipboard\",\"isCache\":\"0\",\"isFrame\":\"1\",\"menuName\":\"支持一下\",\"menuType\":\"C\",\"orderNum\":0,\"params\":{},\"parentId\":2019,\"path\":\"operateSupport\",\"perms\":\"operate:support:list\",\"status\":0,\"visible\":0}', '{\"msg\":\"操作成功\",\"code\":200}', 0, NULL, '2024-05-07 16:13:38', 91, NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sys_oper_log` VALUES (225, '菜单管理', 1, 'com.xianying.system.controller.SysMenuController.add()', 'POST', 1, 'admin', NULL, '/system/menu', '127.0.0.1', '内网IP', '{\"children\":[],\"createTime\":\"2024-05-10 09:05:04\",\"icon\":\"international\",\"isCache\":\"0\",\"isFrame\":\"1\",\"menuName\":\"外链管理\",\"menuType\":\"M\",\"orderNum\":3,\"params\":{},\"parentId\":0,\"path\":\"link\",\"status\":0,\"visible\":0}', '{\"msg\":\"操作成功\",\"code\":200}', 0, NULL, '2024-05-10 09:05:06', 77, NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sys_oper_log` VALUES (226, '菜单管理', 1, 'com.xianying.system.controller.SysMenuController.add()', 'POST', 1, 'admin', NULL, '/system/menu', '127.0.0.1', '内网IP', '{\"children\":[],\"component\":\"link/search/index\",\"createTime\":\"2024-05-10 09:06:14\",\"icon\":\"checkbox\",\"isCache\":\"0\",\"isFrame\":\"1\",\"menuName\":\"搜索引擎\",\"menuType\":\"C\",\"orderNum\":0,\"params\":{},\"parentId\":2021,\"path\":\"linkSearch\",\"perms\":\"link:search:list\",\"status\":0,\"visible\":0}', '{\"msg\":\"操作成功\",\"code\":200}', 0, NULL, '2024-05-10 09:06:16', 66, NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sys_oper_log` VALUES (227, '菜单管理', 1, 'com.xianying.system.controller.SysMenuController.add()', 'POST', 1, 'admin', NULL, '/system/menu', '127.0.0.1', '内网IP', '{\"children\":[],\"component\":\"link/web/index\",\"createTime\":\"2024-05-10 09:07:04\",\"icon\":\"color\",\"isCache\":\"0\",\"isFrame\":\"1\",\"menuName\":\"便捷网站\",\"menuType\":\"C\",\"orderNum\":1,\"params\":{},\"parentId\":2021,\"path\":\"linkWeb\",\"perms\":\"link:web:list\",\"status\":0,\"visible\":0}', '{\"msg\":\"操作成功\",\"code\":200}', 0, NULL, '2024-05-10 09:07:06', 74, NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sys_oper_log` VALUES (228, '菜单管理', 3, 'com.xianying.system.controller.SysMenuController.remove()', 'DELETE', 1, 'admin', NULL, '/system/menu/1046', '127.0.0.1', '内网IP', '{}', '{\"msg\":\"菜单已分配,不允许删除\",\"code\":601}', 0, NULL, '2024-05-11 15:48:20', 51, NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sys_oper_log` VALUES (229, '角色管理', 2, 'com.xianying.system.controller.SysRoleController.edit()', 'PUT', 1, 'admin', NULL, '/system/role', '127.0.0.1', '内网IP', '{\"admin\":false,\"dataScope\":\"2\",\"deptCheckStrictly\":false,\"menuCheckStrictly\":false,\"menuIds\":[100,1000,1001,1002,1003,1004,1005,1006,101,1007,1008,1009,1010,1011,102,1012,1013,1014,1015,103,1016,1017,1018,1019,104,1020,1021,1022,1023,1024,105,1025,1026,1027,1028,1029,106,1030,1031,1032,1033,1034,107,1035,1036,1037,1038,108,500,1039,1040,1041,501,1042,1043,1044,1045,109,1046,1047,1048,110,1049,1050,1051,1052,1053,1054,112,113,114,115,116,1055,1056,1057,1058,1059,1060],\"roleId\":2,\"roleKey\":\"common\",\"roleName\":\"普通角色\",\"roleSort\":2,\"status\":0}', '{\"msg\":\"操作成功\",\"code\":200}', 0, NULL, '2024-05-11 15:48:58', 243, NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sys_oper_log` VALUES (230, '菜单管理', 3, 'com.xianying.system.controller.SysMenuController.remove()', 'DELETE', 1, 'admin', NULL, '/system/menu/1048', '127.0.0.1', '内网IP', '{}', '{\"msg\":\"菜单已分配,不允许删除\",\"code\":601}', 0, NULL, '2024-05-11 15:49:12', 41, NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sys_oper_log` VALUES (231, '菜单管理', 3, 'com.xianying.system.controller.SysMenuController.remove()', 'DELETE', 1, 'admin', NULL, '/system/menu/1048', '127.0.0.1', '内网IP', '{}', '{\"msg\":\"菜单已分配,不允许删除\",\"code\":601}', 0, NULL, '2024-05-11 15:49:26', 40, NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sys_oper_log` VALUES (232, '角色管理', 2, 'com.xianying.system.controller.SysRoleController.edit()', 'PUT', 1, 'admin', NULL, '/system/role', '127.0.0.1', '内网IP', '{\"admin\":false,\"dataScope\":\"2\",\"deptCheckStrictly\":false,\"menuCheckStrictly\":true,\"menuIds\":[],\"roleId\":2,\"roleKey\":\"common\",\"roleName\":\"普通角色\",\"roleSort\":2,\"status\":0}', '{\"msg\":\"操作成功\",\"code\":200}', 0, NULL, '2024-05-11 15:50:07', 186, NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sys_oper_log` VALUES (233, '菜单管理', 3, 'com.xianying.system.controller.SysMenuController.remove()', 'DELETE', 1, 'admin', NULL, '/system/menu/1046', '127.0.0.1', '内网IP', '{}', '{\"msg\":\"操作成功\",\"code\":200}', 0, NULL, '2024-05-11 15:50:14', 84, NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sys_oper_log` VALUES (234, '菜单管理', 3, 'com.xianying.system.controller.SysMenuController.remove()', 'DELETE', 1, 'admin', NULL, '/system/menu/1047', '127.0.0.1', '内网IP', '{}', '{\"msg\":\"操作成功\",\"code\":200}', 0, NULL, '2024-05-11 15:50:16', 87, NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sys_oper_log` VALUES (235, '菜单管理', 3, 'com.xianying.system.controller.SysMenuController.remove()', 'DELETE', 1, 'admin', NULL, '/system/menu/1048', '127.0.0.1', '内网IP', '{}', '{\"msg\":\"操作成功\",\"code\":200}', 0, NULL, '2024-05-11 15:50:19', 83, NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sys_oper_log` VALUES (236, '菜单管理', 3, 'com.xianying.system.controller.SysMenuController.remove()', 'DELETE', 1, 'admin', NULL, '/system/menu/109', '127.0.0.1', '内网IP', '{}', '{\"msg\":\"操作成功\",\"code\":200}', 0, NULL, '2024-05-11 15:50:22', 83, NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sys_oper_log` VALUES (237, '菜单管理', 3, 'com.xianying.system.controller.SysMenuController.remove()', 'DELETE', 1, 'admin', NULL, '/system/menu/112', '127.0.0.1', '内网IP', '{}', '{\"msg\":\"操作成功\",\"code\":200}', 0, NULL, '2024-05-11 15:50:25', 84, NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sys_oper_log` VALUES (238, '菜单管理', 3, 'com.xianying.system.controller.SysMenuController.remove()', 'DELETE', 1, 'admin', NULL, '/system/menu/113', '127.0.0.1', '内网IP', '{}', '{\"msg\":\"操作成功\",\"code\":200}', 0, NULL, '2024-05-11 15:50:28', 84, NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sys_oper_log` VALUES (239, '菜单管理', 3, 'com.xianying.system.controller.SysMenuController.remove()', 'DELETE', 1, 'admin', NULL, '/system/menu/114', '127.0.0.1', '内网IP', '{}', '{\"msg\":\"操作成功\",\"code\":200}', 0, NULL, '2024-05-11 15:50:31', 83, NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sys_oper_log` VALUES (240, '菜单管理', 3, 'com.xianying.system.controller.SysMenuController.remove()', 'DELETE', 1, 'admin', NULL, '/system/menu/1054', '127.0.0.1', '内网IP', '{}', '{\"msg\":\"操作成功\",\"code\":200}', 0, NULL, '2024-05-11 15:50:35', 83, NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sys_oper_log` VALUES (241, '菜单管理', 3, 'com.xianying.system.controller.SysMenuController.remove()', 'DELETE', 1, 'admin', NULL, '/system/menu/1052', '127.0.0.1', '内网IP', '{}', '{\"msg\":\"操作成功\",\"code\":200}', 0, NULL, '2024-05-11 15:50:38', 82, NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sys_oper_log` VALUES (242, '菜单管理', 3, 'com.xianying.system.controller.SysMenuController.remove()', 'DELETE', 1, 'admin', NULL, '/system/menu/1053', '127.0.0.1', '内网IP', '{}', '{\"msg\":\"操作成功\",\"code\":200}', 0, NULL, '2024-05-11 15:50:40', 82, NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sys_oper_log` VALUES (243, '菜单管理', 3, 'com.xianying.system.controller.SysMenuController.remove()', 'DELETE', 1, 'admin', NULL, '/system/menu/1050', '127.0.0.1', '内网IP', '{}', '{\"msg\":\"操作成功\",\"code\":200}', 0, NULL, '2024-05-11 15:50:43', 83, NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sys_oper_log` VALUES (244, '菜单管理', 3, 'com.xianying.system.controller.SysMenuController.remove()', 'DELETE', 1, 'admin', NULL, '/system/menu/1051', '127.0.0.1', '内网IP', '{}', '{\"msg\":\"操作成功\",\"code\":200}', 0, NULL, '2024-05-11 15:50:44', 82, NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sys_oper_log` VALUES (245, '菜单管理', 3, 'com.xianying.system.controller.SysMenuController.remove()', 'DELETE', 1, 'admin', NULL, '/system/menu/1049', '127.0.0.1', '内网IP', '{}', '{\"msg\":\"操作成功\",\"code\":200}', 0, NULL, '2024-05-11 15:50:47', 82, NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sys_oper_log` VALUES (246, '菜单管理', 3, 'com.xianying.system.controller.SysMenuController.remove()', 'DELETE', 1, 'admin', NULL, '/system/menu/110', '127.0.0.1', '内网IP', '{}', '{\"msg\":\"操作成功\",\"code\":200}', 0, NULL, '2024-05-11 15:50:50', 84, NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sys_oper_log` VALUES (247, '菜单管理', 3, 'com.xianying.system.controller.SysMenuController.remove()', 'DELETE', 1, 'admin', NULL, '/system/menu/2', '127.0.0.1', '内网IP', '{}', '{\"msg\":\"操作成功\",\"code\":200}', 0, NULL, '2024-05-11 15:50:53', 81, NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sys_oper_log` VALUES (248, '菜单管理', 3, 'com.xianying.system.controller.SysMenuController.remove()', 'DELETE', 1, 'admin', NULL, '/system/menu/115', '127.0.0.1', '内网IP', '{}', '{\"msg\":\"操作成功\",\"code\":200}', 0, NULL, '2024-05-11 15:52:04', 82, NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sys_oper_log` VALUES (249, '部门管理', 2, 'com.xianying.system.controller.SysDeptController.edit()', 'PUT', 1, 'admin', NULL, '/system/dept', '127.0.0.1', '内网IP', '{\"ancestors\":\"0\",\"children\":[],\"deptId\":100,\"deptName\":\"自得其道\",\"email\":\"xy@qq.com\",\"leader\":\"自得\",\"mobile\":\"15888888888\",\"orderNum\":0,\"params\":{},\"parentId\":0,\"status\":0}', '{\"msg\":\"操作成功\",\"code\":200}', 0, NULL, '2024-05-11 15:53:08', 130, NULL, NULL, NULL, NULL, NULL);
-- ----------------------------
-- Table structure for sys_post
-- ----------------------------
DROP TABLE IF EXISTS `sys_post`;
CREATE TABLE `sys_post` (
`post_id` bigint NOT NULL AUTO_INCREMENT COMMENT '岗位ID',
`post_code` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '岗位编码',
`post_name` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '岗位名称',
`post_sort` int NOT NULL COMMENT '显示顺序',
`status` int NOT NULL DEFAULT 0 COMMENT '状态(0正常 1停用)',
`creator` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT '' COMMENT '创建者',
`create_time` datetime NULL DEFAULT NULL COMMENT '创建时间',
`updater` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT '' COMMENT '更新者',
`update_time` datetime NULL DEFAULT NULL COMMENT '更新时间',
`remark` varchar(500) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '备注',
`deleted` int NULL DEFAULT 0,
PRIMARY KEY (`post_id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 7 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci COMMENT = '岗位信息表' ROW_FORMAT = DYNAMIC;
-- ----------------------------
-- Records of sys_post
-- ----------------------------
INSERT INTO `sys_post` VALUES (1, 'ceo', '董事长', 1, 0, 'admin', '2024-02-25 16:38:43', '', NULL, '', 0);
INSERT INTO `sys_post` VALUES (2, 'se', '项目经理', 2, 0, 'admin', '2024-02-25 16:38:43', '', NULL, '', 0);
INSERT INTO `sys_post` VALUES (3, 'hr', '人力资源', 3, 0, 'admin', '2024-02-25 16:38:43', '', NULL, '', 0);
INSERT INTO `sys_post` VALUES (4, 'user', '普通员工', 4, 0, 'admin', '2024-02-25 16:38:43', '', NULL, '', 0);
INSERT INTO `sys_post` VALUES (5, 'H5', '前端开发', 5, 0, '', '2024-03-20 09:49:45', '', NULL, NULL, 0);
INSERT INTO `sys_post` VALUES (6, 'J', '后端开发', 0, 0, '', '2024-03-20 09:50:03', '', NULL, NULL, 0);
-- ----------------------------
-- Table structure for sys_role
-- ----------------------------
DROP TABLE IF EXISTS `sys_role`;
CREATE TABLE `sys_role` (
`role_id` bigint NOT NULL AUTO_INCREMENT COMMENT '角色ID',
`role_name` varchar(30) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '角色名称',
`role_key` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '角色权限字符串',
`role_sort` int NOT NULL COMMENT '显示顺序',
`data_scope` char(1) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT '1' COMMENT '数据范围(1:全部数据权限 2:自定数据权限 3:本部门数据权限 4:本部门及以下数据权限)',
`menu_check_strictly` tinyint(1) NULL DEFAULT 1 COMMENT '菜单树选择项是否关联显示',
`dept_check_strictly` tinyint(1) NULL DEFAULT 1 COMMENT '部门树选择项是否关联显示',
`status` int NOT NULL DEFAULT 0 COMMENT '角色状态(0正常 1停用)',
`deleted` int NULL DEFAULT 0 COMMENT '删除标志(0代表存在 2代表删除)',
`creator` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT '' COMMENT '创建者',
`create_time` datetime NULL DEFAULT NULL COMMENT '创建时间',
`updater` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT '' COMMENT '更新者',
`update_time` datetime NULL DEFAULT NULL COMMENT '更新时间',
`remark` varchar(500) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '备注',
PRIMARY KEY (`role_id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 102 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci COMMENT = '角色信息表' ROW_FORMAT = DYNAMIC;
-- ----------------------------
-- Records of sys_role
-- ----------------------------
INSERT INTO `sys_role` VALUES (1, '超级管理员', 'admin', 1, '1', 1, 1, 0, 0, 'admin', '2024-02-25 16:38:43', '', NULL, '超级管理员');
INSERT INTO `sys_role` VALUES (2, '普通角色', 'common', 2, '2', 1, 0, 0, 0, 'admin', '2024-02-25 16:38:43', '', '2024-05-11 15:50:06', '普通角色');
INSERT INTO `sys_role` VALUES (100, '财务', 'caiwu', 2, '1', 1, 1, 0, 2, '', '2024-03-20 15:01:58', '', '2024-04-24 14:35:21', NULL);
INSERT INTO `sys_role` VALUES (101, '测试角色', 'test', 1, '1', 1, 1, 0, 2, '', '2024-04-25 11:47:12', '', NULL, NULL);
-- ----------------------------
-- Table structure for sys_role_dept
-- ----------------------------
DROP TABLE IF EXISTS `sys_role_dept`;
CREATE TABLE `sys_role_dept` (
`role_id` bigint NOT NULL COMMENT '角色ID',
`dept_id` bigint NOT NULL COMMENT '部门ID',
PRIMARY KEY (`role_id`, `dept_id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci COMMENT = '角色和部门关联表' ROW_FORMAT = DYNAMIC;
-- ----------------------------
-- Records of sys_role_dept
-- ----------------------------
INSERT INTO `sys_role_dept` VALUES (2, 100);
INSERT INTO `sys_role_dept` VALUES (2, 101);
INSERT INTO `sys_role_dept` VALUES (2, 105);
-- ----------------------------
-- Table structure for sys_role_menu
-- ----------------------------
DROP TABLE IF EXISTS `sys_role_menu`;
CREATE TABLE `sys_role_menu` (
`role_id` bigint NOT NULL COMMENT '角色ID',
`menu_id` bigint NOT NULL COMMENT '菜单ID',
PRIMARY KEY (`role_id`, `menu_id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci COMMENT = '角色和菜单关联表' ROW_FORMAT = DYNAMIC;
-- ----------------------------
-- Records of sys_role_menu
-- ----------------------------
-- ----------------------------
-- Table structure for sys_user
-- ----------------------------
DROP TABLE IF EXISTS `sys_user`;
CREATE TABLE `sys_user` (
`user_id` bigint NOT NULL AUTO_INCREMENT COMMENT '用户ID',
`dept_id` bigint NULL DEFAULT NULL COMMENT '部门ID',
`username` varchar(30) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL DEFAULT '' COMMENT '用户账号',
`nickname` varchar(30) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL DEFAULT '' COMMENT '用户昵称',
`email` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT '' COMMENT '用户邮箱',
`mobile` varchar(11) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT '' COMMENT '手机号码',
`sex` int NULL DEFAULT 0 COMMENT '用户性别(0男 1女 2未知)',
`avatar` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT '' COMMENT '头像地址',
`password` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT '' COMMENT '密码',
`status` int NULL DEFAULT 0 COMMENT '帐号状态(0正常 1停用)',
`deleted` int NULL DEFAULT 0 COMMENT '删除标志(0代表存在 2代表删除)',
`login_ip` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT '' COMMENT '最后登录IP',
`login_date` datetime NULL DEFAULT NULL COMMENT '最后登录时间',
`creator` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT '' COMMENT '创建者',
`create_time` datetime NULL DEFAULT NULL COMMENT '创建时间',
`updater` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT '' COMMENT '更新者',
`update_time` datetime NULL DEFAULT NULL COMMENT '更新时间',
`remark` varchar(500) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '备注',
PRIMARY KEY (`user_id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 102 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci COMMENT = '用户信息表' ROW_FORMAT = DYNAMIC;
-- ----------------------------
-- Records of sys_user
-- ----------------------------
INSERT INTO `sys_user` VALUES (1, 103, 'admin', '若依', 'ry@163.com', '15888888888', 1, 'http://localhost:8128/img/avatar/20240429212209A001.png', '$2a$10$sIFHgwnNqANr6bkxh5CpY.HS6Os2C4k0fGu9lBCfRVbmmsw3FoZ7q', 0, 0, '127.0.0.1', '2024-05-13 14:37:37', 'admin', '2024-02-25 16:38:43', '', '2024-03-19 09:54:55', '管理员');
INSERT INTO `sys_user` VALUES (2, 105, 'ry', '小贤', 'xx@qq.com', '16623254658', 0, '', '$2a$10$7JB720yubVSZvUI0rEqK/.VqGOZTH.ulu33dHOiBE8ByOhJIrdAu2', 0, 0, '127.0.0.1', '2024-02-25 16:38:43', 'admin', '2024-02-25 16:38:43', '', '2024-03-19 15:47:25', '测试员123');
INSERT INTO `sys_user` VALUES (101, 103, 'menghuai', '孟怀', '123@qq.com', '16653565847', 0, '', '$2a$10$/2RVh6OfgppFvalaX0r5/e00RNa6CC37ZeAQSJ88U6BTt8DQQEyWS', 0, 2, '', NULL, '', '2024-03-19 16:17:13', '', NULL, '123456');
-- ----------------------------
-- Table structure for sys_user_post
-- ----------------------------
DROP TABLE IF EXISTS `sys_user_post`;
CREATE TABLE `sys_user_post` (
`user_id` bigint NOT NULL COMMENT '用户ID',
`post_id` bigint NOT NULL COMMENT '岗位ID',
PRIMARY KEY (`user_id`, `post_id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci COMMENT = '用户与岗位关联表' ROW_FORMAT = DYNAMIC;
-- ----------------------------
-- Records of sys_user_post
-- ----------------------------
INSERT INTO `sys_user_post` VALUES (1, 1);
INSERT INTO `sys_user_post` VALUES (2, 3);
-- ----------------------------
-- Table structure for sys_user_role
-- ----------------------------
DROP TABLE IF EXISTS `sys_user_role`;
CREATE TABLE `sys_user_role` (
`user_id` bigint NOT NULL COMMENT '用户ID',
`role_id` bigint NOT NULL COMMENT '角色ID',
PRIMARY KEY (`user_id`, `role_id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci COMMENT = '用户和角色关联表' ROW_FORMAT = DYNAMIC;
-- ----------------------------
-- Records of sys_user_role
-- ----------------------------
INSERT INTO `sys_user_role` VALUES (1, 1);
INSERT INTO `sys_user_role` VALUES (2, 2);
-- ----------------------------
-- Table structure for ums_member
-- ----------------------------
DROP TABLE IF EXISTS `ums_member`;
CREATE TABLE `ums_member` (
`id` bigint NOT NULL AUTO_INCREMENT COMMENT '主键',
`company_id` bigint NULL DEFAULT NULL COMMENT '公司id',
`parent_id` bigint NULL DEFAULT 0 COMMENT '邀请人id',
`nickname` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT '昵称',
`openid` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT '微信openid',
`account` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT '账号',
`mobile` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT '电话',
`email` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT '邮箱',
`level` int NULL DEFAULT 0 COMMENT '用户等级【会员,代理人,合伙人,股东】',
`password` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT '密码',
`sex` int NULL DEFAULT 0 COMMENT '用户性别(0男 1女 2未知)',
`avatar` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT '头像',
`share_img` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT '分享二维码',
`login_date` datetime NULL DEFAULT NULL COMMENT '最后登录时间',
`status` int NULL DEFAULT 0,
`create_time` datetime NULL DEFAULT NULL COMMENT '创建时间',
`update_time` datetime NULL DEFAULT NULL COMMENT '更新时间',
`remark` varchar(500) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT '备注',
`deleted` tinyint NULL DEFAULT 0 COMMENT '是否删除',
`creator` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT '创建者',
`updater` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT '修改者',
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 4 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = DYNAMIC;
-- ----------------------------
-- Records of ums_member
-- ----------------------------
INSERT INTO `ums_member` VALUES (3, NULL, 0, '可靠的抽屉', '', 'stt', '', '', 0, '$2a$10$sAmK/OKJg2zh4nh/6iEG0.PEP9QAqA14oYjNSH2E7qxCpXSKkL3He', 0, 'http://localhost:8128/img/article/20240501180023A002.png', '', NULL, 0, '2024-05-08 10:05:41', NULL, '', 0, '', '');
-- ----------------------------
-- Table structure for video
-- ----------------------------
DROP TABLE IF EXISTS `video`;
CREATE TABLE `video` (
`id` bigint NOT NULL AUTO_INCREMENT COMMENT '主键id',
`user_id` bigint NULL DEFAULT NULL COMMENT '用户id',
`category_id` bigint NULL DEFAULT NULL COMMENT '分类id',
`title` varchar(150) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '视频标题',
`main_img` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT '视频封面地址',
`summary` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '视频简介',
`video_url` varchar(2000) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT '视频地址',
`read_volume` bigint NULL DEFAULT 0 COMMENT '播放量',
`collect_volume` bigint NULL DEFAULT 0 COMMENT '收藏数',
`like_volume` bigint NULL DEFAULT 0 COMMENT '点赞数',
`comment_volume` bigint NULL DEFAULT 0 COMMENT '评论数',
`duration` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT '时长',
`top_status` int NULL DEFAULT 0 COMMENT '是否置顶 0否 1是',
`push_status` int NULL DEFAULT 0 COMMENT '是否发布 0:下架 1:发布',
`show_scope` int NULL DEFAULT 0 COMMENT '可见范围',
`push_type` int NULL DEFAULT 0 COMMENT '是否原创 0:原创 1:转载,2:翻译',
`original_url` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '转载地址',
`create_time` datetime NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`update_time` datetime NULL DEFAULT NULL COMMENT '修改时间',
`recom_status` int NULL DEFAULT 0 COMMENT '是否推荐',
`tag` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT '视频标签',
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 17 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '视频信息表' ROW_FORMAT = DYNAMIC;
-- ----------------------------
-- Records of video
-- ----------------------------
INSERT INTO `video` VALUES (5, NULL, NULL, '05-一篇搞懂Lambda,能提高效率吗?', 'http://localhost:8128/img/article/20240501180023A002.png', '源码地址:git@gitee.com:stt0626/stt-study.git', 'https://www.bilibili.com/video/BV1dj411n7pn/?vd_source=3dc106cba4577ff113674c47cba62e95', 0, 0, 0, 0, '1小时2分钟', 0, 0, 0, 0, NULL, '2024-05-08 16:04:15', NULL, 0, '');
INSERT INTO `video` VALUES (6, NULL, NULL, '05-一篇搞懂Lambda,能提高效率吗?', 'http://localhost:8128/img/article/20240501180023A002.png', '源码地址:git@gitee.com:stt0626/stt-study.git', 'https://www.bilibili.com/video/BV1dj411n7pn/?vd_source=3dc106cba4577ff113674c47cba62e95', 0, 0, 0, 0, '1小时2分钟', 0, 0, 0, 0, NULL, '2024-05-08 16:04:15', NULL, 0, '');
INSERT INTO `video` VALUES (7, NULL, NULL, '05-一篇搞懂Lambda,能提高效率吗?', 'http://localhost:8128/img/article/20240501180023A002.png', '源码地址:git@gitee.com:stt0626/stt-study.git', 'https://www.bilibili.com/video/BV1dj411n7pn/?vd_source=3dc106cba4577ff113674c47cba62e95', 0, 0, 0, 0, '1小时2分钟', 0, 0, 0, 0, NULL, '2024-05-08 16:04:15', NULL, 0, '');
INSERT INTO `video` VALUES (8, NULL, NULL, '05-一篇搞懂Lambda,能提高效率吗?', 'http://localhost:8128/img/article/20240501180023A002.png', '源码地址:git@gitee.com:stt0626/stt-study.git', 'https://www.bilibili.com/video/BV1dj411n7pn/?vd_source=3dc106cba4577ff113674c47cba62e95', 0, 0, 0, 0, '1小时2分钟', 0, 0, 0, 0, NULL, '2024-05-08 16:04:15', NULL, 0, '');
INSERT INTO `video` VALUES (9, NULL, NULL, '05-一篇搞懂Lambda,能提高效率吗?', 'http://localhost:8128/img/article/20240501180023A002.png', '源码地址:git@gitee.com:stt0626/stt-study.git', 'https://www.bilibili.com/video/BV1dj411n7pn/?vd_source=3dc106cba4577ff113674c47cba62e95', 0, 0, 0, 0, '1小时2分钟', 0, 0, 0, 0, NULL, '2024-05-08 16:04:15', NULL, 0, '');
INSERT INTO `video` VALUES (10, NULL, NULL, '05-一篇搞懂Lambda,能提高效率吗?', 'http://localhost:8128/img/article/20240501180023A002.png', '源码地址:git@gitee.com:stt0626/stt-study.git', 'https://www.bilibili.com/video/BV1dj411n7pn/?vd_source=3dc106cba4577ff113674c47cba62e95', 0, 0, 0, 0, '1小时2分钟', 0, 0, 0, 0, NULL, '2024-05-08 16:04:15', NULL, 0, '');
INSERT INTO `video` VALUES (11, NULL, NULL, '05-一篇搞懂Lambda,能提高效率吗?', 'http://localhost:8128/img/article/20240501180023A002.png', '源码地址:git@gitee.com:stt0626/stt-study.git', 'https://www.bilibili.com/video/BV1dj411n7pn/?vd_source=3dc106cba4577ff113674c47cba62e95', 0, 0, 0, 0, '1小时2分钟', 0, 0, 0, 0, NULL, '2024-05-08 16:04:15', NULL, 0, '');
INSERT INTO `video` VALUES (12, NULL, NULL, '05-一篇搞懂Lambda,能提高效率吗?', 'http://localhost:8128/img/article/20240501180023A002.png', '源码地址:git@gitee.com:stt0626/stt-study.git', 'https://www.bilibili.com/video/BV1dj411n7pn/?vd_source=3dc106cba4577ff113674c47cba62e95', 0, 0, 0, 0, '1小时2分钟', 0, 0, 0, 0, NULL, '2024-05-08 16:04:15', NULL, 0, '');
INSERT INTO `video` VALUES (13, NULL, NULL, '05-一篇搞懂Lambda,能提高效率吗?', 'http://localhost:8128/img/article/20240501180023A002.png', '源码地址:git@gitee.com:stt0626/stt-study.git', 'https://www.bilibili.com/video/BV1dj411n7pn/?vd_source=3dc106cba4577ff113674c47cba62e95', 0, 0, 0, 0, '1小时2分钟', 0, 0, 0, 0, NULL, '2024-05-08 16:04:15', NULL, 0, '');
INSERT INTO `video` VALUES (14, NULL, NULL, '05-一篇搞懂Lambda,能提高效率吗?', 'http://localhost:8128/img/article/20240501180023A002.png', '源码地址:git@gitee.com:stt0626/stt-study.git', 'https://www.bilibili.com/video/BV1dj411n7pn/?vd_source=3dc106cba4577ff113674c47cba62e95', 0, 0, 0, 0, '1小时2分钟', 0, 0, 0, 0, NULL, '2024-05-08 16:04:15', NULL, 0, '');
INSERT INTO `video` VALUES (15, NULL, NULL, '05-一篇搞懂Lambda,能提高效率吗?', 'http://localhost:8128/img/article/20240501180023A002.png', '源码地址:git@gitee.com:stt0626/stt-study.git', 'https://www.bilibili.com/video/BV1dj411n7pn/?vd_source=3dc106cba4577ff113674c47cba62e95', 0, 0, 0, 0, '1小时2分钟', 0, 0, 0, 0, NULL, '2024-05-08 16:04:15', NULL, 0, '');
INSERT INTO `video` VALUES (16, NULL, NULL, '05-一篇搞懂Lambda,能提高效率吗?', 'http://localhost:8128/img/article/20240501180023A002.png', '源码地址:git@gitee.com:stt0626/stt-study.git', 'https://www.bilibili.com/video/BV1dj411n7pn/?vd_source=3dc106cba4577ff113674c47cba62e95', 0, 0, 0, 0, '1小时2分钟', 0, 0, 0, 0, NULL, '2024-05-08 16:04:15', NULL, 0, '');
SET FOREIGN_KEY_CHECKS = 1;
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。