Java网络商城项目 SpringBoot+SpringCloud+Vue 网络商城(SSM前后端分离项
method: ‘post’,url: ‘/user/12345’,
data: {
firstName: ‘Fred’,
lastName: ‘Flintstone’
}
});
// 获取远端图片
axios({
method:‘get’,
url:‘http://bit.ly/2mTM3nY’,
responseType:‘stream’
})
.then(function(response) {
response.data.pipe(fs.createWriteStream(‘ada_lovelace.jpg’))
});
b、美满页面的Ajax哀求
在http.js当已经将axios对象添加到Vue的静态常量当中,直接可以通过this.$http来调用axios
固然Vue类以及写好了但是依旧可以往里面添加东西
设置哀求测试
this.$http.get(“/brand/page”,{//设置哀求路径
params:{//设置哀求参数
page : 1,
}
}).then(resp => {//在http.js当已经将axios对象添加到Vue的静态常量当中,直接可以通过this.$http来调用axios
})
[*]搜索功能
双向绑定命据(v-model)
https://img-blog.csdnimg.cn/6e92b2c1c6ed4bd491e7b71fdea200ca.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQ0NzU3MDM0,size_16,color_FFFFFF,t_70
设置初始值
https://img-blog.csdnimg.cn/cf42bca6e69b426cbd68d43780462b98.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQ0NzU3MDM0,size_16,color_FFFFFF,t_70
实现发送哀求返回对应的数据(设置搜索框改变数据的时间边改变边发送数据)
https://img-blog.csdnimg.cn/1de862432ceb4539a2d903ed19a98227.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQ0NzU3MDM0,size_16,color_FFFFFF,t_70
全部代码
新增品牌
<v-data-table
:headers=“headers”
:items=“brands”
:pagination.sync=“pagination”
:total-items=“totalBrands”
:loading=“loading”
class=“elevation-1”
{{ props.item.id }} {{ props.item.name }}{{ props.item.letter }} edit
delete
运行效果
https://img-blog.csdnimg.cn/5201bc8db2744c95b41624f116cd1b97.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQ0NzU3MDM0,size_16,color_FFFFFF,t_70
[*]分页查询(设置pagination)
https://img-blog.csdnimg.cn/73916926f74846d2a4b52a736f59fb9a.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQ0NzU3MDM0,size_16,color_FFFFFF,t_70
Vuetify在this的pagination当中提供了默认的分页信息
https://img-blog.csdnimg.cn/303a973c09404501ab45df83d48e7ee0.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQ0NzU3MDM0,size_16,color_FFFFFF,t_70
每当中分页信息发生变革的时间就方式哀求,所以需要对pagination的值进行监控,将分页参数发送到背景
https://img-blog.csdnimg.cn/68d8c8b60e9145f7ad2fc745be266805.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQ0NzU3MDM0,size_16,color_FFFFFF,t_70
[*]运行观察效果
http://manage.leyou.com/#/item/brand
https://img-blog.csdnimg.cn/ba362ceff4a44bf489061c36a741a84c.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQ0NzU3MDM0,size_16,color_FFFFFF,t_70
https://img-blog.csdnimg.cn/9c570c3b2a6c46539a556c4a675bf10c.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQ0NzU3MDM0,size_16,color_FFFFFF,t_70
https://img-blog.csdnimg.cn/1dff44e09b154c4aab9faa6a49db11f6.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQ0NzU3MDM0,size_16,color_FFFFFF,t_70
通过上述发送的哀求编写后端,并返回当前页面的数据和总条数
2、 背景提供查询接口
(1)数据库
前台页面已经预备好,接下来就是背景提供数据接口了
CREATE TABLE tb_brand (
id bigint(20) NOT NULL AUTO_INCREMENT COMMENT ‘品牌id’,
name varchar(50) NOT NULL COMMENT ‘品牌名称’,
image varchar(200) DEFAULT ‘’ COMMENT ‘品牌图片地址’,
letter char(1) DEFAULT ‘’ COMMENT ‘品牌的首字母’,
PRIMARY KEY (id)
) ENGINE=InnoDB AUTO_INCREMENT=325402 DEFAULT CHARSET=utf8 COMMENT=‘品牌表,一个品牌下有多个商品(spu),一对多关系’;
简朴的四个字段
这里需要注意的是,品牌和商品分类之间是多对多关系。因此我们有一张中间表,来维护两者间关系;
DROP TABLE IF EXISTS tb_category_brand;
CREATE TABLE tb_category_brand (
category_id bigint(20) NOT NULL COMMENT ‘商品类目id’,
brand_id bigint(20) NOT NULL COMMENT ‘品牌id’,
PRIMARY KEY (category_id,brand_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT=‘商品分类和品牌的中间表,两者是多对多关系’;
但是,你可能会发现,这张表中并没有设置外键约束,似乎与数据库的设计范式不符。为什么这么做?
[*] 外键会严峻影响数据库读写的效率
[*] 数据删除时会比较麻烦
在电商行业当中,性能是非常
(2)实体类
创建对应的实体类
https://img-blog.csdnimg.cn/4631ed5392b245088a27f155df7b803c.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQ0NzU3MDM0,size_16,color_FFFFFF,t_70
https://img-blog.csdnimg.cn/2f87a07346e44725a1ee6ad0ee9d263e.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQ0NzU3MDM0,size_16,color_FFFFFF,t_70
package com.leyou.item.pojo;
import lombok.Data;
import tk.mybatis.mapper.annotation.KeySql;
import javax.persistence.Id;
import javax.persistence.Table;
@Data
@Table(name = “tb_brand”)
public class Brand {
/*
useGeneratedKeys设置为 true 时,表示假如插入的表id以自增列为主键,
则允许 JDBC 支持主动生成主键,并可将主动生成的主键id返回。
useGeneratedKeys参数只针对 insert 语句生效,默以为 false;
*/
@Id
@KeySql(useGeneratedKeys = true)
private Long id;
private String name;//
private String image;
private Character letter;
}
(3)创建实体类对应Mapper
https://img-blog.csdnimg.cn/ddcc789d187649ceb56d1a1c4d592f95.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQ0NzU3MDM0,size_16,color_FFFFFF,t_70
https://img-blog.csdnimg.cn/592261a798604945a80db2067f744c1a.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQ0NzU3MDM0,size_16,color_FFFFFF,t_70
package com.leyou.item.mapper;
import com.leyou.item.pojo.Brand;
import tk.mybatis.mapper.common.Mapper;
public interface BrandMapper extends Mapper {
}
(4)实体类对应的Service
https://img-blog.csdnimg.cn/76c514d0b975404e8d536f34b123fcbd.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQ0NzU3MDM0,size_16,color_FFFFFF,t_70
https://img-blog.csdnimg.cn/22c2a973a1a74bce9d7a708be6676d00.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQ0NzU3MDM0,size_16,color_FFFFFF,t_70
(7)生成实体类对应的控制层
https://img-blog.csdnimg.cn/821f8706b41e4c6d86c125103d9eb1b3.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQ0NzU3MDM0,size_16,color_FFFFFF,t_70
、修改页面的代码的哀求路径(在前加上item)
https://img-blog.csdnimg.cn/0f94c23db83d46c4950e97776e882082.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQ0NzU3MDM0,size_16,color_FFFFFF,t_70
b、创建返回效果的数据的对象PageResult类
https://img-blog.csdnimg.cn/61adbe01204846379d1e36475a3a7394.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQ0NzU3MDM0,size_16,color_FFFFFF,t_70
在这里封装一个类用来表示分页效果
https://img-blog.csdnimg.cn/c532c123aca649789b3abd39338307e8.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQ0NzU3MDM0,size_16,color_FFFFFF,t_70
package com.leyou.common.vo;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.List;
/*
@Data 生成getter,setter等函数
@NoArgsConstructor 生成无参构造函数
@AllArgsConstructor //生玉成参数构造函数
*/
@Data
public class PageResult {
private Long total;//总条数
private Integer totalPage;//总页数
private List items;//当前页数据
public PageResult() {
}
public PageResult(Long total,List items){
this.total = total;
this.items = items;
}
public PageResult(Long total, Integer totalPage, List items) {
this.total = total;
this.totalPage = totalPage;
this.items = items;
}
}
c、美满BrandController
https://img-blog.csdnimg.cn/08c68f21787141b08b96b15e808cda51.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQ0NzU3MDM0,size_16,color_FFFFFF,t_70
package com.leyou.item.web;
import com.leyou.common.vo.PageResult;
import com.leyou.item.pojo.Brand;
import com.leyou.item.pojo.Category;
import com.leyou.item.service.BrandService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
@RestController
@RequestMapping(“brand”)
public class BrandController {
@Autowired
public BrandService brandService;
@GetMapping(“page”)
public ResponseEntity<PageResult> queryBrandByPage(
//设置哀求参数参数名称value对应页面上的name,defaultValue默认值 然后是参数类型和参数名称
//相称于Integer name = Intgert.paseInt(request.getParamate(“name”)); 其中(“name”)等价于value=“name”
//Integer name等价于Integer page
//request=false(ture)表示前端的参数是否肯定要传入。true表示必须传入参数,false表示可传或不传
@RequestParam(value = “page”,defaultValue = “1”) Integer page,
@RequestParam(value = “rows”,defaultValue = “5”) Integer rows,
@RequestParam(value = “sortBy”,required = false) String sortBy,
@RequestParam(value = “desc”,defaultValue = “flase”) Boolean desc,
@RequestParam(value = “key”,required = false) String key
){
//上面设置好5个参数
//编写业务代码
PageResult result = brandService.queryBrandByPage(page,rows,sortBy,desc,key);
return ResponseEntity.ok(result);
}
}
d、创建对应商品没有查询到的错误非常
https://img-blog.csdnimg.cn/e7f70f2492b64c00af0f92e9839f0767.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQ0NzU3MDM0,size_16,color_FFFFFF,t_70
BRAND_NOT_FOUND(404,“品牌不存在”),
e、美满业务层代码
https://img-blog.csdnimg.cn/78a1c2e2d3724aa4ae440e4196277ab7.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQ0NzU3MDM0,size_16,color_FFFFFF,t_70
package com.leyou.item.service;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.leyou.common.enums.ExceptionEnum;
import com.leyou.common.exception.LyException;
import com.leyou.common.vo.PageResult;
import com.leyou.item.mapper.BrandMapper;
import com.leyou.item.pojo.Brand;
import lombok.val;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import tk.mybatis.mapper.entity.Example;
import java.util.List;
@Service
public class BrandService {
@Autowired
private BrandMapper brandMapper;
public PageResult queryBrandByPage(Integer page, Integer rows, String sortBy,
Boolean desc, String key) {
//分页(过滤器拦截MyBatis在厥后面拼接分页条件)
PageHelper.startPage(page,rows);//主动创建好分页的条件
//过滤
Example example = new Example(Brand.class);//设置条件并指定到那张表查询
if(StringUtils.isNotBlank(key))//判断只要key不为空
{
//过滤条件
// select * from tb_brand where name like “%%” or letter = ‘’ limit page,rows order by desc
//设置条件
example.createCriteria().//创建条件,并在后面设置对应的条件
orLike(“name”,“%”+key+“%”).//第一个条件
orEqualTo(“letter”,key.toUpperCase());//第二个条件 (key.toUpperCase()变成大写)
}
//排序
if(StringUtils.isNotBlank(sortBy)){//假如不为空做排序
//当sortBy是id的时间根据id查询,当sortBy是字母的时间根据字母排序,
// 三元运算符判断desc假如是true则DESC否则是ASC
String orderByClause = sortBy+(desc ? " DESC":" ASC");
example.setOrderByClause(orderByClause);//设置OrderBy排序,(直接编写SQL语句)
}
//查询
List list = brandMapper.selectByExample(example);
if(CollectionUtils.isEmpty(list)){
throw new LyException(ExceptionEnum.BRAND_NOT_FOUND);
}
PageResult pageResult = new PageResult();
pageResult.setItems(list);//设置数据
//剖析分页效果
PageInfo pageInfo = new PageInfo(list);//得到分页信息
pageResult.setTotal(pageInfo.getTotal());//设置总条数
return pageResult;
}
}
f、假如想要在上述代码当中看到SQL语句,需要添加如下的设置
以下设置设置SQL语句输出在控制台
https://img-blog.csdnimg.cn/8fd23639bbc34a3f93c4dc196b94afeb.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQ0NzU3MDM0,size_16,color_FFFFFF,t_70
mybatis:
configuration:
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
(8)运行项目并测试
https://img-blog.csdnimg.cn/cbf98ac9cfb74048bf84c5b27da13026.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQ0NzU3MDM0,size_16,color_FFFFFF,t_70
http://manage.leyou.com/#/item/brand
https://img-blog.csdnimg.cn/9e66b97092224364a0594f8273bb269b.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQ0NzU3MDM0,size_16,color_FFFFFF,t_70
成功获取到数据
https://img-blog.csdnimg.cn/7e938827fd444dc9a418f901aabb0b4c.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQ0NzU3MDM0,size_16,color_FFFFFF,t_70
并在控制台输出了SQL语句
https://img-blog.csdnimg.cn/2c8d11353b744528af3fbc3b5ff386fb.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQ0NzU3MDM0,size_16,color_FFFFFF,t_70
(9)美满页面代码
https://img-blog.csdnimg.cn/d107aa6034304117b6a98f866386ee75.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQ0NzU3MDM0,size_16,color_FFFFFF,t_70
全部前端代码
新增品牌
<v-data-table
:headers=“headers”
:items=“brands”
:pagination.sync=“pagination”
:total-items=“totalBrands”
:loading=“loading”
class=“elevation-1”
{{ props.item.id }} {{ props.item.name }}{{ props.item.letter }} edit
delete
重新运行测试
http://manage.leyou.com/#/item/brand
https://img-blog.csdnimg.cn/8b17d0acd5ef43e2bdb8b5590d6444ba.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQ0NzU3MDM0,size_16,color_FFFFFF,t_70
(10)美满一下搜索功能
https://img-blog.csdnimg.cn/d02ed1c188d44fec8d4d45cb98ee90af.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQ0NzU3MDM0,size_16,color_FFFFFF,t_70
this.pagination.page = 1;//每次修改条件的时间都将起始页设置为1
3、品牌新增功能
(1)页面搭建
a、初步编写弹框
当我们点击新增按钮,应该出现一个弹窗,然后在弹窗中出现一个表格,我们就可以填写品牌信息了。我们查察Vuetify官网,弹窗是怎样实现:
https://img-blog.csdnimg.cn/0b23a6fab8f54b31b552a2a781c2a62a.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQ0NzU3MDM0,size_16,color_FFFFFF,t_70
https://img-blog.csdnimg.cn/a88fda03a8ae4f179b5799d50c6c604f.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQ0NzU3MDM0,size_16,color_FFFFFF,t_70
https://img-blog.csdnimg.cn/a81c686fcbaf430487b81feeb14d9612.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQ0NzU3MDM0,size_16,color_FFFFFF,t_70
新增品牌
我是表单
将这段代码复制到页面当中
https://img-blog.csdnimg.cn/e0f9b3951a51425ca1e98930ce29df39.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQ0NzU3MDM0,size_16,color_FFFFFF,t_70
接下来,我们要在点击新增品牌按钮时,将窗口表现,因此要给新增按钮绑定事故
https://img-blog.csdnimg.cn/fbea63dcd6e246f59c4b7af14faea2b8.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQ0NzU3MDM0,size_16,color_FFFFFF,t_70
<v-btn color=“primary” @click=“addBrand”>新增品牌
然后界说一个addBrand方法:
https://img-blog.csdnimg.cn/f49f09cc4e554d9481e7fcb938ba959d.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQ0NzU3MDM0,size_16,color_FFFFFF,t_70
addBrand(){
// 控制弹窗可见:
this.show = true;
}
效果:
https://img-blog.csdnimg.cn/a122959a9f484015b2481d61190c4e1a.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQ0NzU3MDM0,size_16,color_FFFFFF,t_70
https://img-blog.csdnimg.cn/ea14c5e9e4a241098396aa22a2e281a8.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQ0NzU3MDM0,size_16,color_FFFFFF,t_70
窗口关闭
如今,悲剧发生了,因为我们设置了persistent属性,窗口无法被关闭了。除非把show属性设置为false
因此我们需要给窗口添加一个关闭按钮:
https://img-blog.csdnimg.cn/b2134b4157514abdac5ce09cf3c0b5ea.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQ0NzU3MDM0,size_16,color_FFFFFF,t_70
并且,我们还给按钮绑定了点击事故,回调函数为closeWindow。
接下来,编写closeWindow函数:
https://img-blog.csdnimg.cn/c25c93ee0b584fdf86c3aa5453b8da3f.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQ0NzU3MDM0,size_16,color_FFFFFF,t_70
closeWindow(){
// 关闭窗口
this.show = false;
}
效果:
https://img-blog.csdnimg.cn/cff292af11dc45269e434f1555a4e3a2.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQ0NzU3MDM0,size_16,color_FFFFFF,t_70
b、新增品牌的表单页
接下来就是写表单了。我们有两种选择:
[*] 直接在dialog对话框中编写表单代码
[*] 另外编写一个组件,组件内写表单代码。然后在对话框引用组件
选第几种?
我们选第二种方案,优点:
[*] 表单代码独立组件,可拔插,方便后期的维护。
[*] 代码分离,可读性更好。
我们新建一个MyBrandForm.vue组件:
https://img-blog.csdnimg.cn/b23091a21e7c473ab9b035ac0bbf6d93.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQ0NzU3MDM0,size_16,color_FFFFFF,t_70
将MyBrandForm引入到MyBrand中,这里利用局部组件的语法:
https://img-blog.csdnimg.cn/ddc933bfffbf479483c56573853175f0.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQ0NzU3MDM0,size_16,color_FFFFFF,t_70
// 导入自界说的表单组件
import MyBrandForm from ‘./MyBrandForm’
修改一下表单的名称以及添加一些内容
https://img-blog.csdnimg.cn/be00bf982db64a9585784041f3fb2592.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQ0NzU3MDM0,size_16,color_FFFFFF,t_70
https://img-blog.csdnimg.cn/050a3f5cd4824df28a68567a3980a3e0.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQ0NzU3MDM0,size_16,color_FFFFFF,t_70
<my-brand-form @close=“closeWindow” >
https://img-blog.csdnimg.cn/30b25260f9fb43d8b1e7ffc3b2667fc7.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQ0NzU3MDM0,size_16,color_FFFFFF,t_70
然后通过components属性来指定局部组件:
https://img-blog.csdnimg.cn/2a0126d904d54d16848f59694d6bdefd.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQ0NzU3MDM0,size_16,color_FFFFFF,t_70
components:{
MyBrandForm
}
c、编写表单
i、表单
查察官网文档,找到表单干系内容
v-form,表单组件,内部可以有很多输入项。v-form有下面的属性:
[*]value:true,代表表单验证通过;false,代表表单验证失败
v-form提供了两个方法:
[*] reset:重置表单数据
[*] validate:校验整个表单数据,条件是你写好了校验规则。返回Boolean表示校验成功或失败
我们在data中界说一个valid属性,跟表单的value进行双向绑定,观察表单是否通过校验,同时把等会要跟表单关联的品牌brand对象声明出来:
https://img-blog.csdnimg.cn/689dceaf81934f3b93c13fda7ff0f6f7.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQ0NzU3MDM0,size_16,color_FFFFFF,t_70
export default {
name: “my-brand-form”,
data() {
return {
valid:false, // 表单校验效果标志
brand:{
name:‘’, // 品牌名称
letter:‘’, // 品牌首字母
image:‘’,// 品牌logo
categories:[], // 品牌所属的商品分类数组
}
}
}
}
然后,在页面先写一个表单:
https://img-blog.csdnimg.cn/b98101a5124f4d89a1f2bb3276a78070.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQ0NzU3MDM0,size_16,color_FFFFFF,t_70
修改会原来的路由规则
https://img-blog.csdnimg.cn/61ee027c96ed499a89e0c1dbaef7d4ef.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQ0NzU3MDM0,size_16,color_FFFFFF,t_70
ii、文本框
我们的品牌总共需要这些字段:
[*] 名称
[*] 首字母
[*] 商品分类,有很多个
[*] LOGO
表单项主要包罗文本框、密码框、多选框、单选框、文本域、下拉选框、文件上传等。思考下我们的品牌需要哪些?
[*] 文本框:品牌名称、品牌首字母都属于文本框
[*] 文件上传:品牌需要图片,这个是文件上传框
[*] 下拉选框:商品分类提前已经界说好,这里需要通过下拉选框展示,提供给用户选择。
先看文本框,昨天已经用过的,叫做v-text-field:
查察文档,v-text-field有以下关键属性:
[*] append-icon:文本框后追加图标,需要填写图标名称。无默认值
[*] clearable:是否添加一个清空图标,点击会清空文本框。默认是false
[*] color:颜色
[*] counter:是否添加一个文本计数器,在角落表现文本长度,指定true或允许的组大长度。无默认值
[*] dark:是否应用黑暗色调,默认是false
[*] disable:是否禁用,默认是false
[*] flat:是否移除默认的动画效果,默认是false
[*] full-width:指定宽度为全屏,默认是false
[*] hide-details:是否因此错误提示,默认是false
[*] hint:输入框的提示文本
[*] label:输入框的标签
[*] multi-line:是否转为文本域,默认是false。文本框和文本域可以自由切换
[*] placeholder:输入框占位符文本,focus后消散
[*] required:是否为必填项,假如是,会在label后加*,不具备校验功能。默认是false
[*] rows:文本域的行数,multi-line为true时才有效
[*] rules:指定校验规则及错误提示信息,数组结构。默认[]
[*] single-line:是否单行文本表现,默认是false
[*] suffix:表现后缀
接下来,我们先添加两个字段:品牌名称、品牌的首字母,校验规则暂时不写:
https://img-blog.csdnimg.cn/0897a74d6c894e8bb44db5453c9ec2f2.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQ0NzU3MDM0,size_16,color_FFFFFF,t_70
https://img-blog.csdnimg.cn/32c23f0634d64e68ad8c9457493d0e19.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQ0NzU3MDM0,size_16,color_FFFFFF,t_70
iii、级联下拉菜单
接下来就是商品分类了,按照刚才的分析,商品分类应该是下拉选框。
但是各人仔细思考,商品分类包罗三级。在展示的时间,应该是先由用户选中1级,才表现2级;选择了2级,才表现3级。形成一个多级分类的三级联动效果。
这个时间,就不是普通的下拉选框,而是三级联动的下拉选框!
如许的选框,在Vuetify中并没有提供(它提供的是根本的下拉框)。因此我已经给各人编写了一个无穷级联动的下拉选框,可以或许满足我们的需求。
https://img-blog.csdnimg.cn/4b5d84159b4b4e9f9883fe2771ef5fc3.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQ0NzU3MDM0,size_16,color_FFFFFF,t_70
<v-cascader
url=“/item/category/list”
multiple
required
v-model=“brand.categories”
label=“请选择商品分类”/>
[*] url:加载商品分类选项的接口路径
[*] multiple:是否多选,这里设置为true,因为一个品牌可能有多个分类
[*] requried:是否是必须的,这里为true,会在提示上加*,提示用户
[*] v-model:关联我们brand对象的categories属性
[*] label:笔墨说明
演示效果如下
https://img-blog.csdnimg.cn/572209010a5f43f6aec7b0bffe89e1c8.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQ0NzU3MDM0,size_16,color_FFFFFF,t_70
iV、文件上传项
在Vuetify中,也没有文件上传的组件。
还好,我已经给各人写好了一个文件上传的组件:
我们添加上传的组件:
品牌LOGO:
<v-upload
v-model=“brand.image”
url=“/upload”
:multiple=“false”
:pic-width=“250”
:pic-height=“90”
/>
https://img-blog.csdnimg.cn/481dd314dfd2420a95db28d2ab0aa401.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQ0NzU3MDM0,size_16,color_FFFFFF,t_70
注意:
[*] 文件上传组件自己没有提供笔墨提示。因此我们需要自己添加一段笔墨说明
[*] 我们要实现笔墨和图片组件左右放置,因此这里利用了v-layout布局组件:
[*] layout添加了row属性,代表这是一行,假如是column,代表是多行
[*] layout下面有v-flex组件,是这一行的单位,我们有2个单位
[*] <v-flex xs3> :表现笔墨说明,xs3是响应式布局,代表占12格中的3格
[*] 剩下的部分就是图片上传组件了
[*] v-upload:图片上传组件,包罗以下属性:
[*] v-model:将上传的效果绑定到brand的image属性
[*] url:上传的路径,我们先随便写一个。
[*] multiple:是否运行多图片上传,这里是false。因为品牌LOGO只有一个
[*] pic-width和pic-height:可以控制l图片上传后展示的宽高
最闭幕果:
https://img-blog.csdnimg.cn/4d209eea9d9b450683c9addea6aeb062.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQ0NzU3MDM0,size_16,color_FFFFFF,t_70
V、按钮
上面已经把全部的表单项写完。最后就差提交和清空的按钮了。
在表单的最下面添加两个按钮:
https://img-blog.csdnimg.cn/e36a8f81d5274a948041869ba08513ce.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQ0NzU3MDM0,size_16,color_FFFFFF,t_70
<v-btn @click=“submit” color=“primary”>提交
<v-btn @click=“clear” >重置
[*] 通过layout来进行布局,my-4增大上下边距
[*] v-spacer占用肯定空间,将按钮都倾轧到页面右侧
[*] 两个按钮分别绑定了submit和clear事故
我们先将方法界说出来:
https://img-blog.csdnimg.cn/2614b825e6404fcba705e64c0ff671a7.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQ0NzU3MDM0,size_16,color_FFFFFF,t_70
methods:{
submit(){
// 提交表单
},
clear(){
// 重置表单
}
}
重置表单相对简朴,因为v-form组件已经提供了reset方法,用来清空表单数据。
只要我们拿到表单组件对象,就可以调用方法了。
我们可以通过$refs内置对象来获取表单组件。
首先,在表单上界说ref属性:
https://img-blog.csdnimg.cn/0088a3ab6ed34581b65db8ffbca6df78.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQ0NzU3MDM0,size_16,color_FFFFFF,t_70
https://img-blog.csdnimg.cn/c27966b2646644bfbc87bdf10b172204.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQ0NzU3MDM0,size_16,color_FFFFFF,t_70
clear(){
// 重置表单
this.$refs.myBrandForm.reset();//获取带ref对应的表单数据
//设置商品分类为空
this.categories = [];
}
要注意的是,这里我们还手动把this.categories清空了,因为我写的级联选择组件并没有跟表单结合起来。需要手动清空。
(2)表单校验
Vuetify的表单校验,是通过rules属性来指定的:
https://img-blog.csdnimg.cn/1b1949fd1fbe4114bb801199091468f1.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQ0NzU3MDM0,size_16,color_FFFFFF,t_70
校验规则的写法:
https://img-blog.csdnimg.cn/cdd7719b69e04815ab625ad32b8baf46.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQ0NzU3MDM0,size_16,color_FFFFFF,t_70
nameRules: [
v => !!v || “品牌名称不能为空”,
v => v.length > 1 || “品牌名称至少2位”
],
letterRules: [
v => !!v || “首字母不能为空”,
v => /1{1}$/.test(v) || “品牌字母只能是1个字母”
]
效果:
https://img-blog.csdnimg.cn/902d6d54235a4aacb3da482e6c65db30.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQ0NzU3MDM0,size_16,color_FFFFFF,t_70
(3)提交表单信息
在submit方法中添加表单提交的逻辑:
https://img-blog.csdnimg.cn/b2d1c880b5e3451c80ccba1e24302b07.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQ0NzU3MDM0,size_16,color_FFFFFF,t_70
submit(){
// 提交表单
if(this.$refs.myBrandForm.validate()){
//界说一个哀求参数的对象,通过结构表达式来获取brand当中的属性
const { categories,letter, …params } = this.brand;
//数据库当中只需要保存分类id即可,因此我们对categories的值进行处理,只保存id,并转换为字符串
params.cids = categories.map(c => c.id).join(“,”);
//将字母都处理为大写
params.letter = letter.toUpperCase();
// 5、将数据提交到背景
this.$http.post(‘/item/brand’, params)
.then(() => {
// 6、弹出提示
this.$message.success(“保存成功!”);
})
.catch(() => {
this.$message.error(“保存失败!”);
});
}
运行测试
https://img-blog.csdnimg.cn/fdb1f45ee932414385a220ce671a1a44.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQ0NzU3MDM0,size_16,color_FFFFFF,t_70
https://img-blog.csdnimg.cn/0135975c42d7455f95cc65f1a8d9eafe.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQ0NzU3MDM0,size_16,color_FFFFFF,t_70
[*] 1、通过this.$refs.myBrandForm选中表单,然后调用表单的validate方法,进行表单校验。返回boolean值,true代表校验通过
[*] 2、通过解构表达式来获取brand中的值,categories和letter需要处理,单独获取。其它的存入params对象中
[*] 3、品牌和商品分类的中间表只保存两者的id,而brand.categories中保存的数对象数组,里面有id和name属性,因此这里通过数组的map功能转为id数组,然后通过join方法拼接为字符串
[*] 4、首字母都处理为大写保存
[*] 5、发起哀求
[*] 6、弹窗提示成功还是失败,这里用到的是我们的自界说组件功能message组件:
https://img-blog.csdnimg.cn/17b9d071b68a4479a95eaddbbb567ab4.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQ0NzU3MDM0,size_16,color_FFFFFF,t_70
这个插件把$message对象绑定到了Vue的原型上,因此我们可以通过this.$message来直接调用。
包罗以下常用方法:
[*] info、error、success、warning等,弹出一个带有提示信息的窗口,色调与为普通(灰)、错误(红色)、成功(绿色)和警告(黄色)。利用方法:this.$message.info(“msg”)
[*] confirm:确认框。用法:this.$message.confirm("确认框的提示信息"),返回一个Promise
[*] 设置在提交成功以后关闭窗口
https://img-blog.csdnimg.cn/cdabf014ac0646b88eb087fc03b2baee.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQ0NzU3MDM0,size_16,color_FFFFFF,t_70
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到如今。
深知大多数前端工程师,想要提升技能,每每是自己探索发展或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此网络整理了一份《2024年Web前端开辟全套学习资料》,初衷也很简朴,就是希望可以或许帮助到想自学提升又不知道该从何学起的朋友,同时减轻各人的负担。
https://img-blog.csdnimg.cn/img_convert/6756e52aa521686ecf15f3105c423332.jpeg
https://img-blog.csdnimg.cn/img_convert/f39c8f17946806682d26fdaecfddec8e.png
既有适合小白学习的零根本资料,也有适合3年以上履历的小同伴深入学习提升的进阶课程,根本涵盖了95%以上前端开辟知识点,真正体系化!
https://img-blog.csdnimg.cn/img_convert/5318dede09c5adffa7d960f214b0f3ec.png
由于文件比较大,这里只是将部分目次截图出来,每个节点里面都包罗大厂面经、学习笔记、源码讲义、实战项目、解说视频,并且会连续更新!
假如你觉得这些内容对你有帮助,可以扫码获取!!(备注:前端)
https://img-blog.csdnimg.cn/img_convert/b5dfb300062710ba0248789bb718ddb9.jpeg 最后
分享一套阿里大牛整理的前端资料给各人,点击前端校招面试题精编剖析大全即可获取
❤️ 谢谢支持,喜欢的话别忘了 关注、点赞哦。
_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQ0NzU3MDM0,size_16,color_FFFFFF,t_70)
https://img-blog.csdnimg.cn/0135975c42d7455f95cc65f1a8d9eafe.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQ0NzU3MDM0,size_16,color_FFFFFF,t_70
[*] 1、通过this.$refs.myBrandForm选中表单,然后调用表单的validate方法,进行表单校验。返回boolean值,true代表校验通过
[*] 2、通过解构表达式来获取brand中的值,categories和letter需要处理,单独获取。其它的存入params对象中
[*] 3、品牌和商品分类的中间表只保存两者的id,而brand.categories中保存的数对象数组,里面有id和name属性,因此这里通过数组的map功能转为id数组,然后通过join方法拼接为字符串
[*] 4、首字母都处理为大写保存
[*] 5、发起哀求
[*] 6、弹窗提示成功还是失败,这里用到的是我们的自界说组件功能message组件:
https://img-blog.csdnimg.cn/17b9d071b68a4479a95eaddbbb567ab4.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQ0NzU3MDM0,size_16,color_FFFFFF,t_70
这个插件把$message对象绑定到了Vue的原型上,因此我们可以通过this.$message来直接调用。
包罗以下常用方法:
[*] info、error、success、warning等,弹出一个带有提示信息的窗口,色调与为普通(灰)、错误(红色)、成功(绿色)和警告(黄色)。利用方法:this.$message.info(“msg”)
[*] confirm:确认框。用法:this.$message.confirm("确认框的提示信息"),返回一个Promise
[*] 设置在提交成功以后关闭窗口
https://img-blog.csdnimg.cn/cdabf014ac0646b88eb087fc03b2baee.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQ0NzU3MDM0,size_16,color_FFFFFF,t_70
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到如今。
深知大多数前端工程师,想要提升技能,每每是自己探索发展或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此网络整理了一份《2024年Web前端开辟全套学习资料》,初衷也很简朴,就是希望可以或许帮助到想自学提升又不知道该从何学起的朋友,同时减轻各人的负担。
[外链图片转存中…(img-pR3TtD6M-1712938045455)]
[外链图片转存中…(img-iGf1caya-1712938045456)]
既有适合小白学习的零根本资料,也有适合3年以上履历的小同伴深入学习提升的进阶课程,根本涵盖了95%以上前端开辟知识点,真正体系化!
[外链图片转存中…(img-fjIOjkdv-1712938045456)]
由于文件比较大,这里只是将部分目次截图出来,每个节点里面都包罗大厂面经、学习笔记、源码讲义、实战项目、解说视频,并且会连续更新!
假如你觉得这些内容对你有帮助,可以扫码获取!!(备注:前端)
https://img-blog.csdnimg.cn/img_convert/b5dfb300062710ba0248789bb718ddb9.jpeg 最后
分享一套阿里大牛整理的前端资料给各人,点击前端校招面试题精编剖析大全即可获取
❤️ 谢谢支持,喜欢的话别忘了 关注、点赞哦。
https://img-blog.csdnimg.cn/img_convert/0119cc540369a7517b1ffa05f0e6f43f.webp?x-oss-process=image/format,png
[*]a-zA-Z ↩︎
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
页:
[1]