概述
在开发完DAO层、Service层、Controller层之后,我们来实现下View层的部分
前端框架选择
我们这里选择阿里的SUI Mobile
具体的介绍,这里我们就不多说了,直接访问官网即可(尴尬,SUI Mobile貌似不维护了。。。)
页面目录结构
搭建商铺注册页面
我们选择使用http://m.sui.taobao.org/demos/form/label-input/ 这个表单作为我们我们的商铺注册页面,基于这个页面来进行修改
根据http://m.sui.taobao.org/getting-started/的指导,结合我们的数据模型,成型的页面如下
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <title>商铺注册</title> <meta name="description" content="MSUI: Build mobile apps with simple HTML, CSS, and JS components."> <meta name="author" content="阿里巴巴国际UED前端"> <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"> <meta name="format-detection" content="telephone=no"> <!-- Google Web Fonts --> <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"> <script> var _hmt = _hmt || []; (function() { var hm = document.createElement("script"); hm.src = "//hm.baidu.com/hm.js?ba76f8230db5f616edc89ce066670710"; var s = document.getElementsByTagName("script")[0]; s.parentNode.insertBefore(hm, s); })(); </script> </head> <body> <div class="page-group"> <div id="page-label-input" class="page"> <header class="bar bar-nav"> <!-- <a class="button button-link button-nav pull-left back" href="/demos/form"> <span class="icon icon-left"></span> 返回 </a> --> <h1 class="title">商铺注册</h1> </header> <div class="content"> <div class="list-block"> <!--根据tb_shop中的字段,店铺信息的页面编写出来--> <ul> <!-- 商铺名称 --> <li> <div class="item-content"> <div class="item-inner"> <div class="item-title label">商铺名称</div> <div class="item-input"> <!-- 添加id 便于在js中操作 --> <input type="text" id="shop-name" placeholder="商铺名称"> </div> </div> </div> </li> <!-- 商铺分类 下拉列表 --> <li> <div class="item-content"> <div class="item-inner"> <div class="item-title label">商铺分类</div> <div class="item-input"> <!-- 增加id,便于js中操作,需要从后台读取数据 --> <select id="shop-category"> </select> </div> </div> </div> </li> <!-- 所属区域 下拉列表 - --> <li> <div class="item-content"> <div class="item-inner"> <div class="item-title label">所属区域</div> <div class="item-input"> <select id="shop-area"> </select> </div> </div> </div> </li> <!-- 详细地址 text--> <li> <div class="item-content"> <div class="item-inner"> <div class="item-title label">详细地址</div> <div class="item-input"> <!-- 添加id 便于在js中操作 --> <input type="text" id="shop-addr" placeholder="详细地址"> </div> </div> </div> </li> <!-- 商铺电话 text--> <li> <div class="item-content"> <div class="item-inner"> <div class="item-title label">商铺电话</div> <div class="item-input"> <!-- 添加id 便于在js中操作 --> <input type="text" id="shop-phone" placeholder="商铺电话"> </div> </div> </div> </li> <!-- 商铺图片 上传组件--> <li class="item-content"> <div class="item-inner"> <div class="item-inner"> <div class="item-title label">商铺图片</div> <div class="item-input"> <input type="file" id="shop-img"> </div> </div> </div> </li> <!-- 商铺简介 textarea--> <li class="align-top"> <div class="item-content"> <div class="item-inner"> <div class="item-title label">商铺简介</div> <div class="item-input"> <textarea id="shop-desc" placeholder="商铺简介"></textarea> </div> </div> </div> </li> <!-- 验证码 kapa--> <li> <div class="item-content"> <div class="item-inner"> <div class="item-title label">验证码</div> <input type="text" id="j_kaptcha" placeholder="验证码"> <div class="item-input"> <img id="kaptcha_img" alt="点击更换" title="点击更换" onclick="changeVerifyCode(this)" src="../Kaptcha"> <!-- src是找到web.xml中 对应的servlet的名字 --> </div> </div> </div> </li> </ul> </div> <div class="content-block"> <div class="row"> <div class="col-50"> <!-- 点击返回,回到商铺管理页面 TODO --> <a href="#" class="button button-big button-fill button-danger">返回</a> </div> <div class="col-50"> <!-- 增加id ,便于js操作 --> <a href="#" class="button button-big button-fill button-success" id="submit">提交</a> </div> </div> </div> </div> </div> </div> <!-- 将css写在头部,将js写在尾部,为了更好地用户体验 --> <script type='text/javascript' src='//g.alicdn.com/sj/lib/zepto/zepto.min.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> <!-- 加载自定义的JS --> <script type='text/javascript' src='../resources/js/shop/shopoperation.js' charset='utf-8'></script> <script type='text/javascript' src='../resources/js/common/common.js' charset='utf-8'></script> </body> </html>
Chrome浏览器,F12进入开发者模式,选择下图右上角的图标
注意:这个页面是整个调测完的页面,js以及kaptcha组件也配置调测完了,如果是第一次搭建,验证码部分是不会有的。
JS部分
shopoperation.js
/** * */ $(function() { // 获取基本信息的URL var initUrl = '/o2o/shopadmin/getshopinitinfo'; // 注册店铺的URL var registerShopUrl = '/o2o/shopadmin/registshop'; // 调用函数,加载数据 getShopInitInfo(); // 验证表单输入,省略。。。。 /** * 从后台加载获取下拉菜单的值 */ function getShopInitInfo() { $.getJSON(initUrl, function(data) { if (data.success) { var tempShopCategoryHtml = ''; var tempShopAreaHtml = ''; data.shopCategoryList.map(function(item, index) { tempShopCategoryHtml += '<option data-id="' + item.shopCategoryId + '">' + item.shopCategoryName + '</option>'; }); data.areaList.map(function(item, index) { tempShopAreaHtml += '<option data-id="' + item.areaId + '">' + item.areaName + '</option>'; }); // 获取html中对应标签的id 赋值 $('#shop-category').html(tempShopCategoryHtml); $('#shop-area').html(tempShopAreaHtml) }else{ $.toast(data.errMsg); } }); }; /** * submit按钮触发的操作 */ $('#submit').click(function() { // 获取页面的值 var shop = {}; // 注意: 这个地方的变量名称要和Shop实体类中的属性保持一致,因为后台接收到shopStr后,会将Json转换为实体类,如果不一致会抛出异常 // com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException shop.shopName = $('#shop-name').val(); shop.shopAddr = $('#shop-addr').val(); shop.phone = $('#shop-phone').val(); shop.shopDesc = $('#shop-desc').val(); // 选择id,双重否定=肯定 shop.shopCategory = { // 这里定义的变量要和ShopCategory.shopCategoryId保持一致,否则使用databind转换会抛出异常 shopCategoryId:$('#shop-category').find('option').not(function(){ return !this.selected; }).data('id') }; shop.area = { // 这里定义的变量要和Area.areaId属性名称保持一致,否则使用databind转换会抛出异常 areaId:$('#shop-area').find('option').not(function(){ return !this.selected; }).data('id') }; // 图片 var shopImg = $('#shop-img')[0].files[0]; // 验证码 var verifyCodeActual =$('#j_kaptcha').val(); console.log('verifyCodeActual:'+verifyCodeActual); if(!verifyCodeActual){ $.toast('请输入验证码'); return; } // 接收数据 var formData = new FormData(); // 和后端约定好,利用shopImg和 shopStr接收 shop图片信息和shop信息 formData.append('shopImg',shopImg); // 转成JSON格式,后端收到后将JSON转为实体类 formData.append('shopStr',JSON.stringify(shop)); // 将数据封装到formData发送到后台 formData.append('verifyCodeActual',verifyCodeActual); // 利用ajax提交 $.ajax({ url:registerShopUrl, type:'POST', data:formData, contentType:false, processData:false, cache:false, success:function(data){ if(data.success){ $.toast('提示信息:'+data.errMsg); }else{ $.toast('提示信息:' + data.errMsg); } // 点击提交后 不管成功失败都更换验证码,防止重复提交 $('#kaptcha_img').click(); } }); }); });
common.js
/** * */ function changeVerifyCode(img){ img.src="../Kaptcha?" + Math.floor(Math.random() * 1000) }
作用为:点击更换验证码
当然了,加上这个也会显示出来验证码,下拉框的初始化数据也不会存在,后文继续更新
乱码问题
如果部署后,前台页面乱码,需要在web.xml中加入CharacterEncodingFilter
<!-- 为避免编码不一致,一般情况下都需要增加编码过滤器 --> <filter> <filter-name>SpringEncodingFilter</filter-name> <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class> <init-param> <param-name>encoding</param-name> <param-value>UTF-8</param-value> </init-param> <init-param> <param-name>forceEncoding</param-name> <param-value>true</param-value> </init-param> </filter> <filter-mapping> <filter-name>SpringEncodingFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>
将页面迁到WEB-INF目录下
为了安全,我们将shopoperation.html 迁移到/o2o/src/main/webapp/WEB-INF/html/shop/shopoperation.html。 通过servlet来控制访问,这样的话,我们就需要来根据请求路径来进行页面的跳转
Controller层的编写
package com.artisan.o2o.web.shopadmin; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; @Controller @RequestMapping("/shopadmin") public class ShopAdminController { @RequestMapping(value = "/shopoperation", method = RequestMethod.GET) public String shopOperation() { return "shop/shopoperation"; } }
根据/o2o/src/main/resources/spring/spring-web.xml中的定义
<!-- 3.定义视图解析器 --> <bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <property name="prefix" value="/WEB-INF/html/"></property> <property name="suffix" value=".html"></property> </bean>
可知会转发到/WEB-INF/html/目录下,文件后缀以html结尾的文件中,符合我们的定义。
访问
启动tomcat,根据RequestMapping,可知访问
http://localhost:8080/o2o/shopadmin/shopoperation