谷粒商城项目笔记之分布式基础(一)

本文档是谷粒商城项目分布式基础的详细笔记,涵盖了项目简介、分布式基础概念,以及环境搭建的全过程。项目采用B2C电商模式,讲解了微服务、集群、远程调用、负载均衡等概念,并深入介绍了服务注册/发现、配置中心、服务熔断&服务降级等。此外,还详述了Linux虚拟机的安装、Docker环境配置、MySQL与Redis的安装与使用,以及开发环境的统一,包括Maven、Idea&VsCode、Git的配置。文章最后探讨了SpringCloud Alibaba-Nacos作为注册中心和配置中心的使用,并展示了微服务间Feign的远程调用。
摘要由CSDN通过智能技术生成

谷粒商城项目之分布式基础

目录

前言

我们在这一阶段正式迈入实战项目—谷粒商城。接下来我们迈入分布式基础之项目环境搭建吧。


1 项目简介

1.1 项目背景

1.1.1 电商模式

在这里插入图片描述

1.1.2 谷粒商城

谷粒商城是一个B2C 模式的电商平台,销售自营商品给客户。

1.2 项目架构图

1.2.1 项目微服务架构图

在这里插入图片描述

1.2.2 微服务划分图

在这里插入图片描述

1.2.3 项目技术&特色

在这里插入图片描述

1.2.4 项目前置要求

在这里插入图片描述


2 分布式基础概念

2.1 微服务

在这里插入图片描述
在这里插入图片描述

2.2 集群&分布式&节点

在这里插入图片描述
在这里插入图片描述

2.3 远程调用

在这里插入图片描述

2.4 负载均衡

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

2.5 服务注册/发现&注册中心

在这里插入图片描述

2.6 配置中心

在这里插入图片描述

2.7 服务熔断&服务降级

在微服务架构中,微服务之间通过网络进行通信,存在相互依赖,当其中一个服务不可用时,有可能会造成雪崩效应。要防止这样的情况,必须要有容错机制来保护服务。

在这里插入图片描述
在这里插入图片描述

2.8 API 网关

在这里插入图片描述
在这里插入图片描述


3 环境搭建

3.1 安装Linux虚拟机

3.1.1 软件下载

  1. 我们下载 virtual box 这个虚拟机软件 ,官网地址.
    在这里插入图片描述
    傻瓜式安装。
    在这里插入图片描述
    注意设置全局虚拟机路径。因为这个到时候虚拟机默认在c盘当前用户下。当然你c盘很大那无需设置。

  2. 下载vagrant 这个软件,官网地址,这个软件可以帮助我们自动安装虚拟机和其配置流程。

在这里插入图片描述
傻瓜式安装,注意这个软件安装之后需要重启电脑。

在这里插入图片描述
vagrant镜像仓库:https://app.vagrantup.com/boxes/search。
这个就是vagrant搭配的第三方centos7镜像。

3.1.2 电脑开启CPU虚拟化

在这里插入图片描述
在这里插入图片描述
虚拟机软件一般都要开启这个。

3.1.3 安装

  1. 打开 window cmd 窗口,运行 Vagrant init centos/7,即可初始化一个 centos7 系统
  2. 运行 vagrant up 即可启动虚拟机。系统 root 用户的密码是 vagrant
  3. vagrant 其他常用命令:
    - vagrant ssh:自动使用 vagrant 用户连接虚拟机。
    - vagrant upload source [destination] [name|id]:上传文件
    - https://www.vagrantup.com/docs/cli/init.html Vagrant 命令行
    在这里插入图片描述

3.1.4 修改ip

默认虚拟机的 ip 地址不是固定 ip,开发不方便.

  • 修改 Vagrantfile
    在这里插入图片描述
    windows下cmd命令行中输入 ifconfig查看 virtual box的ip网段。
    在这里插入图片描述
    config.vm.network "private_network", ip: "192.168.56.10" 将文件这一行注释掉,改为这行代码。
    在这里插入图片描述
    注意:改完之后在命令行输入 vagrant reload 才行,否则会不生效(大坑,否则一直是2个,不会是3个有固定Ip地址的)。

  • 重新使用vagrant up 启动机器即可。然后再vagrant ssh 连接机器。

3.1.5 使用第三方工具登录

在这里插入图片描述
课件上面,修改 PasswordAuthentication yes 这个选项。
网上找到另一种方法来使用第三方ssh登录工具。
在这里插入图片描述
在这里插入图片描述

成功。

3.1.6 从vagrant用户切换为管理员用户

不知道有没有发现。前面我们登录之后命令符是$,这个是普通用户。但是对于我们开发测试学习来说,普通用户权限太低,对于一些配置文件的修改有很大的限制,所以我们可以使用命令切换到root用户。
在这里插入图片描述

3.1.7 修改yum源(下载安装更快)

注意要在root用户下。

  1. 备份原yum源
    mv /etc/yum.repos.d/CentOS-Base.repo /etc/yum.repos.d/CentOS-Base.repo.backup
  2. 使用新yum 源
    curl -o /etc/yum.repos.d/CentOS-Base.repo http://mirrors.163.com/.help/CentOS7-Base-163.repo
  3. 生成缓存
    yum makecache
    在这里插入图片描述

3.2 安装docker

sudo —让普通用户可以拥有超级管理员权限。
Docker 安装文档:https://docs.docker.com/install/linux/docker-ce/centos/

3.2.1 卸载系统之前的docker

sudo yum remove docker \
				docker-client \
				docker-client-latest \
				docker-common \
				docker-latest \
				docker-latest-logrotate \
				docker-logrotate \
				docker-engine

3.2.2 安装Docker-CE

  1. 安装必须的依赖
sudo yum install -y yum-utils \
		device-mapper-persistent-data \
		lvm2
  1. 设置docker repo 的yum 位置
sudo yum-config-manager \
		--add-repo \
		https://download.docker.com/linux/centos/docker-ce.repo
  1. 安装docker,以及docker-cli
sudo yum install docker-ce docker-ce-cli containerd.io

3.3.3 启动docker

sudo systemctl start docker

3.3.4 设置docker 开机自启

sudo systemctl enable docker

**注意:docker 要在root用户下进行测试。

3.3.6 配置docker 镜像加速 — 阿里云镜像加速服务

在这里插入图片描述
在这里插入图片描述

1. mkdir -p /etc/docker

2. tee /etc/docker/daemon.json <<-'EOF'
{
  "registry-mirrors": ["https://6xvuqzlo.mirror.aliyuncs.com"]
}
EOF
  • sudo systemctl daemon-reload #重启docker后台线程
  • sudo systemctl restart docker

3.3 docker 安装MySQL

在这里插入图片描述

3.3.1 下载镜像文件

docker pull mysql:5.7

3.3.2 创建实例并启动

docker run -p 3306:3306 --name mysql \
						-v /mydata/mysql/log:/var/log/mysql \
						-v /mydata/mysql/data:/var/lib/mysql \
						-v /mydata/mysql/conf:/etc/mysql \
						-e MYSQL_ROOT_PASSWORD=root \
						-d mysql:5.7
参数说明
-p 3306:3306:将容器的3306 端口映射到主机的3306 端口
-v /mydata/mysql/conf:/etc/mysql:将配置文件夹挂载到主机
-v /mydata/mysql/log:/var/log/mysql:将日志文件夹挂载到主机
-v /mydata/mysql/data:/var/lib/mysql/:将配置文件夹挂载到主机
-e MYSQL_ROOT_PASSWORD=root:初始化root 用户的密码

3.3.3 配置MYSQL

主要是配置编码方式,因为默认有些不是utf-8.
在这里插入图片描述
所以我们需要进行一些配置,使得变为utf-8,支持中文编码方式,不会乱码。

vi /mydata/mysql/conf/my.cnf
[client]
default-character-set=utf8
[mysql]
default-character-set=utf8
[mysqld]
init_connect='SET collation_connection = utf8_unicode_ci'
init_connect='SET NAMES utf8'
character-set-server=utf8
collation-server=utf8_unicode_ci
skip-character-set-client-handshake
skip-name-resolve

注意:解决MySQL 连接慢的问题
在配置文件中加入如下,并重启mysql
[mysqld]
skip-name-resolve
解释:
skip-name-resolve:跳过域名解析

3.3.4 通过容器的mysql 命令行工具连接

docker exec -it mysql mysql -uroot -proot

3.3.5 设置root 远程访问

grant all privileges on *.* to 'root'@'%' identified by 'root' with grant option;
flush privileges;

3.4 docker 安装redis

3.4.1 下载镜像文件

docker pull redis

3.4.2 创建实例并启动

1. mkdir -p /mydata/redis/conf   # 提前创建好redis挂载文件目录,因为不提前设置,mydata/redis/conf/redis.conf 这个redis.conf会被认为是一个文件夹,不会文件

2. touch /mydata/redis/conf/redis.conf     # 创建redis 启动的配置文件


3. docker run -p 6379:6379 --name redis -v /mydata/redis/data:/data \
-v /mydata/redis/conf/redis.conf:/etc/redis/redis.conf \
-d redis redis-server /etc/redis/redis.conf

在reids.conf中设置开启数据持久化。
在这里插入图片描述
redis 自描述文件:
https://raw.githubusercontent.com/antirez/redis/4.0/redis.conf

如果还需要设置其他的可以去上面这个文件中看。

3.4.3 使用redis 镜像执行redis-cli 命令连接

docker exec -it redis redis-cli

3.4.4 Redis 图形化界面

在这里插入图片描述
连接自己的redis。
在这里插入图片描述

3.5 开发环境统一

在这里插入图片描述
因为我们创建了Mysql 和redis的容器,所以设置自启来避免每次都要重新去运行。

3.5.1 Maven

在maven的配置文件中修改镜像源和jdk版本。

配置阿里云镜像
<mirrors>
		<mirror>
				<id>nexus-aliyun</id>
				<mirrorOf>central</mirrorOf>
				<name>Nexus aliyun</name>
				<url>http://maven.aliyun.com/nexus/content/groups/public</url>
		</mirror>
</mirrors>
配置jdk1.8 编译项目
<profiles>
		<profile>
				<id>jdk-1.8</id>
				<activation>
				<activeByDefault>true</activeByDefault>
				<jdk>1.8</jdk>
				</activation>
				<properties>
				<maven.compiler.source>1.8</maven.compiler.source>
				<maven.compiler.target>1.8</maven.compiler.target>
				<maven.compiler.compilerVersion>1.8</maven.compiler.compilerVersion>
				</properties>
		</profile>
</profiles>

3.5.2 Idea&VsCode

  1. idea 安装lombok、mybatisx 插件
    2.下载 vs code软件----前端必备 https://code.visualstudio.com/
  • Vscode 安装开发必备插件
  • Vetur —— 语法高亮、智能感知、Emmet 等,包含格式化功能, Alt+Shift+F (格式化全文),Ctrl+K Ctrl+F(格式化选中代码,两个Ctrl需要同时按着)
  • EsLint —— 语法纠错
  • Auto Close Tag —— 自动闭合HTML/XML 标签
  • Auto Rename Tag —— 自动完成另一侧标签的同步修改
  • JavaScript(ES6) code snippets — — ES6 语法智能提示以及快速输入, 除js 外还支持.ts,.jsx,.tsx,.html,.vue,省去了配置其支持各种包含js 代码文件的时间
  • HTML CSS Support —— 让html 标签上写class 智能提示当前项目所支持的样式
  • HTML Snippets —— html 快速自动补全
  • Open in browser —— 浏览器快速打开
  • Live Server —— 以内嵌服务器方式打开
  • Chinese (Simplified) Language Pack for Visual Studio Code —— 中文语言包

在这里插入图片描述

3.5.3 安装配置git ---- 配合码云

  1. 下载git;https://git-scm.com
  2. 配置git,进入git bash
# 配置用户名
git config --global user.name "username" //(名字)
# 配置邮箱
git config --global user.email "username@email.com" //(注册账号时用的邮箱)
  1. 配置ssh 免密登录----配合码云
    可以参考码云给出的方法。 https://gitee.com/help/articles/4181#article-header0
    进入git bash;使用:ssh-keygen -t rsa -C "xxxxx@xxxxx.com"命令。连续三次回车。
    一般用户目录下会有
    在这里插入图片描述
    或者cat ~/.ssh/id_rsa.pub
    登录进入gitee,在设置里面找到SSH KEY 将.pub 文件的内容粘贴进去
    使用ssh -T git@gitee.com 测试是否成功即可

Git+码云教程 https://gitee.com/help/articles/4104

3.5.4 创建谷粒商城基础项目仓库----以码云为例

在这里插入图片描述
远程仓库创建之后在idea中进行clone下载到本地项目。
在这里插入图片描述

3.3.6 创建微服务

老师课件
在这里插入图片描述
在这里插入图片描述
同理创建其他微服务。
Group:com.atguigu.gulimall
Artifact: gulimall-product gulimall-order gulimall-ware gulimall-member gulimall-coupon

每个微服务必备: web openfeign
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
项目架构:
在这里插入图片描述
在这里插入图片描述
在父工程的.gitignore文件中设置我们要忽略的文件。
在这里插入图片描述
在这里插入图片描述

3.3.7 数据库 准备

创建数据库。
在这里插入图片描述
对于数据库设计,这些在后面会讲到。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

每一个微服务对应的数据库,进行分库分表。
注意不要设置外键,因为几十万条数据,设置外键,修改,检索需要同时修改。浪费资源。
在这里插入图片描述
在这里插入图片描述

drop table if exists oms_order;

drop table if exists oms_order_item;

drop table if exists oms_order_operate_history;

drop table if exists oms_order_return_apply;

drop table if exists oms_order_return_reason;

drop table if exists oms_order_setting;

drop table if exists oms_payment_info;

drop table if exists oms_refund_info;

/*==============================================================*/
/* Table: oms_order                                             */
/*==============================================================*/
create table oms_order
(
   id                   bigint not null auto_increment comment 'id',
   member_id            bigint comment 'member_id',
   order_sn             char(32) comment '订单号',
   coupon_id            bigint comment '使用的优惠券',
   create_time          datetime comment 'create_time',
   member_username      varchar(200) comment '用户名',
   total_amount         decimal(18,4) comment '订单总额',
   pay_amount           decimal(18,4) comment '应付总额',
   freight_amount       decimal(18,4) comment '运费金额',
   promotion_amount     decimal(18,4) comment '促销优化金额(促销价、满减、阶梯价)',
   integration_amount   decimal(18,4) comment '积分抵扣金额',
   coupon_amount        decimal(18,4) comment '优惠券抵扣金额',
   discount_amount      decimal(18,4) comment '后台调整订单使用的折扣金额',
   pay_type             tinyint comment '支付方式【1->支付宝;2->微信;3->银联; 4->货到付款;】',
   source_type          tinyint comment '订单来源[0->PC订单;1->app订单]',
   status               tinyint comment '订单状态【0->待付款;1->待发货;2->已发货;3->已完成;4->已关闭;5->无效订单】',
   delivery_company     varchar(64) comment '物流公司(配送方式)',
   delivery_sn          varchar(64) comment '物流单号',
   auto_confirm_day     int comment '自动确认时间(天)',
   integration          int comment '可以获得的积分',
   growth               int comment '可以获得的成长值',
   bill_type            tinyint comment '发票类型[0->不开发票;1->电子发票;2->纸质发票]',
   bill_header          varchar(255) comment '发票抬头',
   bill_content         varchar(255) comment '发票内容',
   bill_receiver_phone  varchar(32) comment '收票人电话',
   bill_receiver_email  varchar(64) comment '收票人邮箱',
   receiver_name        varchar(100) comment '收货人姓名',
   receiver_phone       varchar(32) comment '收货人电话',
   receiver_post_code   varchar(32) comment '收货人邮编',
   receiver_province    varchar(32) comment '省份/直辖市',
   receiver_city        varchar(32) comment '城市',
   receiver_region      varchar(32) comment '区',
   receiver_detail_address varchar(200) comment '详细地址',
   note                 varchar(500) comment '订单备注',
   confirm_status       tinyint comment '确认收货状态[0->未确认;1->已确认]',
   delete_status        tinyint comment '删除状态【0->未删除;1->已删除】',
   use_integration      int comment '下单时使用的积分',
   payment_time         datetime comment '支付时间',
   delivery_time        datetime comment '发货时间',
   receive_time         datetime comment '确认收货时间',
   comment_time         datetime comment '评价时间',
   modify_time          datetime comment '修改时间',
   primary key (id)
);

alter table oms_order comment '订单';

/*==============================================================*/
/* Table: oms_order_item                                        */
/*==============================================================*/
create table oms_order_item
(
   id                   bigint not null auto_increment comment 'id',
   order_id             bigint comment 'order_id',
   order_sn             char(32) comment 'order_sn',
   spu_id               bigint comment 'spu_id',
   spu_name             varchar(255) comment 'spu_name',
   spu_pic              varchar(500) comment 'spu_pic',
   spu_brand            varchar(200) comment '品牌',
   category_id          bigint comment '商品分类id',
   sku_id               bigint comment '商品sku编号',
   sku_name             varchar(255) comment '商品sku名字',
   sku_pic              varchar(500) comment '商品sku图片',
   sku_price            decimal(18,4) comment '商品sku价格',
   sku_quantity         int comment '商品购买的数量',
   sku_attrs_vals       varchar(500) comment '商品销售属性组合(JSON)',
   promotion_amount     decimal(18,4) comment '商品促销分解金额',
   coupon_amount        decimal(18,4) comment '优惠券优惠分解金额',
   integration_amount   decimal(18,4) comment '积分优惠分解金额',
   real_amount          decimal(18,4) comment '该商品经过优惠后的分解金额',
   gift_integration     int comment '赠送积分',
   gift_growth          int comment '赠送成长值',
   primary key (id)
);

alter table oms_order_item comment '订单项信息';

/*==============================================================*/
/* Table: oms_order_operate_history                             */
/*==============================================================*/
create table oms_order_operate_history
(
   id                   bigint not null auto_increment comment 'id',
   order_id             bigint comment '订单id',
   operate_man          varchar(100) comment '操作人[用户;系统;后台管理员]',
   create_time          datetime comment '操作时间',
   order_status         tinyint comment '订单状态【0->待付款;1->待发货;2->已发货;3->已完成;4->已关闭;5->无效订单】',
   note                 varchar(500) comment '备注',
   primary key (id)
);

alter table oms_order_operate_history comment '订单操作历史记录';

/*==============================================================*/
/* Table: oms_order_return_apply                                */
/*==============================================================*/
create table oms_order_return_apply
(
   id                   bigint not null auto_increment comment 'id',
   order_id             bigint comment 'order_id',
   sku_id               bigint comment '退货商品id',
   order_sn             char(32) comment '订单编号',
   create_time          datetime comment '申请时间',
   member_username      varchar(64) comment '会员用户名',
   return_amount        decimal(18,4) comment '退款金额',
   return_name          varchar(100) comment '退货人姓名',
   return_phone         varchar(20) comment '退货人电话',
   status               tinyint(1) comment '申请状态[0->待处理;1->退货中;2->已完成;3->已拒绝]',
   handle_time          datetime comment '处理时间',
   sku_img              varchar(500) comment '商品图片',
   sku_name             varchar(200) comment '商品名称',
   sku_brand            varchar(200) comment '商品品牌',
   sku_attrs_vals       varchar(500) comment '商品销售属性(JSON)',
   sku_count            int comment '退货数量',
   sku_price            decimal(18,4) comment '商品单价',
   sku_real_price       decimal(18,4) comment '商品实际支付单价',
   reason               varchar(200) comment '原因',
   description述         varchar(500) comment '描述',
   desc_pics            varchar(2000) comment '凭证图片,以逗号隔开',
   handle_note          varchar(500) comment '处理备注',
   handle_man           varchar(200) comment '处理人员',
   receive_man          varchar(100) comment '收货人',
   receive_time         datetime comment '收货时间',
   receive_note         varchar(500) comment '收货备注',
   receive_phone        varchar(20) comment '收货电话',
   company_address      varchar(500) comment '公司收货地址',
   primary key (id)
);

alter table oms_order_return_apply comment '订单退货申请';

/*==============================================================*/
/* Table: oms_order_return_reason                               */
/*==============================================================*/
create table oms_order_return_reason
(
   id                   bigint not null auto_increment comment 'id',
   name                 varchar(200) comment '退货原因名',
   sort                 int comment '排序',
   status               tinyint(1) comment '启用状态',
   create_time          datetime comment 'create_time',
   primary key (id)
);

alter table oms_order_return_reason comment '退货原因';

/*==============================================================*/
/* Table: oms_order_setting                                     */
/*==============================================================*/
create table oms_order_setting
(
   id                   bigint not null auto_increment comment 'id',
   flash_order_overtime int comment '秒杀订单超时关闭时间(分)',
   normal_order_overtime int comment '正常订单超时时间(分)',
   confirm_overtime     int comment '发货后自动确认收货时间(天)',
   finish_overtime      int comment '自动完成交易时间,不能申请退货(天)',
   comment_overtime     int comment '订单完成后自动好评时间(天)',
   member_level         tinyint(2) comment '会员等级【0-不限会员等级,全部通用;其他-对应的其他会员等级】',
   primary key (id)
);

alter table oms_order_setting comment '订单配置信息';

/*==============================================================*/
/* Table: oms_payment_info                                      */
/*==============================================================*/
create table oms_payment_info
(
   id                   bigint not null auto_increment comment 'id',
   order_sn             char(32) comment '订单号(对外业务号)',
   order_id             bigint comment '订单id',
   alipay_trade_no      varchar(50) comment '支付宝交易流水号',
   total_amount         decimal(18,4) comment '支付总金额',
   subject              varchar(200) comment '交易内容',
   payment_status       varchar(20) comment '支付状态',
   create_time          datetime comment '创建时间',
   confirm_time         datetime comment '确认时间',
   callback_content     varchar(4000) comment '回调内容',
   callback_time        datetime comment '回调时间',
   primary key (id)
);

alter table oms_payment_info comment '支付信息表';

/*==============================================================*/
/* Table: oms_refund_info                                       */
/*==============================================================*/
create table oms_refund_info
(
   id                   bigint not null auto_increment comment 'id',
   order_return_id      bigint comment '退款的订单',
   refund               decimal(18,4) comment '退款金额',
   refund_sn            varchar(64) comment '退款交易流水号',
   refund_status        tinyint(1) comment '退款状态',
   refund_channel       tinyint comment '退款渠道[1-支付宝,2-微信,3-银联,4-汇款]',
   refund_content       varchar(5000),
   primary key (id)
);

alter table oms_refund_info comment '退款信息';

在这里插入图片描述

drop table if exists pms_attr;

drop table if exists pms_attr_attrgroup_relation;

drop table if exists pms_attr_group;

drop table if exists pms_brand;

drop table if exists pms_category;

drop table if exists pms_category_brand_relation;

drop table if exists pms_comment_replay;

drop table if exists pms_product_attr_value;

drop table if exists pms_sku_images;

drop table if exists pms_sku_info;

drop table if exists pms_sku_sale_attr_value;

drop table if exists pms_spu_comment;

drop table if exists pms_spu_images;

drop table if exists pms_spu_info;

drop table if exists pms_spu_info_desc;

/*==============================================================*/
/* Table: pms_attr                                              */
/*==============================================================*/
create table pms_attr
(
   attr_id              bigint not null auto_increment comment '属性id',
   attr_name            char(30) comment '属性名',
   search_type          tinyint comment '是否需要检索[0-不需要,1-需要]',
  `value_type` tinyint(4) DEFAULT NULL COMMENT '值类型[0-为单个值,1-可以选择多个值]',
  `icon` varchar(255) DEFAULT NULL COMMENT '属性图标',
  `value_select` char(255) DEFAULT NULL COMMENT '可选值列表[用逗号分隔]',
  `attr_type` tinyint(4) DEFAULT NULL COMMENT '属性类型[0-销售属性,1-基本属性,2-既是销售属性又是基本属性]',
   enable               bigint comment '启用状态[0 - 禁用,1 - 启用]',
   catelog_id           bigint comment '所属分类',
   show_desc            tinyint comment '快速展示【是否展示在介绍上;0-否 1-是】,在sku中仍然可以调整',
   primary key (attr_id)
);

alter table pms_attr comment '商品属性';

/*==============================================================*/
/* Table: pms_attr_attrgroup_relation                           */
/*==============================================================*/
create table pms_attr_attrgroup_relation
(
   id                   bigint not null auto_increment comment 'id',
   attr_id              bigint comment '属性id',
   attr_group_id        bigint comment '属性分组id',
   attr_sort            int comment '属性组内排序',
   primary key (id)
);

alter table pms_attr_attrgroup_relation comment '属性&属性分组关联';

/*==============================================================*/
/* Table: pms_attr_group                                        */
/*==============================================================*/
create table pms_attr_group
(
   attr_group_id        bigint not null auto_increment comment '分组id',
   attr_group_name      char(20) comment '组名',
   sort                 int comment '排序',
   descript             varchar(255) comment '描述',
   icon                 varchar(255) comment '组图标',
   catelog_id           bigint comment '所属分类id',
   primary key (attr_group_id)
);

alter table pms_attr_group comment '属性分组';

/*==============================================================*/
/* Table: pms_brand                                             */
/*==============================================================*/
create table pms_brand
(
   brand_id             bigint not null auto_increment comment '品牌id',
   name                 char(50) comment '品牌名',
   logo                 varchar(2000) comment '品牌logo地址',
   descript             longtext comment '介绍',
   show_status          tinyint comment '显示状态[0-不显示;1-显示]',
   first_letter         char(1) comment '检索首字母',
   sort                 int comment '排序',
   primary key (brand_id)
);

alter table pms_brand comment '品牌';

/*==============================================================*/
/* Table: pms_category                                          */
/*==============================================================*/
create table pms_category
(
   cat_id               bigint not null auto_increment comment '分类id',
   name                 char(50) comment '分类名称',
   parent_cid           bigint comment '父分类id',
   cat_level            int comment '层级',
   show_status          tinyint comment '是否显示[0-不显示,1显示]',
   sort                 int comment '排序',
   icon                 char(255) comment '图标地址',
   product_unit         char(50) comment '计量单位',
   product_count        int comment '商品数量',
   primary key (cat_id)
);

alter table pms_category comment '商品三级分类';

/*==============================================================*/
/* Table: pms_category_brand_relation                           */
/*==============================================================*/
create table pms_category_brand_relation
(
   id                   bigint not null auto_increment,
   brand_id             bigint comment '品牌id',
   catelog_id           bigint comment '分类id',
   brand_name           varchar(255),
   catelog_name         varchar(255),
   primary key (id)
);

alter table pms_category_brand_relation comment '品牌分类关联';

/*==============================================================*/
/* Table: pms_comment_replay                                    */
/*==============================================================*/
create table pms_comment_replay
(
   id                   bigint not null auto_increment comment 'id',
   comment_id           bigint comment '评论id',
   reply_id             bigint comment '回复id',
   primary key (id)
);

alter table pms_comment_replay comment '商品评价回复关系';

/*==============================================================*/
/* Table: pms_product_attr_value                                */
/*==============================================================*/
create table pms_product_attr_value
(
   id                   bigint not null auto_increment comment 'id',
   spu_id               bigint comment '商品id',
   attr_id              bigint comment '属性id',
   attr_name            varchar(200) comment '属性名',
   attr_value           varchar(200) comment '属性值',
   attr_sort            int comment '顺序',
   quick_show           tinyint comment '快速展示【是否展示在介绍上;0-否 1-是】',
   primary key (id)
);

alter table pms_product_attr_value comment 'spu属性值';

/*==============================================================*/
/* Table: pms_sku_images                                        */
/*==============================================================*/
create table pms_sku_images
(
   id                   bigint not null auto_increment comment 'id',
   sku_id               bigint comment 'sku_id',
   img_url              varchar(255) comment '图片地址',
   img_sort             int comment '排序',
   default_img          int comment '默认图[0 - 不是默认图,1 - 是默认图]',
   primary key (id)
);

alter table pms_sku_images comment 'sku图片';

/*==============================================================*/
/* Table: pms_sku_info                                          */
/*==============================================================*/
create table pms_sku_info
(
   sku_id               bigint not null auto_increment comment 'skuId',
   spu_id               bigint comment 'spuId',
   sku_name             varchar(255) comment 'sku名称',
   sku_desc             varchar(2000) comment 'sku介绍描述',
   catalog_id           bigint comment '所属分类id',
   brand_id             bigint comment '品牌id',
   sku_default_img      varchar(255) comment '默认图片',
   sku_title            varchar(255) comment '标题',
   sku_subtitle         varchar(2000) comment '副标题',
   price                decimal(18,4) comment '价格',
   sale_count           bigint comment '销量',
   primary key (sku_id)
);

alter table pms_sku_info comment 'sku信息';

/*==============================================================*/
/* Table: pms_sku_sale_attr_value                               */
/*==============================================================*/
create table pms_sku_sale_attr_value
(
   id                   bigint not null auto_increment comment 'id',
   sku_id               bigint comment 'sku_id',
   attr_id              bigint comment 'attr_id',
   attr_name            varchar(200) comment '销售属性名',
   attr_value           varchar(200) comment '销售属性值',
   attr_sort            int comment '顺序',
   primary key (id)
);

alter table pms_sku_sale_attr_value comment 'sku销售属性&值';

/*==============================================================*/
/* Table: pms_spu_comment                                       */
/*==============================================================*/
create table pms_spu_comment
(
   id                   bigint not null auto_increment comment 'id',
   sku_id               bigint comment 'sku_id',
   spu_id               bigint comment 'spu_id',
   spu_name             varchar(255) comment '商品名字',
   member_nick_name     varchar(255) comment '会员昵称',
   star                 tinyint(1) comment '星级',
   member_ip            varchar(64) comment '会员ip',
   create_time          datetime comment '创建时间',
   show_status          tinyint(1) comment '显示状态[0-不显示,1-显示]',
   spu_attributes       varchar(255) comment '购买时属性组合',
   likes_count          int comment '点赞数',
   reply_count          int comment '回复数',
   resources            varchar(1000) comment '评论图片/视频[json数据;[{type:文件类型,url:资源路径}]]',
   content              text comment '内容',
   member_icon          varchar(255) comment '用户头像',
   comment_type         tinyint comment '评论类型[0 - 对商品的直接评论,1 - 对评论的回复]',
   primary key (id)
);

alter table pms_spu_comment comment '商品评价';

/*==============================================================*/
/* Table: pms_spu_images                                        */
/*==============================================================*/
create table pms_spu_images
(
   id                   bigint not null auto_increment comment 'id',
   spu_id               bigint comment 'spu_id',
   img_name             varchar(200) comment '图片名',
   img_url              varchar(255) comment '图片地址',
   img_sort             int comment '顺序',
   default_img          tinyint comment '是否默认图',
   primary key (id)
);

alter table pms_spu_images comment 'spu图片';

/*==============================================================*/
/* Table: pms_spu_info                                          */
/*==============================================================*/
create table pms_spu_info
(
   id                   bigint not null auto_increment comment '商品id',
   spu_name             varchar(200) comment '商品名称',
   spu_description      varchar(1000) comment '商品描述',
   catalog_id           bigint comment '所属分类id',
   brand_id             bigint comment '品牌id',
   weight               decimal(18,4),
   publish_status       tinyint comment '上架状态[0 - 下架,1 - 上架]',
   create_time          datetime,
   update_time          datetime,
   primary key (id)
);

alter table pms_spu_info comment 'spu信息';

/*==============================================================*/
/* Table: pms_spu_info_desc                                     */
/*==============================================================*/
create table pms_spu_info_desc
(
   spu_id               bigint not null comment '商品id',
   decript              longtext comment '商品介绍',
   primary key (spu_id)
);

alter table pms_spu_info_desc comment 'spu信息介绍';

在这里插入图片描述

drop table if exists sms_coupon;

drop table if exists sms_coupon_history;

drop table if exists sms_coupon_spu_category_relation;

drop table if exists sms_coupon_spu_relation;

drop table if exists sms_home_adv;

drop table if exists sms_home_subject;

drop table if exists sms_home_subject_spu;

drop table if exists sms_member_price;

drop table if exists sms_seckill_promotion;

drop table if exists sms_seckill_session;

drop table if exists sms_seckill_sku_notice;

drop table if exists sms_seckill_sku_relation;

drop table if exists sms_sku_full_reduction;

drop table if exists sms_sku_ladder;

drop table if exists sms_spu_bounds;

/*==============================================================*/
/* Table: sms_coupon                                            */
/*==============================================================*/
create table sms_coupon
(
   id                   bigint not null auto_increment comment 'id',
   coupon_type          tinyint(1) comment '优惠卷类型[0->全场赠券;1->会员赠券;2->购物赠券;3->注册赠券]',
   coupon_img           varchar(2000) comment '优惠券图片',
   coupon_name          varchar(100) comment '优惠卷名字',
   num                  int comment '数量',
   amount               decimal(18,4) comment '金额',
   per_limit            int comment '每人限领张数',
   min_point            decimal(18,4) comment '使用门槛',
   start_time           datetime comment '开始时间',
   end_time             datetime comment '结束时间',
   use_type             tinyint(1) comment '使用类型[0->全场通用;1->指定分类;2->指定商品]',
   note                 varchar(200) comment '备注',
   publish_count        int(11) comment '发行数量',
   use_count            int(11) comment '已使用数量',
   receive_count        int(11) comment '领取数量',
   enable_start_time    datetime comment '可以领取的开始日期',
   enable_end_time      datetime comment '可以领取的结束日期',
   code                 varchar(64) comment '优惠码',
   member_level         tinyint(1) comment '可以领取的会员等级[0->不限等级,其他-对应等级]',
   publish              tinyint(1) comment '发布状态[0-未发布,1-已发布]',
   primary key (id)
);

alter table sms_coupon comment '优惠券信息';

/*==============================================================*/
/* Table: sms_coupon_history                                    */
/*==============================================================*/
create table sms_coupon_history
(
   id                   bigint not null auto_increment comment 'id',
   coupon_id            bigint comment '优惠券id',
   member_id            bigint comment '会员id',
   member_nick_name     varchar(64) comment '会员名字',
   get_type             tinyint(1) comment '获取方式[0->后台赠送;1->主动领取]',
   create_time          datetime comment '创建时间',
   use_type             tinyint(1) comment '使用状态[0->未使用;1->已使用;2->已过期]',
   use_time             datetime comment '使用时间',
   order_id             bigint comment '订单id',
   order_sn             bigint comment '订单号',
   primary key (id)
);

alter table sms_coupon_history comment '优惠券领取历史记录';

/*==============================================================*/
/* Table: sms_coupon_spu_category_relation                      */
/*==============================================================*/
create table sms_coupon_spu_category_relation
(
   id                   bigint not null auto_increment comment 'id',
   coupon_id            bigint comment '优惠券id',
   category_id          bigint comment '产品分类id',
   category_name        varchar(64) comment '产品分类名称',
   primary key (id)
);

alter table sms_coupon_spu_category_relation comment '优惠券分类关联';

/*==============================================================*/
/* Table: sms_coupon_spu_relation                               */
/*==============================================================*/
create table sms_coupon_spu_relation
(
   id                   bigint not null auto_increment comment 'id',
   coupon_id            bigint comment '优惠券id',
   spu_id               bigint comment 'spu_id',
   spu_name             varchar(255) comment 'spu_name',
   primary key (id)
);

alter table sms_coupon_spu_relation comment '优惠券与产品关联';

/*==============================================================*/
/* Table: sms_home_adv                                          */
/*==============================================================*/
create table sms_home_adv
(
   id                   bigint not null auto_increment comment 'id',
   name                 varchar(100) comment '名字',
   pic                  varchar(500) comment '图片地址',
   start_time           datetime comment '开始时间',
   end_time             datetime comment '结束时间',
   status               tinyint(1) comment '状态',
   click_count          int comment '点击数',
   url                  varchar(500) comment '广告详情连接地址',
   note                 varchar(500) comment '备注',
   sort                 int comment '排序',
   publisher_id         bigint comment '发布者',
   auth_id              bigint comment '审核者',
   primary key (id)
);

alter table sms_home_adv comment '首页轮播广告';

/*==============================================================*/
/* Table: sms_home_subject                                      */
/*==============================================================*/
create table sms_home_subject
(
   id                   bigint not null auto_increment comment 'id',
   name                 varchar(200) comment '专题名字',
   title                varchar(255) comment '专题标题',
   sub_title            varchar(255) comment '专题副标题',
   status               tinyint(1) comment '显示状态',
   url                  varchar(500) comment '详情连接',
   sort                 int comment '排序',
   img                  varchar(500) comment '专题图片地址',
   primary key (id)
);

alter table sms_home_subject comment '首页专题表【jd首页下面很多专题,每个专题链接新的页面,展示专题商品信息】';

/*==============================================================*/
/* Table: sms_home_subject_spu                                  */
/*==============================================================*/
create table sms_home_subject_spu
(
   id                   bigint not null auto_increment comment 'id',
   name                 varchar(200) comment '专题名字',
   subject_id           bigint comment '专题id',
   spu_id               bigint comment 'spu_id',
   sort                 int comment '排序',
   primary key (id)
);

alter table sms_home_subject_spu comment '专题商品';

/*==============================================================*/
/* Table: sms_member_price                                      */
/*==============================================================*/
create table sms_member_price
(
   id                   bigint not null auto_increment comment 'id',
   sku_id               bigint comment 'sku_id',
   member_level_id      bigint comment '会员等级id',
   member_level_name    varchar(100) comment '会员等级名',
   member_price         decimal(18,4) comment '会员对应价格',
   add_other            tinyint(1) comment '可否叠加其他优惠[0-不可叠加优惠,1-可叠加]',
   primary key (id)
);

alter table sms_member_price comment '商品会员价格';

/*==============================================================*/
/* Table: sms_seckill_promotion                                 */
/*==============================================================*/
create table sms_seckill_promotion
(
   id                   bigint not null auto_increment comment 'id',
   title                varchar(255) comment '活动标题',
   start_time           datetime comment '开始日期',
   end_time             datetime comment '结束日期',
   status               tinyint comment '上下线状态',
   create_time          datetime comment '创建时间',
   user_id              bigint comment '创建人',
   primary key (id)
);

alter table sms_seckill_promotion comment '秒杀活动';

/*==============================================================*/
/* Table: sms_seckill_session                                   */
/*==============================================================*/
create table sms_seckill_session
(
   id                   bigint not null auto_increment comment 'id',
   name                 varchar(200) comment '场次名称',
   start_time           datetime comment '每日开始时间',
   end_time             datetime comment '每日结束时间',
   status               tinyint(1) comment '启用状态',
   create_time          datetime comment '创建时间',
   primary key (id)
);

alter table sms_seckill_session comment '秒杀活动场次';

/*==============================================================*/
/* Table: sms_seckill_sku_notice                                */
/*==============================================================*/
create table sms_seckill_sku_notice
(
   id                   bigint not null auto_increment comment 'id',
   member_id            bigint comment 'member_id',
   sku_id               bigint comment 'sku_id',
   session_id           bigint comment '活动场次id',
   subcribe_time        datetime comment '订阅时间',
   send_time            datetime comment '发送时间',
   notice_type          tinyint(1) comment '通知方式[0-短信,1-邮件]',
   primary key (id)
);

alter table sms_seckill_sku_notice comment '秒杀商品通知订阅';

/*==============================================================*/
/* Table: sms_seckill_sku_relation                              */
/*==============================================================*/
create table sms_seckill_sku_relation
(
   id                   bigint not null auto_increment comment 'id',
   promotion_id         bigint comment '活动id',
   promotion_session_id bigint comment '活动场次id',
   sku_id               bigint comment '商品id',
   seckill_price        decimal comment '秒杀价格',
   seckill_count        decimal comment '秒杀总量',
   seckill_limit        decimal comment '每人限购数量',
   seckill_sort         int comment '排序',
   primary key (id)
);

alter table sms_seckill_sku_relation comment '秒杀活动商品关联';

/*==============================================================*/
/* Table: sms_sku_full_reduction                                */
/*==============================================================*/
create table sms_sku_full_reduction
(
   id                   bigint not null auto_increment comment 'id',
   sku_id               bigint comment 'spu_id',
   full_price           decimal(18,4) comment '满多少',
   reduce_price         decimal(18,4) comment '减多少',
   add_other            tinyint(1) comment '是否参与其他优惠',
   primary key (id)
);

alter table sms_sku_full_reduction comment '商品满减信息';

/*==============================================================*/
/* Table: sms_sku_ladder                                        */
/*==============================================================*/
create table sms_sku_ladder
(
   id                   bigint not null auto_increment comment 'id',
   sku_id               bigint comment 'spu_id',
   full_count           int comment '满几件',
   discount             decimal(4,2) comment '打几折',
   price                decimal(18,4) comment '折后价',
   add_other            tinyint(1) comment '是否叠加其他优惠[0-不可叠加,1-可叠加]',
   primary key (id)
);

alter table sms_sku_ladder comment '商品阶梯价格';

/*==============================================================*/
/* Table: sms_spu_bounds                                        */
/*==============================================================*/
create table sms_spu_bounds
(
   id                   bigint not null auto_increment comment 'id',
   spu_id               bigint,
   grow_bounds          decimal(18,4) comment '成长积分',
   buy_bounds           decimal(18,4) comment '购物积分',
   work                 tinyint(1) comment '优惠生效情况[1111(四个状态位,从右到左);0 - 无优惠,成长积分是否赠送;1 - 无优惠,购物积分是否赠送;2 - 有优惠,成长积分是否赠送;3 - 有优惠,购物积分是否赠送【状态位0:不赠送,1:赠送】]',
   primary key (id)
);

alter table sms_spu_bounds comment '商品spu积分设置';

在这里插入图片描述

drop table if exists ums_growth_change_history;

drop table if exists ums_integration_change_history;

drop table if exists ums_member;

drop table if exists ums_member_collect_spu;

drop table if exists ums_member_collect_subject;

drop table if exists ums_member_level;

drop table if exists ums_member_login_log;

drop table if exists ums_member_receive_address;

drop table if exists ums_member_statistics_info;

/*==============================================================*/
/* Table: ums_growth_change_history                             */
/*==============================================================*/
create table ums_growth_change_history
(
   id                   bigint not null auto_increment comment 'id',
   member_id            bigint comment 'member_id',
   create_time          datetime comment 'create_time',
   change_count         int comment '改变的值(正负计数)',
   note                 varchar(0) comment '备注',
   source_type          tinyint comment '积分来源[0-购物,1-管理员修改]',
   primary key (id)
);

alter table ums_growth_change_history comment '成长值变化历史记录';

/*==============================================================*/
/* Table: ums_integration_change_history                        */
/*==============================================================*/
create table ums_integration_change_history
(
   id                   bigint not null auto_increment comment 'id',
   member_id            bigint comment 'member_id',
   create_time          datetime comment 'create_time',
   change_count         int comment '变化的值',
   note                 varchar(255) comment '备注',
   source_tyoe          tinyint comment '来源[0->购物;1->管理员修改;2->活动]',
   primary key (id)
);

alter table ums_integration_change_history comment '积分变化历史记录';

/*==============================================================*/
/* Table: ums_member                                            */
/*==============================================================*/
create table ums_member
(
   id                   bigint not null auto_increment comment 'id',
   level_id             bigint comment '会员等级id',
   username             char(64) comment '用户名',
   password             varchar(64) comment '密码',
   nickname             varchar(64) comment '昵称',
   mobile               varchar(20) comment '手机号码',
   email                varchar(64) comment '邮箱',
   header               varchar(500) comment '头像',
   gender               tinyint comment '性别',
   birth                date comment '生日',
   city                 varchar(500) comment '所在城市',
   job                  varchar(255) comment '职业',
   sign                 varchar(255) comment '个性签名',
   source_type          tinyint comment '用户来源',
   integration          int comment '积分',
   growth               int comment '成长值',
   status               tinyint comment '启用状态',
   create_time          datetime comment '注册时间',
   primary key (id)
);

alter table ums_member comment '会员';

/*==============================================================*/
/* Table: ums_member_collect_spu                                */
/*==============================================================*/
create table ums_member_collect_spu
(
   id                   bigint not null comment 'id',
   member_id            bigint comment '会员id',
   spu_id               bigint comment 'spu_id',
   spu_name             varchar(500) comment 'spu_name',
   spu_img              varchar(500) comment 'spu_img',
   create_time          datetime comment 'create_time',
   primary key (id)
);

alter table ums_member_collect_spu comment '会员收藏的商品';

/*==============================================================*/
/* Table: ums_member_collect_subject                            */
/*==============================================================*/
create table ums_member_collect_subject
(
   id                   bigint not null auto_increment comment 'id',
   subject_id           bigint comment 'subject_id',
   subject_name         varchar(255) comment 'subject_name',
   subject_img          varchar(500) comment 'subject_img',
   subject_urll         varchar(500) comment '活动url',
   primary key (id)
);

alter table ums_member_collect_subject comment '会员收藏的专题活动';

/*==============================================================*/
/* Table: ums_member_level                                      */
/*==============================================================*/
create table ums_member_level
(
   id                   bigint not null auto_increment comment 'id',
   name                 varchar(100) comment '等级名称',
   growth_point         int comment '等级需要的成长值',
   default_status       tinyint comment '是否为默认等级[0->不是;1->是]',
   free_freight_point   decimal(18,4) comment '免运费标准',
   comment_growth_point int comment '每次评价获取的成长值',
   priviledge_free_freight tinyint comment '是否有免邮特权',
   priviledge_member_price tinyint comment '是否有会员价格特权',
   priviledge_birthday  tinyint comment '是否有生日特权',
   note                 varchar(255) comment '备注',
   primary key (id)
);

alter table ums_member_level comment '会员等级';

/*==============================================================*/
/* Table: ums_member_login_log                                  */
/*==============================================================*/
create table ums_member_login_log
(
   id                   bigint not null auto_increment comment 'id',
   member_id            bigint comment 'member_id',
   create_time          datetime comment '创建时间',
   ip                   varchar(64) comment 'ip',
   city                 varchar(64) comment 'city',
   login_type           tinyint(1) comment '登录类型[1-web,2-app]',
   primary key (id)
);

alter table ums_member_login_log comment '会员登录记录';

/*==============================================================*/
/* Table: ums_member_receive_address                            */
/*==============================================================*/
create table ums_member_receive_address
(
   id                   bigint not null auto_increment comment 'id',
   member_id            bigint comment 'member_id',
   name                 varchar(255) comment '收货人姓名',
   phone                varchar(64) comment '电话',
   post_code            varchar(64) comment '邮政编码',
   province             varchar(100) comment '省份/直辖市',
   city                 varchar(100) comment '城市',
   region               varchar(100) comment '区',
   detail_address       varchar(255) comment '详细地址(街道)',
   areacode             varchar(15) comment '省市区代码',
   default_status       tinyint(1) comment '是否默认',
   primary key (id)
);

alter table ums_member_receive_address comment '会员收货地址';

/*==============================================================*/
/* Table: ums_member_statistics_info                            */
/*==============================================================*/
create table ums_member_statistics_info
(
   id                   bigint not null auto_increment comment 'id',
   member_id            bigint comment '会员id',
   consume_amount       decimal(18,4) comment '累计消费金额',
   coupon_amount        decimal(18,4) comment '累计优惠金额',
   order_count          int comment '订单数量',
   coupon_count         int comment '优惠券数量',
   comment_count        int comment '评价数',
   return_order_count   int comment '退货数量',
   login_count          int comment '登录次数',
   attend_count         int comment '关注数量',
   fans_count           int comment '粉丝数量',
   collect_product_count int comment '收藏的商品数量',
   collect_subject_count int comment '收藏的专题活动数量',
   collect_comment_count int comment '收藏的评论数量',
   invite_friend_count  int comment '邀请的朋友数量',
   primary key (id)
);

alter table ums_member_statistics_info comment '会员统计信息';

在这里插入图片描述

drop table if exists wms_purchase;

drop table if exists wms_purchase_detail;

drop table if exists wms_ware_info;

drop table if exists wms_ware_order_task;

drop table if exists wms_ware_order_task_detail;

drop table if exists wms_ware_sku;

/*==============================================================*/
/* Table: wms_purchase                                          */
/*==============================================================*/
create table wms_purchase
(
   id                   bigint not null auto_increment comment '采购单id',
   assignee_id          bigint comment '采购人id',
   assignee_name        varchar(255) comment '采购人名',
   phone                char(13) comment '联系方式',
   priority             int(4) comment '优先级',
   status               int(4) comment '状态',
   ware_id              bigint comment '仓库id',
   amount               decimal(18,4) comment '总金额',
   create_time          datetime comment '创建日期',
   update_time          datetime comment '更新日期',
   primary key (id)
);

alter table wms_purchase comment '采购信息';

/*==============================================================*/
/* Table: wms_purchase_detail                                   */
/*==============================================================*/
create table wms_purchase_detail
(
   id                   bigint not null auto_increment,
   purchase_id          bigint comment '采购单id',
   sku_id               bigint comment '采购商品id',
   sku_num              int comment '采购数量',
   sku_price            decimal(18,4) comment '采购金额',
   ware_id              bigint comment '仓库id',
   status               int comment '状态[0新建,1已分配,2正在采购,3已完成,4采购失败]',
   primary key (id)
);

/*==============================================================*/
/* Table: wms_ware_info                                         */
/*==============================================================*/
create table wms_ware_info
(
   id                   bigint not null auto_increment comment 'id',
   name                 varchar(255) comment '仓库名',
   address              varchar(255) comment '仓库地址',
   areacode             varchar(20) comment '区域编码',
   primary key (id)
);

alter table wms_ware_info comment '仓库信息';

/*==============================================================*/
/* Table: wms_ware_order_task                                   */
/*==============================================================*/
create table wms_ware_order_task
(
   id                   bigint not null auto_increment comment 'id',
   order_id             bigint comment 'order_id',
   order_sn             varchar(255) comment 'order_sn',
   consignee            varchar(100) comment '收货人',
   consignee_tel        char(15) comment '收货人电话',
   delivery_address     varchar(500) comment '配送地址',
   order_comment        varchar(200) comment '订单备注',
   payment_way          tinyint(1) comment '付款方式【 1:在线付款 2:货到付款】',
   task_status          tinyint(2) comment '任务状态',
   order_body           varchar(255) comment '订单描述',
   tracking_no          char(30) comment '物流单号',
   create_time          datetime comment 'create_time',
   ware_id              bigint comment '仓库id',
   task_comment         varchar(500) comment '工作单备注',
   primary key (id)
);

alter table wms_ware_order_task comment '库存工作单';

/*==============================================================*/
/* Table: wms_ware_order_task_detail                            */
/*==============================================================*/
create table wms_ware_order_task_detail
(
   id                   bigint not null auto_increment comment 'id',
   sku_id               bigint comment 'sku_id',
   sku_name             varchar(255) comment 'sku_name',
   sku_num              int comment '购买个数',
   task_id              bigint comment '工作单id',
   primary key (id)
);

alter table wms_ware_order_task_detail comment '库存工作单';

/*==============================================================*/
/* Table: wms_ware_sku                                          */
/*==============================================================*/
create table wms_ware_sku
(
   id                   bigint not null auto_increment comment 'id',
   sku_id               bigint comment 'sku_id',
   ware_id              bigint comment '仓库id',
   stock                int comment '库存数',
   sku_name             varchar(200) comment 'sku_name',
   stock_locked         int comment '锁定库存',
   primary key (id)
);

alter table wms_ware_sku comment '商品库存';

3.3.8 安装Node.js

前端开发,少不了node.js;Node.js 是一个基于Chrome V8 引擎的JavaScript 运行环境。
node 下载 :https://nodejs.org/en/
NPM 是随同NodeJS 一起安装的包管理工具,JavaScript-NPM,Java-Maven;
在这里插入图片描述

  • 检查版本
    在这里插入图片描述
  • 配置npm 使用淘宝镜像 npm config set registry http://registry.npm.taobao.org/
    在这里插入图片描述

3.3.9 使用人人开源后台管理系统

去gitee上面搜索人人开源后台管理系统,
在这里插入图片描述
在这里插入图片描述

  • 下载 Git clone到本地
    在这里插入图片描述
  • 将 renren-fast复制到gulimall项目下。并删除掉其中的.git文件夹。
    在这里插入图片描述

在这里插入图片描述
renren-fast-vue到时候用vscode打开,不过一样要删掉里面的git 文件。

  • idea中修改renren-fast配置
    从模块中不难看出,已经自带了sql文件,所以我们去mysql中创建一个数据库,sql即为该模块下自带的sql.

在这里插入图片描述

在这里插入图片描述

  • application-dev.yml文件中修改成我们自己ip地址,数据库连接。
    在这里插入图片描述
  • 启动renren-fast模块
    在这里插入图片描述

在这里插入图片描述
测试后端,正常。
接下来是前端页面。

  • 前端联调。将renren-fast-vue用vs code打开。
    在这里插入图片描述
    控制台输入 npm install ,如果出现错误,关闭vs code之后重新打开即可。
    在这里插入图片描述
    在这里插入图片描述
    然后输入 npm run dev 进行前后端联调。
    在这里插入图片描述
    在这里插入图片描述

3.6 使用代码生成器快速CRUD

3.6.1 以gulimall_pms为例,对应的是product微服务。

  1. 在renren-generator这个模块下修改成我们要连接的数据库名称,账户和密码。
    在这里插入图片描述
  2. 在配置文件中修改成我们要使用代码生成器生成的代码。
    在这里插入图片描述
  3. 浏览器中访问代码生成器,代码生成器会根据配置文件帮我们生成,然后我们全选下载。下载之后是压缩包,我们可以将压缩包解压。
    在这里插入图片描述
  4. 解压之后里面帮我们把代码和sql也一起生成了,main中是代码。
    在这里插入图片描述
    在这里插入图片描述
  • main->resources->src里面的前端代码我们暂时不需要。
    在这里插入图片描述
    在这里插入图片描述

这个里面帮我们也生成了vue代码,目前暂时用不到所以我们需要将其删除。
5. 创建gulimall-common 工程
每一个微服务都需要引入一些相同的依赖和类。我们索性创建一个gulimall-common工程,到时候其他微服务只要引入这个依赖就可以通过maven的传递性引入依赖。
在这里插入图片描述
用代码生成器帮我们生成的这些代码,还多依赖还没有,所以我们需要进行一个微服务公共依赖的导入。
在这里插入图片描述
在这里插入图片描述

3.3.10 gulimall-common依赖引入

  1. gulimall-common中,引入mybatis-plus的依赖。
    在这里插入图片描述

  2. 我们发现controller中有这个@RequiresPermissions这个注解,我们暂时不需要这个。如果我们只是简单的将其在一个微服务的controller中注解掉,那么其他的微服务怎么办呢?
    在这里插入图片描述

  3. 我们直接在代码生成器中controller中的这个注解直接给注释掉。这样以后用这个代码生成器的就不会每个微服务都有了。
    在这里插入图片描述
    修改之后重启代码生成器,然后将其生成的代码生成器的代码中的controller重新复制到gulimall-product模块下。

  4. 整合mybatis-plus

在这里插入图片描述

  • 查看mysql
    在这里插入图片描述
    根据版本找对应的mysql的依赖。其实mysql的依赖的很多都可以直接使用最新的。
<!--导入mysql驱动-->
        <!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.17</version>
        </dependency>
  • 引入servlet-api依赖
    在这里插入图片描述
  • 有些暂时用不掉的我们可以删掉。
    在这里插入图片描述
    在这里插入图片描述
    我们到时候不用这个。
    在这里插入图片描述
  • 创建application.yml中配置数据源

    在这里插入图片描述
  • 注意这里会一个这个会报错。
    在这里插入图片描述
    最开始我的解决办法是:将接口放到utils下面。但是这个解决办法应该是错误的,因为工具类总一般是不会放置接口。
    在这里插入图片描述
    暂时解决办法是:直接导入renren这个依赖
    在这里插入图片描述
    在gulimall-product中简单进行测试。
    在这里插入图片描述
    测试通过。
    在这里插入图片描述
    在数据库中查看是否保存成功。
    在这里插入图片描述
    在这里插入图片描述
    同时也可以测试其他的
    在这里插入图片描述
  • 同理快速生成其他微服务。比如说gulimall-sms这个优惠服务。
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    测试:
    在这里插入图片描述
  • ums 用户微服务
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
  • 对每一个微服务设置端口
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    测试
  • 注意这里的product端口改为的是11000,因为深信服vpn占用了10000端口,ware改为12000端口。
  • 在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
  • wms 仓储微服务
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    测试
    在这里插入图片描述

4 springcloud alibaba

4.1 SpringCloud Alibaba-Nacos[作为注册中心]

4.1.1 下载

地址:https://github.com/alibaba/nacos/releases?page=3 下载这个版本的保持和老师教课一样,避免其他版本问题。
在这里插入图片描述

4.1.2 启动nacos:

  • 双击bin 中的startup.cmd 文件
  • 访问http://localhost:8848/nacos/
  • 使用默认的nacos/nacos 进行登录

在这里插入图片描述

4.1.3 将微服务注册到nacos中

  • 首先,修改pom.xml 文件,引入Nacos Discovery Starter
<dependency>
		<groupId>com.alibaba.cloud</groupId>
		<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
  • 在应用的/src/main/resources/application.properties 配置文件中配置Nacos Server 地址
    spring.cloud.nacos.discovery.server-addr=127.0.0.1:8848

  • 使用@EnableDiscoveryClient 开启服务注册发现功能
    在这里插入图片描述

  • 启动应用,观察nacos 服务列表是否已经注册上服务.

Nacos 使用三步
1、导包nacos-discovery
2、写配置,指定nacos 地址,指定应用的名字
3、开启服务注册发现功能@EnableDiscoveryClient

在这里插入图片描述

4.2 注册更多的服务上去,测试使用feign 远程调用

在这里插入图片描述
本次以gulimall-coupon远程调用gulimall-member中的方法为例。

4.2.1 首先在gulimall-coupon中的一个controller方法中写一个测试方法,以供被调用。

在这里插入图片描述

4.2.2 在gulimall-coupon中写一个feign接口,我们将这个接口都放在feign中。

@FeifnClient注解:告诉springcloud这个接口是一个远程客户端,它要调用远程服务。
在这里插入图片描述

4.2.3 在gulimall-coupon的controller方法中调用feign接口。

在这里插入图片描述

4.2.4 在调用微服务gulimall-coupon中的启动类上加注解@EnableFeignClients(basePackages = "com.atguigu.gulimall.member.feign" )

在这里插入图片描述

4.2.5 启动这两个微服务。

记住:

  • 遇到的坑:SpringCloud启动报错Did you forget to include spring-cloud-starter-loadbalancer

添加匹配当前OpenFeign的负载均衡依赖

由于SpringCloud Feign在Hoxton.M2 RELEASED版本之后不再使用Ribbon而是使用spring-cloud-loadbalancer,所以不引入spring-cloud-loadbalancer会报错
解决方法 : 加入spring-cloud-loadbalancer依赖, 并且在nacos中排除ribbon依赖,不然loadbalancer无效

 <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
            <exclusions>
                <exclusion>
                    <groupId>com.netflix.ribbon</groupId>
                    <artifactId>ribbon</artifactId>
                </exclusion>
            </exclusions>
        </dependency>


        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-loadbalancer</artifactId>
            <version>3.1.1</version>
        </dependency>

gulimall-comon中添加以上注解解决问题。再次进行测试,如下图,测试成功。

在这里插入图片描述

Feign 使用三步
1、导包openfeign
2、开启@EnableFeignClients 功能
3、编写接口,进行远程调用

4.3 SpringCloud Alibaba-Nacos[作为配置中心]

在这里插入图片描述

4.3.1 pom.xml 引入Nacos Config Starter

<dependency>
			<groupId>com.alibaba.cloud</groupId>
			<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>

4.3.2 在应用的/src/main/resources/bootstrap.properties 配置文件中配置Nacos Config 元数据

spring.application.name=nacos-config-example
spring.cloud.nacos.config.server-addr=127.0.0.1:8848
主要配置应用名和配置中心地址

4.3.3 在nacos 中添加配置

在application.properties中:写这个,先测试。
在这里插入图片描述

在nacos 中创建一个应用名.properties 配置文件并编写配置
在这里插入图片描述

Nacos Config 数据结构
Nacos Config 主要通过dataId 和group 来唯一确定一条配置。
Nacos Client 从Nacos Server 端获取数据时,调用的是此接口ConfigService.getConfig(String dataId, String group, long timeoutMs)。

在这里插入图片描述

4.3.4 在应用中使用@Value 和@RefreshScope

完成上述两步后,应用会从Nacos Config 中获取相应的配置,并添加在Spring Environment的PropertySources 中。这里我们使用@Value 注解来将对应的配置注入到SampleController 的userName 和age 字段,并添加@RefreshScope 打开动态刷新功能。
在这里插入图片描述

4.3.5 测试

  • 坑,启动报错:
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
  • 踩坑 :配置中心不起作用,真的是这个问题。
    在这里插入图片描述

4.4 进阶

4.4.1 核心概念

在这里插入图片描述
在这里插入图片描述

4.4.2 原理

在这里插入图片描述

4.4.3 配置文件整合

我们将微服务中的配置文件进行整合。就是在nacos中每一个微服务都有自己的命名空间。每一个微服务的命名空间下有很多个配置列表,这些配置将我们原本在java本地的代码放到注册中心中,然后我们使用boostrap.properties来对命名空间进行设置。具体还可以进行分组。dev prod test这三组。
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
注意如果在注册中心中找不到就去找默认的,默认的在注册中心中也找不到的时候,就会去找本地的。
在这里插入图片描述
在这里插入图片描述

4.5 前面遇到的坑的究极问题-------版本问题

在这里插入图片描述
突然发现前面为什么和老师一样的代码会报红了,原来是因为springcloud版本不一样导致。怪不得会莫名其妙的报错,为了以后能少点报错,将springboot和springcloud的版本都换成和老师一样的版本吧。

在这里插入图片描述

4.5.1 依赖没写错,更改版本仍然报错的解决方法---- 清除缓存

在这里插入图片描述
在这里插入图片描述

4.5.2 版本切换后测试

  1. 对于以前踩的坑的解决办法引入的在老师之外的依赖,尝试进行注释掉,测试能否正常运行。
  • http://localhost:8000/member/member/coupons
    修改之后进行重新测试,并且将前面遇到的坑的解决加入的依赖都给注释掉,发现仍然正常运行,即版本正确。
    在这里插入图片描述

4.6 springcloud ----- gateway—网关

4.6.1 简介

网关作为流量的入口,常用功能包括路由转发、权限校验、限流控制等。而springcloud gateway作为SpringCloud 官方推出的第二代网关框架,取代了Zuul 网关。
在这里插入图片描述
官网文档地址:https://cloud.spring.io/spring-cloud-static/spring-cloud-gateway/2.1.3.RELEASE/single/spring-cloud-gateway.html
在这里插入图片描述
在这里插入图片描述

4.6.2 核心概念

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

4.6.2 使用

  1. 创建gulimall-gateway网关微服务

在这里插入图片描述
2. 加入gateway依赖
在这里插入图片描述
3. 编写网关配置文件
首先也要将其注册到nacos注册中心,并且为其创建单独的命名空间及端口号。

  • 断言(Predicates)
    在这里插入图片描述

  • 过滤器
    在这里插入图片描述
    在这里插入图片描述

在这里插入图片描述

id:路由的id,没有固定规则但要求唯一
uri:匹配后提供服务的路由地址
path:断言,路径相匹配的进行路由
Query:查询相匹配的进行路由

如果我们在地址栏中访问的地址有qq,或者baidu就会进行转发。
4. 启动测试

测试报错:

  • 网关启动报错 坑:Error creating bean with name 'routeDefinitionRouteLocator' defined in class path resource [org/springframework/cloud/gateway/config/GatewayAutoConfiguration.class]: Unsatisfied dependency expressed through method 'routeDefinitionRouteLocator' parameter 4; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'org.springframework.core.convert.ConversionService' available: expe

  • 网上搜索到的解决办法,我采用的是排除web内置容器的解决办法。

  • 解决办法:
    在这里插入图片描述
    1)解决办法1

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
    <!-- Maven整个生命周期内排除内置容器,排除内置容器导出成war包可以让外部容器运行spring-boot项目-->
    <exclusions>
        <exclusion>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-tomcat</artifactId>
        </exclusion>
    </exclusions>
</dependency>

2)解决办法2 : 使用 spring-webflux 模块,webflux 有一个全新的非堵塞的函数式 Reactive Web 框架,可以用来构建异步的、非堵塞的、事件驱动的服务

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-webflux</artifactId>
</dependency>

最后主启动类还要排除数据源:
@SpringBootApplication(exclude = {DruidDataSourceAutoConfigure.class,DataSourceAutoConfiguration.class})

排除的原因是我们将gateway也引入了gulimall-common,而这里面又有数据源配置(mybatis-plus),启动找不到对应的配置就会报错。解决办法就是排除数据源。

最后成功启动项目

在这里插入图片描述


5 前端

5.1 VSCode 使用

在这里插入图片描述
在这里插入图片描述
如果不想手动保存可以选择一下方法:
前端中Live Server 不起作用是因为需要设置自动保存代码或者是自己修改后手动保存才会热更新。
在设置中找到autosave,选择
在这里插入图片描述
这个即可,代码会自动保存,热更新插件会成功运行。

5.2 ES6

5.2.1 简介

在这里插入图片描述

5.2.2 什么是ECMAScript

在这里插入图片描述
在这里插入图片描述

5.2.3 ES6 新特性

快捷键:
shift + ! — 快速生成html模板
代码格式化:shift + alt +f

1、 let 声明变量
// var 声明的变量往往会越域
// let 声明的变量有严格局部作用域
{
var a = 1;
let b = 2;
}
console.log(a); // 1
console.log(b); // ReferenceError: b is not defined
// var 可以声明多次
// let 只能声明一次
var m = 1
var m = 2
let n = 3
// let n = 4
console.log(m) // 2
console.log(n) // Identifier 'n' has already been declared
// var 会变量提升
// let 不存在变量提升
console.log(x); // undefined
var x = 10;
console.log(y); //ReferenceError: y is not defined
let y = 20;
2、 const 声明常量(只读变量)
// 1. 声明之后不允许改变
// 2. 一但声明必须初始化,否则会报错
const a = 1;
a = 3; //Uncaught TypeError: Assignment to constant variable.
3、解构表达式
1)、数组解构
let arr = [1,2,3];
//以前我们想获取其中的值,只能通过角标。ES6 可以这样:
const [x,y,z] = arr;// x,y,z 将与arr 中的每个位置对应来取值
// 然后打印
console.log(x,y,z);
2)、对象解构
const person = {
name: "jack",
age: 21,
language: ['java', 'js', 'css']
}
// 解构表达式获取值,将person 里面每一个属性和左边对应赋值
const { name, age, language } = person;
// 等价于下面
// const name = person.name;
// const age = person.age;
// const language = person.language;
// 可以分别打印
console.log(name);
console.log(age);
console.log(language);
//扩展:如果想要将name 的值赋值给其他变量,可以如下,nn 是新的变量名
const { name: nn, age, language } = person;
console.log(nn);
console.log(age);
console.log(language);
4、字符串扩展
1)、几个新的API

ES6 为字符串扩展了几个新的API:

  • includes():返回布尔值,表示是否找到了参数字符串。
  • startsWith():返回布尔值,表示参数字符串是否在原字符串的头部。
  • endsWith():返回布尔值,表示参数字符串是否在原字符串的尾部。
let str = "hello.vue";
console.log(str.startsWith("hello"));//true
console.log(str.endsWith(".vue"));//true
console.log(str.includes("e"));//true
console.log(str.includes("hello"));//true
2)、字符串模板

模板字符串相当于加强版的字符串,用反引号`,除了作为普通字符串,还可以用来定义多行字符串,还可以在字符串中加入变量和表达式。

// 1、多行字符串
let ss = `
<div>
<span>hello world<span>
</div>
`
console.log(ss)

// 2、字符串插入变量和表达式。变量名写在${} 中,${} 中可以放
入JavaScript 表达式。
let name = "张三";
let age = 18;
let info = `我是${name},今年${age}`;
console.log(info)

// 3、字符串中调用函数
function fun() {
return "这是一个函数"
}
let sss = `O(∩_∩)O 哈哈~,${fun()}`;
console.log(sss); // O(∩_∩)O 哈哈~,这是一个函数
5、函数优化
1)、函数参数默认值
//在ES6 以前,我们无法给一个函数参数设置默认值,只能采用变通写法:
function add(a, b) {
// 判断b 是否为空,为空就给默认值1
b = b || 1;
return a + b;
}
// 传一个参数
console.log(add(10));
//现在可以这么写:直接给参数写上默认值,没传就会自动使用默认值
function add2(a , b = 1) {
return a + b;
}
// 传一个参数
console.log(add2(10));
2)、不定参数

不定参数用来表示不确定参数个数,形如,…变量名,由…加上一个具名参数标识符组成。具名参数只能放在参数列表的最后,并且有且只有一个不定参数。

function fun(...values) {
console.log(values.length)
}
fun(1, 2) //2
fun(1, 2, 3, 4) //4
3)、箭头函数

ES6 中定义函数的简写方式:

  • 一个参数时:
//以前声明一个方法
// var print = function (obj) {
// console.log(obj);
// }
// 可以简写为:
var print = obj => console.log(obj);
// 测试调用
print(100);
  • 多个参数:
// 两个参数的情况:
var sum = function (a, b) {
return a + b;
}
// 简写为:
//当只有一行语句,并且需要返回结果时,可以省略{} , 结果会自动返回。
var sum2 = (a, b) => a + b;
//测试调用
console.log(sum2(10, 10));//20
// 代码不止一行,可以用`{}`括起来
var sum3 = (a, b) => {
c = a + b;
return c;
};
//测试调用
console.log(sum3(10, 20));//30
4)、实战:箭头函数结合解构表达式
//需求,声明一个对象,hello 方法需要对象的个别属性
//以前的方式:
const person = {
name: "jack",
age: 21,
language: ['java', 'js', 'css']
}
function hello(person) {
console.log("hello," + person.name)
}
//现在的方式
var hello2 = ({ name }) => { console.log("hello," + name) };
//测试
hello2(person);
6、对象优化
1)、新增的API

ES6 给Object 拓展了许多新的方法,如:

  • keys(obj):获取对象的所有key 形成的数组
  • values(obj):获取对象的所有value 形成的数组
  • entries(obj):获取对象的所有key 和value 形成的二维数组。格式:[[k1,v1],[k2,v2],...]
  • assign(dest, …src) :将多个src 对象的值拷贝到dest 中。(第一层为深拷贝,第二层为浅
    拷贝)
const person = {
name: "jack",
age: 21,
language: ['java', 'js', 'css']
}
console.log(Object.keys(person));//["name", "age", "language"]
console.log(Object.values(person));//["jack", 21, Array(3)]
console.log(Object.entries(person));//[Array(2), Array(2), Array(2)]
const target = { a: 1 };
const source1 = { b: 2 };
const source2 = { c: 3 };
//Object.assign 方法的第一个参数是目标对象,后面的参数都是源对象。
Object.assign(target, source1, source2);
console.log(target)//{a: 1, b: 2, c: 3}
2)、声明对象简写
const age = 23
const name = "张三"
// 传统
const person1 = { age: age, name: name }
console.log(person1)
// ES6:属性名和属性值变量名一样,可以省略
const person2 = { age, name }
console.log(person2) //{age: 23, name: "张三"}
3)、对象的函数属性简写
let person = {
name: "jack",
// 以前:
eat: function (food) {
console.log(this.name + "在吃" + food);
},
// 箭头函数版:这里拿不到this
eat2: food => console.log(person.name + "在吃" + food),
// 简写版:
eat3(food) {
console.log(this.name + "在吃" + food);
}
}
person.eat("apple");
4)、对象拓展运算符

拓展运算符(…)用于取出参数对象所有可遍历属性然后拷贝到当前对象。

// 1、拷贝对象(深拷贝)
let person1 = { name: "Amy", age: 15 }
let someone = { ...person1 }
console.log(someone) //{name: "Amy", age: 15}
// 2、合并对象
let age = { age: 15 }
let name = { name: "Amy" }
let person2 = { ...age, ...name } //如果两个对象的字段名重复,后面对象字
段值会覆盖前面对象的字段值
console.log(person2) //{age: 15, name: "Amy"}
7、map 和reduce

数组中新增了map 和reduce 方法。

1)、map

map():接收一个函数,将原数组中的所有元素用这个函数处理后放入新数组返回。

let arr = ['1', '20', '-5', '3'];
console.log(arr)
arr = arr.map(s => parseInt(s));
console.log(arr)	
2)、reduce

语法:
arr.reduce(callback,[initialValue])
reduce 为数组中的每一个元素依次执行回调函数,不包括数组中被删除或从未被赋值的元
素,接受四个参数:初始值(或者上一次回调函数的返回值),当前元素值,当前索引,调
用reduce 的数组。
callback (执行数组中每个值的函数,包含四个参数)
1、previousValue (上一次调用回调返回的值,或者是提供的初始值(initialValue))
2、currentValue (数组中当前被处理的元素)
3、index (当前元素在数组中的索引)
4、array (调用reduce 的数组)
initialValue (作为第一次调用callback 的第一个参数。)
示例:

const arr = [1,20,-5,3];
//没有初始值:
console.log(arr.reduce((a,b)=>a+b));//19
console.log(arr.reduce((a,b)=>a*b));//-300
//指定初始值:
console.log(arr.reduce((a,b)=>a+b,1));//20
console.log(arr.reduce((a,b)=>a*b,0));//-0
8、Promise

在JavaScript 的世界中,所有代码都是单线程执行的。由于这个“缺陷”,导致JavaScript 的所有网络操作,浏览器事件,都必须是异步执行。异步执行可以用回调函数实现。一旦有一连串的ajax 请求a,b,c,d… 后面的请求依赖前面的请求结果,就需要层层嵌套。这种缩进和层
层嵌套的方式,非常容易造成上下文代码混乱,我们不得不非常小心翼翼处理内层函数与外层函数的数据,一旦内层函数使用了上层函数的变量,这种混乱程度就会加剧…总之,这种层叠上下文的层层嵌套方式,着实增加了神经的紧张程度。
案例:用户登录,并展示该用户的各科成绩。在页面发送两次请求:

  1. 查询用户,查询成功说明可以登录
  2. 查询用户成功,查询科目
  3. 根据科目的查询结果,获取去成绩
    分析:此时后台应该提供三个接口,一个提供用户查询接口,一个提供科目的接口,一个提供各科成绩的接口,为了渲染方便,最好响应json 数据。在这里就不编写后台接口了,而是提供三个json 文件,直接提供json 数据,模拟后台接口:
user.json:
{
"id": 1,
"name": "zhangsan",
"password": "123456"
}
user_corse_1.json:
{
"id": 10,
"name": "chinese"
}
corse_score_10.json:
{
"id": 100,
"score": 90
}
//回调函数嵌套的噩梦:层层嵌套。
$.ajax({
url: "mock/user.json",
success(data) {
console.log("查询用户:", data);
$.ajax({
url: `mock/user_corse_${data.id}.json`,
success(data) {
console.log("查询到课程:", data);
$.ajax({
url: `mock/corse_score_${data.id}.json`,
success(data) {
console.log("查询到分数:", data);
},
error(error) {
console.log("出现异常了:" + error);
}
});
},
error(error) {
console.log("出现异常了:" + error);
}
});
},
error(error) {
console.log("出现异常了:" + error);
}
});

我们可以通过Promise 解决以上问题。

1)、Promise 语法
const promise = new Promise(function (resolve, reject) {
// 执行异步操作
if (/* 异步操作成功*/) {
resolve(value);// 调用resolve,代表Promise 将返回成功的结果
} else {
reject(error);// 调用reject,代表Promise 会返回失败结果
}
});

使用箭头函数可以简写为:

const promise = new Promise((resolve, reject) =>{
// 执行异步操作
if (/* 异步操作成功*/) {
resolve(value);// 调用resolve,代表Promise 将返回成功的结果
} else {
reject(error);// 调用reject,代表Promise 会返回失败结果
}
});

这样,在promise 中就封装了一段异步执行的结果。

2)、处理异步结果

如果我们想要等待异步执行完成,做一些事情,我们可以通过promise 的then 方法来实现。
如果想要处理promise 异步执行失败的事件,还可以跟上catch:

promise.then(function (value) {
// 异步执行成功后的回调
}).catch(function (error) {
// 异步执行失败后的回调
})
3)、Promise 改造以前嵌套方式
new Promise((resolve, reject) => {
$.ajax({
url: "mock/user.json",
success(data) {
console.log("查询用户:", data);
resolve(data.id);
},
error(error) {
console.log("出现异常了:" + error);
}
});
}).then((userId) => {
return new Promise((resolve, reject) => {
$.ajax({
url: `mock/user_corse_${userId}.json`,
success(data) {
console.log("查询到课程:", data);
resolve(data.id);
},
error(error) {
console.log("出现异常了:" + error);
}
});
});
}).then((corseId) => {
console.log(corseId);
$.ajax({
url: `mock/corse_score_${corseId}.json`,
success(data) {
console.log("查询到分数:", data);
},
error(error) {
console.log("出现异常了:" + error);
}
});
});
4)、优化处理

优化:通常在企业开发中,会把promise 封装成通用方法,如下:封装了一个通用的get 请求方法

let get = function (url, data) { // 实际开发中会单独放到common.js 中
return new Promise((resolve, reject) => {
$.ajax({
url: url,
type: "GET",
data: data,
success(result) {
resolve(result);
},
error(error) {
reject(error);
}
});
})
}
// 使用封装的get 方法,实现查询分数
get("mock/user.json").then((result) => {
console.log("查询用户:", result);
return get(`mock/user_corse_${result.id}.json`);
}).then((result) => {
console.log("查询到课程:", result);
return get(`mock/corse_score_${result.id}.json`)
}).then((result) => {
console.log("查询到分数:", result);
}).catch(() => {
console.log("出现异常了:" + error);
});

通过比较,我们知道了Promise 的扁平化设计理念,也领略了这种上层设计带来的好处。
我们的项目中会使用到这种异步处理的方式;

9、模块化
1)、什么是模块化

模块化就是把代码进行拆分,方便重复利用。类似java 中的导包:要使用一个包,必须先导包。而JS 中没有包的概念,换来的是模块。
模块功能主要由两个命令构成:exportimport

  • export命令用于规定模块的对外接口。
  • import命令用于导入其他模块提供的功能。
2)、export

比如我定义一个js 文件:hello.js,里面有一个对象:

const util = {
sum(a,b){
return a + b;
}
}

我可以使用export 将这个对象导出:

const util = {
sum(a,b){
return a + b;
}
}
export {util};

当然,也可以简写为:

export const util = {
sum(a,b){
return a + b;
}
}

export不仅可以导出对象,一切JS 变量都可以导出。比如:基本类型变量、函数、数组、对象。
当要导出多个值时,还可以简写。比如我有一个文件:user.js:

var name = "jack"
var age = 21
export {name,age}

省略名称
上面的导出代码中,都明确指定了导出的变量名,这样其它人在导入使用时就必须准确写出
变量名,否则就会出错。
因此js 提供了default关键字,可以对导出的变量名进行省略
例如:

// 无需声明对象的名字
export default {
sum(a,b){
return a + b;
}
}

这样,当使用者导入时,可以任意起名字。

3)、import

使用export命令定义了模块的对外接口以后,其他JS 文件就可以通过import命令加载这个模块。
例如我要使用上面导出的util:

// 导入util
import util from 'hello.js'
// 调用util 中的属性
util.sum(1,2)

要批量导入前面导出的name 和age:

import {name, age} from 'user.js'
console.log(name + " , 今年"+ age +"岁了")

但是上面的代码暂时无法测试,因为浏览器目前还不支持ES6 的导入和导出功能。除非借助于工具,把ES6 的语法进行编译降级到ES5,比如Babel-cli工具我们暂时不做测试,大家了解即可。

5.3 Node.js

前端开发,少不了node.js;Node.js 是一个基于Chrome V8 引擎的JavaScript 运行环境。
http://nodejs.cn/api/
我们关注与node.js 的npm 功能就行;
NPM 是随同NodeJS 一起安装的包管理工具,JavaScript-NPM,Java-Maven;

1)、官网下载安装node.js,并使用node -v 检查版本
2)、配置npm 使用淘宝镜像
npm config set registry http://registry.npm.taobao.org/
3)、大家如果npm install 安装依赖出现chromedriver 之类问题,先在项目里运行下面命令
npm install chromedriver --chromedriver_cdnurl=http://cdn.npm.taobao.org/dist/chromedriver
然后再运行npm install

5.4 Vue

1、MVVM 思想

  • M:即Model,模型,包括数据和一些基本操作
  • V:即View,视图,页面渲染结果
  • VM:即View-Model,模型与视图间的双向操作(无需开发人员干涉)
    在MVVM 之前,开发人员从后端获取需要的数据模型,然后要通过DOM 操作Model 渲染到View 中。而后当用户操作视图,我们还需要通过DOM 获取View 中的数据,然后同步到Model 中。

而MVVM 中的VM 要做的事情就是把DOM 操作完全封装起来,开发人员不用再关心Model和View 之间是如何互相影响的:

  • 只要我们Model 发生了改变,View 上自然就会表现出来。
  • 当用户修改了View,Model 中的数据也会跟着改变。
    把开发人员从繁琐的DOM 操作中解放出来,把关注点放在如何操作Model 上。

在这里插入图片描述

2、Vue 简介

Vue (读音/vjuː/,类似于view) 是一套用于构建用户界面的渐进式框架。与其它大型框架不同的是,Vue 被设计为可以自底向上逐层应用。Vue 的核心库只关注视图层,不仅易于上手,还便于与第三方库或既有项目整合。另一方面,当与现代化的工具链以及各种支持类库结合使用时,Vue 也完全能够为复杂的单页应用提供驱动。

官网:https://cn.vuejs.org/
参考:https://cn.vuejs.org/v2/guide/
Git 地址:https://github.com/vuejs

3、入门案例

1)、安装

官网文档提供了3 种安装方式:

  1. 直接script 引入本地vue 文件。需要通过官网下载vue 文件。
  2. 通过script 引入CDN 代理。需要联网,生产环境可以使用这种方式
  3. 通过npm 安装。这种方式也是官网推荐的方式,需要nodejs 环境。
    本课程就采用第三种方式

在这里插入图片描述
在这里插入图片描述
这里没有vue.js文件的,vue版本错了,npm install vue@2 重装一下,npm默认装的是vue3.0

2)、创建示例项目

1、新建文件夹hello-vue,并使用vscode 打开
2、使用vscode 控制台,npm install -y;
项目会生成package-lock.json 文件,类似于maven 项目的pom.xml 文件。
3、使用npm install vue,给项目安装vue;项目下会多node_modules 目录,并且在下面有
一个vue 目录。
在这里插入图片描述

3)、HelloWorld

在hello.html 中,我们编写一段简单的代码。
h2 中要输出一句话:xx 非常帅。前面的xx是要渲染的数据。
在这里插入图片描述

4)、vue 声明式渲染

页面代码

 <div id="app">
            <h1>{{name}},非常帅!!!</h1>
        </div>
        <script src="./node_modules/vue/dist/vue.min.js"></script>
        <script>
            let vm = new Vue({
                el: "#app",
                data: {
                    name: "张三"
                }
            });
        </script>
    </body>

在这里插入图片描述

5)、双向绑定

我们对刚才的案例进行简单修改:

<div id="app">
            <input type="text" v-model="num">
            <h2>
                {{name}},非常帅!!!有{{num}}个人为他点赞。
            </h2>
        </div>
        <script src="./node_modules/vue/dist/vue.js"></script>
        <script>
            // 创建vue 实例
            let app = new Vue({
                el: "#app", // el 即element,该vue 实例要渲染的页面元素
                data: { // 渲染页面需要的数据
                    name: "张三",
                    num: 5
                }
            });
        </script>

在这里插入图片描述

6)、事件处理

给页面添加一个按钮:

<body>
 <div id="app">
            <input type="text" v-model="num">
            <button v-on:click="num++">关注</button>
            <h2>
                {{name}},非常帅!!!有{{num}}个人为他点赞。
            </h2>
        </div>
        <script src="./node_modules/vue/dist/vue.js"></script>
        <script>
            // 创建vue 实例
            let app = new Vue({
                el: "#app", // el 即element,该vue 实例要渲染的页面元素
                data: { // 渲染页面需要的数据
                    name: "张三",
                    num: 5
                }
            });
        </script>
</body>

在这里插入图片描述
在这里插入图片描述

简单使用总结:
1)、使用Vue 实例管理DOM
2)、DOM 与数据/事件等进行相关绑定
3)、我们只需要关注数据,事件等处理,无需关心视图如何进行修改

4、概念

1、创建Vue 实例

每个Vue 应用都是通过用Vue 函数创建一个新的Vue 实例开始的:

let app = new Vue({
});

在构造函数中传入一个对象,并且在对象中声明各种Vue 需要的数据和方法,包括:

  • el
  • data
  • methods
2、模板或元素

每个Vue 实例都需要关联一段Html 模板,Vue 会基于此模板进行视图渲染。
我们可以通过el 属性来指定。
例如一段html 模板:

<div id="app">
</div>

然后创建Vue 实例,关联这个div

let vm = new Vue({
el: "#app"
})

这样,Vue 就可以基于id 为app的div 元素作为模板进行渲染了。在这个div 范围以外的部
分是无法使用vue 特性的。

3、数据

当Vue 实例被创建时,它会尝试获取在data 中定义的所有属性,用于视图的渲染,并且监视data 中的属性变化,当data 发生改变,所有相关的视图都将重新渲染,这就是“响应式“系统。
html:

<div id="app">
<input type="text" v-model="name" />
</div>

JS:

let vm = new Vue({
el: "#app",
data: {
name: "刘德华"
}
})
4、方法

Vue 实例中除了可以定义data 属性,也可以定义方法,并且在Vue 实例的作用范围内使用。
Html:

<div id="app">
{{num}}
<button v-on:click="add"></button>
</div>

JS:

let vm = new Vue({
el: "#app",
data: {
num: 0
},
methods: {
add: function () {
// this 代表的当前vue 实例
this.num++;
}
}
})
5、安装vue-devtools 方便调试

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

6、安装vscode 的vue 插件

在这里插入图片描述
安装这个插件就可以有语法提示

5、指令

什么是指令?

  • 指令(Directives) 是带有v- 前缀的特殊特性。
  • 指令特性的预期值是:单个JavaScript 表达式。
  • 指令的职责是,当表达式的值改变时,将其产生的连带影响,响应式地作用于DOM
    例如我们在入门案例中的v-on,代表绑定事件。
1、插值表达式
1)、花括号

格式:{{表达式}}
说明:

  • 该表达式支持JS 语法,可以调用js 内置函数(必须有返回值)
  • 表达式必须有返回结果。例如1 + 1,没有结果的表达式不允许使用,如:let a = 1 + 1;
  • 可以直接获取Vue 实例中定义的数据或函数
2)、插值闪烁

使用{{}}方式在网速较慢时会出现问题。在数据未加载完成时,页面会显示出原始的{{}},加载完毕后才显示正确数据,我们称为插值闪烁。
我们将网速调慢一些,然后刷新页面,试试看刚才的案例:
在这里插入图片描述

3)、v-text 和v-html

可以使用v-text 和v-html 指令来替代{{}}
说明:

  • v-text:将数据输出到元素内部,如果输出的数据有HTML 代码,会作为普通文本输出
  • v-html:将数据输出到元素内部,如果输出的数据有HTML 代码,会被渲染
    示例:
<div id="app">
v-text:<span v-text="hello"></span> <br />
v-html:<span v-html="hello"></span>
</div>
<script src="./node_modules/vue/dist/vue.js"></script>
<script>
let vm = new Vue({
el: "#app",
data: {
hello: "<h1>大家好</h1>"
}
})
</script>

效果:
在这里插入图片描述

并且不会出现插值闪烁,当没有数据时,会显示空白或者默认数据。

2、v-bind

html 属性不能使用双大括号形式绑定,我们使用v-bind 指令给HTML 标签属性绑定值;
而且在将v-bind 用于classstyle 时,Vue.js 做了专门的增强。

1)、绑定class
<div class="static" v-bind:class="{ active: isActive, 'text-danger'
        : hasError }">
        </div>
        <script>
            let vm = new Vue({
                el: "#app",
                data: {
                    isActive: true,
                    hasError: false
                }
            })
        </script>
2)、绑定style

v-bind:style 的对象语法十分直观,看着非常像CSS,但其实是一个JavaScript 对象。style属性名可以用驼峰式(camelCase) 或短横线分隔(kebab-case,这种方式记得用单引号括起来) 来命名。
例如:font-size–>fontSize

<div id="app" v-bind:style="{ color: activeColor, fontSize: fontSiz
            e + 'px' }"></div>
        <script>
            let vm = new Vue({
                el: "#app",
                data: {
                    activeColor: 'red',
                    fontSize: 30
                }
            })
        </script>

结果:

3)、绑定其他任意属性
<div id="app" v-bind:style="{ color: activeColor, fontSize: fontS
            ize + 'px' }" v-bind:user="userName">
        </div>
        <script>
            let vm = new Vue({
                el: "#app",
                data: {
                    activeColor: 'red',
                    fontSize: 30,
                    userName: 'zhangsan'
                }
            })
        </script>
4)、v-bind 缩写
<div id="app" :style="{ color: activeColor, fontSize: fontSize +
            'px' }" :user="userName">
        </div>
3、v-model

刚才的v-text、v-html、v-bind 可以看做是单向绑定,数据影响了视图渲染,但是反过来就不
行。接下来学习的v-model 是双向绑定,视图(View)和模型(Model)之间会互相影响。
既然是双向绑定,一定是在视图中可以修改数据,这样就限定了视图的元素类型。目前
v-model 的可使用元素有:

  • input
  • select
  • textarea
  • checkbox
  • radio
  • components(Vue 中的自定义组件)
    基本上除了最后一项,其它都是表单的输入项。
    示例:
<div id="app">
            <input type="checkbox" v-model="language" value="Java" />Java<br />
            <input type="checkbox" v-model="language" value="PHP" />PHP<br />
            <input type="checkbox" v-model="language" value="Swift" />Swift<br />
            <h1>
                你选择了:{{language.join(',')}}
            </h1>
        </div>
        <script src="../node_modules/vue/dist/vue.js"></script>
        <script type="text/javascript">
            let vm = new Vue({
                el: "#app",
                data: {
                    language: []
                }
            })
        </script>
  • 多个CheckBox对应一个model 时,model 的类型是一个数组,单个checkbox 值默认是boolean 类型
  • radio 对应的值是input 的value 值
  • texttextarea 默认对应的model 是字符串
  • select单选对应字符串,多选对应也是数组
    在这里插入图片描述
4、v-on
1、基本用法

v-on 指令用于给页面元素绑定事件。
语法: v-on:事件名=“js 片段或函数名”
示例:

 <div id="app">
            <!--事件中直接写js 片段-->
            <button v-on:click="num++">点赞</button>
            <!--事件指定一个回调函数,必须是Vue 实例中定义的函数-->
            <button v-on:click="decrement">取消</button>
            <h1>有{{num}}个赞</h1>
        </div>
        <script src="../node_modules/vue/dist/vue.js"></script>
        <script type="text/javascript">
            let vm = new Vue({
                el: "#app",
                data: {
                    num: 100
                },
                methods: {
                    decrement() {
                        this.num--; //要使用data 中的属性,必须this.属性名
                    }
                }
            })
        </script>

另外,事件绑定可以简写,例如v-on:click='add'可以简写为@click='add'

2、事件修饰符

在事件处理程序中调用event.preventDefault()event.stopPropagation() 是非常常见的
需求。尽管我们可以在方法中轻松实现这点,但更好的方式是:方法只有纯粹的数据逻辑,
而不是去处理DOM 事件细节。
为了解决这个问题,Vue.js 为v-on 提供了事件修饰符。修饰符是由点开头的指令后缀来
表示的。

  • .stop :阻止事件冒泡到父元素
  • .prevent:阻止默认事件发生
  • .capture:使用事件捕获模式
  • .self:只有元素自身触发事件才执行。(冒泡或捕获的都不执行)
  • .once:只执行一次
<div id="app">
            <!--右击事件,并阻止默认事件发生-->
            <button v-on:contextmenu.prevent="num++">点赞</button>
            <br />
            <!--右击事件,不阻止默认事件发生-->
            <button v-on:contextmenu="decrement($event)">取消</button>
            <br />
            <h1>有{{num}}个赞</h1>
        </div>
        <script src="../node_modules/vue/dist/vue.js"></script>
        <script type="text/javascript">
            let app = new Vue({
                el: "#app",
                data: {
                    num: 100
                },
                methods: {
                    decrement(ev) {
                        // ev.preventDefault();
                        this.num--;
                    }
                }
            })
        </script>

效果:右键“点赞”,不会触发默认的浏览器右击事件;右键“取消”,会触发默认的浏览器右击事件)

3. 按键修饰符

在这里插入图片描述

4、组合按钮

在这里插入图片描述
在这里插入图片描述

5、v-for

遍历数据渲染页面是非常常用的需求,Vue 中通过v-for 指令来实现。

1、遍历数组

语法:v-for=“item in items”

  • items:要遍历的数组,需要在vue 的data 中定义好。
  • item:迭代得到的当前正在遍历的元素
    示例:
<div id="app">
            <ul>
                <li v-for="user in users">
                    {{user.name}} - {{user.gender}} - {{user.age}}
                </li>
            </ul>
        </div>
        <script src="../node_modules/vue/dist/vue.js"></script>
        <script type="text/javascript">
            let app = new Vue({
                el: "#app",
                data: {
                    users: [
                        { name: '柳岩', gender: '女', age: 21 },
                        { name: '张三', gender: '男', age: 18 },
                        { name: '范冰冰', gender: '女', age: 24 },
                        { name: '刘亦菲', gender: '女', age: 18 },
                        { name: '古力娜扎', gender: '女', age: 25 }
                    ]
                },
            })
        </script>

效果:
在这里插入图片描述

2、数组角标

在这里插入图片描述

3、遍历对象

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

4、Key

在这里插入图片描述
在这里插入图片描述

6、v-if 和v-show

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

7、v-else 和v-else-if

v-else 元素必须紧跟在带v-if 或者v-else-if 的元素的后面,否则它将不会被识别。
示例:

<div id="app">
            <button v-on:click="random=Math.random()">点我呀
            </button><span>{{random}}</span>
            <h1 v-if="random >= 0.75">
                看到我啦?!v-if >= 0.75
            </h1>
            <h1 v-else-if="random > 0.5">
                看到我啦?!v-else-if > 0.5
            </h1>
            <h1 v-else-if="random > 0.25">
                看到我啦?!v-else-if > 0.25
            </h1>
            <h1 v-else>
                看到我啦?!v-else
            </h1>
        </div>
        <script src="../node_modules/vue/dist/vue.js"></script>
        <script type="text/javascript">
            let app = new Vue({
                el: "#app",
                data: {
                    random: 1
                }
            })
        </script>

6、计算属性和侦听器

1、计算属性(computed)

某些结果是基于之前数据实时计算出来的,我们可以利用计算属性。来完成
示例:

 <div id="app">
        <ul>
            <li>西游记:价格{{xyjPrice}},数量:
                <input type="number" v-model="xyjNum">
            </li>
            <li>水浒传:价格{{shzPrice}},数量:
                <input type="number" v-model="shzNum">
            </li>
            <li>总价:{{totalPrice}}</li>
        </ul>
    </div>
    <script src="../node_modules/vue/dist/vue.js"></script>
    <script type="text/javascript">
        let app = new Vue({
            el: "#app",
            data: {
                xyjPrice: 56.73,
                shzPrice: 47.98,
                xyjNum: 1,
                shzNum: 1
            },
            computed: {
                totalPrice() {
                    return this.xyjPrice * this.xyjNum + this.shzPrice * this.shzNum;
                }
            },
        })
    </script>

在这里插入图片描述

2、侦听(watch)

watch 可以让我们监控一个值的变化。从而做出相应的反应。
示例:

 <div id="app">
        <ul>
            <li>西游记:价格{{xyjPrice}},数量:
                <input type="number" v-model="xyjNum">
            </li>
            <li>水浒传:价格{{shzPrice}},数量:
                <input type="number" v-model="shzNum">
            </li>
            <li>总价:{{totalPrice}}</li>
            {{msg}}
        </ul>
    </div>
    <script src="../node_modules/vue/dist/vue.js"></script>
    <script type="text/javascript">
        let app = new Vue({
            el: "#app",
            data: {
                xyjPrice: 56.73,
                shzPrice: 47.98,
                xyjNum: 1,
                shzNum: 1,
                msg: ""
            },
            computed: {
                totalPrice() {
                    return this.xyjPrice * this.xyjNum + this.shzPrice * this.shzNum;
                }
            },
            watch: {
                xyjNum(newVal, oldVal) {
                    if (newVal >= 3) {
                        this.msg = "西游记没有更多库存了";
                        this.xyjNum = 3;
                    } else {
                        this.msg = "";
                    }
                }
            }
        })
    </script>

在这里插入图片描述

3、过滤器(filters)

在这里插入图片描述

<body>
            <div id="app">
                <table>
                    <tr v-for="user in userList">
                        <td>{{user.id}}</td>
                        <td>{{user.name}}</td>
                        <!-- 使用代码块实现,有代码侵入-->
                        <td>{{user.gender===1? "男":"女"}}</td>
                    </tr>
                </table>
            </div>
        </body>
        <script src="../node_modules/vue/dist/vue.js"></script>
        <script>
            let app = new Vue({
                el: "#app",
                data: {
                    userList: [
                        { id: 1, name: 'jacky', gender: 1 },
                        { id: 2, name: 'peter', gender: 0 }
                    ]
                }
            });
        </script>
1、局部过滤器

注册在当前vue 实例中,只有当前实例能用

let app = new Vue({
                el: "#app",
                data: {
                    userList: [
                        { id: 1, name: 'jacky', gender: 1 },
                        { id: 2, name: 'peter', gender: 0 }
                    ]
                },
                // filters 定义局部过滤器,只可以在当前vue 实例中使用
                filters: {
                    genderFilter(gender) {
                        return gender === 1 ? '男~' : '女~'
                    }
                }
            });

在这里插入图片描述

2、全局过滤器

在这里插入图片描述

7、组件化

在大型应用开发的时候,页面可以划分成很多部分。往往不同的页面,也会有相同的部分。例如可能会有相同的头部导航。
但是如果每个页面都独自开发,这无疑增加了我们开发的成本。所以我们会把页面的不同部分拆分成独立的组件,然后在不同页面就可以共享这些组件,避免重复开发。在vue 里,所有的vue 实例都是组件。
在这里插入图片描述

1、全局组件

我们通过Vue 的component 方法来定义一个全局组件。

 <div id="app">
        <!--使用定义好的全局组件-->
        <counter></counter>
    </div>
    <script src="../node_modules/vue/dist/vue.js"></script>
    <script type="text/javascript">
        // 定义全局组件,两个参数:1,组件名称。2,组件参数
        Vue.component("counter", {
            template: '<button v-on:click="count++">你点了我{{ count }} 次,我记住了.</button>',
            data() {
                return {
                    count: 0
                }
            }
        })
        let app = new Vue({
            el: "#app"
        })
    </script>

在这里插入图片描述

2、组件的复用

定义好的组件,可以任意复用多次:

<div id="app">
<!--使用定义好的全局组件-->
<counter></counter>
<counter></counter>
<counter></counter>
</div>

在这里插入图片描述

3、局部组件

一旦全局注册,就意味着即便以后你不再使用这个组件,它依然会随着Vue 的加载而加载。因此,对于一些并不频繁使用的组件,我们会采用局部注册。
我们先在外部定义一个对象,结构与创建组件时传递的第二个参数一致:
在这里插入图片描述

在这里插入图片描述

8、生命周期钩子函数

1、生命周期

每个Vue 实例在被创建时都要经过一系列的初始化过程:创建实例,装载模板,渲染模板等等。Vue 为生命周期中的每个状态都设置了钩子函数(监听函数)。每当Vue 实例处于不同的生命周期时,对应的函数就会被触发调用。
生命周期:你不需要立马弄明白所有的东西。
在这里插入图片描述

2、钩子函数

在这里插入图片描述
示例

<body>
    <div id="app">
        <span id="num">{{num}}</span>
        <button v-on:click="num++">赞!</button>
        <h2>
            {{name}},非常帅!!!有{{num}}个人点赞。
        </h2>
    </div>
</body>
<script src="../node_modules/vue/dist/vue.js"></script>
<script>
    let app = new Vue({
        el: "#app",
        data: {
            name: "张三",
            num: 100
        },
        methods: {
            show() {
                return this.name;
            },
            add() {
                this.num++;
            }
        },
        beforeCreate() {
            console.log("=========beforeCreate=============");
            console.log("数据模型未加载:" + this.name, this.num);
            console.log("方法未加载:" + this.show());
            console.log("html 模板未加载:" + document.getElementById("num"));
        },
        created: function () {
            console.log("=========created=============");
            console.log("数据模型已加载:" + this.name, this.num);
            console.log("方法已加载:" + this.show());
            console.log("html 模板已加载:" + document.getElementById("num"));
            console.log("html 模板未渲染:" + document.getElementById("num").innerText);
        },
        beforeMount() {
            console.log("=========beforeMount=============");
            console.log("html 模板未渲染:" + document.getElementById("num").innerText);
        },
        mounted() {
            console.log("=========mounted=============");
            console.log("html 模板已渲染:" + document.getElementById("num").innerText);
        },
        beforeUpdate() {
            console.log("=========beforeUpdate=============");
            console.log("数据模型已更新:" + this.num);
            console.log("html 模板未更新:" + document.getElementById("num").innerText);
        },
        updated() {
            console.log("=========updated=============");
            console.log("数据模型已更新:" + this.num);
            console.log("html 模板已更新:" + document.getElementById("num").innerText);
        }
    });
</script>

</body>

在这里插入图片描述

9、vue 模块化开发

1、npm install webpack -g

全局安装webpack

2、npm install -g @vue/cli-init

全局安装vue 脚手架

3、初始化vue 项目

vue init webpack appname:vue 脚手架使用webpack 模板初始化一个appname 项目
在这里插入图片描述
在这里插入图片描述

4、启动vue 项目;

在这里插入图片描述
在这里插入图片描述
项目的package.json 中有scripts,代表我们能运行的命令
npm start = npm run dev:启动项目
npm run build:将项目打包

5、模块化开发
1、项目结构

在这里插入图片描述
在这里插入图片描述

2、Vue 单文件组件

Vue 单文件组件模板有三个部分;
在这里插入图片描述

3、vscode 添加用户代码片段(快速生成vue 模板)

在这里插入图片描述

{
"生成vue 模板": {
"prefix": "vue",
"body": [
"<template>",
"<div></div>",
"</template>",
"",
"<script>",
"//这里可以导入其他文件(比如:组件,工具js,第三方插件js,json
文件,图片文件等等)",
"//例如:import 《组件名称》from '《组件路径》';",
"",
"export default {",
"//import 引入的组件需要注入到对象中才能使用",
"components: {},",
"props: {},",
"data() {",
"//这里存放数据",
"return {",
"",
"};",
"},",
"//计算属性类似于data 概念",
"computed: {},",
"//监控data 中的数据变化",
"watch: {},",
"//方法集合",
"methods: {",
"",
"},",
"//生命周期- 创建完成(可以访问当前this 实例)",
"created() {",
"",
"},",
"//生命周期- 挂载完成(可以访问DOM 元素)",
"mounted() {",
"",
"},",
"beforeCreate() {}, //生命周期- 创建之前",
"beforeMount() {}, //生命周期- 挂载之前",
"beforeUpdate() {}, //生命周期- 更新之前",
"updated() {}, //生命周期- 更新之后",
"beforeDestroy() {}, //生命周期- 销毁之前",
"destroyed() {}, //生命周期- 销毁完成",
"activated() {}, //如果页面有keep-alive 缓存功能,这个函数会触发
",
"}",
"</script>",
"<style lang='scss' scoped>",
"//@import url($3); 引入公共css 类",
"$4",
"</style>"
],
"description": "生成vue 模板"
}
}
4、导入element-ui 快速开发
  1. 安装element-ui: npm i element-ui
  2. 在main.js 中引入element-ui 就可以全局使用了。
    import ElementUI from ‘element-ui’
    import ‘element-ui/lib/theme-chalk/index.css’
    Vue.use(ElementUI)
  3. 将App.vue 改为element-ui 中的后台布局
  4. 添加测试路由、组件,测试跳转逻辑
    (1) 、参照文档el-menu 添加router 属性
    (2) 、参照文档el-menu-item 指定index 需要跳转的地址

updated() {}, //生命周期- 更新之后
beforeDestroy() {}, //生命周期- 销毁之前
destroyed() {}, //生命周期- 销毁完成
activated() {}, //如果页面有keep-alive 缓存功能,这个函数会触发
};


至此商品服务告一段落。

---



## 6.2 品牌管理

这次要用到的代码是通过renren-generator代码生成器中生成的前端代码。在前面中如果我们不小心进行删除了,可以通过idea自带的恢复功能进行恢复。

步骤:

1. 右键点击resources->Local History->Show History

![image-20221031155936100](https://img-blog.csdnimg.cn/img_convert/127b17e25288dd42c0ac6f2addbafad1.png)

2. 找到删除前端的记录
3. 右键->Revert。 找回成功!

![image-20221031160027348](https://img-blog.csdnimg.cn/img_convert/0d25fbd670db392af9ce373e91e08867.png)

### 6.2.1  使用逆向工程前端代码

1. 菜单管理---新增菜单

![image-20221030162542202](https://img-blog.csdnimg.cn/img_convert/6f59d720ef206007e9540ed57a015409.png) 

2. 将gulimall-product中的前端代码复制到前端工程product下。

![image-20221030170804793](https://img-blog.csdnimg.cn/img_convert/d58986edf0cd838b7a1395d6deb78815.png)

3. 没有新增删除按钮: 修改权限,Ctrl+Shift+F查找`isAuth`,全部返回为true

![image-20221031160612205](https://img-blog.csdnimg.cn/img_convert/74e9fec8cc7401a744eebfc418645a1a.png)

![image-20221031160622591](https://img-blog.csdnimg.cn/img_convert/3c5870869123d4cdfa36708880d123c9.png)



4. 查看效果

![image-20221031160656833](https://img-blog.csdnimg.cn/img_convert/f9bc82cd7a875fda568fb6126fc31bbb.png)

这里提一嘴,我们可以将es6语法检查关闭。

![image-20221030183344496](https://img-blog.csdnimg.cn/img_convert/7fa46835c75df1a19c057f63b9afc5c0.png)

### 6.2.2 效果优化-快速显示开关

1. 在列表中添加自定义列:中间加<template></template>标签。可以通过 Scoped slot 可以获取到 row, column, $index 和 store(table 内部的状态管理)的数据

2. 修改开关状态,发送修改请求

3. 数据库中showStatus是01,开关默认值是true/false。 所以在开关中设置:active-value="1" 、:inactive-value="0"属性,与数据库同步



![image-20221030183722150](https://img-blog.csdnimg.cn/img_convert/0e5cb2e2277f9b5a0a7e5b417ec5b453.png)

![image-20221030183940992](https://img-blog.csdnimg.cn/img_convert/06181424559a618357fcc839b93dc4ff.png)

```vue
<!--brand.vue中显示状态那一列-->
      <el-table-column
        prop="showStatus"
        header-align="center"
        align="center"
        label="显示状态"
      >
        <template slot-scope="scope">
          <el-switch
            v-model="scope.row.showStatus"
            active-color="#13ce66"
            inactive-color="#ff4949"
            :active-value="1" 
            :inactive-value="0"
            @change="updateBrandStatus(scope.row)" 
          >
          </el-switch>
        </template>
      </el-table-column>

<!--brand-add-or-update.vue中显示状态那一列-->
      <el-form-item label="显示状态" prop="showStatus">
        <el-switch
          v-model="dataForm.showStatus"
          active-color="#13ce66"
          inactive-color="#ff4949"
          :active-value="1"
          :inactive-value="0"
        >
        </el-switch>
      </el-form-item>

//brand.vue中新增方法,用来修改状态
updateBrandStatus(data) {
      let { brandId, showStatus } = data;
      this.$http({
        url: this.$http.adornUrl("/product/brand/update"),
        method: "post",
        data: this.$http.adornData({ brandId, showStatus }, false),
      }).then(({ data }) => {
        this.$message({
          message: "状态修改成功",
          type: "success",
        });
      });
    },
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值