commit message

This commit is contained in:
Chopper
2021-05-13 10:56:04 +08:00
commit ec3e958037
728 changed files with 132685 additions and 0 deletions

37
buyer/src/App.vue Normal file
View 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
View 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
View 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
View 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 设置选中 01
*/
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 设置选中01
*/
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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
});
}

View 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
});
}

View 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
})
}

View 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";
}

Binary file not shown.

File diff suppressed because one or more lines are too long

View 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
}
]
}

View 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="&#59110;" 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="&#58947;" 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="&#58881;" 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="&#58995;" 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="&#58880;" 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="&#60174;" 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

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 126 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 169 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 131 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1019 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 138 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 302 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 59 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 117 B

View 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;
}
}
}

View 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;
}
}

View 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;
}

View 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();

View 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;
}
}

View 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>

View 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>

View 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>

View File

@@ -0,0 +1,2 @@
# 广告
## FixedTop 顶部广告

View File

@@ -0,0 +1,12 @@
## 自定义card -
### 参数
>_Title 卡片头部
>_More 右侧栏显示内容 -- 默认不显示
>_Src 右侧内容显示之后的src路径
>_Tabs 传入数组 -- 默认无
>_Change 点击数组返回的index

View 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>

View 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>

View 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>&nbsp; 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>

View 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>

View File

@@ -0,0 +1,42 @@
# 右侧侧边栏组件
> 本组件依赖于iview的组件基础上进行封装
>项目结构
>* Main -- 组件用于挂在右侧的横栏
>* drawer -- 右侧横栏的内容
>* config -- 用于设置大小
#### config设置
```
/**
menuList // 组件的menu
display //是否显示此menu
badge //显示徽标数
titleShow //是否显示title
*/
//实例代码
width : 50, //bar的大小
menuList:[
{
icon
}
]
```
> 账户信息
> 购物车
> 我的订单
> 优惠券
> 我的资产
> 我的足迹
> 我的收藏
> 邮箱订阅
## 如何使用
1.

View 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

View 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{
}

View 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>

View File

@@ -0,0 +1,10 @@
# 空状态封装
```
// _Title
<empty></empty> //默认显示
q
<empty _Title='暂无更多了' ></empty> //自定义返回标题
```

View 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>

View 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)
}

View 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>

View 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"> &nbsp;&nbsp;&nbsp;&nbsp;</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']"> &nbsp;&nbsp;</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">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</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>

View 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>

View 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>

View 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>

View 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>

View 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>

View 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>

View 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>

View 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>

View 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>

View File

@@ -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>

View 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 }} &gt;</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 }} &gt;</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 }} &gt;</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>

View 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>

View 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 }}&gt;</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 }}&gt;</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>

View 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>

View File

@@ -0,0 +1,3 @@
## 此组件为结算页面修改发票信息使用 后续可以复用到个人信息添加发票页面
### 目前没有参数,之后会设置一个参数接收历史的单位发票数据

View 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>

View 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>

View 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>

View 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>

View 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>

View 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>

View 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>

View 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>

View 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
View 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
View 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/>'
});

View 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
View 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="/">去选购&gt;</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>

View 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>

View 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>

View 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
View 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
View 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>

View 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>

View 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
View 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>

View 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">&lt;返回上一级</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>

View 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>

View 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>

View 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>

View 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>

View 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'
}
]

Some files were not shown because too many files have changed in this diff Show More