commit message
37
buyer/src/App.vue
Normal file
@@ -0,0 +1,37 @@
|
||||
<template>
|
||||
<div id="app">
|
||||
<router-view/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {v4 as uuidv4} from 'uuid';
|
||||
import storage from '@/plugins/storage';
|
||||
import {getLogo} from '@/api/common.js';
|
||||
export default {
|
||||
name: 'App',
|
||||
mounted () {
|
||||
let uuid = storage.getItem('uuid');
|
||||
if (!uuid) {
|
||||
uuid = uuidv4();
|
||||
storage.setItem('uuid', uuid);
|
||||
}
|
||||
if (!this.Cookies.getItem('logo')) {
|
||||
setTimeout(() => {
|
||||
getLogo().then(res => {
|
||||
if (res.success) {
|
||||
let logoObj = JSON.parse(res.result.settingValue)
|
||||
this.Cookies.setItem('logo', logoObj.buyerSideLogo)
|
||||
}
|
||||
})
|
||||
}, 1000)
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
<style lang="scss">
|
||||
#app{
|
||||
min-height: 100%;
|
||||
@include background_color($light_background_color);
|
||||
}
|
||||
</style>
|
||||
59
buyer/src/api/account.js
Normal file
@@ -0,0 +1,59 @@
|
||||
// import {
|
||||
// getRequest,
|
||||
// postRequest,
|
||||
// putRequest,
|
||||
// deleteRequest,
|
||||
// importRequest,
|
||||
// getRequestWithNoToken
|
||||
// } from '@/axios/index.js';
|
||||
import request, {Method} from '@/plugins/request.js'
|
||||
|
||||
// 获取密码状态
|
||||
export function getPwdStatus (params) {
|
||||
return request({
|
||||
url: '/buyer/members/wallet/check',
|
||||
method: Method.GET,
|
||||
needToken: true,
|
||||
params
|
||||
})
|
||||
}
|
||||
|
||||
// 设置密码
|
||||
export function setPwd (params) {
|
||||
return request({
|
||||
url: '/buyer/members/wallet/set-password',
|
||||
method: Method.POST,
|
||||
needToken: true,
|
||||
data: params
|
||||
})
|
||||
}
|
||||
|
||||
// 设置支付密码
|
||||
export function setUpdatePwdOrdinary (params) {
|
||||
return request({
|
||||
url: '/buyer/members/wallet/update-password/ordinary',
|
||||
method: Method.GET,
|
||||
needToken: true,
|
||||
data: params
|
||||
})
|
||||
}
|
||||
|
||||
// 修改会员资料
|
||||
export function editMemberInfo (params) {
|
||||
return request({
|
||||
url: '/buyer/members/editOwn',
|
||||
method: Method.PUT,
|
||||
needToken: true,
|
||||
data: params
|
||||
})
|
||||
}
|
||||
|
||||
// 修改密码
|
||||
export function editPwd (params) {
|
||||
return request({
|
||||
url: `/buyer/members/modifyPass`,
|
||||
method: Method.PUT,
|
||||
needToken: true,
|
||||
data: params
|
||||
})
|
||||
}
|
||||
60
buyer/src/api/address.js
Normal file
@@ -0,0 +1,60 @@
|
||||
import request, {
|
||||
Method, commonUrl
|
||||
} from '@/plugins/request.js';
|
||||
|
||||
// 会员收货地址列表
|
||||
export function memberAddress () {
|
||||
return request({
|
||||
url: '/buyer/memberAddress',
|
||||
needToken: true,
|
||||
method: Method.GET
|
||||
});
|
||||
}
|
||||
|
||||
// 添加收货地址
|
||||
export function newMemberAddress (params) {
|
||||
return request({
|
||||
url: '/buyer/memberAddress',
|
||||
needToken: true,
|
||||
method: Method.POST,
|
||||
data: params
|
||||
});
|
||||
}
|
||||
|
||||
// 编辑收货地址
|
||||
export function editMemberAddress (params) {
|
||||
return request({
|
||||
url: '/buyer/memberAddress',
|
||||
needToken: true,
|
||||
method: Method.PUT,
|
||||
params
|
||||
});
|
||||
}
|
||||
|
||||
// 删除收货地址
|
||||
export function delMemberAddress (id) {
|
||||
return request({
|
||||
url: `/buyer/memberAddress/delById/${id}`,
|
||||
needToken: true,
|
||||
method: Method.DELETE
|
||||
});
|
||||
}
|
||||
|
||||
// 根据id获取会员地址详情
|
||||
export function getAddrDetail (id) {
|
||||
return request({
|
||||
url: `/buyer/memberAddress/get/${id}`,
|
||||
needToken: true,
|
||||
method: Method.GET
|
||||
});
|
||||
}
|
||||
|
||||
// 传给后台citycode 获取城市街道等id
|
||||
export function handleRegion (params) {
|
||||
return request({
|
||||
url: `${commonUrl}/common/region/region`,
|
||||
needToken: true,
|
||||
method: Method.GET,
|
||||
params
|
||||
});
|
||||
}
|
||||
214
buyer/src/api/cart.js
Normal file
@@ -0,0 +1,214 @@
|
||||
import request, {
|
||||
Method
|
||||
} from '@/plugins/request.js';
|
||||
|
||||
/**
|
||||
* 清空购物车
|
||||
*/
|
||||
export function clearCart () {
|
||||
return request({
|
||||
url: '/buyer/trade/carts',
|
||||
method: Method.DELETE,
|
||||
needToken: true
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取购物车页面购物车详情
|
||||
*/
|
||||
export function cartGoodsAll () {
|
||||
return request({
|
||||
url: '/buyer/trade/carts/all',
|
||||
method: Method.GET,
|
||||
needToken: true
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取购物车商品数量
|
||||
*/
|
||||
export function cartCount () {
|
||||
return request({
|
||||
url: '/buyer/trade/carts/count',
|
||||
method: Method.GET,
|
||||
needToken: true
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取结算页面购物车详情
|
||||
*/
|
||||
export function cartGoodsPay (params) {
|
||||
return request({
|
||||
url: '/buyer/trade/carts/checked',
|
||||
method: Method.GET,
|
||||
needToken: true,
|
||||
params
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 向购物车添加一个商品
|
||||
* @param skuId skuId
|
||||
* @param num 购买数量
|
||||
*/
|
||||
export function addCartGoods (params) {
|
||||
return request({
|
||||
url: '/buyer/trade/carts',
|
||||
method: Method.POST,
|
||||
needToken: true,
|
||||
params
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建交易
|
||||
* @param client 客户端:H5/移动端 PC/PC端,WECHAT_MP/小程序端,APP/移动应用端
|
||||
* @param way 购物车购买:CART/立即购买:BUY_NOW / 积分购买:POINT
|
||||
* @param remark 备注 非必填
|
||||
*/
|
||||
export function createTrade (data) {
|
||||
return request({
|
||||
url: '/buyer/trade/carts/create/trade',
|
||||
method: Method.POST,
|
||||
needToken: true,
|
||||
headers: {'Content-Type': 'application/json'},
|
||||
data
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 选择优惠券
|
||||
* @param memberCouponId 优惠券id
|
||||
* @param way 购物车购买:CART/立即购买:BUY_NOW/ 积分购买:POINT
|
||||
* @param used 使用true 弃用 false
|
||||
*/
|
||||
export function selectCoupon (params) {
|
||||
return request({
|
||||
url: '/buyer/trade/carts/select/coupon',
|
||||
method: Method.GET,
|
||||
needToken: true,
|
||||
params
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 可用优惠券数量
|
||||
*/
|
||||
export function couponNum (params) {
|
||||
return request({
|
||||
url: '/buyer/trade/carts/coupon/num',
|
||||
method: Method.GET,
|
||||
needToken: true,
|
||||
params
|
||||
});
|
||||
}
|
||||
/**
|
||||
* 选择收货地址
|
||||
* @param shippingAddressId 地址id
|
||||
* @param way 购物车类型
|
||||
*/
|
||||
export function selectAddr (params) {
|
||||
return request({
|
||||
url: `/buyer/trade/carts/shippingAddress`,
|
||||
method: Method.GET,
|
||||
needToken: true,
|
||||
params
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 选中购物车所有商品
|
||||
* @param checked 设置选中 0,1
|
||||
*/
|
||||
export function setCheckedAll (params) {
|
||||
return request({
|
||||
url: `/buyer/trade/carts/sku/checked`,
|
||||
method: Method.POST,
|
||||
needToken: true,
|
||||
params
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量设置某商家的商品为选中或不选中
|
||||
* @param checked 是否选中
|
||||
* @param storeId 商家id
|
||||
*/
|
||||
export function setCheckedSeller (params) {
|
||||
return request({
|
||||
url: `/buyer/trade/carts/store/${params.storeId}`,
|
||||
method: Method.POST,
|
||||
needToken: true,
|
||||
params
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 选中购物车中单个产品
|
||||
* @param skuId 产品id
|
||||
* @param checked 设置选中0,1
|
||||
*/
|
||||
export function setCheckedGoods (params) {
|
||||
return request({
|
||||
url: `/buyer/trade/carts/sku/checked/${params.skuId}`,
|
||||
method: Method.POST,
|
||||
needToken: true,
|
||||
params
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新购物车中单个产品数量
|
||||
* @param skuId 产品id
|
||||
* @param num 产品数量
|
||||
*/
|
||||
export function setCartGoodsNum (params) {
|
||||
return request({
|
||||
url: `/buyer/trade/carts/sku/num/${params.skuId}`,
|
||||
method: Method.POST,
|
||||
needToken: true,
|
||||
params
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除购物车中一个或多个产品
|
||||
* @param skuIds 产品id数组
|
||||
*/
|
||||
export function delCartGoods (params) {
|
||||
return request({
|
||||
url: `/buyer/trade/carts/sku/remove`,
|
||||
method: Method.DELETE,
|
||||
needToken: true,
|
||||
params
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 选择配送方式
|
||||
* @param shippingMethod SELF_PICK_UP(自提),LOCAL_TOWN_DELIVERY(同城配送),LOGISTICS(物流)
|
||||
* @param way 购物方式
|
||||
*/
|
||||
export function shippingMethod (params) {
|
||||
return request({
|
||||
url: `/buyer/trade/carts/shippingMethod`,
|
||||
method: Method.GET,
|
||||
needToken: true,
|
||||
params
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 选择发票
|
||||
* @param receiptId 发票Id
|
||||
* @param way 购物方式
|
||||
*/
|
||||
export function receiptSelect (params) {
|
||||
return request({
|
||||
url: `/buyer/trade/carts/select/receipt`,
|
||||
method: Method.GET,
|
||||
needToken: true,
|
||||
params
|
||||
});
|
||||
}
|
||||
83
buyer/src/api/common.js
Normal file
@@ -0,0 +1,83 @@
|
||||
import request, {Method, commonUrl} from '@/plugins/request.js';
|
||||
|
||||
/**
|
||||
* 获取拼图验证
|
||||
*/
|
||||
export function getVerifyImg (verificationEnums) {
|
||||
return request({
|
||||
url: `${commonUrl}/common/slider/${verificationEnums}`,
|
||||
method: Method.GET,
|
||||
needToken: false
|
||||
});
|
||||
}
|
||||
/**
|
||||
* 验证码校验
|
||||
*/
|
||||
export function postVerifyImg (params) {
|
||||
return request({
|
||||
url: `${commonUrl}/common/slider/${params.verificationEnums}`,
|
||||
method: Method.POST,
|
||||
needToken: false,
|
||||
params
|
||||
});
|
||||
}
|
||||
/**
|
||||
* 发送短信验证码
|
||||
*/
|
||||
export function sendSms (params) {
|
||||
return request({
|
||||
url: `${commonUrl}/common/sms/${params.verificationEnums}/${params.mobile}`,
|
||||
method: Method.GET,
|
||||
needToken: false,
|
||||
params
|
||||
});
|
||||
}
|
||||
/**
|
||||
* 发送短信验证码
|
||||
*/
|
||||
export function getLogo () {
|
||||
return request({
|
||||
url: `${commonUrl}/common/logo`,
|
||||
method: Method.GET,
|
||||
needToken: false
|
||||
});
|
||||
}
|
||||
// 地区数据,用于三级联动
|
||||
export function getRegion (id) {
|
||||
return request({
|
||||
url: `${commonUrl}/common/region/item/${id}`,
|
||||
needToken: true,
|
||||
method: Method.GET
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 分页获取文章列表
|
||||
* @param cateId 文章分类id
|
||||
*/
|
||||
export function articleList (params) {
|
||||
return request({
|
||||
url: `/buyer/article`,
|
||||
method: Method.GET,
|
||||
params
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取帮助中心文章分类列表
|
||||
* @param cateId 文章分类id
|
||||
*/
|
||||
export function articleCateList () {
|
||||
return request({
|
||||
url: `/buyer/article/articleCategory/list`,
|
||||
method: Method.GET
|
||||
});
|
||||
}
|
||||
|
||||
// 通过id获取文章
|
||||
export function articleDetail (id) {
|
||||
return request({
|
||||
url: `/buyer/article/get/${id}`,
|
||||
method: Method.GET
|
||||
});
|
||||
}
|
||||
73
buyer/src/api/goods.js
Normal file
@@ -0,0 +1,73 @@
|
||||
import request, {
|
||||
Method
|
||||
} from '@/plugins/request.js';
|
||||
|
||||
// 商品列表
|
||||
export function goodsList (params) {
|
||||
return request({
|
||||
url: '/buyer/goods/es',
|
||||
method: Method.GET,
|
||||
needToken: false,
|
||||
params
|
||||
});
|
||||
}
|
||||
|
||||
// 商品分类 筛选条件 品牌, 尺寸等
|
||||
export function filterList (params) {
|
||||
return request({
|
||||
url: '/buyer/goods/es/related',
|
||||
method: Method.GET,
|
||||
needToken: false,
|
||||
params
|
||||
});
|
||||
}
|
||||
|
||||
// id获取商品详情
|
||||
export function goodsDetail (goodsId) {
|
||||
return request({
|
||||
url: `/buyer/goods/get/${goodsId}`,
|
||||
method: Method.GET,
|
||||
needToken: false
|
||||
});
|
||||
}
|
||||
|
||||
// id获取商品Sku详情
|
||||
export function goodsSkuDetail (params) {
|
||||
return request({
|
||||
url: `/buyer/goods/sku/${params.goodsId}/${params.skuId}`,
|
||||
method: Method.GET,
|
||||
needToken: false,
|
||||
params
|
||||
});
|
||||
}
|
||||
|
||||
// 获取所有商品分类
|
||||
export function getCategory (parentId) {
|
||||
return request({
|
||||
url: `/buyer/category/get/${parentId}`,
|
||||
method: Method.GET,
|
||||
needToken: false
|
||||
});
|
||||
}
|
||||
|
||||
// 当前拼团活动未成团会员
|
||||
export function pintuanMembers (pintuanId) {
|
||||
return request({
|
||||
url: `/buyer/promotion/pintuan/${pintuanId}/members`,
|
||||
method: Method.GET,
|
||||
needToken: false
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Number} start 搜索起始下标
|
||||
* @param {Number} end 搜索结束下标
|
||||
*/
|
||||
export function hotWords (params) {
|
||||
return request({
|
||||
url: `/buyer/goods/hot-words`,
|
||||
method: Method.GET,
|
||||
needToken: false,
|
||||
params
|
||||
});
|
||||
}
|
||||
35
buyer/src/api/index.js
Normal file
@@ -0,0 +1,35 @@
|
||||
import request, {Method} from '@/plugins/request.js'
|
||||
|
||||
// 获取首页楼层装修数据
|
||||
export function indexData (params) {
|
||||
return request({
|
||||
url: '/buyer/pageData/getIndex',
|
||||
method: Method.GET,
|
||||
needToken: false,
|
||||
params
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 楼层装修数据
|
||||
* @param pageClientType 客户端类型,可用值:PC,H5,WECHAT_MP,APP
|
||||
* @param pageType 页面类型,可用值:INDEX,STORE,SPECIAL
|
||||
*/
|
||||
export function pageData (params) {
|
||||
return request({
|
||||
url: `/buyer/pageData`,
|
||||
method: Method.GET,
|
||||
needToken: false,
|
||||
params
|
||||
})
|
||||
}
|
||||
/**
|
||||
* 刷新token
|
||||
*/
|
||||
export function handleRefreshToken (token) {
|
||||
return request({
|
||||
url: `/buyer/members/refresh/${token}`,
|
||||
method: Method.GET,
|
||||
needToken: false
|
||||
})
|
||||
}
|
||||
94
buyer/src/api/login.js
Normal file
@@ -0,0 +1,94 @@
|
||||
|
||||
import request, {Method, buyerUrl} from '@/plugins/request.js';
|
||||
|
||||
/**
|
||||
* 注册
|
||||
*/
|
||||
export function regist (params) {
|
||||
return request({
|
||||
url: '/buyer/members/register',
|
||||
method: Method.POST,
|
||||
needToken: false,
|
||||
data: params
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 账号密码登录
|
||||
*/
|
||||
export function login (params) {
|
||||
return request({
|
||||
url: '/buyer/members/userLogin',
|
||||
method: Method.POST,
|
||||
needToken: false,
|
||||
data: params,
|
||||
headers: { 'clientType': 'PC' }
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 手机号验证码登录
|
||||
*/
|
||||
export function smsLogin (params) {
|
||||
return request({
|
||||
url: '/buyer/members/smsLogin',
|
||||
method: Method.POST,
|
||||
needToken: false,
|
||||
data: params,
|
||||
headers: { 'clientType': 'PC' }
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取用户信息
|
||||
*/
|
||||
export function getMemberMsg (params) {
|
||||
return request({
|
||||
url: '/buyer/members',
|
||||
method: Method.GET,
|
||||
needToken: true,
|
||||
params
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 第三方登录 支付宝,微博,qq,微信
|
||||
*/
|
||||
export function webLogin (type) {
|
||||
window.open(`${buyerUrl}/buyer/connect/login/web/${type}`, 'blank');
|
||||
}
|
||||
|
||||
/**
|
||||
* 第三方登录成功 回调接口
|
||||
*/
|
||||
export function loginCallback (uuid) {
|
||||
return request({
|
||||
url: `/buyer/connect/result?state=${uuid}`,
|
||||
method: Method.GET,
|
||||
needToken: false
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 忘记密码 验证手机验证码
|
||||
*/
|
||||
export function validateCode (params) {
|
||||
return request({
|
||||
url: `/buyer/members/resetByMobile`,
|
||||
method: Method.POST,
|
||||
needToken: false,
|
||||
params
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 忘记密码 重置密码
|
||||
*/
|
||||
export function resetPassword (params) {
|
||||
return request({
|
||||
url: `/buyer/members/resetPassword`,
|
||||
method: Method.POST,
|
||||
needToken: false,
|
||||
params
|
||||
});
|
||||
}
|
||||
443
buyer/src/api/member.js
Normal file
@@ -0,0 +1,443 @@
|
||||
import request, {Method} from '@/plugins/request.js';
|
||||
|
||||
// 查询账户余额
|
||||
export function getMembersWallet () {
|
||||
return request({
|
||||
url: '/buyer/members/wallet',
|
||||
method: Method.GET,
|
||||
needToken: true
|
||||
});
|
||||
}
|
||||
|
||||
// 查询余额列表
|
||||
export function getDepositLog (params) {
|
||||
return request({
|
||||
url: '/buyer/wallet/log',
|
||||
method: Method.GET,
|
||||
needToken: true,
|
||||
params
|
||||
});
|
||||
}
|
||||
|
||||
// 查询充值记录
|
||||
export function getRecharge (params) {
|
||||
return request({
|
||||
url: '/buyer/member/recharge',
|
||||
method: Method.GET,
|
||||
needToken: true,
|
||||
params
|
||||
});
|
||||
}
|
||||
|
||||
// 查询提现记录
|
||||
export function getWithdrawApply (params) {
|
||||
return request({
|
||||
url: '/buyer/member/withdrawApply',
|
||||
method: Method.GET,
|
||||
needToken: true,
|
||||
params
|
||||
});
|
||||
}
|
||||
|
||||
// 在线充值
|
||||
export function recharge (params) {
|
||||
return request({
|
||||
url: '/buyer/trade/recharge',
|
||||
method: Method.POST,
|
||||
needToken: true,
|
||||
data: params
|
||||
});
|
||||
}
|
||||
|
||||
// 提现
|
||||
export function withdrawalApply (params) {
|
||||
return request({
|
||||
url: '/buyer/members/wallet/withdrawal',
|
||||
method: Method.POST,
|
||||
needToken: true,
|
||||
data: params
|
||||
});
|
||||
}
|
||||
|
||||
// 收藏商品、店铺
|
||||
export function collectGoods (type, id) {
|
||||
return request({
|
||||
url: `/buyer/member/collection/add/${type}/${id}`,
|
||||
method: Method.POST,
|
||||
needToken: true
|
||||
});
|
||||
}
|
||||
|
||||
// 取消 收藏商品、店铺
|
||||
export function cancelCollect (type, id) {
|
||||
return request({
|
||||
url: `/buyer/member/collection/delete/${type}/${id}`,
|
||||
method: Method.DELETE,
|
||||
needToken: true
|
||||
});
|
||||
}
|
||||
|
||||
// 查看是否收藏
|
||||
export function isCollection (type, goodsId) {
|
||||
return request({
|
||||
url: `/buyer/member/collection/isCollection/${type}/${goodsId}`,
|
||||
method: Method.GET,
|
||||
needToken: true
|
||||
});
|
||||
}
|
||||
|
||||
// 会员收藏列表
|
||||
export function collectList (params) {
|
||||
return request({
|
||||
url: `/buyer/member/collection/${params.type}`,
|
||||
method: Method.GET,
|
||||
needToken: true,
|
||||
params
|
||||
});
|
||||
}
|
||||
|
||||
// 单个商品评价
|
||||
export function goodsComment (params) {
|
||||
return request({
|
||||
url: `/buyer/memberEvaluation/${params.goodsId}/goodsEvaluation`,
|
||||
method: Method.GET,
|
||||
needToken: false,
|
||||
params
|
||||
});
|
||||
}
|
||||
|
||||
// 商品各评价类别数量
|
||||
export function goodsCommentNum (goodsId) {
|
||||
return request({
|
||||
url: `/buyer/memberEvaluation/${goodsId}/evaluationNumber`,
|
||||
method: Method.GET,
|
||||
needToken: false
|
||||
});
|
||||
}
|
||||
|
||||
// 添加会员评价
|
||||
export function addEvaluation (params) {
|
||||
return request({
|
||||
url: `/buyer/memberEvaluation`,
|
||||
method: Method.POST,
|
||||
needToken: true,
|
||||
params
|
||||
});
|
||||
}
|
||||
|
||||
// 会员评价详情
|
||||
export function evaluationDetail (id) {
|
||||
return request({
|
||||
url: `/buyer/memberEvaluation/get/${id}`,
|
||||
method: Method.GET,
|
||||
needToken: true
|
||||
});
|
||||
}
|
||||
|
||||
// 发票分页列表
|
||||
export function receiptList () {
|
||||
return request({
|
||||
url: `/buyer/trade/receipt`,
|
||||
method: Method.GET,
|
||||
needToken: true
|
||||
});
|
||||
}
|
||||
|
||||
// 保存发票信息
|
||||
export function saveReceipt (params) {
|
||||
return request({
|
||||
url: `/buyer/trade/receipt`,
|
||||
method: Method.POST,
|
||||
needToken: true,
|
||||
params
|
||||
});
|
||||
}
|
||||
|
||||
// 获取可领取优惠券列表
|
||||
export function couponList (params) {
|
||||
return request({
|
||||
url: `/buyer/promotion/coupon`,
|
||||
method: Method.GET,
|
||||
needToken: true,
|
||||
params
|
||||
});
|
||||
}
|
||||
|
||||
// 会员优惠券列表
|
||||
export function memberCouponList (params) {
|
||||
return request({
|
||||
url: `/buyer/promotion/coupon/getCoupons`,
|
||||
method: Method.GET,
|
||||
needToken: true,
|
||||
params
|
||||
});
|
||||
}
|
||||
|
||||
// 会员优惠券列表
|
||||
export function canUseCouponList (params) {
|
||||
return request({
|
||||
url: `/buyer/promotion/coupon/canUse`,
|
||||
method: Method.GET,
|
||||
needToken: true,
|
||||
params
|
||||
});
|
||||
}
|
||||
|
||||
// 领取优惠券
|
||||
export function receiveCoupon (couponId) {
|
||||
return request({
|
||||
url: `/buyer/promotion/coupon/receive/${couponId}`,
|
||||
method: Method.GET,
|
||||
needToken: true
|
||||
});
|
||||
}
|
||||
|
||||
// 获取申请售后列表
|
||||
export function afterSaleList (params) {
|
||||
return request({
|
||||
url: `/buyer/afterSale/page`,
|
||||
method: Method.GET,
|
||||
needToken: true,
|
||||
params
|
||||
});
|
||||
}
|
||||
|
||||
// 获取申请售后页面信息
|
||||
export function afterSaleInfo (sn) {
|
||||
return request({
|
||||
url: `/buyer/afterSale/applyAfterSaleInfo/${sn}`,
|
||||
method: Method.GET,
|
||||
needToken: true
|
||||
});
|
||||
}
|
||||
|
||||
// 获取申请售后、投诉原因
|
||||
export function afterSaleReason (serviceType) {
|
||||
return request({
|
||||
url: `/buyer/afterSale/get/afterSaleReason/${serviceType}`,
|
||||
method: Method.GET,
|
||||
needToken: true
|
||||
});
|
||||
}
|
||||
// 获取申请售后详情
|
||||
export function afterSaleDetail (sn) {
|
||||
return request({
|
||||
url: `/buyer/afterSale/get/${sn}`,
|
||||
method: Method.GET,
|
||||
needToken: true
|
||||
});
|
||||
}
|
||||
// 售后日志
|
||||
export function afterSaleLog (sn) {
|
||||
return request({
|
||||
url: `/buyer/afterSale/get/getAfterSaleLog/${sn}`,
|
||||
method: Method.GET,
|
||||
needToken: true
|
||||
});
|
||||
}
|
||||
|
||||
// 申请售后
|
||||
export function applyAfterSale (params) {
|
||||
return request({
|
||||
url: `/buyer/afterSale/save/${params.orderItemSn}`,
|
||||
method: Method.POST,
|
||||
needToken: true,
|
||||
params
|
||||
});
|
||||
}
|
||||
|
||||
// 取消售后申请
|
||||
export function cancelAfterSale (afterSaleSn) {
|
||||
return request({
|
||||
url: `/buyer/afterSale/cancel/${afterSaleSn}`,
|
||||
method: Method.POST,
|
||||
needToken: true
|
||||
});
|
||||
}
|
||||
|
||||
// 投诉商品
|
||||
export function handleComplain (data) {
|
||||
return request({
|
||||
url: `/buyer/complain`,
|
||||
method: Method.POST,
|
||||
needToken: true,
|
||||
data
|
||||
});
|
||||
}
|
||||
// 分页获取我的投诉列表
|
||||
export function complainList (params) {
|
||||
return request({
|
||||
url: `/buyer/complain`,
|
||||
method: Method.GET,
|
||||
needToken: true,
|
||||
params
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取投诉详情
|
||||
*/
|
||||
export function getComplainDetail (id) {
|
||||
return request({
|
||||
url: `/buyer/complain/${id}`,
|
||||
method: Method.GET,
|
||||
needToken: true
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 取消投诉
|
||||
*/
|
||||
export function clearComplain (id) {
|
||||
return request({
|
||||
url: `/buyer/complain/status/${id}`,
|
||||
method: Method.PUT,
|
||||
needToken: true
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取当前会员分销信息
|
||||
*/
|
||||
export function distribution () {
|
||||
return request({
|
||||
url: `/buyer/distribution`,
|
||||
method: Method.GET,
|
||||
needToken: true
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 申请成为分销商
|
||||
* @param idNumber 身份证号
|
||||
* @param name 名字
|
||||
*/
|
||||
export function applyDistribution (params) {
|
||||
return request({
|
||||
url: `/buyer/distribution`,
|
||||
method: Method.POST,
|
||||
needToken: true,
|
||||
params
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取分销商订单列表
|
||||
*/
|
||||
export function getDistOrderList (params) {
|
||||
return request({
|
||||
url: `/buyer/distribution/distributionOrder`,
|
||||
method: Method.GET,
|
||||
needToken: true,
|
||||
params
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取分销商商品列表
|
||||
*/
|
||||
export function getDistGoodsList (params) {
|
||||
return request({
|
||||
url: `/buyer/distributionGoods`,
|
||||
method: Method.GET,
|
||||
needToken: true,
|
||||
params
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 选择分销商品
|
||||
* @param distributionGoodsId 分销商品id
|
||||
*/
|
||||
export function selectDistGoods (distributionGoodsId) {
|
||||
return request({
|
||||
url: `/buyer/distributionGoods/checked/${distributionGoodsId}`,
|
||||
method: Method.GET,
|
||||
needToken: true
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 分销商提现历史
|
||||
*/
|
||||
export function distCashHistory (params) {
|
||||
return request({
|
||||
url: `/buyer/distribution/cash`,
|
||||
method: Method.GET,
|
||||
needToken: true,
|
||||
params
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 分销商提现
|
||||
*/
|
||||
export function distCash (params) {
|
||||
return request({
|
||||
url: `/buyer/distribution/cash`,
|
||||
method: Method.POST,
|
||||
needToken: true,
|
||||
params
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 我的足迹
|
||||
* @param {Number} pageNumber 页码
|
||||
* @param {Number} pageSize 页数
|
||||
*/
|
||||
export function tracksList (params) {
|
||||
return request({
|
||||
url: `/buyer/footprint`,
|
||||
method: Method.GET,
|
||||
needToken: true,
|
||||
params
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 清空足迹
|
||||
*/
|
||||
export function clearTracks () {
|
||||
return request({
|
||||
url: `/buyer/footprint`,
|
||||
method: Method.DELETE,
|
||||
needToken: true
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据id删除足迹
|
||||
* @param {String} ids id集合
|
||||
*/
|
||||
export function clearTracksById (ids) {
|
||||
return request({
|
||||
url: `/buyer/footprint/delByIds/${ids}`,
|
||||
method: Method.DELETE,
|
||||
needToken: true
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取会员积分
|
||||
*/
|
||||
export function memberPoint (params) {
|
||||
return request({
|
||||
url: `/buyer/member/memberPointsHistory/getMemberPointsHistoryVO`,
|
||||
method: Method.GET,
|
||||
needToken: true,
|
||||
params
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 积分历史
|
||||
*/
|
||||
export function memberPointHistory (params) {
|
||||
return request({
|
||||
url: `/buyer/member/memberPointsHistory/getByPage`,
|
||||
method: Method.GET,
|
||||
needToken: true,
|
||||
params
|
||||
});
|
||||
}
|
||||
98
buyer/src/api/order.js
Normal file
@@ -0,0 +1,98 @@
|
||||
import request, {
|
||||
Method
|
||||
} from '@/plugins/request.js';
|
||||
|
||||
// 查询会员订单列表
|
||||
export function getOrderList (params) {
|
||||
return request({
|
||||
url: `/buyer/orders`,
|
||||
method: Method.GET,
|
||||
needToken: true,
|
||||
params
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 订单明细
|
||||
* @param {orderSn} 订单编号
|
||||
*/
|
||||
export function orderDetail (orderSn) {
|
||||
return request({
|
||||
url: `/buyer/orders/${orderSn}`,
|
||||
method: Method.GET,
|
||||
needToken: true
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 取消订单
|
||||
* @param {orderSn} 订单编号
|
||||
* @param reason 取消订单原因
|
||||
*/
|
||||
export function cancelOrder (params) {
|
||||
return request({
|
||||
url: `/buyer/orders/${params.orderSn}/cancel`,
|
||||
method: Method.POST,
|
||||
needToken: true,
|
||||
params
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除订单
|
||||
* @param {orderSn} 订单编号
|
||||
*/
|
||||
export function delOrder (orderSn) {
|
||||
return request({
|
||||
url: `/buyer/orders/${orderSn}`,
|
||||
method: Method.DELETE,
|
||||
needToken: true
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 确认收货
|
||||
* @param {orderSn} 订单编号
|
||||
*/
|
||||
export function sureReceived (orderSn) {
|
||||
return request({
|
||||
url: `/buyer/orders/${orderSn}/receiving`,
|
||||
method: Method.POST,
|
||||
needToken: true
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询物流
|
||||
* @param {orderSn} 订单编号
|
||||
*/
|
||||
export function getTraces (orderSn) {
|
||||
return request({
|
||||
url: `/buyer/orders/getTraces/${orderSn}`,
|
||||
method: Method.POST,
|
||||
needToken: true
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 评价列表
|
||||
*
|
||||
*/
|
||||
export function evolutionList (params) {
|
||||
return request({
|
||||
url: `/buyer/memberEvaluation`,
|
||||
method: Method.GET,
|
||||
needToken: true,
|
||||
params
|
||||
});
|
||||
}
|
||||
|
||||
// 添加交易投诉对话
|
||||
export function communication (params) {
|
||||
return request({
|
||||
url: `/buyer/complain/communication`,
|
||||
method: Method.POST,
|
||||
needToken: true,
|
||||
params
|
||||
});
|
||||
}
|
||||
48
buyer/src/api/pay.js
Normal file
@@ -0,0 +1,48 @@
|
||||
import request, {
|
||||
Method
|
||||
} from '@/plugins/request.js';
|
||||
|
||||
/**
|
||||
* 获取支付详情
|
||||
* @param orderType 交易类型,可用值:TRADE,ORDER,RECHARGE
|
||||
* @param sn 订单编号
|
||||
* @param clientType 调起方式,PC
|
||||
*/
|
||||
export function tradeDetail (params) {
|
||||
return request({
|
||||
url: '/buyer/cashier/tradeDetail',
|
||||
needToken: true,
|
||||
method: Method.GET,
|
||||
params
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 支付
|
||||
* @param orderType 交易类型,可用值:TRADE,ORDER,RECHARGE
|
||||
* @param paymentMethod 支付方式 可用值:ALIPAY,WECHAT
|
||||
* @param payClient 调起方式 可用值:APP,NATIVE,JSAPI,H5
|
||||
* @param sn 订单编号
|
||||
*/
|
||||
export function pay (params) {
|
||||
return request({
|
||||
url: `/buyer/cashier/pay/${params.paymentMethod}/${params.paymentClient}`,
|
||||
needToken: true,
|
||||
method: Method.GET,
|
||||
params
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 支付结果查询
|
||||
* @param orderType 交易类型,可用值:TRADE,ORDER,RECHARGE
|
||||
* @param sn 订单编号
|
||||
*/
|
||||
export function payCallback (params) {
|
||||
return request({
|
||||
url: `/buyer/cashier/result`,
|
||||
needToken: true,
|
||||
method: Method.GET,
|
||||
params
|
||||
});
|
||||
}
|
||||
48
buyer/src/api/promotion.js
Normal file
@@ -0,0 +1,48 @@
|
||||
import request, {
|
||||
Method
|
||||
} from '@/plugins/request.js';
|
||||
|
||||
/**
|
||||
* 获取当天限时抢购信息
|
||||
*/
|
||||
export function seckillByDay (params) {
|
||||
return request({
|
||||
url: '/buyer/promotion/seckill',
|
||||
method: Method.GET,
|
||||
params
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取某个时刻限时抢购信息
|
||||
*/
|
||||
export function seckillByTimeline (timeline) {
|
||||
return request({
|
||||
url: `/buyer/promotion/seckill/${timeline}`,
|
||||
method: Method.GET
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取积分商品分类列表
|
||||
*/
|
||||
export function pointGoodsCategory (params) {
|
||||
return request({
|
||||
url: `/buyer/promotion/pointsGoods/category`,
|
||||
method: Method.GET,
|
||||
needToken: true,
|
||||
params
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取积分商品列表
|
||||
*/
|
||||
export function pointGoods (params) {
|
||||
return request({
|
||||
url: `/buyer/promotion/pointsGoods`,
|
||||
method: Method.GET,
|
||||
needToken: true,
|
||||
params
|
||||
});
|
||||
}
|
||||
77
buyer/src/api/shopentry.js
Normal file
@@ -0,0 +1,77 @@
|
||||
import request, {
|
||||
Method
|
||||
} from '@/plugins/request.js'
|
||||
|
||||
// 店铺分页列表
|
||||
export function shopList (params) {
|
||||
return request({
|
||||
url: '/buyer/store',
|
||||
needToken: true,
|
||||
method: Method.GET,
|
||||
params
|
||||
})
|
||||
}
|
||||
|
||||
// 申请店铺第一步-填写企业信息
|
||||
export function applyFirst (params) {
|
||||
return request({
|
||||
url: '/buyer/store/apply/first',
|
||||
needToken: true,
|
||||
method: Method.PUT,
|
||||
params
|
||||
})
|
||||
}
|
||||
|
||||
// 申请店铺第一步-填写企业信息
|
||||
export function applySecond (params) {
|
||||
return request({
|
||||
url: '/buyer/store/apply/second',
|
||||
needToken: true,
|
||||
method: Method.PUT,
|
||||
params
|
||||
})
|
||||
}
|
||||
|
||||
// 申请店铺第一步-填写企业信息
|
||||
export function applyThird (params) {
|
||||
return request({
|
||||
url: '/buyer/store/apply/third',
|
||||
needToken: true,
|
||||
method: Method.PUT,
|
||||
params
|
||||
})
|
||||
}
|
||||
|
||||
// 店铺详情
|
||||
export function getDetailById (id) {
|
||||
return request({
|
||||
url: `/buyer/store/get/detail/${id}`,
|
||||
needToken: true,
|
||||
method: Method.GET
|
||||
})
|
||||
}
|
||||
// 店铺分类
|
||||
export function getCateById (id) {
|
||||
return request({
|
||||
url: `/buyer/store/label/get/${id}`,
|
||||
needToken: true,
|
||||
method: Method.GET
|
||||
})
|
||||
}
|
||||
// 店铺入驻协议
|
||||
export function agreement () {
|
||||
return request({
|
||||
url: `/buyer/article/get/1349291301250293760`,
|
||||
needToken: true,
|
||||
method: Method.GET
|
||||
})
|
||||
}
|
||||
|
||||
// 获取当前登录会员的店铺信息
|
||||
export function applyStatus () {
|
||||
return request({
|
||||
url: `/buyer/store/apply`,
|
||||
needToken: true,
|
||||
method: Method.GET
|
||||
})
|
||||
}
|
||||
41
buyer/src/assets/iconfont/iconfont.css
Normal file
@@ -0,0 +1,41 @@
|
||||
@font-face {font-family: "iconfont";
|
||||
src: url('iconfont.eot?t=1608105836276'); /* IE9 */
|
||||
src: url('iconfont.eot?t=1608105836276#iefix') format('embedded-opentype'), /* IE6-IE8 */
|
||||
url('data:application/x-font-woff2;charset=utf-8;base64,d09GMgABAAAAAAdMAAsAAAAADPQAAAb9AAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHEIGVgCDVgqMUIodATYCJAMcCxAABCAFhG0HWRvmCsiOkUtOluX/f0k8/LOfu+9PRBKZs9KQTCTiSURCgdOJVgN9AiXs+HfTeyS0aaCioU7FjYpvyLyI1mDmsHm7OQtTozMxZGL+ZQfHUj+twfK+7V0qAyvx6fkpajywyKYfbfi8CQ1wyFtgZ1s+k3Q5ARQFiYeWeXV8IOAEdUDBvkYlAcJlgceQA6F3CDk0DegdmIhkJuMqgDf95+MfUoMASDBTIOy6tlchh+IxfHDB9P+fYYCKAGl5LjBHgRQwAtIgHkM91zBTNdI1ZNjv4OqAMgIDPkavy14Pff36g8v//4zBpRBygc1FTIMMLJe0P/+8yAKpKQN2PZsFY5D5ZMAY8UmBcRmfBIyH8kmD8WuXMLdSkKwWDzksrwIDkCRo/QQBN6JJzeJCMQhRSUSkE5tydyKRZ0V0PIpmk95u7FDKZ6zlJd/6SmB/I7K9FmqMG/2WR28ww2IL2XU+cv1Z9b1sfoYtUT1Bi9f70PakZZTdLkJWq2CR7zarFxraZdQvYnWbDLRQWdm1Xr+hf1Hl6q79kXzRYVtQBhF1OE1aLHy9r1GS0pC+nrTZhEHu5RZlJlFmx0ZJWWclVcbFXsYVvuZ93vvscaYjcYdtlg67KIMovwhE2XaXbrakrz97/nCPnzftQyOaEvc2LaOO2CP2WauX7fFnIxYi5SRtYrEAlCQ8+tlSbBWMRXZbr9vClTbeWUuApfimRQDG5b5LzBEbWEXejdUdtyl42Xa+nnPSwl9Kdm3Wm1ndm6gLeVeKTFTF4kav4RN8xZ5ktlZv2FdRWYK311gD7eMjmYR00pC3wG19hl0i3PnGxUvMGzZRIspEoVD+ZGRQGTeDfgOrewsy0FlGL6O3t4ky0CLa53L5Xkv0UWuO+VxWN+uAPe6Ejb/4YnjXdT+aWnbiwrkY85pBff4wm23gVkv5+vD087bc67Y0u2jTBTOHo4eonwNRB7YFGBd5X7IK6Y00bTCxkOlczKIVHKOR9KGLUQkMJHlae+Fxm1cXvdREmawFt7iY5Aru6opfEYWqSGm1T0eMMN14eadAON2ZqAjOCI7zI/OCMsxzc5xNwvozP29Mv+rIizGswEcalrcwQBz068w2xDjyjgIsPZFXPa+Szn88//TVufz3/xdQ6F/kM+cezuXi90ShKlIU9iJzx1FCHj+WU3k9ucGVIZyqlaE+aHJft+rTpBBpW1GDn2peUxP7R5SnhwBpWxjVjCqtWADNhm6YZyMSyq/KXQb5t/j/93dR95APPR+S7CpfhQ3E6tTbcUnDnqZ+uule5rduo4uPfFCIGhs9LbQZBqaP//17nFTitBU/bi+fDo7KCvh+3Scasz/flbcN71rIcGuMIphMJ7/4R48Dq1x0XDnlfo3iuwR2524O3JzHFDmVVu8P3J+7APNrCWoKEHAhc7PBF4lS53qiUl+tsPDpU1FhS5nvt7CUuSBcuPq2jX80Mp/j27Zy4hAYCr42pw0L7vVkYYefujAwp3ZEdR1xMsBzvt98T48Jucxdb7+MFPkLZkrFgB4YpuXI4BpQ0UuTRtRXXlRfll9oDLoDSHFDj3Mw8Fr2/Pb1QXhP+LU1azKSl0QuSc4wbrdYqYYRlzO+fg0r9wIsjwH4CH8qc2G7OLv1hj/zr2CyCMJulmQyVGMb7v7mT91dF/glg2hecea/mzNbxvO9t8mxn073ijgZjjcGxI+Xb4/jMTz8cwasxV5GqvRB72T/4ZLwk1LvnuaAloP5o8flajIuO/mQZGr6mOSQc/Pr2+94cGoKL8/c//WI+xEnaBryRi3oS212LDbM5vCGZFNmAjOsIFjVWW4NrGSnw2iLXiJ1vewAgwDmK7FnmBRgfhw7jZUCzHGnmVgxAOlgrAyTXq+bwWtRyJcW1/xfBOsWHvj9/7Rdr5rrcYTpAY5HLaSWXp3WNCpN8ZUL1lz63UHWho5UI4cGAhzhJkWxB1yVgabH5ek6qaUPAJ23DQlHgZBCCEemsfGQwZIOWYQiKIpTeXSJpyEwKO0EYNFUAhA3O4DBxQnAuLmGxLGPgMnHJ3DgFhiQhOF5SpbI0JBlQxSSYQo5Vzqaq5FpO5WSfRhpFPZSqIa3S4Y45TpFqBgyVBPnpiQme/OVik7FkDL2GDpClTpsmJKrHKLt4PKIqyna27Vc3RBtq0I2LFE9bJguNylJGbZnokzbAaQyQyhIDFM55bikRgtqyGh1UvYfhvR9fy8KKsO1kxgS0/ETFlLYuxoNrJ4rRaLkFMhKTWeqjm0pH2oElVTD0KXEleuH0OrAxUOXQruY0eLShW/USkFmmETqHCmdXEnYTZlWk1i/rmM5T0CR8Eq5YCAM4YiJHJAjIoBxMthhpEIzStNJjFFrlMOlEi3eptDLHUdpJKM10uHMiLBUCwAAAAA=') format('woff2'),
|
||||
url('iconfont.woff?t=1608105836276') format('woff'),
|
||||
url('iconfont.ttf?t=1608105836276') format('truetype'), /* chrome, firefox, opera, Safari, Android, iOS 4.2+ */
|
||||
url('iconfont.svg?t=1608105836276#iconfont') format('svg'); /* iOS 4.1- */
|
||||
}
|
||||
|
||||
.iconfont {
|
||||
font-family: "iconfont" !important;
|
||||
font-size: 16px;
|
||||
font-style: normal;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
}
|
||||
|
||||
.icon-qq:before {
|
||||
content: "\e6e6";
|
||||
}
|
||||
|
||||
.icon-weixin:before {
|
||||
content: "\e643";
|
||||
}
|
||||
|
||||
.icon-zhifubao:before {
|
||||
content: "\e601";
|
||||
}
|
||||
|
||||
.icon-kefu:before {
|
||||
content: "\e673";
|
||||
}
|
||||
|
||||
.icon-xiayibu:before {
|
||||
content: "\e600";
|
||||
}
|
||||
|
||||
.icon-weibo:before {
|
||||
content: "\eb0e";
|
||||
}
|
||||
|
||||
BIN
buyer/src/assets/iconfont/iconfont.eot
Normal file
1
buyer/src/assets/iconfont/iconfont.js
Normal file
51
buyer/src/assets/iconfont/iconfont.json
Normal file
@@ -0,0 +1,51 @@
|
||||
{
|
||||
"id": "2274088",
|
||||
"name": "lili shop",
|
||||
"font_family": "iconfont",
|
||||
"css_prefix_text": "icon-",
|
||||
"description": "",
|
||||
"glyphs": [
|
||||
{
|
||||
"icon_id": "829012",
|
||||
"name": "QQ",
|
||||
"font_class": "qq",
|
||||
"unicode": "e6e6",
|
||||
"unicode_decimal": 59110
|
||||
},
|
||||
{
|
||||
"icon_id": "2450774",
|
||||
"name": "微信",
|
||||
"font_class": "weixin",
|
||||
"unicode": "e643",
|
||||
"unicode_decimal": 58947
|
||||
},
|
||||
{
|
||||
"icon_id": "7010369",
|
||||
"name": "支付宝",
|
||||
"font_class": "zhifubao",
|
||||
"unicode": "e601",
|
||||
"unicode_decimal": 58881
|
||||
},
|
||||
{
|
||||
"icon_id": "10615183",
|
||||
"name": "服务评价-客服",
|
||||
"font_class": "kefu",
|
||||
"unicode": "e673",
|
||||
"unicode_decimal": 58995
|
||||
},
|
||||
{
|
||||
"icon_id": "13090705",
|
||||
"name": "下一步",
|
||||
"font_class": "xiayibu",
|
||||
"unicode": "e600",
|
||||
"unicode_decimal": 58880
|
||||
},
|
||||
{
|
||||
"icon_id": "14510226",
|
||||
"name": "微博",
|
||||
"font_class": "weibo",
|
||||
"unicode": "eb0e",
|
||||
"unicode_decimal": 60174
|
||||
}
|
||||
]
|
||||
}
|
||||
44
buyer/src/assets/iconfont/iconfont.svg
Normal file
@@ -0,0 +1,44 @@
|
||||
<?xml version="1.0" standalone="no"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" >
|
||||
<!--
|
||||
2013-9-30: Created.
|
||||
-->
|
||||
<svg>
|
||||
<metadata>
|
||||
Created by iconfont
|
||||
</metadata>
|
||||
<defs>
|
||||
|
||||
<font id="iconfont" horiz-adv-x="1024" >
|
||||
<font-face
|
||||
font-family="iconfont"
|
||||
font-weight="500"
|
||||
font-stretch="normal"
|
||||
units-per-em="1024"
|
||||
ascent="896"
|
||||
descent="-128"
|
||||
/>
|
||||
<missing-glyph />
|
||||
|
||||
<glyph glyph-name="qq" unicode="" d="M512 865.009172c-265.653359 0-480.988706-215.344556-480.988706-481.012242 0-265.661545 215.335347-481.006102 480.988706-481.006102s480.988706 215.344556 480.988706 481.006102C992.987682 649.664615 777.653359 865.009172 512 865.009172L512 865.009172zM776.822434 234.085642c-12.421914-11.596106-33.748638 1.032516-54.248531 29.399587-8.900717-24.019043-20.496823-46.170552-33.95637-66.051345 28.987195-10.352789 47.625694-26.504654 47.625694-44.725644 0-31.472805-55.698556-56.941873-124.443243-56.941873-40.790008 0-76.818573 8.898671-99.593276 22.776749-22.564925-13.877055-58.799174-22.776749-99.590206-22.776749-68.744687 0-124.443243 25.469068-124.443243 56.941873 0 18.014282 18.637476 34.372855 47.625694 44.725644-13.666254 19.8767-25.055652 42.033325-33.95944 66.051345-20.4958-28.15627-41.821501-40.996716-54.248531-29.399587-16.977673 15.940041-10.555403 72.262814 14.70184 125.687584 5.799076 12.215206 12.009522 23.188118 18.427698 32.716122 3.518127 155.296949 105.804744 279.9469 231.280504 279.9469l0.413416 0c125.474736 0 227.762377-124.443243 231.280504-279.9469 6.417153-9.526981 12.633738-20.500916 18.426675-32.716122C787.176247 306.348456 793.805224 250.025683 776.822434 234.085642L776.822434 234.085642zM776.822434 234.085642" horiz-adv-x="1024" />
|
||||
|
||||
|
||||
<glyph glyph-name="weixin" unicode="" d="M579.6 384.4c-11.7 0-23.4-10.8-23.4-24.2 0-10.8 11.7-21.7 23.4-21.7 17.5 0 30 10.8 30 21.7 0 13.4-12.5 24.2-30 24.2M502.8 497c18.4 0 30 11.7 30 29.2 0 18.4-11.7 29.2-30 29.2-17.5 0-34.2-10.8-34.2-29.2 0-17.5 16.7-29.2 34.2-29.2M512 896C229.2 896 0 666.8 0 384s229.2-512 512-512 512 229.2 512 512S794.8 896 512 896m-96.8-641.7c-30.9 0-53.4 5-82.6 13.3l-84.3-42.5 24.2 71.7c-59.2 41.7-94.3 94.3-94.3 158.5 0 113.5 106.8 200.2 236.9 200.2 115.1 0 217.7-68.4 237.7-165.2-8.3 1.7-15.9 2.5-22.5 2.5-113.5 0-201-85.1-201-187.7 0-17.5 2.5-33.4 6.7-50.1-6.6-0.7-14.1-0.7-20.8-0.7m347.9-81.8l16.7-60.1-63.4 35.9c-24.2-5-47.5-12.5-71.7-12.5-111.8 0-200.2 76.7-200.2 171.8s88.4 171.8 200.2 171.8c105.9 0 201-76.7 201-171.8 0-53.3-35.9-100.9-82.6-135.1M337.7 555.4c-17.5 0-35.9-10.8-35.9-29.2 0-17.5 18.4-29.2 35.9-29.2 16.7 0 30 11.7 30 29.2 0 18.4-13.4 29.2-30 29.2m372.8-171c-12.5 0-23.4-10.8-23.4-24.2 0-10.8 10.8-21.7 23.4-21.7 16.7 0 29.2 10.8 29.2 21.7 0 13.4-12.5 24.2-29.2 24.2m0 0z" horiz-adv-x="1024" />
|
||||
|
||||
|
||||
<glyph glyph-name="zhifubao" unicode="" d="M264.504 327.279c-10.624-8.55-22.01-21.032-25.317-36.9-4.5-21.68-0.94-48.815 19.975-70.103 25.338-25.806 63.842-32.869 80.473-34.083 45.176-3.267 93.326 19.136 129.619 44.687 14.224 10.038 38.583 30.19 61.866 61.279-52.18 26.94-117.314 56.74-186.946 53.824-35.57-1.487-61.044-8.863-79.67-18.704z m661.692-119.131C949.223 262.206 962 321.626 962 384c0 248.126-201.854 450-450 450S62 632.126 62 384c0-248.146 201.854-450 450-450 149.752 0 282.56 73.585 364.422 186.437-77.341 38.445-204.81 101.72-283.324 140.009-37.468-42.711-92.857-85.52-155.426-104.146-39.307-11.68-74.74-16.141-111.796-8.57-36.685 7.514-63.704 24.692-79.454 41.91-8.022 8.784-17.237 19.956-23.91 33.24a62.622 62.622 0 0 1 1.057-2.68s-3.834 6.613-6.769 17.139a75.58 75.58 0 0 0-2.936 15.946 82.193 82.193 0 0 0-0.175 11.465c-0.333 6.77-0.058 13.872 1.467 21.15 3.679 17.785 11.27 38.505 30.913 57.737 43.122 42.222 100.879 44.491 130.794 44.315 44.315-0.254 121.324-19.644 186.163-42.574 17.961 38.25 29.484 79.162 36.92 106.436H330.337v29.151h138.444V539.27H301.185v29.153H468.78v58.284c0 8.003 1.584 14.576 14.575 14.576h65.584v-72.86h182.19v-29.153H548.94v-58.304h145.74s-14.634-81.587-60.398-162c101.564-36.274 244.449-92.152 291.914-110.817z" horiz-adv-x="1024" />
|
||||
|
||||
|
||||
<glyph glyph-name="kefu" unicode="" d="M870.1 333.6v25.5c2 116.5-32.2 214.5-99.6 284-32.2 33.2-71 58.2-116 75.6-7.2 62.8-74.6 112.4-156.8 112.4-82.2 0-150.2-49.5-156.8-112.4-45-17.4-83.8-42.4-116-75.6-67.4-69.5-101.7-167-99.6-283.5v-31.2c-17.4-17.9-31.2-44.4-20.9-82.2 7.7-28.1 28.1-48.5 53.1-57.7 12.8-8.2 27.6-12.8 43.9-12.8 32.2-141 148.1-237 299.9-237 151.7 0 267.7 96 299.9 237.5 1 0 2-0.5 3.1-0.5 19.9 0 38.3 7.2 53.1 18.9 18.9 10.7 33.7 29.1 39.8 52.1 10.7 41-7.2 69.1-27.1 86.9z m-88.9-77.1c0-18.9-1.5-36.8-4.1-54.1-49.5-79.7-131.3-131.8-232.9-143-7.7 10.2-23 16.9-40.9 16.9-25.5 0-46-13.8-46-31.2 0-16.9 20.4-31.2 46-31.2 23 0 41.4 11.2 45.5 26.1 32.7 3.6 63.9 11.7 93.5 23.5 41.9 16.9 78.7 41.9 109.8 73.6 5.1 5.1 9.7 10.2 14.3 15.8-36.8-113-135.4-185.5-263.6-185.5h-1c-165 0-279.9 119-279.9 289.1l-0.5 16.3c0 7.2 1 26.6 2 45 68.5 25 130.3 120.6 155.3 164.5 23-31.2 75.6-91.4 156.3-122.6 30.1-11.7 60.8-17.9 90.9-24.5 59.8-12.8 116.5-25 154.8-75.1l1.5-1.5-1-2.1z m0 0" horiz-adv-x="1024" />
|
||||
|
||||
|
||||
<glyph glyph-name="xiayibu" unicode="" d="M1024.950857 384c0 2.706286-1.097143 5.193143-1.536 7.826286-0.585143 3.145143-0.658286 6.363429-1.901714 9.362285l-0.146286 0.365715c-1.682286 3.949714-4.388571 7.314286-7.021714 10.605714-1.024 1.316571-1.462857 2.925714-2.706286 4.096 0 0-0.146286 0-0.146286 0.146286l-241.590857 240.274285a45.714286 45.714286 0 0 1-64.365714-64.877714l162.889143-162.084571H46.665143a45.714286 45.714286 0 1 1 0-91.428572h821.76L705.536 176.201143a45.714286 45.714286 0 1 1 64.365714-64.877714l241.517715 240.274285 0.219428 0.146286c1.170286 1.243429 1.682286 2.779429 2.706286 4.096 2.633143 3.291429 5.339429 6.582857 7.021714 10.605714l0.146286 0.365715c1.243429 2.925714 1.316571 6.217143 1.901714 9.362285 0.438857 2.633143 1.462857 5.12 1.462857 7.753143V384c0 0.073143 0 0 0 0z" horiz-adv-x="1025" />
|
||||
|
||||
|
||||
<glyph glyph-name="weibo" unicode="" d="M413.422 292.65c-20.053 0-38.503-16.509-38.813-34.706-0.253-15.525 12.797-27.338 30.291-27.338 20.813-0.028 38.222 15.638 38.362 34.481 0.141 16.059-12.403 27.563-29.841 27.563zM463.316 306.487c-5.962-2.925-11.7-7.228-15.806-12.431-0.872-1.125 5.231-7.763 10.181-14.878 6.356 6.975 12.094 10.997 14.203 16.425 0.928 2.334-7.594 11.391-8.578 10.884zM589.259 385.378c-9.675 6.047-20.081 11.109-30.712 15.412-35.578 14.231-72.9 18.45-110.841 15.131-57.375-4.978-110.362-21.881-151.566-64.434-47.784-49.303-41.316-111.712 14.934-150.834 38.081-26.438 81.309-35.522 126.984-34.425 8.297 0 16.622-0.647 24.863 0.113 52.003 4.978 99.9 20.756 139.584 55.941 57.994 51.328 52.172 122.006-13.247 163.097z m-64.35-144.928c-19.744-29.925-54.703-48.094-92.672-48.291-47.869-0.309-83.784 26.578-90.141 68.4-1.406 8.55-1.013 17.944 0.928 26.325 9.647 41.034 38.053 63.956 76.725 74.306 38.194 10.125 73.716 3.516 101.503-26.831 23.006-25.116 23.934-63.394 3.656-93.909zM512.028 834C263.487 834 62 632.513 62 384s201.487-450 450-450c248.512 0 450 201.487 450 450 0 248.512-201.459 450-449.972 450z m214.594-584.353c-38.447-59.147-97.509-88.481-163.491-104.653-31.922-7.875-65.25-10.294-82.575-12.938-81.816 2.025-145.097 14.119-202.162 49.584-71.916 44.691-92.869 111.656-55.266 187.594 40.387 81.45 103.219 141.694 185.681 180.422 15.3 7.172 32.709 11.25 49.5 13.331 34.594 4.303 54.787-15.328 53.916-50.147-0.197-7.622-1.913-15.131-2.362-22.809-0.337-6.553 0.141-13.219 0.309-19.8 6.722 1.097 13.5 1.8 20.081 3.263 26.663 5.709 53.044 15.244 79.903 16.678 46.631 2.475 67.528-25.763 53.353-70.059-6.103-18.872-1.547-25.228 16.088-31.556 66.319-23.906 85.416-79.903 47.025-138.909z m-34.791 248.316c-10.969 13.95-35.859 17.184-43.734 17.269-11.644 0.084-21.037 9.619-20.925 21.234 0.084 11.588 9.506 20.897 21.037 20.897h0.169c5.147 0 51.3-1.322 76.556-33.328 10.013-12.684 20.278-35.241 12.15-70.341-2.25-9.788-10.941-16.369-20.531-16.369a19.75 19.75 0 0 0-4.725 0.591c-11.363 2.616-18.422 13.95-15.806 25.256 3.544 15.356 2.166 26.747-4.191 34.791zM815.834 429c-1.659-10.35-10.575-17.831-20.813-17.831-1.041 0-2.194 0.141-3.291 0.309-11.475 1.772-19.322 12.572-17.55 24.075 7.819 49.753-0.141 88.453-23.766 114.891-41.119 46.069-116.494 43.341-117.253 43.341-11.756-0.478-21.487 8.522-21.994 20.109-0.478 11.616 8.578 21.459 20.166 21.994 3.909 0.141 96.188 3.375 150.525-57.347 32.4-36.366 43.819-86.681 33.975-149.541z" horiz-adv-x="1024" />
|
||||
|
||||
|
||||
|
||||
|
||||
</font>
|
||||
</defs></svg>
|
||||
|
After Width: | Height: | Size: 8.3 KiB |
BIN
buyer/src/assets/iconfont/iconfont.ttf
Normal file
BIN
buyer/src/assets/iconfont/iconfont.woff
Normal file
BIN
buyer/src/assets/iconfont/iconfont.woff2
Normal file
BIN
buyer/src/assets/images/R168dc76973e0ae1cb3f6235b5a8cc0da.png
Normal file
|
After Width: | Height: | Size: 126 KiB |
BIN
buyer/src/assets/images/arrow-left.png
Normal file
|
After Width: | Height: | Size: 169 B |
BIN
buyer/src/assets/images/cart-coupon-icons02.png
Normal file
|
After Width: | Height: | Size: 2.8 KiB |
BIN
buyer/src/assets/images/empty.png
Normal file
|
After Width: | Height: | Size: 5.8 KiB |
BIN
buyer/src/assets/images/feedback.png
Normal file
|
After Width: | Height: | Size: 131 KiB |
BIN
buyer/src/assets/images/festival_icon.png
Normal file
|
After Width: | Height: | Size: 2.3 KiB |
BIN
buyer/src/assets/images/footer/ico_service.png
Normal file
|
After Width: | Height: | Size: 1019 B |
BIN
buyer/src/assets/images/geted.png
Normal file
|
After Width: | Height: | Size: 1.5 KiB |
BIN
buyer/src/assets/images/goodsDetail/price-bg.png
Normal file
|
After Width: | Height: | Size: 2.5 KiB |
BIN
buyer/src/assets/images/logo.png
Normal file
|
After Width: | Height: | Size: 138 KiB |
BIN
buyer/src/assets/images/logo1.png
Normal file
|
After Width: | Height: | Size: 302 KiB |
BIN
buyer/src/assets/images/pay-success.png
Normal file
|
After Width: | Height: | Size: 59 KiB |
BIN
buyer/src/assets/images/seckillBg.png
Normal file
|
After Width: | Height: | Size: 22 KiB |
BIN
buyer/src/assets/images/small-circle.png
Normal file
|
After Width: | Height: | Size: 117 B |
92
buyer/src/assets/styles/coupon.scss
Normal file
@@ -0,0 +1,92 @@
|
||||
.coupon-list {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
.coupon-item {
|
||||
width: 380px;
|
||||
height: 145px;
|
||||
margin-bottom: 20px;
|
||||
margin-right: 10px;
|
||||
margin-left: 10px;
|
||||
position: relative;
|
||||
border: 1px solid #eee;
|
||||
.c-left {
|
||||
width: 100%;
|
||||
padding: 20px;
|
||||
>div, > p {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
>div {
|
||||
.price{
|
||||
color: $theme_color;
|
||||
font-size: 20px;
|
||||
}
|
||||
.describe{
|
||||
background-color: #fff4ec;
|
||||
color: $theme_color;
|
||||
padding: 0 5px;
|
||||
margin-left: 10px;
|
||||
font-size: 13px;
|
||||
}
|
||||
}
|
||||
p:nth-of-type(1){
|
||||
font-weight: bold;
|
||||
}
|
||||
p:nth-of-type(2){
|
||||
color: #999;
|
||||
}
|
||||
}
|
||||
b{
|
||||
position: absolute;
|
||||
z-index: 2;
|
||||
top: 0;
|
||||
right: 50px;
|
||||
display: block;
|
||||
width: 3px;
|
||||
height: 100%;
|
||||
}
|
||||
.c-right {
|
||||
position: absolute;
|
||||
right: 0;
|
||||
top: 0;
|
||||
width: 52px;
|
||||
height: 100%;
|
||||
background-color: $theme_color;
|
||||
color: #fff;
|
||||
font-size: 16px;
|
||||
padding: 20px;
|
||||
&:hover{
|
||||
font-weight: bold;
|
||||
}
|
||||
}
|
||||
i{
|
||||
position: absolute;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
right: 42px;
|
||||
border: 1px solid #eee;
|
||||
background-color: #fff;
|
||||
border-radius: 20px;
|
||||
&:after{
|
||||
content: '';
|
||||
position: absolute;
|
||||
width: 25px;
|
||||
height: 20px;
|
||||
left: -2px;
|
||||
background-color: #fff;
|
||||
|
||||
}
|
||||
}
|
||||
i.circle-top{
|
||||
top: -10px;
|
||||
&::after{
|
||||
top: -11px;
|
||||
}
|
||||
}
|
||||
i.circle-bottom{
|
||||
bottom: -10px;
|
||||
&::after{
|
||||
bottom: -11px;
|
||||
}
|
||||
}
|
||||
}
|
||||
125
buyer/src/assets/styles/global.scss
Normal file
@@ -0,0 +1,125 @@
|
||||
/*
|
||||
* @Author: LMR
|
||||
* @Date: 2020-08-11 10:12:34
|
||||
* @Last Modified by: LMR
|
||||
* @Last Modified time: 2020-08-18 16:00:10
|
||||
*/
|
||||
|
||||
//引入主题色
|
||||
@import "./theme.scss";
|
||||
|
||||
.global_color{
|
||||
color: $theme_color;
|
||||
}
|
||||
.global_background_color{
|
||||
background-color: $theme_color;
|
||||
}
|
||||
.global_text_left {
|
||||
text-align: left;
|
||||
}
|
||||
.global_text_right {
|
||||
text-align: right;
|
||||
}
|
||||
.global_float_left {
|
||||
float: left;
|
||||
}
|
||||
.global_float_right {
|
||||
float: right;
|
||||
}
|
||||
.clearfix::after{
|
||||
content: '';
|
||||
display: block;
|
||||
clear: both;
|
||||
}
|
||||
.width_1200{width: 1200px;}
|
||||
.width_800{width: 800px;}
|
||||
.width_400{width: 400px;}
|
||||
.width_300{width: 300px;}
|
||||
.width_200{width: 200px;}
|
||||
.width_100{width: 100px;}
|
||||
|
||||
.fontsize_12{font-size: 12px;}
|
||||
.fontsize_14{font-size: 14px;}
|
||||
.fontsize_16{font-size: 16px;}
|
||||
.fontsize_18{font-size: 18px;}
|
||||
|
||||
.mb_20{margin-bottom: 20px;}
|
||||
.mt_20{margin-top: 20px;}
|
||||
.ml_20{margin-left: 20px;}
|
||||
.mr_20{margin-right: 20px;}
|
||||
|
||||
.mb_10{margin-bottom: 10px;}
|
||||
.mt_10{margin-top: 10px;}
|
||||
.ml_10{margin-left: 10px;}
|
||||
.mr_10{margin-right: 10px;}
|
||||
|
||||
.pb_20{padding-bottom: 20px;}
|
||||
.pt_20{padding-top: 20px;}
|
||||
.pl_20{padding-left: 20px;}
|
||||
.pr_20{padding-right: 20px;}
|
||||
|
||||
.pb_10{padding-bottom: 10px;}
|
||||
.pt_10{padding-top: 10px;}
|
||||
.pl_10{padding-left: 10px;}
|
||||
.pr_10{padding-right: 10px;}
|
||||
|
||||
.color999{
|
||||
color: #999;
|
||||
}
|
||||
|
||||
html,
|
||||
body {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
font-family: "Helvetica Neue",Helvetica,"PingFang SC","Hiragino Sans GB","Microsoft YaHei","微软雅黑",Arial,sans-serif;
|
||||
// overflow: hidden;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
|
||||
}
|
||||
li{
|
||||
list-style: none;
|
||||
}
|
||||
.hover-color:hover{
|
||||
color: $theme_color!important;
|
||||
cursor: pointer;
|
||||
}
|
||||
.hover-pointer{
|
||||
cursor: pointer;
|
||||
}
|
||||
.center{
|
||||
margin: 0 auto;
|
||||
}
|
||||
.relative{
|
||||
position: relative;
|
||||
}
|
||||
.ellipsis{
|
||||
overflow: hidden;
|
||||
text-overflow:ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.promotion-decorate{
|
||||
width: 200px;
|
||||
text-align: center;
|
||||
font-size: 25px;
|
||||
position: relative;
|
||||
font-weight: bold;
|
||||
margin: 30px auto 30px;
|
||||
&::before,&::after{
|
||||
content: '';
|
||||
display: inline-block;
|
||||
width: 25px;
|
||||
height: 20px;
|
||||
background-size: 50px 20px;
|
||||
background-repeat: no-repeat;
|
||||
background-position: 0 0;
|
||||
position: absolute;
|
||||
top: 10px;
|
||||
left: -3px;
|
||||
}
|
||||
&::after{
|
||||
background-position: -24px 0;
|
||||
right: -3px;
|
||||
left: auto;
|
||||
}
|
||||
}
|
||||
58
buyer/src/assets/styles/goodsList.scss
Normal file
@@ -0,0 +1,58 @@
|
||||
.text-danger {
|
||||
color: $theme_color;
|
||||
}
|
||||
.seckill-price{
|
||||
margin-right: 5px;
|
||||
font-size: 25px;
|
||||
font-weight: bold;
|
||||
}
|
||||
.goods-list {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
width: 1200px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
.goods-show-info {
|
||||
width: 235px;
|
||||
padding: 6px;
|
||||
margin: 10px 0px;
|
||||
margin-left: 5px;
|
||||
position: relative;
|
||||
border: 1px solid #fff;
|
||||
cursor: pointer;
|
||||
background-color: #fff;
|
||||
}
|
||||
.goods-show-info:hover {
|
||||
border: 1px solid #ccc;
|
||||
box-shadow: 0px 0px 15px #ccc;
|
||||
}
|
||||
.goods-show-price {
|
||||
margin-top: 6px;
|
||||
}
|
||||
.goods-show-detail {
|
||||
font-size: 12px;
|
||||
margin: 6px 0px;
|
||||
}
|
||||
.goods-show-num {
|
||||
font-size: 12px;
|
||||
margin-bottom: 6px;
|
||||
color: #666;
|
||||
}
|
||||
.goods-show-num {
|
||||
font-size: 12px;
|
||||
margin-bottom: 6px;
|
||||
color: #009688;
|
||||
}
|
||||
.goods-show-num span {
|
||||
color: #005aa0;
|
||||
font-weight: bold;
|
||||
}
|
||||
.goods-show-seller {
|
||||
font-size: 12px;
|
||||
color: $theme_color;
|
||||
}
|
||||
.goods-page {
|
||||
margin:10px auto ;
|
||||
text-align: right;
|
||||
width: 1200px;
|
||||
}
|
||||
84
buyer/src/assets/styles/theme.less
Normal file
@@ -0,0 +1,84 @@
|
||||
@import '~view-design/src/styles/index.less';
|
||||
|
||||
@primary-color: #ed3f14;
|
||||
|
||||
|
||||
@table-thead-bg : #f8f8f9;
|
||||
@table-td-stripe-bg : #f8f8f9;
|
||||
@table-td-hover-bg : #ededed;
|
||||
@table-td-highlight-bg : #ededed;
|
||||
|
||||
|
||||
|
||||
//
|
||||
//.colorPaletteMixin() {
|
||||
// @functions: ~`(function() {
|
||||
// var hueStep = 2;
|
||||
// var saturationStep = 0.16;
|
||||
// var saturationStep2 = 0.05;
|
||||
// var brightnessStep1 = 0.05;
|
||||
// var brightnessStep2 = 0.15;
|
||||
// var lightColorCount = 5;
|
||||
// var darkColorCount = 4;
|
||||
//
|
||||
// var getHue = function(hsv, i, isLight) {
|
||||
// var hue;
|
||||
// if (hsv.h >= 60 && hsv.h <= 240) {
|
||||
// hue = isLight ? hsv.h - hueStep * i : hsv.h + hueStep * i;
|
||||
// } else {
|
||||
// hue = isLight ? hsv.h + hueStep * i : hsv.h - hueStep * i;
|
||||
// }
|
||||
// if (hue < 0) {
|
||||
// hue += 360;
|
||||
// } else if (hue >= 360) {
|
||||
// hue -= 360;
|
||||
// }
|
||||
// return Math.round(hue);
|
||||
// };
|
||||
// var getSaturation = function(hsv, i, isLight) {
|
||||
// var saturation;
|
||||
// if (isLight) {
|
||||
// saturation = hsv.s - saturationStep * i;
|
||||
// } else if (i === darkColorCount) {
|
||||
// saturation = hsv.s + saturationStep;
|
||||
// } else {
|
||||
// saturation = hsv.s + saturationStep2 * i;
|
||||
// }
|
||||
// if (saturation > 1) {
|
||||
// saturation = 1;
|
||||
// }
|
||||
// if (isLight && i === lightColorCount && saturation > 0.1) {
|
||||
// saturation = 0.1;
|
||||
// }
|
||||
// if (saturation < 0.06) {
|
||||
// saturation = 0.06;
|
||||
// }
|
||||
// return Number(saturation.toFixed(2));
|
||||
// };
|
||||
// var getValue = function(hsv, i, isLight) {
|
||||
// var value;
|
||||
// if (isLight) {
|
||||
// value = hsv.v + brightnessStep1 * i;
|
||||
// }else{
|
||||
// value = hsv.v - brightnessStep2 * i
|
||||
// }
|
||||
// if (value > 1) {
|
||||
// value = 1;
|
||||
// }
|
||||
// return Number(value.toFixed(2))
|
||||
// };
|
||||
//
|
||||
// this.colorPalette = function(color, index) {
|
||||
// var isLight = index <= 6;
|
||||
// var hsv = tinycolor(color).toHsv();
|
||||
// var i = isLight ? lightColorCount + 1 - index : index - lightColorCount - 1;
|
||||
// return tinycolor({
|
||||
// h: getHue(hsv, i, isLight),
|
||||
// s: getSaturation(hsv, i, isLight),
|
||||
// v: getValue(hsv, i, isLight),
|
||||
// }).toHexString();
|
||||
// };
|
||||
//})()`;
|
||||
//}
|
||||
|
||||
//.colorPaletteMixin();
|
||||
114
buyer/src/assets/styles/theme.scss
Normal file
@@ -0,0 +1,114 @@
|
||||
/*
|
||||
* @Author: LMR
|
||||
* @Date: 2020-08-14 11:04:12
|
||||
* @Last Modified by: LMR
|
||||
* @Last Modified time: 2020-08-18 14:21:41
|
||||
*/
|
||||
|
||||
|
||||
// 主题颜色
|
||||
|
||||
// 明亮主题颜色
|
||||
$primary_color: #2d8cf0;
|
||||
$primary_light_color: #0f1011;
|
||||
$primary_dark_color: #2b85e4;
|
||||
$success_color: #19be6b;
|
||||
$warning_color: #ff9900;
|
||||
$error_color: #ed3f14;
|
||||
$handle-btn-color: #438cde;
|
||||
|
||||
$theme_color: #ed3f14;
|
||||
|
||||
$border_color: #dddee1;
|
||||
$title_color: #8c8c8c;
|
||||
$light_title_color: #1c2438;
|
||||
$light_content_color: #495060;
|
||||
$light_sub_color: #80848f;
|
||||
$light_background_color: #f8f8f9;
|
||||
$light_white_background_color :#fff;
|
||||
// 暗黑主题颜色
|
||||
$dark_background_color: #141414;
|
||||
$dark_sub_background_color: #1d1d1d; //稍微浅一点的
|
||||
$dark_content_color: #d5d5d5;
|
||||
|
||||
|
||||
|
||||
/***** 封装一些方法可用于 黑暗主题 ,明亮主题 *****/
|
||||
|
||||
|
||||
// 背景颜色
|
||||
@mixin background_color($color) {
|
||||
/*通过该函数设置字体颜色,后期方便统一管理;*/
|
||||
background-color: $color;
|
||||
transition: 0.35s;
|
||||
[data-theme="dark"] & {
|
||||
background-color: $dark_background_color;
|
||||
}
|
||||
[data-theme="light"] & {
|
||||
background-color: $light_background_color;
|
||||
}
|
||||
}
|
||||
// 辅助背景颜色
|
||||
@mixin sub_background_color($color) {
|
||||
/*通过该函数设置字体颜色,后期方便统一管理;*/
|
||||
background-color: $color;
|
||||
transition: 0.35s;
|
||||
[data-theme="dark"] & {
|
||||
background-color: $dark_sub_background_color;
|
||||
}
|
||||
[data-theme="light"] & {
|
||||
background-color: $light_background_color;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@mixin white_background_color() {
|
||||
/*通过该函数设置字体颜色,后期方便统一管理;*/
|
||||
background-color: $light_white_background_color;
|
||||
transition: 0.35s;
|
||||
[data-theme="dark"] & {
|
||||
background-color: $dark_sub_background_color;
|
||||
}
|
||||
[data-theme="light"] & {
|
||||
background-color: $light_white_background_color;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// 正文颜色
|
||||
@mixin content_color($color) {
|
||||
/*通过该函数设置字体颜色,后期方便统一管理;*/
|
||||
color: $color;
|
||||
[data-theme="dark"] & {
|
||||
color: $dark_content_color;
|
||||
}
|
||||
[data-theme="light"] & {
|
||||
color: $light_content_color;
|
||||
}
|
||||
}
|
||||
|
||||
// 辅助颜色
|
||||
@mixin sub_color($color) {
|
||||
/*通过该函数设置字体颜色,后期方便统一管理;*/
|
||||
color: $color;
|
||||
[data-theme="dark"] & {
|
||||
color: $dark_content_color;
|
||||
}
|
||||
[data-theme="light"] & {
|
||||
color: $light_sub_color;
|
||||
}
|
||||
}
|
||||
|
||||
// 标题颜色
|
||||
@mixin title_color($color) {
|
||||
/*通过该函数设置字体颜色,后期方便统一管理;*/
|
||||
color: $color;
|
||||
[data-theme="dark"] & {
|
||||
color: $dark_content_color;
|
||||
}
|
||||
[data-theme="light"] & {
|
||||
color: $light_title_color;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
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
@@ -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
@@ -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
@@ -0,0 +1,2 @@
|
||||
# 广告
|
||||
## FixedTop 顶部广告
|
||||
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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -0,0 +1,10 @@
|
||||
# 空状态封装
|
||||
|
||||
```
|
||||
// _Title
|
||||
|
||||
<empty></empty> //默认显示
|
||||
|
||||
q
|
||||
<empty _Title='暂无更多了' ></empty> //自定义返回标题
|
||||
```
|
||||
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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -0,0 +1,3 @@
|
||||
## 此组件为结算页面修改发票信息使用 后续可以复用到个人信息添加发票页面
|
||||
|
||||
### 目前没有参数,之后会设置一个参数接收历史的单位发票数据
|
||||
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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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);
|
||||
}
|
||||
48
buyer/src/config/index.js
Normal file
@@ -0,0 +1,48 @@
|
||||
export default {
|
||||
/**
|
||||
* @description 配置显示在浏览器标签的title
|
||||
*/
|
||||
title: 'Lili电商',
|
||||
/**
|
||||
* @description token在Cookie中存储的天数,默认1天
|
||||
*/
|
||||
cookieExpires: 1,
|
||||
/**
|
||||
* @description 是否使用国际化,默认为false
|
||||
* 如果不使用,则需要在路由中给需要在菜单中展示的路由设置meta: {title: 'xxx'}
|
||||
* 用来在菜单中显示文字
|
||||
*/
|
||||
useI18n: true,
|
||||
/**
|
||||
* @description api请求基础路径
|
||||
*/
|
||||
api_dev: {
|
||||
common: 'https://common-api.pickmall.cn',
|
||||
buyer: 'https://buyer-api.pickmall.cn',
|
||||
seller: 'https://store-api.pickmall.cn',
|
||||
manager: 'https://admin-api.pickmall.cn'
|
||||
// common: 'http://192.168.0.111:9000',
|
||||
// buyer: 'http://192.168.0.103:8888',
|
||||
// seller: 'https://store-api.pickmall.cn',
|
||||
// manager: 'https://admin-api.pickmall.cn'
|
||||
},
|
||||
api_prod: {
|
||||
common: 'https://common-api.pickmall.cn',
|
||||
buyer: 'https://buyer-api.pickmall.cn',
|
||||
seller: 'https://store-api.pickmall.cn',
|
||||
manager: 'https://admin-api.pickmall.cn'
|
||||
},
|
||||
/**
|
||||
* @description api请求基础路径前缀
|
||||
*/
|
||||
baseUrlPrefix: '/buyer',
|
||||
/**
|
||||
* @description 需要加载的插件
|
||||
*/
|
||||
plugin: {
|
||||
'error-store': {
|
||||
showInHeader: true, // 设为false后不会在顶部显示错误日志徽标
|
||||
developmentOff: true // 设为true后在开发环境不会收集错误信息,方便开发中排查错误
|
||||
}
|
||||
}
|
||||
};
|
||||
48
buyer/src/main.js
Normal file
@@ -0,0 +1,48 @@
|
||||
// The Vue build version to load with the `import` command
|
||||
// (runtime-only or standalone) has been set in webpack.base.conf with an alias.
|
||||
import Vue from 'vue';
|
||||
import App from './App';
|
||||
import router from './router';
|
||||
import ViewUI from 'view-design';
|
||||
import './assets/styles/theme.less';
|
||||
import './assets/iconfont/iconfont.css';
|
||||
import * as filters from './plugins/filters';
|
||||
import store from '@/vuex/store'
|
||||
import storage from '@/plugins/storage';
|
||||
// 全局引入封装组件
|
||||
import {InstallAll} from '@/components/global.js';
|
||||
|
||||
Vue.use(ViewUI);
|
||||
Vue.use(InstallAll);
|
||||
Vue.config.productionTip = false;
|
||||
|
||||
Object.keys(filters).forEach(key => {
|
||||
Vue.filter(key, filters[key]);
|
||||
});
|
||||
|
||||
router.beforeEach((to, from, next) => {
|
||||
ViewUI.LoadingBar.start();
|
||||
window.document.title = to.meta.title === undefined ? 'lili shop' : to.meta.title
|
||||
next();
|
||||
});
|
||||
|
||||
router.afterEach(route => {
|
||||
ViewUI.LoadingBar.finish();
|
||||
});
|
||||
|
||||
Vue.prototype.linkTo = function (url) {
|
||||
if (url.substr(0, 1) === '/') { // 非外部链接,没有origin,只有路由地址
|
||||
window.open(location.origin + url, '_blank');
|
||||
} else { // 外部链接,完整的url地址
|
||||
window.open(url, '_blank')
|
||||
}
|
||||
}
|
||||
Vue.prototype.Cookies = storage
|
||||
/* eslint-disable no-new */
|
||||
new Vue({
|
||||
el: '#app',
|
||||
router,
|
||||
store,
|
||||
components: { App },
|
||||
template: '<App/>'
|
||||
});
|
||||
348
buyer/src/pages/AllCategories.vue
Normal file
@@ -0,0 +1,348 @@
|
||||
<template>
|
||||
<div class="template">
|
||||
<BaseHeader></BaseHeader>
|
||||
<div class="wrapper">
|
||||
<!--面包屑-->
|
||||
<Breadcrumb class="mb_20" separator=">">
|
||||
<BreadcrumbItem to="/">首页</BreadcrumbItem>
|
||||
<BreadcrumbItem to="/allCategories">全部分类</BreadcrumbItem>
|
||||
</Breadcrumb>
|
||||
|
||||
<Tabs :animated="false">
|
||||
<TabPane class="mt_40" v-for="(item,index) in mockData" :key="index" :label="item.title">
|
||||
<!-- 分类详情-->
|
||||
<div class="cateBox">
|
||||
<div class="width_800 cateContent" ref="cateContent">
|
||||
<div v-for="(data,i) in item.data" :key="i" class="cateList mb_40">
|
||||
<div class="cateListTitle">
|
||||
<p class="mb_40">{{data.title}} </p>
|
||||
<div class="cateList">
|
||||
<div v-for="(cate,j) in data.List" :key="j" class="cateItem">{{cate.content}}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</TabPane>
|
||||
</Tabs>
|
||||
</div>
|
||||
<BaseFooter></BaseFooter>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: "AllCategories",
|
||||
data() {
|
||||
return {
|
||||
mockData: [
|
||||
{
|
||||
title: "图书、电子书",
|
||||
data: [
|
||||
{
|
||||
title: "电子书",
|
||||
List: [
|
||||
{
|
||||
content: "小说"
|
||||
},
|
||||
{
|
||||
content: "经典"
|
||||
},
|
||||
{
|
||||
content: "古装"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
title: "畅销书",
|
||||
List: [
|
||||
{
|
||||
content: "小说畅销"
|
||||
},
|
||||
{
|
||||
content: "经典畅销"
|
||||
},
|
||||
{
|
||||
content: "古装畅销"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
title: "大牌儿2",
|
||||
data: [
|
||||
{
|
||||
title: "电子书2",
|
||||
List: [
|
||||
{
|
||||
content: "小说2"
|
||||
},
|
||||
{
|
||||
content: "经典2"
|
||||
},
|
||||
{
|
||||
content: "古装2"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
title: "畅销书2",
|
||||
List: [
|
||||
{
|
||||
content: "小说畅销2"
|
||||
},
|
||||
{
|
||||
content: "经典畅销2"
|
||||
},
|
||||
{
|
||||
content: "古装畅销2"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
title: "大牌儿3",
|
||||
data: [
|
||||
{
|
||||
title: "电子书3",
|
||||
List: [
|
||||
{
|
||||
content: "小说3"
|
||||
},
|
||||
{
|
||||
content: "经典3"
|
||||
},
|
||||
{
|
||||
content: "古装3"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
title: "畅销书3",
|
||||
List: [
|
||||
{
|
||||
content: "小说畅销3"
|
||||
},
|
||||
{
|
||||
content: "经典畅销3"
|
||||
},
|
||||
{
|
||||
content: "古装畅销3"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
title: "大牌儿",
|
||||
data: [
|
||||
{
|
||||
title: "电子书",
|
||||
List: [
|
||||
{
|
||||
content: "小说"
|
||||
},
|
||||
{
|
||||
content: "经典"
|
||||
},
|
||||
{
|
||||
content: "古装"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
title: "畅销书",
|
||||
List: [
|
||||
{
|
||||
content: "小说畅销"
|
||||
},
|
||||
{
|
||||
content: "经典畅销"
|
||||
},
|
||||
{
|
||||
content: "古装畅销"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
title: "大牌儿",
|
||||
data: [
|
||||
{
|
||||
title: "电子书",
|
||||
List: [
|
||||
{
|
||||
content: "小说"
|
||||
},
|
||||
{
|
||||
content: "经典"
|
||||
},
|
||||
{
|
||||
content: "古装"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
title: "畅销书",
|
||||
List: [
|
||||
{
|
||||
content: "小说畅销"
|
||||
},
|
||||
{
|
||||
content: "经典畅销"
|
||||
},
|
||||
{
|
||||
content: "古装畅销"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
title: "大牌儿",
|
||||
data: [
|
||||
{
|
||||
title: "电子书",
|
||||
List: [
|
||||
{
|
||||
content: "小说"
|
||||
},
|
||||
{
|
||||
content: "经典"
|
||||
},
|
||||
{
|
||||
content: "古装"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
title: "畅销书",
|
||||
List: [
|
||||
{
|
||||
content: "小说畅销"
|
||||
},
|
||||
{
|
||||
content: "经典畅销"
|
||||
},
|
||||
{
|
||||
content: "古装畅销"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
};
|
||||
},
|
||||
created() {
|
||||
this.windowScroll();
|
||||
},
|
||||
methods: {
|
||||
// 获取每个tab的数据
|
||||
// filterCate(){
|
||||
|
||||
// },
|
||||
|
||||
windowScroll() {
|
||||
let cateWay = [];
|
||||
for (
|
||||
let i = 0;
|
||||
i < document.getElementsByClassName("cateTitle").length;
|
||||
i++
|
||||
) {
|
||||
let cate = document.getElementsByClassName("cateTitle")[i];
|
||||
cateWay.push(cate.offsetTop);
|
||||
}
|
||||
|
||||
console.log(cateWay);
|
||||
|
||||
window.onscroll = function() {
|
||||
var scrollTop =
|
||||
document.documentElement.scrollTop || document.body.scrollTop;
|
||||
console.log("滚动距离" + scrollTop);
|
||||
};
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.template {
|
||||
width: 100%;
|
||||
@include background_color($light_background_color);
|
||||
}
|
||||
|
||||
.wrapper {
|
||||
width: 1200px;
|
||||
padding-top: 30px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.cateContent {
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.cateBox {
|
||||
|
||||
min-height: 600px;
|
||||
}
|
||||
|
||||
.cateTitle {
|
||||
background: $theme_color;
|
||||
height: 50px;
|
||||
line-height: 50px;
|
||||
text-align: center;
|
||||
color: #fff;
|
||||
font-size: 18px;
|
||||
}
|
||||
|
||||
.cateMenuItem {
|
||||
@include title_color($light_title_color);
|
||||
padding: 8px 0;
|
||||
font-weight: 400 !important;
|
||||
}
|
||||
|
||||
.cateListTitle {
|
||||
> p {
|
||||
font-size: 14px;
|
||||
font-weight: bold;
|
||||
@include title_color($light_title_color);
|
||||
}
|
||||
}
|
||||
|
||||
.cateList {
|
||||
display: flex;
|
||||
}
|
||||
.cateItem {
|
||||
|
||||
cursor: pointer;
|
||||
display: block;
|
||||
width: 137px;
|
||||
height: 38px;
|
||||
@include background_color($light_background_color);
|
||||
@include content_color($light_title_color);
|
||||
border: 1px dashed $border_color;
|
||||
line-height: 38px;
|
||||
text-align: center;
|
||||
margin-right: -1px;
|
||||
margin-bottom: -1px;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
overflow: hidden;
|
||||
transition: all 0.2s ease-in;
|
||||
}
|
||||
.cateItem:hover{
|
||||
background: $theme_color;
|
||||
color: #fff;
|
||||
}
|
||||
.mt_40{
|
||||
margin-top: 40px;
|
||||
}
|
||||
.mb_40{
|
||||
margin-bottom: 40px;
|
||||
}
|
||||
</style>
|
||||
718
buyer/src/pages/Cart.vue
Normal file
@@ -0,0 +1,718 @@
|
||||
<template>
|
||||
<div class="cart" @click="couponAvailable = false">
|
||||
<BaseHeader></BaseHeader>
|
||||
<!-- LOGO 搜索 -->
|
||||
<div class="width_1200 logo">
|
||||
<div>
|
||||
<router-link to="/"><img :src="logoImg" alt="lili shop" title="lilishop" /></router-link>
|
||||
<div>
|
||||
购物车(<span>{{ goodsTotal }}</span>)
|
||||
</div>
|
||||
</div>
|
||||
<Search :showTag="false" :showLogo="false"></Search>
|
||||
</div>
|
||||
<Divider />
|
||||
<!-- 购物车主体 -->
|
||||
<div class="cart-content width_1200 center">
|
||||
<div class="available-area">
|
||||
<div class="cart-steps">
|
||||
<span :class="stepIndex == 0 ? 'active' : ''">1.我的购物车</span>
|
||||
<Icon :class="stepIndex == 0 ? 'active-arrow' : ''" custom="iconfont icon-xiayibu"></Icon>
|
||||
<span :class="stepIndex == 1 ? 'active' : ''">2.填写订单信息</span>
|
||||
<Icon :class="stepIndex == 1 ? 'active-arrow' : ''" custom="iconfont icon-xiayibu"></Icon>
|
||||
<span :class="stepIndex == 2 ? 'active' : ''">3.成功提交订单</span>
|
||||
</div>
|
||||
</div>
|
||||
<!-- 购物车商品列表 -->
|
||||
<div class="cart-goods">
|
||||
<div class="cart-goods-title">
|
||||
<div class="width_60">
|
||||
<Checkbox v-model="allChecked" @on-change="changeChecked(allChecked, 'all')">全选</Checkbox>
|
||||
</div>
|
||||
<div class="goods-title">商品</div>
|
||||
<div class="width_150">单价(元)</div>
|
||||
<div class="width_100">数量</div>
|
||||
<div class="width_150">小计</div>
|
||||
<div class="width_100">操作</div>
|
||||
</div>
|
||||
<div v-if="cartList.length === 0" class="cart-empty">
|
||||
<p>购物车空空如也</p>
|
||||
<router-link to="/">去选购></router-link>
|
||||
</div>
|
||||
<div v-else class="cart-goods-items" v-for="(shop, index) in cartList" :key="index">
|
||||
<div class="shop-name">
|
||||
<div>
|
||||
<Checkbox v-model="shop.checked" @on-change="changeChecked(shop.checked, 'shop', shop.storeId)"></Checkbox>
|
||||
<span class="go-shop-page" @click="goShopPage(shop.storeId)">{{shop.storeName}}</span>
|
||||
<Icon class="customer-service" custom="iconfont icon-kefu" />
|
||||
</div>
|
||||
<span class="shop-coupon" v-if="shop.couponList.length" :class="couponAvailable === index ? 'shop-coupon-show' : ''" @click.stop="showCoupon(shop.id, index)">
|
||||
<!-- 优惠券模态框 -->
|
||||
<div v-if="couponAvailable === index">
|
||||
<div class="coupon-item" v-for="(item, index) in shop.couponList" :key="index">
|
||||
<span v-if="item.couponType === 'PRICE'">¥{{ item.price }}</span>
|
||||
<span v-if="item.couponType === 'DISCOUNT'">{{ item.discount }}折</span>
|
||||
<span>满{{item.consumeThreshold}}元可用</span>
|
||||
<Button class="coupon-btn" size="small" type="primary" @click="receiveShopCoupon(item)" :disabled="item.disabled">{{ item.disabled ? "已领取" : "领取" }}</Button>
|
||||
</div>
|
||||
</div>
|
||||
</span>
|
||||
<div class="promotion-notice">{{shop.promotionNotice}}</div>
|
||||
</div>
|
||||
<template v-for="(goods, goodsIndex) in shop.skuList">
|
||||
<div class="goods-item" :key="goodsIndex">
|
||||
<div class="width_60">
|
||||
<Checkbox v-model="goods.checked" @on-change="changeChecked(goods.checked, 'goods', goods.goodsSku.id)"></Checkbox>
|
||||
</div>
|
||||
<div class="goods-title" @click="goGoodsDetail(goods.goodsSku.id, goods.goodsSku.goodsId)">
|
||||
<img :src="
|
||||
goods.goodsSku.thumbnail || '../assets/images/goodsDetail/item-detail-1.jpg'
|
||||
" />
|
||||
<div>
|
||||
<p>{{ goods.goodsSku.goodsName }}</p>
|
||||
<template v-for="(promotion, promotionIndex) in goods.promotions">
|
||||
<div class="promotion" :key="promotionIndex" v-if="promotion.promotionType === 'SECKILL'">
|
||||
<span>秒杀</span>
|
||||
<promotion :time="promotion.endTime" type="cart"></promotion>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
<div class="width_150">
|
||||
{{ goods.goodsSku.price | unitPrice("¥") }}
|
||||
</div>
|
||||
<div class="width_100">
|
||||
<InputNumber :min="1" size="small" v-model="goods.num" @on-change="changeNum(goods.num, goods.goodsSku.id)"></InputNumber>
|
||||
<div class="fontsize_12">{{goods.goodsSku.quantity > 0 ? '有货' : '无货'}}</div>
|
||||
</div>
|
||||
<div class="width_150">
|
||||
{{ goods.num * goods.goodsSku.price | unitPrice("¥") }}
|
||||
</div>
|
||||
<div class="width_100">
|
||||
<span class="handle-btn" v-if="!goods.errorMessage" @click="delGoods(goods.goodsSku.id)">删除</span>
|
||||
<span class="handle-btn" v-if="!goods.errorMessage" @click="collectGoods(goods.goodsSku.id)">收藏</span>
|
||||
</div>
|
||||
<div class="error-goods" v-if="goods.errorMessage">
|
||||
<div>{{goods.errorMessage}}</div>
|
||||
<Button type="primary" @click="delGoods(goods.goodsSku.id)">删除</Button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</template>
|
||||
</div>
|
||||
<!-- 底部支付栏 -->
|
||||
<div class="cart-goods-footer">
|
||||
<div>
|
||||
<div class="width_60">
|
||||
<Checkbox v-model="allChecked" @on-change="changeChecked(allChecked, 'all')">全选</Checkbox>
|
||||
</div>
|
||||
<div class="width_100 handle-btn" @click="delGoods">删除选中商品</div>
|
||||
<!-- <div class="width_100 handle-btn" @click="collectGoods">移到我的收藏</div> -->
|
||||
<div class="width_100 handle-btn" @click="clearCart">清空购物车</div>
|
||||
</div>
|
||||
<div>
|
||||
<div class="selected-count">
|
||||
已选择<span>{{ checkedNum }}</span>件商品
|
||||
</div>
|
||||
<div class="ml_20 save-price">
|
||||
已节省<span>{{ priceDetailDTO.discountPrice | unitPrice("¥") }}</span>
|
||||
</div>
|
||||
<div class="ml_20 total-price">
|
||||
总价(不含运费):<span>{{ priceDetailDTO.billPrice | unitPrice("¥") }}</span>
|
||||
</div>
|
||||
<div class="pay ml_20" @click="pay">去支付</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<Spin size="large" fix v-if="loading"></Spin>
|
||||
</div>
|
||||
<!-- 猜你喜欢 -->
|
||||
<!-- <div class="like">
|
||||
<div class="likeGoods">
|
||||
<ShowLikeGoods />
|
||||
</div>
|
||||
</div> -->
|
||||
<BaseFooter></BaseFooter>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import Promotion from '@/components/goodsDetail/Promotion'
|
||||
import Search from '@/components/Search';
|
||||
import ShowLikeGoods from '@/components/like';
|
||||
import * as APICart from '@/api/cart';
|
||||
import * as APIMember from '@/api/member';
|
||||
import {getLogo} from '@/api/common.js'
|
||||
export default {
|
||||
name: 'Cart',
|
||||
beforeRouteEnter (to, from, next) {
|
||||
window.scrollTo(0, 0);
|
||||
next();
|
||||
},
|
||||
components: {
|
||||
Search,
|
||||
ShowLikeGoods,
|
||||
Promotion
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
logoImg: '',
|
||||
couponAvailable: false,
|
||||
stepIndex: 0, // 当前处于哪一步,购物车==0,填写订单信息==1,成功提交订单==2
|
||||
goodsTotal: 1,
|
||||
checkedNum: 0,
|
||||
allChecked: false,
|
||||
loading: false,
|
||||
city: '珠海',
|
||||
cityArr: [
|
||||
['北京', '上海', '天津', '重庆', '广州'],
|
||||
['深圳', '河南', '辽宁', '吉林', '江苏'],
|
||||
['江西', '四川', '海南', '贵州', '云南'],
|
||||
['西藏', '陕西', '甘肃', '青海', '珠海']
|
||||
],
|
||||
cartList: [],
|
||||
couponList: [
|
||||
{
|
||||
name: '优惠券',
|
||||
price: '10',
|
||||
activity: '满99减10',
|
||||
useRange: '全品类使用',
|
||||
disabled: true
|
||||
},
|
||||
{
|
||||
name: '优惠券',
|
||||
price: '10',
|
||||
activity: '满99减10',
|
||||
useRange: '全品类使用',
|
||||
disabled: false
|
||||
},
|
||||
{
|
||||
name: '优惠券',
|
||||
price: '10',
|
||||
activity: '满99减10',
|
||||
useRange: '全品类使用',
|
||||
disabled: false
|
||||
}
|
||||
],
|
||||
priceDetailDTO: {},
|
||||
skuList: []
|
||||
};
|
||||
},
|
||||
computed: {},
|
||||
methods: {
|
||||
// 选择配送区域
|
||||
changeCity (city) {
|
||||
this.city = city;
|
||||
},
|
||||
// 跳转商品详情
|
||||
goGoodsDetail (skuId, goodsId) {
|
||||
let routeUrl = this.$router.resolve({
|
||||
path: '/goodsDetail',
|
||||
query: { skuId, goodsId }
|
||||
});
|
||||
window.open(routeUrl.href, '_blank');
|
||||
},
|
||||
// 跳转店铺首页
|
||||
goShopPage (id) {
|
||||
let routeUrl = this.$router.resolve({
|
||||
path: '/Merchant',
|
||||
query: { id }
|
||||
});
|
||||
window.open(routeUrl.href, '_blank');
|
||||
},
|
||||
// 收藏商品
|
||||
collectGoods (id) {
|
||||
this.$Modal.confirm({
|
||||
title: '收藏',
|
||||
content: '<p>商品收藏后可在个人中心我的收藏查看</p>',
|
||||
onOk: () => {
|
||||
APIMember.collectGoods('GOODS', id).then((res) => {
|
||||
if (res.success) {
|
||||
this.$Message.success('收藏商品成功');
|
||||
this.getCartList();
|
||||
}
|
||||
});
|
||||
},
|
||||
onCancel: () => { }
|
||||
});
|
||||
},
|
||||
// 删除商品
|
||||
delGoods (id) {
|
||||
const idArr = [];
|
||||
if (!id) {
|
||||
const list = this.cartList;
|
||||
list.forEach((shop) => {
|
||||
shop.skuList.forEach((goods) => {
|
||||
idArr.push(goods.goodsSku.id);
|
||||
});
|
||||
});
|
||||
} else {
|
||||
idArr.push(id);
|
||||
}
|
||||
this.$Modal.confirm({
|
||||
title: '删除',
|
||||
content: '<p>确定要删除该商品吗?</p>',
|
||||
onOk: () => {
|
||||
APICart.delCartGoods({ skuIds: idArr.toString() }).then((res) => {
|
||||
if (res.code === 200) {
|
||||
this.$Message.success('删除成功');
|
||||
this.getCartList();
|
||||
} else {
|
||||
this.$Message.error(res.message);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
},
|
||||
clearCart () { // 清空购物车
|
||||
this.$Modal.confirm({
|
||||
title: '提示',
|
||||
content: '<p>确定要清空购物车吗?清空后不可恢复</p>',
|
||||
onOk: () => {
|
||||
APICart.clearCart().then((res) => {
|
||||
if (res.code === 200) {
|
||||
this.$Message.success('清空购物车成功');
|
||||
this.getCartList();
|
||||
} else {
|
||||
this.$Message.error(res.message);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
},
|
||||
// 跳转支付页面
|
||||
pay () {
|
||||
if (this.checkedNum) {
|
||||
this.$router.push({ path: '/pay', query: { way: 'CART' } });
|
||||
} else {
|
||||
this.$Message.warning('请至少选择一件商品');
|
||||
}
|
||||
},
|
||||
// 展示优惠券
|
||||
showCoupon (storeId, index) {
|
||||
this.couponAvailable = index;
|
||||
},
|
||||
changeNum (val, id) {
|
||||
// 设置购买数量
|
||||
console.log(val, id);
|
||||
APICart.setCartGoodsNum({ skuId: id, num: val }).then((res) => {
|
||||
console.log(res);
|
||||
if (res.code === 200) {
|
||||
this.getCartList();
|
||||
}
|
||||
});
|
||||
},
|
||||
async changeChecked (status, type, id) {
|
||||
// 设置商品选中状态
|
||||
const check = status ? 1 : 0;
|
||||
if (type === 'all') {
|
||||
// 全选
|
||||
await APICart.setCheckedAll({ checked: check });
|
||||
} else if (type === 'shop') {
|
||||
// 选中店铺所有商品
|
||||
await APICart.setCheckedSeller({ checked: check, storeId: id });
|
||||
} else {
|
||||
// 单个商品
|
||||
await APICart.setCheckedGoods({ checked: check, skuId: id });
|
||||
}
|
||||
|
||||
this.getCartList();
|
||||
},
|
||||
|
||||
async receiveShopCoupon (item) { // 领取优惠券
|
||||
let res = await APIMember.receiveCoupon(item.id)
|
||||
if (res.code === 200) {
|
||||
this.$set(item, 'disabled', true)
|
||||
this.$Message.success('领取成功')
|
||||
} else {
|
||||
this.$Message.error(res.message)
|
||||
}
|
||||
},
|
||||
async getCartList () {
|
||||
// 购物车列表
|
||||
this.loading = true;
|
||||
try {
|
||||
let res = await APICart.cartGoodsAll();
|
||||
this.loading = false;
|
||||
if (res.code === 200) {
|
||||
this.cartList = res.result.cartList;
|
||||
this.priceDetailDTO = res.result.priceDetailDTO;
|
||||
this.skuList = res.result.skuList;
|
||||
this.checkedNum = 0;
|
||||
let allChecked = true;
|
||||
for (let k = 0; k < this.cartList.length; k++) {
|
||||
let shop = this.cartList[k]
|
||||
let list = await APIMember.couponList({storeId: shop.storeId})
|
||||
shop.couponList.push(...list.result.records)
|
||||
}
|
||||
for (let i = 0; i < this.skuList.length; i++) {
|
||||
if (this.skuList[i].checked) {
|
||||
this.checkedNum += this.skuList[i].num;
|
||||
} else {
|
||||
allChecked = false;
|
||||
}
|
||||
}
|
||||
this.$forceUpdate()
|
||||
this.allChecked = allChecked;
|
||||
}
|
||||
} catch (error) {
|
||||
this.loading = false;
|
||||
}
|
||||
}
|
||||
},
|
||||
mounted () {
|
||||
this.getCartList();
|
||||
APICart.cartCount().then(res => { // 购物车商品数量
|
||||
if (res.success) this.goodsTotal = res.result;
|
||||
});
|
||||
if (!this.Cookies.getItem('logo')) {
|
||||
getLogo().then(res => {
|
||||
if (res.success) {
|
||||
let logoObj = JSON.parse(res.result.settingValue)
|
||||
this.Cookies.setItem('logo', logoObj.buyerSideLogo)
|
||||
}
|
||||
})
|
||||
} else {
|
||||
this.logoImg = this.Cookies.getItem('logo')
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
/** logo 搜索 start **/
|
||||
.logo {
|
||||
height: 40px;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin: 20px auto 0;
|
||||
div:nth-child(1) {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
img {
|
||||
width: 150px;
|
||||
height: auto;
|
||||
cursor: pointer;
|
||||
}
|
||||
div:nth-child(2) {
|
||||
width: 200px;
|
||||
color: #999;
|
||||
font-size: 16px;
|
||||
margin: 0 20px;
|
||||
span {
|
||||
color: $theme_color;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.cart-content {
|
||||
margin: 0 auto;
|
||||
width: 1200px;
|
||||
position: relative;
|
||||
}
|
||||
/** logo end */
|
||||
/** step步骤条 */
|
||||
.cart-steps {
|
||||
height: 30px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-bottom: 15px;
|
||||
span {
|
||||
@include content_color($light_content_color);
|
||||
height: 30px;
|
||||
text-align: center;
|
||||
line-height: 30px;
|
||||
display: inline-block;
|
||||
padding: 0 15px;
|
||||
}
|
||||
|
||||
.ivu-icon {
|
||||
@include content_color($light_content_color);
|
||||
font-size: 20px;
|
||||
margin: 0 15px;
|
||||
}
|
||||
|
||||
.active {
|
||||
border-radius: 50px;
|
||||
background-color: #ff8f23;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.active-arrow {
|
||||
color: #ff8f23;
|
||||
}
|
||||
}
|
||||
/** 步骤条和配送区域总体 */
|
||||
.available-area {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
.city {
|
||||
padding: 10px 15px;
|
||||
}
|
||||
.city-item {
|
||||
font-weight: bold;
|
||||
cursor: pointer;
|
||||
padding: 5px;
|
||||
}
|
||||
.city-item:hover {
|
||||
color: $theme_color;
|
||||
}
|
||||
/** 商品列表 */
|
||||
.cart-goods {
|
||||
&-title {
|
||||
height: 50px;
|
||||
@include background_color($light_white_background_color);
|
||||
@include title_color($title_color);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 0 20px;
|
||||
div {
|
||||
text-align: center;
|
||||
}
|
||||
.goods-title {
|
||||
flex: 1;
|
||||
}
|
||||
}
|
||||
.cart-empty {
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
height: 300px;
|
||||
padding-top: 100px;
|
||||
}
|
||||
&-items {
|
||||
.shop-name {
|
||||
height: 50px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 0 20px;
|
||||
position: relative;
|
||||
@include title_color($light_title_color);
|
||||
> * {
|
||||
width: 50%;
|
||||
}
|
||||
.go-shop-page:hover {
|
||||
color: $theme_color;
|
||||
cursor: pointer;
|
||||
}
|
||||
.customer-service {
|
||||
margin-left: 5px;
|
||||
color: #fcc217;
|
||||
cursor: pointer;
|
||||
&:hover {
|
||||
color: $theme_color;
|
||||
}
|
||||
}
|
||||
/** 优惠券 */
|
||||
.shop-coupon {
|
||||
width: 80px;
|
||||
height: 24px;
|
||||
position: relative;
|
||||
background: url(../assets/images/cart-coupon-icons02.png) 0 0 no-repeat;
|
||||
> div {
|
||||
position: absolute;
|
||||
top: 35px;
|
||||
left: 0;
|
||||
width: 300px;
|
||||
height: 300px;
|
||||
background-color: #fff;
|
||||
border: 1px solid $theme_color;
|
||||
// border-radius: 3px;
|
||||
z-index: 1;
|
||||
padding: 10px 20px;
|
||||
&::before {
|
||||
content: "";
|
||||
display: block;
|
||||
background: url(../assets/images/cart-coupon-icons02.png) 0 -58px no-repeat;
|
||||
width: 80px;
|
||||
height: 12px;
|
||||
position: absolute;
|
||||
top: -12px;
|
||||
left: 0;
|
||||
}
|
||||
.coupon-item {
|
||||
margin-bottom: 10px;
|
||||
span:nth-child(1) {
|
||||
border: 1px solid #e33937;
|
||||
display: inline-block;
|
||||
padding: 3px 10px;
|
||||
color: $theme_color;
|
||||
border-radius: 3px;
|
||||
}
|
||||
span:nth-child(2) {
|
||||
font-size: 12px;
|
||||
margin-left: 5px;
|
||||
color: #999;
|
||||
}
|
||||
.coupon-btn {
|
||||
height: 26px;
|
||||
float: right;
|
||||
font-size: 12px;
|
||||
}
|
||||
&::after {
|
||||
display: block;
|
||||
content: "";
|
||||
clear: right;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.promotion-notice {
|
||||
text-align: right;
|
||||
font-size: 12px;
|
||||
}
|
||||
.shop-coupon-show {
|
||||
background-position-y: -34px;
|
||||
}
|
||||
}
|
||||
.goods-item {
|
||||
position: relative;
|
||||
@extend .cart-goods-title;
|
||||
@include background_color($light_white_background_color);
|
||||
padding: 10px 20px;
|
||||
height: auto;
|
||||
> div:nth-child(1) {
|
||||
padding-left: 15px;
|
||||
width: 30px;
|
||||
}
|
||||
> div:nth-child(2) {
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
box-sizing: border-box;
|
||||
padding-left: 20px;
|
||||
position: relative;
|
||||
img {
|
||||
width: 70px;
|
||||
height: 70px;
|
||||
}
|
||||
>div>p {
|
||||
@include content_color($light_content_color);
|
||||
font-size: 13px;
|
||||
text-align: left;
|
||||
margin-left: 10px;
|
||||
&:hover {
|
||||
color: $theme_color;
|
||||
}
|
||||
}
|
||||
}
|
||||
> div:nth-child(5) {
|
||||
font-weight: bold;
|
||||
}
|
||||
.num-input {
|
||||
width: 60px;
|
||||
border: 1px solid #999;
|
||||
border-radius: 5px;
|
||||
padding: 0 5px;
|
||||
&:focus {
|
||||
outline-color: $theme_color;
|
||||
}
|
||||
}
|
||||
}
|
||||
.error-goods{
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
margin-left: -20px;
|
||||
background-color: rgba($color: #999, $alpha: .5);
|
||||
z-index: 10;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding-left: 150px;
|
||||
color: #000;
|
||||
padding-right: 30px;
|
||||
}
|
||||
}
|
||||
&-footer {
|
||||
@extend .cart-goods-title;
|
||||
position: sticky;
|
||||
bottom: 0;
|
||||
border-top: 1px solid #ddd;
|
||||
margin-top: 10px;
|
||||
padding: 0 0 0 20px;
|
||||
line-height: 50px;
|
||||
justify-content: space-between;
|
||||
> div {
|
||||
display: flex;
|
||||
}
|
||||
.selected-count {
|
||||
span {
|
||||
color: $theme_color;
|
||||
}
|
||||
}
|
||||
|
||||
.save-price span {
|
||||
color: #000;
|
||||
}
|
||||
.total-price span {
|
||||
color: $theme_color;
|
||||
font-size: 20px;
|
||||
}
|
||||
.pay {
|
||||
background-color: $theme_color;
|
||||
width: 150px;
|
||||
font-size: 20px;
|
||||
color: #fff;
|
||||
height: 100%;
|
||||
line-height: 50px;
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
.handle-btn {
|
||||
font-size: 12px;
|
||||
color: $handle-btn-color;
|
||||
cursor: pointer;
|
||||
&:hover {
|
||||
color: $theme_color;
|
||||
}
|
||||
}
|
||||
}
|
||||
.like {
|
||||
width: 1200px;
|
||||
margin: 10px auto;
|
||||
// padding: 20px 0;
|
||||
@include white_background_color();
|
||||
}
|
||||
.likeGoods,
|
||||
.shop-nav-container {
|
||||
width: 1200px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
.ivu-divider {
|
||||
background: $theme_color;
|
||||
height: 2px;
|
||||
}
|
||||
.width_150 {
|
||||
width: 150px;
|
||||
}
|
||||
.width_60 {
|
||||
width: 60px;
|
||||
}
|
||||
.promotion {
|
||||
display: flex;
|
||||
margin-top: 5px;
|
||||
margin-left: 5px;
|
||||
>span{
|
||||
border: 1px solid $theme_color;
|
||||
color: $theme_color;
|
||||
font-size: 12px;
|
||||
border-radius: 2px;
|
||||
padding: 0 2px;
|
||||
}
|
||||
>p{
|
||||
font-size: 12px;
|
||||
margin-left: 10px;
|
||||
color: #999;
|
||||
}
|
||||
}
|
||||
|
||||
</style>
|
||||
<style>
|
||||
.ivu-input-number-input {
|
||||
text-align: center;
|
||||
}
|
||||
</style>
|
||||
89
buyer/src/pages/Feedback.vue
Normal file
@@ -0,0 +1,89 @@
|
||||
<template>
|
||||
<div>
|
||||
<div class="feedback-container">
|
||||
<div class="feedback-img-box">
|
||||
<img src="../assets/images/feedback.png" />
|
||||
</div>
|
||||
<div class="feedback-box-border">
|
||||
<div class="feedback-box">
|
||||
<div class="feedback-title">
|
||||
<h1>意见反馈</h1>
|
||||
<h2>感谢你的反馈,我们会积极改善,做出更好的服务的</h2>
|
||||
</div>
|
||||
<div class="feedback-content">
|
||||
<div class="feedback-form">
|
||||
<Form :model="formItem" :label-width="80">
|
||||
<FormItem label="标题">
|
||||
<i-input v-model="formItem.title" placeholder="请输入标题"></i-input>
|
||||
</FormItem>
|
||||
<FormItem label="反馈信息">
|
||||
<i-input
|
||||
v-model="formItem.content"
|
||||
type="textarea"
|
||||
:autosize="{minRows: 8,maxRows: 10}"
|
||||
placeholder="请输入反馈信息"
|
||||
></i-input>
|
||||
</FormItem>
|
||||
<FormItem>
|
||||
<Button type="primary">提交</Button>
|
||||
<Button type="ghost">清空信息</Button>
|
||||
</FormItem>
|
||||
</Form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: "Feedback",
|
||||
data() {
|
||||
return {
|
||||
formItem: {
|
||||
title: "",
|
||||
content: "",
|
||||
},
|
||||
};
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.feedback-container {
|
||||
margin: 15px auto;
|
||||
width: 80%;
|
||||
height: 600px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
/* background-color: #ccc; */
|
||||
}
|
||||
.feedback-img-box {
|
||||
width: 50%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
.feedback-img-box img {
|
||||
width: 80%;
|
||||
}
|
||||
.feedback-box-border {
|
||||
width: 50%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
.feedback-box {
|
||||
width: 480px;
|
||||
}
|
||||
.feedback-content {
|
||||
margin: 15px auto;
|
||||
border: 1px #ccc dotted;
|
||||
}
|
||||
.feedback-form {
|
||||
margin: 30px auto;
|
||||
width: 90%;
|
||||
}
|
||||
</style>
|
||||
170
buyer/src/pages/GoodsDetail.vue
Normal file
@@ -0,0 +1,170 @@
|
||||
<template>
|
||||
<div style="background:#fff;">
|
||||
<BaseHeader></BaseHeader>
|
||||
<Search></Search>
|
||||
<drawer></drawer>
|
||||
<ShopHeader v-if="goodsMsg.data" :detail="goodsMsg.data"></ShopHeader>
|
||||
<div class="shop-item-path">
|
||||
<div class="shop-nav-container">
|
||||
<Breadcrumb>
|
||||
<BreadcrumbItem to="/">首页</BreadcrumbItem>
|
||||
<BreadcrumbItem v-for="(item, index) in categoryBar" :to="goGoodsList(index)" target="_blank" :key="index">{{item.name}}</BreadcrumbItem>
|
||||
</Breadcrumb>
|
||||
<div class="store-collect">
|
||||
<span class="mr_10"><router-link :to="'Merchant?id='+goodsMsg.data.storeId">{{goodsMsg.data.storeName}}</router-link></span>
|
||||
<span @click="collect" ><Icon type="ios-heart" :color="storeCollected ? '#ed3f14' : '#666'" />{{storeCollected?'已收藏店铺':'收藏店铺'}}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- 商品信息展示 -->
|
||||
<ShowGoods v-if="goodsMsg.data" :detail="goodsMsg"></ShowGoods>
|
||||
<!-- 商品详细展示 -->
|
||||
<ShowGoodsDetail v-if="goodsMsg.data" :detail="goodsMsg"></ShowGoodsDetail>
|
||||
|
||||
<!-- 猜你喜欢-->
|
||||
<!-- <div class="like">
|
||||
<div class="likeGoods">
|
||||
<ShowLikeGoods/>
|
||||
</div>
|
||||
</div> -->
|
||||
<Spin size="large" fix v-if="isLoading"></Spin>
|
||||
<BaseFooter></BaseFooter>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import Search from '@/components/Search';
|
||||
import ShopHeader from '@/components/header/ShopHeader';
|
||||
import ShowGoods from '@/components/goodsDetail/ShowGoods';
|
||||
import ShowGoodsDetail from '@/components/goodsDetail/ShowGoodsDetail';
|
||||
import ShowLikeGoods from '@/components/like';
|
||||
import { goodsSkuDetail } from '@/api/goods';
|
||||
import { cancelCollect, collectGoods, isCollection } from '@/api/member';
|
||||
export default {
|
||||
name: 'GoodsDetail',
|
||||
beforeRouteEnter (to, from, next) {
|
||||
window.scrollTo(0, 0);
|
||||
next();
|
||||
},
|
||||
created () {
|
||||
this.getGoodsDetail();
|
||||
if (this.Cookies.getItem('userInfo')) {
|
||||
isCollection('STORE', this.goodsMsg.data.storeId).then(res => {
|
||||
if (res.success && res.result) {
|
||||
this.storeCollected = true;
|
||||
}
|
||||
})
|
||||
}
|
||||
},
|
||||
mounted () {
|
||||
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
tagsColor: ['blue', 'green', 'red', 'yellow'],
|
||||
goodsMsg: {},
|
||||
isLoading: false,
|
||||
categoryBar: [],
|
||||
storeCollected: false
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
getGoodsDetail () {
|
||||
this.isLoading = true;
|
||||
const params = this.$route.query
|
||||
goodsSkuDetail(params).then((res) => {
|
||||
this.isLoading = false;
|
||||
if (res.code === 200) {
|
||||
const result = res.result;
|
||||
const cateName = res.result.categoryName;
|
||||
const cateId = result.data.categoryPath.split(',');
|
||||
const cateArr = [];
|
||||
cateId.forEach((e, index) => { // 插入分类id和name
|
||||
cateArr.push({
|
||||
id: e,
|
||||
name: cateName[index]
|
||||
});
|
||||
});
|
||||
this.categoryBar = cateArr;
|
||||
this.goodsMsg = res.result;
|
||||
} else {
|
||||
this.$Message.error(res.message)
|
||||
this.$router.push('/')
|
||||
}
|
||||
}).catch(() => {
|
||||
this.$router.push('/')
|
||||
});
|
||||
},
|
||||
goGoodsList (currIndex) {
|
||||
const arr = []
|
||||
this.categoryBar.forEach((e, index) => {
|
||||
if (index <= currIndex) {
|
||||
arr.push(e.id)
|
||||
}
|
||||
})
|
||||
return location.origin + '/goodsList?categoryId=' + arr.toString()
|
||||
},
|
||||
async collect () { // 收藏店铺
|
||||
if (this.storeCollected) {
|
||||
let cancel = await cancelCollect('STORE', this.goodsMsg.data.storeId)
|
||||
if (cancel.success) {
|
||||
this.$Message.success('已取消收藏')
|
||||
this.storeCollected = false;
|
||||
}
|
||||
} else {
|
||||
let collect = await collectGoods('STORE', this.goodsMsg.data.storeId);
|
||||
if (collect.code === 200) {
|
||||
this.storeCollected = true;
|
||||
this.$Message.success('收藏店铺成功,可以前往个人中心我的收藏查看');
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
'$route.query.skuId': function (val) {
|
||||
location.reload();
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
},
|
||||
components: {
|
||||
Search,
|
||||
ShopHeader,
|
||||
ShowGoods,
|
||||
ShowGoodsDetail,
|
||||
ShowLikeGoods
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.shop-item-path {
|
||||
height: 38px;
|
||||
@include background_color($light_background_color);
|
||||
line-height: 38px;
|
||||
color: #2c2c2c;
|
||||
}
|
||||
|
||||
.like {
|
||||
width: 100%;
|
||||
padding: 20px 0;
|
||||
@include white_background_color();
|
||||
}
|
||||
.shop-nav-container {
|
||||
width: 1200px;
|
||||
margin: 0 auto;
|
||||
position: relative;
|
||||
.store-collect {
|
||||
position: absolute;
|
||||
right: 20px;
|
||||
top: 0;
|
||||
color: #999;
|
||||
span{
|
||||
&:hover{
|
||||
cursor: pointer;
|
||||
color: $theme_color;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
339
buyer/src/pages/GoodsList.vue
Normal file
@@ -0,0 +1,339 @@
|
||||
<template>
|
||||
<div>
|
||||
<BaseHeader></BaseHeader>
|
||||
<Search @search="handleSearch"></Search>
|
||||
<drawer></drawer>
|
||||
<cateNav></cateNav>
|
||||
<div class="container">
|
||||
<!-- 商品筛选栏 -->
|
||||
<GoodsClassNav @getParams="getParams"></GoodsClassNav>
|
||||
|
||||
<!-- 商品展示容器 -->
|
||||
<div class="goods-box">
|
||||
<!-- 商品列表 -->
|
||||
<div class="goods-list-box">
|
||||
<!-- 排序 -->
|
||||
<div class="goods-list-tool">
|
||||
<ul>
|
||||
<li
|
||||
v-for="(item, index) in goodsTool"
|
||||
:key="index"
|
||||
@click="orderBy(item.en, index)"
|
||||
>
|
||||
<span :class="{ 'goods-list-tool-active': index === sortIndex }"
|
||||
>{{ item.title }}<Icon type="ios-arrow-round-down"
|
||||
/></span>
|
||||
</li>
|
||||
<li @click="orderBy('price', 5, 'up')" class="price-sort">
|
||||
<span :class="{ 'goods-list-tool-active': 5 === sortIndex }">
|
||||
价格
|
||||
<div>
|
||||
<Icon
|
||||
type="md-arrow-dropup"
|
||||
:class="{ 'price-color': sortPriceIndex == 'desc' }"
|
||||
/>
|
||||
<Icon
|
||||
type="md-arrow-dropdown"
|
||||
:class="{ 'price-color': sortPriceIndex == 'asc' }"
|
||||
/>
|
||||
</div>
|
||||
</span>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<!-- 列表 -->
|
||||
<div class="goods-list">
|
||||
<empty v-if="goodsList.length === 0" />
|
||||
<div
|
||||
v-else
|
||||
class="goods-show-info"
|
||||
v-for="(item, index) in goodsList"
|
||||
:key="index"
|
||||
@click="goGoodsDetail(item.id, item.goodsId)"
|
||||
>
|
||||
<div class="goods-show-img">
|
||||
<img width="220" height="220" :src="item.thumbnail" />
|
||||
</div>
|
||||
<div class="goods-show-price">
|
||||
<span>
|
||||
<span class="seckill-price text-danger">{{
|
||||
item.price | unitPrice("¥")
|
||||
}}</span>
|
||||
</span>
|
||||
</div>
|
||||
<div class="goods-show-detail">
|
||||
<span>{{ item.goodsName }}</span>
|
||||
</div>
|
||||
<div class="goods-show-num">
|
||||
已有<span>{{ item.commentNum || 0 }}</span
|
||||
>人评价
|
||||
</div>
|
||||
<div class="goods-show-seller">
|
||||
<span>{{ item.storeName }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="goods-page">
|
||||
<Page
|
||||
show-sizer
|
||||
@on-change="changePageNum"
|
||||
@on-page-size-change="changePageSize"
|
||||
:total="total"
|
||||
:page-size="params.pageSize"
|
||||
></Page>
|
||||
</div>
|
||||
</div>
|
||||
<Spin size="large" fix v-if="loading"></Spin>
|
||||
<BaseFooter></BaseFooter>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import GoodsClassNav from '@/components/nav/GoodsClassNav';
|
||||
import * as apiGoods from '@/api/goods';
|
||||
export default {
|
||||
name: 'GoodsList',
|
||||
beforeRouteEnter (to, from, next) {
|
||||
window.scrollTo(0, 0);
|
||||
next();
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
sortIndex: 0,
|
||||
sortPriceIndex: false, // 判断价格升序还是降序
|
||||
goodsTool: [
|
||||
{ title: '综合', en: '' },
|
||||
{ title: '销量', en: 'buyCount' },
|
||||
{ title: '评论数', en: 'commentNum' },
|
||||
{ title: '新品', en: 'releaseTime' }
|
||||
],
|
||||
goodsList: [],
|
||||
loading: false,
|
||||
total: 0,
|
||||
params: {
|
||||
pageNumber: 0,
|
||||
pageSize: 20,
|
||||
categoryId: ''
|
||||
}
|
||||
};
|
||||
},
|
||||
watch: {
|
||||
$route () {
|
||||
const keyword = this.$route.query.keyword
|
||||
this.handleSearch(keyword)
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
handleSearch (key) {
|
||||
this.params.keyword = key
|
||||
this.params.pageNumber = 0
|
||||
this.getGoodsList()
|
||||
},
|
||||
orderBy (data, index) {
|
||||
// 排序
|
||||
this.sortIndex = index;
|
||||
this.params.sort = data;
|
||||
this.params.order = 'desc';
|
||||
if (data === 'price') {
|
||||
if (!this.sortPriceIndex) {
|
||||
this.sortPriceIndex = 'asc';
|
||||
} else {
|
||||
this.sortPriceIndex === 'desc' ? (this.sortPriceIndex = 'asc') : (this.sortPriceIndex = 'desc');
|
||||
}
|
||||
this.params.order = this.sortPriceIndex
|
||||
} else {
|
||||
this.sortPriceIndex = false
|
||||
}
|
||||
this.getGoodsList();
|
||||
},
|
||||
goGoodsDetail (skuId, goodsId) {
|
||||
// 跳转商品详情
|
||||
let routeUrl = this.$router.resolve({
|
||||
path: '/goodsDetail',
|
||||
query: { skuId, goodsId }
|
||||
});
|
||||
window.open(routeUrl.href, '_blank');
|
||||
},
|
||||
changePageNum (val) {
|
||||
this.params.pageNumber = val - 1;
|
||||
this.getGoodsList();
|
||||
},
|
||||
changePageSize (val) {
|
||||
this.params.pageNumber = 0;
|
||||
this.params.pageSize = val;
|
||||
this.getGoodsList();
|
||||
},
|
||||
getGoodsList () {
|
||||
this.loading = true;
|
||||
apiGoods.goodsList(this.params)
|
||||
.then((res) => {
|
||||
this.loading = false;
|
||||
if (res.code === 200) {
|
||||
this.goodsList = res.result.content;
|
||||
this.total = res.result.totalElements;
|
||||
}
|
||||
}).catch(() => {
|
||||
this.loading = false;
|
||||
});
|
||||
},
|
||||
getParams (val) {
|
||||
// 筛选条件回显
|
||||
Object.assign(this.params, val)
|
||||
this.getGoodsList()
|
||||
}
|
||||
},
|
||||
created () {
|
||||
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.getGoodsList()
|
||||
},
|
||||
mounted () {},
|
||||
components: {
|
||||
GoodsClassNav
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
@import '../assets/styles/goodsList.scss';
|
||||
.container {
|
||||
margin: 15px auto;
|
||||
width: 1200px;
|
||||
min-width: 1000px;
|
||||
position: relative;
|
||||
}
|
||||
.goods-box {
|
||||
display: flex;
|
||||
}
|
||||
/* ---------------侧边广告栏开始------------------- */
|
||||
.as-box {
|
||||
width: 200px;
|
||||
border: 1px solid #ccc;
|
||||
}
|
||||
.item-as-title {
|
||||
width: 100%;
|
||||
height: 36px;
|
||||
color: $theme_color;
|
||||
line-height: 36px;
|
||||
font-size: 18px;
|
||||
}
|
||||
.item-as-title span:first-child {
|
||||
margin-left: 20px;
|
||||
}
|
||||
.item-as-title span:last-child {
|
||||
float: right;
|
||||
margin-right: 15px;
|
||||
font-size: 10px;
|
||||
color: #ccc;
|
||||
}
|
||||
.item-as {
|
||||
width: 160px;
|
||||
margin: 18px auto;
|
||||
}
|
||||
.item-as-img {
|
||||
width: 160px;
|
||||
height: 160px;
|
||||
margin: 0px auto;
|
||||
}
|
||||
.item-as-price span {
|
||||
font-size: 18px;
|
||||
}
|
||||
.item-as-intro {
|
||||
margin-top: 5px;
|
||||
font-size: 12px;
|
||||
}
|
||||
.item-as-selled {
|
||||
margin-top: 5px;
|
||||
font-size: 12px;
|
||||
}
|
||||
.item-as-selled span {
|
||||
color: #005aa0;
|
||||
}
|
||||
/* ---------------侧边广告栏结束------------------- */
|
||||
|
||||
/* ---------------商品栏开始------------------- */
|
||||
.goods-list-box {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
// margin-left: 15px;
|
||||
// width: calc(100% - 215px);
|
||||
}
|
||||
.goods-list-tool {
|
||||
width: 100%;
|
||||
height: 38px;
|
||||
border: 1px solid #ccc;
|
||||
background-color: #f1f1f1;
|
||||
}
|
||||
.goods-list-tool ul {
|
||||
padding-left: 15px;
|
||||
font-size: 12px;
|
||||
margin-top: 10px;
|
||||
&::after {
|
||||
content: "";
|
||||
display: block;
|
||||
clear: left;
|
||||
}
|
||||
.price-sort {
|
||||
span {
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
width: 50px;
|
||||
height: 22px;
|
||||
position: relative;
|
||||
line-height: 15px;
|
||||
top: -2px;
|
||||
left: 0;
|
||||
}
|
||||
span > div {
|
||||
display: inline-block;
|
||||
.ivu-icon {
|
||||
font-size: 12px;
|
||||
position: absolute;
|
||||
&:nth-child(1) {
|
||||
top: 1px;
|
||||
}
|
||||
&:nth-child(2) {
|
||||
top: 7px;
|
||||
}
|
||||
}
|
||||
.price-color {
|
||||
color: #b3b3b3;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.goods-list-tool li {
|
||||
cursor: pointer;
|
||||
float: left;
|
||||
}
|
||||
.goods-list-tool span {
|
||||
padding: 3px 5px;
|
||||
border: 1px solid #ccc;
|
||||
margin-left: -1px;
|
||||
background-color: #fff;
|
||||
}
|
||||
.goods-list-tool span:hover {
|
||||
border-color: $theme_color;
|
||||
position: relative;
|
||||
text-decoration: none;
|
||||
z-index: 1;
|
||||
}
|
||||
.goods-list-tool .ivu-icon {
|
||||
font-weight: bold;
|
||||
font-size: 16px;
|
||||
}
|
||||
.goods-list-tool-active {
|
||||
color: #fff;
|
||||
border-left: 1px solid #ccc;
|
||||
background-color: $theme_color !important;
|
||||
}
|
||||
|
||||
/* ---------------商品栏结束------------------- */
|
||||
</style>
|
||||
134
buyer/src/pages/Index.vue
Normal file
@@ -0,0 +1,134 @@
|
||||
<template>
|
||||
<div class="container">
|
||||
<drawer></drawer>
|
||||
<!-- 固定头部 -->
|
||||
<hover-search class="hover-search" :class="{show: topSearchShow}"></hover-search>
|
||||
|
||||
<!-- 顶部广告 -->
|
||||
<FixedTopPage :data="topAdvert"></FixedTopPage>
|
||||
<!-- 头部 包括登录,我的订单等 -->
|
||||
<BaseHeader></BaseHeader>
|
||||
<!-- 搜索框、logo -->
|
||||
<Search></Search>
|
||||
<!-- 商品分类 -->
|
||||
<cateNav :showAlways="true" v-if="showNav"></cateNav>
|
||||
<!-- 楼层装修部分 -->
|
||||
<model-form ref="modelForm" :data="modelForm"></model-form>
|
||||
<!-- 底部栏 -->
|
||||
<BaseFooter></BaseFooter>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import Search from '@/components/Search';
|
||||
import ModelForm from '@/components/indexDecorate/modelForm';
|
||||
import HoverSearch from '@/components/header/hoverSearch';
|
||||
import storage from '@/plugins/storage';
|
||||
import { indexData } from '@/api/index.js';
|
||||
export default {
|
||||
name: 'Index',
|
||||
mounted () {
|
||||
this.getIndexData();
|
||||
let that = this;
|
||||
window.onscroll = function () {
|
||||
let top = document.documentElement.scrollTop || document.body.scrollTop;
|
||||
if (top > 300) {
|
||||
that.topSearchShow = true;
|
||||
} else {
|
||||
that.topSearchShow = false;
|
||||
}
|
||||
};
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
modelForm: { list: [] }, // 楼层装修数据
|
||||
topAdvert: {}, // 顶部广告
|
||||
showNav: false, // 是否展示分类栏
|
||||
topSearchShow: false // 滚动后顶部搜索栏展示
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
getIndexData () {
|
||||
// 获取首页装修数据
|
||||
indexData({ clientType: 'PC' }).then((res) => {
|
||||
if (res.success) {
|
||||
let dataJson = JSON.parse(res.result.pageData);
|
||||
this.modelForm = dataJson;
|
||||
storage.setItem('navList', dataJson.list[1])
|
||||
this.showNav = true
|
||||
this.topAdvert = dataJson.list[0];
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
components: {
|
||||
Search,
|
||||
ModelForm,
|
||||
HoverSearch
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.container {
|
||||
@include sub_background_color($light_background_color);
|
||||
}
|
||||
/** 商品分类 */
|
||||
.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 {
|
||||
width: 50px;
|
||||
font-size: 16px;
|
||||
font-weight: bold;
|
||||
margin-left: 15px;
|
||||
color: rgb(89, 88, 88);
|
||||
font-size: 15px;
|
||||
&:hover {
|
||||
color: $theme_color;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
<style>
|
||||
.hover-search {
|
||||
width: 100%;
|
||||
height: 60px;
|
||||
transform: translateY(-200px);
|
||||
background-color: #fff;
|
||||
position: fixed;
|
||||
top: 0;
|
||||
z-index: 3000;
|
||||
box-shadow:0 0 10px 2px rgb(90 90 90 / 60%);
|
||||
transition: 0.35s;
|
||||
}
|
||||
.show {
|
||||
transform: translateY(0);
|
||||
-webkit-transform: translateZ(0);
|
||||
-moz-transform: translateZ(0);
|
||||
-ms-transform: translateZ(0);
|
||||
-o-transform: translateZ(0);
|
||||
transform: translateZ(0);
|
||||
top: 0;
|
||||
}
|
||||
</style>
|
||||
484
buyer/src/pages/Login.vue
Normal file
@@ -0,0 +1,484 @@
|
||||
<template>
|
||||
<div class="login" @keyup.enter="handleSubmit('formInline')">
|
||||
<!-- 顶部logo -->
|
||||
<div class="top-content">
|
||||
<div class="logo-box">
|
||||
<img
|
||||
:src="logoImg"
|
||||
@click="$router.push('/')"
|
||||
/>
|
||||
<div>欢迎登录</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- 登录主体 包含轮播图 登录模块 -->
|
||||
<div class="login-container">
|
||||
<!-- 轮播 -->
|
||||
<Carousel loop :autoplay-speed="5000" class="login-carousel" arrow="never">
|
||||
<CarouselItem>
|
||||
<div class="demo-carousel">
|
||||
<img
|
||||
src="https://wanmi-b2b.oss-cn-shanghai.aliyuncs.com/201811141632252680"
|
||||
/>
|
||||
</div>
|
||||
</CarouselItem>
|
||||
</Carousel>
|
||||
<!-- 登录模块 -->
|
||||
<div class="form-box">
|
||||
<div class="account-number">
|
||||
<div class="tab-switch">
|
||||
<span>{{type?'账号登录':'验证码登录'}}</span>
|
||||
<span @click="type = !type">{{type?'验证码登录':'账号登录'}}</span>
|
||||
</div>
|
||||
<div @click="$router.push('signUp')">立即注册</div>
|
||||
</div>
|
||||
<!-- 账号密码登录 -->
|
||||
<Form
|
||||
ref="formInline"
|
||||
:model="formData"
|
||||
:rules="ruleInline"
|
||||
v-show="type === true"
|
||||
>
|
||||
<FormItem prop="username">
|
||||
<i-input
|
||||
type="text"
|
||||
v-model="formData.username"
|
||||
clearable
|
||||
placeholder="用户名"
|
||||
>
|
||||
<Icon type="md-person" slot="prepend"></Icon>
|
||||
</i-input>
|
||||
</FormItem>
|
||||
<FormItem prop="password">
|
||||
<i-input
|
||||
type="password"
|
||||
v-model="formData.password"
|
||||
clearable
|
||||
placeholder="密码"
|
||||
>
|
||||
<Icon type="md-lock" slot="prepend"> </Icon>
|
||||
</i-input>
|
||||
</FormItem>
|
||||
<FormItem>
|
||||
<Button
|
||||
type="error"
|
||||
@click.stop="handleSubmit('formInline')"
|
||||
long
|
||||
>登录</Button>
|
||||
</FormItem>
|
||||
</Form>
|
||||
<!-- 验证码登录 -->
|
||||
<Form
|
||||
ref="formSms"
|
||||
:model="formSms"
|
||||
:rules="ruleInline"
|
||||
v-show="type === false"
|
||||
>
|
||||
<FormItem prop="mobile">
|
||||
<i-input
|
||||
type="text"
|
||||
v-model="formSms.mobile"
|
||||
clearable
|
||||
placeholder="手机号"
|
||||
>
|
||||
<Icon type="md-lock" slot="prepend"></Icon>
|
||||
</i-input>
|
||||
</FormItem>
|
||||
<FormItem prop="code">
|
||||
<i-input
|
||||
type="text"
|
||||
v-model="formSms.code"
|
||||
placeholder="手机验证码"
|
||||
>
|
||||
<Icon
|
||||
type="ios-text-outline"
|
||||
style="font-weight: bold"
|
||||
slot="prepend"
|
||||
/>
|
||||
<Button slot="append" @click="sendCode">{{ codeMsg }}</Button>
|
||||
</i-input>
|
||||
</FormItem>
|
||||
<FormItem>
|
||||
<Button @click.stop="verifyBtnClick" long :type="verifyStatus?'success':'default'">{{verifyStatus?'验证通过':'点击完成安全验证'}}</Button>
|
||||
</FormItem>
|
||||
<FormItem>
|
||||
<Button
|
||||
type="error"
|
||||
@click="handleSubmit('formSms')"
|
||||
long
|
||||
>登录</Button>
|
||||
</FormItem>
|
||||
</Form>
|
||||
<div class="regist">
|
||||
<span @click="$router.push('forgetPassword')">忘记密码</span>
|
||||
</div>
|
||||
<div class="other-login">
|
||||
<Icon custom="iconfont icon-qq" color="" class="icon-hover" @click="handleWebLogin('QQ')"/>
|
||||
<Icon custom="iconfont icon-weixin" color="" class="icon-hover" @click="handleWebLogin('WECHAT_PC')"/>
|
||||
<!-- <Icon custom="iconfont icon-zhifubao" color="" class="icon-hover" @click="handleWebLogin('ALIPAY')"/> -->
|
||||
<!-- <Icon custom="iconfont icon-weibo" color="" class="icon-hover" @click="handleWebLogin('WEIBO')"/> -->
|
||||
</div>
|
||||
</div>
|
||||
<!-- 拼图验证码 -->
|
||||
<verify
|
||||
ref="verify"
|
||||
class="verify-con"
|
||||
verifyType="LOGIN"
|
||||
@change="verifyChange"
|
||||
></verify>
|
||||
</div>
|
||||
<div class="foot">
|
||||
<Row type="flex" justify="space-around" class="help">
|
||||
<router-link to="/article" class="item" target="_blank">帮助</router-link>
|
||||
<router-link to="/article?id=1371779927900160000" class="item" target="_blank">隐私</router-link>
|
||||
<router-link to="/article?id=1371992704333905920" class="item" target="_blank">条款</router-link>
|
||||
</Row>
|
||||
<Row type="flex" justify="center" class="copyright">
|
||||
Copyright © 2021 - Present
|
||||
<a href="https://pickmall.cn" target="_blank" style="margin: 0 5px">lili-shop</a>
|
||||
版权所有
|
||||
</Row>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import * as RegExp from '@/plugins/RegExp.js';
|
||||
import { md5 } from '@/plugins/md5.js';
|
||||
import * as apiLogin from '@/api/login.js';
|
||||
import { sendSms } from '@/api/common.js';
|
||||
import { webLogin, loginCallback } from '@/api/login.js';
|
||||
import storage from '@/plugins/storage.js';
|
||||
import verify from '@/components/verify';
|
||||
|
||||
export default {
|
||||
name: 'Login',
|
||||
components: {
|
||||
verify
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
type: true, // true 账号登录 false 验证码登录
|
||||
formData: {
|
||||
// 登录表单
|
||||
username: '',
|
||||
password: ''
|
||||
},
|
||||
formSms: {
|
||||
code: '',
|
||||
mobile: ''
|
||||
},
|
||||
verifyStatus: false,
|
||||
ruleInline: {
|
||||
// 验证规则
|
||||
username: [{ required: true, message: '请输入用户名' }],
|
||||
password: [
|
||||
{ required: true, message: '请输入密码' },
|
||||
{ type: 'string', min: 6, message: '密码不能少于6位' }
|
||||
],
|
||||
mobile: [
|
||||
{ required: true, message: '请输入手机号码' },
|
||||
{
|
||||
pattern: RegExp.mobile,
|
||||
message: '请输入正确的手机号'
|
||||
}
|
||||
],
|
||||
code: [{ required: true, message: '请输入手机验证码' }]
|
||||
},
|
||||
codeMsg: '发送验证码',
|
||||
interval: '',
|
||||
time: 60,
|
||||
logoImg: ''
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
// 登录
|
||||
handleSubmit (name) {
|
||||
this.$refs[name].validate((valid) => {
|
||||
if (valid) {
|
||||
if (this.type) {
|
||||
this.$refs.verify.show = true;
|
||||
} else {
|
||||
let data = JSON.parse(JSON.stringify(this.formSms));
|
||||
apiLogin.smsLogin(data).then((res) => {
|
||||
this.$refs.verify.show = false;
|
||||
if (res.code === 200) {
|
||||
this.$Message.success('登录成功');
|
||||
storage.setItem('accessToken', res.result.accessToken);
|
||||
storage.setItem('refreshToken', res.result.refreshToken);
|
||||
apiLogin.getMemberMsg().then((res) => {
|
||||
if (res.code === 200) {
|
||||
storage.setItem('userInfo', res.result);
|
||||
let query = this.$route.query;
|
||||
if (query.rePath) {
|
||||
this.$router.push({path: query.rePath, query: JSON.parse(query.query)});
|
||||
} else {
|
||||
this.$router.push('/');
|
||||
}
|
||||
}
|
||||
});
|
||||
} else {
|
||||
this.$Message.error(res.message);
|
||||
}
|
||||
});
|
||||
}
|
||||
} else {
|
||||
// this.$Message.error('请填写正确的用户名或密码');
|
||||
}
|
||||
});
|
||||
},
|
||||
sendCode () {
|
||||
if (this.time === 60) {
|
||||
if (this.formSms.mobile === '') {
|
||||
this.$Message.warning('请先填写手机号');
|
||||
return;
|
||||
}
|
||||
if (!this.verifyStatus) {
|
||||
this.$Message.warning('请先完成安全验证');
|
||||
return;
|
||||
}
|
||||
let params = {
|
||||
mobile: this.formSms.mobile,
|
||||
verificationEnums: 'LOGIN'
|
||||
};
|
||||
sendSms(params).then(res => {
|
||||
if (res.code === 200) {
|
||||
this.$Message.success('验证码发送成功');
|
||||
let that = this;
|
||||
this.interval = setInterval(() => {
|
||||
that.time--;
|
||||
if (that.time === 0) {
|
||||
that.time = 60;
|
||||
that.codeMsg = '重新发送';
|
||||
that.verifyStatus = false;
|
||||
clearInterval(that.interval);
|
||||
} else {
|
||||
that.codeMsg = that.time;
|
||||
}
|
||||
}, 1000);
|
||||
} else {
|
||||
this.$Message.warning(res.message);
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
verifyChange (con) { // 拼图验证码回显
|
||||
if (!con.status) return;
|
||||
|
||||
if (this.type === true) { // 账号密码登录
|
||||
let data = JSON.parse(JSON.stringify(this.formData));
|
||||
data.password = md5(data.password);
|
||||
this.$refs.verify.show = false;
|
||||
this.$Spin.show();
|
||||
apiLogin.login(data).then((res) => {
|
||||
if (res.code === 200) {
|
||||
this.$Message.success('登录成功');
|
||||
storage.setItem('accessToken', res.result.accessToken);
|
||||
storage.setItem('refreshToken', res.result.refreshToken);
|
||||
apiLogin.getMemberMsg().then((res) => {
|
||||
this.$Spin.hide();
|
||||
if (res.code === 200) {
|
||||
storage.setItem('userInfo', res.result);
|
||||
let query = this.$route.query;
|
||||
if (query.rePath) {
|
||||
this.$router.push({path: query.rePath, query: JSON.parse(query.query)});
|
||||
} else {
|
||||
this.$router.push('/');
|
||||
}
|
||||
}
|
||||
});
|
||||
} else {
|
||||
this.$Spin.hide();
|
||||
this.$Message.error(res.message);
|
||||
}
|
||||
}).catch(() => {
|
||||
this.$Spin.hide()
|
||||
});
|
||||
} else {
|
||||
this.verifyStatus = true;
|
||||
this.$refs.verify.show = false;
|
||||
}
|
||||
},
|
||||
verifyBtnClick () {
|
||||
if (!this.verifyStatus) {
|
||||
this.$refs.verify.show = true;
|
||||
}
|
||||
},
|
||||
handleWebLogin (type) { // 第三方登录
|
||||
webLogin(type);
|
||||
}
|
||||
},
|
||||
mounted () {
|
||||
let uuid = this.$route.query.state;
|
||||
if (uuid) {
|
||||
storage.setItem('uuid', uuid);
|
||||
loginCallback(uuid).then(res => {
|
||||
if (res.code === 200) {
|
||||
const result = res.result;
|
||||
storage.setItem('accessToken', result.accessToken);
|
||||
storage.setItem('refreshToken', result.refreshToken);
|
||||
apiLogin.getMemberMsg().then((res) => {
|
||||
if (res.code === 200) {
|
||||
storage.setItem('userInfo', res.result);
|
||||
let query = this.$route.query;
|
||||
if (query.rePath) {
|
||||
this.$router.push({path: query.rePath, query: JSON.parse(query.query)});
|
||||
} else {
|
||||
this.$router.push('/');
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
this.logoImg = this.Cookies.getItem('logo')
|
||||
},
|
||||
watch: {
|
||||
type (v) {
|
||||
if (v) {
|
||||
this.$refs.formInline.resetFields();
|
||||
} else {
|
||||
this.$refs.formSms.resetFields();
|
||||
}
|
||||
this.verifyStatus = false;
|
||||
this.$refs.verify.show = false;
|
||||
clearInterval(this.interval);
|
||||
this.codeMsg = '发送验证码';
|
||||
this.time = 60;
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
<style scoped lang="scss">
|
||||
.login {
|
||||
height: 100%;
|
||||
background-color: #f0f2f5;
|
||||
}
|
||||
.top-content {
|
||||
width: 100%;
|
||||
height: 80px;
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
|
||||
box-shadow: 0 1px 1px #ddd;
|
||||
background-color: #fff;
|
||||
|
||||
.logo-box {
|
||||
width: 80%;
|
||||
max-width: 1200px;
|
||||
height: 80px;
|
||||
margin: 0 auto;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
img {
|
||||
width: 150px;
|
||||
cursor: pointer;
|
||||
}
|
||||
div {
|
||||
font-size: 20px;
|
||||
margin-top: 10px;
|
||||
}
|
||||
}
|
||||
}
|
||||
.login-carousel {
|
||||
width: 100%;
|
||||
height: 550px;
|
||||
.demo-carousel {
|
||||
height: 550px;
|
||||
width: inherit;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
}
|
||||
}
|
||||
|
||||
.login-container {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
height: 550px;
|
||||
}
|
||||
|
||||
.form-box {
|
||||
width: 350px;
|
||||
box-sizing: border-box;
|
||||
position: absolute;
|
||||
top: 80px;
|
||||
right: 15%;
|
||||
padding: 20px;
|
||||
background:rgba(255,255,255,.8);
|
||||
.account-number{
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: baseline;
|
||||
font-weight: bold;
|
||||
>div:nth-child(2){
|
||||
color: $theme_color;
|
||||
cursor: pointer;
|
||||
}
|
||||
.tab-switch{
|
||||
height: 40px;
|
||||
font-size: 14px;
|
||||
|
||||
span:nth-child(1){
|
||||
font-size: 16px;
|
||||
border-right: 1px solid #ddd;
|
||||
padding-right: 10px;
|
||||
}
|
||||
|
||||
span:nth-child(2){
|
||||
cursor: pointer;
|
||||
padding-left: 10px;
|
||||
&:hover{
|
||||
color: $theme_color;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.verify-con{
|
||||
position: absolute;
|
||||
right: 16%;
|
||||
top: 90px;
|
||||
z-index: 10;
|
||||
}
|
||||
|
||||
.other-login {
|
||||
margin: 0 auto;
|
||||
.ivu-icon {
|
||||
font-size: 24px;
|
||||
}
|
||||
}
|
||||
.regist {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
margin-top: -10px;
|
||||
span {
|
||||
margin-left: 10px;
|
||||
&:hover {
|
||||
cursor: pointer;
|
||||
color: $theme_color;
|
||||
}
|
||||
}
|
||||
}
|
||||
.foot {
|
||||
position: fixed;
|
||||
bottom: 4vh;
|
||||
width: 368px;
|
||||
left: calc(50% - 184px);
|
||||
color: rgba(0, 0, 0, 0.45);
|
||||
font-size: 14px;
|
||||
.help {
|
||||
margin: 0 auto;
|
||||
margin-bottom: 1vh;
|
||||
width: 60%;
|
||||
.item {
|
||||
color: rgba(0, 0, 0, 0.45);
|
||||
}
|
||||
:hover {
|
||||
color: rgba(0, 0, 0, 0.65);
|
||||
}
|
||||
}
|
||||
}
|
||||
.icon-hover{
|
||||
cursor: pointer;
|
||||
}
|
||||
</style>
|
||||
231
buyer/src/pages/Merchant.vue
Normal file
@@ -0,0 +1,231 @@
|
||||
<template>
|
||||
<div class="merchant">
|
||||
<BaseHeader />
|
||||
<!-- 搜索栏 -->
|
||||
<Search :store="true" @search="search"></Search>
|
||||
<!-- 店铺logo -->
|
||||
<div class="shop-logo">
|
||||
<div>
|
||||
<img :src="storeMsg.storeLogo" height="50" alt="">
|
||||
<div>
|
||||
<p>{{storeMsg.storeName || 'xx店铺'}}</p>
|
||||
<p>{{storeMsg.storeDesc || 'xx店铺描述'}}</p>
|
||||
</div>
|
||||
<div class="store-collect" @click="collect"><Icon type="ios-heart" :color="storeCollected ? '#ed3f14' : '#fff'" />{{storeCollected?'已收藏店铺':'收藏店铺'}}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="store-category">
|
||||
<ul>
|
||||
<li @click="searchByCate({id:'', labelName: '店铺推荐'})">首页</li>
|
||||
<li v-for="(cate, index) in cateList" :key="index" @click="searchByCate(cate)">
|
||||
{{cate.labelName}}
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="promotion-decorate">{{cateName}}</div>
|
||||
|
||||
<div class="goods-list">
|
||||
<empty v-if="goodsList.length === 0" />
|
||||
<div
|
||||
v-else
|
||||
class="goods-show-info"
|
||||
v-for="(item, index) in goodsList"
|
||||
:key="index"
|
||||
@click="goGoodsDetail(item.id, item.goodsId)"
|
||||
>
|
||||
<div class="goods-show-img">
|
||||
<img width="220" height="220" :src="item.thumbnail" />
|
||||
</div>
|
||||
<div class="goods-show-price">
|
||||
<span>
|
||||
<span class="seckill-price text-danger">{{
|
||||
item.price | unitPrice("¥")
|
||||
}}</span>
|
||||
</span>
|
||||
</div>
|
||||
<div class="goods-show-detail">
|
||||
<span>{{ item.goodsName }}</span>
|
||||
</div>
|
||||
<div class="goods-show-num">
|
||||
已有<span>{{ item.commentNum || 0 }}</span>人评价
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="goods-page">
|
||||
<Page
|
||||
show-sizer
|
||||
@on-change="changePageNum"
|
||||
@on-page-size-change="changePageSize"
|
||||
:total="total"
|
||||
:page-size="params.pageSize"
|
||||
></Page>
|
||||
</div>
|
||||
<BaseFooter />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {getDetailById, getCateById} from '@/api/shopentry'
|
||||
import { cancelCollect, collectGoods, isCollection } from '@/api/member';
|
||||
import {goodsList} from '@/api/goods';
|
||||
export default {
|
||||
name: 'Merchant',
|
||||
data () {
|
||||
return {
|
||||
storeMsg: {},
|
||||
cateList: [],
|
||||
goodsList: [],
|
||||
total: 0,
|
||||
params: {
|
||||
pageNumber: 1,
|
||||
pageSize: 20,
|
||||
keyword: '',
|
||||
storeId: this.$route.query.id,
|
||||
storeCatId: ''
|
||||
},
|
||||
cateName: '店铺推荐',
|
||||
storeCollected: false
|
||||
}
|
||||
},
|
||||
created () {
|
||||
this.getStoreMsg()
|
||||
this.getCateList()
|
||||
this.getGoodsList()
|
||||
},
|
||||
mounted () {
|
||||
if (this.Cookies.getItem('userInfo')) {
|
||||
isCollection('STORE', this.soterMsg.storeId).then(res => {
|
||||
if (res.success && res.result) {
|
||||
this.storeCollected = true;
|
||||
}
|
||||
})
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
getStoreMsg () { // 店铺信息
|
||||
getDetailById(this.$route.query.id).then(res => {
|
||||
if (res.success) {
|
||||
this.storeMsg = res.result
|
||||
document.title = this.storeMsg.storeName
|
||||
}
|
||||
})
|
||||
},
|
||||
getCateList () { // 店铺分类
|
||||
getCateById(this.$route.query.id).then(res => {
|
||||
if (res.success) {
|
||||
this.cateList = res.result
|
||||
}
|
||||
})
|
||||
},
|
||||
getGoodsList () { // 商品信息
|
||||
goodsList(this.params).then((res) => {
|
||||
if (res.code === 200) {
|
||||
this.goodsList = res.result.content;
|
||||
this.total = res.result.totalElements;
|
||||
}
|
||||
}).catch(() => {
|
||||
});
|
||||
},
|
||||
goGoodsDetail (skuId, goodsId) {
|
||||
// 跳转商品详情
|
||||
let routeUrl = this.$router.resolve({
|
||||
path: '/goodsDetail',
|
||||
query: { skuId, goodsId }
|
||||
});
|
||||
window.open(routeUrl.href, '_blank');
|
||||
},
|
||||
search (val) { // 搜索本店商品
|
||||
console.log(val);
|
||||
this.params.keyword = val
|
||||
this.getGoodsList()
|
||||
},
|
||||
searchByCate (cate) { // 搜索同分类下商品
|
||||
this.params.storeCatId = cate.id
|
||||
this.cateName = cate.labelName
|
||||
this.getGoodsList()
|
||||
},
|
||||
changePageNum (val) {
|
||||
this.params.pageNumber = val - 1;
|
||||
this.getGoodsList();
|
||||
},
|
||||
changePageSize (val) {
|
||||
this.params.pageNumber = 0;
|
||||
this.params.pageSize = val;
|
||||
this.getGoodsList();
|
||||
},
|
||||
async collect () { // 收藏店铺
|
||||
if (this.storeCollected) {
|
||||
let cancel = await cancelCollect('STORE', this.storeMsg.storeId)
|
||||
if (cancel.success) {
|
||||
this.$Message.success('已取消收藏')
|
||||
this.storeCollected = false;
|
||||
}
|
||||
} else {
|
||||
let collect = await collectGoods('STORE', this.storeMsg.storeId);
|
||||
if (collect.code === 200) {
|
||||
this.storeCollected = true;
|
||||
this.$Message.success('收藏店铺成功,可以前往个人中心我的收藏查看');
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
@import '../assets/styles/goodsList.scss';
|
||||
.merchant {
|
||||
margin: 0 auto;
|
||||
}
|
||||
.shop-logo {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
background-color: #666;
|
||||
padding: 10px;
|
||||
color: #fff;
|
||||
>div{
|
||||
display: flex;
|
||||
width: 1200px;
|
||||
margin: 0 auto;
|
||||
align-items: center;
|
||||
>div{
|
||||
margin-left: 10px;
|
||||
}
|
||||
}
|
||||
img {
|
||||
height: 80px;
|
||||
}
|
||||
p:nth-child(1) {
|
||||
font-size: 20px;
|
||||
}
|
||||
p:nth-child(2){
|
||||
font-size: 14px;
|
||||
}
|
||||
}
|
||||
.store-collect{
|
||||
margin-left: 20px!important;
|
||||
&:hover{
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
.store-category {
|
||||
background-color: #005aa0;
|
||||
color: #fff;
|
||||
ul{
|
||||
width: 1200px;
|
||||
margin: 0 auto 10px;
|
||||
padding: 3px 0;
|
||||
display: flex;
|
||||
li {
|
||||
margin-right: 25px;
|
||||
}
|
||||
li:hover{
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
}
|
||||
.promotion-decorate::before,.promotion-decorate::after{
|
||||
background-image: url('../../static/sprite@2x.png');
|
||||
}
|
||||
</style>
|
||||
225
buyer/src/pages/ShoppingCart.vue
Normal file
@@ -0,0 +1,225 @@
|
||||
<template>
|
||||
<div>
|
||||
<BaseHeader></BaseHeader>
|
||||
<Search></Search>
|
||||
<cateNav></cateNav>
|
||||
<!-- 添加成功提示 -->
|
||||
<div class="add-info-box-container">
|
||||
<div class="add-info-box">
|
||||
<div class="add-info-detail">
|
||||
<div class="add-info-title">
|
||||
<p>
|
||||
<i class="fa fa-check-circle"></i> 商品已成功加入购物车!</p>
|
||||
</div>
|
||||
<div class="add-info-box-row">
|
||||
<div class="add-info-img">
|
||||
<img :src="this.detail.thumbnail" alt="">
|
||||
</div>
|
||||
<div class="add-info-intro">
|
||||
<p>{{detail.goodsName}}</p>
|
||||
<p class="add-info-intro-detail">数量:{{$route.query.count}}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="car-btn-group">
|
||||
<div></div>
|
||||
<div class="car-btn-row">
|
||||
<router-link :to="`/goodsDetail?skuId=${detail.id}&goodsId=${detail.goodsId}`">
|
||||
<button class="btn-car hover-pointer btn-car-to-detail">查看商品详情</button>
|
||||
</router-link>
|
||||
<router-link to="/cart">
|
||||
<button class="btn-car hover-pointer btn-car-to-pay">去购物车结算></button>
|
||||
</router-link>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- <div class="other-user-buy-box">
|
||||
<div class="other-user-buy-title">
|
||||
<p>可以顺便看下其他商品哦 ~</p>
|
||||
</div>
|
||||
<div class="other-user-buy-row" v-for="(items,index1) in recommend" :key="index1">
|
||||
<div class="other-user-buy-item-box" v-for="(item,index2) in items" :key="index2">
|
||||
<div class="other-user-buy-item-img">
|
||||
<a href="item_detail.html"><img :src="item.img" alt=""></a>
|
||||
</div>
|
||||
<div class="other-buy-detail-box">
|
||||
<div class="other-buy-title">
|
||||
<a href="item_detail.html">
|
||||
<p>{{item.intro}}</p>
|
||||
</a>
|
||||
</div>
|
||||
<div class="other-buy-price">
|
||||
<p>¥{{item.price}}</p>
|
||||
</div>
|
||||
<div class="other-buy-btn-box">
|
||||
<router-link to="/goodsDetail">
|
||||
<button class="other-buy-btn"><Icon type="ios-cart"></Icon> 加入购物车</button>
|
||||
</router-link>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div> -->
|
||||
<BaseFooter></BaseFooter>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'ShoppingCart',
|
||||
beforeRouteEnter (to, from, next) {
|
||||
window.scrollTo(0, 0);
|
||||
next();
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
detail: {}
|
||||
};
|
||||
},
|
||||
mounted () {
|
||||
let detail = this.$route.query.detail;
|
||||
if (detail) this.detail = detail;
|
||||
},
|
||||
methods: {
|
||||
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
/****************************加入购物车页面开始*****************************/
|
||||
.add-info-box-container{
|
||||
width: 100%;
|
||||
background-color: #F5F5F5;
|
||||
}
|
||||
.add-info-box{
|
||||
width: 1200px;
|
||||
margin: 0px auto;
|
||||
padding: 15px 0px;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: space-between;
|
||||
}
|
||||
.add-info-detail{
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
.add-info-title{
|
||||
font-size: 25px;
|
||||
color: #71b247;
|
||||
}
|
||||
.add-info-box-row{
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
margin-top: 15px;
|
||||
}
|
||||
.add-info-img{
|
||||
width: 56px;
|
||||
height: 56px;
|
||||
margin-right: 15px;
|
||||
}
|
||||
.add-info-img img{
|
||||
width: 100%;
|
||||
}
|
||||
.add-info-intro{
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
}
|
||||
.add-info-intro-detail{
|
||||
font-size: 12px;
|
||||
color: #999999;
|
||||
}
|
||||
.car-btn-group{
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
}
|
||||
/*按钮*/
|
||||
.btn-car{
|
||||
padding: 8px 10px;
|
||||
font-size: 16px;
|
||||
border-radius: 0px;
|
||||
border:none;
|
||||
margin-right: 15px;
|
||||
}
|
||||
.btn-car-to-detail{
|
||||
background-color: #fff;
|
||||
color: $theme_color;
|
||||
border:1px solid #fff;
|
||||
}
|
||||
.btn-car-to-detail:hover{
|
||||
border:1px solid $theme_color;
|
||||
}
|
||||
.btn-car-to-pay{
|
||||
background-color: $theme_color;
|
||||
color: #fff;
|
||||
border:1px solid $theme_color;
|
||||
}
|
||||
.btn-car-to-pay:hover{
|
||||
background-color: $theme_color;
|
||||
border:1px solid $theme_color;
|
||||
}
|
||||
/*其他用户购买*/
|
||||
.other-user-buy-box{
|
||||
width: 90%;
|
||||
margin: 0px auto;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
.other-user-buy-title{
|
||||
margin-top: 25px;
|
||||
font-size: 14px;
|
||||
color: #666;
|
||||
font-weight: bold;
|
||||
}
|
||||
.other-user-buy-row{
|
||||
margin-top: 25px;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: space-between;
|
||||
}
|
||||
.other-user-buy-item-box{
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
}
|
||||
.other-user-buy-item-img{
|
||||
width: 96px;
|
||||
height: 96px;
|
||||
}
|
||||
.other-user-buy-item-img img{
|
||||
width: 100%;
|
||||
}
|
||||
.other-buy-detail-box{
|
||||
width: 160px;
|
||||
margin-left: 15px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
.other-buy-title{
|
||||
font-size: 12px;
|
||||
}
|
||||
.other-buy-title a{
|
||||
color: #2c2c2c;
|
||||
text-decoration: none;
|
||||
}
|
||||
.other-buy-price{
|
||||
font-size: 12px;
|
||||
font-weight: bold;
|
||||
color: $theme_color;
|
||||
}
|
||||
.other-buy-btn{
|
||||
padding: 3px 10px;
|
||||
color: $theme_color;
|
||||
font-size: 12px;
|
||||
border: 1px solid $theme_color;
|
||||
border-radius: 0px;
|
||||
background-color: #fff;
|
||||
}
|
||||
.other-buy-btn:hover{
|
||||
color: $theme_color;
|
||||
border: 1px solid $theme_color;
|
||||
}
|
||||
/****************************加入购物车页面结束*****************************/
|
||||
</style>
|
||||
294
buyer/src/pages/SignUp.vue
Normal file
@@ -0,0 +1,294 @@
|
||||
<template>
|
||||
<div class="login">
|
||||
<div style="height:50px;"></div>
|
||||
<div class="logo-box">
|
||||
<img
|
||||
width="150"
|
||||
:src="logoImg"
|
||||
@click="$router.push('/')"
|
||||
/>
|
||||
<div>注册</div>
|
||||
</div>
|
||||
<div class="login-container">
|
||||
|
||||
<!-- 注册 -->
|
||||
<Form
|
||||
ref="formRegist"
|
||||
:model="formRegist"
|
||||
:rules="ruleInline"
|
||||
style="width:300px;"
|
||||
>
|
||||
<FormItem prop="username">
|
||||
<i-input
|
||||
type="text"
|
||||
v-model="formRegist.username"
|
||||
clearable
|
||||
placeholder="用户名"
|
||||
>
|
||||
<Icon type="md-person" slot="prepend"></Icon>
|
||||
</i-input>
|
||||
</FormItem>
|
||||
<FormItem prop="password">
|
||||
<i-input
|
||||
type="password"
|
||||
v-model="formRegist.password"
|
||||
clearable
|
||||
placeholder="请输入大于6位密码"
|
||||
>
|
||||
<Icon type="md-lock" slot="prepend"> </Icon>
|
||||
</i-input>
|
||||
</FormItem>
|
||||
<FormItem prop="mobilePhone">
|
||||
<i-input
|
||||
type="text"
|
||||
v-model="formRegist.mobilePhone"
|
||||
clearable
|
||||
placeholder="手机号"
|
||||
>
|
||||
<Icon type="md-phone-portrait" slot="prepend"></Icon>
|
||||
</i-input>
|
||||
</FormItem>
|
||||
<FormItem prop="code">
|
||||
<i-input
|
||||
type="text"
|
||||
v-model="formRegist.code"
|
||||
clearable
|
||||
placeholder="手机验证码"
|
||||
>
|
||||
<Icon
|
||||
type="ios-text-outline"
|
||||
style="font-weight: bold"
|
||||
slot="prepend"
|
||||
/>
|
||||
<Button slot="append" @click="sendCode">{{ codeMsg }}</Button>
|
||||
</i-input>
|
||||
</FormItem>
|
||||
<FormItem>
|
||||
<Button @click="verifyBtnClick" long :type="verifyStatus?'success':'default'">{{verifyStatus?'验证通过':'点击完成安全验证'}}</Button>
|
||||
</FormItem>
|
||||
<FormItem>
|
||||
<Button type="error" size="large" @click="handleRegist" long
|
||||
>注册</Button
|
||||
>
|
||||
</FormItem>
|
||||
<FormItem><span class="color999 ml_20">点击注册,表示您同意《<router-link to="/article?id=1371992704333905920" target="_blank">商城用户协议</router-link>》</span></FormItem>
|
||||
</Form>
|
||||
<!-- 拼图验证码 -->
|
||||
<Verify
|
||||
ref="verify"
|
||||
class="verify-con"
|
||||
:verifyType="verifyType"
|
||||
@change="verifyChange"
|
||||
></Verify>
|
||||
<div class="login-btn">已有账号?<a @click="$router.push('login')">立即登录</a></div>
|
||||
</div>
|
||||
<div class="foot">
|
||||
<Row type="flex" justify="space-around" class="help">
|
||||
<router-link to="/article" class="item" target="_blank">帮助</router-link>
|
||||
<router-link to="/article?id=1371779927900160000" class="item" target="_blank">隐私</router-link>
|
||||
<router-link to="/article?id=1371992704333905920" class="item" target="_blank">条款</router-link>
|
||||
</Row>
|
||||
<Row type="flex" justify="center" class="copyright">
|
||||
Copyright © 2021 - Present
|
||||
<a href="https://pickmall.cn" target="_blank" style="margin: 0 5px">lili-shop</a>
|
||||
版权所有
|
||||
</Row>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import * as RegExp from '@/plugins/RegExp.js';
|
||||
import { md5 } from '@/plugins/md5.js';
|
||||
import * as apiLogin from '@/api/login.js';
|
||||
import { sendSms } from '@/api/common.js';
|
||||
import Verify from '@/components/verify';
|
||||
export default {
|
||||
name: 'Login',
|
||||
components: { Verify },
|
||||
data () {
|
||||
return {
|
||||
formRegist: {
|
||||
// 注册表单
|
||||
mobilePhone: '',
|
||||
code: '',
|
||||
username: '',
|
||||
password: ''
|
||||
},
|
||||
ruleInline: {
|
||||
// 验证规则
|
||||
username: [{ required: true, message: '请输入用户名' }],
|
||||
password: [
|
||||
{ required: true, message: '请输入密码' },
|
||||
{ type: 'string', min: 6, message: '密码不能少于6位' }
|
||||
],
|
||||
mobilePhone: [
|
||||
{ required: true, message: '请输入手机号码' },
|
||||
{
|
||||
pattern: RegExp.mobile,
|
||||
trigger: 'blur',
|
||||
message: '请输入正确的手机号'
|
||||
}
|
||||
],
|
||||
code: [{ required: true, message: '请输入手机验证码' }]
|
||||
},
|
||||
verifyStatus: false,
|
||||
verifyType: 'REGISTER',
|
||||
codeMsg: '发送验证码',
|
||||
interval: '',
|
||||
time: 60,
|
||||
logoImg: ''
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
// 注册
|
||||
handleRegist () {
|
||||
this.$refs.formRegist.validate((valid) => {
|
||||
if (valid) {
|
||||
let data = JSON.parse(JSON.stringify(this.formRegist));
|
||||
data.password = md5(data.password);
|
||||
apiLogin.regist(data).then((res) => {
|
||||
if (res.code === 200) {
|
||||
this.$Message.success('注册成功!');
|
||||
this.$router.push('login');
|
||||
} else {
|
||||
this.$Message.warning(res.message);
|
||||
}
|
||||
});
|
||||
} else {}
|
||||
});
|
||||
},
|
||||
sendCode () {
|
||||
if (this.time === 60) {
|
||||
if (this.formRegist.mobilePhone === '') {
|
||||
this.$Message.warning('请先填写手机号');
|
||||
return;
|
||||
}
|
||||
if (!this.verifyStatus) {
|
||||
this.$Message.warning('请先完成安全验证');
|
||||
return;
|
||||
}
|
||||
let params = {
|
||||
mobile: this.formRegist.mobilePhone,
|
||||
verificationEnums: 'REGISTER'
|
||||
};
|
||||
sendSms(params).then(res => {
|
||||
if (res.code === 200) {
|
||||
this.$Message.success('验证码发送成功');
|
||||
let that = this;
|
||||
this.interval = setInterval(() => {
|
||||
that.time--;
|
||||
if (that.time === 0) {
|
||||
that.time = 60;
|
||||
that.codeMsg = '重新发送';
|
||||
that.verifyStatus = false;
|
||||
clearInterval(that.interval);
|
||||
} else {
|
||||
that.codeMsg = that.time;
|
||||
}
|
||||
}, 1000);
|
||||
} else {
|
||||
this.$Message.warning(res.message);
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
handleCancel () {
|
||||
this.$refs.formRegist.resetFields();
|
||||
},
|
||||
verifyChange (con) {
|
||||
if (!con.status) return;
|
||||
this.$refs.verify.show = false;
|
||||
this.verifyStatus = true;
|
||||
},
|
||||
verifyBtnClick () {
|
||||
if (!this.verifyStatus) {
|
||||
this.$refs.verify.show = true;
|
||||
}
|
||||
}
|
||||
},
|
||||
mounted () {
|
||||
this.$refs.formRegist.resetFields();
|
||||
this.logoImg = this.Cookies.getItem('logo')
|
||||
},
|
||||
watch: {
|
||||
}
|
||||
};
|
||||
</script>
|
||||
<style scoped lang="scss">
|
||||
|
||||
.logo-box {
|
||||
width: 600px;
|
||||
height: 80px;
|
||||
margin: 0 auto;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
img {
|
||||
width: 150px;
|
||||
cursor: pointer;
|
||||
}
|
||||
div {
|
||||
font-size: 20px;
|
||||
margin-top: 10px;
|
||||
}
|
||||
}
|
||||
|
||||
.login-container {
|
||||
border-top: 2px solid $theme_color;
|
||||
position: relative;
|
||||
margin: 0 auto;
|
||||
width: 600px;
|
||||
background-color: #fff;
|
||||
padding: 20px 150px;
|
||||
.login-btn{
|
||||
position: absolute;
|
||||
right: 20px;
|
||||
top: -45px;
|
||||
}
|
||||
}
|
||||
|
||||
.verify-con{
|
||||
position: absolute;
|
||||
left: 140px;
|
||||
top: 80px;
|
||||
z-index: 10;
|
||||
}
|
||||
|
||||
.other-login {
|
||||
margin: 0 auto;
|
||||
.ivu-icon {
|
||||
font-size: 24px;
|
||||
}
|
||||
}
|
||||
.regist {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
margin-top: -10px;
|
||||
span {
|
||||
margin-left: 10px;
|
||||
&:hover {
|
||||
cursor: pointer;
|
||||
color: $theme_color;
|
||||
}
|
||||
}
|
||||
}
|
||||
.foot {
|
||||
position: fixed;
|
||||
bottom: 4vh;
|
||||
width: 368px;
|
||||
left: calc(50% - 184px);
|
||||
color: rgba(0, 0, 0, 0.45);
|
||||
font-size: 14px;
|
||||
.help {
|
||||
margin: 0 auto;
|
||||
margin-bottom: 1vh;
|
||||
width: 60%;
|
||||
.item {
|
||||
color: rgba(0, 0, 0, 0.45);
|
||||
}
|
||||
:hover {
|
||||
color: rgba(0, 0, 0, 0.65);
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
219
buyer/src/pages/article/index.vue
Normal file
@@ -0,0 +1,219 @@
|
||||
<template>
|
||||
<div>
|
||||
<BaseHeader></BaseHeader>
|
||||
<Search></Search>
|
||||
<cateNav></cateNav>
|
||||
<div class="title-bg"><p>文章帮助中心</p></div>
|
||||
<div class="container width_1200">
|
||||
<Layout class="layoutAll">
|
||||
<Sider class="side-bar" ref="side" :collapsed-width="78">
|
||||
<div class="article-cate">文章分类列表</div>
|
||||
<Menu
|
||||
class="side-menu"
|
||||
theme="light"
|
||||
width="auto"
|
||||
ref='menu'
|
||||
:active-name="activeName"
|
||||
:open-names="openName"
|
||||
@on-select="onSelect"
|
||||
>
|
||||
<!-- 循环导航栏 -->
|
||||
<Submenu
|
||||
v-show="menu.children"
|
||||
v-for="(menu, index) in list"
|
||||
:key="index"
|
||||
:name="menu.articleCategoryName"
|
||||
>
|
||||
<template slot="title">
|
||||
<span>{{ menu.articleCategoryName }}</span>
|
||||
</template>
|
||||
<MenuItem
|
||||
v-for="(chlidren, i) in menu.children"
|
||||
:key="i"
|
||||
:name="chlidren.id"
|
||||
>{{ chlidren.articleCategoryName }}</MenuItem
|
||||
>
|
||||
</Submenu>
|
||||
|
||||
</Menu>
|
||||
</Sider>
|
||||
<Layout class="layout ml_10">
|
||||
<Content class="content">
|
||||
<ul class="article-list" v-show="showList">
|
||||
<li v-for="(article, index) in articleList" :key="index" @click="getDetail(article.id)">
|
||||
{{article.title}}
|
||||
</li>
|
||||
</ul>
|
||||
<transition mode="out-in">
|
||||
<div v-show="!showList">
|
||||
<a class="back-btn" @click="showList = true"><返回上一级</a>
|
||||
<h2 class="mt_10 mb_10">{{detail.title}}</h2>
|
||||
<div class="mt_10 mb_10" v-html="detail.content"></div>
|
||||
</div>
|
||||
</transition>
|
||||
</Content>
|
||||
</Layout>
|
||||
</Layout>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {articleCateList, articleDetail, articleList} from '@/api/common.js'
|
||||
export default {
|
||||
name: 'Home',
|
||||
data () {
|
||||
return {
|
||||
list: [], // 分类列表
|
||||
detail: '', // 文章详情
|
||||
articleList: [], // 分类下的文章列表
|
||||
activeName: '1347456734864367616', // 左侧激活项
|
||||
openName: [], // 展开的名称
|
||||
params: { // 请求参数
|
||||
pageNumber: 1,
|
||||
pageSize: 100,
|
||||
categoryId: '',
|
||||
sort: 'sort'
|
||||
},
|
||||
showList: true // 展示文章列表
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
// 每次点击左侧bar的callback
|
||||
onSelect (id) {
|
||||
this.getList(id)
|
||||
this.detail = ''
|
||||
this.showList = true
|
||||
},
|
||||
getCateList () { // 文章分类列表
|
||||
articleCateList().then(res => {
|
||||
if (res.success) {
|
||||
this.list = res.result
|
||||
if (this.$route.query.id) {
|
||||
this.activeName = this.detail.categoryId
|
||||
this.list.forEach(e => {
|
||||
if (e.children.length) {
|
||||
e.children.forEach(i => {
|
||||
if (i.id === this.detail.categoryId) {
|
||||
this.openName.push(e.articleCategoryName)
|
||||
}
|
||||
})
|
||||
} else {
|
||||
delete e.children
|
||||
}
|
||||
})
|
||||
} else {
|
||||
this.activeName = this.list[0].children[0].id
|
||||
this.openName.push(this.list[0].articleCategoryName)
|
||||
}
|
||||
this.$nextTick(() => {
|
||||
this.$refs.menu.updateOpened()
|
||||
this.$refs.menu.updateActiveName()
|
||||
})
|
||||
this.getList(this.activeName)
|
||||
}
|
||||
})
|
||||
},
|
||||
getList (id) { // 文章列表
|
||||
this.params.categoryId = id
|
||||
articleList(this.params).then(res => {
|
||||
if (res.success) {
|
||||
this.articleList = res.result.records
|
||||
}
|
||||
})
|
||||
},
|
||||
async getDetail (id) { // 文章详情
|
||||
await articleDetail(id).then(res => {
|
||||
if (res.success) {
|
||||
this.detail = res.result
|
||||
this.showList = false
|
||||
}
|
||||
})
|
||||
}
|
||||
},
|
||||
async mounted () {
|
||||
const articleId = this.$route.query.id
|
||||
if (articleId) {
|
||||
await this.getDetail(articleId)
|
||||
}
|
||||
this.getCateList()
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.content {
|
||||
padding: 15px 50px;
|
||||
}
|
||||
|
||||
.header {
|
||||
@include background_color($light_background_color);
|
||||
}
|
||||
|
||||
.side-menu,
|
||||
.side-bar,
|
||||
.content {
|
||||
@include white_background_color();
|
||||
@include title_color($light_title_color);
|
||||
}
|
||||
|
||||
.side-bar {
|
||||
min-height: 600px;
|
||||
height: auto;
|
||||
}
|
||||
|
||||
.layoutAll {
|
||||
min-height: 1200px;
|
||||
@include background_color($light_background_color);
|
||||
}
|
||||
|
||||
.container {
|
||||
margin: 0 auto;
|
||||
padding: 20px 0;
|
||||
}
|
||||
|
||||
.side-bar a {
|
||||
@include title_color($light_title_color);
|
||||
}
|
||||
|
||||
.layout-footer-center {
|
||||
padding: 0px 15px;
|
||||
|
||||
padding-bottom: 15px;
|
||||
text-align: center;
|
||||
}
|
||||
.title-bg{
|
||||
border-top: 3px solid $theme_color;
|
||||
height: 100px;
|
||||
width: 100%;
|
||||
background-color: #7b7b7b;
|
||||
p{
|
||||
width: 1200px;
|
||||
font-size: 30px;
|
||||
height: 100px;
|
||||
line-height: 100px;
|
||||
color: #fff;
|
||||
line-height: 100px;
|
||||
margin: 0 auto;
|
||||
padding-left: 10px;
|
||||
}
|
||||
}
|
||||
.article-cate{
|
||||
width: 200px;
|
||||
height: 30px;
|
||||
color: #fff;
|
||||
line-height: 30px;
|
||||
text-align: center;
|
||||
font-size: 18px;
|
||||
background-color: #666;
|
||||
}
|
||||
.article-list {
|
||||
li{
|
||||
margin: 10px 0;
|
||||
color: #2D8CF0;
|
||||
&:hover{
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
174
buyer/src/pages/couponCenter.vue
Normal file
@@ -0,0 +1,174 @@
|
||||
<template>
|
||||
<div class="coupon-center">
|
||||
<BaseHeader></BaseHeader>
|
||||
<div class="content">
|
||||
<div>
|
||||
<div class="coupon-title">
|
||||
<router-link to="/">
|
||||
<img src="../assets/images/logo.png" width="120" alt="">
|
||||
</router-link>
|
||||
<p>领券中心</p>
|
||||
<Input search style="width:400px" @on-search='search' enter-button="搜索" placeholder="搜索优惠券" />
|
||||
</div>
|
||||
|
||||
<div class="fontsize_18 recommend">推荐好券</div>
|
||||
|
||||
<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="receive(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>
|
||||
</div>
|
||||
</div>
|
||||
<BaseFooter></BaseFooter>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import {couponList, receiveCoupon} from '@/api/member.js'
|
||||
export default {
|
||||
data () {
|
||||
return {
|
||||
list: [],
|
||||
total: 0,
|
||||
params: {
|
||||
pageNumber: 1,
|
||||
pageSize: 20
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
search (item) {
|
||||
this.params.couponName = item
|
||||
this.params.pageNumber = 1
|
||||
this.getList()
|
||||
},
|
||||
getList () {
|
||||
this.$Spin.show()
|
||||
couponList(this.params).then(res => {
|
||||
this.$Spin.hide()
|
||||
this.loading = false
|
||||
if (res.success) {
|
||||
this.list = res.result.records
|
||||
this.total = res.result.total
|
||||
}
|
||||
}).catch(() => { this.$Spin.hide() })
|
||||
},
|
||||
|
||||
changePageNum (val) {
|
||||
this.params.pageNumber = val;
|
||||
this.getList()
|
||||
},
|
||||
|
||||
changePageSize (val) {
|
||||
this.pageNumber = 1;
|
||||
this.params.pageSize = val;
|
||||
this.getList()
|
||||
},
|
||||
|
||||
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}可用`
|
||||
}
|
||||
},
|
||||
mounted () {
|
||||
this.getList()
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
@import '../assets/styles/coupon.scss';
|
||||
.content{
|
||||
width: 100%;
|
||||
background-color: #fff;
|
||||
|
||||
> div {
|
||||
margin: 10px auto;
|
||||
width: 1200px;
|
||||
}
|
||||
}
|
||||
.coupon-title {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
p{
|
||||
font-size: 18px;
|
||||
margin-right: 500px;
|
||||
}
|
||||
border-bottom: 2px solid $theme_color;
|
||||
}
|
||||
.recommend {
|
||||
margin: 20px auto;
|
||||
font-weight: bold;
|
||||
width: 200px;
|
||||
text-align: center;
|
||||
}
|
||||
.coupon-item {
|
||||
b{
|
||||
background: url('../assets/images/small-circle.png') top left repeat-y;
|
||||
}
|
||||
}
|
||||
.pageration {
|
||||
text-align: right;
|
||||
padding-bottom: 10px;
|
||||
}
|
||||
</style>
|
||||
337
buyer/src/pages/forgetPassword.vue
Normal file
@@ -0,0 +1,337 @@
|
||||
<template>
|
||||
<div class="login">
|
||||
<!-- 顶部logo -->
|
||||
<div class="top-content">
|
||||
<div class="logo-box">
|
||||
<img
|
||||
src="../assets/images/logo1.png"
|
||||
@click="$router.push('/')"
|
||||
/>
|
||||
<div>修改密码</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="login-container">
|
||||
<!-- 验证手机号 -->
|
||||
<Form
|
||||
ref="formFirst"
|
||||
:model="formFirst"
|
||||
:rules="ruleInline"
|
||||
style="width:300px;"
|
||||
v-show="step === 0"
|
||||
>
|
||||
<FormItem prop="mobile">
|
||||
<i-input
|
||||
type="text"
|
||||
v-model="formFirst.mobile"
|
||||
clearable
|
||||
placeholder="手机号"
|
||||
>
|
||||
<Icon type="md-phone-portrait" slot="prepend"></Icon>
|
||||
</i-input>
|
||||
</FormItem>
|
||||
<FormItem prop="code">
|
||||
<i-input
|
||||
type="text"
|
||||
v-model="formFirst.code"
|
||||
clearable
|
||||
placeholder="手机验证码"
|
||||
>
|
||||
<Icon
|
||||
type="ios-text-outline"
|
||||
style="font-weight: bold"
|
||||
slot="prepend"
|
||||
/>
|
||||
<Button slot="append" @click="sendCode">{{ codeMsg }}</Button>
|
||||
</i-input>
|
||||
</FormItem>
|
||||
<FormItem>
|
||||
<Button @click="verifyBtnClick" long :type="verifyStatus?'success':'default'">{{verifyStatus?'验证通过':'点击完成安全验证'}}</Button>
|
||||
</FormItem>
|
||||
<FormItem>
|
||||
<Button type="error" @click="next" :loading="loading" long>下一步</Button>
|
||||
</FormItem>
|
||||
</Form>
|
||||
<Form
|
||||
ref="form"
|
||||
:model="form"
|
||||
:rules="ruleInline"
|
||||
style="width:300px;"
|
||||
v-show="step === 1"
|
||||
>
|
||||
<FormItem prop="password">
|
||||
<i-input
|
||||
type="password"
|
||||
v-model="form.password"
|
||||
clearable
|
||||
placeholder="请输入至少六位密码"
|
||||
>
|
||||
<Icon type="md-lock" slot="prepend"></Icon>
|
||||
</i-input>
|
||||
</FormItem>
|
||||
<FormItem prop="password">
|
||||
<i-input
|
||||
type="password"
|
||||
v-model="form.oncePasd"
|
||||
clearable
|
||||
placeholder="请再次输入密码"
|
||||
>
|
||||
<Icon type="md-lock" slot="prepend"></Icon>
|
||||
</i-input>
|
||||
</FormItem>
|
||||
<FormItem>
|
||||
<Button type="error" size="large" @click="handleSubmit" :loading="loading1" long>提交</Button>
|
||||
</FormItem>
|
||||
</Form>
|
||||
<!-- 拼图验证码 -->
|
||||
<Verify
|
||||
ref="verify"
|
||||
class="verify-con"
|
||||
:verifyType="verifyType"
|
||||
@change="verifyChange"
|
||||
></Verify>
|
||||
<div class="login-btn"><a @click="$router.push('login')">前往登录</a></div>
|
||||
</div>
|
||||
<div class="foot">
|
||||
<Row type="flex" justify="space-around" class="help">
|
||||
<a class="item" href="https://lilishop.com" target="_blank">帮助</a>
|
||||
<a class="item" href="https://lilishop.com" target="_blank">隐私</a>
|
||||
<a class="item" href="https://lilishop.com" target="_blank">条款</a>
|
||||
</Row>
|
||||
<Row type="flex" justify="center" class="copyright">
|
||||
Copyright © 2020 - Present
|
||||
<a href="http://lili.cn" target="_blank" style="margin: 0 5px"
|
||||
>lili-shop</a
|
||||
>
|
||||
版权所有
|
||||
</Row>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import * as RegExp from '@/plugins/RegExp.js';
|
||||
import { md5 } from '@/plugins/md5.js';
|
||||
import * as apiLogin from '@/api/login.js';
|
||||
import { sendSms } from '@/api/common.js';
|
||||
import Verify from '@/components/verify';
|
||||
export default {
|
||||
name: 'Login',
|
||||
components: { Verify },
|
||||
data () {
|
||||
return {
|
||||
loading: false,
|
||||
loading1: false,
|
||||
formFirst: {
|
||||
// 注册表单
|
||||
mobile: '',
|
||||
code: ''
|
||||
},
|
||||
form: {
|
||||
password: '',
|
||||
oncePasd: ''
|
||||
},
|
||||
step: 0,
|
||||
ruleInline: {
|
||||
// 验证规则
|
||||
mobile: [
|
||||
{ required: true, message: '请输入手机号码' },
|
||||
{
|
||||
pattern: RegExp.mobile,
|
||||
trigger: 'blur',
|
||||
message: '请输入正确的手机号'
|
||||
}
|
||||
],
|
||||
code: [{ required: true, message: '请输入手机验证码' }],
|
||||
password: [{required: true, message: '密码不能为空'}, {pattern: RegExp.password, message: '密码不能少于6位'}]
|
||||
},
|
||||
verifyStatus: false,
|
||||
verifyType: 'FIND_USER',
|
||||
codeMsg: '发送验证码',
|
||||
interval: '',
|
||||
time: 60
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
// 提交短信验证码,修改密码
|
||||
next () {
|
||||
this.$refs.formFirst.validate((valid) => {
|
||||
if (valid) {
|
||||
this.loading = true;
|
||||
let data = JSON.parse(JSON.stringify(this.formFirst));
|
||||
apiLogin.validateCode(data).then((res) => {
|
||||
this.loading = false;
|
||||
if (res.code === 200) {
|
||||
// this.$Message.success('');
|
||||
this.step = 1;
|
||||
} else {
|
||||
this.$Message.warning(res.message);
|
||||
}
|
||||
}).catch(() => { this.loading = false; });
|
||||
} else {}
|
||||
});
|
||||
},
|
||||
handleSubmit () { // 提交密码
|
||||
this.$refs.form.validate(valid => {
|
||||
if (valid) {
|
||||
let params = JSON.parse(JSON.stringify(this.form));
|
||||
if (params.password !== params.oncePasd) {
|
||||
this.$Message.warning('两次输入密码不一致');
|
||||
return;
|
||||
};
|
||||
params.mobile = this.formFirst.mobile;
|
||||
params.password = md5(params.password);
|
||||
delete params.oncePasd;
|
||||
this.loading1 = true;
|
||||
|
||||
apiLogin.resetPassword(params).then(res => {
|
||||
this.loading1 = false;
|
||||
console.log(res);
|
||||
if (res.code === 200) {
|
||||
this.$Message.success('修改密码成功');
|
||||
this.$router.push('login');
|
||||
}
|
||||
}).catch(() => { this.loading = false; });
|
||||
};
|
||||
});
|
||||
},
|
||||
sendCode () { // 发送验证码
|
||||
if (this.time === 60) {
|
||||
if (this.formFirst.mobile === '') {
|
||||
this.$Message.warning('请先填写手机号');
|
||||
return;
|
||||
}
|
||||
if (!this.verifyStatus) {
|
||||
this.$Message.warning('请先完成安全验证');
|
||||
return;
|
||||
}
|
||||
let params = {
|
||||
mobile: this.formFirst.mobile,
|
||||
verificationEnums: 'FIND_USER'
|
||||
};
|
||||
sendSms(params).then(res => {
|
||||
if (res.code === 200) {
|
||||
this.$Message.success('验证码发送成功');
|
||||
let that = this;
|
||||
this.interval = setInterval(() => {
|
||||
that.time--;
|
||||
if (that.time === 0) {
|
||||
that.time = 60;
|
||||
that.codeMsg = '重新发送';
|
||||
that.verifyStatus = false;
|
||||
clearInterval(that.interval);
|
||||
} else {
|
||||
that.codeMsg = that.time;
|
||||
}
|
||||
}, 1000);
|
||||
} else {
|
||||
this.$Message.warning(res.message);
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
verifyChange (con) { // 验证通过
|
||||
if (!con.status) return;
|
||||
this.$refs.verify.show = false;
|
||||
this.verifyStatus = true;
|
||||
},
|
||||
verifyBtnClick () {
|
||||
if (!this.verifyStatus) {
|
||||
this.$refs.verify.show = true;
|
||||
}
|
||||
}
|
||||
},
|
||||
mounted () {
|
||||
this.$refs.formFirst.resetFields();
|
||||
},
|
||||
watch: {
|
||||
}
|
||||
};
|
||||
</script>
|
||||
<style scoped lang="scss">
|
||||
.login {
|
||||
height: 100%;
|
||||
}
|
||||
.top-content {
|
||||
width: 100%;
|
||||
height: 80px;
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
box-shadow: 0 1px 1px #ddd;
|
||||
background-color: #fff;
|
||||
|
||||
.logo-box {
|
||||
width: 80%;
|
||||
max-width: 1200px;
|
||||
height: 80px;
|
||||
margin: 0 auto;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
img {
|
||||
width: 200px;
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
div {
|
||||
font-size: 20px;
|
||||
margin-top: 10px;
|
||||
}
|
||||
}
|
||||
|
||||
.login-container {
|
||||
position: relative;
|
||||
margin: 10px auto;
|
||||
width: 1200px;
|
||||
background-color: #fff;
|
||||
padding: 20px;
|
||||
.login-btn{
|
||||
position: absolute;
|
||||
right: 20px;
|
||||
top: 20px;
|
||||
}
|
||||
}
|
||||
|
||||
.verify-con{
|
||||
position: absolute;
|
||||
left: 400px;
|
||||
top: 50px;
|
||||
z-index: 10;
|
||||
}
|
||||
|
||||
.other-login {
|
||||
margin: 0 auto;
|
||||
.ivu-icon {
|
||||
font-size: 24px;
|
||||
}
|
||||
}
|
||||
.regist {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
margin-top: -10px;
|
||||
span {
|
||||
margin-left: 10px;
|
||||
&:hover {
|
||||
cursor: pointer;
|
||||
color: $theme_color;
|
||||
}
|
||||
}
|
||||
}
|
||||
.foot {
|
||||
position: fixed;
|
||||
bottom: 4vh;
|
||||
width: 368px;
|
||||
left: calc(50% - 184px);
|
||||
color: rgba(0, 0, 0, 0.45);
|
||||
font-size: 14px;
|
||||
.help {
|
||||
margin: 0 auto;
|
||||
margin-bottom: 1vh;
|
||||
width: 60%;
|
||||
.item {
|
||||
color: rgba(0, 0, 0, 0.45);
|
||||
}
|
||||
:hover {
|
||||
color: rgba(0, 0, 0, 0.65);
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
102
buyer/src/pages/home/Main.vue
Normal file
@@ -0,0 +1,102 @@
|
||||
<template>
|
||||
<div class="wrapper">
|
||||
<div class="orderBox">
|
||||
<!-- <ul class="orderUl">
|
||||
<li>
|
||||
<div class="circle">
|
||||
<Icon size="50" type="ios-card" />
|
||||
</div>
|
||||
<div class="info">
|
||||
<Badge :count="0"> 代付款 </Badge>
|
||||
</div>
|
||||
</li>
|
||||
<li>
|
||||
<div class="circle">
|
||||
<Icon size="50" type="ios-card" />
|
||||
</div>
|
||||
<div class="info">
|
||||
<Badge :count="0"> 待收货 </Badge>
|
||||
</div>
|
||||
</li>
|
||||
<li>
|
||||
<div class="circle">
|
||||
<Icon size="50" type="ios-card" />
|
||||
</div>
|
||||
<div class="info">
|
||||
<Badge :count="0"> 待评价 </Badge>
|
||||
</div>
|
||||
</li>
|
||||
</ul> -->
|
||||
<div class="userBox">
|
||||
<div class="box">
|
||||
<!-- 我的订单组件 -->
|
||||
<myOrderPage :paging="false" :homePage="true" />
|
||||
</div>
|
||||
<div class="box">
|
||||
<!-- 近期收藏 -->
|
||||
<myFavorites :paging="false" :homePage="true" />
|
||||
</div>
|
||||
<div class="box">
|
||||
<!-- 猜你喜欢 -->
|
||||
<!-- <myLike /> -->
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import myOrderPage from '@/pages/home/orderCenter/MyOrder'
|
||||
import myFavorites from '@/pages/home/memberCenter/Favorites'
|
||||
// import myLike from '@/components/like'
|
||||
|
||||
export default {
|
||||
name: 'main',
|
||||
components: {
|
||||
myOrderPage,
|
||||
myFavorites
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.circle {
|
||||
width: 70px;
|
||||
height: 70px;
|
||||
border-radius: 50%;
|
||||
overflow: hidden;
|
||||
background: $success_color;
|
||||
margin: 0 auto;
|
||||
text-align: center;
|
||||
color: #fff;
|
||||
|
||||
> i {
|
||||
line-height: 70px;
|
||||
}
|
||||
}
|
||||
|
||||
.info {
|
||||
text-align: center;
|
||||
font-size: 18px;
|
||||
margin: 10px 0;
|
||||
}
|
||||
|
||||
.orderUl {
|
||||
overflow: hidden;
|
||||
|
||||
> li {
|
||||
cursor: pointer;
|
||||
border-radius: 0.4em;
|
||||
float: left;
|
||||
padding: 10px 0;
|
||||
margin: 0 11px;
|
||||
width: 200px;
|
||||
text-align: center;
|
||||
|
||||
@include background_color($light_background_color);
|
||||
}
|
||||
}
|
||||
.userBox {
|
||||
padding: 0 0 20px 0;
|
||||
}
|
||||
</style>
|
||||
86
buyer/src/pages/home/MyShoppingCart.vue
Normal file
@@ -0,0 +1,86 @@
|
||||
<template>
|
||||
<div>
|
||||
<Table border ref="selection" :columns="columns" :data="shoppingCart" size="large" no-data-text="您的购物车没有商品,请先添加商品到购物车再点击购买"></Table>
|
||||
<div class="go-to">
|
||||
<Button @click="goTo" type="primary">去付款</Button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import store from '@/vuex/store';
|
||||
import { mapState, mapActions } from 'vuex';
|
||||
export default {
|
||||
name: 'MyShoppingCart',
|
||||
data () {
|
||||
return {
|
||||
columns: [ // 表格表头
|
||||
{
|
||||
type: 'selection',
|
||||
width: 58,
|
||||
align: 'center'
|
||||
},
|
||||
{
|
||||
title: '图片',
|
||||
key: 'img',
|
||||
width: 86,
|
||||
render: (h, params) => {
|
||||
return h('div', [
|
||||
h('img', {
|
||||
attrs: {
|
||||
src: params.row.img
|
||||
}
|
||||
})
|
||||
]);
|
||||
},
|
||||
align: 'center'
|
||||
},
|
||||
{
|
||||
title: '标题',
|
||||
key: 'title',
|
||||
align: 'center'
|
||||
},
|
||||
{
|
||||
title: '套餐',
|
||||
width: 198,
|
||||
key: 'package',
|
||||
align: 'center'
|
||||
},
|
||||
{
|
||||
title: '数量',
|
||||
key: 'count',
|
||||
width: 68,
|
||||
align: 'center'
|
||||
},
|
||||
{
|
||||
title: '价格',
|
||||
width: 68,
|
||||
key: 'price',
|
||||
align: 'center'
|
||||
}
|
||||
]
|
||||
};
|
||||
},
|
||||
created () {
|
||||
this.loadShoppingCart();
|
||||
},
|
||||
computed: {
|
||||
...mapState(['shoppingCart'])
|
||||
},
|
||||
methods: {
|
||||
...mapActions(['loadShoppingCart']),
|
||||
goTo () {
|
||||
this.$router.push('/cart');
|
||||
}
|
||||
},
|
||||
store
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.go-to {
|
||||
margin: 15px;
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
}
|
||||
</style>
|
||||
79
buyer/src/pages/home/enumeration.js
Normal file
@@ -0,0 +1,79 @@
|
||||
|
||||
// 订单状态
|
||||
export const orderStatusList = [
|
||||
{
|
||||
name: '全部',
|
||||
status: 'ALL'
|
||||
},
|
||||
{
|
||||
name: '未付款',
|
||||
status: 'UNPAID'
|
||||
},
|
||||
{
|
||||
name: '已付款',
|
||||
status: 'PAID'
|
||||
},
|
||||
{
|
||||
name: '待发货',
|
||||
status: 'UNDELIVERED'
|
||||
},
|
||||
{
|
||||
name: '已发货',
|
||||
status: 'DELIVERED'
|
||||
},
|
||||
{
|
||||
name: '已完成',
|
||||
status: 'COMPLETED'
|
||||
},
|
||||
{
|
||||
name: '待核验',
|
||||
status: 'TAKE'
|
||||
},
|
||||
{
|
||||
name: '已取消',
|
||||
status: 'CANCELLED'
|
||||
}
|
||||
]
|
||||
// 订单售后状态
|
||||
export const afterSaleStatusList = [
|
||||
{
|
||||
name: '申请中',
|
||||
status: 'APPLY'
|
||||
},
|
||||
{
|
||||
name: '通过',
|
||||
status: 'PASS'
|
||||
},
|
||||
{
|
||||
name: '拒绝',
|
||||
status: 'REFUSE'
|
||||
},
|
||||
{
|
||||
name: '买家退货,待卖家收货',
|
||||
status: 'BUYER_RETURN'
|
||||
},
|
||||
{
|
||||
name: '商家换货/补发',
|
||||
status: 'SELLER_RE_DELIVERY'
|
||||
},
|
||||
{
|
||||
name: '卖家确认收货',
|
||||
status: 'SELLER_CONFIRM'
|
||||
},
|
||||
{
|
||||
name: '卖家终止售后',
|
||||
status: 'SELLER_TERMINATION'
|
||||
},
|
||||
{
|
||||
name: '买家确认收货',
|
||||
status: 'BUYER_CONFIRM'
|
||||
},
|
||||
{
|
||||
name: '买家取消售后',
|
||||
status: 'BUYER_CANCEL'
|
||||
},
|
||||
{
|
||||
name: '完成售后',
|
||||
status: 'COMPLETE'
|
||||
}
|
||||
]
|
||||