mirror of
https://gitee.com/beijing_hongye_huicheng/lilishop-ui.git
synced 2026-11-13 04:18:55 +08:00
feat(buyer): 新增功能并优化样式,提升用户体验
- 新增 `getMemberMessage` 接口方法,用于获取会员消息 - 调整全局及商品列表样式,提升可读性与一致性 - 精简 `Search.vue`,移除不必要的店铺搜索切换 - 放宽 `addressManage` 中地址别名的输入长度 - 优化 `ShowGoods.vue` 和 `ShowGoodsDetail.vue` 的布局与样式 - 更新 `Cart.vue` 中的购物车步骤展示,让流程导航更清晰 - 调整多个组件,统一字号并优化界面元素
This commit is contained in:
@@ -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 {
|
||||
|
||||
Reference in New Issue
Block a user