feat: 更新 API 请求参数与组件样式优化

- 在 account.js 和 member.js 中添加 loading 和 skipMessage 参数,提升 API 调用的用户体验。
- 在 ShowGoods.vue 中优化商品详情展示样式,增强可读性和交互性。
- 在 Cart.vue 中重构购物车商品列表结构,提升布局一致性。
- 在多个页面中修复了提示信息的内容,确保用户操作的清晰反馈。
This commit is contained in:
田香琪
2026-07-06 16:33:21 +08:00
parent e13ca6281d
commit 297bdd95dd
28 changed files with 689 additions and 259 deletions

View File

@@ -55,7 +55,9 @@ export function editPwd (params) {
url: `/buyer/passport/member/modifyPass`,
method: Method.PUT,
needToken: true,
data: params
data: params,
loading: false,
skipMessage: true
})
}

View File

@@ -427,7 +427,9 @@ export function distCash (params) {
url: `/buyer/distribution/cash`,
method: Method.POST,
needToken: true,
params
params,
loading: false,
skipMessage: true
});
}

View File

@@ -28,28 +28,36 @@
</div>
<div class="goodsConfig mt_10">
<span @click="collect"
><el-icon :color="isCollected ? '#ed3f14' : '#666'"><StarFilled /></el-icon>{{ isCollected ? "已收藏" : "收藏" }}</span>
<span
class="collect-btn"
:class="{ 'is-collected': isCollected }"
@click="collect"
>
<el-icon class="collect-icon"><StarFilled /></el-icon>
<span class="collect-text">{{ isCollected ? '已收藏' : '收藏' }}</span>
</span>
</div>
</div>
<!-- 右侧商品信息活动信息操作展示 -->
<div class="item-detail-right">
<div class="item-detail-title">
<p>
{{ skuDetail.goodsName }}
<div class="item-detail-title-row">
<span class="item-detail-name">{{ skuDetail.goodsName }}</span>
<el-tag
v-if="skuDetail.goodsType !== 'VIRTUAL_GOODS'"
style="margin-top:10px;rgb(153, 149, 149);"
class="goods-type-tag"
size="small"
>
实物商品
</el-tag>
<el-tag
v-else-if="skuDetail.goodsType == 'VIRTUAL_GOODS'"
style="margin-top:10px;rgb(153, 149, 149);"
class="goods-type-tag"
size="small"
>
虚拟商品
</el-tag>
</p>
</div>
</div>
<div class="sell-point">
{{ skuDetail.sellingPoint }}
@@ -224,13 +232,13 @@
<div class="item-select-row">
<el-input-number
:min="1"
:max="skuDetail.quantity"
:disabled="skuDetail.quantity === 0"
:max="quantityMax"
:disabled="isOutOfStock"
v-model="count"
:precision="0.1"
:precision="0"
@blur="changeCount"
></el-input-number>
<span class="inventory"> 库存{{ skuDetail.quantity }}</span>
<span class="inventory">&nbsp&nbsp库存{{ skuDetail.quantity }}</span>
</div>
</div>
</div>
@@ -325,9 +333,7 @@ export default {
handler(val) {
this.skuDetail = val.data;
this.wholesaleList = val.wholesaleList;
if (this.wholesaleList && this.wholesaleList.length > 0) {
this.count = this.wholesaleList[0].num;
}
this.syncCountWithQuantity();
this.promotion();
this.swiperGoodsImg();
},
@@ -388,6 +394,13 @@ export default {
})
: [];
},
quantityMax() {
const qty = Number(this.skuDetail.quantity) || 0;
return qty > 0 ? qty : 1;
},
isOutOfStock() {
return (Number(this.skuDetail.quantity) || 0) <= 0;
},
},
methods: {
// 初始化video
@@ -408,6 +421,22 @@ export default {
},
syncCountWithQuantity() {
const qty = Number(this.skuDetail.quantity) || 0;
if (qty <= 0) {
this.count = 1;
return;
}
if (this.wholesaleList && this.wholesaleList.length > 0) {
this.count = Math.min(Math.max(this.wholesaleList[0].num, 1), qty);
return;
}
if (this.count > qty) {
this.count = qty;
} else if (this.count < 1) {
this.count = 1;
}
},
changeCount(val) {
if (this.wholesaleList && this.wholesaleList.length > 0) {
if (this.count <= this.wholesaleList[0].num) {
@@ -688,11 +717,23 @@ export default {
flex-direction: column;
}
.item-detail-title p {
.item-detail-title-row {
display: flex;
align-items: center;
flex-wrap: wrap;
gap: 8px;
padding: 8px 0;
}
.item-detail-name {
@include content_color($light_content_color);
font-weight: bold;
font-size: 20px;
padding: 8px 0;
line-height: 1.4;
}
.goods-type-tag {
flex-shrink: 0;
}
.item-detail-express {
@@ -941,13 +982,32 @@ export default {
.goodsConfig {
display: flex;
justify-content: space-between;
> span {
.collect-btn {
display: inline-flex;
align-items: center;
gap: 4px;
padding-right: 10px;
&:hover {
cursor: pointer;
color: $theme_color;
color: #666;
cursor: pointer;
line-height: 1;
&.is-collected {
.collect-icon {
color: #ffc107;
}
}
}
.collect-icon {
display: inline-flex;
align-items: center;
font-size: 16px;
}
.collect-text {
line-height: 1;
}
}
.sell-point {
font-size: 12px;

View File

@@ -338,7 +338,7 @@ export default {
font-weight: bolder;
}
.item-intro-detail{
margin: 0 30px;
margin: 0;
width: 100%;
}
.item-intro-nav{
@@ -365,6 +365,8 @@ export default {
}
.item-intro-img {
width: 100%;
box-sizing: border-box;
padding: 0 30px;
min-height: 300px;
:deep img{
margin:0 auto;
@@ -377,6 +379,8 @@ export default {
.item-param-container {
display: flex;
flex-direction: column;
box-sizing: border-box;
padding: 0 30px;
}
.item-param-box {
padding: 5px;
@@ -400,6 +404,10 @@ export default {
color: #666666;
background-color: #F7F7F7;
}
.remarks-container {
box-sizing: border-box;
padding: 0 30px;
}
.remarks-analyse-box {
padding: 15px;
display: flex;
@@ -507,31 +515,36 @@ export default {
}
/***************商品详情介绍和推荐侧边栏结束***************/
/* 改变标签页样式 */
:deep(.el-tabs__active-bar) {
background-color: $theme_color !important;
}
:deep(.el-tabs__header) {
border: none;
}
.item-tabs > .el-tabs > .el-tabs__header .el-tabs__item {
border-radius: 0px;
color: #999;
height: 38px;
}
.item-tabs > .el-tabs > .el-tabs__header .el-tabs__item.is-active {
color: #fff;
background-color: $theme_color;
}
.item-tabs > .el-tabs > .el-tabs__header .el-tabs__item.is-active:before {
content: '';
display: block;
width: 100%;
height: 1px;
color: #fff;
background: #F7F7F7;
position: absolute;
top: 0;
left: 0;
.item-tabs {
:deep(.el-tabs__header) {
border: none;
margin: 0;
background-color: #f7f7f7;
}
:deep(.el-tabs__active-bar) {
background-color: $theme_color !important;
}
:deep(.el-tabs__item) {
border-radius: 0;
color: #999;
height: 38px;
padding: 0 20px;
&:hover {
color: #999;
}
}
:deep(.el-tabs__nav) {
padding-left: 10px;
}
:deep(.el-tabs__item.is-active) {
color: $theme_color !important;
background-color: transparent;
}
}
:deep(.el-rate__icon) {
color: $theme_color;

View File

@@ -25,8 +25,9 @@
</div>
<!-- 购物车商品列表 -->
<div class="cart-goods">
<div class="cart-goods-table">
<div class="cart-goods-title">
<div class="width_60">
<div class="width_60 cart-col-check">
<el-checkbox
v-model="allChecked"
@change="changeChecked(allChecked, 'all')"
@@ -43,56 +44,58 @@
<p>购物车空空如也</p>
<router-link to="/">去选购&gt;</router-link>
</div>
<div
v-else
class="cart-goods-items"
v-for="(shop, index) in cartList"
:key="index"
>
<div class="shop-name">
<div>
<el-checkbox
v-model="shop.checked"
@change="changeChecked(shop.checked, 'shop', shop.storeId)"
></el-checkbox>
<span class="go-shop-page" @click="goShopPage(shop.storeId)">{{
shop.storeName
}}</span>
</div>
<span
class="shop-coupon"
v-if="shop.couponList.length"
:class="couponAvailable === index ? 'shop-coupon-show' : ''"
@click.stop="showCoupon(shop.id, index)"
>
<!-- 优惠券模态框 -->
<div v-if="couponAvailable === index">
<div
class="coupon-item"
v-for="(item, index) in shop.couponList"
:key="index"
>
<span v-if="item.couponType === 'PRICE'"
>{{ item.price }}</span>
<span v-if="item.couponType === 'DISCOUNT'"
>{{ item.couponDiscount }}</span>
<span>{{ item.consumeThreshold }}元可用</span>
<el-button
class="coupon-btn"
size="small"
type="primary"
@click="receiveShopCoupon(item)"
:disabled="item.disabled"
>{{ item.disabled ? "已领取" : "领取" }}</el-button
>
</div>
<div v-else class="cart-goods-list-box">
<div
class="cart-shop-group"
v-for="(shop, index) in cartList"
:key="index"
>
<div class="shop-name">
<div class="width_60 cart-col-check">
<el-checkbox
v-model="shop.checked"
@change="changeChecked(shop.checked, 'shop', shop.storeId)"
></el-checkbox>
</div>
</span>
<div class="promotion-notice">{{ shop.promotionNotice }}</div>
</div>
<template v-for="(goods, goodsIndex) in shop.skuList" :key="goods.goodsSku?.id || goodsIndex">
<div class="goods-item">
<div class="width_60">
<div class="shop-info">
<span class="go-shop-page" @click="goShopPage(shop.storeId)">{{
shop.storeName
}}</span>
<span
class="shop-coupon"
v-if="shop.couponList.length"
:class="couponAvailable === index ? 'shop-coupon-show' : ''"
@click.stop="showCoupon(shop.id, index)"
>
<!-- 优惠券模态框 -->
<div v-if="couponAvailable === index">
<div
class="coupon-item"
v-for="(item, couponIndex) in shop.couponList"
:key="couponIndex"
>
<span v-if="item.couponType === 'PRICE'"
>{{ item.price }}</span>
<span v-if="item.couponType === 'DISCOUNT'"
>{{ item.couponDiscount }}</span>
<span>{{ item.consumeThreshold }}元可用</span>
<el-button
class="coupon-btn"
size="small"
type="primary"
@click="receiveShopCoupon(item)"
:disabled="item.disabled"
>{{ item.disabled ? "已领取" : "领取" }}</el-button
>
</div>
</div>
</span>
<div class="promotion-notice">{{ shop.promotionNotice }}</div>
</div>
</div>
<template v-for="(goods, goodsIndex) in shop.skuList" :key="goods.goodsSku?.id || goodsIndex">
<div class="goods-item">
<div class="width_60 cart-col-check">
<el-checkbox
v-model="goods.checked"
@change="
@@ -155,21 +158,21 @@
</template>
</div>
</div>
<div class="width_150">
<div class="width_150 cart-col-price">
{{ $filters.unitPrice(goods.purchasePrice, "¥") }}
</div>
<div class="width_100">
<div class="width_100 cart-col-qty">
<el-input-number
:min="1"
size="small"
v-model="goods.num"
@change="changeNum(goods.num, goods.goodsSku.id)"
></el-input-number>
<div class="fontsize_12">
<div class="fontsize_12 cart-qty-stock">
{{ goods.goodsSku.quantity > 0 ? "有货" : "无货" }}
</div>
</div>
<div class="width_150">
<div class="width_150 cart-col-subtotal">
{{ $filters.unitPrice(goods.subTotal, "¥") }}
</div>
<div class="cart-ops-col">
@@ -195,12 +198,14 @@
>
</div>
</div>
</template>
</template>
</div>
</div>
</div>
<!-- 底部支付栏 -->
<div class="cart-goods-footer">
<div>
<div class="width_60">
<div class="width_60 cart-col-check">
<el-checkbox
v-model="allChecked"
@change="changeChecked(allChecked, 'all')"
@@ -286,7 +291,7 @@ export default {
collectGoods(id) {
this.$Modal.confirm({
title: "收藏",
content: "<p>商品收藏后可在个人中心我的收藏查看</p>",
content: "商品收藏后可在个人中心我的收藏查看",
onOk: () => {
APIMember.collectGoods("GOODS", id).then((res) => {
if (res.success) {
@@ -315,7 +320,7 @@ export default {
}
this.$Modal.confirm({
title: "删除",
content: "<p>确定要删除该商品吗?</p>",
content: "确定要删除该商品吗?",
onOk: () => {
APICart.delCartGoods({ skuIds: idArr.toString() }).then((res) => {
if (res.success) {
@@ -332,7 +337,7 @@ export default {
clearCart() {
this.$Modal.confirm({
title: "提示",
content: "<p>确定要清空购物车吗?清空后不可恢复</p>",
content: "确定要清空购物车吗?清空后不可恢复",
onOk: () => {
APICart.clearCart().then((res) => {
if (res.success) {
@@ -512,6 +517,10 @@ export default {
}
/** 商品列表 */
.cart-goods {
.cart-goods-table {
border: 1px solid #e0e0e0;
@include background_color($light_white_background_color);
}
&-title {
height: 50px;
@include background_color($light_white_background_color);
@@ -519,7 +528,8 @@ export default {
display: flex;
align-items: center;
padding: 0 20px;
div {
border-bottom: 1px solid #e0e0e0;
div:not(.cart-col-check) {
text-align: center;
}
.goods-title {
@@ -532,7 +542,26 @@ export default {
height: 300px;
padding-top: 100px;
}
&-items {
.cart-goods-list-box {
@include background_color($light_white_background_color);
}
.cart-col-check {
width: 60px;
min-width: 60px;
flex-shrink: 0;
display: flex;
align-items: center;
justify-content: flex-start;
text-align: left;
:deep(.el-checkbox) {
margin-right: 0;
}
}
.cart-shop-group {
&:not(:last-child) {
border-bottom: 1px solid #e0e0e0;
}
.shop-name {
height: 50px;
display: flex;
@@ -540,8 +569,14 @@ export default {
padding: 0 20px;
position: relative;
@include title_color($light_title_color);
> * {
width: 50%;
.shop-info {
flex: 1;
min-width: 0;
display: flex;
align-items: center;
.promotion-notice {
margin-left: auto;
}
}
.go-shop-page:hover {
color: $theme_color;
@@ -559,6 +594,7 @@ export default {
.shop-coupon {
width: 80px;
height: 24px;
flex-shrink: 0;
position: relative;
background: url(../assets/images/cart-coupon-icons02.png) 0 0 no-repeat;
> div {
@@ -569,7 +605,6 @@ export default {
height: 300px;
background-color: #fff;
border: 1px solid $theme_color;
// border-radius: 3px;
z-index: 1;
padding: 10px 20px;
&::before {
@@ -612,6 +647,8 @@ export default {
.promotion-notice {
text-align: right;
font-size: 12px;
flex-shrink: 0;
margin-left: 10px;
}
.shop-coupon-show {
background-position-y: -34px;
@@ -620,12 +657,16 @@ export default {
.goods-item {
position: relative;
@extend .cart-goods-title;
@include background_color($light_white_background_color);
background: transparent;
border-top: 1px solid #f0f0f0;
padding: 10px 20px;
height: auto;
.cart-col-check {
padding-left: 20px;
box-sizing: border-box;
}
> div:nth-child(1) {
padding-left: 15px;
width: 30px;
width: 60px;
}
> div:nth-child(2) {
cursor: pointer;
@@ -647,9 +688,38 @@ export default {
}
}
}
> div:nth-child(5) {
.cart-col-price,
.cart-col-subtotal {
display: flex;
align-items: center;
justify-content: center;
flex-shrink: 0;
text-align: center;
}
.cart-col-subtotal {
font-weight: bold;
}
.cart-col-qty {
position: relative;
display: flex;
align-items: center;
justify-content: center;
flex-shrink: 0;
:deep(.el-input-number) {
width: 100%;
}
.cart-qty-stock {
position: absolute;
top: calc(100% + 4px);
left: 50%;
transform: translateX(-50%);
white-space: nowrap;
line-height: 1.2;
color: #999;
}
}
.num-input {
width: 60px;
border: 1px solid #999;

View File

@@ -13,14 +13,15 @@
<div class="store-collect" v-if="!takeDownSale && goodsMsg.data">
<span class="mr_10" v-if="goodsMsg.data">
<router-link
class="store-name-link"
:to="{ path: '/merchant', query: { id: goodsMsg.data.storeId } }"
>{{ goodsMsg.data.storeName }}</router-link>
</span>
<span @click="collect">
<el-icon :color="storeCollected ? '#ed3f14' : '#666'"><StarFilled /></el-icon>
<span class="store-collect-btn" @click="collect">
<el-icon :color="storeCollected ? '#ffc107' : '#666'"><StarFilled /></el-icon>
{{ storeCollected? "已收藏店铺": "收藏店铺" }}
</span>
<span class="ml_10" @click="IMService(goodsMsg.data.storeId,goodsMsg.data.goodsId,goodsMsg.data.id)">联系客服</span>
<span class="ml_10 contact-service-btn" @click="IMService(goodsMsg.data.storeId,goodsMsg.data.goodsId,goodsMsg.data.id)">联系客服</span>
</div>
</div>
</div>
@@ -233,12 +234,27 @@ export default {
transform: translateY(-50%);
color: #999;
span {
span:not(.store-collect-btn):not(.contact-service-btn) {
&:hover {
cursor: pointer;
color: $theme_color;
}
}
.store-collect-btn,
.contact-service-btn {
cursor: pointer;
}
.store-name-link {
color: $theme_color;
text-decoration: none;
&:hover {
color: $theme_color;
text-decoration: none;
}
}
}
}
.sale-btn{

View File

@@ -56,8 +56,7 @@
<div class="goods-show-detail">
<el-tag
v-if="item.salesModel === 'WHOLESALE'"
class="goods-show-tag"
color="purple"
class="goods-show-tag goods-show-tag-wholesale"
>
批发
</el-tag>
@@ -302,6 +301,17 @@ export default {
}
}
.goods-show-tag-wholesale {
margin-right: 5px;
background-color: #f9f0ff;
border-color: #d3adf7;
color: #9254de;
:deep(.el-tag__content) {
color: #9254de;
}
}
.goods-show-tag-physical {
background-color: #e6f4ff;
border-color: #b3d8ff;

View File

@@ -109,7 +109,7 @@ export default {
cancel (id) { // 取消投诉
this.$Modal.confirm({
title: '取消投诉',
content: '<p>确定取消投诉吗?</p>',
content: '确定取消投诉吗?',
onOk: () => {
clearComplain(id).then((res) => {
if (res.success) {

View File

@@ -362,18 +362,36 @@ export default {
}
});
},
normalizeWithdrawError (message) {
if (!message) return '提现失败,请稍后重试';
const text = String(message);
if (text.includes('最少提现金额为1元')) {
return '提现金额单次最少提现金额为1元';
}
const colonIndex = text.indexOf(':');
if (colonIndex > -1 && colonIndex < text.length - 1) {
return text.slice(colonIndex + 1).trim();
}
return text;
},
withdraw() {
// 申请提现
const price = Number(this.withdrawPrice);
if (!price || price < 1) {
this.$Message.error('提现金额单次最少提现金额为1元');
return;
}
distCash({ price: this.withdrawPrice }).then((res) => {
this.withdrawApplyModal = false;
this.price = 0;
if (res.success) {
this.$Message.success("申请已提交,请等待审核");
this.withdrawApplyModal = false;
this.withdrawPrice = 0;
this.$Message.success('申请已提交,请等待审核');
this.distribution();
this.getLog();
} else {
this.$Message.error(res.message);
this.$Message.error(this.normalizeWithdrawError(res.message));
}
}).catch((err) => {
this.$Message.error(this.normalizeWithdrawError(err?.message || err?.data?.message));
});
},
qrcodeData(data64) {

View File

@@ -146,8 +146,8 @@ export default {
cancel(id) { // 取消收藏
let typeName = this.params.type === 'GOODS' ? '商品' : '店铺'
this.$Modal.confirm({
title: 'Title',
content: `<p>确定取消收藏该${typeName}吗?</p>`,
title: '取消收藏',
content: `确定取消收藏该${typeName}吗?`,
onOk: () => {
cancelCollect(this.params.type, id).then(res => {
if (res.success) {
@@ -160,8 +160,8 @@ export default {
cancelStore(id) { // 取消收藏
let typeName = this.params.type === 'GOODS' ? '商品' : '店铺'
this.$Modal.confirm({
title: 'Title',
content: `<p>确定取消收藏该${typeName}吗?</p>`,
title: '取消收藏',
content: `确定取消收藏该${typeName}吗?`,
onOk: () => {
cancelStoreCollect(this.params.type, id).then(res => {
if (res.success) {

View File

@@ -139,6 +139,13 @@ export default {
this.status = this.$route.query.status
},
methods: {
normalizePwdError (message) {
if (!message) return '修改失败,请稍后重试';
if (String(message).includes('旧密码') || String(message).includes('密码不正确')) {
return '旧密码不正确';
}
return message;
},
// 修改
handleRegist () {
this.$refs['formRegister'].validate((valid) => {
@@ -146,7 +153,7 @@ export default {
const {newPassword, againPassword, password} = this.formRegister
if (newPassword !== againPassword) {
this.$Message.error({
content: '新密码不一致'
content: '新密码和确认密码不一致'
});
return
}
@@ -154,10 +161,14 @@ export default {
params.newPassword = md5(newPassword)
params.password = md5(password)
editPwd(params).then(res => {
if (res.message === 'success' && res.result) {
if (res.success && res.result) {
this.$Message.success('修改密码成功');
this.$router.push('/home')
} else {
this.$Message.error(this.normalizePwdError(res.message));
}
}).catch((err) => {
this.$Message.error(this.normalizePwdError(err?.message || err?.data?.message));
});
}
})
@@ -183,7 +194,7 @@ export default {
}
if (newPassword !== againPassword) {
this.$Message.error({
content: '新密码不一致'
content: '新密码和确认密码不一致'
});
return
}

View File

@@ -37,26 +37,30 @@
<div>
<el-input type="textarea" maxlength="500" show-word-limit :rows="4" v-model="orderGoods.content" />
</div>
<div style="display:flex;align-items:center;">
<div class="demo-upload-list" v-for="(img, index) in orderGoods.uploadList" :key="index">
<img :src="img">
<div class="demo-upload-list-cover">
<div class="upload-section">
<div class="upload-row">
<div class="demo-upload-list" v-for="(img, index) in orderGoods.uploadList" :key="index">
<img :src="img">
<div class="demo-upload-list-cover">
<el-icon @click="handleView(img)"><View /></el-icon>
<el-icon @click="handleRemove(index)"><Delete /></el-icon>
</div>
</div>
</div>
<el-upload
:show-upload-list="false"
<el-upload
class="upload-trigger"
:show-file-list="false"
:on-success="handleSuccess"
:before-upload="handleBeforeUpload"
:format="['jpg','jpeg','png']"
:action="action"
:headers="accessToken"
style="display: inline-block;width:58px;">
<div class="hover-pointer icon-upload" style="">
>
<div class="hover-pointer icon-upload">
<el-icon :size="20"><Camera /></el-icon>
</div>
</el-upload>
</el-upload>
</div>
<div class="describe">上传评价图片最多9张</div>
</div>
</div>
</li>
@@ -165,7 +169,7 @@ export default {
this.$forceUpdate()
},
handleBeforeUpload () { // 上传之前钩子
const check = this.orderGoods.uploadList.length < 10;
const check = this.orderGoods.uploadList.length < 9;
if (!check) {
this.$Notice.warning({
title: '最多可以上传九张图片'
@@ -237,7 +241,7 @@ export default {
}
.demo-upload-list{
display: inline-block;
display: block;
width: 60px;
height: 60px;
text-align: center;
@@ -248,8 +252,7 @@ export default {
background: #fff;
position: relative;
box-shadow: 0 1px 1px rgba(0,0,0,.2);
margin-right: 4px;
margin-top: 10px;
flex-shrink: 0;
}
.demo-upload-list img{
width: 100%;
@@ -274,17 +277,47 @@ export default {
margin: 0 2px;
}
.icon-upload {
width: 58px;
height:58px;
line-height: 58px;
text-align:center;
display: inline-block;
border:1px dashed #999;
width: 60px;
height: 60px;
line-height: 60px;
text-align: center;
display: flex;
align-items: center;
justify-content: center;
border: 1px dashed #999;
border-radius: 4px;
margin-top: 10px;
box-sizing: border-box;
&:hover{
cursor: pointer;
border-color: $theme_color;
}
}
.upload-section {
margin-top: 10px;
}
.upload-row {
display: flex;
align-items: center;
flex-wrap: wrap;
gap: 4px;
}
.upload-trigger {
display: inline-flex;
align-items: center;
flex-shrink: 0;
:deep(.el-upload) {
display: inline-flex;
align-items: center;
}
}
.describe {
font-size: 12px;
color: #999;
margin-top: 8px;
}
</style>

View File

@@ -26,9 +26,9 @@
</el-form-item>
</el-form>
</div>
<div class="mt_20">
<el-button type="primary" class="mr_10" :loading="loading" @click="save">保存收货地址</el-button>
<div class="action-bar mt_20">
<el-button @click="$router.back()">返回</el-button>
<el-button type="primary" class="ml_10" :loading="loading" @click="save">保存收货地址</el-button>
</div>
</UserCenterLayout>
@@ -153,4 +153,9 @@ export default {
.add-box {
margin: 40px 0;
}
.action-bar {
display: flex;
justify-content: flex-end;
}
</style>

View File

@@ -39,7 +39,7 @@
</div>
</div>
<div>
<span @click="shopPage(order.shopId)">{{ order.storeName }}</span>
<span @click="shopPage(order.storeId)">{{ order.storeName }}</span>
</div>
<div class="order-actions">
<!-- 订单基础操作 -->
@@ -89,7 +89,7 @@
</div>
<div class="mt_10">
<span class="global_color"
>{{ $filters.unitPrice(singleOrder.flowPrice, "¥") }} </span>x {{ singleOrder.num }}
>{{ $filters.unitPrice(singleOrder.flowPrice, "¥") }} </span> x {{ singleOrder.num }}
</div>
</div>
</div>
@@ -173,7 +173,7 @@ export default {
cancel(sn) { // 取消售后申请
this.$Modal.confirm({
title: '取消',
content: '<p>确定取消此次售后申请吗?</p>',
content: '确定取消此次售后申请吗?',
onOk: () => {
cancelAfterSale(sn).then(res => {
if (res.success) {

View File

@@ -4,8 +4,12 @@
<!-- 操作按钮 -->
<el-card class="mb_10" shadow="never" v-if="(afterSale.serviceStatus == 'PASS' &&
afterSale.serviceType != 'RETURN_MONEY') || (afterSale.afterSaleAllowOperationVO && afterSale.afterSaleAllowOperationVO.cancel)">
<el-button type="success" @click="openModal" v-if="afterSale.serviceStatus == 'PASS' &&
afterSale.serviceType != 'RETURN_MONEY'" size="small">提交物流</el-button>&nbsp;
<el-button
@click="openModal"
v-if="afterSale.serviceStatus == 'PASS' && afterSale.serviceType != 'RETURN_MONEY'"
size="small"
class="submit-logistics-btn"
>提交物流</el-button>&nbsp;
<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">
@@ -302,4 +306,17 @@ table{
padding: 5px;
}
}
:deep(.submit-logistics-btn) {
background-color: #ff9900 !important;
border-color: #ff9900 !important;
color: #fff !important;
&:hover,
&:focus {
background-color: #e68a00 !important;
border-color: #e68a00 !important;
color: #fff !important;
}
}
</style>

View File

@@ -17,10 +17,12 @@
<div class="eval-con">
<div class="eval-form">
<span class="color999">投诉主题</span>
<el-select v-model="form.complainTopic" style="width:260px;margin-bottom:10px">
<el-option v-for="item in reasonList" :value="item.reason" :key="item.id">{{ item.reason }}</el-option>
</el-select>
<div class="topic-row">
<span class="color999 topic-label">投诉主题</span>
<el-select v-model="form.complainTopic" class="topic-select">
<el-option v-for="item in reasonList" :value="item.reason" :key="item.id">{{ item.reason }}</el-option>
</el-select>
</div>
<el-input type="textarea" maxlength="500" show-word-limit :rows="4" placeholder="请输入投诉内容" v-model="form.content" />
</div>
<div class="upload-section">
@@ -186,6 +188,22 @@ export default {
}
}
.topic-row {
display: flex;
align-items: center;
margin-bottom: 10px;
}
.topic-label {
flex-shrink: 0;
margin-right: 8px;
}
.topic-select {
width: 200px;
flex-shrink: 0;
}
.demo-upload-list{
display: block;
width: 60px;

View File

@@ -174,17 +174,6 @@
<td>{{ $filters.unitPrice(goods.refundPrice, "¥") }}</td>
<td>{{ $filters.unitPrice((goods.goodsPrice * goods.num), "¥") }}</td>
<td class="order-item-actions">
<el-button
v-if="
goods.afterSaleStatus.includes('NOT_APPLIED') ||
goods.afterSaleStatus.includes('PART_AFTER_SALE')
"
@click="applyAfterSale(goods.sn)"
type="default"
size="small"
class="order-item-action-btn mb_5"
>申请售后</el-button
>
<el-button
v-if="goods.commentStatus == 'UNFINISHED'"
@click="comment(order.order.sn, goodsIndex)"
@@ -201,6 +190,17 @@
size="small"
>投诉</el-button
>
<el-button
v-if="
goods.afterSaleStatus.includes('NOT_APPLIED') ||
goods.afterSaleStatus.includes('PART_AFTER_SALE')
"
@click="applyAfterSale(goods.sn)"
type="default"
size="small"
class="order-item-action-btn mb_5"
>申请售后</el-button
>
</td>
</tr>
</tbody>
@@ -256,7 +256,7 @@
</el-dialog>
<!--查询物流-->
<el-dialog v-model="logisticsModal" width="40">
<el-dialog v-model="logisticsModal" width="40%">
<template #header><p><span>查询物流</span></p></template>
<div class="layui-layer-wrap">
<dl>

View File

@@ -22,11 +22,15 @@
</ul>
<!-- 分页 -->
<div class="page-size">
<el-pagination :total="total"
<el-pagination
:total="total"
:current-page="params.pageNumber"
:page-size="params.pageSize"
:page-sizes="[10, 20, 30, 40, 50, 100]"
layout="sizes, prev, pager, next, jumper"
@current-change="changePageNum"
@size-change="changePageSize"
:page-size="params.pageSize"
layout="sizes, prev, pager, next, jumper"></el-pagination>
/>
</div>
</UserCenterLayout>
</div>
@@ -44,7 +48,7 @@ export default {
spinShow: false, // 控制loading是否加载
params: {
pageNumber: 1,
pageSize: 30,
pageSize: 10,
order: "desc",
sort: "updateTime",
},

View File

@@ -29,6 +29,16 @@ export const sellerUrl =
let isRefreshToken = 0;
const refreshToken = getTokenDebounce();
/** 会员中心(/home/*)页面使用局部 loading不启用全屏遮罩 */
function isMemberCenterRoute() {
try {
const path = router.currentRoute?.value?.path || "";
return path === "/home" || path.startsWith("/home/");
} catch {
return false;
}
}
const service = axios.create({
timeout: 10000,
baseURL: buyerUrl,
@@ -56,7 +66,8 @@ service.interceptors.request.use(
const method = (config.method || "get").toLowerCase();
const isReadRequest = method === "get" || method === "head";
const shouldShowLoading =
loading === true || (!isReadRequest && loading !== false);
loading === true ||
(!isReadRequest && loading !== false && !isMemberCenterRoute());
if (typeof window !== "undefined" && shouldShowLoading) {
config.loading = ElLoading.service({ fullscreen: true });
@@ -166,7 +177,7 @@ service.interceptors.response.use(
if (errorResponse.status === 404) {
return Promise.reject(buildRejectError(error, { message: "请求的资源不存在" }));
}
if (error.message) {
if (error.message && !error.config?.skipMessage) {
const _message =
error.code === "ECONNABORTED"
? "连接超时,请稍候再试!"