@ -0,0 +1,9 @@
|
||||
root = true
|
||||
|
||||
[*]
|
||||
charset = utf-8
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
end_of_line = lf
|
||||
insert_final_newline = true
|
||||
trim_trailing_whitespace = true
|
Before Width: | Height: | Size: 4.2 KiB |
After Width: | Height: | Size: 2.7 KiB |
@ -1,28 +1,24 @@
|
||||
<template>
|
||||
<div id="app">
|
||||
<img alt="Vue logo" src="./assets/logo.png">
|
||||
<HelloWorld msg="Welcome to Your Vue.js App"/>
|
||||
<keep-alive exclude="Detail">
|
||||
<router-view/>
|
||||
</keep-alive>
|
||||
<MainTabBar/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import HelloWorld from './components/HelloWorld.vue'
|
||||
import MainTabBar from "components/content/mainTabbar/MainTabBar";
|
||||
|
||||
|
||||
export default {
|
||||
name: 'App',
|
||||
components: {
|
||||
HelloWorld
|
||||
MainTabBar
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
#app {
|
||||
font-family: Avenir, Helvetica, Arial, sans-serif;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
text-align: center;
|
||||
color: #2c3e50;
|
||||
margin-top: 60px;
|
||||
}
|
||||
@import "./assets/css/base.css";
|
||||
</style>
|
||||
|
@ -0,0 +1,341 @@
|
||||
/*! normalize.css v8.0.0 | MIT License | github.com/necolas/normalize.css */
|
||||
|
||||
/* Document
|
||||
========================================================================== */
|
||||
|
||||
/**
|
||||
* 1. Correct the line height in all browsers.
|
||||
* 2. Prevent adjustments of font size after orientation changes in iOS.
|
||||
*/
|
||||
|
||||
html {
|
||||
line-height: 1.15; /* 1 */
|
||||
-webkit-text-size-adjust: 100%; /* 2 */
|
||||
}
|
||||
|
||||
/* Sections
|
||||
========================================================================== */
|
||||
|
||||
/**
|
||||
* Remove the margin in all browsers.
|
||||
*/
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Correct the font size and margin on `h1` elements within `section` and
|
||||
* `article` contexts in Chrome, Firefox, and Safari.
|
||||
*/
|
||||
|
||||
h1 {
|
||||
font-size: 2em;
|
||||
margin: 0.67em 0;
|
||||
}
|
||||
|
||||
/* Grouping content
|
||||
========================================================================== */
|
||||
|
||||
/**
|
||||
* 1. Add the correct box sizing in Firefox.
|
||||
* 2. Show the overflow in Edge and IE.
|
||||
*/
|
||||
|
||||
hr {
|
||||
box-sizing: content-box; /* 1 */
|
||||
height: 0; /* 1 */
|
||||
overflow: visible; /* 2 */
|
||||
}
|
||||
|
||||
/**
|
||||
* 1. Correct the inheritance and scaling of font size in all browsers.
|
||||
* 2. Correct the odd `em` font sizing in all browsers.
|
||||
*/
|
||||
|
||||
pre {
|
||||
font-family: monospace, monospace; /* 1 */
|
||||
font-size: 1em; /* 2 */
|
||||
}
|
||||
|
||||
/* Text-level semantics
|
||||
========================================================================== */
|
||||
|
||||
/**
|
||||
* Remove the gray background on active links in IE 10.
|
||||
*/
|
||||
|
||||
a {
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
/**
|
||||
* 1. Remove the bottom border in Chrome 57-
|
||||
* 2. Add the correct text decoration in Chrome, Edge, IE, Opera, and Safari.
|
||||
*/
|
||||
|
||||
abbr[title] {
|
||||
border-bottom: none; /* 1 */
|
||||
text-decoration: underline; /* 2 */
|
||||
text-decoration: underline dotted; /* 2 */
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the correct font weight in Chrome, Edge, and Safari.
|
||||
*/
|
||||
|
||||
b,
|
||||
strong {
|
||||
font-weight: bolder;
|
||||
}
|
||||
|
||||
/**
|
||||
* 1. Correct the inheritance and scaling of font size in all browsers.
|
||||
* 2. Correct the odd `em` font sizing in all browsers.
|
||||
*/
|
||||
|
||||
code,
|
||||
kbd,
|
||||
samp {
|
||||
font-family: monospace, monospace; /* 1 */
|
||||
font-size: 1em; /* 2 */
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the correct font size in all browsers.
|
||||
*/
|
||||
|
||||
small {
|
||||
font-size: 80%;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prevent `sub` and `sup` elements from affecting the line height in
|
||||
* all browsers.
|
||||
*/
|
||||
|
||||
sub,
|
||||
sup {
|
||||
font-size: 75%;
|
||||
line-height: 0;
|
||||
position: relative;
|
||||
vertical-align: baseline;
|
||||
}
|
||||
|
||||
sub {
|
||||
bottom: -0.25em;
|
||||
}
|
||||
|
||||
sup {
|
||||
top: -0.5em;
|
||||
}
|
||||
|
||||
/* Embedded content
|
||||
========================================================================== */
|
||||
|
||||
/**
|
||||
* Remove the border on images inside links in IE 10.
|
||||
*/
|
||||
|
||||
img {
|
||||
border-style: none;
|
||||
}
|
||||
|
||||
/* Forms
|
||||
========================================================================== */
|
||||
|
||||
/**
|
||||
* 1. Change the font styles in all browsers.
|
||||
* 2. Remove the margin in Firefox and Safari.
|
||||
*/
|
||||
|
||||
button,
|
||||
input,
|
||||
optgroup,
|
||||
select,
|
||||
textarea {
|
||||
font-family: inherit; /* 1 */
|
||||
font-size: 100%; /* 1 */
|
||||
line-height: 1.15; /* 1 */
|
||||
margin: 0; /* 2 */
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the overflow in IE.
|
||||
* 1. Show the overflow in Edge.
|
||||
*/
|
||||
|
||||
button,
|
||||
input { /* 1 */
|
||||
overflow: visible;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the inheritance of text transform in Edge, Firefox, and IE.
|
||||
* 1. Remove the inheritance of text transform in Firefox.
|
||||
*/
|
||||
|
||||
button,
|
||||
select { /* 1 */
|
||||
text-transform: none;
|
||||
}
|
||||
|
||||
/**
|
||||
* Correct the inability to style clickable types in iOS and Safari.
|
||||
*/
|
||||
|
||||
button,
|
||||
[type="button"],
|
||||
[type="reset"],
|
||||
[type="submit"] {
|
||||
-webkit-appearance: button;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the inner border and padding in Firefox.
|
||||
*/
|
||||
|
||||
button::-moz-focus-inner,
|
||||
[type="button"]::-moz-focus-inner,
|
||||
[type="reset"]::-moz-focus-inner,
|
||||
[type="submit"]::-moz-focus-inner {
|
||||
border-style: none;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Restore the focus styles unset by the previous rule.
|
||||
*/
|
||||
|
||||
button:-moz-focusring,
|
||||
[type="button"]:-moz-focusring,
|
||||
[type="reset"]:-moz-focusring,
|
||||
[type="submit"]:-moz-focusring {
|
||||
outline: 1px dotted ButtonText;
|
||||
}
|
||||
|
||||
/**
|
||||
* Correct the padding in Firefox.
|
||||
*/
|
||||
|
||||
fieldset {
|
||||
padding: 0.35em 0.75em 0.625em;
|
||||
}
|
||||
|
||||
/**
|
||||
* 1. Correct the text wrapping in Edge and IE.
|
||||
* 2. Correct the color inheritance from `fieldset` elements in IE.
|
||||
* 3. Remove the padding so developers are not caught out when they zero out
|
||||
* `fieldset` elements in all browsers.
|
||||
*/
|
||||
|
||||
legend {
|
||||
box-sizing: border-box; /* 1 */
|
||||
color: inherit; /* 2 */
|
||||
display: table; /* 1 */
|
||||
max-width: 100%; /* 1 */
|
||||
padding: 0; /* 3 */
|
||||
white-space: normal; /* 1 */
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the correct vertical alignment in Chrome, Firefox, and Opera.
|
||||
*/
|
||||
|
||||
progress {
|
||||
vertical-align: baseline;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the default vertical scrollbar in IE 10+.
|
||||
*/
|
||||
|
||||
textarea {
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
/**
|
||||
* 1. Add the correct box sizing in IE 10.
|
||||
* 2. Remove the padding in IE 10.
|
||||
*/
|
||||
|
||||
[type="checkbox"],
|
||||
[type="radio"] {
|
||||
box-sizing: border-box; /* 1 */
|
||||
padding: 0; /* 2 */
|
||||
}
|
||||
|
||||
/**
|
||||
* Correct the cursor style of increment and decrement buttons in Chrome.
|
||||
*/
|
||||
|
||||
[type="number"]::-webkit-inner-spin-button,
|
||||
[type="number"]::-webkit-outer-spin-button {
|
||||
height: auto;
|
||||
}
|
||||
|
||||
/**
|
||||
* 1. Correct the odd appearance in Chrome and Safari.
|
||||
* 2. Correct the outline style in Safari.
|
||||
*/
|
||||
|
||||
[type="search"] {
|
||||
-webkit-appearance: textfield; /* 1 */
|
||||
outline-offset: -2px; /* 2 */
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the inner padding in Chrome and Safari on macOS.
|
||||
*/
|
||||
|
||||
[type="search"]::-webkit-search-decoration {
|
||||
-webkit-appearance: none;
|
||||
}
|
||||
|
||||
/**
|
||||
* 1. Correct the inability to style clickable types in iOS and Safari.
|
||||
* 2. Change font properties to `inherit` in Safari.
|
||||
*/
|
||||
|
||||
::-webkit-file-upload-button {
|
||||
-webkit-appearance: button; /* 1 */
|
||||
font: inherit; /* 2 */
|
||||
}
|
||||
|
||||
/* Interactive
|
||||
========================================================================== */
|
||||
|
||||
/*
|
||||
* Add the correct display in Edge, IE 10+, and Firefox.
|
||||
*/
|
||||
|
||||
details {
|
||||
display: block;
|
||||
}
|
||||
|
||||
/*
|
||||
* Add the correct display in all browsers.
|
||||
*/
|
||||
|
||||
summary {
|
||||
display: list-item;
|
||||
}
|
||||
|
||||
/* Misc
|
||||
========================================================================== */
|
||||
|
||||
/**
|
||||
* Add the correct display in IE 10+.
|
||||
*/
|
||||
|
||||
template {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the correct display in IE 10.
|
||||
*/
|
||||
|
||||
[hidden] {
|
||||
display: none;
|
||||
}
|
After Width: | Height: | Size: 410 B |
After Width: | Height: | Size: 566 B |
After Width: | Height: | Size: 2.2 KiB |
After Width: | Height: | Size: 5.0 KiB |
After Width: | Height: | Size: 2.6 KiB |
After Width: | Height: | Size: 8.1 KiB |
After Width: | Height: | Size: 57 KiB |
After Width: | Height: | Size: 881 B |
After Width: | Height: | Size: 881 B |
After Width: | Height: | Size: 902 B |
After Width: | Height: | Size: 902 B |
After Width: | Height: | Size: 937 B |
After Width: | Height: | Size: 937 B |
After Width: | Height: | Size: 924 B |
After Width: | Height: | Size: 924 B |
Before Width: | Height: | Size: 6.7 KiB |
@ -0,0 +1,38 @@
|
||||
import {debounce} from "@/common/utils";
|
||||
|
||||
export const itemListenerMixin={
|
||||
data(){
|
||||
return{
|
||||
itemImgListener:null,
|
||||
}
|
||||
},
|
||||
|
||||
mounted(){
|
||||
const refresh = debounce(this.$refs.scroll.refresh,500)
|
||||
|
||||
this.itemImgListener=()=>{
|
||||
refresh()
|
||||
}
|
||||
|
||||
this.$bus.$on('itemImgLoad',this.itemImgListener)
|
||||
|
||||
}
|
||||
}
|
||||
export const backTopMixin={
|
||||
data(){
|
||||
return{
|
||||
isShowBackTop:false,
|
||||
tabOffsetTop:0,
|
||||
isTabFixed:false,
|
||||
}
|
||||
},
|
||||
methods:{
|
||||
backClick(){
|
||||
this.$refs.scroll.scrollTo(0,0)
|
||||
},
|
||||
contentScoll(position){
|
||||
this.isShowBackTop=(-position.y)>1000
|
||||
this.isTabFixed=(-position.y)>this.tabOffsetTop
|
||||
},
|
||||
}
|
||||
}
|
@ -0,0 +1,37 @@
|
||||
export function debounce(func,delay){
|
||||
let timer=null
|
||||
//...args多个参数 delay是延迟执行 但timer已经赋值 再次传入timer清空
|
||||
return function (...args){
|
||||
if(timer) clearTimeout(timer)
|
||||
|
||||
timer=setTimeout(()=>{
|
||||
func.apply(this,args)
|
||||
},delay)
|
||||
}
|
||||
}
|
||||
|
||||
export function formatDate(date, fmt) {
|
||||
if (/(y+)/.test(fmt)) {
|
||||
fmt = fmt.replace(RegExp.$1, (date.getFullYear() + '').substr(4 - RegExp.$1.length));
|
||||
}
|
||||
let o = {
|
||||
'M+': date.getMonth() + 1,
|
||||
'd+': date.getDate(),
|
||||
'h+': date.getHours(),
|
||||
'm+': date.getMinutes(),
|
||||
's+': date.getSeconds()
|
||||
};
|
||||
for (let k in o) {
|
||||
if (new RegExp(`(${k})`).test(fmt)) {
|
||||
let str = o[k] + '';
|
||||
fmt = fmt.replace(RegExp.$1, (RegExp.$1.length === 1) ? str : padLeftZero(str));
|
||||
}
|
||||
}
|
||||
return fmt;
|
||||
}
|
||||
|
||||
function padLeftZero (str) {
|
||||
return ('00' + str).substr(str.length);
|
||||
}
|
||||
|
||||
|
@ -1,57 +0,0 @@
|
||||
<template>
|
||||
<div class="hello">
|
||||
<h1>{{ msg }}</h1>
|
||||
<p>
|
||||
For a guide and recipes on how to configure / customize this project,<br>
|
||||
check out the
|
||||
<a href="https://cli.vuejs.org" target="_blank" rel="noopener">vue-cli documentation</a>.
|
||||
</p>
|
||||
<h3>Installed CLI Plugins</h3>
|
||||
<ul>
|
||||
<li><a href="https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-babel" target="_blank" rel="noopener">babel</a></li>
|
||||
</ul>
|
||||
<h3>Essential Links</h3>
|
||||
<ul>
|
||||
<li><a href="https://vuejs.org" target="_blank" rel="noopener">Core Docs</a></li>
|
||||
<li><a href="https://forum.vuejs.org" target="_blank" rel="noopener">Forum</a></li>
|
||||
<li><a href="https://chat.vuejs.org" target="_blank" rel="noopener">Community Chat</a></li>
|
||||
<li><a href="https://twitter.com/vuejs" target="_blank" rel="noopener">Twitter</a></li>
|
||||
<li><a href="https://news.vuejs.org" target="_blank" rel="noopener">News</a></li>
|
||||
</ul>
|
||||
<h3>Ecosystem</h3>
|
||||
<ul>
|
||||
<li><a href="https://router.vuejs.org" target="_blank" rel="noopener">vue-router</a></li>
|
||||
<li><a href="https://vuex.vuejs.org" target="_blank" rel="noopener">vuex</a></li>
|
||||
<li><a href="https://github.com/vuejs/vue-devtools#vue-devtools" target="_blank" rel="noopener">vue-devtools</a></li>
|
||||
<li><a href="https://vue-loader.vuejs.org" target="_blank" rel="noopener">vue-loader</a></li>
|
||||
<li><a href="https://github.com/vuejs/awesome-vue" target="_blank" rel="noopener">awesome-vue</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'HelloWorld',
|
||||
props: {
|
||||
msg: String
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<!-- Add "scoped" attribute to limit CSS to this component only -->
|
||||
<style scoped>
|
||||
h3 {
|
||||
margin: 40px 0 0;
|
||||
}
|
||||
ul {
|
||||
list-style-type: none;
|
||||
padding: 0;
|
||||
}
|
||||
li {
|
||||
display: inline-block;
|
||||
margin: 0 10px;
|
||||
}
|
||||
a {
|
||||
color: #42b983;
|
||||
}
|
||||
</style>
|
@ -0,0 +1,65 @@
|
||||
<template>
|
||||
<div class="wrapper" ref="wrapper">
|
||||
<div class="content">
|
||||
<slot></slot>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import BScroll from 'better-scroll'
|
||||
export default {
|
||||
name: "Scroll",
|
||||
props:{
|
||||
probeType:{
|
||||
type:Number,
|
||||
default:0
|
||||
},
|
||||
pullUpLoad:{
|
||||
type:Boolean,
|
||||
default: false
|
||||
}
|
||||
},
|
||||
data(){
|
||||
return{
|
||||
scroll:null
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.scroll=new BScroll(this.$refs.wrapper,{
|
||||
click:true,
|
||||
probeType:this.probeType,
|
||||
pullUpLoad: this.pullUpLoad
|
||||
})
|
||||
this.scroll.on('scroll',(position)=>{
|
||||
this.$emit('scroll',position)
|
||||
})
|
||||
|
||||
this.scroll.on('pullingUp',()=>{
|
||||
this.$emit('pullingUp')
|
||||
})
|
||||
|
||||
|
||||
|
||||
this.scroll.scrollTo(0,0)
|
||||
},
|
||||
methods:{
|
||||
scrollTo(x,y,time=3000){
|
||||
this.scroll && this.scroll.scrollTo(x,y,time)
|
||||
},
|
||||
finishPullUp(){
|
||||
this.scroll && this.scroll.finishPullUp()
|
||||
},
|
||||
refresh(){
|
||||
this.scroll && this.scroll.refresh()
|
||||
},
|
||||
getScrolly(){
|
||||
return this.scroll ? this.scroll.y : 0
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
@ -0,0 +1,29 @@
|
||||
<template>
|
||||
<div class="nav-bar">
|
||||
<div class="left"><slot name="left"></slot></div>
|
||||
<div class="center"><slot name="center"></slot></div>
|
||||
<div class="right"><slot name="right"></slot></div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: "NavBar"
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.nav-bar{
|
||||
display: flex;
|
||||
line-height: 44px;
|
||||
height: 44px;
|
||||
text-align: center;
|
||||
box-shadow: 0 1px 1px rgba(100,100,100,.1);
|
||||
}
|
||||
.left,.right{
|
||||
width:60px;
|
||||
}
|
||||
.center{
|
||||
flex:1;
|
||||
}
|
||||
</style>
|
@ -0,0 +1,371 @@
|
||||
<template>
|
||||
<div id="hy-swiper">
|
||||
<div class="swiper" @touchstart="touchStart" @touchmove="touchMove" @touchend="touchEnd">
|
||||
<slot></slot>
|
||||
</div>
|
||||
<slot name="indicator">
|
||||
</slot>
|
||||
<div class="indicator">
|
||||
<slot name="indicator" v-if="showIndicator && slideCount>1">
|
||||
<div v-for="(item, index) in slideCount" class="indi-item" :class="{active: index === currentIndex-1}" :key="index"></div>
|
||||
</slot>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: "Swiper",
|
||||
props: {
|
||||
interval: {
|
||||
type: Number,
|
||||
default: 3000
|
||||
},
|
||||
animDuration: {
|
||||
type: Number,
|
||||
default: 300
|
||||
},
|
||||
moveRatio: {
|
||||
type: Number,
|
||||
default: 0.25
|
||||
},
|
||||
showIndicator: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
}
|
||||
},
|
||||
data: function () {
|
||||
return {
|
||||
slideCount: 0, // 元素个数
|
||||
totalWidth: 0, // swiper的宽度
|
||||
swiperStyle: {}, // swiper样式
|
||||
currentIndex: 1, // 当前的index
|
||||
scrolling: false, // 是否正在滚动
|
||||
}
|
||||
},
|
||||
mounted: function () {
|
||||
// 1.操作DOM, 在前后添加Slide
|
||||
setTimeout(() => {
|
||||
this.handleDom();
|
||||
// 2.开启定时器
|
||||
this.startTimer();
|
||||
}, 500)
|
||||
},
|
||||
methods: {
|
||||
/**
|
||||
* 定时器操作
|
||||
*/
|
||||
startTimer: function () {
|
||||
this.playTimer = window.setInterval(() => {
|
||||
this.currentIndex++;
|
||||
this.scrollContent(-this.currentIndex * this.totalWidth);
|
||||
}, this.interval)
|
||||
},
|
||||
stopTimer: function () {
|
||||
window.clearInterval(this.playTimer);
|
||||
},
|
||||
|
||||
/**
|
||||
* 滚动到正确的位置
|
||||
*/
|
||||
scrollContent: function (currentPosition) {
|
||||
// 0.设置正在滚动
|
||||
this.scrolling = true;
|
||||
|
||||
// 1.开始滚动动画
|
||||
this.swiperStyle.transition ='transform '+ this.animDuration + 'ms';
|
||||
this.setTransform(currentPosition);
|
||||
|
||||
// 2.判断滚动到的位置
|
||||
this.checkPosition();
|
||||
|
||||
// 4.滚动完成
|
||||
this.scrolling = false
|
||||
},
|
||||
|
||||
/**
|
||||
* 校验正确的位置
|
||||
*/
|
||||
checkPosition: function () {
|
||||
window.setTimeout(() => {
|
||||
// 1.校验正确的位置
|
||||
this.swiperStyle.transition = '0ms';
|
||||
if (this.currentIndex >= this.slideCount + 1) {
|
||||
this.currentIndex = 1;
|
||||
this.setTransform(-this.currentIndex * this.totalWidth);
|
||||
} else if (this.currentIndex <= 0) {
|
||||
this.currentIndex = this.slideCount;
|
||||
this.setTransform(-this.currentIndex * this.totalWidth);
|
||||
}
|
||||
|
||||
// 2.结束移动后的回调
|
||||
this.$emit('transitionEnd', this.currentIndex-1);
|
||||
}, this.animDuration)
|
||||
},
|
||||
|
||||
/**
|
||||
* 设置滚动的位置
|
||||
*/
|
||||
setTransform: function (position) {
|
||||
this.swiperStyle.transform = `translate3d(${position}px, 0, 0)`;
|
||||
this.swiperStyle['-webkit-transform'] = `translate3d(${position}px), 0, 0`;
|
||||
this.swiperStyle['-ms-transform'] = `translate3d(${position}px), 0, 0`;
|
||||
},
|
||||
|
||||
/**
|
||||
* 操作DOM, 在DOM前后添加Slide
|
||||
*/
|
||||
handleDom: function () {
|
||||
// 1.获取要操作的元素
|
||||
let swiperEl = document.querySelector('.swiper');
|
||||
let slidesEls = swiperEl.getElementsByClassName('slide');
|
||||
// 2.保存个数
|
||||
this.slideCount = slidesEls.length;
|
||||
|
||||
// 3.如果大于1个, 那么在前后分别添加一个slide
|
||||
if (this.slideCount > 1) {
|
||||
let cloneFirst = slidesEls[0].cloneNode(true);
|
||||
let cloneLast = slidesEls[this.slideCount - 1].cloneNode(true);
|
||||
swiperEl.insertBefore(cloneLast, slidesEls[0]);
|
||||
swiperEl.appendChild(cloneFirst);
|
||||
this.totalWidth = swiperEl.offsetWidth;
|
||||
this.swiperStyle = swiperEl.style;
|
||||
}
|
||||
|
||||
// 4.让swiper元素, 显示第一个(目前是显示前面添加的最后一个元素)
|
||||
this.setTransform(-this.totalWidth);
|
||||
},
|
||||
|
||||
/**
|
||||
* 拖动事件的处理
|
||||
*/
|
||||
touchStart: function (e) {
|
||||
// 1.如果正在滚动, 不可以拖动
|
||||
if (this.scrolling) return;
|
||||
|
||||
// 2.停止定时器
|
||||
this.stopTimer();
|
||||
|
||||
// 3.保存开始滚动的位置
|
||||
this.startX = e.touches[0].pageX;
|
||||
},
|
||||
|
||||
touchMove: function (e) {
|
||||
// 1.计算出用户拖动的距离
|
||||
this.currentX = e.touches[0].pageX;
|
||||
this.distance = this.currentX - this.startX;
|
||||
let currentPosition = -this.currentIndex * this.totalWidth;
|
||||
let moveDistance = this.distance + currentPosition;
|
||||
|
||||
// 2.设置当前的位置
|
||||
this.setTransform(moveDistance);
|
||||
},
|
||||
|
||||
touchEnd: function (e) {
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// 1.获取移动的距离
|
||||
let currentMove = Math.abs(this.distance);
|
||||
|
||||
// 2.判断最终的距离
|
||||
if (this.distance === 0) {
|
||||
return
|
||||
} else if (this.distance > 0 && currentMove > this.totalWidth * this.moveRatio) { // 右边移动超过0.5
|
||||
this.currentIndex--
|
||||
} else if (this.distance < 0 && currentMove > this.totalWidth * this.moveRatio) { // 向左移动超过0.5
|
||||
this.currentIndex++
|
||||
}
|
||||
|
||||
// 3.移动到正确的位置
|
||||
this.scrollContent(-this.currentIndex * this.totalWidth);
|
||||
|
||||
// 4.移动完成后重新开启定时器
|
||||
this.startTimer();
|
||||
},
|
||||
|
||||
/**
|
||||
* 控制上一个, 下一个
|
||||
*/
|
||||
previous: function () {
|
||||
this.changeItem(-1);
|
||||
},
|
||||
|
||||
next: function () {
|
||||
this.changeItem(1);
|
||||
},
|
||||
|
||||
changeItem: function (num) {
|
||||
// 1.移除定时器
|
||||
this.stopTimer();
|
||||
|
||||
// 2.修改index和位置
|
||||
this.currentIndex += num;
|
||||
this.scrollContent(-this.currentIndex * this.totalWidth);
|
||||
|
||||
// 3.添加定时器
|
||||
this.startTimer();
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
#hy-swiper {
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.swiper {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.indicator {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
bottom: 8px;
|
||||
}
|
||||
|
||||
.indi-item {
|
||||
box-sizing: border-box;
|
||||
width: 8px;
|
||||
height: 8px;
|
||||
border-radius: 4px;
|
||||
background-color: #fff;
|
||||
line-height: 8px;
|
||||
text-align: center;
|
||||
font-size: 12px;
|
||||
margin: 0 5px;
|
||||
}
|
||||
|
||||
.indi-item.active {
|
||||
background-color: rgba(212,62,46,1.0);
|
||||
}
|
||||
</style>
|
@ -0,0 +1,22 @@
|
||||
<template>
|
||||
<div class="slide">
|
||||
<slot></slot>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: "Slide"
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.slide {
|
||||
width: 100%;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.slide img {
|
||||
width: 100%;
|
||||
}
|
||||
</style>
|
@ -0,0 +1,6 @@
|
||||
import Swiper from './Swiper'
|
||||
import SwiperItem from './SwiperItem'
|
||||
|
||||
export {
|
||||
Swiper, SwiperItem
|
||||
}
|
@ -0,0 +1,24 @@
|
||||
<template>
|
||||
<div id="tab-bar">
|
||||
<slot></slot>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: "TabBar"
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
#tab-bar{
|
||||
display: flex;
|
||||
background-color: #f6f6f6;
|
||||
|
||||
position: fixed;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom:0;
|
||||
box-shadow: 0 -3px 1px rgba(100,100,100,.1);
|
||||
}
|
||||
</style>
|
@ -0,0 +1,53 @@
|
||||
<template>
|
||||
<div class="tab-bar-item" @click="itemClick">
|
||||
<div v-if="!isActive"><slot name="item-icon"></slot></div>
|
||||
<div v-else><slot name="item-icon-active"></slot></div>
|
||||
<div :style="activeStyle"><slot name="item-text"></slot></div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: "TabBarItem",
|
||||
props:{
|
||||
path:String,
|
||||
activeColor:{
|
||||
type:String,
|
||||
default:'red'
|
||||
}
|
||||
},
|
||||
data(){
|
||||
return{
|
||||
// isActive:true
|
||||
}
|
||||
},
|
||||
computed:{
|
||||
isActive(){
|
||||
return this.$route.path.indexOf(this.path)!==-1
|
||||
},
|
||||
activeStyle(){
|
||||
return this.isActive ? {color:this.activeColor} : {}
|
||||
}
|
||||
},
|
||||
methods:{
|
||||
itemClick(){
|
||||
this.$router.replace(this.path)
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.tab-bar-item{
|
||||
flex:1;
|
||||
text-align: center;
|
||||
height: 49px;
|
||||
}
|
||||
.tab-bar-item img{
|
||||
width:24px;
|
||||
height:24px;
|
||||
margin-top: 3px;
|
||||
vertical-align: middle;
|
||||
margin-bottom: 2px;
|
||||
}
|
||||
</style>
|
@ -0,0 +1,23 @@
|
||||
<template>
|
||||
<div class="back-Top" >
|
||||
<img src="@/assets/img/common/top.png" alt="">
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: "backTop",
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.back-Top{
|
||||
position: fixed;
|
||||
right: 8px;
|
||||
bottom: 55px;
|
||||
}
|
||||
.back-Top img{
|
||||
width: 48px;
|
||||
height: 48px;
|
||||
}
|
||||
</style>
|
@ -0,0 +1,32 @@
|
||||
<template>
|
||||
<div class="goods">
|
||||
<GoodsListItem v-for="(item, index) in goods" :key="index" :goodsItem="item"/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import GoodsListItem from "@/components/content/goods/GoodsListItem";
|
||||
|
||||
export default {
|
||||
name: "GoodsList",
|
||||
components:{
|
||||
GoodsListItem
|
||||
},
|
||||
props:{
|
||||
goods:{
|
||||
type:Array,
|
||||
default(){
|
||||
return []
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.goods{
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
justify-content: space-around;
|
||||
}
|
||||
</style>
|
@ -0,0 +1,85 @@
|
||||
<template>
|
||||
<div class="goods-items" @click="itemClick">
|
||||
<img :src="showImage" alt="" @load="imageLoad">
|
||||
<div class="goods-info">
|
||||
<p>{{goodsItem.title}}</p>
|
||||
<span class="price">{{goodsItem.price}}</span>
|
||||
<span class="collect">{{goodsItem.cfav}}</span>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: "GoodsListItem",
|
||||
props:{
|
||||
goodsItem:{
|
||||
type:Object,
|
||||
default(){
|
||||
return {}
|
||||
}
|
||||
}
|
||||
},
|
||||
methods:{
|
||||
imageLoad(){
|
||||
this.$bus.$emit('itemImageLoad')
|
||||
},
|
||||
itemClick(){
|
||||
this.$router.push('/detail/'+this.goodsItem.iid)
|
||||
}
|
||||
},
|
||||
computed:{
|
||||
showImage(){
|
||||
return this.goodsItem.image || this.goodsItem.show.img
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.goods-items {
|
||||
padding-bottom: 40px;
|
||||
position: relative;
|
||||
|
||||
width:48%;
|
||||
}
|
||||
.goods-items img {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.goods-info {
|
||||
font-size: 12px;
|
||||
position: absolute;
|
||||
bottom: 5px;
|
||||
left: 0;
|
||||
right: 0;
|
||||
overflow: hidden;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.goods-info p {
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
margin-bottom: 3px;
|
||||
}
|
||||
|
||||
.goods-info .price {
|
||||
color: var(--color-high-text);
|
||||
margin-right: 20px;
|
||||
}
|
||||
|
||||
.goods-info .collect {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.goods-info .collect::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
left: -15px;
|
||||
top: 0;
|
||||
width: 14px;
|
||||
height: 14px;
|
||||
background: url("~assets/img/common/collect.svg") 0 0/14px 14px;
|
||||
}
|
||||
</style>
|
@ -0,0 +1,42 @@
|
||||
<template>
|
||||
<tab-bar>
|
||||
<tab-bar-item path="/home" activeColor="red">
|
||||
<img slot="item-icon" src="~assets/img/tabbar/home.svg" alt="">
|
||||
<img slot="item-icon-active" src="~assets/img/tabbar/home_active.svg" alt="">
|
||||
<div slot="item-text">首页</div>
|
||||
</tab-bar-item>
|
||||
<tab-bar-item path="/category" activeColor="red">
|
||||
<img slot="item-icon" src="~assets/img/tabbar/category.svg" alt="">
|
||||
<img slot="item-icon-active" src="~assets/img/tabbar/category_active.svg" alt="">
|
||||
<div slot="item-text">分类</div>
|
||||
</tab-bar-item>
|
||||
<tab-bar-item path="/cart" activeColor="red">
|
||||
<img slot="item-icon" src="~assets/img/tabbar/cart.svg" alt="">
|
||||
<img slot="item-icon-active" src="~assets/img/tabbar/cart_active.svg" alt="">
|
||||
<div slot="item-text">购物车</div>
|
||||
</tab-bar-item>
|
||||
<tab-bar-item path="/profile" activeColor="red">
|
||||
<img slot="item-icon" src="~assets/img/tabbar/profile.svg" alt="">
|
||||
<img slot="item-icon-active" src="~assets/img/tabbar/profile_active.svg" alt="">
|
||||
<div slot="item-text">我的</div>
|
||||
</tab-bar-item>
|
||||
</tab-bar>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import TabBar from "@/components/common/tabbar/TabBar";
|
||||
import TabBarItem from "@/components/common/tabbar/TabBarItem";
|
||||
|
||||
export default {
|
||||
|
||||
name: "MainTabBar",
|
||||
components:{
|
||||
TabBar,
|
||||
TabBarItem
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
@ -0,0 +1,55 @@
|
||||
<template>
|
||||
<div class="tab-control">
|
||||
<div v-for="(item,index) in titles"
|
||||
class="tab-control-item" :class="{active:index===currentIndex}" @click="itemclick(index)">
|
||||
<span>{{item}}</span>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: "TabControl",
|
||||
props:{
|
||||
titles:{
|
||||
type:Array,
|
||||
default(){
|
||||
return []
|
||||
}
|
||||
}
|
||||
},
|
||||
data(){
|
||||
return{
|
||||
currentIndex:0
|
||||
}
|
||||
},
|
||||
methods:{
|
||||
itemclick(index){
|
||||
this.currentIndex=index;
|
||||
this.$emit('tabClick',index);
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.tab-control{
|
||||
display: flex;
|
||||
text-align: center;
|
||||
font-size: 15px;
|
||||
height: 40px;
|
||||
line-height: 40px;
|
||||
background-color: #fff;
|
||||
z-index: 9;
|
||||
}
|
||||
.tab-control-item{
|
||||
flex:1;
|
||||
}
|
||||
.tab-control-item span{
|
||||
padding: 5px;
|
||||
}
|
||||
|
||||
.active span{
|
||||
border-bottom: 3px solid var(--color-tint);
|
||||
}
|
||||
</style>
|
@ -1,8 +1,11 @@
|
||||
import Vue from 'vue'
|
||||
import App from './App.vue'
|
||||
import router from './router'
|
||||
|
||||
Vue.config.productionTip = false
|
||||
Vue.prototype.$bus = new Vue()
|
||||
|
||||
new Vue({
|
||||
render: h => h(App),
|
||||
router,
|
||||
}).$mount('#app')
|
||||
|
@ -0,0 +1,50 @@
|
||||
import {request} from "@/network/request";
|
||||
|
||||
export function getDetail(iid){
|
||||
return request({
|
||||
url:'/detail',
|
||||
params:{
|
||||
iid
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
export function getRecommend(){
|
||||
return request({
|
||||
url:'/recommend'
|
||||
})
|
||||
}
|
||||
|
||||
export class Goods{
|
||||
constructor(itemInfo, columns, services) {
|
||||
this.title = itemInfo.title;
|
||||
this.desc = itemInfo.desc;
|
||||
this.newPrice = itemInfo.price;
|
||||
this.oldPrice = itemInfo.oldPrice;
|
||||
this.discount = itemInfo.discountDesc;
|
||||
this.columns = columns;
|
||||
this.services = services;
|
||||
this.nowPrice = itemInfo.highNowPrice;
|
||||
}
|
||||
}
|
||||
|
||||
export class Shop {
|
||||
constructor(shopInfo) {
|
||||
this.logo = shopInfo.shopLogo;
|
||||
this.name = shopInfo.name;
|
||||
this.fans = shopInfo.cFans;
|
||||
this.sells = shopInfo.cSells;
|
||||
this.score = shopInfo.score;
|
||||
this.goodsCount = shopInfo.cGoods
|
||||
}
|
||||
}
|
||||
|
||||
export class GoodsParam {
|
||||
constructor(info, rule) {
|
||||
// 注: images可能没有值(某些商品有值, 某些没有值)
|
||||
this.image = info.images ? info.images[0] : '';
|
||||
this.infos = info.set;
|
||||
this.sizes = rule.tables;
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,18 @@
|
||||
import {request} from "@/network/request";
|
||||
|
||||
export function getHomeMutidata(){
|
||||
return request({
|
||||
url:'/home/multidata'
|
||||
})
|
||||
}
|
||||
export function getHomeGoods(type,page){
|
||||
return request({
|
||||
url:'/home/data',
|
||||
params:{
|
||||
type,
|
||||
page
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,26 @@
|
||||
import axios from 'axios'
|
||||
|
||||
export function request(config){
|
||||
const instance =axios.create({
|
||||
baseURL:'http://152.136.185.210:8000/api/w6',
|
||||
timeout:5000
|
||||
})
|
||||
|
||||
// //拦截
|
||||
// instance.interceptors.request.use(config=>{
|
||||
// console.log(config);
|
||||
// return config
|
||||
// },
|
||||
// err=>{
|
||||
// // console.log(err)
|
||||
// })
|
||||
//
|
||||
// instance.interceptors.request.use(res=>{
|
||||
// return res.get
|
||||
// },err=>{
|
||||
// console.log(err);
|
||||
// })
|
||||
|
||||
return instance(config)
|
||||
}
|
||||
|
@ -0,0 +1,41 @@
|
||||
import Vue from 'vue'
|
||||
import Router from 'vue-router'
|
||||
|
||||
const Home=()=>import('../views/home/Home')
|
||||
const Category=()=>import('../views/category/Category')
|
||||
const Cart=()=>import('../views/cart/Cart')
|
||||
const Profile=()=>import('../views/profile/Profile')
|
||||
const Detail=()=>import('../views/detail/Detail')
|
||||
Vue.use(Router)
|
||||
|
||||
const routes=[
|
||||
{
|
||||
path:'',
|
||||
redirect:'/home'
|
||||
},
|
||||
{
|
||||
path:'/home',
|
||||
component:Home
|
||||
},
|
||||
{
|
||||
path:'/category',
|
||||
component:Category
|
||||
},
|
||||
{
|
||||
path:'/cart',
|
||||
component:Cart
|
||||
},
|
||||
{
|
||||
path: '/profile',
|
||||
component: Profile
|
||||
},
|
||||
{
|
||||
path: '/detail/:iid',
|
||||
component: Detail
|
||||
}
|
||||
]
|
||||
const router =new Router({
|
||||
routes,
|
||||
mode:'history'
|
||||
})
|
||||
export default router
|
@ -0,0 +1,15 @@
|
||||
<template>
|
||||
<div>
|
||||
<h2>购物车</h2>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: "Home"
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
@ -0,0 +1,152 @@
|
||||
<template>
|
||||
<div class="wrapper" ref="aaaa">
|
||||
<ul >
|
||||
<button @click="btnClick">按钮</button>
|
||||
<li>分类列表1</li>
|
||||
<li>分类列表2</li>
|
||||
<li>分类列表3</li>
|
||||
<li>分类列表4</li>
|
||||
<li>分类列表5</li>
|
||||
<li>分类列表6</li>
|
||||
<li>分类列表7</li>
|
||||
<li>分类列表8</li>
|
||||
<li>分类列表9</li>
|
||||
<li>分类列表10</li>
|
||||
<li>分类列表11</li>
|
||||
<li>分类列表12</li>
|
||||
<li>分类列表13</li>
|
||||
<li>分类列表14</li>
|
||||
<li>分类列表15</li>
|
||||
<li>分类列表16</li>
|
||||
<li>分类列表17</li>
|
||||
<li>分类列表18</li>
|
||||
<li>分类列表19</li>
|
||||
<li>分类列表20</li>
|
||||
<li>分类列表21</li>
|
||||
<li>分类列表22</li>
|
||||
<li>分类列表23</li>
|
||||
<li>分类列表24</li>
|
||||
<li>分类列表25</li>
|
||||
<li>分类列表26</li>
|
||||
<li>分类列表27</li>
|
||||
<li>分类列表28</li>
|
||||
<li>分类列表29</li>
|
||||
<li>分类列表30</li>
|
||||
<li>分类列表31</li>
|
||||
<li>分类列表32</li>
|
||||
<li>分类列表33</li>
|
||||
<li>分类列表34</li>
|
||||
<li>分类列表35</li>
|
||||
<li>分类列表36</li>
|
||||
<li>分类列表37</li>
|
||||
<li>分类列表38</li>
|
||||
<li>分类列表39</li>
|
||||
<li>分类列表40</li>
|
||||
<li>分类列表41</li>
|
||||
<li>分类列表42</li>
|
||||
<li>分类列表43</li>
|
||||
<li>分类列表44</li>
|
||||
<li>分类列表45</li>
|
||||
<li>分类列表46</li>
|
||||
<li>分类列表47</li>
|
||||
<li>分类列表48</li>
|
||||
<li>分类列表49</li>
|
||||
<li>分类列表50</li>
|
||||
<li>分类列表51</li>
|
||||
<li>分类列表52</li>
|
||||
<li>分类列表53</li>
|
||||
<li>分类列表54</li>
|
||||
<li>分类列表55</li>
|
||||
<li>分类列表56</li>
|
||||
<li>分类列表57</li>
|
||||
<li>分类列表58</li>
|
||||
<li>分类列表59</li>
|
||||
<li>分类列表60</li>
|
||||
<li>分类列表61</li>
|
||||
<li>分类列表62</li>
|
||||
<li>分类列表63</li>
|
||||
<li>分类列表64</li>
|
||||
<li>分类列表65</li>
|
||||
<li>分类列表66</li>
|
||||
<li>分类列表67</li>
|
||||
<li>分类列表68</li>
|
||||
<li>分类列表69</li>
|
||||
<li>分类列表70</li>
|
||||
<li>分类列表71</li>
|
||||
<li>分类列表72</li>
|
||||
<li>分类列表73</li>
|
||||
<li>分类列表74</li>
|
||||
<li>分类列表75</li>
|
||||
<li>分类列表76</li>
|
||||
<li>分类列表77</li>
|
||||
<li>分类列表78</li>
|
||||
<li>分类列表79</li>
|
||||
<li>分类列表80</li>
|
||||
<li>分类列表81</li>
|
||||
<li>分类列表82</li>
|
||||
<li>分类列表83</li>
|
||||
<li>分类列表84</li>
|
||||
<li>分类列表85</li>
|
||||
<li>分类列表86</li>
|
||||
<li>分类列表87</li>
|
||||
<li>分类列表88</li>
|
||||
<li>分类列表89</li>
|
||||
<li>分类列表90</li>
|
||||
<li>分类列表91</li>
|
||||
<li>分类列表92</li>
|
||||
<li>分类列表93</li>
|
||||
<li>分类列表94</li>
|
||||
<li>分类列表95</li>
|
||||
<li>分类列表96</li>
|
||||
<li>分类列表97</li>
|
||||
<li>分类列表98</li>
|
||||
<li>分类列表99</li>
|
||||
<li>分类列表100</li>
|
||||
</ul>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import BScroll from 'better-scroll'
|
||||
|
||||
export default {
|
||||
name: "Category",
|
||||
data(){
|
||||
return {
|
||||
scroll:null
|
||||
}
|
||||
},
|
||||
created() {
|
||||
},
|
||||
mounted() {
|
||||
this.scroll=new BScroll(document.querySelector('.wrapper'),{
|
||||
probeType:3,
|
||||
pullUpLoad:true,
|
||||
})
|
||||
|
||||
this.scroll.on('scroll',(position)=>{
|
||||
// console.log(position);
|
||||
})
|
||||
|
||||
this.scroll.on('pullingUp',()=>{
|
||||
console.log('上拉加载更多');
|
||||
})
|
||||
},
|
||||
methods:{
|
||||
btnClick(){
|
||||
console.log('ctnClick');
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.wrapper{
|
||||
height: 150px;
|
||||
background-color: red;
|
||||
|
||||
/*overflow: hidden;*/
|
||||
overflow-y:scroll;
|
||||
}
|
||||
|
||||
</style>
|
@ -0,0 +1,168 @@
|
||||
<template>
|
||||
<div id="detail" >
|
||||
<DetailNewBar class="detail-nav" @titleClick="titleClick" ref="nav"/>
|
||||
<scroll class="content"
|
||||
ref="scroll"
|
||||
@scroll="totalScroll"
|
||||
:probe-type="3" >
|
||||
<DetailSwiper :top-images="topImages"/>
|
||||
<DetailBaseInfo :goods="goods"/>
|
||||
<DetailShopInfo :shop="shop" />
|
||||
<DetailGoodsInfo :detail-info="detailInfo" @detailImageload="detailImageload"/>
|
||||
<DetailParamInfo ref="params" :param-info="paramInfo"/>
|
||||
<DetailCommentInfo ref="comment" :comment-info="commentInfo"/>
|
||||
<GoodsList ref="recommend" :goods="recommends"></GoodsList>
|
||||
</scroll>
|
||||
<back-top @click.native="backClick" v-show="isShowBackTop"/>
|
||||
<detail-bottom-bar @addToCart="addToCart"/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import DetailNewBar from "@/views/detail/childComps/DetailNewBar";
|
||||
import DetailSwiper from "@/views/detail/childComps/DetailSwiper";
|
||||
import DetailBaseInfo from "@/views/detail/childComps/DetailBaseInfo";
|
||||
import DetailShopInfo from "@/views/detail/childComps/DetailShopInfo";
|
||||
import DetailGoodsInfo from "@/views/detail/childComps/DetailGoodsInfo";
|
||||
import DetailParamInfo from "@/views/detail/childComps/DetailParamInfo";
|
||||
import DetailCommentInfo from "@/views/detail/childComps/DetailCommentInfo";
|
||||
import DetailBottomBar from "@/views/detail/childComps/DetailBottomBar";
|
||||
|
||||
import backTop from "@/components/content/backTop/backTop";
|
||||
import GoodsList from "@/components/content/goods/GoodsList";
|
||||
import scroll from "@/components/common/Scroll/Scroll";
|
||||
|
||||
import {itemListenerMixin,backTopMixin} from "@/common/mixin";
|
||||
import {debounce} from "@/common/utils";
|
||||
|
||||
import {getDetail, Goods, Shop, GoodsParam, getRecommend} from "@/network/detail";
|
||||
|
||||
|
||||
export default {
|
||||
name: "Detail",
|
||||
components: {
|
||||
DetailNewBar,
|
||||
DetailSwiper,
|
||||
DetailBaseInfo,
|
||||
DetailShopInfo,
|
||||
DetailGoodsInfo,
|
||||
DetailParamInfo,
|
||||
DetailCommentInfo,
|
||||
DetailBottomBar,
|
||||
|
||||
backTop,
|
||||
GoodsList,
|
||||
scroll,
|
||||
|
||||
},
|
||||
mixins: [itemListenerMixin,backTopMixin],
|
||||
data() {
|
||||
return {
|
||||
iid: null,
|
||||
topImages: [],
|
||||
goods: {},
|
||||
shop: {},
|
||||
detailInfo: {},
|
||||
paramInfo: {},
|
||||
commentInfo: {},
|
||||
recommends: [],
|
||||
themeTopYs: [],
|
||||
getThemeTopY: null,
|
||||
currentIndex:0,
|
||||
}
|
||||
},
|
||||
created() {
|
||||
//home主页传入iid
|
||||
this.iid = this.$route.params.iid
|
||||
//数据的展示
|
||||
getDetail(this.iid).then(res => {
|
||||
const data = res.data.result
|
||||
//轮播图的切换
|
||||
this.topImages = data.itemInfo.topImages
|
||||
//商品介绍
|
||||
this.goods = new Goods(data.itemInfo, data.columns, data.shopInfo.services)
|
||||
//店铺名的展示
|
||||
this.shop = new Shop(data.shopInfo)
|
||||
//穿着展示
|
||||
this.detailInfo = data.detailInfo
|
||||
//商品推荐的展示
|
||||
this.paramInfo = new GoodsParam(data.itemParams.info, data.itemParams.rule)
|
||||
|
||||
if (data.rate.list) {
|
||||
this.commentInfo = data.rate.list[0];
|
||||
}
|
||||
//导航栏点击切换
|
||||
this.getThemeTopY = debounce(() => {
|
||||
this.themeTopYs = []
|
||||
this.themeTopYs.push(0);
|
||||
this.themeTopYs.push(this.$refs.params.$el.offsetTop)
|
||||
this.themeTopYs.push(this.$refs.comment.$el.offsetTop)
|
||||
this.themeTopYs.push(this.$refs.recommend.$el.offsetTop)
|
||||
this.themeTopYs.push(Number.MAX_VALUE)
|
||||
}, 500)
|
||||
|
||||
})
|
||||
//获取评论的数据
|
||||
getRecommend().then(res => {
|
||||
this.recommends = res.data.data.list
|
||||
})
|
||||
},
|
||||
mounted() {
|
||||
},
|
||||
destroyed() {
|
||||
//无keep-live时activated无法使用
|
||||
this.$bus.$off('itemImgLoad', this.itemImgListener)
|
||||
},
|
||||
methods: {
|
||||
//上拉图片加载
|
||||
detailImageload() {
|
||||
this.itemImgListener()
|
||||
this.getThemeTopY()
|
||||
},
|
||||
//导航栏点击切换
|
||||
titleClick(index) {
|
||||
this.$refs.scroll.scrollTo(0, -this.themeTopYs[index], 1000);
|
||||
},
|
||||
//位置移动时导航栏跟着移动
|
||||
positionScroll(position) {
|
||||
const positionY = -position.y
|
||||
let length = this.themeTopYs.length
|
||||
for (let i = 0; i < length-1; i++) {
|
||||
if(this.currentIndex!==i&&(positionY>=this.themeTopYs[i]&&positionY<this.themeTopYs[i+1]))
|
||||
{
|
||||
this .currentIndex=i;
|
||||
this.$refs.nav.currentIndex=this.currentIndex
|
||||
|
||||
}
|
||||
}
|
||||
},
|
||||
//mixin混入回退顶部的按钮
|
||||
totalScroll(position){
|
||||
this.positionScroll(position)
|
||||
this.contentScoll(position)
|
||||
},
|
||||
//加入购物车
|
||||
addToCart(){
|
||||
console.log('----');
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
#detail{
|
||||
position: relative;
|
||||
z-index: 9;
|
||||
background-color: #ffffff;
|
||||
height: 100vh;
|
||||
}
|
||||
.detail-nav{
|
||||
position: relative;
|
||||
z-index: 9;
|
||||
background-color: #ffffff;
|
||||
}
|
||||
.content{
|
||||
height: calc(100% - 96px);
|
||||
position: relative;
|
||||
}
|
||||
</style>
|
@ -0,0 +1,103 @@
|
||||
<template>
|
||||
<div v-if="Object.keys(goods).length !== 0" class="base-info">
|
||||
<div class="info-title">{{goods.title}}</div>
|
||||
<div class="info-price">
|
||||
<span class="n-price">{{goods.newPrice}}</span>
|
||||
<span class="o-price">{{goods.oldPrice}}</span>
|
||||
<span class="discount">{{goods.discount}}</span>
|
||||
</div>
|
||||
<div class="info-other">
|
||||
<span>{{goods.columns[0]}}</span>
|
||||
<span>{{goods.columns[1]}}</span>
|
||||
<span>{{goods.services[goods.services.length-1].name}}</span>
|
||||
</div>
|
||||
<div class="info-service">
|
||||
<span class="info-service-item" v-for="index in goods.services.length-1" :key="index">
|
||||
<img :src="goods.services[index-1].icon">
|
||||
<span>{{goods.services[index-1].name}}</span>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: "DetailBaseInfo",
|
||||
props: {
|
||||
goods: {
|
||||
type: Object,
|
||||
default(){
|
||||
return []
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.base-info {
|
||||
margin-top: 15px;
|
||||
padding: 0 8px;
|
||||
color: #999;
|
||||
border-bottom: 5px solid #f2f5f8;
|
||||
}
|
||||
|
||||
.info-title {
|
||||
color: #222
|
||||
}
|
||||
|
||||
.info-price {
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
.info-price .n-price {
|
||||
font-size: 24px;
|
||||
color: var(--color-high-text);
|
||||
}
|
||||
|
||||
.info-price .o-price {
|
||||
font-size: 13px;
|
||||
margin-left: 5px;
|
||||
text-decoration: line-through;
|
||||
}
|
||||
|
||||
.info-price .discount {
|
||||
font-size: 12px;
|
||||
padding: 2px 5px;
|
||||
color: #fff;
|
||||
background-color: var(--color-high-text);
|
||||
border-radius: 8px;
|
||||
margin-left: 5px;
|
||||
|
||||
/*让元素上浮一些: 使用相对定位即可*/
|
||||
position: relative;
|
||||
top: -8px;
|
||||
}
|
||||
|
||||
.info-other {
|
||||
margin-top: 15px;
|
||||
line-height: 30px;
|
||||
display: flex;
|
||||
font-size: 13px;
|
||||
border-bottom: 1px solid rgba(100,100,100,.1);
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.info-service {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
line-height: 60px;
|
||||
}
|
||||
|
||||
.info-service-item img {
|
||||
width: 10px;
|
||||
height: 10px;
|
||||
position: relative;
|
||||
top: 2px;
|
||||
}
|
||||
|
||||
.info-service-item span {
|
||||
font-size: 13px;
|
||||
color: #333;
|
||||
}
|
||||
</style>
|
@ -0,0 +1,91 @@
|
||||
<template>
|
||||
<div class="bottom-bar">
|
||||
<div class="bar-item bar-left">
|
||||
<div>
|
||||
<i class="icon service"></i>
|
||||
<span class="text">客服</span>
|
||||
</div>
|
||||
<div>
|
||||
<i class="icon shop"></i>
|
||||
<span class="text">店铺</span>
|
||||
</div>
|
||||
<div>
|
||||
<i class="icon select"></i>
|
||||
<span class="text">收藏</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="bar-item bar-right">
|
||||
<div class="cart" @click="addToCart">加入购物车</div>
|
||||
<div class="buy">购买</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: "DetailBottomBar",
|
||||
methods: {
|
||||
addToCart() {
|
||||
this.$emit('addToCart')
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.bottom-bar {
|
||||
height: 58px;
|
||||
position: fixed;
|
||||
background-color: #fff;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
|
||||
display: flex;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.bar-item {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.bar-item>div {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.bar-left .text {
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
.bar-left .icon {
|
||||
display: block;
|
||||
width: 22px;
|
||||
height: 22px;
|
||||
margin: 10px auto 3px;
|
||||
background: url("~assets/img/detail/detail_bottom.png") 0 0/100%;
|
||||
}
|
||||
|
||||
.bar-left .service {
|
||||
background-position:0 -54px;
|
||||
}
|
||||
|
||||
.bar-left .shop {
|
||||
background-position:0 -98px;
|
||||
}
|
||||
|
||||
.bar-right {
|
||||
font-size: 15px;
|
||||
color: #fff;
|
||||
line-height: 58px;
|
||||
}
|
||||
|
||||
.bar-right .cart {
|
||||
background-color: #ffe817;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.bar-right .buy {
|
||||
background-color: #f69;
|
||||
}
|
||||
</style>
|
@ -0,0 +1,118 @@
|
||||
<template>
|
||||
<div>
|
||||
<div v-if="Object.keys(commentInfo).length !== 0" class="comment-info">
|
||||
<div class="info-header">
|
||||
<div class="header-title">用户评价</div>
|
||||
<div class="header-more">
|
||||
更多
|
||||
<i class="arrow-right"></i>
|
||||
</div>
|
||||
</div>
|
||||
<div class="info-user">
|
||||
<img :src="commentInfo.user.avatar" alt="">
|
||||
<span>{{commentInfo.user.uname}}</span>
|
||||
</div>
|
||||
<div class="info-detail">
|
||||
<p>{{commentInfo.content}}</p>
|
||||
<div class="info-other">
|
||||
<span class="date">{{commentInfo.created | showDate}}</span>
|
||||
<span>{{commentInfo.style}}</span>
|
||||
</div>
|
||||
<div class="info-imgs">
|
||||
<img :src="item" v-for="(item, index) in commentInfo.images">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {formatDate} from "@/common/utils";
|
||||
|
||||
export default {
|
||||
name: "DetailCommentInfo",
|
||||
props: {
|
||||
commentInfo: {
|
||||
type: Object,
|
||||
}
|
||||
},
|
||||
filters: {
|
||||
showDate: function (value) {
|
||||
let date = new Date(value*1000);
|
||||
return formatDate(date, 'yyyy-MM-dd')
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.comment-info {
|
||||
padding: 5px 12px;
|
||||
color: #333;
|
||||
border-bottom: 5px solid #f2f5f8;
|
||||
}
|
||||
|
||||
.info-header {
|
||||
height: 50px;
|
||||
line-height: 50px;
|
||||
border-bottom: 1px solid rgba(0,0,0,.1);
|
||||
}
|
||||
|
||||
.header-title {
|
||||
float: left;
|
||||
font-size: 15px;
|
||||
}
|
||||
|
||||
.header-more {
|
||||
float: right;
|
||||
margin-right: 10px;
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
.info-user {
|
||||
padding: 10px 0 5px;
|
||||
}
|
||||
|
||||
.info-user img {
|
||||
width: 42px;
|
||||
height: 42px;
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
.info-user span {
|
||||
position: relative;
|
||||
font-size: 15px;
|
||||
top: -15px;
|
||||
margin-left: 10px;
|
||||
}
|
||||
|
||||
.info-detail {
|
||||
padding: 0 5px 15px;
|
||||
}
|
||||
|
||||
.info-detail p {
|
||||
font-size: 14px;
|
||||
color: #777;
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
.info-detail .info-other {
|
||||
font-size: 12px;
|
||||
color: #999;
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
.info-other .date {
|
||||
margin-right: 8px;
|
||||
}
|
||||
|
||||
.info-imgs {
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
.info-imgs img {
|
||||
width: 70px;
|
||||
height: 70px;
|
||||
margin-right: 5px;
|
||||
}
|
||||
</style>
|
@ -0,0 +1,90 @@
|
||||
<template>
|
||||
<div v-if="Object.keys(detailInfo).length !== 0" class="goods-info" >
|
||||
<div class="info-desc clear-fix">
|
||||
<div class="start">
|
||||
</div>
|
||||
<div class="desc">{{detailInfo.desc}}</div>
|
||||
<div class="end"></div>
|
||||
</div>
|
||||
<div class="info-key">{{detailInfo.detailImage[0].key}}</div>
|
||||
<div class="info-list">
|
||||
<img v-for="(item, index) in detailInfo.detailImage[0].list" :key="index" :src="item" alt="" @load="imgLoad">
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: "DetailGoodsInfo",
|
||||
props: {
|
||||
detailInfo: {
|
||||
type: Object
|
||||
}
|
||||
},
|
||||
data(){
|
||||
return{
|
||||
rounter:0,
|
||||
imagesLength:0,
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
imgLoad() {
|
||||
this.$emit('detailImageload')
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.goods-info {
|
||||
padding: 20px 0;
|
||||
border-bottom: 5px solid #f2f5f8;
|
||||
}
|
||||
|
||||
.info-desc {
|
||||
padding: 0 15px;
|
||||
}
|
||||
|
||||
.info-desc .start, .info-desc .end {
|
||||
width: 90px;
|
||||
height: 1px;
|
||||
background-color: #a3a3a5;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.info-desc .start {
|
||||
float: left;
|
||||
}
|
||||
|
||||
.info-desc .end {
|
||||
float: right;
|
||||
}
|
||||
|
||||
.info-desc .start::before, .info-desc .end::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
width: 5px;
|
||||
height: 5px;
|
||||
background-color: #333;
|
||||
bottom: 0;
|
||||
}
|
||||
|
||||
.info-desc .end::after {
|
||||
right: 0;
|
||||
}
|
||||
|
||||
.info-desc .desc {
|
||||
padding: 15px 0;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.info-key {
|
||||
margin: 10px 0 10px 15px;
|
||||
color: #333;
|
||||
font-size: 15px;
|
||||
}
|
||||
|
||||
.info-list img {
|
||||
width: 100%;
|
||||
}
|
||||
</style>
|
@ -0,0 +1,56 @@
|
||||
<template>
|
||||
<nav-bar>
|
||||
<div slot="left" class="back" @click="backClick">
|
||||
<img src="~assets/img/common/back.svg" alt="">
|
||||
</div>
|
||||
<div slot="center" class="title">
|
||||
<div v-for="(item,index) in titles"
|
||||
class="title-item"
|
||||
:class="{active:index===currentIndex}" @click="titleClick(index)">
|
||||
{{item}}
|
||||
</div>
|
||||
</div>
|
||||
</nav-bar>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import NavBar from "@/components/common/navbar/NavBar";
|
||||
|
||||
export default {
|
||||
name: "DetailNewBar",
|
||||
components: {
|
||||
NavBar
|
||||
},
|
||||
data(){
|
||||
return{
|
||||
titles:['商品','参数','评论','推荐'],
|
||||
currentIndex:0,
|
||||
}
|
||||
},
|
||||
methods:{
|
||||
titleClick(index){
|
||||
this.currentIndex=index;
|
||||
this.$emit('titleClick',index)
|
||||
},
|
||||
backClick(){
|
||||
this.$router.back()
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.title{
|
||||
display: flex;
|
||||
font-size: 13px;
|
||||
}
|
||||
.title-item{
|
||||
flex:1;
|
||||
}
|
||||
.active{
|
||||
color: var(--color-high-text);
|
||||
}
|
||||
.back img{
|
||||
margin-top: 12px;
|
||||
}
|
||||
</style>
|
@ -0,0 +1,68 @@
|
||||
<template>
|
||||
<div class="param-info" v-if="Object.keys(paramInfo).length !== 0">
|
||||
<table v-for="(table, index) in paramInfo.sizes"
|
||||
class="info-size" :key="index">
|
||||
<tr v-for="(tr, indey) in table" :key="indey">
|
||||
<td v-for="(td, indez) in tr" :key="indez">{{td}}</td>
|
||||
</tr>
|
||||
</table>
|
||||
<table class="info-param">
|
||||
<tr v-for="(info, index) in paramInfo.infos">
|
||||
<td class="info-param-key">{{info.key}}</td>
|
||||
<td class="param-value">{{info.value}}</td>
|
||||
</tr>
|
||||
</table>
|
||||
<div class="info-img" v-if="paramInfo.image.length !== 0">
|
||||
<img :src="paramInfo.image" alt="">
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: "DetailParamInfo",
|
||||
props: {
|
||||
paramInfo: {
|
||||
type: Object
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.param-info {
|
||||
padding: 20px 15px;
|
||||
font-size: 14px;
|
||||
border-bottom: 5px solid #f2f5f8;
|
||||
}
|
||||
|
||||
.param-info table {
|
||||
width: 100%;
|
||||
border-collapse: collapse;
|
||||
}
|
||||
|
||||
.param-info table tr {
|
||||
height: 42px;
|
||||
}
|
||||
|
||||
.param-info table tr td {
|
||||
border-bottom: 1px solid rgba(100,100,100,.1);
|
||||
}
|
||||
|
||||
.info-param-key {
|
||||
/*当value的数据量比较大的时候, 会挤到key,所以给一个固定的宽度*/
|
||||
width: 95px;
|
||||
}
|
||||
|
||||
.info-param {
|
||||
border-top: 1px solid rgba(0,0,0,.1);
|
||||
}
|
||||
|
||||
.param-value {
|
||||
color: #eb4868
|
||||
}
|
||||
|
||||
.info-img img {
|
||||
width: 100%;
|
||||
}
|
||||
</style>
|
@ -0,0 +1,157 @@
|
||||
<template>
|
||||
<div class="shop-info">
|
||||
<div class="shop-top">
|
||||
<img :src="shop.logo">
|
||||
<span class="title">{{shop.name}}</span>
|
||||
</div>
|
||||
<div class="shop-middle">
|
||||
<div class="shop-middle-item shop-middle-left">
|
||||
<div class="info-sells">
|
||||
<div class="sells-count">
|
||||
{{shop.sells | sellCountFilter}}
|
||||
</div>
|
||||
<div class="sells-text">总销量</div>
|
||||
</div>
|
||||
<div class="info-goods">
|
||||
<div class="goods-count">
|
||||
{{shop.goodsCount}}
|
||||
</div>
|
||||
<div class="goods-text">全部宝贝</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="shop-middle-item shop-middle-right">
|
||||
<table>
|
||||
<tr v-for="(item, index) in shop.score" :key="index">
|
||||
<td>{{item.name}}</td>
|
||||
<td class="score" :class="{'score-better': item.isBetter}">{{item.score}}</td>
|
||||
<td class="better" :class="{'better-more': item.isBetter}"><span>{{item.isBetter ? '高':'低'}}</span></td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
<div class="shop-bottom">
|
||||
<div class="enter-shop">进店逛逛</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: "DetailShopInfo",
|
||||
props: {
|
||||
shop: {
|
||||
type: Object,
|
||||
default(){
|
||||
return []
|
||||
}
|
||||
}
|
||||
},
|
||||
filters: {
|
||||
sellCountFilter: function (value) {
|
||||
if (value < 10000) return value;
|
||||
return (value/10000).toFixed(1) + '万'
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.shop-info {
|
||||
padding: 25px 8px;
|
||||
border-bottom: 5px solid #f2f5f8;
|
||||
}
|
||||
|
||||
.shop-top {
|
||||
line-height: 45px;
|
||||
/* 让元素垂直中心对齐 */
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.shop-top img {
|
||||
width: 45px;
|
||||
height: 45px;
|
||||
border-radius: 50%;
|
||||
border: 1px solid rgba(0,0,0,.1);
|
||||
}
|
||||
|
||||
.shop-top .title {
|
||||
margin-left: 10px;
|
||||
vertical-align: center;
|
||||
}
|
||||
|
||||
.shop-middle {
|
||||
margin-top: 15px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.shop-middle-item {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.shop-middle-left {
|
||||
display: flex;
|
||||
justify-content: space-evenly;
|
||||
color: #333;
|
||||
text-align: center;
|
||||
border-right: 1px solid rgba(0,0,0,.1);
|
||||
}
|
||||
|
||||
.sells-count, .goods-count {
|
||||
font-size: 18px;
|
||||
}
|
||||
|
||||
.sells-text, .goods-text {
|
||||
margin-top: 10px;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.shop-middle-right {
|
||||
font-size: 13px;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.shop-middle-right table {
|
||||
width: 120px;
|
||||
margin-left: 30px;
|
||||
}
|
||||
|
||||
.shop-middle-right table td {
|
||||
padding: 5px 0;
|
||||
}
|
||||
|
||||
.shop-middle-right .score {
|
||||
color: #5ea732;
|
||||
}
|
||||
|
||||
.shop-middle-right .score-better {
|
||||
color: #f13e3a;
|
||||
}
|
||||
|
||||
.shop-middle-right .better span {
|
||||
background-color: #5ea732;
|
||||
color: #fff;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.shop-middle-right .better-more span {
|
||||
background-color: #f13e3a;
|
||||
}
|
||||
|
||||
.shop-bottom {
|
||||
text-align: center;
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
.enter-shop {
|
||||
display: inline-block;
|
||||
font-size: 14px;
|
||||
background-color: #f2f5f8;
|
||||
width: 150px;
|
||||
height: 30px;
|
||||
text-align: center;
|
||||
line-height: 30px;
|
||||
border-radius: 10px;
|
||||
}
|
||||
</style>
|
@ -0,0 +1,35 @@
|
||||
<template>
|
||||
<swiper class="swiper-item">
|
||||
<swiper-item v-for="(item,index) in topImages">
|
||||
<img :src="item" :key="index" alt="">
|
||||
</swiper-item>
|
||||
</swiper>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {Swiper,SwiperItem} from '@/components/common/swiper'
|
||||
|
||||
|
||||
export default {
|
||||
name: "DetailSwiper",
|
||||
props:{
|
||||
topImages:{
|
||||
type:Array,
|
||||
default(){
|
||||
return []
|
||||
}
|
||||
}
|
||||
},
|
||||
components:{
|
||||
SwiperItem,
|
||||
Swiper,
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.swiper-item{
|
||||
height: 200px;
|
||||
overflow: hidden;
|
||||
}
|
||||
</style>
|
@ -0,0 +1,42 @@
|
||||
<template>
|
||||
<div class="recommends">
|
||||
<div v-for="item in recommends" class="recommends-item">
|
||||
<a :href="item.link">
|
||||
<img :src="item.image" alt="">
|
||||
<div>{{item.title}}</div>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: "HomeRecommendView",
|
||||
props:{
|
||||
recommends:{
|
||||
type:Array,
|
||||
default() {
|
||||
return [];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.recommends{
|
||||
display: flex;
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
font-size: 12px;
|
||||
padding: 10px 0 20px;
|
||||
border-bottom: 8px solid #eee;
|
||||
}
|
||||
.recommends-item{
|
||||
flex:1;
|
||||
}
|
||||
.recommends-item img{
|
||||
width: 65px;
|
||||
height: 65px;
|
||||
}
|
||||
</style>
|
@ -0,0 +1,45 @@
|
||||
<template>
|
||||
<swiper>
|
||||
<swiperItem v-for="item in banners">
|
||||
<a :href="item.link" >
|
||||
<img :src="item.image" alt="" @load="imageLoad">
|
||||
</a>
|
||||
</swiperItem>
|
||||
</swiper>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {Swiper, SwiperItem} from "@/components/common/swiper/index"
|
||||
export default {
|
||||
name: "HomeSwiper",
|
||||
components:{
|
||||
Swiper,
|
||||
SwiperItem
|
||||
},
|
||||
props:{
|
||||
banners:{
|
||||
type:Array,
|
||||
default(){
|
||||
return[]
|
||||
}
|
||||
}
|
||||
},
|
||||
data(){
|
||||
return {
|
||||
isLoad:false
|
||||
}
|
||||
},
|
||||
methods:{
|
||||
imageLoad(){
|
||||
if(!this.isLoad) {
|
||||
this.$emit('swiperImageLoad')
|
||||
this.isLoad=true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
@ -0,0 +1,20 @@
|
||||
<template>
|
||||
<div class="feature">
|
||||
<a href="https://act.mogujie.com/zzlx67">
|
||||
<img src="@/assets/img/home/recommend_bg.jpg" alt="">
|
||||
</a>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: "HomefeatureView"
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.feature img{
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
</style>
|
@ -0,0 +1,15 @@
|
||||
<template>
|
||||
<div>
|
||||
<h2>我的</h2>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: "Profile"
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
@ -0,0 +1,13 @@
|
||||
module.exports={
|
||||
configureWebpack:{
|
||||
resolve:{
|
||||
alias:{
|
||||
'assets':'@/assets',
|
||||
'common':'@/common',
|
||||
'components':'@/components',
|
||||
'network':'@/network',
|
||||
'views':'@/views',
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|