mirror of
https://gitee.com/beijing_hongye_huicheng/lilishop-ui.git
synced 2025-12-20 09:55:53 +08:00
commit message
This commit is contained in:
149
buyer/src/components/Search.vue
Normal file
149
buyer/src/components/Search.vue
Normal file
@@ -0,0 +1,149 @@
|
||||
<template>
|
||||
<div>
|
||||
<div class="container">
|
||||
<img
|
||||
:src="logoImg"
|
||||
v-if="showLogo"
|
||||
class="logo-img"
|
||||
alt=""
|
||||
@click="$router.push('/')"
|
||||
/>
|
||||
<i-input
|
||||
v-model="searchData"
|
||||
size="large"
|
||||
class="search"
|
||||
placeholder="输入你想查找的商品"
|
||||
@keyup.enter.native="search"
|
||||
>
|
||||
<Button v-if="!store" slot="append" @click="search">搜索</Button>
|
||||
</i-input>
|
||||
<div v-if="store" class="btn-div">
|
||||
<Button class="store-search" type="warning" @click="searchStore">搜本店</Button>
|
||||
<Button class="store-search" type="primary" @click="search">搜全站</Button>
|
||||
</div>
|
||||
<template v-if="showTag">
|
||||
<div style="height:12px" v-if="promotionTags.length === 0"></div>
|
||||
<div v-else>
|
||||
<Tag
|
||||
v-for="(item, index) in promotionTags"
|
||||
:key="index"
|
||||
>
|
||||
<span class="hover-color" @click="selectTags(item)">{{ item }}</span>
|
||||
</Tag>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {getLogo} from '@/api/common.js'
|
||||
import {hotWords} from '@/api/goods.js'
|
||||
export default {
|
||||
name: 'search',
|
||||
props: {
|
||||
showTag: { // 是否展示搜索栏下方热门搜索
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
showLogo: { // 是否展示左侧logo
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
store: { // 是否为店铺页面
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
searchData: '', // 搜索内容
|
||||
logoImg: '', // pc端展示logo
|
||||
promotionTags: [] // 热门搜索列表
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
selectTags (item) {
|
||||
this.searchData = item;
|
||||
this.search();
|
||||
},
|
||||
search () {
|
||||
this.$router.push({
|
||||
path: '/goodsList',
|
||||
query: { keyword: this.searchData }
|
||||
});
|
||||
},
|
||||
searchStore () {
|
||||
this.$emit('search', this.searchData)
|
||||
}
|
||||
},
|
||||
mounted () {
|
||||
if (!this.Cookies.getItem('logo')) {
|
||||
getLogo().then(res => {
|
||||
if (res.success) {
|
||||
let logoObj = JSON.parse(res.result.settingValue)
|
||||
this.Cookies.setItem('logo', logoObj.buyerSideLogo)
|
||||
this.logoImg = logoObj.buyerSideLogo
|
||||
}
|
||||
})
|
||||
} else {
|
||||
this.logoImg = this.Cookies.getItem('logo')
|
||||
}
|
||||
this.searchData = this.$route.query.keyword
|
||||
hotWords({start: 1, end: 5}).then(res => {
|
||||
if (res.success) this.promotionTags = res.result
|
||||
})
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.container {
|
||||
margin: 30px auto;
|
||||
width: 460px;
|
||||
position: relative;
|
||||
}
|
||||
.search {
|
||||
margin: 10px 0px 5px 0;
|
||||
/deep/ .ivu-input.ivu-input-large {
|
||||
border: 2px solid $theme_color;
|
||||
font-size: 12px;
|
||||
height: 34px;
|
||||
&:focus {
|
||||
box-shadow: none;
|
||||
}
|
||||
}
|
||||
/deep/ .ivu-input-group-append {
|
||||
border: 1px solid $theme_color;
|
||||
border-left: none;
|
||||
height: 30px;
|
||||
background-color: $theme_color;
|
||||
color: #ffffff;
|
||||
button {
|
||||
font-size: 14px;
|
||||
font-weight: 600;
|
||||
line-height: 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
.logo-img {
|
||||
position: absolute;
|
||||
left: -360px;
|
||||
top: -9px;
|
||||
width: 150px;
|
||||
cursor: pointer;
|
||||
}
|
||||
.store-search{
|
||||
padding: 0 9px;
|
||||
border-radius: 0;
|
||||
&:nth-child(2){
|
||||
margin-left: -5px;
|
||||
}
|
||||
}
|
||||
.btn-div{
|
||||
position: relative;
|
||||
height: 0px;
|
||||
top: -38px;
|
||||
left: 336px;
|
||||
}
|
||||
</style>
|
||||
173
buyer/src/components/addressManage/index.vue
Normal file
173
buyer/src/components/addressManage/index.vue
Normal file
@@ -0,0 +1,173 @@
|
||||
<template>
|
||||
<div>
|
||||
<Modal v-model="showAddr" width="800" title="收件人地址">
|
||||
<Form
|
||||
:model="formData"
|
||||
ref="form"
|
||||
label-position="left"
|
||||
:label-width="100"
|
||||
:rules="ruleInline"
|
||||
>
|
||||
<FormItem label="收件人" prop="name">
|
||||
<i-input v-model="formData.name" style="width: 600px"></i-input>
|
||||
</FormItem>
|
||||
<FormItem label="收件地区" prop="address">
|
||||
<i-input
|
||||
v-model="formData.address"
|
||||
disabled
|
||||
style="width: 600px"
|
||||
></i-input>
|
||||
<Button type="primary" size="small" @click="$refs.map.showMap = true">选择</Button>
|
||||
</FormItem>
|
||||
<FormItem label="详细地址" prop="detail">
|
||||
<i-input v-model="formData.detail" style="width: 600px"></i-input>
|
||||
</FormItem>
|
||||
<FormItem label="手机号码" prop="mobile">
|
||||
<i-input v-model="formData.mobile" style="width: 600px"></i-input>
|
||||
</FormItem>
|
||||
<FormItem label="地址别名">
|
||||
<i-input
|
||||
v-model="formData.alias"
|
||||
length
|
||||
:maxlength="4"
|
||||
placeholder="请输入地址别名,例如公司"
|
||||
style="width: 600px"
|
||||
></i-input>
|
||||
</FormItem>
|
||||
<FormItem label="默认地址">
|
||||
<i-switch v-model="formData.isDefault" />
|
||||
</FormItem>
|
||||
</Form>
|
||||
<div class="mt_20" slot="footer">
|
||||
<Button @click="hide">取消</Button>
|
||||
<Button type="primary" class="mr_10" :loading="loading" @click="save">保存收货地址</Button>
|
||||
</div>
|
||||
</Modal>
|
||||
<lili-map ref="map" @getAddress="getAddress"></lili-map>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import liliMap from '@/components/map';
|
||||
import {
|
||||
newMemberAddress,
|
||||
editMemberAddress,
|
||||
getAddrDetail
|
||||
} from '@/api/address';
|
||||
export default {
|
||||
name: 'addressManage',
|
||||
props: {
|
||||
id: {
|
||||
defalut: '',
|
||||
type: String
|
||||
}
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
showAddr: false, // 控制模态框显隐
|
||||
formData: { // 表单数据
|
||||
isDefault: false
|
||||
},
|
||||
ruleInline: { // 验证规则
|
||||
name: [{ required: true, message: '请输入收件人姓名', trigger: 'blur' }],
|
||||
address: [{ required: true, message: '请输入地址', trigger: 'change' }],
|
||||
detail: [
|
||||
{ required: true, message: '请输入详细地址', trigger: 'blur' }
|
||||
],
|
||||
mobile: [
|
||||
{ required: true, message: '手机号不能为空', trigger: 'blur' },
|
||||
{
|
||||
type: 'string',
|
||||
pattern: /^1[3|4|5|6|7|8][0-9]{9}$/,
|
||||
message: '手机号格式出错',
|
||||
trigger: 'blur'
|
||||
}
|
||||
]
|
||||
},
|
||||
loading: false, // 提交的加载状态
|
||||
mapMsg: {} // 地图信息
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
save () {
|
||||
this.$refs.form.validate((valid) => {
|
||||
if (valid) {
|
||||
const params = JSON.parse(JSON.stringify(this.formData));
|
||||
params.consigneeAddressPath = params.address.replace(/\s/g, ',');
|
||||
delete params.address;
|
||||
this.loading = true;
|
||||
if (this.id) {
|
||||
editMemberAddress(params).then((res) => {
|
||||
this.loading = false;
|
||||
if (res.code === 200) {
|
||||
this.$Message.success('编辑地址成功');
|
||||
this.$emit('change', true);
|
||||
this.hide();
|
||||
}
|
||||
}).catch(() => { this.loading = false; });
|
||||
} else {
|
||||
newMemberAddress(params).then((res) => {
|
||||
this.loading = false;
|
||||
if (res.code === 200) {
|
||||
this.$Message.success('新增地址成功');
|
||||
this.$emit('change', true);
|
||||
this.hide();
|
||||
}
|
||||
}).catch(() => { this.loading = false; });
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
getAddrById (id) {
|
||||
// 获取地址详情
|
||||
getAddrDetail(id).then((res) => {
|
||||
if (res.code === 200) {
|
||||
console.log(res);
|
||||
const data = res.result;
|
||||
data.address = res.result.consigneeAddressPath.replace(/,/g, ' ');
|
||||
this.formData = data;
|
||||
}
|
||||
});
|
||||
},
|
||||
getAddress (item) {
|
||||
// 获取地图选择信息
|
||||
console.log(item);
|
||||
this.mapMsg = item;
|
||||
this.$set(this.formData, 'address', item.addr);
|
||||
this.$set(this.formData, 'consigneeAddressIdPath', item.addrId);
|
||||
this.$set(this.formData, 'detail', item.detail);
|
||||
this.formData.lat = item.position.lat;
|
||||
this.formData.lon = item.position.lng;
|
||||
},
|
||||
show () {
|
||||
this.showAddr = true;
|
||||
},
|
||||
hide () {
|
||||
this.showAddr = false;
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
id: {
|
||||
immediate: true,
|
||||
handler: function (v) {
|
||||
console.log(v);
|
||||
if (v) {
|
||||
this.getAddrById(v);
|
||||
} else {
|
||||
this.formData = {}
|
||||
this.$refs.form.resetFields();
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
components: {
|
||||
liliMap
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.add-box {
|
||||
margin: 40px 0;
|
||||
}
|
||||
</style>
|
||||
42
buyer/src/components/advertising/FixedTop.vue
Normal file
42
buyer/src/components/advertising/FixedTop.vue
Normal file
@@ -0,0 +1,42 @@
|
||||
<template>
|
||||
<!-- 头部广告 -->
|
||||
<div class="advertising" v-if="show" :style="{'background-color': data.bgColor}">
|
||||
<img :src="data.img" class="hover-pointer" @click="linkTo(data.url)"/>
|
||||
<Icon type="md-close-circle" size="20" @click="show = false" />
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
export default {
|
||||
props: {
|
||||
data: { // 传入的广告信息
|
||||
type: Object,
|
||||
default: null
|
||||
}
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
show: true // 是否显示头部广告
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
<style scoped lang="scss">
|
||||
.advertising {
|
||||
height: 80px;
|
||||
width: 100%;
|
||||
background-color: $theme_color;
|
||||
text-align: center;
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
> img {
|
||||
width: 1200px;
|
||||
height: 100%;
|
||||
}
|
||||
*:nth-child(2){
|
||||
position: relative;
|
||||
right: 36px;
|
||||
top: -57px;
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
2
buyer/src/components/advertising/README.md
Normal file
2
buyer/src/components/advertising/README.md
Normal file
@@ -0,0 +1,2 @@
|
||||
# 广告
|
||||
## FixedTop 顶部广告
|
||||
12
buyer/src/components/card/README.md
Normal file
12
buyer/src/components/card/README.md
Normal file
@@ -0,0 +1,12 @@
|
||||
## 自定义card -
|
||||
|
||||
### 参数
|
||||
>_Title 卡片头部
|
||||
|
||||
>_More 右侧栏显示内容 -- 默认不显示
|
||||
|
||||
>_Src 右侧内容显示之后的src路径
|
||||
|
||||
>_Tabs 传入数组 -- 默认无
|
||||
|
||||
>_Change 点击数组返回的index
|
||||
149
buyer/src/components/card/index.vue
Normal file
149
buyer/src/components/card/index.vue
Normal file
@@ -0,0 +1,149 @@
|
||||
<template>
|
||||
<Card class="_Card" :bordered="false" :dis-hover="true">
|
||||
<div slot="title" class="cardTitle">
|
||||
<span :style="{fontSize:`${_Size}px`}">{{_Title}}</span>
|
||||
|
||||
<div v-if="_Tabs" class="cardTabs">
|
||||
<div @click="tabsChange(index)" :class="{active:(isActive==index)}" class="cardTabsItem" :style="{fontSize:`${_Size-2}px`}" v-for="(item,index) in _Tabs"
|
||||
:key="index">
|
||||
{{item}}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div slot="extra" class="cardExtra" v-if="_More" @click="callBack()">
|
||||
{{_More}}
|
||||
</div>
|
||||
<div>
|
||||
|
||||
</div>
|
||||
</Card>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'index',
|
||||
props:
|
||||
{
|
||||
_Tabs: { // 可点击的tab栏
|
||||
type: null,
|
||||
default: ''
|
||||
},
|
||||
// 头部
|
||||
_Title: { // 标题
|
||||
type: null,
|
||||
default: '卡片头部'
|
||||
},
|
||||
// 右侧更多
|
||||
_More: {
|
||||
type: null,
|
||||
default: false
|
||||
},
|
||||
_Size: { // 文字大小
|
||||
type: Number,
|
||||
default: 16
|
||||
},
|
||||
// 点击更多触发跳转
|
||||
_Src: {
|
||||
type: null,
|
||||
default: function (val) {
|
||||
if (this._More) {
|
||||
return val;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
isActive: 0 // 已激活tab栏下标
|
||||
};
|
||||
},
|
||||
mounted () {},
|
||||
methods: {
|
||||
// 点击右侧的回调
|
||||
callBack () {
|
||||
let _this = this;
|
||||
if (this._Src !== '' || this._Src != null) {
|
||||
this.$router.push({
|
||||
path: _this._Src
|
||||
});
|
||||
}
|
||||
},
|
||||
// 点击tab的回调
|
||||
tabsChange (index) {
|
||||
// 处理并返回index
|
||||
this.isActive = index;
|
||||
this.$emit('_Change', index);
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.cardTitle {
|
||||
display: flex;
|
||||
cursor: pointer;
|
||||
}
|
||||
.active{
|
||||
color: $theme_color;
|
||||
position: relative;
|
||||
&::before{
|
||||
content: '';
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
height: 3px;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
background: $theme_color;
|
||||
}
|
||||
}
|
||||
|
||||
.cardTabs {
|
||||
display: flex;
|
||||
padding: 0 12px;
|
||||
|
||||
> .cardTabsItem {
|
||||
padding: 0 12px;
|
||||
|
||||
}
|
||||
|
||||
> .cardTabsItem:hover {
|
||||
|
||||
color: $theme_color;
|
||||
}
|
||||
}
|
||||
|
||||
/deep/ .ivu-card, .ivu-card-head, ._Card {
|
||||
margin-bottom: 20px;
|
||||
@include white_background_color();
|
||||
}
|
||||
|
||||
/deep/ .ivu-card-head {
|
||||
position: relative;
|
||||
padding: 0 14px;
|
||||
height: 50px;
|
||||
line-height: 50px;
|
||||
|
||||
&::before {
|
||||
content: '';
|
||||
width: 3px;
|
||||
height: 50%;
|
||||
top: 25%;
|
||||
background: $theme_color;
|
||||
position: absolute;
|
||||
left: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.cardExtra {
|
||||
color: $theme_color;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
/deep/ .ivu-card-body {
|
||||
padding: 0 !important;
|
||||
display: none;
|
||||
}
|
||||
|
||||
</style>
|
||||
110
buyer/src/components/coupon/Coupon.vue
Normal file
110
buyer/src/components/coupon/Coupon.vue
Normal file
@@ -0,0 +1,110 @@
|
||||
<template>
|
||||
<div class="wrapper">
|
||||
<empty v-if="list.length==0" />
|
||||
<ul class="coupon-list" v-else>
|
||||
<li v-for="(item, index) in list" class="coupon-item" :key="index">
|
||||
<div class="c-left">
|
||||
<div>
|
||||
<span v-if="item.couponType === 'PRICE'" class="fontsize_12 global_color">¥<span class="price">{{item.price | unitPrice}}</span></span>
|
||||
<span v-if="item.couponType === 'DISCOUNT'" class="fontsize_12 global_color"><span class="price">{{item.discount}}</span>折</span>
|
||||
<span class="describe">满{{item.consumeThreshold}}元可用</span>
|
||||
</div>
|
||||
<p>使用范围:{{useScope(item.scopeType, item.storeName)}}</p>
|
||||
<p>有效期:{{item.endTime}}</p>
|
||||
</div>
|
||||
<b></b>
|
||||
<a class="c-right" @click="go(item)">立即使用</a>
|
||||
<i class="circle-top"></i>
|
||||
<i class="circle-bottom"></i>
|
||||
</li>
|
||||
</ul>
|
||||
<Page :total="total" @on-change="changePageNum"
|
||||
v-if="list.length && total > params.pageNumber"
|
||||
class="pageration"
|
||||
@on-page-size-change="changePageSize"
|
||||
:page-size="params.pageSize"
|
||||
show-sizer>
|
||||
</Page>
|
||||
<Spin v-if="loading" fix></Spin>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { memberCouponList } from '@/api/member.js';
|
||||
export default {
|
||||
data () {
|
||||
return {
|
||||
loading: false, // 列表加载状态
|
||||
params: { // 请求参数
|
||||
pageNumber: 1,
|
||||
pageSize: 10
|
||||
},
|
||||
total: 0, // 优惠券总数
|
||||
list: [] // 优惠券列表
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
getList () {
|
||||
this.loading = true
|
||||
memberCouponList(this.params).then(res => {
|
||||
this.loading = false
|
||||
if (res.success) {
|
||||
this.list = res.result.records
|
||||
this.total = res.result.total
|
||||
}
|
||||
})
|
||||
},
|
||||
|
||||
go (item) { // 根据使用条件跳转商品列表页面
|
||||
if (item.storeId !== 'platform') {
|
||||
this.$router.push({path: '/merchant', query: {id: item.storeId}})
|
||||
} else {
|
||||
if (item.scopeType === 'PORTION_GOODS_CATEGORY') {
|
||||
this.$router.push({path: '/goodsList', query: {categoryId: item.scopeId}})
|
||||
} else {
|
||||
this.$router.push({path: '/goodsList'})
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
changePageNum (val) {
|
||||
this.params.pageNumber = val;
|
||||
this.getList()
|
||||
},
|
||||
|
||||
changePageSize (val) {
|
||||
this.pageNumber = 1;
|
||||
this.params.pageSize = val;
|
||||
this.getList()
|
||||
},
|
||||
|
||||
useScope (type, storeName) {
|
||||
let shop = '平台';
|
||||
let goods = '全部商品'
|
||||
if (storeName !== 'platform') shop = storeName
|
||||
switch (type) {
|
||||
case 'ALL':
|
||||
goods = '全部商品'
|
||||
break;
|
||||
case 'PORTION_GOODS':
|
||||
goods = '部分商品'
|
||||
break;
|
||||
case 'PORTION_GOODS_CATEGORY':
|
||||
goods = '部分分类商品'
|
||||
break;
|
||||
}
|
||||
return `${shop}${goods}可用`
|
||||
}
|
||||
},
|
||||
mounted () {
|
||||
this.getList()
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
@import '../../assets/styles/coupon.scss';
|
||||
.pageration{
|
||||
text-align: right;
|
||||
}
|
||||
</style>
|
||||
323
buyer/src/components/drawer/Drawer.vue
Normal file
323
buyer/src/components/drawer/Drawer.vue
Normal file
@@ -0,0 +1,323 @@
|
||||
<template>
|
||||
<div class="content-drawer">
|
||||
<div v-if="title === '购物车'" class="cart-con">
|
||||
<ul>
|
||||
<li v-for="(goods,goodsIndex) in cartList" :key="goodsIndex">
|
||||
<div>
|
||||
<img :src="goods.goodsSku.thumbnail" width="90" height="90" alt="">
|
||||
</div>
|
||||
<div>
|
||||
<p class="hover-color" @click="linkTo(`/goodsDetail?skuId=${goods.goodsSku.id}&goodsId=${goods.goodsSku.goodsId}`)">{{goods.goodsSku.goodsName}}</p>
|
||||
<p class="price">{{goods.goodsSku.price | unitPrice('¥')}}<span> x{{goods.num}}</span></p>
|
||||
</div>
|
||||
<span class="del hover-color" @click="delGoods(goods.goodsSku.id)">删除</span>
|
||||
</li>
|
||||
</ul>
|
||||
<Button size="large" class="mt_10" type="primary" @click="linkTo('/cart')" long>去购物车结算</Button>
|
||||
</div>
|
||||
|
||||
<div v-else-if="title === '我的订单'" class="order-con">
|
||||
<ul>
|
||||
<li v-for="(order,orderIndex) in orderList" :key="orderIndex">
|
||||
<div class="order-status"><span>{{filterOrderStatus(order.orderStatus)}}</span><span>{{order.createTime}}</span></div>
|
||||
<div class="goods-img">
|
||||
<img :src="img.image"
|
||||
@click="linkTo(`/goodsDetail?skuId=${img.skuId}&goodsId=${img.goodsId}`)"
|
||||
v-for="(img,imgIndex) in order.orderItems"
|
||||
:key="imgIndex" width="40" height="40" alt="">
|
||||
</div>
|
||||
<div class="order-handle"><span>{{ order.flowPrice | unitPrice("¥") }}</span><span class="hover-color" @click="linkTo(`home/OrderDetail?sn=${order.sn}`)">查看订单</span></div>
|
||||
</li>
|
||||
</ul>
|
||||
<Button type="primary" @click="linkTo('/home/MyOrder')" long>查看全部订单</Button>
|
||||
</div>
|
||||
|
||||
<div v-else-if="title === '优惠券'" class="coupon-con">
|
||||
<ul class="coupon-list">
|
||||
<li v-for="(coupon, index) in couponList" class="coupon-item" :key="index">
|
||||
<div class="c-left">
|
||||
<div>
|
||||
<span v-if="coupon.couponType === 'PRICE'" class="fontsize_12 global_color">¥<span class="price">{{coupon.price | unitPrice}}</span></span>
|
||||
<span v-if="coupon.couponType === 'DISCOUNT'" class="fontsize_12 global_color"><span class="price">{{coupon.discount}}</span>折</span>
|
||||
<span class="describe">满{{coupon.consumeThreshold}}元可用</span>
|
||||
</div>
|
||||
<p>使用范围:{{useScope(coupon.scopeType, coupon.storeName)}}</p>
|
||||
<p>有效期:{{coupon.endTime}}</p>
|
||||
</div>
|
||||
<b></b>
|
||||
<a class="c-right" @click="receive(coupon)">立即领取</a>
|
||||
<i class="circle-top"></i>
|
||||
<i class="circle-bottom"></i>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div v-else-if="title === '我的足迹'" class="tracks-con">
|
||||
<ul>
|
||||
<li v-for="(track,trackIndex) in tracksList" :key="trackIndex">
|
||||
<img :src="track.thumbnail" :alt="track.thumbnail" @click="linkTo(`/goodsDetail?skuId=${track.id}&goodsId=${track.goodsId}`)" width="100" height="100">
|
||||
<div @click="addToCart(track.id)">加入购物车</div>
|
||||
<p class="global_color">{{track.price | unitPrice('¥')}}</p>
|
||||
</li>
|
||||
</ul>
|
||||
<div class="hover-color" style="text-align:center;" @click="linkTo('/home/MyTracks')">查看更多>></div>
|
||||
</div>
|
||||
<div v-else-if="title === '我的收藏'" class="collect-con">
|
||||
<ul>
|
||||
<li v-for="(collect,collectIndex) in collectList" :key="collectIndex">
|
||||
<img :src="collect.image" :alt="collect.image" @click="linkTo(`/goodsDetail?skuId=${collect.skuId}&goodsId=${collect.goodsId}`)" width="100" height="100">
|
||||
<div @click="addToCart(collect.skuId)">加入购物车</div>
|
||||
<span class="del-icon" @click.stop="cancelCollect(collect.skuId)">
|
||||
<Icon type="md-trash" />
|
||||
</span>
|
||||
<p class="global_color">{{collect.price | unitPrice('¥')}}</p>
|
||||
</li>
|
||||
</ul>
|
||||
<div class="hover-color" style="text-align:center;" @click="linkTo('/home/Favorites')">查看更多>></div>
|
||||
</div>
|
||||
<Spin v-if="loading" fix></Spin>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {cartGoodsAll, delCartGoods, addCartGoods, cartCount} from '@/api/cart.js'
|
||||
import { getOrderList } from '@/api/order';
|
||||
import {couponList, receiveCoupon, tracksList, collectList, cancelCollect} from '@/api/member.js'
|
||||
export default {
|
||||
name: 'Drawer',
|
||||
props: {
|
||||
title: {
|
||||
default: '',
|
||||
type: String
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
title (val) {
|
||||
switch (val) {
|
||||
case '购物车':
|
||||
this.getCartList()
|
||||
break;
|
||||
case '我的订单':
|
||||
this.getOrderList()
|
||||
break;
|
||||
case '我的足迹':
|
||||
this.getTracksList()
|
||||
break;
|
||||
case '优惠券':
|
||||
this.getCouponList()
|
||||
break;
|
||||
case '我的收藏':
|
||||
this.getCollectList()
|
||||
break;
|
||||
}
|
||||
}
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
loading: false, // 控制spin显隐
|
||||
cartList: [], // 购物车列表
|
||||
couponList: [], // 优惠券列表
|
||||
orderList: [], // 订单列表
|
||||
collectList: [], // 收藏列表
|
||||
tracksList: [], // 足迹列表
|
||||
orderStatusList: [ // 订单状态
|
||||
{
|
||||
name: '未付款',
|
||||
status: 'UNPAID'
|
||||
},
|
||||
{
|
||||
name: '已付款',
|
||||
status: 'PAID'
|
||||
},
|
||||
{
|
||||
name: '待发货',
|
||||
status: 'UNDELIVERED'
|
||||
},
|
||||
{
|
||||
name: '已发货',
|
||||
status: 'DELIVERED'
|
||||
},
|
||||
{
|
||||
name: '已完成',
|
||||
status: 'COMPLETED'
|
||||
},
|
||||
{
|
||||
name: '待核验',
|
||||
status: 'TAKE'
|
||||
},
|
||||
{
|
||||
name: '已取消',
|
||||
status: 'CANCELLED'
|
||||
}
|
||||
]
|
||||
};
|
||||
},
|
||||
components: {},
|
||||
mounted () {},
|
||||
methods: {
|
||||
getCartList () { // 获取购物车列表
|
||||
this.loading = true
|
||||
cartGoodsAll().then(res => {
|
||||
this.loading = false
|
||||
this.cartList = res.result.skuList
|
||||
})
|
||||
},
|
||||
// 删除商品
|
||||
delGoods (id) {
|
||||
delCartGoods({ skuIds: id }).then((res) => {
|
||||
if (res.code === 200) {
|
||||
this.$Message.success('删除成功');
|
||||
this.getCartList();
|
||||
cartCount().then(res => {
|
||||
this.$store.commit('SET_CARTNUM', res.result)
|
||||
this.Cookies.setItem('cartNum', res.result)
|
||||
})
|
||||
} else {
|
||||
this.$Message.error(res.message);
|
||||
}
|
||||
});
|
||||
},
|
||||
filterOrderStatus (status) { // 获取订单状态中文
|
||||
const ob = this.orderStatusList.filter(e => { return e.status === status });
|
||||
return ob[0].name
|
||||
},
|
||||
receive (item) { // 领取优惠券
|
||||
receiveCoupon(item.id).then(res => {
|
||||
if (res.success) {
|
||||
this.$Modal.confirm({
|
||||
title: '领取优惠券',
|
||||
content: '<p>优惠券领取成功,可到我的优惠券页面查看</p>',
|
||||
okText: '我的优惠券',
|
||||
cancelText: '立即使用',
|
||||
onOk: () => {
|
||||
this.$router.push('/home/Coupons')
|
||||
},
|
||||
onCancel: () => {
|
||||
if (item.storeId !== 'platform') {
|
||||
this.$router.push({path: '/merchant', query: {id: item.storeId}})
|
||||
} else {
|
||||
if (item.scopeType === 'PORTION_GOODS_CATEGORY') {
|
||||
this.$router.push({path: '/goodsList', query: {categoryId: item.scopeId}})
|
||||
} else {
|
||||
this.$router.push({path: '/goodsList'})
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
})
|
||||
},
|
||||
useScope (type, storeName) { // 判断优惠券使用范围
|
||||
let shop = '平台';
|
||||
let goods = '全部商品'
|
||||
if (storeName !== 'platform') shop = storeName
|
||||
switch (type) {
|
||||
case 'ALL':
|
||||
goods = '全部商品'
|
||||
break;
|
||||
case 'PORTION_GOODS':
|
||||
goods = '部分商品'
|
||||
break;
|
||||
case 'PORTION_GOODS_CATEGORY':
|
||||
goods = '部分分类商品'
|
||||
break;
|
||||
}
|
||||
return `${shop}${goods}可用`
|
||||
},
|
||||
addToCart (id) { // 添加商品到购物车
|
||||
const params = {
|
||||
num: 1,
|
||||
skuId: id
|
||||
}
|
||||
this.loading = true;
|
||||
addCartGoods(params).then(res => {
|
||||
this.loading = false;
|
||||
if (res.code === 200) {
|
||||
this.$Message.success('商品已成功添加到购物车')
|
||||
} else {
|
||||
this.$Message.warning(res.message);
|
||||
}
|
||||
}).catch(() => { this.loading = false });
|
||||
},
|
||||
getCouponList () { // 获取优惠券列表
|
||||
// this.loading = true;
|
||||
const params = {
|
||||
pageNumber: 1,
|
||||
pageSize: 10
|
||||
}
|
||||
couponList(params).then(res => {
|
||||
this.loading = false
|
||||
if (res.success) {
|
||||
this.couponList = res.result.records
|
||||
}
|
||||
}).catch(() => { this.loading = false })
|
||||
},
|
||||
getOrderList () { // 获取订单列表
|
||||
this.loading = true
|
||||
const params = {
|
||||
pageNumber: 1,
|
||||
pageSize: 10,
|
||||
tag: 'ALL'
|
||||
}
|
||||
getOrderList(params).then(res => {
|
||||
this.loading = false
|
||||
if (res.success) {
|
||||
this.orderList = res.result.records;
|
||||
}
|
||||
});
|
||||
},
|
||||
getCollectList () { // 获取收藏列表
|
||||
const params = {
|
||||
pageNumber: 1,
|
||||
pageSize: 10,
|
||||
type: 'GOODS'
|
||||
}
|
||||
this.loading = true
|
||||
collectList(params).then(res => {
|
||||
this.loading = false
|
||||
this.collectList = res.result.records
|
||||
})
|
||||
},
|
||||
cancelCollect (id) { // 取消商品收藏
|
||||
cancelCollect('GOODS', id).then(res => {
|
||||
if (res.success) {
|
||||
this.$Message.success('取消收藏成功')
|
||||
this.getCollectList();
|
||||
}
|
||||
})
|
||||
},
|
||||
getTracksList () { // 获取足迹列表
|
||||
const params = {
|
||||
pageNumber: 1,
|
||||
pageSize: 20
|
||||
}
|
||||
this.loading = true
|
||||
tracksList(params).then(res => {
|
||||
this.tracksList = res.result
|
||||
this.loading = false
|
||||
}).catch(() => { this.loading = false })
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
@import '../../assets/styles/coupon.scss';
|
||||
@import './drawer.scss';
|
||||
.coupon-item{
|
||||
overflow: hidden;
|
||||
background-color: #fff;
|
||||
height: 120px;
|
||||
.c-left{
|
||||
padding: 15px;
|
||||
}
|
||||
.c-right{
|
||||
width: 38px;
|
||||
padding: 13px;
|
||||
font-size: 14px;
|
||||
}
|
||||
i{
|
||||
right: 30px;
|
||||
background-color: #eee;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
155
buyer/src/components/drawer/Main.vue
Normal file
155
buyer/src/components/drawer/Main.vue
Normal file
@@ -0,0 +1,155 @@
|
||||
<template>
|
||||
<div>
|
||||
<div class="wrapper" :style="{right:handleDrawer ? '300px' : '0px'}">
|
||||
|
||||
<div class="barItem" @mouseenter="showCartNum(item)" @click="clickBar(item)" v-for="(item,index) in resetConfig.menuList" :key="index">
|
||||
<Tooltip placement="left" :content="item.title">
|
||||
<Icon size="20" :type="item.icon"/>
|
||||
<p class="barTitle" v-if="item.titleShow"> {{item.title}}</p>
|
||||
<div class="circle" v-if="item.title === '购物车'">
|
||||
{{cartNum < 100 ? cartNum : 99}}
|
||||
</div>
|
||||
</Tooltip>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<Drawer width="300" class="popup" :title="drawerData.title" :mask="resetConfig.mask" :closable="resetConfig.closable"
|
||||
v-model="handleDrawer">
|
||||
<drawerPage :title="drawerData.title" />
|
||||
</Drawer>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import Storage from '@/plugins/storage.js';
|
||||
import Configuration from './config';
|
||||
import drawerPage from './Drawer'
|
||||
import {cartCount} from '@/api/cart.js'
|
||||
export default {
|
||||
name: 'Main',
|
||||
data () {
|
||||
return {
|
||||
resetConfig: Configuration, // 菜单项
|
||||
handleDrawer: false, // 是否可展开
|
||||
drawerData: '' // 菜单基础数据
|
||||
}
|
||||
},
|
||||
components: {drawerPage},
|
||||
computed: {
|
||||
userInfo () {
|
||||
return Storage.getItem('userInfo');
|
||||
},
|
||||
cartNum () {
|
||||
return this.$store.state.cartNum
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
showCartNum (item) {
|
||||
if (this.userInfo && item.title === '购物车') {
|
||||
this.getCartList()
|
||||
}
|
||||
},
|
||||
clickBar (val) {
|
||||
if (!this.userInfo) {
|
||||
this.$Modal.confirm({
|
||||
title: '请登录',
|
||||
content: '<p>请登录后执行此操作</p>',
|
||||
okText: '立即登录',
|
||||
cancelText: '继续浏览',
|
||||
onOk: () => {
|
||||
this.$router.push({
|
||||
path: '/login',
|
||||
query: {
|
||||
rePath: this.$router.history.current.path,
|
||||
query: JSON.stringify(this.$router.history.current.query)
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
} else {
|
||||
if (val.display) {
|
||||
this.handleDrawer = true
|
||||
this.drawerData = val
|
||||
} else {
|
||||
this.handleDrawer = false
|
||||
switch (val.title) {
|
||||
case '会员中心':
|
||||
this.openBlank('/home')
|
||||
break;
|
||||
case '我的资产':
|
||||
this.openBlank('/home/MoneyManagement')
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
openBlank (path) {
|
||||
let routerUrl = this.$router.resolve({
|
||||
path: path
|
||||
})
|
||||
window.open(routerUrl.href, '_blank')
|
||||
},
|
||||
getCartList () { // 获取购物车列表
|
||||
cartCount().then(res => {
|
||||
this.$store.commit('SET_CARTNUM', res.result)
|
||||
this.Cookies.setItem('cartNum', res.result)
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.wrapper {
|
||||
background-color: #000!important;
|
||||
}
|
||||
.barItem {
|
||||
text-align: center;
|
||||
padding: 13px 0;
|
||||
|
||||
cursor: pointer;
|
||||
color: #fff;
|
||||
&:hover{
|
||||
background-color: $theme_color;
|
||||
.circle{
|
||||
color: $theme_color;
|
||||
background-color: #fff;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.barTitle {
|
||||
writing-mode: vertical-lr;
|
||||
letter-spacing: 2px;
|
||||
padding: 4px 0;
|
||||
|
||||
}
|
||||
|
||||
.circle {
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
border-radius: 50%;
|
||||
color: #fff;
|
||||
background: $theme_color;
|
||||
}
|
||||
|
||||
.wrapper {
|
||||
width: 40px;
|
||||
position: fixed;
|
||||
transition: .35s;
|
||||
height: 100%;
|
||||
z-index: 9999;
|
||||
background: $dark_background_color;
|
||||
top: 0;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
flex-direction: column;
|
||||
}
|
||||
/deep/.popup .ivu-drawer-body{
|
||||
padding: 0!important;
|
||||
background-color: #eee;
|
||||
}
|
||||
/deep/.popup .ivu-drawer-wrap{
|
||||
z-index: 3001;
|
||||
}
|
||||
</style>
|
||||
42
buyer/src/components/drawer/README.md
Normal file
42
buyer/src/components/drawer/README.md
Normal file
@@ -0,0 +1,42 @@
|
||||
# 右侧侧边栏组件
|
||||
> 本组件依赖于iview的组件基础上进行封装
|
||||
>项目结构
|
||||
>* Main -- 组件用于挂在右侧的横栏
|
||||
>* drawer -- 右侧横栏的内容
|
||||
>* config -- 用于设置大小
|
||||
|
||||
|
||||
#### config设置
|
||||
```
|
||||
/**
|
||||
menuList // 组件的menu
|
||||
display //是否显示此menu
|
||||
badge //显示徽标数
|
||||
titleShow //是否显示title
|
||||
*/
|
||||
|
||||
//实例代码
|
||||
width : 50, //bar的大小
|
||||
menuList:[
|
||||
{
|
||||
icon
|
||||
}
|
||||
]
|
||||
|
||||
|
||||
```
|
||||
|
||||
|
||||
|
||||
> 账户信息
|
||||
> 购物车
|
||||
> 我的订单
|
||||
> 优惠券
|
||||
> 我的资产
|
||||
> 我的足迹
|
||||
> 我的收藏
|
||||
> 邮箱订阅
|
||||
|
||||
|
||||
## 如何使用
|
||||
1.
|
||||
63
buyer/src/components/drawer/config.js
Normal file
63
buyer/src/components/drawer/config.js
Normal file
@@ -0,0 +1,63 @@
|
||||
const config = {
|
||||
closable: true, // 是否显示右上角关闭按钮
|
||||
mask: true, // 是否显示遮罩层
|
||||
|
||||
menuList: [{
|
||||
icon: 'md-person', // menu的icon
|
||||
title: '会员中心', // menu的标题
|
||||
titleShow: false,
|
||||
path: '', // menu点击的路径
|
||||
display: false // 是否显示此menu
|
||||
},
|
||||
{
|
||||
icon: 'ios-cart', // menu的icon
|
||||
title: '购物车', // menu的标题
|
||||
path: '', // menu点击的路径
|
||||
display: true, // 是否显示此menu
|
||||
badge: 12,
|
||||
titleShow: true
|
||||
},
|
||||
{
|
||||
icon: 'md-clipboard', // menu的icon
|
||||
title: '我的订单', // menu的标题
|
||||
path: '', // menu点击的路径
|
||||
display: true, // 是否显示此menu
|
||||
badge: '',
|
||||
titleShow: false
|
||||
},
|
||||
{
|
||||
icon: 'md-pricetag', // menu的icon
|
||||
title: '优惠券', // menu的标题
|
||||
path: '', // menu点击的路径
|
||||
display: true, // 是否显示此menu
|
||||
badge: '',
|
||||
titleShow: false
|
||||
},
|
||||
{
|
||||
icon: 'logo-usd', // menu的icon
|
||||
title: '我的资产', // menu的标题
|
||||
path: '', // menu点击的路径
|
||||
display: false, // 是否显示此menu
|
||||
badge: '',
|
||||
titleShow: false
|
||||
},
|
||||
{
|
||||
icon: 'ios-eye', // menu的icon
|
||||
title: '我的足迹', // menu的标题
|
||||
path: '', // menu点击的路径
|
||||
display: true, // 是否显示此menu
|
||||
badge: '',
|
||||
titleShow: false
|
||||
},
|
||||
{
|
||||
icon: 'md-star', // menu的icon
|
||||
title: '我的收藏', // menu的标题
|
||||
path: '', // menu点击的路径
|
||||
display: true, // 是否显示此menu
|
||||
badge: '',
|
||||
titleShow: false
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
export default config
|
||||
130
buyer/src/components/drawer/drawer.scss
Normal file
130
buyer/src/components/drawer/drawer.scss
Normal file
@@ -0,0 +1,130 @@
|
||||
.content-drawer {
|
||||
height: 100%;
|
||||
font-size: 12px;
|
||||
}
|
||||
// 购物车样式
|
||||
.cart-con{
|
||||
position: relative;
|
||||
background: #fff;
|
||||
height: 100%;
|
||||
ul>li{
|
||||
font-size: 12px;
|
||||
border-bottom: 1px dashed #999;
|
||||
margin: 0 10px;
|
||||
display: flex;
|
||||
padding: 10px 0;
|
||||
align-items: center;
|
||||
position: relative;
|
||||
p{margin-bottom: 10px;}
|
||||
.del{
|
||||
position: absolute;
|
||||
right: 10px;
|
||||
bottom: 30px;
|
||||
}
|
||||
|
||||
.price {
|
||||
color: $theme_color;
|
||||
span{color: #999;}
|
||||
}
|
||||
|
||||
&:last-child{border: none;}
|
||||
}
|
||||
|
||||
}
|
||||
// 订单样式
|
||||
.order-con{
|
||||
ul>li {
|
||||
margin: 10px;
|
||||
background-color: #fff;
|
||||
.order-status {
|
||||
display: flex;
|
||||
background-color: #666;
|
||||
border-radius: 3px 3px 0 0;
|
||||
color: #fff;
|
||||
justify-content: space-between;
|
||||
padding: 0 10px;
|
||||
}
|
||||
|
||||
.goods-img {
|
||||
padding-left: 10px;
|
||||
padding-top: 10px;
|
||||
img{
|
||||
border: 1px solid #eee;
|
||||
margin-right: 10px;
|
||||
|
||||
&:hover{
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.order-handle{
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
padding:5px 10px;
|
||||
border-top: 1px solid #eee;
|
||||
span:nth-child(1){
|
||||
color: $theme_color;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// 优惠券样式
|
||||
.coupon-con{
|
||||
margin-top: 10px;
|
||||
}
|
||||
// 足迹样式
|
||||
.tracks-con,.collect-con{
|
||||
ul{
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
padding: 10px;
|
||||
}
|
||||
li {
|
||||
background-color: #fff;
|
||||
margin: 10px;
|
||||
width: 120px;
|
||||
position: relative;
|
||||
text-align: center;
|
||||
&:hover{
|
||||
div,.del-icon{
|
||||
display: block;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
img{
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
div{
|
||||
display: none;
|
||||
position: absolute;
|
||||
bottom: 18px;
|
||||
width: 100%;
|
||||
background-color: #666;
|
||||
color: #fff;
|
||||
&:hover{
|
||||
background-color: $theme_color;
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
.del-icon{
|
||||
display: none;
|
||||
font-size: 20px;
|
||||
position: absolute;
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
line-height: 30px;
|
||||
text-align: center;
|
||||
right: 0;
|
||||
top: 0;
|
||||
cursor: pointer;
|
||||
color: $theme_color;
|
||||
}
|
||||
}
|
||||
}
|
||||
// 我的收藏样式
|
||||
.collect-con{
|
||||
|
||||
}
|
||||
45
buyer/src/components/empty/Main.vue
Normal file
45
buyer/src/components/empty/Main.vue
Normal file
@@ -0,0 +1,45 @@
|
||||
<template>
|
||||
<div class="empty">
|
||||
<img
|
||||
class="empty-img"
|
||||
:style="{ width: _Size + 'px' }"
|
||||
src="../../assets/images/empty.png"
|
||||
alt=""
|
||||
/>
|
||||
<p v-if="_Title">{{ _Title }}</p>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'Main',
|
||||
data () {
|
||||
return {
|
||||
|
||||
};
|
||||
},
|
||||
props: {
|
||||
_Title: { // 描述内容
|
||||
type: null,
|
||||
default: '暂无更多'
|
||||
},
|
||||
_Size: { // 图片大小
|
||||
type: Number,
|
||||
default: 150
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.empty {
|
||||
margin: 30px 0;
|
||||
text-align: center;
|
||||
width: 100%;
|
||||
|
||||
}
|
||||
p {
|
||||
cursor: pointer;
|
||||
@include sub_color($light_sub_color);
|
||||
}
|
||||
</style>
|
||||
10
buyer/src/components/empty/README.md
Normal file
10
buyer/src/components/empty/README.md
Normal file
@@ -0,0 +1,10 @@
|
||||
# 空状态封装
|
||||
|
||||
```
|
||||
// _Title
|
||||
|
||||
<empty></empty> //默认显示
|
||||
|
||||
q
|
||||
<empty _Title='暂无更多了' ></empty> //自定义返回标题
|
||||
```
|
||||
189
buyer/src/components/footer/Footer.vue
Normal file
189
buyer/src/components/footer/Footer.vue
Normal file
@@ -0,0 +1,189 @@
|
||||
<template>
|
||||
<div>
|
||||
<footer class="footer">
|
||||
<div class="clearfix"></div>
|
||||
<div class="icon-row">
|
||||
<div class="footer-icon">
|
||||
<h5 class="footer-icon-child"></h5>
|
||||
<span class="footer-icon-text">品类齐全,轻松购物</span>
|
||||
</div>
|
||||
<div class="footer-icon">
|
||||
<h5 class="footer-icon-child footer-icon-child-2"></h5>
|
||||
<span class="footer-icon-text">多仓直发,极速配送</span>
|
||||
</div>
|
||||
<div class="footer-icon">
|
||||
<h5 class="footer-icon-child footer-icon-child-3"></h5>
|
||||
<span class="footer-icon-text">正品行货,精致服务</span>
|
||||
</div>
|
||||
<div class="footer-icon">
|
||||
<h5 class="footer-icon-child footer-icon-child-4"></h5>
|
||||
<span class="footer-icon-text">天天低价,畅选无忧</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="service-intro">
|
||||
<div class="servece-type">
|
||||
<div class="servece-type-info" v-for="(guide, index) in guideArr" :key="index">
|
||||
<ul>
|
||||
<li v-for="(item, index) in guide" :key="index" @click="goArticle">{{item}}</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<div class="clearfix"></div>
|
||||
<div class="friend-link">
|
||||
<div class="friend-link-item">
|
||||
<ul>
|
||||
<li v-for="(link, index) in moreLink" :key="index" @click="goArticle">
|
||||
<span class="link-item" :class="{'link-last-item': index === 4}">{{link}}</span>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<div class="clearfix"></div>
|
||||
<div class="copyright">
|
||||
<p>Copyright © LILI</p>
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'Footer',
|
||||
data () {
|
||||
return {
|
||||
guideArr: [ // 导航链接
|
||||
[ '购物指南', '购物流程', '会员介绍', '生活旅行', '常见问题', '大家电', '联系客服' ],
|
||||
[ '配送方式', '上门自提', '211限时达', '配送服务查询', '收取标准', '海外配送' ],
|
||||
[ '支付方式', '货到付款', '在线支付', '分期付款', '邮局汇款', '公司转账' ],
|
||||
[ '售后服务', '售后政策', '价格保护', '退款说明', '返修/退换货', '取消订单' ]
|
||||
],
|
||||
moreLink: ['关于我们', '联系我们', '联系客服', '商家帮助', '隐私政策'] // 更多链接
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
goArticle () { // 跳转
|
||||
let routeUrl = this.$router.resolve({
|
||||
path: '/article'
|
||||
})
|
||||
window.open(routeUrl.href, '_blank')
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
/*****************************底 部 开 始*****************************/
|
||||
.footer {
|
||||
width: 100%;
|
||||
height: 450px;
|
||||
padding-top: 30px;
|
||||
|
||||
@include background_color($light_background_color);
|
||||
|
||||
}
|
||||
.icon-row {
|
||||
margin: 15px auto;
|
||||
padding-top: 8px;
|
||||
width: 1000px;
|
||||
height: 64px;
|
||||
}
|
||||
.footer-icon {
|
||||
margin-left: 17px;
|
||||
margin-right: 17px;
|
||||
float: left;
|
||||
}
|
||||
.footer-icon-child {
|
||||
margin-top: 10px;
|
||||
overflow: hidden;
|
||||
position: absolute;
|
||||
width: 36px;
|
||||
height: 42px;
|
||||
background-image: url("../../assets/images/footer/ico_service.png");
|
||||
text-indent: -999px;
|
||||
}
|
||||
.footer-icon-child-2 {
|
||||
background-position: 0 -43px;
|
||||
}
|
||||
.footer-icon-child-3 {
|
||||
background-position: 0 -86px;
|
||||
}
|
||||
.footer-icon-child-4 {
|
||||
background-position: 0 -129px;
|
||||
}
|
||||
.footer-icon-text{
|
||||
margin-left: 45px;
|
||||
font-size: 18px;
|
||||
font-weight: bold;
|
||||
line-height: 64px;
|
||||
}
|
||||
.service-intro {
|
||||
width: 100%;
|
||||
border-top: 1px solid $border_color;
|
||||
}
|
||||
.servece-type {
|
||||
margin: 15px auto;
|
||||
height: 200px;
|
||||
width: 800px;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.servece-type-info ul {
|
||||
list-style: none;
|
||||
}
|
||||
.servece-type-info li {
|
||||
font-size: 14px;
|
||||
cursor: pointer;
|
||||
line-height: 26px;
|
||||
}
|
||||
.servece-type-info li:first-child {
|
||||
font-size: 16px;
|
||||
line-height: 28px;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.friend-link {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
width: 908px;
|
||||
height: 30px;
|
||||
margin: 0px auto;
|
||||
border-top: 1px solid $border_color;
|
||||
}
|
||||
.friend-link-item {
|
||||
margin: 0px auto;
|
||||
}
|
||||
.friend-link-item ul {
|
||||
list-style: none;
|
||||
}
|
||||
.friend-link-item li {
|
||||
padding: 5px 0px;
|
||||
float: left;
|
||||
}
|
||||
.link-item {
|
||||
padding: 0px 8px;
|
||||
cursor: pointer;
|
||||
border-right: 1px solid $border_color;
|
||||
}
|
||||
.link-last-item {
|
||||
border: none;
|
||||
}
|
||||
.copyright {
|
||||
width: 100%;
|
||||
line-height: 30px;
|
||||
text-align: center;
|
||||
}
|
||||
.copyright a{
|
||||
color: #232323;
|
||||
font-size: 20px;
|
||||
}
|
||||
.footer-icon-text{
|
||||
@include title_color($light_title_color)
|
||||
}
|
||||
.copyright,.friend-link,.servece-type-info {
|
||||
@include sub_color($light_sub_color)
|
||||
}
|
||||
/*****************************底 部 结 束*****************************/
|
||||
</style>
|
||||
54
buyer/src/components/global.js
Normal file
54
buyer/src/components/global.js
Normal file
@@ -0,0 +1,54 @@
|
||||
// 全局组件配置
|
||||
|
||||
import empty from './empty/Main' // 空状态组件
|
||||
import drawer from './drawer/Main' // 右侧bar
|
||||
import Header from '@/components/header/Header'; // 头部组件
|
||||
import FixedTopPage from '@/components/advertising/FixedTop'; // 顶部广告
|
||||
import Footer from '@/components/footer/Footer'; // 底部栏
|
||||
import Search from '@/components/Search' // 搜索框
|
||||
import card from '@/components/card' // 个人中心 卡片
|
||||
import cateNav from '@/components/nav/cateNav' // 个人中心 卡片
|
||||
|
||||
empty.install = function (Vue) {
|
||||
Vue.component('empty', empty);
|
||||
};
|
||||
|
||||
drawer.install = function (Vue) {
|
||||
Vue.component('drawer', drawer);
|
||||
};
|
||||
|
||||
Header.install = function (Vue) {
|
||||
Vue.component('BaseHeader', Header);
|
||||
};
|
||||
|
||||
FixedTopPage.install = function (Vue) {
|
||||
Vue.component('FixedTopPage', FixedTopPage);
|
||||
};
|
||||
|
||||
Footer.install = function (Vue) {
|
||||
Vue.component('BaseFooter', Footer);
|
||||
};
|
||||
|
||||
Search.install = function (Vue) {
|
||||
Vue.component('Search', Search);
|
||||
};
|
||||
|
||||
card.install = function (Vue) {
|
||||
Vue.component('card', card)
|
||||
}
|
||||
|
||||
cateNav.install = function (Vue) {
|
||||
Vue.component('cateNav', cateNav)
|
||||
}
|
||||
|
||||
// 引用本js中所有的组件
|
||||
export function InstallAll (Vue) {
|
||||
Vue.use(empty)
|
||||
Vue.use(drawer)
|
||||
Vue.use(Header)
|
||||
Vue.use(FixedTopPage)
|
||||
Vue.use(Footer)
|
||||
Vue.use(Search)
|
||||
Vue.use(card)
|
||||
Vue.use(cateNav)
|
||||
}
|
||||
123
buyer/src/components/goodsDetail/Promotion.vue
Normal file
123
buyer/src/components/goodsDetail/Promotion.vue
Normal file
@@ -0,0 +1,123 @@
|
||||
<template>
|
||||
<div>
|
||||
<div class="wrapper" v-if="type === 'goodsDetail'">
|
||||
<div class="wr-l"><Icon size="23" type="ios-alarm-outline" /> 秒杀活动</div>
|
||||
<div class="count-down" v-if="end === ''">
|
||||
<p>倒计时:</p><span>{{ hours }}</span><span>{{ minutes }}</span><span>{{ seconds }}</span>
|
||||
</div>
|
||||
<div v-else>{{end}}</div>
|
||||
</div>
|
||||
<span v-else class="cart-promotion">
|
||||
<span v-if="end === ''">据活动结束:<span>{{ hours }}</span> : <span>{{ minutes }}</span> : <span>{{ seconds }}</span></span>
|
||||
<span v-else>活动已结束</span>
|
||||
</span>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
export default {
|
||||
props: {
|
||||
time: { // 传入的初始时间
|
||||
default: 1718977559428
|
||||
},
|
||||
type: {
|
||||
default: 'goodsDetail', // 设置两个值,goodsDetail和cart,样式不同
|
||||
type: String
|
||||
}
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
end: '', // 结束状态
|
||||
hours: '', // 小时
|
||||
minutes: '', // 分钟
|
||||
seconds: '', // 秒
|
||||
interval: '' // 定时器
|
||||
};
|
||||
},
|
||||
mounted () {
|
||||
this.init()
|
||||
},
|
||||
methods: {
|
||||
countDown (val) {
|
||||
function addZero (i) {
|
||||
return i < 10 ? '0' + i : i + '';
|
||||
}
|
||||
var nowtime = new Date();
|
||||
var endtime = new Date(val);
|
||||
var lefttime = parseInt((endtime.getTime() - nowtime.getTime()) / 1000);
|
||||
var h = parseInt((lefttime / (60 * 60)) % 24);
|
||||
var m = parseInt((lefttime / 60) % 60);
|
||||
var s = parseInt(lefttime % 60);
|
||||
h = addZero(h);
|
||||
m = addZero(m);
|
||||
s = addZero(s);
|
||||
this.hours = h;
|
||||
this.minutes = m
|
||||
this.seconds = s;
|
||||
if (lefttime <= 0) {
|
||||
this.end = `活动已结束`;
|
||||
clearInterval(this.interval)
|
||||
}
|
||||
},
|
||||
init () {
|
||||
this.interval = setInterval((item) => {
|
||||
this.countDown(this.time);
|
||||
}, 1000);
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
<style scoped lang="scss">
|
||||
.cart-promotion{
|
||||
font-size: 13px;
|
||||
color: #999;
|
||||
margin-left: 10px;
|
||||
}
|
||||
.wrapper {
|
||||
background-image: linear-gradient(266deg, #ff0b33, #ff4257, #ff5f7c, #fa78a2);
|
||||
height: 32px;
|
||||
color: #fff;
|
||||
line-height: 32px;
|
||||
font-size: 16px;
|
||||
padding: 0 10px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
}
|
||||
.wr-r{
|
||||
font-size: 13px;
|
||||
}
|
||||
.count-down {
|
||||
margin-right: -20px;
|
||||
p{
|
||||
float: left;
|
||||
line-height: 20px;
|
||||
}
|
||||
> span {
|
||||
position: relative;
|
||||
float: left;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
text-align: center;
|
||||
background-color: #2f3430;
|
||||
margin-right: 20px;
|
||||
color: white;
|
||||
font-size: 14px;
|
||||
line-height: 20px;
|
||||
&::after {
|
||||
content: ":";
|
||||
display: block;
|
||||
position: absolute;
|
||||
right: -20px;
|
||||
font-weight: bolder;
|
||||
font-size: 14px;
|
||||
width: 20px;
|
||||
height: 100%;
|
||||
top: 0;
|
||||
}
|
||||
}
|
||||
> span:last-child::after {
|
||||
content: "";
|
||||
}
|
||||
}
|
||||
|
||||
</style>
|
||||
658
buyer/src/components/goodsDetail/ShowGoods.vue
Normal file
658
buyer/src/components/goodsDetail/ShowGoods.vue
Normal file
@@ -0,0 +1,658 @@
|
||||
<template>
|
||||
<div class="wrapper">
|
||||
<div class="item-detail-show">
|
||||
<!-- 详情左侧展示数据、图片,收藏、举报 -->
|
||||
<div class="item-detail-left">
|
||||
<!-- 大图、放大镜 -->
|
||||
<div class="item-detail-big-img">
|
||||
<pic-zoom :url="imgList[imgIndex].url" :scale="2"></pic-zoom>
|
||||
</div>
|
||||
<div class="item-detail-img-row">
|
||||
<div
|
||||
class="item-detail-img-small"
|
||||
@mouseover="imgIndex = index"
|
||||
v-for="(item, index) in imgList"
|
||||
:key="index"
|
||||
>
|
||||
<img :src="item.url" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="goodsConfig mt_10">
|
||||
<span @click="collect" ><Icon type="ios-heart" :color="isCollected ? '#ed3f14' : '#666'" />{{isCollected?'已收藏':'收藏'}}</span>
|
||||
<!-- <span>举报</span> -->
|
||||
</div>
|
||||
</div>
|
||||
<!-- 右侧商品信息、活动信息、操作展示 -->
|
||||
<div class="item-detail-right">
|
||||
<div class="item-detail-title">
|
||||
<p>
|
||||
{{ skuDetail.goodsName }}
|
||||
</p>
|
||||
</div>
|
||||
<!-- 限时秒杀 -->
|
||||
<Promotion v-if="promotionMap['SECKILL']" :time="promotionMap['SECKILL'].endTime"></Promotion>
|
||||
<!-- 商品详细 价格、优惠券、促销 -->
|
||||
<div class="item-detail-price-row">
|
||||
<div class="item-price-left">
|
||||
<!-- 商品原价 -->
|
||||
<div class="item-price-row" v-if="!skuDetail.promotionPrice">
|
||||
<p>
|
||||
<span class="item-price-title">价 格</span>
|
||||
<span class="item-price">{{skuDetail.price | unitPrice("¥")}}</span>
|
||||
</p>
|
||||
</div>
|
||||
<!-- 秒杀价格 -->
|
||||
<div class="item-price-row" v-if="skuDetail.promotionPrice">
|
||||
<p>
|
||||
<span class="item-price-title" v-if="promotionMap['SECKILL']">秒 杀 价</span>
|
||||
<span class="item-price">{{skuDetail.promotionPrice | unitPrice("¥")}}</span>
|
||||
<span class="item-price-old">{{skuDetail.price | unitPrice("¥")}}</span>
|
||||
</p>
|
||||
</div>
|
||||
<!-- 优惠券展示 -->
|
||||
<div class="item-price-row" v-if="promotionMap['COUPON'].length">
|
||||
<p>
|
||||
<span class="item-price-title">优 惠 券</span>
|
||||
<span
|
||||
class="item-coupon"
|
||||
v-for="(item, index) in promotionMap['COUPON']"
|
||||
:key="index"
|
||||
@click="receiveCoupon(item.id)"
|
||||
>
|
||||
<span v-if="item.couponType == 'PRICE'">满{{ item.consumeThreshold }}减{{item.price}}</span>
|
||||
<span v-if="item.couponType == 'DISCOUNT'">满{{ item.consumeThreshold }}打{{item.couponDiscount}}折</span>
|
||||
</span>
|
||||
</p>
|
||||
</div>
|
||||
<!-- 满减展示 -->
|
||||
<div class="item-price-row" v-if="promotionMap['FULL_DISCOUNT']">
|
||||
<p>
|
||||
<span class="item-price-title">促 销</span>
|
||||
<span class="item-promotion">满减</span>
|
||||
<span class="item-desc-pintuan" v-if="promotionMap['FULL_DISCOUNT'].fullMinus">满{{ promotionMap['FULL_DISCOUNT'].fullMoney }}元,立减现金{{ promotionMap['FULL_DISCOUNT'].fullMinus}}元</span>
|
||||
<span class="item-desc-pintuan" v-if="promotionMap['FULL_DISCOUNT'].fullRate">满{{ promotionMap['FULL_DISCOUNT'].fullMoney }}元,立享{{ promotionMap['FULL_DISCOUNT'].fullRate}}折</span>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="item-price-right">
|
||||
<div class="item-remarks-sum">
|
||||
<p>累计评价</p>
|
||||
<p>
|
||||
<span class="item-remarks-num">{{ skuDetail.commentNum || 0 }} 条</span>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- 选择颜色 -->
|
||||
<div class="item-select" v-for="(sku, index) in formatList" :key="sku.id">
|
||||
<div class="item-select-title">
|
||||
<p>{{ sku.name }}</p>
|
||||
</div>
|
||||
<div class="item-select-column">
|
||||
<div class="item-select-row" v-for="(item) in sku.values" :key="item.id">
|
||||
<div class="item-select-box" @click="select(index, sku.id, item.id)"
|
||||
:class="{ 'item-select-box-active': item.id === currentSelceted[index] }"
|
||||
>
|
||||
<div class="item-select-intro">
|
||||
<p>{{ item.value }}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<br />
|
||||
<div class="add-buy-car-box">
|
||||
<div class="item-select">
|
||||
<div class="item-select-title">
|
||||
<p>数量</p>
|
||||
</div>
|
||||
<div class="item-select-row">
|
||||
<InputNumber :min="1" :disabled="skuDetail.quantity === 0" v-model="count"></InputNumber>
|
||||
<span class="inventory"> 库存{{skuDetail.quantity}}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="item-select">
|
||||
<div class="item-select-title">
|
||||
<p>重量</p>
|
||||
</div>
|
||||
<div class="item-select-row">
|
||||
<span class="inventory"> {{skuDetail.weight}}kg</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="add-buy-car">
|
||||
<Button type="error" :loading="loading" :disabled="skuDetail.quantity === 0" @click="addShoppingCartBtn">加入购物车</Button>
|
||||
<Button type="warning" :loading="loading1" :disabled="skuDetail.quantity === 0" @click="buyNow">立即购买</Button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- <div class="item-detail-see">
|
||||
<Divider>更多推荐</Divider>
|
||||
<Row>
|
||||
<Col :span="24" class="see-Item">
|
||||
<img class="see-Img" src="https://demo.dscmall.cn/storage/images/201703/thumb_img/0_thumb_G_1489099128797.jpg" alt="" />
|
||||
<p>
|
||||
名龙堂i7 6700升7700 GTX1060 6G台式电脑主机DIY游戏组装整机
|
||||
升6GB独显 送正版WIN10 一年上门
|
||||
</p>
|
||||
<p class="global_color">¥2500.00</p>
|
||||
</Col>
|
||||
<Col :span="24" class="see-Item">
|
||||
<img
|
||||
class="see-Img"
|
||||
src="https://demo.dscmall.cn/storage/images/201703/thumb_img/0_thumb_G_1489099128797.jpg"
|
||||
alt=""
|
||||
/>
|
||||
<p>
|
||||
名龙堂i7 6700升7700 GTX1060 6G台式电脑主机DIY游戏组装整机
|
||||
升6GB独显 送正版WIN10 一年上门
|
||||
</p>
|
||||
<p class="global_color">¥2500.00</p>
|
||||
</Col>
|
||||
</Row>
|
||||
</div> -->
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import Promotion from './Promotion.vue';
|
||||
import PicZoom from 'vue-piczoom'; // 图片放大 https://github.com/826327700/vue-piczoom
|
||||
import { collectGoods, isCollection, receiveCoupon, cancelCollect } from '@/api/member.js';
|
||||
import { addCartGoods } from '@/api/cart.js';
|
||||
export default {
|
||||
name: 'ShowGoods',
|
||||
props: {
|
||||
detail: {
|
||||
type: Object,
|
||||
default: null
|
||||
}
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
count: 1, // 商品数量
|
||||
imgIndex: 0, // 展示图片下标
|
||||
currentSelceted: [], // 当前商品sku
|
||||
imgList: this.detail.data.specList[0].specImage, // 商品图片列表
|
||||
skuDetail: this.detail.data, // sku详情
|
||||
goodsSpecList: this.detail.specs, // 商品spec
|
||||
promotionMap: { // 活动状态
|
||||
SECKILL: null,
|
||||
FULL_DISCOUNT: null,
|
||||
COUPON: []
|
||||
}, // 促销活动
|
||||
formatList: [], // 选择商品品类的数组
|
||||
loading: false, // 立即购买loading
|
||||
loading1: false, // 加入购物车loading
|
||||
isCollected: false // 是否收藏
|
||||
};
|
||||
},
|
||||
components: {
|
||||
PicZoom,
|
||||
Promotion
|
||||
},
|
||||
methods: {
|
||||
select (index, id, valueId) { // 选择规格
|
||||
this.$set(this.currentSelceted, index, valueId);
|
||||
|
||||
let selectedSkuId = this.goodsSpecList.find((i) => {
|
||||
let matched = true;
|
||||
let specValues = i.specValues.filter((j) => j.specName !== 'images');
|
||||
for (let n = 0; n < specValues.length; n++) {
|
||||
if (specValues[n].specValueId !== this.currentSelceted[n]) {
|
||||
matched = false;
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (matched) {
|
||||
return i;
|
||||
}
|
||||
});
|
||||
console.log(selectedSkuId);
|
||||
this.$router.push({
|
||||
path: '/goodsDetail',
|
||||
query: { skuId: selectedSkuId.skuId, goodsId: this.skuDetail.goodsId }
|
||||
});
|
||||
},
|
||||
|
||||
addShoppingCartBtn () { // 添加购物车
|
||||
const params = {
|
||||
num: this.count,
|
||||
skuId: this.skuDetail.id
|
||||
};
|
||||
this.loading = true;
|
||||
addCartGoods(params).then(res => {
|
||||
this.loading = false;
|
||||
if (res.code === 200) {
|
||||
this.$router.push({path: '/shoppingCart', query: {detail: this.skuDetail, count: this.count}});
|
||||
} else {
|
||||
this.$Message.warning(res.message);
|
||||
}
|
||||
});
|
||||
},
|
||||
buyNow () { // 立即购买
|
||||
const params = {
|
||||
num: this.count,
|
||||
skuId: this.skuDetail.id,
|
||||
cartType: 'BUY_NOW'
|
||||
};
|
||||
this.loading1 = true;
|
||||
addCartGoods(params).then(res => {
|
||||
this.loading1 = false;
|
||||
if (res.code === 200) {
|
||||
this.$router.push({path: '/pay', query: {way: 'BUY_NOW'}});
|
||||
} else {
|
||||
this.$Message.warning(res.message);
|
||||
}
|
||||
});
|
||||
},
|
||||
async collect () { // 收藏商品
|
||||
if (this.isCollected) {
|
||||
let cancel = await cancelCollect('GOODS', this.skuDetail.id)
|
||||
if (cancel.success) {
|
||||
this.$Message.success('取消收藏成功')
|
||||
this.isCollected = false
|
||||
}
|
||||
} else {
|
||||
let collect = await collectGoods('GOODS', this.skuDetail.id);
|
||||
if (collect.code === 200) {
|
||||
this.isCollected = true;
|
||||
this.$Message.success('收藏商品成功,可以前往个人中心我的收藏查看');
|
||||
}
|
||||
}
|
||||
},
|
||||
formatSku (list) {
|
||||
// 格式化数据
|
||||
|
||||
let arr = [{}];
|
||||
|
||||
list.forEach((item, index) => {
|
||||
item.specValues.forEach((spec, specIndex) => {
|
||||
let id = spec.specNameId;
|
||||
let name = spec.specName;
|
||||
let values = {
|
||||
id: spec.specValueId,
|
||||
value: spec.specValue,
|
||||
quantity: item.quantity
|
||||
};
|
||||
if (name === 'images') {
|
||||
return;
|
||||
}
|
||||
|
||||
arr.forEach((arrItem, arrIndex) => {
|
||||
if (
|
||||
arrItem.name === name &&
|
||||
arrItem.values &&
|
||||
!arrItem.values.find((i) => i.id === values.id)
|
||||
) {
|
||||
arrItem.values.push(values);
|
||||
}
|
||||
|
||||
let keys = arr.map((key) => {
|
||||
return key.name;
|
||||
});
|
||||
if (!keys.includes(name)) {
|
||||
arr.push({
|
||||
id: id,
|
||||
name: name,
|
||||
values: [values]
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
arr.shift();
|
||||
this.formatList = arr;
|
||||
|
||||
let cur = list.filter((i) => i.skuId === this.$route.query.skuId)[0];
|
||||
if (cur) {
|
||||
cur.specValues.filter((i) => i.specName !== 'images')
|
||||
.forEach((value, _index) => {
|
||||
this.currentSelceted[_index] = value.specValueId;
|
||||
});
|
||||
}
|
||||
this.skuList = list;
|
||||
},
|
||||
receiveCoupon (id) { // 领取优惠券
|
||||
receiveCoupon(id).then(res => {
|
||||
if (res.success) {
|
||||
this.$Message.success('优惠券领取成功')
|
||||
} else {
|
||||
this.$Message.warning(res.message)
|
||||
}
|
||||
})
|
||||
},
|
||||
promotion () { // 格式化促销活动,返回当前促销的对象
|
||||
let keysArr = Object.keys(this.detail.promotionMap);
|
||||
if (keysArr.length === 0) return false;
|
||||
|
||||
for (let i = 0; i < keysArr.length; i++) {
|
||||
let key = keysArr[i].split('-')[0]
|
||||
if (key === 'COUPON') {
|
||||
this.promotionMap[key].push(this.detail.promotionMap[keysArr[i]])
|
||||
} else {
|
||||
this.promotionMap[key] = this.detail.promotionMap[keysArr[i]]
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
mounted () {
|
||||
if (this.Cookies.getItem('userInfo')) {
|
||||
isCollection('GOODS', this.skuDetail.id).then(res => {
|
||||
if (res.success && res.result) {
|
||||
this.isCollected = true;
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
this.formatSku(this.goodsSpecList);
|
||||
this.promotion()
|
||||
document.title = this.skuDetail.goodsName
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
/******************商品图片及购买详情开始******************/
|
||||
.item-detail-see {
|
||||
width: 175px;
|
||||
margin-left: 30px;
|
||||
}
|
||||
.inventory {
|
||||
padding-left: 4px;
|
||||
@include sub_color($light_sub_color);
|
||||
}
|
||||
|
||||
.global_color {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.see-Img {
|
||||
width: 100%;
|
||||
height: 175px;
|
||||
}
|
||||
|
||||
.see-Item {
|
||||
> p {
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
}
|
||||
|
||||
.Report {
|
||||
color: $theme_color !important;
|
||||
}
|
||||
|
||||
.wrapper {
|
||||
@include white_background_color();
|
||||
}
|
||||
.item-sale-flex {
|
||||
width: 29%;
|
||||
padding: 0 3%;
|
||||
}
|
||||
.item-sale {
|
||||
margin: 10px 0;
|
||||
> h3 {
|
||||
width: 13%;
|
||||
text-align: center;
|
||||
font-size: 20px;
|
||||
line-height: 60px;
|
||||
box-sizing: border-box;
|
||||
border-right: 1px solid $border_color;
|
||||
}
|
||||
height: 60px;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
display: flex;
|
||||
width: 1200px;
|
||||
margin: 0 auto;
|
||||
margin-bottom: 10px;
|
||||
border: 1px solid $border_color;
|
||||
background: #f7f7f7;
|
||||
}
|
||||
|
||||
.item-detail-show {
|
||||
width: 1200px;
|
||||
margin: 0 auto;
|
||||
padding: 30px;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
}
|
||||
|
||||
.item-detail-left {
|
||||
width: 350px;
|
||||
margin-right: 30px;
|
||||
}
|
||||
|
||||
.item-detail-big-img {
|
||||
width: 350px;
|
||||
height: 350px;
|
||||
box-shadow: 0px 0px 8px $border_color;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.item-detail-big-img img {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.item-detail-img-row {
|
||||
margin-top: 15px;
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.item-detail-img-small {
|
||||
width: 68px;
|
||||
height: 68px;
|
||||
box-shadow: 0px 0px 8px #ccc;
|
||||
cursor: pointer;
|
||||
margin-left: 5px;
|
||||
}
|
||||
|
||||
.item-detail-img-small img {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
/*商品选购详情*/
|
||||
.item-detail-right {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.item-detail-title p {
|
||||
@include content_color($light_content_color);
|
||||
font-weight: bold;
|
||||
font-size: 20px;
|
||||
padding: 8px 0;
|
||||
}
|
||||
|
||||
.item-detail-express {
|
||||
font-size: 14px;
|
||||
padding: 2px 3px;
|
||||
border-radius: 3px;
|
||||
background-color: $theme_color;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
/*商品标签*/
|
||||
.item-detail-tag {
|
||||
padding: 8px 0;
|
||||
font-size: 12px;
|
||||
color: $theme_color;
|
||||
}
|
||||
|
||||
/*价格详情等*/
|
||||
.item-detail-price-row {
|
||||
padding: 10px;
|
||||
display: flex;
|
||||
// width: 555px;
|
||||
flex-direction: row;
|
||||
justify-content: space-between;
|
||||
// @include background_color($light_background_color);
|
||||
background: url("../../assets/images/goodsDetail/price-bg.png");
|
||||
}
|
||||
|
||||
.item-price-left {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.item-price-title {
|
||||
color: #999999;
|
||||
font-size: 14px;
|
||||
margin-right: 15px;
|
||||
}
|
||||
|
||||
.item-price-row {
|
||||
margin: 5px 0px;
|
||||
}
|
||||
|
||||
.item-price {
|
||||
color: $theme_color;
|
||||
font-size: 20px;
|
||||
cursor: pointer;
|
||||
}
|
||||
.item-price-old {
|
||||
color: gray;
|
||||
text-decoration: line-through;
|
||||
font-size: 14px;
|
||||
margin-left: 5px;
|
||||
}
|
||||
|
||||
.item-coupon {
|
||||
margin-right: 5px;
|
||||
padding: 3px;
|
||||
color: $theme_color;
|
||||
font-size: 12px;
|
||||
background-color: #ffdedf;
|
||||
border: 1px dotted $theme_color;
|
||||
cursor: pointer;
|
||||
}
|
||||
.item-promotion {
|
||||
margin-right: 5px;
|
||||
padding: 3px;
|
||||
color: $theme_color;
|
||||
font-size: 12px;
|
||||
border: 1px solid $theme_color;
|
||||
}
|
||||
.item-remarks-sum {
|
||||
padding-left: 8px;
|
||||
border-left: 1px solid $border_color;
|
||||
}
|
||||
|
||||
.item-remarks-sum p {
|
||||
color: #999999;
|
||||
font-size: 12px;
|
||||
line-height: 10px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.item-remarks-num {
|
||||
line-height: 18px;
|
||||
color: #005eb7;
|
||||
}
|
||||
|
||||
.item-select {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
margin-top: 15px;
|
||||
}
|
||||
|
||||
.item-select-title {
|
||||
@include content_color($light_content_color);
|
||||
font-size: 14px;
|
||||
margin-right: 15px;
|
||||
width: 60px;
|
||||
}
|
||||
|
||||
.item-select-column {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.item-select-row {
|
||||
// display: flex;
|
||||
// flex-direction: row;
|
||||
// flex-wrap: wrap;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.item-select-box {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.item-select-img {
|
||||
width: 36px;
|
||||
}
|
||||
|
||||
.item-select-box {
|
||||
padding: 5px;
|
||||
margin-right: 8px;
|
||||
@include background_color($light_background_color);
|
||||
border: 0.5px solid $border_color;
|
||||
cursor: pointer;
|
||||
@include content_color($light_content_color);
|
||||
}
|
||||
|
||||
.item-select-box:hover {
|
||||
border: 0.5px solid $theme_color;
|
||||
}
|
||||
|
||||
.item-select-box-active {
|
||||
border: 0.5px solid $theme_color;
|
||||
}
|
||||
|
||||
.item-select-box-disabled {
|
||||
background-color: gray;
|
||||
}
|
||||
|
||||
.item-select-img img {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.item-select-intro p {
|
||||
margin: 0px;
|
||||
padding: 5px;
|
||||
}
|
||||
|
||||
.item-select-class {
|
||||
padding: 5px;
|
||||
margin-right: 8px;
|
||||
@include sub_background_color($light_background_color);
|
||||
border: 0.5px solid #ccc;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.item-select-class:hover {
|
||||
border: 0.5px solid $theme_color;
|
||||
}
|
||||
|
||||
.add-buy-car-box {
|
||||
width: 100%;
|
||||
margin-top: 15px;
|
||||
border-top: 1px dotted $border_color;
|
||||
}
|
||||
|
||||
.add-buy-car {
|
||||
margin-top: 15px;
|
||||
}
|
||||
|
||||
.goodsConfig {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
> span {
|
||||
padding-right: 10px;
|
||||
&:hover{
|
||||
cursor: pointer;
|
||||
color: $theme_color;
|
||||
}
|
||||
}
|
||||
}
|
||||
/******************商品图片及购买详情结束******************/
|
||||
</style>
|
||||
489
buyer/src/components/goodsDetail/ShowGoodsDetail.vue
Normal file
489
buyer/src/components/goodsDetail/ShowGoodsDetail.vue
Normal file
@@ -0,0 +1,489 @@
|
||||
<template>
|
||||
<div>
|
||||
<div class="item-intro-show">
|
||||
<!-- <div class="item-intro-recommend">
|
||||
<div class="item-recommend-title">
|
||||
<p>店铺热销</p>
|
||||
</div>
|
||||
<div class="item-intro-recommend-column">
|
||||
<div class="item-recommend-column" v-for="(item, index) in hotList" :key="index">
|
||||
<div class="item-recommend-img">
|
||||
<img :src="item.img" alt="">
|
||||
</div>
|
||||
<div class="item-recommend-intro">
|
||||
<span>
|
||||
<span class="item-recommend-top-num">{{index + 1}}</span> 热销{{item.sale}}件</span>
|
||||
<span class="item-recommend-price">¥{{item.price | unitPrice}}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div> -->
|
||||
<div class="item-intro-detail" ref="itemIntroDetail">
|
||||
<div class="item-intro-nav item-tabs">
|
||||
<Tabs :animated="false" @on-click="tabClick">
|
||||
<TabPane label="商品介绍">
|
||||
<div class="item-intro-img" ref="itemIntroGoods">
|
||||
<div v-html="skuDetail.intro" v-if="skuDetail.intro"></div>
|
||||
<div v-else style="margin:20px;">暂无商品介绍</div>
|
||||
</div>
|
||||
</TabPane>
|
||||
<TabPane label="商品评价">
|
||||
<div class="remarks-container" ref="itemGoodsComment">
|
||||
<div class="remarks-analyse-box">
|
||||
<div class="remarks-analyse-goods">
|
||||
<i-circle :percent="skuDetail.grade || 100" stroke-color="#5cb85c">
|
||||
<span class="remarks-analyse-num">{{skuDetail.grade || 100}}%</span>
|
||||
<p class="remarks-analyse-title">好评率</p>
|
||||
</i-circle>
|
||||
</div>
|
||||
</div>
|
||||
<div class="remarks-bar">
|
||||
<span @click="searchByGrade('')" :class="{selectedBar: commentParams.grade === ''}">全部({{commentTypeNum.all}})</span>
|
||||
<span @click="searchByGrade('GOOD')" :class="{selectedBar: commentParams.grade === 'GOOD'}">好评({{commentTypeNum.good}})</span>
|
||||
<span @click="searchByGrade('MODERATE')" :class="{selectedBar: commentParams.grade === 'MODERATE'}">中评({{commentTypeNum.moderate}})</span>
|
||||
<span @click="searchByGrade('WORSE')" :class="{selectedBar: commentParams.grade === 'WORSE'}">差评({{commentTypeNum.worse}})</span>
|
||||
</div>
|
||||
<div style="text-align: center;margin-top: 20px;" v-if="commentList.length === 0">
|
||||
暂无评价数据
|
||||
</div>
|
||||
<div class="remarks-box" v-for="(item,index) in commentList" :key="index" v-else>
|
||||
<div class="remarks-user">
|
||||
<Avatar :src="item.memberProfile" />
|
||||
<span class="remarks-user-name">{{item.memberName | secrecyMobile}}</span>
|
||||
</div>
|
||||
<div class="remarks-content-box">
|
||||
<p>
|
||||
<Rate disabled :value="Number(item.descriptionScore)" allow-half class="remarks-star"></Rate>
|
||||
</p>
|
||||
<p class="remarks-content">{{item.content}}</p>
|
||||
<div class="comment-img" v-if="item.haveImage">
|
||||
<div v-for="(img, imgIndex) in item.image.split(',')"
|
||||
@click="previewImg(img, item)"
|
||||
:class="{borderColor:img === item.previewImg}"
|
||||
:key="imgIndex">
|
||||
<img :src="img" alt="">
|
||||
</div>
|
||||
</div>
|
||||
<div class="preview-img" v-if="item.previewImg" @click.prevent="hidePreviewImg(item)">
|
||||
<div>
|
||||
<span @click.stop="rotatePreviewImg(0, item)"><Icon type="md-refresh" />左转</span>
|
||||
<span @click.stop="rotatePreviewImg(1, item)"><Icon type="md-refresh" />右转</span>
|
||||
</div>
|
||||
<img :src="item.previewImg" :style="{transform:`rotate(${item.deg}deg)`}" width="198" alt="">
|
||||
</div>
|
||||
<p class="remarks-sub">
|
||||
<span class="remarks-item">{{item.goodsName}}</span>
|
||||
<span class="remarks-time">{{item.createTime}}</span>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="remarks-page">
|
||||
<Page :total="commentTotal" size="small"
|
||||
@on-change="changePageNum"
|
||||
@on-page-size-change="changePageSize"
|
||||
:page-size="commentParams.pageSize"
|
||||
></Page>
|
||||
</div>
|
||||
</div>
|
||||
</TabPane>
|
||||
<!-- <TabPane label="商品问答">
|
||||
<ShowGoodsQuestion/>
|
||||
</TabPane> -->
|
||||
</Tabs>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import ShowGoodsQuestion from '@/components/goodsDetail/ShowGoodsQuestion';
|
||||
import { goodsComment, goodsCommentNum } from '@/api/member.js';
|
||||
export default {
|
||||
name: 'ShowGoodsDetail',
|
||||
props: {
|
||||
detail: { // 商品详情
|
||||
type: Object,
|
||||
default: null
|
||||
}
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
commentList: [], // 评论列表
|
||||
commentParams: { // 评论传参
|
||||
pageNumber: 1,
|
||||
pageSize: 10,
|
||||
grade: '',
|
||||
goodsId: ''
|
||||
},
|
||||
commentTypeNum: {}, // 评论数量,包括好中差分别的数量
|
||||
commentTotal: 0, // 评论总数
|
||||
onceFlag: true // 只调用一次
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
skuDetail () {
|
||||
return this.detail.data;
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
changeHeight (name) {
|
||||
let heightCss = window.getComputedStyle(this.$refs[name]).height;
|
||||
heightCss = parseInt(heightCss.substr(0, heightCss.length - 2)) + 89;
|
||||
this.$refs.itemIntroDetail.style.height = heightCss + 'px';
|
||||
},
|
||||
changePageNum (val) {
|
||||
this.commentParams.pageNumber = val;
|
||||
this.getList();
|
||||
},
|
||||
changePageSize (val) {
|
||||
this.commentParams.pageNumber = 1;
|
||||
this.commentParams.pageSize = val;
|
||||
this.getList();
|
||||
},
|
||||
getList () { // 获取评论列表
|
||||
this.commentParams.goodsId = this.skuDetail.goodsId;
|
||||
goodsComment(this.commentParams).then(res => {
|
||||
if (res.code === 200) {
|
||||
this.commentList = res.result.records;
|
||||
this.commentTotal = res.result.total;
|
||||
}
|
||||
});
|
||||
goodsCommentNum(this.skuDetail.goodsId).then(res => {
|
||||
if (res.code === 200) {
|
||||
this.commentTypeNum = res.result;
|
||||
}
|
||||
});
|
||||
},
|
||||
searchByGrade (grade) {
|
||||
this.$set(this.commentParams, 'grade', grade);
|
||||
this.commentParams.pageNumber = 1;
|
||||
this.getList();
|
||||
},
|
||||
tabClick (name) {
|
||||
if (name === 0) {
|
||||
this.$nextTick(() => {
|
||||
this.changeHeight('itemIntroGoods')
|
||||
});
|
||||
} else {
|
||||
this.$nextTick(() => {
|
||||
this.changeHeight('itemGoodsComment')
|
||||
});
|
||||
}
|
||||
},
|
||||
previewImg (img, item) { // 预览图片
|
||||
this.$set(item, 'previewImg', img);
|
||||
this.$nextTick(() => {
|
||||
this.changeHeight('itemGoodsComment')
|
||||
});
|
||||
},
|
||||
hidePreviewImg (item) { // 隐藏预览图片
|
||||
this.$set(item, 'previewImg', '');
|
||||
this.$nextTick(() => {
|
||||
this.changeHeight('itemGoodsComment')
|
||||
});
|
||||
},
|
||||
rotatePreviewImg (type, item) { // 图片旋转
|
||||
if (type) {
|
||||
if (item.deg) {
|
||||
this.$set(item, 'deg', item.deg + 90);
|
||||
} else {
|
||||
this.$set(item, 'deg', 90);
|
||||
}
|
||||
} else {
|
||||
if (item.deg) {
|
||||
this.$set(item, 'deg', item.deg - 90);
|
||||
} else {
|
||||
this.$set(item, 'deg', -90);
|
||||
}
|
||||
}
|
||||
},
|
||||
handleScroll () {
|
||||
if (this.onceFlag) {
|
||||
this.$nextTick(() => {
|
||||
this.changeHeight('itemIntroGoods')
|
||||
});
|
||||
this.onceFlag = false
|
||||
}
|
||||
}
|
||||
},
|
||||
mounted () {
|
||||
this.$nextTick(() => {
|
||||
setTimeout(this.changeHeight('itemIntroGoods'), 2000);
|
||||
});
|
||||
window.addEventListener('scroll', this.handleScroll)
|
||||
this.getList();
|
||||
},
|
||||
components: {
|
||||
ShowGoodsQuestion
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
/***************商品详情介绍和推荐侧边栏开始***************/
|
||||
.item-intro-show{
|
||||
|
||||
width: 1200px;
|
||||
margin: 15px auto;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
|
||||
}
|
||||
.item-intro-recommend{
|
||||
width: 200px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
.item-intro-recommend-column{
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
box-shadow: 0px 0px 5px #999;
|
||||
}
|
||||
.item-recommend-title{
|
||||
width: 100%;
|
||||
height: 38px;
|
||||
font-size: 16px;
|
||||
line-height: 38px;
|
||||
color: #fff;
|
||||
background-color: $theme_color;
|
||||
box-shadow: 0px 0px 5px $theme_color;
|
||||
text-align: center;
|
||||
}
|
||||
.item-recommend-column{
|
||||
margin-top: 15px;
|
||||
}
|
||||
.item-recommend-intro{
|
||||
padding: 5px 15px;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: space-between;
|
||||
font-size: 12px;
|
||||
color: #999;
|
||||
cursor: pointer;
|
||||
}
|
||||
.item-recommend-img{
|
||||
width: 80%;
|
||||
margin: 0px auto;
|
||||
cursor: pointer;
|
||||
}
|
||||
.item-recommend-img img{
|
||||
width: 100%;
|
||||
}
|
||||
.item-recommend-top-num{
|
||||
color: #fff;
|
||||
margin: 0px 2px;
|
||||
padding: 1px 5px;
|
||||
border-radius: 12px;
|
||||
background-color: $theme_color;
|
||||
}
|
||||
.item-recommend-price{
|
||||
color: $theme_color;
|
||||
font-weight: bolder;
|
||||
}
|
||||
.item-intro-detail{
|
||||
margin: 0 30px;
|
||||
// min-height: 1500px;
|
||||
width: 100%;
|
||||
}
|
||||
.item-intro-nav{
|
||||
width: 100%;
|
||||
height: 38px;
|
||||
background-color: #F7F7F7;
|
||||
// border-bottom: 1px solid $theme_color;
|
||||
}
|
||||
.item-intro-nav ul{
|
||||
margin: 0px;
|
||||
padding: 0px;
|
||||
list-style: none;
|
||||
}
|
||||
.item-intro-nav li{
|
||||
float: left;
|
||||
height: 100%;
|
||||
width: 120px;
|
||||
line-height: 38px;
|
||||
text-align: center;
|
||||
color: $theme_color;
|
||||
}
|
||||
.item-intro-nav li:first-child{
|
||||
background-color: $theme_color;
|
||||
color: #fff;
|
||||
}
|
||||
.item-intro-img {
|
||||
width: 100%;
|
||||
min-height: 300px;
|
||||
}
|
||||
.item-intro-img img{
|
||||
max-width: 1000px;
|
||||
}
|
||||
/************* 商品参数 *************/
|
||||
.item-param-container {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
flex-direction: row;
|
||||
justify-content: space-between;
|
||||
}
|
||||
.item-param-box {
|
||||
padding: 5px;
|
||||
padding-left: 30px;
|
||||
width: 240px;
|
||||
height: 36px;
|
||||
font-size: 14px;
|
||||
/* text-align: center; */
|
||||
/* background-color: #ccc; */
|
||||
}
|
||||
.item-param-title {
|
||||
color: #232323;
|
||||
}
|
||||
.item-param-content {
|
||||
color: #999;
|
||||
}
|
||||
.remarks-title {
|
||||
padding-left: 15px;
|
||||
height: 36px;
|
||||
font-size: 16px;
|
||||
font-weight: bolder;
|
||||
line-height: 36px;
|
||||
color: #666666;
|
||||
background-color: #F7F7F7;
|
||||
}
|
||||
.remarks-analyse-box {
|
||||
padding: 15px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
.remarks-analyse-goods {
|
||||
margin-left: 15px;
|
||||
margin-right: 15px;
|
||||
}
|
||||
.remarks-analyse-num {
|
||||
font-size: 26px;
|
||||
}
|
||||
.remarks-analyse-title {
|
||||
font-size: 12px;
|
||||
line-height: 20px;
|
||||
}
|
||||
.remarks-bar {
|
||||
padding-left: 15px;
|
||||
height: 36px;
|
||||
line-height: 36px;
|
||||
color: #666666;
|
||||
background-color: #F7F7F7;
|
||||
.selectedBar{
|
||||
color: $theme_color;
|
||||
}
|
||||
}
|
||||
.remarks-bar span {
|
||||
margin-right: 15px;
|
||||
&:hover{
|
||||
color: $theme_color;
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
.remarks-box {
|
||||
padding: 15px;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
border-bottom: 1px #ccc dotted;
|
||||
}
|
||||
.remarks-user {
|
||||
width: 180px;
|
||||
}
|
||||
.remarks-user-name {
|
||||
padding-left: 15px;
|
||||
}
|
||||
.remarks-content-box {
|
||||
width: calc(100% - 180px);
|
||||
.comment-img{
|
||||
display: flex;
|
||||
.borderColor{
|
||||
border-color: $theme_color;
|
||||
}
|
||||
div{
|
||||
border: 1px solid #999;
|
||||
margin-right: 5px;
|
||||
width: 50px;
|
||||
height: 50px;
|
||||
img{width: 100%;}
|
||||
}
|
||||
}
|
||||
.preview-img{
|
||||
position: relative;
|
||||
border: 1px solid #eee;
|
||||
margin: 10px 0;
|
||||
width: 200px;
|
||||
|
||||
div{
|
||||
position: absolute;
|
||||
top: 3px;
|
||||
left: 3px;
|
||||
z-index: 3;
|
||||
span{
|
||||
display: inline-block;
|
||||
background-color: rgba(0,0,0,.5);
|
||||
padding:3px 5px;
|
||||
color: #fff;
|
||||
border-radius: 4px;
|
||||
cursor: pointer;
|
||||
}
|
||||
span:nth-child(1) .ivu-icon {
|
||||
transform: rotateY(180deg);
|
||||
}
|
||||
}
|
||||
|
||||
img:hover{
|
||||
cursor: url(require('../../../static/small.cur')),auto;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.remarks-content {
|
||||
font-size: 14px;
|
||||
color: #232323;
|
||||
line-height: 28px;
|
||||
}
|
||||
.remarks-sub {
|
||||
margin-top: 5px;
|
||||
color: #ccc;
|
||||
}
|
||||
.remarks-time {
|
||||
margin-left: 15px;
|
||||
}
|
||||
.remarks-page {
|
||||
margin: 15px;
|
||||
display: flex;
|
||||
justify-content:flex-end;
|
||||
}
|
||||
/***************商品详情介绍和推荐侧边栏结束***************/
|
||||
/* 改变便签页样式 */
|
||||
.ivu-tabs-ink-bar {
|
||||
background-color: $theme_color !important;
|
||||
}
|
||||
/deep/.ivu-tabs-bar{
|
||||
border: none;
|
||||
}
|
||||
.item-tabs > .ivu-tabs > .ivu-tabs-bar .ivu-tabs-tab{
|
||||
border-radius: 0px;
|
||||
color: #999;
|
||||
height: 38px;
|
||||
// background: #F7F7F7;
|
||||
}
|
||||
.item-tabs > .ivu-tabs > .ivu-tabs-bar .ivu-tabs-tab-active{
|
||||
color: #fff;
|
||||
background-color: $theme_color;
|
||||
}
|
||||
.item-tabs > .ivu-tabs > .ivu-tabs-bar .ivu-tabs-tab-active:before{
|
||||
content: '';
|
||||
display: block;
|
||||
width: 100%;
|
||||
height: 1px;
|
||||
color: #fff;
|
||||
background: #F7F7F7;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
}
|
||||
.ivu-rate-star-full:before, .ivu-rate-star-half .ivu-rate-star-content:before {
|
||||
color: $theme_color;
|
||||
}
|
||||
</style>
|
||||
53
buyer/src/components/goodsDetail/ShowGoodsQuestion.vue
Normal file
53
buyer/src/components/goodsDetail/ShowGoodsQuestion.vue
Normal file
@@ -0,0 +1,53 @@
|
||||
<template>
|
||||
<div class="wrapper">
|
||||
<div v-if="true" class="question-list">
|
||||
<div class="-item" v-for="index in 6" :key="index">
|
||||
<!-- 提问 -->
|
||||
<div class="-item-put -item-div">
|
||||
<div class="-item-div-l blod">
|
||||
<Tag color="warning">问</Tag>
|
||||
有屏幕调节亮度吗
|
||||
</div>
|
||||
<div class="-item-div-r">2020年10月21日17:03:35</div>
|
||||
</div>
|
||||
<!-- 解答 -->
|
||||
<div class="-item-reply -item-div">
|
||||
<div class="-item-div-l">
|
||||
<Tag color="success">答</Tag>
|
||||
能调节,点屏幕上方有一条调整带,可正负2调整。
|
||||
</div>
|
||||
<div class="-item-div-r">2020年10月21日17:03:35</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div v-else class="question-empty">
|
||||
<empty></empty>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
export default {};
|
||||
</script>
|
||||
<style scoped lang="scss">
|
||||
.-item-div {
|
||||
padding: 10px 0;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
margin: 10px 0;
|
||||
}
|
||||
.-item-div-l {
|
||||
display: flex;
|
||||
@include content_color($light_content_color);
|
||||
}
|
||||
.-item-div-r {
|
||||
@include sub_color($light_content_color);
|
||||
}
|
||||
.blod {
|
||||
font-weight: bold;
|
||||
}
|
||||
.-item {
|
||||
margin: 10px 0;
|
||||
border-bottom: 1px solid $border_color;
|
||||
}
|
||||
</style>
|
||||
85
buyer/src/components/goodsDetail/ShowProductWarranty.vue
Normal file
85
buyer/src/components/goodsDetail/ShowProductWarranty.vue
Normal file
@@ -0,0 +1,85 @@
|
||||
<template>
|
||||
<div>
|
||||
<div class="remarks-title">
|
||||
<span>售后保障</span>
|
||||
</div>
|
||||
<div class="item-protect-container">
|
||||
<div class="item-protect-box">
|
||||
<p class="item-protect-title-box">
|
||||
<Avatar style="background-color: #e4393c" icon="ribbon-a" />
|
||||
<span class="item-protect-title">卖家服务</span>
|
||||
</p>
|
||||
<p class="item-protect-detail">
|
||||
高品质敢承诺:7天无理由退货,30天免费换新,质量问题商家承担来回运费换新;如需发票,请在确认收货无误后联系商家开出。(注*发票不随货品一同发出)
|
||||
</p>
|
||||
</div>
|
||||
<div class="item-protect-box">
|
||||
<p class="item-protect-title-box">
|
||||
<Avatar style="background-color: #e4393c" icon="cash" />
|
||||
<span class="item-protect-title">平台承诺</span>
|
||||
</p>
|
||||
<p class="item-protect-detail">
|
||||
平台卖家销售并发货的商品,由平台卖家提供发票和相应的售后服务。请您放心购买!<br> 注:因厂家会在没有任何提前通知的情况下更改产品包装、产地或者一些附件,本司不能确保客户收到的货物与商城图片、产地、附件说明完全一致。只能确保为原厂正货!并且保证与当时市场上同样主流新品一致。若本商城没有及时更新,请大家谅解!
|
||||
</p>
|
||||
</div>
|
||||
<div class="item-protect-box">
|
||||
<p class="item-protect-title-box">
|
||||
<Avatar style="background-color: #e4393c" icon="locked" />
|
||||
<span class="item-protect-title">正品行货</span>
|
||||
</p>
|
||||
<p class="item-protect-detail">
|
||||
BIT商城向您保证所售商品均为正品行货,BIT自营商品开具机打发票或电子发票。
|
||||
</p>
|
||||
</div>
|
||||
<div class="item-protect-box">
|
||||
<p class="item-protect-title-box">
|
||||
<Avatar style="background-color: #e4393c" icon="settings" />
|
||||
<span class="item-protect-title">全国联保</span>
|
||||
</p>
|
||||
<p class="item-protect-detail">
|
||||
凭质保证书及BIT商城发票,可享受全国联保服务(奢侈品、钟表除外;奢侈品、钟表由BIT联系保修,享受法定三包售后服务),与您亲临商场选购的商品享受相同的质量保证。BIT商城还为您提供具有竞争力的商品价格和运费政策,请您放心购买!<br><br> 注:因厂家会在没有任何提前通知的情况下更改产品包装、产地或者一些附件,本司不能确保客户收到的货物与商城图片、产地、附件说明完全一致。只能确保为原厂正货!并且保证与当时市场上同样主流新品一致。若本商城没有及时更新,请大家谅解!
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'ShowProductWarranty'
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.remarks-title {
|
||||
padding-left: 15px;
|
||||
height: 36px;
|
||||
font-size: 16px;
|
||||
font-weight: bolder;
|
||||
line-height: 36px;
|
||||
color: #666666;
|
||||
background-color: #F7F7F7;
|
||||
}
|
||||
.item-protect-container {
|
||||
padding: 15px;
|
||||
}
|
||||
.item-protect-box {
|
||||
margin-bottom: 30px;
|
||||
}
|
||||
.item-protect-title-box {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
.item-protect-title {
|
||||
padding-left: 15px;
|
||||
font-size: 20px;
|
||||
font-weight: bolder;
|
||||
color: $theme_color;
|
||||
}
|
||||
.item-protect-detail {
|
||||
padding-top: 5px;
|
||||
padding-left: 46px;
|
||||
font-size: 14px;
|
||||
color: #999;
|
||||
}
|
||||
</style>
|
||||
426
buyer/src/components/header/Header.vue
Normal file
426
buyer/src/components/header/Header.vue
Normal file
@@ -0,0 +1,426 @@
|
||||
<template>
|
||||
<div class="box">
|
||||
<div class="nav">
|
||||
<ul class="location">
|
||||
<li><router-link to="/" v-if="$route.path !== '/'" class="home-page" ><Icon type="md-home" />首页</router-link></li>
|
||||
<li>
|
||||
<Dropdown placement="bottom-start">
|
||||
<a href="javascript:void(0)">
|
||||
<Icon type="ios-pin" class="icon"></Icon>
|
||||
{{ city }}
|
||||
</a>
|
||||
<DropdownMenu slot="list">
|
||||
<div class="city">
|
||||
<p v-for="(items, index) in cityArr" :key="index">
|
||||
<span
|
||||
v-for="(item, index) in items"
|
||||
class="city-item"
|
||||
:key="index"
|
||||
@click="changeCity(item)"
|
||||
>{{ item }}</span>
|
||||
</p>
|
||||
</div>
|
||||
</DropdownMenu>
|
||||
</Dropdown>
|
||||
</li>
|
||||
</ul>
|
||||
<ul class="detail">
|
||||
<!-- <li class="first hover-pointer" @click="handleClickTheme()">切换主题</li> -->
|
||||
<li class="first" v-show="!userInfo.username">
|
||||
<router-link :to="`/login?rePath=${$route.path}&query=${JSON.stringify($route.query)}`">
|
||||
<span style="border:none" class="tipsLogin">请登录</span>
|
||||
</router-link>
|
||||
</li>
|
||||
<li v-show="!!userInfo.username">
|
||||
<Dropdown>
|
||||
<p class="username-p">
|
||||
<Avatar class="person-icon" :src="userInfo.face" icon="person" size="small" />
|
||||
<span class="username">{{ userInfo.nickName? userInfo.nickName : userInfo.username | secrecyMobile }}</span>
|
||||
</p>
|
||||
<DropdownMenu slot="list">
|
||||
<div class="my-page">
|
||||
<div class="my-info" @click="myInfo">
|
||||
<Icon type="md-home"></Icon>
|
||||
<p>我的主页</p>
|
||||
</div>
|
||||
<div class="sign-out" @click="signOutFun">
|
||||
<Icon type="md-exit"></Icon>
|
||||
<p>退出登陆</p>
|
||||
</div>
|
||||
</div>
|
||||
</DropdownMenu>
|
||||
</Dropdown>
|
||||
</li>
|
||||
<li class="hover-color" @click="goUserCenter('home/MyOrder')"><span class="nav-item">我的订单</span></li>
|
||||
<li class="hover-color" @click="goUserCenter('home/MyTracks')"><span class="nav-item">我的足迹</span></li>
|
||||
<li v-if="$route.name !== 'Cart'" style="position:relative;" @mouseenter="getCartList">
|
||||
<i class="cart-badge" v-show="cartNum">{{cartNum < 100 ? cartNum : '99'}}</i>
|
||||
<Dropdown placement="bottom-start">
|
||||
<router-link to="cart" target="_blank">
|
||||
<Icon
|
||||
size="18"
|
||||
class="cart-icon"
|
||||
type="ios-cart-outline"
|
||||
></Icon>
|
||||
购物车
|
||||
</router-link>
|
||||
|
||||
<DropdownMenu slot="list">
|
||||
<div class="shopping-cart-null" style="width:200px" v-show="shoppingCart.length <= 0">
|
||||
<Icon type="ios-cart-outline" class="cart-null-icon"></Icon>
|
||||
<span>你的购物车没有宝贝哦</span>
|
||||
<span>赶快去添加商品吧~</span>
|
||||
</div>
|
||||
<div class="shopping-cart-list" v-show="shoppingCart.length > 0">
|
||||
<div
|
||||
class="shopping-cart-box"
|
||||
v-for="(item, index) in shoppingCart"
|
||||
@click="goToPay"
|
||||
:key="index"
|
||||
>
|
||||
<div class="shopping-cart-img">
|
||||
<img :src="item.goodsSku.thumbnail" class="hover-pointer" />
|
||||
</div>
|
||||
<div class="shopping-cart-info">
|
||||
<div class="shopping-cart-title ">
|
||||
<p class="hover-pointer goods-title">{{ item.goodsSku.goodsName }}</p>
|
||||
</div>
|
||||
<div class="shopping-cart-detail">
|
||||
<p>
|
||||
数量:
|
||||
<span class="shopping-cart-text">{{ item.num }}</span>
|
||||
价钱:
|
||||
<span class="shopping-cart-text">{{ item.purchasePrice | unitPrice('¥') }}</span>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="go-to-buy">
|
||||
<Button type="error" size="small" @click="goToPay">去结账</Button>
|
||||
</div>
|
||||
</div>
|
||||
</DropdownMenu>
|
||||
</Dropdown>
|
||||
</li>
|
||||
<li>
|
||||
<span class="nav-item" @click="shopEntry">店铺入驻</span>
|
||||
</li>
|
||||
<!-- <li>
|
||||
<router-link to="/feedback">意见反馈</router-link>
|
||||
</li>-->
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import storage from '@/plugins/storage.js';
|
||||
import {cartGoodsAll, cartCount} from '@/api/cart.js'
|
||||
export default {
|
||||
name: 'M-Header',
|
||||
created () {
|
||||
if (storage.getItem('userInfo')) {
|
||||
this.userInfo = JSON.parse(storage.getItem('userInfo'));
|
||||
}
|
||||
},
|
||||
|
||||
data () {
|
||||
return {
|
||||
// 主题颜色切换
|
||||
themeType: 'light',
|
||||
city: '珠海', // 展示城市
|
||||
cityArr: [
|
||||
['北京', '上海', '天津', '重庆', '广州'],
|
||||
['深圳', '河南', '辽宁', '吉林', '江苏'],
|
||||
['江西', '四川', '海南', '贵州', '云南'],
|
||||
['西藏', '陕西', '甘肃', '青海', '珠海']
|
||||
],
|
||||
userInfo: {}, // 用户信息
|
||||
shoppingCart: [] // 购物车
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
cartNum () {
|
||||
return this.$store.state.cartNum
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
handleClickTheme () {
|
||||
this.themeType === 'light'
|
||||
? (this.themeType = 'dark')
|
||||
: (this.themeType = 'light');
|
||||
window.document.documentElement.setAttribute(
|
||||
'data-theme',
|
||||
this.themeType
|
||||
);
|
||||
},
|
||||
changeCity (city) {
|
||||
this.city = city;
|
||||
},
|
||||
goToPay () {
|
||||
let url = this.$router.resolve({
|
||||
path: '/cart'
|
||||
})
|
||||
window.open(url.href, '_blank')
|
||||
},
|
||||
myInfo () {
|
||||
let url = this.$router.resolve({
|
||||
path: '/home'
|
||||
})
|
||||
window.open(url.href, '_blank')
|
||||
},
|
||||
signOutFun () {
|
||||
storage.removeItem('accessToken');
|
||||
storage.removeItem('refreshToken');
|
||||
storage.removeItem('userInfo');
|
||||
this.$router.push('/login');
|
||||
},
|
||||
goUserCenter (path) { // 跳转我的订单,我的足迹
|
||||
if (this.userInfo.username) {
|
||||
this.$router.push({path: path})
|
||||
} else {
|
||||
this.$Modal.confirm({
|
||||
title: '请登录',
|
||||
content: '<p>请登录后执行此操作</p>',
|
||||
okText: '立即登录',
|
||||
cancelText: '继续浏览',
|
||||
onOk: () => {
|
||||
this.$router.push({
|
||||
path: '/login',
|
||||
query: {
|
||||
rePath: this.$router.history.current.path,
|
||||
query: JSON.stringify(this.$router.history.current.query)
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
shopEntry () { // 店铺入驻
|
||||
if (storage.getItem('accessToken')) {
|
||||
let routeUrl = this.$router.resolve({
|
||||
path: '/shopEntry',
|
||||
query: {id: 1}
|
||||
});
|
||||
window.open(routeUrl.href, '_blank');
|
||||
} else {
|
||||
this.$router.push('login');
|
||||
}
|
||||
},
|
||||
getCartList () { // 获取购物车列表
|
||||
if (this.userInfo.username) {
|
||||
cartCount().then(res => {
|
||||
this.$store.commit('SET_CARTNUM', res.result)
|
||||
this.Cookies.setItem('cartNum', res.result)
|
||||
})
|
||||
cartGoodsAll().then(res => {
|
||||
this.shoppingCart = res.result.skuList
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.shopping-cart-detail,
|
||||
.shopping-cart-text,
|
||||
.shopping-cart-info,
|
||||
.nav a,
|
||||
.location,
|
||||
.first,
|
||||
.username,
|
||||
.shopping-cart-null span {
|
||||
@include sub_color($light_sub_color);
|
||||
}
|
||||
.tipsLogin {
|
||||
color: $theme_color;
|
||||
}
|
||||
|
||||
.box {
|
||||
width: 100%;
|
||||
// height: 35px;
|
||||
@include background_color($light_white_background_color);
|
||||
}
|
||||
.nav {
|
||||
margin: 0 auto;
|
||||
width: 1200px;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: space-between;
|
||||
}
|
||||
.nav ul {
|
||||
list-style: none;
|
||||
}
|
||||
.nav li {
|
||||
float: left;
|
||||
font-size: 14px;
|
||||
line-height: 35px;
|
||||
margin-right: 15px;
|
||||
font-weight: bold;
|
||||
}
|
||||
.nav a,.nav-item {
|
||||
text-decoration: none;
|
||||
padding-left: 15px;
|
||||
border-left: 1px solid #ccc;
|
||||
color: #999;
|
||||
cursor: pointer;
|
||||
}
|
||||
.location a {
|
||||
border-left: none;
|
||||
}
|
||||
.nav a:hover {
|
||||
color: $theme_color;
|
||||
}
|
||||
|
||||
.icon {
|
||||
color: gray;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.first a:first-child {
|
||||
padding-left: 3px;
|
||||
border-left: none;
|
||||
}
|
||||
.city {
|
||||
padding: 10px 15px;
|
||||
}
|
||||
.city-item {
|
||||
font-weight: bold;
|
||||
cursor: pointer;
|
||||
padding: 5px;
|
||||
}
|
||||
.city-item:hover {
|
||||
color: $theme_color;
|
||||
}
|
||||
.person-icon {
|
||||
color: $theme_color;
|
||||
background-color: #f0cdb2;
|
||||
}
|
||||
|
||||
.shopping-cart-list {
|
||||
padding: 10px 15px;
|
||||
box-sizing: border-box;
|
||||
height: 300px;
|
||||
overflow: scroll;
|
||||
}
|
||||
.shopping-cart-box {
|
||||
margin: 8px 0px;
|
||||
margin-top: 15px;
|
||||
padding-bottom: 15px;
|
||||
height: 40px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
border-bottom: 1px #ccc dotted;
|
||||
}
|
||||
.shopping-cart-box:first-child {
|
||||
margin-top: 8px;
|
||||
}
|
||||
.shopping-cart-img {
|
||||
margin-right: 15px;
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
}
|
||||
.shopping-cart-img img {
|
||||
width: 100%;
|
||||
}
|
||||
.shopping-cart-info {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
align-content: space-between;
|
||||
width: 200px;
|
||||
overflow: hidden;
|
||||
font-size: 12px;
|
||||
line-height: 20px;
|
||||
}
|
||||
|
||||
.go-to-buy {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
}
|
||||
.shopping-cart-null {
|
||||
padding: 15px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
.cart-null-icon {
|
||||
font-size: 38px;
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
.shopping-cart-null span {
|
||||
font-size: 12px;
|
||||
line-height: 16px;
|
||||
}
|
||||
.username-p {
|
||||
cursor: pointer;
|
||||
}
|
||||
.my-page {
|
||||
padding: 3px 5px;
|
||||
width: 180px;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
.my-page a {
|
||||
margin: 0px;
|
||||
padding: 0px;
|
||||
border: none;
|
||||
}
|
||||
.my-info {
|
||||
padding: 5px;
|
||||
width: 50%;
|
||||
height: 100%;
|
||||
text-align: center;
|
||||
cursor: pointer;
|
||||
}
|
||||
.my-info:hover {
|
||||
box-shadow: 0px 0px 5px #ccc;
|
||||
}
|
||||
.my-info i {
|
||||
font-size: 28px;
|
||||
}
|
||||
.my-info p {
|
||||
font-size: 12px;
|
||||
}
|
||||
.sign-out {
|
||||
padding: 5px;
|
||||
width: 50%;
|
||||
height: 100%;
|
||||
text-align: center;
|
||||
cursor: pointer;
|
||||
}
|
||||
.sign-out:hover {
|
||||
box-shadow: 0px 0px 5px $border_color;
|
||||
}
|
||||
.sign-out i {
|
||||
font-size: 28px;
|
||||
}
|
||||
.sign-out p {
|
||||
font-size: 12px;
|
||||
}
|
||||
.cart-icon{
|
||||
padding: 0 6px;
|
||||
}
|
||||
.goods-title:hover {
|
||||
color: $theme_color;
|
||||
}
|
||||
.cart-badge {
|
||||
position: absolute;
|
||||
right: -8px;
|
||||
font-style: normal;
|
||||
background-color: $theme_color;
|
||||
color: #fff;
|
||||
font-size: 12px;
|
||||
width: 17px;
|
||||
height: 17px;
|
||||
border-radius: 10px;
|
||||
line-height: 17px;
|
||||
text-align: center;
|
||||
z-index: 3;
|
||||
top: 3px;
|
||||
}
|
||||
</style>
|
||||
102
buyer/src/components/header/ShopHeader.vue
Normal file
102
buyer/src/components/header/ShopHeader.vue
Normal file
@@ -0,0 +1,102 @@
|
||||
<template>
|
||||
<div class="shop-box">
|
||||
<div class="shop-container">
|
||||
<div class="shop-title">
|
||||
<div class="shop-title-content">
|
||||
<p><router-link :to="`/merchant?id=${skuDetail.storeId}`">{{ skuDetail.storeName }}</router-link></p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'ShopHeader',
|
||||
props: {
|
||||
detail: {
|
||||
type: Object,
|
||||
default: null
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
skuDetail () {
|
||||
return this.detail;
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
/* 店铺介绍 */
|
||||
.shop-box {
|
||||
width: 100%;
|
||||
height: 50px;
|
||||
background-color: #484848;
|
||||
}
|
||||
|
||||
.shop-container {
|
||||
width: 1200px;
|
||||
height: 100%;
|
||||
margin: 0px auto;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.shop-title {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
}
|
||||
|
||||
.shop-title-icon {
|
||||
font-size: 46px;
|
||||
}
|
||||
|
||||
.shop-title-content {
|
||||
padding-top: 8px;
|
||||
margin-left: 15px;
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.shop-title-content p {
|
||||
line-height: 26px;
|
||||
font-size: 20px;
|
||||
|
||||
}
|
||||
.shop-title-content p:nth-child(2) {
|
||||
font-size: 16px;
|
||||
margin-left: 20px;
|
||||
}
|
||||
.shop-title-content a {
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.shop-another-item {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
}
|
||||
|
||||
.shop-another-item-detail {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
margin-left: 15px;
|
||||
}
|
||||
|
||||
.shop-another-item-img {
|
||||
height: 80px;
|
||||
border-radius: 40px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.shop-another-item-img img {
|
||||
width: 80px;
|
||||
}
|
||||
|
||||
.shop-anoter-item-intro {
|
||||
margin-left: 15px;
|
||||
}
|
||||
</style>
|
||||
93
buyer/src/components/header/hoverSearch.vue
Normal file
93
buyer/src/components/header/hoverSearch.vue
Normal file
@@ -0,0 +1,93 @@
|
||||
<template>
|
||||
<div class="scroll-show">
|
||||
<div class="content clearfix">
|
||||
<cateNav class="cate" :showNavBar="false"></cateNav>
|
||||
<Search class="search-con" :showLogo="false" :showTag="false"></Search>
|
||||
<Icon type="ios-cart-outline" @click="goCartList" class="cart-icon" @mouseenter.native="getCartList" />
|
||||
<i class="cart-badge">{{cartNum < 100 ? cartNum : '99'}}</i>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import {cartCount} from '@/api/cart.js'
|
||||
import storage from '@/plugins/storage.js';
|
||||
export default {
|
||||
data () {
|
||||
return {
|
||||
userInfo: {} // 用户信息
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
cartNum () { // 购物车数量
|
||||
return this.$store.state.cartNum
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
goCartList () {
|
||||
let routerUrl = this.$router.resolve({
|
||||
path: '/cart'
|
||||
})
|
||||
window.open(routerUrl.href, '_blank')
|
||||
},
|
||||
getCartList () { // 获取购物车列表
|
||||
if (storage.getItem('userInfo')) {
|
||||
cartCount().then(res => {
|
||||
this.$store.commit('SET_CARTNUM', res.result)
|
||||
this.Cookies.setItem('cartNum', res.result)
|
||||
})
|
||||
}
|
||||
}
|
||||
},
|
||||
mounted () {
|
||||
if (storage.getItem('userInfo')) {
|
||||
this.userInfo = JSON.parse(storage.getItem('userInfo'));
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.content{
|
||||
width: 1200px;
|
||||
height: 40px;
|
||||
margin: 10px auto;
|
||||
position: relative;
|
||||
}
|
||||
.cate {
|
||||
float: left;
|
||||
width: 200px!important;
|
||||
}
|
||||
.search-con{
|
||||
float: left;
|
||||
width: 800px;
|
||||
overflow: hidden;
|
||||
margin-top: -27px;
|
||||
}
|
||||
.cart-icon {
|
||||
width: 30px;
|
||||
float: left;
|
||||
font-size: 25px;
|
||||
margin-top: 8px;
|
||||
color: $theme_color;
|
||||
z-index: 1;
|
||||
position: relative;
|
||||
&:hover{
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
.cart-badge {
|
||||
position: absolute;
|
||||
font-style: normal;
|
||||
right: 165px;
|
||||
display: block;
|
||||
background-color: $theme_color;
|
||||
color: #fff;
|
||||
font-size: 12px;
|
||||
width: 17px;
|
||||
height: 17px;
|
||||
border-radius: 10px;
|
||||
line-height: 17px;
|
||||
text-align: center;
|
||||
z-index: 5;
|
||||
top: 3px;
|
||||
}
|
||||
</style>
|
||||
33
buyer/src/components/indexDecorate/modelForm.vue
Normal file
33
buyer/src/components/indexDecorate/modelForm.vue
Normal file
@@ -0,0 +1,33 @@
|
||||
<template>
|
||||
<div class="model-form">
|
||||
<div class="model-content">
|
||||
<template v-for="(element, index) in data.list">
|
||||
<model-form-item
|
||||
v-if="element && element.key"
|
||||
:key="element.key"
|
||||
:element="element"
|
||||
:index="index"
|
||||
:data="data"
|
||||
></model-form-item>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import ModelFormItem from './modelFormItem.vue';
|
||||
export default {
|
||||
name: 'modelForm',
|
||||
components: {
|
||||
ModelFormItem
|
||||
},
|
||||
props: ['data']
|
||||
};
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.model-content {
|
||||
width: 1200px;
|
||||
margin: 0 auto;
|
||||
background: #fff;
|
||||
min-height: 1200px;
|
||||
}
|
||||
</style>
|
||||
302
buyer/src/components/indexDecorate/modelFormItem.vue
Normal file
302
buyer/src/components/indexDecorate/modelFormItem.vue
Normal file
@@ -0,0 +1,302 @@
|
||||
<template>
|
||||
<div class="model-item" v-if="element && element.key">
|
||||
<!-- 轮播图模块,包括个人信息,快捷导航模块 -->
|
||||
<template v-if="element.type == 'carousel'">
|
||||
<model-carousel :data="element"></model-carousel>
|
||||
</template>
|
||||
<!-- 热门广告 -->
|
||||
<template v-if="element.type == 'hotAdvert'">
|
||||
<div>
|
||||
<img
|
||||
style="display: block"
|
||||
class="hover-pointer"
|
||||
:src="element.options.list[0].img"
|
||||
@click="linkTo(element.options.list[0].url)"
|
||||
width="1200"
|
||||
alt=""
|
||||
/>
|
||||
</div>
|
||||
<ul class="advert-list">
|
||||
<template v-for="(item, index) in element.options.list">
|
||||
<li
|
||||
v-if="index !== 0"
|
||||
@click="linkTo(item.url)"
|
||||
class="hover-pointer"
|
||||
:key="index"
|
||||
>
|
||||
<img :src="item.img" width="230" height="190" alt="" />
|
||||
</li>
|
||||
</template>
|
||||
</ul>
|
||||
</template>
|
||||
<!-- 限时秒杀 待完善 -->
|
||||
<!-- <template v-if="element.type == 'seckill'">
|
||||
<seckill :data="element"></seckill>
|
||||
</template> -->
|
||||
<!-- 折扣广告 -->
|
||||
<template v-if="element.type == 'discountAdvert'">
|
||||
<div
|
||||
class="discountAdvert"
|
||||
:style="{
|
||||
'background-image': 'url(' + element.options.bgImg.img + ')',
|
||||
}"
|
||||
>
|
||||
<img
|
||||
@click="linkTo(item.url)"
|
||||
class="hover-pointer"
|
||||
v-for="(item, index) in element.options.classification"
|
||||
:key="index"
|
||||
:src="item.img"
|
||||
width="190"
|
||||
height="210"
|
||||
alt=""
|
||||
/>
|
||||
<img
|
||||
@click="linkTo(item.url)"
|
||||
class="hover-pointer"
|
||||
v-for="(item, index) in element.options.brandList"
|
||||
:key="'discount' + index"
|
||||
:src="item.img"
|
||||
width="240"
|
||||
height="105"
|
||||
alt=""
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<!-- 好货推荐 -->
|
||||
<template v-if="element.type == 'recommend'">
|
||||
<recommend :data="element"></recommend>
|
||||
</template>
|
||||
<!-- 新品排行 -->
|
||||
<template v-if="element.type == 'newGoodsSort'">
|
||||
<new-goods-sort :data="element"></new-goods-sort>
|
||||
</template>
|
||||
<!-- 首页广告 -->
|
||||
<template v-if="element.type == 'firstAdvert'">
|
||||
<first-page-advert :data="element"></first-page-advert>
|
||||
</template>
|
||||
<!-- 横幅广告 -->
|
||||
<template v-if="element.type == 'bannerAdvert'">
|
||||
<img
|
||||
width="1200"
|
||||
class="hover-pointer"
|
||||
@click="linkTo(element.options.url)"
|
||||
:src="element.options.img"
|
||||
alt=""
|
||||
/>
|
||||
</template>
|
||||
<template v-if="element.type == 'notEnough'">
|
||||
<not-enough :data="element"></not-enough>
|
||||
</template>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import ModelCarousel from './modelList/carousel.vue';
|
||||
import FirstPageAdvert from './modelList/firstPageAdvert.vue';
|
||||
import NewGoodsSort from './modelList/newGoodsSort.vue';
|
||||
import Recommend from './modelList/recommend.vue';
|
||||
import NotEnough from './modelList/notEnough.vue';
|
||||
import Seckill from './modelList/seckill.vue';
|
||||
|
||||
export default {
|
||||
name: 'modelFormItem',
|
||||
props: ['element', 'select', 'index', 'data'],
|
||||
components: {
|
||||
ModelCarousel,
|
||||
Recommend,
|
||||
NewGoodsSort,
|
||||
FirstPageAdvert,
|
||||
NotEnough,
|
||||
Seckill
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
showModal: false, // 控制模态框显隐
|
||||
selected: {} // 已选数据
|
||||
};
|
||||
}
|
||||
};
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.model-item {
|
||||
position: relative;
|
||||
margin-bottom: 20px;
|
||||
&:hover {
|
||||
.del-btn {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
}
|
||||
.del-btn {
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
display: none;
|
||||
position: absolute;
|
||||
right: -100px;
|
||||
top: 0;
|
||||
&:hover {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
|
||||
/** 热门广告 */
|
||||
.advert-list {
|
||||
background: $theme_color;
|
||||
height: 200px;
|
||||
display: flex;
|
||||
justify-content: space-around;
|
||||
padding: 3px 10px;
|
||||
> li {
|
||||
img {
|
||||
cursor: pointer;
|
||||
border-radius: 10px;
|
||||
transition: all 150ms ease-in-out;
|
||||
&:hover {
|
||||
transform: translateY(-3px);
|
||||
box-shadow: rgba(0, 0, 0, 0.4) 0px 5px 20px 0px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/** 限时秒杀 */
|
||||
.limit-img {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
img {
|
||||
width: 300px;
|
||||
height: 100px;
|
||||
}
|
||||
}
|
||||
/** 折扣广告 */
|
||||
.discountAdvert {
|
||||
height: 566px;
|
||||
background-repeat: no-repeat;
|
||||
margin-left: -97px;
|
||||
position: relative;
|
||||
padding-left: 295px;
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
align-items: start;
|
||||
img {
|
||||
margin-top: 10px;
|
||||
margin-right: 10px;
|
||||
transition: all 150ms ease-in-out;
|
||||
&:hover {
|
||||
box-shadow: 0 5px 12px 0 rgba(0, 0, 0, 0.4);
|
||||
transform: translateY(-2px);
|
||||
}
|
||||
}
|
||||
}
|
||||
/** 首页品牌 */
|
||||
.brand {
|
||||
.brand-view {
|
||||
display: flex;
|
||||
margin-top: 10px;
|
||||
.brand-view-content {
|
||||
width: 470px;
|
||||
margin-left: 10px;
|
||||
img {
|
||||
width: 100%;
|
||||
height: 316px;
|
||||
}
|
||||
.brand-view-title {
|
||||
height: 50px;
|
||||
padding: 0 5px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
}
|
||||
}
|
||||
.brand-view-content:first-child {
|
||||
width: 240px;
|
||||
margin-left: 0;
|
||||
}
|
||||
}
|
||||
.brand-list {
|
||||
margin-top: 10px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
flex-wrap: wrap;
|
||||
li {
|
||||
width: 121px;
|
||||
height: 112px;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
border: 1px solid #f5f5f5;
|
||||
margin: -1px -1px 0 0;
|
||||
&:hover {
|
||||
.brand-mash {
|
||||
display: flex;
|
||||
}
|
||||
}
|
||||
.brand-img {
|
||||
text-align: center;
|
||||
margin-top: 30px;
|
||||
img {
|
||||
width: 100px;
|
||||
height: auto;
|
||||
}
|
||||
}
|
||||
.brand-mash {
|
||||
display: none;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
background: rgba(0, 0, 0, 0.5);
|
||||
width: inherit;
|
||||
height: inherit;
|
||||
font-size: 12px;
|
||||
font-weight: bold;
|
||||
.ivu-icon {
|
||||
position: absolute;
|
||||
right: 10px;
|
||||
top: 10px;
|
||||
font-size: 15px;
|
||||
}
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
flex-direction: column;
|
||||
color: #fff;
|
||||
cursor: pointer;
|
||||
div:last-child {
|
||||
background-color: $theme_color;
|
||||
border-radius: 9px;
|
||||
padding: 0 10px;
|
||||
margin-top: 5px;
|
||||
}
|
||||
}
|
||||
}
|
||||
.refresh {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
.ivu-icon {
|
||||
font-size: 18px;
|
||||
transition: all 0.3s ease-out;
|
||||
}
|
||||
&:hover {
|
||||
background-color: $theme_color;
|
||||
color: #fff;
|
||||
.ivu-icon {
|
||||
transform: rotateZ(360deg);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** 装修模态框 内部样式start */
|
||||
.modal-top-advert {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
flex-direction: column;
|
||||
> * {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
180
buyer/src/components/indexDecorate/modelList/carousel.vue
Normal file
180
buyer/src/components/indexDecorate/modelList/carousel.vue
Normal file
@@ -0,0 +1,180 @@
|
||||
<template>
|
||||
<div class="model-carousel">
|
||||
<div class="nav-body clearfix">
|
||||
<!-- 侧边导航占位 -->
|
||||
<div class="nav-side"></div>
|
||||
<div class="nav-content">
|
||||
<!-- 轮播图 -->
|
||||
<Carousel autoplay>
|
||||
<CarouselItem v-for="(item, index) in data.options.list" :key="index">
|
||||
<div style="overflow: hidden">
|
||||
<img
|
||||
:src="item.img"
|
||||
width="790"
|
||||
@click="linkTo(item.url)"
|
||||
height="340"
|
||||
class="hover-pointer"
|
||||
/>
|
||||
</div>
|
||||
</CarouselItem>
|
||||
</Carousel>
|
||||
</div>
|
||||
<div class="nav-right">
|
||||
<div class="person-msg">
|
||||
<img :src="userInfo.face" v-if="userInfo.face" alt />
|
||||
<Avatar icon="ios-person" class="mb_10" v-else size="80" />
|
||||
<div>Hi,{{ userInfo.nickName || "欢迎来到LiLi Shop" | secrecyMobile }}</div>
|
||||
<div v-if="userInfo.id">
|
||||
<Button type="error" shape="circle" @click="$router.push('home')">会员中心</Button>
|
||||
</div>
|
||||
<div v-else>
|
||||
<Button type="error" @click="$router.push('login')" shape="circle"
|
||||
>请登录</Button
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
<div class="shop-msg">
|
||||
<div>
|
||||
<span>常见问题</span>
|
||||
<ul class="article-list">
|
||||
<li class="ellipsis" :alt="article.title" v-for="(article, index) in articleList" :key="index" @click="goArticle(article.id)">
|
||||
{{article.title}}
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {articleList} from '@/api/common.js'
|
||||
import storage from '@/plugins/storage';
|
||||
export default {
|
||||
name: 'modelCarousel',
|
||||
props: ['data'],
|
||||
data () {
|
||||
return {
|
||||
userInfo: {}, // 用户信息
|
||||
articleList: [], // 常见问题
|
||||
params: { // 请求常见问题参数
|
||||
pageNumber: 1,
|
||||
pageSize: 5,
|
||||
type: 'ANNOUNCEMENT',
|
||||
sort: 'sort'
|
||||
}
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
getArticleList () {
|
||||
articleList(this.params).then(res => {
|
||||
if (res.success) {
|
||||
this.articleList = res.result.records
|
||||
}
|
||||
})
|
||||
},
|
||||
goArticle (id) {
|
||||
let routeUrl = this.$router.resolve({
|
||||
path: '/article',
|
||||
query: {id}
|
||||
});
|
||||
window.open(routeUrl.href, '_blank');
|
||||
}
|
||||
},
|
||||
mounted () {
|
||||
if (storage.getItem('userInfo')) this.userInfo = JSON.parse(storage.getItem('userInfo'));
|
||||
this.getArticleList()
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.model-carousel {
|
||||
width: 1200px;
|
||||
height: 340px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
/* 导航主体 */
|
||||
.nav-body {
|
||||
width: 1200px;
|
||||
height: 340px;
|
||||
margin: 0px auto;
|
||||
}
|
||||
|
||||
.nav-side {
|
||||
height: 100%;
|
||||
width: 200px;
|
||||
float: left;
|
||||
padding: 0px;
|
||||
color: #fff;
|
||||
background-color: #6e6568;
|
||||
}
|
||||
|
||||
/*导航内容*/
|
||||
.nav-content {
|
||||
width: 790px;
|
||||
overflow: hidden;
|
||||
float: left;
|
||||
position: relative;
|
||||
}
|
||||
.nav-right {
|
||||
float: left;
|
||||
width: 210px;
|
||||
.person-msg {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
flex-direction: column;
|
||||
margin: 20px auto;
|
||||
button {
|
||||
height: 25px !important;
|
||||
margin-top: 10px;
|
||||
}
|
||||
.ivu-btn-default {
|
||||
color: $theme_color;
|
||||
border-color: $theme_color;
|
||||
}
|
||||
img {
|
||||
margin-bottom: 10px;
|
||||
width: 80px;
|
||||
height: 80px;
|
||||
border-radius: 50%;
|
||||
}
|
||||
}
|
||||
.shop-msg {
|
||||
div {
|
||||
width: 100%;
|
||||
margin: 10px 27px;
|
||||
span {
|
||||
cursor: pointer;
|
||||
text-align: center;
|
||||
font-weight: bold;
|
||||
margin-left: 5px;
|
||||
}
|
||||
span:nth-child(1) {
|
||||
@include content_color($theme_color);
|
||||
margin-left: 0;
|
||||
}
|
||||
span:nth-child(2) {
|
||||
font-weight: normal;
|
||||
}
|
||||
span:nth-child(3):hover {
|
||||
color: $theme_color;
|
||||
}
|
||||
}
|
||||
ul {
|
||||
li {
|
||||
cursor: pointer;
|
||||
margin: 5px 0;
|
||||
color: #999395;
|
||||
width: 150px;
|
||||
font-size: 12px;
|
||||
&:hover {
|
||||
color: $theme_color;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,99 @@
|
||||
<template>
|
||||
<div class="first-page-advert">
|
||||
<div
|
||||
class="item hover-pointer"
|
||||
@click="linkTo(item.url)"
|
||||
:style="{
|
||||
backgroundImage: `linear-gradient(to right, ${item.fromColor}, ${item.toColor})`,
|
||||
}"
|
||||
v-for="(item, index) in options.list"
|
||||
:key="index"
|
||||
>
|
||||
<div>
|
||||
<span class="line top-line"></span>
|
||||
<p>{{ item.name }}</p>
|
||||
<span class="line btm-line"></span>
|
||||
<p>{{ item.describe }}</p>
|
||||
</div>
|
||||
<img :src="item.img" width="170" height="170" alt="" />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
export default {
|
||||
props: {
|
||||
data: {
|
||||
type: Object,
|
||||
default: null
|
||||
}
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
options: this.data.options // 装修数据
|
||||
};
|
||||
},
|
||||
methods: {}
|
||||
};
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.first-page-advert {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
justify-content: space-between;
|
||||
// margin-top: -10px;
|
||||
.item {
|
||||
width: 393px;
|
||||
height: 170px;
|
||||
margin-top: 10px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
img {
|
||||
margin-left: 20px;
|
||||
transition: transform 0.5s, -webkit-transform 0.5s, -moz-transform 0.5s;
|
||||
&:hover {
|
||||
transform: translateX(-5px);
|
||||
}
|
||||
}
|
||||
|
||||
&:nth-of-type(1),
|
||||
&:nth-of-type(2),
|
||||
&:nth-of-type(3) {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
p:nth-of-type(1) {
|
||||
margin: 3px 0;
|
||||
font-size: 18px;
|
||||
color: #fff;
|
||||
}
|
||||
p:nth-of-type(2) {
|
||||
margin-top: 3px;
|
||||
color: #fff;
|
||||
}
|
||||
}
|
||||
.line {
|
||||
position: relative;
|
||||
display: block;
|
||||
height: 2px;
|
||||
background: url(../../../assets/images/festival_icon.png);
|
||||
z-index: 1;
|
||||
}
|
||||
.top-line {
|
||||
width: 78px;
|
||||
background-position: -1px -3px;
|
||||
}
|
||||
.btm-line {
|
||||
background-position: 0 -11px;
|
||||
width: 154px;
|
||||
}
|
||||
}
|
||||
.modal-top-advert {
|
||||
align-items: start;
|
||||
padding: 0 30px;
|
||||
.exhibition {
|
||||
width: 300px;
|
||||
height: 50px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
234
buyer/src/components/indexDecorate/modelList/newGoodsSort.vue
Normal file
234
buyer/src/components/indexDecorate/modelList/newGoodsSort.vue
Normal file
@@ -0,0 +1,234 @@
|
||||
<template>
|
||||
<div class="new-goods">
|
||||
<div class="left">
|
||||
<div class="top-header" :style="{ background: options.left.bgColor }">
|
||||
<span>{{ options.left.title }}</span>
|
||||
<span @click="linkTo(options.left.url)" class="hover-pointer"
|
||||
>{{ options.left.secondTitle }} ></span
|
||||
>
|
||||
</div>
|
||||
<div class="content">
|
||||
<div
|
||||
class="con-item hover-pointer"
|
||||
v-for="(item, index) in options.left.list"
|
||||
:key="index"
|
||||
@click="linkTo(item.url)"
|
||||
>
|
||||
<div>
|
||||
<p>{{ item.name }}</p>
|
||||
<p class="describe">{{ item.describe }}</p>
|
||||
</div>
|
||||
<img :src="item.img" alt="" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="middle">
|
||||
<div class="top-header" :style="{ background: options.middle.bgColor }">
|
||||
<span>{{ options.middle.title }}</span>
|
||||
<span class="hover-pointer" @click="linkTo(options.middle.url)"
|
||||
>{{ options.middle.secondTitle }} ></span
|
||||
>
|
||||
</div>
|
||||
<div class="content">
|
||||
<div
|
||||
class="con-item hover-pointer"
|
||||
v-for="(item, index) in options.middle.list"
|
||||
:key="index"
|
||||
@click="linkTo(item.url)"
|
||||
>
|
||||
<div>
|
||||
<p>{{ item.name }}</p>
|
||||
<p class="describe">{{ item.describe }}</p>
|
||||
</div>
|
||||
<img :src="item.img" alt="" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="right">
|
||||
<div class="top-header" :style="{ background: options.right.bgColor }">
|
||||
<span>{{ options.right.title }}</span>
|
||||
<span @click="linkTo(options.right.url)" class="hover-pointer"
|
||||
>{{ options.right.secondTitle }} ></span
|
||||
>
|
||||
</div>
|
||||
<div class="content">
|
||||
<div
|
||||
v-for="(item, index) in options.right.list"
|
||||
:key="index"
|
||||
class="hover-pointer"
|
||||
@click="linkTo(item.url)"
|
||||
>
|
||||
<img :src="item.img" alt="" />
|
||||
<p>{{ item.name }}</p>
|
||||
<p>{{ item.price | unitPrice("¥") }}</p>
|
||||
<div class="jiaobiao" :class="'jiaobiao' + (index + 1)">
|
||||
{{ index + 1 }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
export default {
|
||||
props: {
|
||||
data: {
|
||||
type: Object,
|
||||
default: null
|
||||
}
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
options: this.data.options // 装修数据
|
||||
};
|
||||
},
|
||||
methods: {}
|
||||
};
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.new-goods {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
> div {
|
||||
width: 393px;
|
||||
height: 440px;
|
||||
}
|
||||
|
||||
.left > .content {
|
||||
> div:nth-child(1) {
|
||||
height: 240px;
|
||||
flex-direction: column;
|
||||
border: 1px solid #eee;
|
||||
border-top: none;
|
||||
border-left: none;
|
||||
justify-content: space-between;
|
||||
img {
|
||||
width: 160px;
|
||||
height: 160px;
|
||||
}
|
||||
.describe {
|
||||
margin-top: 10px;
|
||||
}
|
||||
}
|
||||
> div:nth-child(2) {
|
||||
border-right: 1px solid #eee;
|
||||
}
|
||||
> div:nth-child(3),
|
||||
> div:nth-child(4) {
|
||||
border-bottom: 1px solid #eee;
|
||||
}
|
||||
}
|
||||
|
||||
.middle > .content {
|
||||
> div {
|
||||
border-style: solid;
|
||||
border-color: #eee;
|
||||
border-width: 0;
|
||||
border-bottom-width: 1px;
|
||||
}
|
||||
> div:nth-child(1),
|
||||
> div:nth-child(2),
|
||||
> div:nth-child(3) {
|
||||
border-right-width: 1px;
|
||||
}
|
||||
> div:nth-child(6),
|
||||
> div:nth-child(3) {
|
||||
border-bottom-width: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.right > .content {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
flex-direction: row;
|
||||
font-size: 12px;
|
||||
> div {
|
||||
position: relative;
|
||||
width: 120px;
|
||||
padding: 5px 10px 0 10px;
|
||||
img {
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
}
|
||||
border-bottom: 1px solid #eee;
|
||||
:nth-child(2) {
|
||||
height: 38px;
|
||||
overflow: hidden;
|
||||
}
|
||||
:nth-child(3) {
|
||||
color: $theme_color;
|
||||
margin-top: 5px;
|
||||
}
|
||||
.jiaobiao {
|
||||
position: absolute;
|
||||
width: 23px;
|
||||
height: 23px;
|
||||
top: 10px;
|
||||
right: 16px;
|
||||
background: url(../../../assets/images/festival_icon.png);
|
||||
color: #fff;
|
||||
text-align: center;
|
||||
}
|
||||
.jiaobiao1,
|
||||
.jiaobiao4 {
|
||||
background-position: -2px -30px;
|
||||
}
|
||||
.jiaobiao2,
|
||||
.jiaobiao5 {
|
||||
background-position: -31px -30px;
|
||||
}
|
||||
.jiaobiao3,
|
||||
.jiaobiao6 {
|
||||
background-position: -60px -30px;
|
||||
}
|
||||
}
|
||||
> div:nth-child(4),
|
||||
> div:nth-child(5),
|
||||
> div:nth-child(6) {
|
||||
border: none;
|
||||
}
|
||||
}
|
||||
|
||||
.top-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
height: 50px;
|
||||
padding: 0 10px;
|
||||
background: #c43d7e;
|
||||
color: #fff;
|
||||
span:nth-child(1) {
|
||||
font-size: 20px;
|
||||
}
|
||||
span:nth-child(2) {
|
||||
font-size: 12px;
|
||||
}
|
||||
}
|
||||
.content {
|
||||
padding: 10px 12px 0;
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
flex-direction: column;
|
||||
height: 370px;
|
||||
}
|
||||
.con-item {
|
||||
width: 185px;
|
||||
height: 120px;
|
||||
display: flex;
|
||||
padding-left: 10px;
|
||||
padding-top: 10px;
|
||||
img {
|
||||
width: 90px;
|
||||
height: 90px;
|
||||
margin-top: 10px;
|
||||
}
|
||||
}
|
||||
.describe {
|
||||
color: #999;
|
||||
font-size: 12px;
|
||||
margin-top: 15px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
145
buyer/src/components/indexDecorate/modelList/notEnough.vue
Normal file
145
buyer/src/components/indexDecorate/modelList/notEnough.vue
Normal file
@@ -0,0 +1,145 @@
|
||||
<template>
|
||||
<div class="not-enough">
|
||||
<ul class="nav-bar">
|
||||
<li
|
||||
v-for="(item, index) in conData.options.navList"
|
||||
:class="currentIndex === index ? 'curr' : ''"
|
||||
@click="changeCurr(index)"
|
||||
:key="index"
|
||||
>
|
||||
<p>{{ item.title }}</p>
|
||||
<p>{{ item.desc }}</p>
|
||||
</li>
|
||||
</ul>
|
||||
<div class="content" v-if="showContent">
|
||||
<div
|
||||
v-for="(item, index) in conData.options.list[currentIndex]"
|
||||
:key="index"
|
||||
class="hover-pointer"
|
||||
@click="linkTo(item.url)"
|
||||
>
|
||||
<img :src="item.img" width="210" height="210" :alt="item.name" />
|
||||
<p>{{ item.name }}</p>
|
||||
<p>
|
||||
<span>{{ Number(item.price) | unitPrice("¥") }}</span>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
export default {
|
||||
props: {
|
||||
data: {
|
||||
type: Object,
|
||||
default: null
|
||||
}
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
currentIndex: 0, // 当前分类下标
|
||||
conData: this.data, // 装修数据
|
||||
showContent: true // 是否展示内容
|
||||
};
|
||||
},
|
||||
watch: {
|
||||
data: function (val) {
|
||||
this.conData = val;
|
||||
},
|
||||
conData: function (val) {
|
||||
this.$emit('content', val);
|
||||
}
|
||||
},
|
||||
mounted () {},
|
||||
methods: {
|
||||
changeCurr (index) {
|
||||
this.currentIndex = index;
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.nav-bar {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
width: 100%;
|
||||
margin-bottom: 10px;
|
||||
background-color: rgb(218, 217, 217);
|
||||
height: 60px;
|
||||
align-items: center;
|
||||
position: relative;
|
||||
li {
|
||||
padding: 0 30px;
|
||||
text-align: center;
|
||||
p:nth-child(1) {
|
||||
font-size: 16px;
|
||||
border-radius: 50px;
|
||||
padding: 0 7px;
|
||||
}
|
||||
|
||||
p:nth-child(2) {
|
||||
font-size: 14px;
|
||||
color: #999;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
p {
|
||||
color: $theme_color;
|
||||
}
|
||||
cursor: pointer;
|
||||
}
|
||||
border-right: 1px solid #eee;
|
||||
}
|
||||
li:last-of-type {
|
||||
border: none;
|
||||
}
|
||||
|
||||
.curr {
|
||||
p:nth-child(1) {
|
||||
background-color: $theme_color;
|
||||
|
||||
color: #fff;
|
||||
}
|
||||
p:nth-child(2) {
|
||||
color: $theme_color;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.content {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
justify-content: space-between;
|
||||
> div {
|
||||
padding: 10px;
|
||||
box-sizing: border-box;
|
||||
border: 1px solid #eee;
|
||||
margin-bottom: 10px;
|
||||
|
||||
&:hover {
|
||||
border-color: $theme_color;
|
||||
color: $theme_color;
|
||||
}
|
||||
|
||||
p:nth-of-type(1) {
|
||||
overflow: hidden;
|
||||
width: 210px;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
margin: 10px 0 5px 0;
|
||||
}
|
||||
p:nth-of-type(2) {
|
||||
color: $theme_color;
|
||||
font-size: 16px;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
span:nth-child(2) {
|
||||
text-decoration: line-through;
|
||||
font-size: 12px;
|
||||
color: #999;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
217
buyer/src/components/indexDecorate/modelList/recommend.vue
Normal file
217
buyer/src/components/indexDecorate/modelList/recommend.vue
Normal file
@@ -0,0 +1,217 @@
|
||||
<template>
|
||||
<div class="recommend">
|
||||
<div class="recommend-left">
|
||||
<div class="head-recommend" :style="{ background: msgLeft.bgColor }">
|
||||
<span>{{ msgLeft.title }}</span>
|
||||
<span class="hover-pointer" @click="linkTo(msgLeft.url)">{{ msgLeft.secondTitle }}></span>
|
||||
</div>
|
||||
<div class="content-left">
|
||||
<div>
|
||||
<img class="hover-pointer" @click="linkTo(msgLeft.list[0].url)" :src="msgLeft.list[0].img" width="160" height="160" alt="" />
|
||||
<div class="margin-left">{{ msgLeft.list[0].name }}</div>
|
||||
<div class="margin-left">{{ msgLeft.list[0].describe }}</div>
|
||||
<Button
|
||||
size="small"
|
||||
:style="{ background: msgLeft.bgColor }"
|
||||
@click="linkTo(msgLeft.list[0].url)"
|
||||
class="fz_12 view-btn"
|
||||
>点击查看</Button
|
||||
>
|
||||
</div>
|
||||
<div>
|
||||
<template v-for="(item, index) in msgLeft.list">
|
||||
<div v-if="index != 0" :key="index" @click="linkTo(item.url)" class="hover-pointer">
|
||||
<img :src="item.img" width="80" height="80" alt="" />
|
||||
<div>
|
||||
<div>{{ item.name }}</div>
|
||||
<div>{{ item.describe }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="recommend-right">
|
||||
<div class="head-recommend" :style="{ background: msgRight.bgColor }">
|
||||
<span>{{ msgRight.title }}</span>
|
||||
<span @click="linkTo(msgRight.url)" class="hover-pointer"
|
||||
>{{ msgRight.secondTitle }}></span
|
||||
>
|
||||
</div>
|
||||
<div class="content-right">
|
||||
<div
|
||||
v-for="(item, index) in msgRight.list"
|
||||
:key="index"
|
||||
@click="linkTo(item.url)" class="hover-pointer"
|
||||
>
|
||||
<div class="right-item" :style="{'border': index===2 || index===3 ?'none': ''}">
|
||||
<div>
|
||||
<span :style="{ background: msgRight.bgColor }">{{item.name}}</span>
|
||||
<span>{{ item.describe }}</span>
|
||||
</div>
|
||||
<div class="right-img">
|
||||
<img :src="item.img" alt="" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
export default {
|
||||
props: {
|
||||
data: {
|
||||
type: Object,
|
||||
default: {}
|
||||
}
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
msgLeft: this.data.options.contentLeft, // 左侧数据
|
||||
msgRight: this.data.options.contentRight // 右侧数据
|
||||
};
|
||||
},
|
||||
methods: {}
|
||||
};
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.recommend {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
.recommend-left {
|
||||
width: 595px;
|
||||
.content-left {
|
||||
display: flex;
|
||||
padding-top: 10px;
|
||||
font-size: 12px;
|
||||
> div:nth-child(1) {
|
||||
width: 189px;
|
||||
border-right: 1px solid #eee;
|
||||
height: 360px;
|
||||
img {
|
||||
margin: 40px 0 0 15px;
|
||||
}
|
||||
.margin-left {
|
||||
margin-left: 15px;
|
||||
width: 145px;
|
||||
}
|
||||
div:nth-of-type(1) {
|
||||
font-weight: bold;
|
||||
border-top: 1px solid #eee;
|
||||
padding-top: 10px;
|
||||
padding-bottom: 10px;
|
||||
}
|
||||
div:nth-of-type(2) {
|
||||
color: #999;
|
||||
}
|
||||
.view-btn {
|
||||
margin-left: 15px;
|
||||
margin-top: 10px;
|
||||
color: #fff;
|
||||
}
|
||||
}
|
||||
> div:nth-child(2) {
|
||||
width: 405px;
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
> div {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
width: 200px;
|
||||
height: 120px;
|
||||
img {
|
||||
margin: 0 10px;
|
||||
}
|
||||
> div:nth-child(2) {
|
||||
:nth-child(2) {
|
||||
color: #449dae;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.recommend-right {
|
||||
width: 595px;
|
||||
height: 360px;
|
||||
.head-recommend {
|
||||
background: #a25684;
|
||||
}
|
||||
.content-right {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding-top: 10px;
|
||||
> div {
|
||||
width: 50%;
|
||||
text-align: center;
|
||||
height: 180px;
|
||||
padding-top: 10px;
|
||||
.right-item {
|
||||
border-bottom: 1px solid #eee;
|
||||
display: flex;
|
||||
margin-top: 30px;
|
||||
margin-left: 5px;
|
||||
margin-right: 5px;
|
||||
height: 150px;
|
||||
padding: 0 10px;
|
||||
font-size: 12px;
|
||||
>div:nth-child(1) {
|
||||
width: 130px;
|
||||
margin-top: 30px;
|
||||
span:nth-child(1){
|
||||
color: #fff;
|
||||
border-radius: 10px;
|
||||
padding: 0 5px;
|
||||
background-color: #a25684;
|
||||
display: block;
|
||||
width: 120px;
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
margin: 0 10px 10px 0;
|
||||
}
|
||||
span:nth-child(2) {
|
||||
font-size: 12px;
|
||||
color: #666;
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
.right-img {
|
||||
width: 100;
|
||||
height: 100px;
|
||||
text-align: center;
|
||||
margin: 0 auto;
|
||||
img{
|
||||
max-height: 100px;
|
||||
max-width: 100px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
> div:nth-child(n + 1) {
|
||||
border-right: 1px solid #eee;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.head-recommend {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
height: 50px;
|
||||
padding: 0 10px;
|
||||
background: #449dae;
|
||||
color: #fff;
|
||||
span:nth-child(1) {
|
||||
font-size: 20px;
|
||||
}
|
||||
span:nth-child(2) {
|
||||
font-size: 12px;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
289
buyer/src/components/indexDecorate/modelList/seckill.vue
Normal file
289
buyer/src/components/indexDecorate/modelList/seckill.vue
Normal file
@@ -0,0 +1,289 @@
|
||||
<template>
|
||||
<div class="seckill">
|
||||
<div class="aside hover-pointer" @click="goPromotion">
|
||||
<div class="title">{{ actName }}</div>
|
||||
<div class="hour">
|
||||
<span>{{ currHour }}:00</span>点场 倒计时
|
||||
</div>
|
||||
<div class="count-down" v-if="actStatus === 1">
|
||||
<span>{{ hours }}</span
|
||||
><span>{{ minutes }}</span
|
||||
><span>{{ seconds }}</span>
|
||||
</div>
|
||||
<div class="act-status" v-else>
|
||||
{{ actStatus == 0 ? "未开始" : "已结束" }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="section">
|
||||
<swiper ref="mySwiper" :options="swiperOptions">
|
||||
<swiper-slide
|
||||
v-for="(item, index) in options.list[0].goodsList"
|
||||
:key="index"
|
||||
class="swiper-slide"
|
||||
>
|
||||
<div class="content hover-pointer" @click="goPromotion">
|
||||
<img :src="item.img" width="140" height="140" :alt="item.name" />
|
||||
<div class="ellipsis">{{ item.name }}</div>
|
||||
<div>
|
||||
<span>{{ item.price | unitPrice("¥") }}</span>
|
||||
<span>{{ item.originalPrice | unitPrice("¥") }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</swiper-slide>
|
||||
</swiper>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import { Swiper, SwiperSlide, directive } from 'vue-awesome-swiper';
|
||||
import 'swiper/swiper-bundle.css';
|
||||
export default {
|
||||
components: {
|
||||
Swiper,
|
||||
SwiperSlide
|
||||
},
|
||||
directives: {
|
||||
swiper: directive
|
||||
},
|
||||
props: {
|
||||
data: {
|
||||
type: Object,
|
||||
default: null
|
||||
}
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
options: this.data.options, // 装修数据
|
||||
actStatus: 0, // 0 未开始 1 进行中 2 已结束
|
||||
actName: '限时秒杀', // 活动名称
|
||||
currHour: '00', // 当前秒杀场
|
||||
diffSeconds: 0, // 倒计时秒数
|
||||
days: 0, // 天
|
||||
hours: 0, // 小时
|
||||
minutes: 0, // 分钟
|
||||
seconds: 0, // 秒
|
||||
interval: undefined, // 定时器
|
||||
swiperOptions: { // 轮播图参数
|
||||
slidesPerView: 5,
|
||||
autoplay: true,
|
||||
loop: true
|
||||
}
|
||||
};
|
||||
},
|
||||
watch: {
|
||||
diffSeconds (val) {
|
||||
const hours = Math.floor(val / 3600);
|
||||
// 当前秒数 / 60,向下取整
|
||||
// 获取到所有分钟数 3600 / 60 = 60分钟
|
||||
// 对60取模,超过小时数的分钟数
|
||||
const minutes = Math.floor(val / 60) % 60;
|
||||
// 当前的秒数 % 60,获取到 超过小时数、分钟数的秒数(秒数)
|
||||
const seconds = val % 60;
|
||||
this.hours = hours < 10 ? '0' + hours : hours;
|
||||
this.minutes = minutes < 10 ? '0' + minutes : minutes;
|
||||
this.seconds = seconds < 10 ? '0' + seconds : seconds;
|
||||
|
||||
if (val === 0) {
|
||||
clearInterval(this.interval);
|
||||
this.hours = 0;
|
||||
this.minutes = 0;
|
||||
this.seconds = 0;
|
||||
this.countDown(this.options.list);
|
||||
}
|
||||
}
|
||||
},
|
||||
mounted () {
|
||||
this.countDown(this.options.list);
|
||||
},
|
||||
beforeDestroy () {
|
||||
clearInterval(this.interval);
|
||||
},
|
||||
methods: {
|
||||
// 倒计时
|
||||
countDown (list) {
|
||||
/**
|
||||
* 默认倒计时两小时
|
||||
* 如果没有开始,则显示未开始
|
||||
* 进行中显示倒计时 + 时间
|
||||
* 今天的秒杀结束则显示已结束
|
||||
*/
|
||||
let nowHour = new Date().getHours();
|
||||
if (nowHour < Number(list[0].time)) {
|
||||
// 活动未开始
|
||||
this.currHour = list[0].time;
|
||||
this.actStatus = 0;
|
||||
} else if (nowHour >= Number(list[list.length - 1].time + 2)) {
|
||||
// 活动已结束
|
||||
this.actStatus = 2;
|
||||
this.currHour = list[list.length - 1].time;
|
||||
} else {
|
||||
// 活动进行中
|
||||
this.actStatus = 1;
|
||||
for (let i = 0; i < list.length; i++) {
|
||||
if (nowHour === Number(list[i].time)) {
|
||||
this.currHour = list[i].time;
|
||||
}
|
||||
if (
|
||||
nowHour > Number(list[i].time) &&
|
||||
nowHour < Number(list[i].time + 2)
|
||||
) {
|
||||
this.currHour = list[i].time;
|
||||
}
|
||||
}
|
||||
// 当前0点时间戳
|
||||
let zeroTime = new Date(new Date().toLocaleDateString()).getTime();
|
||||
// 活动倒计时
|
||||
this.diffSeconds = Math.floor((zeroTime + 3600 * 1000 * (this.currHour + 2) - new Date().getTime()) / 1000);
|
||||
this.interval = setInterval(() => {
|
||||
this.diffSeconds--;
|
||||
}, 1000);
|
||||
}
|
||||
},
|
||||
goPromotion () {
|
||||
let routeUrl = this.$router.resolve({
|
||||
path: '/seckill'
|
||||
});
|
||||
window.open(routeUrl.href, '_blank');
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.seckill {
|
||||
width: 100%;
|
||||
height: 260px;
|
||||
display: flex;
|
||||
.aside {
|
||||
overflow: hidden;
|
||||
width: 190px;
|
||||
height: 100%;
|
||||
color: #fff;
|
||||
background-image: url("../../../assets/images/seckillBg.png");
|
||||
|
||||
.title {
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
font-size: 28px;
|
||||
margin-top: 31px;
|
||||
}
|
||||
|
||||
.hour {
|
||||
margin-top: 90px;
|
||||
text-align: center;
|
||||
span {
|
||||
font-size: 18px;
|
||||
}
|
||||
}
|
||||
|
||||
.count-down {
|
||||
margin: 10px 0 0 30px;
|
||||
> span {
|
||||
position: relative;
|
||||
float: left;
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
text-align: center;
|
||||
background-color: #2f3430;
|
||||
margin-right: 20px;
|
||||
color: white;
|
||||
font-size: 20px;
|
||||
&::after {
|
||||
content: ":";
|
||||
display: block;
|
||||
position: absolute;
|
||||
right: -20px;
|
||||
font-weight: bolder;
|
||||
font-size: 18px;
|
||||
width: 20px;
|
||||
height: 100%;
|
||||
top: 0;
|
||||
}
|
||||
}
|
||||
> span:last-child::after {
|
||||
content: "";
|
||||
}
|
||||
}
|
||||
|
||||
.act-status {
|
||||
margin: 10px 0 0 65px;
|
||||
font-size: 20px;
|
||||
}
|
||||
}
|
||||
|
||||
.section {
|
||||
width: 1000px;
|
||||
// background: #efefef;
|
||||
.swiper-slide {
|
||||
height: 260px;
|
||||
.content {
|
||||
width: 200px;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
flex-direction: column;
|
||||
position: relative;
|
||||
&::after {
|
||||
content: "";
|
||||
display: block;
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
right: 0;
|
||||
width: 1px;
|
||||
height: 200px;
|
||||
transform: translateY(-50%);
|
||||
background: linear-gradient(180deg, white, #eeeeee, white);
|
||||
}
|
||||
img {
|
||||
margin-top: 30px;
|
||||
}
|
||||
> div {
|
||||
width: 160px;
|
||||
margin-top: 10px;
|
||||
font-size: 12px;
|
||||
position: relative;
|
||||
}
|
||||
> div:nth-of-type(1):hover {
|
||||
color: $theme_color;
|
||||
cursor: pointer;
|
||||
}
|
||||
> div:nth-of-type(2) {
|
||||
border: 1px solid $theme_color;
|
||||
line-height: 24px;
|
||||
display: flex;
|
||||
text-align: center;
|
||||
|
||||
span:nth-child(1) {
|
||||
color: #fff;
|
||||
font-size: 16px;
|
||||
width: 92px;
|
||||
background-color: $theme_color;
|
||||
position: relative;
|
||||
&::before {
|
||||
content: " ";
|
||||
width: 0;
|
||||
height: 0;
|
||||
border-color: transparent white transparent transparent;
|
||||
border-style: solid;
|
||||
border-width: 24px 8px 0 0;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 84px;
|
||||
}
|
||||
}
|
||||
|
||||
span:nth-child(2) {
|
||||
color: #999;
|
||||
width: 66px;
|
||||
text-decoration: line-through;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.ellipsis {
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
</style>
|
||||
3
buyer/src/components/invoiceModal/README.md
Normal file
3
buyer/src/components/invoiceModal/README.md
Normal file
@@ -0,0 +1,3 @@
|
||||
## 此组件为结算页面修改发票信息使用 后续可以复用到个人信息添加发票页面
|
||||
|
||||
### 目前没有参数,之后会设置一个参数接收历史的单位发票数据
|
||||
171
buyer/src/components/invoiceModal/index.vue
Normal file
171
buyer/src/components/invoiceModal/index.vue
Normal file
@@ -0,0 +1,171 @@
|
||||
<template>
|
||||
<div class="invoice-modal">
|
||||
<Modal v-model="invoiceAvailable" width="600" footer-hide>
|
||||
<p slot="header">
|
||||
<span>发票信息</span>
|
||||
</p>
|
||||
<!-- <div>
|
||||
<div>为响应环保,自营全面启用电子普通发票,非自营发票由第三方商家实际开具。</div>
|
||||
<div>电子普通发票是税务机关认可的有效收付款凭证,与纸质普通发票具有同等法律效力,可用于报销入账、售后维权等。</div>
|
||||
<div>如商品由第三方卖家销售,发票类型及内容将由该卖家决定。</div>
|
||||
</div> -->
|
||||
<!-- 普通发票 -->
|
||||
<div class="nav-content">
|
||||
<Form
|
||||
:model="invoiceForm"
|
||||
ref="form"
|
||||
label-position="left"
|
||||
:rules="ruleInline"
|
||||
:label-width="110"
|
||||
>
|
||||
<FormItem label="发票类型">
|
||||
<RadioGroup v-model="invoiceForm.type">
|
||||
<Radio :label="1">个人</Radio>
|
||||
<Radio :label="2">单位</Radio>
|
||||
</RadioGroup>
|
||||
</FormItem>
|
||||
<FormItem
|
||||
label="发票抬头"
|
||||
v-if="invoiceForm.type == 2"
|
||||
prop="receiptTitle"
|
||||
>
|
||||
<i-input v-model="invoiceForm.receiptTitle"></i-input>
|
||||
</FormItem>
|
||||
<FormItem
|
||||
label="纳税人识别号"
|
||||
v-if="invoiceForm.type == 2"
|
||||
prop="taxpayerId"
|
||||
>
|
||||
<i-input v-model="invoiceForm.taxpayerId"></i-input>
|
||||
</FormItem>
|
||||
<FormItem label="发票内容">
|
||||
<RadioGroup v-model="invoiceForm.receiptContent">
|
||||
<Radio label="不开发票">不开发票</Radio>
|
||||
<Radio label="商品明细">商品明细</Radio>
|
||||
</RadioGroup>
|
||||
</FormItem>
|
||||
</Form>
|
||||
<div style="text-align: center">
|
||||
<Button type="primary" :loading="loading" @click="save">保存发票信息</Button>
|
||||
<Button type="default" @click="invoiceAvailable = false">取消</Button>
|
||||
</div>
|
||||
</div>
|
||||
</Modal>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import { saveReceipt } from '@/api/member.js';
|
||||
import { TINumber } from '@/plugins/RegExp.js';
|
||||
export default {
|
||||
name: 'invoiceModal',
|
||||
data () {
|
||||
return {
|
||||
invoiceAvailable: false, // 模态框显隐
|
||||
loading: false, // 提交状态
|
||||
invoiceForm: { // 发票表单
|
||||
// 普票表单
|
||||
receiptTitle: '', // 发票抬头
|
||||
taxpayerId: '', // 纳税人识别号
|
||||
receiptContent: '不开发票', // 发票内容
|
||||
type: 1 // 1 个人 2 单位
|
||||
},
|
||||
ruleInline: {
|
||||
receiptTitle: [{ required: true, message: '请填写公司名称' }],
|
||||
taxpayerId: [
|
||||
{ required: true, message: '请填写纳税人识别号' },
|
||||
{ pattern: TINumber, message: '请填写正确的纳税人识别号' }
|
||||
]
|
||||
}
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
save () {
|
||||
if (this.invoiceForm.type === 1) {
|
||||
// 个人
|
||||
let flag = true;
|
||||
this.receiptItems.forEach((e) => {
|
||||
if (
|
||||
e.receiptTitle === '个人' &&
|
||||
e.receiptContent === this.invoiceForm.receiptContent
|
||||
) {
|
||||
this.$emit('change', e);
|
||||
flag = false;
|
||||
this.invoiceAvailable = false;
|
||||
}
|
||||
});
|
||||
|
||||
if (flag) {
|
||||
let params = {
|
||||
receiptTitle: '个人',
|
||||
receiptContent: this.invoiceForm.receiptContent
|
||||
};
|
||||
this.loading = true;
|
||||
saveReceipt(params)
|
||||
.then((res) => {
|
||||
this.loading = false;
|
||||
if (res.success) {
|
||||
this.$emit('change', res.result);
|
||||
this.invoiceAvailable = false;
|
||||
}
|
||||
})
|
||||
.catch(() => {
|
||||
this.loading = false;
|
||||
});
|
||||
}
|
||||
} else {
|
||||
// 单位
|
||||
this.$refs.form.validate((valid) => {
|
||||
if (valid) {
|
||||
this.loading = true;
|
||||
let params = {
|
||||
receiptTitle: this.invoiceForm.receiptTitle,
|
||||
taxpayerId: this.invoiceForm.taxpayerId,
|
||||
receiptContent: this.invoiceForm.receiptContent
|
||||
};
|
||||
let flag = true;
|
||||
this.receiptItems.forEach((e) => {
|
||||
if (e.taxpayerId === params.taxpayerId) {
|
||||
flag = false;
|
||||
}
|
||||
});
|
||||
if (!flag) {
|
||||
this.$Message.error('已有当前税号的发票信息,请直接选择已有发票');
|
||||
} else {
|
||||
saveReceipt(params)
|
||||
.then((res) => {
|
||||
this.loading = false;
|
||||
if (res.success) {
|
||||
this.$emit('change', res.result);
|
||||
this.invoiceAvailable = false;
|
||||
}
|
||||
})
|
||||
.catch(() => {
|
||||
this.loading = false;
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
/** 普票 */
|
||||
.inv-type {
|
||||
text-align: center;
|
||||
}
|
||||
.add-inv {
|
||||
font-size: 12px;
|
||||
color: #438cde;
|
||||
cursor: pointer;
|
||||
&:hover {
|
||||
color: $theme_color;
|
||||
}
|
||||
}
|
||||
|
||||
.nav-content {
|
||||
width: 500px;
|
||||
margin: 10px auto;
|
||||
}
|
||||
</style>
|
||||
65
buyer/src/components/like/index.vue
Normal file
65
buyer/src/components/like/index.vue
Normal file
@@ -0,0 +1,65 @@
|
||||
<template>
|
||||
<div class="wrapper">
|
||||
<card _Title="猜你喜欢" :_Size="16"> </card>
|
||||
|
||||
<Row :gutter="12" class="likeList">
|
||||
<Col
|
||||
:span="4"
|
||||
class="likeItem"
|
||||
v-for="(item, index) in goodsData"
|
||||
:key="index"
|
||||
>
|
||||
<img :src="item.img" alt="" />
|
||||
<div class="likeTitle">{{ item.title }}</div>
|
||||
<div class="likePrice">{{ item.price }}</div>
|
||||
</Col>
|
||||
</Row>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'like',
|
||||
data () {
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.wrapper {
|
||||
@include white_background_color();
|
||||
}
|
||||
.likeList {
|
||||
padding: 0 12px;
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
|
||||
> .likeItem {
|
||||
/*width: 210px;*/
|
||||
/*margin: 10px 5px;*/
|
||||
|
||||
> img {
|
||||
display: block;
|
||||
width: 100%;
|
||||
height: auto;
|
||||
}
|
||||
|
||||
> .likeTitle,
|
||||
.likePrice {
|
||||
margin: 6px 0;
|
||||
text-align: center;
|
||||
display: -webkit-box;
|
||||
|
||||
-webkit-box-orient: vertical;
|
||||
|
||||
-webkit-line-clamp: 2;
|
||||
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
> .likePrice {
|
||||
color: $theme_color;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
201
buyer/src/components/map/index.vue
Normal file
201
buyer/src/components/map/index.vue
Normal file
@@ -0,0 +1,201 @@
|
||||
<template>
|
||||
<div class="lili-map">
|
||||
<Modal v-model="showMap" title="选择地址" width="800">
|
||||
<div class="address">{{ addrContent.address }}</div>
|
||||
<div id="map-container"></div>
|
||||
|
||||
<div class="search-con">
|
||||
<Input
|
||||
placeholder="输入关键字搜索"
|
||||
id="input-map"
|
||||
v-model="mapSearch"
|
||||
/>
|
||||
<ul>
|
||||
<li
|
||||
v-for="(tip, index) in tips"
|
||||
:key="index"
|
||||
@click="selectAddr(tip.location)"
|
||||
>
|
||||
<p>{{ tip.name }}</p>
|
||||
<p>{{ tip.district + tip.address }}</p>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div slot="footer">
|
||||
<Button type="default" @click="showMap = false">取消</Button>
|
||||
<Button type="primary" :loading="loading" @click="ok">确定</Button>
|
||||
</div>
|
||||
</Modal>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import AMapLoader from '@amap/amap-jsapi-loader';
|
||||
import { handleRegion } from '@/api/address.js';
|
||||
export default {
|
||||
name: 'map',
|
||||
props: {
|
||||
useApi: {
|
||||
default: true,
|
||||
type: Boolean
|
||||
}
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
showMap: false, // 展示地图
|
||||
mapSearch: '', // 地图搜索
|
||||
map: null, // 初始化地图
|
||||
autoComplete: null, // 初始化搜索方法
|
||||
geocoder: null, // 初始化地理、坐标转化
|
||||
positionPicker: null, // 地图拖拽选点
|
||||
tips: [], // 搜索关键字列表
|
||||
addrContent: {}, // 回显地址信息
|
||||
loading: false // 加载状态
|
||||
};
|
||||
},
|
||||
watch: {
|
||||
mapSearch: function (val) {
|
||||
this.searchOfMap(val);
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
ok () {
|
||||
// 确定选择
|
||||
this.loading = true;
|
||||
const address = this.addrContent.address;
|
||||
const township = this.addrContent.regeocode.addressComponent.township;
|
||||
const index = address.indexOf(township) + township.length;
|
||||
this.addrContent.detail = address.substring(index);
|
||||
const params = {
|
||||
cityCode: this.addrContent.regeocode.addressComponent.citycode,
|
||||
townName: this.addrContent.regeocode.addressComponent.township
|
||||
};
|
||||
if (this.useApi) {
|
||||
handleRegion(params).then((res) => {
|
||||
this.loading = false;
|
||||
if (res.code === 200) {
|
||||
this.showMap = false;
|
||||
this.addrContent.addr = res.result.name.replace(/,/g, ' ');
|
||||
this.addrContent.addrId = res.result.id;
|
||||
this.$emit('getAddress', this.addrContent);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
this.loading = false;
|
||||
this.showMap = false;
|
||||
this.$emit('getAddress', this.addrContent);
|
||||
}
|
||||
},
|
||||
init () {
|
||||
AMapLoader.load({
|
||||
key: 'b440952723253aa9fe483e698057bf7d', // 申请好的Web端开发者Key,首次调用 load 时必填
|
||||
version: '', // 指定要加载的 JSAPI 的版本,缺省时默认为 1.4.15
|
||||
plugins: [
|
||||
'AMap.ToolBar',
|
||||
'AMap.Autocomplete',
|
||||
'AMap.PlaceSearch',
|
||||
'AMap.Geolocation',
|
||||
'AMap.Geocoder'
|
||||
], // 需要使用的的插件列表,如比例尺'AMap.Scale'等
|
||||
AMapUI: {
|
||||
// 是否加载 AMapUI,缺省不加载
|
||||
version: '1.1', // AMapUI 缺省 1.1
|
||||
plugins: ['misc/PositionPicker'] // 需要加载的 AMapUI ui插件
|
||||
}
|
||||
})
|
||||
.then((AMap) => {
|
||||
let that = this;
|
||||
this.map = new AMap.Map('map-container', {
|
||||
zoom: 12
|
||||
});
|
||||
that.map.addControl(new AMap.ToolBar());
|
||||
that.map.addControl(new AMap.Autocomplete());
|
||||
that.map.addControl(new AMap.PlaceSearch());
|
||||
that.map.addControl(new AMap.Geocoder());
|
||||
|
||||
// 实例化Autocomplete
|
||||
let autoOptions = {
|
||||
city: '全国'
|
||||
};
|
||||
that.autoComplete = new AMap.Autocomplete(autoOptions); // 搜索
|
||||
that.geocoder = new AMap.Geocoder(autoOptions);
|
||||
|
||||
that.positionPicker = new AMapUI.PositionPicker({
|
||||
// 拖拽选点
|
||||
mode: 'dragMap',
|
||||
map: that.map
|
||||
});
|
||||
that.positionPicker.start();
|
||||
/**
|
||||
*
|
||||
* 所有回显数据,都在positionResult里面
|
||||
* 需要字段可以查找
|
||||
*
|
||||
*/
|
||||
that.positionPicker.on('success', function (positionResult) {
|
||||
// console.log(positionResult);
|
||||
that.addrContent = positionResult;
|
||||
});
|
||||
})
|
||||
.catch((e) => {});
|
||||
},
|
||||
searchOfMap (val) {
|
||||
// 地图搜索
|
||||
let that = this;
|
||||
this.autoComplete.search(val, function (status, result) {
|
||||
// 搜索成功时,result即是对应的匹配数据
|
||||
if (status === 'complete' && result.info === 'OK') {
|
||||
that.tips = result.tips;
|
||||
} else {
|
||||
that.tips = [];
|
||||
}
|
||||
});
|
||||
},
|
||||
selectAddr (location) {
|
||||
// 选择坐标
|
||||
if (!location) {
|
||||
this.$Message.warning('请选择正确点位');
|
||||
return false;
|
||||
}
|
||||
const lnglat = [location.lng, location.lat];
|
||||
this.positionPicker.start(lnglat);
|
||||
}
|
||||
},
|
||||
mounted () {
|
||||
this.init();
|
||||
}
|
||||
};
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
#map-container {
|
||||
width: 500px;
|
||||
height: 400px;
|
||||
}
|
||||
|
||||
.search-con {
|
||||
position: absolute;
|
||||
right: 20px;
|
||||
top: 64px;
|
||||
width: 260px;
|
||||
ul {
|
||||
width: 260px;
|
||||
height: 400px;
|
||||
overflow: scroll;
|
||||
li {
|
||||
padding: 5px;
|
||||
p:nth-child(2) {
|
||||
color: #999;
|
||||
font-size: 12px;
|
||||
}
|
||||
&:hover {
|
||||
background-color: #eee;
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.address {
|
||||
margin-bottom: 10px;
|
||||
font-weight: bold;
|
||||
}
|
||||
</style>
|
||||
186
buyer/src/components/map/region.vue
Normal file
186
buyer/src/components/map/region.vue
Normal file
@@ -0,0 +1,186 @@
|
||||
<template>
|
||||
<div>
|
||||
<Cascader
|
||||
:data="data"
|
||||
:load-data="loadData"
|
||||
v-model="addr"
|
||||
@on-change="change"
|
||||
style="width: 300px"
|
||||
></Cascader>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import {getRegion} from '@/api/common.js';
|
||||
export default {
|
||||
data () {
|
||||
return {
|
||||
data: [], // 地区数据
|
||||
addr: [] // 已选数据
|
||||
};
|
||||
},
|
||||
props: ['addressId'],
|
||||
mounted () {},
|
||||
methods: {
|
||||
change (val, selectedData) {
|
||||
/**
|
||||
* @returns [regionId,region]
|
||||
*/
|
||||
this.$emit('selected', [
|
||||
val,
|
||||
selectedData[selectedData.length - 1].__label.split('/')
|
||||
]);
|
||||
},
|
||||
loadData (item, callback) {
|
||||
item.loading = true;
|
||||
getRegion(item.value).then((res) => {
|
||||
if (res.result.length <= 0) {
|
||||
item.loading = false;
|
||||
} else {
|
||||
res.result.forEach((child) => {
|
||||
item.loading = false;
|
||||
|
||||
let data = {
|
||||
value: child.id,
|
||||
label: child.name,
|
||||
loading: false,
|
||||
children: []
|
||||
};
|
||||
|
||||
if (child.level === 'street' || item.label === '香港特别行政区') {
|
||||
item.children.push({
|
||||
value: child.id,
|
||||
label: child.name
|
||||
});
|
||||
} else {
|
||||
item.children.push(data);
|
||||
}
|
||||
});
|
||||
callback();
|
||||
}
|
||||
});
|
||||
},
|
||||
async init () {
|
||||
let data = await getRegion(0);
|
||||
let arr = [];
|
||||
data.result.forEach((item) => {
|
||||
let obj;
|
||||
// 台湾省做处理
|
||||
if (item.name === '台湾省') {
|
||||
obj = {
|
||||
value: item.id,
|
||||
label: item.name
|
||||
};
|
||||
} else {
|
||||
obj = {
|
||||
value: item.id,
|
||||
label: item.name,
|
||||
loading: false,
|
||||
children: []
|
||||
};
|
||||
}
|
||||
arr.push(obj);
|
||||
});
|
||||
this.data = arr;
|
||||
console.warn('init');
|
||||
},
|
||||
async reviewData () {
|
||||
// 数据回显
|
||||
let addr = JSON.parse(JSON.stringify(this.addressId.split(',')));
|
||||
let length = addr.length;
|
||||
let data = await getRegion(0);
|
||||
let arr0 = [];
|
||||
let arr1 = [];
|
||||
let arr2 = [];
|
||||
// 第一级数据
|
||||
data.result.forEach((item) => {
|
||||
let obj;
|
||||
// 台湾省做处理
|
||||
if (item.name === '台湾省') {
|
||||
obj = {
|
||||
value: item.id,
|
||||
label: item.name
|
||||
};
|
||||
} else {
|
||||
obj = {
|
||||
value: item.id,
|
||||
label: item.name,
|
||||
loading: false,
|
||||
children: []
|
||||
};
|
||||
}
|
||||
arr0.push(obj);
|
||||
});
|
||||
// 根据选择的数据来加载数据列表
|
||||
if (length > 0) {
|
||||
let children = await getRegion(addr[0]);
|
||||
children = this.handleData(children.result);
|
||||
arr0.forEach((e) => {
|
||||
if (e.value === addr[0]) {
|
||||
e.children = arr1 = children;
|
||||
}
|
||||
});
|
||||
}
|
||||
if (length > 1) {
|
||||
let children = await getRegion(addr[1]);
|
||||
children = this.handleData(children.result);
|
||||
arr1.forEach((e) => {
|
||||
if (e.value === addr[1]) {
|
||||
e.children = arr2 = children;
|
||||
}
|
||||
});
|
||||
}
|
||||
if (length > 2) {
|
||||
let children = await getRegion(addr[2]);
|
||||
children = this.handleData(children.result);
|
||||
arr2.forEach((e) => {
|
||||
if (e.value === addr[2]) {
|
||||
e.children = children;
|
||||
}
|
||||
});
|
||||
}
|
||||
this.data = arr0;
|
||||
this.addr = addr;
|
||||
},
|
||||
handleData (data) {
|
||||
// 处理接口数据
|
||||
let item = [];
|
||||
data.forEach((child) => {
|
||||
let obj = {
|
||||
value: child.id,
|
||||
label: child.name,
|
||||
loading: false,
|
||||
children: []
|
||||
};
|
||||
|
||||
if (child.level === 'street' || item.label === '香港特别行政区') {
|
||||
item.push({
|
||||
value: child.id,
|
||||
label: child.name
|
||||
});
|
||||
} else {
|
||||
item.push(obj);
|
||||
}
|
||||
});
|
||||
return item;
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
addressId: {
|
||||
handler: function (v) {
|
||||
console.log(v);
|
||||
if (v) {
|
||||
this.reviewData();
|
||||
} else {
|
||||
this.init();
|
||||
}
|
||||
},
|
||||
immediate: true
|
||||
},
|
||||
addr (v) {
|
||||
console.log(v);
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
<style scoped lang="scss">
|
||||
</style>
|
||||
708
buyer/src/components/nav/GoodsClassNav.vue
Normal file
708
buyer/src/components/nav/GoodsClassNav.vue
Normal file
@@ -0,0 +1,708 @@
|
||||
<template>
|
||||
<div class="item-class-show">
|
||||
<div class="head-bar">
|
||||
<!-- 有商品分类展示商品分类 -->
|
||||
<template v-if="$route.query.categoryId">
|
||||
<!-- 头部展示筛选信息 -->
|
||||
<div @click="cateClick(tabBar,1)">{{ tabBar.name }}</div>
|
||||
<Icon type="ios-arrow-forward" />
|
||||
|
||||
<div class="bar" v-if="tabBar.first">
|
||||
{{ tabBar.first.name }} <Icon type="ios-arrow-down" />
|
||||
<ul>
|
||||
<li v-for="item in tabBar.children" :key="item.id" @click="cateClick(item,2)">
|
||||
{{ item.name }}
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<Icon type="ios-arrow-forward" v-if="tabBar.first" />
|
||||
|
||||
<div class="bar" v-if="tabBar.second">
|
||||
{{ tabBar.second.name }} <Icon type="ios-arrow-down" />
|
||||
<ul>
|
||||
<li v-for="item in tabBar.first.children" :key="item.id" @click="cateClick(item,3)">
|
||||
{{ item.name }}
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<Icon type="ios-arrow-forward" v-if="tabBar.second" />
|
||||
</template>
|
||||
<!-- 无商品分类,展示搜索结果 -->
|
||||
<template v-else>
|
||||
<div style="font-size:14px">全部结果</div>
|
||||
<Icon type="ios-arrow-forward" />
|
||||
<div>{{params.keyword}}</div>
|
||||
</template>
|
||||
<!-- 所选分类 -->
|
||||
<a
|
||||
class="selected-item"
|
||||
@click="cancelSelected(item, index)"
|
||||
v-for="(item, index) in selectedItem"
|
||||
:key="index"
|
||||
:title="item.name"
|
||||
>
|
||||
<span>{{ item.type }}:</span><span>{{ item.name }}</span
|
||||
><Icon type="md-close" />
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<!-- 筛选主体 -->
|
||||
<div class="content">
|
||||
<!-- 品牌, 有图片,独立出来 -->
|
||||
<div class="brand" v-show="tagsContent[0].show && tagsContent[0].values.length">
|
||||
<div>
|
||||
<strong>{{ tagsContent[0].key }}:</strong>
|
||||
</div>
|
||||
<div>
|
||||
<ul :class="{ 'show-more': tagsContent[0].more }">
|
||||
<li
|
||||
@click="selectBrand(item.name, 0)"
|
||||
:class="{ 'border-color': multSelected.includes(item) }"
|
||||
v-for="(item, index) in tagsContent[0].values"
|
||||
:key="index"
|
||||
>
|
||||
<img :src="item.url" alt="" /><span>{{ item.name }}</span>
|
||||
<div
|
||||
class="corner-icon"
|
||||
v-show="multSelected.includes(item.name)"
|
||||
>
|
||||
<div></div>
|
||||
<Icon type="md-checkmark" />
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<div class="btn" v-show="multiple !== 0">
|
||||
<span @click="moreBrand(0)"
|
||||
>{{ tagsContent[0].more ? "收起" : "更多"
|
||||
}}<Icon
|
||||
:type="tagsContent[0].more ? 'ios-arrow-up' : 'ios-arrow-down'"
|
||||
/></span>
|
||||
<span @click="multSelectBrand(0)"><Icon type="md-add" />多选</span>
|
||||
</div>
|
||||
|
||||
<div class="multBtn" v-show="multiple === 0">
|
||||
<Button
|
||||
type="primary"
|
||||
size="small"
|
||||
:disabled="!multSelected.length"
|
||||
@click="sure(0)"
|
||||
>确定</Button
|
||||
>
|
||||
<Button size="small" @click="cancel">取消</Button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 其他筛选项 -->
|
||||
<template v-for="(tag, tagIndex) in tagsContent">
|
||||
<div class="other" v-if="tag.show && tagIndex !== 0" :key="tagIndex">
|
||||
<div>
|
||||
<strong>{{ tag.key }}:</strong>
|
||||
</div>
|
||||
<div>
|
||||
<ul
|
||||
:class="{ 'show-more': tag.more }"
|
||||
class="list"
|
||||
v-show="multiple !== tagIndex"
|
||||
>
|
||||
<li
|
||||
@click="selectBrand(item, tagIndex)"
|
||||
class="item"
|
||||
v-for="(item, index) in tag.values"
|
||||
:key="index"
|
||||
>
|
||||
{{ item }}
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<CheckboxGroup
|
||||
:class="{ 'show-more': tag.more }"
|
||||
class="list"
|
||||
v-model="multSelected"
|
||||
v-show="multiple === tagIndex"
|
||||
>
|
||||
<Checkbox
|
||||
class="item"
|
||||
:label="item"
|
||||
v-for="(item, index) in tag.values"
|
||||
:key="index"
|
||||
>{{ item }}</Checkbox
|
||||
>
|
||||
</CheckboxGroup>
|
||||
|
||||
<div class="btn" v-show="multiple !== tagIndex">
|
||||
<span @click="moreBrand(tagIndex)" v-show="tag.values.length > 9"
|
||||
>{{ tag.more ? "收起" : "更多"
|
||||
}}<Icon :type="tag.more ? 'ios-arrow-up' : 'ios-arrow-down'"
|
||||
/></span>
|
||||
<span @click="multSelectBrand(tagIndex)"
|
||||
><Icon type="md-add" />多选</span
|
||||
>
|
||||
</div>
|
||||
|
||||
<div class="multBtn" v-show="multiple === tagIndex">
|
||||
<Button
|
||||
type="primary"
|
||||
size="small"
|
||||
:disabled="!multSelected.length"
|
||||
@click="sure(tagIndex)"
|
||||
>确定</Button
|
||||
>
|
||||
<Button size="small" @click="cancel">取消</Button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import * as APIGoods from '@/api/goods';
|
||||
export default {
|
||||
name: 'GoodsClassNav',
|
||||
data () {
|
||||
return {
|
||||
tabBar: { // 分类数据
|
||||
name: '',
|
||||
first: {},
|
||||
second: {}
|
||||
},
|
||||
multiple: false, // 多选
|
||||
tagsContent: [
|
||||
// 标签
|
||||
{
|
||||
key: '品牌',
|
||||
more: false,
|
||||
show: true,
|
||||
values: []
|
||||
}
|
||||
],
|
||||
multSelected: [], // 多选分类
|
||||
selectedItem: [], // 已选分类集合 顶部展示
|
||||
brandIds: [], // 品牌id合集
|
||||
params: {}, // 请求参数
|
||||
cateList: [] // 全部商品分类
|
||||
};
|
||||
},
|
||||
watch: {
|
||||
selectedItem: {
|
||||
// 监听已选条件,来调用列表接口
|
||||
handler (val) {
|
||||
let classification = [];
|
||||
if (val.length) {
|
||||
val.forEach((item) => {
|
||||
if (item.type === '品牌') {
|
||||
this.params.brandId = this.brandIds.join('@');
|
||||
} else {
|
||||
const nameArr = item.name.split('、');
|
||||
nameArr.forEach((name) => {
|
||||
classification.push(item.type + '_' + name);
|
||||
});
|
||||
}
|
||||
});
|
||||
this.params.prop = classification.join('@');
|
||||
} else {
|
||||
this.params.prop = ''
|
||||
this.params.brandId = ''
|
||||
}
|
||||
this.getFilterList(this.params);
|
||||
this.$emit('getParams', this.params);
|
||||
},
|
||||
deep: true
|
||||
},
|
||||
'$route': {
|
||||
handler (val, oVal) {
|
||||
if (this.$route.query.categoryId) {
|
||||
let cateId = this.$route.query.categoryId.split(',')
|
||||
Object.assign(this.params, this.$route.query)
|
||||
this.params.categoryId = cateId[cateId.length - 1]
|
||||
} else {
|
||||
Object.assign(this.params, this.$route.query)
|
||||
}
|
||||
this.getFilterList(this.params)
|
||||
this.getNav()
|
||||
},
|
||||
deep: true
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
getNav () { // 获取商品分类,分类下展示
|
||||
if (!this.$route.query.categoryId) return
|
||||
|
||||
this.cateList = JSON.parse(localStorage.getItem('category'))
|
||||
const arr = this.$route.query.categoryId.split(',')
|
||||
if (arr.length > 0) {
|
||||
this.tabBar = this.cateList.filter(e => {
|
||||
return e.id === arr[0]
|
||||
})[0]
|
||||
}
|
||||
if (arr.length > 1) {
|
||||
const first = this.tabBar.children.filter(e => {
|
||||
return e.id === arr[1]
|
||||
})[0]
|
||||
this.$set(this.tabBar, 'first', first)
|
||||
}
|
||||
if (arr.length > 2) {
|
||||
const second = this.tabBar.first.children.filter(e => {
|
||||
return e.id === arr[2]
|
||||
})[0]
|
||||
this.$set(this.tabBar, 'second', second)
|
||||
}
|
||||
},
|
||||
cateClick (item, index) {
|
||||
switch (index) {
|
||||
case 1:
|
||||
this.$router.push({
|
||||
path: '/goodsList',
|
||||
query: {categoryId: item.id}
|
||||
})
|
||||
break;
|
||||
case 2:
|
||||
this.$router.push({
|
||||
path: '/goodsList',
|
||||
query: {categoryId: [item.parentId, item.id].toString()}
|
||||
})
|
||||
break;
|
||||
case 3:
|
||||
this.$router.push({
|
||||
path: '/goodsList',
|
||||
query: {categoryId: [this.tabBar.id, item.parentId, item.id].toString()}
|
||||
})
|
||||
break;
|
||||
}
|
||||
},
|
||||
selectBrand (item, index) {
|
||||
// 选择筛选项
|
||||
if (this.multiple !== false) {
|
||||
// 非多选直接在顶部栏展示,多选则添加选择状态
|
||||
|
||||
let key = this.multSelected.indexOf(item);
|
||||
if (key > -1) {
|
||||
this.multSelected.splice(key, 1);
|
||||
} else {
|
||||
this.multSelected.push(item);
|
||||
}
|
||||
} else {
|
||||
this.selectedItem.push({
|
||||
type: this.tagsContent[index].key,
|
||||
name: item
|
||||
});
|
||||
|
||||
this.tagsContent[index].show = false;
|
||||
|
||||
if (index === 0) {
|
||||
// 如果是品牌,获取品牌id
|
||||
|
||||
let brands = this.tagsContent[0].values;
|
||||
|
||||
brands.forEach((val) => {
|
||||
if (val.name === item) this.brandIds.push(val.value);
|
||||
console.log(this.brandIds);
|
||||
});
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
cancelSelected (item, index) {
|
||||
// 顶部栏 取消已选中的项
|
||||
this.selectedItem.splice(index, 1);
|
||||
|
||||
this.tagsContent.forEach((tag, index) => {
|
||||
if (tag.key === item.type) {
|
||||
tag.show = true;
|
||||
tag.more = false;
|
||||
}
|
||||
});
|
||||
if (item.type === '品牌') {
|
||||
this.brandIds = [];
|
||||
}
|
||||
},
|
||||
moreBrand (index) {
|
||||
// 更多按钮
|
||||
const flag = !this.tagsContent[index].more
|
||||
this.$set(this.tagsContent[index], 'more', flag)
|
||||
},
|
||||
multSelectBrand (index) {
|
||||
// 多选按钮
|
||||
this.$set(this.tagsContent[index], 'more', true)
|
||||
this.multiple = index;
|
||||
},
|
||||
sure (index) {
|
||||
// 多选确认按钮
|
||||
this.selectedItem.push({
|
||||
type: this.tagsContent[index].key,
|
||||
name: this.multSelected.join('、')
|
||||
});
|
||||
|
||||
if (index === 0) {
|
||||
// 如果是品牌,获取品牌id
|
||||
|
||||
let brands = this.tagsContent[0].values;
|
||||
|
||||
brands.forEach((val) => {
|
||||
if (this.multSelected.includes(val.name)) this.brandIds.push(val.value);
|
||||
});
|
||||
}
|
||||
|
||||
this.tagsContent[index].show = false;
|
||||
this.cancel();
|
||||
},
|
||||
cancel () {
|
||||
// 多选取消按钮
|
||||
this.multSelected = [];
|
||||
this.tagsContent[0].more = false;
|
||||
this.multiple = false;
|
||||
},
|
||||
getFilterList (params) {
|
||||
// 筛选、分类 列表
|
||||
APIGoods.filterList(params).then((res) => {
|
||||
if (res.code === 200) {
|
||||
const data = res.result;
|
||||
this.tagsContent = [{
|
||||
key: '品牌',
|
||||
more: false,
|
||||
show: true,
|
||||
values: []
|
||||
}]
|
||||
this.tagsContent[0].values = data.brands;
|
||||
this.tagsContent = this.tagsContent.concat(data.paramOptions);
|
||||
this.tagsContent.forEach((item) => {
|
||||
this.$set(item, 'show', true)
|
||||
this.$set(item, 'more', false)
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
mounted () {
|
||||
if (this.$route.query.categoryId) {
|
||||
let cateId = this.$route.query.categoryId.split(',')
|
||||
Object.assign(this.params, this.$route.query)
|
||||
this.params.categoryId = cateId[cateId.length - 1]
|
||||
} else {
|
||||
Object.assign(this.params, this.$route.query)
|
||||
}
|
||||
this.getFilterList(this.params);
|
||||
this.getNav();
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
/** 头部展示筛选项 */
|
||||
.head-bar {
|
||||
width: 100%;
|
||||
background: #fff;
|
||||
margin-top: -13px;
|
||||
display: flex;
|
||||
height: 40px;
|
||||
align-items: center;
|
||||
> div:first-child {
|
||||
padding: 0 8px;
|
||||
font-size: 18px;
|
||||
font-weight: bold;
|
||||
&:hover {
|
||||
color: $theme_color;
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
.bar {
|
||||
font-size: 12px;
|
||||
position: relative;
|
||||
background: #fff;
|
||||
border: 1px solid #999;
|
||||
padding: 0 8px;
|
||||
width: 85px;
|
||||
text-align: center;
|
||||
margin: 0 3px;
|
||||
&:hover {
|
||||
color: $theme_color;
|
||||
border-color: $theme_color;
|
||||
border-bottom-color: #fff;
|
||||
cursor: pointer;
|
||||
ul {
|
||||
display: block;
|
||||
}
|
||||
.ivu-icon {
|
||||
transform: rotate(180deg);
|
||||
}
|
||||
}
|
||||
ul {
|
||||
display: none;
|
||||
position: absolute;
|
||||
top: 18px;
|
||||
left: -1px;
|
||||
width: 300px;
|
||||
padding: 5px 10px;
|
||||
background: #fff;
|
||||
border: 1px solid $theme_color;
|
||||
z-index: 1;
|
||||
&::before {
|
||||
content: "";
|
||||
position: absolute;
|
||||
width: 83px;
|
||||
left: 0;
|
||||
top: -1px;
|
||||
z-index: 2;
|
||||
border-top: 1px solid #fff;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
display: block;
|
||||
}
|
||||
clear: left;
|
||||
li {
|
||||
color: #999;
|
||||
float: left;
|
||||
width: 30%;
|
||||
margin: 3px 0;
|
||||
text-align: left;
|
||||
&:hover {
|
||||
color: $theme_color;
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
//所选分类
|
||||
.selected-item {
|
||||
font-size: 12px;
|
||||
color: #000;
|
||||
padding: 2px 22px 2px 8px;
|
||||
margin-right: 5px;
|
||||
max-width: 250px;
|
||||
height: 24px;
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
background-color: #f3f3f3;
|
||||
border: 1px solid #ddd;
|
||||
&:hover {
|
||||
border-color: $theme_color;
|
||||
background-color: #fff;
|
||||
.ivu-icon {
|
||||
color: #fff;
|
||||
background-color: $theme_color;
|
||||
}
|
||||
}
|
||||
|
||||
span:nth-child(2) {
|
||||
color: $theme_color;
|
||||
}
|
||||
|
||||
.ivu-icon {
|
||||
position: absolute;
|
||||
right: 0;
|
||||
top: 0;
|
||||
color: $theme_color;
|
||||
line-height: 22px;
|
||||
width: 21px;
|
||||
height: 22px;
|
||||
font-size: 14px;
|
||||
}
|
||||
}
|
||||
}
|
||||
/** 筛选主体 */
|
||||
.content {
|
||||
background: #fff;
|
||||
border-top: 1px solid #999;
|
||||
border-bottom: 1px solid #999;
|
||||
margin: 10px 0;
|
||||
}
|
||||
/** 品牌 start */
|
||||
.brand {
|
||||
border-bottom: 1px solid #ddd;
|
||||
display: flex;
|
||||
// min-height: 120px;
|
||||
font-size: 12px;
|
||||
> div:first-child {
|
||||
width: 100px;
|
||||
background: #eee;
|
||||
padding: 10px 0 0 10px;
|
||||
}
|
||||
> div:last-child {
|
||||
width: 1100px;
|
||||
padding: 10px;
|
||||
position: relative;
|
||||
ul {
|
||||
width: 900px;
|
||||
max-height: 100px;
|
||||
overflow: hidden;
|
||||
padding-top: 1px;
|
||||
clear: left;
|
||||
li {
|
||||
width: 100px;
|
||||
height: 50px;
|
||||
float: left;
|
||||
line-height: 50px;
|
||||
border: 1px solid #ddd;
|
||||
margin: -1px -1px 0 0;
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
padding: 2px;
|
||||
img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
border-color: $theme_color;
|
||||
top: 0;
|
||||
left: 0;
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
img {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
span {
|
||||
display: inline-block;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
color: $theme_color;
|
||||
text-align: center;
|
||||
font-size: 12px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.corner-icon {
|
||||
position: absolute;
|
||||
right: -1px;
|
||||
bottom: -1px;
|
||||
div {
|
||||
width: 0;
|
||||
border-top: 20px solid transparent;
|
||||
border-right: 20px solid $theme_color;
|
||||
}
|
||||
.ivu-icon {
|
||||
font-size: 12px;
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
right: 1px;
|
||||
transform: rotate(-15deg);
|
||||
color: #fff;
|
||||
}
|
||||
}
|
||||
}
|
||||
.border-color {
|
||||
border-color: $theme_color;
|
||||
z-index: 1;
|
||||
}
|
||||
}
|
||||
.show-more {
|
||||
height: auto;
|
||||
max-height: 200px;
|
||||
overflow: scroll;
|
||||
}
|
||||
.btn {
|
||||
position: absolute;
|
||||
right: 10px;
|
||||
top: 10px;
|
||||
span {
|
||||
border: 1px solid #ddd;
|
||||
margin-left: 10px;
|
||||
color: #999;
|
||||
display: inline-block;
|
||||
padding: 1px 3px;
|
||||
font-size: 12px;
|
||||
&:hover {
|
||||
cursor: pointer;
|
||||
color: $theme_color;
|
||||
border-color: $theme_color;
|
||||
}
|
||||
}
|
||||
}
|
||||
.multBtn {
|
||||
text-align: center;
|
||||
margin-top: 10px;
|
||||
.ivu-btn {
|
||||
font-size: 12px !important;
|
||||
}
|
||||
.ivu-btn:last-child {
|
||||
margin-left: 10px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/** 品牌 end */
|
||||
/** 其他筛选项 start */
|
||||
.other {
|
||||
border-bottom: 1px solid #ddd;
|
||||
display: flex;
|
||||
min-height: 30px;
|
||||
font-size: 12px;
|
||||
&:last-child {
|
||||
border: none;
|
||||
}
|
||||
> div:first-child {
|
||||
width: 100px;
|
||||
background: #eee;
|
||||
padding: 10px 0 0 10px;
|
||||
}
|
||||
> div:last-child {
|
||||
width: 1100px;
|
||||
padding: 0 10px;
|
||||
position: relative;
|
||||
.list {
|
||||
width: 900px;
|
||||
height: 30px;
|
||||
overflow: hidden;
|
||||
clear: left;
|
||||
.item {
|
||||
width: 100px;
|
||||
height: 30px;
|
||||
float: left;
|
||||
line-height: 30px;
|
||||
color: $primary_color;
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
font-size: 12px;
|
||||
padding: 2px;
|
||||
cursor: pointer;
|
||||
&:hover {
|
||||
color: $theme_color;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.show-more {
|
||||
height: auto;
|
||||
}
|
||||
|
||||
.btn {
|
||||
position: absolute;
|
||||
right: 10px;
|
||||
top: 5px;
|
||||
span {
|
||||
border: 1px solid #ddd;
|
||||
margin-left: 10px;
|
||||
color: #999;
|
||||
display: inline-block;
|
||||
padding: 1px 3px;
|
||||
font-size: 12px;
|
||||
&:hover {
|
||||
cursor: pointer;
|
||||
color: $theme_color;
|
||||
border-color: $theme_color;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.multBtn {
|
||||
text-align: center;
|
||||
margin-top: 10px;
|
||||
margin-bottom: 10px;
|
||||
.ivu-btn {
|
||||
font-size: 12px !important;
|
||||
}
|
||||
.ivu-btn:last-child {
|
||||
margin-left: 10px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** 其他筛选项 end */
|
||||
</style>
|
||||
285
buyer/src/components/nav/cateNav.vue
Normal file
285
buyer/src/components/nav/cateNav.vue
Normal file
@@ -0,0 +1,285 @@
|
||||
<template>
|
||||
<div class="cate-nav">
|
||||
<div class="nav-con">
|
||||
<div class="all-categories hover-pointer" @mouseenter="showFirstList = true" @mouseleave="showFirstList = false">全部商品分类</div>
|
||||
<ul class="nav-item" v-if="showNavBar">
|
||||
<li
|
||||
class="hover-color"
|
||||
v-for="(item, index) in navList.list"
|
||||
:key="index"
|
||||
@click="linkTo(item.url)"
|
||||
>
|
||||
{{ item.name }}
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<!-- 侧边导航 -->
|
||||
<div class="cate-list" v-show="showAlways || showFirstList" @mouseenter="showFirstList = true" @mouseleave="showFirstList = false">
|
||||
<div class="nav-side">
|
||||
<ul>
|
||||
<li v-for="(item, index) in cateList" :key="index" @mouseenter="showDetail(index)" @mouseleave="panel = false">
|
||||
<span class="nav-side-item" @click="goGoodsList(item.id)">{{item.name}}</span>
|
||||
<span v-for="(second, secIndex) in item.children" :key="secIndex">
|
||||
<span v-if="secIndex < 2" > / </span>
|
||||
<span @click="goGoodsList(second.id, second.parentId)" class="nav-side-item" v-if="secIndex < 2">{{second.name}}</span>
|
||||
</span>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<transition name="fade">
|
||||
<div
|
||||
class="detail-item-panel"
|
||||
:duration="{ enter: 100, leave: 100 }"
|
||||
v-show="panel"
|
||||
@mouseenter="panel = true"
|
||||
ref="itemPanel1"
|
||||
@mouseleave="panel = false"
|
||||
>
|
||||
<div class="nav-detail-item">
|
||||
<template v-for="(item, index) in panelData">
|
||||
<span @click="goGoodsList(item.id, item.parentId)" v-if="index < 8" :key="index">{{ item.name }}<Icon type="ios-arrow-forward" /></span>
|
||||
</template>
|
||||
</div>
|
||||
<ul>
|
||||
<li
|
||||
v-for="(items, index) in panelData"
|
||||
:key="index"
|
||||
class="detail-item-row"
|
||||
>
|
||||
<span class="detail-item-title" @click="goGoodsList(items.id,items.parentId)">
|
||||
{{ items.name }} <Icon type="ios-arrow-forward" />
|
||||
<span class="glyphicon glyphicon-menu-right"></span>
|
||||
</span>
|
||||
<div>
|
||||
<span v-for="(item, subIndex) in items.children" @click="goGoodsList(item.id,items.id,items.parentId)"
|
||||
:key="subIndex" class="detail-item">{{ item.name }}</span>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</transition>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { getCategory } from '@/api/goods';
|
||||
import storage from '@/plugins/storage.js'
|
||||
export default {
|
||||
name: 'GoodsListNav',
|
||||
props: {
|
||||
showAlways: { // 总是显示下拉分类
|
||||
default: false,
|
||||
type: Boolean
|
||||
},
|
||||
showNavBar: { // 显示全部商品分类右侧导航条
|
||||
default: true,
|
||||
type: Boolean
|
||||
}
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
cateList: [], // 分类数据
|
||||
panel: false, // 二级分类展示
|
||||
panelData: [], // 二级分类数据
|
||||
showFirstList: false // 始终展示一级列表
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
navList () {
|
||||
return JSON.parse(storage.getItem('navList')) || []
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
getCate () {
|
||||
getCategory(0).then(res => {
|
||||
if (res.success) {
|
||||
this.cateList = res.result;
|
||||
localStorage.setItem('category', JSON.stringify(res.result))
|
||||
}
|
||||
});
|
||||
},
|
||||
showDetail (index) {
|
||||
this.panel = true
|
||||
this.panelData = this.cateList[index].children
|
||||
},
|
||||
goGoodsList (id, secondId, firstId) { // 分类共有三级,传全部分类过去
|
||||
const arr = [firstId, secondId, id]
|
||||
if (!arr[1]) {
|
||||
arr.splice(0, 2)
|
||||
}
|
||||
if (!arr[0]) {
|
||||
arr.shift()
|
||||
}
|
||||
let routerUrl = this.$router.resolve({
|
||||
path: '/goodsList',
|
||||
query: {categoryId: arr.toString()}
|
||||
})
|
||||
window.open(routerUrl.href, '_blank')
|
||||
}
|
||||
},
|
||||
mounted () {
|
||||
if (localStorage.getItem('category')) {
|
||||
this.cateList = JSON.parse(localStorage.getItem('category'))
|
||||
} else {
|
||||
this.getCate()
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.cate-nav{
|
||||
width: 1200px;
|
||||
position: relative;
|
||||
margin: 0 auto;
|
||||
}
|
||||
/** 商品分类 */
|
||||
.nav-con {
|
||||
width: 1200px;
|
||||
height: 40px;
|
||||
// background: #eee;
|
||||
margin: 0 auto;
|
||||
display: flex;
|
||||
.all-categories {
|
||||
width: 200px;
|
||||
line-height: 40px;
|
||||
color: #fff;
|
||||
background-color: $theme_color;
|
||||
text-align: center;
|
||||
font-size: 16px;
|
||||
}
|
||||
.nav-item {
|
||||
width: 1000px;
|
||||
height: 40px;
|
||||
line-height: 40px;
|
||||
overflow: hidden;
|
||||
list-style: none;
|
||||
background-color: #eee;
|
||||
display: flex;
|
||||
li {
|
||||
font-size: 16px;
|
||||
font-weight: bold;
|
||||
margin-left: 20px;
|
||||
color: rgb(89, 88, 88);
|
||||
font-size: 15px;
|
||||
&:hover {
|
||||
color: $theme_color;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.cate-list{
|
||||
margin: 0 auto;
|
||||
position: absolute;
|
||||
z-index: 1000;
|
||||
}
|
||||
.nav-item li {
|
||||
float: left;
|
||||
font-size: 16px;
|
||||
font-weight: bold;
|
||||
margin-left: 30px;
|
||||
}
|
||||
.nav-item a {
|
||||
text-decoration: none;
|
||||
color: #555555;
|
||||
}
|
||||
.nav-item a:hover {
|
||||
color: $theme_color;
|
||||
}
|
||||
|
||||
.nav-side {
|
||||
width: 200px;
|
||||
float: left;
|
||||
padding: 0px;
|
||||
color: #fff;
|
||||
background-color: #6e6568;
|
||||
height: 335px;
|
||||
overflow: hidden;
|
||||
}
|
||||
.nav-side ul {
|
||||
width: 100%;
|
||||
padding: 0px;
|
||||
padding-top: 5px;
|
||||
list-style: none;
|
||||
}
|
||||
.nav-side li {
|
||||
padding: 7.5px 0;
|
||||
padding-left: 12px;
|
||||
font-size: 13px;
|
||||
line-height: 18px;
|
||||
}
|
||||
.nav-side li:hover {
|
||||
background: #999395;
|
||||
}
|
||||
.nav-side-item:hover {
|
||||
cursor: pointer;
|
||||
color: $theme_color;
|
||||
}
|
||||
|
||||
/*显示商品详细信息*/
|
||||
.detail-item-panel {
|
||||
width: 815px;
|
||||
min-height: 340px;
|
||||
background-color: #fff;
|
||||
box-shadow: 0px 0px 15px #ccc;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 200px;
|
||||
z-index: 1000;
|
||||
padding: 15px;
|
||||
}
|
||||
.nav-detail-item {
|
||||
margin-top: 5px;
|
||||
margin-bottom: 15px;
|
||||
cursor: pointer;
|
||||
color: #eee;
|
||||
}
|
||||
.nav-detail-item span {
|
||||
padding: 6px;
|
||||
padding-left: 12px;
|
||||
margin-right: 15px;
|
||||
font-size: 12px;
|
||||
background-color: #6e6568;
|
||||
}
|
||||
.nav-detail-item span:hover {
|
||||
background-color: $theme_color;
|
||||
}
|
||||
.detail-item-panel ul {
|
||||
list-style: none;
|
||||
}
|
||||
.detail-item-panel li {
|
||||
line-height: 30px;
|
||||
// margin-left: 40px;
|
||||
}
|
||||
.detail-item-title {
|
||||
font-weight: bold;
|
||||
font-size: 12px;
|
||||
cursor: pointer;
|
||||
color: #555555;
|
||||
padding-right: 10px;
|
||||
width: 81px;
|
||||
text-align: right;
|
||||
}
|
||||
.detail-item-title:hover {
|
||||
color: $theme_color;
|
||||
}
|
||||
.detail-item-row {
|
||||
display: flex;
|
||||
>div{flex: 1;}
|
||||
}
|
||||
.detail-item {
|
||||
font-size: 12px;
|
||||
padding-left: 8px;
|
||||
padding-right: 8px;
|
||||
cursor: pointer;
|
||||
border-left: 1px solid #ccc;
|
||||
&:first-child{
|
||||
border: none;
|
||||
padding-left: 0;
|
||||
}
|
||||
}
|
||||
.detail-item:hover {
|
||||
color: $theme_color;
|
||||
}
|
||||
</style>
|
||||
14
buyer/src/components/verify/README.md
Normal file
14
buyer/src/components/verify/README.md
Normal file
@@ -0,0 +1,14 @@
|
||||
### 滑动拼图验证
|
||||
|
||||
### 在页面中引入 .vue文件
|
||||
|
||||
#### 参数
|
||||
|
||||
#### 在组件上添加v-if来判断组件显隐
|
||||
|
||||
#### verifyType 验证格式[ 'LOGIN' ,'REGISTER' ]等,详情看接口文档
|
||||
|
||||
#### @change方法 获取回调,参数为对象 {status:false,distance:100} status 为回调状态,distance为移动距离
|
||||
|
||||
|
||||
#### <Verify class="verify-content" verifyType='LOGIN' @change="verifyChange"></Verify>
|
||||
185
buyer/src/components/verify/index.vue
Normal file
185
buyer/src/components/verify/index.vue
Normal file
@@ -0,0 +1,185 @@
|
||||
<template>
|
||||
<div class="verify-content" v-if="show" @mousemove="mouseMove" @mouseup="mouseUp">
|
||||
<div class="imgBox" :style="{width:data.originalWidth+'px',height:data.originalHeight + 'px'}">
|
||||
<img :src="data.backImage" style="width:100%;height:100%" alt="">
|
||||
<img class="slider" :src="data.slidingImage" :style="{left:distance+'px',top:data.randomY+'px'}" :width="data.sliderWidth" :height="data.sliderHeight" alt="">
|
||||
<Icon type="md-refresh" class="refresh" @click="refresh" />
|
||||
</div>
|
||||
<div class="handle" :style="{width:data.originalWidth+'px'}">
|
||||
<span class="bgcolor" :style="{width:distance + 'px',background:bgColor}"></span>
|
||||
<span class="swiper" :style="{left:distance + 'px'}" @mousedown="mouseDown">
|
||||
<Icon type="md-arrow-round-forward" />
|
||||
</span>
|
||||
<span class="text">{{verifyText}}</span>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import { getVerifyImg, postVerifyImg } from './verify.js';
|
||||
export default {
|
||||
props: {
|
||||
verifyType: {
|
||||
defalut: 'LOGIN',
|
||||
type: String
|
||||
}
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
show: false, // 验证码显隐
|
||||
type: 'LOGIN', // 请求类型
|
||||
data: { // 验证码数据
|
||||
backImage: '',
|
||||
slidingImage: '',
|
||||
originalHeight: 150,
|
||||
originalWidth: 300,
|
||||
sliderWidth: 60,
|
||||
sliderHeight: 60
|
||||
},
|
||||
distance: 0, // 拼图移动距离
|
||||
flag: false, // 判断滑块是否按下
|
||||
downX: 0, // 鼠标按下位置
|
||||
bgColor: 'aqua', // 滑动背景颜色
|
||||
verifyText: '拖动滑块解锁' // 文字提示
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
mouseDown (e) {
|
||||
this.downX = e.clientX;
|
||||
this.flag = true;
|
||||
},
|
||||
mouseMove (e) {
|
||||
if (this.flag) {
|
||||
let offset = e.clientX - this.downX;
|
||||
|
||||
if (offset > this.data.originalWidth - 43) {
|
||||
this.distance = this.data.originalWidth - 43;
|
||||
} else if (offset < 0) {
|
||||
this.distance = 0;
|
||||
} else {
|
||||
this.distance = offset;
|
||||
}
|
||||
}
|
||||
},
|
||||
mouseUp () {
|
||||
if (!this.flag) return false;
|
||||
this.flag = false;
|
||||
let params = {
|
||||
verificationEnums: this.type,
|
||||
xPos: this.distance
|
||||
};
|
||||
postVerifyImg(params).then(res => {
|
||||
if (res.result) {
|
||||
this.bgColor = 'green';
|
||||
this.verifyText = '解锁成功';
|
||||
this.$emit('change', { status: true, distance: this.distance });
|
||||
} else {
|
||||
this.bgColor = 'red';
|
||||
this.verifyText = '解锁失败';
|
||||
let that = this;
|
||||
setTimeout(() => {
|
||||
that.refresh();
|
||||
}, 1000);
|
||||
this.$emit('change', { status: false, distance: this.distance });
|
||||
}
|
||||
});
|
||||
},
|
||||
refresh () {
|
||||
this.flag = false;
|
||||
this.downX = 0;
|
||||
this.distance = 0;
|
||||
this.bgColor = 'aqua';
|
||||
this.verifyText = '拖动滑块解锁';
|
||||
this.getImg();
|
||||
},
|
||||
getImg () {
|
||||
getVerifyImg(this.type).then(res => {
|
||||
this.data = res.result;
|
||||
});
|
||||
}
|
||||
},
|
||||
created () {
|
||||
this.getImg();
|
||||
},
|
||||
watch: {
|
||||
verifyType: {
|
||||
immediate: true,
|
||||
handler: function (v) {
|
||||
this.type = v;
|
||||
this.refresh();
|
||||
}
|
||||
},
|
||||
show (v) {
|
||||
if (v) this.refresh();
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.verify-content{
|
||||
padding: 10px;
|
||||
background: #fff;
|
||||
border: 1px solid #eee;
|
||||
border-radius: 5px;
|
||||
box-shadow: 1px 1px 3px #999;
|
||||
}
|
||||
.imgBox {
|
||||
width: 300px;
|
||||
height: 150px;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
|
||||
.slider {
|
||||
position: absolute;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.refresh {
|
||||
position: absolute;
|
||||
right: 5px;
|
||||
top: 5px;
|
||||
font-size: 20px;
|
||||
color: #fff;
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
.handle {
|
||||
border: 1px solid rgb(134, 134, 134);
|
||||
margin-top: 5px;
|
||||
height: 42px;
|
||||
background: #ddd;
|
||||
position: relative;
|
||||
|
||||
.bgcolor {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
opacity: 0.5;
|
||||
background: aqua;
|
||||
}
|
||||
|
||||
.swiper {
|
||||
position: absolute;
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
background-color: #fff;
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
.ivu-icon {
|
||||
font-size: 20px;
|
||||
}
|
||||
}
|
||||
|
||||
.text {
|
||||
display: inline-block;
|
||||
width: inherit;
|
||||
text-align: center;
|
||||
line-height: 42px;
|
||||
font-size: 14px;
|
||||
user-select: none;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
32
buyer/src/components/verify/verify.js
Normal file
32
buyer/src/components/verify/verify.js
Normal file
@@ -0,0 +1,32 @@
|
||||
|
||||
import request, {Method, commonUrl} from '@/plugins/request.js';
|
||||
import storage from '@/plugins/storage.js';
|
||||
|
||||
/**
|
||||
* 获取拼图验证
|
||||
*/
|
||||
export function getVerifyImg (verificationEnums) {
|
||||
return request({
|
||||
url: `${commonUrl}/common/slider/${verificationEnums}`,
|
||||
method: Method.GET,
|
||||
needToken: false,
|
||||
headers: {uuid: storage.getItem('uuid')}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 验证码校验
|
||||
*/
|
||||
export function postVerifyImg (params) {
|
||||
return request({
|
||||
url: `${commonUrl}/common/slider/${params.verificationEnums}`,
|
||||
method: Method.POST,
|
||||
needToken: false,
|
||||
params,
|
||||
headers: {uuid: storage.getItem('uuid')}
|
||||
});
|
||||
}
|
||||
|
||||
export function mouseup () {
|
||||
console.log(111);
|
||||
}
|
||||
Reference in New Issue
Block a user