Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
jinli gu
Litemall
Commits
104523c6
Commit
104523c6
authored
Apr 19, 2019
by
Junling Bu
Browse files
doc
parents
70c31ee4
4ee32ff6
Changes
153
Expand all
Show whitespace changes
Inline
Side-by-side
litemall-vue/src/assets/scss/iconfont/iconfont.ttf
0 → 100755
View file @
104523c6
File added
litemall-vue/src/assets/scss/mixin/_one-border.scss
0 → 100755
View file @
104523c6
@mixin
one-border
(
$direction
:
bottom
){
position
:
relative
;
&
::after
{
content
:
""
;
position
:
absolute
;
top
:
0
;
left
:
0
;
width
:
200%
;
height
:
200%
;
transform
:
scale
(
.5
);
transform-origin
:
0
0
;
pointer-events
:
none
;
box-sizing
:
border-box
;
border-
#{
$direction
}
:
1px
solid
$
border-color
;
}
}
\ No newline at end of file
litemall-vue/src/assets/scss/spinner.scss
0 → 100644
View file @
104523c6
@keyframes
lds-ball
{
0
%
,
100
%
{
animation-timing-function
:
cubic-bezier
(
0
.45
,
0
,
0
.9
,
0
.55
);
}
0
%
{
-webkit-transform
:
translate
(
0
,
0
);
transform
:
translate
(
0
,
0
);
}
50
%
{
-webkit-transform
:
translate
(
0
,
108px
);
transform
:
translate
(
0
,
108px
);
animation-timing-function
:
cubic-bezier
(
0
,
0
.45
,
0
.55
,
0
.9
);
}
100
%
{
-webkit-transform
:
translate
(
0
,
0
);
transform
:
translate
(
0
,
0
);
}
}
@-webkit-keyframes
lds-ball
{
0
%
,
100
%
{
animation-timing-function
:
cubic-bezier
(
0
.45
,
0
,
0
.9
,
0
.55
);
}
0
%
{
-webkit-transform
:
translate
(
0
,
0
);
transform
:
translate
(
0
,
0
);
}
50
%
{
-webkit-transform
:
translate
(
0
,
108px
);
transform
:
translate
(
0
,
108px
);
animation-timing-function
:
cubic-bezier
(
0
,
0
.45
,
0
.55
,
0
.9
);
}
100
%
{
-webkit-transform
:
translate
(
0
,
0
);
transform
:
translate
(
0
,
0
);
}
}
.lds-ball
{
position
:
relative
;
}
.lds-ball
div
{
width
:
52px
;
height
:
52px
;
border-radius
:
50%
;
background
:
#e15b64
;
-webkit-animation
:
lds-ball
1s
linear
infinite
;
animation
:
lds-ball
1s
linear
infinite
;
}
.lds-ball
{
position
:
fixed
;
left
:
50%
;
top
:
30%
;
transform
:
translateX
(
-50%
);
}
\ No newline at end of file
litemall-vue/src/core/async-loader.js
0 → 100644
View file @
104523c6
// 使用这个会导致组件内部的 router 导航守卫无法使用, 慎用
/**
* @param { string } chunkPath views 文件夹下的页面路径
* @return { function } 返回 promise<component> 的匿名函数
*/
import
spinner
from
'
@/vue/components/spinner
'
;
export
default
chunkPath
=>
{
const
AsyncHandler
=
()
=>
({
component
:
new
Promise
(
resolve
=>
{
setTimeout
(()
=>
{
resolve
(
import
(
/* webpackChunkName: "[request]" */
`@/views/
${
chunkPath
}
`
)
);
},
1000
);
}),
loading
:
spinner
,
error
:
{
render
(
h
)
{
return
h
(
'
div
'
,
{},
[
'
异步组件加载失败
'
]);
}
},
timeout
:
10000
});
return
()
=>
Promise
.
resolve
({
functional
:
true
,
render
(
h
,
{
data
,
children
})
{
return
h
(
AsyncHandler
,
data
,
children
);
}
});
};
litemall-vue/src/core/regexp/index.js
0 → 100755
View file @
104523c6
export
const
idCard
=
/^
[
1-9
]{1}[
0-9
]{14}
$|^
[
1-9
]{1}[
0-9
]{16}([
0-9
]
|
[
xX
])
$/
;
export
const
mobileReg
=
/^1
[
0-9
]{10}
$/
;
export
const
address
=
val
=>
{
const
value
=
val
.
trim
();
return
value
.
length
>=
5
&&
value
.
length
<=
100
;
};
export
const
userName
=
/^
[
a-zA-Z0-9_
\u
4e00-
\u
9fa5
]{3,20}
$/
;
export
const
emailReg
=
/^
(\w)
+
(\.\w
+
)
*@
(\w)
+
((\.\w
+
)
+
)
$/
;
litemall-vue/src/core/utils/local-storage.js
0 → 100644
View file @
104523c6
export
const
getLocalStorage
=
(...
args
)
=>
{
const
storage
=
{};
args
.
forEach
(
arg
=>
{
storage
[
arg
]
=
window
.
localStorage
.
getItem
(
arg
)
||
null
;
});
return
storage
;
};
export
const
setLocalStorage
=
data
=>
{
Object
.
keys
(
data
).
forEach
(
prop
=>
{
const
el
=
data
[
prop
];
window
.
localStorage
.
setItem
(
prop
,
el
);
});
};
export
const
removeLocalStorage
=
(...
args
)
=>
{
args
.
forEach
(
arg
=>
{
window
.
localStorage
.
removeItem
(
arg
);
});
};
litemall-vue/src/core/utils/location-param.js
0 → 100644
View file @
104523c6
export
default
name
=>
{
const
reg
=
new
RegExp
(
`(^|&)
${
name
}
=([^&]*)(&|$)`
);
const
r
=
window
.
location
.
search
.
substr
(
1
).
match
(
reg
);
if
(
r
!=
null
)
return
decodeURIComponent
(
r
[
2
]);
return
''
;
};
litemall-vue/src/core/utils/request.js
0 → 100755
View file @
104523c6
// import axios from 'axios'
// import { Message, MessageBox } from 'element-ui'
// import store from '@/store'
// import { getToken } from '@/utils/auth'
// // create an axios instance
// const service = axios.create({
// baseURL: process.env.BASE_API, // api 的 base_url
// timeout: 5000 // request timeout
// })
// // request interceptor
// service.interceptors.request.use(
// config => {
// // Do something before request is sent
// if (store.getters.token) {
// // 让每个请求携带token-- ['X-Litemall-Admin-Token']为自定义key 请根据实际情况自行修改
// config.headers['X-Litemall-Admin-Token'] = getToken()
// }
// return config
// },
// error => {
// // Do something with request error
// console.log(error) // for debug
// Promise.reject(error)
// }
// )
// // response interceptor
// service.interceptors.response.use(
// response => {
// const res = response.data
// if (res.errno === 501) {
// MessageBox.alert('系统未登录,请重新登录', '错误', {
// confirmButtonText: '确定',
// type: 'error'
// }).then(() => {
// store.dispatch('FedLogOut').then(() => {
// location.reload()
// })
// })
// return Promise.reject('error')
// } else if (res.errno === 502) {
// MessageBox.alert('系统内部错误,请联系管理员维护', '错误', {
// confirmButtonText: '确定',
// type: 'error'
// })
// return Promise.reject('error')
// } else if (res.errno === 503) {
// MessageBox.alert('请求业务目前未支持', '警告', {
// confirmButtonText: '确定',
// type: 'error'
// })
// return Promise.reject('error')
// } else if (res.errno === 504) {
// MessageBox.alert('更新数据已经失效,请刷新页面重新操作', '警告', {
// confirmButtonText: '确定',
// type: 'error'
// })
// return Promise.reject('error')
// } else if (res.errno === 505) {
// MessageBox.alert('更新失败,请再尝试一次', '警告', {
// confirmButtonText: '确定',
// type: 'error'
// })
// return Promise.reject('error')
// } else if (res.errno === 506) {
// MessageBox.alert('没有操作权限,请联系管理员授权', '错误', {
// confirmButtonText: '确定',
// type: 'error'
// })
// return Promise.reject('error')
// } else if (res.errno !== 0) {
// // 非5xx的错误属于业务错误,留给具体页面处理
// return Promise.reject(response)
// } else {
// return response
// }
// }, error => {
// console.log('err' + error)// for debug
// Message({
// message: '登录连接超时(后台不能连接,请联系系统管理员)',
// type: 'error',
// duration: 5 * 1000
// })
// return Promise.reject(error)
// })
// export default service
litemall-vue/src/core/utils/scroll.js
0 → 100755
View file @
104523c6
export
default
{
isAttached
(
element
)
{
let
currentNode
=
element
.
parentNode
;
while
(
currentNode
)
{
if
(
currentNode
.
tagName
===
'
HTML
'
)
{
return
true
;
}
if
(
currentNode
.
nodeType
===
11
)
{
return
false
;
}
currentNode
=
currentNode
.
parentNode
;
}
return
false
;
},
getScrollLeft
(
element
)
{
return
'
scrollLeft
'
in
element
?
element
.
scrollLeft
:
element
.
pageXOffset
;
},
getVisibleHeight
(
element
)
{
return
element
===
window
?
element
.
innerHeight
:
element
.
getBoundingClientRect
().
height
;
},
getVisibleWidth
(
element
)
{
return
element
===
window
?
element
.
innerWidth
:
element
.
getBoundingClientRect
().
width
;
}
};
litemall-vue/src/main.js
0 → 100644
View file @
104523c6
import
Vue
from
'
vue
'
;
import
App
from
'
./App.vue
'
;
import
router
from
'
./vue/router
'
;
import
'
./assets/scss/global.scss
'
;
import
'
@/assets/scss/iconfont/iconfont.css
'
;
import
VeeValidate
,
{
Validator
}
from
'
vee-validate
'
;
import
VueCountdown
from
'
@/vue/plugins/vue-countdown
'
;
import
zhCN
from
'
vee-validate/dist/locale/zh_CN
'
;
import
axios
from
'
@/vue/plugins/axios
'
;
import
filters
from
'
@/vue/filter
'
;
Vue
.
use
(
VueCountdown
);
Vue
.
use
(
axios
);
Vue
.
use
(
filters
);
Validator
.
localize
(
'
zh-CN
'
,
zhCN
);
Vue
.
use
(
VeeValidate
,
{
locale
:
'
zh-CN
'
});
import
{
Lazyload
,
Icon
,
Cell
,
CellGroup
,
loading
,
Button
,
Toast
}
from
'
vant
'
;
Vue
.
use
(
Icon
);
Vue
.
use
(
Cell
);
Vue
.
use
(
CellGroup
);
Vue
.
use
(
loading
);
Vue
.
use
(
Button
);
Vue
.
use
(
Toast
);
Vue
.
use
(
Lazyload
,
{
preLoad
:
1.3
,
error
:
require
(
'
@/assets/images/goods_default.png
'
),
loading
:
require
(
'
@/assets/images/goods_default.png
'
),
attempt
:
1
,
listenEvents
:
[
'
scroll
'
],
lazyComponent
:
true
});
Vue
.
config
.
productionTip
=
false
;
new
Vue
({
router
,
render
:
h
=>
h
(
App
)
}).
$mount
(
'
#app
'
);
litemall-vue/src/views/home/tabbar-home-shop-info.vue
0 → 100755
View file @
104523c6
<
template
>
<van-cell-group>
<van-cell>
<van-notice-bar
:text=
"notice"
background=
"white"
:leftIcon=
"trumpet"
style=
"padding-left: 0"
/>
</van-cell>
<van-cell
:title=
"address"
icon=
"dingwei"
isLink
:url=
"mapSrc"
></van-cell>
<van-cell
icon=
"phone"
isLink
>
<template
slot=
"title"
>
<a
:href=
"'tel:' + mobile"
class=
"store_mobile"
>
{{
mobile
}}
</a>
</
template
>
</van-cell>
</van-cell-group>
</template>
<
script
>
import
{
NoticeBar
}
from
'
vant
'
;
import
trumpet
from
'
@/assets/images/trumpet.png
'
;
export
default
{
name
:
'
shop-info-group
'
,
props
:
{
address
:
{
type
:
String
,
required
:
true
},
mobile
:
{
type
:
String
,
required
:
true
},
notice
:
{
type
:
String
,
default
:
''
},
location
:
Object
},
data
()
{
const
{
location
}
=
this
;
const
MAP_PATH
=
`http://m.amap.com/navi/?dest=
${
location
.
lat
}
,
${
location
.
lng
}
&key=ab67b14d58d47912a9feb63ba862450c&destName=
${
location
.
name
}
`
;
return
{
trumpet
,
mapSrc
:
location
?
MAP_PATH
:
'
#
'
};
},
created
()
{},
components
:
{
[
NoticeBar
.
name
]:
NoticeBar
}
};
</
script
>
<
style
lang=
"scss"
scoped
>
.store_mobile
{
color
:
#0000a0
;
text-decoration
:
underline
;
}
</
style
>
litemall-vue/src/views/home/tabbar-home-sign-board.vue
0 → 100755
View file @
104523c6
<
template
>
<div
class=
"signboard"
>
<img
:src=
"boardUrl"
:height=
"signboardHeight"
width=
"100%"
>
<div
class=
"store_opacity clearfix"
>
<div
class=
"float-l"
>
{{
storeName
}}
</div>
<div
class=
"float-r store_collect isCollect"
@
click=
"showCollect = true"
>
<van-icon
name=
"shoucang-full"
/>
<span>
收藏
</span>
</div>
</div>
<van-popup
v-model=
"showCollect"
position=
"top"
style=
"background-color: transparent"
>
<img
:src=
"showCollect && collectImg"
@
click=
"showCollect = false"
width=
"100%"
alt=
"右上角收藏"
>
</van-popup>
</div>
</
template
>
<
script
>
import
{
Popup
}
from
'
vant
'
;
import
collectImg
from
'
@/assets/images/index_collect.png
'
;
export
default
{
name
:
'
sign-board
'
,
props
:
{
boardUrl
:
{
type
:
String
,
required
:
true
},
storeName
:
{
type
:
String
,
required
:
true
}
},
data
()
{
const
clientW
=
document
.
body
.
clientWidth
||
document
.
documentElement
.
clientWidth
;
const
signboardHeight
=
clientW
?
(
clientW
*
2
)
/
3
:
250
;
return
{
signboardHeight
,
showCollect
:
false
,
collectImg
};
},
components
:
{
[
Popup
.
name
]:
Popup
}
};
</
script
>
<
style
lang=
"scss"
scoped
>
.signboard
{
position
:
relative
;
min-height
:
250px
;
}
.store_opacity
{
position
:
absolute
;
bottom
:
0
;
color
:
#fff
;
width
:
100%
;
background-image
:
linear-gradient
(
rgba
(
0
,
0
,
0
,
0
)
,
rgba
(
0
,
0
,
0
,
1
));
padding
:
15px
10px
;
box-sizing
:
border-box
;
}
.isCollect
i
{
color
:
$red
;
}
</
style
>
litemall-vue/src/views/home/tabbar-home.vue
0 → 100755
View file @
104523c6
<
template
>
<div
class=
"tab_home"
>
<div
class=
"tal_class_searchBox"
>
<van-search
placeholder=
"点击前往搜索"
@
click=
"$router.push(
{ name: 'search' })"/>
<div
class=
"tal_class_searchMask"
></div>
</div>
<van-swipe
:autoplay=
"3000"
indicator-color=
"white"
>
<van-swipe-item
v-for=
"(image, index) in brandList"
:key=
"index"
>
<img
:src=
"image"
style=
"height:230px"
>
</van-swipe-item>
</van-swipe>
<van-tabbar
active-color=
"#7d7e80"
v-model=
"active"
class=
"goods-channel"
>
<van-tabbar-item
@
click=
"changeTabbar(iconJson)"
style=
"font-size:14px"
v-if=
"index
<
5"
v-for=
"(iconJson, index) in shopInfos.channel"
:key=
"index"
:icon=
"iconJson.iconUrl"
>
{{
iconJson
.
name
}}
</van-tabbar-item>
</van-tabbar>
<van-tabbar
active-color=
"#7d7e80"
v-model=
"active"
class=
"goods-channel"
>
<van-tabbar-item
@
click=
"changeTabbar(iconJson)"
style=
"font-size:14px"
v-if=
"index >= 5"
v-for=
"(iconJson, index) in shopInfos.channel"
:key=
"index"
:icon=
"iconJson.iconUrl"
>
{{
iconJson
.
name
}}
</van-tabbar-item>
<van-tabbar-item></van-tabbar-item>
</van-tabbar>
<!--
<van-panel
title=
"优惠券"
style=
" padding-bottom: 10px;"
>
<div
class=
"van-coupon-item"
v-for=
"(coupon,index) in shopInfos.couponList"
:key=
"index"
@
click=
"getCoupon(coupon.id)"
>
<div
class=
"van-coupon-item__content"
>
<div
class=
"van-coupon-item__head"
>
<h2>
<span>
¥
</span>
{{
coupon
.
discount
}}
元
</h2>
<p>
{{
coupon
.
desc
}}
-
{{
coupon
.
tag
}}
</p>
</div>
<div
class=
"van-coupon-item__body"
>
<h2>
{{
coupon
.
name
}}
</h2>
<p>
有效期:
{{
coupon
.
days
}}
天
</p>
</div>
</div>
</div>
</van-panel>
-->
<van-panel
title=
"团购专区"
>
<!--
{{
shopInfos
.
grouponList
}}
-->
<van-card
:thumb-link=
"goDetail(groupGood.goods.id)"
v-for=
"(groupGood ,index) in shopInfos.grouponList"
:key=
"index"
:title=
"groupGood.goods.name"
:desc=
"groupGood.goods.brief"
:num=
"groupGood.groupon_member"
:origin-price=
"groupGood.goods.counterPrice"
:price=
"groupGood.goods.retailPrice +'.00'"
:thumb=
"groupGood.goods.picUrl"
@
native-click=
"goDetail(groupGood.goods.id)"
>
<!--
<div
slot=
"footer"
>
添加日期
{{
item
.
addTime
}}
</div>
-->
</van-card>
</van-panel>
<van-panel
title=
"新品首发"
>
<!--
{{
shopInfos
.
grouponList
}}
-->
<van-row
gutter
>
<van-col
span=
"12"
v-for=
"(newGood ,index) in shopInfos.newGoodsList"
:key=
"index"
>
<router-link
:to=
"
{ path: `/items/detail/${newGood.id}`}">
<img
:src=
"newGood.picUrl"
style=
"width:180px;height:180px;"
>
</router-link>
<span
style=
"padding-left: 20px;position: relative;bottom: 10px; color: rgb(123, 116, 116);white-space: nowrap;"
>
{{
newGood
.
name
}}
</span>
<span
style=
"padding-left: 80px;position: relative;bottom: 10px; color:#ab956d"
>
¥
{{
newGood
.
retailPrice
}}
</span>
</van-col>
</van-row>
</van-panel>
<van-panel
title=
"人气推荐"
>
<!--
{{
shopInfos
.
grouponList
}}
-->
<van-card
:thumb-link=
"goDetail(groupGood.id)"
v-for=
"(groupGood ,index) in shopInfos.hotGoodsList"
:key=
"index"
:title=
"groupGood.name"
:desc=
"groupGood.brief"
:origin-price=
"groupGood.counterPrice"
:price=
"groupGood.retailPrice +'.00'"
:thumb=
"groupGood.picUrl"
@
native-click=
"goDetail(groupGood.id)"
>
<!--
<div
slot=
"footer"
>
添加日期
{{
item
.
addTime
}}
</div>
-->
</van-card>
</van-panel>
<!--
<van-list
v-model=
"loading"
class=
"scroll-load"
:finished=
"finished"
:immediate-check=
"false"
:offset=
"100"
@
load=
"loadMore"
>
<item-group
v-for=
"( group, key ) in itemGroup"
v-if=
"group"
:key=
"key"
class=
"interval_bot"
:setting=
"group.setting"
>
<component
v-for=
"item in group.items"
:goods=
"item"
:key=
"item.id"
:is=
"getStyle(group.setting.style)"
@
click=
"toGoods(item)"
>
<div
slot=
"mask"
v-if=
"lootAll(item)"
>
<img
src=
"../../assets/images/not_enough.png"
alt=
"已抢光"
>
</div>
<div
slot=
"leftTopIcon"
v-if=
"item.as_status
<
2"
>
<img
:src=
"mxStatus(item.as_status)"
alt=
"秒杀"
>
</div>
</component>
</item-group>
</van-list>
-->
</div>
</
template
>
<
script
>
import
{
HOME_module
,
ALL_GOODS
}
from
'
@/api/shop
'
;
import
getLocationParam
from
'
core/utils/location-param
'
;
import
mx_be_to
from
'
@/assets/images/mx_be_to.png
'
;
import
mx_start
from
'
@/assets/images/mx_start.png
'
;
import
SignBoard
from
'
./tabbar-home-sign-board
'
;
import
ShopInfoGroup
from
'
./tabbar-home-shop-info
'
;
import
ItemGroup
from
'
@/vue/components/item-group/
'
;
import
ItemCardVert
from
'
@/vue/components/item-card-vert/
'
;
import
ItemCardHori
from
'
@/vue/components/item-card-hori/
'
;
import
loadMore
from
'
@/vue/mixin/list-load-more
'
;
import
scrollFixed
from
'
@/vue/mixin/scroll-fixed
'
;
import
_
from
'
lodash
'
;
const
coupon
=
{
available
:
1
,
discount
:
0
,
denominations
:
150
,
originCondition
:
0
,
reason
:
''
,
value
:
150
,
name
:
'
优惠券名称
'
,
startAt
:
1489104000
,
endAt
:
1514592000
};
import
{
List
,
Swipe
,
SwipeItem
,
Tabbar
,
TabbarItem
,
Search
,
Panel
,
CouponCell
,
CouponList
,
Toast
,
Card
,
Row
,
Col
}
from
'
vant
'
;
export
default
{
mixins
:
[
loadMore
,
scrollFixed
],
data
()
{
const
shop_id
=
getLocationParam
(
'
shop_id
'
);
return
{
shop_id
,
brandList
:
[],
shopInfos
:
[],
shopInfo
:
null
,
coupons
:
[
coupon
],
itemGroup
:
{
mx_goods
:
null
,
activity_seckill
:
null
,
shop_recommend
:
null
,
goods
:
null
},
mx_be_to
,
mx_start
,
isLoading
:
false
};
},
computed
:
{
location
()
{
const
shopInfo
=
this
.
shopInfo
;
const
local
=
{
name
:
shopInfo
.
shop_name
,
lat
:
shopInfo
.
lat
,
lng
:
shopInfo
.
lng
};
return
local
.
lat
&&
local
.
lng
?
local
:
null
;
}
},
created
()
{
// this.initViews();
this
.
initNewViews
();
},
methods
:
{
goDetail
(
id
)
{
return
`#/items/detail/
${
id
}
`
;
},
async
getCoupon
(
id
)
{
let
errmsg
=
await
this
.
$reqPost
(
'
/wx/coupon/receive
'
,
{
couponId
:
id
});
Toast
.
success
(
'
领取成功
'
);
},
async
changeTabbar
(
o
)
{
let
{
data
}
=
await
this
.
$reqGet
(
`/wx/goods/category?id=
${
o
.
id
}
`
);
let
categoryId
=
data
.
data
.
currentCategory
.
id
;
this
.
$router
.
push
({
path
:
`items/list?keyword=&itemClass=
${
categoryId
}
`
});
},
initViews
()
{
this
.
$reqGet
(
HOME_module
,
{
shop_id
:
this
.
shop_id
,
'
per-page
'
:
this
.
pages
.
perPage
,
page
:
1
}).
then
(
res
=>
{
const
{
shop_info
,
page
}
=
res
.
data
.
data
;
const
{
mx_goods
,
shop_recommend
,
activity_seckill
,
goods
}
=
this
.
decorate
(
res
.
data
.
data
);
this
.
shopInfo
=
shop_info
;
this
.
itemGroup
.
mx_goods
=
mx_goods
;
this
.
itemGroup
.
shop_recommend
=
shop_recommend
;
this
.
itemGroup
.
activity_seckill
=
activity_seckill
;
this
.
itemGroup
.
goods
=
goods
;
this
.
setPages
(
page
);
});
},
initNewViews
()
{
this
.
$reqGet
(
'
/wx/home/index
'
).
then
(
res
=>
{
this
.
shopInfos
=
res
.
data
.
data
;
this
.
brandList
=
[];
_
.
each
(
res
.
data
.
data
.
brandList
,
v
=>
{
this
.
brandList
.
push
(
v
.
picUrl
);
});
});
},
initData
()
{
// return this.$reqGet(ALL_GOODS, {
// shop_id: this.shop_id,
// 'per-page': this.pages.perPage,
// page: this.pages.currPage
// }).then(res => {
// const { items, page } = res.data.data;
// this.itemGroup.goods && this.itemGroup.goods.items.push(...items);
// return page;
// });
},
toGoods
(
item
)
{
// 如果是秒杀商品, 并且已经抢光
if
(
this
.
lootAll
(
item
))
{
this
.
$dialog
.
alert
({
message
:
'
该秒杀商品已抢光,看看别的吧!
'
});
return
;
}
this
.
$router
.
push
({
path
:
`/items/detail/
${
item
.
id
}
`
});
},
groupIcon
(
key
)
{
const
iconGroup
=
{
activity_seckill
:
'
naozhong
'
,
goods
:
'
list
'
,
mx_goods
:
'
n4
'
,
shop_recommend
:
'
good
'
};
return
iconGroup
[
key
]
||
''
;
},
getStyle
(
style
)
{
return
style
?
'
item-card-vert
'
:
'
item-card-hori
'
;
},
decorate
({
mx_goods
,
shop_recommend
,
activity_seckill
,
goods
})
{
if
(
mx_goods
)
{
mx_goods
.
setting
.
icon
=
'
n4
'
;
mx_goods
.
setting
.
title_desc
=
'
分享得金豆
'
;
mx_goods
.
setting
.
title_color
=
'
#db3d3c
'
;
mx_goods
.
setting
.
item_len
=
mx_goods
.
items
.
length
;
}
if
(
shop_recommend
)
{
shop_recommend
.
setting
.
icon
=
'
good
'
;
shop_recommend
.
setting
.
item_len
=
shop_recommend
.
items
.
length
;
}
if
(
activity_seckill
)
{
activity_seckill
.
setting
.
icon
=
'
naozhong
'
;
activity_seckill
.
setting
.
title_color
=
'
#db3d3c
'
;
activity_seckill
.
setting
.
item_len
=
activity_seckill
.
items
.
length
;
}
if
(
goods
)
{
goods
.
setting
.
icon
=
'
list
'
;
goods
.
setting
.
item_len
=
goods
.
items
.
length
;
}
return
{
mx_goods
,
shop_recommend
,
activity_seckill
,
goods
};
},
lootAll
(
item
)
{
return
(
typeof
item
.
as_status
!==
'
undefined
'
&&
item
.
sold_num
==
item
.
total
);
},
mxStatus
(
as_status
)
{
return
as_status
?
this
.
mx_start
:
this
.
mx_be_to
;
}
},
components
:
{
// Vue.use(Tabbar).use(TabbarItem);,
[
Row
.
name
]:
Row
,
[
Col
.
name
]:
Col
,
[
Card
.
name
]:
Card
,
[
Toast
.
name
]:
Toast
,
[
CouponCell
.
name
]:
CouponCell
,
[
CouponList
.
name
]:
CouponList
,
[
Search
.
name
]:
Search
,
[
Panel
.
name
]:
Panel
,
[
List
.
name
]:
List
,
[
Swipe
.
name
]:
Swipe
,
[
SwipeItem
.
name
]:
SwipeItem
,
[
Tabbar
.
name
]:
Tabbar
,
[
TabbarItem
.
name
]:
TabbarItem
,
[
SignBoard
.
name
]:
SignBoard
,
[
ShopInfoGroup
.
name
]:
ShopInfoGroup
,
[
ItemGroup
.
name
]:
ItemGroup
,
[
ItemCardVert
.
name
]:
ItemCardVert
,
[
ItemCardHori
.
name
]:
ItemCardHori
}
};
</
script
>
<
style
lang=
"scss"
scoped
>
.interval_bot
{
margin-bottom
:
10px
;
}
.goods-channel
{
position
:
sticky
;
border-bottom-width
:
0px
;
}
.van-coupon-cell--selected
{
color
:
#323233
;
}
.van-coupon-list
{
height
:
100%
;
position
:
relative
;
background-color
:
#f8f8f8
;
}
.van-coupon-list__field
{
padding
:
7px
15px
;
}
.van-coupon-list__exchange
{
height
:
32px
;
line-height
:
30px
;
}
.van-coupon-list__list
{
overflow-y
:
auto
;
padding
:
15px
0
;
-webkit-box-sizing
:
border-box
;
box-sizing
:
border-box
;
-webkit-overflow-scrolling
:
touch
;
}
.van-coupon-list__close
{
left
:
0
;
bottom
:
0
;
position
:
absolute
;
font-weight
:
500
;
}
.van-coupon-list__empty
{
padding-top
:
100px
;
text-align
:
center
;
}
.van-coupon-list__empty
p
{
color
:
#969799
;
margin
:
15px
0
;
font-size
:
14px
;
line-height
:
20px
;
}
.van-coupon-list__empty
img
{
width
:
80px
;
height
:
84px
;
}
.van-coupon-item
{
overflow
:
hidden
;
border-radius
:
4px
;
margin
:
0
15px
15px
;
background-color
:
#fff
;
-webkit-box-shadow
:
0
0
4px
rgba
(
0
,
0
,
0
,
0
.1
);
box-shadow
:
0
0
4px
rgba
(
0
,
0
,
0
,
0
.1
);
}
.van-coupon-item
:active
{
background-color
:
#e8e8e8
;
}
.van-coupon-item__content
{
display
:
-
webkit-box
;
display
:
-
ms-flexbox
;
display
:
flex
;
height
:
100px
;
padding
:
24px
0
0
15px
;
-webkit-box-sizing
:
border-box
;
box-sizing
:
border-box
;
}
.van-coupon-item
h2
,
.van-coupon-item
p
{
margin
:
0
;
overflow
:
hidden
;
white-space
:
nowrap
;
text-overflow
:
ellipsis
;
}
.van-coupon-item
h2
{
height
:
34px
;
font-weight
:
500
;
line-height
:
34px
;
}
.van-coupon-item
p
{
font-size
:
12px
;
line-height
:
16px
;
color
:
#969799
;
}
.van-coupon-item__head
{
min-width
:
90px
;
}
.van-coupon-item__head
h2
{
color
:
#f44
;
font-size
:
24px
;
}
.van-coupon-item__head
h2
span
{
font-size
:
50%
;
}
.van-coupon-item__body
{
-webkit-box-flex
:
1
;
-ms-flex
:
1
;
flex
:
1
;
position
:
relative
;
border-radius
:
0
4px
4px
0
;
}
.van-coupon-item__body
h2
{
font-size
:
16px
;
}
.van-coupon-item__corner
{
top
:
16px
;
right
:
15px
;
position
:
absolute
;
}
.van-coupon-item__corner
.van-icon
{
border-color
:
#f44
;
background-color
:
#f44
;
}
.van-coupon-item__reason
{
padding
:
7px
15px
;
border-top
:
1px
dashed
#ebedf0
;
background-color
:
#fafafa
;
}
.van-coupon-item--disabled
:active
{
background-color
:
#fff
;
}
.van-coupon-item--disabled
.van-coupon-item__content
{
height
:
90px
;
}
.van-coupon-item--disabled
h2
,
.van-coupon-item--disabled
p
,
.van-coupon-item--disabled
span
{
color
:
#969799
;
}
</
style
>
litemall-vue/src/views/items/detail/EntityGroup/area.json
0 → 100755
View file @
104523c6
This diff is collapsed.
Click to expand it.
litemall-vue/src/views/items/detail/EntityGroup/index.vue
0 → 100755
View file @
104523c6
<
template
>
<div
class=
"item_cell_group"
>
<van-cell-group>
<van-cell
title=
"选择规格"
isLink
:value=
"selectSku.selectedSkuComb.sku_str"
@
click.native=
"skuClick"
/>
<van-cell
title=
"商品属性"
isLink
@
click.native=
"propsPopup = true"
/>
<!--
<van-cell
title=
"配送至"
isLink
:value=
"addressVal.area_name"
@
click.native=
"addressPopup = true"
/>
-->
<!--
<van-cell
title=
"运费"
:value=
"postFee | yuan"
/>
-->
</van-cell-group>
<van-sku
v-model=
"showSku"
:showAddCartBtn=
"showAddCartBtn"
:buyText=
"buyText"
:sku=
"skus.sku"
:goods=
"skus.goods_info"
:goodsId=
"goodsInfo.id"
:disableStepperInput=
"true"
@
buy-clicked=
"buyGoods"
@
add-cart=
"onAddCartClicked"
/>
<van-popup
v-model=
"propsPopup"
position=
"bottom"
>
<popup-props
:propsStr=
"props_str"
></popup-props>
</van-popup>
<van-popup
v-model=
"areaPopup"
position=
"bottom"
>
<popup-area
v-if=
"areaPopup"
@
confirm=
"emitAddressVal"
@
cancel=
"areaPopup = false"
/>
</van-popup>
<van-popup
v-model=
"addressPopup"
position=
"bottom"
>
<popup-address
:is-show=
"addressPopup"
:addressVal=
"addressVal"
:default-id=
"defaultId"
@
confirm=
"emitAddressVal"
@
area-click=
"areaClick"
/>
</van-popup>
</div>
</
template
>
<
script
>
const
popupArea
=
()
=>
import
(
/* webpackChunkName: "popup-area" */
'
./popup-area
'
);
import
popupAddress
from
'
./popup-address
'
;
import
popupProps
from
'
./popup-props
'
;
import
actionMixin
from
'
../mix
'
;
import
{
ADDRESS_DEFAULT
}
from
'
@/api/user
'
;
import
_
from
'
lodash
'
;
import
{
debug
}
from
'
util
'
;
// import { POST_FEE } from '@/api/shop';
function
getGoodInfoFromSpecification
(
productLists
,
compareS1
,
compareS2
)
{
if
(
productLists
.
length
===
0
)
{
return
productLists
;
}
_
.
each
(
productLists
,
v
=>
{
if
(
_
.
without
(
v
,
compareS1
,
compareS2
).
length
>
0
)
{
return
v
;
}
});
console
.
error
(
compareS1
+
'
,
'
+
compareS2
+
'
getGoodInfoFromSpecification no match !!!
'
);
return
{};
}
export
default
{
name
:
'
entity-group
'
,
props
:
{
goodsInfo
:
{
type
:
Object
,
default
:
()
=>
({})
},
specification_list
:
{
type
:
Array
,
default
:
()
=>
[]
},
selectSku
:
{
type
:
Object
,
default
:
()
=>
({})
},
addressVal
:
{
type
:
Object
,
default
:
()
=>
({})
}
},
mixins
:
[
actionMixin
],
data
()
{
const
sku
=
this
.
skuAdapter
(
this
.
goodsInfo
.
skus
,
this
.
goodsInfo
.
prop_imgs
);
const
goods_info
=
this
.
setSkuGoodsInfo
(
this
.
goodsInfo
);
const
postFee
=
this
.
goodsInfo
.
is_fenxiao
?
'
免邮费
'
:
''
;
return
{
postFee
,
cartOrBuy
:
''
,
propsPopup
:
false
,
addressPopup
:
false
,
areaPopup
:
false
,
skus
:
{
sku
,
goods_info
},
defaultId
:
-
1
};
},
computed
:
{
props_str
()
{
// this.goodsInfo.props_str = '品牌:GOON大王天使;纸尿裤尺码:S58;';
// if (this.goodsInfo.props_str) {
// return this.goodsInfo.props_str
// .split(';')
// .filter(str => str != '')
// .map(str => str.split(':'));
// }
let
props_arr
=
[];
_
.
each
(
this
.
goodsInfo
.
attribute
,
json
=>
{
props_arr
.
push
([
json
[
'
attribute
'
],
json
[
'
value
'
]]);
});
return
props_arr
||
[];
},
weight
()
{
return
parseFloat
(
this
.
goodsInfo
.
weight
)
*
this
.
selectSku
.
selectedNum
;
}
},
created
()
{
// this.getAddressDefault();
},
methods
:
{
skuClick
(
status
)
{
this
.
cartOrBuy
=
status
;
this
.
showSku
=
true
;
},
buyGoods
(
data
)
{
switch
(
this
.
cartOrBuy
)
{
case
'
cart
'
:
this
.
addCart
(
data
);
break
;
case
'
buy
'
:
this
.
bug
(
data
);
break
;
default
:
break
;
}
// this.$toast(JSON.stringify(data));
this
.
showSku
=
false
;
},
getProductId
(
s1
,
s2
)
{
var
productId
;
let
s1_name
=
_
.
find
(
this
.
specification_list
,
v
=>
{
return
v
.
id
===
s1
;
}).
value
;
let
s2_name
=
_
.
find
(
this
.
specification_list
,
v
=>
{
return
v
.
id
===
s2
;
}).
value
;
_
.
each
(
this
.
goodsInfo
.
productList
,
v
=>
{
let
result
=
_
.
without
(
v
.
specifications
,
s1_name
,
s2_name
);
if
(
result
.
length
===
0
)
{
productId
=
v
.
id
;
}
});
return
productId
;
},
getProductIdByOne
(
s1
)
{
var
productId
;
let
s1_name
=
_
.
find
(
this
.
specification_list
,
v
=>
{
return
v
.
id
===
s1
;
}).
value
;
_
.
each
(
this
.
goodsInfo
.
productList
,
v
=>
{
let
result
=
_
.
without
(
v
.
specifications
,
s1_name
);
if
(
result
.
length
===
0
)
{
productId
=
v
.
id
;
}
});
return
productId
;
},
async
bug
(
data
)
{
console
.
log
(
data
);
// debugger;
let
params
=
{
goodsId
:
data
.
goodsId
,
number
:
data
.
selectedNum
,
productId
:
this
.
getProductIdByOne
(
data
.
selectedSkuComb
.
s1
)
};
// 如果包含s2说明多种规格,目前支持两个规格
if
(
_
.
has
(
data
.
selectedSkuComb
,
'
s2
'
))
{
params
.
productId
=
this
.
getProductId
(
data
.
selectedSkuComb
.
s1
,
data
.
selectedSkuComb
.
s2
);
}
this
.
$reqPost
(
'
/wx/cart/fastadd
'
,
params
).
then
(
req
=>
{
let
cartId
=
req
.
data
.
data
;
// this.$reqGet(
// `/wx/cart/checkout?cartId=${cartId}&addressId=0&couponId=0&grouponRulesId=0`
// ).then(() => {cartId=${cartId}
this
.
$router
.
push
({
name
:
`placeOrderEntity`
,
params
:
{
cartId
:
cartId
}
});
// });
});
},
addCart
(
data
)
{
console
.
log
(
data
);
// debugger;
let
params
=
{
goodsId
:
data
.
goodsId
,
number
:
data
.
selectedNum
,
productId
:
this
.
getProductIdByOne
(
data
.
selectedSkuComb
.
s1
)
};
// 如果包含s2说明多种规格,目前支持两个规格
if
(
_
.
has
(
data
.
selectedSkuComb
,
'
s2
'
))
{
params
.
productId
=
this
.
getProductId
(
data
.
selectedSkuComb
.
s1
,
data
.
selectedSkuComb
.
s2
);
}
this
.
$reqPost
(
'
/wx/cart/add
'
,
params
).
then
(()
=>
{
this
.
$emit
(
'
cart-count
'
,
data
.
selectedNum
);
this
.
$toast
({
message
:
'
已添加至购物车
'
,
duration
:
1500
});
// this.cartInfo = String(parseInt(this.cartInfo) + 1);
});
},
onAddCartClicked
(
data
)
{
this
.
$toast
(
JSON
.
stringify
(
data
));
},
areaClick
()
{
this
.
areaPopup
=
true
;
this
.
addressPopup
=
false
;
},
emitAddressVal
(
data
)
{
this
.
$emit
(
'
update:addressVal
'
,
data
);
},
setSkuGoodsInfo
({
name
,
pic_url
,
sales_price
})
{
return
{
title
:
name
,
picture
:
pic_url
,
price
:
sales_price
};
},
getAddressDefault
()
{
localStorage
.
getItem
(
'
Authorization
'
)
&&
this
.
$reqGet
(
ADDRESS_DEFAULT
).
then
(
res
=>
{
const
data
=
res
.
data
.
data
;
this
.
defaultId
=
data
.
id
;
this
.
emitAddressVal
(
data
);
});
},
skuAdapter
(
skus
=
[],
prop_imgs
=
[])
{
// debugger;
const
tree
=
this
.
setSkuTree
(
skus
,
prop_imgs
);
const
list
=
this
.
setSkuList
(
skus
);
const
skuInfo
=
{
price
:
parseInt
(
this
.
goodsInfo
.
retailPrice
),
// 未选择规格时的价格
stock_num
:
this
.
goodsInfo
.
productList
[
0
].
number
||
1024
,
// 总库存
collection_id
:
''
,
// 无规格商品skuId取collection_id,否则取所选sku组合对应的id
none_sku
:
false
,
// 是否无规格商品
hide_stock
:
false
};
return
{
tree
,
list
,
...
skuInfo
};
},
setSkuList
(
skus
)
{
// debugger;
// return [
// // {
// // id: 2259,
// // price: this.goodsInfo.retailPrice * 100,
// // discount: 100,
// // code: '',
// // s1: this.goodsInfo.specificationList[0].valueList[0].id,
// // // s1: this.goodsInfo.productList[0].id,
// // kdt_id: 55,
// // discount_price: 0,
// // stock_num: this.goodsInfo.productList[0].number || 1024,
// // stock_mode: 0,
// // is_sell: null,
// // combin_sku: false,
// // goods_id: 946755
// // },
// // {
// // id: 2259,
// // price: this.goodsInfo.retailPrice * 100,
// // discount: 100,
// // code: '',
// // s1: this.goodsInfo.specificationList[0].valueList[1].id,
// // // s1: this.goodsInfo.productList[0].id,
// // kdt_id: 55,
// // discount_price: 0,
// // stock_num: this.goodsInfo.productList[0].number || 1024,
// // stock_mode: 0,
// // is_sell: null,
// // combin_sku: false,
// // goods_id: 946755
// // },
// // {
// // id: 2259,
// // price: this.goodsInfo.retailPrice * 100,
// // discount: 100,
// // code: '',
// // s2: this.goodsInfo.specificationList[1].valueList[0].id,
// // // s1: this.goodsInfo.productList[0].id,
// // kdt_id: 55,
// // discount_price: 0,
// // stock_num: this.goodsInfo.productList[0].number || 1024,
// // stock_mode: 0,
// // is_sell: null,
// // combin_sku: false,
// // goods_id: 946755
// // },
// // {
// // id: 2259,
// // price: this.goodsInfo.retailPrice * 100,
// // discount: 100,
// // code: '',
// // s2: this.goodsInfo.specificationList[1].valueList[1].id,
// // // s1: this.goodsInfo.productList[0].id,
// // kdt_id: 55,
// // discount_price: 0,
// // stock_num: this.goodsInfo.productList[0].number || 1024,
// // stock_mode: 0,
// // is_sell: null,
// // combin_sku: false,
// // goods_id: 946755
// // },
// {
// id: 2259, // skuId,下单时后端需要
// price: 30, // 价格(单位分)
// s1: 270, // 规格类目 k_s 为 s1 的对应规格值 id
// s2: 272, // 规格类目 k_s 为 s2 的对应规格值 id
// s3: '0', // 最多包含3个规格值,为0表示不存在该规格
// stock_num: 30 // 当前 sku 组合对应的库存
// }
// ];
var
sku_list
=
[];
// 如果是多种规格则需要特殊处理
if
(
this
.
goodsInfo
.
specificationList
.
length
>
1
)
{
_
.
each
(
this
.
goodsInfo
.
productList
,
v
=>
{
if
(
v
.
specifications
.
length
>
1
)
{
var
sku_list_obj
=
{};
_
.
each
(
v
.
specifications
,
(
specificationName
,
index
)
=>
{
sku_list_obj
[
'
s
'
+
(
~~
index
+
1
)
]
=
this
.
findSpecificationInfoByName
(
specificationName
).
id
;
});
}
sku_list_obj
.
price
=
v
.
price
*
100
;
sku_list_obj
.
stock_num
=
v
.
number
;
sku_list
.
push
(
sku_list_obj
);
});
// debugger;
}
else
{
sku_list
=
[
{
id
:
2259
,
price
:
this
.
goodsInfo
.
retailPrice
*
100
,
discount
:
100
,
code
:
''
,
s1
:
this
.
goodsInfo
.
specificationList
[
0
].
valueList
[
0
].
id
,
// s1: this.goodsInfo.productList[0].id,
kdt_id
:
55
,
discount_price
:
0
,
stock_num
:
this
.
goodsInfo
.
productList
[
0
].
number
||
1024
,
stock_mode
:
0
,
is_sell
:
null
,
combin_sku
:
false
,
goods_id
:
946755
}
];
}
return
sku_list
;
},
findSpecificationInfoByName
(
name
)
{
let
info
=
{};
_
.
each
(
this
.
specification_list
,
specification
=>
{
if
(
specification
.
value
===
name
)
{
info
=
specification
;
}
});
return
info
;
},
setSkuTree
(
skus
,
prop_imgs
)
{
// const skulist = [];
// skus.forEach(el => {
// const propImg = prop_imgs.find(img => img.props == el.props);
// el.props_str_arr = el.props_str.split(';').filter(str => str != '');
// el.props_arr = el.props.split(';').filter(str => str != '');
// el.imgUrl = propImg ? propImg.url : '';
// });
// debugger;
// skus.forEach(el => {
// el.props_str_arr.forEach((sku, i) => {
// const prop = el.props_arr[i];
// // 大规格
// const pName = sku.substr(0, sku.indexOf(':'));
// const k_id = prop.substr(0, prop.indexOf(':'));
// // 规格值 prop_values
// const vName = sku.substr(sku.indexOf(':') + 1);
// const vid = prop.substr(prop.indexOf(':') + 1);
// debugger;
// if (!skulist[i]) {
// skulist[i] = {
// k_id,
// k: pName,
// v: [
// {
// id: vid,
// name: vName,
// imgUrl: el.imgUrl
// }
// ],
// k_s: `s${i + 1}`
// };
// } else {
// const isPass = skulist[i].v.some(val => val.id == vid);
// !isPass &&
// skulist[i].v.push({
// id: vid,
// name: vName,
// imgUrl: el.imgUrl
// });
// }
// });
// });
// return skulist;
let
that
=
this
;
let
specifications
=
[];
_
.
each
(
this
.
goodsInfo
.
specificationList
,
(
v
,
k
)
=>
{
_
.
each
(
v
.
valueList
,
vv
=>
{
vv
.
name
=
vv
.
value
;
_
.
each
(
this
.
goodsInfo
.
productList
,
p
=>
{
if
(
p
.
id
===
vv
.
id
)
{
vv
.
imgUrl
=
p
.
url
;
vv
.
number
=
p
.
number
;
// vv.id = getGoodInfoFromSpecification(
// this.goodsInfo.productList,
// v.name,
// vv.value
// ).id;
//todo id
}
});
_
.
isEmpty
(
vv
.
imgUrl
)
?
(
vv
.
imgUrl
=
this
.
goodsInfo
.
productList
[
0
].
url
)
:
vv
.
imgUrl
;
});
_
.
each
(
v
.
valueList
,
v
=>
{
that
.
specification_list
.
push
(
v
);
});
specifications
.
push
({
k
:
v
.
name
,
v
:
v
.
valueList
,
k_s
:
'
s
'
+
(
~~
k
+
1
)
});
});
// _.each(this.goodsInfo.productList, v => {
// v.imgUrl = v.url;
// v.specification = v.specifications[0];
// });
// specifications.push({
// k: '规格',
// v: this.goodsInfo.productList,
// k_s: 's1'
// });
// debugger;
return
specifications
;
}
},
components
:
{
popupArea
,
[
popupAddress
.
name
]:
popupAddress
,
[
popupProps
.
name
]:
popupProps
}
};
</
script
>
<
style
lang=
"scss"
scoped
>
</
style
>
litemall-vue/src/views/items/detail/EntityGroup/popup-address.vue
0 → 100755
View file @
104523c6
<
template
>
<div
class=
"popup_wrap address_wrap"
>
<van-icon
name=
"clear"
class=
"cancel_popup"
@
click.native=
"hide"
></van-icon>
<!--
<div
class=
"popup_header"
>
配送至
</div>
-->
<div
class=
"popup_content"
>
<van-loading
v-if=
"!addressReady"
class=
"address_popup_load"
type=
"circle"
color=
"black"
/>
<div
v-for=
"(li, i) in address_list"
:key=
"i"
@
click=
"listChoose(li)"
>
<van-tag
plain
type=
"danger"
style=
"margin-right: 5px;"
v-if=
"li.isDefault"
>
默认
</van-tag>
{{
li
.
area_name
+
li
.
address
}}
<van-icon
name=
"success"
class=
"address_active"
v-show=
"addressVal.id == li.id"
></van-icon>
</div>
</div>
<div
class=
"popup_footer"
>
<van-cell-group>
<van-cell
is-link
title=
"其他区域"
@
click.native=
"areaChoose"
></van-cell>
</van-cell-group>
</div>
</div>
</
template
>
<
script
>
import
{
ADDRESS
}
from
'
@/api/user
'
;
import
{
Tag
}
from
'
vant
'
;
export
default
{
name
:
'
popup-address
'
,
props
:
{
isShow
:
Boolean
,
defaultId
:
[
Number
,
String
],
addressVal
:
{
type
:
Object
,
default
:
()
=>
({})
}
},
data
()
{
return
{
addressReady
:
false
,
address_list
:
[],
address_default
:
{}
};
},
watch
:
{
isShow
(
val
)
{
val
&&
!
this
.
address_list
.
length
&&
this
.
getAddress
();
}
},
created
()
{
!
this
.
address_list
.
length
&&
this
.
getAddress
();
},
methods
:
{
hide
()
{
this
.
$parent
.
$emit
(
'
input
'
,
false
);
},
getAddress
()
{
if
(
localStorage
.
getItem
(
'
Authorization
'
))
{
this
.
$reqGet
(
ADDRESS
).
then
(
res
=>
{
const
data
=
res
.
data
.
data
.
map
(
data
=>
{
data
.
isDefault
=
data
.
id
==
this
.
defaultId
;
return
data
;
});
this
.
address_list
=
data
;
this
.
addressReady
=
true
;
});
}
else
{
this
.
address_list
=
[];
this
.
addressReady
=
true
;
}
},
listChoose
(
li
)
{
this
.
$emit
(
'
confirm
'
,
li
);
this
.
hide
();
},
areaChoose
()
{
this
.
$emit
(
'
area-click
'
,
true
);
}
},
components
:
{
[
Tag
.
name
]:
Tag
}
};
</
script
>
<
style
lang=
"scss"
scoped
>
@import
'../../../../assets/scss/var'
;
@import
'../../../../assets/scss/mixin'
;
.popup_wrap
{
position
:
relative
;
padding-bottom
:
30px
;
box-sizing
:
border-box
;
.popup_header
{
padding
:
15px
0
30px
0
;
text-align
:
center
;
}
.popup_content
{
min-height
:
150px
;
max-height
:
400px
;
box-sizing
:
border-box
;
overflow-x
:
hidden
;
overflow-y
:
scroll
;
padding
:
0
10px
;
line-height
:
30px
;
&
::-webkit-scrollbar
{
background-color
:
#fff
;
width
:
5px
;
}
&
::-webkit-scrollbar-thumb
{
border-radius
:
3px
;
background-color
:
#bebebe
;
}
ol
{
padding-left
:
15px
;
list-style
:
decimal
;
}
}
.cancel_popup
{
position
:
absolute
;
right
:
15px
;
top
:
15px
;
z-index
:
9
;
font-size
:
18px
;
}
}
.address_wrap
{
.popup_header
{
@include
one-border
;
text-align
:
left
;
padding-bottom
:
15px
;
padding-left
:
10px
;
margin-bottom
:
15px
;
}
.popup_content
{
@include
one-border
;
line-height
:
22px
;
max-height
:
300px
;
overflow-x
:
hidden
;
overflow-y
:
auto
;
>
div
{
position
:
relative
;
margin-bottom
:
10px
;
padding-right
:
30px
;
}
>
div
.address_popup_load
{
margin
:
0
auto
;
padding
:
0
;
}
>
div
i
{
position
:
absolute
;
right
:
0
;
top
:
50%
;
transform
:
translate
(
0
,
-50%
);
color
:
#fff
;
&
.address_active
{
color
:
$red
;
}
}
}
}
</
style
>
litemall-vue/src/views/items/detail/EntityGroup/popup-area.vue
0 → 100755
View file @
104523c6
<
template
>
<van-area
v-once
:areaList=
"areaList"
@
confirm=
"areaConfirm"
@
cancel=
"areaCanccel"
/>
</
template
>
<
script
>
import
areaList
from
'
./area.json
'
;
import
{
Area
}
from
'
vant
'
;
export
default
{
name
:
'
popup-area
'
,
data
()
{
return
{
areaList
};
},
methods
:
{
areaCanccel
()
{
this
.
$emit
(
'
cancel
'
);
},
areaConfirm
(
areaData
)
{
if
(
areaData
.
every
(
area
=>
area
.
code
!=
-
1
))
{
this
.
$emit
(
'
confirm
'
,
this
.
analyArea
(
areaData
));
this
.
$emit
(
'
cancel
'
);
}
else
{
this
.
$toast
(
'
请选择完整地区
'
);
}
},
analyArea
(
areaData
)
{
const
province
=
areaData
[
0
]
||
{};
const
city
=
areaData
[
1
]
||
{};
const
district
=
areaData
[
2
]
||
{};
return
{
id
:
null
,
area_name
:
`
${
province
.
name
}
${
city
.
name
}
${
district
.
name
}
`
,
district
:
district
.
code
,
city
:
city
.
code
,
province
:
province
.
code
};
}
},
components
:
{
[
Area
.
name
]:
Area
}
};
</
script
>
litemall-vue/src/views/items/detail/EntityGroup/popup-props.vue
0 → 100755
View file @
104523c6
<
template
>
<div
class=
"popup_wrap"
>
<van-icon
name=
"clear"
class=
"cancel_popup"
@
click.native=
"$parent.value = false"
></van-icon>
<div
class=
"popup_header"
>
商品属性
</div>
<div
class=
"popup_content"
>
<van-cell-group>
<van-cell
v-for=
"(str, i) in propsStr"
:key=
"i"
>
<van-row>
<van-col
span=
"8"
>
{{
str
[
0
]
}}
</van-col>
<van-col
span=
"16"
>
{{
str
[
1
]
}}
</van-col>
</van-row>
</van-cell>
</van-cell-group>
</div>
</div>
</
template
>
<
script
>
import
{
Row
,
Col
}
from
'
vant
'
;
export
default
{
name
:
'
popup-props
'
,
props
:
{
propsStr
:
{
type
:
Array
,
default
:
()
=>
[]
}
},
components
:
{
[
Col
.
name
]:
Col
,
[
Row
.
name
]:
Row
}
};
</
script
>
<
style
lang=
"scss"
scoped
>
.popup_wrap
{
position
:
relative
;
padding-bottom
:
30px
;
box-sizing
:
border-box
;
.popup_header
{
padding
:
15px
0
30px
0
;
text-align
:
center
;
}
.popup_content
{
min-height
:
150px
;
max-height
:
400px
;
box-sizing
:
border-box
;
overflow-x
:
hidden
;
overflow-y
:
scroll
;
padding
:
0
10px
;
line-height
:
30px
;
&
::-webkit-scrollbar
{
background-color
:
#fff
;
width
:
5px
;
}
&
::-webkit-scrollbar-thumb
{
border-radius
:
3px
;
background-color
:
#bebebe
;
}
ol
{
padding-left
:
15px
;
list-style
:
decimal
;
}
}
.cancel_popup
{
position
:
absolute
;
right
:
15px
;
top
:
15px
;
z-index
:
9
;
font-size
:
18px
;
}
}
</
style
>
litemall-vue/src/views/items/detail/VirtualGroup/index.vue
0 → 100755
View file @
104523c6
<
template
>
<div
class=
"item_cell_group"
>
<van-cell-group>
<van-cell
title=
"有效期"
value=
"2017-8-18~2018-8-19"
/>
<van-cell
title=
"选择规格"
isLink
:value=
"skuComb.sku_str"
@
click.native=
"skuClick"
/>
<van-cell
title=
"文一西路花蒋路交叉口"
isLink
url=
"http://m.amap.com/navi/?dest=120.145409,30.238695&key=ab67b14d58d47912a9feb63ba862450c&destName=三潭印月"
/>
<van-cell
isLink
v-if=
"mobile"
>
<template
slot=
"title"
>
<a
:href=
"'tel:' + mobile"
class=
"store_mobile"
>
{{
mobile
}}
</a>
</
template
>
</van-cell>
<van-cell
title=
"注意事项"
@
click.native=
"showPopup = true"
isLink
/>
</van-cell-group>
<van-sku
v-model=
"showSku"
:showAddCartBtn=
"showAddCartBtn"
:buyText=
"buyText"
:sku=
"sku.sku"
:goods=
"sku.goods_info"
:goodsId=
"sku.goods_id"
:disableStepperInput=
"true"
@
buy-clicked=
"buyGoods"
/>
<van-popup
v-model=
"showPopup"
position=
"bottom"
lockOnScroll
>
<div
class=
"popup_wrap"
>
<van-icon
name=
"clear"
class=
"cancel_popup"
@
click.native=
"showPopup = false"
></van-icon>
<div
class=
"popup_header"
>
注意事项
</div>
<div
class=
"popup_content"
>
<div>
这里是注意事项的内容:
</div>
<ol>
<li>
这里是注意意事项的内容事项的内容
</li>
<li>
这里是注意事意事项的内容项的内容
</li>
<li>
这里是注意意事项的内容事项的内容
</li>
<li>
这里是注意意事项的内容事项的内容
</li>
<li>
这里是注意意事项的内容事项的内容
</li>
<li>
这里是注意事项的内容
</li>
<li>
这里是注意意事项的内容事项的内容
</li>
<li>
这里是注意意事项的内容事项的内容
</li>
<li>
这里是注意意事项的内容事项的内容
</li>
</ol>
</div>
</div>
</van-popup>
</div>
</template>
<
script
>
// import sku from "./sku";
import
actionMixin
from
'
../mix
'
;
export
default
{
name
:
'
virtual-group
'
,
props
:
{
mobile
:
String
,
skuComb
:
{
type
:
Object
,
default
:
()
=>
({})
},
addressVal
:
{
type
:
Object
,
default
:
()
=>
({})
}
},
mixins
:
[
actionMixin
],
data
()
{
return
{
// sku,
};
},
methods
:
{
addressClick
()
{}
}
};
</
script
>
<
style
lang=
"scss"
scoped
>
.popup_wrap
{
position
:
relative
;
padding-bottom
:
30px
;
box-sizing
:
border-box
;
}
.popup_header
{
padding
:
15px
0
30px
0
;
text-align
:
center
;
}
.popup_content
{
height
:
150px
;
box-sizing
:
border-box
;
overflow-x
:
hidden
;
overflow-y
:
scroll
;
padding
:
0
10px
;
line-height
:
30px
;
&
::-webkit-scrollbar
{
background-color
:
#fff
;
width
:
5px
;
}
&
::-webkit-scrollbar-thumb
{
border-radius
:
3px
;
background-color
:
#bebebe
;
}
ol
{
padding-left
:
15px
;
list-style
:
decimal
;
}
}
.store_mobile
{
display
:
block
;
}
.cancel_popup
{
position
:
absolute
;
right
:
15px
;
top
:
15px
;
font-size
:
18px
;
}
</
style
>
litemall-vue/src/views/items/detail/index.vue
0 → 100755
View file @
104523c6
<
template
>
<div
class=
"item_detail"
>
<van-swipe
:autoplay=
"3000"
>
<van-swipe-item
v-for=
"(image, index) in itemImgs"
:key=
"index"
>
<!--
<img
v-lazy=
"image"
width=
"100%"
>
-->
<img
:src=
"image"
width=
"100%"
>
</van-swipe-item>
</van-swipe>
<van-cell-group
class=
"item_cell_group"
v-if=
"goods"
>
<van-cell
class=
"item_info"
>
<div>
<span
class=
"item_price"
>
{{
goods
.
retailPrice
*
100
|
yuan
}}
</span>
<span
class=
"item_market_price"
>
{{
goods
.
counterPrice
*
100
|
yuan
}}
</span>
</div>
<div
class=
"item-title"
>
<!--
<van-tag
plain
type=
"danger"
v-if=
"goods.is_haitao"
>
海淘
</van-tag>
-->
{{
goods
.
name
}}
</div>
<!--
<div
class=
"item_intro"
>
{{
goods
.
sell_point
}}
</div>
???-->
<!--
<div
class=
"item_dispatch"
>
发货地:
{{}}
</div>
-->
</van-cell>
</van-cell-group>
<component
v-if=
"goods"
ref=
"goodAction"
v-bind:is=
"'entity-group'"
:selectSku.sync=
"selectSku"
:addressVal.sync=
"addressVal"
:mobile=
"mobile"
:goods-info=
"goods"
@
skuBuy=
"doBuyNow"
@
cart-count=
"cartEvent"
/>
<div
class=
"item_desc"
v-if=
"goods"
>
<div
class=
"item_desc_title"
>
商品详情
</div>
<div
class=
"item_desc_wrap"
v-if=
"goods.detail.length === 0"
style=
"padding-left: 170px;"
>
<p>
无详情
</p>
</div>
<div
class=
"item_desc_wrap"
v-html=
"goods.detail"
></div>
</div>
<van-goods-action>
<!--
<van-goods-action-mini-btn
@
click=
"doContact"
icon=
"wangwang"
iconClass=
"red afterTag"
/>
-->
<van-goods-action-mini-btn
@
click=
"toCart"
icon=
"cart"
:info=
"cartInfo"
/>
<van-goods-action-mini-btn
:style=
"collectAdd ? 'color: #f7b444;':''"
@
click=
"addCollect"
icon=
"shoucang"
/>
<van-goods-action-big-btn
@
click=
"openSku('cart')"
text=
"加入购物车"
/>
<van-goods-action-big-btn
primary
@
click=
"openSku('buy')"
text=
"立即购买"
/>
</van-goods-action>
<van-popup
v-model=
"showContact"
>
<md-kefu
mobile=
"16454193338"
/>
</van-popup>
</div>
</
template
>
<
script
>
import
{
GOODS_DETAIL
}
from
'
@/api/goods
'
;
import
{
Swipe
,
SwipeItem
,
GoodsAction
,
GoodsActionBigBtn
,
GoodsActionMiniBtn
,
Popup
}
from
'
vant
'
;
import
md_kefu
from
'
@/vue/components/md-kefu/
'
;
export
default
{
props
:
{
itemId
:
[
String
,
Number
]
},
data
()
{
const
isLogin
=
!!
localStorage
.
getItem
(
'
Authorization
'
);
return
{
isLogin
,
itemImgs
:
[],
collectAdd
:
false
,
showContact
:
false
,
cartInfo
:
'
0
'
,
mobile
:
'
13454193338
'
,
selectSku
:
{
selectedNum
:
1
,
selectedSkuComb
:
{}
},
addressVal
:
{
id
:
null
,
area_name
:
''
,
district
:
''
,
city
:
''
,
province
:
''
},
goods
:
null
,
productList
:
[]
};
},
computed
:
{
// itemImgs() {
// debugger;
// return this.goods.info.gallery;
// }
},
created
()
{
this
.
initData
();
},
methods
:
{
async
initData
()
{
// let a = this.$route.params.itemId;
this
.
$reqGet
(
`/wx/goods/detail?id=
${
this
.
itemId
}
`
).
then
(
res
=>
{
this
.
goods
=
res
.
data
.
data
.
info
;
this
.
goods
.
attribute
=
res
.
data
.
data
.
attribute
;
this
.
goods
.
specificationList
=
res
.
data
.
data
.
specificationList
;
this
.
goods
.
productList
=
res
.
data
.
data
.
productList
;
this
.
productList
=
res
.
data
.
data
.
productList
;
this
.
itemImgs
=
res
.
data
.
data
.
info
.
gallery
||
[];
this
.
collectAdd
=
res
.
data
.
data
.
userHasCollect
===
1
;
}
);
let
{
data
}
=
await
this
.
$reqGet
(
'
/wx/cart/goodscount
'
);
this
.
cartInfo
=
data
.
data
;
// this.$reqGet(GOODS_DETAIL).then(res => {
// this.goods = res.data.data;
// });
},
openSku
(
status
)
{
const
goodAction
=
this
.
$refs
.
goodAction
;
goodAction
.
skuClick
(
status
);
},
cartEvent
(
count
)
{
this
.
cartInfo
=
~~
this
.
cartInfo
+
~~
count
+
''
;
},
doBuyNow
()
{
// if (
// (this.goods.has_sku && this.selectSku.sku_id) ||
// !this.goods.has_sku
// ) {
// this.$router.push({ name: 'placeOrderEntity' });
// } else {
// const goodAction = this.$refs.goodAction;
// goodAction.showSku = true;
// goodAction.isSkuBuy = true;
// }
},
addCart
()
{
// debugger;
// if (this.goods.has_sku && this.selectSku.sku_id) {
// this.$reqPost('/wx/cart/add', {
// goodsId: this.itemId,
// number: 1
// }).then(() => {
// this.$toast({
// message: '已添加至购物车',
// duration: 1500
// });
// this.cartInfo = String(parseInt(this.cartInfo) + 1);
// });
// }
},
doContact
()
{
this
.
showContact
=
true
;
},
toCart
()
{
this
.
$router
.
push
({
name
:
'
cart
'
});
},
async
addCollect
()
{
let
{
data
}
=
await
this
.
$reqPost
(
'
/wx/collect/addordelete
'
,
{
valueId
:
this
.
itemId
,
type
:
0
}
);
let
type
=
data
.
data
.
type
;
this
.
collectAdd
=
type
===
'
add
'
?
true
:
false
;
this
.
$toast
({
message
:
this
.
collectAdd
?
'
添加成功
'
:
'
取消成功
'
,
duration
:
1500
});
}
},
components
:
{
[
md_kefu
.
name
]:
md_kefu
,
[
Popup
.
name
]:
Popup
,
[
Swipe
.
name
]:
Swipe
,
[
SwipeItem
.
name
]:
SwipeItem
,
[
GoodsAction
.
name
]:
GoodsAction
,
[
GoodsActionBigBtn
.
name
]:
GoodsActionBigBtn
,
[
GoodsActionMiniBtn
.
name
]:
GoodsActionMiniBtn
,
'
entity-group
'
:
()
=>
import
(
/* webpackChunkName: "EntityGroup" */
'
./EntityGroup/index
'
),
'
virtual-group
'
:
()
=>
import
(
/* webpackChunkName: "VirtualGroup" */
'
./VirtualGroup/index.vue
'
)
}
};
</
script
>
<
style
lang=
"scss"
scoped
>
.item_detail
{
img
{
max-width
:
100%
;
}
}
.item_cell_group
{
margin-bottom
:
15px
;
}
.item_price
{
font-size
:
20px
;
color
:
$red
;
margin-right
:
10px
;
}
.item_market_price
{
color
:
$font-color-gray
;
text-decoration
:
line-through
;
font-size
:
$font-size-small
;
}
.item-title
{
line-height
:
1
.4
;
}
.item_dispatch
{
font-size
:
$font-size-small
;
color
:
$font-color-gray
;
}
.item_intro
{
line-height
:
18px
;
margin
:
5px
0
;
font-size
:
$font-size-small
;
color
:
$font-color-gray
;
overflow
:
hidden
;
text-overflow
:
ellipsis
;
display
:
-
webkit-box
;
-webkit-box-orient
:
vertical
;
-webkit-line-clamp
:
3
;
}
.item_desc
{
background-color
:
#fff
;
p
{
padding
:
0
10px
;
}
/
deep
/
img
{
max-width
:
100%
;
display
:
block
;
}
}
.item_desc_title
{
@include
one-border
;
padding
:
10px
0
;
text-align
:
center
;
}
</
style
>
Prev
1
2
3
4
5
6
7
8
Next
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment