<template>
|
<view class="container">
|
<view class="custom-navbar" :style="{ paddingTop: statusBarHeight + 'px' }">
|
<view class="nav-content">
|
<image class="back-icon" src="/static/image/home/left.png" mode="aspectFit" @tap="goBack"></image>
|
<text class="nav-title">帮助中心</text>
|
<view class="nav-right-placeholder"></view>
|
</view>
|
</view>
|
|
<view class="top-bg">
|
<image class="bg-img" src="https://mxcd.zhinenganguan.com/file/2026-03-30/5d3dd485-5af1-4913-ba22-c27f668c4660.png" mode="widthFix"></image>
|
</view>
|
|
<view class="content">
|
<view class="service-card">
|
<view class="service-info">
|
<view class="info-item">
|
<text class="label">客服电话:</text>
|
<text class="phone">{{ displayServicePhone }}</text>
|
</view>
|
<view class="info-item">
|
<text class="time">{{ displayServiceOnlineTime }}</text>
|
</view>
|
</view>
|
<image class="service-icon" src="/static/image/mine/Weixin.png" mode="aspectFit"></image>
|
</view>
|
|
<view class="contact-btn" @tap="handleContact">
|
<image class="btn-icon" src="/static/image/mine/listen.png" mode="aspectFit"></image>
|
<text>人工客服</text>
|
</view>
|
|
<view class="faq-section">
|
<view class="section-title">常见问题</view>
|
<view class="faq-list">
|
<view v-if="faqList.length === 0" class="empty-box">
|
<text class="empty-text">暂无常见问题</text>
|
</view>
|
<block v-for="(item, index) in faqList" :key="item.id || index">
|
<view class="faq-item" @tap="goFaqDetail(item)">
|
<text class="faq-title">{{ index + 1 }}、{{ item.title }}</text>
|
<u-icon name="arrow-right" color="#999" size="14"></u-icon>
|
</view>
|
</block>
|
</view>
|
</view>
|
</view>
|
</view>
|
</template>
|
|
<script setup lang="ts">
|
import { computed, ref } from 'vue'
|
import { onLoad, onShow } from '@dcloudio/uni-app'
|
import { getHelpCenter } from './service'
|
|
interface HelpCenterQuestionItem {
|
id: number | null
|
title: string
|
}
|
|
interface HelpCenterData {
|
servicePhone: string
|
serviceOnlineTime: string
|
questions: HelpCenterQuestionItem[]
|
}
|
|
const statusBarHeight = ref(20)
|
const helpCenterData = ref<HelpCenterData>(createDefaultHelpCenter())
|
|
const displayServicePhone = computed(() => {
|
return helpCenterData.value.servicePhone || '--'
|
})
|
const displayServiceOnlineTime = computed(() => {
|
return helpCenterData.value.serviceOnlineTime || '人工客服在线时间暂未配置'
|
})
|
const faqList = computed(() => helpCenterData.value.questions)
|
|
/**
|
* 创建帮助中心默认值,避免首屏访问空对象。
|
*/
|
function createDefaultHelpCenter(): HelpCenterData {
|
return {
|
servicePhone: '',
|
serviceOnlineTime: '',
|
questions: [],
|
}
|
}
|
|
/**
|
* 页面加载时初始化状态栏高度。
|
*/
|
onLoad(() => {
|
const systemInfo = uni.getSystemInfoSync()
|
statusBarHeight.value = systemInfo.statusBarHeight || 20
|
})
|
|
/**
|
* 页面显示时刷新帮助中心数据。
|
*/
|
onShow(() => {
|
loadHelpCenter()
|
})
|
|
/**
|
* 拉取帮助中心首页聚合数据。
|
*/
|
async function loadHelpCenter() {
|
try {
|
const response = await getHelpCenter()
|
if (response?.code !== 0 || !response.data) {
|
return
|
}
|
helpCenterData.value = normalizeHelpCenter(response.data)
|
} catch {
|
// 请求层会统一处理异常提示。
|
}
|
}
|
|
/**
|
* 将接口数据归一化为页面可直接渲染的结构。
|
*/
|
function normalizeHelpCenter(value: unknown): HelpCenterData {
|
const source = (value && typeof value === 'object' ? value : {}) as Record<string, unknown>
|
return {
|
servicePhone: normalizeOptionalText(source.servicePhone),
|
serviceOnlineTime: normalizeOptionalText(source.serviceOnlineTime),
|
questions: normalizeQuestions(source.questions),
|
}
|
}
|
|
/**
|
* 将常见问题列表归一化。
|
*/
|
function normalizeQuestions(value: unknown): HelpCenterQuestionItem[] {
|
if (!Array.isArray(value)) {
|
return []
|
}
|
return value.map((item) => {
|
const source = (item && typeof item === 'object' ? item : {}) as Record<string, unknown>
|
return {
|
id: normalizeOptionalNumber(source.id),
|
title: normalizeOptionalText(source.title) || '常见问题',
|
}
|
})
|
}
|
|
/**
|
* 返回上一页。
|
*/
|
function goBack() {
|
uni.navigateBack()
|
}
|
|
/**
|
* 拨打系统设置中的客服电话,未配置时给出兜底提示。
|
*/
|
function handleContact() {
|
const servicePhone = normalizePhoneNumber(helpCenterData.value.servicePhone)
|
if (!servicePhone) {
|
uni.showToast({
|
title: '暂未配置客服电话',
|
icon: 'none',
|
})
|
return
|
}
|
uni.makePhoneCall({
|
phoneNumber: servicePhone,
|
fail() {
|
uni.showToast({
|
title: '拨号失败,请检查客服电话配置',
|
icon: 'none',
|
})
|
},
|
})
|
}
|
|
/**
|
* 跳转到常见问题详情页。
|
*/
|
function goFaqDetail(item: HelpCenterQuestionItem) {
|
if (!item.id) {
|
return
|
}
|
uni.navigateTo({
|
url: `/pages/help/help?id=${item.id}`,
|
})
|
}
|
|
/**
|
* 将可选文本归一化为空字符串。
|
*/
|
function normalizeOptionalText(value: unknown) {
|
if (typeof value !== 'string') {
|
return ''
|
}
|
return value.trim()
|
}
|
|
/**
|
* 清洗客服电话,兼容空格、横杠和中文括号等展示字符。
|
*/
|
function normalizePhoneNumber(value: unknown) {
|
if (typeof value !== 'string') {
|
return ''
|
}
|
return value
|
.trim()
|
.replace(/[()()\s-]/g, '')
|
.replace(/(?!^)\+/g, '')
|
}
|
|
/**
|
* 将可选数字归一化为空值。
|
*/
|
function normalizeOptionalNumber(value: unknown) {
|
const parsedValue = Number(value)
|
if (!Number.isFinite(parsedValue)) {
|
return null
|
}
|
return parsedValue
|
}
|
</script>
|
|
<style lang="scss" scoped>
|
page {
|
background-color: #F8F6F4;
|
}
|
|
.container {
|
width: 100vw;
|
min-height: 100vh;
|
display: flex;
|
flex-direction: column;
|
background-color: #F8F6F4;
|
position: relative;
|
}
|
|
/* 顶部背景 */
|
.top-bg {
|
position: absolute;
|
top: 0;
|
left: 0;
|
width: 100%;
|
z-index: 0;
|
|
.bg-img {
|
width: 100%;
|
height: auto;
|
}
|
}
|
|
/* 自定义导航栏 */
|
.custom-navbar {
|
width: 100%;
|
position: relative;
|
z-index: 100;
|
background-color: transparent;
|
}
|
|
.nav-content {
|
height: 88rpx;
|
display: flex;
|
align-items: center;
|
justify-content: space-between;
|
padding: 0 32rpx;
|
|
}
|
|
.back-icon {
|
width: 40rpx;
|
height: 40rpx;
|
}
|
|
.nav-title {
|
font-size: 36rpx;
|
color: #1A1A1A;
|
font-weight: bold;
|
}
|
|
.nav-right-placeholder {
|
width: 40rpx;
|
}
|
|
.content {
|
position: relative;
|
z-index: 1;
|
padding: 40rpx;
|
padding-right: 0rpx !important;
|
}
|
|
/* 客服卡片 */
|
.service-card {
|
display: flex;
|
justify-content: space-between;
|
align-items: center;
|
margin-bottom: 40rpx;
|
// padding-right: 20rpx;
|
}
|
|
.service-info {
|
.info-item {
|
margin-bottom: 12rpx;
|
|
&:last-child {
|
margin-bottom: 0;
|
}
|
}
|
|
.label {
|
font-size: 32rpx;
|
color: #1A1A1A;
|
font-weight: bold;
|
}
|
|
.phone {
|
font-size: 36rpx;
|
color: #1A1A1A;
|
font-weight: bold;
|
display: block;
|
margin-top: 8rpx;
|
}
|
|
.time {
|
font-size: 24rpx;
|
color: #86909C;
|
}
|
}
|
|
.service-icon {
|
width: 200rpx;
|
height: 200rpx;
|
}
|
|
/* 客服按钮 */
|
.contact-btn {
|
width: 670rpx;
|
height: 88rpx;
|
background-color: #D32E29;
|
border-radius: 16rpx;
|
display: flex;
|
justify-content: center;
|
align-items: center;
|
color: #FFFFFF;
|
font-size: 32rpx;
|
font-weight: 500;
|
margin-bottom: 60rpx;
|
box-shadow: 0 4rpx 12rpx rgba(211, 46, 41, 0.2);
|
|
.btn-icon {
|
width: 36rpx;
|
height: 36rpx;
|
margin-right: 12rpx;
|
}
|
}
|
|
/* 常见问题 */
|
.section-title {
|
font-size: 32rpx;
|
color: #1A1A1A;
|
font-weight: bold;
|
margin-bottom: 24rpx;
|
}
|
|
.faq-list {
|
background-color: #FFFFFF;
|
border-radius: 16rpx;
|
padding: 0 24rpx;
|
}
|
|
.empty-box {
|
height: 120rpx;
|
display: flex;
|
align-items: center;
|
justify-content: center;
|
}
|
|
.empty-text {
|
font-size: 26rpx;
|
color: #999999;
|
}
|
|
.faq-item {
|
height: 100rpx;
|
display: flex;
|
align-items: center;
|
justify-content: space-between;
|
border-bottom: 1px solid #F2F3F5;
|
|
&:last-child {
|
border-bottom: none;
|
}
|
|
.faq-title {
|
flex: 1;
|
font-size: 28rpx;
|
color: #1A1A1A;
|
white-space: nowrap;
|
overflow: hidden;
|
text-overflow: ellipsis;
|
padding-right: 20rpx;
|
}
|
}
|
</style>
|