feat: 新增工单中心、房间巡查、失物招领等业务模块
- 新增工单中心(ticket_center)与工单工作台(ticket_workbench)页面 - 新增房间巡查(room_inspection)与失物招领发布(lost_found_publish)页面 - 预约看样流程新增房型/楼栋/楼层选择器组件 - 新增工具模块: booking-entry、privacy、reservation-flow - api/index.js 补充楼层列表、看样提交等接口 - locales/messages.js 补充多语言文案 - manifest.json 开启微信小程序隐私检查 - 完善登录、注册、申请详情、账单等相关页面交互
This commit is contained in:
@@ -1,10 +1,10 @@
|
||||
<template>
|
||||
<view class="service-page tn-safe-area-inset-bottom">
|
||||
<tn-nav-bar :isBack="false" :bottomShadow="false" backgroundColor="transparent" :customBackStyle="{ transition: 'all 0.3s ease' }">
|
||||
<tn-nav-bar :isBack="false" :bottomShadow="false" :backgroundColor="navBarBackgroundColor" :customBackStyle="{ transition: 'all 0.3s ease' }">
|
||||
<view class="tn-text-bold tn-text-xl tn-color-black">{{ t('title') }}</view>
|
||||
</tn-nav-bar>
|
||||
|
||||
<scroll-view class="service-scroll" scroll-y :style="{paddingTop: vuex_custom_bar_height + 'px'}">
|
||||
<scroll-view class="service-scroll" scroll-y :style="{paddingTop: vuex_custom_bar_height + 'px'}" @scroll="handleScroll">
|
||||
<view v-if="!hasCheckedIn" class="empty-state tn-padding animation-fade-in">
|
||||
<!-- 无预订:去选房 -->
|
||||
<view v-if="!currentBooking" class="no-booking-card">
|
||||
@@ -112,21 +112,6 @@
|
||||
|
||||
<!-- 已入住状态下的服务大厅内容 -->
|
||||
<view v-else class="animation-fade-in tn-padding-bottom">
|
||||
<view class="tn-margin-top tn-margin-left tn-margin-right">
|
||||
<view class="tn-text-bold tn-text tn-color-black tn-margin-bottom">{{ t('stayService') }}</view>
|
||||
<view class="tn-flex tn-flex-row-between">
|
||||
<view
|
||||
v-for="item in stayActions"
|
||||
:key="item.key"
|
||||
class="stay-action-card"
|
||||
@click="openServicePage(item)"
|
||||
>
|
||||
<view class="stay-action-icon"><text :class="item.icon" class="stay-action-icon-symbol"></text></view>
|
||||
<view class="stay-action-title tn-margin-top-sm">{{ pickItemText(item, 'label', 'labelEn') }}</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 融合房卡与智能控制的新卡片 -->
|
||||
<view class="integrated-room-card tn-margin-left tn-margin-right tn-margin-top">
|
||||
<!-- 房卡背景 -->
|
||||
@@ -181,6 +166,32 @@
|
||||
</view>
|
||||
|
||||
<view class="tn-margin-top tn-margin-left tn-margin-right">
|
||||
<view class="tn-text-bold tn-text tn-color-black tn-margin-bottom">{{ t('stayService') }}</view>
|
||||
|
||||
<view class="tn-flex tn-flex-wrap tn-flex-row-between">
|
||||
<view class="service-item tn-margin-bottom-sm" v-for="item in stayActions" :key="item.key" @click="openServicePage(item)">
|
||||
<view class="service-card-visual">
|
||||
<image :src="item.image" mode="aspectFill" class="service-card-bg"></image>
|
||||
<view class="service-card-mask"></view>
|
||||
<view class="service-card-content tn-padding-sm tn-flex tn-flex-direction-column tn-flex-row-between" style="height: 100%;">
|
||||
<view class="tn-flex tn-flex-row-between tn-flex-col-center">
|
||||
<view class="service-icon-box tn-flex tn-flex-col-center tn-flex-row-center">
|
||||
<text :class="item.icon" class="service-icon-symbol"></text>
|
||||
</view>
|
||||
<view class="status-tag tn-text-xs" :class="item.isBusy ? 'tag-busy' : 'tag-free'">
|
||||
{{ pickItemText(item, 'statusZh', 'statusEn') }}
|
||||
</view>
|
||||
</view>
|
||||
<view>
|
||||
<view class="tn-text-bold tn-text tn-color-white">{{ pickItemText(item, 'label', 'labelEn') }}</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="tn-margin-top-sm tn-margin-left tn-margin-right">
|
||||
<view class="tn-flex tn-flex-row-between tn-flex-col-bottom tn-margin-bottom">
|
||||
<view class="tn-text-bold tn-text tn-color-black">{{ t('publicService') }}</view>
|
||||
<view class="tn-text-sm tn-color-gray">{{ t('viewAll') }} <text class="tn-icon-right section-arrow-icon"></text></view>
|
||||
@@ -238,36 +249,38 @@
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 专属管家 (原活动位置) -->
|
||||
<!-- 宿管与管理员列表 -->
|
||||
<view class="butler-card-new tn-margin-top tn-margin-left tn-margin-right">
|
||||
<view class="tn-text-bold tn-text tn-color-black tn-margin-bottom">{{ t('butler') }}</view>
|
||||
<view class="tn-text-bold tn-text tn-color-black tn-margin-bottom">{{ t('managementContacts') }}</view>
|
||||
<view class="butler-card-new__inner">
|
||||
<view v-if="areaManagers.length" class="butler-card-new__list">
|
||||
<view v-if="managerContacts.length" class="butler-card-new__list">
|
||||
<view
|
||||
v-for="(manager, index) in areaManagers"
|
||||
:key="manager.userCode || manager.userName || manager.name || index"
|
||||
v-for="(contact, index) in managerContacts"
|
||||
:key="contact.contactKey || index"
|
||||
class="butler-member-new"
|
||||
>
|
||||
<view class="butler-member-new__identity">
|
||||
<view class="butler-avatar-new">
|
||||
<image v-if="getManagerAvatar(manager)" :src="getManagerAvatar(manager)" mode="aspectFill"></image>
|
||||
<image v-if="getManagerAvatar(contact)" :src="getManagerAvatar(contact)" mode="aspectFill"></image>
|
||||
<view v-else class="butler-avatar-new-fallback tn-flex tn-flex-col-center tn-flex-row-center">
|
||||
<text class="butler-avatar-new-fallback-text">{{ getManagerInitial(manager) }}</text>
|
||||
<text class="butler-avatar-new-fallback-text">{{ getManagerInitial(contact) }}</text>
|
||||
</view>
|
||||
<view class="online-dot"></view>
|
||||
</view>
|
||||
<view class="butler-member-new__info">
|
||||
<view class="butler-member-new__name">
|
||||
{{ getManagerName(manager) }}
|
||||
<text v-if="index === 0" class="butler-member-new__tag">{{ t('primaryButlerTag') }}</text>
|
||||
{{ getManagerName(contact) }}
|
||||
<text class="butler-member-new__tag butler-member-new__tag--type" :class="contact.contactType === 'counselor' ? 'tag-counselor' : 'tag-dormitory'">
|
||||
{{ contact.contactType === 'counselor' ? t('counselorTag') : t('dormitoryManagerTag') }}
|
||||
</text>
|
||||
</view>
|
||||
<view class="butler-member-new__phone">{{ getManagerPhone(manager) || t('noContactPhone') }}</view>
|
||||
<view class="butler-member-new__phone">{{ getManagerPhone(contact) || t('noContactPhone') }}</view>
|
||||
</view>
|
||||
</view>
|
||||
<view
|
||||
class="butler-member-new__action"
|
||||
:class="{ 'disabled': !getManagerPhone(manager) }"
|
||||
@click.stop="handleAreaManagerCall(manager)"
|
||||
:class="{ 'disabled': !getManagerPhone(contact) }"
|
||||
@click.stop="handleAreaManagerCall(contact)"
|
||||
>
|
||||
<text class="tn-icon-phone-fill"></text>
|
||||
</view>
|
||||
@@ -278,12 +291,12 @@
|
||||
<view class="butler-member-new__identity">
|
||||
<view class="butler-avatar-new">
|
||||
<view class="butler-avatar-new-fallback tn-flex tn-flex-col-center tn-flex-row-center">
|
||||
<text class="tn-icon-service-fill" style="font-size: 32rpx; color: #fff;"></text>
|
||||
<text class="tn-icon-my-fill" style="font-size: 32rpx; color: #fff;"></text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="butler-member-new__info">
|
||||
<view class="butler-member-new__name">{{ t('butler') }}</view>
|
||||
<view class="butler-member-new__phone">{{ isAreaManagerLoading ? t('loadingButlerInfo') : t('noButlerInfo') }}</view>
|
||||
<view class="butler-member-new__name">{{ t('managementContacts') }}</view>
|
||||
<view class="butler-member-new__phone">{{ isManagementContactsLoading ? t('loadingButlerInfo') : t('noManagerContacts') }}</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
@@ -296,7 +309,7 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { accountQueryBills, facilityManagers, gatewayRoomDeviceList, orderSearchedDetail } from '../../../api/index.js'
|
||||
import { accountQueryBills, facilityManagers, myDormitoryManagers, myCounselor, gatewayRoomDeviceList, orderSearchedDetail } from '../../../api/index.js'
|
||||
import { getSessionSnapshot, saveMyRoomData } from '../../../utils/app-state'
|
||||
import { ACCOUNT_BILL_PAYMENT_STATUS, ACCOUNT_BILL_STATUS, fetchEnums, getAccountReferenceTypeLabel, getApplicationDetailStatusLabel } from '../../../utils/enum-store'
|
||||
import { getBookingStatusText } from '../../../utils/flow'
|
||||
@@ -400,14 +413,62 @@ export default {
|
||||
areaManager: null,
|
||||
areaManagers: [],
|
||||
isAreaManagerLoading: false,
|
||||
// 宿管与管理员联系人
|
||||
dormitoryManagers: [],
|
||||
counselor: null,
|
||||
isManagementContactsLoading: false,
|
||||
// 导航栏滚动背景色
|
||||
navBarBackgroundColor: 'transparent',
|
||||
unpaidBillList: [],
|
||||
smartDevices: [],
|
||||
isSmartDevicesLoading: false,
|
||||
smartDeviceError: '',
|
||||
stayActions: [
|
||||
{ key: 'change-room', label: '换房申请', labelEn: 'Change Room', icon: 'tn-icon-home-smile-fill', title: '换房申请', titleEn: 'Change Room Request', titleEnShort: 'Room Change', desc: '提交换房原因、期望房型和管家审核说明。', descEn: 'Submit your reason, expected room type, and butler review notes.' },
|
||||
{ key: 'renew-stay', label: '续住申请', labelEn: 'Renew Stay', icon: 'tn-icon-calendar-fill', title: '续住申请', titleEn: 'Renew Stay Request', titleEnShort: 'Renew Stay', desc: '提交续住时长、续住原因和新的租期需求。', descEn: 'Submit extension duration, reason, and new lease request.' },
|
||||
{ key: 'checkout', label: '退房申请', labelEn: 'Check Out', icon: 'tn-icon-home-in-fill', title: '退房申请', titleEn: 'Checkout Request', titleEnShort: 'Check Out', desc: '提交退房时间、离场说明和验房申请。', descEn: 'Submit checkout time, leave notes, and inspection request.' }
|
||||
{
|
||||
key: 'change-room',
|
||||
label: '换房申请',
|
||||
labelEn: 'Change Room',
|
||||
icon: 'tn-icon-home-smile-fill',
|
||||
statusZh: '可提交',
|
||||
statusEn: 'Available',
|
||||
isBusy: false,
|
||||
image: 'https://hi.aizhuhotel.com/%E7%95%99%E5%AD%A6%E7%94%9F%E5%85%AC%E5%AF%93%20-%200320%281%29_converted_11.png',
|
||||
title: '换房申请',
|
||||
titleEn: 'Change Room Request',
|
||||
titleEnShort: 'Room Change',
|
||||
desc: '提交换房原因、期望房型和管家审核说明。',
|
||||
descEn: 'Submit your reason, expected room type, and butler review notes.'
|
||||
},
|
||||
{
|
||||
key: 'renew-stay',
|
||||
label: '续住申请',
|
||||
labelEn: 'Renew Stay',
|
||||
icon: 'tn-icon-calendar-fill',
|
||||
statusZh: '可提交',
|
||||
statusEn: 'Available',
|
||||
isBusy: false,
|
||||
image: 'https://hi.aizhuhotel.com/%E7%95%99%E5%AD%A6%E7%94%9F%E5%85%AC%E5%AF%93%20-%200320%281%29_converted_16.png',
|
||||
title: '续住申请',
|
||||
titleEn: 'Renew Stay Request',
|
||||
titleEnShort: 'Renew Stay',
|
||||
desc: '提交续住时长、续住原因和新的租期需求。',
|
||||
descEn: 'Submit extension duration, reason, and new lease request.'
|
||||
},
|
||||
{
|
||||
key: 'checkout',
|
||||
label: '退房申请',
|
||||
labelEn: 'Check Out',
|
||||
icon: 'tn-icon-home-in-fill',
|
||||
statusZh: '可提交',
|
||||
statusEn: 'Available',
|
||||
isBusy: false,
|
||||
image: 'https://hi.aizhuhotel.com/%E7%95%99%E5%AD%A6%E7%94%9F%E5%85%AC%E5%AF%93%20-%200320%281%29_converted_17.png',
|
||||
title: '退房申请',
|
||||
titleEn: 'Checkout Request',
|
||||
titleEnShort: 'Check Out',
|
||||
desc: '提交退房时间、离场说明和验房申请。',
|
||||
descEn: 'Submit checkout time, leave notes, and inspection request.'
|
||||
}
|
||||
],
|
||||
services: [
|
||||
{
|
||||
@@ -440,6 +501,21 @@ export default {
|
||||
desc: '填写备注说明需要几桶水后提交申请。',
|
||||
descEn: 'Submit the quantity of water needed and any notes.'
|
||||
},
|
||||
{
|
||||
key: 'meal-delivery',
|
||||
icon: 'tn-icon-cart-fill',
|
||||
nameZh: '送餐服务',
|
||||
nameEn: 'Food Delivery',
|
||||
statusZh: '可下单',
|
||||
statusEn: 'Order Now',
|
||||
isBusy: false,
|
||||
image: 'https://hi.aizhuhotel.com/%E7%95%99%E5%AD%A6%E7%94%9F%E5%85%AC%E5%AF%93%20-%200320%281%29_converted_15.png',
|
||||
title: '送餐服务',
|
||||
titleEn: 'Food Delivery',
|
||||
titleEnShort: 'Food',
|
||||
desc: '一键跳转点餐小程序,挑选餐品并下单配送。',
|
||||
descEn: 'Open the ordering mini-program to pick meals and get delivery.'
|
||||
},
|
||||
{
|
||||
key: 'cleaning',
|
||||
icon: 'tn-icon-clean',
|
||||
@@ -503,7 +579,7 @@ export default {
|
||||
butler: '专属社区管家',
|
||||
online: '当前在线 · 响应时间 < 5分钟',
|
||||
callNow: '拨打',
|
||||
publicService: '社区设施预约',
|
||||
publicService: '公寓精选服务',
|
||||
viewAll: '全部',
|
||||
leaseTerm: '租期',
|
||||
activeStatus: '使用中',
|
||||
@@ -525,6 +601,10 @@ export default {
|
||||
noContactPhone: '暂无联系电话',
|
||||
loadingButlerInfo: '正在同步管家信息...',
|
||||
noButlerInfo: '暂未获取到管家信息',
|
||||
managementContacts: '宿管与管理员',
|
||||
dormitoryManagerTag: '宿管',
|
||||
counselorTag: '管理员',
|
||||
noManagerContacts: '暂无管理联系人',
|
||||
managerContactSummary: '当前区域共有 {count} 位管家可联系',
|
||||
contactPhonePrefix: '联系电话 ',
|
||||
loadingShort: '同步中',
|
||||
@@ -583,7 +663,7 @@ export default {
|
||||
butler: 'Community Butler',
|
||||
online: 'Online · Response < 5 mins',
|
||||
callNow: 'Call',
|
||||
publicService: 'Facility Booking',
|
||||
publicService: 'Premium Services',
|
||||
viewAll: 'View All',
|
||||
leaseTerm: 'Lease',
|
||||
activeStatus: 'Active',
|
||||
@@ -605,6 +685,10 @@ export default {
|
||||
noContactPhone: 'No contact number',
|
||||
loadingButlerInfo: 'Syncing butler info...',
|
||||
noButlerInfo: 'No butler information yet',
|
||||
managementContacts: 'Dorm Managers & Admins',
|
||||
dormitoryManagerTag: 'Dorm Mgr',
|
||||
counselorTag: 'Admin',
|
||||
noManagerContacts: 'No management contacts',
|
||||
managerContactSummary: '{count} butlers are available in this area',
|
||||
contactPhonePrefix: 'Phone ',
|
||||
loadingShort: 'Syncing',
|
||||
@@ -884,6 +968,25 @@ export default {
|
||||
butlerPhoneNumber() {
|
||||
const manager = this.primaryAreaManager || {}
|
||||
return this.getManagerPhone(manager)
|
||||
},
|
||||
// 合并宿管列表与管理员(辅导员)为统一联系人列表
|
||||
managerContacts() {
|
||||
const contacts = Array.isArray(this.dormitoryManagers)
|
||||
? this.dormitoryManagers.map((item, index) => ({
|
||||
...this.normalizeManager(item),
|
||||
contactType: 'dormitory-manager',
|
||||
contactKey: String(item.code || item.userCode || item.phone || index)
|
||||
}))
|
||||
: []
|
||||
const counselor = this.counselor
|
||||
if (counselor && typeof counselor === 'object' && (counselor.name || counselor.phone || counselor.code)) {
|
||||
contacts.push({
|
||||
...this.normalizeManager(counselor),
|
||||
contactType: 'counselor',
|
||||
contactKey: String(counselor.code || counselor.userCode || counselor.phone || 'counselor')
|
||||
})
|
||||
}
|
||||
return contacts
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
@@ -1123,6 +1226,58 @@ export default {
|
||||
|
||||
return this._loadAreaManagerPromise
|
||||
},
|
||||
// 获取宿管列表与管理员(辅导员)联系人
|
||||
fetchManagementContacts() {
|
||||
if (!this.isCurrentLogin()) {
|
||||
this.dormitoryManagers = []
|
||||
this.counselor = null
|
||||
return Promise.resolve()
|
||||
}
|
||||
|
||||
if (this._fetchManagementContactsPromise) {
|
||||
return this._fetchManagementContactsPromise
|
||||
}
|
||||
|
||||
this.isManagementContactsLoading = true
|
||||
this._fetchManagementContactsPromise = Promise.allSettled([
|
||||
myDormitoryManagers(this.language),
|
||||
myCounselor(this.language)
|
||||
])
|
||||
.then(([dormitoryManagersResult, counselorResult]) => {
|
||||
this.dormitoryManagers = dormitoryManagersResult.status === 'fulfilled' && Array.isArray(dormitoryManagersResult.value && dormitoryManagersResult.value.data)
|
||||
? dormitoryManagersResult.value.data
|
||||
: []
|
||||
this.counselor = counselorResult.status === 'fulfilled' && counselorResult.value && counselorResult.value.data && typeof counselorResult.value.data === 'object'
|
||||
? counselorResult.value.data
|
||||
: null
|
||||
if (dormitoryManagersResult.status === 'rejected') {
|
||||
console.warn('获取宿管联系人失败', dormitoryManagersResult.reason)
|
||||
}
|
||||
if (counselorResult.status === 'rejected') {
|
||||
console.warn('获取管理员信息失败', counselorResult.reason)
|
||||
}
|
||||
})
|
||||
.catch((error) => {
|
||||
this.dormitoryManagers = []
|
||||
this.counselor = null
|
||||
console.warn('获取管理联系人失败', error)
|
||||
})
|
||||
.finally(() => {
|
||||
this.isManagementContactsLoading = false
|
||||
this._fetchManagementContactsPromise = null
|
||||
})
|
||||
|
||||
return this._fetchManagementContactsPromise
|
||||
},
|
||||
// 滚动事件处理:顶部导航栏加背景色
|
||||
handleScroll(e) {
|
||||
const scrollTop = (e && e.detail && e.detail.scrollTop) || 0
|
||||
if (scrollTop > 20) {
|
||||
this.navBarBackgroundColor = '#F8FAFF'
|
||||
} else {
|
||||
this.navBarBackgroundColor = 'transparent'
|
||||
}
|
||||
},
|
||||
fetchCurrentOrderDetail() {
|
||||
if (!this.hasCheckedIn) {
|
||||
return Promise.resolve()
|
||||
@@ -1165,10 +1320,14 @@ export default {
|
||||
this.hasCheckedIn = false
|
||||
this.currentBooking = null
|
||||
this.myRoomData = null
|
||||
this.dormitoryManagers = []
|
||||
this.counselor = null
|
||||
return
|
||||
}
|
||||
|
||||
this.currentBooking = storeUser.currentBooking || session.currentBooking || null
|
||||
// 已登录即获取宿管与管理员联系人
|
||||
this.fetchManagementContacts()
|
||||
if (this.getStoreCheckinStatus() || session.hasCheckedIn) {
|
||||
this.hasCheckedIn = true
|
||||
this.myRoomData = buildRoomDataFromOrder(storeCurrentOrder) || buildRoomDataFromOrder(session.myRoomData) || session.myRoomData || null
|
||||
@@ -1294,17 +1453,65 @@ export default {
|
||||
}
|
||||
return `/pkgService/submit_request/submit_request?title=${encodeURIComponent(title || this.t('submitRequest'))}&titleZh=${encodeURIComponent(titleZh)}&titleEn=${encodeURIComponent(titleEn)}&desc=${encodeURIComponent(desc || this.t('completeFormBeforeSubmit'))}&descZh=${encodeURIComponent(descZh)}&descEn=${encodeURIComponent(descEn)}&payload=${encodeURIComponent(JSON.stringify(payload))}`
|
||||
},
|
||||
buildTicketWorkbenchUrl(item = {}) {
|
||||
const serviceTypeMap = {
|
||||
repair: 'TicketRepairApply',
|
||||
complaint: 'TicketSuggestionApply',
|
||||
'change-room': 'TicketChangeApply',
|
||||
checkout: 'TicketCheckOutApply',
|
||||
'renew-stay': 'TicketRenewalApply',
|
||||
'water-delivery': 'TicketWaterDeliveryApply',
|
||||
cleaning: 'TicketCleaningApply'
|
||||
}
|
||||
const serviceType = serviceTypeMap[item.key]
|
||||
if (!serviceType) {
|
||||
return ''
|
||||
}
|
||||
return `/pkgService/ticket_workbench/ticket_workbench?serviceType=${encodeURIComponent(serviceType)}`
|
||||
},
|
||||
openServicePage(item) {
|
||||
if (item.key === 'meal-delivery') {
|
||||
this.openMealDeliveryMiniProgram()
|
||||
return
|
||||
}
|
||||
if (item.key === 'utility') {
|
||||
uni.navigateTo({
|
||||
url: '/pkgService/utility_recharge/utility_recharge'
|
||||
});
|
||||
return
|
||||
}
|
||||
if (item.key === 'lost-found') {
|
||||
uni.navigateTo({
|
||||
url: '/pkgService/lost_found_publish/lost_found_publish'
|
||||
});
|
||||
return
|
||||
}
|
||||
const ticketUrl = this.buildTicketWorkbenchUrl(item)
|
||||
if (ticketUrl) {
|
||||
uni.navigateTo({
|
||||
url: ticketUrl
|
||||
});
|
||||
return
|
||||
}
|
||||
uni.navigateTo({
|
||||
url: this.buildServiceSubmitUrl(item)
|
||||
});
|
||||
},
|
||||
// 送餐服务:跳转外部点餐小程序
|
||||
openMealDeliveryMiniProgram() {
|
||||
uni.navigateToMiniProgram({
|
||||
appId: 'wxf221ee13f2abd417',
|
||||
path: 'pages/scan/index?scene=1005&toMenuList=5&entityId=00684887&multiMenuId=006848879dd2e038019e017ba6e330d5',
|
||||
success: () => {},
|
||||
fail: (error) => {
|
||||
console.error('跳转送餐小程序失败', error)
|
||||
uni.showToast({
|
||||
title: this.t('mealDeliveryJumpFailed'),
|
||||
icon: 'none'
|
||||
})
|
||||
}
|
||||
})
|
||||
},
|
||||
getManagerName(manager = {}) {
|
||||
return manager.displayName || manager.name || manager.userName || manager.nickname || manager.userCode || manager.phone || ''
|
||||
},
|
||||
@@ -1400,6 +1607,10 @@ export default {
|
||||
background: linear-gradient(180deg, #F0F6FF 0%, #F8FAFF 100%);
|
||||
min-height: 100vh;
|
||||
}
|
||||
/* 导航栏背景色过渡 */
|
||||
.service-page ::v-deep .tn-custom-nav-bar__bar {
|
||||
transition: background-color 0.3s ease;
|
||||
}
|
||||
.service-scroll {
|
||||
height: calc(100vh - 100rpx);
|
||||
}
|
||||
@@ -1729,43 +1940,6 @@ export default {
|
||||
box-shadow: 0 6rpx 14rpx rgba($brand-primary, 0.16);
|
||||
}
|
||||
|
||||
.stay-action-card {
|
||||
width: 31%;
|
||||
background: #ffffff;
|
||||
border-radius: 24rpx;
|
||||
padding: 24rpx 12rpx;
|
||||
text-align: center;
|
||||
box-shadow: 0 10rpx 26rpx rgba(0, 0, 0, 0.03);
|
||||
}
|
||||
|
||||
.stay-action-icon {
|
||||
width: 72rpx;
|
||||
height: 72rpx;
|
||||
margin: 0 auto;
|
||||
border-radius: 50%;
|
||||
background: linear-gradient(135deg, $icon-surface-brand-soft 0%, rgba($brand-primary, 0.04) 100%);
|
||||
color: $icon-tone-brand-deep;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 34rpx;
|
||||
box-shadow: inset 0 0 0 1rpx rgba($brand-primary, 0.08);
|
||||
}
|
||||
|
||||
.stay-action-icon-symbol {
|
||||
font-size: 32rpx;
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
.stay-action-title {
|
||||
font-size: 24rpx;
|
||||
font-weight: bold;
|
||||
color: #222222;
|
||||
line-height: 1.3;
|
||||
text-align: center;
|
||||
word-break: break-word;
|
||||
}
|
||||
|
||||
.half-btn {
|
||||
width: 48%;
|
||||
height: 92rpx;
|
||||
@@ -2044,6 +2218,18 @@ export default {
|
||||
margin-left: 10rpx;
|
||||
}
|
||||
|
||||
/* 宿管标签 - 绿色 */
|
||||
.butler-member-new__tag--type.tag-dormitory {
|
||||
background: rgba(16, 185, 129, 0.1);
|
||||
color: #10B981;
|
||||
}
|
||||
|
||||
/* 管理员标签 - 琥珀色 */
|
||||
.butler-member-new__tag--type.tag-counselor {
|
||||
background: rgba(245, 158, 11, 0.1);
|
||||
color: #F59E0B;
|
||||
}
|
||||
|
||||
.butler-member-new__phone {
|
||||
font-size: 24rpx;
|
||||
color: #888888;
|
||||
|
||||
Reference in New Issue
Block a user