SSM校园商铺平台(二)
1. Logback日志记录
1.1 主要模块
- logback-class
- logback-classic
- logback-core
1.2 主要标签
- logger
- appender
- layout
1.3使用logback
1.3.1 logback属性配置,在resources创建一个logback.xml
- 配置logback刷新时间间隔,60秒
- 定义日志级别,TRACE<DEBUG<INFO<WARN<ERROR,日志级别定义为debug就会显示高于debug级别的日志
- 定义存储时间,30天
- 定义日志文件存放位置
- 定义日志显示方式,日期+线程+日志级别+信息+换行
<?xml version="1.0" encoding="utf-8" standalone="no"?>
<configuration debug="false">
<appender name="INFO-FILE"
class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${catalina.base}/webapps/myo2o/logs/info/info.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>${catalina.base}/webapps/myo2o/logs/info/info.%d{yyyy-MM-dd}.%i.log.zip</fileNamePattern>
<timeBasedFileNamingAndTriggeringPolicy
class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<maxFileSize>1024MB</maxFileSize>
</timeBasedFileNamingAndTriggeringPolicy>
<maxHistory>30</maxHistory>
</rollingPolicy>
<layout class="ch.qos.logback.classic.PatternLayout">
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{55} -
%msg%n
</pattern>
</layout>
</appender>
<appender name="ACCESS-FILE"
class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>
${catalina.base}/webapps/myo2o/logs/access/access.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<FileNamePattern>${catalina.base}/webapps/myo2o/logs/access/access.%d{yyyy-MM-dd}.%i.log.zip</FileNamePattern>
<timeBasedFileNamingAndTriggeringPolicy
class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<maxFileSize>1024MB</maxFileSize>
</timeBasedFileNamingAndTriggeringPolicy>
<maxHistory>30</maxHistory>
</rollingPolicy>
<layout class="ch.qos.logback.classic.PatternLayout">
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{55} -
%msg%n
</pattern>
</layout>
</appender>
<logger name="com.imooc.myo2o" level="DEBUG" additivity="false">
<appender-ref ref="ACCESS-FILE" />
</logger>
<root level="INFO">
<appender-ref ref="INFO-FILE" />
</root>
</configuration>
2.店铺模块
2.1 新增店铺(店铺注册)
2.1.1 创建ShopDao接口
返回值为主键shop_id
public interface ShopDao {
// 新增店铺
int insertShop(Shop shop);
//更新店铺
int updateShop(Shop shop);
}
2.1.2 ShopDao.xml文件
- 指定名称空间为ShopDao接口
- 对于insert语句,设置数据库中的主键keyColum和entity中的主键
- useGeneratedKeys指定返回值为主键id
- update的parameterType指定传入参数类型
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.imooc.o2o.dao.ShopDao">
<!-- useGeneratedKeys取出shop的主键id -->
<insert id="insertShop" useGeneratedKeys="true" keyColumn="shop_id" keyProperty="shopId">
insert into
tb_shop(owner_id,area_id,shop_category_id,shop_name,shop_desc,shop_addr,
phone,shop_img,priority,create_time,last_edit_time,enable_status,advice)
values
(#{owner.userId},#{area.areaId},#{shopCategory.shopCategoryId},#{shopName},#{shopDesc},
#{shopAddr},#{phone},#{shopImg},#{priority},#{createTime},#{lastEditTime},#{enableStatus},
#{advice})
</insert>
<update id="updateShop" parameterType="com.imooc.o2o.entity.Shop">
update tb_shop
<set>
<if test="shopName != null">shop_name=#{shopName},</if>
<if test="shopDesc != null">shop_desc=#{shopDesc},</if>
<if test="shopAddr != null">shop_addr=#{shopAddr},</if>
<if test="phone != null">phone=#{phone},</if>
<if test="shopImg != null">shop_img=#{shopImg},</if>
<if test="priority != null">priority=#{priority},</if>
<if test="lastEditTime != null">last_edit_time=#{lastEditTime},</if>
<if test="enableStatus != null">enable_status=#{enableStatus},</if>
<if test="advice != null">advice=#{advice},</if>
<if test="area != null">area_id=#{area.areaId},</if>
<if test="shopCategory != null">shop_category_id=#{shopCategory.shopCategoryId},</if>
</set>
where shop_id=#{shopId}
</update>
</mapper>
2.2 测试输出
3. 图片处理和封装Util
3.1 使用thumbnailator进行图片处理
3.1.1 添加图片处理的包
<!-- https://mvnrepository.com/artifact/net.coobird/thumbnailator -->
<dependency>
<groupId>net.coobird</groupId>
<artifactId>thumbnailator</artifactId>
<version>0.4.8</version>
</dependency>
3.1.2 该包使用测试
- 获取当前线程下resources包的路径
- 调用Thumbnails工具类
- of 方法指定要处理的图片的位置
- size方法指定将图片压缩的大小
- watermark方法指定水印加在的位置、水印图片位置、水印透明度
- toFile方法自定返回图片的位置
public class ImageUtil {
public static void main(String[] args) throws IOException {
String basePath = Thread.currentThread().getContextClassLoader().getResource("").getPath();
Thumbnails.of(new File("D:\\TaoTao\\需要的图片\\images\\item\\shop\\15\\20170605234852321010.jpg"))
.size(200, 200)
.watermark(Positions.BOTTOM_RIGHT, ImageIO.read(new File(basePath+"\\watermark.png")), 0.25f)
.outputQuality(0.8)
.toFile("D:\\TaoTao\\需要的图片\\images\\item\\shop\\15\\watermark.png");
}
}
3.2 封装工具类
3.2.1 在util包下创建PathUtil类
public class PathUtil {
private static String seperator = System.getProperty("file.separator");
//返回项目图片的根路径
public static String getImgBasePath() {
//获取操作系统名称
String os = System.getProperty("os.name");
String basePath = "";
//如果是Windows系统
if(os.toLowerCase().startsWith("win")) {
basePath = "F:/project/image/";
}
else {
basePath = "/home/xiangze/image/";
}
//为了使符号/符合各个操作系统,将/替换成操作系统指定的分隔符
basePath = basePath.replace("/" , seperator);
return basePath;
}
//返回项目图片的子路径
public static String getShopImagePath(long shopId) {
String imagePath = "/upload/item/shop"+shopId+"/";
return imagePath.replace("/", seperator);
}
}
3.2.2 在util包下创建ImageUtil类
public class ImageUtil {
private static String basePath = Thread.currentThread().getContextClassLoader().getResource("").getPath();
private static final SimpleDateFormat sDateFormat = new SimpleDateFormat(
"yyyyMMddHHmmss"); // 时间格式化的格式
private static final Random r = new Random();
//处理缩略图
public static String generateThumbnail(CommonsMultipartFile thumbnail, String targetAddr) {
String realFileName = getRandomFileName();
String extension = getFileExtension(thumbnail);
makeDirPath(targetAddr);
String relativeAddr = targetAddr + realFileName + extension;
File dest = new File(PathUtil.getImgBasePath() + relativeAddr);
try {
Thumbnails.of(thumbnail.getInputStream()).size(200, 200).outputQuality(0.25f).toFile(dest);
} catch (IOException e) {
throw new RuntimeException("创建缩略图失败:" + e.toString());
}
return relativeAddr;
}
//生成随机文件名
public static String getRandomFileName() {
// 生成随机文件名:当前年月日时分秒+五位随机数(为了在实际项目中防止文件同名而进行的处理)
int rannum = (int) (r.nextDouble() * (99999 - 10000 + 1)) + 10000; // 获取随机数
String nowTimeStr = sDateFormat.format(new Date()); // 当前时间
return nowTimeStr + rannum;
}
//获取输入文件流的扩展名
private static String getFileExtension(CommonsMultipartFile cFile) {
String originalFileName = cFile.getOriginalFilename();
return originalFileName.substring(originalFileName.lastIndexOf("."));
}
//创建目标路径所涉及到的目录,比如com/immoc/o2o
//让其自动创建com、imooc,o2o三个文件夹
private static void makeDirPath(String targetAddr) {
String realFileParentPath = PathUtil.getImgBasePath() + targetAddr;
File dirPath = new File(realFileParentPath);
if (!dirPath.exists()) {
dirPath.mkdirs();
}
}
}
4.添加店铺返回类型(用在service层)
比如在操作店铺Shop类的时候,添加店铺是成功还是失败,我们需要有一个返回类型,卸载dto包中。返回给controller层去处理
4.1 在dto包创建ShopExecution类
- 店铺添加结果的状态(状态码)
- 状态标识(状态码对应的名称)
- 为了识别状态和状态码,创建了一个枚举类保存所有状态
- 店铺数量
- 操作的店铺
- 店铺列表
public class ShopExecution {
//结果状态
private int state;
//状态标识
private String stateInfo;
//店铺数量
private int count;
//操作的店铺(增删改店铺时用到)
private Shop shop;
//shop列表(查询店铺的首使用)
private List<Shop> shopList;
public ShopExecution() {
}
//店铺操作失败的时候使用的构造器
public ShopExecution(ShopStateEnum stateEnum) {
this.state = stateEnum.getState();
this.stateInfo = stateEnum.getStateInfo();
}
//店铺操作成功的时候使用的构造器
public ShopExecution(ShopStateEnum stateEnum,Shop shop) {
this.state = stateEnum.getState();
this.stateInfo = stateEnum.getStateInfo();
this.shop = shop;
}
//店铺操作成功的时候使用的构造器
public ShopExecution(ShopStateEnum stateEnum,List<Shop> shopList) {
this.state = stateEnum.getState();
this.stateInfo = stateEnum.getStateInfo();
this.shopList = shopList;
}
}
4.2在enum包下创建ShopStateEnum枚举类,来标识各种状态
- 该类没有set方法,不能让外界修改枚举类型
- 提供了外界查找枚举类型的接口
public enum ShopStateEnum {
CHECK(0,"审核中"),
OFFLINE(1,"非法店铺"),
SUCCESS(1,"操作成功"),
PASS(2,"通过认证"),
INNER_ERROR(-1001,"内部系统错误"),
NULL_SHOPID(-1002,"shopId为空");
private int state;
private String stateInfo;
private ShopStateEnum(int state, String stateInfo) {
this.state = state;
this.stateInfo = stateInfo;
}
//外部查找state的枚举类型
public static ShopStateEnum stateOf(int state) {
for(ShopStateEnum stateEnum:values()) {
if(stateEnum.getState()==state) {
return stateEnum;
}
}
return null;
}
public int getState() {
return state;
}
public String getStateInfo() {
return stateInfo;
}
}
5.添加店铺的Service层设计
5.1 店铺设计的ShopServiceimpl类
- 自动装载shopDao
- 实现接口中的添加店铺的方法
- 判断店铺是否为空,为空返回ShopExecution空值的对象,对象包含店铺为空状态和标识info
- shop对象不为空,给shop添加初始信息:初始状态:0待审核状态,创建日期和更新日期
- 将店铺添加到数据库,返回shopId主键
- 返回值<=0则说明添加到数据库失败,否则添加成功
- 店铺添加到数据库后,再添加店铺对应的图片到数据库,调用addShopImg方法
- addShopImg方法:根据shopId创建保存该店铺图片的路径,并且将上传到服务器的图片保存到该路径,并将shop的img地址修改为当前保存的路径。
- addShopImg方法抵用结束后,shop对象被修改了,我们将该对象的修改更新到数据库,抵用dao层的店铺更新方法。再判断更新是否成功,不成功抛出店铺操作异常。
- 返回ShopExecution对象,表明审核状态。
public class ShopServiceImpl implements ShopService{
@Autowired
private ShopDao shopDao;
@Override
public ShopExecution addShop(Shop shop, CommonsMultipartFile shopImg) {
//验证店铺是否为空
if(shop==null) {
return new ShopExecution(ShopStateEnum.NULL_SHOP);
}
try {
//给店铺信息赋初始值
shop.setEnableStatus(0);
shop.setCreateTime(new Date());
shop.setLastEditTime(new Date());
//添加店铺信息
int effectedNum = shopDao.insertShop(shop);
if(effectedNum<=0) {
throw new RuntimeException("店铺创建失败");
}
else {
if(shopImg != null) {
//存储图片
try {
addShopImg(shop,shopImg);
} catch (Exception e) {
throw new RuntimeException("addShopImg error:"+e.getMessage());
}
//更新店铺的图片地址
effectedNum = shopDao.updateShop(shop);
if(effectedNum <= 0) {
throw new ShopOperationException("更新图片地址失败");
}
}
}
}catch(Exception e) {
throw new RuntimeException("addShop error:"+e.getMessage());
}
return null;
}
private void addShopImg(Shop shop, CommonsMultipartFile shopImg) {
//获取shop图片目录的相对路径
String dest = PathUtil.getShopImagePath(shop.getShopId());
String shopImgAddr = ImageUtil.generateThumbnail(shopImg, dest);
//修改shop中的的img地址
shop.setShopImg(shopImgAddr);
}
}
5.2 店铺操作异常类
该类继承自RuntimeException 是为了保证事务的原子性,操作失败进行回滚。也就是如果添加到数据库的数据成功后抛出异常,也会将前面的操作进行回滚,清楚数据库的该条信息。
public class ShopOperationException extends RuntimeException {
/**
*
*/
private static final long serialVersionUID = 4771094100507194189L;
public ShopOperationException(String msg) {
super(msg);
}
}
6.前端页面
前端采用阿里巴巴的SUI mobile框架,源码的git地址https://github.com/sdc-alibaba/SUI-Mobile
7.controller层的设计
由于html文件全部存放在WEB-INF目录下面,无法直接访问,所以要写相应的controller,让controller跳转到WEB-INF下的路径
7.1 测试controller
7.1.1 测试controller
@Controller
@RequestMapping(value="shopadmin",method= {RequestMethod.GET})
public class ShopAdminController {
@RequestMapping("/shopedit")
public String shopOperation() {
return "shop/shopedit";
}
}
7.1.2 测试前端显示
7.2 创建shopManagementController类
用于注册店铺等
7.2.1 shopManagementController类
- registerShop方法注册店铺
- 传入前端传过来的request数据
- 将前端传过来的request数据中shopStr部分通过JSON转换成shop对象实例
- 获取前端传过来的图片字节流shopImg:
- 注册店铺
- 由于注册店铺调用的addShop需要传入File类型的图片,所以我们为了便于接受来自前端的数据,我们重写了service层的addShop方法,传入3个参数,inputStream字节流文件和文件名fileName
- 返回对象
@Controller
@RequestMapping("/shopadmin")
public class ShopManagementController {
@Autowired
private ShopService shopService;
@RequestMapping(value="/registershop",method= {RequestMethod.POST})
@ResponseBody
private Map<String,Object> registerShop(HttpServletRequest request) throws IOException{
Map<String,Object> modelMap = new HashMap<>();
//1.接受并转换相应的参数
String shopStr = HttpServletRequestUtil.getString(request, "shopStr");
ObjectMapper mapper = new ObjectMapper();
Shop shop = null;
try {
//这是将字符串shopStr转换成Shop.class类的JSON数据格式
shop = mapper.readValue(shopStr , Shop.class);
} catch (Exception e) {
modelMap.put("success", false);
modelMap.put("errMsg",e.getMessage());
return modelMap;
}
//获取前端传递的文件流(图片)
CommonsMultipartFile shopImg = null;
CommonsMultipartResolver commonsMultipartResolver = new CommonsMultipartResolver(
request.getSession().getServletContext());
//判断上传的request是否含有图片,是就将图片赋值给shopImg
if(commonsMultipartResolver.isMultipart(request)) {
MultipartHttpServletRequest httpServletRequest = (MultipartHttpServletRequest) request;
shopImg = (CommonsMultipartFile) httpServletRequest.getFile("shopImg");
}
else {
modelMap.put("success", false);
modelMap.put("errMsg","上传图片不能为空");
return modelMap;
}
//2.注册店铺
if(shop!=null && shopImg!=null) {
PersonInfo owner = new PersonInfo();
//UserId是session传过来的
owner.setUserId(1L);
shop.setOwner(owner);
ShopExecution se = shopService.addShop(shop, shopImg.getInputStream(),shopImg.getOriginalFilename());
if(se.getState()==ShopStateEnum.CHECK.getState()) {
modelMap.put("success", true);
}
else {
modelMap.put("success", false);
modelMap.put("errMsg", se.getStateInfo());
}
}
else {
modelMap.put("success", false);
modelMap.put("errMsg","请输入店铺信息");
return modelMap;
}
//3.返回结果
return modelMap;
}
}
7.3 店铺注册的前端实现
7.3.1 店铺注册页面跳转
首先我们需要通过url跳转到店铺注册页面,因为店铺注册页面的html文件是放在WEB-INF目录下的,不能直接访问,需要controller来实现跳转
@Controller
@RequestMapping(value="shopadmin",method= {RequestMethod.GET})
public class ShopAdminController {
@RequestMapping("/shopedit")
public String shopOperation() {
return "shop/shopedit";
}
}
7.3.2 店铺注册前端shopedit.html代码
- 由于需要显示店铺类别和所属区域的选择项,所以我们需要从后台获取到这两部分内容,显示到前台
- 还需要将填写的内容提交到后台
- 为了完成这两个操作,我们采用js来实现,所以需要实现shopedit.js代码
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>商店信息</title>
<meta name="viewport" content="initial-scale=1, maximum-scale=1">
<link rel="shortcut icon" href="/favicon.ico">
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="black">
<link rel="stylesheet"
href="//g.alicdn.com/msui/sm/0.6.2/css/sm.min.css">
<link rel="stylesheet"
href="//g.alicdn.com/msui/sm/0.6.2/css/sm-extend.min.css">
</head>
<body>
<header class="bar bar-nav">
<h1 class="title">商店信息</h1>
</header>
<div class="content">
<div class="list-block">
<ul>
<li>
<div class="item-content">
<div class="item-media">
<i class="icon icon-form-name"></i>
</div>
<div class="item-inner">
<div class="item-title label">商铺名称</div>
<div class="item-input">
<input type="text" id="shop-name" placeholder="商铺名称">
</div>
</div>
</div>
</li>
<li>
<div class="item-content">
<div class="item-media">
<i class="icon icon-form-email"></i>
</div>
<div class="item-inner">
<div class="item-title label">商铺分类</div>
<div class="item-input">
<select id="shop-category">
</select>
</div>
</div>
</div>
</li>
<li>
<div class="item-content">
<div class="item-media">
<i class="icon icon-form-email"></i>
</div>
<div class="item-inner">
<div class="item-title label">所属区域</div>
<div class="item-input">
<select id="area">
</select>
</div>
</div>
</div>
</li>
<li>
<div class="item-content">
<div class="item-media">
<i class="icon icon-form-email"></i>
</div>
<div class="item-inner">
<div class="item-title label">详细地址</div>
<div class="item-input">
<input type="text" id="shop-addr" placeholder="详细地址">
</div>
</div>
</div>
</li>
<li>
<div class="item-content">
<div class="item-media">
<i class="icon icon-form-email"></i>
</div>
<div class="item-inner">
<div class="item-title label">联系电话</div>
<div class="item-input">
<input type="tel" id="shop-phone" placeholder="联系电话">
</div>
</div>
</div>
</li>
<li>
<div class="item-content">
<div class="item-media">
<i class="icon icon-form-email"></i>
</div>
<div class="item-inner">
<div class="item-title label">缩略图</div>
<div class="item-input">
<input type="file" id="shop-img" placeholder="联系电话">
</div>
</div>
</div>
</li>
<li>
<div class="item-content">
<div class="item-media">
<i class="icon icon-form-email"></i>
</div>
<div class="item-inner">
<div class="item-title label">店铺简介</div>
<div class="item-input">
<textarea placeholder="店铺简介" id="shop-desc"></textarea>
</div>
</div>
</div>
</li>
<li>
<div class="item-content">
<div class="item-media">
<i class="icon icon-form-email"></i>
</div>
<div class="item-inner">
<label for="j_captcha" class="item-title label">验证码</label> <input
id="j_captcha" name="j_captcha" type="text"
class="form-control in" placeholder="验证码" />
<div class="item-input">
<img id="captcha_img" alt="点击更换" title="点击更换"
onclick="changeVerifyCode(this)" src="../Kaptcha" />
</div>
</div>
</div>
</li>
</ul>
</div>
<div class="content-block">
<div class="row">
<div class="col-50">
<a href="/myo2o/shop/shopmanage"
class="button button-big button-fill button-danger">返回</a>
</div>
<div class="col-50">
<a href="#" class="button button-big button-fill" id="submit">提交</a>
</div>
</div>
</div>
</div>
<script type='text/javascript'
src='//g.alicdn.com/sj/lib/zepto/zepto.js' charset='utf-8'></script>
<script type='text/javascript'
src='//g.alicdn.com/msui/sm/0.6.2/js/sm.min.js' charset='utf-8'></script>
<script type='text/javascript'
src='//g.alicdn.com/msui/sm/0.6.2/js/sm-extend.min.js' charset='utf-8'></script>
<script type='text/javascript'
src='../resources/js/common/commonutil.js' charset='utf-8'></script>
<script type='text/javascript' src='../resources/js/shop/shopedit.js'
charset='utf-8'></script>
</body>
</html>
7.3.3 店铺注册前端shopedit.js代码
- 从后台获取shopCategoryName和areaName,通过js返回到到前台变量中,供前台显示
- 添加提交按钮的事件方法,如果点击提交按钮,执行该方法,将前台数据提交到后台
- 提交方法主要获取两部分内容,一部分为字节流文件,就是输入的String类型存到shop中;另一部分为字节流文件,就是图片文件存放在shopImg。将这两个变量封装成JSON数据格式保存到formData中,再通过ajax提交到后台。
- 为了使第一个方法自动执行,需要在该js文件中调用该方法,自动获取后台传过来的区域和类别信息
$(function() {
var shopId = getQueryString('shopId');
var isEdit = shopId ? true : false;
var shopInfoUrl = '/myo2o/shop/getshopbyid?shopId=1';
// var shopInfoUrl = '/myo2o/shop/getshopbyid?shopId=' + shopId;
//用于获取店铺的info信息
var initUrl = '/o2o/shop/getshopinitinfo';
//注册店铺
var editShopUrl = '/o2o/shop/registershop';
if (isEdit) {
editShopUrl = '/myo2o/shop/modifyshop';
}
function getInfo(shopId) {
$.getJSON(shopInfoUrl, function(data) {
if (data.success) {
var shop = data.shop;
$('#shop-name').val(shop.shopName);
$('#shop-addr').val(shop.shopAddr);
$('#shop-phone').val(shop.phone);
$('#shop-desc').val(shop.shopDesc);
var shopCategory = '<option data-id="'
+ shop.shopCategory.shopCategoryId + '" selected>'
+ shop.shopCategory.shopCategoryName + '</option>';
var tempAreaHtml = '';
data.areaList.map(function(item, index) {
tempAreaHtml += '<option data-id="' + item.areaId + '">'
+ item.areaName + '</option>';
});
$('#shop-category').html(shopCategory);
$('#shop-category').attr('disabled','disabled');
$('#area').html(tempAreaHtml);
$('#area').attr('data-id',shop.areaId);
}
});
}
//1. 获取从后台获取shopCategoryName和areaName,并显示到前台变量中
function getCategory() {
$.getJSON(initUrl, function(data) {
if (data.success) {
var tempHtml = '';
var tempAreaHtml = '';
data.shopCategoryList.map(function(item, index) {
tempHtml += '<option data-id="' + item.shopCategoryId
+ '">' + item.shopCategoryName + '</option>';
});
data.areaList.map(function(item, index) {
tempAreaHtml += '<option data-id="' + item.areaId + '">'
+ item.areaName + '</option>';
});
$('#shop-category').html(tempHtml);
$('#shop-category').removeAttr('disabled');
$('#area').html(tempAreaHtml);
}
});
}
alert(initUrl);
if (isEdit) {
getInfo(shopId);
} else {
getCategory();
}
//2. 该函数用于执行点击提交,就将前台数据提交到后台
$('#submit').click(function() {
var shop = {};
shop.shopName = $('#shop-name').val();
shop.shopAddr = $('#shop-addr').val();
shop.phone = $('#shop-phone').val();
shop.shopDesc = $('#shop-desc').val();
shop.shopCategory = {
shopCategoryId : $('#shop-category').find('option').not(function() {
return !this.selected;
}).data('id')
};
shop.area = {
areaId : $('#area').find('option').not(function() {
return !this.selected;
}).data('id')
};
//上传文件流
var shopImg = $("#shop-img")[0].files[0];
var formData = new FormData();
formData.append('shopImg', shopImg);
//上传shopStr字符流
formData.append('shopStr', JSON.stringify(shop));
var verifyCodeActual = $('#j_captcha').val();
if (!verifyCodeActual) {
$.toast('请输入验证码!');
return;
}
formData.append("verifyCodeActual", verifyCodeActual);
//将formData提交到后台
$.ajax({
url : editShopUrl,
type : 'POST',
// contentType: "application/x-www-form-urlencoded; charset=utf-8",
data : formData,
contentType : false,
processData : false,
cache : false,
success : function(data) {
if (data.success) {
$.toast('提交成功!');
if (isEdit){
$('#captcha_img').click();
} else{
window.location.href="/shop/shoplist";
}
} else {
$.toast('提交失败!');
$('#captcha_img').click();
}
}
});
});
});
对于从后台获取店铺类别和区域信息在下一节讲到。