Files
QSY-lvjuxcx/pkgExplore/room_detail/components/RoomInfo.vue
liangjian 6e721ccc7e refactor: 国际化文本迁移至全局 locales/messages.js
将组件级 i18n 对象重构为统一由全局 locales/messages.js 管理,确保中英文语言切换时正确显示对应文本。

- 新增 utils/i18n.js 国际化工具函数
- 更新 store/$t.mixin.js 翻译混入逻辑
- 迁移 pkgService、pkgBooking、pkgAccount、pkgExplore、pages 等共 58 个组件的中英文文本至全局消息表
2026-07-24 13:43:41 +08:00

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>