237 lines
5.0 KiB
Plaintext
237 lines
5.0 KiB
Plaintext
<template>
|
|
<view
|
|
class="layout"
|
|
:class="className"
|
|
:style="{
|
|
backgroundColor: transparentBackground ? 'transparent' : backgroundColor,
|
|
}"
|
|
>
|
|
<!-- 微信安全区 -->
|
|
<safety-zone v-if="hasSafetyZone"></safety-zone>
|
|
<view class="nav-bar">
|
|
<!-- 左侧菜单按钮 -->
|
|
<view class="left-box">
|
|
<view class="menu-btn">
|
|
<text
|
|
v-if="showBack"
|
|
class="iconfont icon-a-Chevronleft"
|
|
@tap="onBackClick"
|
|
></text>
|
|
<slot name="left"></slot>
|
|
</view>
|
|
</view>
|
|
|
|
<!-- 中间 logo + 名称 -->
|
|
<view class="logo-wrap">
|
|
<view class="title-box">
|
|
<!-- 图标 -->
|
|
<view class="logo" v-if="icon">
|
|
<image
|
|
class="image"
|
|
:src="currentIcon"
|
|
mode="aspectFill"
|
|
:alt="displayTitle || t('Mobile.Common.agentIconAlt')"
|
|
@error="handleImageError"
|
|
></image>
|
|
</view>
|
|
<!-- 标题 -->
|
|
<text
|
|
class="title text-ellipsis"
|
|
:class="icon ? 'title-exist-icon' : 'title-no-icon'"
|
|
>{{ displayTitle }}</text
|
|
>
|
|
</view>
|
|
</view>
|
|
|
|
<!-- 右侧插槽 -->
|
|
<view class="right-box">
|
|
<slot name="right"></slot>
|
|
</view>
|
|
|
|
<!-- 微信胶囊按钮功能区 -->
|
|
<!-- #ifdef MP-WEIXIN -->
|
|
<view
|
|
v-if="false"
|
|
class="right-safety"
|
|
:style="{
|
|
width: clientRect.width + 'px',
|
|
height: clientRect.height + 'px',
|
|
}"
|
|
></view>
|
|
<!-- #endif -->
|
|
</view>
|
|
</view>
|
|
</template>
|
|
|
|
<script setup lang="uts">
|
|
import { chatService } from "@/utils/chatService";
|
|
import agentImage from "@/static/assets/agent_image.png";
|
|
import { translateText, useI18n } from "@/utils/i18n";
|
|
const { t } = useI18n();
|
|
|
|
// #ifdef MP-WEIXIN
|
|
const clientRect = uni.getMenuButtonBoundingClientRect();
|
|
// #endif
|
|
|
|
const props = defineProps({
|
|
title: {
|
|
type: String,
|
|
default: "",
|
|
},
|
|
icon: {
|
|
type: String,
|
|
default: "",
|
|
},
|
|
showBack: {
|
|
type: Boolean,
|
|
default: false,
|
|
},
|
|
className: {
|
|
type: String,
|
|
default: "",
|
|
},
|
|
hasSafetyZone: {
|
|
type: Boolean,
|
|
default: true,
|
|
},
|
|
// 背景是否透明
|
|
transparentBackground: {
|
|
type: Boolean,
|
|
default: false,
|
|
},
|
|
// 背景颜色
|
|
backgroundColor: {
|
|
type: String,
|
|
default: "#fff",
|
|
},
|
|
});
|
|
|
|
const displayTitle = computed(() => {
|
|
return translateText(props.title);
|
|
});
|
|
|
|
// 当前显示的图标(用于处理加载失败时使用默认图片)
|
|
const currentIcon = ref<string>(props.icon || agentImage);
|
|
|
|
const onBackClick = () => {
|
|
// 中止当前会话
|
|
chatService?.abort();
|
|
// 获取当前页面栈
|
|
const pages = getCurrentPages();
|
|
// 如果页面栈中有多个页面,正常返回
|
|
if (pages.length > 1) {
|
|
uni.navigateBack({
|
|
delta: 1,
|
|
});
|
|
return;
|
|
}
|
|
// 如果页面栈只有一个页面(浏览器刷新后),使用浏览器历史记录返回 如果没有历史记录,跳转到首页
|
|
uni.reLaunch({
|
|
url: "/pages/index/index",
|
|
});
|
|
};
|
|
|
|
/**
|
|
* 图片加载失败处理
|
|
* 当图片加载失败时,使用默认图片
|
|
*/
|
|
const handleImageError = () => {
|
|
currentIcon.value = agentImage;
|
|
};
|
|
|
|
// 监听 props.icon 变化,更新当前图标
|
|
watch(
|
|
() => props.icon,
|
|
(newIcon) => {
|
|
currentIcon.value = newIcon || agentImage;
|
|
},
|
|
{ immediate: true },
|
|
);
|
|
</script>
|
|
|
|
<style lang="scss" scoped>
|
|
.layout {
|
|
.nav-bar {
|
|
display: flex;
|
|
flex-direction: row;
|
|
align-items: center;
|
|
height: 90rpx;
|
|
padding: 20rpx;
|
|
box-sizing: border-box;
|
|
|
|
.left-box {
|
|
min-width: 30%;
|
|
align-items: start;
|
|
|
|
.menu-btn {
|
|
margin-right: 12rpx;
|
|
width: 100%;
|
|
display: flex;
|
|
flex-direction: row;
|
|
align-items: center;
|
|
justify-content: start;
|
|
gap: 20rpx;
|
|
min-width: 0;
|
|
}
|
|
}
|
|
|
|
.logo-wrap {
|
|
flex: 1;
|
|
|
|
.title-box {
|
|
width: 100%;
|
|
margin: 0 auto;
|
|
display: flex;
|
|
flex-direction: row;
|
|
align-items: center;
|
|
justify-content: center;
|
|
gap: 12rpx;
|
|
min-width: 0;
|
|
|
|
.logo {
|
|
width: 64rpx;
|
|
height: 64rpx;
|
|
border-radius: 50%;
|
|
overflow: hidden;
|
|
position: relative;
|
|
flex-shrink: 0;
|
|
|
|
.image {
|
|
position: absolute;
|
|
left: -3%;
|
|
top: -3%;
|
|
width: 106%;
|
|
height: 106%;
|
|
}
|
|
}
|
|
|
|
.title {
|
|
font-size: 32rpx;
|
|
font-weight: 600;
|
|
line-height: 48rpx;
|
|
color: rgba(21, 23, 31, 1);
|
|
|
|
&-exist-icon {
|
|
max-width: calc(100% - 64rpx - 12rpx);
|
|
text-align: left;
|
|
}
|
|
|
|
&-no-icon {
|
|
max-width: 100%;
|
|
text-align: center;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
.right-box {
|
|
min-width: 30%;
|
|
display: flex;
|
|
flex-direction: row;
|
|
align-items: center;
|
|
justify-content: flex-end;
|
|
}
|
|
}
|
|
}
|
|
</style>
|