瀏覽代碼

init from phab

xielq 4 年之前
父節點
當前提交
ad2bbe0c8b

+ 0 - 0
README.md


+ 21 - 0
build.gradle

@@ -0,0 +1,21 @@
+apply from: "$rootDir/gradle/service-base.gradle"
+apply from: "$rootDir/gradle/publish.gradle"
+
+group 'com.uas.cloud.mall'
+version '0.1.0'
+
+jar {
+    baseName = 'mall-home-app'
+    version = '0.1.0'
+}
+
+dependencies {
+ 	compile("org.springframework.boot:spring-boot-starter-web")
+    compile("org.thymeleaf:thymeleaf-spring4")
+    compile("org.springframework.cloud:spring-cloud-starter-feign")
+    compile("org.springframework.cloud:spring-cloud-starter-ribbon")
+    compile("org.springframework.cloud:spring-cloud-starter-hystrix")
+
+    compile "com.uas.cloud.base.commons:common:0.1.0"
+}
+

+ 78 - 0
gradle/publish.gradle

@@ -0,0 +1,78 @@
+task sourcesJar(type: Jar) {
+    baseName 'home-app'
+    classifier 'sources'
+    from sourceSets.main.allSource
+}
+artifacts {
+    archives sourcesJar
+}
+
+apply plugin: 'distribution'
+
+distributions {
+    main {
+        baseName = archivesBaseName
+
+        contents {
+            from { libsDir }
+        }
+    }
+
+    docs {
+        baseName = "$archivesBaseName-docs"
+
+        contents {
+            from(libsDir) {
+                include sourcesJar.archiveName
+            }
+        }
+    }
+}
+
+ext {
+    artifactoryBaseUrl = 'http://113.105.74.141:8081/artifactory'
+    artifactorySnapshotRepoUrl = "$artifactoryBaseUrl/libs-snapshot-local"
+    artifactoryReleaseRepoUrl = "$artifactoryBaseUrl/libs-release-local"
+}
+
+apply plugin: 'maven-publish'
+
+publishing {
+    publications {
+        plugin(MavenPublication) {
+            from components.java
+            artifactId 'home-app'
+
+            pom.withXml {
+                def root = asNode()
+                root.appendNode('name', 'dfs service')
+                root.appendNode('description', '商城首页 app')
+                root.appendNode('inceptionYear', '2017')
+
+                def developer = root.appendNode('developers').appendNode('developer')
+                developer.appendNode('id', 'yangck')
+                developer.appendNode('name', '杨朝坤')
+                developer.appendNode('email', 'yangck@usoftchina.com')
+            }
+
+            artifact sourcesJar
+        }
+    }
+
+    repositories {
+        maven {
+            name 'myLocal'
+            url "file://$projectDir/repo"
+        }
+
+        maven {
+            name 'remoteArtifactory'
+            url project.version.endsWith('-SNAPSHOT') ? artifactorySnapshotRepoUrl : artifactoryReleaseRepoUrl
+
+            credentials {
+                username = 'yingp'
+                password = '111111'
+            }
+        }
+    }
+}

+ 61 - 0
gradle/service-base.gradle

@@ -0,0 +1,61 @@
+buildscript {
+    ext {
+        springBootVersion = '1.4.4.RELEASE'
+    }
+    repositories {
+        maven { url "http://maven.aliyun.com/nexus/content/groups/public/" }
+        mavenCentral()
+        jcenter()
+    }
+    dependencies {
+        classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
+    }
+}
+
+apply plugin: 'idea'
+apply plugin: 'eclipse'
+apply plugin: 'java'
+//apply plugin: 'spring-boot'
+apply plugin: org.springframework.boot.gradle.plugin.SpringBootPlugin // applying a plugin by plugin id is not supported in script plugins. You must use the plugin's fully qualified class name.
+sourceCompatibility = 1.8 // 必须在apply java插件之后
+targetCompatibility = 1.8
+
+bootRun {
+    addResources = true
+}
+idea {
+    module {
+        downloadSources = true
+        downloadJavadoc = false
+        inheritOutputDirs = false
+        outputDir = file("$buildDir/classes/main/")
+    }
+}
+
+repositories {
+    mavenLocal()
+    maven { url "http://maven.aliyun.com/nexus/content/groups/public/" }
+    maven {
+        url 'http://10.10.101.21:8081/artifactory/libs-release'
+    }
+    maven {
+        url 'http://10.10.101.21:8081/artifactory/libs-snapshot'
+    }
+    maven {
+        url 'http://10.10.101.21:8081/artifactory/plugins-snapshot'
+    }
+    mavenCentral()
+}
+
+dependencyManagement {
+    imports {
+        mavenBom 'org.springframework.cloud:spring-cloud-dependencies:Camden.SR5'
+    }
+}
+dependencies {
+    testCompile 'org.springframework.boot:spring-boot-starter-test'
+    compile 'org.springframework.cloud:spring-cloud-starter-config'
+    // compile("org.springframework.boot:spring-boot-devtools")
+    compile "org.springframework.cloud:spring-cloud-starter-eureka"
+
+}

+ 2 - 0
settings.gradle

@@ -0,0 +1,2 @@
+rootProject.name = 'home-app'
+

+ 24 - 0
src/main/java/com/umall/shop/home/HomeApplication.java

@@ -0,0 +1,24 @@
+package com.umall.shop.home;
+
+import com.umall.shop.home.config.RootConfig;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.boot.builder.SpringApplicationBuilder;
+import org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker;
+import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
+import org.springframework.context.annotation.Import;
+
+/**
+ * 商城首页
+ *
+ * @author yangck
+ * @create 2017-02-15 17:34
+ */
+@SpringBootApplication
+@EnableDiscoveryClient
+@EnableCircuitBreaker // 开启断路器功能
+@Import(RootConfig.class)
+public class HomeApplication {
+    public static void main(String[] args) {
+        new SpringApplicationBuilder(HomeApplication.class).web(true).run(args);
+    }
+}

+ 22 - 0
src/main/java/com/umall/shop/home/config/RootConfig.java

@@ -0,0 +1,22 @@
+package com.umall.shop.home.config;
+
+import org.springframework.cloud.client.loadbalancer.LoadBalanced;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.web.client.RestTemplate;
+
+/**
+ * Bean配置
+ *
+ * @author umall
+ * @create 2017/2/15
+ */
+@Configuration
+public class RootConfig {
+
+    @LoadBalanced
+    @Bean
+    public RestTemplate restTemplate() {
+        return new RestTemplate();
+    }
+}

+ 142 - 0
src/main/java/com/umall/shop/home/domain/Carousel.java

@@ -0,0 +1,142 @@
+package com.umall.shop.home.domain;
+
+import javax.servlet.http.Part;
+
+/**
+ * 轮播
+ *
+ * @author yangck
+ * @create 2017-02-16 10:27
+ */
+public class Carousel {
+
+    private Long id;
+
+    /**
+     * 用于哪个应用
+     */
+    private String usedFor;
+
+    /**
+     * 排序数字
+     */
+    private Long orderNumber;
+
+    private Part picture;
+
+    /**
+     * 图片url
+     * 主要是获取其它域名的图片
+     */
+    private String pictureUrl;
+
+    /**
+     * 链接URI
+     * 根据上下文拼接完整url
+     */
+    private String pictureUri;
+
+
+    /**
+     * 链接地址
+     * 主要是跳到其它域名
+     */
+    private String hrefUrl;
+
+    /**
+     * 链接URI
+     * 根据上下文拼接完整url
+     */
+    private String hrefUri;
+
+    /**
+     * 主要内容
+     */
+    private String body;
+
+    public Carousel() {
+    }
+
+    public Carousel(Long id, String usedFor, Long orderNumber, String pictureUrl, String pictureUri, String hrefUrl, String hrefUri, String body, Part picture) {
+        this.id = id;
+        this.usedFor = usedFor;
+        this.orderNumber = orderNumber;
+        this.pictureUrl = pictureUrl;
+        this.pictureUri = pictureUri;
+        this.hrefUrl = hrefUrl;
+        this.hrefUri = hrefUri;
+        this.body = body;
+    }
+
+    public Long getId() {
+        return id;
+    }
+
+    public void setId(Long id) {
+        this.id = id;
+    }
+
+    public String getUsedFor() {
+        return usedFor;
+    }
+
+    public void setUsedFor(String usedFor) {
+        this.usedFor = usedFor;
+    }
+
+    public Long getOrderNumber() {
+        return orderNumber;
+    }
+
+    public void setOrderNumber(Long orderNumber) {
+        this.orderNumber = orderNumber;
+    }
+
+    public String getPictureUrl() {
+        return pictureUrl;
+    }
+
+    public void setPictureUrl(String pictureUrl) {
+        this.pictureUrl = pictureUrl;
+    }
+
+    public String getPictureUri() {
+        return pictureUri;
+    }
+
+    public void setPictureUri(String pictureUri) {
+        this.pictureUri = pictureUri;
+    }
+
+    public String getHrefUrl() {
+        return hrefUrl;
+    }
+
+    public void setHrefUrl(String hrefUrl) {
+        this.hrefUrl = hrefUrl;
+    }
+
+    public String getHrefUri() {
+        return hrefUri;
+    }
+
+    public void setHrefUri(String hrefUri) {
+        this.hrefUri = hrefUri;
+    }
+
+    public String getBody() {
+        return body;
+    }
+
+    public void setBody(String body) {
+        this.body = body;
+    }
+
+    public Part getPicture() {
+        return picture;
+    }
+
+    public void setPicture(Part picture) {
+        this.picture = picture;
+    }
+}

+ 228 - 0
src/main/java/com/umall/shop/home/domain/Cart.java

@@ -0,0 +1,228 @@
+package com.umall.shop.home.domain;
+
+import java.util.Date;
+
+/**
+ * Created by John on 2017/2/22.
+ */
+public class Cart {
+
+    private Long id;
+
+    /**
+     * 用户id
+     */
+    private Long uu;
+
+    /**
+     * 用户的enuu
+     */
+    private Long enuu;
+
+    /**
+     * 产品的uuid
+     */
+    private String uuid;
+
+    /**
+     * 批次号
+     */
+    private String batchCode;
+
+    /**
+     * 原厂型号
+     */
+    private String code;
+
+    /**
+     * 器件所属类目
+     */
+    private String kiName;
+
+    /**
+     * 器件所属品牌
+     */
+    private String brName;
+
+    /**
+     * 图片path
+     */
+    private String img;
+
+    /**
+     * 货物类型(1311, "现货") ( 1312, "呆滞库存") (暂时不用1313 废料)
+     */
+    private Integer type;
+
+    /**
+     * 数量
+     */
+    private Double number;
+
+    /**
+     * 单价,单位为元,有可能是含税的单价
+     */
+    private Double unitprice;
+
+    private Double taxes;
+
+    /**
+     * 是否支持7天无理由退货,1:支持,0:不支持
+     */
+    private Short returnInWeek;
+
+    /**
+     * 税率
+     */
+    private Short tax;
+
+    /**
+     * 币种名称
+     */
+    private String currencyName;
+
+    /**
+     * 加入购物车的时间
+     */
+    private Date appendTime;
+
+	public Cart() {
+	}
+
+	public Long getId() {
+		return id;
+	}
+
+	public void setId(Long id) {
+		this.id = id;
+	}
+
+	public Long getUu() {
+		return uu;
+	}
+
+	public void setUu(Long uu) {
+		this.uu = uu;
+	}
+
+	public Long getEnuu() {
+		return enuu;
+	}
+
+	public void setEnuu(Long enuu) {
+		this.enuu = enuu;
+	}
+
+	public String getUuid() {
+		return uuid;
+	}
+
+	public void setUuid(String uuid) {
+		this.uuid = uuid;
+	}
+
+	public String getBatchCode() {
+		return batchCode;
+	}
+
+	public void setBatchCode(String batchCode) {
+		this.batchCode = batchCode;
+	}
+
+	public String getCode() {
+		return code;
+	}
+
+	public void setCode(String code) {
+		this.code = code;
+	}
+
+	public String getKiName() {
+		return kiName;
+	}
+
+	public void setKiName(String kiName) {
+		this.kiName = kiName;
+	}
+
+	public String getBrName() {
+		return brName;
+	}
+
+	public void setBrName(String brName) {
+		this.brName = brName;
+	}
+
+	public String getImg() {
+		return img;
+	}
+
+	public void setImg(String img) {
+		this.img = img;
+	}
+
+	public Integer getType() {
+		return type;
+	}
+
+	public void setType(Integer type) {
+		this.type = type;
+	}
+
+	public Double getNumber() {
+		return number;
+	}
+
+	public void setNumber(Double number) {
+		this.number = number;
+	}
+
+	public Double getUnitprice() {
+		return unitprice;
+	}
+
+	public void setUnitprice(Double unitprice) {
+		this.unitprice = unitprice;
+	}
+
+	public Double getTaxes() {
+		return taxes;
+	}
+
+	public void setTaxes(Double taxes) {
+		this.taxes = taxes;
+	}
+
+	public Short getReturnInWeek() {
+		return returnInWeek;
+	}
+
+	public void setReturnInWeek(Short returnInWeek) {
+		this.returnInWeek = returnInWeek;
+	}
+
+	public Short getTax() {
+		return tax;
+	}
+
+	public void setTax(Short tax) {
+		this.tax = tax;
+	}
+
+	public String getCurrencyName() {
+		return currencyName;
+	}
+
+	public void setCurrencyName(String currencyName) {
+		this.currencyName = currencyName;
+	}
+
+	public Date getAppendTime() {
+		return appendTime;
+	}
+
+	public void setAppendTime(Date appendTime) {
+		this.appendTime = appendTime;
+	}
+
+}

+ 106 - 0
src/main/java/com/umall/shop/home/domain/Category.java

@@ -0,0 +1,106 @@
+package com.umall.shop.home.domain;
+
+import java.io.Serializable;
+import java.util.List;
+
+/**
+ * 分类
+ *
+ * @author yangck
+ * @create 2017-02-15 14:41
+ */
+public class Category implements Serializable {
+
+    private Long id;
+
+    /**
+     * 分类层级,从0开始
+     */
+    private Integer level;
+
+    private Long parentId;
+
+    private List<Category> childs;
+
+    /**
+     * 分类名字
+     */
+    private String name;
+
+    /**
+     * 排序数字
+     */
+    private Long orderNumber;
+
+    public Category() {
+    }
+
+    public Category(Long id, Integer level, Long parentId, List<Category> childs, String name, Long orderNumber) {
+        this.id = id;
+        this.level = level;
+        this.parentId = parentId;
+        this.childs = childs;
+        this.name = name;
+        this.orderNumber = orderNumber;
+    }
+
+    public Long getId() {
+        return id;
+    }
+
+    public void setId(Long id) {
+        this.id = id;
+    }
+
+    public Integer getLevel() {
+        return level;
+    }
+
+    public void setLevel(Integer level) {
+        this.level = level;
+    }
+
+    public Long getParentId() {
+        return parentId;
+    }
+
+    public void setParentId(Long parentId) {
+        this.parentId = parentId;
+    }
+
+    public List<Category> getChilds() {
+        return childs;
+    }
+
+    public void setChilds(List<Category> childs) {
+        this.childs = childs;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    public Long getOrderNumber() {
+        return orderNumber;
+    }
+
+    public void setOrderNumber(Long orderNumber) {
+        this.orderNumber = orderNumber;
+    }
+
+    @Override
+    public String toString() {
+        return "Category{" +
+                "id=" + id +
+                ", level=" + level +
+                ", parentId=" + parentId +
+                ", childs=" + childs +
+                ", name='" + name + '\'' +
+                ", orderNumber=" + orderNumber +
+                '}';
+    }
+}

+ 70 - 0
src/main/java/com/umall/shop/home/domain/CustomService.java

@@ -0,0 +1,70 @@
+package com.umall.shop.home.domain;
+
+public class CustomService {
+
+    private Long id;
+
+    /**
+     * 客服电话
+     */
+    private String telephone;
+
+    /**
+     * 公司地址
+     */
+    private String address;
+
+    /**
+     * 公司邮箱
+     */
+    private String email;
+
+    /**
+     * 公司UU
+     */
+
+    private Long enuu;
+
+    public CustomService() {
+    }
+
+    public Long getId() {
+        return id;
+    }
+
+    public void setId(Long id) {
+        this.id = id;
+    }
+
+    public String getTelephone() {
+        return telephone;
+    }
+
+    public void setTelephone(String telephone) {
+        this.telephone = telephone;
+    }
+
+    public String getAddress() {
+        return address;
+    }
+
+    public void setAddress(String address) {
+        this.address = address;
+    }
+
+    public String getEmail() {
+        return email;
+    }
+
+    public void setEmail(String email) {
+        this.email = email;
+    }
+
+    public Long getEnuu() {
+        return enuu;
+    }
+
+    public void setEnuu(Long enuu) {
+        this.enuu = enuu;
+    }
+}

+ 85 - 0
src/main/java/com/umall/shop/home/service/HomeService.java

@@ -0,0 +1,85 @@
+package com.umall.shop.home.service;
+
+import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
+import com.umall.shop.home.domain.Carousel;
+import com.umall.shop.home.domain.Category;
+import com.umall.shop.home.domain.CustomService;
+import org.apache.log4j.LogManager;
+import org.apache.log4j.Logger;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.web.client.RestTemplate;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @author yangck
+ * @create 2017-02-15 17:40
+ */
+@Service
+public class HomeService {
+
+    private final Logger logger = LogManager.getLogger(getClass());
+
+    @Autowired
+    private RestTemplate restTemplate;
+
+    @HystrixCommand(fallbackMethod = "getCategoryFallback")
+    public Category getCategory(Long id) {
+//        System.out.println("getCategory");
+        return restTemplate.getForEntity("http://CATEGORY-SERVICE/category/" + id, Category.class).getBody();
+    }
+
+    private Category getCategoryFallback(Long id) {
+        // throw new ServiceUnavailableException("CATEGORY-SERVICE");
+        logger.error("CATEGORY-SERVICE unavailable");
+        return new Category();
+    }
+
+    @HystrixCommand(fallbackMethod = "getCarousels")
+    public List<Carousel> getCarousels(String usedFor) {
+        return restTemplate.getForEntity("http://CAROUSEL-SERVICE/carousels?usedFor=" + usedFor, List.class).getBody();
+    }
+
+    private List<Carousel> getCarousels() {
+        logger.error("CAROUSEL-SERVICE unavailable");
+        return new ArrayList<>();
+    }
+
+    /**
+     * 获取商城客服信息
+     *
+     * @param enuu  商城企业UU信息
+     */
+    @HystrixCommand(fallbackMethod = "getCustomService")
+    public CustomService getCustomService(Long enuu) {
+        return restTemplate.getForEntity(String.format("http://MALL-CUSTOM-SERVICE/customService/cus/%d", enuu), CustomService.class).getBody();
+    }
+
+    private CustomService getCustomService() {
+        logger.error("MALL-CUSTOM-SERVICE unavailable");
+        CustomService customService = new CustomService();
+        customService.setTelephone("0755-86564892");
+        customService.setAddress("深圳市南山区英唐大厦6楼");
+        return customService;
+    }
+
+    /**
+     * 根据用户的企业UU和用户UU获取购物车中商品的数量
+     *
+     * @param enuu      用户企业UU
+     * @param userUU    用户UU
+     * @return      购物车中商品的数量,非负
+     */
+    @HystrixCommand(fallbackMethod = "getCartCount")
+    public Integer getCartCount(Long enuu, Long userUU) {
+        Integer cartCount = restTemplate.getForEntity(String.format("http://MALL-CART-SERVICE/cart/count?enuu=%d&useruu=%d", enuu, userUU), Integer.class).getBody();
+        return cartCount == null ? 0 : cartCount;
+    }
+
+    private Integer getCartCount() {
+        logger.error("MALL-CART-SERVICE unavailable");
+        return -1;
+    }
+}

+ 42 - 0
src/main/java/com/umall/shop/home/web/HomeController.java

@@ -0,0 +1,42 @@
+package com.umall.shop.home.web;
+
+import com.umall.shop.home.domain.Carousel;
+import com.umall.shop.home.domain.Category;
+import com.umall.shop.home.domain.CustomService;
+import com.umall.shop.home.service.HomeService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @author yangck
+ * @create 2017-02-15 17:41
+ */
+@Controller
+@RequestMapping("/")
+public class HomeController {
+
+    @Autowired
+    private HomeService homeService;
+
+    @RequestMapping(method = RequestMethod.GET)
+    public String home(Map<String, Object> model) {
+        Category category = homeService.getCategory(1L);
+        List<Carousel> carousels = homeService.getCarousels("home");
+        // 楼层
+        model.put("category", category);
+        model.put("carousels", carousels);
+        // 楼层
+        // TODO 客服信息,之后从配置文件中获取商城的企业UU信息
+        CustomService customService = homeService.getCustomService(10030994L);
+        model.put("customService", customService);
+        // TODO 购物车商品数量,之后采用异步方式获取
+        int cartCount = homeService.getCartCount(10030994L, 1000002363L);
+        System.out.println(cartCount);
+        return "home";
+    }
+}

+ 9 - 0
src/main/resources/application.yml

@@ -0,0 +1,9 @@
+spring:
+  application:
+    name: home-app
+server:
+  port: 3333
+eureka:
+  client:
+    serviceUrl:
+      defaultZone: http://eureka1:1111/eureka/,http://eureka2:1112/eureka/

+ 137 - 0
src/main/resources/static/css/carousel.css

@@ -0,0 +1,137 @@
+/* GLOBAL STYLES
+-------------------------------------------------- */
+/* Padding below the footer and lighter body text */
+
+body {
+    padding-bottom: 40px;
+    color: #5a5a5a;
+}
+
+
+/* CUSTOMIZE THE NAVBAR
+-------------------------------------------------- */
+
+/* Special class on .container surrounding .navbar, used for positioning it into place. */
+.navbar-wrapper {
+    position: absolute;
+    top: 0;
+    right: 0;
+    left: 0;
+    z-index: 20;
+}
+
+/* Flip around the padding for proper display in narrow viewports */
+.navbar-wrapper > .container {
+    padding-right: 0;
+    padding-left: 0;
+}
+.navbar-wrapper .navbar {
+    padding-right: 15px;
+    padding-left: 15px;
+}
+.navbar-wrapper .navbar .container {
+    width: auto;
+}
+
+
+/* CUSTOMIZE THE CAROUSEL
+-------------------------------------------------- */
+
+/* Carousel base class */
+.carousel {
+    height: 300px;
+    margin-bottom: 60px;
+}
+/* Since positioning the image, we need to help out the caption */
+.carousel-caption {
+    z-index: 10;
+    position: absolute;
+    top: 50%;
+    transform: translateY(-50%);
+}
+
+/* Declare heights because of positioning of img element */
+.carousel .item {
+    height: 300px;
+    /*background-color: #777;*/
+}
+.carousel-inner > .item > img {
+    position: absolute;
+    top: 0;
+    left: 0;
+    min-width: 100%;
+    height: 300px;
+}
+
+
+/* MARKETING CONTENT
+-------------------------------------------------- */
+
+/* Center align the text within the three columns below the carousel */
+.marketing .col-lg-4 {
+    margin-bottom: 20px;
+    text-align: center;
+}
+.marketing h2 {
+    font-weight: normal;
+}
+.marketing .col-lg-4 p {
+    margin-right: 10px;
+    margin-left: 10px;
+}
+
+
+/* Featurettes
+------------------------- */
+
+.featurette-divider {
+    margin: 80px 0; /* Space out the Bootstrap <hr> more */
+}
+
+/* Thin out the marketing headings */
+.featurette-heading {
+    font-weight: 300;
+    line-height: 1;
+    letter-spacing: -1px;
+}
+
+
+/* RESPONSIVE CSS
+-------------------------------------------------- */
+
+@media (min-width: 768px) {
+    /* Navbar positioning foo */
+    .navbar-wrapper {
+        margin-top: 20px;
+    }
+    .navbar-wrapper .container {
+        padding-right: 15px;
+        padding-left: 15px;
+    }
+    .navbar-wrapper .navbar {
+        padding-right: 0;
+        padding-left: 0;
+    }
+
+    /* The navbar becomes detached from the top, so we round the corners */
+    .navbar-wrapper .navbar {
+        border-radius: 4px;
+    }
+
+    /* Bump up size of carousel content */
+    .carousel-caption p {
+        margin-bottom: 20px;
+        font-size: 21px;
+        line-height: 1.4;
+    }
+
+    .featurette-heading {
+        font-size: 50px;
+    }
+}
+
+@media (min-width: 992px) {
+    .featurette-heading {
+        margin-top: 120px;
+    }
+}

+ 27 - 0
src/main/resources/static/css/category.css

@@ -0,0 +1,27 @@
+#category {
+    position: relative;
+}
+#category .level1 {
+}
+
+
+#category .level2 {
+    display: none;
+    text-align: left;
+}
+#category .level1:hover .level2 {
+    display: block;
+}
+#category .level2-container {
+    position: absolute;
+    top: 0;
+    left: 100%;
+    width: 50em;
+    z-index: 100;
+    background-color: dimgrey;
+}
+
+
+#category .level3 {
+    display: inline-block;
+}

+ 18 - 0
src/main/resources/static/css/home.css

@@ -0,0 +1,18 @@
+#main-container {
+    background-color: hsl(348, 83%, 47%);
+    padding-top: 5.1em;
+    padding-left: 7.5em;
+}
+#category {
+    text-align: center;
+    float: left;
+    width: 20%;
+    height: 300px;
+    color: white;
+    font-size: 16px;
+    background-color: cornflowerblue;
+}
+#myCarousel {
+    float: left;
+    width: 71.6%;
+}

+ 13 - 0
src/main/resources/static/css/ie10-viewport-bug-workaround.css

@@ -0,0 +1,13 @@
+/*!
+ * IE10 viewport hack for Surface/desktop Windows 8 bug
+ * Copyright 2014-2015 Twitter, Inc.
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
+ */
+
+/*
+ * See the Getting Started docs for more information:
+ * http://getbootstrap.com/getting-started/#support-ie10-width
+ */
+@-ms-viewport     { width: device-width; }
+@-o-viewport      { width: device-width; }
+@viewport         { width: device-width; }

+ 3 - 0
src/main/resources/static/js/home.js

@@ -0,0 +1,3 @@
+/**
+ * Created by umall on 2017/2/15.
+ */

+ 23 - 0
src/main/resources/static/js/ie10-viewport-bug-workaround.js

@@ -0,0 +1,23 @@
+/*!
+ * IE10 viewport hack for Surface/desktop Windows 8 bug
+ * Copyright 2014-2015 Twitter, Inc.
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
+ */
+
+// See the Getting Started docs for more information:
+// http://getbootstrap.com/getting-started/#support-ie10-width
+
+(function () {
+    'use strict';
+
+    if (navigator.userAgent.match(/IEMobile\/10\.0/)) {
+        var msViewportStyle = document.createElement('style')
+        msViewportStyle.appendChild(
+            document.createTextNode(
+                '@-ms-viewport{width:auto!important}'
+            )
+        )
+        document.querySelector('head').appendChild(msViewportStyle)
+    }
+
+})();

File diff suppressed because it is too large
+ 1 - 0
src/main/resources/static/js/jquery.min.js


+ 165 - 0
src/main/resources/templates/home.html

@@ -0,0 +1,165 @@
+<!DOCTYPE html>
+<html xmlns:th="http://www.thymeleaf.org">
+<head>
+    <meta charset="utf-8"/>
+    <meta http-equiv="X-UA-Compatible" content="IE=edge"/>
+    <meta name="viewport" content="width=device-width, initial-scale=1"/>
+    <!-- 上述3个meta标签*必须*放在最前面,任何其他内容都*必须*跟随其后! -->
+    <meta name="description" content="商城首页"/>
+    <meta name="author" content="umall"/>
+    <link rel="icon" th:href="@{/favicon.ico}" />
+
+    <title>商城首页</title>
+
+    <!-- Bootstrap core CSS -->
+    <link href="https://cdn.bootcss.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet"/>
+
+    <!-- IE10 viewport hack for Surface/desktop Windows 8 bug -->
+    <link th:href="@{/ie10-viewport-bug-workaround.css}" rel="stylesheet"/>
+
+    <!-- HTML5 shim and Respond.js for IE8 support of HTML5 elements and media queries -->
+    <!--[if lt IE 9]>
+    <script src="https://cdn.bootcss.com/html5shiv/3.7.3/html5shiv.min.js"></script>
+    <script src="https://cdn.bootcss.com/respond.js/1.4.2/respond.min.js"></script>
+    <![endif]-->
+
+    <!-- Custom styles for this template -->
+    <link href="../static/css/home.css" th:href="@{/css/home.css}" rel="stylesheet"/>
+    <link href="../static/css/carousel.css" th:href="@{/css/category.css}" rel="stylesheet"/>
+    <link href="../static/css/carousel.css" th:href="@{/css/carousel.css}" rel="stylesheet"/>
+</head>
+<body>
+<div class="navbar-wrapper">
+    <div class="container">
+        <nav class="navbar navbar-inverse navbar-static-top">
+            <div class="container">
+                <div class="navbar-header">
+                    <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar">
+                        <span class="sr-only">Toggle navigation</span>
+                        <span class="icon-bar"></span>
+                        <span class="icon-bar"></span>
+                        <span class="icon-bar"></span>
+                    </button>
+                    <a class="navbar-brand" href="#">Project name</a>
+                </div>
+                <div id="navbar" class="navbar-collapse collapse">
+                    <ul class="nav navbar-nav">
+                        <li class="active"><a href="#">Home</a></li>
+                        <li><a href="#about">About</a></li>
+                        <li><a href="#contact">Contact</a></li>
+                    </ul>
+                </div>
+            </div>
+        </nav>
+
+    </div>
+</div>
+
+<div id="main-container" class="clearfix">
+    <!-- 分类 -->
+    <div id="category">
+        <!--/*@thymesVar id="category" type="com.umall.shop.home.domain.Category"*/-->
+        <ul class="list-unstyled">
+            <li class="level1" th:each="level1 : ${category.getChilds()}">
+                <span th:text="${level1.name}">l1 category element name</span>
+                <ul class="level2-container list-unstyled">
+                    <li class="level2" th:each="level2 : ${level1.getChilds()}">
+                        <span th:text="${level2.name}">l2 category element name</span>
+                        <ul class="list-unstyled">
+                            <li class="level3" th:each="level3 : ${level2.getChilds()}">
+                                <span th:text="${level3.name}">l3 category element name</span>
+                            </li>
+                        </ul>
+                    </li>
+                </ul>
+            </li>
+        </ul>
+    </div>
+
+    <!--/*@thymesVar id="carousels" type="java.util.List<com.umall.shop.model.Carousel>"*/-->
+    <!-- Carousel
+================================================== -->
+    <div id="myCarousel" class="carousel slide" data-ride="carousel">
+        <!-- Indicators -->
+        <ol class="carousel-indicators">
+            <li data-target="#myCarousel" class="active" th:each="carousel, iterStat : ${carousels}" th:class="${iterStat.index == 0} ? 'active'" th:attr="data-slide-to=${iterStat.index}">
+            </li>
+            <!--<li data-target="#myCarousel" data-slide-to="1"></li>-->
+        </ol>
+        <div class="carousel-inner" role="listbox">
+            <div th:each="carousel, iterStat : ${carousels}" th:class="${iterStat.index == 0} ? 'item active' : 'item'">
+                <a th:href="${carousel.hrefUrl}">
+                    <img class="first-slide" th:src="${carousel.pictureUrl}" alt="First slide" />
+                    <div class="container">
+                        <div class="carousel-caption">
+                            <p th:text="${carousel.body}"></p>
+                        </div>
+                    </div>
+                </a>
+            </div>
+        </div>
+
+        <a class="left carousel-control" href="#myCarousel" role="button" data-slide="prev">
+            <span class="glyphicon glyphicon-chevron-left" aria-hidden="true"></span>
+            <span class="sr-only">Previous</span>
+        </a>
+        <a class="right carousel-control" href="#myCarousel" role="button" data-slide="next">
+            <span class="glyphicon glyphicon-chevron-right" aria-hidden="true"></span>
+            <span class="sr-only">Next</span>
+        </a>
+    </div><!-- /.carousel -->
+</div>
+
+
+
+<div class="container marketing">
+
+
+    <hr class="featurette-divider"/>
+
+    <div class="row featurette">
+        <div class="col-md-7">
+            <h2 class="featurette-heading">楼层 <span class="text-muted">1 手机</span></h2>
+            <p class="lead">楼层1</p>
+        </div>
+        <div class="col-md-5">
+            <img class="featurette-image img-responsive center-block" data-src="holder.js/500x500/auto" alt="Generic placeholder image" />
+        </div>
+    </div>
+
+    <hr class="featurette-divider"/>
+
+    <div class="row featurette">
+        <div class="col-md-7 col-md-push-5">
+            <h2 class="featurette-heading">楼层<span class="text-muted">2 VR</span></h2>
+            <p class="lead">楼层2 内容</p>
+        </div>
+        <div class="col-md-5 col-md-pull-7">
+            <img class="featurette-image img-responsive center-block" data-src="holder.js/500x500/auto" alt="Generic placeholder image" />
+        </div>
+    </div>
+
+    <hr class="featurette-divider"/>
+
+    <!-- FOOTER -->
+    <footer>
+        <p class="pull-right"><a href="#">Back to top</a></p>
+        <p style="text-align: center;">
+            <span>客服电话:<span th:text="${customService.telephone}"></span></span>&nbsp;&nbsp;
+            <span>公司地址:<span th:text="${customService.address}"></span></span>&nbsp;&nbsp;
+            <span>&copy;2016&nbsp;深圳市优软科技有限公司&nbsp;粤ICP备15112126号-3</span>
+        </p>
+    </footer>
+
+</div><!-- /.container -->
+
+
+<!-- Bootstrap core JavaScript
+================================================== -->
+<!-- Placed at the end of the document so the pages load faster -->
+<script src="https://cdn.bootcss.com/jquery/1.12.4/jquery.min.js"></script>
+<script src="https://cdn.bootcss.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
+<!-- IE10 viewport hack for Surface/desktop Windows 8 bug -->
+<script th:src="@{/js/ie10-viewport-bug-workaround.js}"></script>
+</body>
+</html>

Some files were not shown because too many files changed in this diff