feat: 客服

This commit is contained in:
2026-07-20 15:31:52 +08:00
parent 0099ccaa60
commit 82a8043578
23 changed files with 5071 additions and 360 deletions
+258 -202
View File
@@ -5,37 +5,25 @@
<view class="mine_data">
<up-image
:src="currentUserData.avatarUrl ? currentUserData.avatarUrl : 'https://static.tbmall.xin/static/mine/avatar.png'"
shape="circle"
width="54"
height="54"
bgColor="#f1f6ff00"
></up-image>
shape="circle" width="54" height="54" bgColor="#f1f6ff00"></up-image>
<view class="mine_info">
<view class="mine_info_name">
<text style="margin-right: 20rpx">{{ currentUserData.nickname || '信任桥用户' }}</text>
<view class="level level-grade" @click="jumpToTrustBridge" v-if="currentUserData.agentName">
<up-image
src="https://static.tbmall.xin/static/mine/rz.png"
style="margin-right: 8rpx; margin-top: 6rpx"
shape="circle"
width="13"
height="13"
bgColor="#f1f6ff00"
></up-image>
<up-image src="https://static.tbmall.xin/static/mine/rz.png"
style="margin-right: 8rpx; margin-top: 6rpx" shape="circle" width="13" height="13"
bgColor="#f1f6ff00"></up-image>
<view>{{ currentUserData.agentName }}</view>
</view>
<view :class="['level', currentUserData.grade ? 'level-name' : 'level-grade']" v-if="!currentUserData.agentName && currentUserData.gradeName">
<view :class="['level', currentUserData.grade ? 'level-name' : 'level-grade']"
v-if="!currentUserData.agentName && currentUserData.gradeName">
<view style="display: flex; align-items: center">
<up-image
:src="currentUserData.grade ? '/static/common/level.png' : 'https://static.tbmall.xin/static/mine/rz.png'"
style="margin-right: 8rpx; margin-top: 6rpx"
shape="circle"
width="14"
height="14"
bgColor="#f1f6ff00"
></up-image>
style="margin-right: 8rpx; margin-top: 6rpx" shape="circle" width="14"
height="14" bgColor="#f1f6ff00"></up-image>
<view>{{ currentUserData.gradeName }}</view>
</view>
</view>
@@ -58,17 +46,20 @@
</view>
<view class="mine_info_id">
<text style="margin-right: 20rpx">邀请码:{{ currentUserData.inviteCode }}</text>
<up-image src="/static/common/copy.png" width="14" height="14" bgColor="#f1f6ff00" @click="copyData(currentUserData.inviteCode)"></up-image>
<up-image src="/static/common/copy.png" width="14" height="14" bgColor="#f1f6ff00"
@click="copyData(currentUserData.inviteCode)"></up-image>
</view>
</view>
</view>
<view @click="jumpSetting">
<up-image src="https://static.tbmall.xin/static/mine/icon_arrow_black_off.png" width="22" height="22" bgColor="#f1f6ff00"></up-image>
<up-image src="https://static.tbmall.xin/static/mine/icon_arrow_black_off.png" width="22"
height="22" bgColor="#f1f6ff00"></up-image>
</view>
</view>
<view class="mine_no_login_data" v-else>
<view class="mine_data">
<up-image src="https://static.tbmall.xin/static/avater_not.png" shape="circle" width="80" height="80" bgColor="#f1f6ff00"></up-image>
<up-image src="https://static.tbmall.xin/static/avater_not.png" shape="circle" width="80"
height="80" bgColor="#f1f6ff00"></up-image>
<view class="mine_info_not_login">未登录</view>
</view>
<view @click="jumpLogin" class="login_warp">
@@ -84,20 +75,24 @@
<view>我的订单</view>
<view class="mine_order_title_all" @click="jumpOrder({})">
<view style="margin-right: 10rpx; font-size: 28rpx; font-weight: normal">全部</view>
<up-image style="margin-top: 10rpx" src="/static/common/right.png" width="15" height="15" bgColor="#f1f6ff00"></up-image>
<up-image style="margin-top: 10rpx" src="/static/common/right.png" width="15" height="15"
bgColor="#f1f6ff00"></up-image>
</view>
</view>
<view class="mine_order_list">
<view class="mine_fontsize_comm_warp order_list_item" v-for="item in orderTemplList" :key="item.id" @click="jumpOrder(item)">
<view class="mine_fontsize_comm_warp order_list_item" v-for="item in orderTemplList" :key="item.id"
@click="jumpOrder(item)">
<up-image :src="item.url" width="28" height="28" bgColor="#f1f6ff00"></up-image>
<view>{{ item.title }}</view>
<up-badge :absolute="true" :offset="[0, 8]" max="99" :value="statisticsObj[item.note]"></up-badge>
<up-badge :absolute="true" :offset="[0, 8]" max="99"
:value="statisticsObj[item.note]"></up-badge>
</view>
</view>
</view>
<!-- 应用 -->
<view class="mine_content_comm_warp mine_top_comm_warp apply_list">
<view class="apply_item mine_fontsize_comm_warp" v-for="item in applyList" :key="item.id" @click="jumpTool(item)">
<view class="apply_item mine_fontsize_comm_warp" v-for="item in applyList" :key="item.id"
@click="jumpTool(item)">
<up-image :src="item.url" width="36" height="36" bgColor="#f1f6ff00"></up-image>
<view>{{ item.title }}</view>
</view>
@@ -168,7 +163,11 @@
<view class="mine_tool_title">服务工具</view>
<view class="tool_list">
<view class="tool_item" v-for="item in toolList" :key="item.id" @click="jumpTool(item)">
<up-image :src="item.url" width="28" height="28" bgColor="#f1f6ff00"></up-image>
<view class="tool-icon-wrap">
<up-image :src="item.url" width="28" height="28" bgColor="#f1f6ff00"></up-image>
<view v-if="item.id === 7 && kefuUnreadCount > 0" class="kefu-unread-dot"
aria-label="有新的客服消息"></view>
</view>
<text class="mine_fontsize_comm_warp">{{ item.title }}</text>
</view>
</view>
@@ -236,6 +235,7 @@ import CustomTabBar from '@/components/custom-tab-bar.vue';
import { getStatistics } from '@/api/order.js';
import { getUserInfo } from '@/api/auth.js';
import { CUSTOMER_SERVICE_PHONE_NUMBER } from '@/utils/config.js';
import { getUnreadCount as getKefuUnreadCount } from "@/uni_modules/hashmall-customer-service/js_sdk/api.js";
export default {
computed: {
@@ -411,7 +411,9 @@ export default {
}, // 角标统计
serviceShow: false, // 我的客服弹框
openShow: false, // 暂未开放
platformType: true
platformType: true,
kefuUnreadCount: 0,
kefuUnreadTimer: null,
};
},
onShow() {
@@ -426,16 +428,45 @@ export default {
this.getStatistics();
this.getUserInfo();
this.startKefuUnreadPolling();
},
mounted() {},
onHide() {
this.stopKefuUnreadPolling();
},
onUnload() {
this.stopKefuUnreadPolling();
},
mounted() { },
methods: {
copyData,
async refreshKefuUnreadCount() {
const userId = this.currentUserData && this.currentUserData.id;
if (!userId) {
this.kefuUnreadCount = 0;
return;
}
try {
this.kefuUnreadCount = await getKefuUnreadCount(userId);
} catch (error) {
this.kefuUnreadCount = 0;
}
},
startKefuUnreadPolling() {
this.stopKefuUnreadPolling();
this.refreshKefuUnreadCount();
this.kefuUnreadTimer = setInterval(() => this.refreshKefuUnreadCount(), 15000);
},
stopKefuUnreadPolling() {
if (this.kefuUnreadTimer) clearInterval(this.kefuUnreadTimer);
this.kefuUnreadTimer = null;
},
// 查询用户等级
async getUserInfo() {
const result = await getUserInfo();
if (result && result.bizcode === 100) {
const data = result.data;
this.currentUserData = result.data || {};
this.refreshKefuUnreadCount();
if (!this.currentUserData?.isNewUser) {
this.applyList = this.applyList.filter((item) => item.id !== 5);
}
@@ -464,7 +495,7 @@ export default {
// 客服
if (item.id === 7) {
uni.navigateTo({
url: '/pages/rwa_package/setting/kefu?type=5257'
url: "/pages/rwa_package/setting/kefu",
});
} else if (item.id === 9) {
// 实名认证
@@ -557,274 +588,299 @@ export default {
<style lang="scss">
.mine_warp {
height: calc(100vh - env(safe-area-inset-bottom));
overflow: auto;
position: relative;
background-color: $app-bj;
height: calc(100vh - env(safe-area-inset-bottom));
overflow: auto;
position: relative;
background-color: $app-bj;
&.iosplatformType {
height: 100vh;
&.iosplatformType {
height: 100vh;
.mine_content_warp {
padding-bottom: 100rpx !important;
}
.mine_content_warp {
padding-bottom: 100rpx !important;
}
}
}
.mine_header {
// height: 300rpx;
background: linear-gradient(180deg, #f2ebff 0%, rgba(245, 245, 247, 0) 100%, #ffffff 100%);
/* 将图片居中显示 */
padding: 90rpx 20rpx 0;
// height: 300rpx;
background: linear-gradient(180deg,
#f2ebff 0%,
rgba(245, 245, 247, 0) 100%,
#ffffff 100%);
/* 将图片居中显示 */
padding: 90rpx 20rpx 0;
.mine_login_data {
display: flex;
justify-content: space-between;
align-items: center;
}
}
.mine_content_warp {
margin-top: 20rpx;
margin-left: 30rpx;
width: 690rpx;
padding-bottom: calc(100rpx + env(safe-area-inset-bottom));
}
.mine_no_login_data {
.mine_login_data {
display: flex;
justify-content: space-between;
align-items: center;
}
}
.login_warp {
display: flex;
align-items: center;
font-weight: 500;
font-size: 26rpx;
color: #111111;
}
.mine_content_warp {
margin-top: 20rpx;
margin-left: 30rpx;
width: 690rpx;
padding-bottom: calc(100rpx + env(safe-area-inset-bottom));
}
.mine_no_login_data {
display: flex;
justify-content: space-between;
align-items: center;
.login_warp {
display: flex;
align-items: center;
font-weight: 500;
font-size: 26rpx;
color: #111111;
}
}
.mine_data {
display: flex;
align-items: center;
display: flex;
align-items: center;
}
.mine_info_not_login {
font-weight: bold;
font-size: 40rpx;
color: #111111;
font-weight: bold;
font-size: 40rpx;
color: #111111;
}
.mine_info {
margin-left: 20rpx;
margin-left: 20rpx;
}
.mine_info_name {
font-weight: bold;
font-size: 40rpx;
color: #111111;
font-weight: bold;
font-size: 40rpx;
color: #111111;
display: flex;
justify-content: start;
align-items: center;
.grade_warp {
position: relative;
}
.level {
border-radius: 8rpx;
display: flex;
justify-content: start;
justify-content: center;
align-items: center;
padding: 0rpx 16rpx;
font-size: 24rpx;
height: 44rpx;
.grade_warp {
position: relative;
&.level-name {
background: rgba(248, 185, 75, 0.15);
color: #613700;
margin-left: 10rpx;
}
.level {
border-radius: 8rpx;
display: flex;
justify-content: center;
align-items: center;
padding: 0rpx 16rpx;
font-size: 24rpx;
height: 44rpx;
&.level-name {
background: rgba(248, 185, 75, 0.15);
color: #613700;
margin-left: 10rpx;
}
&.level-grade {
background: rgba(122, 53, 246, 0.1);
color: #7a35f6;
}
&.level-grade {
background: rgba(122, 53, 246, 0.1);
color: #7a35f6;
}
}
.grade_key_warp {
position: absolute;
top: 0rpx;
left: 30%;
font-size: 24rpx;
color: #ffffff;
width: 100rpx;
height: 44rpx;
line-height: 50rpx;
text-align: center;
}
.grade_key_warp {
position: absolute;
top: 0rpx;
left: 30%;
font-size: 24rpx;
color: #ffffff;
width: 100rpx;
height: 44rpx;
line-height: 50rpx;
text-align: center;
}
.grade_key_warp1 {
font-size: 24rpx;
line-height: 48rpx;
}
.grade_key_warp1 {
font-size: 24rpx;
line-height: 48rpx;
}
.grade_key_warp3 {
font-size: 20rpx;
}
.grade_key_warp3 {
font-size: 20rpx;
}
}
.mine_info_id {
font-weight: 500;
font-size: 24rpx;
color: #666666;
display: flex;
margin-top: 10rpx;
font-weight: 500;
font-size: 24rpx;
color: #666666;
display: flex;
margin-top: 10rpx;
}
/* 内容公共 start */
.mine_content_comm_warp {
background: #ffffff;
box-shadow: 0rpx 0rpx 10rpx 0rpx #eeeeee;
border-radius: 30rpx;
padding: 30rpx;
background: #ffffff;
box-shadow: 0rpx 0rpx 10rpx 0rpx #eeeeee;
border-radius: 30rpx;
padding: 30rpx;
}
.mine_fontsize_comm_warp {
font-weight: 500;
font-size: 24rpx;
color: #222222;
font-weight: 500;
font-size: 24rpx;
color: #222222;
}
.mine_top_comm_warp {
margin-top: 30rpx;
margin-top: 30rpx;
.settled_list {
width: 100%;
box-sizing: border-box;
.settled_list {
width: 100%;
box-sizing: border-box;
.enter_item {
width: 100%;
margin-top: 10rpx;
padding: 12rpx 0;
box-sizing: border-box;
.enter_item {
width: 100%;
margin-top: 10rpx;
padding: 12rpx 0;
box-sizing: border-box;
.enter_item_cell {
display: flex;
.enter_item_cell {
display: flex;
.u-transition {
margin-top: 5rpx;
}
.enter_item_text {
margin-left: 10rpx;
.enter_remark {
font-size: 24rpx;
color: #999999;
margin-top: 10rpx;
}
}
}
.u-transition {
margin-top: 5rpx;
}
.enter_item_text {
margin-left: 10rpx;
.enter_remark {
font-size: 24rpx;
color: #999999;
margin-top: 10rpx;
}
}
}
}
}
}
/* 内容公共 end */
.mine_order_title {
display: flex;
align-items: center;
justify-content: space-between;
font-weight: bold;
font-size: 32rpx;
color: #333333;
display: flex;
align-items: center;
justify-content: space-between;
font-weight: bold;
font-size: 32rpx;
color: #333333;
}
.mine_order_title_all {
display: flex;
align-items: center;
justify-content: center;
font-size: 20rpx;
color: #bbbbbb;
display: flex;
align-items: center;
justify-content: center;
font-size: 20rpx;
color: #bbbbbb;
}
.mine_order_list {
display: flex;
justify-content: space-between;
margin: 40rpx 0 10rpx 0;
display: flex;
justify-content: space-between;
margin: 40rpx 0 10rpx 0;
}
.order_list_item {
width: 25%;
text-align: center;
position: relative;
width: 25%;
text-align: center;
position: relative;
}
.apply_list {
display: flex;
justify-content: space-between;
display: flex;
justify-content: space-between;
}
.apply_item {
width: 20%;
text-align: center;
width: 20%;
text-align: center;
}
.enter_list {
display: flex;
justify-content: space-between;
display: flex;
justify-content: space-between;
}
.enter_item {
width: 40%;
background: #ffffff;
border-radius: 30rpx;
display: flex;
justify-content: space-between;
padding: 12rpx 30rpx;
align-items: center;
width: 40%;
background: #ffffff;
border-radius: 30rpx;
display: flex;
justify-content: space-between;
padding: 12rpx 30rpx;
align-items: center;
}
.enter_title {
font-weight: bold;
font-size: 26rpx;
color: #333333;
font-weight: bold;
font-size: 26rpx;
color: #333333;
}
.enter_apply {
font-weight: 400;
font-size: 24rpx;
color: #666666;
display: flex;
align-items: center;
margin-top: 10rpx;
font-weight: 400;
font-size: 24rpx;
color: #666666;
display: flex;
align-items: center;
margin-top: 10rpx;
}
.enter_apply_title {
margin-right: 10rpx;
margin-right: 10rpx;
}
.mine_tool_title {
font-weight: bold;
font-size: 30rpx;
color: #333333;
font-weight: bold;
font-size: 30rpx;
color: #333333;
}
.tool_list {
display: flex;
flex-wrap: wrap;
margin-top: 10rpx;
display: flex;
flex-wrap: wrap;
margin-top: 10rpx;
}
.tool_item {
width: 25%;
text-align: center;
margin-top: 20rpx;
width: 25%;
text-align: center;
margin-top: 20rpx;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
}
.tool-icon-wrap {
position: relative;
display: inline-flex;
}
.kefu-unread-dot {
position: absolute;
top: -5rpx;
right: -7rpx;
width: 14rpx;
height: 14rpx;
border: 3rpx solid #ffffff;
border-radius: 50%;
background: #f04444;
box-sizing: content-box;
}
::v-deep .u-modal__content {
padding: 40rpx !important;
padding: 40rpx !important;
}
</style>