Files
olons_server/web/src/mobile/views/SupportView.vue
T
2026-10-12 23:40:02 +08:00

110 lines
3.7 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<template>
<section v-if="!isChat" class="m-support">
<div class="m-support-hero" :style="{ backgroundImage: `url(${mobileAssets.supportHero})` }">
<PageHeader title="客服中心" :back="false" />
<div><h1>在线客服</h1><p>账户与业务问题请联系在线客服,全程跟进处理</p></div>
</div>
<div class="m-support-body">
<AsyncState
:loading="loading"
:error="error"
:empty="!services.length"
empty-text="在线客服暂未开放"
@retry="load"
>
<button
v-for="item in services"
:key="item.id"
class="m-service-card"
@click="$router.push(`/app/support/${item.id}`)"
>
<div class="m-service-avatar"
><img
v-if="safeImage(item.avatar_url)"
:src="safeImage(item.avatar_url)"
:alt="item.name" /><n-icon v-else :component="HeadsetOutline"
/></div>
<div
><h2>{{ item.name }}</h2
><p>工作时间:{{ item.work_time || '以客服在线状态为准' }}</p
><small v-if="item.backup_contact">{{ item.backup_contact }}</small></div
>
<span :class="`is-${item.online_status}`">{{ statusText(item.online_status) }}</span>
</button>
</AsyncState>
</div>
</section>
<section v-else class="m-chat">
<PageHeader :title="current?.name || '在线客服'" />
<div class="m-chat-time">会话内容由客服系统提供</div>
<div class="m-chat-empty">
<n-icon :component="ChatbubbleEllipsesOutline" />
<h2>正在连接客服</h2>
<p>{{ current?.privacy_notice || '请勿在聊天中发送登录密码或支付密码' }}</p>
<a
v-if="safeServiceUrl"
:href="safeServiceUrl"
target="_blank"
rel="noopener noreferrer"
class="m-primary-btn m-btn-link"
>进入客服会话</a
>
<p v-else class="m-form-error">客服会话地址尚未配置</p>
</div>
<div class="m-chat-input"
><button aria-label="语音"><img :src="mobileAssets.chatVoice" alt="" /></button
><input disabled placeholder="请先连接客服会话" /><button aria-label="更多"
><img :src="mobileAssets.chatMore" alt="" /></button
></div>
</section>
</template>
<script setup lang="ts">
import { computed, onMounted, ref } from 'vue';
import { useRoute } from 'vue-router';
import { ChatbubbleEllipsesOutline, HeadsetOutline } from '@vicons/ionicons5';
import PageHeader from '../components/PageHeader.vue';
import AsyncState from '../components/AsyncState.vue';
import { errorText, request, safeImage } from '../api';
import { mobileAssets } from '../assets';
const route = useRoute();
const isChat = computed(() => Boolean(route.params.id));
const loading = ref(true);
const error = ref('');
const services = ref<any[]>([]);
const current = computed(
() =>
services.value.find((item) => String(item.id) === String(route.params.id)) ||
services.value[0]
);
const safeServiceUrl = computed(() => {
const value = current.value?.service_url;
if (!value) return '';
try {
const u = new URL(value);
return u.protocol === 'https:' ? u.href : '';
} catch {
return '';
}
});
async function load() {
loading.value = true;
error.value = '';
try {
services.value = await request<any[]>({ url: '/v1/customer-services' });
} catch (err) {
error.value = errorText(err);
services.value = [];
} finally {
loading.value = false;
}
}
function statusText(status: string) {
if (status === 'online') return '在线咨询';
if (status === 'busy') return '忙碌';
return '离线留言';
}
onMounted(load);
</script>