目录
- 拿当前登录人信息工具类
- 服务模块
- 业务分析
- 表结构
- 后端代码
- 后台代码
- 覆写删除-加详情一起删
- 调整前端Data,handleAdd和编辑框
- 覆写新增
- 编辑按钮展示详情
- 资源:多图上传和回显图片
拿当前登录人信息工具类
工具类准备:LoginContext: 登录上下文,获取当前登录人的信息
/**
* 登录上下文
* 1.获取当前登录人的信息
* 2.获取当前登录人的权限(我们不写)
* 我们如何在非Spring容器管理的对象中,获取Spring管理的Bean对对象
*/
public class LoginContext {
/**
* 通过从请求头中获得token
* 再通过以token为key去redis拿登录人信息返回
*/
public static Logininfo getLoginIn(HttpServletRequest request){
//1.获取token
String token = request.getHeader("token");
if(!StringUtils.isEmpty(token)){
//获取Spring容器
WebApplicationContext applicationContext =
WebApplicationContextUtils.getWebApplicationContext(request.getServletContext());
//从容器中获取bean
RedisTemplate redisTemplate = applicationContext.getBean("redisTemplate",RedisTemplate.class);
//2.根据token从redis中获取loginInfo
Object obj = redisTemplate.opsForValue().get(token);
if(obj != null){//redis中登录用户还没有过期
return (Logininfo)obj;
}
}
return null;
}
}
服务模块
业务分析
要两张表,基础信息表和服务详情表,前台上架都展示,后台要录入,只用展示基础信息
平台提供基础的洗澡,美容,洁牙等基础服务。
在线下单:用户通过前台页面下单,平台把订单的推送给离用户最近的门店,由门店提供线下服务。
线下服务:用户到店消费,由店员下单完成交易。
表结构
CREATE TABLE `t_product` (
`id` bigint(2) NOT NULL AUTO_INCREMENT,
`name` varchar(255) DEFAULT NULL COMMENT '服务名称',
`resources` varchar(255) DEFAULT NULL COMMENT '存放fastdfs地址,多个资源使用,分割',
`saleprice` decimal(19,2) DEFAULT NULL COMMENT '售价',
`offsaletime` datetime DEFAULT NULL COMMENT '下架时间',
`onsaletime` datetime DEFAULT NULL COMMENT '上架时间',
`state` bigint(2) DEFAULT NULL COMMENT '状态:0下架 1上架',
`costprice` varchar(255) DEFAULT NULL COMMENT '成本价',
`createtime` datetime DEFAULT NULL,
`salecount` bigint(20) DEFAULT NULL COMMENT '销售数量',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=169 DEFAULT CHARSET=utf8;
salecount:冗余过来,防止数据库压力过大
CREATE TABLE `t_product_detail` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`product_id` bigint(20) DEFAULT NULL,
`intro` text COMMENT '简介',
`orderNotice` text COMMENT '预约须知',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=160 DEFAULT CHARSET=utf8;
后端代码
新建模块,
product:domain,query,mapper,service,controller,yml
productDetail:domain,query,mapper,不用service和controller,由product级联操作
拦截器放行swagger
.excludePathPatterns("/swagger-resources/**","/webjars/**","/v2/**","/swagger-ui.html/**");
swagger不支持token,用postman测试
后台代码
拷贝department页面为product页面
替换英文单词与中文汉字,删掉部门树方法,getEmployee方法,dirpath,管理员,父服务,交给路由,调整分页SQL,
调整页面显示字段,data层:编辑需要的字段,domain调整时间显示格式,
覆写删除-加详情一起删
ProductServiceImpl
@Override
@Transactional
public void delete(Long id) {
//1.删除服务详情
productDetailMapper.removeByProductId(id);
//2.删除服务
productMapper.remove(id);
}
调整前端Data,handleAdd和编辑框
略
覆写新增
ProductServiceImpl
@Override
public void add(Product product) {
//1.保存基本信息
productMapper.save(product);
//2.保存详情
ProductDetail detail = product.getDetail();
detail.setProduct_id(product.getId());
productDetailMapper.save(detail);
}
编辑按钮展示详情
查列表页不查详情,点编辑再查详情
product.vue
//显示编辑界面
handleEdit: function (index, row) {
// this.productFormVisible = true;
this.productForm = Object.assign({}, row);// 克隆当前行数据
//查询详情数据 回显
this.$http.get("/product/detail/"+row.id)
.then(result=>{
result = result.data;//ProductDetail
this.productForm.detail = result;
this.productFormVisible = true;//显示编辑窗口
})
.catch(result=>{
this.$message({
message: '系统错误',
type: 'error'
});
});
},
ProductController
/**
* 通过服务id获取服务详情
* @param productId
* @return
*/
@GetMapping("/detail/{productId}")
@ApiOperation(value = "查询一条服务数据",notes = "需要传入productId")
public ProductDetail getDetailByProductId(@PathVariable("productId") Long productId){
return productService.getDetailByProductId(productId);
}
ProductServiceImpl
@Override
public ProductDetail getDetailByProductId(Long productId) {
return productDetailMapper.loadByProductId(productId);
}
ProductDetailMapper
<select id="loadByProductId" resultType="ProductDetail">
SELECT * FROM t_product_detail WHERE product_id = #{productId}
</select>
资源:多图上传和回显图片
页面元素:resources,data声明fileList: [],,拷贝3个钩子方法,
handleSuccess把fileList组合拼接后给到resources(然后才能传到后端)
没有handleRemove图片清除fileList 导致每行打开编辑按钮图片一样或都没有 -> 需要在编辑界面先清空fileList
回显要弄成规定格式,
fileList: [
{name: 'food.jpeg', url: 'http://115.159.217.249:8888/group1/M00/00/4D/rBEAA2S5zz-AG8C3AADiDkvRRWc389.jpg'},
{name: 'food2.jpeg', url: 'http://115.159.217.249:8888/group1/M00/00/4D/rBEAA2S5z0eAJSzaAABTid_F4kM953.jpg'}
]
let resources = row.resources;
let fileListTmp = [];
if(resources){
resources = resources.split(",");//[xxx.jpg,yyy.jpg]
for(let i=0;i<resources.length;i++){
fileListTmp.push(
{
response:{resultObj:resources[i]},//和handleSuccess里的fileList结构一致
url:"http://115.159.217.249:8888"+resources[i]
});
}
}
this.fileList = fileListTmp;//图片回显
删除成功后重新刷新resources
//删除成功后,需要重新刷新resources
let resources = '';
if(fileList){
for(let i=0;i<fileList.length;i++){
if(i == fileList.length-1){//如果是最后一张就不需要加,
resources = resources + fileList[i].response.resultObj;
// /group1/M00/00/75/rBEAA2BUYpyAE1ndAACffoTtVYI783.jpg
}else{
resources = resources + fileList[i].response.resultObj +",";
}
}
}