将组件级 i18n 对象重构为统一由全局 locales/messages.js 管理,确保中英文语言切换时正确显示对应文本。 - 新增 utils/i18n.js 国际化工具函数 - 更新 store/$t.mixin.js 翻译混入逻辑 - 迁移 pkgService、pkgBooking、pkgAccount、pkgExplore、pages 等共 58 个组件的中英文文本至全局消息表
172 lines
3.4 KiB
Vue
172 lines
3.4 KiB
Vue
<template>
|
|
<view class="room-info-wrapper">
|
|
<view class="section-panel" v-if="basicInfoRows.length">
|
|
<view class="section-header">
|
|
<text class="section-title">{{ $tr('基础信息') }}</text>
|
|
</view>
|
|
<view class="info-list">
|
|
<view v-for="item in basicInfoRows" :key="item.label" class="info-row tn-flex tn-flex-row-between tn-flex-col-center">
|
|
<text class="info-label">{{ item.label }}</text>
|
|
<text class="info-value">{{ item.value }}</text>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
|
|
<slot></slot>
|
|
|
|
<view class="section-panel" v-if="displayDescriptions.length">
|
|
<view class="section-header">
|
|
<text class="section-title">{{ isRoomType ? $tr('房型介绍') : $tr('房间介绍') }}</text>
|
|
</view>
|
|
<view class="desc-wrap" :class="{ 'desc-wrap--collapsed': isDescCollapsed }">
|
|
<view
|
|
v-for="(item, index) in displayDescriptions"
|
|
:key="`${item}-${index}`"
|
|
class="desc-text"
|
|
>
|
|
<rich-text :nodes="item"></rich-text>
|
|
</view>
|
|
</view>
|
|
<view
|
|
v-if="shouldShowDescToggle"
|
|
class="expand-btn tn-flex tn-flex-row-center tn-flex-col-center"
|
|
@click="toggleDesc"
|
|
>
|
|
<text>{{ isDescCollapsed ? $tr('展开全部') : $tr('收起') }}</text>
|
|
<text :class="isDescCollapsed ? 'tn-icon-down' : 'tn-icon-up'" class="expand-icon"></text>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
</template>
|
|
|
|
<script>
|
|
export default {
|
|
props: {
|
|
basicInfoRows: {
|
|
type: Array,
|
|
default: () => []
|
|
},
|
|
displayDescriptions: {
|
|
type: Array,
|
|
default: () => []
|
|
},
|
|
isRoomType: {
|
|
type: Boolean,
|
|
default: true
|
|
},
|
|
shouldShowDescToggle: {
|
|
type: Boolean,
|
|
default: false
|
|
},
|
|
language: {
|
|
type: String,
|
|
default: 'zh'
|
|
}
|
|
},
|
|
data() {
|
|
return {
|
|
isDescCollapsed: true
|
|
}
|
|
},
|
|
methods: {
|
|
toggleDesc() {
|
|
this.isDescCollapsed = !this.isDescCollapsed;
|
|
}
|
|
}
|
|
}
|
|
</script>
|
|
|
|
<style scoped lang="scss">
|
|
.room-info-wrapper {
|
|
padding: 0;
|
|
}
|
|
|
|
.section-panel {
|
|
background: #ffffff;
|
|
padding: 48rpx 32rpx;
|
|
border-bottom: 1rpx solid #F2F3F5;
|
|
}
|
|
|
|
.section-header {
|
|
margin-bottom: 32rpx;
|
|
}
|
|
|
|
.section-title {
|
|
position: relative;
|
|
font-size: 36rpx;
|
|
font-weight: 800;
|
|
color: #1D2129;
|
|
letter-spacing: 2rpx;
|
|
}
|
|
|
|
.info-list {
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: 32rpx;
|
|
}
|
|
|
|
.info-row {
|
|
gap: 24rpx;
|
|
align-items: flex-start;
|
|
}
|
|
|
|
.info-label {
|
|
width: 160rpx;
|
|
font-size: 26rpx;
|
|
color: #86909C;
|
|
}
|
|
|
|
.info-value {
|
|
flex: 1;
|
|
text-align: right;
|
|
font-size: 28rpx;
|
|
line-height: 1.5;
|
|
color: #1D2129;
|
|
font-weight: 600;
|
|
}
|
|
|
|
.desc-wrap {
|
|
position: relative;
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: 24rpx;
|
|
transition: max-height 0.4s cubic-bezier(0.25, 0.8, 0.25, 1);
|
|
max-height: 5000rpx;
|
|
overflow: hidden;
|
|
}
|
|
|
|
.desc-wrap--collapsed {
|
|
max-height: 180rpx;
|
|
}
|
|
|
|
.desc-wrap--collapsed::after {
|
|
content: '';
|
|
position: absolute;
|
|
left: 0;
|
|
right: 0;
|
|
bottom: 0;
|
|
height: 80rpx;
|
|
background: linear-gradient(180deg, rgba(255,255,255,0) 0%, rgba(255,255,255,1) 100%);
|
|
pointer-events: none;
|
|
}
|
|
|
|
.desc-text {
|
|
font-size: 28rpx;
|
|
line-height: 1.8;
|
|
color: #4E5969;
|
|
text-align: justify;
|
|
}
|
|
|
|
.expand-btn {
|
|
margin-top: 22rpx;
|
|
color: $brand-primary;
|
|
font-size: 25rpx;
|
|
font-weight: 600;
|
|
}
|
|
|
|
.expand-icon {
|
|
margin-left: 8rpx;
|
|
font-size: 26rpx;
|
|
}
|
|
</style>
|