mirror of
https://gitee.com/beijing_hongye_huicheng/lilishop-ui.git
synced 2026-11-06 17:09:08 +08:00
feat(buyer): 新增功能并优化样式,提升用户体验
- 新增 `getMemberMessage` 接口方法,用于获取会员消息 - 调整全局及商品列表样式,提升可读性与一致性 - 精简 `Search.vue`,移除不必要的店铺搜索切换 - 放宽 `addressManage` 中地址别名的输入长度 - 优化 `ShowGoods.vue` 和 `ShowGoodsDetail.vue` 的布局与样式 - 更新 `Cart.vue` 中的购物车步骤展示,让流程导航更清晰 - 调整多个组件,统一字号并优化界面元素
This commit is contained in:
@@ -446,6 +446,15 @@ export function memberMsgList (params) {
|
||||
* @param {String} messageId 消息id
|
||||
*/
|
||||
|
||||
export function getMemberMessage (id) {
|
||||
return request({
|
||||
url: `/buyer/message/member/${id}`,
|
||||
method: Method.GET,
|
||||
needToken: true,
|
||||
skipMessage: true
|
||||
});
|
||||
}
|
||||
|
||||
export function readMemberMsg (id) {
|
||||
return request({
|
||||
url: `/buyer/message/member/${id}`,
|
||||
|
||||
@@ -355,16 +355,17 @@ li {
|
||||
margin-top: 6px;
|
||||
}
|
||||
.goods-show-detail {
|
||||
font-size: 12px;
|
||||
font-size: 14px;
|
||||
line-height: 21px;
|
||||
margin: 6px 0px;
|
||||
}
|
||||
.goods-show-num {
|
||||
font-size: 12px;
|
||||
font-size: 14px;
|
||||
margin-bottom: 6px;
|
||||
color: #666;
|
||||
}
|
||||
.goods-show-num {
|
||||
font-size: 12px;
|
||||
font-size: 14px;
|
||||
margin-bottom: 6px;
|
||||
color: #009688;
|
||||
}
|
||||
@@ -373,7 +374,7 @@ li {
|
||||
font-weight: bold;
|
||||
}
|
||||
.goods-show-seller {
|
||||
font-size: 12px;
|
||||
font-size: 14px;
|
||||
color: $theme_color;
|
||||
}
|
||||
.goods-page {
|
||||
|
||||
@@ -36,8 +36,9 @@
|
||||
margin-top: 6px;
|
||||
}
|
||||
.goods-show-detail {
|
||||
height: 36px;
|
||||
font-size: 12px;
|
||||
height: 42px;
|
||||
font-size: 14px;
|
||||
line-height: 21px;
|
||||
margin: 6px 0px;
|
||||
overflow:hidden;
|
||||
text-overflow: ellipsis;
|
||||
@@ -51,12 +52,12 @@
|
||||
color:#E23A3A;
|
||||
}
|
||||
.goods-show-num {
|
||||
font-size: 12px;
|
||||
font-size: 14px;
|
||||
margin-bottom: 6px;
|
||||
color: #666;
|
||||
}
|
||||
.goods-show-num {
|
||||
font-size: 12px;
|
||||
font-size: 14px;
|
||||
margin-bottom: 6px;
|
||||
color: #009688;
|
||||
}
|
||||
@@ -65,7 +66,7 @@
|
||||
font-weight: bold;
|
||||
}
|
||||
.goods-show-seller {
|
||||
font-size: 12px;
|
||||
font-size: 14px;
|
||||
color: $theme_color;
|
||||
}
|
||||
.goods-page {
|
||||
|
||||
@@ -37,10 +37,6 @@
|
||||
</div>
|
||||
</div>
|
||||
<template v-if="showTag">
|
||||
<div class="only-store" v-if="storeId" @click="research()">
|
||||
切换为{{!onlyStore ? '店铺内' : '平台'}}搜索
|
||||
|
||||
</div>
|
||||
<div v-if="promotionTags.length === 0"></div>
|
||||
<div v-else class="history-list flex">
|
||||
<div
|
||||
@@ -88,15 +84,9 @@ export default {
|
||||
default:''
|
||||
}
|
||||
},
|
||||
watch:{
|
||||
storeId(val){
|
||||
this.onlyStore = val ? true : false
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
searchData: '', // 搜索内容
|
||||
onlyStore:false,
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
@@ -104,9 +94,6 @@ export default {
|
||||
this.searchData = item;
|
||||
this.search();
|
||||
},
|
||||
research(){
|
||||
this.onlyStore = !this.onlyStore
|
||||
},
|
||||
search () { // 全平台搜索商品
|
||||
const url = this.$route.path;
|
||||
if(url == '/goodsList'){
|
||||
@@ -116,8 +103,7 @@ export default {
|
||||
path:'/goodsList',
|
||||
query: { keyword: this.searchData },
|
||||
}
|
||||
if(this.storeId && this.onlyStore) pushData.query.storeId = this.storeId
|
||||
|
||||
if(this.storeId) pushData.query.storeId = this.storeId
|
||||
|
||||
this.$router.push(pushData);
|
||||
}
|
||||
@@ -162,11 +148,6 @@ export default {
|
||||
};
|
||||
</script>
|
||||
<style scoped lang="scss">
|
||||
.only-store{
|
||||
text-align: right;
|
||||
color:$theme_color;
|
||||
cursor: pointer;
|
||||
}
|
||||
.navbar {
|
||||
height: 113px;
|
||||
background: #fff;
|
||||
|
||||
@@ -24,8 +24,8 @@
|
||||
<el-form-item label="地址别名">
|
||||
<el-input
|
||||
v-model="formData.alias"
|
||||
length
|
||||
:maxlength="4"
|
||||
:maxlength="5"
|
||||
show-word-limit
|
||||
placeholder="请输入地址别名,例如公司"
|
||||
style="width: 600px"
|
||||
></el-input>
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
|
||||
<div
|
||||
class="item-detail-img-small"
|
||||
:class="{ 'is-active': imgIndex === index }"
|
||||
@mouseover="imgIndex = index"
|
||||
v-for="(item, index) in imgList"
|
||||
:key="index"
|
||||
@@ -84,7 +85,7 @@
|
||||
>
|
||||
<p>
|
||||
<span class="item-price-title" v-if="promotionMap['SECKILL']"
|
||||
>秒 杀 价</span>
|
||||
>秒杀价</span>
|
||||
<span class="item-price">{{ $filters.unitPrice(skuDetail.promotionPrice, "¥") }}</span>
|
||||
<span class="item-price-old">{{ $filters.unitPrice(skuDetail.price, "¥") }}</span>
|
||||
</p>
|
||||
@@ -94,9 +95,7 @@
|
||||
<!-- 批发价格 -->
|
||||
<div v-if="!isECouponGoods && wholesaleNum && wholesaleNum.length">
|
||||
<div class="flex">
|
||||
<div class="item-price-title">
|
||||
价 格
|
||||
</div>
|
||||
<div class="item-price-title">价格</div>
|
||||
|
||||
<div
|
||||
v-for="(item, index) in wholesalePrice"
|
||||
@@ -107,7 +106,7 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex">
|
||||
<div class="item-price-title">起 批 量</div>
|
||||
<div class="item-price-title">起批量</div>
|
||||
<div
|
||||
v-for="(item, index) in wholesaleNum"
|
||||
:key="index"
|
||||
@@ -120,15 +119,14 @@
|
||||
|
||||
<!-- 普通价格 -->
|
||||
<div v-else>
|
||||
<span class="item-price-title"
|
||||
>价 格</span>
|
||||
<span class="item-price-title">价格</span>
|
||||
<span class="item-price">{{ $filters.unitPrice(skuDetail.price, "¥") }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<!-- 优惠券展示 -->
|
||||
<div class="item-price-coupon-row" v-if="promotionMap['COUPON'].length">
|
||||
<div class="Ellipsis">
|
||||
<span class="item-price-title">优 惠 券</span>
|
||||
<span class="item-price-title">优惠券</span>
|
||||
<span>
|
||||
<span
|
||||
class="item-coupon"
|
||||
@@ -168,7 +166,7 @@
|
||||
<!-- 限时折扣 -->
|
||||
<div class="item-price-row" v-if="promotionMap['DISCOUNT']">
|
||||
<p>
|
||||
<span class="item-price-title">促 销</span>
|
||||
<span class="item-price-title">促销</span>
|
||||
<span class="item-promotion">限时折扣</span>
|
||||
<span class="item-desc-pintuan" v-if="promotionMap['DISCOUNT'].discount">
|
||||
享 {{ promotionMap["DISCOUNT"].discount }} 折
|
||||
@@ -178,7 +176,7 @@
|
||||
<!-- 第N件优惠 -->
|
||||
<div class="item-price-row" v-if="promotionMap['NTH']">
|
||||
<p>
|
||||
<span class="item-price-title">促 销</span>
|
||||
<span class="item-price-title">促销</span>
|
||||
<span class="item-promotion">第N件</span>
|
||||
<span class="item-desc-pintuan">
|
||||
第 {{ promotionMap["NTH"].nthNum || promotionMap["NTH"].num }} 件优惠
|
||||
@@ -188,7 +186,7 @@
|
||||
<!-- 拼团 -->
|
||||
<div class="item-price-row" v-if="promotionMap['PINTUAN']">
|
||||
<p>
|
||||
<span class="item-price-title">拼 团</span>
|
||||
<span class="item-price-title">拼团</span>
|
||||
<span class="item-promotion">拼团价</span>
|
||||
<span class="item-desc-pintuan" v-if="promotionMap['PINTUAN'].price">
|
||||
{{ $filters.unitPrice(promotionMap["PINTUAN"].price, "¥") }}
|
||||
@@ -198,8 +196,7 @@
|
||||
<!-- 满减展示 -->
|
||||
<div class="item-price-row" v-if="promotionMap['FULL_DISCOUNT']">
|
||||
<p>
|
||||
<span class="item-price-title"
|
||||
>促 销</span>
|
||||
<span class="item-price-title">促销</span>
|
||||
<span class="item-promotion">满减</span>
|
||||
<span
|
||||
class="item-desc-pintuan"
|
||||
@@ -300,7 +297,7 @@
|
||||
<div class="item-select-column">
|
||||
<div class="add-buy-car">
|
||||
<el-button
|
||||
type="danger"
|
||||
class="goods-action-btn is-solid"
|
||||
:loading="loading"
|
||||
:disabled="skuDetail.quantity === 0"
|
||||
@click="pointPay"
|
||||
@@ -324,7 +321,7 @@
|
||||
>加入购物车</el-button
|
||||
>
|
||||
<el-button
|
||||
class="goods-action-btn"
|
||||
class="goods-action-btn is-solid"
|
||||
v-if="promotionMap['PINTUAN']"
|
||||
:loading="loadingPintuan"
|
||||
:disabled="isOutOfStock"
|
||||
@@ -332,7 +329,7 @@
|
||||
>拼团购买</el-button
|
||||
>
|
||||
<el-button
|
||||
class="goods-action-btn"
|
||||
class="goods-action-btn is-solid"
|
||||
:loading="loading1"
|
||||
:disabled="isOutOfStock"
|
||||
@click="buyNow"
|
||||
@@ -778,23 +775,28 @@ export default {
|
||||
.item-detail-show {
|
||||
width: 1200px;
|
||||
margin: 0 auto;
|
||||
padding: 30px;
|
||||
padding: 24px;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
background: #fff;
|
||||
border-radius: 4px;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.item-detail-left {
|
||||
width: 350px;
|
||||
|
||||
margin-right: 30px;
|
||||
margin-right: 32px;
|
||||
}
|
||||
|
||||
.item-detail-big-img {
|
||||
width: 350px;
|
||||
height: 350px;
|
||||
box-shadow: 0px 0px 8px $border_color;
|
||||
border: 1px solid #eee;
|
||||
border-radius: 4px;
|
||||
overflow: hidden;
|
||||
cursor: pointer;
|
||||
margin-bottom: 24px;
|
||||
margin-bottom: 12px;
|
||||
background: #fff;
|
||||
}
|
||||
#dplayer{
|
||||
width: 100%;
|
||||
@@ -807,14 +809,21 @@ export default {
|
||||
.item-detail-img-row {
|
||||
margin-top: 0;
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.item-detail-img-small {
|
||||
width: 68px;
|
||||
height: 68px;
|
||||
box-shadow: 0px 0px 8px #ccc;
|
||||
width: 64px;
|
||||
height: 64px;
|
||||
border: 1px solid #eee;
|
||||
border-radius: 4px;
|
||||
overflow: hidden;
|
||||
cursor: pointer;
|
||||
margin-left: 5px;
|
||||
box-sizing: border-box;
|
||||
|
||||
&.is-active {
|
||||
border-color: $theme_color;
|
||||
}
|
||||
}
|
||||
|
||||
.item-detail-img-small img {
|
||||
@@ -838,14 +847,17 @@ export default {
|
||||
}
|
||||
|
||||
.item-detail-name {
|
||||
@include content_color($light_content_color);
|
||||
font-weight: bold;
|
||||
color: #171A26;
|
||||
font-weight: 600;
|
||||
font-size: 20px;
|
||||
line-height: 1.4;
|
||||
line-height: 28px;
|
||||
}
|
||||
|
||||
.goods-type-tag {
|
||||
flex-shrink: 0;
|
||||
--el-tag-bg-color: #fafafa;
|
||||
--el-tag-border-color: #eee;
|
||||
--el-tag-text-color: #666;
|
||||
}
|
||||
|
||||
.item-detail-express {
|
||||
@@ -859,17 +871,18 @@ export default {
|
||||
/*商品标签*/
|
||||
.item-detail-tag {
|
||||
padding: 8px 0;
|
||||
font-size: 12px;
|
||||
font-size: 14px;
|
||||
color: $theme_color;
|
||||
}
|
||||
|
||||
/*价格详情等*/
|
||||
.item-detail-price-row {
|
||||
padding: 10px;
|
||||
padding: 16px 20px;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: space-between;
|
||||
background: url("../../assets/images/goodsDetail/price-bg.png");
|
||||
background: #fafafa;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.item-price-left {
|
||||
@@ -878,19 +891,30 @@ export default {
|
||||
}
|
||||
|
||||
.item-price-title {
|
||||
color: #999999;
|
||||
display: inline-block;
|
||||
width: 56px;
|
||||
margin-right: 12px;
|
||||
color: #666;
|
||||
font-size: 14px;
|
||||
margin-right: 15px;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.item-price-row {
|
||||
margin: 5px 0px;
|
||||
margin: 4px 0;
|
||||
|
||||
> div,
|
||||
> p {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.item-price {
|
||||
color: $theme_color;
|
||||
font-size: 20px;
|
||||
cursor: pointer;
|
||||
font-size: 28px;
|
||||
font-weight: 600;
|
||||
line-height: 1;
|
||||
}
|
||||
.item-price-old {
|
||||
color: gray;
|
||||
@@ -925,7 +949,7 @@ export default {
|
||||
align-items: center;
|
||||
color: $theme_color;
|
||||
margin: 5px 0;
|
||||
font-size: 12px;
|
||||
font-size: 14px;
|
||||
background-color: var(--theme-tint-12, #ffdedf);
|
||||
border: 1px dotted $theme_color;
|
||||
cursor: pointer;
|
||||
@@ -950,7 +974,7 @@ export default {
|
||||
margin-right: 5px;
|
||||
padding: 0 5px;
|
||||
color: $theme_color;
|
||||
font-size: 12px;
|
||||
font-size: 14px;
|
||||
background-color: var(--theme-tint-12, #ffdedf);
|
||||
border: 1px dotted $theme_color;
|
||||
cursor: pointer;
|
||||
@@ -963,7 +987,7 @@ export default {
|
||||
margin-right: 5px;
|
||||
padding: 3px;
|
||||
color: $theme_color;
|
||||
font-size: 12px;
|
||||
font-size: 14px;
|
||||
border: 1px solid $theme_color;
|
||||
}
|
||||
|
||||
@@ -974,22 +998,25 @@ export default {
|
||||
}
|
||||
|
||||
.item-remarks-sum {
|
||||
width: 70px;
|
||||
min-width: 72px;
|
||||
text-align: center;
|
||||
padding: 0 10px;
|
||||
border-left: 1px solid $border_color;
|
||||
padding: 0 4px 0 16px;
|
||||
border-left: 1px solid #eee;
|
||||
}
|
||||
|
||||
.item-remarks-sum p {
|
||||
color: #999999;
|
||||
font-size: 12px;
|
||||
line-height: 10px;
|
||||
color: #999;
|
||||
font-size: 13px;
|
||||
line-height: 20px;
|
||||
text-align: center;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.item-remarks-num {
|
||||
line-height: 18px;
|
||||
color: #005eb7;
|
||||
line-height: 24px;
|
||||
color: #171A26;
|
||||
font-size: 16px;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.item-select {
|
||||
@@ -1000,10 +1027,10 @@ export default {
|
||||
}
|
||||
|
||||
.item-select-title {
|
||||
@include content_color($light_content_color);
|
||||
color: #666;
|
||||
font-size: 14px;
|
||||
margin-right: 15px;
|
||||
width: 60px;
|
||||
margin-right: 16px;
|
||||
width: 56px;
|
||||
flex-shrink: 0;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
@@ -1033,32 +1060,39 @@ export default {
|
||||
}
|
||||
|
||||
.item-select-box {
|
||||
padding: 5px;
|
||||
min-height: 36px;
|
||||
padding: 0 16px;
|
||||
margin-right: 8px;
|
||||
@include background_color($light_background_color);
|
||||
border: 0.5px solid $border_color;
|
||||
background: #fff;
|
||||
border: 1px solid #e5e5e5;
|
||||
border-radius: 4px;
|
||||
cursor: pointer;
|
||||
@include content_color($light_content_color);
|
||||
color: #171A26;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.item-select-box:hover {
|
||||
border: 0.5px solid $theme_color;
|
||||
border-color: $theme_color;
|
||||
color: $theme_color;
|
||||
}
|
||||
|
||||
.item-select-box-active {
|
||||
border: 0.5px solid $theme_color;
|
||||
border-color: $theme_color;
|
||||
background: #fff5f4;
|
||||
color: $theme_color;
|
||||
}
|
||||
|
||||
.item-select-intro p {
|
||||
margin: 0px;
|
||||
padding: 5px;
|
||||
margin: 0;
|
||||
padding: 8px 0;
|
||||
font-size: 14px;
|
||||
line-height: 20px;
|
||||
}
|
||||
|
||||
.add-buy-car-box {
|
||||
width: 100%;
|
||||
|
||||
margin-top: 15px;
|
||||
border-top: 1px dotted $border_color;
|
||||
margin-top: 8px;
|
||||
border-top: 1px solid #f0f0f0;
|
||||
}
|
||||
|
||||
.e-coupon-after-sale-notice {
|
||||
@@ -1072,7 +1106,7 @@ export default {
|
||||
}
|
||||
|
||||
:deep(.el-alert__title) {
|
||||
font-size: 12px;
|
||||
font-size: 14px;
|
||||
line-height: 1.5;
|
||||
}
|
||||
}
|
||||
@@ -1107,23 +1141,36 @@ export default {
|
||||
}
|
||||
|
||||
.goods-action-btn {
|
||||
background-color: #ff475d !important;
|
||||
border-color: #ff475d !important;
|
||||
color: #fff !important;
|
||||
height: 40px;
|
||||
min-width: 140px;
|
||||
padding: 0 24px;
|
||||
border-radius: 4px;
|
||||
font-size: 16px;
|
||||
background: #fff !important;
|
||||
border: 1px solid $theme_color !important;
|
||||
color: $theme_color !important;
|
||||
|
||||
&:hover,
|
||||
&:focus {
|
||||
background-color: #e63e52 !important;
|
||||
border-color: #e63e52 !important;
|
||||
background: #fff5f4 !important;
|
||||
border-color: $theme_color !important;
|
||||
color: $theme_color !important;
|
||||
}
|
||||
|
||||
&.is-solid {
|
||||
background: $theme_color !important;
|
||||
color: #fff !important;
|
||||
|
||||
&:hover,
|
||||
&:focus {
|
||||
background: $theme_color !important;
|
||||
color: #fff !important;
|
||||
}
|
||||
}
|
||||
|
||||
&.is-disabled,
|
||||
&.is-disabled:hover,
|
||||
&.is-disabled:focus {
|
||||
background-color: #ff475d !important;
|
||||
border-color: #ff475d !important;
|
||||
color: #fff !important;
|
||||
opacity: 0.5;
|
||||
}
|
||||
}
|
||||
@@ -1160,9 +1207,16 @@ export default {
|
||||
}
|
||||
}
|
||||
.sell-point {
|
||||
font-size: 12px;
|
||||
color: red;
|
||||
margin-bottom: 5px;
|
||||
font-size: 14px;
|
||||
line-height: 22px;
|
||||
color: #999;
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
|
||||
.inventory {
|
||||
padding-left: 8px;
|
||||
color: #999;
|
||||
font-size: 13px;
|
||||
}
|
||||
.view-video{
|
||||
cursor: pointer;
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -238,8 +238,8 @@ export default {
|
||||
|
||||
.box {
|
||||
width: 100%;
|
||||
font-size: 12px !important;
|
||||
height: 36px;
|
||||
font-size: 14px;
|
||||
height: 40px;
|
||||
background: #333;
|
||||
color: #fff;
|
||||
display: flex;
|
||||
@@ -266,7 +266,7 @@ export default {
|
||||
.location > ul.flex > li {
|
||||
cursor: pointer;
|
||||
float: none;
|
||||
line-height: 36px;
|
||||
line-height: 40px;
|
||||
margin-right: 15px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
@@ -274,7 +274,7 @@ export default {
|
||||
|
||||
.nav a,
|
||||
.nav-item {
|
||||
font-size: 13px;
|
||||
font-size: 14px;
|
||||
font-weight: normal;
|
||||
text-decoration: none;
|
||||
cursor: pointer;
|
||||
@@ -297,7 +297,7 @@ export default {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
vertical-align: middle;
|
||||
line-height: 36px;
|
||||
line-height: 40px;
|
||||
}
|
||||
|
||||
:deep(.el-tooltip__trigger),
|
||||
@@ -429,7 +429,7 @@ export default {
|
||||
justify-content: space-between;
|
||||
margin-top: 8px;
|
||||
color: #999;
|
||||
font-size: 12px;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.shopping-price {
|
||||
@@ -477,7 +477,7 @@ export default {
|
||||
padding: 8px 16px;
|
||||
line-height: 1.4;
|
||||
color: #666;
|
||||
font-size: 13px;
|
||||
font-size: 14px;
|
||||
font-weight: normal;
|
||||
text-align: center;
|
||||
white-space: nowrap;
|
||||
@@ -556,7 +556,7 @@ export default {
|
||||
}
|
||||
|
||||
.my-info p {
|
||||
font-size: 12px;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.sign-out {
|
||||
@@ -576,7 +576,7 @@ export default {
|
||||
}
|
||||
|
||||
.sign-out p {
|
||||
font-size: 12px;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.goods-title:hover {
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
<template>
|
||||
<el-dialog width="800" v-model="enableMap">
|
||||
<el-radio-group @change="changeMap" v-model="mapDefault" type="button">
|
||||
<el-radio label="select">级联选择</el-radio>
|
||||
<el-radio label="map" v-if="aMapSwitch">高德地图</el-radio>
|
||||
<el-radio-group v-if="aMapSwitch" @change="changeMap" v-model="mapDefault">
|
||||
<el-radio label="select">地区选择</el-radio>
|
||||
<el-radio label="map">高德地图</el-radio>
|
||||
</el-radio-group>
|
||||
<div>
|
||||
<div v-if="mapDefault === 'select'">
|
||||
|
||||
@@ -26,31 +26,22 @@
|
||||
:style="{'top':!showNavBar ?'60px':'46px'}"
|
||||
v-show="showAlways || showFirstList"
|
||||
@mouseenter="showFirstList = true"
|
||||
@mouseleave="showFirstList = false"
|
||||
@mouseleave="closePanel"
|
||||
>
|
||||
<!-- 第一级分类 -->
|
||||
<div
|
||||
class="nav-side"
|
||||
:class="{ 'large-nav': large, 'opacity-nav': opacity }"
|
||||
@mouseleave="panel = false"
|
||||
>
|
||||
<ul>
|
||||
<li
|
||||
v-for="(item, index) in cateList"
|
||||
:key="index"
|
||||
:class="{ 'is-active': panel && panelIndex === index }"
|
||||
@mouseenter="showDetail(index)"
|
||||
>
|
||||
<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>
|
||||
<span class="nav-side-item" @click="goGoodsList(item.id)">{{ item.name }}</span>
|
||||
<el-icon><ArrowRight /></el-icon>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
@@ -139,6 +130,7 @@ export default {
|
||||
data() {
|
||||
return {
|
||||
panel: false, // 二级分类展示
|
||||
panelIndex: -1,
|
||||
panelData: [], // 二级分类数据
|
||||
showFirstList: false, // 始终展示一级列表
|
||||
cateList: [], // 商品分类
|
||||
@@ -189,8 +181,14 @@ export default {
|
||||
showDetail(index) {
|
||||
// 展示全部分类
|
||||
this.panel = true;
|
||||
this.panelIndex = index;
|
||||
this.panelData = this.cateList[index].children;
|
||||
},
|
||||
closePanel() {
|
||||
this.showFirstList = false;
|
||||
this.panel = false;
|
||||
this.panelIndex = -1;
|
||||
},
|
||||
goGoodsList(id, secondId, firstId) {
|
||||
// 分类共有三级,传全部分类过去
|
||||
const arr = [firstId, secondId, id];
|
||||
@@ -278,16 +276,15 @@ export default {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
height: 46px;
|
||||
border-top-left-radius: 10px;
|
||||
border-top-right-radius: 10px;
|
||||
padding-left: 37.4px;
|
||||
border-top-left-radius: 4px;
|
||||
border-top-right-radius: 4px;
|
||||
padding-left: 16px;
|
||||
background: #FFFFFF;
|
||||
width: 263.2px;
|
||||
border-bottom: none;
|
||||
font-size: 16.8px;
|
||||
font-weight: normal;
|
||||
color: #333333;
|
||||
letter-spacing: 0px;
|
||||
font-size: 15px;
|
||||
font-weight: 600;
|
||||
color: #171A26;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
.nav-item {
|
||||
@@ -304,9 +301,9 @@ export default {
|
||||
display: flex;
|
||||
li {
|
||||
float: left;
|
||||
font-size: 17px;
|
||||
font-weight: normal;
|
||||
color: #333333;
|
||||
font-size: 15px;
|
||||
font-weight: 400;
|
||||
color: #171A26;
|
||||
|
||||
|
||||
&:hover {
|
||||
@@ -325,14 +322,13 @@ export default {
|
||||
|
||||
.nav-side {
|
||||
width: 263.2px;
|
||||
color: #666;
|
||||
color: #171A26;
|
||||
float: left;
|
||||
overflow:hidden;
|
||||
|
||||
border-bottom-left-radius: 10px;
|
||||
border-bottom-right-radius: 10px;
|
||||
overflow: hidden;
|
||||
border-bottom-left-radius: 4px;
|
||||
border-bottom-right-radius: 4px;
|
||||
background-color: #fff;
|
||||
height: 340px;
|
||||
height: 344px;
|
||||
////自动移滚动条样式
|
||||
//&::-webkit-scrollbar {
|
||||
// width: 1px;
|
||||
@@ -349,24 +345,53 @@ export default {
|
||||
}
|
||||
.large-nav {
|
||||
height: 470px;
|
||||
ul > li {
|
||||
line-height: 20px;
|
||||
}
|
||||
}
|
||||
.opacity-nav {
|
||||
background-color: rgba(0, 0, 0, 0.5);
|
||||
}
|
||||
.nav-side ul {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
list-style: none;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
.nav-side li {
|
||||
padding: 0 0 16.2px 37.4px;
|
||||
font-size: 13px;
|
||||
line-height: 18px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
flex: 1 1 0;
|
||||
min-height: 0;
|
||||
height: auto;
|
||||
padding: 0 12px 0 16px;
|
||||
font-size: 14px;
|
||||
line-height: 20px;
|
||||
box-sizing: border-box;
|
||||
cursor: pointer;
|
||||
|
||||
.el-icon {
|
||||
flex-shrink: 0;
|
||||
color: #ccc;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
&:hover,
|
||||
&.is-active {
|
||||
background: #fff5f4;
|
||||
color: $theme_color;
|
||||
|
||||
.el-icon {
|
||||
color: $theme_color;
|
||||
}
|
||||
}
|
||||
}
|
||||
.nav-side-item {
|
||||
min-width: 0;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.nav-side-item:hover {
|
||||
cursor: pointer;
|
||||
@@ -375,63 +400,102 @@ export default {
|
||||
|
||||
/*显示商品详细信息*/
|
||||
.detail-item-panel {
|
||||
width: 1000px;
|
||||
width: 936px;
|
||||
min-height: 340px;
|
||||
background-color: #fff;
|
||||
box-shadow: 0px 0px 15px #ccc;
|
||||
box-shadow: 0 8px 24px rgba(0, 0, 0, 0.08);
|
||||
border-radius: 0 4px 4px 0;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 200px;
|
||||
left: 263.2px;
|
||||
z-index: 1000;
|
||||
padding: 15px;
|
||||
padding: 8px 20px 16px;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
.nav-detail-item {
|
||||
margin-top: 5px;
|
||||
margin-bottom: 15px;
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 4px 20px;
|
||||
margin: 8px 0 4px;
|
||||
padding-bottom: 8px;
|
||||
border-bottom: 1px solid #f0f0f0;
|
||||
cursor: pointer;
|
||||
color: #eee;
|
||||
}
|
||||
.nav-detail-item span {
|
||||
padding: 6px;
|
||||
padding-left: 12px;
|
||||
margin-right: 15px;
|
||||
font-size: 12px;
|
||||
color: #333;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 2px;
|
||||
padding: 4px 0;
|
||||
font-size: 14px;
|
||||
font-weight: 600;
|
||||
color: #171A26;
|
||||
|
||||
.el-icon {
|
||||
font-size: 12px;
|
||||
color: #ccc;
|
||||
}
|
||||
}
|
||||
.nav-detail-item span:hover {
|
||||
background-color: $theme_color;
|
||||
color: #fff;
|
||||
color: $theme_color;
|
||||
|
||||
.el-icon {
|
||||
color: $theme_color;
|
||||
}
|
||||
}
|
||||
.detail-item-panel li {
|
||||
line-height: 30px;
|
||||
line-height: 28px;
|
||||
}
|
||||
.detail-item-title {
|
||||
font-weight: bold;
|
||||
font-size: 12px;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 2px;
|
||||
flex-shrink: 0;
|
||||
width: 108px;
|
||||
font-weight: 600;
|
||||
font-size: 14px;
|
||||
line-height: 28px;
|
||||
cursor: pointer;
|
||||
color: #555555;
|
||||
padding-right: 10px;
|
||||
width: 81px;
|
||||
text-align: right;
|
||||
color: #171A26;
|
||||
text-align: left;
|
||||
|
||||
.glyphicon {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.el-icon {
|
||||
font-size: 12px;
|
||||
color: #ccc;
|
||||
}
|
||||
}
|
||||
.detail-item-title:hover {
|
||||
color: $theme_color;
|
||||
|
||||
.el-icon {
|
||||
color: $theme_color;
|
||||
}
|
||||
}
|
||||
.detail-item-row {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
padding: 6px 0;
|
||||
|
||||
> div {
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
}
|
||||
.detail-item {
|
||||
font-size: 12px;
|
||||
padding-left: 8px;
|
||||
padding-right: 8px;
|
||||
font-size: 14px;
|
||||
line-height: 28px;
|
||||
padding: 0 12px;
|
||||
color: #666;
|
||||
cursor: pointer;
|
||||
border-left: 1px solid #ccc;
|
||||
border: none;
|
||||
|
||||
&:first-child {
|
||||
border: none;
|
||||
padding-left: 0;
|
||||
padding-left: 12px;
|
||||
}
|
||||
}
|
||||
.detail-item:hover {
|
||||
|
||||
@@ -29,9 +29,9 @@
|
||||
</template>
|
||||
<!-- 无商品分类,展示搜索结果 -->
|
||||
<template v-else>
|
||||
<div style="font-size:14px">全部结果</div>
|
||||
<div class="result-label">全部结果</div>
|
||||
<el-icon><ArrowRight /></el-icon>
|
||||
<div style="font-weight:bold;" class="mr_10">“{{params.keyword}}”</div>
|
||||
<div class="result-keyword">“{{params.keyword}}”</div>
|
||||
</template>
|
||||
<!-- 所选分类 -->
|
||||
<a
|
||||
@@ -50,43 +50,26 @@
|
||||
<!-- 品牌, 有图片,独立出来 -->
|
||||
<div class="brand" v-show="tagsContent[0].show && tagsContent[0].values.length">
|
||||
<div>
|
||||
<strong>{{ tagsContent[0].key }}:</strong>
|
||||
{{ tagsContent[0].key }}:
|
||||
</div>
|
||||
<div>
|
||||
<ul :class="{ 'show-more': tagsContent[0].more }">
|
||||
<li :class="{ 'is-active': !isGroupSelected(0) }" @click="selectAll(0)">
|
||||
<span>全部</span>
|
||||
</li>
|
||||
<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>
|
||||
<el-icon><Check /></el-icon>
|
||||
</div>
|
||||
<span>{{ item.name }}</span>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<div class="btn" v-show="multiple !== 0">
|
||||
<div class="btn" v-show="rowOverflow[0]">
|
||||
<span @click="moreBrand(0)"
|
||||
>{{ tagsContent[0].more ? "收起" : "更多"
|
||||
}}<el-icon><ArrowUp v-if="tagsContent[0].more" /><ArrowDown v-else /></el-icon></span>
|
||||
<span @click="multSelectBrand(0)"><el-icon><Plus /></el-icon>多选</span>
|
||||
</div>
|
||||
|
||||
<div class="multBtn" v-show="multiple === 0">
|
||||
<el-button
|
||||
type="primary"
|
||||
size="small"
|
||||
:disabled="!multSelected.length"
|
||||
@click="sure(0)"
|
||||
>确定</el-button
|
||||
>
|
||||
<el-button size="small" @click="cancel">取消</el-button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -95,14 +78,19 @@
|
||||
<template v-for="(tag, tagIndex) in tagsContent">
|
||||
<div class="other" v-if="tag.show && tagIndex !== 0" v-show="tagIndex < showTagCount" :key="tagIndex">
|
||||
<div>
|
||||
<strong>{{ tag.key }}:</strong>
|
||||
{{ tag.key }}:
|
||||
</div>
|
||||
<div>
|
||||
<ul
|
||||
:class="{ 'show-more': tag.more }"
|
||||
:data-index="tagIndex"
|
||||
class="list"
|
||||
v-show="multiple !== tagIndex"
|
||||
>
|
||||
<li
|
||||
class="item"
|
||||
:class="{ 'is-active': !isGroupSelected(tagIndex) }"
|
||||
@click="selectAll(tagIndex)"
|
||||
>全部</li>
|
||||
<li
|
||||
@click="selectBrand(item, tagIndex)"
|
||||
class="item"
|
||||
@@ -113,38 +101,10 @@
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<el-checkbox-group
|
||||
:class="{ 'show-more': tag.more }"
|
||||
class="list"
|
||||
v-model="multSelected"
|
||||
v-show="multiple === tagIndex"
|
||||
>
|
||||
<el-checkbox
|
||||
class="item"
|
||||
:value="item"
|
||||
v-for="(item, index) in tag.values"
|
||||
:key="index"
|
||||
>{{ item }}</el-checkbox
|
||||
>
|
||||
</el-checkbox-group>
|
||||
|
||||
<div class="btn" v-show="multiple !== tagIndex">
|
||||
<span @click="moreBrand(tagIndex)" v-show="tag.values.length > 9"
|
||||
<div class="btn" v-show="rowOverflow[tagIndex]">
|
||||
<span @click="moreBrand(tagIndex)"
|
||||
>{{ tag.more ? "收起" : "更多"
|
||||
}}<el-icon><ArrowUp v-if="tag.more" /><ArrowDown v-else /></el-icon></span>
|
||||
<span @click="multSelectBrand(tagIndex)"
|
||||
><el-icon><Plus /></el-icon>多选</span>
|
||||
</div>
|
||||
|
||||
<div class="multBtn" v-show="multiple === tagIndex">
|
||||
<el-button
|
||||
type="primary"
|
||||
size="small"
|
||||
:disabled="!multSelected.length"
|
||||
@click="sure(tagIndex)"
|
||||
>确定</el-button
|
||||
>
|
||||
<el-button size="small" @click="cancel">取消</el-button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -157,10 +117,10 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { ArrowDown, ArrowRight, ArrowUp, Check, Close, Plus } from '@element-plus/icons-vue';
|
||||
import { ArrowDown, ArrowRight, ArrowUp, Close } from '@element-plus/icons-vue';
|
||||
import * as APIGoods from '@/api/goods';
|
||||
export default {
|
||||
components: { ArrowDown, ArrowRight, ArrowUp, Check, Close, Plus },
|
||||
components: { ArrowDown, ArrowRight, ArrowUp, Close },
|
||||
name: 'GoodsClassNav',
|
||||
data () {
|
||||
return {
|
||||
@@ -171,7 +131,6 @@ export default {
|
||||
second: null
|
||||
},
|
||||
showTagCount: 5, // 展示的搜索项数量
|
||||
multiple: false, // 多选
|
||||
tagsContent: [
|
||||
// 标签
|
||||
{
|
||||
@@ -181,10 +140,10 @@ export default {
|
||||
values: []
|
||||
}
|
||||
],
|
||||
multSelected: [], // 多选分类
|
||||
selectedItem: [], // 已选分类集合 顶部展示
|
||||
brandIds: [], // 品牌id合集
|
||||
params: {} // 请求参数
|
||||
params: {}, // 请求参数
|
||||
rowOverflow: {} // 一行排不下时才显示更多
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
@@ -280,33 +239,30 @@ export default {
|
||||
break;
|
||||
}
|
||||
},
|
||||
isGroupSelected (index) {
|
||||
const group = this.tagsContent[index];
|
||||
if (!group) return false;
|
||||
return this.selectedItem.some((selected) => selected.type === group.key);
|
||||
},
|
||||
selectAll (index) {
|
||||
const group = this.tagsContent[index];
|
||||
if (!group) return;
|
||||
const selectedIndex = this.selectedItem.findIndex((selected) => selected.type === group.key);
|
||||
if (selectedIndex === -1) return;
|
||||
this.cancelSelected(this.selectedItem[selectedIndex], selectedIndex);
|
||||
},
|
||||
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 {
|
||||
const type = this.tagsContent[index].key;
|
||||
if (this.selectedItem.some((selected) => selected.type === type)) {
|
||||
return;
|
||||
}
|
||||
this.selectedItem.push({
|
||||
type,
|
||||
name: item
|
||||
});
|
||||
|
||||
this.tagsContent[index].show = false;
|
||||
|
||||
if (index === 0) {
|
||||
// 如果是品牌,获取品牌id
|
||||
this.appendBrandIdsByNames([item]);
|
||||
}
|
||||
const type = this.tagsContent[index].key;
|
||||
if (this.selectedItem.some((selected) => selected.type === type)) {
|
||||
return;
|
||||
}
|
||||
this.selectedItem.push({
|
||||
type,
|
||||
name: item
|
||||
});
|
||||
this.tagsContent[index].show = false;
|
||||
if (index === 0) {
|
||||
this.appendBrandIdsByNames([item]);
|
||||
}
|
||||
},
|
||||
|
||||
@@ -328,37 +284,25 @@ export default {
|
||||
// 更多按钮
|
||||
const flag = !this.tagsContent[index].more
|
||||
this.tagsContent[index]['more'] = flag
|
||||
this.$nextTick(() => this.measureRows())
|
||||
},
|
||||
multSelectBrand (index) {
|
||||
// 多选按钮
|
||||
this.tagsContent[index]['more'] = true
|
||||
this.multiple = index;
|
||||
},
|
||||
sure (index) {
|
||||
// 多选确认按钮
|
||||
const type = this.tagsContent[index].key;
|
||||
if (this.selectedItem.some((selected) => selected.type === type)) {
|
||||
this.cancel();
|
||||
return;
|
||||
measureRows () {
|
||||
if (!this.$el) return
|
||||
const next = {}
|
||||
const brand = this.$el.querySelector('.brand ul')
|
||||
if (brand && brand.offsetParent) {
|
||||
next[0] = !!(this.tagsContent[0] && this.tagsContent[0].more) || brand.scrollHeight > brand.clientHeight + 1
|
||||
}
|
||||
this.selectedItem.push({
|
||||
type,
|
||||
name: this.multSelected.join('、')
|
||||
});
|
||||
|
||||
if (index === 0) {
|
||||
// 如果是品牌,获取品牌id
|
||||
this.appendBrandIdsByNames(this.multSelected);
|
||||
}
|
||||
|
||||
this.tagsContent[index].show = false;
|
||||
this.cancel();
|
||||
},
|
||||
cancel () {
|
||||
// 多选取消按钮
|
||||
this.multSelected = [];
|
||||
this.tagsContent[0].more = false;
|
||||
this.multiple = false;
|
||||
this.$el.querySelectorAll('.other .list').forEach((list) => {
|
||||
if (!list.offsetParent) return
|
||||
const index = Number(list.dataset.index)
|
||||
const tag = this.tagsContent[index]
|
||||
next[index] = !!(tag && tag.more) || list.scrollHeight > list.clientHeight + 1
|
||||
})
|
||||
const prev = this.rowOverflow
|
||||
const keys = new Set([...Object.keys(prev), ...Object.keys(next)])
|
||||
const changed = [...keys].some((key) => !!prev[key] !== !!next[key])
|
||||
if (changed) this.rowOverflow = next
|
||||
},
|
||||
appendBrandIdsByNames (names) {
|
||||
const selectedNames = names || [];
|
||||
@@ -385,12 +329,14 @@ export default {
|
||||
item.show = !hiddenKeys.has(item.key);
|
||||
item.more = false;
|
||||
});
|
||||
this.$nextTick(() => this.measureRows())
|
||||
}
|
||||
});
|
||||
},
|
||||
// 展示更多搜索项
|
||||
moreOptions () {
|
||||
this.showTagCount = this.showTagCount === 5 ? 100 : 5
|
||||
this.$nextTick(() => this.measureRows())
|
||||
}
|
||||
},
|
||||
mounted () {
|
||||
@@ -404,6 +350,10 @@ export default {
|
||||
}
|
||||
this.getFilterList(this.params);
|
||||
this.getNav();
|
||||
window.addEventListener('resize', this.measureRows)
|
||||
},
|
||||
beforeUnmount () {
|
||||
window.removeEventListener('resize', this.measureRows)
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@@ -413,70 +363,100 @@ export default {
|
||||
.head-bar {
|
||||
width: 100%;
|
||||
background: #fff;
|
||||
margin-top: -13px;
|
||||
display: flex;
|
||||
height: 40px;
|
||||
flex-wrap: wrap;
|
||||
gap: 8px;
|
||||
min-height: 48px;
|
||||
align-items: center;
|
||||
padding: 8px 16px;
|
||||
border: 1px solid #eee;
|
||||
border-bottom: none;
|
||||
border-radius: 4px 4px 0 0;
|
||||
color: #666;
|
||||
font-size: 14px;
|
||||
box-sizing: border-box;
|
||||
|
||||
> div:first-child {
|
||||
padding: 0 8px;
|
||||
font-size: 18px;
|
||||
font-weight: bold;
|
||||
padding: 0;
|
||||
font-size: 14px;
|
||||
font-weight: 400;
|
||||
color: #666;
|
||||
&:hover {
|
||||
color: $theme_color;
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
.bar {
|
||||
|
||||
.result-label {
|
||||
color: #666;
|
||||
}
|
||||
|
||||
.result-keyword {
|
||||
margin-left: 4px;
|
||||
color: #171A26;
|
||||
font-size: 15px;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
> .el-icon {
|
||||
color: #ccc;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.bar {
|
||||
position: relative;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
height: 28px;
|
||||
margin: 0 4px;
|
||||
padding: 0 10px;
|
||||
border: 1px solid #e5e5e5;
|
||||
border-radius: 4px;
|
||||
background: #fff;
|
||||
border: 1px solid #999;
|
||||
padding: 0 8px;
|
||||
min-width: 85px;
|
||||
text-align: center;
|
||||
margin: 0 3px;
|
||||
color: #171A26;
|
||||
font-size: 14px;
|
||||
line-height: 26px;
|
||||
|
||||
&:hover {
|
||||
color: $theme_color;
|
||||
border-color: $theme_color;
|
||||
border-bottom-color: #fff;
|
||||
color: $theme_color;
|
||||
cursor: pointer;
|
||||
|
||||
ul {
|
||||
display: block;
|
||||
display: flex;
|
||||
}
|
||||
.el-icon {
|
||||
|
||||
> .el-icon {
|
||||
transform: rotate(180deg);
|
||||
}
|
||||
}
|
||||
|
||||
ul {
|
||||
display: none;
|
||||
position: absolute;
|
||||
top: 18px;
|
||||
left: -1px;
|
||||
width: 300px;
|
||||
padding: 5px 10px;
|
||||
top: calc(100% + 6px);
|
||||
left: 0;
|
||||
z-index: 5;
|
||||
width: 280px;
|
||||
margin: 0;
|
||||
padding: 8px;
|
||||
flex-wrap: wrap;
|
||||
list-style: none;
|
||||
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;
|
||||
}
|
||||
border: 1px solid #eee;
|
||||
border-radius: 4px;
|
||||
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08);
|
||||
|
||||
&:hover {
|
||||
display: block;
|
||||
}
|
||||
clear: left;
|
||||
li {
|
||||
color: #999;
|
||||
float: left;
|
||||
width: 30%;
|
||||
margin: 3px 0;
|
||||
width: 33.33%;
|
||||
padding: 6px 8px;
|
||||
box-sizing: border-box;
|
||||
color: #171A26;
|
||||
font-size: 14px;
|
||||
line-height: 20px;
|
||||
text-align: left;
|
||||
|
||||
&:hover {
|
||||
color: $theme_color;
|
||||
cursor: pointer;
|
||||
@@ -486,252 +466,257 @@ export default {
|
||||
}
|
||||
//所选分类
|
||||
.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;
|
||||
.el-icon {
|
||||
color: #fff;
|
||||
background-color: $theme_color;
|
||||
}
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
max-width: 240px;
|
||||
height: 28px;
|
||||
margin: 0;
|
||||
padding: 0 8px;
|
||||
border: 1px solid #ffd0cb;
|
||||
border-radius: 4px;
|
||||
background: #fff5f4;
|
||||
color: #666;
|
||||
font-size: 13px;
|
||||
line-height: 26px;
|
||||
text-decoration: none;
|
||||
box-sizing: border-box;
|
||||
cursor: pointer;
|
||||
|
||||
span:first-child {
|
||||
flex-shrink: 0;
|
||||
color: #666;
|
||||
}
|
||||
|
||||
span:nth-child(2) {
|
||||
min-width: 0;
|
||||
overflow: hidden;
|
||||
color: $theme_color;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.el-icon {
|
||||
position: absolute;
|
||||
right: 0;
|
||||
top: 0;
|
||||
color: $theme_color;
|
||||
line-height: 22px;
|
||||
width: 21px;
|
||||
height: 22px;
|
||||
font-size: 14px;
|
||||
position: static;
|
||||
flex-shrink: 0;
|
||||
width: 14px;
|
||||
height: 14px;
|
||||
color: #999;
|
||||
font-size: 12px;
|
||||
line-height: 1;
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
border-color: $theme_color;
|
||||
background: #fff5f4;
|
||||
|
||||
.el-icon {
|
||||
color: $theme_color;
|
||||
background: transparent;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/** 筛选主体 */
|
||||
.content {
|
||||
background: #fff;
|
||||
border-top: 1px solid #ddd;
|
||||
border-bottom: 1px solid #ddd;
|
||||
margin: 10px 0;
|
||||
border: 1px solid #eee;
|
||||
border-top: none;
|
||||
margin: 0 0 12px;
|
||||
border-radius: 0 0 4px 4px;
|
||||
}
|
||||
/** 品牌 start */
|
||||
.brand {
|
||||
border-bottom: 1px solid #ddd;
|
||||
border-bottom: 1px solid #f0f0f0;
|
||||
display: flex;
|
||||
// min-height: 120px;
|
||||
font-size: 12px;
|
||||
min-height: 44px;
|
||||
font-size: 14px;
|
||||
> div:first-child {
|
||||
width: 100px;
|
||||
background: #eee;
|
||||
padding: 10px 0 0 10px;
|
||||
width: 88px;
|
||||
background: transparent;
|
||||
padding-left: 16px;
|
||||
line-height: 44px;
|
||||
color: #666;
|
||||
font-weight: 400;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
> div:last-child {
|
||||
width: 1100px;
|
||||
padding: 10px;
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
width: auto;
|
||||
padding: 0 16px;
|
||||
position: relative;
|
||||
ul {
|
||||
width: 900px;
|
||||
max-height: 100px;
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
align-items: center;
|
||||
width: calc(100% - 72px);
|
||||
height: 44px;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
overflow: hidden;
|
||||
padding-top: 1px;
|
||||
clear: left;
|
||||
list-style: none;
|
||||
li {
|
||||
width: 100px;
|
||||
height: 50px;
|
||||
float: left;
|
||||
line-height: 45px;
|
||||
border: 1px solid #ddd;
|
||||
margin: -1px -1px 0 0;
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
padding: 2px;
|
||||
img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
flex: 0 0 auto;
|
||||
width: auto;
|
||||
max-width: none;
|
||||
height: 44px;
|
||||
margin: 0 40px 0 0;
|
||||
line-height: 44px;
|
||||
overflow: visible;
|
||||
padding: 0;
|
||||
cursor: pointer;
|
||||
|
||||
&:hover span {
|
||||
color: $theme_color;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
border-color: $theme_color;
|
||||
border: 2px solid $theme_color;
|
||||
top: 0;
|
||||
left: 0;
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
img {
|
||||
display: none;
|
||||
}
|
||||
&.is-active span {
|
||||
color: $theme_color;
|
||||
font-weight: 400;
|
||||
}
|
||||
|
||||
span {
|
||||
display: inline-block;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
color: $theme_color;
|
||||
text-align: center;
|
||||
font-size: 12px;
|
||||
display: block;
|
||||
overflow: visible;
|
||||
color: #171A26;
|
||||
text-align: left;
|
||||
font-size: 14px;
|
||||
font-weight: 400;
|
||||
line-height: 44px;
|
||||
white-space: nowrap;
|
||||
text-overflow: clip;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.corner-icon {
|
||||
position: absolute;
|
||||
right: -1px;
|
||||
bottom: -1px;
|
||||
div {
|
||||
width: 0;
|
||||
border-top: 20px solid transparent;
|
||||
border-right: 20px solid $theme_color;
|
||||
}
|
||||
.el-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;
|
||||
max-height: none;
|
||||
overflow: visible;
|
||||
}
|
||||
.btn {
|
||||
position: absolute;
|
||||
right: 10px;
|
||||
top: 10px;
|
||||
right: 16px;
|
||||
top: 8px;
|
||||
span {
|
||||
border: 1px solid #ddd;
|
||||
margin-left: 10px;
|
||||
color: #999;
|
||||
display: inline-block;
|
||||
padding: 1px 3px;
|
||||
font-size: 12px;
|
||||
margin-left: 12px;
|
||||
color: #438cde;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 2px;
|
||||
padding: 0;
|
||||
border: none;
|
||||
font-size: 14px;
|
||||
line-height: 28px;
|
||||
&:hover {
|
||||
cursor: pointer;
|
||||
color: $theme_color;
|
||||
border-color: $theme_color;
|
||||
}
|
||||
}
|
||||
}
|
||||
.multBtn {
|
||||
text-align: center;
|
||||
margin-top: 10px;
|
||||
.el-button {
|
||||
font-size: 12px !important;
|
||||
}
|
||||
.el-button:last-child {
|
||||
margin-left: 10px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/** 品牌 end */
|
||||
/** 其他筛选项 start */
|
||||
.other {
|
||||
border-bottom: 1px solid #ddd;
|
||||
border-bottom: 1px solid #f0f0f0;
|
||||
display: flex;
|
||||
min-height: 30px;
|
||||
font-size: 12px;
|
||||
min-height: 44px;
|
||||
font-size: 14px;
|
||||
&:last-child {
|
||||
border: none;
|
||||
}
|
||||
> div:first-child {
|
||||
width: 100px;
|
||||
background: #eee;
|
||||
padding-left: 10px;
|
||||
line-height: 30px;
|
||||
width: 88px;
|
||||
background: transparent;
|
||||
padding-left: 16px;
|
||||
line-height: 44px;
|
||||
color: #666;
|
||||
font-weight: 400;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
> div:last-child {
|
||||
width: 1100px;
|
||||
padding: 0 10px;
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
width: auto;
|
||||
padding: 0 16px;
|
||||
position: relative;
|
||||
.list {
|
||||
width: 900px;
|
||||
height: 30px;
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
align-items: center;
|
||||
width: calc(100% - 72px);
|
||||
height: 44px;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
overflow: hidden;
|
||||
clear: left;
|
||||
list-style: none;
|
||||
.item {
|
||||
width: 100px;
|
||||
height: 30px;
|
||||
float: left;
|
||||
line-height: 30px;
|
||||
color:#4d9cf1;
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
font-size: 12px;
|
||||
padding: 2px;
|
||||
flex: 0 0 auto;
|
||||
width: auto;
|
||||
max-width: none;
|
||||
height: 44px;
|
||||
margin: 0 40px 0 0;
|
||||
line-height: 44px;
|
||||
color: #171A26;
|
||||
overflow: visible;
|
||||
white-space: nowrap;
|
||||
text-overflow: clip;
|
||||
font-size: 14px;
|
||||
font-weight: 400;
|
||||
padding: 0;
|
||||
cursor: pointer;
|
||||
&:hover {
|
||||
color: $theme_color;
|
||||
}
|
||||
|
||||
&.is-active {
|
||||
color: $theme_color;
|
||||
font-weight: 400;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.show-more {
|
||||
height: auto;
|
||||
max-height: none;
|
||||
overflow: visible;
|
||||
}
|
||||
|
||||
.btn {
|
||||
position: absolute;
|
||||
right: 10px;
|
||||
top: 5px;
|
||||
right: 16px;
|
||||
top: 8px;
|
||||
span {
|
||||
border: 1px solid #ddd;
|
||||
margin-left: 10px;
|
||||
color: #999;
|
||||
display: inline-block;
|
||||
padding: 1px 3px;
|
||||
font-size: 12px;
|
||||
margin-left: 12px;
|
||||
color: #438cde;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 2px;
|
||||
padding: 0;
|
||||
border: none;
|
||||
font-size: 14px;
|
||||
line-height: 28px;
|
||||
&:hover {
|
||||
cursor: pointer;
|
||||
color: $theme_color;
|
||||
border-color: $theme_color;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.multBtn {
|
||||
text-align: center;
|
||||
margin-top: 10px;
|
||||
margin-bottom: 10px;
|
||||
.el-button {
|
||||
font-size: 12px !important;
|
||||
}
|
||||
.el-button:last-child {
|
||||
margin-left: 10px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.more-options{
|
||||
margin: 5px;
|
||||
color: #4d9cf1;
|
||||
font-size: 12px;
|
||||
margin: 0;
|
||||
padding: 10px 16px;
|
||||
color: #438cde;
|
||||
font-size: 14px;
|
||||
cursor: pointer;
|
||||
text-align: right;
|
||||
}
|
||||
.more-options:hover{
|
||||
color:#0165d1;
|
||||
color: $theme_color;
|
||||
}
|
||||
/** 其他筛选项 end */
|
||||
</style>
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
<template>
|
||||
<div class="user-center-page">
|
||||
<div class="user-center-title">{{ title }}</div>
|
||||
<div v-if="title" class="user-center-title">{{ title }}</div>
|
||||
<div class="user-center-panel">
|
||||
<div v-if="showToolbar" class="user-center-toolbar">
|
||||
<div v-if="showToolbar" class="user-center-toolbar" :class="{ 'is-actions-only': !tabs.length }">
|
||||
<div class="user-center-tabs">
|
||||
<div
|
||||
v-for="(item, index) in tabs"
|
||||
@@ -33,7 +33,7 @@ export default {
|
||||
props: {
|
||||
title: {
|
||||
type: String,
|
||||
required: true,
|
||||
default: "",
|
||||
},
|
||||
tabs: {
|
||||
type: Array,
|
||||
@@ -101,21 +101,35 @@ export default {
|
||||
justify-content: space-between;
|
||||
min-height: 54px;
|
||||
border-bottom: 1px solid #eee;
|
||||
gap: 16px;
|
||||
}
|
||||
|
||||
.user-center-toolbar.is-actions-only {
|
||||
justify-content: flex-start;
|
||||
|
||||
.user-center-tabs {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
.user-center-tabs {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
height: 54px;
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.user-center-tab {
|
||||
position: relative;
|
||||
flex-shrink: 0;
|
||||
height: 54px;
|
||||
line-height: 54px;
|
||||
margin-right: 28px;
|
||||
color: #333;
|
||||
cursor: pointer;
|
||||
white-space: nowrap;
|
||||
|
||||
&:hover,
|
||||
&.active {
|
||||
@@ -127,7 +141,7 @@ export default {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: -1px;
|
||||
bottom: 0;
|
||||
height: 2px;
|
||||
background: $theme_color;
|
||||
}
|
||||
@@ -136,6 +150,7 @@ export default {
|
||||
.user-center-extra {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.user-center-content {
|
||||
|
||||
@@ -9,20 +9,17 @@
|
||||
购物车(<span>{{ goodsTotal }}</span>)
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="cart-steps">
|
||||
<span :class="stepIndex == 0 ? 'active' : ''">1.我的购物车</span>
|
||||
<i class="icomoon icon-next" :class="stepIndex == 0 ? 'active-arrow' : ''"></i>
|
||||
<span :class="stepIndex == 1 ? 'active' : ''">2.填写订单信息</span>
|
||||
<i class="icomoon icon-next" :class="stepIndex == 1 ? 'active-arrow' : ''"></i>
|
||||
<span :class="stepIndex == 2 ? 'active' : ''">3.成功提交订单</span>
|
||||
</div>
|
||||
</div>
|
||||
<el-divider />
|
||||
<!-- 购物车主体 -->
|
||||
<div class="cart-content width_1200 center">
|
||||
<div class="available-area">
|
||||
<div class="cart-steps">
|
||||
<span :class="stepIndex == 0 ? 'active' : ''">1.我的购物车</span>
|
||||
<i class="icomoon icon-next" :class="stepIndex == 0 ? 'active-arrow' : ''"></i>
|
||||
<span :class="stepIndex == 1 ? 'active' : ''">2.填写订单信息</span>
|
||||
<i class="icomoon icon-next" :class="stepIndex == 1 ? 'active-arrow' : ''"></i>
|
||||
<span :class="stepIndex == 2 ? 'active' : ''">3.成功提交订单</span>
|
||||
</div>
|
||||
</div>
|
||||
<!-- 购物车商品列表 -->
|
||||
<div class="cart-goods">
|
||||
<div class="cart-goods-table">
|
||||
@@ -168,7 +165,7 @@
|
||||
v-model="goods.num"
|
||||
@change="changeNum(goods.num, goods.goodsSku.id)"
|
||||
></el-input-number>
|
||||
<div class="fontsize_12 cart-qty-stock">
|
||||
<div class="cart-qty-stock">
|
||||
{{ goods.goodsSku.quantity > 0 ? "有货" : "无货" }}
|
||||
</div>
|
||||
</div>
|
||||
@@ -538,7 +535,7 @@ export default {
|
||||
}
|
||||
}
|
||||
.cart-content {
|
||||
margin: 0 auto;
|
||||
margin: 20px auto;
|
||||
width: 1200px;
|
||||
position: relative;
|
||||
}
|
||||
@@ -548,7 +545,8 @@ export default {
|
||||
height: 30px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-bottom: 15px;
|
||||
gap: 12px;
|
||||
|
||||
span {
|
||||
@include content_color($light_content_color);
|
||||
height: 30px;
|
||||
@@ -556,45 +554,40 @@ export default {
|
||||
line-height: 30px;
|
||||
display: inline-block;
|
||||
padding: 0 15px;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.el-icon {
|
||||
@include content_color($light_content_color);
|
||||
font-size: 20px;
|
||||
margin: 0 15px;
|
||||
.icon-next {
|
||||
flex-shrink: 0;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.active {
|
||||
border-radius: 50px;
|
||||
background-color: #ff8f23;
|
||||
background-color: $theme_color;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.active-arrow {
|
||||
color: #ff8f23;
|
||||
color: $theme_color;
|
||||
}
|
||||
}
|
||||
/** 步骤条和配送区域总体 */
|
||||
.available-area {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
/** 商品列表 */
|
||||
.cart-goods {
|
||||
.cart-goods-table {
|
||||
border: 1px solid #e0e0e0;
|
||||
@include background_color($light_white_background_color);
|
||||
border: 1px solid #eee;
|
||||
background: #fff;
|
||||
padding: 0 8px;
|
||||
}
|
||||
&-title {
|
||||
height: 50px;
|
||||
@include background_color($light_white_background_color);
|
||||
@include title_color($title_color);
|
||||
height: 44px;
|
||||
background: #fff;
|
||||
color: #999;
|
||||
font-size: 13px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 0 20px;
|
||||
border-bottom: 1px solid #e0e0e0;
|
||||
padding: 0 12px;
|
||||
border-bottom: 1px solid #f0f0f0;
|
||||
div:not(.cart-col-check) {
|
||||
text-align: center;
|
||||
}
|
||||
@@ -629,10 +622,14 @@ export default {
|
||||
border-bottom: 1px solid #e0e0e0;
|
||||
}
|
||||
.shop-name {
|
||||
height: 50px;
|
||||
min-height: 48px;
|
||||
height: auto;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 0 20px;
|
||||
padding: 8px 12px;
|
||||
color: #171A26;
|
||||
font-size: 15px;
|
||||
font-weight: 600;
|
||||
position: relative;
|
||||
@include title_color($light_title_color);
|
||||
.shop-info {
|
||||
@@ -693,14 +690,14 @@ export default {
|
||||
border-radius: 3px;
|
||||
}
|
||||
span:nth-child(2) {
|
||||
font-size: 12px;
|
||||
font-size: 14px;
|
||||
margin-left: 5px;
|
||||
color: #999;
|
||||
}
|
||||
.coupon-btn {
|
||||
height: 26px;
|
||||
height: 28px;
|
||||
float: right;
|
||||
font-size: 12px;
|
||||
font-size: 14px;
|
||||
}
|
||||
&::after {
|
||||
display: block;
|
||||
@@ -712,7 +709,9 @@ export default {
|
||||
}
|
||||
.promotion-notice {
|
||||
text-align: right;
|
||||
font-size: 12px;
|
||||
font-size: 13px;
|
||||
color: #999;
|
||||
font-weight: 400;
|
||||
flex-shrink: 0;
|
||||
margin-left: 10px;
|
||||
}
|
||||
@@ -725,7 +724,7 @@ export default {
|
||||
@extend .cart-goods-title;
|
||||
background: transparent;
|
||||
border-top: 1px solid #f0f0f0;
|
||||
padding: 10px 20px;
|
||||
padding: 16px 12px 28px;
|
||||
height: auto;
|
||||
.cart-col-check {
|
||||
padding-left: 20px;
|
||||
@@ -741,14 +740,19 @@ export default {
|
||||
padding-left: 20px;
|
||||
position: relative;
|
||||
img {
|
||||
width: 70px;
|
||||
height: 70px;
|
||||
width: 72px;
|
||||
height: 72px;
|
||||
border-radius: 4px;
|
||||
object-fit: cover;
|
||||
background: #f5f5f5;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
> div > p {
|
||||
@include content_color($light_content_color);
|
||||
font-size: 13px;
|
||||
color: #171A26;
|
||||
font-size: 15px;
|
||||
line-height: 22px;
|
||||
text-align: left;
|
||||
margin-left: 10px;
|
||||
margin-left: 12px;
|
||||
&:hover {
|
||||
color: $theme_color;
|
||||
}
|
||||
@@ -761,9 +765,12 @@ export default {
|
||||
justify-content: center;
|
||||
flex-shrink: 0;
|
||||
text-align: center;
|
||||
color: #171A26;
|
||||
font-size: 15px;
|
||||
}
|
||||
.cart-col-subtotal {
|
||||
font-weight: bold;
|
||||
color: $theme_color;
|
||||
font-weight: 600;
|
||||
}
|
||||
.cart-col-qty {
|
||||
position: relative;
|
||||
@@ -777,6 +784,7 @@ export default {
|
||||
}
|
||||
|
||||
.cart-qty-stock {
|
||||
font-size: 14px;
|
||||
position: absolute;
|
||||
top: calc(100% + 4px);
|
||||
left: 50%;
|
||||
@@ -784,6 +792,7 @@ export default {
|
||||
white-space: nowrap;
|
||||
line-height: 1.2;
|
||||
color: #999;
|
||||
font-size: 13px;
|
||||
}
|
||||
}
|
||||
.num-input {
|
||||
@@ -813,11 +822,14 @@ export default {
|
||||
@extend .cart-goods-title;
|
||||
position: sticky;
|
||||
bottom: 0;
|
||||
border-top: 1px solid #ddd;
|
||||
margin-top: 10px;
|
||||
padding: 0 0 0 20px;
|
||||
line-height: 50px;
|
||||
height: 64px;
|
||||
border-top: 1px solid #f0f0f0;
|
||||
margin-top: 0;
|
||||
padding: 0 0 0 12px;
|
||||
line-height: 64px;
|
||||
justify-content: space-between;
|
||||
color: #171A26;
|
||||
font-size: 14px;
|
||||
> div {
|
||||
display: flex;
|
||||
}
|
||||
@@ -832,21 +844,26 @@ export default {
|
||||
}
|
||||
.total-price div {
|
||||
color: $theme_color;
|
||||
font-size: 20px;
|
||||
font-size: 22px;
|
||||
font-weight: 600;
|
||||
}
|
||||
.pay {
|
||||
background-color: $theme_color;
|
||||
width: 150px;
|
||||
font-size: 20px;
|
||||
width: 160px;
|
||||
font-size: 16px;
|
||||
color: #fff;
|
||||
height: 100%;
|
||||
line-height: 50px;
|
||||
line-height: 64px;
|
||||
cursor: pointer;
|
||||
|
||||
&:hover {
|
||||
opacity: 0.92;
|
||||
}
|
||||
}
|
||||
}
|
||||
.handle-btn {
|
||||
font-size: 12px;
|
||||
color: $handle-btn-color;
|
||||
font-size: 14px;
|
||||
color: #666;
|
||||
cursor: pointer;
|
||||
&:hover {
|
||||
color: $theme_color;
|
||||
@@ -881,12 +898,12 @@ export default {
|
||||
> span {
|
||||
border: 1px solid $theme_color;
|
||||
color: $theme_color;
|
||||
font-size: 12px;
|
||||
font-size: 14px;
|
||||
border-radius: 2px;
|
||||
padding: 0 2px;
|
||||
}
|
||||
> p {
|
||||
font-size: 12px;
|
||||
font-size: 14px;
|
||||
margin-left: 10px;
|
||||
color: #999;
|
||||
}
|
||||
@@ -915,44 +932,25 @@ export default {
|
||||
flex-wrap: nowrap;
|
||||
}
|
||||
|
||||
.cart-del-btn {
|
||||
background-color: #ff7d79 !important;
|
||||
border-color: #ff7d79 !important;
|
||||
color: #fff !important;
|
||||
.cart-del-btn,
|
||||
.cart-collect-btn {
|
||||
height: auto !important;
|
||||
margin: 0 !important;
|
||||
padding: 0 4px !important;
|
||||
border: none !important;
|
||||
background: transparent !important;
|
||||
color: #171A26 !important;
|
||||
font-size: 14px !important;
|
||||
|
||||
&:hover,
|
||||
&:focus {
|
||||
background-color: #ff6b66 !important;
|
||||
border-color: #ff6b66 !important;
|
||||
color: #fff !important;
|
||||
color: $theme_color !important;
|
||||
background: transparent !important;
|
||||
}
|
||||
}
|
||||
|
||||
.cart-collect-btn {
|
||||
background-color: #fa6419 !important;
|
||||
border-color: #fa6419 !important;
|
||||
color: #fff !important;
|
||||
margin: 0 !important;
|
||||
|
||||
&:hover,
|
||||
&:focus {
|
||||
background-color: #e55a15 !important;
|
||||
border-color: #e55a15 !important;
|
||||
color: #fff !important;
|
||||
}
|
||||
|
||||
&.is-collected {
|
||||
background-color: $theme_color !important;
|
||||
border-color: $theme_color !important;
|
||||
|
||||
&:hover,
|
||||
&:focus {
|
||||
background-color: $theme_color !important;
|
||||
border-color: $theme_color !important;
|
||||
opacity: 0.9;
|
||||
}
|
||||
}
|
||||
.cart-collect-btn.is-collected {
|
||||
color: $theme_color !important;
|
||||
}
|
||||
</style>
|
||||
<style>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<div style="background: #fff">
|
||||
<div class="goods-detail-page">
|
||||
<BaseHeader></BaseHeader>
|
||||
<Search></Search>
|
||||
<div class="shop-item-path">
|
||||
@@ -178,7 +178,10 @@ export default {
|
||||
arr.push(e.id);
|
||||
}
|
||||
});
|
||||
return location.origin + "/goodsList?categoryId=" + arr.toString();
|
||||
return {
|
||||
path: "/goodsList",
|
||||
query: { categoryId: arr.toString() },
|
||||
};
|
||||
},
|
||||
async collect () {
|
||||
// 收藏店铺
|
||||
@@ -214,10 +217,14 @@ export default {
|
||||
};
|
||||
</script>
|
||||
<style scoped lang="scss">
|
||||
.goods-detail-page {
|
||||
background: #f5f5f5;
|
||||
}
|
||||
|
||||
.shop-item-path {
|
||||
height: 38px;
|
||||
@include background_color($light_background_color);
|
||||
color: #2c2c2c;
|
||||
height: 44px;
|
||||
background: transparent;
|
||||
color: #666;
|
||||
}
|
||||
|
||||
.shop-nav-container {
|
||||
@@ -230,51 +237,65 @@ export default {
|
||||
|
||||
:deep(.el-breadcrumb) {
|
||||
line-height: 1;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
:deep(.el-breadcrumb__inner) {
|
||||
color: #666;
|
||||
font-weight: 400;
|
||||
}
|
||||
|
||||
:deep(.el-breadcrumb__item:last-child .el-breadcrumb__inner) {
|
||||
color: #171A26;
|
||||
}
|
||||
|
||||
.store-collect {
|
||||
position: absolute;
|
||||
right: 20px;
|
||||
right: 0;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
color: #999;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 16px;
|
||||
color: #171A26;
|
||||
font-size: 14px;
|
||||
|
||||
.store-collect-btn,
|
||||
.contact-service-btn {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
cursor: pointer;
|
||||
color: #171A26;
|
||||
|
||||
span:not(.store-collect-btn):not(.contact-service-btn) {
|
||||
&:hover {
|
||||
cursor: pointer;
|
||||
color: $theme_color;
|
||||
}
|
||||
}
|
||||
|
||||
.store-collect-btn,
|
||||
.contact-service-btn {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.store-collect-btn {
|
||||
.store-collect-icon {
|
||||
color: #666;
|
||||
vertical-align: middle;
|
||||
color: #999;
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
&.is-collected,
|
||||
&.is-collected .store-collect-icon {
|
||||
color: $theme_color;
|
||||
}
|
||||
}
|
||||
|
||||
.store-name-link {
|
||||
color: $theme_color;
|
||||
color: #438cde;
|
||||
text-decoration: none;
|
||||
|
||||
&:hover {
|
||||
color: $theme_color;
|
||||
text-decoration: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.sale-btn{
|
||||
margin:10px 0
|
||||
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -63,12 +63,12 @@
|
||||
<span>{{ item.goodsName }}</span>
|
||||
</div>
|
||||
<div class="goods-show-num">
|
||||
已有<span>{{ item.commentNum || 0 }}</span>人评价
|
||||
<span>{{ formatGrade(item.grade) }}%好评</span>
|
||||
<span class="goods-show-sales">销量 {{ item.buyCount || 0 }}</span>
|
||||
</div>
|
||||
<div class="goods-show-seller">
|
||||
<span
|
||||
class="text-bottom hover-pointer"
|
||||
style="color: #e4393c"
|
||||
@click.stop="goShopPage(item.storeId)"
|
||||
>{{ item.storeName }}</span>
|
||||
</div>
|
||||
@@ -80,25 +80,6 @@
|
||||
>
|
||||
自营
|
||||
</el-tag>
|
||||
<!-- E_COUPON 卡密商品类型标识 -->
|
||||
<el-tag
|
||||
class="goods-show-tag goods-show-tag-physical goods-show-tag-ecoupon"
|
||||
v-if="item.goodsType === 'E_COUPON'"
|
||||
>
|
||||
电子卡券
|
||||
</el-tag>
|
||||
<el-tag
|
||||
class="goods-show-tag goods-show-tag-physical"
|
||||
v-else-if="item.goodsType === 'VIRTUAL_GOODS'"
|
||||
>
|
||||
虚拟
|
||||
</el-tag>
|
||||
<el-tag
|
||||
class="goods-show-tag goods-show-tag-physical"
|
||||
v-else-if="item.goodsType === 'PHYSICAL_GOODS'"
|
||||
>
|
||||
实物
|
||||
</el-tag>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -125,7 +106,6 @@ import { Message } from "@/utils/message";
|
||||
import { ArrowDown, ArrowUp } from '@element-plus/icons-vue';
|
||||
import GoodsClassNav from "@/components/nav/GoodsClassNav";
|
||||
import * as apiGoods from "@/api/goods";
|
||||
import { isBuyerLoggedIn, redirectToLogin } from "@/utils/buyerLogin";
|
||||
export default {
|
||||
name: "GoodsList",
|
||||
beforeRouteEnter(to, from, next) {
|
||||
@@ -201,15 +181,22 @@ export default {
|
||||
}
|
||||
this.getGoodsList();
|
||||
},
|
||||
formatGrade(grade) {
|
||||
if (grade === null || grade === undefined || grade === "") {
|
||||
return 100;
|
||||
}
|
||||
const num = Number(grade);
|
||||
if (Number.isNaN(num)) {
|
||||
return 100;
|
||||
}
|
||||
const fixed = Number(num.toFixed(1));
|
||||
return fixed % 1 === 0 ? fixed.toFixed(0) : String(fixed);
|
||||
},
|
||||
goGoodsDetail(skuId, goodsId) {
|
||||
const location = {
|
||||
path: "/goodsDetail",
|
||||
query: { skuId, goodsId },
|
||||
};
|
||||
if (!isBuyerLoggedIn()) {
|
||||
redirectToLogin(this.$router, location);
|
||||
return;
|
||||
}
|
||||
window.open(this.$router.resolve(location).href, "_blank");
|
||||
},
|
||||
goShopPage(id) {
|
||||
@@ -308,10 +295,6 @@ export default {
|
||||
}
|
||||
}
|
||||
|
||||
.goods-show-tag-ecoupon {
|
||||
padding: 0 5px;
|
||||
}
|
||||
|
||||
.goods-show-tag-self {
|
||||
--el-tag-bg-color: #fa2c19;
|
||||
--el-tag-border-color: #fa2c19;
|
||||
@@ -336,28 +319,18 @@ export default {
|
||||
}
|
||||
}
|
||||
|
||||
.goods-show-tag-physical {
|
||||
background-color: #e6f4ff;
|
||||
border-color: #b3d8ff;
|
||||
color: #409eff;
|
||||
|
||||
:deep(.el-tag__content) {
|
||||
color: #409eff;
|
||||
}
|
||||
}
|
||||
|
||||
.goods-show-seller {
|
||||
// padding:3px 0;
|
||||
vertical-align: middle;
|
||||
}
|
||||
.container {
|
||||
margin:25px auto 15px auto;
|
||||
width: 1184px;
|
||||
margin: 20px auto 24px;
|
||||
width: 1200px;
|
||||
min-width: 1000px;
|
||||
position: relative;
|
||||
}
|
||||
.price-sort:hover {
|
||||
color: #e23a3a;
|
||||
color: $theme_color;
|
||||
}
|
||||
.goods-box {
|
||||
display: flex;
|
||||
@@ -383,16 +356,16 @@ export default {
|
||||
}
|
||||
.goods-list-tool {
|
||||
width: 100%;
|
||||
height: 38px;
|
||||
border: 1px solid #ccc;
|
||||
background-color: #f1f1f1;
|
||||
height: 48px;
|
||||
border: 1px solid #eee;
|
||||
background-color: #fff;
|
||||
}
|
||||
.goods-list-tool ul {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
height: 100%;
|
||||
padding-left: 15px;
|
||||
font-size: 12px;
|
||||
font-size: 14px;
|
||||
margin: 0;
|
||||
list-style: none;
|
||||
|
||||
@@ -435,33 +408,105 @@ export default {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 2px;
|
||||
padding: 3px 5px;
|
||||
border: 1px solid #ccc;
|
||||
margin-left: -1px;
|
||||
background-color: #fff;
|
||||
height: 48px;
|
||||
padding: 0 16px;
|
||||
border: none;
|
||||
margin-left: 0;
|
||||
background-color: transparent;
|
||||
color: #666;
|
||||
line-height: 1;
|
||||
white-space: nowrap;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
.goods-list-tool li > span:hover {
|
||||
border-color: $theme_color;
|
||||
color: $theme_color;
|
||||
position: relative;
|
||||
text-decoration: none;
|
||||
z-index: 1;
|
||||
}
|
||||
.goods-list-tool li > span .el-icon {
|
||||
font-size: 12px;
|
||||
font-size: 14px;
|
||||
line-height: 1;
|
||||
}
|
||||
.goods-list-tool-active {
|
||||
color: #fff;
|
||||
border-left: 1px solid #ccc;
|
||||
background-color: $theme_color !important;
|
||||
color: $theme_color !important;
|
||||
background-color: transparent !important;
|
||||
font-weight: 600;
|
||||
|
||||
.price-color {
|
||||
color: rgba(255, 255, 255, 0.65) !important;
|
||||
color: $theme_color !important;
|
||||
}
|
||||
}
|
||||
|
||||
.goods-list {
|
||||
column-gap: 12px;
|
||||
padding: 4px 12px 16px;
|
||||
background: #fff;
|
||||
border: 1px solid #eee;
|
||||
border-top: none;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.goods-show-info {
|
||||
width: calc(20% - 10px);
|
||||
margin: 12px 0 0;
|
||||
padding: 12px;
|
||||
border: 1px solid #f0f0f0;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.goods-show-info:hover {
|
||||
border-color: #f0d0cc;
|
||||
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.06);
|
||||
}
|
||||
|
||||
.seckill-price {
|
||||
font-size: 20px;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.goods-show-detail {
|
||||
height: 44px;
|
||||
margin: 8px 0 6px;
|
||||
color: #171A26;
|
||||
font-size: 15px;
|
||||
line-height: 22px;
|
||||
}
|
||||
|
||||
.goods-show-num {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
gap: 8px;
|
||||
margin-bottom: 6px;
|
||||
color: #999;
|
||||
font-size: 13px;
|
||||
font-weight: 400;
|
||||
line-height: 20px;
|
||||
}
|
||||
|
||||
.goods-show-num span {
|
||||
color: #999;
|
||||
font-size: 13px;
|
||||
font-weight: 400;
|
||||
}
|
||||
|
||||
.goods-show-sales {
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.goods-show-seller {
|
||||
color: #438cde;
|
||||
font-size: 14px;
|
||||
|
||||
span:hover {
|
||||
color: $theme_color;
|
||||
}
|
||||
}
|
||||
|
||||
.goods-page {
|
||||
margin: 16px 0 8px;
|
||||
}
|
||||
|
||||
/* ---------------商品栏结束------------------- */
|
||||
</style>
|
||||
|
||||
@@ -12,8 +12,8 @@
|
||||
<span v-if="item.couponType === 'PRICE'" class="fontsize_12 global_color" style="font-size: 15px;">¥<span class="price">{{ $filters.unitPrice(item.price) }}</span></span>
|
||||
<span v-if="item.couponType === 'DISCOUNT'" class="fontsize_12 global_color" style="font-size: 15px;"><span class="price">{{item.discount}}</span>折</span>
|
||||
<span class="describe" style="font-size: 15px;margin-left: 5px;">满{{item.consumeThreshold}}元可用</span>
|
||||
<p style="font-size: 10px;">使用范围:{{useScope(item.scopeType, item.storeName)}}</p>
|
||||
<p style="font-size: 10px;">有效期:{{item.endTime}}</p>
|
||||
<p style="font-size: 14px;">使用范围:{{useScope(item.scopeType, item.storeName)}}</p>
|
||||
<p style="font-size: 14px;">有效期:{{item.endTime}}</p>
|
||||
</el-card>
|
||||
</div>
|
||||
<template #footer>
|
||||
|
||||
@@ -19,55 +19,13 @@
|
||||
</el-carousel>
|
||||
<!-- 登录模块 -->
|
||||
<div class="form-box" @click="hideVerify">
|
||||
<div class="account-number">
|
||||
<div class="tab-switch">
|
||||
<span>{{ type ? '账号登录' : '验证码登录' }}</span>
|
||||
<span @click="type = !type,scannerCodeLoginFLag=false">{{ type ? '验证码登录' : '账号登录' }}</span>
|
||||
</div>
|
||||
<!---->
|
||||
<div @click="scannerCodeLoginFLag=!scannerCodeLoginFLag">{{!scannerCodeLoginFLag ? '扫码登录' : '返回'}}</div>
|
||||
</div>
|
||||
<!--扫码登录-->
|
||||
<div v-show="scannerCodeLoginFLag">
|
||||
<div class="qr-container">
|
||||
<div class='qr-shadow flex' v-show="qrCodeStatus == 'fail'">
|
||||
<span>
|
||||
二维码已失效
|
||||
</span>
|
||||
<el-button size='small' @click="createPCLoginSession">刷新二维码</el-button>
|
||||
</div>
|
||||
<vue-qr
|
||||
:text="qrCode"
|
||||
:margin="0"
|
||||
colorDark="#000"
|
||||
colorLight="#fff"
|
||||
:size="150"
|
||||
></vue-qr>
|
||||
</div>
|
||||
<div class="drag-area">
|
||||
<!-- 等待扫码-->
|
||||
<div v-if="scannerCodeLoginStatus === 0" class="pending-scan">
|
||||
<p>打开手机App/小程序,扫码登录</p>
|
||||
</div>
|
||||
<!-- 已经扫码-->
|
||||
<div v-else-if="scannerCodeLoginStatus === 1" class="scanned">
|
||||
<p>扫码成功,等待确认</p>
|
||||
</div>
|
||||
|
||||
<!-- 存在session,等待发送给客户端验证-->
|
||||
<div v-if="scannerCodeLoginStatus === 2" class="scanned">
|
||||
<p>登录成功,正在页面跳转</p>
|
||||
</div>
|
||||
|
||||
<!-- 已经发送登录请求-->
|
||||
<div v-else-if="scannerCodeLoginStatus === 3" class="quick-logining">
|
||||
<p>取消登录</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="login-tabs">
|
||||
<span :class="{ active: type }" @click="type = true">账号登录</span>
|
||||
<span :class="{ active: !type }" @click="type = false">验证码登录</span>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<div v-show="!scannerCodeLoginFLag">
|
||||
<div>
|
||||
<!-- 账号密码登录 -->
|
||||
<el-form ref="formInline" :model="formData" :rules="ruleInline" v-show="type === true"
|
||||
@click.self="hideVerify">
|
||||
@@ -82,7 +40,7 @@
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="danger" @click.stop="handleSubmit('formInline')" style="width:100%">登录</el-button>
|
||||
<el-button class="login-btn" @click.stop="handleSubmit('formInline')">登录</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<!-- 验证码登录 -->
|
||||
@@ -90,22 +48,17 @@
|
||||
@click.self="hideVerify">
|
||||
<el-form-item prop="mobile">
|
||||
<el-input type="text" v-model="formSms.mobile" clearable placeholder="手机号">
|
||||
<template #prepend><el-icon><Lock /></el-icon></template>
|
||||
<template #prepend><el-icon><Iphone /></el-icon></template>
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
<el-form-item prop="code">
|
||||
<el-input type="text" v-model="formSms.code" placeholder="手机验证码">
|
||||
<template #prepend><el-icon style="font-weight: bold"><Document /></el-icon></template>
|
||||
<template #append><el-button @click="sendCode">{{ codeMsg }}</el-button></template>
|
||||
<template #append><el-button @click.stop="sendCode">{{ codeMsg }}</el-button></template>
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button @click.stop="verifyBtnClick" style="width:100%"
|
||||
:type="verifyStatus?'success':'default'">{{ verifyStatus ? '验证通过' : '点击完成安全验证' }}
|
||||
</el-button>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="danger" @click="handleSubmit('formSms')" style="width:100%">登录</el-button>
|
||||
<el-button class="login-btn" @click="handleSubmit('formSms')">登录</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</div>
|
||||
@@ -126,7 +79,7 @@
|
||||
</svg>
|
||||
</div>
|
||||
<div class="register">
|
||||
<span style="color:red" @click.stop="$router.push('signUp')">还没有账号?点击立即注册</span>
|
||||
<span class="register-link" @click.stop="$router.push('signUp')">立即注册</span>
|
||||
<span @click.stop="$router.push('forgetPassword')">忘记密码</span>
|
||||
</div>
|
||||
</div>
|
||||
@@ -159,33 +112,23 @@ 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,sCLogin,getSCLoginCode} from "@/api/login.js";
|
||||
import { webLogin, loginCallback } from "@/api/login.js";
|
||||
import storage from "@/plugins/storage.js";
|
||||
import verify from "@/components/verify";
|
||||
import vueQr from "vue-qr";
|
||||
import { User, Lock, Document } from "@element-plus/icons-vue";
|
||||
import { User, Lock, Document, Iphone } from "@element-plus/icons-vue";
|
||||
import config from "@/config";
|
||||
|
||||
export default {
|
||||
name: "Login",
|
||||
components: {
|
||||
verify,
|
||||
vueQr,
|
||||
User,
|
||||
Lock,
|
||||
Document,
|
||||
Iphone,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
qrCodeStatus:"success", //
|
||||
qrCode: '',
|
||||
qrSessionToken:'',
|
||||
//是否是二维码登录
|
||||
scannerCodeLoginFLag: false,
|
||||
scannerCodeLoginStatus: 0,
|
||||
qrCodeTimer:null,
|
||||
qrExpireMs: 20000,
|
||||
qrCreateSeq: 0,
|
||||
config,
|
||||
type: true, // true 账号登录 false 验证码登录
|
||||
formData: {
|
||||
@@ -234,10 +177,6 @@ export default {
|
||||
if (this.type) {
|
||||
this.$refs.verify?.init();
|
||||
} else {
|
||||
if (!this.verifyStatus) {
|
||||
Message.warning("请先完成安全验证");
|
||||
return;
|
||||
}
|
||||
if (!this.codeSent) {
|
||||
Message.warning("请先获取短信验证码");
|
||||
return;
|
||||
@@ -274,41 +213,44 @@ export default {
|
||||
},
|
||||
// 发送手机验证码
|
||||
sendCode() {
|
||||
if (this.time === 60) {
|
||||
if (this.formSms.mobile === "") {
|
||||
Message.warning("请先填写手机号");
|
||||
return;
|
||||
}
|
||||
if (!this.verifyStatus) {
|
||||
Message.warning("请先完成安全验证");
|
||||
return;
|
||||
}
|
||||
let params = {
|
||||
mobile: this.formSms.mobile,
|
||||
verificationEnums: "LOGIN",
|
||||
};
|
||||
sendSms(params).then((res) => {
|
||||
if (res.success) {
|
||||
Message.success("验证码发送成功");
|
||||
this.codeSent = true;
|
||||
let that = this;
|
||||
this.interval = setInterval(() => {
|
||||
that.time--;
|
||||
if (that.time === 0) {
|
||||
that.time = 60;
|
||||
that.codeMsg = "重新发送";
|
||||
that.verifyStatus = false;
|
||||
that.codeSent = false;
|
||||
clearInterval(that.interval);
|
||||
} else {
|
||||
that.codeMsg = that.time;
|
||||
}
|
||||
}, 1000);
|
||||
} else {
|
||||
Message.warning(res.message);
|
||||
}
|
||||
}).catch(() => {});
|
||||
if (this.time !== 60) return;
|
||||
if (this.formSms.mobile === "") {
|
||||
Message.warning("请先填写手机号");
|
||||
return;
|
||||
}
|
||||
if (!RegExp.mobile.test(this.formSms.mobile)) {
|
||||
Message.warning("请输入正确的手机号");
|
||||
return;
|
||||
}
|
||||
this.$refs.verify?.init();
|
||||
},
|
||||
dispatchSms() {
|
||||
sendSms({
|
||||
mobile: this.formSms.mobile,
|
||||
verificationEnums: "LOGIN",
|
||||
}).then((res) => {
|
||||
if (res.success) {
|
||||
Message.success("验证码发送成功");
|
||||
this.codeSent = true;
|
||||
this.interval = setInterval(() => {
|
||||
this.time--;
|
||||
if (this.time === 0) {
|
||||
this.time = 60;
|
||||
this.codeMsg = "重新发送";
|
||||
this.verifyStatus = false;
|
||||
this.codeSent = false;
|
||||
clearInterval(this.interval);
|
||||
} else {
|
||||
this.codeMsg = this.time;
|
||||
}
|
||||
}, 1000);
|
||||
} else {
|
||||
this.verifyStatus = false;
|
||||
Message.warning(res.message);
|
||||
}
|
||||
}).catch(() => {
|
||||
this.verifyStatus = false;
|
||||
});
|
||||
},
|
||||
verifyChange(con) {
|
||||
// 拼图验证码回显
|
||||
@@ -336,12 +278,7 @@ export default {
|
||||
} else {
|
||||
this.verifyStatus = true;
|
||||
this.hideVerify();
|
||||
}
|
||||
},
|
||||
// 开启滑块验证
|
||||
verifyBtnClick() {
|
||||
if (!this.verifyStatus) {
|
||||
this.$refs.verify?.init();
|
||||
this.dispatchSms();
|
||||
}
|
||||
},
|
||||
handleWebLogin(type) {
|
||||
@@ -369,92 +306,9 @@ export default {
|
||||
});
|
||||
},
|
||||
|
||||
async createPCLoginSession() {
|
||||
const requestId = ++this.qrCreateSeq;
|
||||
this.clearQRLoginInfo();
|
||||
getSCLoginCode({}).then(response=>{
|
||||
if (requestId !== this.qrCreateSeq) return;
|
||||
if (response.code == 200 && response.result) {
|
||||
this.qrCodeStatus = 'success'
|
||||
let session = response.result;
|
||||
this.qrSessionToken = session.token;
|
||||
this.qrExpireMs = Number(session.duration) > 0 ? Number(session.duration) : 20000;
|
||||
if (session.status === 0) {
|
||||
this.qrCode = session.token;
|
||||
this.refreshQrCode();
|
||||
}
|
||||
this.qrLogin();
|
||||
} else {
|
||||
this.markQrExpired();
|
||||
}
|
||||
}).catch(() => {
|
||||
if (requestId !== this.qrCreateSeq) return;
|
||||
this.markQrExpired();
|
||||
});
|
||||
},
|
||||
|
||||
refreshQrCode() {
|
||||
this.clearQrTimer();
|
||||
this.qrCodeTimer = setTimeout(() => {
|
||||
this.qrCodeStatus = 'fail';
|
||||
this.clearQrTimer();
|
||||
}, this.qrExpireMs);
|
||||
},
|
||||
|
||||
clearQrTimer() {
|
||||
if (this.qrCodeTimer) {
|
||||
clearTimeout(this.qrCodeTimer);
|
||||
}
|
||||
this.qrCodeTimer = null;
|
||||
},
|
||||
|
||||
markQrExpired() {
|
||||
this.qrCodeStatus = 'fail';
|
||||
this.scannerCodeLoginStatus = 0;
|
||||
this.qrSessionToken = '';
|
||||
this.clearQrTimer();
|
||||
},
|
||||
|
||||
clearQRLoginInfo(){
|
||||
this.scannerCodeLoginStatus=0;
|
||||
this.qrSessionToken='';
|
||||
this.clearQrTimer();
|
||||
},
|
||||
|
||||
async qrLogin() {
|
||||
const token = this.qrSessionToken;
|
||||
if(!token) return;
|
||||
sCLogin(token,{beforeSessionStatus:this.scannerCodeLoginStatus}).then(response=>{
|
||||
if (token !== this.qrSessionToken) return;
|
||||
if (response.success) {
|
||||
this.scannerCodeLoginStatus = response.result.status;
|
||||
switch (response.result.status) {
|
||||
case 0:
|
||||
case 1:
|
||||
this.qrLogin();break;
|
||||
case 2:
|
||||
this.clearQRLoginInfo();
|
||||
this.loginSuccess(response.result.token.accessToken,response.result.token.refreshToken);
|
||||
break;
|
||||
case 3:
|
||||
this.createPCLoginSession();
|
||||
break;
|
||||
default:
|
||||
this.markQrExpired();
|
||||
break
|
||||
}
|
||||
} else{
|
||||
this.markQrExpired();
|
||||
}
|
||||
}).catch(() => {
|
||||
if (token !== this.qrSessionToken) return;
|
||||
this.markQrExpired();
|
||||
});
|
||||
},
|
||||
},
|
||||
beforeUnmount() {
|
||||
this.qrCreateSeq++;
|
||||
this.clearQRLoginInfo();
|
||||
clearInterval(this.interval);
|
||||
},
|
||||
mounted() {
|
||||
let uuid = this.$route.query.state;
|
||||
@@ -468,16 +322,6 @@ export default {
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
scannerCodeLoginFLag(v){
|
||||
if(v){
|
||||
this.createPCLoginSession();
|
||||
console.log("二维码登录");
|
||||
}else{
|
||||
console.log("取消二维码登录");
|
||||
this.qrCreateSeq++;
|
||||
this.clearQRLoginInfo();
|
||||
}
|
||||
},
|
||||
type(v) {
|
||||
if (v) {
|
||||
this.$refs.formInline.resetFields();
|
||||
@@ -502,83 +346,44 @@ export default {
|
||||
};
|
||||
</script>
|
||||
<style scoped lang="scss">
|
||||
.drag-area{
|
||||
margin: 10px 0;
|
||||
}
|
||||
.login {
|
||||
height: 100%;
|
||||
background-color: #f0f2f5;
|
||||
}
|
||||
.other{
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
}
|
||||
.qr-container{
|
||||
text-align: center;
|
||||
margin: 20px 0;
|
||||
position: relative;
|
||||
>.qr-shadow{
|
||||
background: rgba(0, 0, 0, 0.45);
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
margin-left: -75px;
|
||||
top: 0;
|
||||
z-index: 99;
|
||||
width: 150px;
|
||||
height: 150px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
flex-direction: column;
|
||||
color: #fff;
|
||||
>span{
|
||||
margin-bottom: 20px;
|
||||
font-size: 13px;
|
||||
letter-spacing: 2px;
|
||||
}
|
||||
}
|
||||
min-height: 100vh;
|
||||
background-color: #f5f5f5;
|
||||
}
|
||||
|
||||
.top-content {
|
||||
width: 100%;
|
||||
height: 80px;
|
||||
height: 72px;
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
|
||||
box-shadow: 0 1px 1px #ddd;
|
||||
background-color: #fff;
|
||||
border-bottom: 1px solid #eee;
|
||||
|
||||
.logo-box {
|
||||
width: 80%;
|
||||
max-width: 1200px;
|
||||
height: 80px;
|
||||
width: 1200px;
|
||||
max-width: calc(100% - 48px);
|
||||
height: 72px;
|
||||
margin: 0 auto;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
img {
|
||||
width: 150px;
|
||||
height: 36px;
|
||||
width: auto;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
div {
|
||||
font-size: 20px;
|
||||
margin-top: 10px;
|
||||
margin-left: 16px;
|
||||
padding-left: 16px;
|
||||
border-left: 1px solid #e5e5e5;
|
||||
font-size: 18px;
|
||||
font-weight: 600;
|
||||
color: #171A26;
|
||||
line-height: 24px;
|
||||
}
|
||||
}
|
||||
}
|
||||
.pending-scan{
|
||||
text-align: center;
|
||||
color:black;
|
||||
}
|
||||
.scanned{
|
||||
text-align: center;
|
||||
color:green;
|
||||
}
|
||||
.quick-logining{
|
||||
text-align: center;
|
||||
color:red;
|
||||
}
|
||||
|
||||
.login-carousel {
|
||||
width: 100%;
|
||||
@@ -586,118 +391,213 @@ export default {
|
||||
|
||||
.demo-carousel {
|
||||
height: 550px;
|
||||
width: inherit;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
width: 100%;
|
||||
overflow: hidden;
|
||||
|
||||
img {
|
||||
display: block;
|
||||
width: 100%;
|
||||
height: 550px;
|
||||
object-fit: cover;
|
||||
object-position: center;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.login-container {
|
||||
--login-card-right: max(96px, 10%);
|
||||
position: relative;
|
||||
width: 100%;
|
||||
height: 550px;
|
||||
}
|
||||
|
||||
.form-box {
|
||||
width: 350px;
|
||||
width: 460px;
|
||||
box-sizing: border-box;
|
||||
position: absolute;
|
||||
top: 80px;
|
||||
right: 15%;
|
||||
padding: 20px;
|
||||
background: rgba(255, 255, 255, 0.8);
|
||||
top: 48px;
|
||||
right: var(--login-card-right);
|
||||
padding: 32px 32px 24px;
|
||||
background: #fff;
|
||||
border-radius: 4px;
|
||||
box-shadow: 0 8px 24px rgba(0, 0, 0, 0.08);
|
||||
|
||||
.account-number {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: baseline;
|
||||
font-weight: bold;
|
||||
:deep(.el-form-item) {
|
||||
margin-bottom: 22px;
|
||||
}
|
||||
|
||||
> div:nth-child(2) {
|
||||
color: $theme_color;
|
||||
cursor: pointer;
|
||||
}
|
||||
:deep(.el-form-item__error) {
|
||||
padding-top: 2px;
|
||||
font-size: 12px;
|
||||
line-height: 16px;
|
||||
}
|
||||
|
||||
.tab-switch {
|
||||
height: 40px;
|
||||
font-size: 14px;
|
||||
:deep(.el-input__wrapper),
|
||||
:deep(.el-input-group__prepend),
|
||||
:deep(.el-input-group__append) {
|
||||
box-shadow: none;
|
||||
background: #fff;
|
||||
}
|
||||
|
||||
span:nth-child(1) {
|
||||
font-size: 16px;
|
||||
border-right: 1px solid #ddd;
|
||||
padding-right: 10px;
|
||||
}
|
||||
:deep(.el-input) {
|
||||
height: 48px;
|
||||
border: 1px solid #e5e5e5;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
span:nth-child(2) {
|
||||
cursor: pointer;
|
||||
padding-left: 10px;
|
||||
:deep(.el-input__inner) {
|
||||
height: 48px;
|
||||
font-size: 16px;
|
||||
color: #171A26;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
color: $theme_color;
|
||||
}
|
||||
:deep(.el-input-group__prepend) {
|
||||
padding: 0 14px;
|
||||
color: #999;
|
||||
font-size: 18px;
|
||||
border-right: 1px solid #f0f0f0;
|
||||
}
|
||||
|
||||
:deep(.el-input-group__append) {
|
||||
padding: 0;
|
||||
border-left: 1px solid #f0f0f0;
|
||||
}
|
||||
|
||||
:deep(.el-input-group__append .el-button) {
|
||||
height: 46px;
|
||||
margin: 0;
|
||||
padding: 0 14px;
|
||||
border: none;
|
||||
color: $theme_color;
|
||||
font-size: 16px;
|
||||
background: transparent;
|
||||
}
|
||||
}
|
||||
|
||||
.login-tabs {
|
||||
display: flex;
|
||||
gap: 32px;
|
||||
margin-bottom: 28px;
|
||||
border-bottom: 1px solid #f0f0f0;
|
||||
|
||||
span {
|
||||
position: relative;
|
||||
padding-bottom: 14px;
|
||||
color: #666;
|
||||
font-size: 18px;
|
||||
line-height: 26px;
|
||||
cursor: pointer;
|
||||
|
||||
&.active {
|
||||
color: #171A26;
|
||||
font-weight: 600;
|
||||
|
||||
&::after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: -1px;
|
||||
height: 2px;
|
||||
background: $theme_color;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.login-btn {
|
||||
width: 100%;
|
||||
height: 48px;
|
||||
border-radius: 4px;
|
||||
font-size: 18px;
|
||||
}
|
||||
|
||||
.login-btn {
|
||||
background: $theme_color !important;
|
||||
border-color: $theme_color !important;
|
||||
color: #fff !important;
|
||||
}
|
||||
|
||||
.verify-con {
|
||||
position: absolute;
|
||||
right: 16%;
|
||||
right: var(--login-card-right);
|
||||
top: 90px;
|
||||
z-index: 10;
|
||||
}
|
||||
|
||||
.other {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
margin-top: 4px;
|
||||
}
|
||||
|
||||
.other-login {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 12px;
|
||||
|
||||
> svg {
|
||||
cursor: pointer;
|
||||
width: 24px;
|
||||
margin-right: 10px;
|
||||
height: 24px;
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
}
|
||||
}
|
||||
|
||||
.register {
|
||||
display: flex;
|
||||
margin-top: -10px;
|
||||
font-size: 12px;
|
||||
align-items: center;
|
||||
gap: 16px;
|
||||
font-size: 15px;
|
||||
|
||||
span {
|
||||
margin-left: 10px;
|
||||
font-size: 12px;
|
||||
color: #666;
|
||||
cursor: pointer;
|
||||
|
||||
&:hover {
|
||||
cursor: pointer;
|
||||
color: $theme_color;
|
||||
}
|
||||
}
|
||||
|
||||
.register-link {
|
||||
color: $theme_color;
|
||||
}
|
||||
}
|
||||
|
||||
.foot {
|
||||
position: fixed;
|
||||
bottom: 4vh;
|
||||
width: 368px;
|
||||
left: calc(50% - 184px);
|
||||
color: rgba(0, 0, 0, 0.45);
|
||||
bottom: 24px;
|
||||
width: 420px;
|
||||
left: calc(50% - 210px);
|
||||
color: #999;
|
||||
font-size: 14px;
|
||||
text-align: center;
|
||||
|
||||
.help {
|
||||
margin: 0 auto;
|
||||
margin-bottom: 1vh;
|
||||
width: 60%;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
gap: 24px;
|
||||
margin-bottom: 8px;
|
||||
|
||||
.item {
|
||||
color: rgba(0, 0, 0, 0.45);
|
||||
}
|
||||
color: #666;
|
||||
text-decoration: none;
|
||||
|
||||
:hover {
|
||||
color: rgba(0, 0, 0, 0.65);
|
||||
&:hover {
|
||||
color: $theme_color;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.copyright {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
|
||||
a {
|
||||
color: #666;
|
||||
text-decoration: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.icon-hover {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
</style>
|
||||
|
||||
@@ -3,65 +3,63 @@
|
||||
<BaseHeader/>
|
||||
<!-- 搜索栏 -->
|
||||
<Search :storeId="storeMsg.storeId || $route.query.id" @search="search"></Search>
|
||||
<!-- 店铺logo -->
|
||||
<div class="shop-logo">
|
||||
<div class="shop-logo-inner">
|
||||
<div class="store-head">
|
||||
<div class="store-head-main">
|
||||
<div class="shop-info">
|
||||
<p class="shop-name">{{ storeMsg.storeName || '店铺' }}</p>
|
||||
<p
|
||||
v-if="storeMsg.storeDesc"
|
||||
:alt="storeMsg.storeDesc"
|
||||
class="shop-desc ellipsis"
|
||||
v-html="storeMsg.storeDesc"
|
||||
></p>
|
||||
</div>
|
||||
<div class="shop-actions">
|
||||
<span class="hover-pointer store-collect-btn" @click="collect">
|
||||
<el-icon :color="storeCollected ? '#ffc107' : '#fff'">
|
||||
<StarFilled />
|
||||
</el-icon>
|
||||
<span>{{
|
||||
storeCollected ? '已收藏店铺' : '收藏店铺'
|
||||
}}</span>
|
||||
</span>
|
||||
<span
|
||||
class="hover-pointer store-service-btn"
|
||||
@click="IMService(storeMsg.storeId, null, null)"
|
||||
class="store-collect-btn"
|
||||
:class="{ 'is-collected': storeCollected }"
|
||||
@click="collect"
|
||||
>
|
||||
<i class="icomoon icon-customer-service"></i>联系客服
|
||||
<el-icon><StarFilled /></el-icon>
|
||||
<span>{{ storeCollected ? '已收藏店铺' : '收藏店铺' }}</span>
|
||||
</span>
|
||||
<span class="store-service-btn" @click="IMService(storeMsg.storeId, null, null)">联系客服</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="store-category">
|
||||
<ul class="cate-list">
|
||||
<li
|
||||
class="cate-item"
|
||||
@click="searchByCate({ id: '', labelName: '店铺推荐' })"
|
||||
>
|
||||
首页
|
||||
</li>
|
||||
<li v-for="(cate, index) in cateList" :key="index" class="cate-item">
|
||||
<el-dropdown v-if="cate.children.length" trigger="hover">
|
||||
<div @click.self="searchByCate(cate)">
|
||||
{{ cate.labelName }}
|
||||
<el-icon><ArrowDown /></el-icon>
|
||||
</div>
|
||||
<template #dropdown>
|
||||
<el-dropdown-menu>
|
||||
<el-dropdown-item
|
||||
v-for="sec in cate.children"
|
||||
:key="sec.id"
|
||||
@click="searchByCate(sec)"
|
||||
>{{ sec.labelName }}</el-dropdown-item>
|
||||
</el-dropdown-menu>
|
||||
</template>
|
||||
</el-dropdown>
|
||||
<span v-else @click.self="searchByCate(cate)">{{
|
||||
cate.labelName
|
||||
}}</span>
|
||||
</li>
|
||||
</ul>
|
||||
<div class="store-category">
|
||||
<ul class="cate-list">
|
||||
<li
|
||||
class="cate-item"
|
||||
:class="{ active: !params.storeCatId }"
|
||||
@click="searchByCate({ id: '', labelName: '店铺推荐' })"
|
||||
>
|
||||
首页
|
||||
</li>
|
||||
<li
|
||||
v-for="(cate, index) in cateList"
|
||||
:key="index"
|
||||
class="cate-item"
|
||||
:class="{ active: isCateActive(cate) }"
|
||||
@click="searchByCate(cate)"
|
||||
>
|
||||
<el-dropdown v-if="cate.children && cate.children.length" trigger="hover">
|
||||
<div class="cate-label">
|
||||
{{ cate.labelName }}
|
||||
<el-icon><ArrowDown /></el-icon>
|
||||
</div>
|
||||
<template #dropdown>
|
||||
<el-dropdown-menu>
|
||||
<el-dropdown-item
|
||||
v-for="sec in cate.children"
|
||||
:key="sec.id"
|
||||
@click.stop="searchByCate(sec)"
|
||||
>{{ sec.labelName }}</el-dropdown-item>
|
||||
</el-dropdown-menu>
|
||||
</template>
|
||||
</el-dropdown>
|
||||
<span v-else>{{ cate.labelName }}</span>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -72,42 +70,49 @@
|
||||
|
||||
|
||||
<div v-else class="store-goods-section">
|
||||
<div class="promotion-decorate">{{ cateName }}</div>
|
||||
<div class="store-goods-hd">{{ cateName }}</div>
|
||||
<div class="goods-list">
|
||||
<empty v-if="goodsList.length === 0"/>
|
||||
<template v-else>
|
||||
<div
|
||||
v-for="(item, index) in goodsList"
|
||||
v-else
|
||||
:key="index"
|
||||
class="goods-show-info"
|
||||
@click="goGoodsDetail(item.id, item.goodsId)"
|
||||
>
|
||||
|
||||
<div class="goods-show-img">
|
||||
<img :src="item.small" alt=""/>
|
||||
<img :src="item.thumbnail || item.small" alt=""/>
|
||||
</div>
|
||||
<div class="goods-show-price">
|
||||
<span>
|
||||
<span class="seckill-price text-danger">{{ $filters.unitPrice(item.price, "¥") }}</span>
|
||||
</span>
|
||||
<span class="seckill-price text-danger">{{ $filters.unitPrice(item.price, "¥") }}</span>
|
||||
</div>
|
||||
<div class="goods-show-detail">
|
||||
<el-tag
|
||||
v-if="item.salesModel === 'WHOLESALE'"
|
||||
class="goods-show-tag goods-show-tag-wholesale"
|
||||
>批发</el-tag>
|
||||
<span>{{ item.goodsName }}</span>
|
||||
</div>
|
||||
<div class="goods-show-num">
|
||||
已有<span>{{ item.commentNum || 0 }}</span>人评价
|
||||
<span>{{ formatGrade(item.grade) }}%好评</span>
|
||||
<span class="goods-show-sales">销量 {{ item.buyCount || 0 }}</span>
|
||||
</div>
|
||||
<div class="goods-show-right" v-if="item.selfOperated">
|
||||
<el-tag class="goods-show-tag goods-show-tag-self">自营</el-tag>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
<div class="goods-page">
|
||||
<el-pagination v-model:current-page="params.pageNumber"
|
||||
<div class="goods-page" v-if="total > 0">
|
||||
<el-pagination
|
||||
v-model:current-page="params.pageNumber"
|
||||
v-model:page-size="params.pageSize"
|
||||
:total="total"
|
||||
@current-change="changePageNum"
|
||||
@size-change="changePageSize"
|
||||
layout="sizes, prev, pager, next"></el-pagination>
|
||||
layout="total, prev, pager, next, sizes"
|
||||
></el-pagination>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<BaseFooter/>
|
||||
@@ -311,9 +316,22 @@ export default {
|
||||
searchByCate(cate) {
|
||||
// 搜索同分类下商品
|
||||
this.params.storeCatId = cate.id;
|
||||
this.params.pageNumber = 1;
|
||||
this.cateName = cate.labelName;
|
||||
this.getGoodsList();
|
||||
},
|
||||
isCateActive(cate) {
|
||||
if (!cate || !this.params.storeCatId) return false;
|
||||
if (this.params.storeCatId === cate.id) return true;
|
||||
return Array.isArray(cate.children) && cate.children.some((sec) => sec.id === this.params.storeCatId);
|
||||
},
|
||||
formatGrade(grade) {
|
||||
if (grade === null || grade === undefined || grade === "") return 100;
|
||||
const num = Number(grade);
|
||||
if (Number.isNaN(num)) return 100;
|
||||
const fixed = Number(num.toFixed(1));
|
||||
return fixed % 1 === 0 ? fixed.toFixed(0) : String(fixed);
|
||||
},
|
||||
// 分页 修改页码
|
||||
changePageNum(val) {
|
||||
this.params.pageNumber = val;
|
||||
@@ -364,123 +382,285 @@ export default {
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@import "../assets/styles/goodsList.scss";
|
||||
|
||||
.merchant {
|
||||
margin: 0 auto;
|
||||
min-height: 100%;
|
||||
background: #f5f5f5;
|
||||
}
|
||||
|
||||
.shop-logo {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
background-color: #666;
|
||||
padding: 4px;
|
||||
color: #fff;
|
||||
.store-head {
|
||||
width: 1200px;
|
||||
margin: 0 auto;
|
||||
background: #fff;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.shop-logo-inner {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: flex-start;
|
||||
gap: 8px;
|
||||
width: 1200px;
|
||||
margin: 0 auto;
|
||||
.store-head-main {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
gap: 24px;
|
||||
padding: 20px 24px 16px;
|
||||
}
|
||||
|
||||
.shop-info {
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.shop-name {
|
||||
margin: 0;
|
||||
color: #171A26;
|
||||
font-size: 20px;
|
||||
font-weight: 600;
|
||||
line-height: 28px;
|
||||
}
|
||||
|
||||
.shop-desc {
|
||||
margin: 6px 0 0;
|
||||
max-width: 760px;
|
||||
color: #999;
|
||||
font-size: 13px;
|
||||
line-height: 20px;
|
||||
}
|
||||
|
||||
.shop-actions {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
flex-shrink: 0;
|
||||
gap: 20px;
|
||||
color: #171A26;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.store-collect-btn,
|
||||
.store-service-btn {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
cursor: pointer;
|
||||
|
||||
&:hover {
|
||||
color: $theme_color;
|
||||
}
|
||||
}
|
||||
|
||||
.store-collect-btn {
|
||||
.el-icon {
|
||||
color: #999;
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.shop-info {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
gap: 12px;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.shop-name {
|
||||
margin: 0;
|
||||
font-size: 20px;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.shop-desc {
|
||||
margin: 0;
|
||||
font-size: 14px;
|
||||
max-height: 40px;
|
||||
max-width: 400px;
|
||||
}
|
||||
|
||||
.shop-actions {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
gap: 16px;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.store-collect-btn {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
}
|
||||
|
||||
.store-service-btn {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
min-width: 80px;
|
||||
&.is-collected,
|
||||
&.is-collected .el-icon {
|
||||
color: $theme_color;
|
||||
}
|
||||
}
|
||||
|
||||
.store-category {
|
||||
background-color: #005aa0;
|
||||
color: #fff;
|
||||
border-top: 1px solid #f0f0f0;
|
||||
}
|
||||
|
||||
.cate-list {
|
||||
width: 1200px;
|
||||
margin: 0 auto;
|
||||
clear: left;
|
||||
height: 30px;
|
||||
line-height: 30px;
|
||||
.cate-list {
|
||||
display: flex;
|
||||
align-items: stretch;
|
||||
width: 100%;
|
||||
height: 48px;
|
||||
margin: 0;
|
||||
padding: 0 8px;
|
||||
list-style: none;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.cate-item {
|
||||
margin-right: 25px;
|
||||
float: left;
|
||||
.cate-item {
|
||||
position: relative;
|
||||
height: 48px;
|
||||
padding: 0 18px;
|
||||
color: #666;
|
||||
font-size: 15px;
|
||||
line-height: 48px;
|
||||
cursor: pointer;
|
||||
|
||||
&:hover {
|
||||
color: #171A26;
|
||||
}
|
||||
|
||||
&.active {
|
||||
color: #171A26;
|
||||
font-weight: 600;
|
||||
|
||||
&::after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
left: 18px;
|
||||
right: 18px;
|
||||
bottom: 0;
|
||||
height: 2px;
|
||||
border-radius: 1px;
|
||||
background: $theme_color;
|
||||
}
|
||||
}
|
||||
|
||||
.cate-item:hover {
|
||||
cursor: pointer;
|
||||
}
|
||||
:deep(.el-dropdown) {
|
||||
color: inherit;
|
||||
font-size: inherit;
|
||||
line-height: inherit;
|
||||
vertical-align: top;
|
||||
outline: none;
|
||||
}
|
||||
|
||||
:deep(.el-tooltip__trigger) {
|
||||
outline: none;
|
||||
}
|
||||
}
|
||||
|
||||
.promotion-decorate::before,
|
||||
.promotion-decorate::after {
|
||||
background-image: url("/src/assets/images/sprite@2x.png");
|
||||
.cate-label {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 2px;
|
||||
color: inherit;
|
||||
line-height: 48px;
|
||||
|
||||
.el-icon {
|
||||
font-size: 12px;
|
||||
}
|
||||
}
|
||||
|
||||
.store-goods-section {
|
||||
width: 1200px;
|
||||
max-width: 100%;
|
||||
margin: 0 auto;
|
||||
padding: 0 10px;
|
||||
margin: 16px auto 24px;
|
||||
background: #fff;
|
||||
border-radius: 4px;
|
||||
box-sizing: border-box;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.goods-list {
|
||||
width: 100%;
|
||||
margin: 0;
|
||||
column-gap: 10px;
|
||||
}
|
||||
.store-goods-hd {
|
||||
padding: 16px 24px 0;
|
||||
color: #171A26;
|
||||
font-size: 16px;
|
||||
font-weight: 600;
|
||||
line-height: 24px;
|
||||
}
|
||||
|
||||
.goods-show-info {
|
||||
width: calc(20% - 8px);
|
||||
min-width: 0;
|
||||
}
|
||||
.goods-list {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(5, minmax(0, 1fr));
|
||||
gap: 12px;
|
||||
width: 100%;
|
||||
margin: 0;
|
||||
padding: 12px 16px 4px;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.seckill-price {
|
||||
font-size: 16px;
|
||||
}
|
||||
.goods-show-info {
|
||||
width: auto;
|
||||
min-width: 0;
|
||||
margin: 0;
|
||||
padding: 12px;
|
||||
border: 1px solid #f0f0f0;
|
||||
border-radius: 4px;
|
||||
background: #fff;
|
||||
box-sizing: border-box;
|
||||
cursor: pointer;
|
||||
|
||||
.goods-show-detail {
|
||||
height: 32px;
|
||||
line-height: 16px;
|
||||
&:hover {
|
||||
border-color: #f0d0cc;
|
||||
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.06);
|
||||
}
|
||||
}
|
||||
|
||||
.goods-show-img img {
|
||||
display: block;
|
||||
width: 100%;
|
||||
aspect-ratio: 1;
|
||||
object-fit: cover;
|
||||
}
|
||||
|
||||
.goods-show-price {
|
||||
margin-top: 8px;
|
||||
}
|
||||
|
||||
.seckill-price {
|
||||
color: $theme_color;
|
||||
font-size: 20px;
|
||||
font-weight: 600;
|
||||
line-height: 28px;
|
||||
}
|
||||
|
||||
.goods-show-detail {
|
||||
height: 44px;
|
||||
margin: 6px 0;
|
||||
overflow: hidden;
|
||||
color: #171A26;
|
||||
font-size: 14px;
|
||||
line-height: 22px;
|
||||
text-overflow: ellipsis;
|
||||
display: -webkit-box;
|
||||
-webkit-line-clamp: 2;
|
||||
line-clamp: 2;
|
||||
-webkit-box-orient: vertical;
|
||||
}
|
||||
|
||||
.goods-show-num {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
gap: 8px;
|
||||
margin: 0;
|
||||
color: #999;
|
||||
font-size: 13px;
|
||||
font-weight: 400;
|
||||
line-height: 20px;
|
||||
|
||||
span {
|
||||
color: #999;
|
||||
font-size: 13px;
|
||||
font-weight: 400;
|
||||
}
|
||||
}
|
||||
|
||||
.goods-show-sales {
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.goods-show-right {
|
||||
display: flex;
|
||||
margin-top: 6px;
|
||||
}
|
||||
|
||||
.goods-show-tag {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
height: 18px;
|
||||
margin-right: 4px;
|
||||
padding: 0 4px;
|
||||
line-height: 1;
|
||||
vertical-align: 1px;
|
||||
}
|
||||
|
||||
.goods-show-tag-self {
|
||||
--el-tag-bg-color: #fa2c19;
|
||||
--el-tag-border-color: #fa2c19;
|
||||
--el-tag-text-color: #fff;
|
||||
background-color: #fa2c19;
|
||||
border-color: #fa2c19;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.goods-show-tag-wholesale {
|
||||
--el-tag-bg-color: #f9f0ff;
|
||||
--el-tag-border-color: #d3adf7;
|
||||
--el-tag-text-color: #9254de;
|
||||
background-color: #f9f0ff;
|
||||
border-color: #d3adf7;
|
||||
color: #9254de;
|
||||
}
|
||||
|
||||
.goods-page {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
width: 100%;
|
||||
margin: 0;
|
||||
padding: 16px;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -1,16 +1,21 @@
|
||||
<template>
|
||||
<div class="sign-up" @click="hideVerify">
|
||||
<div style="height:50px;"></div>
|
||||
<div class="logo-box">
|
||||
<img
|
||||
width="150"
|
||||
:src="$store.state.logoImg"
|
||||
@click="$router.push('/')"
|
||||
/>
|
||||
<div>注册</div>
|
||||
<div class="top-content">
|
||||
<div class="top-inner">
|
||||
<div class="logo-box">
|
||||
<img :src="$store.state.logoImg" @click="$router.push('/')" />
|
||||
<div>欢迎注册</div>
|
||||
</div>
|
||||
<div class="to-login">已有账号?<a @click.stop="$router.push('login')">立即登录</a></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="login-container">
|
||||
<!-- 注册 -->
|
||||
<div class="signup-banner">
|
||||
<img
|
||||
class="signup-bg"
|
||||
src="https://lili-system.oss-cn-beijing.aliyuncs.com/background.jpg"
|
||||
alt=""
|
||||
/>
|
||||
<div class="signup-card">
|
||||
<el-form
|
||||
ref="formRegist"
|
||||
:model="formRegist"
|
||||
@@ -55,27 +60,21 @@
|
||||
placeholder="手机验证码"
|
||||
>
|
||||
<template #prepend><el-icon style="font-weight: bold"><Document /></el-icon></template>
|
||||
<template #append><el-button @click="sendCode">{{ codeMsg }}</el-button></template>
|
||||
<template #append><el-button @click.stop="sendCode">{{ codeMsg }}</el-button></template>
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button @click="verifyBtnClick" style="width:100%" :type="verifyStatus?'success':'default'">{{verifyStatus?'验证通过':'点击完成安全验证'}}</el-button>
|
||||
<el-button class="signup-btn" @click="handleRegist">注册</el-button>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="danger" size="large" @click="handleRegist" style="width:100%"
|
||||
>注册</el-button
|
||||
>
|
||||
</el-form-item>
|
||||
<el-form-item><span class="color999">点击注册,表示您同意《<router-link to="/article?id=1371992704333905920" target="_blank">商城用户协议</router-link>》</span></el-form-item>
|
||||
<p class="agreement">点击注册,表示您同意《<router-link to="/article?id=1371992704333905920" target="_blank">商城用户协议</router-link>》</p>
|
||||
</el-form>
|
||||
<!-- 拼图验证码 -->
|
||||
<Verify
|
||||
ref="verify"
|
||||
class="verify-con"
|
||||
:verifyType="verifyType"
|
||||
@change="verifyChange"
|
||||
></Verify>
|
||||
<div class="login-btn">已有账号?<a @click.stop="$router.push('login')">立即登录</a></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="foot">
|
||||
<div type="flex" justify="space-around" class="help">
|
||||
@@ -164,140 +163,259 @@ export default {
|
||||
},
|
||||
// 发送短信验证码
|
||||
sendCode () {
|
||||
if (this.time === 60) {
|
||||
if (this.formRegist.mobilePhone === '') {
|
||||
Message.warning('请先填写手机号');
|
||||
return;
|
||||
}
|
||||
if (!this.verifyStatus) {
|
||||
Message.warning('请先完成安全验证');
|
||||
return;
|
||||
}
|
||||
let params = {
|
||||
mobile: this.formRegist.mobilePhone,
|
||||
verificationEnums: 'REGISTER'
|
||||
};
|
||||
sendSms(params).then(res => {
|
||||
if (res.success) {
|
||||
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 {
|
||||
Message.warning(res.message || '验证码发送失败');
|
||||
}
|
||||
}).catch(() => {});
|
||||
if (this.time !== 60) return;
|
||||
if (this.formRegist.mobilePhone === '') {
|
||||
Message.warning('请先填写手机号');
|
||||
return;
|
||||
}
|
||||
if (!RegExp.mobile.test(this.formRegist.mobilePhone)) {
|
||||
Message.warning('请输入正确的手机号');
|
||||
return;
|
||||
}
|
||||
this.$refs.verify?.init();
|
||||
},
|
||||
dispatchSms () {
|
||||
sendSms({
|
||||
mobile: this.formRegist.mobilePhone,
|
||||
verificationEnums: 'REGISTER'
|
||||
}).then(res => {
|
||||
if (res.success) {
|
||||
Message.success('验证码发送成功');
|
||||
this.interval = setInterval(() => {
|
||||
this.time--;
|
||||
if (this.time === 0) {
|
||||
this.time = 60;
|
||||
this.codeMsg = '重新发送';
|
||||
this.verifyStatus = false;
|
||||
clearInterval(this.interval);
|
||||
} else {
|
||||
this.codeMsg = this.time;
|
||||
}
|
||||
}, 1000);
|
||||
} else {
|
||||
this.verifyStatus = false;
|
||||
Message.warning(res.message || '验证码发送失败');
|
||||
}
|
||||
}).catch(() => {
|
||||
this.verifyStatus = false;
|
||||
});
|
||||
},
|
||||
// 图片验证码成功回调
|
||||
verifyChange (con) {
|
||||
if (!con.status) return;
|
||||
this.hideVerify();
|
||||
this.verifyStatus = true;
|
||||
},
|
||||
// 打开图片验证码
|
||||
verifyBtnClick () {
|
||||
if (!this.verifyStatus) {
|
||||
this.$refs.verify?.init();
|
||||
}
|
||||
this.dispatchSms();
|
||||
}
|
||||
},
|
||||
mounted () {
|
||||
this.$refs.formRegist.resetFields();
|
||||
document.querySelector('.sign-up').style.height = window.innerHeight + 'px'
|
||||
}
|
||||
};
|
||||
</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 40px;
|
||||
.sign-up {
|
||||
min-height: 100vh;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
background: #f5f5f5;
|
||||
}
|
||||
|
||||
.top-content {
|
||||
background: #fff;
|
||||
border-bottom: 1px solid #eee;
|
||||
}
|
||||
|
||||
.top-inner {
|
||||
width: 1200px;
|
||||
max-width: calc(100% - 48px);
|
||||
height: 72px;
|
||||
margin: 0 auto;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.logo-box {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
.signup-form {
|
||||
width: 300px;
|
||||
img {
|
||||
height: 36px;
|
||||
width: auto;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.login-btn{
|
||||
position: absolute;
|
||||
right: 20px;
|
||||
top: -45px;
|
||||
div {
|
||||
margin-left: 16px;
|
||||
padding-left: 16px;
|
||||
border-left: 1px solid #e5e5e5;
|
||||
font-size: 18px;
|
||||
font-weight: 600;
|
||||
color: #171A26;
|
||||
line-height: 24px;
|
||||
}
|
||||
}
|
||||
|
||||
.verify-con{
|
||||
.to-login {
|
||||
font-size: 15px;
|
||||
color: #666;
|
||||
|
||||
a {
|
||||
margin-left: 4px;
|
||||
color: $theme_color;
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
|
||||
.signup-banner {
|
||||
position: relative;
|
||||
height: 680px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.signup-bg {
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: cover;
|
||||
object-position: center;
|
||||
}
|
||||
|
||||
.signup-card {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
right: max(72px, 8%);
|
||||
transform: translateY(-50%);
|
||||
z-index: 1;
|
||||
width: 480px;
|
||||
box-sizing: border-box;
|
||||
padding: 36px 40px 28px;
|
||||
background: #fff;
|
||||
border-radius: 4px;
|
||||
box-shadow: 0 8px 24px rgba(0, 0, 0, 0.08);
|
||||
}
|
||||
|
||||
.signup-form {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.signup-card {
|
||||
:deep(.el-form-item) {
|
||||
margin-bottom: 22px;
|
||||
}
|
||||
|
||||
:deep(.el-form-item__error) {
|
||||
padding-top: 2px;
|
||||
font-size: 12px;
|
||||
line-height: 16px;
|
||||
}
|
||||
|
||||
:deep(.el-input__wrapper),
|
||||
:deep(.el-input-group__prepend),
|
||||
:deep(.el-input-group__append) {
|
||||
box-shadow: none;
|
||||
background: #fff;
|
||||
}
|
||||
|
||||
:deep(.el-input) {
|
||||
height: 48px;
|
||||
border: 1px solid #e5e5e5;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
:deep(.el-input__inner) {
|
||||
height: 48px;
|
||||
font-size: 16px;
|
||||
color: #171A26;
|
||||
}
|
||||
|
||||
:deep(.el-input-group__prepend) {
|
||||
padding: 0 14px;
|
||||
color: #999;
|
||||
font-size: 18px;
|
||||
border-right: 1px solid #f0f0f0;
|
||||
}
|
||||
|
||||
:deep(.el-input-group__append) {
|
||||
padding: 0;
|
||||
border-left: 1px solid #f0f0f0;
|
||||
}
|
||||
|
||||
:deep(.el-input-group__append .el-button) {
|
||||
height: 46px;
|
||||
margin: 0;
|
||||
padding: 0 14px;
|
||||
border: none;
|
||||
color: $theme_color;
|
||||
font-size: 16px;
|
||||
background: transparent;
|
||||
}
|
||||
}
|
||||
|
||||
.signup-btn {
|
||||
width: 100%;
|
||||
height: 48px;
|
||||
border-radius: 4px;
|
||||
font-size: 18px;
|
||||
background: $theme_color !important;
|
||||
border-color: $theme_color !important;
|
||||
color: #fff !important;
|
||||
}
|
||||
|
||||
.agreement {
|
||||
margin: 0;
|
||||
font-size: 14px;
|
||||
line-height: 22px;
|
||||
color: #999;
|
||||
|
||||
a {
|
||||
color: $theme_color;
|
||||
text-decoration: none;
|
||||
}
|
||||
}
|
||||
|
||||
.verify-con {
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
top: 80px;
|
||||
top: 120px;
|
||||
transform: translateX(-50%);
|
||||
z-index: 10;
|
||||
}
|
||||
|
||||
.other-login {
|
||||
margin: 0 auto;
|
||||
.el-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);
|
||||
bottom: 24px;
|
||||
width: 420px;
|
||||
left: calc(50% - 210px);
|
||||
color: #999;
|
||||
font-size: 14px;
|
||||
text-align: center;
|
||||
|
||||
.help {
|
||||
margin: 0 auto;
|
||||
margin-bottom: 1vh;
|
||||
width: 60%;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
gap: 24px;
|
||||
margin-bottom: 8px;
|
||||
|
||||
.item {
|
||||
color: rgba(0, 0, 0, 0.45);
|
||||
color: #666;
|
||||
text-decoration: none;
|
||||
|
||||
&:hover {
|
||||
color: $theme_color;
|
||||
}
|
||||
}
|
||||
:hover {
|
||||
color: rgba(0, 0, 0, 0.65);
|
||||
}
|
||||
|
||||
.copyright {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
|
||||
a {
|
||||
color: #666;
|
||||
text-decoration: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,11 +3,11 @@
|
||||
<BaseHeader></BaseHeader>
|
||||
<Search></Search>
|
||||
|
||||
<div class="title-bg"><p>文章帮助中心</p></div>
|
||||
<div class="container width_1200">
|
||||
<h1 class="page-title">文章帮助中心</h1>
|
||||
<div class="layoutAll">
|
||||
<el-aside class="side-bar" width="200px">
|
||||
<div class="article-cate">文章分类列表</div>
|
||||
<el-aside class="side-bar" width="220px">
|
||||
<div class="article-cate">文章分类</div>
|
||||
<el-menu
|
||||
class="side-menu"
|
||||
:key="menuKey"
|
||||
@@ -15,36 +15,33 @@
|
||||
:default-openeds="openName"
|
||||
@select="onSelect"
|
||||
>
|
||||
<el-sub-menu
|
||||
v-for="(menu, index) in list"
|
||||
v-show="menu.children"
|
||||
:key="index"
|
||||
:index="menu.articleCategoryName"
|
||||
>
|
||||
<template #title>
|
||||
<span>{{ menu.articleCategoryName }}</span>
|
||||
</template>
|
||||
<el-menu-item
|
||||
v-for="(chlidren, i) in menu.children"
|
||||
:key="i"
|
||||
:index="String(chlidren.id)"
|
||||
>{{ chlidren.articleCategoryName }}</el-menu-item>
|
||||
</el-sub-menu>
|
||||
<template v-for="(menu, index) in list" :key="menu.id || index">
|
||||
<el-sub-menu v-if="menu.children && menu.children.length" :index="String(menu.id)">
|
||||
<template #title>
|
||||
<span @click="onSelect(menu.id)">{{ menu.articleCategoryName }}</span>
|
||||
</template>
|
||||
<el-menu-item
|
||||
v-for="(child, i) in menu.children"
|
||||
:key="child.id || i"
|
||||
:index="String(child.id)"
|
||||
>{{ child.articleCategoryName }}</el-menu-item>
|
||||
</el-sub-menu>
|
||||
<el-menu-item v-else :index="String(menu.id)">{{ menu.articleCategoryName }}</el-menu-item>
|
||||
</template>
|
||||
</el-menu>
|
||||
</el-aside>
|
||||
<el-main class="content ml_10">
|
||||
<el-main class="content">
|
||||
<ul class="article-list" v-show="showList">
|
||||
<li v-for="(article, index) in articleList" :key="index" @click="getDetail(article.id)">
|
||||
<li v-if="!articleList.length" class="article-empty">暂无文章</li>
|
||||
<li v-for="(article, index) in articleList" :key="article.id || index" @click="getDetail(article.id)">
|
||||
{{ article.title }}
|
||||
</li>
|
||||
</ul>
|
||||
<transition mode="out-in">
|
||||
<div v-show="!showList">
|
||||
<a class="back-btn" @click="showList = true"><返回上一级</a>
|
||||
<h2 class="mt_10 mb_10">{{ detail.title }}</h2>
|
||||
<div class="mt_10 mb_10" v-html="detail.content"></div>
|
||||
</div>
|
||||
</transition>
|
||||
<div v-show="!showList" class="article-detail">
|
||||
<button type="button" class="back-btn" @click="showList = true">返回列表</button>
|
||||
<h2>{{ detail.title }}</h2>
|
||||
<div class="article-html" v-html="detail.content"></div>
|
||||
</div>
|
||||
</el-main>
|
||||
</div>
|
||||
</div>
|
||||
@@ -82,26 +79,28 @@ export default {
|
||||
getCateList () {
|
||||
articleCateList().then(res => {
|
||||
if (res.success) {
|
||||
this.list = res.result
|
||||
if (this.$route.query.id) {
|
||||
this.list = res.result || []
|
||||
this.openName = []
|
||||
if (this.$route.query.id && this.detail && this.detail.categoryId) {
|
||||
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
|
||||
const children = e.children || []
|
||||
const hitParent = String(e.id) === String(this.activeName)
|
||||
const hitChild = children.some(i => i && String(i.id) === String(this.activeName))
|
||||
if ((hitParent || hitChild) && children.length) {
|
||||
this.openName.push(String(e.id))
|
||||
}
|
||||
})
|
||||
} else {
|
||||
this.activeName = this.list[0].children[0].id
|
||||
this.openName.push(this.list[0].articleCategoryName)
|
||||
} else if (this.list[0] && this.list[0].id) {
|
||||
this.activeName = this.list[0].id
|
||||
if (this.list[0].children && this.list[0].children.length) {
|
||||
this.openName.push(String(this.list[0].id))
|
||||
}
|
||||
}
|
||||
this.menuKey++
|
||||
this.getList(this.activeName)
|
||||
if (this.activeName) {
|
||||
this.getList(this.activeName)
|
||||
}
|
||||
}
|
||||
})
|
||||
},
|
||||
@@ -133,76 +132,152 @@ export default {
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.content {
|
||||
padding: 15px 50px;
|
||||
.container {
|
||||
margin: 0 auto;
|
||||
padding: 20px 0 40px;
|
||||
}
|
||||
|
||||
.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;
|
||||
.page-title {
|
||||
margin: 0 0 16px;
|
||||
color: #171A26;
|
||||
font-size: 20px;
|
||||
font-weight: 600;
|
||||
line-height: 28px;
|
||||
}
|
||||
|
||||
.layoutAll {
|
||||
display: flex;
|
||||
min-height: 1200px;
|
||||
@include background_color($light_background_color);
|
||||
align-items: stretch;
|
||||
gap: 16px;
|
||||
}
|
||||
|
||||
.container {
|
||||
margin: 0 auto;
|
||||
padding: 20px 0;
|
||||
.side-bar,
|
||||
.content {
|
||||
background: #fff;
|
||||
border: 1px solid #eee;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.side-bar a {
|
||||
@include title_color($light_title_color);
|
||||
.side-bar {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
flex-shrink: 0;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.layout-footer-center {
|
||||
padding: 0px 15px;
|
||||
padding-bottom: 15px;
|
||||
text-align: center;
|
||||
.article-cate {
|
||||
height: 48px;
|
||||
padding: 0 16px;
|
||||
border-bottom: 1px solid #f0f0f0;
|
||||
color: #171A26;
|
||||
font-size: 15px;
|
||||
font-weight: 600;
|
||||
line-height: 48px;
|
||||
}
|
||||
.title-bg{
|
||||
height: 100px;
|
||||
width: 100%;
|
||||
background-color: #7b7b7b;
|
||||
p{
|
||||
width: 1200px;
|
||||
font-size: 30px;
|
||||
height: 100px;
|
||||
line-height: 100px;
|
||||
color: #fff;
|
||||
margin: 0 auto;
|
||||
padding-left: 10px;
|
||||
|
||||
.side-menu {
|
||||
flex: 1;
|
||||
border-right: none;
|
||||
padding: 8px 0 12px;
|
||||
|
||||
:deep(.el-sub-menu__title),
|
||||
:deep(.el-menu-item) {
|
||||
height: 40px;
|
||||
line-height: 40px;
|
||||
color: #171A26;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
:deep(.el-sub-menu__title:hover),
|
||||
:deep(.el-menu-item:hover) {
|
||||
background: #fafafa;
|
||||
color: $theme_color;
|
||||
}
|
||||
|
||||
:deep(.el-menu-item.is-active),
|
||||
:deep(.el-sub-menu.is-active > .el-sub-menu__title) {
|
||||
background: #fff5f4;
|
||||
color: $theme_color;
|
||||
}
|
||||
}
|
||||
.article-cate{
|
||||
width: 200px;
|
||||
height: 30px;
|
||||
color: #fff;
|
||||
line-height: 30px;
|
||||
text-align: center;
|
||||
font-size: 18px;
|
||||
background-color: #666;
|
||||
|
||||
.content {
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
padding: 4px 28px 12px;
|
||||
}
|
||||
|
||||
.article-list {
|
||||
li{
|
||||
margin: 10px 0;
|
||||
color: #2D8CF0;
|
||||
&:hover{
|
||||
cursor: pointer;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
list-style: none;
|
||||
|
||||
li {
|
||||
margin: 0 -28px;
|
||||
padding: 16px 28px;
|
||||
border-bottom: 1px solid #f0f0f0;
|
||||
color: #171A26;
|
||||
font-size: 15px;
|
||||
line-height: 22px;
|
||||
cursor: pointer;
|
||||
|
||||
&:last-child {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
background: #fafafa;
|
||||
color: $theme_color;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.article-empty {
|
||||
color: #999 !important;
|
||||
cursor: default !important;
|
||||
|
||||
&:hover {
|
||||
color: #999 !important;
|
||||
}
|
||||
}
|
||||
|
||||
.back-btn {
|
||||
margin-top: 16px;
|
||||
padding: 0;
|
||||
border: none;
|
||||
background: none;
|
||||
color: #438cde;
|
||||
font-family: inherit;
|
||||
font-size: 14px;
|
||||
line-height: 22px;
|
||||
cursor: pointer;
|
||||
|
||||
&:hover {
|
||||
color: $theme_color;
|
||||
}
|
||||
}
|
||||
|
||||
.article-detail h2 {
|
||||
margin: 16px 0 20px;
|
||||
color: #171A26;
|
||||
font-size: 22px;
|
||||
font-weight: 600;
|
||||
line-height: 32px;
|
||||
}
|
||||
|
||||
.article-html {
|
||||
color: #333;
|
||||
font-size: 15px;
|
||||
line-height: 1.8;
|
||||
word-break: break-word;
|
||||
|
||||
:deep(img) {
|
||||
max-width: 100%;
|
||||
height: auto;
|
||||
}
|
||||
|
||||
:deep(p) {
|
||||
margin: 0 0 12px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -57,7 +57,7 @@ export const afterSaleStatusList = [
|
||||
status: 'REFUSE'
|
||||
},
|
||||
{
|
||||
name: '买家退货,待卖家收货',
|
||||
name: '待卖家收货',
|
||||
status: 'BUYER_RETURN'
|
||||
},
|
||||
{
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<div class="wrapper">
|
||||
<UserCenterLayout title="账户安全" :tabs="['账户安全']">
|
||||
<UserCenterLayout>
|
||||
<div class="safeList">
|
||||
<!-- 密码 -->
|
||||
<div class="safeItem">
|
||||
@@ -365,7 +365,7 @@ export default {
|
||||
|
||||
.wechatQrEmpty {
|
||||
color: $light_sub_color;
|
||||
font-size: 12px;
|
||||
font-size: 14px;
|
||||
text-align: center;
|
||||
padding: 0 8px;
|
||||
}
|
||||
@@ -379,7 +379,7 @@ export default {
|
||||
.wechatQrTip {
|
||||
margin-top: 10px;
|
||||
color: $light_sub_color;
|
||||
font-size: 12px;
|
||||
font-size: 14px;
|
||||
line-height: 1.6;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -1,50 +1,38 @@
|
||||
<template>
|
||||
<div class="wrapper">
|
||||
<UserCenterLayout title="评论/晒单" :tabs="['评论/晒单']">
|
||||
<UserCenterLayout>
|
||||
|
||||
<div class="order">
|
||||
<div class="order-title">
|
||||
<div class="order-row title">
|
||||
<div class="order-detail-title col-10">订单详情</div>
|
||||
<div class="col-4">收货人</div>
|
||||
<div class="col-4">评价等级</div>
|
||||
<div class="col-4">评价内容</div>
|
||||
<div class="col-2"></div>
|
||||
</div>
|
||||
<empty v-if="list.length === 0" />
|
||||
<div class="comment-list" v-else>
|
||||
<div class="comment-cols">
|
||||
<span>订单详情</span>
|
||||
<span>评价等级</span>
|
||||
<span>评价内容</span>
|
||||
<span>操作</span>
|
||||
</div>
|
||||
<empty v-if="list.length === 0" />
|
||||
|
||||
<div class="order-item" v-else v-for="(item, index) in list" :key="index">
|
||||
<div>
|
||||
<div class="title order-item-title">
|
||||
<span>订单号:{{item.orderNo}}</span>
|
||||
<span class="color999 ml_10">{{item.createTime}}</span>
|
||||
<span class="hover-pointer fontsize_12 eval-detail" @click="evaluateDetail(item.id)">评价详情</span>
|
||||
<div class="comment-card" v-for="(item, index) in list" :key="item.id || index">
|
||||
<div class="comment-head">
|
||||
<div class="order-sn">
|
||||
{{ item.createTime }}<span>订单号 {{ item.orderNo }}</span>
|
||||
</div>
|
||||
<div class="order-item-view">
|
||||
<div class="item-view-name col-10">
|
||||
<div class="order-img hover-color" @click="linkTo(`/goodsDetail?goodsId=${item.goodsId}&skuId=${item.skuId}`)">
|
||||
<img :src="item.goodsImage" alt="" />
|
||||
</div>
|
||||
<div class="order-name hover-color" @click="linkTo(`/goodsDetail?goodsId=${item.goodsId}&skuId=${item.skuId}`)">
|
||||
{{item.goodsName}}
|
||||
</div>
|
||||
</div>
|
||||
<div class="comment-body">
|
||||
<div class="goods">
|
||||
<div class="goods-thumb" @click="linkTo(`/goodsDetail?goodsId=${item.goodsId}&skuId=${item.skuId}`)">
|
||||
<img
|
||||
:src="item.goodsImage"
|
||||
alt=""
|
||||
@error="$event.target.style.visibility = 'hidden'"
|
||||
/>
|
||||
</div>
|
||||
<div class="col-4">{{ $filters.secrecyMobile(item.createBy ) }}</div>
|
||||
<div class="col-4">
|
||||
{{item.grade==='GOOD'?'好评' : item.grade === 'WORSE'?'差评' : '中评'}}
|
||||
<div class="goods-name" @click="linkTo(`/goodsDetail?goodsId=${item.goodsId}&skuId=${item.skuId}`)">
|
||||
{{ item.goodsName }}
|
||||
</div>
|
||||
<div class="col-4">
|
||||
<el-tooltip>
|
||||
<div class="content">{{item.content}}</div>
|
||||
<template #content>
|
||||
<div style="white-space: normal;word-break:break-all">
|
||||
{{item.content}}
|
||||
</div>
|
||||
</template>
|
||||
</el-tooltip>
|
||||
</div>
|
||||
<div class="col-2"></div>
|
||||
</div>
|
||||
<div class="comment-cell">{{ item.grade === 'GOOD' ? '好评' : item.grade === 'WORSE' ? '差评' : '中评' }}</div>
|
||||
<div class="comment-content">{{ item.content }}</div>
|
||||
<div class="comment-ops">
|
||||
<button type="button" class="text-link" @click="evaluateDetail(item.id)">评价详情</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -53,7 +41,7 @@
|
||||
<!-- 分页 -->
|
||||
<div class="page-size">
|
||||
<el-pagination v-model:current-page="params.pageNumber" v-model:page-size="params.pageSize"
|
||||
:total="total" @current-change="changePageNum"
|
||||
:total="total" :page-sizes="[20, 50, 100]" @current-change="changePageNum"
|
||||
@size-change="changePageSize" layout="total, sizes, prev, pager, next, jumper"></el-pagination>
|
||||
</div>
|
||||
</UserCenterLayout>
|
||||
@@ -72,7 +60,7 @@ export default {
|
||||
total: 0, // 评价总数
|
||||
params: { // 请求参数
|
||||
pageNumber: 1,
|
||||
pageSize: 10
|
||||
pageSize: 20
|
||||
}
|
||||
};
|
||||
},
|
||||
@@ -112,108 +100,143 @@ export default {
|
||||
.page-size {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
}
|
||||
.order-img {
|
||||
> img {
|
||||
width: 60px;
|
||||
height: 60px;
|
||||
border: 1px solid $border_color;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
}
|
||||
.title {
|
||||
@include background_color($light_background_color);
|
||||
}
|
||||
.item-view-name {
|
||||
display: flex;
|
||||
}
|
||||
.order-name {
|
||||
display: -webkit-box;
|
||||
margin-top: 16px;
|
||||
|
||||
-webkit-box-orient: vertical;
|
||||
|
||||
-webkit-line-clamp: 2;
|
||||
|
||||
overflow: hidden;
|
||||
text-align: left;
|
||||
padding: 0 10px;
|
||||
font-size: 13px;
|
||||
@include content_color($light_content_color);
|
||||
}
|
||||
.order-item-title {
|
||||
padding: 5px 20px;
|
||||
text-align: left;
|
||||
font-size: 13px;
|
||||
position: relative;
|
||||
}
|
||||
.order-row,
|
||||
.order-item-view {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
> [class*='col-'] {
|
||||
box-sizing: border-box;
|
||||
padding: 0 8px;
|
||||
}
|
||||
|
||||
> .col-12 {
|
||||
flex: 0 0 50%;
|
||||
max-width: 50%;
|
||||
}
|
||||
|
||||
> .col-10 {
|
||||
flex: 0 0 41.666667%;
|
||||
max-width: 41.666667%;
|
||||
}
|
||||
|
||||
> .col-4 {
|
||||
flex: 0 0 16.666667%;
|
||||
max-width: 16.666667%;
|
||||
}
|
||||
|
||||
> .col-2 {
|
||||
flex: 0 0 8.333333%;
|
||||
max-width: 8.333333%;
|
||||
}
|
||||
|
||||
> .col-6 {
|
||||
flex: 0 0 25%;
|
||||
max-width: 25%;
|
||||
:deep(.el-pagination) {
|
||||
justify-content: flex-end;
|
||||
}
|
||||
}
|
||||
|
||||
.order-item-view {
|
||||
padding: 10px 20px;
|
||||
align-items: flex-start;
|
||||
.comment-list {
|
||||
--comment-cols: minmax(220px, 1.3fr) 90px minmax(160px, 1.6fr) 96px;
|
||||
--comment-gap: 12px;
|
||||
padding-top: 8px;
|
||||
}
|
||||
.order-item {
|
||||
text-align: center;
|
||||
border: 1px solid $border_color;
|
||||
margin: 10px 0;
|
||||
|
||||
.comment-cols,
|
||||
.comment-body {
|
||||
display: grid;
|
||||
grid-template-columns: var(--comment-cols);
|
||||
column-gap: var(--comment-gap);
|
||||
align-items: start;
|
||||
}
|
||||
.order-row {
|
||||
padding: 10px 0;
|
||||
text-align: center;
|
||||
}
|
||||
.order-detail-title {
|
||||
text-align: left;
|
||||
padding-left: 20px !important;
|
||||
}
|
||||
.content {
|
||||
|
||||
.comment-cols {
|
||||
padding: 0 16px 10px;
|
||||
color: #999;
|
||||
max-height: 60px;
|
||||
overflow: hidden;
|
||||
// word-wrap: break-word;
|
||||
display:-webkit-box;
|
||||
-webkit-box-orient:vertical;/*设置方向*/
|
||||
-webkit-line-clamp:3;/*设置超过为省略号的行数*/
|
||||
word-break:break-all;
|
||||
font-size: 13px;
|
||||
|
||||
span:first-child {
|
||||
padding-left: 72px;
|
||||
}
|
||||
|
||||
span:nth-child(n + 2) {
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
|
||||
.eval-detail {
|
||||
position: absolute;
|
||||
right: 20px;
|
||||
&:hover{
|
||||
.comment-card {
|
||||
margin-bottom: 12px;
|
||||
border: 1px solid #eee;
|
||||
border-radius: 8px;
|
||||
background: #fff;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.comment-head {
|
||||
padding: 10px 16px;
|
||||
background: #f7f7f7;
|
||||
border-bottom: 1px solid #f0f0f0;
|
||||
}
|
||||
|
||||
.order-sn {
|
||||
color: #171A26;
|
||||
font-size: 14px;
|
||||
line-height: 22px;
|
||||
|
||||
span {
|
||||
margin-left: 16px;
|
||||
}
|
||||
}
|
||||
|
||||
.comment-body {
|
||||
padding: 14px 16px;
|
||||
}
|
||||
|
||||
.goods {
|
||||
display: grid;
|
||||
grid-template-columns: 60px minmax(0, 1fr);
|
||||
column-gap: 12px;
|
||||
align-items: start;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.goods-thumb {
|
||||
width: 60px;
|
||||
height: 60px;
|
||||
border: 1px solid #f0f0f0;
|
||||
overflow: hidden;
|
||||
background: #f5f5f5;
|
||||
cursor: pointer;
|
||||
|
||||
img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: cover;
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
|
||||
.goods-name {
|
||||
color: #333;
|
||||
font-size: 16px;
|
||||
line-height: 22px;
|
||||
max-height: 44px;
|
||||
display: -webkit-box;
|
||||
-webkit-box-orient: vertical;
|
||||
-webkit-line-clamp: 2;
|
||||
overflow: hidden;
|
||||
word-break: break-all;
|
||||
cursor: pointer;
|
||||
|
||||
&:hover {
|
||||
color: $theme_color;
|
||||
}
|
||||
}
|
||||
|
||||
.comment-cell,
|
||||
.comment-ops {
|
||||
text-align: center;
|
||||
color: #171A26;
|
||||
font-size: 14px;
|
||||
line-height: 22px;
|
||||
}
|
||||
|
||||
.comment-content {
|
||||
min-width: 0;
|
||||
color: #666;
|
||||
font-size: 14px;
|
||||
line-height: 22px;
|
||||
white-space: pre-wrap;
|
||||
word-break: break-all;
|
||||
}
|
||||
|
||||
.comment-ops {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.text-link {
|
||||
border: none;
|
||||
background: none;
|
||||
padding: 0;
|
||||
color: #171A26;
|
||||
font-family: inherit;
|
||||
font-size: 14px;
|
||||
line-height: 22px;
|
||||
cursor: pointer;
|
||||
|
||||
&:hover {
|
||||
color: $theme_color;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<div class="add-eval">
|
||||
<UserCenterLayout title="订单投诉" :tabs="['订单投诉']">
|
||||
<UserCenterLayout>
|
||||
<div class="title">
|
||||
<p>
|
||||
<span class="fontsize_16 global_color">{{ statusLabel[detail.complainStatus] }}</span>
|
||||
@@ -123,7 +123,7 @@
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<el-dialog title="View Image" v-model="visible">
|
||||
<el-dialog title="图片预览" v-model="visible">
|
||||
<img :src="previewImage" v-if="visible" style="width: 100%">
|
||||
</el-dialog>
|
||||
</UserCenterLayout>
|
||||
|
||||
@@ -1,51 +1,46 @@
|
||||
<template>
|
||||
<div class="wrapper">
|
||||
<UserCenterLayout title="我的投诉" :tabs="['我的投诉']">
|
||||
<UserCenterLayout>
|
||||
|
||||
<div class="order">
|
||||
<div class="order-title">
|
||||
<div class="order-row title">
|
||||
<div class="order-detail-title col-10">商品信息</div>
|
||||
<div class="col-4">投诉状态</div>
|
||||
<div class="col-4">投诉主题</div>
|
||||
<div class="col-4">投诉内容</div>
|
||||
<div class="col-2"></div>
|
||||
</div>
|
||||
<empty v-if="list.length === 0" />
|
||||
<div class="complain-list" v-else>
|
||||
<div class="complain-cols">
|
||||
<span>商品信息</span>
|
||||
<span>投诉状态</span>
|
||||
<span>投诉主题</span>
|
||||
<span>投诉内容</span>
|
||||
<span>操作</span>
|
||||
</div>
|
||||
<empty v-if="list.length === 0" />
|
||||
|
||||
<div class="order-item" v-else v-for="(item, index) in list" :key="index">
|
||||
<div>
|
||||
<div class="title order-item-title">
|
||||
<span>投诉单号:{{item.id}}</span>
|
||||
<span class="color999 ml_10">{{item.createTime}}</span>
|
||||
<span class="hover-pointer fontsize_12 eval-detail" @click="goDetail(item.id)">投诉详情</span>
|
||||
<span class="hover-pointer fontsize_12 eval-detail" style="right: 90px" v-if="item.complainStatus === 'APPLYING' || item.complainStatus === 'NEW'" @click="cancel(item.id)">取消投诉</span>
|
||||
<div class="complain-card" v-for="(item, index) in list" :key="item.id || index">
|
||||
<div class="complain-head">
|
||||
<div class="order-sn">
|
||||
{{ item.createTime }}<span>投诉单号 {{ item.id }}</span>
|
||||
</div>
|
||||
<div class="order-item-view">
|
||||
<div class="item-view-name col-10">
|
||||
<div class="order-img hover-color" @click="linkTo(`/goodsDetail?goodsId=${item.goodsId}&skuId=${item.skuId}`)">
|
||||
<img :src="item.goodsImage" alt="" />
|
||||
</div>
|
||||
<div class="order-name hover-color" @click="linkTo(`/goodsDetail?goodsId=${item.goodsId}&skuId=${item.skuId}`)">
|
||||
{{item.goodsName}}
|
||||
</div>
|
||||
</div>
|
||||
<div class="complain-body">
|
||||
<div class="goods">
|
||||
<div class="goods-thumb" @click="linkTo(`/goodsDetail?goodsId=${item.goodsId}&skuId=${item.skuId}`)">
|
||||
<img
|
||||
:src="item.goodsImage"
|
||||
alt=""
|
||||
@error="$event.target.style.visibility = 'hidden'"
|
||||
/>
|
||||
</div>
|
||||
<div class="col-4">{{statusLabel[item.complainStatus]}}</div>
|
||||
<div class="col-4">
|
||||
<div class="content">{{item.complainTopic}}</div>
|
||||
<div class="goods-name" @click="linkTo(`/goodsDetail?goodsId=${item.goodsId}&skuId=${item.skuId}`)">
|
||||
{{ item.goodsName }}
|
||||
</div>
|
||||
<div class="col-4">
|
||||
<el-tooltip>
|
||||
<div class="content">{{item.content}}</div>
|
||||
<template #content>
|
||||
<div style="white-space: normal;">
|
||||
{{item.content}}
|
||||
</div>
|
||||
</template>
|
||||
</el-tooltip>
|
||||
</div>
|
||||
<div class="col-2"></div>
|
||||
</div>
|
||||
<div class="complain-cell">{{ statusLabel[item.complainStatus] || item.complainStatus }}</div>
|
||||
<div class="complain-topic">{{ item.complainTopic }}</div>
|
||||
<div class="complain-content">{{ item.content }}</div>
|
||||
<div class="complain-ops">
|
||||
<button type="button" class="text-link" @click="goDetail(item.id)">投诉详情</button>
|
||||
<button
|
||||
v-if="item.complainStatus === 'APPLYING' || item.complainStatus === 'NEW'"
|
||||
type="button"
|
||||
class="text-link"
|
||||
@click="cancel(item.id)"
|
||||
>取消投诉</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -54,7 +49,7 @@
|
||||
<!-- 分页 -->
|
||||
<div class="page-size">
|
||||
<el-pagination v-model:current-page="params.pageNumber" v-model:page-size="params.pageSize"
|
||||
:total="total" @current-change="changePageNum"
|
||||
:total="total" :page-sizes="[20, 50, 100]" @current-change="changePageNum"
|
||||
@size-change="changePageSize" layout="total, sizes, prev, pager, next, jumper"></el-pagination>
|
||||
</div>
|
||||
</UserCenterLayout>
|
||||
@@ -81,7 +76,7 @@ export default {
|
||||
total: 0, // 投诉总数
|
||||
params: { // 请求参数
|
||||
pageNumber: 1,
|
||||
pageSize: 10
|
||||
pageSize: 20
|
||||
}
|
||||
};
|
||||
},
|
||||
@@ -130,101 +125,158 @@ export default {
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.order-img {
|
||||
> img {
|
||||
width: 60px;
|
||||
height: 60px;
|
||||
border: 1px solid $border_color;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
}
|
||||
.title {
|
||||
@include background_color($light_background_color);
|
||||
}
|
||||
.item-view-name {
|
||||
.page-size {
|
||||
display: flex;
|
||||
}
|
||||
.order-name {
|
||||
display: -webkit-box;
|
||||
justify-content: flex-end;
|
||||
margin-top: 16px;
|
||||
|
||||
-webkit-box-orient: vertical;
|
||||
|
||||
-webkit-line-clamp: 2;
|
||||
|
||||
overflow: hidden;
|
||||
text-align: left;
|
||||
padding: 0 10px;
|
||||
font-size: 13px;
|
||||
@include content_color($light_content_color);
|
||||
}
|
||||
.order-item-title {
|
||||
padding: 5px 20px;
|
||||
text-align: left;
|
||||
font-size: 13px;
|
||||
position: relative;
|
||||
}
|
||||
.order-row,
|
||||
.order-item-view {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
> [class*='col-'] {
|
||||
box-sizing: border-box;
|
||||
padding: 0 8px;
|
||||
}
|
||||
|
||||
> .col-10 {
|
||||
flex: 0 0 41.666667%;
|
||||
max-width: 41.666667%;
|
||||
}
|
||||
|
||||
> .col-4 {
|
||||
flex: 0 0 16.666667%;
|
||||
max-width: 16.666667%;
|
||||
}
|
||||
|
||||
> .col-2 {
|
||||
flex: 0 0 8.333333%;
|
||||
max-width: 8.333333%;
|
||||
:deep(.el-pagination) {
|
||||
justify-content: flex-end;
|
||||
}
|
||||
}
|
||||
|
||||
.order-item-view {
|
||||
padding: 10px 20px;
|
||||
align-items: flex-start;
|
||||
.complain-list {
|
||||
--complain-cols: minmax(220px, 1.3fr) 90px minmax(100px, 0.8fr) minmax(160px, 1.4fr) 96px;
|
||||
--complain-gap: 12px;
|
||||
padding-top: 8px;
|
||||
}
|
||||
.order-item {
|
||||
text-align: center;
|
||||
border: 1px solid $border_color;
|
||||
margin: 10px 0;
|
||||
|
||||
.complain-cols,
|
||||
.complain-body {
|
||||
display: grid;
|
||||
grid-template-columns: var(--complain-cols);
|
||||
column-gap: var(--complain-gap);
|
||||
align-items: start;
|
||||
}
|
||||
.order-row {
|
||||
padding: 10px 0;
|
||||
text-align: center;
|
||||
}
|
||||
.order-detail-title {
|
||||
text-align: left;
|
||||
padding-left: 20px !important;
|
||||
}
|
||||
.content {
|
||||
|
||||
.complain-cols {
|
||||
padding: 0 16px 10px;
|
||||
color: #999;
|
||||
max-height: 60px;
|
||||
font-size: 13px;
|
||||
|
||||
span:first-child {
|
||||
padding-left: 72px;
|
||||
}
|
||||
|
||||
span:nth-child(n + 2) {
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
|
||||
.complain-card {
|
||||
margin-bottom: 12px;
|
||||
border: 1px solid #eee;
|
||||
border-radius: 8px;
|
||||
background: #fff;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.complain-head {
|
||||
padding: 10px 16px;
|
||||
background: #f7f7f7;
|
||||
border-bottom: 1px solid #f0f0f0;
|
||||
}
|
||||
|
||||
.order-sn {
|
||||
color: #171A26;
|
||||
font-size: 14px;
|
||||
line-height: 22px;
|
||||
|
||||
span {
|
||||
margin-left: 16px;
|
||||
}
|
||||
}
|
||||
|
||||
.complain-body {
|
||||
padding: 14px 16px;
|
||||
}
|
||||
|
||||
.goods {
|
||||
display: grid;
|
||||
grid-template-columns: 60px minmax(0, 1fr);
|
||||
column-gap: 12px;
|
||||
align-items: start;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.goods-thumb {
|
||||
width: 60px;
|
||||
height: 60px;
|
||||
border: 1px solid #f0f0f0;
|
||||
overflow: hidden;
|
||||
background: #f5f5f5;
|
||||
cursor: pointer;
|
||||
|
||||
img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: cover;
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
|
||||
.goods-name {
|
||||
color: #333;
|
||||
font-size: 16px;
|
||||
line-height: 22px;
|
||||
max-height: 44px;
|
||||
display: -webkit-box;
|
||||
-webkit-box-orient: vertical;
|
||||
-webkit-line-clamp: 2;
|
||||
overflow: hidden;
|
||||
word-break: break-all;
|
||||
display: -webkit-box;
|
||||
-webkit-box-orient: vertical;
|
||||
-webkit-line-clamp: 3;
|
||||
}
|
||||
cursor: pointer;
|
||||
|
||||
.eval-detail {
|
||||
position: absolute;
|
||||
right: 20px;
|
||||
&:hover{
|
||||
&:hover {
|
||||
color: $theme_color;
|
||||
}
|
||||
}
|
||||
.page-size{
|
||||
|
||||
.complain-cell,
|
||||
.complain-topic,
|
||||
.complain-ops {
|
||||
color: #171A26;
|
||||
font-size: 14px;
|
||||
line-height: 22px;
|
||||
}
|
||||
|
||||
.complain-cell,
|
||||
.complain-ops {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.complain-topic,
|
||||
.complain-content {
|
||||
min-width: 0;
|
||||
white-space: pre-wrap;
|
||||
word-break: break-all;
|
||||
}
|
||||
|
||||
.complain-content {
|
||||
color: #666;
|
||||
font-size: 14px;
|
||||
line-height: 22px;
|
||||
}
|
||||
|
||||
.complain-ops {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.text-link {
|
||||
border: none;
|
||||
background: none;
|
||||
padding: 0;
|
||||
color: #171A26;
|
||||
font-family: inherit;
|
||||
font-size: 14px;
|
||||
line-height: 22px;
|
||||
cursor: pointer;
|
||||
|
||||
&:hover {
|
||||
color: $theme_color;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -2,78 +2,80 @@
|
||||
<div class="wrapper">
|
||||
<UserCenterLayout
|
||||
v-if="!homePage"
|
||||
title="近期收藏"
|
||||
:tabs="favoriteWay"
|
||||
:active-tab="activeTabIndex"
|
||||
@tab-change="change"
|
||||
>
|
||||
<div v-if="list.length">
|
||||
<div v-for="(item, index) in list" :key="index">
|
||||
<div class="goodsItem" :key="item.skuId">
|
||||
<div class="goodsImg hover-pointer" v-if="params.type === 'GOODS'">
|
||||
<img :src="item.image" />
|
||||
<empty v-if="!list.length" />
|
||||
<div v-else class="fav-list" :class="{ 'is-store': params.type === 'STORE' }">
|
||||
<div class="fav-cols">
|
||||
<span>{{ params.type === 'GOODS' ? '商品' : '店铺' }}</span>
|
||||
<span v-if="params.type === 'GOODS'">金额</span>
|
||||
<span>操作</span>
|
||||
</div>
|
||||
<div class="fav-row" v-for="(item, index) in list" :key="item.id || item.skuId || index">
|
||||
<div class="fav-goods">
|
||||
<div class="fav-thumb" @click="openItem(item)">
|
||||
<img
|
||||
:src="params.type === 'GOODS' ? item.image : item.storeLogo"
|
||||
alt=""
|
||||
@error="$event.target.style.visibility = 'hidden'"
|
||||
/>
|
||||
</div>
|
||||
<div class="goodsImg hover-pointer" v-else>
|
||||
<img :src="item.storeLogo" />
|
||||
</div>
|
||||
<div class="goodsTitle hover-color" v-if="params.type === 'GOODS'" @click="buynow(item.skuId, item.goodsId,item.id)">
|
||||
{{ item.goodsName }}
|
||||
</div>
|
||||
<div v-else class="goodsTitle hover-pointer" @click="buynow(item.skuId, item.goodsId,item.id)" >
|
||||
{{ item.storeName }}
|
||||
<el-tag color="error" class="operated" v-if="item.selfOperated">商家自营</el-tag>
|
||||
</div>
|
||||
<div class="goodsPrice">
|
||||
<span v-if="params.type === 'GOODS'">{{ $filters.unitPrice(item.price, '¥') }}</span>
|
||||
|
||||
</div>
|
||||
<div class="goodsBuy">
|
||||
<el-button size="small" type="primary" @click="buynow(item.skuId, item.goodsId)"
|
||||
v-if="params.type === 'GOODS'">立即购买</el-button>
|
||||
<el-button size="small" type="primary" @click="goShop(item.id)" v-else>店铺购买</el-button>
|
||||
<el-button size="small" v-if="params.type === 'GOODS'" @click="cancel(item.skuId)">取消收藏</el-button>
|
||||
<el-button size="small" v-if="params.type === 'STORE'" @click="cancelStore(item.id)">取消收藏</el-button>
|
||||
<div class="fav-info">
|
||||
<div class="fav-name" @click="openItem(item)">
|
||||
{{ params.type === 'GOODS' ? item.goodsName : item.storeName }}
|
||||
</div>
|
||||
<span v-if="params.type === 'STORE' && item.selfOperated" class="self-tag">商家自营</span>
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="params.type === 'GOODS'" class="fav-price">{{ $filters.unitPrice(item.price, '¥') }}</div>
|
||||
<div class="fav-ops">
|
||||
<button v-if="params.type === 'GOODS'" type="button" class="op-btn" @click="buynow(item.skuId, item.goodsId)">立即购买</button>
|
||||
<button v-else type="button" class="op-btn" @click="goShop(item.id)">查看店铺</button>
|
||||
<button v-if="params.type === 'GOODS'" type="button" class="text-link" @click="cancel(item.skuId)">取消收藏</button>
|
||||
<button v-else type="button" class="text-link" @click="cancelStore(item.id)">取消收藏</button>
|
||||
</div>
|
||||
</div>
|
||||
<el-skeleton size="large" fix v-if="spinShow"></el-skeleton>
|
||||
</div>
|
||||
<empty v-else />
|
||||
</UserCenterLayout>
|
||||
|
||||
<template v-else>
|
||||
<card _Title="近期收藏" :_Size="16" :_Tabs="favoriteWay" :_ActiveTab="activeTabIndex" @_Change="change" _More="全部收藏" _Src="/home/Favorites"></card>
|
||||
<div v-if="list.length">
|
||||
<div v-for="(item, index) in list" :key="index">
|
||||
<div class="goodsItem" :key="item.skuId">
|
||||
<div class="goodsImg hover-pointer" v-if="params.type === 'GOODS'">
|
||||
<img :src="item.image" />
|
||||
<empty v-if="!list.length" />
|
||||
<div v-else class="fav-list" :class="{ 'is-store': params.type === 'STORE' }">
|
||||
<div class="fav-cols">
|
||||
<span>{{ params.type === 'GOODS' ? '商品' : '店铺' }}</span>
|
||||
<span v-if="params.type === 'GOODS'">金额</span>
|
||||
<span>操作</span>
|
||||
</div>
|
||||
<div class="fav-row" v-for="(item, index) in list" :key="item.id || item.skuId || index">
|
||||
<div class="fav-goods">
|
||||
<div class="fav-thumb" @click="openItem(item)">
|
||||
<img
|
||||
:src="params.type === 'GOODS' ? item.image : item.storeLogo"
|
||||
alt=""
|
||||
@error="$event.target.style.visibility = 'hidden'"
|
||||
/>
|
||||
</div>
|
||||
<div class="goodsImg hover-pointer" v-else>
|
||||
<img :src="item.storeLogo" />
|
||||
</div>
|
||||
<div class="goodsTitle hover-color" v-if="params.type === 'GOODS'" @click="buynow(item.skuId, item.goodsId,item.id)">
|
||||
{{ item.goodsName }}
|
||||
</div>
|
||||
<div v-else class="goodsTitle hover-pointer" @click="buynow(item.skuId, item.goodsId,item.id)" >
|
||||
{{ item.storeName }}
|
||||
<el-tag color="error" class="operated" v-if="item.selfOperated">商家自营</el-tag>
|
||||
</div>
|
||||
<div class="goodsPrice">
|
||||
<span v-if="params.type === 'GOODS'">{{ $filters.unitPrice(item.price, '¥') }}</span>
|
||||
</div>
|
||||
<div class="goodsBuy">
|
||||
<el-button size="small" type="primary" @click="buynow(item.skuId, item.goodsId)"
|
||||
v-if="params.type === 'GOODS'">立即购买</el-button>
|
||||
<el-button size="small" type="primary" @click="goShop(item.id)" v-else>店铺购买</el-button>
|
||||
<el-button size="small" v-if="params.type === 'GOODS'" @click="cancel(item.skuId)">取消收藏</el-button>
|
||||
<el-button size="small" v-if="params.type === 'STORE'" @click="cancelStore(item.id)">取消收藏</el-button>
|
||||
<div class="fav-info">
|
||||
<div class="fav-name" @click="openItem(item)">
|
||||
{{ params.type === 'GOODS' ? item.goodsName : item.storeName }}
|
||||
</div>
|
||||
<span v-if="params.type === 'STORE' && item.selfOperated" class="self-tag">商家自营</span>
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="params.type === 'GOODS'" class="fav-price">{{ $filters.unitPrice(item.price, '¥') }}</div>
|
||||
<div class="fav-ops">
|
||||
<button v-if="params.type === 'GOODS'" type="button" class="op-btn" @click="buynow(item.skuId, item.goodsId)">立即购买</button>
|
||||
<button v-else type="button" class="op-btn" @click="goShop(item.id)">查看店铺</button>
|
||||
<button v-if="params.type === 'GOODS'" type="button" class="text-link" @click="cancel(item.skuId)">取消收藏</button>
|
||||
<button v-else type="button" class="text-link" @click="cancelStore(item.id)">取消收藏</button>
|
||||
</div>
|
||||
</div>
|
||||
<el-skeleton size="large" fix v-if="spinShow"></el-skeleton>
|
||||
</div>
|
||||
<empty v-else />
|
||||
</template>
|
||||
</div>
|
||||
</template>
|
||||
@@ -172,6 +174,13 @@ export default {
|
||||
}
|
||||
});
|
||||
},
|
||||
openItem (item) {
|
||||
if (this.params.type === 'STORE') {
|
||||
this.goShop(item.id)
|
||||
return
|
||||
}
|
||||
this.buynow(item.skuId, item.goodsId)
|
||||
},
|
||||
buynow(skuId, goodsId,storeId) { // 跳转详情
|
||||
console.log(this.params.type)
|
||||
let url
|
||||
@@ -206,73 +215,148 @@ export default {
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.goodsShop,
|
||||
.goodsImg,
|
||||
.goodsPrice,
|
||||
.goodsShop,
|
||||
.goodsTitle {
|
||||
margin: 0 6px;
|
||||
}
|
||||
|
||||
.operated {
|
||||
margin-left: 10px;
|
||||
}
|
||||
|
||||
.wrapper {
|
||||
margin-bottom: 40px;
|
||||
}
|
||||
|
||||
.goodsItem {
|
||||
display: flex;
|
||||
.fav-list {
|
||||
--fav-cols: minmax(0, 1fr) 140px 200px;
|
||||
--fav-gap: 12px;
|
||||
padding-top: 8px;
|
||||
|
||||
&.is-store {
|
||||
--fav-cols: minmax(0, 1fr) 200px;
|
||||
}
|
||||
}
|
||||
|
||||
.fav-cols,
|
||||
.fav-row {
|
||||
display: grid;
|
||||
grid-template-columns: var(--fav-cols);
|
||||
column-gap: var(--fav-gap);
|
||||
align-items: center;
|
||||
height: 60px;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
>.goodsImg {
|
||||
width: 60px;
|
||||
height: 60px;
|
||||
overflow: hidden;
|
||||
flex-shrink: 0;
|
||||
.fav-cols {
|
||||
padding: 0 8px 10px;
|
||||
color: #999;
|
||||
font-size: 13px;
|
||||
|
||||
>img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
span:first-child {
|
||||
padding-left: 72px;
|
||||
}
|
||||
|
||||
>.goodsPrice,
|
||||
.goodsShop {
|
||||
width: 120px;
|
||||
flex-shrink: 0;
|
||||
span:nth-child(n + 2) {
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
|
||||
>.goodsTitle {
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
line-height: 60px;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
.fav-row {
|
||||
padding: 14px 8px;
|
||||
border-top: 1px solid #f0f0f0;
|
||||
}
|
||||
|
||||
.fav-goods {
|
||||
display: grid;
|
||||
grid-template-columns: 60px minmax(0, 1fr);
|
||||
column-gap: 12px;
|
||||
align-items: center;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.fav-thumb {
|
||||
width: 60px;
|
||||
height: 60px;
|
||||
border: 1px solid #f0f0f0;
|
||||
overflow: hidden;
|
||||
background: #f5f5f5;
|
||||
cursor: pointer;
|
||||
|
||||
img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: cover;
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
|
||||
.goodsBuy {
|
||||
.fav-info {
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.fav-name {
|
||||
color: #333;
|
||||
font-size: 16px;
|
||||
line-height: 22px;
|
||||
max-height: 44px;
|
||||
display: -webkit-box;
|
||||
-webkit-box-orient: vertical;
|
||||
-webkit-line-clamp: 2;
|
||||
overflow: hidden;
|
||||
word-break: break-all;
|
||||
cursor: pointer;
|
||||
|
||||
&:hover {
|
||||
color: $theme_color;
|
||||
}
|
||||
}
|
||||
|
||||
.self-tag {
|
||||
display: inline-block;
|
||||
margin-top: 6px;
|
||||
padding: 0 6px;
|
||||
border-radius: 4px;
|
||||
background: #fff1f0;
|
||||
color: $theme_color;
|
||||
font-size: 12px;
|
||||
line-height: 20px;
|
||||
}
|
||||
|
||||
.fav-price {
|
||||
text-align: center;
|
||||
color: #333;
|
||||
font-size: 16px;
|
||||
font-weight: 600;
|
||||
line-height: 1.4;
|
||||
}
|
||||
|
||||
.fav-ops {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: flex-end;
|
||||
flex-shrink: 0;
|
||||
gap: 8px;
|
||||
width: 170px;
|
||||
margin-left: 16px;
|
||||
line-height: normal;
|
||||
justify-content: center;
|
||||
gap: 16px;
|
||||
}
|
||||
|
||||
:deep(.el-button) {
|
||||
margin: 0;
|
||||
.op-btn {
|
||||
min-width: 96px;
|
||||
height: 32px;
|
||||
padding: 0 12px;
|
||||
border: 1px solid $theme_color;
|
||||
border-radius: 4px;
|
||||
background: $theme_color;
|
||||
color: #fff;
|
||||
font-family: inherit;
|
||||
font-size: 14px;
|
||||
line-height: 30px;
|
||||
cursor: pointer;
|
||||
|
||||
&:hover {
|
||||
opacity: 0.9;
|
||||
}
|
||||
}
|
||||
|
||||
.page-size {
|
||||
text-align: right;
|
||||
.text-link {
|
||||
border: none;
|
||||
background: none;
|
||||
padding: 0;
|
||||
color: #171A26;
|
||||
font-family: inherit;
|
||||
font-size: 14px;
|
||||
line-height: 22px;
|
||||
cursor: pointer;
|
||||
|
||||
&:hover {
|
||||
color: $theme_color;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -1,83 +1,73 @@
|
||||
<template>
|
||||
<div class="memberGrade">
|
||||
<UserCenterLayout title="我的等级" :tabs="['我的等级']">
|
||||
<div class="summary">
|
||||
<div class="gradeCard">
|
||||
<div class="gradeLeft">
|
||||
<img v-if="currentGrade.gradeImage" class="gradeIcon" :src="currentGrade.gradeImage" alt="等级图标" />
|
||||
<div class="gradeInfo">
|
||||
<div class="gradeNameRow">
|
||||
<span class="gradeNameText">{{ currentGrade.gradeName || '暂无等级' }}</span>
|
||||
<span v-if="currentGradeBenefits.length" class="benefitTagsInline">
|
||||
<el-tag v-for="b in currentGradeBenefits" :key="b.id" class="benefitTag" type="primary">{{ b.benefitName || '-' }}</el-tag>
|
||||
</span>
|
||||
</div>
|
||||
<div class="gradeExp">
|
||||
当前经验值:<span class="num">{{ currentExperience || 0 }}</span>
|
||||
</div>
|
||||
<div class="gradeNext" v-if="nextGrade">
|
||||
距 {{ nextGrade.gradeName }} 还差 <span class="num">{{ diffExperience }}</span> 经验值
|
||||
</div>
|
||||
<div class="gradeNext" v-else>已达最高等级</div>
|
||||
</div>
|
||||
<UserCenterLayout>
|
||||
<div class="grade-card">
|
||||
<img v-if="currentGrade.gradeImage" class="grade-icon" :src="currentGrade.gradeImage" alt="" />
|
||||
<div class="grade-info">
|
||||
<div class="grade-name-row">
|
||||
<span class="grade-name">{{ currentGrade.gradeName || '暂无等级' }}</span>
|
||||
<span v-for="b in currentGradeBenefits" :key="b.id" class="benefit-tag">{{ b.benefitName || '-' }}</span>
|
||||
</div>
|
||||
<div class="grade-exp">当前经验值:<span class="num">{{ currentExperience || 0 }}</span></div>
|
||||
<div class="grade-next" v-if="nextGrade">
|
||||
距 {{ nextGrade.gradeName }} 还差 <span class="num">{{ diffExperience }}</span> 经验值
|
||||
</div>
|
||||
<div class="grade-next" v-else>已达最高等级</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<el-tabs v-model="activeGradeTab">
|
||||
<el-tab-pane label="获取经验值方式" name="rules">
|
||||
<el-table v-loading="rulesLoading" :data="ruleList">
|
||||
<el-table-column label="获取方式" min-width="720">
|
||||
<template #default="{ row }">
|
||||
<div class="ruleItem">
|
||||
<div class="ruleTop">
|
||||
<div class="ruleName">
|
||||
<span>{{ row.ruleName || row.ruleKey || '-' }}</span>
|
||||
</div>
|
||||
<el-tag v-if="row.completed === true" color="success">已完成</el-tag>
|
||||
<el-tag v-else color="default">未完成</el-tag>
|
||||
</div>
|
||||
<div class="ruleDesc">{{ getRuleDesc(row.ruleKey) }}</div>
|
||||
<div class="ruleMeta">
|
||||
<span class="metaItem">单次获得:<b>+{{ row.value == null ? 0 : row.value }}</b></span>
|
||||
<span v-if="row.maxValue != null && Number(row.maxValue) > 0" class="metaItem">限额:<b>{{ row.maxValue }}</b></span>
|
||||
<span class="metaItem">已获得:<b>{{ row.gainedExperience == null ? 0 : row.gainedExperience }}</b></span>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<div class="rulesDesc" v-if="rulesDescription">{{ rulesDescription }}</div>
|
||||
</el-tab-pane>
|
||||
<el-tab-pane label="经验值记录" name="logs">
|
||||
<el-table v-loading="logLoading" :data="experienceLogs.records || []">
|
||||
<el-table-column prop="createTime" label="时间" align="center" min-width="160" />
|
||||
<el-table-column label="规则" align="center" min-width="160">
|
||||
<template #default="{ row }">
|
||||
<span>{{ getRuleName(row.ruleKey) }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="变动值" align="center" min-width="120">
|
||||
<template #default="{ row }">
|
||||
<div :style="{ color: getLogDeltaColor(row) }">
|
||||
<span v-if="getLogDeltaSign(row) === '+'">+</span>{{ getLogDeltaAbsValue(row) }}
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<div class="grade-pagination">
|
||||
<el-pagination
|
||||
v-model:current-page="params.pageNumber"
|
||||
v-model:page-size="params.pageSize"
|
||||
:total="experienceLogs.total || 0"
|
||||
@current-change="changePage"
|
||||
@size-change="changePageSize"
|
||||
:page-sizes="[10, 20, 50]"
|
||||
layout="total, prev, pager, next, jumper"
|
||||
/>
|
||||
<div class="grade-tabs">
|
||||
<div class="grade-tab" :class="{ active: activeGradeTab === 'rules' }" @click="activeGradeTab = 'rules'">获取经验值方式</div>
|
||||
<div class="grade-tab" :class="{ active: activeGradeTab === 'logs' }" @click="activeGradeTab = 'logs'">经验值记录</div>
|
||||
</div>
|
||||
|
||||
<div v-show="activeGradeTab === 'rules'" v-loading="rulesLoading">
|
||||
<empty v-if="!rulesLoading && !ruleList.length" />
|
||||
<div v-else class="rule-list">
|
||||
<div class="rule-item" v-for="row in ruleList" :key="row.ruleKey || row.id">
|
||||
<div class="rule-top">
|
||||
<div class="rule-name">{{ row.ruleName || row.ruleKey || '-' }}</div>
|
||||
<span class="rule-status" :class="{ done: row.completed === true }">{{ row.completed === true ? '已完成' : '未完成' }}</span>
|
||||
</div>
|
||||
<div class="rule-desc">{{ getRuleDesc(row.ruleKey) }}</div>
|
||||
<div class="rule-meta">
|
||||
<span>单次获得 <b>+{{ row.value == null ? 0 : row.value }}</b></span>
|
||||
<span v-if="row.maxValue != null && Number(row.maxValue) > 0">限额 <b>{{ row.maxValue }}</b></span>
|
||||
<span>已获得 <b>{{ row.gainedExperience == null ? 0 : row.gainedExperience }}</b></span>
|
||||
</div>
|
||||
</div>
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
</div>
|
||||
<div class="rules-desc" v-if="rulesDescription">{{ rulesDescription }}</div>
|
||||
</div>
|
||||
|
||||
<div v-show="activeGradeTab === 'logs'" v-loading="logLoading">
|
||||
<empty v-if="!(experienceLogs.records || []).length" />
|
||||
<div v-else class="log-list">
|
||||
<div class="log-head">
|
||||
<span>时间</span>
|
||||
<span>规则</span>
|
||||
<span>变动值</span>
|
||||
</div>
|
||||
<div class="log-row" v-for="(row, index) in experienceLogs.records" :key="row.id || index">
|
||||
<div class="log-time">{{ row.createTime }}</div>
|
||||
<div class="log-rule">{{ getRuleName(row.ruleKey) }}</div>
|
||||
<div class="log-point" :class="getLogDeltaSign(row) === '+' ? 'is-plus' : 'is-minus'">
|
||||
{{ getLogDeltaSign(row) }}{{ getLogDeltaAbsValue(row) }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="grade-pagination">
|
||||
<el-pagination
|
||||
v-model:current-page="params.pageNumber"
|
||||
v-model:page-size="params.pageSize"
|
||||
:total="experienceLogs.total || 0"
|
||||
@current-change="changePage"
|
||||
@size-change="changePageSize"
|
||||
:page-sizes="[20, 50, 100]"
|
||||
layout="total, sizes, prev, pager, next, jumper"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</UserCenterLayout>
|
||||
|
||||
</div>
|
||||
@@ -106,7 +96,7 @@ export default {
|
||||
gradeLoading: false,
|
||||
params: {
|
||||
pageNumber: 1,
|
||||
pageSize: 10
|
||||
pageSize: 20
|
||||
},
|
||||
experienceLogs: {}
|
||||
}
|
||||
@@ -288,131 +278,220 @@ export default {
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
h3 {
|
||||
font-size: 16px;
|
||||
margin: 20px 10px;
|
||||
}
|
||||
|
||||
.summary {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.rulesDesc {
|
||||
margin: 10px 0 0 0;
|
||||
padding: 10px 12px;
|
||||
border: 1px solid $border_color;
|
||||
border-radius: 4px;
|
||||
background: #fff;
|
||||
color: $light_sub_color;
|
||||
font-size: 12px;
|
||||
line-height: 1.7;
|
||||
}
|
||||
|
||||
.gradeCard {
|
||||
padding: 16px;
|
||||
border: 1px solid $border_color;
|
||||
border-radius: 6px;
|
||||
background: #fff;
|
||||
background-repeat: no-repeat;
|
||||
background-size: cover;
|
||||
}
|
||||
|
||||
.gradeLeft {
|
||||
.grade-card {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
gap: 12px;
|
||||
align-items: center;
|
||||
gap: 16px;
|
||||
margin-bottom: 8px;
|
||||
padding: 16px;
|
||||
background: #fafafa;
|
||||
border-radius: 8px;
|
||||
}
|
||||
|
||||
.gradeIcon {
|
||||
width: 48px;
|
||||
height: 48px;
|
||||
.grade-icon {
|
||||
width: 56px;
|
||||
height: 56px;
|
||||
object-fit: contain;
|
||||
border-radius: 4px;
|
||||
background: #fff;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.gradeNameRow {
|
||||
.grade-name-row {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
align-items: center;
|
||||
gap: 8px 10px;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.grade-name {
|
||||
color: #171A26;
|
||||
font-size: 18px;
|
||||
font-weight: 600;
|
||||
line-height: 1.4;
|
||||
}
|
||||
|
||||
.gradeNameText {
|
||||
font-size: 16px;
|
||||
color: $light_title_color;
|
||||
font-weight: 600;
|
||||
.benefit-tag {
|
||||
padding: 0 8px;
|
||||
border-radius: 4px;
|
||||
background: #fff;
|
||||
color: $theme_color;
|
||||
font-size: 14px;
|
||||
line-height: 22px;
|
||||
}
|
||||
|
||||
.benefitTagsInline {
|
||||
display: inline-flex;
|
||||
flex-wrap: wrap;
|
||||
align-items: center;
|
||||
gap: 6px 8px;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.benefitTag {
|
||||
margin: 0 !important;
|
||||
}
|
||||
|
||||
.gradeExp,
|
||||
.gradeNext {
|
||||
.grade-exp,
|
||||
.grade-next {
|
||||
margin-top: 6px;
|
||||
font-size: 12px;
|
||||
color: #000;
|
||||
color: #666;
|
||||
font-size: 14px;
|
||||
line-height: 22px;
|
||||
}
|
||||
|
||||
.num {
|
||||
color: $theme_color;
|
||||
font-size: 16px;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.ruleItem {
|
||||
padding: 10px 8px;
|
||||
.grade-tabs {
|
||||
display: flex;
|
||||
gap: 24px;
|
||||
margin: 16px 0;
|
||||
border-bottom: 1px solid #f0f0f0;
|
||||
}
|
||||
|
||||
.ruleTop {
|
||||
.grade-tab {
|
||||
position: relative;
|
||||
padding: 10px 0;
|
||||
color: #666;
|
||||
font-size: 14px;
|
||||
line-height: 22px;
|
||||
cursor: pointer;
|
||||
|
||||
&.active {
|
||||
color: $theme_color;
|
||||
font-weight: 600;
|
||||
|
||||
&::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
height: 2px;
|
||||
background: $theme_color;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.rule-item {
|
||||
padding: 14px 0;
|
||||
border-top: 1px solid #f0f0f0;
|
||||
|
||||
&:first-child {
|
||||
border-top: none;
|
||||
}
|
||||
}
|
||||
|
||||
.rule-top {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
gap: 10px;
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.ruleName {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
color: $light_title_color;
|
||||
.rule-name {
|
||||
color: #171A26;
|
||||
font-size: 16px;
|
||||
line-height: 22px;
|
||||
}
|
||||
|
||||
.rule-status {
|
||||
flex-shrink: 0;
|
||||
padding: 0 8px;
|
||||
border-radius: 4px;
|
||||
background: #f5f5f5;
|
||||
color: #999;
|
||||
font-size: 14px;
|
||||
line-height: 22px;
|
||||
|
||||
&.done {
|
||||
background: #f6ffed;
|
||||
color: #19be6b;
|
||||
}
|
||||
}
|
||||
|
||||
.ruleDesc {
|
||||
.rule-desc {
|
||||
margin-top: 6px;
|
||||
color: $light_sub_color;
|
||||
font-size: 12px;
|
||||
line-height: 1.6;
|
||||
color: #666;
|
||||
font-size: 14px;
|
||||
line-height: 22px;
|
||||
}
|
||||
|
||||
.ruleMeta {
|
||||
margin-top: 8px;
|
||||
.rule-meta {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 16px;
|
||||
color: $light_sub_color;
|
||||
font-size: 12px;
|
||||
margin-top: 8px;
|
||||
color: #666;
|
||||
font-size: 14px;
|
||||
line-height: 22px;
|
||||
|
||||
b {
|
||||
color: $theme_color;
|
||||
font-weight: 600;
|
||||
}
|
||||
}
|
||||
|
||||
.metaItem b {
|
||||
color: $theme_color;
|
||||
.rules-desc {
|
||||
margin-top: 16px;
|
||||
padding: 12px 16px;
|
||||
border-radius: 8px;
|
||||
background: #fafafa;
|
||||
color: #666;
|
||||
font-size: 14px;
|
||||
line-height: 22px;
|
||||
white-space: pre-wrap;
|
||||
word-break: break-all;
|
||||
}
|
||||
|
||||
.log-list {
|
||||
--log-cols: 180px minmax(0, 1fr) 100px;
|
||||
}
|
||||
|
||||
.log-head,
|
||||
.log-row {
|
||||
display: grid;
|
||||
grid-template-columns: var(--log-cols);
|
||||
column-gap: 16px;
|
||||
align-items: start;
|
||||
}
|
||||
|
||||
.log-head {
|
||||
padding: 0 8px 10px;
|
||||
color: #999;
|
||||
font-size: 13px;
|
||||
|
||||
span:nth-child(n + 2) {
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
|
||||
.log-row {
|
||||
padding: 14px 8px;
|
||||
border-top: 1px solid #f0f0f0;
|
||||
font-size: 14px;
|
||||
line-height: 22px;
|
||||
}
|
||||
|
||||
.log-time,
|
||||
.log-rule {
|
||||
color: #171A26;
|
||||
}
|
||||
|
||||
.log-rule,
|
||||
.log-point {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.log-point {
|
||||
font-weight: 600;
|
||||
|
||||
&.is-plus {
|
||||
color: #19be6b;
|
||||
}
|
||||
|
||||
&.is-minus {
|
||||
color: $theme_color;
|
||||
}
|
||||
}
|
||||
|
||||
.grade-pagination {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
margin-top: 10px;
|
||||
}
|
||||
margin-top: 16px;
|
||||
|
||||
:deep(.el-pagination) {
|
||||
justify-content: flex-end;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
<template>
|
||||
<div class="wrapper">
|
||||
<UserCenterLayout title="账户安全" :tabs="['账户安全']">
|
||||
<UserCenterLayout>
|
||||
<!-- 手机号验证 -->
|
||||
<el-form ref="formData" :model="formData" label-position="left" label-width="100px" :rules="ruleInLines"
|
||||
v-if="(status == 2 || status == 3) && !showPwd">
|
||||
<el-form-item label="手机号">
|
||||
<div class="phone">1234567890</div>
|
||||
<div class="phone">{{ displayMobile }}</div>
|
||||
</el-form-item>
|
||||
<el-form-item label="图片验证码" prop="picture" style="width: 350px">
|
||||
<el-input v-model="formData.picture" size="large" maxlength="4"></el-input>
|
||||
@@ -80,6 +80,8 @@ import {
|
||||
setPwd,
|
||||
editPwd
|
||||
} from '@/api/account';
|
||||
import { getMemberMsg } from '@/api/login.js';
|
||||
import storage from '@/plugins/storage.js';
|
||||
import {md5} from '@/plugins/md5.js'
|
||||
|
||||
export default {
|
||||
@@ -89,6 +91,7 @@ export default {
|
||||
return {
|
||||
// 1为修改 2为设置 3为提交校验的下一步
|
||||
status: '',
|
||||
mobile: '',
|
||||
showPwd: false, // 显示密码
|
||||
formData: { // 验证表单
|
||||
picture: '',
|
||||
@@ -136,10 +139,33 @@ export default {
|
||||
}
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
displayMobile () {
|
||||
if (!this.mobile) return '未绑定手机号';
|
||||
return this.$filters.secrecyMobile(this.mobile);
|
||||
}
|
||||
},
|
||||
mounted () {
|
||||
this.status = this.$route.query.status
|
||||
this.loadMobile()
|
||||
},
|
||||
methods: {
|
||||
loadMobile () {
|
||||
const rawUserInfo = storage.getItem('userInfo');
|
||||
if (rawUserInfo) {
|
||||
try {
|
||||
const userInfo = JSON.parse(rawUserInfo);
|
||||
if (userInfo && userInfo.mobile) this.mobile = userInfo.mobile;
|
||||
} catch (e) {}
|
||||
}
|
||||
if (!storage.getItem('accessToken')) return;
|
||||
getMemberMsg().then(res => {
|
||||
if (res.success && res.result) {
|
||||
storage.setItem('userInfo', res.result);
|
||||
this.mobile = res.result.mobile || '';
|
||||
}
|
||||
}).catch(() => {});
|
||||
},
|
||||
normalizePwdError (message) {
|
||||
if (!message) return '修改失败,请稍后重试';
|
||||
if (String(message).includes('旧密码') || String(message).includes('密码不正确')) {
|
||||
|
||||
@@ -1,22 +1,32 @@
|
||||
<template>
|
||||
<div class="point">
|
||||
<UserCenterLayout title="我的积分" :tabs="['我的积分']">
|
||||
<div class="point-content">
|
||||
<span>剩余积分:<span>{{ pointObj.point || 0 }}</span></span>
|
||||
<span>累计获得:<span>{{ pointObj.totalPoint || 0 }}</span></span>
|
||||
<UserCenterLayout>
|
||||
<div class="point-summary">
|
||||
<div class="point-stat">
|
||||
<div class="label">剩余积分</div>
|
||||
<div class="value">{{ pointObj.point || 0 }}</div>
|
||||
</div>
|
||||
<div class="point-stat">
|
||||
<div class="label">累计获得</div>
|
||||
<div class="value">{{ pointObj.totalPoint || 0 }}</div>
|
||||
</div>
|
||||
</div>
|
||||
<h3>积分日志</h3>
|
||||
<el-table :data="logData.records || []">
|
||||
<el-table-column prop="content" label="日志内容" align="center" />
|
||||
<el-table-column prop="createTime" label="时间" align="center" />
|
||||
<el-table-column label="积分明细" align="center">
|
||||
<template #default="{ row }">
|
||||
<div :style="{ color: row.pointType === 'INCREASE' ? 'green' : 'red' }">
|
||||
<span v-if="row.pointType === 'INCREASE'">+</span>{{ row.variablePoint }}
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<empty v-if="!(logData.records || []).length" />
|
||||
<div v-else class="log-list">
|
||||
<div class="log-head">
|
||||
<span>日志内容</span>
|
||||
<span>时间</span>
|
||||
<span>积分明细</span>
|
||||
</div>
|
||||
<div class="log-row" v-for="(row, index) in logData.records" :key="row.id || index">
|
||||
<div class="log-content">{{ row.content }}</div>
|
||||
<div class="log-time">{{ row.createTime }}</div>
|
||||
<div class="log-point" :class="row.pointType === 'INCREASE' ? 'is-plus' : 'is-minus'">
|
||||
<span v-if="row.pointType === 'INCREASE'">+</span>{{ row.variablePoint }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- 分页 -->
|
||||
<div class="point-pagination">
|
||||
<el-pagination
|
||||
@@ -25,8 +35,8 @@
|
||||
:total="logData.total"
|
||||
@current-change="changePage"
|
||||
@size-change="changePageSize"
|
||||
:page-sizes="[10, 20, 50]"
|
||||
layout="total, prev, pager, next, jumper"
|
||||
:page-sizes="[20, 50, 100]"
|
||||
layout="total, sizes, prev, pager, next, jumper"
|
||||
/>
|
||||
</div>
|
||||
</UserCenterLayout>
|
||||
@@ -44,7 +54,7 @@ export default {
|
||||
loading: false, // 请求接口加载框
|
||||
params: { // 积分列表请求参数
|
||||
pageNumber: 1,
|
||||
pageSize: 10
|
||||
pageSize: 20
|
||||
},
|
||||
}
|
||||
},
|
||||
@@ -77,28 +87,101 @@ export default {
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
h3 {
|
||||
font-size: 16px;
|
||||
margin: 20px 10px;
|
||||
margin: 8px 0 12px;
|
||||
font-size: 15px;
|
||||
font-weight: 600;
|
||||
color: #333;
|
||||
line-height: 1.4;
|
||||
}
|
||||
|
||||
.point-content {
|
||||
.point-summary {
|
||||
display: flex;
|
||||
gap: 16px;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.point-stat {
|
||||
flex: 1;
|
||||
padding: 16px 20px;
|
||||
background: #fafafa;
|
||||
border-radius: 8px;
|
||||
|
||||
.label {
|
||||
color: #666;
|
||||
font-size: 14px;
|
||||
line-height: 22px;
|
||||
}
|
||||
|
||||
.value {
|
||||
margin-top: 4px;
|
||||
color: $theme_color;
|
||||
font-size: 28px;
|
||||
font-weight: 600;
|
||||
line-height: 1.2;
|
||||
}
|
||||
}
|
||||
|
||||
.log-list {
|
||||
--log-cols: minmax(0, 1.6fr) 180px 100px;
|
||||
}
|
||||
|
||||
.log-head,
|
||||
.log-row {
|
||||
display: grid;
|
||||
grid-template-columns: var(--log-cols);
|
||||
column-gap: 16px;
|
||||
align-items: start;
|
||||
}
|
||||
|
||||
.log-head {
|
||||
padding: 0 8px 10px;
|
||||
color: #999;
|
||||
font-size: 13px;
|
||||
|
||||
span:nth-child(n + 2) {
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
|
||||
.log-row {
|
||||
padding: 14px 8px;
|
||||
border-top: 1px solid #f0f0f0;
|
||||
font-size: 14px;
|
||||
line-height: 22px;
|
||||
}
|
||||
|
||||
.log-content {
|
||||
min-width: 0;
|
||||
color: #171A26;
|
||||
white-space: pre-wrap;
|
||||
word-break: break-all;
|
||||
}
|
||||
|
||||
.log-time {
|
||||
text-align: center;
|
||||
margin-bottom: 30px;
|
||||
color: #171A26;
|
||||
}
|
||||
|
||||
> span {
|
||||
color: #999;
|
||||
margin-right: 100px;
|
||||
.log-point {
|
||||
text-align: center;
|
||||
font-weight: 600;
|
||||
|
||||
span {
|
||||
color: $theme_color;
|
||||
font-size: 24px;
|
||||
}
|
||||
&.is-plus {
|
||||
color: #19be6b;
|
||||
}
|
||||
|
||||
&.is-minus {
|
||||
color: $theme_color;
|
||||
}
|
||||
}
|
||||
|
||||
.point-pagination {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
margin-top: 10px;
|
||||
margin-top: 16px;
|
||||
|
||||
:deep(.el-pagination) {
|
||||
justify-content: flex-end;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -1,191 +1,248 @@
|
||||
<template>
|
||||
|
||||
<div class="wrapper">
|
||||
|
||||
<UserCenterLayout title="用户信息" :tabs="['用户信息']">
|
||||
|
||||
<el-form :model="formItem" :rules="rules" ref="form" label-width="80px">
|
||||
|
||||
<el-form-item label="头像" class="avatar-form-item">
|
||||
|
||||
<div class="avatar-upload">
|
||||
|
||||
<el-avatar v-if="formItem.face" :src="formItem.face" :size="80" />
|
||||
|
||||
<el-avatar v-else :size="80"><el-icon><User /></el-icon></el-avatar>
|
||||
|
||||
<el-upload
|
||||
|
||||
:show-file-list="false"
|
||||
|
||||
:on-success="handleSuccess"
|
||||
|
||||
:format="['jpg','jpeg','png']"
|
||||
|
||||
:action="action"
|
||||
|
||||
:headers="accessToken"
|
||||
|
||||
>
|
||||
|
||||
<el-button>上传头像</el-button>
|
||||
|
||||
</el-upload>
|
||||
|
||||
</div>
|
||||
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="昵称" prop="nickName">
|
||||
|
||||
<el-input class="profile-field" v-model="formItem.nickName" placeholder="" />
|
||||
|
||||
</el-form-item>
|
||||
|
||||
|
||||
|
||||
<el-form-item label="生日">
|
||||
|
||||
<el-date-picker
|
||||
|
||||
class="profile-field"
|
||||
|
||||
type="date"
|
||||
|
||||
placeholder="选择您的生日"
|
||||
|
||||
v-model="formItem.birthday"
|
||||
|
||||
/>
|
||||
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="性别">
|
||||
|
||||
<el-radio-group v-model="formItem.sex" type="button" button-style="solid">
|
||||
|
||||
<el-radio :label="1">男</el-radio>
|
||||
|
||||
<el-radio :label="0">女</el-radio>
|
||||
|
||||
</el-radio-group>
|
||||
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item>
|
||||
|
||||
<el-button type="primary" @click="save">确认修改</el-button>
|
||||
|
||||
|
||||
|
||||
</el-form-item>
|
||||
|
||||
</el-form>
|
||||
|
||||
</UserCenterLayout>
|
||||
|
||||
</div>
|
||||
|
||||
</template>
|
||||
|
||||
|
||||
|
||||
<script>
|
||||
|
||||
import { Message } from "@/utils/message";
|
||||
|
||||
import { editMemberInfo } from '@/api/account.js';
|
||||
|
||||
import { getMemberMsg } from '@/api/login.js';
|
||||
|
||||
import { buyerUrl } from '@/plugins/request.js';
|
||||
|
||||
import storage from '@/plugins/storage.js';
|
||||
|
||||
import { User } from '@element-plus/icons-vue';
|
||||
|
||||
export default {
|
||||
|
||||
components: { User },
|
||||
|
||||
name: 'Profile',
|
||||
|
||||
data () {
|
||||
|
||||
return {
|
||||
|
||||
rules: { // 验证规则
|
||||
|
||||
nickName: [{required: true, message: '用户昵称不能为空'}, { max: 16, message: '用户昵称不能超过15个字符' }]
|
||||
|
||||
},
|
||||
|
||||
formItem: {}, // 表单数据
|
||||
|
||||
action: buyerUrl + '/buyer/common/upload/file', // 上传接口
|
||||
|
||||
accessToken: {} // 验证token
|
||||
|
||||
}
|
||||
|
||||
},
|
||||
|
||||
mounted () {
|
||||
|
||||
this.accessToken.accessToken = storage.getItem('accessToken');
|
||||
|
||||
this.loadUserInfo();
|
||||
|
||||
},
|
||||
|
||||
methods: {
|
||||
|
||||
loadUserInfo () {
|
||||
|
||||
const rawUserInfo = storage.getItem('userInfo');
|
||||
|
||||
if (rawUserInfo) {
|
||||
|
||||
this.applyUserInfo(JSON.parse(rawUserInfo));
|
||||
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
if (!storage.getItem('accessToken')) {
|
||||
|
||||
this.redirectToLogin();
|
||||
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
getMemberMsg().then(res => {
|
||||
|
||||
if (res.success && res.result) {
|
||||
|
||||
storage.setItem('userInfo', res.result);
|
||||
|
||||
this.applyUserInfo(res.result);
|
||||
|
||||
} else {
|
||||
|
||||
this.redirectToLogin();
|
||||
|
||||
}
|
||||
|
||||
}).catch(() => {
|
||||
|
||||
this.redirectToLogin();
|
||||
|
||||
});
|
||||
|
||||
},
|
||||
|
||||
applyUserInfo (userInfo) {
|
||||
|
||||
this.formItem = { ...userInfo };
|
||||
|
||||
this.formItem.birthday = this.normalizeBirthday(this.formItem.birthday);
|
||||
|
||||
},
|
||||
<template>
|
||||
<div class="wrapper">
|
||||
<UserCenterLayout>
|
||||
<el-form class="profile-form" :model="formItem" :rules="rules" ref="form" label-width="72px" label-position="left">
|
||||
<el-form-item label="头像" class="avatar-form-item">
|
||||
<div class="avatar-upload">
|
||||
<el-avatar v-if="formItem.face" :src="formItem.face" :size="72" />
|
||||
<el-avatar v-else :size="72"><el-icon><User /></el-icon></el-avatar>
|
||||
<el-upload
|
||||
:show-file-list="false"
|
||||
:on-success="handleSuccess"
|
||||
:format="['jpg','jpeg','png']"
|
||||
:action="action"
|
||||
:headers="accessToken"
|
||||
>
|
||||
<button type="button" class="ghost-btn">上传头像</button>
|
||||
</el-upload>
|
||||
</div>
|
||||
</el-form-item>
|
||||
<el-form-item label="昵称" prop="nickName">
|
||||
<el-input class="profile-field" v-model="formItem.nickName" maxlength="16" placeholder="请输入昵称" />
|
||||
</el-form-item>
|
||||
<el-form-item label="生日">
|
||||
<el-date-picker
|
||||
class="profile-field"
|
||||
type="date"
|
||||
placeholder="选择您的生日"
|
||||
v-model="formItem.birthday"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="性别">
|
||||
<div class="sex-group">
|
||||
<button type="button" class="sex-btn" :class="{ active: formItem.sex === 1 }" @click="formItem.sex = 1">男</button>
|
||||
<button type="button" class="sex-btn" :class="{ active: formItem.sex === 0 }" @click="formItem.sex = 0">女</button>
|
||||
</div>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<button type="button" class="op-btn" @click="save">确认修改</button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</UserCenterLayout>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { Message } from "@/utils/message";
|
||||
import { editMemberInfo } from '@/api/account.js';
|
||||
import { getMemberMsg } from '@/api/login.js';
|
||||
import { buyerUrl } from '@/plugins/request.js';
|
||||
import storage from '@/plugins/storage.js';
|
||||
import { User } from '@element-plus/icons-vue';
|
||||
export default {
|
||||
components: { User },
|
||||
name: 'Profile',
|
||||
data () {
|
||||
return {
|
||||
rules: { // 验证规则
|
||||
nickName: [{required: true, message: '用户昵称不能为空'}, { max: 16, message: '用户昵称不能超过15个字符' }]
|
||||
},
|
||||
formItem: {}, // 表单数据
|
||||
action: buyerUrl + '/buyer/common/upload/file', // 上传接口
|
||||
accessToken: {} // 验证token
|
||||
}
|
||||
},
|
||||
mounted () {
|
||||
this.accessToken.accessToken = storage.getItem('accessToken');
|
||||
this.loadUserInfo();
|
||||
},
|
||||
methods: {
|
||||
loadUserInfo () {
|
||||
const rawUserInfo = storage.getItem('userInfo');
|
||||
if (rawUserInfo) {
|
||||
this.applyUserInfo(JSON.parse(rawUserInfo));
|
||||
return;
|
||||
}
|
||||
if (!storage.getItem('accessToken')) {
|
||||
this.redirectToLogin();
|
||||
return;
|
||||
}
|
||||
getMemberMsg().then(res => {
|
||||
if (res.success && res.result) {
|
||||
storage.setItem('userInfo', res.result);
|
||||
this.applyUserInfo(res.result);
|
||||
} else {
|
||||
this.redirectToLogin();
|
||||
}
|
||||
}).catch(() => {
|
||||
this.redirectToLogin();
|
||||
});
|
||||
},
|
||||
applyUserInfo (userInfo) {
|
||||
this.formItem = { ...userInfo };
|
||||
this.formItem.birthday = this.normalizeBirthday(this.formItem.birthday);
|
||||
},
|
||||
redirectToLogin () {
|
||||
this.$router.push({
|
||||
path: '/login',
|
||||
query: {
|
||||
rePath: this.$route.path,
|
||||
query: JSON.stringify(this.$route.query || {}),
|
||||
},
|
||||
});
|
||||
},
|
||||
normalizeBirthday (value) {
|
||||
if (!value) return ''
|
||||
if (value instanceof Date) return value
|
||||
if (typeof value === 'number') return new Date(value)
|
||||
if (typeof value === 'string') {
|
||||
const m = value.match(/^(\d{4})-(\d{2})-(\d{2})/)
|
||||
if (m) return new Date(Number(m[1]), Number(m[2]) - 1, Number(m[3]))
|
||||
const d = new Date(value)
|
||||
return isNaN(d.getTime()) ? '' : d
|
||||
}
|
||||
return ''
|
||||
},
|
||||
formatBirthday (value) {
|
||||
if (!value) return null
|
||||
if (typeof value === 'string') {
|
||||
const m = value.match(/^(\d{4})-(\d{2})-(\d{2})/)
|
||||
return m ? `${m[1]}-${m[2]}-${m[3]}` : null
|
||||
}
|
||||
const d = value instanceof Date ? value : new Date(value)
|
||||
if (isNaN(d.getTime())) return null
|
||||
const yyyy = d.getFullYear()
|
||||
const mm = String(d.getMonth() + 1).padStart(2, '0')
|
||||
const dd = String(d.getDate()).padStart(2, '0')
|
||||
return `${yyyy}-${mm}-${dd}`
|
||||
},
|
||||
save () { // 保存
|
||||
this.$refs.form.validate(valid => {
|
||||
if (valid) {
|
||||
let params = {
|
||||
birthday: this.formatBirthday(this.formItem.birthday),
|
||||
face: this.formItem.face,
|
||||
nickName: this.formItem.nickName,
|
||||
sex: this.formItem.sex
|
||||
}
|
||||
editMemberInfo(params).then(res => {
|
||||
if (res.success) {
|
||||
Message.success('修改个人资料成功')
|
||||
storage.setItem('userInfo', res.result)
|
||||
this.$router.go(0)
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
},
|
||||
handleSuccess (res, file) { // 上传成功
|
||||
this.formItem['face'] = res.result
|
||||
},
|
||||
}
|
||||
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.profile-form {
|
||||
max-width: 480px;
|
||||
padding-top: 4px;
|
||||
|
||||
:deep(.el-form-item) {
|
||||
margin-bottom: 22px;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
:deep(.el-form-item__label) {
|
||||
height: auto;
|
||||
line-height: 22px;
|
||||
color: #666;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
:deep(.el-input__wrapper),
|
||||
:deep(.el-date-editor.el-input__wrapper) {
|
||||
min-height: 36px;
|
||||
}
|
||||
}
|
||||
|
||||
.avatar-form-item {
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.avatar-upload {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 16px;
|
||||
|
||||
:deep(.el-upload) {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
}
|
||||
|
||||
.profile-field {
|
||||
width: 320px;
|
||||
}
|
||||
|
||||
:deep(.profile-field.el-date-editor) {
|
||||
width: 320px;
|
||||
}
|
||||
|
||||
.sex-group {
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.sex-btn,
|
||||
.ghost-btn,
|
||||
.op-btn {
|
||||
height: 32px;
|
||||
padding: 0 16px;
|
||||
border-radius: 4px;
|
||||
font-family: inherit;
|
||||
font-size: 14px;
|
||||
line-height: 30px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.sex-btn,
|
||||
.ghost-btn {
|
||||
border: 1px solid #ddd;
|
||||
background: #fff;
|
||||
color: #171A26;
|
||||
|
||||
&:hover {
|
||||
border-color: $theme_color;
|
||||
color: $theme_color;
|
||||
}
|
||||
}
|
||||
|
||||
.sex-btn.active {
|
||||
border-color: $theme_color;
|
||||
background: #fff5f4;
|
||||
color: $theme_color;
|
||||
}
|
||||
|
||||
.op-btn {
|
||||
min-width: 96px;
|
||||
border: 1px solid $theme_color;
|
||||
background: $theme_color;
|
||||
color: #fff;
|
||||
|
||||
&:hover {
|
||||
opacity: 0.9;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<div class="add-eval">
|
||||
<UserCenterLayout title="订单评价" :tabs="['订单评价']">
|
||||
<UserCenterLayout>
|
||||
<div class="title">
|
||||
<p>
|
||||
<span class="color999">订单号:</span><span>{{$route.query.sn}}</span>
|
||||
@@ -68,7 +68,7 @@
|
||||
<div class="submit-row">
|
||||
<el-button type="primary" :loading="loading" @click="save">发表</el-button>
|
||||
</div>
|
||||
<el-dialog title="View Image" v-model="visible">
|
||||
<el-dialog title="图片预览" v-model="visible">
|
||||
<img :src="previewImage" v-if="visible" style="width: 100%">
|
||||
</el-dialog>
|
||||
</UserCenterLayout>
|
||||
@@ -326,7 +326,7 @@ export default {
|
||||
}
|
||||
|
||||
.describe {
|
||||
font-size: 12px;
|
||||
font-size: 14px;
|
||||
color: #999;
|
||||
margin-top: 8px;
|
||||
}
|
||||
|
||||
@@ -1,97 +1,81 @@
|
||||
<template>
|
||||
<div class="add-eval">
|
||||
<UserCenterLayout title="评价详情" :tabs="['评价详情']">
|
||||
<div class="title">
|
||||
<p>
|
||||
<span class="color999">创建人:</span><span>{{ $filters.secrecyMobile( orderGoods.createBy ) }}</span>
|
||||
<span class="color999 ml_20">{{ orderGoods.createTime }}</span>
|
||||
</p>
|
||||
</div>
|
||||
<!-- 物流评分、服务评分 -->
|
||||
<div class="delivery-rate">
|
||||
<div class="fontsize_16">物流服务评价:</div>
|
||||
<div class="color999 delivery-rate-items">
|
||||
<span>物流评价:<el-rate disabled :model-value="Number(orderGoods.deliveryScore) || 0" :colors="rateThemeColors" class="theme-rate" /></span>
|
||||
<span>服务评价:<el-rate disabled :model-value="Number(orderGoods.serviceScore) || 0" :colors="rateThemeColors" class="theme-rate" /></span>
|
||||
<span>描述评价:<el-rate disabled :model-value="Number(orderGoods.descriptionScore) || 0" :colors="rateThemeColors" class="theme-rate" /></span>
|
||||
</div>
|
||||
</div>
|
||||
<!-- 添加订单评价 左侧商品详情 右侧评价框 -->
|
||||
<ul class="goods-eval">
|
||||
<li>
|
||||
<div class="goods-con">
|
||||
<UserCenterLayout>
|
||||
<div class="order-card status-card" v-if="orderGoods.goodsName || orderGoods.content">
|
||||
<div class="status-head">
|
||||
<div class="status-main">
|
||||
<p class="status-text">{{ gradeText }}</p>
|
||||
<p class="status-sn">评价时间:{{ orderGoods.createTime }}</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="goods-row" v-if="orderGoods.goodsName">
|
||||
<img
|
||||
:src="orderGoods.goodsImage"
|
||||
class="hover-pointer"
|
||||
alt=""
|
||||
width="100"
|
||||
@click="goGoodsDetail(orderGoods.skuId, orderGoods.goodsId)"
|
||||
@error="$event.target.style.visibility = 'hidden'"
|
||||
/>
|
||||
<p
|
||||
class="hover-pointer color999"
|
||||
@click="goGoodsDetail(orderGoods.skuId, orderGoods.goodsId)"
|
||||
>
|
||||
<div class="goods-name" @click="goGoodsDetail(orderGoods.skuId, orderGoods.goodsId)">
|
||||
{{ orderGoods.goodsName }}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="eval-con">
|
||||
<div>
|
||||
<span class="color999">商品评价:</span>
|
||||
<el-radio-group
|
||||
style="margin-bottom: 5px; color: #999"
|
||||
v-model="orderGoods.grade"
|
||||
type="button"
|
||||
button-style="solid"
|
||||
>
|
||||
<el-radio label="GOOD" disabled>好评</el-radio>
|
||||
<el-radio label="MODERATE" disabled>中评</el-radio>
|
||||
<el-radio label="WORSE" disabled>差评</el-radio>
|
||||
</el-radio-group>
|
||||
<el-input
|
||||
type="textarea"
|
||||
maxlength="500"
|
||||
readonly
|
||||
show-word-limit
|
||||
:rows="4"
|
||||
v-model="orderGoods.content"
|
||||
/>
|
||||
<div class="order-card">
|
||||
<h3>物流服务评价</h3>
|
||||
<div class="rate-list">
|
||||
<div class="rate-row">
|
||||
<span>物流评价</span>
|
||||
<el-rate disabled :model-value="Number(orderGoods.deliveryScore) || 0" :colors="rateThemeColors" class="theme-rate" />
|
||||
</div>
|
||||
<div style="display: flex; align-items: center">
|
||||
<template v-if="orderGoods.images">
|
||||
<div class="demo-upload-list" v-for="(img, index) in orderGoods.images.split(',')" :key="index">
|
||||
<img :src="img" />
|
||||
<div class="demo-upload-list-cover"><el-icon @click="handleView(img)"><View /></el-icon></div>
|
||||
</div>
|
||||
</template>
|
||||
<div class="rate-row">
|
||||
<span>服务评价</span>
|
||||
<el-rate disabled :model-value="Number(orderGoods.serviceScore) || 0" :colors="rateThemeColors" class="theme-rate" />
|
||||
</div>
|
||||
<div style="margin-top: 20px;" v-if="orderGoods.reply || orderGoods.replyImage">
|
||||
<span class="color999">商家回复:</span>
|
||||
<span>{{ orderGoods.reply }}</span>
|
||||
<div style="display: flex; align-items: center">
|
||||
<template v-if="orderGoods.replyImage">
|
||||
<div class="demo-upload-list" v-for="(img, index) in orderGoods.replyImage.split(',')" :key="index">
|
||||
<img :src="img" />
|
||||
<div class="demo-upload-list-cover"><el-icon @click="handleView(img)"><View /></el-icon></div>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
<div class="rate-row">
|
||||
<span>描述评价</span>
|
||||
<el-rate disabled :model-value="Number(orderGoods.descriptionScore) || 0" :colors="rateThemeColors" class="theme-rate" />
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
<el-dialog title="View Image" v-model="visible">
|
||||
<img :src="previewImage" v-if="visible" style="width: 100%" />
|
||||
</el-dialog>
|
||||
</div>
|
||||
|
||||
<div class="order-card">
|
||||
<h3>评价内容</h3>
|
||||
<p class="eval-text">{{ orderGoods.content || '暂无评价内容' }}</p>
|
||||
<div class="image-list" v-if="orderGoods.images">
|
||||
<img
|
||||
v-for="(img, index) in orderGoods.images.split(',')"
|
||||
:key="index"
|
||||
:src="img"
|
||||
alt=""
|
||||
@click="handleView(img)"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="order-card" v-if="orderGoods.reply || orderGoods.replyImage">
|
||||
<h3>商家回复</h3>
|
||||
<p class="eval-text" v-if="orderGoods.reply">{{ orderGoods.reply }}</p>
|
||||
<div class="image-list" v-if="orderGoods.replyImage">
|
||||
<img
|
||||
v-for="(img, index) in orderGoods.replyImage.split(',')"
|
||||
:key="index"
|
||||
:src="img"
|
||||
alt=""
|
||||
@click="handleView(img)"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<el-dialog title="查看图片" v-model="visible" width="640px">
|
||||
<img :src="previewImage" v-if="visible" class="preview-img" alt="" />
|
||||
</el-dialog>
|
||||
</UserCenterLayout>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import { View } from '@element-plus/icons-vue';
|
||||
import { evaluationDetail } from "@/api/member.js";
|
||||
export default {
|
||||
components: { View },
|
||||
data() {
|
||||
return {
|
||||
order: {}, // 订单详情
|
||||
@@ -103,6 +87,12 @@ export default {
|
||||
rateThemeColors: ["var(--theme-color)", "var(--theme-color)", "var(--theme-color)"],
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
gradeText () {
|
||||
const map = { GOOD: '好评', MODERATE: '中评', WORSE: '差评' }
|
||||
return map[this.orderGoods.grade] || '评价详情'
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
getDetail() {
|
||||
// 获取评价详情
|
||||
@@ -130,103 +120,140 @@ export default {
|
||||
};
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.delivery-rate {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-top: 20px;
|
||||
min-height: 50px;
|
||||
border-bottom: 1px solid #eee;
|
||||
> div:nth-child(1) {
|
||||
width: 120px;
|
||||
font-weight: bold;
|
||||
.add-eval {
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.order-card {
|
||||
padding: 4px 0 16px;
|
||||
margin-bottom: 8px;
|
||||
border-bottom: 1px solid #f0f0f0;
|
||||
|
||||
h3 {
|
||||
margin: 0 0 12px;
|
||||
font-size: 15px;
|
||||
font-weight: 600;
|
||||
color: #333;
|
||||
line-height: 1.4;
|
||||
}
|
||||
|
||||
&:last-of-type {
|
||||
border-bottom: none;
|
||||
}
|
||||
}
|
||||
|
||||
.delivery-rate-items {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
align-items: center;
|
||||
gap: 16px;
|
||||
.status-card {
|
||||
padding-top: 8px;
|
||||
}
|
||||
|
||||
.delivery-rate-items :deep(.theme-rate.el-rate) {
|
||||
.status-text {
|
||||
margin: 0;
|
||||
color: $theme_color;
|
||||
font-size: 18px;
|
||||
font-weight: 600;
|
||||
line-height: 1.4;
|
||||
}
|
||||
|
||||
.status-sn {
|
||||
margin: 6px 0 0;
|
||||
color: #171A26;
|
||||
font-size: 14px;
|
||||
line-height: 22px;
|
||||
|
||||
span {
|
||||
margin-left: 16px;
|
||||
}
|
||||
}
|
||||
|
||||
.goods-row {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 12px;
|
||||
margin-top: 16px;
|
||||
padding: 12px;
|
||||
background: #fafafa;
|
||||
border-radius: 8px;
|
||||
|
||||
img {
|
||||
width: 64px;
|
||||
height: 64px;
|
||||
object-fit: cover;
|
||||
border: 1px solid #f0f0f0;
|
||||
background: #f5f5f5;
|
||||
flex-shrink: 0;
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
|
||||
.goods-name {
|
||||
color: #333;
|
||||
font-size: 16px;
|
||||
line-height: 22px;
|
||||
word-break: break-all;
|
||||
cursor: pointer;
|
||||
|
||||
&:hover {
|
||||
color: $theme_color;
|
||||
}
|
||||
}
|
||||
|
||||
.rate-list {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 8px 32px;
|
||||
}
|
||||
|
||||
.rate-row {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
min-width: 180px;
|
||||
color: #171A26;
|
||||
font-size: 14px;
|
||||
line-height: 22px;
|
||||
|
||||
span {
|
||||
width: 72px;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.rate-row :deep(.theme-rate.el-rate) {
|
||||
--el-rate-fill-color: #{$theme_color};
|
||||
--el-rate-disabled-fill-color: #{$theme_color};
|
||||
height: 22px;
|
||||
}
|
||||
|
||||
:deep(.theme-rate .el-rate__icon.is-active) {
|
||||
color: $theme_color !important;
|
||||
}
|
||||
.goods-eval li {
|
||||
|
||||
.eval-text {
|
||||
margin: 0;
|
||||
color: #171A26;
|
||||
font-size: 14px;
|
||||
line-height: 22px;
|
||||
white-space: pre-wrap;
|
||||
word-break: break-all;
|
||||
}
|
||||
|
||||
.image-list {
|
||||
display: flex;
|
||||
border-bottom: 1px solid #eee;
|
||||
flex-wrap: wrap;
|
||||
gap: 12px;
|
||||
margin-top: 12px;
|
||||
|
||||
.goods-con {
|
||||
width: 30%;
|
||||
padding: 20px;
|
||||
text-align: center;
|
||||
p {
|
||||
word-wrap: wrap;
|
||||
&:hover {
|
||||
color: $theme_color;
|
||||
}
|
||||
}
|
||||
}
|
||||
.eval-con {
|
||||
width: 70%;
|
||||
padding: 20px;
|
||||
}
|
||||
}
|
||||
|
||||
.demo-upload-list {
|
||||
display: inline-block;
|
||||
width: 60px;
|
||||
height: 60px;
|
||||
text-align: center;
|
||||
line-height: 60px;
|
||||
border: 1px solid transparent;
|
||||
border-radius: 4px;
|
||||
overflow: hidden;
|
||||
background: #fff;
|
||||
position: relative;
|
||||
box-shadow: 0 1px 1px rgba(0, 0, 0, 0.2);
|
||||
margin-right: 4px;
|
||||
margin-top: 10px;
|
||||
}
|
||||
.demo-upload-list img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
.demo-upload-list-cover {
|
||||
display: none;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
background: rgba(0, 0, 0, 0.6);
|
||||
}
|
||||
.demo-upload-list:hover .demo-upload-list-cover {
|
||||
display: block;
|
||||
}
|
||||
.demo-upload-list-cover i {
|
||||
color: #fff;
|
||||
font-size: 20px;
|
||||
cursor: pointer;
|
||||
margin: 0 2px;
|
||||
}
|
||||
.icon-upload {
|
||||
width: 58px;
|
||||
height: 58px;
|
||||
line-height: 58px;
|
||||
text-align: center;
|
||||
display: inline-block;
|
||||
border: 1px dashed #999;
|
||||
border-radius: 4px;
|
||||
margin-top: 10px;
|
||||
&:hover {
|
||||
img {
|
||||
width: 88px;
|
||||
height: 88px;
|
||||
object-fit: cover;
|
||||
border: 1px solid #f0f0f0;
|
||||
border-radius: 6px;
|
||||
cursor: pointer;
|
||||
border-color: $theme_color;
|
||||
}
|
||||
}
|
||||
|
||||
.preview-img {
|
||||
display: block;
|
||||
width: 100%;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -1,17 +1,138 @@
|
||||
<template>
|
||||
<div class="msg-list">
|
||||
会员消息详情
|
||||
<div class="msg-detail-page">
|
||||
<UserCenterLayout title="消息详情">
|
||||
<div v-if="detail.id" class="msg-detail">
|
||||
<div class="msg-detail-head">
|
||||
<h2>{{ detail.title || '站内消息' }}</h2>
|
||||
<p>{{ detail.createTime }}</p>
|
||||
</div>
|
||||
<div class="msg-detail-content">{{ detail.content || '暂无内容' }}</div>
|
||||
<div class="msg-detail-actions">
|
||||
<el-button @click="goBack">返回</el-button>
|
||||
<el-button v-if="detail.status !== 'ALREADY_REMOVE'" type="danger" @click="removeMessage">删除</el-button>
|
||||
</div>
|
||||
</div>
|
||||
<div v-else-if="loaded">
|
||||
<empty _Title="消息不存在或已失效" />
|
||||
<div class="msg-detail-actions is-empty">
|
||||
<el-button @click="goBack">返回消息列表</el-button>
|
||||
</div>
|
||||
</div>
|
||||
</UserCenterLayout>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { Message, Modal } from "@/utils/message";
|
||||
import { delMemberMsg, getMemberMessage, readMemberMsg } from '@/api/member.js';
|
||||
|
||||
const CACHE_KEY = 'buyer-member-message';
|
||||
|
||||
export default {
|
||||
data() {
|
||||
name: 'MsgDetail',
|
||||
data () {
|
||||
return {
|
||||
detail: {}, // 消息详情
|
||||
detail: {},
|
||||
loaded: false
|
||||
}
|
||||
},
|
||||
mounted () {
|
||||
this.loadDetail()
|
||||
},
|
||||
methods: {
|
||||
loadDetail () {
|
||||
const id = this.$route.query.id
|
||||
if (!id) {
|
||||
this.loaded = true
|
||||
return
|
||||
}
|
||||
const cached = this.readCache(id)
|
||||
if (cached) this.detail = cached
|
||||
getMemberMessage(id).then(res => {
|
||||
if (res && res.success && res.result && res.result.id) {
|
||||
this.detail = res.result
|
||||
sessionStorage.setItem(CACHE_KEY, JSON.stringify(res.result))
|
||||
}
|
||||
}).catch(() => {}).finally(() => {
|
||||
this.loaded = true
|
||||
this.markRead()
|
||||
})
|
||||
},
|
||||
readCache (id) {
|
||||
try {
|
||||
const raw = sessionStorage.getItem(CACHE_KEY)
|
||||
if (!raw) return null
|
||||
const message = JSON.parse(raw)
|
||||
return message && String(message.id) === String(id) ? message : null
|
||||
} catch (e) {
|
||||
return null
|
||||
}
|
||||
},
|
||||
markRead () {
|
||||
if (!this.detail.id || this.detail.status !== 'UN_READY') return
|
||||
readMemberMsg(this.detail.id).then(res => {
|
||||
if (res && res.success) this.detail.status = 'ALREADY_READY'
|
||||
}).catch(() => {})
|
||||
},
|
||||
goBack () {
|
||||
this.$router.push({ name: 'MsgList' })
|
||||
},
|
||||
removeMessage () {
|
||||
Modal.confirm({
|
||||
title: '确认删除',
|
||||
content: '确认要删除此消息?',
|
||||
loading: true,
|
||||
onOk: () =>
|
||||
delMemberMsg(this.detail.id).then((res) => {
|
||||
if (res.success) {
|
||||
Message.success('消息已成功放入回收站')
|
||||
this.goBack()
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
|
||||
</style>
|
||||
.msg-detail-head {
|
||||
padding-bottom: 16px;
|
||||
border-bottom: 1px solid #f0f0f0;
|
||||
|
||||
h2 {
|
||||
margin: 0;
|
||||
color: #171A26;
|
||||
font-size: 18px;
|
||||
font-weight: 600;
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
p {
|
||||
margin: 8px 0 0;
|
||||
color: #999;
|
||||
font-size: 14px;
|
||||
line-height: 22px;
|
||||
}
|
||||
}
|
||||
|
||||
.msg-detail-content {
|
||||
padding: 20px 0 8px;
|
||||
color: #333;
|
||||
font-size: 14px;
|
||||
line-height: 1.8;
|
||||
white-space: pre-wrap;
|
||||
word-break: break-all;
|
||||
}
|
||||
|
||||
.msg-detail-actions {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
gap: 12px;
|
||||
margin-top: 24px;
|
||||
|
||||
&.is-empty {
|
||||
justify-content: center;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -1,43 +1,47 @@
|
||||
<template>
|
||||
<div class="msg-list">
|
||||
<UserCenterLayout
|
||||
title="我的消息"
|
||||
:tabs="status"
|
||||
:active-tab="activeStatusIndex"
|
||||
@tab-change="statusChange"
|
||||
>
|
||||
|
||||
<el-table v-if="params.status != 'ALREADY_REMOVE'" :data="messageData.records || []">
|
||||
<el-table-column prop="title" label="消息标题" align="left" show-overflow-tooltip />
|
||||
<el-table-column prop="content" label="消息内容" align="left" show-overflow-tooltip />
|
||||
<el-table-column prop="createTime" label="发送时间" align="left" width="240" />
|
||||
<el-table-column label="操作" align="center" fixed="right" width="150">
|
||||
<template #default="{ row }">
|
||||
<el-button
|
||||
v-if="row.status === 'UN_READY'"
|
||||
type="primary"
|
||||
size="small"
|
||||
style="margin-right: 5px"
|
||||
@click="setRead(row.id)"
|
||||
>已读</el-button>
|
||||
<el-button type="danger" size="small" @click="removeMessage(row.id)">删除</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<el-table v-else :data="messageData.records || []">
|
||||
<el-table-column prop="title" label="消息标题" align="left" show-overflow-tooltip />
|
||||
<el-table-column prop="content" label="消息内容" align="left" show-overflow-tooltip />
|
||||
<el-table-column prop="createTime" label="发送时间" align="left" width="240" />
|
||||
</el-table>
|
||||
<div class="msg-pagination">
|
||||
<empty v-if="!(messageData.records || []).length" />
|
||||
<div v-else class="msg-table" :class="{ 'is-recycle': params.status === 'ALREADY_REMOVE' }">
|
||||
<div class="msg-head">
|
||||
<span>消息标题</span>
|
||||
<span>消息内容</span>
|
||||
<span>发送时间</span>
|
||||
<span v-if="params.status !== 'ALREADY_REMOVE'">操作</span>
|
||||
</div>
|
||||
<div
|
||||
class="msg-row"
|
||||
v-for="row in messageData.records"
|
||||
:key="row.id"
|
||||
:class="{ unread: row.status === 'UN_READY' }"
|
||||
>
|
||||
<div class="msg-title" @click="openDetail(row)">
|
||||
<i v-if="row.status === 'UN_READY'" class="unread-dot"></i>
|
||||
<span>{{ row.title }}</span>
|
||||
</div>
|
||||
<div class="msg-content" @click="openDetail(row)">{{ row.content }}</div>
|
||||
<div class="msg-time">{{ row.createTime }}</div>
|
||||
<div class="msg-ops" v-if="params.status !== 'ALREADY_REMOVE'">
|
||||
<button type="button" class="text-link" @click="openDetail(row)">查看</button>
|
||||
<button v-if="row.status === 'UN_READY'" type="button" class="text-link" @click="setRead(row.id)">已读</button>
|
||||
<button type="button" class="text-link" @click="removeMessage(row.id)">删除</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="msg-pagination" v-if="messageData.total">
|
||||
<el-pagination
|
||||
v-model:current-page="params.pageNumber"
|
||||
v-model:page-size="params.pageSize"
|
||||
:total="messageData.total"
|
||||
@current-change="changePage"
|
||||
@size-change="changePageSize"
|
||||
:page-sizes="[10, 20, 50]"
|
||||
layout="total, prev, pager, next, jumper"
|
||||
:page-sizes="[20, 50, 100]"
|
||||
layout="total, sizes, prev, pager, next, jumper"
|
||||
/>
|
||||
</div>
|
||||
</UserCenterLayout>
|
||||
@@ -53,7 +57,7 @@ export default {
|
||||
status: ['未读', '已读', '回收站'],
|
||||
params: {
|
||||
pageNumber: 1,
|
||||
pageSize: 10,
|
||||
pageSize: 20,
|
||||
status: 'UN_READY'
|
||||
},
|
||||
}
|
||||
@@ -70,6 +74,7 @@ export default {
|
||||
if (index === 0) { this.params.status = 'UN_READY' }
|
||||
if (index === 1) { this.params.status = 'ALREADY_READY' }
|
||||
if (index === 2) { this.params.status = 'ALREADY_REMOVE' }
|
||||
this.params.pageNumber = 1
|
||||
this.getList()
|
||||
},
|
||||
changePage (v) {
|
||||
@@ -77,9 +82,14 @@ export default {
|
||||
this.getList();
|
||||
},
|
||||
changePageSize (v) {
|
||||
this.params.pageNumber = 1
|
||||
this.params.pageSize = v;
|
||||
this.getList();
|
||||
},
|
||||
openDetail (row) {
|
||||
sessionStorage.setItem('buyer-member-message', JSON.stringify(row))
|
||||
this.$router.push({ name: 'MsgDetail', query: { id: row.id } })
|
||||
},
|
||||
getList () {
|
||||
memberMsgList(this.params).then(res => {
|
||||
if (res.success) {
|
||||
@@ -115,9 +125,112 @@ export default {
|
||||
}
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.msg-table {
|
||||
--msg-cols: minmax(140px, 1.1fr) minmax(0, 2.2fr) 180px 168px;
|
||||
padding-top: 8px;
|
||||
}
|
||||
|
||||
.msg-table.is-recycle {
|
||||
--msg-cols: minmax(140px, 1.1fr) minmax(0, 2.2fr) 180px;
|
||||
}
|
||||
|
||||
.msg-head,
|
||||
.msg-row {
|
||||
display: grid;
|
||||
grid-template-columns: var(--msg-cols);
|
||||
column-gap: 16px;
|
||||
align-items: start;
|
||||
}
|
||||
|
||||
.msg-head {
|
||||
padding: 0 8px 10px;
|
||||
color: #999;
|
||||
font-size: 13px;
|
||||
|
||||
span:last-child {
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
|
||||
.msg-row {
|
||||
padding: 14px 8px;
|
||||
border-top: 1px solid #f0f0f0;
|
||||
font-size: 14px;
|
||||
line-height: 22px;
|
||||
}
|
||||
|
||||
.msg-title {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
min-width: 0;
|
||||
color: #171A26;
|
||||
cursor: pointer;
|
||||
|
||||
&:hover span {
|
||||
color: $theme_color;
|
||||
}
|
||||
|
||||
span {
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
}
|
||||
|
||||
.unread .msg-title {
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.unread-dot {
|
||||
width: 6px;
|
||||
height: 6px;
|
||||
margin-right: 8px;
|
||||
border-radius: 50%;
|
||||
background: $theme_color;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.msg-content {
|
||||
min-width: 0;
|
||||
color: #666;
|
||||
cursor: pointer;
|
||||
white-space: pre-wrap;
|
||||
word-break: break-all;
|
||||
line-height: 22px;
|
||||
}
|
||||
|
||||
.msg-time {
|
||||
color: #171A26;
|
||||
}
|
||||
|
||||
.msg-ops {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
gap: 16px;
|
||||
}
|
||||
|
||||
.text-link {
|
||||
border: none;
|
||||
background: none;
|
||||
padding: 0;
|
||||
color: #171A26;
|
||||
font-family: inherit;
|
||||
font-size: 14px;
|
||||
line-height: 22px;
|
||||
cursor: pointer;
|
||||
|
||||
&:hover {
|
||||
color: $theme_color;
|
||||
}
|
||||
}
|
||||
|
||||
.msg-pagination {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
margin-top: 10px;
|
||||
margin-top: 16px;
|
||||
|
||||
:deep(.el-pagination) {
|
||||
justify-content: flex-end;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<div>
|
||||
<UserCenterLayout title="收货地址" :tabs="['收货地址']">
|
||||
<UserCenterLayout>
|
||||
<div class="add-box">
|
||||
<el-form :model="formData" ref="form" label-position="left" label-width="100px" :rules="ruleInline">
|
||||
<el-form-item label="收件人" prop="name">
|
||||
@@ -18,7 +18,7 @@
|
||||
<el-input v-model="formData.mobile" placeholder="请输入收件人手机号" style="width: 600px"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="地址别名">
|
||||
<el-input v-model="formData.alias" length :maxlength="4" placeholder="请输入地址别名,例如公司" style="width: 600px">
|
||||
<el-input v-model="formData.alias" :maxlength="5" show-word-limit placeholder="请输入地址别名,例如公司" style="width: 600px">
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="默认地址">
|
||||
|
||||
@@ -1,78 +1,85 @@
|
||||
<template>
|
||||
<div class="wrapper">
|
||||
<UserCenterLayout title="我的售后" :tabs="['我的售后']">
|
||||
<UserCenterLayout
|
||||
:tabs="changeWay.map((item) => item.name)"
|
||||
:active-tab="activeTab"
|
||||
@tab-change="change"
|
||||
>
|
||||
<template #extra>
|
||||
<el-input
|
||||
class="width_300"
|
||||
|
||||
|
||||
v-model="params.keywords"
|
||||
@keyup.enter="getList"
|
||||
placeholder="请输入订单号搜索"
|
||||
/>
|
||||
<div class="order-search">
|
||||
<el-input
|
||||
v-model="params.keywords"
|
||||
size="large"
|
||||
@keyup.enter="getList"
|
||||
placeholder="输入订单号搜索"
|
||||
/>
|
||||
<el-button type="primary" @click="getList">搜索</el-button>
|
||||
</div>
|
||||
</template>
|
||||
<!-- 列表 -->
|
||||
<empty v-if="orderList.length === 0"/>
|
||||
<div class="order-content" v-else>
|
||||
<template v-for="(order, onderIndex) in orderList" :key="order.sn || onderIndex">
|
||||
<div class="order-list">
|
||||
<div class="order-header">
|
||||
<div>
|
||||
<div v-if="order.serviceStatus">{{ filterOrderStatus(order.serviceStatus) }}</div>
|
||||
<div>
|
||||
售后单号:{{ order.sn }} {{ order.createTime }}
|
||||
{{ $filters.secrecyMobile( order.memberName ) }}
|
||||
<div class="order-cols">
|
||||
<span>订单详情</span>
|
||||
<span>金额</span>
|
||||
<span>操作</span>
|
||||
</div>
|
||||
<div
|
||||
class="order-list"
|
||||
v-for="(order, orderIndex) in orderList"
|
||||
:key="order.sn || orderIndex"
|
||||
>
|
||||
<div class="order-header">
|
||||
<div class="order-sn">
|
||||
{{ order.createTime }}<span>售后单号 {{ order.sn }}</span><span class="order-store" @click="shopPage(order.storeId)">{{ order.storeName }}</span>
|
||||
</div>
|
||||
<div class="order-status">{{ filterOrderStatus(order.serviceStatus) }}</div>
|
||||
</div>
|
||||
<div class="order-body">
|
||||
<div class="col-detail">
|
||||
<div class="goods-item">
|
||||
<div class="goods-thumb">
|
||||
<img
|
||||
@click="goodsDetail(order.skuId, order.goodsId)"
|
||||
class="hover-color"
|
||||
:src="order.goodsImage"
|
||||
alt=""
|
||||
@error="$event.target.style.visibility = 'hidden'"
|
||||
/>
|
||||
</div>
|
||||
<div class="goods-info">
|
||||
<div class="goods-name hover-color" @click="goodsDetail(order.skuId, order.goodsId)">{{ order.goodsName }}</div>
|
||||
<div class="goods-num">共{{ order.num }}件</div>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<span>申请退款金额:<span class="global_color">{{ $filters.unitPrice(order.applyRefundPrice, "¥") }}</span></span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="order-body">
|
||||
<div class="goods-list">
|
||||
<img @click="goodsDetail(order.skuId, order.goodsId)" class="hover-color" :src="order.goodsImage" alt=""/>
|
||||
|
||||
<div>
|
||||
<div class="hover-color" @click="goodsDetail(order.skuId, order.goodsId)">{{ order.goodsName }}</div>
|
||||
<div class="mt_10"> x {{ order.num }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<span @click="shopPage(order.storeId)">{{ order.storeName }}</span>
|
||||
</div>
|
||||
<div class="order-actions">
|
||||
<!-- 订单基础操作 -->
|
||||
<el-button
|
||||
@click="goDetail(order.sn)"
|
||||
type="warning"
|
||||
size="small"
|
||||
class="after-sale-action-btn"
|
||||
>售后详情</el-button>
|
||||
<el-button
|
||||
@click="openModal(order)"
|
||||
v-if="order.serviceStatus == 'PASS' && order.serviceType != 'RETURN_MONEY'"
|
||||
size="small"
|
||||
class="after-sale-action-btn submit-logistics-btn"
|
||||
>提交物流</el-button>
|
||||
<el-button
|
||||
@click="cancel(order.sn)"
|
||||
type="danger"
|
||||
v-if="order.afterSaleAllowOperationVO.cancel"
|
||||
size="small"
|
||||
class="after-sale-action-btn"
|
||||
>取消售后</el-button>
|
||||
</div>
|
||||
<div class="col-amount">
|
||||
<div class="order-amount">{{ $filters.unitPrice(order.applyRefundPrice, "¥") }}</div>
|
||||
</div>
|
||||
<div class="col-ops">
|
||||
<button
|
||||
v-if="order.serviceStatus == 'PASS' && order.serviceType != 'RETURN_MONEY'"
|
||||
type="button"
|
||||
class="op-btn"
|
||||
@click="openModal(order)"
|
||||
>提交物流</button>
|
||||
<button type="button" class="text-link" @click="goDetail(order.sn)">售后详情</button>
|
||||
<button
|
||||
v-if="order.afterSaleAllowOperationVO && order.afterSaleAllowOperationVO.cancel"
|
||||
type="button"
|
||||
class="text-link"
|
||||
@click="cancel(order.sn)"
|
||||
>取消售后</button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
<el-skeleton size="large" fix v-if="spinShow"></el-skeleton>
|
||||
</div>
|
||||
<!-- 分页 -->
|
||||
<div class="page-size">
|
||||
<el-pagination v-model:current-page="params.pageNumber" v-model:page-size="params.pageSize"
|
||||
:total="total" @current-change="changePageNum"
|
||||
@size-change="changePageSize" layout="sizes, prev, pager, next, jumper"></el-pagination>
|
||||
:total="total" :page-sizes="[20, 50, 100]" @current-change="changePageNum"
|
||||
@size-change="changePageSize" layout="total, sizes, prev, pager, next, jumper"></el-pagination>
|
||||
</div>
|
||||
</UserCenterLayout>
|
||||
<el-dialog v-model="logisticsShow" width="530">
|
||||
@@ -135,7 +142,8 @@ export default {
|
||||
orderList: [], // 订单列表
|
||||
params: { // 请求参数
|
||||
pageNumber: 1,
|
||||
pageSize: 10,
|
||||
pageSize: 20,
|
||||
keywords: '',
|
||||
sn: '',
|
||||
sort: 'createTime',
|
||||
order: 'desc'
|
||||
@@ -158,7 +166,14 @@ export default {
|
||||
logisticsNo: [{required: true, message: '请填写物流编号'}],
|
||||
mDeliverTime: [{required: true, message: '请选择发货时间'}]
|
||||
},
|
||||
submitLoading: false // 提交加载状态
|
||||
submitLoading: false, // 提交加载状态
|
||||
changeWay: [
|
||||
{ name: '全部', status: '' },
|
||||
{ name: '申请中', status: 'APPLY' },
|
||||
{ name: '通过', status: 'PASS' },
|
||||
{ name: '完成售后', status: 'COMPLETE' },
|
||||
],
|
||||
activeTab: 0,
|
||||
};
|
||||
},
|
||||
mounted() {
|
||||
@@ -203,6 +218,17 @@ export default {
|
||||
});
|
||||
window.open(routeUrl.href, '_blank');
|
||||
},
|
||||
change(index) {
|
||||
this.activeTab = index
|
||||
this.params.pageNumber = 1
|
||||
const current = this.changeWay[index]
|
||||
if (!current || !current.status) {
|
||||
delete this.params.serviceStatus
|
||||
} else {
|
||||
this.params.serviceStatus = current.status
|
||||
}
|
||||
this.getList()
|
||||
},
|
||||
getList() { // 获取售后列表
|
||||
this.spinShow = true;
|
||||
let params = JSON.parse(JSON.stringify(this.params))
|
||||
@@ -227,7 +253,7 @@ export default {
|
||||
const ob = this.afterSaleStatusList.filter(e => {
|
||||
return e.status === status
|
||||
});
|
||||
return ob[0].name
|
||||
return ob && ob[0] ? ob[0].name : status
|
||||
},
|
||||
// 获取物流公司列表
|
||||
getCompany() {
|
||||
@@ -275,109 +301,220 @@ export default {
|
||||
margin-bottom: 40px;
|
||||
}
|
||||
|
||||
.box {
|
||||
overflow: hidden;
|
||||
.order-search {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
width: 330px;
|
||||
|
||||
:deep(.el-input) {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
:deep(.el-button) {
|
||||
margin-left: 8px;
|
||||
}
|
||||
}
|
||||
|
||||
.order-content {
|
||||
--order-cols: minmax(0, 1fr) 120px 120px;
|
||||
--order-gap: 12px;
|
||||
padding-top: 14px;
|
||||
}
|
||||
|
||||
.page-size {
|
||||
margin: 15px 0px;
|
||||
margin: 15px 0;
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
align-items: center;
|
||||
|
||||
:deep(.el-pagination) {
|
||||
justify-content: flex-end;
|
||||
}
|
||||
}
|
||||
|
||||
.order-cols {
|
||||
display: grid;
|
||||
grid-template-columns: var(--order-cols);
|
||||
column-gap: var(--order-gap);
|
||||
align-items: center;
|
||||
padding: 0 16px 10px;
|
||||
color: #999;
|
||||
font-size: 13px;
|
||||
|
||||
span:first-child {
|
||||
padding-left: 72px;
|
||||
}
|
||||
|
||||
span:nth-child(n + 2) {
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
|
||||
/** 订单列表 */
|
||||
.order-list {
|
||||
border: 1px solid #ddd;
|
||||
border-radius: 3px;
|
||||
margin-bottom: 10px;
|
||||
|
||||
&:hover {
|
||||
.del-btn {
|
||||
visibility: visible;
|
||||
}
|
||||
}
|
||||
|
||||
.del-btn {
|
||||
visibility: hidden;
|
||||
}
|
||||
border: 1px solid #eee;
|
||||
border-radius: 8px;
|
||||
margin-bottom: 12px;
|
||||
background: #fff;
|
||||
overflow: hidden;
|
||||
|
||||
.order-header {
|
||||
display: grid;
|
||||
grid-template-columns: var(--order-cols);
|
||||
column-gap: var(--order-gap);
|
||||
align-items: center;
|
||||
padding: 10px 16px;
|
||||
background: #f7f7f7;
|
||||
border-bottom: 1px solid #f0f0f0;
|
||||
}
|
||||
|
||||
.order-sn {
|
||||
grid-column: 1 / 3;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 10px;
|
||||
justify-content: space-between;
|
||||
border-bottom: 1px solid #ddd;
|
||||
min-width: 0;
|
||||
font-size: 14px;
|
||||
color: #171A26;
|
||||
line-height: 1.5;
|
||||
|
||||
> div:nth-child(1) > div:nth-child(2) {
|
||||
font-size: 12px;
|
||||
color: #999;
|
||||
margin-top: 3px;
|
||||
span {
|
||||
margin-left: 16px;
|
||||
}
|
||||
}
|
||||
|
||||
.order-store {
|
||||
min-width: 0;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
color: #438cde;
|
||||
cursor: pointer;
|
||||
|
||||
&:hover {
|
||||
color: $theme_color;
|
||||
}
|
||||
}
|
||||
|
||||
.order-status {
|
||||
grid-column: 3;
|
||||
min-width: 0;
|
||||
text-align: center;
|
||||
font-size: 14px;
|
||||
color: #666;
|
||||
line-height: 1.4;
|
||||
}
|
||||
|
||||
.order-body {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
color: #999;
|
||||
padding: 10px;
|
||||
display: grid;
|
||||
grid-template-columns: var(--order-cols);
|
||||
column-gap: var(--order-gap);
|
||||
align-items: center;
|
||||
padding: 14px 16px;
|
||||
}
|
||||
|
||||
> div:nth-child(2) {
|
||||
width: 150px;
|
||||
text-align: center;
|
||||
.goods-item {
|
||||
display: grid;
|
||||
grid-template-columns: 60px minmax(0, 1fr);
|
||||
column-gap: 12px;
|
||||
align-items: start;
|
||||
width: 100%;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
span {
|
||||
color: #438cde;
|
||||
cursor: pointer;
|
||||
.goods-thumb {
|
||||
width: 60px;
|
||||
height: 60px;
|
||||
border: 1px solid #f0f0f0;
|
||||
overflow: hidden;
|
||||
background: #f5f5f5;
|
||||
|
||||
&:hover {
|
||||
color: $theme_color;
|
||||
}
|
||||
}
|
||||
|
||||
.el-icon {
|
||||
color: #ff8f23;
|
||||
cursor: pointer;
|
||||
|
||||
&:hover {
|
||||
color: $theme_color;
|
||||
}
|
||||
}
|
||||
img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: cover;
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
|
||||
.order-actions {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 8px;
|
||||
min-width: 100px;
|
||||
.goods-info {
|
||||
min-width: 0;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.after-sale-action-btn {
|
||||
display: block;
|
||||
margin: 0;
|
||||
min-width: 88px;
|
||||
}
|
||||
.goods-name {
|
||||
max-width: 100%;
|
||||
color: #333;
|
||||
font-size: 16px;
|
||||
line-height: 22px;
|
||||
max-height: 44px;
|
||||
display: -webkit-box;
|
||||
-webkit-box-orient: vertical;
|
||||
-webkit-line-clamp: 2;
|
||||
overflow: hidden;
|
||||
word-break: break-all;
|
||||
}
|
||||
|
||||
:deep(.submit-logistics-btn) {
|
||||
background-color: #ff9900 !important;
|
||||
border-color: #ff9900 !important;
|
||||
color: #fff !important;
|
||||
.goods-num {
|
||||
margin-top: 6px;
|
||||
color: #999;
|
||||
font-size: 14px;
|
||||
line-height: 1.4;
|
||||
}
|
||||
|
||||
&:hover,
|
||||
&:focus {
|
||||
background-color: #e68a00 !important;
|
||||
border-color: #e68a00 !important;
|
||||
color: #fff !important;
|
||||
}
|
||||
}
|
||||
.col-amount,
|
||||
.col-ops {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.order-amount {
|
||||
color: #333;
|
||||
font-size: 16px;
|
||||
font-weight: 600;
|
||||
line-height: 1.4;
|
||||
}
|
||||
|
||||
.col-ops {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.op-btn {
|
||||
min-width: 96px;
|
||||
height: 32px;
|
||||
padding: 0 12px;
|
||||
border: 1px solid $theme_color;
|
||||
border-radius: 4px;
|
||||
background: $theme_color;
|
||||
color: #fff;
|
||||
font-family: inherit;
|
||||
font-size: 14px;
|
||||
line-height: 30px;
|
||||
cursor: pointer;
|
||||
|
||||
&:hover {
|
||||
opacity: 0.9;
|
||||
}
|
||||
}
|
||||
|
||||
.text-link {
|
||||
border: none;
|
||||
background: none;
|
||||
padding: 0;
|
||||
color: #171A26;
|
||||
font-family: inherit;
|
||||
font-size: 14px;
|
||||
line-height: 22px;
|
||||
cursor: pointer;
|
||||
|
||||
&:hover {
|
||||
color: $theme_color;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.goods-list {
|
||||
// width: 500px;
|
||||
.modal-goods {
|
||||
display: flex;
|
||||
padding: 5px;
|
||||
margin-bottom: 10px;
|
||||
|
||||
img {
|
||||
@@ -390,8 +527,4 @@ export default {
|
||||
flex: 1;
|
||||
}
|
||||
}
|
||||
|
||||
.modal-goods {
|
||||
padding: 5px;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -1,84 +1,102 @@
|
||||
<template>
|
||||
<div class="order-detail">
|
||||
<UserCenterLayout title="售后详情" :tabs="['售后详情']">
|
||||
<!-- 操作按钮 -->
|
||||
<el-card class="mb_10" shadow="never" v-if="(afterSale.serviceStatus == 'PASS' &&
|
||||
afterSale.serviceType != 'RETURN_MONEY') || (afterSale.afterSaleAllowOperationVO && afterSale.afterSaleAllowOperationVO.cancel)">
|
||||
<el-button
|
||||
@click="openModal"
|
||||
v-if="afterSale.serviceStatus == 'PASS' && afterSale.serviceType != 'RETURN_MONEY'"
|
||||
size="small"
|
||||
class="submit-logistics-btn"
|
||||
>提交物流</el-button>
|
||||
<el-button type="danger" @click="cancel(afterSale.sn)" v-if="afterSale.afterSaleAllowOperationVO && afterSale.afterSaleAllowOperationVO.cancel" size="small">取消售后</el-button>
|
||||
</el-card>
|
||||
<div class="order-card">
|
||||
<h3>{{afterSale.serviceName}}</h3>
|
||||
<p class="global_color fontsize_18">{{ afterSale.orderStatusValue }}</p>
|
||||
<p class="order-meta">
|
||||
<span>售后单号:{{ afterSale.sn }} 订单号:{{ afterSale.orderSn }}</span>
|
||||
<span class="order-meta-time">创建时间:{{ afterSale.createTime }}</span>
|
||||
</p>
|
||||
<div class="service-after">
|
||||
<div>
|
||||
本次售后服务由<span>{{afterSale.storeName}}</span>为您提供
|
||||
<UserCenterLayout>
|
||||
<div class="order-card status-card" v-if="afterSale.sn">
|
||||
<div class="status-head">
|
||||
<div class="status-main">
|
||||
<p class="status-text">{{ afterSale.serviceName }}</p>
|
||||
<p class="status-sn">
|
||||
售后单号:{{ afterSale.sn }}
|
||||
<span>订单号:{{ afterSale.orderSn }}</span>
|
||||
</p>
|
||||
</div>
|
||||
<div class="service-after-goods">
|
||||
<img :src="afterSale.goodsImage" alt="" width="60" height="60">
|
||||
<span>{{afterSale.goodsName}}</span>
|
||||
<div class="status-side">
|
||||
<div class="operation-time">创建时间:{{ afterSale.createTime }}</div>
|
||||
<div class="status-actions" v-if="canSubmitLogistics || canCancel">
|
||||
<button v-if="canSubmitLogistics" type="button" class="op-btn" @click="openModal">提交物流</button>
|
||||
<button v-if="canCancel" type="button" class="text-link" @click="cancel(afterSale.sn)">取消售后</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="goods-row">
|
||||
<img :src="afterSale.goodsImage" alt="" @error="$event.target.style.visibility = 'hidden'">
|
||||
<div class="goods-info">
|
||||
<div class="goods-name">{{ afterSale.goodsName }}</div>
|
||||
<div class="store-line">
|
||||
本次售后服务由<span @click="shopPage(afterSale.storeId)">{{ afterSale.storeName }}</span>为您提供
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="order-card">
|
||||
<div class="order-card" v-if="logList.length">
|
||||
<h3>售后进程</h3>
|
||||
<el-steps class="progress" :current="logList.length" direction="vertical">
|
||||
<el-step :content="'操作人:'+ log.operatorName + ' ' + log.createTime"
|
||||
<el-steps
|
||||
class="progress"
|
||||
:active="logList.length - 1"
|
||||
direction="vertical"
|
||||
>
|
||||
<el-step
|
||||
:title="log.message"
|
||||
:description="logDesc(log)"
|
||||
v-for="(log, index) in logList"
|
||||
:key="index"
|
||||
></el-step>
|
||||
</el-steps>
|
||||
</div>
|
||||
<div class="order-card">
|
||||
<h3 class="mb_10">服务单信息</h3>
|
||||
<table border="1" cellpadding='0' cellspacing="0">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>退款方式</td><td>{{afterSale.refundWay == 'ORIGINAL' ? '原路退回' : '账号退款'}}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>申请退款金额</td><td>{{ $filters.unitPrice(afterSale.applyRefundPrice, '¥') }}</td>
|
||||
</tr>
|
||||
<tr v-if="afterSale.actualRefundPrice">
|
||||
<td>实际退款金额</td><td>{{ $filters.unitPrice(afterSale.actualRefundPrice, '¥') }}</td>
|
||||
</tr>
|
||||
<h3>服务单信息</h3>
|
||||
<div class="info-list">
|
||||
<div class="info-row">
|
||||
<span class="label">退款方式</span>
|
||||
<span>{{ afterSale.refundWay == 'ORIGINAL' ? '原路退回' : '账号退款' }}</span>
|
||||
</div>
|
||||
<div class="info-row">
|
||||
<span class="label">申请退款金额</span>
|
||||
<span>{{ $filters.unitPrice(afterSale.applyRefundPrice, '¥') }}</span>
|
||||
</div>
|
||||
<div class="info-row" v-if="afterSale.actualRefundPrice">
|
||||
<span class="label">实际退款金额</span>
|
||||
<span>{{ $filters.unitPrice(afterSale.actualRefundPrice, '¥') }}</span>
|
||||
</div>
|
||||
<template v-if="afterSale.refundWay === 'OFFLINE'">
|
||||
<tr>
|
||||
<td>退款开户行</td><td>{{afterSale.bankDepositName}}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>退款开户名</td><td>{{afterSale.bankAccountName}}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>退款卡号</td><td>{{afterSale.bankAccountNumber}}</td>
|
||||
</tr>
|
||||
<div class="info-row">
|
||||
<span class="label">退款开户行</span>
|
||||
<span>{{ afterSale.bankDepositName }}</span>
|
||||
</div>
|
||||
<div class="info-row">
|
||||
<span class="label">退款开户名</span>
|
||||
<span>{{ afterSale.bankAccountName }}</span>
|
||||
</div>
|
||||
<div class="info-row">
|
||||
<span class="label">退款卡号</span>
|
||||
<span>{{ afterSale.bankAccountNumber }}</span>
|
||||
</div>
|
||||
</template>
|
||||
<tr>
|
||||
<td>商品处理方式</td><td>{{afterSale.serviceType == 'RETURN_MONEY' ? '退款' : '退货'}}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>退款原因</td><td>{{afterSale.reasonName}}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>问题描述</td><td>{{afterSale.problemDesc}}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<div class="info-row">
|
||||
<span class="label">商品处理方式</span>
|
||||
<span>{{ afterSale.serviceType == 'RETURN_MONEY' ? '退款' : '退货' }}</span>
|
||||
</div>
|
||||
<div class="info-row">
|
||||
<span class="label">退款原因</span>
|
||||
<span>{{ afterSale.reasonName }}</span>
|
||||
</div>
|
||||
<div class="info-row">
|
||||
<span class="label">问题描述</span>
|
||||
<span>{{ afterSale.problemDesc }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="order-card" v-if="afterSale.afterSaleImage">
|
||||
<h3 class="mb_10">图片信息</h3>
|
||||
<div v-for="img in afterSale.afterSaleImage.split(',')" :key="img">
|
||||
<img :src="img" width="200" height="200" @click="perviewImg(img)" class="hover-pointer" alt="">
|
||||
<h3>图片信息</h3>
|
||||
<div class="image-list">
|
||||
<img
|
||||
v-for="img in afterSale.afterSaleImage.split(',')"
|
||||
:key="img"
|
||||
:src="img"
|
||||
@click="perviewImg(img)"
|
||||
class="hover-pointer"
|
||||
alt=""
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
<el-dialog v-model="logisticsShow" width="530">
|
||||
@@ -144,6 +162,14 @@ export default {
|
||||
submitLoading: false // 提交加载状态
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
canSubmitLogistics () {
|
||||
return this.afterSale.serviceStatus == 'PASS' && this.afterSale.serviceType != 'RETURN_MONEY'
|
||||
},
|
||||
canCancel () {
|
||||
return this.afterSale.afterSaleAllowOperationVO && this.afterSale.afterSaleAllowOperationVO.cancel
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
getDetail () { // 售后详情
|
||||
afterSaleDetail(this.$route.query.sn).then(res => {
|
||||
@@ -174,9 +200,23 @@ export default {
|
||||
},
|
||||
getLog () { // 获取售后日志
|
||||
afterSaleLog(this.$route.query.sn).then(res => {
|
||||
this.logList = res.result;
|
||||
this.logList = (res.result || []).slice().sort((a, b) => {
|
||||
return new Date(a.createTime).getTime() - new Date(b.createTime).getTime()
|
||||
})
|
||||
})
|
||||
},
|
||||
logDesc (log) {
|
||||
const operator = log.operatorName ? `操作人:${log.operatorName}` : ''
|
||||
return [operator, log.createTime].filter(Boolean).join(' ')
|
||||
},
|
||||
shopPage (id) {
|
||||
if (!id) return
|
||||
const routeUrl = this.$router.resolve({
|
||||
path: '/merchant',
|
||||
query: { id }
|
||||
})
|
||||
window.open(routeUrl.href, '_blank')
|
||||
},
|
||||
filterOrderStatus (status) { // 获取订单状态中文
|
||||
const ob = this.afterSaleStatusList.filter(e => { return e.status === status });
|
||||
if (ob.length) return ob[0].name
|
||||
@@ -240,97 +280,235 @@ export default {
|
||||
};
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.order-detail {
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.order-card {
|
||||
padding: 10px;
|
||||
padding-bottom: 10px;
|
||||
margin-bottom: 10px;
|
||||
border-bottom: 1px solid #e8eaec;
|
||||
position: relative;
|
||||
.global_color {
|
||||
padding: 4px 0 16px;
|
||||
margin-bottom: 8px;
|
||||
border-bottom: 1px solid #f0f0f0;
|
||||
|
||||
h3 {
|
||||
margin: 0 0 12px;
|
||||
font-size: 15px;
|
||||
font-weight: 600;
|
||||
color: #333;
|
||||
line-height: 1.4;
|
||||
}
|
||||
|
||||
&:last-child {
|
||||
border-bottom: none;
|
||||
}
|
||||
}
|
||||
|
||||
.status-card {
|
||||
padding-top: 8px;
|
||||
}
|
||||
|
||||
.status-head {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
justify-content: space-between;
|
||||
gap: 16px;
|
||||
}
|
||||
|
||||
.status-text {
|
||||
margin: 0;
|
||||
color: $theme_color;
|
||||
font-size: 18px;
|
||||
font-weight: 600;
|
||||
line-height: 1.4;
|
||||
}
|
||||
|
||||
.status-sn {
|
||||
margin: 6px 0 0;
|
||||
color: #171A26;
|
||||
font-size: 14px;
|
||||
line-height: 22px;
|
||||
|
||||
span {
|
||||
margin-left: 16px;
|
||||
}
|
||||
}
|
||||
|
||||
.status-side {
|
||||
flex-shrink: 0;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.operation-time {
|
||||
color: #171A26;
|
||||
font-size: 14px;
|
||||
line-height: 22px;
|
||||
}
|
||||
|
||||
.status-actions {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
align-items: center;
|
||||
flex-wrap: wrap;
|
||||
gap: 12px;
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
.goods-row {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 12px;
|
||||
margin-top: 16px;
|
||||
padding: 12px;
|
||||
background: #fafafa;
|
||||
border-radius: 8px;
|
||||
|
||||
img {
|
||||
width: 64px;
|
||||
height: 64px;
|
||||
object-fit: cover;
|
||||
border: 1px solid #f0f0f0;
|
||||
background: #f5f5f5;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.goods-info {
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.goods-name {
|
||||
color: #333;
|
||||
font-size: 16px;
|
||||
line-height: 22px;
|
||||
word-break: break-all;
|
||||
}
|
||||
|
||||
.store-line {
|
||||
margin-top: 6px;
|
||||
color: #666;
|
||||
font-size: 14px;
|
||||
line-height: 22px;
|
||||
|
||||
span {
|
||||
margin: 0 4px;
|
||||
color: #438cde;
|
||||
cursor: pointer;
|
||||
|
||||
&:hover {
|
||||
color: $theme_color;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.progress {
|
||||
max-width: 640px;
|
||||
margin: 4px 0 0;
|
||||
|
||||
:deep(.el-step.is-vertical) {
|
||||
padding-bottom: 20px;
|
||||
}
|
||||
|
||||
:deep(.el-step.is-vertical:last-child) {
|
||||
padding-bottom: 0;
|
||||
}
|
||||
|
||||
:deep(.el-step__head.is-finish) {
|
||||
color: #c0c4cc;
|
||||
border-color: #c0c4cc;
|
||||
}
|
||||
|
||||
:deep(.el-step__title.is-finish),
|
||||
:deep(.el-step__description.is-finish) {
|
||||
color: #909399;
|
||||
font-weight: 400;
|
||||
}
|
||||
|
||||
:deep(.el-step__head.is-process) {
|
||||
color: $theme_color;
|
||||
border-color: $theme_color;
|
||||
}
|
||||
|
||||
:deep(.el-step__title.is-process),
|
||||
:deep(.el-step__description.is-process) {
|
||||
color: $theme_color;
|
||||
}
|
||||
p {
|
||||
color: #999;
|
||||
margin: 3px;
|
||||
}
|
||||
|
||||
.info-list {
|
||||
border: 1px solid #f0f0f0;
|
||||
border-radius: 8px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.info-row {
|
||||
display: grid;
|
||||
grid-template-columns: 140px minmax(0, 1fr);
|
||||
min-height: 44px;
|
||||
border-top: 1px solid #f0f0f0;
|
||||
font-size: 14px;
|
||||
line-height: 22px;
|
||||
|
||||
&:first-child {
|
||||
border-top: none;
|
||||
}
|
||||
.order-meta {
|
||||
|
||||
span {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
gap: 16px;
|
||||
padding: 10px 16px;
|
||||
color: #171A26;
|
||||
}
|
||||
|
||||
.order-meta-time {
|
||||
flex-shrink: 0;
|
||||
white-space: nowrap;
|
||||
}
|
||||
}
|
||||
h3 {
|
||||
font-weight: normal;
|
||||
font-size: 16px;
|
||||
}
|
||||
&:last-child{
|
||||
border: none;
|
||||
.label {
|
||||
background: #fafafa;
|
||||
color: #666;
|
||||
}
|
||||
}
|
||||
.service-after {
|
||||
border: 1px solid #eee;
|
||||
|
||||
.image-list {
|
||||
display: flex;
|
||||
height: 80px;
|
||||
padding: 10px;
|
||||
>div:nth-child(1) {
|
||||
width: 400px;
|
||||
font-size: 15px;
|
||||
font-weight: bold;
|
||||
text-align: center;
|
||||
line-height: 60px;
|
||||
span{color: $theme_color;}
|
||||
border-right: 1px solid #eee;
|
||||
}
|
||||
>div:nth-child(2){
|
||||
padding-left: 15px;
|
||||
}
|
||||
.service-after-goods {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
flex-wrap: wrap;
|
||||
gap: 12px;
|
||||
|
||||
img {
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
span {
|
||||
color: #999;
|
||||
}
|
||||
}
|
||||
}
|
||||
/** 售后进度条 */
|
||||
.progress {
|
||||
margin: 15px 0;
|
||||
}
|
||||
table{
|
||||
border-color: #eee;
|
||||
width: 100%;
|
||||
color: #999;
|
||||
tr{
|
||||
td:nth-child(1){
|
||||
width: 200px;
|
||||
}
|
||||
}
|
||||
td{
|
||||
padding: 5px;
|
||||
img {
|
||||
width: 120px;
|
||||
height: 120px;
|
||||
object-fit: cover;
|
||||
border: 1px solid #f0f0f0;
|
||||
border-radius: 6px;
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
|
||||
:deep(.submit-logistics-btn) {
|
||||
background-color: #ff9900 !important;
|
||||
border-color: #ff9900 !important;
|
||||
color: #fff !important;
|
||||
.op-btn {
|
||||
min-width: 96px;
|
||||
height: 32px;
|
||||
padding: 0 12px;
|
||||
border: 1px solid $theme_color;
|
||||
border-radius: 4px;
|
||||
background: $theme_color;
|
||||
color: #fff;
|
||||
font-family: inherit;
|
||||
font-size: 14px;
|
||||
line-height: 30px;
|
||||
cursor: pointer;
|
||||
|
||||
&:hover,
|
||||
&:focus {
|
||||
background-color: #e68a00 !important;
|
||||
border-color: #e68a00 !important;
|
||||
color: #fff !important;
|
||||
&:hover {
|
||||
opacity: 0.9;
|
||||
}
|
||||
}
|
||||
|
||||
.text-link {
|
||||
border: none;
|
||||
background: none;
|
||||
padding: 0;
|
||||
color: #171A26;
|
||||
font-family: inherit;
|
||||
font-size: 14px;
|
||||
line-height: 22px;
|
||||
cursor: pointer;
|
||||
|
||||
&:hover {
|
||||
color: $theme_color;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<div class="apply-after-sale">
|
||||
<UserCenterLayout title="申请售后" :tabs="['申请售后']">
|
||||
<UserCenterLayout>
|
||||
<el-table :data="goodsData" border>
|
||||
<el-table-column label="商品名称">
|
||||
<template #default="{ row }">
|
||||
@@ -94,7 +94,7 @@
|
||||
<el-button type="primary" @click="apply">提交申请</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<el-dialog title="View Image" v-model="visible">
|
||||
<el-dialog title="图片预览" v-model="visible">
|
||||
<img :src="previewImage" v-if="visible" style="width: 100%">
|
||||
</el-dialog>
|
||||
</div>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
|
||||
<template>
|
||||
<div class="add-eval">
|
||||
<UserCenterLayout title="商品投诉" :tabs="['商品投诉']">
|
||||
<UserCenterLayout>
|
||||
<div class="title">
|
||||
<p>
|
||||
<span class="color999">订单号:</span><span>{{$route.query.sn}}</span>
|
||||
@@ -55,7 +55,7 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<el-dialog title="View Image" v-model="visible">
|
||||
<el-dialog title="图片预览" v-model="visible">
|
||||
<img :src="previewImage" v-if="visible" style="width: 100%">
|
||||
</el-dialog>
|
||||
</UserCenterLayout>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<div class="wrapper">
|
||||
<UserCenterLayout title="收货地址" :tabs="['收货地址']" more-text="添加新地址" more-to="/home/addAddress">
|
||||
<UserCenterLayout>
|
||||
<template #extra>
|
||||
<el-button type="primary" @click="add">添加新地址</el-button>
|
||||
</template>
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
|
||||
<UserCenterLayout
|
||||
v-if="!homePage"
|
||||
title="我的订单"
|
||||
:tabs="changeWay"
|
||||
:active-tab="activeOrderTab"
|
||||
@tab-change="change"
|
||||
@@ -13,6 +12,7 @@
|
||||
<div class="order-search">
|
||||
<el-input
|
||||
v-model="params.keywords"
|
||||
size="large"
|
||||
@keyup.enter="getList"
|
||||
placeholder="输入订单号搜索"
|
||||
/>
|
||||
@@ -23,68 +23,67 @@
|
||||
<!-- 订单列表 -->
|
||||
<empty v-if="orderList.length === 0" />
|
||||
<div class="order-content" v-else>
|
||||
<div class="order-cols">
|
||||
<span>订单详情</span>
|
||||
<span>金额</span>
|
||||
<span>操作</span>
|
||||
</div>
|
||||
<div
|
||||
class="order-list"
|
||||
v-for="(order, onderIndex) in orderList"
|
||||
:key="onderIndex"
|
||||
>
|
||||
<div class="order-header">
|
||||
<div class="order-header-main">
|
||||
<div class="order-status">{{ order.isAfterSale ? filterAfterSaleStatus(order.serviceStatus) : filterOrderStatus(order.orderStatus) }}</div>
|
||||
<div class="order-sn" v-if="order.isAfterSale">
|
||||
售后单号:{{ order.serviceSn }}<span>{{ order.createTime }}</span>
|
||||
</div>
|
||||
<div class="order-sn" v-else>
|
||||
订单号:{{ order.sn }}<span>{{ order.createTime }}</span>
|
||||
</div>
|
||||
<div class="order-sn" v-if="order.isAfterSale">
|
||||
{{ order.createTime }}<span>售后单号 {{ order.serviceSn }}</span><span class="order-store" @click="shopPage(order.storeId)">{{ order.storeName }}</span>
|
||||
</div>
|
||||
<div class="order-header-side">
|
||||
<el-button v-if="!order.isAfterSale && order.orderStatus === 'COMPLETED'" class="del-btn" link @click="delOrder(order.sn)">
|
||||
<el-icon><Delete /></el-icon>
|
||||
</el-button>
|
||||
<span class="order-amount">{{ $filters.unitPrice(order.flowPrice, "¥") }}</span>
|
||||
<div class="order-sn" v-else>
|
||||
{{ order.createTime }}<span>订单号 {{ order.sn }}</span><span class="order-store" @click="shopPage(order.storeId)">{{ order.storeName }}</span>
|
||||
</div>
|
||||
<div class="order-status">{{ order.isAfterSale ? filterAfterSaleStatus(order.serviceStatus) : filterOrderStatus(order.orderStatus) }}</div>
|
||||
</div>
|
||||
<div class="order-body">
|
||||
<div class="goods-list">
|
||||
<div class="col-detail">
|
||||
<div
|
||||
v-for="(goods, goodsIndex) in order.orderItems"
|
||||
:key="goodsIndex"
|
||||
class="goods-item"
|
||||
>
|
||||
<img
|
||||
@click="goodsDetail(goods.skuId, goods.goodsId)"
|
||||
class="hover-color"
|
||||
:src="goods.image"
|
||||
alt=""
|
||||
/>
|
||||
<div class="goods-thumb">
|
||||
<img
|
||||
@click="goodsDetail(goods.skuId, goods.goodsId)"
|
||||
class="hover-color"
|
||||
:src="goods.image"
|
||||
alt=""
|
||||
@error="$event.target.style.visibility = 'hidden'"
|
||||
/>
|
||||
</div>
|
||||
<div class="goods-info">
|
||||
<div class="goods-name hover-color" @click="goodsDetail(goods.skuId, goods.goodsId)">{{ goods.name }}</div>
|
||||
<div class="goods-meta">
|
||||
<span class="global_color">{{ $filters.unitPrice(goods.goodsPrice, "¥") }}</span>
|
||||
<span class="goods-num">x {{ goods.num }}</span>
|
||||
<div class="goods-num">共{{ goods.num }}件</div>
|
||||
<div class="goods-extra">
|
||||
<span v-if="refundPriceList(goods.isRefund)" class="refund-tag">{{ refundPriceList(goods.isRefund) }}</span>
|
||||
</div>
|
||||
<div class="goods-ops" v-if="goods.commentStatus == 'UNFINISHED' || goods.complainStatus == 'NO_APPLY'">
|
||||
<el-button v-if="goods.commentStatus == 'UNFINISHED'" @click="comment(order.sn, goodsIndex)" size="small" type="success">评价</el-button>
|
||||
<el-button v-if="goods.complainStatus == 'NO_APPLY'" @click="complain(order.sn, goodsIndex)" type="danger" size="small">投诉</el-button>
|
||||
<button v-if="goods.complainStatus == 'NO_APPLY'" type="button" class="sub-btn" @click="complain(order.sn, goodsIndex)">投诉</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<button v-if="canAfterSale(order)" type="button" class="sub-btn" @click="applyAfterSale(order.orderItems)">申请售后</button>
|
||||
</div>
|
||||
<div class="store-name">
|
||||
<span @click="shopPage(order.storeId)">{{ order.storeName }}</span>
|
||||
<div class="col-amount">
|
||||
<div class="order-amount">{{ $filters.unitPrice(order.flowPrice, "¥") }}</div>
|
||||
<div v-if="paymentLabel(order)" class="pay-method">{{ paymentLabel(order) }}</div>
|
||||
</div>
|
||||
<div class="order-actions" v-if="order.isAfterSale">
|
||||
<el-button @click="goAfterSaleDetail(order.serviceSn)" type="warning" size="small">售后详情</el-button>
|
||||
</div>
|
||||
<div class="order-actions" v-else>
|
||||
<el-button @click="orderDetail(order.sn)" type="warning" size="small">订单详情</el-button>
|
||||
<el-button @click="handleCancelOrder(order.sn)" type="danger" v-if="order.allowOperationVO.cancel" size="small">取消订单</el-button>
|
||||
<el-button @click="goPay(order.sn)" size="small" type="success" v-if="order.allowOperationVO.pay">去支付</el-button>
|
||||
<el-button @click="received(order.sn)" size="small" type="primary" v-if="order.allowOperationVO.rog">确认收货</el-button>
|
||||
<el-button v-if="order.orderType !== 'E_COUPON' && order.groupAfterSaleStatus && (order.groupAfterSaleStatus.includes('NOT_APPLIED')|| order.groupAfterSaleStatus.includes('PART_AFTER_SALE'))"
|
||||
@click="applyAfterSale(order.orderItems)" size="small">申请售后</el-button>
|
||||
<div class="col-ops">
|
||||
<template v-if="order.isAfterSale">
|
||||
<button type="button" class="text-link" @click="goAfterSaleDetail(order.serviceSn)">售后详情</button>
|
||||
</template>
|
||||
<template v-else>
|
||||
<button v-if="order.allowOperationVO && order.allowOperationVO.pay" type="button" class="op-btn" @click="goPay(order.sn)">去支付</button>
|
||||
<button v-if="order.allowOperationVO && order.allowOperationVO.rog" type="button" class="op-btn" @click="received(order.sn)">确认收货</button>
|
||||
<button type="button" class="text-link" @click="orderDetail(order.sn)">订单详情</button>
|
||||
<button v-if="order.allowOperationVO && order.allowOperationVO.cancel" type="button" class="text-link" @click="handleCancelOrder(order.sn)">取消订单</button>
|
||||
<button v-if="order.orderStatus === 'COMPLETED'" type="button" class="text-link" @click="delOrder(order.sn)">删除订单</button>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -94,7 +93,7 @@
|
||||
<!-- 分页 -->
|
||||
<div class="page-size">
|
||||
<el-pagination v-model:current-page="params.pageNumber" v-model:page-size="params.pageSize"
|
||||
:total="total" @current-change="changePageNum"
|
||||
:total="total" :page-sizes="[20, 50, 100]" @current-change="changePageNum"
|
||||
@size-change="changePageSize" layout="total, sizes, prev, pager, next, jumper"></el-pagination>
|
||||
</div>
|
||||
</UserCenterLayout>
|
||||
@@ -102,68 +101,67 @@
|
||||
<!-- 个人中心首页订单列表 -->
|
||||
<empty v-if="homePage && orderList.length === 0" />
|
||||
<div class="order-content" v-else-if="homePage">
|
||||
<div class="order-cols">
|
||||
<span>订单详情</span>
|
||||
<span>金额</span>
|
||||
<span>操作</span>
|
||||
</div>
|
||||
<div
|
||||
class="order-list"
|
||||
v-for="(order, onderIndex) in orderList"
|
||||
:key="onderIndex"
|
||||
>
|
||||
<div class="order-header">
|
||||
<div class="order-header-main">
|
||||
<div class="order-status">{{ order.isAfterSale ? filterAfterSaleStatus(order.serviceStatus) : filterOrderStatus(order.orderStatus) }}</div>
|
||||
<div class="order-sn" v-if="order.isAfterSale">
|
||||
售后单号:{{ order.serviceSn }}<span>{{ order.createTime }}</span>
|
||||
</div>
|
||||
<div class="order-sn" v-else>
|
||||
订单号:{{ order.sn }}<span>{{ order.createTime }}</span>
|
||||
</div>
|
||||
<div class="order-sn" v-if="order.isAfterSale">
|
||||
{{ order.createTime }}<span>售后单号 {{ order.serviceSn }}</span><span class="order-store" @click="shopPage(order.storeId)">{{ order.storeName }}</span>
|
||||
</div>
|
||||
<div class="order-header-side">
|
||||
<el-button v-if="!order.isAfterSale && order.orderStatus === 'COMPLETED'" class="del-btn" link @click="delOrder(order.sn)">
|
||||
<el-icon><Delete /></el-icon>
|
||||
</el-button>
|
||||
<span class="order-amount">{{ $filters.unitPrice(order.flowPrice, "¥") }}</span>
|
||||
<div class="order-sn" v-else>
|
||||
{{ order.createTime }}<span>订单号 {{ order.sn }}</span><span class="order-store" @click="shopPage(order.storeId)">{{ order.storeName }}</span>
|
||||
</div>
|
||||
<div class="order-status">{{ order.isAfterSale ? filterAfterSaleStatus(order.serviceStatus) : filterOrderStatus(order.orderStatus) }}</div>
|
||||
</div>
|
||||
<div class="order-body">
|
||||
<div class="goods-list">
|
||||
<div class="col-detail">
|
||||
<div
|
||||
v-for="(goods, goodsIndex) in order.orderItems"
|
||||
:key="goodsIndex"
|
||||
class="goods-item"
|
||||
>
|
||||
<img
|
||||
@click="goodsDetail(goods.skuId, goods.goodsId)"
|
||||
class="hover-color"
|
||||
:src="goods.image"
|
||||
alt=""
|
||||
/>
|
||||
<div class="goods-thumb">
|
||||
<img
|
||||
@click="goodsDetail(goods.skuId, goods.goodsId)"
|
||||
class="hover-color"
|
||||
:src="goods.image"
|
||||
alt=""
|
||||
@error="$event.target.style.visibility = 'hidden'"
|
||||
/>
|
||||
</div>
|
||||
<div class="goods-info">
|
||||
<div class="goods-name hover-color" @click="goodsDetail(goods.skuId, goods.goodsId)">{{ goods.name }}</div>
|
||||
<div class="goods-meta">
|
||||
<span class="global_color">{{ $filters.unitPrice(goods.goodsPrice, "¥") }}</span>
|
||||
<span class="goods-num">x {{ goods.num }}</span>
|
||||
<div class="goods-num">共{{ goods.num }}件</div>
|
||||
<div class="goods-extra">
|
||||
<span v-if="refundPriceList(goods.isRefund)" class="refund-tag">{{ refundPriceList(goods.isRefund) }}</span>
|
||||
</div>
|
||||
<div class="goods-ops" v-if="goods.commentStatus == 'UNFINISHED' || goods.complainStatus == 'NO_APPLY'">
|
||||
<el-button v-if="goods.commentStatus == 'UNFINISHED'" @click="comment(order.sn, goodsIndex)" size="small" type="success">评价</el-button>
|
||||
<el-button v-if="goods.complainStatus == 'NO_APPLY'" @click="complain(order.sn, goodsIndex)" type="danger" size="small">投诉</el-button>
|
||||
<button v-if="goods.complainStatus == 'NO_APPLY'" type="button" class="sub-btn" @click="complain(order.sn, goodsIndex)">投诉</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<button v-if="canAfterSale(order)" type="button" class="sub-btn" @click="applyAfterSale(order.orderItems)">申请售后</button>
|
||||
</div>
|
||||
<div class="store-name">
|
||||
<span @click="shopPage(order.storeId)">{{ order.storeName }}</span>
|
||||
<div class="col-amount">
|
||||
<div class="order-amount">{{ $filters.unitPrice(order.flowPrice, "¥") }}</div>
|
||||
<div v-if="paymentLabel(order)" class="pay-method">{{ paymentLabel(order) }}</div>
|
||||
</div>
|
||||
<div class="order-actions" v-if="order.isAfterSale">
|
||||
<el-button @click="goAfterSaleDetail(order.serviceSn)" type="warning" size="small">售后详情</el-button>
|
||||
</div>
|
||||
<div class="order-actions" v-else>
|
||||
<el-button @click="orderDetail(order.sn)" type="warning" size="small">订单详情</el-button>
|
||||
<el-button @click="handleCancelOrder(order.sn)" type="danger" v-if="order.allowOperationVO.cancel" size="small">取消订单</el-button>
|
||||
<el-button @click="goPay(order.sn)" size="small" type="success" v-if="order.allowOperationVO.pay">去支付</el-button>
|
||||
<el-button @click="received(order.sn)" size="small" type="primary" v-if="order.allowOperationVO.rog">确认收货</el-button>
|
||||
<el-button v-if="order.orderType !== 'E_COUPON' && order.groupAfterSaleStatus && (order.groupAfterSaleStatus.includes('NOT_APPLIED')|| order.groupAfterSaleStatus.includes('PART_AFTER_SALE'))"
|
||||
@click="applyAfterSale(order.orderItems)" size="small">申请售后</el-button>
|
||||
<div class="col-ops">
|
||||
<template v-if="order.isAfterSale">
|
||||
<button type="button" class="text-link" @click="goAfterSaleDetail(order.serviceSn)">售后详情</button>
|
||||
</template>
|
||||
<template v-else>
|
||||
<button v-if="order.allowOperationVO && order.allowOperationVO.pay" type="button" class="op-btn" @click="goPay(order.sn)">去支付</button>
|
||||
<button v-if="order.allowOperationVO && order.allowOperationVO.rog" type="button" class="op-btn" @click="received(order.sn)">确认收货</button>
|
||||
<button type="button" class="text-link" @click="orderDetail(order.sn)">订单详情</button>
|
||||
<button v-if="order.allowOperationVO && order.allowOperationVO.cancel" type="button" class="text-link" @click="handleCancelOrder(order.sn)">取消订单</button>
|
||||
<button v-if="order.orderStatus === 'COMPLETED'" type="button" class="text-link" @click="delOrder(order.sn)">删除订单</button>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -198,12 +196,10 @@
|
||||
<script>
|
||||
import { Message, Modal } from "@/utils/message";
|
||||
import { getOrderList, sureReceived, cancelOrder, delOrder } from '@/api/order';
|
||||
import { afterSaleReason, afterSaleList } from '@/api/member';
|
||||
import { afterSaleReason } from '@/api/member';
|
||||
import { orderStatusList, afterSaleStatusList } from '../enumeration.js'
|
||||
import { Delete } from '@element-plus/icons-vue'
|
||||
export default {
|
||||
name: 'MyOrder',
|
||||
components: { Delete },
|
||||
props: {
|
||||
homePage: { // 判断是否个人中心首页展示内容
|
||||
type: Boolean,
|
||||
@@ -215,7 +211,7 @@ export default {
|
||||
orderList: [], // 订单列表
|
||||
params: { // 请求参数
|
||||
pageNumber: 1,
|
||||
pageSize: 10,
|
||||
pageSize: 20,
|
||||
// orderStatus: 'ALL',
|
||||
keywords: '',
|
||||
tag: 'ALL'
|
||||
@@ -227,7 +223,7 @@ export default {
|
||||
// 状态数组
|
||||
orderStatusList,
|
||||
afterSaleStatusList,
|
||||
changeWay: ['全部', '待支付', '待发货', '待收货/使用', '评价', '售后'],
|
||||
changeWay: ['全部', '待支付', '待发货', '待收货/使用'],
|
||||
activeOrderTab: 0,
|
||||
total: 0, // 数据总数
|
||||
spinShow: false, // 加载状态
|
||||
@@ -270,11 +266,8 @@ export default {
|
||||
this.activeOrderTab = index;
|
||||
this.params.pageNumber = 1;
|
||||
delete this.params.commentStatus;
|
||||
const tags = ['ALL', 'WAIT_PAY', 'WAIT_SHIP', 'WAIT_USE', 'ALL', 'AFTER_SALE'];
|
||||
const tags = ['ALL', 'WAIT_PAY', 'WAIT_SHIP', 'WAIT_USE'];
|
||||
this.params.tag = tags[index] || 'ALL';
|
||||
if (index === 4) {
|
||||
this.params.commentStatus = 'UNFINISHED';
|
||||
}
|
||||
this.getList()
|
||||
},
|
||||
// 跳转店铺首页
|
||||
@@ -320,9 +313,6 @@ export default {
|
||||
afterSaleSelect (item) {
|
||||
this.$router.push({name: 'ApplyAfterSale', query: {sn: item.sn}})
|
||||
},
|
||||
comment (sn, goodsIndex) { // 评价
|
||||
this.$router.push({path: '/home/addEval', query: {sn, index: goodsIndex}})
|
||||
},
|
||||
complain (sn, goodsIndex) { // 投诉
|
||||
this.$router.push({name: 'Complain', query: {sn, index: goodsIndex}})
|
||||
},
|
||||
@@ -343,29 +333,10 @@ export default {
|
||||
},
|
||||
getList () {
|
||||
this.spinShow = true;
|
||||
if (this.activeOrderTab === 5) {
|
||||
afterSaleList({
|
||||
pageNumber: this.params.pageNumber,
|
||||
pageSize: this.params.pageSize,
|
||||
keywords: this.params.keywords,
|
||||
sort: 'createTime',
|
||||
order: 'desc',
|
||||
}).then(res => {
|
||||
this.spinShow = false
|
||||
if (res.success) {
|
||||
this.orderList = (res.result.records || []).map(item => this.mapAfterSaleOrder(item));
|
||||
this.total = res.result.total;
|
||||
}
|
||||
});
|
||||
return;
|
||||
}
|
||||
let params = JSON.parse(JSON.stringify(this.params))
|
||||
if (params.orderStatus === 'ALL') {
|
||||
delete params.orderStatus
|
||||
}
|
||||
if (params.tag === 'AFTER_SALE') {
|
||||
delete params.tag
|
||||
}
|
||||
getOrderList(params).then(res => {
|
||||
this.spinShow = false
|
||||
if (res.success) {
|
||||
@@ -431,6 +402,27 @@ export default {
|
||||
filterAfterSaleStatus (status) {
|
||||
const ob = this.afterSaleStatusList.filter(e => e.status === status);
|
||||
return ob && ob[0] ? ob[0].name : status
|
||||
},
|
||||
canAfterSale (order) {
|
||||
if (order.isAfterSale || order.orderType === 'E_COUPON' || !order.groupAfterSaleStatus) {
|
||||
return false
|
||||
}
|
||||
return order.groupAfterSaleStatus.includes('NOT_APPLIED') || order.groupAfterSaleStatus.includes('PART_AFTER_SALE')
|
||||
},
|
||||
paymentLabel (order) {
|
||||
const map = {
|
||||
WECHAT: '微信支付',
|
||||
ALIPAY: '支付宝',
|
||||
WALLET: '余额支付',
|
||||
BANK_TRANSFER: '线下转账'
|
||||
}
|
||||
if (order.paymentMethod && map[order.paymentMethod]) {
|
||||
return map[order.paymentMethod]
|
||||
}
|
||||
if (order.payStatus === 'UNPAID' || order.orderStatus === 'UNPAID') {
|
||||
return '待支付'
|
||||
}
|
||||
return ''
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -454,6 +446,8 @@ export default {
|
||||
}
|
||||
}
|
||||
.order-content {
|
||||
--order-cols: minmax(0, 1fr) 120px 120px;
|
||||
--order-gap: 12px;
|
||||
padding-top: 14px;
|
||||
}
|
||||
.page-size {
|
||||
@@ -466,6 +460,23 @@ export default {
|
||||
}
|
||||
}
|
||||
/** 订单列表 */
|
||||
.order-cols {
|
||||
display: grid;
|
||||
grid-template-columns: var(--order-cols);
|
||||
column-gap: var(--order-gap);
|
||||
align-items: center;
|
||||
padding: 0 16px 10px;
|
||||
color: #999;
|
||||
font-size: 13px;
|
||||
|
||||
span:first-child {
|
||||
padding-left: 72px;
|
||||
}
|
||||
|
||||
span:nth-child(n + 2) {
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
.order-list {
|
||||
border: 1px solid #eee;
|
||||
border-radius: 8px;
|
||||
@@ -473,120 +484,121 @@ export default {
|
||||
background: #fff;
|
||||
overflow: hidden;
|
||||
|
||||
&:hover {
|
||||
.del-btn { visibility: visible; }
|
||||
}
|
||||
|
||||
.del-btn {
|
||||
visibility: hidden;
|
||||
padding: 0;
|
||||
height: auto;
|
||||
color: #999;
|
||||
}
|
||||
|
||||
.order-header {
|
||||
display: flex;
|
||||
display: grid;
|
||||
grid-template-columns: var(--order-cols);
|
||||
column-gap: var(--order-gap);
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
gap: 16px;
|
||||
padding: 12px 16px;
|
||||
background: #fafafa;
|
||||
padding: 10px 16px;
|
||||
background: #f7f7f7;
|
||||
border-bottom: 1px solid #f0f0f0;
|
||||
}
|
||||
|
||||
.order-header-main {
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.order-status {
|
||||
font-size: 14px;
|
||||
font-weight: 600;
|
||||
color: #333;
|
||||
line-height: 1.4;
|
||||
}
|
||||
|
||||
.order-sn {
|
||||
margin-top: 4px;
|
||||
font-size: 12px;
|
||||
color: #999;
|
||||
line-height: 1.4;
|
||||
grid-column: 1 / 3;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
min-width: 0;
|
||||
font-size: 14px;
|
||||
color: #171A26;
|
||||
line-height: 1.5;
|
||||
|
||||
span {
|
||||
margin-left: 16px;
|
||||
}
|
||||
}
|
||||
|
||||
.order-header-side {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
flex-shrink: 0;
|
||||
gap: 8px;
|
||||
.order-store {
|
||||
min-width: 0;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
color: #438cde;
|
||||
cursor: pointer;
|
||||
|
||||
&:hover {
|
||||
color: $theme_color;
|
||||
}
|
||||
}
|
||||
|
||||
.order-amount {
|
||||
min-width: 88px;
|
||||
text-align: right;
|
||||
font-size: 16px;
|
||||
font-weight: 600;
|
||||
color: $theme_color;
|
||||
.order-status {
|
||||
grid-column: 3;
|
||||
min-width: 0;
|
||||
text-align: center;
|
||||
font-size: 14px;
|
||||
color: #666;
|
||||
line-height: 1.4;
|
||||
}
|
||||
|
||||
.order-body {
|
||||
display: grid;
|
||||
grid-template-columns: minmax(0, 1fr) 120px 100px;
|
||||
gap: 12px;
|
||||
align-items: start;
|
||||
grid-template-columns: var(--order-cols);
|
||||
column-gap: var(--order-gap);
|
||||
align-items: center;
|
||||
padding: 14px 16px;
|
||||
color: #999;
|
||||
}
|
||||
|
||||
.goods-item {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
display: grid;
|
||||
grid-template-columns: 60px minmax(0, 1fr);
|
||||
column-gap: 12px;
|
||||
align-items: start;
|
||||
width: 100%;
|
||||
min-width: 0;
|
||||
|
||||
& + .goods-item {
|
||||
margin-top: 12px;
|
||||
padding-top: 12px;
|
||||
border-top: 1px solid #f5f5f5;
|
||||
}
|
||||
}
|
||||
|
||||
.goods-thumb {
|
||||
width: 60px;
|
||||
height: 60px;
|
||||
border: 1px solid #f0f0f0;
|
||||
overflow: hidden;
|
||||
background: #f5f5f5;
|
||||
|
||||
img {
|
||||
width: 72px;
|
||||
height: 72px;
|
||||
margin-right: 12px;
|
||||
border-radius: 6px;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: cover;
|
||||
flex-shrink: 0;
|
||||
background: #f5f5f5;
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
|
||||
.goods-info {
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.goods-name {
|
||||
max-width: 100%;
|
||||
color: #333;
|
||||
font-size: 14px;
|
||||
line-height: 1.4;
|
||||
font-size: 16px;
|
||||
line-height: 22px;
|
||||
max-height: 44px;
|
||||
display: -webkit-box;
|
||||
-webkit-box-orient: vertical;
|
||||
-webkit-line-clamp: 2;
|
||||
overflow: hidden;
|
||||
word-break: break-all;
|
||||
}
|
||||
|
||||
.goods-meta {
|
||||
.goods-num {
|
||||
margin-top: 6px;
|
||||
color: #999;
|
||||
font-size: 14px;
|
||||
line-height: 1.4;
|
||||
}
|
||||
|
||||
.goods-extra {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
flex-wrap: wrap;
|
||||
gap: 8px;
|
||||
margin-top: 8px;
|
||||
font-size: 13px;
|
||||
line-height: 1.4;
|
||||
}
|
||||
|
||||
.goods-num {
|
||||
color: #666;
|
||||
margin-top: 6px;
|
||||
}
|
||||
|
||||
.refund-tag {
|
||||
@@ -594,47 +606,88 @@ export default {
|
||||
border-radius: 4px;
|
||||
background: #fff7e8;
|
||||
color: #ff9900;
|
||||
font-size: 12px;
|
||||
line-height: 20px;
|
||||
font-size: 14px;
|
||||
line-height: 22px;
|
||||
}
|
||||
|
||||
.goods-ops {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 8px;
|
||||
.sub-btn {
|
||||
height: 28px;
|
||||
margin-top: 8px;
|
||||
padding: 0 10px;
|
||||
border: 1px solid #ddd;
|
||||
border-radius: 4px;
|
||||
background: #fff;
|
||||
color: #666;
|
||||
font-size: 14px;
|
||||
line-height: 26px;
|
||||
cursor: pointer;
|
||||
|
||||
.el-button {
|
||||
margin: 0;
|
||||
&:hover {
|
||||
border-color: $theme_color;
|
||||
color: $theme_color;
|
||||
}
|
||||
}
|
||||
|
||||
.store-name {
|
||||
padding-top: 4px;
|
||||
.goods-extra .sub-btn {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
.col-amount,
|
||||
.col-ops {
|
||||
text-align: center;
|
||||
font-size: 13px;
|
||||
line-height: 1.4;
|
||||
word-break: break-all;
|
||||
|
||||
span {
|
||||
color: #438cde;
|
||||
cursor: pointer;
|
||||
|
||||
&:hover {
|
||||
color: $theme_color;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.order-actions {
|
||||
.order-amount {
|
||||
color: #333;
|
||||
font-size: 16px;
|
||||
font-weight: 600;
|
||||
line-height: 1.4;
|
||||
}
|
||||
|
||||
.pay-method {
|
||||
margin-top: 4px;
|
||||
color: #999;
|
||||
font-size: 14px;
|
||||
line-height: 1.4;
|
||||
}
|
||||
|
||||
.col-ops {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: stretch;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.el-button {
|
||||
margin: 0;
|
||||
width: 100%;
|
||||
.op-btn {
|
||||
min-width: 96px;
|
||||
height: 32px;
|
||||
padding: 0 12px;
|
||||
border: 1px solid $theme_color;
|
||||
border-radius: 4px;
|
||||
background: #fff;
|
||||
color: #171A26;
|
||||
font-family: inherit;
|
||||
font-size: 14px;
|
||||
line-height: 30px;
|
||||
cursor: pointer;
|
||||
|
||||
&:hover {
|
||||
background: #fff5f4;
|
||||
}
|
||||
}
|
||||
|
||||
.text-link {
|
||||
border: none;
|
||||
background: none;
|
||||
padding: 0;
|
||||
color: #171A26;
|
||||
font-family: inherit;
|
||||
font-size: 14px;
|
||||
line-height: 22px;
|
||||
cursor: pointer;
|
||||
|
||||
&:hover {
|
||||
color: $theme_color;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,56 +1,66 @@
|
||||
<template>
|
||||
<div class="order-detail" v-if="order.order">
|
||||
<UserCenterLayout title="订单详情" :tabs="['订单详情']">
|
||||
<el-card
|
||||
class="mb_10"
|
||||
shadow="never"
|
||||
v-if="
|
||||
order.allowOperationVO.pay ||
|
||||
order.allowOperationVO.rog ||
|
||||
order.allowOperationVO.cancel
|
||||
"
|
||||
>
|
||||
<el-button
|
||||
type="success"
|
||||
@click="goPay(order.order.sn)"
|
||||
size="small"
|
||||
v-if="order.allowOperationVO.pay"
|
||||
>去支付</el-button>
|
||||
<el-button
|
||||
type="primary"
|
||||
@click="received(order.order.sn)"
|
||||
size="small"
|
||||
v-if="order.allowOperationVO.rog"
|
||||
>确认收货</el-button>
|
||||
<el-button
|
||||
type="danger"
|
||||
@click="handleCancelOrder(order.order.sn)"
|
||||
v-if="order.allowOperationVO.cancel"
|
||||
size="small"
|
||||
>取消订单</el-button>
|
||||
<el-button v-if="order.allowOperationVO.showLogistics || orderPackage.length > 0 || logistics" type="info" @click="logisticsList()" size="small">查看物流</el-button>
|
||||
</el-card>
|
||||
<p class="verificationCode" v-if="order.order.verificationCode && !isECouponOrder">
|
||||
核验码:<span>{{ order.order.verificationCode }}</span>
|
||||
</p>
|
||||
<div class="order-card">
|
||||
<p class="global_color fontsize_18">{{ order.orderStatusValue }}</p>
|
||||
<p>订单号:{{ order.order.sn }}</p>
|
||||
<div style="color: #999" class="operation-time">
|
||||
操作时间:{{ order.order.updateTime || order.order.createTime }}
|
||||
<UserCenterLayout>
|
||||
<div class="order-card status-card">
|
||||
<div class="status-head">
|
||||
<div class="status-main">
|
||||
<p class="status-text">{{ order.orderStatusValue }}</p>
|
||||
<p class="status-sn">订单号:{{ order.order.sn }}</p>
|
||||
</div>
|
||||
<div class="status-side">
|
||||
<div class="operation-time">
|
||||
操作时间:{{ order.order.updateTime || order.order.createTime }}
|
||||
</div>
|
||||
<div
|
||||
class="status-actions"
|
||||
v-if="
|
||||
order.allowOperationVO.pay ||
|
||||
order.allowOperationVO.rog ||
|
||||
order.allowOperationVO.cancel ||
|
||||
order.allowOperationVO.showLogistics ||
|
||||
orderPackage.length > 0 ||
|
||||
logistics
|
||||
"
|
||||
>
|
||||
<el-button
|
||||
type="success"
|
||||
@click="goPay(order.order.sn)"
|
||||
size="small"
|
||||
v-if="order.allowOperationVO.pay"
|
||||
>去支付</el-button>
|
||||
<el-button
|
||||
type="primary"
|
||||
@click="received(order.order.sn)"
|
||||
size="small"
|
||||
v-if="order.allowOperationVO.rog"
|
||||
>确认收货</el-button>
|
||||
<el-button
|
||||
type="danger"
|
||||
@click="handleCancelOrder(order.order.sn)"
|
||||
v-if="order.allowOperationVO.cancel"
|
||||
size="small"
|
||||
>取消订单</el-button>
|
||||
<el-button v-if="order.allowOperationVO.showLogistics || orderPackage.length > 0 || logistics" type="info" @click="logisticsList()" size="small">查看物流</el-button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<el-steps
|
||||
v-if="progressList.length"
|
||||
class="progress"
|
||||
:current="progressList.length"
|
||||
:active="progressList.length - 1"
|
||||
direction="vertical"
|
||||
>
|
||||
<el-step :title="progress.message"
|
||||
:content="progress.createTime"
|
||||
<el-step
|
||||
:title="progress.message"
|
||||
:description="progress.createTime"
|
||||
v-for="(progress, index) in progressList"
|
||||
:key="index"
|
||||
></el-step>
|
||||
</el-steps>
|
||||
</div>
|
||||
<p class="verificationCode" v-if="order.order.verificationCode && !isECouponOrder">
|
||||
核验码:<span>{{ order.order.verificationCode }}</span>
|
||||
</p>
|
||||
<div class="order-card" v-if="order.order.deliveryMethod === 'LOGISTICS' && !isNonPhysicalOrder">
|
||||
<h3>收货人信息</h3>
|
||||
<p>收货人:{{ order.order.consigneeName }}</p>
|
||||
@@ -191,28 +201,26 @@
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th width="30%">商品</th>
|
||||
<th width="15%">货号</th>
|
||||
<th width="28%">商品</th>
|
||||
<th width="16%">货号</th>
|
||||
<th width="10%">单价</th>
|
||||
<th width="5%">数量</th>
|
||||
<th width="10%" v-if="!isECouponOrder">退款状态</th>
|
||||
<th width="10%" v-if="!isECouponOrder">实际退款金额</th>
|
||||
<th width="8%">数量</th>
|
||||
<th width="10%">小计</th>
|
||||
<th width="10%">操作</th>
|
||||
<th width="8%">操作</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr v-for="(goods, goodsIndex) in order.orderItems" :key="goodsIndex">
|
||||
<td>
|
||||
<img
|
||||
@click="goodsDetail(goods.skuId, goods.goodsId)"
|
||||
:src="goods.image"
|
||||
alt=""
|
||||
/>
|
||||
<div>
|
||||
<div class="goods-cell">
|
||||
<img
|
||||
@click="goodsDetail(goods.skuId, goods.goodsId)"
|
||||
:src="goods.image"
|
||||
alt=""
|
||||
/>
|
||||
<p
|
||||
@click="goodsDetail(goods.skuId, goods.goodsId)"
|
||||
class="hover-color"
|
||||
class="hover-color goods-name"
|
||||
>
|
||||
{{ goods.goodsName }}
|
||||
</p>
|
||||
@@ -221,23 +229,19 @@
|
||||
<td>{{ goods.id }}</td>
|
||||
<td>{{ $filters.unitPrice(goods.goodsPrice, "¥") }}</td>
|
||||
<td>{{ goods.num }}</td>
|
||||
<td v-if="!isECouponOrder">{{refundPriceList(goods.isRefund)}}</td>
|
||||
<td v-if="!isECouponOrder">{{ $filters.unitPrice(goods.refundPrice, "¥") }}</td>
|
||||
<td>{{ $filters.unitPrice((goods.goodsPrice * goods.num), "¥") }}</td>
|
||||
<td class="order-item-actions">
|
||||
<el-button
|
||||
<button
|
||||
v-if="goods.commentStatus == 'UNFINISHED'"
|
||||
type="button"
|
||||
class="comment-text"
|
||||
@click="comment(order.order.sn, goodsIndex)"
|
||||
size="small"
|
||||
type="success"
|
||||
class="order-item-action-btn fontsize_12 mb_5"
|
||||
>评价</el-button
|
||||
>
|
||||
>评价</button>
|
||||
<el-button
|
||||
v-if="goods.complainStatus == 'NO_APPLY'"
|
||||
@click="complain(order.order.sn, goodsIndex)"
|
||||
type="danger"
|
||||
class="order-item-action-btn fontsize_12 mb_5"
|
||||
class="order-item-action-btn mb_5"
|
||||
size="small"
|
||||
>投诉</el-button
|
||||
>
|
||||
@@ -575,21 +579,6 @@ export default {
|
||||
}
|
||||
window.open(invoiceAddress, "_blank");
|
||||
},
|
||||
// 退款状态枚举
|
||||
refundPriceList(status) {
|
||||
switch (status) {
|
||||
case 'ALL_REFUND':
|
||||
return "全部退款";
|
||||
case 'PART_REFUND':
|
||||
return "部分退款";
|
||||
case 'NO_REFUND':
|
||||
return "未退款";
|
||||
case 'REFUNDING':
|
||||
return "退款中";
|
||||
default:
|
||||
return "未退款";
|
||||
}
|
||||
},
|
||||
goodsDetail(skuId, goodsId) {
|
||||
// 跳转商品详情
|
||||
let routeUrl = this.$router.resolve({
|
||||
@@ -621,7 +610,9 @@ export default {
|
||||
this.order["receipt"] = receiptRes.result;
|
||||
}
|
||||
}
|
||||
this.progressList = res.result.orderLogs;
|
||||
this.progressList = (res.result.orderLogs || []).slice().sort((a, b) => {
|
||||
return new Date(a.createTime).getTime() - new Date(b.createTime).getTime();
|
||||
});
|
||||
if (this.order.order.deliveryMethod === 'LOGISTICS') {
|
||||
this.getOrderPackage(this.order.order.sn);
|
||||
}
|
||||
@@ -727,109 +718,237 @@ export default {
|
||||
.mb_5 {
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
.order-detail {
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.order-card {
|
||||
padding: 10px;
|
||||
padding-bottom: 10px;
|
||||
margin-bottom: 10px;
|
||||
border-bottom: 1px solid #e8eaec;
|
||||
position: relative;
|
||||
.global_color {
|
||||
color: $theme_color;
|
||||
}
|
||||
p {
|
||||
color: #999;
|
||||
margin: 3px;
|
||||
margin-left: 5px;
|
||||
}
|
||||
padding: 4px 0 16px;
|
||||
margin-bottom: 8px;
|
||||
border-bottom: 1px solid #f0f0f0;
|
||||
|
||||
h3 {
|
||||
font-weight: normal;
|
||||
font-size: 16px;
|
||||
margin: 0 0 12px;
|
||||
font-size: 15px;
|
||||
font-weight: 600;
|
||||
color: #333;
|
||||
line-height: 1.4;
|
||||
}
|
||||
.operation-time {
|
||||
position: absolute;
|
||||
right: 20px;
|
||||
top: 20px;
|
||||
|
||||
p {
|
||||
margin: 0;
|
||||
padding: 4px 0;
|
||||
color: #666;
|
||||
line-height: 22px;
|
||||
}
|
||||
}
|
||||
/** 店铺名称 */
|
||||
|
||||
.status-card {
|
||||
padding-top: 8px;
|
||||
}
|
||||
|
||||
.status-head {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
justify-content: space-between;
|
||||
gap: 16px;
|
||||
}
|
||||
|
||||
.status-text {
|
||||
color: $theme_color;
|
||||
font-size: 18px;
|
||||
font-weight: 600;
|
||||
line-height: 1.4;
|
||||
}
|
||||
|
||||
.status-sn {
|
||||
margin-top: 6px;
|
||||
color: #666;
|
||||
}
|
||||
|
||||
.status-side {
|
||||
flex-shrink: 0;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.operation-time {
|
||||
color: #999;
|
||||
font-size: 13px;
|
||||
line-height: 22px;
|
||||
}
|
||||
|
||||
.status-actions {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
flex-wrap: wrap;
|
||||
gap: 8px;
|
||||
margin-top: 10px;
|
||||
|
||||
.el-button {
|
||||
margin: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.progress {
|
||||
max-width: 640px;
|
||||
margin: 20px 0 0;
|
||||
|
||||
:deep(.el-step.is-vertical) {
|
||||
padding-bottom: 20px;
|
||||
}
|
||||
|
||||
:deep(.el-step.is-vertical:last-child) {
|
||||
padding-bottom: 0;
|
||||
}
|
||||
|
||||
:deep(.el-step__head.is-finish) {
|
||||
color: #c0c4cc;
|
||||
border-color: #c0c4cc;
|
||||
}
|
||||
|
||||
:deep(.el-step__title.is-finish),
|
||||
:deep(.el-step__description.is-finish) {
|
||||
color: #909399;
|
||||
font-weight: 400;
|
||||
}
|
||||
|
||||
:deep(.el-step__head.is-process) {
|
||||
color: $theme_color;
|
||||
border-color: $theme_color;
|
||||
}
|
||||
|
||||
:deep(.el-step__title.is-process),
|
||||
:deep(.el-step__description.is-process) {
|
||||
color: $theme_color;
|
||||
}
|
||||
}
|
||||
|
||||
.goods {
|
||||
padding-top: 8px;
|
||||
}
|
||||
|
||||
.shop-name {
|
||||
margin: 15px 0;
|
||||
margin: 8px 0 12px;
|
||||
font-size: 14px;
|
||||
font-weight: 600;
|
||||
|
||||
span {
|
||||
color: #438cde;
|
||||
cursor: pointer;
|
||||
&:hover {
|
||||
color: $theme_color;
|
||||
}
|
||||
}
|
||||
.el-icon {
|
||||
color: #ff8f23;
|
||||
cursor: pointer;
|
||||
|
||||
&:hover {
|
||||
color: $theme_color;
|
||||
}
|
||||
}
|
||||
}
|
||||
/** 商品列表 */
|
||||
|
||||
table {
|
||||
border: 1px solid #ddd;
|
||||
color: #999;
|
||||
border: 1px solid #eee;
|
||||
color: #666;
|
||||
border-collapse: collapse;
|
||||
width: 100%;
|
||||
|
||||
tr {
|
||||
border-top: 1px solid #ddd;
|
||||
border-top: 1px solid #eee;
|
||||
}
|
||||
|
||||
thead > tr {
|
||||
height: 40px;
|
||||
background: #eee;
|
||||
background: #fafafa;
|
||||
}
|
||||
|
||||
th {
|
||||
font-size: 12px;
|
||||
font-weight: normal;
|
||||
padding: 0 8px;
|
||||
font-size: 13px;
|
||||
font-weight: 500;
|
||||
color: #666;
|
||||
}
|
||||
|
||||
td {
|
||||
padding: 5px;
|
||||
padding: 12px 8px;
|
||||
text-align: center;
|
||||
vertical-align: middle;
|
||||
|
||||
&:first-child {
|
||||
text-align: left;
|
||||
display: flex;
|
||||
img {
|
||||
width: 70px;
|
||||
height: 70px;
|
||||
margin-right: 10px;
|
||||
margin-left: 10px;
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
&:last-child {
|
||||
color: $theme_color;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.goods-cell {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 12px;
|
||||
min-width: 0;
|
||||
|
||||
img {
|
||||
width: 64px;
|
||||
height: 64px;
|
||||
border-radius: 6px;
|
||||
object-fit: cover;
|
||||
flex-shrink: 0;
|
||||
background: #f5f5f5;
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
|
||||
.goods-name {
|
||||
min-width: 0;
|
||||
color: #333;
|
||||
line-height: 20px;
|
||||
display: -webkit-box;
|
||||
-webkit-box-orient: vertical;
|
||||
-webkit-line-clamp: 2;
|
||||
overflow: hidden;
|
||||
word-break: break-word;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.order-item-actions {
|
||||
vertical-align: middle;
|
||||
|
||||
.comment-text {
|
||||
display: block;
|
||||
margin: 0 auto 6px;
|
||||
padding: 0;
|
||||
border: 0;
|
||||
background: transparent;
|
||||
color: $theme_color;
|
||||
font-size: 14px;
|
||||
line-height: 22px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.order-item-action-btn {
|
||||
display: block;
|
||||
margin: 0 auto 5px;
|
||||
margin: 0 auto 6px;
|
||||
min-width: 88px;
|
||||
}
|
||||
}
|
||||
/** 订单价格 */
|
||||
|
||||
.order-price {
|
||||
text-align: right;
|
||||
margin-top: 30px;
|
||||
font-size: 16px;
|
||||
color: #999;
|
||||
> div > span:nth-child(2) {
|
||||
width: 130px;
|
||||
text-align: right;
|
||||
display: inline-block;
|
||||
margin-top: 10px;
|
||||
margin-top: 16px;
|
||||
padding-top: 8px;
|
||||
font-size: 14px;
|
||||
color: #666;
|
||||
|
||||
> div {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
align-items: center;
|
||||
line-height: 28px;
|
||||
}
|
||||
|
||||
> div > span:nth-child(2) {
|
||||
width: 140px;
|
||||
margin-top: 0;
|
||||
text-align: right;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.actrual-price {
|
||||
color: $theme_color;
|
||||
font-weight: bold;
|
||||
font-weight: 600;
|
||||
font-size: 20px;
|
||||
}
|
||||
}
|
||||
@@ -875,11 +994,6 @@ table {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
/** 订单进度条 */
|
||||
.progress {
|
||||
margin: 15px 0;
|
||||
}
|
||||
|
||||
.layui-layer-wrap {
|
||||
dl {
|
||||
border-top: solid 1px #f5f5f5;
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
<template>
|
||||
<div class="wrapper">
|
||||
<UserCenterLayout
|
||||
title="优惠券列表"
|
||||
:tabs="statusNameList"
|
||||
:active-tab="activeStatusIndex"
|
||||
@tab-change="change"
|
||||
@@ -13,16 +12,16 @@
|
||||
<div>
|
||||
<span
|
||||
v-if="item.couponType === 'PRICE'"
|
||||
class="fontsize_12 global_color"
|
||||
class="global_color coupon-amount"
|
||||
>¥<span class="price">{{ $filters.unitPrice(item.price) }}</span></span>
|
||||
<span
|
||||
v-if="item.couponType === 'DISCOUNT'"
|
||||
class="fontsize_12 global_color"
|
||||
class="global_color coupon-amount"
|
||||
><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>
|
||||
<p class="coupon-expire">有效期:{{ formatValidity(item) }}</p>
|
||||
</div>
|
||||
<b></b>
|
||||
<a
|
||||
@@ -40,6 +39,7 @@
|
||||
v-model:current-page="params.pageNumber"
|
||||
v-model:page-size="params.pageSize"
|
||||
:total="total"
|
||||
:page-sizes="[20, 50, 100]"
|
||||
@current-change="changePageNum"
|
||||
@size-change="changePageSize"
|
||||
layout="total, sizes, prev, pager, next, jumper"
|
||||
@@ -67,7 +67,7 @@ export default {
|
||||
params: {
|
||||
// 请求参数
|
||||
pageNumber: 1,
|
||||
pageSize: 10,
|
||||
pageSize: 20,
|
||||
memberCouponStatus: "NEW",
|
||||
},
|
||||
total: 0, // 优惠券总数
|
||||
@@ -84,13 +84,19 @@ export default {
|
||||
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;
|
||||
}
|
||||
});
|
||||
memberCouponList(this.params)
|
||||
.then((res) => {
|
||||
this.loading = false;
|
||||
if (res.success) {
|
||||
this.list = res.result.records || [];
|
||||
this.total = res.result.total || 0;
|
||||
}
|
||||
})
|
||||
.catch(() => {
|
||||
this.loading = false;
|
||||
this.list = [];
|
||||
this.total = 0;
|
||||
});
|
||||
},
|
||||
// 切换优惠券状态
|
||||
change(index) {
|
||||
@@ -139,6 +145,25 @@ export default {
|
||||
}
|
||||
return `${shop}${goods}可用`;
|
||||
},
|
||||
formatValidity(item) {
|
||||
const start = this.formatCouponTime(item && item.startTime);
|
||||
const end = this.formatCouponTime(item && item.endTime);
|
||||
if (start && end) return `${start} 至 ${end}`;
|
||||
if (end) return `至 ${end}`;
|
||||
if (start) return `${start} 起`;
|
||||
return "长期有效";
|
||||
},
|
||||
formatCouponTime(value) {
|
||||
if (!value) return "";
|
||||
const text = String(value).trim();
|
||||
if (/^\d{4}-\d{2}-\d{2}/.test(text)) {
|
||||
return text.slice(0, 16);
|
||||
}
|
||||
const date = new Date(text);
|
||||
if (Number.isNaN(date.getTime())) return text;
|
||||
const pad = (n) => String(n).padStart(2, "0");
|
||||
return `${date.getFullYear()}-${pad(date.getMonth() + 1)}-${pad(date.getDate())} ${pad(date.getHours())}:${pad(date.getMinutes())}`;
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
this.getList();
|
||||
@@ -150,19 +175,31 @@ export default {
|
||||
@import "../../../assets/styles/coupon.scss";
|
||||
.coupon-item {
|
||||
overflow: hidden;
|
||||
height: 145px;
|
||||
height: auto;
|
||||
min-height: 168px;
|
||||
margin-left: 0;
|
||||
$claim-width: 55px;
|
||||
|
||||
.c-left {
|
||||
width: calc(100% - #{$claim-width});
|
||||
box-sizing: border-box;
|
||||
padding: 20px;
|
||||
padding: 16px 16px 14px;
|
||||
|
||||
.coupon-amount {
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.describe {
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
p {
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
font-size: 14px;
|
||||
overflow: visible;
|
||||
text-overflow: unset;
|
||||
white-space: normal;
|
||||
word-break: break-all;
|
||||
line-height: 20px;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,19 +1,21 @@
|
||||
<template>
|
||||
<div class="wrapper">
|
||||
<UserCenterLayout title="资金管理" :tabs="['资金管理']">
|
||||
<UserCenterLayout>
|
||||
|
||||
<div class="box">
|
||||
<div class="mb_20 account-price">
|
||||
<span class="subTips">账户余额:</span>
|
||||
<span class="global_color mr_10" style="font-size:26px">¥{{ $filters.unitPrice(memberDeposit) }}</span>
|
||||
<span class="subTips">冻结金额:</span>
|
||||
<span class="">¥{{ $filters.unitPrice(frozenDeposit) }}</span>
|
||||
<div class="wallet-summary">
|
||||
<div class="wallet-stat">
|
||||
<div class="label">账户余额</div>
|
||||
<div class="value">¥{{ $filters.unitPrice(memberDeposit) }}</div>
|
||||
</div>
|
||||
<div class="account-btns">
|
||||
<el-button type="primary" @click="recharge">在线充值</el-button>
|
||||
<el-button @click="withdrawalApply">申请提现</el-button>
|
||||
<div class="wallet-stat">
|
||||
<div class="label">冻结金额</div>
|
||||
<div class="value is-muted">¥{{ $filters.unitPrice(frozenDeposit) }}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="account-btns">
|
||||
<button type="button" class="op-btn" @click="recharge">在线充值</button>
|
||||
<button type="button" class="ghost-btn" @click="withdrawalApply">申请提现</button>
|
||||
</div>
|
||||
<el-dialog v-model="modal" width="530">
|
||||
<template #header><p>
|
||||
<el-icon><Edit /></el-icon>
|
||||
@@ -87,103 +89,93 @@
|
||||
<el-button size="large" type="success" @click="withdrawal">提现</el-button>
|
||||
</div></template>
|
||||
</el-dialog>
|
||||
<!-- 余额日志 -->
|
||||
<el-tabs v-model="activeWalletTab" @tab-click="(tab) => tabPaneChange(tab.paneName)">
|
||||
<el-tab-pane label="余额日志" name="log">
|
||||
<el-table ref="logTable" :data="logColumnsData.records || []">
|
||||
<el-table-column prop="createTime" label="时间" width="190" />
|
||||
<el-table-column label="金额" width="180">
|
||||
<template #default="{ row }">
|
||||
<span v-if="row.money > 0" style="color: green">{{ $filters.unitPrice(row.money, '+ ¥') }}</span>
|
||||
<span v-else-if="row.money < 0" style="color: red">{{ $filters.unitPrice(0 - row.money, '- ¥') }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="detail" label="变动日志" />
|
||||
</el-table>
|
||||
<!-- 分页 -->
|
||||
<div class="page-size">
|
||||
<el-pagination v-model:current-page="walletForm.pageNumber"
|
||||
v-model:page-size="walletForm.pageSize"
|
||||
:page-sizes="[10, 20, 50]"
|
||||
:total="logColumnsData.total"
|
||||
@current-change="changePage"
|
||||
@size-change="changePageSize"
|
||||
layout="total, sizes, prev, pager, next, jumper"></el-pagination>
|
||||
</div>
|
||||
</el-tab-pane>
|
||||
<!-- 充值记录 -->
|
||||
<el-tab-pane label="充值记录" name="recharge">
|
||||
<el-table ref="rechargeTable" :data="rechargeListData.records || []">
|
||||
<el-table-column prop="createTime" label="充值时间" width="168" />
|
||||
<el-table-column prop="rechargeSn" label="支付单号" width="200" />
|
||||
<el-table-column label="充值金额">
|
||||
<template #default="{ row }">
|
||||
<span v-if="row.payStatus === 'PAID'" style="color: green">{{ $filters.unitPrice(row.rechargeMoney, '+ ¥') }}</span>
|
||||
<span v-else>{{ $filters.unitPrice(row.rechargeMoney, '¥') }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="支付状态">
|
||||
<template #default="{ row }">
|
||||
<span v-if="row.payStatus === 'PAID'">已付款</span>
|
||||
<span v-else-if="row.payStatus === 'UNPAID'">未付款</span>
|
||||
<span v-else-if="row.payStatus === 'CANCEL'">已取消</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="支付方式">
|
||||
<template #default="{ row }">
|
||||
<span v-if="row.rechargeWay === 'ALIPAY'">支付宝</span>
|
||||
<span v-else-if="row.rechargeWay === 'WECHAT'">微信</span>
|
||||
<span v-else-if="row.rechargeWay === 'BANK_TRANSFER'">线下转账</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="payTime" label="支付时间" width="180" />
|
||||
</el-table>
|
||||
<!-- 分页 -->
|
||||
<div class="page-size">
|
||||
<el-pagination v-model:current-page="rechargeForm.pageNumber"
|
||||
v-model:page-size="rechargeForm.pageSize"
|
||||
:page-sizes="[10, 20, 50]"
|
||||
:total="rechargeListData.total"
|
||||
@current-change="rechargeChangePage"
|
||||
@size-change="rechargeChangePageSize"
|
||||
layout="total, sizes, prev, pager, next, jumper"></el-pagination>
|
||||
</div>
|
||||
</el-tab-pane>
|
||||
<div class="wallet-tabs">
|
||||
<div class="wallet-tab" :class="{ active: activeWalletTab === 'log' }" @click="tabPaneChange('log')">余额日志</div>
|
||||
<div class="wallet-tab" :class="{ active: activeWalletTab === 'recharge' }" @click="tabPaneChange('recharge')">充值记录</div>
|
||||
<div class="wallet-tab" :class="{ active: activeWalletTab === 'withdrawApply' }" @click="tabPaneChange('withdrawApply')">提现记录</div>
|
||||
</div>
|
||||
|
||||
<el-tab-pane label="提现记录" name="withdrawApply">
|
||||
<el-table ref="withdrawTable" :data="withdrawApplyColumnsListData.records || []">
|
||||
<el-table-column prop="createTime" label="申请时间" width="168" />
|
||||
<el-table-column prop="sn" label="提现单号" width="200" />
|
||||
<el-table-column label="提现金额" width="110">
|
||||
<template #default="{ row }">
|
||||
<span v-if="row.applyStatus === 'VIA_AUDITING'" style="color: green">{{ $filters.unitPrice(row.applyMoney, '+ ¥') }}</span>
|
||||
<span v-else>{{ $filters.unitPrice(row.applyMoney, '¥') }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="提现状态" width="95">
|
||||
<template #default="{ row }">
|
||||
<span v-if="row.applyStatus === 'APPLY'">申请中</span>
|
||||
<span v-else-if="row.applyStatus === 'VIA_AUDITING'">审核通过</span>
|
||||
<span v-else-if="row.applyStatus === 'SUCCESS'">提现成功</span>
|
||||
<span v-else-if="row.applyStatus === 'ERROR'">提现失败</span>
|
||||
<span v-else>审核拒绝</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="inspectTime" label="审核时间" width="168" />
|
||||
<el-table-column prop="inspectRemark" label="审核备注" show-overflow-tooltip />
|
||||
</el-table>
|
||||
<!-- 分页 -->
|
||||
<div class="page-size">
|
||||
<el-pagination v-model:current-page="withdrawApplyForm.pageNumber"
|
||||
v-model:page-size="withdrawApplyForm.pageSize"
|
||||
:page-sizes="[10, 20, 50]"
|
||||
:total="withdrawApplyColumnsListData.total"
|
||||
@current-change="withdrawChangePage"
|
||||
@size-change="withdrawChangePageSize"
|
||||
layout="total, sizes, prev, pager, next, jumper"></el-pagination>
|
||||
<div v-show="activeWalletTab === 'log'">
|
||||
<empty v-if="!(logColumnsData.records || []).length" />
|
||||
<div v-else class="wallet-list log-list">
|
||||
<div class="wallet-head">
|
||||
<span>时间</span>
|
||||
<span>金额</span>
|
||||
<span>变动日志</span>
|
||||
</div>
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
<div class="wallet-row" v-for="(row, index) in logColumnsData.records" :key="row.id || index">
|
||||
<div class="wallet-time">{{ row.createTime }}</div>
|
||||
<div class="wallet-money" :class="row.money > 0 ? 'is-plus' : 'is-minus'">
|
||||
<span v-if="row.money > 0">{{ $filters.unitPrice(row.money, '+ ¥') }}</span>
|
||||
<span v-else-if="row.money < 0">{{ $filters.unitPrice(0 - row.money, '- ¥') }}</span>
|
||||
</div>
|
||||
<div class="wallet-detail">{{ row.detail }}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="page-size">
|
||||
<el-pagination v-model:current-page="walletForm.pageNumber" v-model:page-size="walletForm.pageSize"
|
||||
:page-sizes="[20, 50, 100]" :total="logColumnsData.total" @current-change="changePage"
|
||||
@size-change="changePageSize" layout="total, sizes, prev, pager, next, jumper"></el-pagination>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div v-show="activeWalletTab === 'recharge'">
|
||||
<empty v-if="!(rechargeListData.records || []).length" />
|
||||
<div v-else class="wallet-list recharge-list">
|
||||
<div class="wallet-head">
|
||||
<span>充值时间</span>
|
||||
<span>支付单号</span>
|
||||
<span>充值金额</span>
|
||||
<span>支付状态</span>
|
||||
<span>支付方式</span>
|
||||
<span>支付时间</span>
|
||||
</div>
|
||||
<div class="wallet-row" v-for="(row, index) in rechargeListData.records" :key="row.rechargeSn || index">
|
||||
<div>{{ row.createTime }}</div>
|
||||
<div class="wallet-detail">{{ row.rechargeSn }}</div>
|
||||
<div class="wallet-money" :class="row.payStatus === 'PAID' ? 'is-plus' : ''">
|
||||
{{ $filters.unitPrice(row.rechargeMoney, row.payStatus === 'PAID' ? '+ ¥' : '¥') }}
|
||||
</div>
|
||||
<div>{{ rechargeStatusText(row.payStatus) }}</div>
|
||||
<div>{{ rechargeWayText(row.rechargeWay) }}</div>
|
||||
<div>{{ row.payTime || '—' }}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="page-size">
|
||||
<el-pagination v-model:current-page="rechargeForm.pageNumber" v-model:page-size="rechargeForm.pageSize"
|
||||
:page-sizes="[20, 50, 100]" :total="rechargeListData.total" @current-change="rechargeChangePage"
|
||||
@size-change="rechargeChangePageSize" layout="total, sizes, prev, pager, next, jumper"></el-pagination>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div v-show="activeWalletTab === 'withdrawApply'">
|
||||
<empty v-if="!(withdrawApplyColumnsListData.records || []).length" />
|
||||
<div v-else class="wallet-list withdraw-list">
|
||||
<div class="wallet-head">
|
||||
<span>申请时间</span>
|
||||
<span>提现单号</span>
|
||||
<span>提现金额</span>
|
||||
<span>提现状态</span>
|
||||
<span>审核时间</span>
|
||||
<span>审核备注</span>
|
||||
</div>
|
||||
<div class="wallet-row" v-for="(row, index) in withdrawApplyColumnsListData.records" :key="row.sn || index">
|
||||
<div>{{ row.createTime }}</div>
|
||||
<div class="wallet-detail">{{ row.sn }}</div>
|
||||
<div class="wallet-money" :class="row.applyStatus === 'VIA_AUDITING' ? 'is-plus' : ''">
|
||||
{{ $filters.unitPrice(row.applyMoney, row.applyStatus === 'VIA_AUDITING' ? '+ ¥' : '¥') }}
|
||||
</div>
|
||||
<div>{{ withdrawStatusText(row.applyStatus) }}</div>
|
||||
<div>{{ row.inspectTime || '—' }}</div>
|
||||
<div class="wallet-detail">{{ row.inspectRemark || '—' }}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="page-size">
|
||||
<el-pagination v-model:current-page="withdrawApplyForm.pageNumber" v-model:page-size="withdrawApplyForm.pageSize"
|
||||
:page-sizes="[20, 50, 100]" :total="withdrawApplyColumnsListData.total" @current-change="withdrawChangePage"
|
||||
@size-change="withdrawChangePageSize" layout="total, sizes, prev, pager, next, jumper"></el-pagination>
|
||||
</div>
|
||||
</div>
|
||||
</UserCenterLayout>
|
||||
</div>
|
||||
</template>
|
||||
@@ -221,19 +213,19 @@ export default {
|
||||
walletForm: {
|
||||
// 搜索框初始化对象
|
||||
pageNumber: 1,
|
||||
pageSize: 10
|
||||
pageSize: 20
|
||||
},
|
||||
// 充值记录
|
||||
rechargeForm: {
|
||||
// 搜索框初始化对象
|
||||
pageNumber: 1, // 当前页数
|
||||
pageSize: 10 // 页面大小
|
||||
pageSize: 20 // 页面大小
|
||||
},
|
||||
// 提现记录
|
||||
withdrawApplyForm: {
|
||||
// 搜索框初始化对象
|
||||
pageNumber: 1, // 当前页数
|
||||
pageSize: 10 // 页面大小
|
||||
pageSize: 20 // 页面大小
|
||||
},
|
||||
// 提现申请校验
|
||||
withdrawApplyFormValidate: {
|
||||
@@ -280,31 +272,26 @@ export default {
|
||||
getDepositLog(this.walletForm).then((res) => {
|
||||
if (res.message === 'success') {
|
||||
this.logColumnsData = res.result;
|
||||
this.refreshActiveTableLayout();
|
||||
}
|
||||
});
|
||||
},
|
||||
tabPaneChange(v) {
|
||||
// 如果查询充值记录
|
||||
this.activeWalletTab = v;
|
||||
if (v === 'recharge') {
|
||||
this.getRechargeData();
|
||||
}
|
||||
// 如果是余额日志
|
||||
if (v === 'log') {
|
||||
this.init();
|
||||
}
|
||||
// 如果是提现记录
|
||||
if (v === 'withdrawApply') {
|
||||
this.getWithdrawApplyData();
|
||||
}
|
||||
this.refreshActiveTableLayout();
|
||||
},
|
||||
// 充值记录
|
||||
getRechargeData() {
|
||||
getRecharge(this.rechargeForm).then((res) => {
|
||||
if (res.message === 'success') {
|
||||
this.rechargeListData = res.result;
|
||||
this.refreshActiveTableLayout();
|
||||
}
|
||||
});
|
||||
},
|
||||
@@ -313,19 +300,25 @@ export default {
|
||||
getWithdrawApply(this.withdrawApplyForm).then((res) => {
|
||||
if (res.message === 'success') {
|
||||
this.withdrawApplyColumnsListData = res.result;
|
||||
this.refreshActiveTableLayout();
|
||||
}
|
||||
});
|
||||
},
|
||||
refreshActiveTableLayout() {
|
||||
this.$nextTick(() => {
|
||||
const tableMap = {
|
||||
log: this.$refs.logTable,
|
||||
recharge: this.$refs.rechargeTable,
|
||||
withdrawApply: this.$refs.withdrawTable
|
||||
};
|
||||
tableMap[this.activeWalletTab]?.doLayout?.();
|
||||
});
|
||||
rechargeStatusText (status) {
|
||||
const map = { PAID: '已付款', UNPAID: '未付款', CANCEL: '已取消' }
|
||||
return map[status] || status || '—'
|
||||
},
|
||||
rechargeWayText (way) {
|
||||
const map = { ALIPAY: '支付宝', WECHAT: '微信', BANK_TRANSFER: '线下转账' }
|
||||
return map[way] || way || '—'
|
||||
},
|
||||
withdrawStatusText (status) {
|
||||
const map = {
|
||||
APPLY: '申请中',
|
||||
VIA_AUDITING: '审核通过',
|
||||
SUCCESS: '提现成功',
|
||||
ERROR: '提现失败'
|
||||
}
|
||||
return map[status] || '审核拒绝'
|
||||
},
|
||||
// 余额日志
|
||||
changePage(v) {
|
||||
@@ -413,31 +406,167 @@ export default {
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.box {
|
||||
margin: 20px 0;
|
||||
}
|
||||
|
||||
.page-size {
|
||||
margin: 15px 0px;
|
||||
.wallet-summary {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
align-items: center;
|
||||
gap: 16px;
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
.account-price {
|
||||
font-weight: bold;
|
||||
}
|
||||
.wallet-stat {
|
||||
flex: 1;
|
||||
padding: 16px 20px;
|
||||
background: #fafafa;
|
||||
border-radius: 8px;
|
||||
|
||||
.subTips {
|
||||
margin-left: 10px;
|
||||
.label {
|
||||
color: #666;
|
||||
font-size: 14px;
|
||||
line-height: 22px;
|
||||
}
|
||||
|
||||
.value {
|
||||
margin-top: 4px;
|
||||
color: $theme_color;
|
||||
font-size: 28px;
|
||||
font-weight: 600;
|
||||
line-height: 1.2;
|
||||
|
||||
&.is-muted {
|
||||
color: #171A26;
|
||||
font-size: 22px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.account-btns {
|
||||
margin: 10px 0;
|
||||
display: flex;
|
||||
gap: 12px;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.el-button {
|
||||
margin: 0 4px;
|
||||
.op-btn,
|
||||
.ghost-btn {
|
||||
height: 32px;
|
||||
padding: 0 16px;
|
||||
border-radius: 4px;
|
||||
font-family: inherit;
|
||||
font-size: 14px;
|
||||
line-height: 30px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.op-btn {
|
||||
border: 1px solid $theme_color;
|
||||
background: $theme_color;
|
||||
color: #fff;
|
||||
|
||||
&:hover {
|
||||
opacity: 0.9;
|
||||
}
|
||||
}
|
||||
|
||||
.ghost-btn {
|
||||
border: 1px solid #ddd;
|
||||
background: #fff;
|
||||
color: #171A26;
|
||||
|
||||
&:hover {
|
||||
border-color: $theme_color;
|
||||
color: $theme_color;
|
||||
}
|
||||
}
|
||||
|
||||
.wallet-tabs {
|
||||
display: flex;
|
||||
gap: 24px;
|
||||
margin: 16px 0;
|
||||
border-bottom: 1px solid #f0f0f0;
|
||||
}
|
||||
|
||||
.wallet-tab {
|
||||
position: relative;
|
||||
padding: 10px 0;
|
||||
color: #666;
|
||||
font-size: 14px;
|
||||
line-height: 22px;
|
||||
cursor: pointer;
|
||||
|
||||
&.active {
|
||||
color: $theme_color;
|
||||
font-weight: 600;
|
||||
|
||||
&::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
height: 2px;
|
||||
background: $theme_color;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.wallet-list {
|
||||
--wallet-cols: 180px 120px minmax(0, 1fr);
|
||||
}
|
||||
|
||||
.recharge-list,
|
||||
.withdraw-list {
|
||||
--wallet-cols: 156px minmax(120px, 1.1fr) 100px 80px 80px 156px;
|
||||
}
|
||||
|
||||
.withdraw-list {
|
||||
--wallet-cols: 156px minmax(120px, 1fr) 100px 80px 156px minmax(100px, 1fr);
|
||||
}
|
||||
|
||||
.wallet-head,
|
||||
.wallet-row {
|
||||
display: grid;
|
||||
grid-template-columns: var(--wallet-cols);
|
||||
column-gap: 12px;
|
||||
align-items: start;
|
||||
}
|
||||
|
||||
.wallet-head {
|
||||
padding: 0 8px 10px;
|
||||
color: #999;
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
.wallet-row {
|
||||
padding: 14px 8px;
|
||||
border-top: 1px solid #f0f0f0;
|
||||
color: #171A26;
|
||||
font-size: 14px;
|
||||
line-height: 22px;
|
||||
}
|
||||
|
||||
.wallet-detail {
|
||||
min-width: 0;
|
||||
white-space: pre-wrap;
|
||||
word-break: break-all;
|
||||
}
|
||||
|
||||
.wallet-money {
|
||||
font-weight: 600;
|
||||
|
||||
&.is-plus {
|
||||
color: #19be6b;
|
||||
}
|
||||
|
||||
&.is-minus {
|
||||
color: $theme_color;
|
||||
}
|
||||
}
|
||||
|
||||
.page-size {
|
||||
margin: 16px 0;
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
|
||||
:deep(.el-pagination) {
|
||||
justify-content: flex-end;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<div class="wrapper my-gift-cards">
|
||||
<UserCenterLayout title="我的礼品卡" :tabs="['我的礼品卡']">
|
||||
<UserCenterLayout>
|
||||
|
||||
<div class="bind-section mb_20">
|
||||
<div class="section-title">兑换礼品卡</div>
|
||||
@@ -11,7 +11,6 @@
|
||||
<el-form-item label="兑换码" prop="cardSecret" label-width="70px">
|
||||
<el-input
|
||||
v-model="bindForm.cardSecret"
|
||||
type="password"
|
||||
placeholder="请输入兑换码(卡密)"
|
||||
maxlength="128"
|
||||
style="width: 220px"
|
||||
@@ -75,7 +74,7 @@
|
||||
<div class="page-size">
|
||||
<el-pagination v-model:current-page="params.pageNumber"
|
||||
v-model:page-size="params.pageSize"
|
||||
:page-sizes="[10, 20, 50]"
|
||||
:page-sizes="[20, 50, 100]"
|
||||
:total="total"
|
||||
@current-change="changePage"
|
||||
@size-change="changePageSize"
|
||||
@@ -111,7 +110,7 @@ export default {
|
||||
list: [],
|
||||
params: {
|
||||
pageNumber: 1,
|
||||
pageSize: 10,
|
||||
pageSize: 20,
|
||||
sort: "createTime",
|
||||
order: "desc",
|
||||
memberCardStatus: "AVAILABLE",
|
||||
@@ -372,12 +371,12 @@ export default {
|
||||
}
|
||||
.gcc-face {
|
||||
margin-top: 8px;
|
||||
font-size: 13px;
|
||||
font-size: 14px;
|
||||
opacity: 0.95;
|
||||
}
|
||||
.gcc-cardno {
|
||||
margin-top: 22px;
|
||||
font-size: 12px;
|
||||
font-size: 14px;
|
||||
letter-spacing: 0.02em;
|
||||
opacity: 0.75;
|
||||
word-break: break-all;
|
||||
@@ -393,7 +392,7 @@ export default {
|
||||
}
|
||||
.gcc-expire {
|
||||
margin-top: 10px;
|
||||
font-size: 12px;
|
||||
font-size: 14px;
|
||||
opacity: 0.9;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<div class="wrapper">
|
||||
<UserCenterLayout title="我的足迹" :tabs="['我的足迹']">
|
||||
<UserCenterLayout>
|
||||
<template #extra>
|
||||
<el-button class="del-btn" @click="clearAll" type="primary">删除全部</el-button>
|
||||
</template>
|
||||
@@ -12,9 +12,11 @@
|
||||
:key="index"
|
||||
@click="goodsDetail(item.id, item.goodsId)"
|
||||
>
|
||||
<img :src="item.thumbnail" :alt="item.goodsName" />
|
||||
<p class="ellipsis">{{ item.goodsName }}</p>
|
||||
<p>{{ $filters.unitPrice(item.price, "¥") }}</p>
|
||||
<div class="thumb">
|
||||
<img :src="item.thumbnail" :alt="item.goodsName" />
|
||||
</div>
|
||||
<p class="goods-name">{{ item.goodsName }}</p>
|
||||
<p class="goods-price">{{ $filters.unitPrice(item.price, "¥") }}</p>
|
||||
<span class="del-icon" @click.stop="clearById(item.goodsId)">
|
||||
<el-icon><Delete /></el-icon>
|
||||
</span>
|
||||
@@ -26,7 +28,7 @@
|
||||
v-model:current-page="params.pageNumber"
|
||||
v-model:page-size="params.pageSize"
|
||||
:total="total"
|
||||
:page-sizes="[10, 20, 30, 40, 50, 100]"
|
||||
:page-sizes="[20, 50, 100]"
|
||||
layout="sizes, prev, pager, next, jumper"
|
||||
@current-change="changePageNum"
|
||||
@size-change="changePageSize"
|
||||
@@ -49,7 +51,7 @@ export default {
|
||||
spinShow: false, // 控制loading是否加载
|
||||
params: {
|
||||
pageNumber: 1,
|
||||
pageSize: 10,
|
||||
pageSize: 20,
|
||||
order: "desc",
|
||||
sort: "updateTime",
|
||||
},
|
||||
@@ -135,61 +137,86 @@ export default {
|
||||
margin-bottom: 40px;
|
||||
}
|
||||
.del-btn {
|
||||
margin: 0 0 10px 15px;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.track-list {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(4, 1fr);
|
||||
gap: 12px;
|
||||
padding: 0 15px;
|
||||
box-sizing: border-box;
|
||||
grid-template-columns: repeat(4, minmax(0, 1fr));
|
||||
gap: 16px;
|
||||
margin: 4px 0 0;
|
||||
padding: 0;
|
||||
list-style: none;
|
||||
|
||||
li {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
min-width: 0;
|
||||
border: 1px solid #f0f0f0;
|
||||
border-radius: 8px;
|
||||
overflow: hidden;
|
||||
border: 1px solid #eee;
|
||||
background: #fff;
|
||||
position: relative;
|
||||
box-sizing: border-box;
|
||||
|
||||
&:hover {
|
||||
cursor: pointer;
|
||||
box-shadow: 0 4px 16px rgba(0, 0, 0, 0.08);
|
||||
|
||||
.del-icon {
|
||||
display: flex;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.thumb {
|
||||
width: 100%;
|
||||
aspect-ratio: 1;
|
||||
background: #f5f5f5;
|
||||
overflow: hidden;
|
||||
|
||||
img {
|
||||
width: 100%;
|
||||
aspect-ratio: 1;
|
||||
height: 100%;
|
||||
object-fit: cover;
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
|
||||
&:hover {
|
||||
cursor: pointer;
|
||||
box-shadow: 1px 1px 3px #999;
|
||||
.del-icon {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
p {
|
||||
padding: 0 5px;
|
||||
margin: 3px 0;
|
||||
}
|
||||
p:nth-child(2) {
|
||||
color: #999;
|
||||
}
|
||||
p:nth-child(3) {
|
||||
color: $theme_color;
|
||||
}
|
||||
.del-icon {
|
||||
display: none;
|
||||
font-size: 30px;
|
||||
background-color: rgba(0, 0, 0, 0.3);
|
||||
position: absolute;
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
line-height: 40px;
|
||||
text-align: center;
|
||||
right: 0;
|
||||
top: 0;
|
||||
cursor: pointer;
|
||||
}
|
||||
.goods-name {
|
||||
margin: 10px 12px 0;
|
||||
color: #333;
|
||||
font-size: 13px;
|
||||
line-height: 1.4;
|
||||
height: 36px;
|
||||
display: -webkit-box;
|
||||
-webkit-box-orient: vertical;
|
||||
-webkit-line-clamp: 2;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.goods-price {
|
||||
margin: 8px 12px 12px;
|
||||
color: $theme_color;
|
||||
font-size: 16px;
|
||||
font-weight: 600;
|
||||
line-height: 1.2;
|
||||
}
|
||||
|
||||
.del-icon {
|
||||
display: none;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
position: absolute;
|
||||
right: 8px;
|
||||
top: 8px;
|
||||
width: 28px;
|
||||
height: 28px;
|
||||
border-radius: 50%;
|
||||
background: rgba(0, 0, 0, 0.45);
|
||||
color: #fff;
|
||||
font-size: 14px;
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
.page-size {
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -177,7 +177,7 @@ export default {
|
||||
}
|
||||
|
||||
.left-tips-count-down {
|
||||
font-size: 10px;
|
||||
font-size: 14px;
|
||||
color: red;
|
||||
}
|
||||
|
||||
|
||||
@@ -193,7 +193,7 @@ export default {
|
||||
.qrcode-status-tip {
|
||||
margin-top: 8px;
|
||||
color: #909399;
|
||||
font-size: 12px;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.intro {
|
||||
|
||||
@@ -183,7 +183,7 @@
|
||||
>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<el-dialog title="View Image" v-model="visible">
|
||||
<el-dialog title="图片预览" v-model="visible">
|
||||
<img :src="previewPicture" v-if="visible" style="width: 100%" />
|
||||
</el-dialog>
|
||||
|
||||
|
||||
@@ -86,7 +86,7 @@
|
||||
>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<el-dialog title="View Image" v-model="visible">
|
||||
<el-dialog title="图片预览" v-model="visible">
|
||||
<img :src="previewPicture" v-if="visible" style="width: 100%" />
|
||||
</el-dialog>
|
||||
<multipleMap ref="map" @callback="getAddress" />
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<div>
|
||||
<div class="user-home-page">
|
||||
<BaseHeader></BaseHeader>
|
||||
|
||||
<div class="container width_1200">
|
||||
@@ -68,6 +68,12 @@ export default {
|
||||
return {};
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
document.body.classList.add("buyer-user-center");
|
||||
},
|
||||
beforeUnmount() {
|
||||
document.body.classList.remove("buyer-user-center");
|
||||
},
|
||||
methods: {
|
||||
onSelect(name) {
|
||||
this.$router.push({ name });
|
||||
@@ -134,3 +140,38 @@ export default {
|
||||
text-align: center;
|
||||
}
|
||||
</style>
|
||||
|
||||
<style lang="scss">
|
||||
/* 会员中心按钮统一放大一号:small→默认,默认→large,large→48px。弹窗挂到 body,靠页面 class 一起放大。 */
|
||||
body.buyer-user-center {
|
||||
.user-home-page .content .el-button.el-button--small:not(.is-link):not(.is-text),
|
||||
.el-overlay .el-button.el-button--small:not(.is-link):not(.is-text) {
|
||||
height: 32px;
|
||||
padding: 8px 15px;
|
||||
font-size: var(--el-font-size-base);
|
||||
border-radius: var(--el-border-radius-base);
|
||||
}
|
||||
|
||||
.user-home-page .content .el-button:not(.el-button--small):not(.el-button--large):not(.is-link):not(.is-text),
|
||||
.el-overlay .el-button:not(.el-button--small):not(.el-button--large):not(.is-link):not(.is-text) {
|
||||
height: 40px;
|
||||
padding: 12px 19px;
|
||||
font-size: var(--el-font-size-base);
|
||||
border-radius: var(--el-border-radius-base);
|
||||
}
|
||||
|
||||
.user-home-page .content .el-button.el-button--large:not(.is-link):not(.is-text),
|
||||
.el-overlay .el-button.el-button--large:not(.is-link):not(.is-text) {
|
||||
--el-button-size: 48px;
|
||||
height: var(--el-button-size);
|
||||
padding: 16px 23px;
|
||||
font-size: var(--el-font-size-base);
|
||||
border-radius: var(--el-border-radius-base);
|
||||
}
|
||||
|
||||
.user-home-page .content .el-button.is-link.el-button--small,
|
||||
.el-overlay .el-button.is-link.el-button--small {
|
||||
font-size: var(--el-font-size-base);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -303,7 +303,7 @@ export const router = createRouter({
|
||||
path: "MsgDetail",
|
||||
name: "MsgDetail",
|
||||
component: MsgDetail,
|
||||
meta: { title: "我的消息" },
|
||||
meta: { title: "消息详情" },
|
||||
},
|
||||
{
|
||||
path: "MyOrder",
|
||||
|
||||
@@ -1,59 +1,16 @@
|
||||
/**
|
||||
* 买家端登录态与商品详情跳转校验
|
||||
* 买家端内部链接跳转(首页装修、列表等共用)
|
||||
*
|
||||
* @author Mike
|
||||
* @date 2026-08-05
|
||||
*/
|
||||
import storage from "@/plugins/storage";
|
||||
|
||||
export function isBuyerLoggedIn() {
|
||||
const rawUserInfo = storage.getItem("userInfo");
|
||||
if (rawUserInfo) {
|
||||
try {
|
||||
return !!JSON.parse(rawUserInfo).username;
|
||||
} catch {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return !!storage.getItem("accessToken");
|
||||
}
|
||||
|
||||
export function parseInternalLink(url) {
|
||||
const [path, search = ""] = url.split("?");
|
||||
const query = {};
|
||||
if (search) {
|
||||
new URLSearchParams(search).forEach((value, key) => {
|
||||
query[key] = value;
|
||||
});
|
||||
}
|
||||
return { path, query };
|
||||
}
|
||||
|
||||
export function isGoodsDetailPath(path) {
|
||||
return path === "/goodsDetail";
|
||||
}
|
||||
|
||||
export function redirectToLogin(router, location) {
|
||||
router.push({
|
||||
path: "/login",
|
||||
query: {
|
||||
rePath: location.path,
|
||||
query: JSON.stringify(location.query || {}),
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
/** 内部链接跳转;访问商品详情前校验登录(首页装修、列表等共用) */
|
||||
/** 内部链接新窗口打开,外链直接打开。浏览商品详情不要求登录。 */
|
||||
export function openLink(url, router) {
|
||||
if (!url) return;
|
||||
if (url.charAt(0) !== "/") {
|
||||
window.open(url, "_blank");
|
||||
return;
|
||||
}
|
||||
const location = parseInternalLink(url);
|
||||
if (!isBuyerLoggedIn() && isGoodsDetailPath(location.path)) {
|
||||
redirectToLogin(router, location);
|
||||
return;
|
||||
}
|
||||
window.open(router.resolve(url).href, "_blank");
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user