xielq преди 4 години
родител
ревизия
0b7ebf7dc9
променени са 100 файла, в които са добавени 4856 реда и са изтрити 0 реда
  1. 8 0
      Dockerfile
  2. 22 0
      README.md
  3. 36 0
      app.html
  4. 8 0
      assets/README.md
  5. 107 0
      assets/scss/_common.scss
  6. 402 0
      assets/scss/_mixins.scss
  7. 153 0
      assets/scss/_reset.scss
  8. 67 0
      assets/scss/_variables.scss
  9. 2 0
      assets/scss/app.scss
  10. 170 0
      components/common/page/pageComponent.vue
  11. 92 0
      components/common/upload/upload.vue
  12. 26 0
      components/common/vue-empty/empty.vue
  13. 7 0
      components/common/vue-empty/index.js
  14. 7 0
      components/common/vue-loading/index.js
  15. 132 0
      components/common/vue-loading/loading.vue
  16. 94 0
      components/default/footer.vue
  17. 220 0
      components/default/header.vue
  18. 4 0
      components/default/index.js
  19. 21 0
      components/garden/banner.vue
  20. 330 0
      components/garden/detail.vue
  21. 5 0
      components/garden/index.js
  22. 223 0
      components/garden/list.vue
  23. 65 0
      components/home/banner.vue
  24. 59 0
      components/home/carousel.vue
  25. 177 0
      components/home/garden.vue
  26. 6 0
      components/home/index.js
  27. 114 0
      components/home/news.vue
  28. 42 0
      components/news/banner.vue
  29. 76 0
      components/news/detail.vue
  30. 6 0
      components/news/index.js
  31. 205 0
      components/news/items.vue
  32. 102 0
      components/news/navs.vue
  33. 27 0
      components/park/banner.vue
  34. 4 0
      components/park/index.js
  35. 63 0
      components/park/info.vue
  36. 141 0
      components/service/ServiceList.vue
  37. 23 0
      components/service/banner.vue
  38. 3 0
      components/service/index.js
  39. 45 0
      layouts/error.vue
  40. 35 0
      layouts/town.vue
  41. BIN
      linux_musl-x64-57_binding.node
  42. 5 0
      middleware/authenticated.js
  43. 79 0
      nuxt.config.js
  44. 47 0
      package.json
  45. 139 0
      pages/about/index.vue
  46. 32 0
      pages/index.vue
  47. 53 0
      pages/news/_id.vue
  48. 45 0
      pages/news/index.vue
  49. 18 0
      pages/park/index.vue
  50. 236 0
      pages/repairs/_id/historicalInfo/_fdid.vue
  51. 129 0
      pages/repairs/_id/historicalInfo/index.vue
  52. 406 0
      pages/repairs/_id/index.vue
  53. 31 0
      pages/repairs/index.vue
  54. 22 0
      pages/townInfo/_id.vue
  55. 24 0
      pages/townInfo/index.vue
  56. 8 0
      plugins/README.md
  57. 41 0
      plugins/axios.js
  58. 44 0
      plugins/city-service.js
  59. 12 0
      plugins/element-ui.js
  60. 4 0
      plugins/filters.js
  61. 4 0
      plugins/jsonp.js
  62. 4 0
      plugins/swiper.js
  63. 4 0
      plugins/vue-clipboard2.js
  64. 5 0
      plugins/vue-empty.js
  65. 3 0
      plugins/vue-jsonp.js
  66. 4 0
      plugins/vue-loading.js
  67. 16 0
      post.sh
  68. 32 0
      run.sh
  69. 80 0
      server.js
  70. BIN
      static/404.png
  71. BIN
      static/U.png
  72. BIN
      static/icon/developers.png
  73. BIN
      static/icon/enterprise.png
  74. BIN
      static/icon/garden.png
  75. BIN
      static/icon/government.png
  76. BIN
      static/icon/info.png
  77. BIN
      static/icon/left-arrow.png
  78. BIN
      static/icon/link.png
  79. BIN
      static/icon/new.png
  80. BIN
      static/icon/new_icon1.png
  81. BIN
      static/icon/new_icon2.png
  82. BIN
      static/icon/new_icon3.png
  83. BIN
      static/icon/new_icon4.png
  84. BIN
      static/icon/new_icon5.png
  85. BIN
      static/icon/new_icon6.png
  86. BIN
      static/icon/qq.png
  87. BIN
      static/icon/space.png
  88. BIN
      static/icon/trumpet.png
  89. BIN
      static/icon/weibo.png
  90. BIN
      static/img/banner/1.png
  91. BIN
      static/img/banner/10.png
  92. BIN
      static/img/banner/2.png
  93. BIN
      static/img/banner/9.png
  94. BIN
      static/img/news/banner.jpg
  95. BIN
      static/img/park/1.png
  96. BIN
      static/logo.png
  97. BIN
      static/map.png
  98. BIN
      static/qrcode/code.png
  99. BIN
      static/qrcode/uas.jpg
  100. BIN
      static/qrcode/uu.jpg

+ 8 - 0
Dockerfile

@@ -0,0 +1,8 @@
+FROM 10.10.100.200:5000/node-python:8.10.0
+RUN mkdir -p /app
+WORKDIR /app
+COPY . /app
+RUN chmod +x run.sh
+RUN yarn config set sass-binary-site http://npm.taobao.org/mirrors/node-sass -g
+RUN yarn
+CMD [ "bash", "run.sh" ]

+ 22 - 0
README.md

@@ -0,0 +1,22 @@
+# mall-web-ssr
+
+> mall web project
+
+## Build Setup
+
+``` bash
+# install dependencies
+$ npm install # Or yarn install
+
+# serve with hot reload at localhost:3000
+$ npm run dev
+
+# build for production and launch server
+$ npm run build
+$ npm start
+
+# generate static project
+$ npm run generate
+```
+
+For detailed explanation on how things work, checkout the [Nuxt.js docs](https://github.com/nuxt/nuxt.js).

+ 36 - 0
app.html

@@ -0,0 +1,36 @@
+<!DOCTYPE html>
+<html {{ HTML_ATTRS }}>
+<head>
+  <link rel="stylesheet" type="text/css" href="https://cdn.bootcss.com/bootstrap/3.3.7/css/bootstrap.min.css" />
+  <link href="//netdna.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css" rel="stylesheet">
+  <link rel="stylesheet" href="https://unpkg.com/element-ui/lib/theme-chalk/index.css">
+  {{ HEAD }}
+  <script>
+    var _hmt = _hmt || [];
+    (function (w, d) {
+      if (/(MSIE)|(Trident)/.test(w.navigator.userAgent)) {
+        var head = d.getElementsByTagName('head')[0]
+        var appendScript = function (src) {
+          var node = d.createElement('script')
+          node.src = src
+          head.appendChild(node)
+        }
+        // ployfill for all ie
+        appendScript('https://cdn.bootcss.com/html5shiv/r29/html5.min.js')
+        appendScript('https://cdn.bootcss.com/js-polyfills/0.1.33/polyfill.min.js')
+      }
+      var hm = d.createElement("script");
+      hm.src = "https://hm.baidu.com/hm.js?34793672f88552a77437f2cee7864118;"
+      var s = d.getElementsByTagName("script")[0];
+      s.parentNode.insertBefore(hm, s);
+      var cnzz_protocol = (("https:" == d.location.protocol) ? " https://" : " http://");
+      d.write(unescape("%3Cspan id='cnzz_stat_icon_1267002346'%3E%3C/span%3E%3Cscript src='" + cnzz_protocol + "s19.cnzz.com/z_stat.php%3Fid%3D1267002346%26show%3Dpic' type='text/javascript'%3E%3C/script%3E"));
+    })(window, document)
+  </script>
+  <script type="text/javascript">
+  </script>
+</head>
+<body {{ BODY_ATTRS }}>
+{{ APP }}
+</body>
+</html>

+ 8 - 0
assets/README.md

@@ -0,0 +1,8 @@
+# ASSETS
+
+This directory contains your un-compiled assets such as LESS, SASS, or JavaScript.
+
+More information about the usage of this directory in the documentation:
+https://nuxtjs.org/guide/assets#webpacked
+
+**This directory is not required, you can delete it if you don't want to use it.**

+ 107 - 0
assets/scss/_common.scss

@@ -0,0 +1,107 @@
+// scroll
+::-webkit-scrollbar {
+  width: .5rem;
+  height: .5rem;
+  background: hsla(0, 0%, 100%, 0.6);
+}
+
+::-webkit-scrollbar-track {
+  border-radius: 0;
+}
+
+::-webkit-scrollbar-thumb {
+  border-radius: 0;
+  background-color: rgba(95,95,95,.4);
+  transition: background-color .15s;
+
+  &:hover {
+    background-color: rgba(95,95,95, .7);
+  }
+}
+
+// ie等滚动条遮住元素
+html, body {
+  -ms-overflow-style: scrollbar;
+}
+
+// common style
+.clearfix {
+  &:before, &:after {
+    display: table;
+    content: " ";
+  }
+  &:after {
+    clear: both;
+  }
+}
+.list-unstyled {
+  padding-left: 0;
+  list-style: none;
+}
+
+.list-inline li {
+  display: inline-block;
+  padding-left: 5px;
+  padding-right: 5px;
+}
+
+.hide {
+  opacity: 0;
+  visibility: hidden;
+  pointer-events: none;
+}
+
+.pull-left {
+  float: left;
+}
+
+.pull-right {
+  float: right;
+}
+
+.container{
+  width:1180px;
+  margin:0 auto;
+}
+
+// vue animate
+.slide-down-enter-active, .slide-down-leave-active {
+  transition: all .4s cubic-bezier(0, 1.2, 1, 0.5);
+  opacity: .7;
+  transform: translate3d(0, 4em, 0);
+}
+.slide-down-enter, .slide-down-leave-active {
+  opacity: .3;
+  transform: translate3d(0, 4em, 0);
+}
+
+.slide-left-enter-active, .slide-left-leave-active {
+  transition: all .2s cubic-bezier(0, 1.2, 1, 0.5);
+  opacity: .5;
+  transform: translate3d(2em, 0, 0);
+}
+
+.slide-left-enter, .slide-left-leave-active {
+  opacity: .3;
+  transform: translate3d(2em, 0, 0);
+}
+
+.slide-right-enter-active, .slide-right-leave-active {
+  transition: all .4s cubic-bezier(0, 1.2, 1, 0.5);
+  opacity: .5;
+  transform: translate3d(5em, 0, 0);
+}
+.slide-right-enter, .slide-right-leave-active {
+  opacity: .3;
+  transform: translate3d(5em, 0, 0);
+}
+
+.fade-enter-active, .fade-leave-active {
+  transition: opacity .25s
+}
+.fade-enter, .fade-leave-active {
+  opacity: 0
+}
+.fade-move {
+  transition: transform .25s;
+}

+ 402 - 0
assets/scss/_mixins.scss

@@ -0,0 +1,402 @@
+/// Adds a browser prefix to the property
+/// @param {*} $property Property
+/// @param {*} $value Value
+
+@mixin clamp($lines: 2) {
+  display: -webkit-box;
+  overflow: hidden;
+  -webkit-line-clamp: $lines;
+  -webkit-box-orient: vertical;
+}
+
+@mixin css3-prefix($property, $value) {
+  -webkit-#{$property}: #{$value};
+   -khtml-#{$property}: #{$value};
+     -moz-#{$property}: #{$value};
+      -ms-#{$property}: #{$value};
+       -o-#{$property}: #{$value};
+          #{$property}: #{$value};
+}
+
+
+/// Background Gradient
+/// @param {Color} $startColor [#3C3C3C] - Start Color
+/// @param {Color} $endColor [#999999] - End Color
+
+@mixin background-gradient($startColor: #3C3C3C, $endColor: #999999) {
+    background-color: $startColor;
+    background-image: -webkit-gradient(linear, left top, left bottom, from($startColor), to($endColor));
+    background-image: -webkit-linear-gradient(top, $startColor, $endColor);
+    background-image:    -moz-linear-gradient(top, $startColor, $endColor);
+    background-image:     -ms-linear-gradient(top, $startColor, $endColor);
+    background-image:      -o-linear-gradient(top, $startColor, $endColor);
+    background-image:         linear-gradient(top, $startColor, $endColor);
+    filter:            progid:DXImageTransform.Microsoft.gradient(startColorStr='#{$startColor}', endColorStr='#{$endColor}');
+}
+
+
+/// Background Horizontal
+/// @param {Color} $startColor [#3C3C3C] - Start Color
+/// @param {Color} $endColor [#999999] - End Color
+
+@mixin background-horizontal($startColor: #3C3C3C, $endColor: #999999) {
+    background-color: $startColor;
+    background-image: -webkit-gradient(linear, left top, right top, from($startColor), to($endColor));
+    background-image: -webkit-linear-gradient(left, $startColor, $endColor);
+    background-image:    -moz-linear-gradient(left, $startColor, $endColor);
+    background-image:     -ms-linear-gradient(left, $startColor, $endColor);
+    background-image:      -o-linear-gradient(left, $startColor, $endColor);
+    background-image:         linear-gradient(left, $startColor, $endColor);
+    filter:            progid:DXImageTransform.Microsoft.gradient(startColorStr='#{$startColor}', endColorStr='#{$endColor}', gradientType='1');
+}
+
+
+/// Background Radial
+/// @param {Color} $startColor [#3C3C3C] - Start Color
+/// @param {Percentage} $startPos [0%] - Start position
+/// @param {Color} $endColor [#999999] - End Color
+/// @param {Percentage} $endPos [100%] - End position
+
+@mixin background-radial($startColor: #FFFFFF, $startPos: 0%, $endColor: #000000, $endPos:100%) {
+    background: -moz-radial-gradient(center, ellipse cover, $startColor $startPos, $endColor $endPos);
+    background: -webkit-gradient(radial, center center, 0px, center center, 100%, color-stop($startPos,$startColor), color-stop($endPos,$endColor));
+    background: -webkit-radial-gradient(center, ellipse cover, $startColor $startPos,$endColor $endPos);
+    background: -o-radial-gradient(center, ellipse cover, $startColor $startPos,$endColor $endPos);
+    background: -ms-radial-gradient(center, ellipse cover, $startColor $startPos,$endColor $endPos);
+    background: radial-gradient(ellipse at center, $startColor $startPos,$endColor $endPos);
+}
+
+
+/// Background Size
+/// @param {Size} $width [100%] - Width
+/// @param {Size} $width [$width] - Height
+/// @require {mixin} css3-prefix
+
+@mixin background-size($width: 100%, $height: $width) {
+  @if type-of($width) == 'number' and $height != null {
+    @include css3-prefix('background-size', $width $height);
+  } @else {
+    @include css3-prefix('background-size', $width);
+  }
+}
+
+
+/// Background Color Opacity
+/// @param {Color} $color [100%] - Color
+/// @param {Double} $opacity [0.85] - Opacity
+
+@mixin background-opacity($color: #000, $opacity: 0.85) {
+  background: $color;
+  background: rgba($color, $opacity);
+}
+
+
+/// Border Radius
+/// @param {Size} $radius [5px] - Radius
+/// @require {mixin} css3-prefix
+
+@mixin border-radius($radius: 5px) {
+    @include css3-prefix('border-radius', $radius);
+}
+
+
+/// Border Radius Separate
+/// @param {Size} $topLeftRadius [5px] - Top Left
+/// @param {Size} $topRightRadius [5px] - Top Right
+/// @param {Size} $bottomLeftRadius [5px] - Bottom Left
+/// @param {Size} $bottomRightRadius [5px] - Bottom Right
+
+@mixin border-radius-separate($topLeftRadius: 5px, $topRightRadius: 5px, $bottomLeftRadius: 5px, $bottomRightRadius: 5px) {
+  -webkit-border-top-left-radius:     $topLeftRadius;
+  -webkit-border-top-right-radius:    $topRightRadius;
+  -webkit-border-bottom-right-radius: $bottomRightRadius;
+  -webkit-border-bottom-left-radius:  $bottomLeftRadius;
+
+  -moz-border-radius-topleft:     $topLeftRadius;
+  -moz-border-radius-topright:    $topRightRadius;
+  -moz-border-radius-bottomright: $bottomRightRadius;
+  -moz-border-radius-bottomleft:  $bottomLeftRadius;
+
+  border-top-left-radius:     $topLeftRadius;
+  border-top-right-radius:    $topRightRadius;
+  border-bottom-right-radius: $bottomRightRadius;
+  border-bottom-left-radius:  $bottomLeftRadius;
+}
+
+
+/// Box
+/// @param {*} $orient [horizontal] - Orientation
+/// @param {*} $pack [center] - Pack
+/// @param {*} $align [center] - Align
+/// @require {mixin} css3-prefix
+
+@mixin box($orient: horizontal, $pack: center, $align: center) {
+  display: -webkit-box;
+  display: -moz-box;
+  display: box;
+
+  @include css3-prefix('box-orient', $orient);
+  @include css3-prefix('box-pack', $pack);
+  @include css3-prefix('box-align', $align);
+}
+
+
+/// Box RGBA
+/// @param {Integer} $r [60] - Red
+/// @param {Integer} $g [3] - Green
+/// @param {Integer} $b [12] - Blue
+/// @param {Double} $opacity [0.23] - Opacity
+/// @param {Color} $color [#3C3C3C] - Color
+
+@mixin box-rgba($r: 60, $g: 3, $b: 12, $opacity: 0.23, $color: #3C3C3C) {
+  background-color: transparent;
+  background-color: rgba($r, $g, $b, $opacity);
+            filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#{$color}',endColorstr='#{$color}');
+            zoom:   1;
+}
+
+
+/// Box Shadow
+/// @param {Size} $x [2px] - X
+/// @param {Size} $y [2px] - Y
+/// @param {Size} $blur [5px] - Blur
+/// @param {Color} $color [rgba(0,0,0,.4)] - Color
+/// @param {Boolean} $inset - Inset
+
+@mixin box-shadow($x: 2px, $y: 2px, $blur: 5px, $color: rgba(0,0,0,.4), $inset: "") {
+  @if ($inset != "") {
+    @include css3-prefix('box-shadow', $inset $x $y $blur $color);
+  } @else {
+    @include css3-prefix('box-shadow', $x $y $blur $color);
+  }
+}
+
+
+/// Box Sizing
+/// @param {*} $type [border-box] - Type
+/// @require {mixin} css3-prefix
+
+@mixin box-sizing($type: border-box) {
+  @include css3-prefix('box-sizing', $type);
+}
+
+
+/// Columns
+/// @param {Integer} $count [3] - Count
+/// @param {Integer} $gap [10] - Gap
+/// @require {mixin} css3-prefix
+
+@mixin columns($count: 3, $gap: 10) {
+  @include css3-prefix('column-count', $count);
+  @include css3-prefix('column-gap', $gap);
+}
+
+
+/// Double Borders
+/// @param {Color} $colorOne [#3C3C3C] - Color One
+/// @param {Color} $colorTwo [#999999] - Color Two
+/// @param {Size} $radius [0] - Radius
+/// @require {mixin} css3-prefix
+/// @require {mixin} border-radius
+
+@mixin double-borders($colorOne: #3C3C3C, $colorTwo: #999999, $radius: 0) {
+  border: 1px solid $colorOne;
+
+  @include css3-prefix('box-shadow', 0 0 0 1px $colorTwo);
+
+  @include border-radius( $radius );
+}
+
+
+/// Flex
+/// @param {Integer} $value [1] - Value
+/// @require {mixin} css3-prefix
+
+@mixin flex($value: 1) {
+  @include css3-prefix('box-flex', $value);
+}
+
+
+/// Flip
+/// @param {Double} $scaleX [-1] - ScaleX
+/// @require {mixin} css3-prefix
+
+@mixin flip($scaleX: -1) {
+  @include css3-prefix('transform', scaleX($scaleX));
+  filter:            "FlipH";
+  -ms-filter:        "FlipH";
+}
+
+
+/// Font Face
+/// @param {Font} $fontFamily [myFont] - Font Family
+/// @param {String} $eotFileSrc ['myFont.eot'] - Eot File Source
+/// @param {String} $woffFileSrc ['myFont.woff'] - Woff File Source
+/// @param {String} $ttfFileSrc ['myFont.ttf'] - Ttf File Source
+/// @param {String} $svgFileSrc ['myFont.svg'] - Svg File Source
+
+@mixin font-face($fontFamily: myFont, $eotFileSrc: 'myFont.eot', $woffFileSrc: 'myFont.woff', $ttfFileSrc: 'myFont.ttf', $svgFileSrc: 'myFont.svg', $svgFontID: '#myFont') {
+  font-family: $fontFamily;
+  src: url($eotFileSrc)  format('eot'),
+       url($woffFileSrc) format('woff'),
+       url($ttfFileSrc)  format('truetype'),
+       url($svgFileSrc + $svgFontID) format('svg');
+}
+
+
+/// Opacity
+/// @param {Double} $opacity [0.5] - Opacity
+/// @require {mixin} css3-prefix
+
+@mixin opacity($opacity: 0.5) {
+    $opacityMultiplied: ($opacity * 100);
+
+    filter:         alpha(opacity=$opacityMultiplied);
+    -ms-filter:     "progid:DXImageTransform.Microsoft.Alpha(Opacity=" + $opacityMultiplied + ")";
+    @include css3-prefix('opacity', $opacity);
+}
+
+
+/// Outline Radius
+/// @param {Size} $radius [5px] - Radius
+/// @require {mixin} css3-prefix
+
+@mixin outline-radius($radius: 5px) {
+  @include css3-prefix('outline-radius', $radius);
+}
+
+
+/// Resize
+/// @param {*} $directoin [both] - Direction
+/// @require {mixin} css3-prefix
+
+@mixin resize($direction: both) {
+  @include css3-prefix('resize', $direction);
+}
+
+
+/// Rotate
+///
+/// CSS Matrix Rotation Calculator http://www.boogdesign.com/examples/transforms/matrix-calculator.html
+/// @param {Double} $deg [0] - Degree
+/// @param {Double} $m11 [0] - M11
+/// @param {Double} $m12 [0] - M12
+/// @param {Double} $m21 [0] - M21
+/// @param {Double} $m22 [0] - M22
+/// @require {mixin} css3-prefix
+
+@mixin rotate($deg: 0, $m11: 0, $m12: 0, $m21: 0, $m22: 0) {
+  @include css3-prefix('transform', rotate($deg + deg));
+  filter: progid:DXImageTransform.Microsoft.Matrix(
+       M11=#{$m11}, M12=#{$m12}, M21=#{$m21}, M22=#{$m22}, sizingMethod='auto expand');
+    zoom: 1;
+}
+
+
+/// Text Shadow
+/// @param {Size} $x [2px] - X
+/// @param {Size} $y [2px] - Y
+/// @param {Size} $blur [2px] - Blur
+/// @param {Color} $color [rgba(0,0,0,.4)] - Color
+
+@mixin text-shadow($x: 2px, $y: 2px, $blur: 5px, $color: rgba(0,0,0,.4)) {
+    text-shadow: $x $y $blur $color;
+}
+
+
+/// Transform
+/// @param {List} $params - Params
+/// @require {mixin} css3-prefix
+
+@mixin transform($params) {
+  @include css3-prefix('transform', $params);
+}
+
+
+/// Transform-Origin
+/// @param {List} $params - Params
+/// @require {mixin} css3-prefix
+
+@mixin transform-origin($params) {
+  @include css3-prefix('transform-origin', $params);
+}
+
+
+// Transform-Style
+/// @param {List} $params - Params
+/// @require {mixin} css3-prefix
+
+@mixin transform-style($style: preserve-3d) {
+  @include css3-prefix('transform-style', $style);
+}
+
+/// Transition
+/// @param {List} $properties - Properties
+/// @require {mixin} css3-prefix
+
+@mixin transition($properties...) {
+
+  @if length($properties) >= 1 {
+    @include css3-prefix('transition', $properties);
+  }
+
+  @else {
+    @include css3-prefix('transition',  "all 0.2s ease-in-out 0s");
+  }
+}
+
+
+/// Triple Borders
+/// @param {Color} $colorOne [#3C3C3C] - Color One
+/// @param {Color} $colorTwo [#999999] - Color Two
+/// @param {Color} $colorThree [#000000] - Color Three
+/// @param {Size} $radius [0] - Radius
+/// @require {mixin} border-radius
+/// @require {mixin} css3-prefix
+
+@mixin triple-borders($colorOne: #3C3C3C, $colorTwo: #999999, $colorThree: #000000, $radius: 0) {
+    border: 1px solid $colorOne;
+
+    @include border-radius($radius);
+
+    @include css3-prefix('box-shadow', "0 0 0 1px #{$colorTwo}, 0 0 0 2px #{$colorThree}");
+}
+
+
+/// Keyframes
+/// @param {*} $animation-name - Animation name
+/// @content [Animation css]
+
+@mixin keyframes($animation-name) {
+  @-webkit-keyframes #{$animation-name} {
+    @content;
+  }
+  @-moz-keyframes #{$animation-name} {
+    @content;
+  }
+  @-ms-keyframes #{$animation-name} {
+    @content;
+  }
+  @-o-keyframes #{$animation-name} {
+    @content;
+  }
+  @keyframes #{$animation-name} {
+    @content;
+  }
+}
+
+
+/// Animation
+/// @param {*} $str - name duration timing-function delay iteration-count direction fill-mode play-state ([http://www.w3schools.com/cssref/css3_pr_animation.asp](http://www.w3schools.com/cssref/css3_pr_animation.asp))
+/// @require {mixin} css3-prefix
+
+@mixin animation($str) {
+  @include css3-prefix('animation', $str);
+}
+
+
+@mixin text-overflow() {
+  overflow: hidden;
+  text-overflow: ellipsis;
+  white-space: nowrap;
+}

+ 153 - 0
assets/scss/_reset.scss

@@ -0,0 +1,153 @@
+* {
+  -webkit-box-sizing: border-box;
+  -moz-box-sizing: border-box;
+  box-sizing: border-box;
+}
+
+body {
+  margin: 0;
+  padding: 0;
+  background: $body-bg;
+  color: $text;
+  font-family: $font-family;
+  font-size: $font-size;
+  line-height: $line-height;
+  -webkit-font-smoothing: antialiased;
+}
+
+article,aside,dialog,footer,header,section,footer,nav,figure,menu {
+  display: block
+}
+
+a,a:focus,a:hover{
+  text-decoration: none !important;
+}
+
+dl {
+  margin-bottom: $md-pad;
+}
+
+dd {
+  margin-left: $xlg-pad;
+}
+
+ul,
+ol {
+  margin: 0;
+  padding: 0;
+  vertical-align: baseline;
+  list-style: none;
+  -webkit-padding-start: 0;
+  -webkit-margin-before: 0;
+  -webkit-margin-after: 0;
+}
+
+main,
+header,
+footer,
+article,
+section,
+aside,
+details,
+summary {
+  margin: 0 auto;
+  width: 100%;
+}
+
+a.nuxt-link-active {
+  cursor: pointer;
+  text-decoration: none;
+  color: $text;
+  transition: color .2s ease;
+  outline: 0;
+  &:hover,&:active {
+    text-decoration: none;
+    color: $skin-bg;
+  }
+}
+a.header-link {
+  cursor: pointer;
+  text-decoration: none;
+  color: #fff;
+  transition: color .2s ease;
+  outline: 0;
+  &:hover {
+    text-decoration: underline;
+  }
+}
+
+img {
+  outline: 0;
+  border: none;
+  vertical-align: middle;
+}
+
+.f12{
+  font-size: $font-size-small
+}
+.f14{
+  font-size: $font-size;
+}
+.f16{
+  font-size: $font-size-large;
+}
+
+.text-right{
+  text-align: right;
+}
+.icon-left-arrow{
+  display:inline-block;
+  position:relative;
+  top:0;
+  width:10px;
+  height:10px;
+  background: url(../../static/icon/left-arrow.png)no-repeat;
+}
+.icon-info{
+  display:inline-block;
+  position:relative;
+  top:0;
+  width:20px;
+  height:20px;
+  background: url(../../static/icon/info.png)no-repeat;
+}
+.icon-trumpet{
+  display:inline-block;
+  position:relative;
+  top:5px;
+  width:20px;
+  height:20px;
+  background: url(../../static/icon/trumpet.png)no-repeat;
+}
+.icon-qq{
+  display:inline-block;
+  position:relative;
+  top:5px;
+  width:20px;
+  height:20px;
+  background: url(../../static/icon/qq.png)no-repeat;
+}
+.icon-space{
+  display:inline-block;
+  position:relative;
+  top:5px;
+  width:20px;
+  height:20px;
+  background: url(../../static/icon/space.png)no-repeat;
+}
+.icon-weibo{
+  display:inline-block;
+  position:relative;
+  top:5px;
+  width:20px;
+  height:20px;
+  background: url(../../static/icon/weibo.png)no-repeat;
+}
+.icon-link{
+  display:inline-block;
+  position:relative;
+  top:5px;
+  width:20px;
+  height:20px;
+  background: url(../../static/icon/link.png)no-repeat;
+}

+ 67 - 0
assets/scss/_variables.scss

@@ -0,0 +1,67 @@
+@charset "utf-8";
+// container
+$container-width: 1196px;
+$body-bg: #eee;
+$grey-bg: #f7f7f7;
+$dark-bg: rgba(197,197,197,0.4);
+$module-bg: rgba(255,255,255,0.6);
+$module-hover-bg: $dark-bg;
+$skin-bg: #149ccf;
+
+//Other
+$radius: 2px;
+
+//Basic stylings
+$br: 4px;
+$xs-pad: 4px;
+$sm-pad: 8px;
+$pad: 1em;
+$md-pad: 1.2em;
+$lg-pad: 1.5em;
+$xlg-pad: 3em;
+$trans: .3s;
+
+//Breakpoints
+$small-breakpoint: 400px;
+$large-breakpoint: $container-width;
+
+//Colors
+$primary: #5078CB;
+$accent: #1162a4;
+$red: #f44336;
+$yellow: #ffeb3b;
+$dark: #999;
+$grey: rgb(230, 230, 230);
+$gray: #666;
+$grey-light: #efefef;
+$white: #fff;
+$black: #000;
+$black-light: #dce1e9;
+
+//Text
+$text: $black-light;
+$secondary: rgba(0, 0, 0, .54);
+$disabled: rgba(0, 0, 0, .38);
+$dividers: #e3e3e3;
+
+//Links
+$link-color: $text;
+$link-hover-color: darken($link-color, 20%);
+
+//Font
+$font-family: "Microsoft YaHei",serif;
+
+//Typography
+$font-size-small: 12px;
+$font-size: 14px;
+$font-size-large: 1.2rem;
+$font-size-h1: 2rem;
+$font-size-h2: 1.75rem;
+$font-size-h3: 1.5rem;
+$font-size-h4: 1.2rem;
+$font-size-h5: 1rem;
+$font-size-h6: $font-size-small;
+
+$line-height: 1.2;
+
+$border: 1px solid $dividers;

+ 2 - 0
assets/scss/app.scss

@@ -0,0 +1,2 @@
+@charset "utf-8";
+@import "_variables", "_mixins", "_reset", "_common";

+ 170 - 0
components/common/page/pageComponent.vue

@@ -0,0 +1,170 @@
+<template>
+  <div class="page-wrap" v-if="total/1.0/pageSize>1">
+    <el-pagination
+      :current-page.sync="currentPage"
+      :page-size="pageSize"
+      layout="prev, pager, next"
+      :total="total"
+      @current-change="handleCurrentChange"
+      v-if="total/pageSize>=1"/>
+    <ul class="pagination" style="float:right;margin-left:20px;">
+      <li>
+        <input type="number" class="page-number" @keyup.13="changePage" v-model="nowPage">
+      </li>
+      <li>
+        <a class="page-a" @click="changePage">GO</a>
+      </li>
+    </ul>
+  </div>
+</template>
+
+<script>
+  export default {
+    data () {
+      return {
+        nowPage: 1,
+        currentPage: 1
+      }
+    },
+    watch: {
+      current: function () {
+        this.nowPage = Number(this.current)
+        this.currentPage = this.nowPage
+      }
+    },
+    props: ['current', 'total', 'pageSize'],
+    methods: {
+      handleCurrentChange: function (changedPage) {
+        if (this.nowPage !== this.currentPage) {
+          this.$emit('childEvent', changedPage)
+        }
+      },
+      changePage: function () {
+        let totalPage = Math.ceil(this.total / this.pageSize)
+        if (this.nowPage > totalPage) {
+          this.nowPage = totalPage
+        } else if (this.nowPage < 1) {
+          this.nowPage = 1
+        }
+        this.$emit('childEvent', this.nowPage)
+      }
+    }
+  }
+</script>
+
+<style>
+  .page-wrap a {
+    color: #2d8cf0;
+    background: 0 0;
+    text-decoration: none;
+    outline: 0;
+    cursor: pointer;
+    transition: color .2s ease;
+  }
+  .el-pagination {
+    padding: 0;
+  }
+  .el-pagination .btn-next, .el-pagination .btn-prev {
+    color: #337ab7;
+    width: 33px;
+    height: 30px;
+  }
+  .el-pagination .btn-next {
+    border-top-right-radius: 4px;
+    border-bottom-right-radius: 4px;
+  }
+  .el-pagination .btn-prev {
+    border-top-left-radius: 4px;
+    border-bottom-left-radius: 4px;
+  }
+  .el-pager li{
+    color: #337ab7;
+    text-decoration: none;
+    background-color: #fff;
+    border: 1px solid #ddd;
+    font-size: 10px;
+    width: 33px;
+    height: 30px;
+    border-right: none;
+  }
+  .el-pager li:not(.active):hover, .el-pagination button:hover {
+    z-index: 3;
+    color: #23527c;
+    background-color: #eee;
+    border-color: #ddd;
+  }
+  .el-pager li.active {
+    background: #5078cb!important;
+  }
+  .el-icon-arrow-left:before {
+    content: "\f100";
+    font-family: FontAwesome;
+  }
+  .el-icon-arrow-right:before {
+    content: "\f101";
+    font-family: FontAwesome;
+  }
+  .el-pagination button.disabled {
+    color: #337ab7;
+    background-color: #fff;
+    cursor: not-allowed;
+  }
+  .pagination {
+    display: inline-block;
+    padding-left: 0;
+    margin: 20px 0;
+    border-radius: 4px;
+  }
+  .pagination>li {
+    display: inline;
+  }
+  input.page-number {
+    vertical-align: inherit;
+    display: inline-block;
+    width: 40px;
+    height: 31px;
+    padding: 6px 6px;
+    font-size: 14px;
+    line-height: 1.42857143;
+    color: #9B9792;
+    text-align: center;
+    background-color: #F6F5F4;
+    background-image: none;
+    border: 1px solid #ccc;
+    border-top-left-radius: 4px;
+    border-bottom-left-radius: 4px;
+    box-shadow: inset 0 1px 1px rgba(0,0,0,.075);
+    transition: border-color ease-in-out .15s,box-shadow ease-in-out .15s;
+  }
+  .page-a {
+    background: #5078cb !important;
+    color: #fff !important;
+    float: right!important;
+  }
+  .page-a {
+    color: #fff;
+    border-color: #4574e8;
+    padding: 6px 6px!important;
+    font-size: 14px!important;
+    border-top-right-radius: 4px!important;
+    border-bottom-right-radius: 4px!important;
+    text-decoration: none;
+    height: 31px;
+  }
+  .page-wrap{
+    float: right;
+    margin: 30px 0;
+  }
+  .page-wrap ul, .page-wrap div {
+    display: inline-block;
+    margin: 0;
+  }
+  input.page-number {
+    -moz-appearance:textfield;
+  }
+  input.page-number::-webkit-inner-spin-button,
+  input.page-number::-webkit-outer-spin-button {
+    -webkit-appearance: none;
+    margin: 0;
+  }
+</style>

+ 92 - 0
components/common/upload/upload.vue

@@ -0,0 +1,92 @@
+<template>
+  <div>
+    <div class="preview">
+      <img :src="qualifications.url==''?'images/all/upload-apply.png': isPdf?'/images/all/timg.png':qualifications.url" class="previewImage">
+      <input type="file" v-if="!qualifications.url" class="com-input" @change="update" accept="image/jpeg,image/jpg,image/gif,image/bmp,image/png,.pdf" >
+    </div>
+    <div class="hover-show" v-if="qualifications.url">
+      <span class="delete" title="删除" @click="deleteImg(qualifications.url)"><i class="fa fa-trash"/></span>
+      <a @click="showImg(qualifications.url)"><i class="fa fa-search"/>查看</a>
+    </div>
+    <div id="image-box" v-if="isShow">
+      <div class="x-floating-wrap"/>
+      <div class="x-floating">
+        <div id="item-content">
+          <div class="x-close-wrap" @click="isShow = false"><a href="javascript:void(0);">&times;</a></div>
+          <div class="img"><img :src="qualifications.url"></div>
+        </div>
+      </div>
+    </div>
+  </div>
+</template>
+<script>
+  export default {
+    props: ['typeData', 'url'],
+    data () {
+      return {
+        qualifications: {
+          url: '',
+          type: ''
+        },
+        isShow: false,
+        isPdf: false
+      }
+    },
+    watch: {
+      url: function (val) {
+        if (val && val !== '') {
+          this.qualifications.url = val
+        }
+      }
+    },
+    methods: {
+      update (e) {
+        let file = e.target.files[0]
+        let param = new FormData()
+        param.append('file', file, file.name)
+        param.append('chunk', '0')
+        if (file.type !== 'application/pdf') {
+          let config = {
+            headers: {'Content-Type': 'multipart/form-data'}
+          }
+          this.$http.post('/api/images', param, config)
+            .then(response => {
+              this.isPdf = false
+              this.qualifications.url = response.data[0].path
+              this.qualifications.type = typeof this.typeData === 'undefined' ? '' : this.typeData
+              this.$emit('uploadAction', this.qualifications)
+            })
+        } else {
+          let config = {
+            headers: {'Content-Type': file.type}
+          }
+          this.$http.post('/file', param, config)
+            .then(response => {
+              this.isPdf = true
+              this.qualifications.url = response.data[0].path
+              this.qualifications.type = typeof this.typeData === 'undefined' ? '' : this.typeData
+              this.$emit('uploadAction', this.qualifications)
+            }, err => {
+              console.log(err)
+            })
+        }
+      },
+      showImg (imgUrl) {
+        if (!this.isPdf) {
+          this.qualifications.url = imgUrl
+          this.isShow = true
+        } else {
+          window.open(imgUrl)
+        }
+      },
+      deleteImg () {
+        this.qualifications.url = ''
+        this.qualifications.type = this.typeData
+        this.$emit('uploadAction', this.qualifications)
+      }
+    }
+  }
+</script>
+<style>
+
+</style>

+ 26 - 0
components/common/vue-empty/empty.vue

@@ -0,0 +1,26 @@
+<template>
+  <div class="empty-box">
+    <slot>没有数据</slot>
+  </div>
+</template>
+
+<script>
+  export default {
+    name: 'VueEmpty'
+  }
+</script>
+
+<style lang="scss">
+  @import '~assets/scss/mixins';
+  @import '~assets/scss/variables';
+  .empty-box {
+    position: relative;
+    display: flex;
+    width: 100%;
+    height: 100%;
+    min-height: 5em;
+    text-align: center;
+    justify-content: center;
+    align-items: center;
+  }
+</style>

+ 7 - 0
components/common/vue-empty/index.js

@@ -0,0 +1,7 @@
+import EmptyComponent from './empty.vue'
+
+export default {
+  install (Vue) {
+    Vue.component('empty-box', EmptyComponent)
+  }
+}

+ 7 - 0
components/common/vue-loading/index.js

@@ -0,0 +1,7 @@
+import LoadingComponent from './loading.vue'
+
+export default {
+  install (Vue) {
+    Vue.component('loading-box', LoadingComponent)
+  }
+}

+ 132 - 0
components/common/vue-loading/loading.vue

@@ -0,0 +1,132 @@
+<template>
+  <div class="spinner-box" v-show="loading">
+    <div class="spinner-inner" :style="{color: color}">
+      <div class="la-ball-beat">
+        <div :style="spinnerStyle"/>
+        <div :style="spinnerStyle"/>
+        <div :style="spinnerStyle"/>
+      </div>
+      <slot/>
+    </div>
+  </div>
+</template>
+
+<script>
+  export default {
+    name: 'Loader',
+    props: {
+      loading: {
+        type: Boolean,
+        default: true
+      },
+      color: {
+        type: String,
+        default: 'rgba(197, 197, 197, 0.4)'
+      },
+      height: {
+        type: String,
+        default: '15px'
+      },
+      width: {
+        type: String,
+        default: '15px'
+      },
+      margin: {
+        type: String,
+        default: '5px'
+      }
+    },
+    data () {
+      return {
+        spinnerStyle: {
+          backgroundColor: this.color,
+          height: this.height,
+          width: this.width,
+          margin: this.margin
+        }
+      }
+    }
+  }
+</script>
+
+<style lang="scss" scoped>
+  @import '~assets/scss/mixins';
+  @import '~assets/scss/variables';
+  .spinner-box {
+    position: relative;
+    width: 100%;
+    min-height: 50px;
+    height: 100%;
+    > .spinner-inner {
+      width: 80px;
+      height: 30px;
+      position: absolute;
+      top: 50%;
+      left: 50%;
+      margin-left: -40px;
+      margin-top: -15px;
+      text-align: center;
+      > .la-ball-beat {
+        display: block;
+        position: relative;
+        box-sizing: border-box;
+        font-size: 0;
+        color: #fff;
+        width: 80px;
+        height: 30px;
+        > div {
+          position: relative;
+          box-sizing: border-box;
+          display: inline-block;
+          float: none;
+          border: none;
+          width: 15px;
+          height: 15px;
+          margin: 5px;
+          background-color: $module-hover-bg;
+          @include css3-prefix(animation, ball-beat 0.7s -0.15s infinite linear);
+          &:nth-child(2n-1) {
+            @include css3-prefix(animation-delay, -.5s);
+          }
+        }
+        &.la-sm {
+          width: 26px;
+          height: 8px;
+          > div {
+            width: 8px;
+            height: 8px;
+            margin: 3px;
+          }
+        }
+        &.la-2x {
+          width: 108px;
+          height: 36px;
+          > div {
+            width: 20px;
+            height: 20px;
+            margin: 8px;
+          }
+        }
+        &.la-3x {
+          width: 162px;
+          height: 54px;
+          > div {
+            width: 30px;
+            height: 30px;
+            margin: 12px
+          }
+        }
+      }
+    }
+  }
+  @include keyframes(ball-beat) {
+    50% {
+      opacity: .2;
+      @include css3-prefix(transform, scale(0.75));
+    }
+    100% {
+      opacity: 1;
+      @include css3-prefix(transform, scale(1));
+    }
+  }
+</style>

+ 94 - 0
components/default/footer.vue

@@ -0,0 +1,94 @@
+<template>
+  <footer class="footer">
+    <div class="container">
+      <div class="footer-info">
+        <div class="footer-left">
+          <p>
+            <a href="#">开放平台</a>
+            <a href="#">法律条款</a>
+            <a href="#">联系我们</a>
+            <a href="#">关于我们</a>
+          </p>
+          <span>版权所有:深圳市优软科技有限公司 Copyright @ 2017 All Rights Reserved</span>
+        </div>
+        <div class="footer-right">
+          <div class="r_text">
+            <p>服务热线:</p>
+            <span style="font-size: 24px;">0755-26994808</span>
+          </div>
+          <div class="r_app">
+            <img src="/qrcode/uu.jpg">
+            <p style="padding-top:15px;">APP 下载</p>
+          </div>
+          <div class="r_weixin">
+            <img src="/qrcode/uas.jpg">
+            <p style="padding-top:15px;">微信公众号</p>
+          </div>
+        </div>
+      </div>
+    </div>
+  </footer>
+</template>
+
+<script>
+  export default {
+    name: 'FooterView'
+  }
+</script>
+
+<style scoped>
+  .footer{
+    width:100%;
+    background: #474443;
+    padding-top:20px;
+  }
+  .container{
+    padding:0;
+  }
+  .footer .footer-info{
+    width:100%;
+    height:153px;
+    display: inline-flex;
+    justify-content: space-between;
+    align-items: center;
+    padding-left:15px;
+    padding-right:20px;
+  }
+  .footer .footer-info .footer-left{
+    width:500px;
+    color:#fff;
+  }
+  .footer .footer-info .footer-left p{
+    margin-bottom:30px;
+  }
+  .footer .footer-info .footer-left p a{
+      color:#fff;
+    margin-right:25px;
+  }
+  .footer .footer-info .footer-left p a:hover{
+    color:#5280e3;
+    text-decoration: none;
+    cursor:pointer;
+  }
+  .footer .footer-info .footer-left span{}
+
+  .footer .footer-info .footer-right{
+    width:450px;
+    height: 153px;
+    color:#fff;
+    display: inline-flex;
+    justify-content: flex-end;
+    align-items: center;
+  }
+  .footer .footer-right .r_text{
+    text-align: right;
+  }
+  .footer .footer-right .r_app{
+    text-align: center;
+    margin-left:50px;
+  }
+  .footer .footer-right .r_weixin{
+    text-align: center;
+    margin-left:40px;
+  }
+</style>

+ 220 - 0
components/default/header.vue

@@ -0,0 +1,220 @@
+<template>
+  <header class="header">
+    <div class="container clearfix">
+      <div class="nav-list pull-left">
+        <a href="http://town.ubtob.com">
+          <img src="/logo.png">
+        </a>
+        <nuxt-link to="/" exact>
+          <span>首页</span>
+        </nuxt-link>
+        <nuxt-link to="/repairs">
+          <span>园区服务</span>
+        </nuxt-link>
+        <a href="https://www.ubtob.com/saas/about"><span>信息化服务</span></a>
+        <a href="http://uas.ubtob.com"><span>市场开拓</span></a>
+        <a href="http://zb.uuzcc.com/" target="_blank"><span>众创空间</span></a>
+        <a href="http://www.yitoa-fintech.com/" target="_blank"><span>金融服务</span></a>
+        <a href="https://www.usoftmall.com" target="_blank"><span>电子商城</span></a>
+        <a href="http://job.uuzcc.com/"><span>人才招聘</span></a>
+        <nuxt-link to="/park"><span>园区介绍</span></nuxt-link>
+        <nuxt-link to="/about"><span>联系我们</span></nuxt-link>
+      </div>
+      <div class="nav-right pull-right">
+        <div class="nav-search">
+          <i class="fa fa-search"/>
+        </div>
+        <template v-if="user != null && user.name">
+          <div class="info">
+            <i class="fa fa-user-circle"/>
+            <span v-text="user.name"/>
+            <ul class="list-unstyled">
+              <li>个人中心</li>
+              <li>消息中心</li>
+              <li>订单中心</li>
+              <li @click="logout()">安全退出</li>
+            </ul>
+          </div>
+        </template>
+        <template v-if="user == null || !user.name">
+          <div class="info">
+            <a @click="onLoginClick()">登录</a>&nbsp;/&nbsp;
+            <a @click="onRegisterClick">注册</a>
+          </div>
+        </template>
+      </div>
+    </div>
+  </header>
+</template>
+
+<script>
+  export default {
+    name: 'HeaderView',
+    computed: {
+      user () {
+        return this.$store.state.option.user.data
+      }
+    },
+    methods: {
+      logout () {
+        this.$http.get('/logout/crossBefore').then(response => {
+          if (response.data) {
+            window.location.href = response.data.logoutUrl + '&baseUrl=' + encodeURIComponent(window.location.protocol + '//' + window.location.host + response.data.baseUrl)
+          }
+        })
+      },
+      onLoginClick () {
+        this.$http.get('/login/page', {params: {returnUrl: window.location.href}}).then(response => {
+          if (response.data) {
+            window.location.href = response.data.content + '&baseUrl=' + encodeURIComponent(window.location.protocol + '//' + window.location.host + response.data.baseUrl)
+          }
+        })
+        // TODO 待Account Center改版
+      },
+      onRegisterClick () {
+        this.$http.get('/register/page').then(response => {
+          if (response.data && response.data.content) {
+            window.location.href = response.data.content + '&fromDomain=thxz'
+            //  console.log(response.data.content + '&fromDomain=thxz')
+          }
+        })
+      }
+    }
+  }
+</script>
+
+<style scoped type="text/scss" lang="scss">
+  .header{
+    position:fixed;
+    top:0;
+    left:0;
+    z-index:100;
+    height:70px;
+    background: #122931;
+    .nav-list{
+      height:70px;
+      a{
+        &:first-child{
+          margin-left:16px;
+          margin-right:20px;
+        }
+        &.nuxt-link-active span{
+          color:#149ccf;
+          &:after{
+            content:'';
+            position:absolute;
+            bottom:0;
+            left:50%;
+            display:block;
+            height:5px;
+            width:30px;
+            margin-left:-15px;
+            background: #149ccf;
+          }
+        }
+      }
+      span{
+        position:relative;
+        display:inline-block;
+        height:70px;
+        line-height: 70px;
+        padding:0 15px;
+        font-size: 14px;
+        color:#dce1e9;
+        &:hover{
+          color:#149ccf;
+          &:after{
+            content:'';
+            position:absolute;
+            bottom:0;
+            left:50%;
+            display:block;
+            height:5px;
+            width:30px;
+            margin-left:-15px;
+            background: #149ccf;
+          }
+        }
+      }
+    }
+    .nav-right{
+      text-align: right;
+      line-height:70px;
+      .nav-search{
+        display:inline-block;
+        vertical-align: middle;
+        i{
+          display:block;
+          padding:12px;
+          font-size: 18px;
+          background: #101f24;
+          color:#dce1e9;
+        }
+      }
+      .info{
+        display:inline-block;
+        vertical-align: top;
+        position:relative;
+        margin-left:20px;
+        color:#dce1e9;
+        ul{
+          display:none;
+          position:absolute;
+          top: 100%;
+          right:0;
+          z-index:1000;
+          background: #13252b;
+          padding-bottom:20px;
+          li{
+            line-height: 40px;
+            text-align: center;
+            width:110px;
+            color:#f5f5f5;
+            &:hover{
+              color:#149ccf;
+            }
+          }
+        }
+        &:hover{
+          background: #142e37;
+          cursor:pointer;
+          i{
+            color:#149ccf;
+          }
+          span{
+            color:#149ccf;
+          }
+          ul{
+            display:block;
+          }
+        }
+        >i{
+          position:relative;
+          top:1px;
+          left:-5px;
+          font-size: 16px;
+          color:#f5f5f5;
+        }
+        >span{
+          display:inline-block;
+          vertical-align: top;
+          text-align: left;
+          width:80px;
+          overflow: hidden;
+          text-overflow: ellipsis;
+          white-space:nowrap;
+          font-size: 14px;
+          color:#f5f5f5;
+        }
+        a{
+          color:#dce1e9;
+          text-decoration: none;
+          &:hover{
+            color:#149ccf;
+            cursor:pointer;
+          }
+        }
+      }
+    }
+  }
+</style>

+ 4 - 0
components/default/index.js

@@ -0,0 +1,4 @@
+import Header from './header.vue'
+import Footer from './footer.vue'
+
+export { Header, Footer }

+ 21 - 0
components/garden/banner.vue

@@ -0,0 +1,21 @@
+<template>
+  <div class="banner">
+    <div class="img"/>
+  </div>
+</template>
+
+<script>
+    export default {
+      name: 'Banner'
+    }
+</script>
+
+<style scoped type="text/scss" lang="scss">
+.banner{
+  margin-top:54px;
+  .img{
+    height:310px;
+    background: url(/img/banner/10.png)no-repeat center center;
+  }
+}
+</style>

+ 330 - 0
components/garden/detail.vue

@@ -0,0 +1,330 @@
+<template>
+  <div class="detail">
+    <div class="top">
+      <div class="container">
+        <div class="breadcrumb">
+          <a href="/townInfo">园区活动 > </a> <span v-text="detail.ac_title">12</span>
+        </div>
+        <div class="title">
+          <div class="img">
+            <img :src="detail.ac_image">
+          </div>
+          <div class="info">
+            <h4 v-text="detail.ac_title">2</h4>
+            <p class="mb20" v-text="detail.ac_desc">1</p>
+            <p>类别:<span v-text="detail.ac_type">23</span></p>
+            <p>时间:<span v-text="formatDate(detail.ac_enddate)">23</span></p>
+            <p class="mb20">地点:<span v-text="detail.ac_addr">23</span></p>
+            <p>
+              分享:
+              <a href="javascript:void(0)" @click="shareQQ"><i class="icon-qq"/></a>
+              <a href="javascript:void(0)" @click="spaceQQ"><i class="icon-space"/></a>
+              <a href="javascript:void(0)" @click="weibo"><i class="icon-weibo"/></a>
+              <a href="javascript:void(0)" @click="copyHref" v-clipboard:copy="linkUrl"><i class="icon-link"/></a>
+            </p>
+          </div>
+          <div class="btn">
+            <a v-if="!detail.hasRegistrat && detail.ac_status !== '已结束'" href="javascript:void(0)" @click="enterFor">报 名 参 加</a>
+            <a v-if="detail.hasRegistrat && detail.ac_status !== '已结束'" href="javascript:void(0)" class="disable_a">已 报 名</a>
+            <a v-if="detail.ac_status === '已结束'" href="javascript:void(0)" class="disable_a">活 动 已 结 束</a>
+            <span>报名人数:</span><span v-text="detail.ac_enternum">32</span><span>&nbsp;/&nbsp;</span><span v-text="detail.ac_maxenternum? detail.ac_maxenternum : '不限'">1</span>
+          </div>
+        </div>
+      </div>
+    </div>
+    <div class="container">
+      <div class="content">
+        <div class="left">
+          <ul class="list-unstyled">
+            <li>
+              <h4>活动介绍</h4>
+              <p v-html="detail.ac_content">1</p>
+            </li>
+            <li>
+              <h4>报名须知</h4>
+              <p v-html="detail.ac_notice">1</p>
+            </li>
+            <li>
+              <h4>费用信息</h4>
+              <p v-html="detail.ac_costinfo">1</p>
+            </li>
+          </ul>
+        </div>
+        <div class="right">
+          <h3>更多活动</h3>
+          <template v-for="detail in list">
+            <a class="item" :href="'/townInfo/' + detail.ac_id">
+              <div class="img">
+                <img :src="detail.ac_icon">
+              </div>
+              <h4 v-text="detail.ac_title">1</h4>
+              <p v-text="detail.ac_addr">1</p>
+              <p v-text="formatDate(detail.ac_startdate)">1</p>
+            </a>
+          </template>
+        </div>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script>
+  import {formatDate} from '@/utils/date.js'
+  export default {
+    name: 'GardenDetail',
+    data () {
+      return {
+        linkUrl: ''
+      }
+    },
+    mounted () {
+      this.linkUrl = window.location.href
+    },
+    computed: {
+      user () {
+        return this.$store.state.option.user.data
+      },
+      detail () {
+        return this.$store.state.gardens.detail.data.data
+      },
+      list () {
+        return this.$store.state.gardens.list.data.list
+      }
+    },
+    methods: {
+      // 格式化时间
+      formatDate (row) {
+        let date = new Date(row)
+        return formatDate(date, 'yyyy-MM-dd hh:mm')
+      },
+      // qq分享
+      shareQQ () {
+         let url = encodeURIComponent(document.location)
+         let title = this.detail.ac_title
+         let summary = encodeURIComponent('')
+         let desc = this.detail.ac_desc
+         let pics = this.detail.ac_image
+         window.open('http://connect.qq.com/widget/shareqq/index.html?url=' +
+           url + '&title=' + title + '&summary=' + summary + '&desc=' + desc + '&pics=' + pics)
+      },
+      // QQ空间
+      spaceQQ () {
+        let url = encodeURIComponent(document.location)
+        let title = this.detail.ac_title
+        let summary = encodeURIComponent('')
+        let desc = this.detail.ac_desc
+        let pics = this.detail.ac_image
+        window.open('http://sns.qzone.qq.com/cgi-bin/qzshare/cgi_qzshare_onekey?url=' +
+          url + '&title=' + title + '&summary=' + summary + '&desc=' + desc + '&pics=' + pics)
+      },
+      // 新浪微博
+      weibo () {
+        let url = encodeURIComponent(document.location)
+        let title = this.detail.ac_title
+        let summary = encodeURIComponent('')
+        let desc = this.detail.ac_desc
+        let pics = this.detail.ac_image
+        window.open('http://sns.qzone.qq.com/cgi-bin/qzshare/cgi_qzshare_onekey?url=' +
+          url + '&title=' + title + '&summary=' + summary + '&desc=' + desc + '&pics=' + pics)
+      },
+      // 复制链接
+      copyHref () {
+        this.$message({
+          type: 'success',
+          message: '复制链接成功!'
+        })
+      },
+      enterFor () {
+        if (!this.$store.state.option.user.data.name) {
+          this.$message({
+            type: 'error',
+            message: '亲,请先登录!'
+          })
+        } else {
+          this.$http.get('api/serve/ActivityRegistration.action', {params: {id: this.$route.params.id, uu: this.user.userUu, name: this.user.name, client_type: 'cc', cityId: this.user.currentCity ? this.user.currentCity.id : null}})
+            .then(res => {
+              if (res.data.success) {
+                this.$message({
+                  message: res.data.msg,
+                  type: 'success'
+                })
+                this.$store.dispatch('loadGardenDetail', {id: this.$route.params.id, uu: this.user.userUu})
+              }
+            })
+            .catch(() => {
+              console.log('请检查网络!')
+            })
+        }
+      }
+    }
+  }
+</script>
+
+<style scoped type="text/scss" lang="scss">
+.detail{
+  margin-top:54px;
+  .top{
+    height:440px;
+    background: #fff;
+    overflow: hidden;
+    .breadcrumb{
+      line-height: 60px;
+      margin:0;
+      background: #fff;
+      color:#8b8b8b;
+      font-size: 16px;
+      a{text-decoration: none; color:#8b8b8b;}
+    }
+    .title {
+      position:relative;
+      height:300px;
+      .img{
+        float:left;
+        width:460px;
+        height:300px;
+        img{
+          width:460px;
+          height:300px;
+          vertical-align: top;
+        }
+      }
+      .info{
+        margin-left:520px;
+        h4{
+          font-size: 30px;
+          color:#323232;
+          margin:0;
+          margin-bottom:34px;
+        }
+        p{
+          color:#787878;
+          font-size: 14px;
+          margin-bottom:10px;
+          &.mb20{
+            margin-bottom:20px;
+          }
+          span{
+            color:#333;
+          }
+          i{
+            margin-right:10px;
+          }
+        }
+      }
+      .btn{
+        position:absolute;
+        left:520px;
+        bottom:0;
+        a{
+          display:inline-block;
+          width:174px;
+          height:36px;
+          line-height: 36px;
+          color:#fff;
+          background: #149cd0;
+          text-align: center;
+          margin-right:30px;
+          text-decoration: none;
+          &.disable_a{
+            background: #909399;
+            &:hover{
+              cursor:auto;
+            }
+          }
+          &:hover{
+            cursor:pointer;
+          }
+        }
+        span{
+          color:#a1a1a1;
+          font-size: 14px;
+        }
+      }
+    }
+  }
+  .content{
+    background: #fff;
+    padding:40px 0;
+    margin-bottom:60px;
+    .left{
+      display:inline-block;
+      width:850px;
+      border-right:1px solid #e5e5e5;
+      padding-left:46px;
+      ul{
+        li{
+          margin-bottom:90px;
+          padding-right:50px;
+          h4{
+            font-size: 20px;
+            color:#323232;
+            margin:0;
+            margin-bottom:30px;
+            &:before{
+              content:'';
+              width:4px;
+              height:16px;
+              background: #159ccb;
+              display:inline-block;
+              margin-right:10px;
+              position:relative;
+              top:2px;
+            }
+          }
+          p{
+            font-size: 14px;
+            color:#787878;
+            margin-bottom:10px;
+          }
+        }
+      }
+    }
+    .right{
+      float:right;
+      width:330px;
+      padding-left:30px;
+      padding-right:20px;
+      .item{
+        display:block;
+        vertical-align: top;
+        cursor:pointer;
+        .img{
+          text-align: center;
+          width:178px;
+          height:160px;
+          margin:0 auto;
+          margin-bottom:25px;
+          img{
+            width:178px;
+            height:160px;
+            vertical-align: top;
+          }
+        }
+        h4{
+          font-size: 16px;
+          color:#323232;
+          margin:0;
+          margin-bottom:15px;
+          text-align: center;
+          overflow: hidden;
+          white-space: nowrap;
+        }
+        p{
+          font-size: 14px;
+          color:#a0a0a0;
+          text-align: center;
+          margin-bottom:10px;
+          overflow: hidden;
+          white-space: nowrap;
+        }
+      }
+      h3{
+        font-size: 20px;
+        color:#787878;
+        margin:0;
+        margin-bottom:45px;
+      }
+    }
+  }
+}
+</style>

+ 5 - 0
components/garden/index.js

@@ -0,0 +1,5 @@
+import Banner from './banner.vue'
+import List from './list.vue'
+import Detail from './detail.vue'
+
+export { Banner, List, Detail }

+ 223 - 0
components/garden/list.vue

@@ -0,0 +1,223 @@
+<template>
+  <div class="garden">
+    <div class="container">
+      <div class="top">
+        <ul class="list-inline">
+          <li :class="{active: step === ''}" @click="selectEvent()">全部</li>
+          <li v-for="item in typeList" v-text="item.at_name" @click="selectEvent(item.at_name)" :class="{active: item.active === true}">旅行</li>
+        </ul>
+      </div>
+      <div class="content">
+        <div class="empty" v-if="listCount.list.length === 0">无相关活动信息!</div>
+        <div class="info-list" v-for="item in listCount.list">
+          <div class="img">
+            <img :src="item.ac_icon">
+          </div>
+          <div class="list-right">
+            <p v-text="item.ac_title">企业为员工打造全新潼湖小镇,舒服办公环境</p>
+            <span v-text="item.ac_desc">2017年,优软科技携手碧桂园创办全新智慧生态园,发扬优软新势力,适应互联网潮流 发展.</span>
+          </div>
+          <div class="detail">
+            <h4 v-text="item.ac_title">12</h4>
+            <span v-text="item.ac_desc">3213ffds</span>
+            <p v-text="formatDate(item.ac_startdate)">32342</p>
+            <p v-text="item.ac_addr">32342</p>
+            <p>{{item.ac_enternum}}&nbsp;参加活动</p>
+            <a :href="'/townInfo/' + item.ac_id">查看详情</a>
+          </div>
+        </div>
+      </div>
+      <div class="page" v-if="listCount.total > count">
+        <el-pagination
+          @current-change="handleCurrentChange"
+          :current-page.sync="page"
+          :page-size="count"
+          layout="total, prev, pager, next, jumper"
+          :total="listCount.total"/>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script>
+  import {formatDate} from '@/utils/date.js'
+    export default {
+      name: 'GardenList',
+      data () {
+        return {
+          step: '',
+          count: 16,
+          page: 1,
+          typeList: {}
+        }
+      },
+      mounted () {
+        let list = this.$store.state.gardens.gardenType.data.list
+        for(let i = 0; i < list.length; i++) {
+          list[i].active = false
+        }
+        this.typeList = JSON.parse(JSON.stringify(list))
+      },
+      computed: {
+        listCount () {
+          return this.$store.state.gardens.list.data
+        }
+      },
+      methods: {
+        // 格式化时间
+        formatDate (row) {
+          let date = new Date(row)
+          return formatDate(date, 'yyyy-MM-dd hh:mm')
+        },
+        selectEvent (type) {
+          for(let i = 0; i < this.typeList.length; i++) {
+            if(type) {
+              this.step = type
+              this.typeList[i].at_name === type ? this.typeList[i].active = true : this.typeList[i].active = false
+            } else {
+              this.typeList[i].active = false
+              this.step = ''
+            }
+          }
+          this.$store.dispatch('loadGardenList', {limit: 16, page: this.page, type: type})
+        },
+        handleCurrentChange(val) {
+          this.$store.dispatch('loadGardenList', {limit: 16, page: val, type: this.step})
+        }
+      }
+    }
+</script>
+
+<style scoped type="text/scss" lang="scss">
+.garden{
+  background: #f4f4f4;
+  padding-bottom:80px;
+  .top{
+    margin: 0 auto;
+    overflow: hidden;
+    padding:55px 0;
+    text-align: center;
+    ul{
+      li{
+        padding:0 24px;
+        font-size: 14px;
+        color:#333;
+        font-weight: bold;
+        border-right:1px solid #bfbfbf;
+        &:last-child{
+          border:none;
+        }
+        &:hover,&.active{
+          cursor:pointer;
+          color:#149ccf;
+        }
+      }
+    }
+  }
+  .content{
+    .empty{
+      padding:50px 0;
+      font-size: 28px;
+      text-align: center;
+      color:#333;
+    }
+    .info-list{
+      position:relative;
+      display:inline-block;
+      width:24%;
+      height:430px;
+      vertical-align: top;
+      margin-right:10px;
+      margin-bottom:30px;
+      background: #fff;
+      overflow: hidden;
+      &:last-child{
+        margin:0;
+      }
+      &:hover{
+        cursor:pointer;
+        .detail{
+          opacity:1;
+          top:0;
+        }
+      }
+      .img{
+        width:280px;
+        height:250px;
+        img{
+          width:100%;
+          height:100%;
+          border:none;
+          padding:0;
+        }
+      }
+      .list-right{
+        padding:24px 16px 0 16px;
+        overflow: hidden;
+        p{
+          font-size: 20px;
+          color:#333;
+          margin-bottom:25px;
+          width:98%;
+          overflow: hidden;
+          text-overflow: ellipsis;
+          white-space: nowrap;
+        }
+        span{
+          font-size: 14px;
+          line-height: 20px;
+          color:#969696;
+        }
+      }
+      .detail{
+        position:absolute;
+        top:100%;
+        opacity:0;
+        transition: all .5s ease;
+        background: rgba(0,0,0,.8);
+        width:100%;
+        height:430px;
+        padding:30px 16px;
+        h4{
+          font-size: 20px;
+          color:#fff;
+          margin-bottom:25px;
+        }
+        span{
+          display:block;
+          font-size: 14px;
+          color:#fff;
+          line-height: 20px;
+          margin-bottom:10px;
+        }
+        p{
+          font-size: 14px;
+          color:#b4b4b4;
+          margin-bottom:10px;
+        }
+        a{
+          display: block;
+          width:200px;
+          height:40px;
+          line-height: 38px;
+          text-align: center;
+          margin:0 auto;
+          margin-top:30px;
+          font-size: 16px;
+          color:#fff;
+          border:1px solid #fff;
+          &:hover{
+            cursor:pointer;
+            color:#149ccf;
+            border: 1px solid #149ccf;
+          }
+        }
+      }
+    }
+  }
+  .page{
+    text-align: center;
+    padding: 55px 0;
+  }
+}
+</style>

+ 65 - 0
components/home/banner.vue

@@ -0,0 +1,65 @@
+<template>
+  <div class="banner">
+    <div class="img"/>
+    <div class="banner-list">
+      <div class="container">
+        <ul class="list-inline">
+          <li>U 智慧 · 企业</li>
+          <li>U 智慧 · 园区</li>
+          <li>U 智慧 · 政务</li>
+        </ul>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script>
+    export default {
+      name: 'Banner'
+    }
+</script>
+
+<style scoped type="text/scss" lang="scss">
+.banner{
+  margin-top:54px;
+  .img{
+    height:450px;
+    background: url(/img/banner/1.png)no-repeat center center;
+  }
+  .banner-list{
+    height:90px;
+    background: #126a8d;
+    padding-top:20px;
+    ul{
+      li{
+        width:32%;
+        height:50px;
+        line-height: 50px;
+        text-align: center;
+        border-right:1px solid #45849a;
+        &:before{
+          content: '';
+          display:inline-block;
+          width:30px;
+          height:30px;
+          position:relative;
+          top:8px;
+          left:-20px;
+        }
+        &:first-child:before{
+          background: url(/icon/enterprise.png)no-repeat;
+        }
+        &:nth-child(2):before{
+          background: url(/icon/developers.png)no-repeat;
+        }
+        &:last-child{
+          border:none;
+          &:before{
+            background: url(/icon/government.png)no-repeat;
+          }
+        }
+      }
+    }
+  }
+}
+</style>

+ 59 - 0
components/home/carousel.vue

@@ -0,0 +1,59 @@
+<template>
+  <div class="carousel">
+    <div class="container">
+      <div v-swiper:mySwiper="swiperOption">
+        <div class="swiper-wrapper">
+          <div class="swiper-slide" v-for="item in carouselData">
+            <!--<a :href="banner.hrefUrl" target="_blank" v-if="banner.hrefUrl">-->
+            <!--<img :src="banner.pictureUrl"/>-->
+            <!--</a>-->
+            <span>
+              <img :src="item.url" style="width:100%;height:100%;">
+            </span>
+          </div>
+          <div class="swiper-button-prev"/>
+          <div class="swiper-button-next"/>
+        </div>
+        <div class="swiper-pagination swiper-pagination-bullets"/>
+      </div>
+      <slot/>
+    </div>
+  </div>
+</template>
+
+<script>
+    export default {
+      name: 'Carousel',
+      props: ['carouselData'],
+      data () {
+        return {
+          activeSlide: 0,
+          swiperOption: {
+            autoplay: 6000,
+            pagination: '.swiper-pagination',
+            paginationClickable: true,
+            mousewheel: true,
+            effect: 'fade',
+            lazyLoading: true,
+            loop: true,
+            prevButton: '.swiper-button-prev',
+            nextButton: '.swiper-button-next'
+          }
+        }
+      }
+    }
+</script>
+
+<style scoped>
+.carousel{
+  width:100%;
+  margin:0 auto;
+  text-align: center;
+  position:relative;
+}
+  .container{
+    width:100%;
+    margin:0 auto;
+    padding:0;
+  }
+</style>

+ 177 - 0
components/home/garden.vue

@@ -0,0 +1,177 @@
+<template>
+  <div class="garden">
+    <div class="container">
+      <div class="title">
+        <p><i class="icon-info"/>园区活动</p>
+        <a href="/townInfo">更多</a>
+      </div>
+      <div class="content">
+        <div class="info-list" v-for="item in list">
+          <div class="img">
+            <img :src="item.ac_icon">
+          </div>
+          <div class="list-right">
+            <p v-text="item.ac_title">企业为员工打造全新潼湖小镇,舒服办公环境</p>
+            <span v-text="item.ac_desc">2017年,优软科技携手碧桂园创办全新智慧生态园,发扬优软新势力,适应互联网潮流 发展.</span>
+          </div>
+          <div class="detail">
+            <h4 v-text="item.ac_title">12</h4>
+            <span v-text="item.ac_desc">3213ffds</span>
+            <p v-text="formatDate(item.ac_startdate)">32342</p>
+            <p v-text="item.ac_addr">32342</p>
+            <p>{{item.ac_enternum}}&nbsp;参加活动</p>
+            <a :href="'/townInfo/' + item.ac_id">查看详情</a>
+          </div>
+        </div>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script>
+  import {formatDate} from '@/utils/date.js'
+  export default {
+    name: 'Garden',
+    computed: {
+      list () {
+        return this.$store.state.gardens.list.data.list
+      }
+    },
+    methods: {
+      // 格式化时间
+      formatDate (row) {
+        let date = new Date(row)
+        return formatDate(date, 'yyyy-MM-dd hh:mm')
+      }
+    }
+  }
+</script>
+
+<style scoped type="text/scss" lang="scss">
+.garden{
+  height:610px;
+  background: #f4f4f4;
+  .title{
+    position:relative;
+    a{
+      position:absolute;
+      right:0;
+      top:65px;
+      display:block;
+      width:50px;
+      height:26px;
+      line-height: 26px;
+      text-align: center;
+      background: #fff;
+      color:#797979;
+      &:hover{
+        cursor:pointer;
+        color:#149ccf;
+      }
+    }
+    p{
+      line-height: 130px;
+      font-size: 26px;
+      color:#149ccf;
+      margin:0;
+      i{
+        margin-right:10px;
+      }
+    }
+  }
+  .content{
+    .info-list{
+      position:relative;
+      display:inline-block;
+      width:24%;
+      height:430px;
+      vertical-align: top;
+      margin-right:10px;
+      background: #fff;
+      overflow: hidden;
+      &:last-child{
+        margin:0;
+      }
+      &:hover{
+        cursor:pointer;
+        .detail{
+          opacity:1;
+          top:0;
+        }
+      }
+      .img{
+        width:280px;
+        height:250px;
+        img{
+          width:100%;
+          height:100%;
+          border:none;
+          padding:0;
+        }
+      }
+      .list-right{
+        padding:24px 16px 0 16px;
+        overflow: hidden;
+        p{
+          font-size: 20px;
+          color:#333;
+          margin-bottom:25px;
+          width:98%;
+          overflow: hidden;
+          text-overflow: ellipsis;
+          white-space: nowrap;
+        }
+        span{
+          font-size: 14px;
+          line-height: 20px;
+          color:#969696;
+        }
+      }
+      .detail{
+        position:absolute;
+        top:100%;
+        opacity:0;
+        transition: all .5s ease;
+        background: rgba(0,0,0,.8);
+        width:100%;
+        height:430px;
+        padding:30px 16px;
+        h4{
+          font-size: 20px;
+          color:#fff;
+          margin-bottom:25px;
+        }
+        span{
+          display:block;
+          font-size: 14px;
+          color:#fff;
+          line-height: 20px;
+          margin-bottom:10px;
+        }
+        p{
+          font-size: 14px;
+          color:#b4b4b4;
+          margin-bottom:10px;
+        }
+        a{
+          display: block;
+          width:200px;
+          height:40px;
+          line-height: 38px;
+          text-align: center;
+          margin:0 auto;
+          margin-top:30px;
+          font-size: 16px;
+          color:#fff;
+          border:1px solid #fff;
+          &:hover{
+            cursor:pointer;
+            color:#149ccf;
+            border: 1px solid #149ccf;
+          }
+        }
+      }
+    }
+  }
+}
+</style>

+ 6 - 0
components/home/index.js

@@ -0,0 +1,6 @@
+import Banner from './banner.vue'
+import Carousel from './carousel.vue'
+import News from './news.vue'
+import Garden from './garden.vue'
+
+export { Banner, Carousel, News, Garden }

+ 114 - 0
components/home/news.vue

@@ -0,0 +1,114 @@
+<template>
+  <div class="news">
+    <div class="container">
+      <div class="title">
+        <a href="/news">更多</a>
+        <p><i class="icon-trumpet"/>新闻动态</p>
+      </div>
+      <div class="content">
+        <ul class="list-inline">
+          <li class="info-list" v-for="item in list">
+            <a :href="'/news/' + item.nc_id + '?type=' + item.nc_type">
+              <img :src="item.nc_image">
+              <div class="list-right">
+                <p v-text="item.nc_title">企业为员工打造全新潼湖小镇,舒服办公环境</p>
+                <span v-text="item.nc_desc">2017年,优软科技携手碧桂园创办全新智慧生态园,发扬优软新势力,适应互联网潮流 发展.</span>
+              </div>
+            </a>
+          </li>
+        </ul>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script>
+    export default {
+      name: 'News',
+      computed: {
+        list () {
+          return this.$store.state.news.list.data.list
+        }
+      }
+    }
+</script>
+
+<style scoped type="text/scss" lang="scss">
+.news{
+  background: #fff;
+  height:470px;
+  .title{
+    position:relative;
+    a{
+      position:absolute;
+      right:0;
+      top:65px;
+      display:block;
+      width:50px;
+      height:26px;
+      line-height: 26px;
+      text-align: center;
+      background: #eee;
+      color:#797979;
+      &:hover{
+        cursor:pointer;
+        color:#149ccf;
+      }
+    }
+    p{
+      line-height: 130px;
+      font-size: 26px;
+      color:#149ccf;
+      margin:0;
+      i{
+        margin-right:10px;
+      }
+    }
+  }
+  .content{
+    ul{
+      li{
+        width:580px;
+        height:110px;
+        border:1px solid #e5e5e5;
+        padding:25px 16px;
+        margin-bottom:30px;
+        margin-right:10px;
+        &:hover{
+          cursor:pointer;
+          box-shadow: 5px 5px 13px rgba(0,0,0,.14);
+          border:none;
+        }
+        img{
+          float:left;
+          width:80px;
+          height:55px;
+          vertical-align:top;
+        }
+        .list-right{
+          margin-left:100px;
+          p{
+            width:98%;
+            font-size: 20px;
+            color:#333;
+            margin-bottom:20px;
+            overflow: hidden;
+            text-overflow:ellipsis;
+            white-space:nowrap;
+          }
+          span{
+            display:block;
+            width:100%;
+            font-size: 14px;
+            color:#969696;
+            overflow: hidden;
+            text-overflow:ellipsis;
+            white-space:nowrap;
+          }
+        }
+      }
+    }
+
+  }
+}
+</style>

+ 42 - 0
components/news/banner.vue

@@ -0,0 +1,42 @@
+<template>
+  <div class="banner">
+    <div class="container">
+      <p>新闻中心</p>
+      <span>NEWS INFORMATION</span>
+    </div>
+  </div>
+</template>
+
+<script>
+  export default {
+    name: 'BannerView'
+  }
+</script>
+
+<style scoped type="text/scss" lang="scss">
+.banner{
+  margin-top:54px;
+  margin-bottom:45px;
+  background: url(/img/news/banner.jpg)no-repeat;
+  height:430px;
+  p{
+    padding-top:170px;
+    text-align: center;
+    font-size: 48px;
+    font-weight: bold;
+    color:#fff;
+    margin-bottom:45px;
+  }
+  span{
+    display:block;
+    border:1px solid #8c9ca2;
+    width:280px;
+    height:50px;
+    line-height: 48px;
+    text-align: center;
+    margin: 0 auto;
+    color:#fff;
+    font-size: 20px;
+  }
+}
+</style>

+ 76 - 0
components/news/detail.vue

@@ -0,0 +1,76 @@
+<template>
+  <div class="detail">
+    <div class="top">
+      <p v-text="listData.NC_TITLE">1</p>
+      <span class="icon_new" v-text="listData.NC_READNUM">1</span>
+      <span v-text="formatDate(listData.NC_PUBLISHDATE, 'yyyy-MM-dd hh:mm:ss')">1</span>
+    </div>
+    <div class="content" v-html="listData.NC_CONTENT"/>
+  </div>
+</template>
+
+<script>
+  import {formatDate} from '@/utils/date.js'
+  export default {
+    name: 'DetailView',
+    computed: {
+      listData () {
+        return this.$store.state.news.detail.data.data
+      }
+    },
+    methods: {
+      // 格式化时间
+      formatDate (row) {
+        let date = new Date(row)
+        return formatDate(date, 'yyyy-MM-dd hh:mm:ss')
+      }
+    }
+  }
+</script>
+
+<style type="text/scss" lang="scss">
+.detail{
+  background: #fff;
+  .top{
+    padding:0 40px;
+    padding-top:42px;
+    height:146px;
+    border-bottom:1px solid #f1f1f1;
+    p{
+      font-size: 30px;
+      color:#1e1e1e;
+      margin-bottom:30px;
+      width:98%;
+      overflow: hidden;
+      text-overflow: ellipsis;
+      white-space: nowrap;
+    }
+    span{
+      font-size: 14px;
+      color:#a0a0a0;
+      margin-right:25px;
+      &.icon_new:before{
+        content: '';
+        display: inline-block;
+        width: 16px;
+        height: 16px;
+        margin-right: 10px;
+        vertical-align: middle;
+        background: url(/icon/new.png) no-repeat 0 2px;
+      }
+    }
+  }
+  .content{
+    padding:42px 40px;
+    line-height: 25px;
+    font-size: 14px;
+    color: #626262;
+    p{
+      font-size: 14px;
+      color: #626262;
+      text-indent: 2em;
+      margin: 32px 0;
+    }
+  }
+}
+</style>

+ 6 - 0
components/news/index.js

@@ -0,0 +1,6 @@
+import Detail from './detail'
+import Items from  './items'
+import Navs from './navs'
+import Banner from './banner'
+
+export {Detail, Navs, Items, Banner}

+ 205 - 0
components/news/items.vue

@@ -0,0 +1,205 @@
+<template>
+  <div class="news-item">
+    <div class="empty" v-if="listInfo.total == 0">无快讯信息!</div>
+    <a class="item" :href="'/news/' + item.nc_id + '?type=' + item.nc_type" v-for="item in listData">
+      <div class="date">
+        <p v-text="new Date(item.nc_publishdate).getDay()">1</p>
+        <p v-text="formatTime(item.nc_publishdate)">Jan</p>
+      </div>
+      <div class="img" v-if="item.nc_image != null">
+        <img :src="item.nc_image">
+      </div>
+      <div :class="{content_img: item.nc_image != null, content: item.nc_image == null}">
+        <h4 v-text="item.nc_title">11</h4>
+        <p v-text="item.nc_desc">11</p>
+        <span v-text="item.nc_readnum" v-if="item.nc_image != null">323</span>
+      </div>
+    </a>
+    <div class="page" v-if="listInfo.total > 10">
+      <el-pagination
+        @current-change="handleCurrentChange"
+        :current-page="page"
+        :page-size="count"
+        layout="total, prev, pager, next, jumper"
+        :total="listInfo.total"/>
+    </div>
+  </div>
+</template>
+
+<script>
+  export default {
+    name: 'ItemView',
+    data () {
+      return {
+        count: 10,
+        page: 1
+      }
+    },
+    computed: {
+      listInfo () {
+        return this.$store.state.news.list.data
+      },
+      listData () {
+        return this.listInfo.list
+      }
+    },
+    methods: {
+      handleCurrentChange(val) {
+        this.$store.dispatch('loadNewsList', {page: val, limit: this.count, type: this.step})
+      },
+      // 输出时间日期
+      formatTime (row) {
+        let count = new Date(row).getMonth()
+        switch (count) {
+          case 0 : return 'Jan'
+          case 1 : return 'Feb'
+          case 2 : return 'Mar'
+          case 3 : return 'Apr'
+          case 4 : return 'May'
+          case 5 : return 'Jun'
+          case 6 : return 'Jul'
+          case 7 : return 'Aug'
+          case 8 : return 'Sep'
+          case 9 : return 'Oct'
+          case 10 : return 'Nov'
+          case 11 : return 'Dec'
+        }
+      }
+    }
+  }
+</script>
+
+<style scoped type="text/scss" lang="scss">
+.news-item{
+  .empty{
+    padding-top:120px;
+    font-size: 30px;
+    text-align: center;
+    font-weight: bold;
+    color:#333;
+  }
+  .page{
+    padding:20px 0;
+    text-align: center;
+  }
+  .item{
+    position:relative;
+    display:block;
+    padding:35px 40px 35px 145px;
+    border-bottom:1px solid #f1f1f1;
+    &:hover{
+      .date{
+        p{
+          color:#149ccf;
+        }
+      }
+      .content{
+        h4{
+          color:#149ccf;
+        }
+      }
+      .content_img{
+        h4{
+          color:#149ccf;
+        }
+      }
+    }
+    .date{
+      position:absolute;
+      top:35px;
+      left:75px;
+      width:70px;
+      height:90px;
+      background: #f4f4f4;
+      text-align: center;
+      p{
+        font-size: 18px;
+        font-weight: bold;
+        color:#323232;
+        margin:0;
+        line-height: 45px;
+      }
+    }
+    .img{
+      display:inline-block;
+      vertical-align: top;
+      width:200px;
+      height:160px;
+      img{
+        width:200px;
+        height:160px;
+      }
+    }
+    .content_img{
+      width:520px;
+      height:160px;
+      display:inline-block;
+      vertical-align: top;
+      padding-left:30px;
+      position:relative;
+      h4{
+        font-size: 20px;
+        color:#1e1e1e;
+        width:500px;
+        overflow:hidden;
+        text-overflow: ellipsis;
+        white-space:nowrap;
+        margin-bottom:25px;
+      }
+      p{
+        font-size: 14px;
+        color:#797979;
+        line-height: 20px;
+        overflow: hidden;
+        text-overflow: ellipsis;
+        display: -webkit-box;
+        -webkit-line-clamp: 2;
+        -webkit-box-orient: vertical;
+      }
+      span{
+        position:absolute;
+        bottom:0;
+        left:25px;
+        font-size: 14px;
+        color:#797979;
+        &:before{
+          content: '';
+          display: inline-block;
+          width: 16px;
+          height: 16px;
+          margin-right: 10px;
+          vertical-align: middle;
+          background: url(/icon/new.png) no-repeat 0 2px;
+        }
+      }
+    }
+    .content{
+      width:700px;
+      display:inline-block;
+      vertical-align: top;
+      padding-left:30px;
+      position:relative;
+      height:90px;
+      h4{
+        font-size: 20px;
+        color:#1e1e1e;
+        width:700px;
+        overflow:hidden;
+        text-overflow: ellipsis;
+        white-space:nowrap;
+        margin-bottom:25px;
+      }
+      p{
+        font-size: 14px;
+        color:#797979;
+        line-height: 20px;
+        overflow: hidden;
+        text-overflow: ellipsis;
+        display: -webkit-box;
+        -webkit-line-clamp: 2;
+        -webkit-box-orient: vertical;
+      }
+    }
+  }
+}
+</style>

+ 102 - 0
components/news/navs.vue

@@ -0,0 +1,102 @@
+<template>
+  <div class="list-info">
+    <div class="title">
+      <h4>园区快讯</h4>
+    </div>
+    <div class="list">
+      <ul class="list-unstyled">
+        <li v-for="(item, key) in listData" @mouseenter="item.activeImg = true" @mouseleave="item.activeImg = false" :class="{active: item.active}" @click="setActive(key)">
+          <img :src="item.activeImg || item.active ? item.nt_activeicon : item.nt_icon">
+          <span v-text="item.nt_name">12</span>
+        </li>
+      </ul>
+    </div>
+  </div>
+</template>
+
+<script>
+  export default {
+    name: 'NavsView',
+    data () {
+      return {
+        listData: [],
+        page: 1,
+        limit: 10
+      }
+    },
+    created () {
+      if (!this.$store.state.news.newType.data.list) return  false
+      let data = JSON.parse(JSON.stringify(this.$store.state.news.newType.data.list))
+      if (this.$route.query.type) {
+        for (let i = 0; i < data.length; i++) {
+          this.$set(data[i], 'active', data[i].nt_name === this.$route.query.type)
+          this.$set(data[i], 'activeImg', data[i].nt_name === this.$route.query.type)
+        }
+      } else {
+        for (let i = 0; i < data.length; i++) {
+          this.$set(data[i], 'active', i === 0)
+          this.$set(data[i], 'activeImg', i === 0)
+        }
+      }
+      this.$store.dispatch('loadNewsList', {page: this.page, limit: this.limit, type: this.$route.query.type ? this.$route.query.type : data[0].nt_name})
+      this.listData = data
+    },
+    methods: {
+      setActive(type) {
+        for (let i = 0; i < this.listData.length; i++) {
+          if (type === i) {
+            this.listData[i].active = true
+            this.$store.dispatch('loadNewsList', {page: this.page, limit: this.limit, type: this.listData[i].nt_name})
+            this.$emit('loadStep', this.listData[i].nt_name)
+            this.$router.push('/news' + (this.$route.query.type ? '?type=' + this.listData[i].nt_name : ''))
+          } else {
+            this.listData[i].active = false
+            this.listData[i].activeImg = false
+          }
+        }
+      }
+    }
+  }
+</script>
+
+<style scoped type="text/scss" lang="scss">
+.list-info{
+  background: #fff;
+  .title{
+    padding-left:25px;
+    border-bottom:2px solid #8d8d8d;
+    h4{
+      line-height: 45px;
+      color:#8d8d8d;
+      font-size: 16px;
+    }
+  }
+  .list{
+    padding:10px 0;
+    ul{
+      li{
+        text-align: center;
+        height:60px;
+        line-height: 60px;
+        &.active, &:hover{
+          background: #f8f8f8;
+          cursor:pointer;
+          span{
+            color:#46a9d4;
+          }
+        }
+        img{
+          margin-right:15px;
+          width:20px;
+          height:20px;
+          vertical-align: middle;
+        }
+        span{
+          font-size: 18px;
+          color:#646464;
+        }
+      }
+    }
+  }
+}
+</style>

+ 27 - 0
components/park/banner.vue

@@ -0,0 +1,27 @@
+<template>
+  <div class="banner">
+    <div class="container">
+      <p>园区介绍</p>
+    </div>
+  </div>
+</template>
+
+<script>
+  export default {
+    name: 'BannerView'
+  }
+</script>
+
+<style scoped type="text/scss" lang="scss">
+.banner{
+  margin-top:54px;
+  background: url(/img/banner/9.png)no-repeat;
+  height:650px;
+  p{
+    padding-top:294px;
+    text-align: center;
+    font-size: 48px;
+    color:#fff;
+  }
+}
+</style>

+ 4 - 0
components/park/index.js

@@ -0,0 +1,4 @@
+import Banner from './banner.vue'
+import Info from './info.vue'
+
+export {Banner, Info}

+ 63 - 0
components/park/info.vue

@@ -0,0 +1,63 @@
+<template>
+  <div class="info">
+    <div class="container">
+      <div class="top">
+        <span>碧桂园创新小镇所在的惠州市潼湖生态智慧区,作为广东重要的高新技术集聚区,地处粤港澳大湾区的重要节点,深、惠、莞交界的中心位置,距离深圳市中心60公里,距离惠州市中心20公里,区位优势明显。作为广东省重大区域发展平台、惠州创新驱动发展的创新核,潼湖生态智慧区已启动了创新与总部经济区、国际合作产业园和创新园等起步区建设,还与省科技厅合作共建“广东省科技体制改革创新示范区”。</span>
+      </div>
+      <div class="content">
+        <img src="/img/park/1.png">
+        <p>碧桂园创新小镇定位为世界级物联网和智能控制产业基地,以“城市编织”为规划理念,沿综合科技发展带串联三大特色科技产业组团。创新小镇将会结合潼湖生态湿地资源,将生态系统、产业聚集区、生活休闲区、商业中心区及公共配套区等有机融合,有希望成为在深圳周边率先实现功能一体化、交通一体化、配套一体化、服务一体化的世界级创新产业集聚地。而创新小镇将借力潼湖良好的区位优势,对接粤港澳大湾区的世界级湾区经济的发展机遇,承接粤港澳的战略新兴产业转移,成为推动粤港澳大湾区建设的典范和珠三角经济飞速发展新的增长点。</p>
+        <p>潼湖科技小镇借助合作伙伴优软科技在移动互联、大数据及智慧城市等方面的领先优势,形成以物联网、移动互联及大数据为核心主导产业,智能控制、智能制造及科技服务为配套产业的发展平台</p>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script>
+  export default {
+    name: 'InfoView'
+  }
+</script>
+
+<style scoped type="text/scss" lang="scss">
+.info{
+  position:relative;
+  background: #f8f8f8;
+  .container {
+    width:910px;
+    margin:0 auto;
+    .top{
+      position:absolute;
+      top:-200px;
+      width:910px;
+      height:260px;
+      background: #122931;
+      padding: 85px 65px 0 65px;
+      span{
+        font-size: 14px;
+        line-height:25px;
+        color:#fff;
+      }
+    }
+    .content{
+      margin-top:60px;
+      padding:70px;
+      background: #ffffff;
+      img{
+        display:block;
+        vertical-align: top;
+        width:695px;
+        height:390px;
+        margin:0 auto;
+        margin-bottom:70px;
+      }
+      p{
+        font-size: 14px;
+        color:#122931;
+        line-height: 25px;
+        margin-bottom:30px;
+      }
+    }
+  }
+}
+</style>

+ 141 - 0
components/service/ServiceList.vue

@@ -0,0 +1,141 @@
+<template>
+  <div class="service-list">
+    <div class="container">
+      <div class="list-title">
+        <p>园区服务</p>
+      </div>
+      <div class="list-link">
+        <ul class="list-inline">
+          <li class="active">全部</li>
+          <li v-for="item in serviceData" class="active">{{ item.st_name }}</li>
+        </ul>
+      </div>
+      <div class="list-bottom" v-for="(item) in serviceData">
+        <div class="left_title">
+          <img :src="item.st_icon">
+          <p v-text="item.st_name"/>
+        </div>
+        <ul class="list-inline" >
+          <li v-for="(childItem) in item.serves" @click="jump(childItem.sv_id)">
+            <img :src="childItem.sv_logourl.platform">
+            <p>{{ childItem.sv_name }}</p>
+          </li>
+        </ul>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script>
+    export default {
+      name: 'ServiceList',
+      computed: {
+        serviceData () {
+          return this.$store.state.serviceList.serviceData.data.configs
+        }
+      },
+      methods: {
+        jump (type) {
+          if (!this.$store.state.option.user.data.name) {
+            this.$message({
+              type: 'error',
+              message: '亲,请先登录!'
+            })
+          } else {
+            this.$router.push('/repairs/' + type)
+          }
+        }
+      }
+    }
+</script>
+
+<style scoped type="text/scss" lang="scss">
+  .service-list{
+    padding-top:50px;
+    padding-bottom:165px;
+    .list-title {
+      text-align: center;
+      p{
+        margin-bottom:40px;
+        font-size: 28px;
+        color:#000;
+      }
+    }
+    .list-link{
+      margin:0 auto;
+      margin-bottom:80px;
+      text-align: center;
+      ul{
+        margin:0;
+        li {
+          padding: 0 15px;
+          font-size: 14px;
+          color: #333;
+          text-align: center;
+          border-right:1px solid #bfbfbf;
+          &:last-child{
+            border:0;
+          }
+          &:hover, &.active{
+            color:#149ccf;
+            cursor:pointer;
+          }
+        }
+      }
+    }
+    .list-bottom{
+      margin-bottom:45px;
+      .left_title{
+        float:left;
+        width:130px;
+        height:240px;
+        position:relative;
+        img{
+          position:absolute;
+          top:0 ;
+          left:0;
+          width: 100%;
+          height:100%;
+          z-index:-100;
+        }
+        p{
+          padding-top:24px;
+          font-size: 22px;
+          color:#fff;
+          text-align: center;
+        }
+      }
+      ul{
+        margin-left:130px;
+        height:240px;
+        background: #fff;
+        li{
+          width: 150px;
+          height: 120px;
+          text-align: center;
+          line-height: 40px;
+          padding-top: 15px;
+          &:hover{
+            cursor:pointer;
+            transform:scale(1.1);
+            > p{
+              color:#149ccf;
+            }
+          }
+          img{
+            vertical-align: top;
+            text-align: center;
+            width:40%;
+            height:40%;
+          }
+          > p{
+            font-size: 16px;
+            color:#464646;
+            width:100%;
+            margin:0;
+          }
+        }
+      }
+    }
+  }
+</style>

+ 23 - 0
components/service/banner.vue

@@ -0,0 +1,23 @@
+<template>
+  <div class="banner"/>
+</template>
+
+<script>
+  export default {
+    name: 'BannerView'
+  }
+</script>
+
+<style scoped type="text/scss" lang="scss">
+.banner{
+  margin-top:54px;
+  background: url(/img/banner/2.png)no-repeat center center;
+  height:450px;
+  p{
+    padding-top:294px;
+    text-align: center;
+    font-size: 48px;
+    color:#fff;
+  }
+}
+</style>

+ 3 - 0
components/service/index.js

@@ -0,0 +1,3 @@
+import ServiceList from './ServiceList.vue'
+import Banner from './banner'
+export { ServiceList, Banner }

+ 45 - 0
layouts/error.vue

@@ -0,0 +1,45 @@
+<template>
+  <div class="error">
+    <div class="section">
+      <div class="container">
+        <div class="btn-click">
+          <a href="/"><i class="fa fa-home" style="margin-right:5px;"/>返回首页</a>
+          <a href="javascript:history.go(-1)"><i class="fa fa-reply" style="margin-right:5px;"/>返回上一页</a>
+        </div>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script>
+  export default {
+    props: ['error']
+  }
+</script>
+
+<style scoped lang="scss">
+  .section{
+    background: #ebfdff url('/404.png')no-repeat center center;
+    height:900px;
+    position:relative;
+  }
+  .section .btn-click{
+    position:absolute;
+    top:54%;
+    left:50%;
+    margin-left:-150px;
+  }
+  .section .btn-click a{
+    display:inline-block;
+    width:130px;
+    height:33px;
+    font-size: 16px;
+    line-height: 33px;
+    color:#fff;
+    background: #f87c29;
+    text-align: center;
+    margin:0 10px;
+    border-radius: 2px;
+    text-decoration: none;
+  }
+</style>

+ 35 - 0
layouts/town.vue

@@ -0,0 +1,35 @@
+<template>
+  <div class="main">
+    <header-view/>
+    <nuxt/>
+    <footer-view/>
+  </div>
+</template>
+
+<script>
+  import { Header, Footer } from '@/components/default'
+  export default {
+    name: 'Town',
+    components: {
+      HeaderView: Header,
+      FooterView: Footer
+    }
+  }
+</script>
+
+<style>
+  html {
+    font-family: '微软雅黑', Arial, sans-serif;
+    font-size: 14px;
+    box-sizing: border-box;
+  }
+
+  *, *:before, *:after {
+    box-sizing: border-box;
+    margin: 0;
+  }
+  .container{
+    padding:0;
+    width:1180px;
+  }
+</style>

BIN
linux_musl-x64-57_binding.node


+ 5 - 0
middleware/authenticated.js

@@ -0,0 +1,5 @@
+export default function ({store, redirect}) {
+  if (!store.state.option.user.logged) {
+    return redirect('/')
+  }
+}

+ 79 - 0
nuxt.config.js

@@ -0,0 +1,79 @@
+const isProdMode = Object.is(process.env.NODE_ENV, 'production')
+const baseUrl = process.env.BASE_URL || (isProdMode ? 'https://city-service.ubtob.com' : 'http://10.1.51.81:8687/')
+const cityDomain = process.env.CITY_DOMAIN || (isProdMode ? 'thxz' : 'thxz')
+
+module.exports = {
+  head: {
+    title: '产城园区',
+    meta: [
+      { charset: 'utf-8' },
+      { 'http-equiv': 'X-UA-Compatible', content: 'IE=edge,chrome=1' },
+      { name: 'render', content: 'webkit' },
+      { name: 'viewport', content: 'width=device-width, initial-scale=1' },
+      { hid: 'description', name: 'description', content: '服务一体化' }
+    ],
+    link: [
+      { rel: 'icon', type: 'image/x-icon', href: '/U.png' }
+    ]
+  },
+  /*
+  ** Customize the progress-bar color
+  */
+  loading: { color: '#3B8070' },
+  /*
+  ** Build configuration
+  */
+  build: {
+    /*
+    ** Run ESLINT on save
+    */
+    extend(config, { isDev }) {
+      if (isDev && process.client) {
+        config.module.rules.push({
+          enforce: "pre",
+          test: /\.(js|vue)$/,
+          loader: "eslint-loader",
+          exclude: /(node_modules)/
+        })
+      }
+    },
+    vendor: [
+      'axios',
+      'element-ui',
+      'vue-jsonp',
+      'vue-clipboard2'
+    ]
+  },
+  css: [{src: '~assets/scss/app.scss', lang: 'scss'}],
+  dev: !isProdMode,
+  env: {
+    baseUrl,
+    cityDomain
+  },
+  plugins: [{
+    src: '~plugins/axios.js'
+  }, {
+    src: '~plugins/city-service.js'
+  }, {
+    src: '~plugins/element-ui.js',
+  },{
+    src: "~plugins/vue-jsonp.js",
+    ssr: false
+  }, {
+    src: "~plugins/vue-clipboard2.js",
+    ssr: false
+  }],
+  /* TODO 暂时代理到商城测试版,之后再做出调整 */
+  proxyTable: [
+    '/search/**',
+    '/user/**',
+    '/login/**',
+    '/register/**',
+    '/logout/**',
+    '/city/**',
+    '/city/thxz/api/**',
+    '/api/**',
+    '/zuul/**',
+    '/ERP/**',
+    '/sync/**']
+}

+ 47 - 0
package.json

@@ -0,0 +1,47 @@
+{
+  "name": "usoft-town",
+  "version": "1.0.0",
+  "description": "Nuxt.js project",
+  "author": "wangcz <549517968@qq.com>",
+  "private": true,
+  "scripts": {
+    "dev": "node server.js",
+    "dev-build": "nuxt build",
+    "dev-start": "node server.js",
+    "dev-generate": "nuxt generate",
+    "prod": "cross-env NODE_ENV=production nuxt",
+    "build": "cross-env NODE_ENV=production nuxt build",
+    "start": "cross-env NODE_ENV=production node server.js",
+    "generate": "cross-env NODE_ENV=production nuxt generate",
+    "lint": "eslint --ext .js,.vue --ignore-path .gitignore .",
+    "lintfix": "eslint --fix --ext .js,.vue --ignore-path .gitignore .",
+    "precommit": "npm run lint"
+  },
+  "dependencies": {
+    "axios": "^0.18.0",
+    "cookiejar": "^2.1.1",
+    "element-ui": "^2.2.1",
+    "express": "^4.16.2",
+    "http-proxy-middleware": "^0.17.4",
+    "nuxt": "^1.4.0",
+    "swiper": "^4.2.0",
+    "vue-clipboard2": "^0.1.0",
+    "vue-jsonp": "^0.1.7"
+  },
+  "devDependencies": {
+    "babel-eslint": "^8.2.2",
+    "babel-preset-env": "^1.6.1",
+    "cross-env": "^5.1.3",
+    "eslint": "^4.18.2",
+    "eslint-config-prettier": "^2.9.0",
+    "eslint-friendly-formatter": "^3.0.0",
+    "eslint-loader": "^1.9.0",
+    "eslint-plugin-html": "^4.0.2",
+    "eslint-plugin-prettier": "^2.6.0",
+    "eslint-plugin-vue": "^4.3.0",
+    "node-sass": "^4.9.0",
+    "prettier": "^1.11.1",
+    "rebuild-node-sass": "^1.1.0",
+    "sass-loader": "^6.0.7"
+  }
+}

+ 139 - 0
pages/about/index.vue

@@ -0,0 +1,139 @@
+<template>
+  <div class="about">
+    <div class="container">
+      <div class="address">
+        <h4>联系方式</h4>
+        <p>contact</p>
+        <div class="tel">
+          <ul class="list-inline">
+            <li>
+              <h4>联系方式</h4>
+              <p>400 - 930 - 3066</p>
+              <p>bgyicdd@countrygarden.com.cn</p>
+              <a href="">申 请</a>
+            </li>
+            <li>
+              <h4>预约参观</h4>
+              <img src="/qrcode/code.png">
+            </li>
+          </ul>
+        </div>
+      </div>
+      <div class="map">
+        <img src="/map.png">
+        <div class="map-info">
+          <ul class="list-unstyled">
+            <li>
+              <p>A 潼湖科技小镇</p>
+              <p>地址:惠州市惠城区沥林镇英光村</p>
+            </li>
+            <li>
+              <p>B 潼湖科技小镇 .产业发展中心 </p>
+              <p>地址:惠州市惠城区沥林镇英光村潼湖科技小镇</p>
+            </li>
+            <li>
+              <p>C 潼湖科技小镇 .深圳展厅</p>
+              <p>地址:深圳市南山区科技园(中区)科技路一号桑达科技大厦13楼</p>
+            </li>
+          </ul>
+        </div>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script>
+    export default {
+      name: 'About',
+      layout: 'town'
+    }
+</script>
+
+<style type="text/scss" lang="scss" scoped>
+  .about{
+    margin-top:54px;
+    padding-bottom:150px;
+    .address{
+      padding:48px 42px;
+      margin-bottom:140px;
+      h4{
+        font-size: 48px;
+        color:#1f5a6f;
+        margin:0;
+        margin-bottom:10px;
+      }
+      p{
+        padding-left:86px;
+        font-size: 30px;
+        color:#b3cbd3;
+        margin-bottom:40px;
+      }
+      ul{
+        li{
+          vertical-align: top;
+          margin:0 50px;
+          border-left:6px solid #122931;
+          width:440px;
+          height:228px;
+          text-align: center;
+          background: #e3e7e9;
+          padding-top:48px;
+          h4{
+            font-size: 24px;
+            margin:0;
+            color:#122931;
+            margin-bottom:30px;
+          }
+          p{
+            font-size: 14px;
+            color:#777;
+            margin-bottom:10px;
+            padding:0;
+          }
+          a{
+            display:block;
+            margin:0 auto;
+            margin-top:20px;
+            width:120px;
+            height:36px;
+            background: #217694;
+            text-align: center;
+            line-height: 36px;
+            color:#fff;
+            &:hover{
+              cursor:pointer;
+            }
+          }
+          img{
+            width:100px;
+            height:100px;
+          }
+        }
+      }
+    }
+    .map{
+      position:relative;
+      .map-info{
+        position:absolute;
+        right:0;
+        top:50%;
+        width:350px;
+        height:380px;
+        background: #1f5a6f;
+        margin-top:-190px;
+        padding-top:70px;
+        ul{
+          li{
+            padding: 10px 20px;
+            p{
+              font-size: 14px;
+              color:#e5edf0;
+              margin-bottom:10px;
+              line-height: 20px;
+            }
+          }
+        }
+      }
+    }
+  }
+</style>

+ 32 - 0
pages/index.vue

@@ -0,0 +1,32 @@
+<template>
+  <div class="index">
+    <banner/>
+    <news/>
+    <garden/>
+  </div>
+</template>
+
+<script>
+  import { Banner, News, Garden } from '@/components/home'
+  export default {
+    name: 'Index',
+    layout: 'town',
+    fetch ({ store }) {
+      return Promise.all([
+        store.dispatch('loadCarouselInfo', { client_type: 'cc', cityId: store.state.option.user.data.currentCity ? store.state.option.user.data.currentCity.id : null }),
+        store.dispatch('loadNewsList', { limit: 4, page: 1 }),
+        store.dispatch('loadGardenList', { limit: 4, page: 1 })
+      ])
+    },
+    components: {
+      News,
+      Banner,
+      Garden
+    },
+    computed: {
+      bannerData () {
+        return this.$store.state.carouselInfo.infoData.data.index
+      }
+    }
+  }
+</script>

+ 53 - 0
pages/news/_id.vue

@@ -0,0 +1,53 @@
+<template>
+  <div class="news">
+    <banner/>
+    <div class="container">
+      <div class="news-navs">
+        <navs/>
+      </div>
+      <div class="news-content">
+        <detail/>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script>
+  import {Navs, Detail, Banner} from '@/components/news'
+  export default {
+    name: 'NewsDetail',
+    layout: 'town',
+    fetch ({store, route}) {
+      return Promise.all([
+        store.dispatch('loadNewsDetail', {id: route.params.id})
+      ])
+    },
+    components: {
+      Navs,
+      Detail,
+      Banner
+    }
+  }
+</script>
+
+<style type="text/scss" lang="scss">
+  .news{
+    background: #f4f4f4;
+    padding-bottom:60px;
+    .news-navs{
+      float:left;
+      width:240px;
+      min-height:280px;
+      background: #fff;
+    }
+    .news-content{
+      background: #fff;
+      margin-left:260px;
+      min-height:300px;
+      img{
+        width:90%;
+        height:100%;
+      }
+    }
+  }
+</style>

+ 45 - 0
pages/news/index.vue

@@ -0,0 +1,45 @@
+<template>
+  <div class="news">
+    <banner/>
+    <div class="container">
+      <div class="news-navs">
+        <navs/>
+      </div>
+      <div class="news-content">
+        <items/>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script>
+  import {Navs, Items, Banner} from '@/components/news'
+  export default {
+    name: 'News',
+    layout: 'town',
+    components: {
+      Navs,
+      Items,
+      Banner
+    }
+  }
+</script>
+
+<style scoped type="text/scss" lang="scss">
+.news{
+  background: #f4f4f4;
+  padding-bottom:60px;
+  .news-navs{
+    float:left;
+    width:240px;
+    min-height:280px;
+    background: #fff;
+  }
+  .news-content{
+    background: #fff;
+    margin-left:260px;
+    min-height:300px;
+    padding: 20px 0;
+  }
+}
+</style>

+ 18 - 0
pages/park/index.vue

@@ -0,0 +1,18 @@
+<template>
+  <div class="park">
+    <banner/>
+    <info/>
+  </div>
+</template>
+
+<script>
+  import {Banner, Info} from '@/components/park'
+  export default {
+    name: 'Park',
+    layout: 'town',
+    components: {
+      Banner,
+      Info
+    }
+  }
+</script>

+ 236 - 0
pages/repairs/_id/historicalInfo/_fdid.vue

@@ -0,0 +1,236 @@
+<template>
+  <div class="order-info">
+    <div class="container">
+      <div class="order-title">
+        <div class="title-left">
+          <span>园区服务</span> &gt;
+          <span>历史服务信息</span> &gt;
+          <span>订单号:{{ formAttr.rp_code }}</span>
+        </div>
+        <div class="title-right">
+          <a :href="'/repairs/' + $route.params.id + '/historicalInfo'"><i class="fa fa-history"/>历史服务申请</a>
+        </div>
+      </div>
+      <div class="order-flow">
+        <ul class="list-inline">
+          <li v-for="item in processList">
+            <i class="fa fa-file-text-o" v-if="item.time"/>
+            <span v-if="item.time">{{ item.status }}</span>
+            <span v-if="item.time">{{ item.time }}</span>
+          </li>
+        </ul>
+      </div>
+      <div class="order-form">
+        <form class="form-horizontal" v-for="item in formData.formconfigs">
+          <div class="form-group" v-if="item.FD_TYPE === 'SS'">
+            <div class="col-xs-2 input-label">{{ item.FD_CAPTION }}:</div>
+            <div class="col-xs-10" >
+              <input type="text" class="form-control" :placeholder="formAttr[item.FD_FIELD]" disabled>
+            </div>
+          </div>
+
+          <div class="form-group" v-if="item.FD_TYPE === 'CBG'">
+            <div class="col-xs-2 input-label">{{ item.FD_CAPTION }}:</div>
+            <div class="col-xs-10">
+              <label class="checkbox-inline" v-for="attr in item.FD_LOGICTYPE.split(';')">
+                <input type="checkbox" disabled :value="attr" :name="item.FD_CAPTION" :checked="formAttr[item.FD_FIELD] ? formAttr[item.FD_FIELD].search(attr)>=0 : false">{{ attr }}
+              </label>
+            </div>
+          </div>
+
+          <div class="form-group" v-if="item.FD_TYPE === 'D'">
+            <div class="col-xs-2 input-label">{{ item.FD_CAPTION }}:</div>
+            <div class="col-xs-10" >
+              <el-date-picker
+                type="datetime"
+                readonly
+                :placeholder="formAttr[item.FD_FIELD]"
+                value-format="yyyy-MM-dd HH-mm-ss"/>
+            </div>
+          </div>
+
+          <div class="form-group" v-if="item.FD_TYPE === 'FF'">
+            <div class="col-xs-2 input-label">{{ item.FD_CAPTION }}:</div>
+            <div class="col-xs-10" style="padding-top:20px;">
+              <div class="file-box">+
+                <!--<img src="" style="width:120px; height:120px;">-->
+              </div>
+            <!--<div class="file-title">-->
+              <!--<p>上传文档说明: </p>-->
+              <!--<span>为方便物业维修师傅上门服务,您可以在此上传需要维修的图片, 文件大小不超过3M</span>-->
+            <!--</div>-->
+            </div>
+          </div>
+
+          <div class="form-group" v-if="item.FD_TYPE === 'RG'">
+            <div class="col-xs-2 input-label">{{ item.FD_CAPTION }}:</div>
+            <div class="col-xs-10">
+              <label class="radio-inline" v-for="attr in item.FD_LOGICTYPE.split(';')">
+                <input type="radio" disabled name="item.FD_CAPTION" :value="attr" v-model="formAttr[item.FD_FIELD]" :checked="attr===formAttr[item.FD_FIELD]">{{ attr }}
+              </label>
+            </div>
+          </div>
+        </form>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script>
+    export default {
+      name: 'HistoricalInfoId',
+      layout: 'town',
+      data () {
+        return {
+//          order_id: this.route.params.fdid
+        }
+      },
+      fetch ({ store, route }) {
+        return Promise.all([
+          store.dispatch('loadFormData', { serve_id: route.params.id, id: route.params.fdid, client_type: 'cc', cityId: store.state.option.user.data.currentCity ? store.state.option.user.data.currentCity.id : null }),
+          store.dispatch('loadServiceProcess', { serve_id: route.params.id, id: route.params.fdid, client_type: 'cc', cityId: store.state.option.user.data.currentCity ? store.state.option.user.data.currentCity.id : null })
+        ])
+      },
+      computed: {
+        formData () {
+          return this.$store.state.formConfig.formData.data.datas
+        },
+        formAttr () {
+          return this.formData.formdata[0]
+        },
+        processList () {
+          return this.$store.state.serviceProcess.processInfo.data.process
+        }
+      }
+    }
+</script>
+
+<style scoped>
+.order-info{
+  padding-top:90px;
+  padding-bottom:40px;
+  color:#333;
+  background: #fff;
+}
+  .container{
+    width:1180px;
+    padding:0 10px;
+  }
+  .order-info .order-title{
+    width:100%;
+    display:inline-flex;
+    justify-content:space-between;
+  }
+  .order-info .order-title .title-left span{
+    margin:0 2px;
+  }
+  .order-info .order-title .title-left span:last-child{
+    color:#d82128;
+  }
+  .order-info .order-title .title-right a{
+    color:#333;
+  }
+  .order-info .order-title .title-right a i{
+    color:#5280e3;
+    margin-right:10px;
+  }
+  .order-info .order-title .title-right a:hover{
+    cursor:pointer;
+    color:#d82128;
+  }
+  .order-info .order-flow{
+    padding:55px 10px;
+  }
+  .order-info .order-flow .list-inline{
+    display: inline-flex;
+    justify-content: space-between;
+    width:100%;
+
+  }
+  .order-info .order-flow .list-inline li{
+    width:80px;
+    height:160px;
+    text-align: center;
+  }
+  .order-info .order-flow .list-inline li i{
+    display: block;
+    width:80px;
+    height:80px;
+    border-radius: 50%;
+    font-size: 40px;
+    line-height: 80px;
+    color:#fff;
+    margin-bottom:5px;
+  }
+  .order-info .order-flow .list-inline li:nth-child(1) i{
+    background: #62cde0;
+  }
+  .order-info .order-flow .list-inline li:nth-child(2) i{
+    background: #62afe0;
+  }
+  .order-info .order-flow .list-inline li:nth-child(3) i{
+    background: #6289e0;
+  }
+  .order-info .order-flow .list-inline li:nth-child(4) i{
+    background: #8662e0;
+  }
+  .order-info .order-flow .list-inline li:nth-child(5) i{
+    background: #c162e0;
+  }
+  .order-info .order-flow .list-inline li:nth-child(6) i{
+    background: #e062a3;
+  }
+  .order-info .order-flow .list-inline li span{
+    display:block;
+    font-size: 12px;
+    line-height: 25px;
+  }
+.order-info .order-form{
+  border:1px solid #e6e6e6;
+  margin-bottom:5px;
+  padding:30px 50px 0 30px;
+  min-height:200px;
+}
+.order-info .order-form .input-label{
+  line-height: 34px;
+  font-size: 14px;
+  color:#666;
+  text-align: right;
+}
+.order-info .order-form .checkbox-inline{
+  margin-right:10px;
+}
+.order-info .order-form .radio-inline{
+  margin-right:10px;
+}
+.order-info .order-form .file-box
+{
+  display: inline-block;
+  position: relative;
+  width: 120px;
+  height: 120px;
+  line-height: 100px;
+  text-align: center;
+  cursor: pointer;
+  overflow: hidden;
+  z-index: 1;
+  font-size: 120px;
+  border:1px solid #cbcbcb;
+  border-radius:5px;
+  color:#cbcbcb;
+}
+.order-info .order-form .file-box input
+{
+  position: absolute;
+  width: 120px;
+  height: 120px;
+  opacity: 0;
+  filter: "alpha(opacity=0)";
+  filter: alpha(opacity=0);
+  -moz-opacity: 0;
+  left: 0px;
+  top: 0px;
+  cursor: pointer;
+  z-index: 2;
+}
+</style>

+ 129 - 0
pages/repairs/_id/historicalInfo/index.vue

@@ -0,0 +1,129 @@
+<template>
+  <div class="historical-info">
+    <div class="container">
+      <div class="historical-top">
+        <p>历史服务申请</p>
+        <div class="top-list">
+          <div class="list-left">
+            <span>全部</span>
+          </div>
+          <div class="list-right">
+            <span>共&nbsp;<b>{{ searchList ? searchList.listdata.length : '0' }}</b>&nbsp;条</span>
+            <div class="nav-search">
+              <input type="text">
+              <i class="fa fa-search"/>
+            </div>
+          </div>
+        </div>
+      </div>
+      <table class="table table-hover">
+        <thead class="text-center">
+          <tr style="background: #efefef;">
+            <th class="text-center" v-for="list in searchList.columns">{{ list.caption }}</th>
+          </tr>
+        </thead>
+        <tbody class="text-center" >
+          <tr v-for="(item, index) in searchList.listdata" @click="onclick(index)">
+            <td v-for="(sun, num) in searchList.columns">{{ item[searchList.columns[num].dataIndex] }}</td>
+          </tr>
+        </tbody>
+      </table>
+    </div>
+  </div>
+</template>
+
+<script>
+    export default {
+      name: 'HistoricalInfo',
+      layout: 'town',
+      fetch ({ store, route }) {
+        return Promise.all([
+          store.dispatch('searchServiceList', { serve_id: route.params.id, page: 1, pageSize: 20, _self: true, client_type: 'cc', cityId: store.state.option.user.data.currentCity ? store.state.option.user.data.currentCity.id : null })
+        ])
+      },
+      data () {
+        return {
+          page: 1,
+          pageSize: 20
+        }
+      },
+      computed: {
+        searchList () {
+          return this.$store.state.searchList.listData.data
+        }
+      },
+      methods: {
+        onclick (index) {
+          let _self = this
+          _self.$router.push('/repairs/' + _self.$route.params.id + '/historicalInfo/' + _self.searchList.listdata[index].rp_id)
+        }
+      }
+    }
+</script>
+
+<style scoped>
+.historical-info{
+  margin-top:54px;
+  border-bottom:8px solid #d5d5d5;
+  color:#333;
+}
+.historical-info .container{width:1180px;}
+.historical-info .historical-top{
+  padding-top:40px;
+  margin-bottom:12px;
+}
+.historical-info .historical-top p{
+  padding-left:10px;
+  font-size: 24px;
+  color:#333;
+  margin-bottom:25px;
+}
+.historical-info .historical-top .top-list{
+  display:inline-flex;
+  width:100%;
+  justify-content:space-between;
+}
+.historical-info .historical-top .top-list .list-left span{
+  display:inline-block;
+  height:40px;
+  line-height:40px;
+  margin:0 14px;
+  border-bottom:5px solid transparent;
+}
+.historical-info .historical-top .top-list .list-left span:hover{
+  color:#d82128;
+  border-bottom:5px solid #d82128;
+  cursor:pointer;
+}
+.historical-info .historical-top .top-list .list-right{
+  line-height: 40px;
+}
+.historical-info .historical-top .top-list .list-right span{
+  margin-right:20px;
+}
+.historical-info .historical-top .top-list .list-right span b{
+  color:#d82128;
+}
+.historical-info .historical-top .top-list .list-right .nav-search{
+  display:inline-block;
+  position:relative;
+  margin-right:20px;
+  padding-right:20px;
+}
+.historical-info .historical-top .top-list .list-right .nav-search i{
+  position:absolute;
+  font-weight: bold;
+  top:12px ;
+  right:25px;
+  color:#9e9e9e;
+}
+.historical-info .historical-top .top-list .list-right .nav-search input{
+  border-right:1px solid #ddd;
+  border-radius: 10px;
+  width:112px;
+  height:24px;
+  line-height: 22px;
+  font-size: 14px;
+  padding:0 20px 0 5px ;
+}
+</style>

+ 406 - 0
pages/repairs/_id/index.vue

@@ -0,0 +1,406 @@
+<template>
+  <div class="repairs">
+    <div class="container">
+      <div class="repairs-title">
+        <div class="title-left">
+          <p>服务说明:</p>
+          <span>{{ titleData.servedesc }}</span>
+        </div>
+        <div class="title-right">
+          <a :href="'/repairs/' + $route.params.id + '/historicalInfo'"><i class="fa fa-history"/>历史服务申请</a>
+        </div>
+      </div>
+      <div class="repairs-flow">
+        <ul class="list-inline">
+          <li><span>01 发起申请</span></li>
+          <li><i class="fa fa-long-arrow-right"/><span>02 受理派工</span></li>
+          <li><i class="fa fa-long-arrow-right"/><span>03 服务预约</span></li>
+          <li><i class="fa fa-long-arrow-right"/><span>04 上门服务</span></li>
+          <li><i class="fa fa-long-arrow-right"/><span>05 结果反馈</span></li>
+          <li><i class="fa fa-long-arrow-right"/><span>06 客户评价</span></li>
+        </ul>
+      </div>
+      <div class="repairs-form">
+        <form class="form-horizontal" v-for="(item, index) in formData.formdetail">
+          <div class="form-group" v-if="item.fd_type === 'SS'">
+            <div class="col-xs-2 input-label">{{ item.fd_caption }}:</div>
+            <div class="col-xs-10" >
+              <input type="text" class="form-control" v-model="modelData[index]" :name="item.fd_field" :required="item.fd_allowblank==='f'">
+            </div>
+          </div>
+
+          <div class="form-group" v-if="item.fd_type === 'CBG'">
+            <div class="col-xs-2 input-label">{{ item.fd_caption }}:</div>
+            <div class="col-xs-10" >
+              <label class="checkbox-inline" v-for="(list, k) in item.fd_logictype.split(';')">
+                <input type="checkbox"
+                       :name="item.fd_id"
+                       :value="list"
+                       :checked="lists[k]"
+                       @change="handleInput(index, item.fd_logictype.split(';').length, k)">{{ list }}
+              </label>
+            </div>
+          </div>
+
+          <div class="form-group" v-if="item.fd_type === 'D'">
+            <div class="col-xs-2 input-label">{{ item.fd_caption }}:</div>
+            <div class="col-xs-10">
+              <el-date-picker
+                v-model="modelData[index]"
+                type="datetime"
+                format="yyyy-MM-dd HH:mm:ss"
+                value-format="yyyy-MM-dd HH:mm:ss"
+                :picker-options="pickerDate"
+                default-time="item.fd_defaultvalue"/>
+            </div>
+          </div>
+
+          <div class="form-group" v-if="item.fd_type === 'RG'">
+            <div class="col-xs-2 input-label">{{ item.fd_caption }}:</div>
+            <div class="col-xs-10">
+              <label class="radio-inline" v-for="list in item.fd_logictype.split(';')">
+                <input
+                  type="radio"
+                  :name="item.fd_id"
+                  :value="list"
+                  v-model="radioData"
+                  @change="handleInputRadio(index)"
+                  :checked="item.fd_defaultvalue.search(list)>=0">{{ list }}
+              </label>
+            </div>
+          </div>
+
+          <div class="form-group" v-if="item.fd_type === 'FF'">
+            <div class="col-xs-2 input-label">{{ item.fd_caption }}:</div>
+            <div class="col-xs-10" style="padding-right:410px;margin-top:10px;">
+              <div class="file-box">
+                <el-upload
+                  action="/zuul/city/thxz/api/serve/uploadAttach.action"
+                  accept="image/jpeg,image/jpg,image/gif,image/bmp,image/png"
+                  list-type="picture-card"
+                  :on-remove="(file, fileList)=>{return handleRemove(file, fileList, index)}"
+                  :on-success="(res)=>{return handleSuccess(res, index)}">
+                  <i class="el-icon-plus"/>
+                </el-upload>
+              </div>
+              <div class="file-title">
+                <p>上传文档说明: </p>
+                <span>为方便物业维修师傅上门服务,您可以在此上传需要维修的图片, 文件大小不超过3M</span>
+              </div>
+            </div>
+          </div>
+
+        </form>
+      </div>
+      <div class="repairs-btn text-right">
+        <button class="btn text-right" @click="submitForm($event)">提交申请</button>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script>
+  export default {
+    name: 'Repairs',
+    layout: 'town',
+    fetch ({ store, route }) {
+      return Promise.all([
+        store.dispatch('loadFormData', { serve_id: route.params.id, operate_type: 'Add', client_type: 'cc', cityId: store.state.option.user.data.currentCity ? store.state.option.user.data.currentCity.id : null})
+      ])
+    },
+    data () {
+      return {
+        pickerDate: {
+          disabledDate (time) {
+            return time.getTime() < Date.now()
+          }
+        },
+        keys: {},
+        operateid: '',
+        fd_fiedid: '',
+        operateurl: '',
+        modelData: [],
+        checkboxData: [],
+        radioData: '',
+        fileData: []
+      }
+    },
+    computed: {
+      user () {
+        return this.$store.state.option.user.data
+      },
+      formData () {
+        return this.$store.state.formConfig.formData.data.data
+      },
+      lists () {
+        let listsData = []
+        for (let i = 0; i < this.formData.formdetail.length; i++) {
+          if (this.formData.formdetail[i].fd_type === 'CBG') {
+            let lists = this.formData.formdetail[i].fd_logictype.split(';')
+            let defaultList = this.formData.formdetail[i].fd_defaultvalue
+            for (let j = 0; j < lists.length; j++) {
+              listsData[j] = false
+              if (defaultList.search(lists[j]) >= 0) {
+                listsData[j] = true
+              }
+            }
+          }
+        }
+        return listsData
+      },
+      titleData () {
+        return this.$store.state.formConfig.formData.data
+      }
+    },
+    methods: {
+      handleSuccess (res, index) {
+        if (this.fileData.indexOf(res.id) === -1) {
+          this.fileData.push(res.id)
+          this.modelData[index] = this.fileData.join(';')
+        }
+      },
+      handleRemove (file, fileList, index) {
+        this.fileData = []
+        for (let i = 0; i < fileList.length; i++) {
+          this.fileData.push(fileList[i].response.id)
+        }
+        this.modelData[index] = this.fileData.join(';')
+      },
+      handleInput (index, w, k) {
+        let _self = this
+        _self.lists[k] = !_self.lists[k]
+        for (let i = 0; i <= w; i++) {
+          if (_self.lists[i] === true) {
+            _self.checkboxData[i] = 1
+          }
+          if (_self.lists[i] === false) {
+            _self.checkboxData[i] = 0
+          }
+        }
+        _self.modelData[index] = _self.checkboxData.join(';')
+      },
+      handleInputRadio (index) {
+        let _self = this
+        _self.modelData[index] = _self.radioData
+      },
+      submitForm (event) {
+        event.preventDefault()
+        let _self = this
+        let datalist = _self.$store.state.formConfig.formData.data
+        _self.operateid = datalist.operateid
+        _self.operateurl = datalist.operateurl
+        for (let [index, value] of datalist.data.formdetail.entries()) {
+          _self.keys[value.fd_field] = _self.modelData[index]
+        }
+        let params = new FormData()
+        params.append('data' , JSON.stringify(_self.keys))
+        params.append('operate_id' , this.operateid)
+        params.append('client_type' , 'cc')
+        params.append('cityId' , this.user.currentCity ? this.user.currentCity.id : null)
+        let config = {
+          headers: {'Content-Type': 'multipart/form-data'}
+        }
+        // let config = {
+        //   headers: {'Content-Type': 'application/x-www-form-urlencoded'},
+        //   transformRequest: [function (data) {
+        //     let ret = ''
+        //     for (let it in data) {
+        //       ret += encodeURIComponent(encodeURIComponent(it)) + '=' +
+        //         encodeURIComponent(encodeURIComponent(data[it])) + '&'
+        //     }
+        //     return ret
+        //   }]
+        // }
+        this.$http.post('/' + this.operateurl, params, config)
+        // this.$http.post('/' + this.operateurl, { data: JSON.stringify(_self.keys), operate_id: this.operateid, client_type: 'cc', cityId: this.user.currentCity ? this.user.currentCity.id : null })
+          .then(response => {
+            if (response.data.success) {
+              this.$message({
+                message: '申请提交成功',
+                type: 'success'
+              })
+              let _self = this
+              _self.$router.push('/repairs/' + _self.$route.params.id + '/historicalInfo')
+            }
+          }, err => {
+            console.log(err)
+            this.$message.error('申请提交失败')
+          })
+      }
+    }
+  }
+</script>
+
+<style>
+  .el-date-editor.el-input{
+    width:100%;
+  }
+  .el-input__icon+.el-input__inner{
+    border:1px solid #cbcbcb;
+  }
+  .repairs{
+    margin-top:54px;
+    width:100%;
+    border-bottom: 8px solid #cbcbcb;
+    padding-bottom:111px;
+    background: #fff;
+  }
+  .container{
+    width:1180px;
+    padding-right:0;
+  }
+  .repairs .repairs-title{
+    padding-top:40px;
+    margin-bottom:40px;
+    width:100%;
+    display:inline-flex;
+    justify-content:space-between;
+  }
+  .repairs .repairs-title .title-left p{
+    font-size: 14px;
+    color:#000;
+    font-weight: bold;
+    line-height: 14px;
+
+  }
+  .repairs .repairs-title .title-left span{
+    font-size: 14px;
+    color:#000;
+  }
+  .repairs .repairs-title .title-right a{
+    color:#333;
+  }
+  .repairs .repairs-title .title-right a i{
+    color:#5280e3;
+    margin-right:10px;
+  }
+  .repairs .repairs-title .title-right a:hover{
+    cursor:pointer;
+    color:#d82128;
+
+  }
+  .repairs .repairs-flow{
+    width:100%;
+    display: inline-flex;
+    margin-bottom:43px;
+  }
+  .repairs .repairs-flow ul li{
+    height:50px;
+    padding:0;
+  }
+  .repairs .repairs-flow ul li span{
+    display: inline-block;
+    width:150px;
+    height:50px;
+    line-height: 50px;
+    border-radius:30px;
+    text-align: center;
+    font-size: 18px;
+    color:#fff;
+  }
+  .repairs .repairs-flow ul li:hover span{
+    cursor:pointer;
+  }
+  .repairs .repairs-flow ul li:nth-child(1){
+    width:150px;
+  }
+  .repairs .repairs-flow ul li:nth-child(1) span{
+    background: #62cde0;
+  }
+  .repairs .repairs-flow ul li:nth-child(2) span{
+    background: #62afe0;
+  }
+  .repairs .repairs-flow ul li:nth-child(3) span{
+    background: #6289e0;
+  }
+  .repairs .repairs-flow ul li:nth-child(4) span{
+    background: #8662e0;
+  }
+  .repairs .repairs-flow ul li:nth-child(5) span{
+    background: #c162e0;
+  }
+  .repairs .repairs-flow ul li:nth-child(6) span{
+    background: #e062a3;
+  }
+  .repairs .repairs-flow ul li i{
+    display: inline-block;
+    padding:0 4px;
+    font-size: 45px;
+    color:#cacaca;
+    position:relative;
+    top:12px;
+  }
+  .repairs .repairs-form{
+    width:1164px;
+    margin:0 auto;
+    border:1px solid #e6e6e6;
+    margin-bottom:5px;
+    padding:30px 50px 0 30px;
+    color:#333;
+  }
+  .repairs .repairs-form .input-label{
+    line-height: 34px;
+    font-size: 14px;
+    color:#666;
+    text-align: right;
+  }
+  .repairs .repairs-btn button{
+    width:228px;
+    height:80px;
+    color:#fff;
+    font-size: 18px;
+    text-align: center;
+    background: #2f95dd;
+  }
+  .repairs .repairs-form .checkbox-inline{
+    margin-right:10px;
+  }
+  .repairs .repairs-form .file-box {
+    display: inline-block;
+    position: relative;
+    text-align: center;
+    cursor: pointer;
+    overflow: hidden;
+  }
+  .repairs .repairs-form .el-upload-list--picture-card .el-upload-list__item{
+    width:120px;
+    height:120px;
+  }
+  .repairs .repairs-form .el-upload--picture-card{
+    width:120px;
+    height:120px;
+    line-height: 120px;
+    border:2px solid #cbcbcb;
+  }
+  .repairs .repairs-form .file-box input
+  {
+    position: absolute;
+    width: 0px;
+    height: 0px;
+    opacity: 0;
+    filter: "alpha(opacity=0)";
+    filter: alpha(opacity=0);
+    -moz-opacity: 0;
+    left: 0px;
+    bottom:-15px;
+    cursor: pointer;
+    z-index: 2;
+  }
+  .repairs .repairs-form .file-title{
+    display: inline-block;
+    color:#333;
+    font-weight: bold;
+    width:410px;
+    position:relative;
+    top:-40px;
+    left:25px;
+    margin-right:-410px;
+  }
+  .repairs .repairs-form .file-title span{
+    font-weight: normal;
+    color:#cbcbcb;
+  }
+  .repairs .repairs-form .radio-inline{
+    margin-right:10px;
+  }
+</style>

+ 31 - 0
pages/repairs/index.vue

@@ -0,0 +1,31 @@
+<template>
+  <div class="repairs">
+    <banner/>
+    <service-list/>
+  </div>
+</template>
+
+<script>
+  import { Carousel } from '@/components/home'
+  import { ServiceList, Banner } from '@/components/service'
+  export default {
+    name: 'Repairs',
+    layout: 'town',
+    fetch ({ store }) {
+      return Promise.all([
+        store.dispatch('loadServiceList', { kind: 'cc', client_type: 'cc', cityId: store.state.option.user.data.currentCity ? store.state.option.user.data.currentCity.id : null}),
+        store.dispatch('loadCarouselInfo', { client_type: 'cc', cityId: store.state.option.user.data.currentCity ? store.state.option.user.data.currentCity.id : null})
+      ])
+    },
+    components: {
+      Carousel,
+      ServiceList,
+      Banner
+    },
+    computed: {
+      bannerData () {
+        return this.$store.state.carouselInfo.infoData.data.serve
+      }
+    }
+  }
+</script>

+ 22 - 0
pages/townInfo/_id.vue

@@ -0,0 +1,22 @@
+<template>
+  <div class="town-info">
+    <detail/>
+  </div>
+</template>
+
+<script>
+  import {Detail} from '@/components/garden'
+  export default {
+    name: 'TownInfoDetail',
+    layout: 'town',
+    fetch({store, route}) {
+      return Promise.all([
+        store.dispatch('loadGardenDetail', {id: route.params.id, uu: store.state.option.user.data.userUu}),
+        store.dispatch('loadGardenList', {limit: 1, page: 1})
+      ])
+    },
+    components: {
+      Detail
+    }
+  }
+</script>

+ 24 - 0
pages/townInfo/index.vue

@@ -0,0 +1,24 @@
+<template>
+  <div class="town-info">
+    <banner/>
+    <list/>
+  </div>
+</template>
+
+<script>
+  import {Banner, List} from '@/components/garden'
+  export default {
+    name: 'TownInfo',
+    layout: 'town',
+    components: {
+      Banner,
+      List
+    },
+    fetch({store}) {
+      return Promise.all([
+        store.dispatch('loadGardenType'),
+        store.dispatch('loadGardenList', {limit: 16, page: 1})
+      ])
+    }
+  }
+</script>

+ 8 - 0
plugins/README.md

@@ -0,0 +1,8 @@
+# PLUGINS
+
+This directory contains your Javascript plugins that you want to run before instantiating the root vue.js application.
+
+More information about the usage of this directory in the documentation:
+https://nuxtjs.org/guide/plugins
+
+**This directory is not required, you can delete it if you don't want to use it.**

+ 41 - 0
plugins/axios.js

@@ -0,0 +1,41 @@
+import axios from 'axios'
+
+export default ({app}, inject) => {
+  const service = axios.create({
+    withCredentials: true,
+    baseURL: '/',
+    timeout: 5000
+  })
+
+  service.interceptors.request.use(config => {
+    if (process.server) {
+      config.url = process.env.baseUrl + config.url
+      config.headers.cookie = app.store.state.option.cookies + ';' + app.store.state.option.sessionId
+      config.headers['User-Agent'] = app.store.state.option.userAgent
+    }
+    return config
+  }, error => {
+    return Promise.reject(error)
+  })
+
+  service.interceptors.response.use(response => {
+    const cookies = response.headers['set-cookie']
+    if (cookies && cookies.length) {
+      for (let i = 0; i < cookies.length; i++) {
+        if (cookies[i].indexOf('JSESSIONID') > -1) {
+          const sessionId = cookies[i]
+          const first = sessionId.indexOf(';')
+          const second = sessionId.lastIndexOf(';')
+          const newSessionId = sessionId.replace(sessionId.substring(first, second), '')
+          app.store.commit('option/SET_SESSION_ID', newSessionId)
+          break
+        }
+      }
+    }
+    return response
+  }, error => {
+    return Promise.reject(error)
+  })
+
+  inject('http', service)
+}

+ 44 - 0
plugins/city-service.js

@@ -0,0 +1,44 @@
+import axios from 'axios'
+
+export default ({app}, inject) => {
+  const service = axios.create({
+    withCredentials: true,
+    baseURL: '/'
+  })
+
+  service.interceptors.request.use(config => {
+    // is server render, use ${baseUrl} directly rather than ${proxyUrl}
+    if (typeof window === 'undefined') {
+      config.url = process.env.baseUrl + '/city/' + process.env.cityDomain + config.url
+      config.headers.cookie = app.store.state.option.cookies + '; ' + app.store.state.option.sessionId
+      config.headers['User-Agent'] = app.store.state.option.userAgent
+    } else {
+      config.url = '/city/' + process.env.cityDomain + config.url
+    }
+
+    return config
+  }, error => {
+    return Promise.reject(error)
+  })
+
+  service.interceptors.response.use(response => {
+    const cookies = response.headers['set-cookie']
+    if (cookies && cookies.length) {
+      for (let i = 0; i < cookies.length; i++) {
+        if (cookies[i].indexOf('JSESSIONID') > -1) {
+          const sessionId = cookies[i]
+          const first = sessionId.indexOf(';')
+          const second = sessionId.lastIndexOf(';')
+          const newSessionId = sessionId.replace(sessionId.substring(first, second), '')
+          app.store.commit('option/SET_SESSION_ID', newSessionId)
+          break
+        }
+      }
+    }
+    return response
+  }, error => {
+    return Promise.reject(error)
+  })
+
+  inject('cityService', service)
+}

+ 12 - 0
plugins/element-ui.js

@@ -0,0 +1,12 @@
+import Vue from 'vue'
+import { Message, Breadcrumb, BreadcrumbItem, Tree, Pagination, Upload, Dialog, DatePicker } from 'element-ui'
+
+Vue.use(Breadcrumb)
+Vue.use(BreadcrumbItem)
+Vue.use(Tree)
+Vue.use(Pagination)
+Vue.use(Upload)
+Vue.use(Dialog)
+Vue.use(DatePicker)
+
+Vue.prototype.$message = Message

+ 4 - 0
plugins/filters.js

@@ -0,0 +1,4 @@
+import Vue from 'vue'
+import Vue2Filters from 'vue2-filters'
+
+Vue.use(Vue2Filters)

+ 4 - 0
plugins/jsonp.js

@@ -0,0 +1,4 @@
+import jsonp from 'jsonp'
+import Vue from 'vue'
+
+Vue.prototype.$jsonp = jsonp

+ 4 - 0
plugins/swiper.js

@@ -0,0 +1,4 @@
+import Vue from 'vue'
+import VueAwesomeSwiper from 'vue-awesome-swiper/dist/ssr'
+
+Vue.use(VueAwesomeSwiper)

+ 4 - 0
plugins/vue-clipboard2.js

@@ -0,0 +1,4 @@
+import Vue from 'vue'
+import VueClipboard from 'vue-clipboard2'
+
+Vue.use(VueClipboard)

+ 5 - 0
plugins/vue-empty.js

@@ -0,0 +1,5 @@
+
+import Vue from 'vue'
+import VueEmpty from '~components/common/vue-empty'
+
+Vue.use(VueEmpty)

+ 3 - 0
plugins/vue-jsonp.js

@@ -0,0 +1,3 @@
+import Vue from 'vue'
+import VueJsonp from 'vue-jsonp'
+Vue.use(VueJsonp)

+ 4 - 0
plugins/vue-loading.js

@@ -0,0 +1,4 @@
+import Vue from 'vue'
+import VueLoading from '~components/common/vue-loading'
+
+Vue.use(VueLoading)

+ 16 - 0
post.sh

@@ -0,0 +1,16 @@
+#!/bin/sh
+
+groupId=com.uas.platform
+artifactId=mall-ssr
+packaging=tgz
+version=1.0.0
+repo_uri='http://10.10.100.23:23004/v1/artifact'
+
+basepath=$(cd `dirname $0`; pwd)
+buildfile=$basepath/dist.tgz
+
+cnpm install
+npm run build
+tar -czf $buildfile .
+curl -H "Expect:" -F "groupId=$groupId" -F "artifactId=$artifactId" -F "packaging=$packaging"  -F "version=$version" -F "file=@$buildfile" $repo_uri
+rm -rf $buildfile

+ 32 - 0
run.sh

@@ -0,0 +1,32 @@
+#!/bin/sh
+
+echo "NODE_ENV: $NODE_ENV"
+echo "BASE_URL: $BASE_URL"
+
+updateHost(){
+  in_ip = ${1}
+  in_url = ${2}
+  inner_host=`cat /etc/hosts | grep ${in_url} | awk '{print $1}'`
+  if [ ${inner_host} = ${in_ip} ];then
+    echo "${inner_host} ${in_url} ok"
+  else
+    if [ ${inner_host} != "" ];then
+      echo " change is ok "
+    else
+      inner_ip_map="${in_ip} ${in_url}"
+      echo ${inner_ip_map} >> /etc/hosts
+      if [ $? = 0 ]; then
+        echo "${inner_ip_map} to hosts success host is `cat /etc/hosts`"
+      fi
+    fi
+  fi
+}
+
+if [ "$NODE_ENV" == 'production' ]; then
+  # updateHost 10.10.0.150 api-order.usoftmall.com
+  # updateHost 10.10.0.150 api-product.usoftmall.com
+  npm run build
+  npm run start
+else
+  npm run dev-start
+fi

+ 80 - 0
server.js

@@ -0,0 +1,80 @@
+const { Nuxt, Builder } = require('nuxt')
+const app = require('express')()
+const proxy = require('http-proxy-middleware')
+const cookiejar = require('cookiejar')
+const isProd = (process.env.NODE_ENV === 'production')
+const host = process.env.HOST || '127.0.0.1'
+const port = process.env.PORT || 4444
+process.noDeprecation = true
+app.set('port', port)
+
+// We instantiate nuxt.js with the options
+const config = require('./nuxt.config.js')
+config.dev = !isProd
+
+
+// 请求代理,dev模式下使用,接口服务器如果支持跨域可去掉
+const proxyTable = config.proxyTable
+if (proxyTable) {
+  // 本地代理支持localhost、127.0.0.1等不同地址跨域
+  app.use((req, res, next) => {
+    res.header('Access-Control-Allow-Origin', '*')
+    res.header('Access-Control-Allow-Methods', 'GET,POST,PUT,DELETE,TRACE,OPTIONS,PATCH')
+    res.header('Access-Control-Allow-Headers', 'Origin,X-Requested-With,Content-Type,Accept,withCredentials')
+    res.header('Access-Control-Allow-Credentials', 'true')
+    next()
+  })
+  if (Array.isArray(proxyTable)) {
+    app.use(proxy(proxyTable, {
+      target: config.env.baseUrl,
+      changeOrigin: true,
+      logLevel: config.dev ? 'debug' : 'info',
+      onProxyRes: (proxyRes) => {
+        const setCookieHeaders = proxyRes.headers['set-cookie'] || []
+        const modifiedSetCookieHeaders = setCookieHeaders
+          .map(str => new cookiejar.Cookie(str))
+          .map(cookie => {
+            cookie.path = '/'
+            return cookie
+          })
+          .map(cookie => cookie.toString())
+        proxyRes.headers['set-cookie'] = modifiedSetCookieHeaders
+      }
+    }))
+  } else {
+    Object.keys(proxyTable).forEach((context) => {
+      let options = proxyTable[context]
+      if (typeof options === 'string') {
+        options = { target: options }
+      }
+      app.use(proxy(context, options))
+    })
+  }
+  // axios use proxy url
+  config.env.proxyUrl = '/'
+}
+
+
+const nuxt = new Nuxt(config)
+
+// Render every route with Nuxt.js
+app.use(nuxt.render)
+
+// Build only in dev mode with hot-reloading
+if (config.dev) {
+  new Builder(nuxt).build()
+    .then(listen)
+    .catch((error) => {
+      console.error(error)
+      process.exit(1)
+    })
+}
+else {
+  listen()
+}
+
+function listen() {
+  // Listen the server
+  app.listen(port)
+  console.log(`\n Server listening on ${host}:${port}, at ${new Date().toLocaleString()} \n to api ${config.env.baseUrl}`)
+}

BIN
static/404.png


BIN
static/U.png


BIN
static/icon/developers.png


BIN
static/icon/enterprise.png


BIN
static/icon/garden.png


BIN
static/icon/government.png


BIN
static/icon/info.png


BIN
static/icon/left-arrow.png


BIN
static/icon/link.png


BIN
static/icon/new.png


BIN
static/icon/new_icon1.png


BIN
static/icon/new_icon2.png


BIN
static/icon/new_icon3.png


BIN
static/icon/new_icon4.png


BIN
static/icon/new_icon5.png


BIN
static/icon/new_icon6.png


BIN
static/icon/qq.png


BIN
static/icon/space.png


BIN
static/icon/trumpet.png


BIN
static/icon/weibo.png


BIN
static/img/banner/1.png


BIN
static/img/banner/10.png


BIN
static/img/banner/2.png


BIN
static/img/banner/9.png


BIN
static/img/news/banner.jpg


BIN
static/img/park/1.png


BIN
static/logo.png


BIN
static/map.png


BIN
static/qrcode/code.png


BIN
static/qrcode/uas.jpg


BIN
static/qrcode/uu.jpg


Някои файлове не бяха показани, защото твърде много файлове са промени