style(member): 统一会员中心页面风格(卡片面板/状态标签/链接按钮/右对齐分页)

This commit is contained in:
pikachu1995@126.com
2026-10-26 17:01:30 +08:00
parent 1f872254cc
commit b72c792ade
15 changed files with 269 additions and 452 deletions

View File

@@ -27,9 +27,9 @@
</div> </div>
<div class="connect-row"> <div class="connect-row">
<span class="connect-name">{{ wechatConnect.label }}</span> <span class="connect-name">{{ wechatConnect.label }}</span>
<span class="connect-status" :class="{ 'is-bound': isBound(wechatConnect.type) }"> <el-tag :type="isBound(wechatConnect.type) ? 'success' : 'info'" size="small">
{{ isBound(wechatConnect.type) ? "已绑定" : "未绑定" }} {{ isBound(wechatConnect.type) ? "已绑定" : "未绑定" }}
</span> </el-tag>
<el-skeleton v-if="connectLoading" animated class="connect-skeleton" /> <el-skeleton v-if="connectLoading" animated class="connect-skeleton" />
</div> </div>
</div> </div>
@@ -277,8 +277,9 @@ onMounted(() => {
.safe-card { .safe-card {
padding: 20px; padding: 20px;
border: 1px solid #f0f0f0; border: 1px solid #eee;
border-radius: 8px; border-radius: 8px;
background: #fff;
} }
.safe-card-connect { .safe-card-connect {
@@ -295,7 +296,7 @@ onMounted(() => {
width: 48px; width: 48px;
height: 48px; height: 48px;
border-radius: 8px; border-radius: 8px;
background: #fff5f4; background: color-mix(in srgb, #{$theme_color} 8%, #fff);
color: $theme_color; color: $theme_color;
display: flex; display: flex;
align-items: center; align-items: center;
@@ -309,7 +310,7 @@ onMounted(() => {
.safe-title { .safe-title {
margin: 0; margin: 0;
color: #171A26; color: #333;
font-size: 16px; font-size: 16px;
font-weight: 600; font-weight: 600;
line-height: 24px; line-height: 24px;
@@ -333,26 +334,11 @@ onMounted(() => {
} }
.connect-name { .connect-name {
color: #171A26; color: #333;
font-size: 14px; font-size: 14px;
line-height: 22px; line-height: 22px;
} }
.connect-status {
height: 22px;
padding: 0 8px;
border-radius: 4px;
background: #f5f5f5;
color: #999;
font-size: 12px;
line-height: 22px;
}
.connect-status.is-bound {
background: #f0faf3;
color: #1f9d55;
}
.connect-skeleton { .connect-skeleton {
width: 120px; width: 120px;
height: 22px; height: 22px;

View File

@@ -34,7 +34,7 @@
<div class="comment-cell">{{ item.grade === 'GOOD' ? '好评' : item.grade === 'WORSE' ? '差评' : '中评' }}</div> <div class="comment-cell">{{ item.grade === 'GOOD' ? '好评' : item.grade === 'WORSE' ? '差评' : '中评' }}</div>
<div class="comment-content">{{ item.content }}</div> <div class="comment-content">{{ item.content }}</div>
<div class="comment-ops"> <div class="comment-ops">
<button type="button" class="text-link" @click="evaluateDetail(item.id)">评价详情</button> <el-button link type="primary" @click="evaluateDetail(item.id)">评价详情</el-button>
</div> </div>
</div> </div>
</div> </div>
@@ -230,19 +230,4 @@ onMounted(() => {
display: flex; display: flex;
justify-content: center; 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;
}
}
</style> </style>

View File

@@ -32,17 +32,19 @@
{{ item.goodsName }} {{ item.goodsName }}
</div> </div>
</div> </div>
<div class="complain-cell">{{ statusLabel[item.complainStatus] || item.complainStatus }}</div> <div class="complain-cell">
<el-tag size="small" :type="statusTagType(item.complainStatus)">{{ statusLabel[item.complainStatus] || item.complainStatus }}</el-tag>
</div>
<div class="complain-topic">{{ item.complainTopic }}</div> <div class="complain-topic">{{ item.complainTopic }}</div>
<div class="complain-content">{{ item.content }}</div> <div class="complain-content">{{ item.content }}</div>
<div class="complain-ops"> <div class="complain-ops">
<button type="button" class="text-link" @click="goDetail(item.id)">投诉详情</button> <el-button link type="primary" @click="goDetail(item.id)">投诉详情</el-button>
<button <el-button
v-if="item.complainStatus === 'APPLYING' || item.complainStatus === 'NEW'" v-if="item.complainStatus === 'APPLYING' || item.complainStatus === 'NEW'"
type="button" link
class="text-link" type="danger"
@click="cancel(item.id)" @click="cancel(item.id)"
>取消投诉</button> >取消投诉</el-button>
</div> </div>
</div> </div>
</div> </div>
@@ -84,6 +86,18 @@ const params = reactive({ // 请求参数
pageSize: 20 pageSize: 20
}); });
function statusTagType(status) { // 投诉状态标签类型
const map = {
COMPLETE: 'success',
APPLYING: 'warning',
NEW: 'warning',
CANCEL: 'info',
EXPIRED: 'info',
NO_APPLY: 'info'
};
return map[status] || 'info';
}
function getList() { // 获取投诉列表 function getList() { // 获取投诉列表
complainList(params).then(res => { complainList(params).then(res => {
if (res.success) { if (res.success) {
@@ -268,20 +282,9 @@ onMounted(() => {
flex-direction: column; flex-direction: column;
align-items: center; align-items: center;
gap: 8px; gap: 8px;
}
.text-link { .el-button + .el-button {
border: none; margin-left: 0;
background: none;
padding: 0;
color: #171A26;
font-family: inherit;
font-size: 14px;
line-height: 22px;
cursor: pointer;
&:hover {
color: $theme_color;
} }
} }
</style> </style>

View File

@@ -33,10 +33,10 @@
</div> </div>
<div v-if="params.type === 'GOODS'" class="fav-price">{{ $filters.unitPrice(item.price, '¥') }}</div> <div v-if="params.type === 'GOODS'" class="fav-price">{{ $filters.unitPrice(item.price, '¥') }}</div>
<div class="fav-ops"> <div class="fav-ops">
<button v-if="params.type === 'GOODS'" type="button" class="op-btn" @click="buynow(item.skuId, item.goodsId)">立即购买</button> <el-button v-if="params.type === 'GOODS'" type="primary" size="small" @click="buynow(item.skuId, item.goodsId)">立即购买</el-button>
<button v-else type="button" class="op-btn" @click="goShop(item.id)">查看店铺</button> <el-button v-else type="primary" size="small" @click="goShop(item.id)">查看店铺</el-button>
<button v-if="params.type === 'GOODS'" type="button" class="text-link" @click="cancel(item.skuId)">取消收藏</button> <el-button v-if="params.type === 'GOODS'" link type="danger" @click="cancel(item.skuId)">取消收藏</el-button>
<button v-else type="button" class="text-link" @click="cancelStore(item.id)">取消收藏</button> <el-button v-else link type="danger" @click="cancelStore(item.id)">取消收藏</el-button>
</div> </div>
</div> </div>
<el-skeleton size="large" fix v-if="spinShow"></el-skeleton> <el-skeleton size="large" fix v-if="spinShow"></el-skeleton>
@@ -72,10 +72,10 @@
</div> </div>
<div v-if="params.type === 'GOODS'" class="fav-price">{{ $filters.unitPrice(item.price, '¥') }}</div> <div v-if="params.type === 'GOODS'" class="fav-price">{{ $filters.unitPrice(item.price, '¥') }}</div>
<div class="fav-ops"> <div class="fav-ops">
<button v-if="params.type === 'GOODS'" type="button" class="op-btn" @click="buynow(item.skuId, item.goodsId)">立即购买</button> <el-button v-if="params.type === 'GOODS'" type="primary" size="small" @click="buynow(item.skuId, item.goodsId)">立即购买</el-button>
<button v-else type="button" class="op-btn" @click="goShop(item.id)">查看店铺</button> <el-button v-else type="primary" size="small" @click="goShop(item.id)">查看店铺</el-button>
<button v-if="params.type === 'GOODS'" type="button" class="text-link" @click="cancel(item.skuId)">取消收藏</button> <el-button v-if="params.type === 'GOODS'" link type="danger" @click="cancel(item.skuId)">取消收藏</el-button>
<button v-else type="button" class="text-link" @click="cancelStore(item.id)">取消收藏</button> <el-button v-else link type="danger" @click="cancelStore(item.id)">取消收藏</el-button>
</div> </div>
</div> </div>
<el-skeleton size="large" fix v-if="spinShow"></el-skeleton> <el-skeleton size="large" fix v-if="spinShow"></el-skeleton>
@@ -316,7 +316,7 @@ onMounted(() => {
margin-top: 6px; margin-top: 6px;
padding: 0 6px; padding: 0 6px;
border-radius: 4px; border-radius: 4px;
background: #fff1f0; background: color-mix(in srgb, #{$theme_color} 8%, #fff);
color: $theme_color; color: $theme_color;
font-size: 12px; font-size: 12px;
line-height: 20px; line-height: 20px;
@@ -336,37 +336,4 @@ onMounted(() => {
justify-content: center; justify-content: center;
gap: 16px; gap: 16px;
} }
.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;
}
}
</style> </style>

View File

@@ -15,10 +15,10 @@
<template #append><span>输入验证码</span></template> <template #append><span>输入验证码</span></template>
</el-input> </el-input>
</el-form-item> </el-form-item>
<el-form-item>
<el-button type="primary" @click="submitRegister">下一步</el-button>
</el-form-item>
</el-form> </el-form>
<div v-if="(status == 2 || status == 3) && !showPwd" style="text-align: center;width: 50%">
<el-button type="primary" class="ml_10" @click="submitRegister">下一步</el-button>
</div>
<!-- 修改 --> <!-- 修改 -->
<el-form ref="formRegisterRef" :model="formRegister" :rules="ruleInline" label-width="80px" v-if="status == 1 && !showPwd"> <el-form ref="formRegisterRef" :model="formRegister" :rules="ruleInline" label-width="80px" v-if="status == 1 && !showPwd">
@@ -43,11 +43,10 @@
<template #prepend><el-icon><Lock /></el-icon></template> <template #prepend><el-icon><Lock /></el-icon></template>
</el-input> </el-input>
</el-form-item> </el-form-item>
<el-form-item>
<el-button type="primary" @click="handleRegist">修改</el-button>
</el-form-item>
</el-form> </el-form>
<div v-if="status == 1 && !showPwd" style="width: 50%;text-align: center">
<el-button type="primary" class="ml_10" @click="handleRegist">修改</el-button>
</div>
<!-- 设置&修改的第二种情况 --> <!-- 设置&修改的第二种情况 -->
<el-form ref="formDataUpdateRef" :model="formDataUpdate" label-position="left" label-width="100px" :rules="ruleIn" <el-form ref="formDataUpdateRef" :model="formDataUpdate" label-position="left" label-width="100px" :rules="ruleIn"
v-if="showPwd"> v-if="showPwd">
@@ -65,10 +64,10 @@
<template #prepend><el-icon><Lock /></el-icon></template> <template #prepend><el-icon><Lock /></el-icon></template>
</el-input> </el-input>
</el-form-item> </el-form-item>
<el-form-item>
<el-button type="primary" @click="setPassword">设置</el-button>
</el-form-item>
</el-form> </el-form>
<div v-if="showPwd" style="text-align: center;width: 50%">
<el-button type="primary" class="ml_10" @click="setPassword">设置</el-button>
</div>
</UserCenterLayout> </UserCenterLayout>
</div> </div>
</template> </template>
@@ -252,9 +251,6 @@ onMounted(() => {
</script> </script>
<style scoped lang="scss"> <style scoped lang="scss">
.wrapper {
text-align: center;
}
.phone { .phone {
text-align: left; text-align: left;
} }

View File

@@ -87,10 +87,10 @@ onMounted(() => {
<style lang="scss" scoped> <style lang="scss" scoped>
h3 { h3 {
margin: 8px 0 12px; margin: 8px 0 12px;
font-size: 15px; font-size: 16px;
font-weight: 600; font-weight: 600;
color: #333; color: #333;
line-height: 1.4; line-height: 24px;
} }
.point-summary { .point-summary {
@@ -102,7 +102,8 @@ h3 {
.point-stat { .point-stat {
flex: 1; flex: 1;
padding: 16px 20px; padding: 16px 20px;
background: #fafafa; background: #fff;
border: 1px solid #eee;
border-radius: 8px; border-radius: 8px;
.label { .label {

View File

@@ -13,7 +13,7 @@
:action="action" :action="action"
:headers="accessToken" :headers="accessToken"
> >
<button type="button" class="ghost-btn">上传头像</button> <el-button size="small">上传头像</el-button>
</el-upload> </el-upload>
</div> </div>
</el-form-item> </el-form-item>
@@ -29,13 +29,13 @@
/> />
</el-form-item> </el-form-item>
<el-form-item label="性别"> <el-form-item label="性别">
<div class="sex-group"> <el-radio-group v-model="formItem.sex">
<button type="button" class="sex-btn" :class="{ active: formItem.sex === 1 }" @click="formItem.sex = 1">男</button> <el-radio-button :value="1">男</el-radio-button>
<button type="button" class="sex-btn" :class="{ active: formItem.sex === 0 }" @click="formItem.sex = 0">女</button> <el-radio-button :value="0">女</el-radio-button>
</div> </el-radio-group>
</el-form-item> </el-form-item>
<el-form-item> <el-form-item>
<button type="button" class="op-btn" @click="save">确认修改</button> <el-button type="primary" @click="save">确认修改</el-button>
</el-form-item> </el-form-item>
</el-form> </el-form>
</UserCenterLayout> </UserCenterLayout>
@@ -167,7 +167,7 @@ function handleSuccess (res, file) { // 上传成功
:deep(.el-form-item__label) { :deep(.el-form-item__label) {
height: auto; height: auto;
line-height: 22px; line-height: 22px;
color: #666; color: #999;
font-size: 14px; font-size: 14px;
} }
@@ -199,51 +199,5 @@ function handleSuccess (res, file) { // 上传成功
:deep(.profile-field.el-date-editor) { :deep(.profile-field.el-date-editor) {
width: 320px; 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> </style>

View File

@@ -4,7 +4,7 @@
<div class="order-card status-card" v-if="orderGoods.goodsName || orderGoods.content"> <div class="order-card status-card" v-if="orderGoods.goodsName || orderGoods.content">
<div class="status-head"> <div class="status-head">
<div class="status-main"> <div class="status-main">
<p class="status-text">{{ gradeText }}</p> <el-tag :type="gradeTagType" effect="dark">{{ gradeText }}</el-tag>
<p class="status-sn">评价时间:{{ orderGoods.createTime }}</p> <p class="status-sn">评价时间:{{ orderGoods.createTime }}</p>
</div> </div>
</div> </div>
@@ -99,6 +99,10 @@ const gradeText = computed(() => {
const map = { GOOD: '好评', MODERATE: '中评', WORSE: '差评' } const map = { GOOD: '好评', MODERATE: '中评', WORSE: '差评' }
return map[orderGoods.value.grade] || '评价详情' return map[orderGoods.value.grade] || '评价详情'
}); });
const gradeTagType = computed(() => {
const map = { GOOD: 'success', MODERATE: 'warning', WORSE: 'info' }
return map[orderGoods.value.grade] || 'info'
});
function getDetail() { function getDetail() {
// 获取评价详情 // 获取评价详情
@@ -130,33 +134,23 @@ onMounted(() => {
} }
.order-card { .order-card {
padding: 4px 0 16px; margin-top: 16px;
margin-bottom: 8px; padding: 16px 20px;
border-bottom: 1px solid #f0f0f0; border: 1px solid #eee;
border-radius: 8px;
background: #fff;
h3 { h3 {
margin: 0 0 12px; margin: 0 0 12px;
font-size: 15px; font-size: 16px;
font-weight: 600; font-weight: 600;
color: #333; color: #333;
line-height: 1.4; line-height: 24px;
}
&:last-of-type {
border-bottom: none;
} }
} }
.status-card { .status-card {
padding-top: 8px; margin-top: 0;
}
.status-text {
margin: 0;
color: $theme_color;
font-size: 18px;
font-weight: 600;
line-height: 1.4;
} }
.status-sn { .status-sn {

View File

@@ -33,7 +33,9 @@
<div class="order-sn"> <div class="order-sn">
{{ order.createTime }}<span>售后单号 {{ order.sn }}</span><span class="order-store" @click="shopPage(order.storeId)">{{ order.storeName }}</span> {{ order.createTime }}<span>售后单号 {{ order.sn }}</span><span class="order-store" @click="shopPage(order.storeId)">{{ order.storeName }}</span>
</div> </div>
<div class="order-status">{{ filterOrderStatus(order.serviceStatus) }}</div> <div class="order-status">
<el-tag size="small" :type="statusTagType(order.serviceStatus)">{{ filterOrderStatus(order.serviceStatus) }}</el-tag>
</div>
</div> </div>
<div class="order-body"> <div class="order-body">
<div class="col-detail"> <div class="col-detail">
@@ -59,19 +61,19 @@
<div class="order-amount">{{ $filters.unitPrice(order.applyRefundPrice, "¥") }}</div> <div class="order-amount">{{ $filters.unitPrice(order.applyRefundPrice, "¥") }}</div>
</div> </div>
<div class="col-ops"> <div class="col-ops">
<button <el-button
v-if="order.serviceStatus == 'PASS' && order.serviceType != 'RETURN_MONEY'" v-if="order.serviceStatus == 'PASS' && order.serviceType != 'RETURN_MONEY'"
type="button" type="primary"
class="op-btn" size="small"
@click="openModal(order)" @click="openModal(order)"
>提交物流</button> >提交物流</el-button>
<button type="button" class="text-link" @click="goDetail(order.sn)">售后详情</button> <el-button link type="primary" @click="goDetail(order.sn)">售后详情</el-button>
<button <el-button
v-if="order.afterSaleAllowOperationVO && order.afterSaleAllowOperationVO.cancel" v-if="order.afterSaleAllowOperationVO && order.afterSaleAllowOperationVO.cancel"
type="button" link
class="text-link" type="danger"
@click="cancel(order.sn)" @click="cancel(order.sn)"
>取消售后</button> >取消售后</el-button>
</div> </div>
</div> </div>
</div> </div>
@@ -253,6 +255,14 @@ function filterOrderStatus(status) { // 获取订单状态中文
}); });
return ob && ob[0] ? ob[0].name : status return ob && ob[0] ? ob[0].name : status
} }
function statusTagType(status) { // 售后状态对应标签类型
const map = {
APPLY: 'warning', APPLYING: 'warning',
COMPLETE: 'success',
CANCEL: 'info', EXPIRED: 'info'
}
return map[status] || 'info'
}
// 获取物流公司列表 // 获取物流公司列表
function getCompany() { function getCompany() {
getLogisticsCompany().then(res => { getLogisticsCompany().then(res => {
@@ -372,7 +382,7 @@ onMounted(() => {
align-items: center; align-items: center;
min-width: 0; min-width: 0;
font-size: 14px; font-size: 14px;
color: #171A26; color: #333;
line-height: 1.5; line-height: 1.5;
span { span {
@@ -476,38 +486,9 @@ onMounted(() => {
flex-direction: column; flex-direction: column;
align-items: center; align-items: center;
gap: 8px; gap: 8px;
}
.op-btn { :deep(.el-button + .el-button) {
min-width: 96px; margin-left: 0;
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;
} }
} }
} }

View File

@@ -1,10 +1,10 @@
<template> <template>
<div class="order-detail"> <div class="order-detail">
<UserCenterLayout> <UserCenterLayout>
<div class="order-card status-card" v-if="afterSale.sn"> <div class="panel" v-if="afterSale.sn">
<div class="status-head"> <div class="status-head">
<div class="status-main"> <div class="status-main">
<p class="status-text">{{ afterSale.serviceName }}</p> <el-tag :type="statusTagType" effect="dark">{{ afterSale.serviceName }}</el-tag>
<p class="status-sn"> <p class="status-sn">
售后单号:{{ afterSale.sn }} 售后单号:{{ afterSale.sn }}
<span>订单号:{{ afterSale.orderSn }}</span> <span>订单号:{{ afterSale.orderSn }}</span>
@@ -13,8 +13,8 @@
<div class="status-side"> <div class="status-side">
<div class="operation-time">创建时间:{{ afterSale.createTime }}</div> <div class="operation-time">创建时间:{{ afterSale.createTime }}</div>
<div class="status-actions" v-if="canSubmitLogistics || canCancel"> <div class="status-actions" v-if="canSubmitLogistics || canCancel">
<button v-if="canSubmitLogistics" type="button" class="op-btn" @click="openModal">提交物流</button> <el-button v-if="canSubmitLogistics" type="primary" size="small" @click="openModal">提交物流</el-button>
<button v-if="canCancel" type="button" class="text-link" @click="cancel(afterSale.sn)">取消售后</button> <el-button v-if="canCancel" link type="primary" @click="cancel(afterSale.sn)">取消售后</el-button>
</div> </div>
</div> </div>
</div> </div>
@@ -28,7 +28,7 @@
</div> </div>
</div> </div>
</div> </div>
<div class="order-card" v-if="logList.length"> <div class="panel" v-if="logList.length">
<h3>售后进程</h3> <h3>售后进程</h3>
<el-steps <el-steps
class="progress" class="progress"
@@ -43,50 +43,48 @@
></el-step> ></el-step>
</el-steps> </el-steps>
</div> </div>
<div class="order-card"> <div class="panel">
<h3>服务单信息</h3> <h3>服务单信息</h3>
<div class="info-list"> <div class="info-row">
<span class="info-label">退款方式</span>
<span class="info-value">{{ afterSale.refundWay == 'ORIGINAL' ? '原路退回' : '账号退款' }}</span>
</div>
<div class="info-row">
<span class="info-label">申请退款金额</span>
<span class="info-value">{{ $filters.unitPrice(afterSale.applyRefundPrice, '¥') }}</span>
</div>
<div class="info-row" v-if="afterSale.actualRefundPrice">
<span class="info-label">实际退款金额</span>
<span class="info-value">{{ $filters.unitPrice(afterSale.actualRefundPrice, '¥') }}</span>
</div>
<template v-if="afterSale.refundWay === 'OFFLINE'">
<div class="info-row"> <div class="info-row">
<span class="label">退款方式</span> <span class="info-label">退款开户行</span>
<span>{{ afterSale.refundWay == 'ORIGINAL' ? '原路退回' : '账号退款' }}</span> <span class="info-value">{{ afterSale.bankDepositName }}</span>
</div> </div>
<div class="info-row"> <div class="info-row">
<span class="label">申请退款金额</span> <span class="info-label">退款开户名</span>
<span>{{ $filters.unitPrice(afterSale.applyRefundPrice, '¥') }}</span> <span class="info-value">{{ afterSale.bankAccountName }}</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'">
<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>
<div class="info-row">
<span class="label">商品处理方式</span>
<span>{{ afterSale.serviceType == 'RETURN_MONEY' ? '退款' : '退货' }}</span>
</div> </div>
<div class="info-row"> <div class="info-row">
<span class="label">退款原因</span> <span class="info-label">退款卡号</span>
<span>{{ afterSale.reasonName }}</span> <span class="info-value">{{ afterSale.bankAccountNumber }}</span>
</div>
<div class="info-row">
<span class="label">问题描述</span>
<span>{{ afterSale.problemDesc }}</span>
</div> </div>
</template>
<div class="info-row">
<span class="info-label">商品处理方式</span>
<span class="info-value">{{ afterSale.serviceType == 'RETURN_MONEY' ? '退款' : '退货' }}</span>
</div>
<div class="info-row">
<span class="info-label">退款原因</span>
<span class="info-value">{{ afterSale.reasonName }}</span>
</div>
<div class="info-row">
<span class="info-label">问题描述</span>
<span class="info-value">{{ afterSale.problemDesc }}</span>
</div> </div>
</div> </div>
<div class="order-card" v-if="afterSale.afterSaleImage"> <div class="panel" v-if="afterSale.afterSaleImage">
<h3>图片信息</h3> <h3>图片信息</h3>
<div class="image-list"> <div class="image-list">
<img <img
@@ -175,6 +173,22 @@ const canCancel = computed(() => {
return afterSale.value.afterSaleAllowOperationVO && afterSale.value.afterSaleAllowOperationVO.cancel return afterSale.value.afterSaleAllowOperationVO && afterSale.value.afterSaleAllowOperationVO.cancel
}); });
const statusTagType = computed(() => {
const map = {
APPLY: 'warning',
PASS: 'success',
REFUSE: 'info',
BUYER_RETURN: 'warning',
SELLER_CONFIRM: 'warning',
SELLER_TERMINATION: 'info',
BUYER_CONFIRM: 'warning',
BUYER_CANCEL: 'info',
COMPLETE: 'success',
WAIT_REFUND: 'warning'
};
return map[afterSale.value.serviceStatus] || 'info';
});
function getDetail () { // 售后详情 function getDetail () { // 售后详情
afterSaleDetail(route.query.sn).then(res => { afterSaleDetail(route.query.sn).then(res => {
if (res.success) { if (res.success) {
@@ -286,26 +300,22 @@ onMounted(() => {
color: #333; color: #333;
} }
.order-card { .panel {
padding: 4px 0 16px; margin-top: 16px;
margin-bottom: 8px; padding: 16px 20px;
border-bottom: 1px solid #f0f0f0; border: 1px solid #eee;
border-radius: 8px;
background: #fff;
h3 { h3 {
margin: 0 0 12px; margin: 0 0 12px;
font-size: 15px; padding-bottom: 12px;
border-bottom: 1px solid #f5f5f5;
font-size: 16px;
font-weight: 600; font-weight: 600;
color: #333; color: #333;
line-height: 1.4; line-height: 24px;
} }
&:last-child {
border-bottom: none;
}
}
.status-card {
padding-top: 8px;
} }
.status-head { .status-head {
@@ -315,17 +325,16 @@ onMounted(() => {
gap: 16px; gap: 16px;
} }
.status-text { .status-main {
margin: 0; display: flex;
color: $theme_color; align-items: center;
font-size: 18px; gap: 12px;
font-weight: 600; flex-wrap: wrap;
line-height: 1.4;
} }
.status-sn { .status-sn {
margin: 6px 0 0; margin: 0;
color: #171A26; color: #999;
font-size: 14px; font-size: 14px;
line-height: 22px; line-height: 22px;
@@ -340,7 +349,7 @@ onMounted(() => {
} }
.operation-time { .operation-time {
color: #171A26; color: #999;
font-size: 14px; font-size: 14px;
line-height: 22px; line-height: 22px;
} }
@@ -392,7 +401,7 @@ onMounted(() => {
span { span {
margin: 0 4px; margin: 0 4px;
color: #438cde; color: #333;
cursor: pointer; cursor: pointer;
&:hover { &:hover {
@@ -435,35 +444,30 @@ onMounted(() => {
} }
} }
.info-list {
border: 1px solid #f0f0f0;
border-radius: 8px;
overflow: hidden;
}
.info-row { .info-row {
display: grid; display: flex;
grid-template-columns: 140px minmax(0, 1fr); gap: 16px;
min-height: 44px; padding: 12px 0;
border-top: 1px solid #f0f0f0; border-bottom: 1px solid #f5f5f5;
font-size: 14px; font-size: 14px;
line-height: 22px; line-height: 22px;
&:first-child { &:last-child {
border-top: none; border-bottom: none;
padding-bottom: 4px;
} }
}
span { .info-label {
display: flex; flex: 0 0 96px;
align-items: center; color: #999;
padding: 10px 16px; }
color: #171A26;
}
.label { .info-value {
background: #fafafa; flex: 1;
color: #666; min-width: 0;
} color: #333;
word-break: break-all;
} }
.image-list { .image-list {
@@ -480,37 +484,4 @@ onMounted(() => {
cursor: pointer; cursor: pointer;
} }
} }
.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;
}
}
</style> </style>

View File

@@ -1,26 +1,20 @@
<template> <template>
<div class="apply-after-sale"> <div class="apply-after-sale">
<UserCenterLayout> <UserCenterLayout>
<el-table :data="goodsData" border> <div class="goods-row" v-for="(goods, index) in goodsData" :key="index">
<el-table-column label="商品名称"> <img class="goods-img" :src="goods.image" loading="lazy" decoding="async" alt="">
<template #default="{ row }"> <div class="goods-info">
<div style="padding:5px;display:flex;"> <div class="goods-name">{{ goods.goodsName }}</div>
<img :src="row.image" loading="lazy" decoding="async" style="vertical-align: top;" width="60" height="60" alt=""> <div class="goods-meta">
<span class="ml_10">{{ row.goodsName }}</span> <span class="goods-price">{{ $filters.unitPrice(goods.applyRefundPrice, '¥') }}</span>
</div> <span class="goods-num">×{{ goods.num }}</span>
</template> </div>
</el-table-column> </div>
<el-table-column label="价格"> </div>
<template #default="{ row }">
<div>{{ $filters.unitPrice(row.applyRefundPrice, '¥') }}</div>
</template>
</el-table-column>
<el-table-column prop="num" label="购买数量" />
</el-table>
<div> <div>
<el-form :model="form" ref="formRef" class="mt_10" :rules="rules" label-width="80px"> <el-form :model="form" ref="formRef" class="mt_10" :rules="rules" label-width="80px">
<el-form-item label="售后类别"> <el-form-item label="售后类别">
<el-radio-group v-model="form.serviceType" @change="changeReason" type="button" button-style="solid"> <el-radio-group v-model="form.serviceType" @change="changeReason">
<el-radio v-if="info.returnGoods" label="RETURN_GOODS">退货</el-radio> <el-radio v-if="info.returnGoods" label="RETURN_GOODS">退货</el-radio>
<el-radio v-if="info.returnMoney" label="RETURN_MONEY">退款</el-radio> <el-radio v-if="info.returnMoney" label="RETURN_MONEY">退款</el-radio>
</el-radio-group> </el-radio-group>
@@ -224,6 +218,50 @@ onMounted(() => {
<style lang="scss" scoped> <style lang="scss" scoped>
/** 商品信息 */ /** 商品信息 */
.goods-row {
display: flex;
align-items: center;
padding: 12px 0;
}
.goods-img {
width: 56px;
height: 56px;
flex-shrink: 0;
border: 1px solid #f0f0f0;
border-radius: 4px;
object-fit: cover;
}
.goods-info {
min-width: 0;
margin-left: 12px;
}
.goods-name {
color: #333;
font-size: 14px;
line-height: 22px;
}
.goods-meta {
display: flex;
align-items: center;
gap: 12px;
margin-top: 4px;
}
.goods-price {
color: $theme_color;
font-size: 14px;
font-weight: 600;
}
.goods-num {
color: #999;
font-size: 14px;
}
.order-price { .order-price {
text-align: right; text-align: right;
margin-top: 30px; margin-top: 30px;

View File

@@ -164,17 +164,6 @@ onMounted(() => {
}) })
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.delivery-rate {
display: flex;
align-items: center;
margin-top: 20px;
height: 50px;
border-bottom: 1px solid #eee;
>div:nth-child(1) {
width: 30%;
font-weight: bold;
}
}
.goods-eval{ .goods-eval{
display: flex; display: flex;
.goods-con { .goods-con {

View File

@@ -30,7 +30,7 @@
</div> </div>
</div> </div>
</div> </div>
<el-empty v-else description="暂无收货地址" /> <empty v-else _Title="暂无收货地址" />
</UserCenterLayout> </UserCenterLayout>
</div> </div>
</template> </template>
@@ -130,7 +130,7 @@ onMounted(() => {
.address-name { .address-name {
font-size: 16px; font-size: 16px;
font-weight: 600; font-weight: 600;
color: $light_title_color; color: #333;
} }
.address-mobile { .address-mobile {
@@ -183,13 +183,13 @@ onMounted(() => {
} }
.del-btn:hover { .del-btn:hover {
color: #f56c6c; color: $theme_color;
} }
} }
.default-address-tag { .default-address-tag {
margin-left: 10px; margin-left: 10px;
background-color: #fff3f2 !important; background-color: color-mix(in srgb, #{$theme_color} 8%, #fff) !important;
border: 1px solid $theme_color !important; border: 1px solid $theme_color !important;
color: $theme_color !important; color: $theme_color !important;
} }

View File

@@ -1,6 +1,10 @@
<template> <template>
<div class="wrapper"> <div class="wrapper">
<UserCenterLayout> <UserCenterLayout
:tabs="walletTabs"
:active-tab="activeWalletTabIndex"
@tab-change="handleTabChange"
>
<div class="wallet-summary"> <div class="wallet-summary">
<div class="wallet-stat"> <div class="wallet-stat">
@@ -13,8 +17,8 @@
</div> </div>
</div> </div>
<div class="account-btns"> <div class="account-btns">
<button type="button" class="op-btn" @click="recharge">在线充值</button> <el-button type="primary" @click="recharge">在线充值</el-button>
<button type="button" class="ghost-btn" @click="withdrawalApply">申请提现</button> <el-button @click="withdrawalApply">申请提现</el-button>
</div> </div>
<el-dialog v-model="modal" width="530"> <el-dialog v-model="modal" width="530">
<template #header><p> <template #header><p>
@@ -36,7 +40,7 @@
</el-form> </el-form>
</div> </div>
<template #footer><div style="text-align: center"> <template #footer><div style="text-align: center">
<el-button size="large" type="success" @click="rechargePrice">充值</el-button> <el-button size="large" type="primary" @click="rechargePrice">充值</el-button>
</div></template> </div></template>
</el-dialog> </el-dialog>
<!-- 提现申请 --> <!-- 提现申请 -->
@@ -65,7 +69,7 @@
number number
size="large" size="large"
><template #append><span>元</span></template></el-input> ><template #append><span>元</span></template></el-input>
<span style="color: red">最低提现金额 {{ withdrawApplyFormData.minPrice }}元</span> <span class="form-tip">最低提现金额 {{ withdrawApplyFormData.minPrice }}元</span>
</el-form-item> </el-form-item>
<el-form-item v-if="withdrawApplyFormData.type === 'ALI'" label="真实姓名" prop="realName"> <el-form-item v-if="withdrawApplyFormData.type === 'ALI'" label="真实姓名" prop="realName">
<el-input <el-input
@@ -86,14 +90,9 @@
</el-form> </el-form>
</div> </div>
<template #footer><div style="text-align: center"> <template #footer><div style="text-align: center">
<el-button size="large" type="success" @click="withdrawal">提现</el-button> <el-button size="large" type="primary" @click="withdrawal">提现</el-button>
</div></template> </div></template>
</el-dialog> </el-dialog>
<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>
<div v-show="activeWalletTab === 'log'"> <div v-show="activeWalletTab === 'log'">
<empty v-if="!(logColumnsData.records || []).length" /> <empty v-if="!(logColumnsData.records || []).length" />
@@ -181,7 +180,7 @@
</template> </template>
<script setup> <script setup>
import { onMounted, reactive, ref } from "vue"; import { computed, onMounted, reactive, ref } from "vue";
import { useRouter } from "vue-router"; import { useRouter } from "vue-router";
import { Message } from "@/utils/message"; import { Message } from "@/utils/message";
import {getDepositLog, getMembersWallet, getRecharge, getWithdrawApply, recharge as apiRecharge, withdrawalApply as apiWithdrawalApply} from '@/api/member'; import {getDepositLog, getMembersWallet, getRecharge, getWithdrawApply, recharge as apiRecharge, withdrawalApply as apiWithdrawalApply} from '@/api/member';
@@ -196,6 +195,12 @@ const formDataRef = ref(null);
const withdrawApplyFormDataRef = ref(null); const withdrawApplyFormDataRef = ref(null);
const activeWalletTab = ref("log"); const activeWalletTab = ref("log");
const walletTabs = ["余额日志", "充值记录", "提现记录"]; // 钱包页签
const walletTabKeys = ["log", "recharge", "withdrawApply"]; // 页签对应标识
const activeWalletTabIndex = computed(() => {
const index = walletTabKeys.indexOf(activeWalletTab.value);
return index > -1 ? index : 0;
});
const frozenDeposit = ref(0); // 冻结余额 const frozenDeposit = ref(0); // 冻结余额
const memberDeposit = ref(0); // 余额 const memberDeposit = ref(0); // 余额
@@ -290,6 +295,10 @@ function tabPaneChange(v) {
getWithdrawApplyData(); getWithdrawApplyData();
} }
} }
// 页签切换
function handleTabChange(index) {
tabPaneChange(walletTabKeys[index]);
}
// 充值记录 // 充值记录
function getRechargeData() { function getRechargeData() {
getRecharge(rechargeForm).then((res) => { getRecharge(rechargeForm).then((res) => {
@@ -416,7 +425,8 @@ function withdrawal() {
.wallet-stat { .wallet-stat {
flex: 1; flex: 1;
padding: 16px 20px; padding: 16px 20px;
background: #fafafa; background: #fff;
border: 1px solid #eee;
border-radius: 8px; border-radius: 8px;
.label { .label {
@@ -445,67 +455,9 @@ function withdrawal() {
margin-bottom: 8px; margin-bottom: 8px;
} }
.op-btn, .form-tip {
.ghost-btn { color: #999;
height: 32px;
padding: 0 16px;
border-radius: 4px;
font-family: inherit;
font-size: 14px; 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-list {