congming_huose-apk/pages/company/home-tabs.vue

512 lines
12 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>
<view class="page">
<app-top-push-notice />
<view class="tabback">
<view class="rtjt" @click="back"></view>
<view class="name">{{ navTitle }}</view>
<view class="tabback-placeholder"></view>
</view>
<view class="main-area">
<scroll-view v-show="currentTab === 0" scroll-y class="panel" :show-scrollbar="false">
<view v-if="tab0Loading" class="state state--muted">{{ $i18n.t('loading') }}</view>
<template v-else>
<view class="company-card">
<view class="company-card-media">
<image
v-if="companyLogoUrl"
class="company-card-logo"
:src="companyLogoUrl"
mode="aspectFill"
/>
<view v-else class="company-card-logo company-card-logo--ph"></view>
</view>
<text class="company-card-name">{{ companyName }}</text>
<text v-if="companyEmail" class="company-card-line">{{ companyEmail }}</text>
<text v-if="companyPhone" class="company-card-line">{{ companyPhone }}</text>
<text v-if="companyDesc" class="company-card-desc">{{ companyDesc }}</text>
</view>
<view class="section-title">{{ $i18n.t('companyHomeSpaces') }}</view>
<view v-if="spacesLoading" class="state state--muted sm">{{ $i18n.t('loading') }}</view>
<view v-else-if="spaceList.length === 0" class="state state--muted sm">{{ $i18n.t('companyEmptySpaces') }}</view>
<view
v-else
v-for="(item, index) in spaceList"
:key="spaceKey(item, index)"
class="cell"
@click="openSpace(item)"
>
<text class="cell-title">{{ spaceTitle(item) }}</text>
<text v-if="spaceSub(item)" class="cell-sub">{{ spaceSub(item) }}</text>
<text class="cell-arrow"></text>
</view>
</template>
</scroll-view>
<scroll-view v-show="currentTab === 1" scroll-y class="panel" :show-scrollbar="false">
<view v-if="panicLoading" class="state state--muted">{{ $i18n.t('loading') }}</view>
<view v-else-if="panicList.length === 0" class="state state--muted">{{ $i18n.t('companyEmptyPanic') }}</view>
<view
v-else
v-for="(item, index) in panicList"
:key="panicKey(item, index)"
class="cell cell--panic"
@click="openPanic(item)"
>
<view class="panic-row-top">
<text class="cell-title">{{ panicTitle(item) }}</text>
<text v-if="panicStatus(item)" class="panic-badge">{{ panicStatus(item) }}</text>
</view>
<text v-if="panicTime(item)" class="cell-sub">{{ panicTime(item) }}</text>
<text class="cell-link">{{ $i18n.t('companyPanicDetailTitle') }} </text>
</view>
</scroll-view>
<scroll-view v-show="currentTab === 2" scroll-y class="panel" :show-scrollbar="false">
<view class="state state--muted manage-placeholder">{{ $i18n.t('companyManageNoApi') }}</view>
</scroll-view>
</view>
<view class="bottom-tabs">
<view
v-for="(tab, idx) in tabs"
:key="idx"
class="bottom-tab"
:class="{ 'bottom-tab--active': currentTab === idx }"
@click="switchTab(idx)"
>
<text class="bottom-tab-text">{{ tab.label }}</text>
</view>
</view>
</view>
</template>
<script>
export default {
data() {
return {
companyId: '',
currentTab: 0,
companyDetail: {},
tab0Loading: true,
spacesLoading: false,
spaceList: [],
panicLoading: false,
panicLoaded: false,
panicList: []
}
},
computed: {
tabs() {
return [
{ label: this.$i18n.t('companyTabHome') },
{ label: this.$i18n.t('companyTabPanic') },
{ label: this.$i18n.t('companyTabManage') }
]
},
navTitle() {
if (this.currentTab === 1) return this.$i18n.t('companyPanicListTitle')
if (this.currentTab === 2) return this.$i18n.t('companyTabManage')
return this.companyName || this.$i18n.t('companyTabHome')
},
companyName() {
const d = this.companyDetail
return d.name || d.companyName || d.title || d.shortName || '--'
},
companyLogoUrl() {
const d = this.companyDetail
const u = d.logo || d.companyLogo || ''
return u ? String(u).trim() : ''
},
companyEmail() {
const d = this.companyDetail
const e = d.email || d.companyEmail || ''
return e ? String(e).trim() : ''
},
companyPhone() {
const d = this.companyDetail
const parts = [d.phoneCode, d.phone, d.contact].filter(Boolean)
return parts.length ? parts.join(' ') : ''
},
companyDesc() {
const d = this.companyDetail
const t = d.description || d.remark || ''
return t ? String(t).trim() : ''
}
},
onLoad(options) {
this.companyId = (options && (options.id || options.companyId)) ? String(options.id || options.companyId) : ''
if (!this.companyId) {
uni.showToast({ title: this.$i18n.t('requestFailed'), icon: 'none' })
return
}
this.loadHomeData()
},
methods: {
back() {
uni.navigateBack({ delta: 1 })
},
switchTab(idx) {
if (this.currentTab === idx) return
this.currentTab = idx
if (idx === 1 && !this.panicLoaded) {
this.loadPanicList()
}
},
normalizeRows(res) {
if (!res) return []
if (Array.isArray(res.rows)) return res.rows
if (Array.isArray(res.data)) return res.data
if (Array.isArray(res.records)) return res.records
if (Array.isArray(res.list)) return res.list
return []
},
loadHomeData() {
this.tab0Loading = true
this.spacesLoading = true
this.spaceList = []
this.$http
.get(`/bst/company/${this.companyId}`)
.then((res) => {
if (res.code == 200) {
this.companyDetail = res.data || {}
} else {
uni.showToast({ title: res.msg || this.$i18n.t('requestFailed'), icon: 'none' })
this.companyDetail = {}
}
})
.catch(() => {
uni.showToast({ title: this.$i18n.t('requestFailed'), icon: 'none' })
this.companyDetail = {}
})
.finally(() => {
this.tab0Loading = false
})
this.$http
.get(`/bst/companySpace/list?companyId=${this.companyId}&pageNum=1&pageSize=100`)
.then((res) => {
if (res.code == 200) {
this.spaceList = this.normalizeRows(res)
} else {
this.spaceList = []
}
})
.catch(() => {
this.spaceList = []
})
.finally(() => {
this.spacesLoading = false
})
},
loadPanicList() {
this.panicLoading = true
this.$http
.get(`/bst/panic/list?companyId=${this.companyId}&pageNum=1&pageSize=100`)
.then((res) => {
if (res.code == 200) {
this.panicList = this.normalizeRows(res)
this.panicLoaded = true
} else {
this.panicList = []
uni.showToast({ title: res.msg || this.$i18n.t('requestFailed'), icon: 'none' })
}
})
.catch(() => {
this.panicList = []
uni.showToast({ title: this.$i18n.t('requestFailed'), icon: 'none' })
})
.finally(() => {
this.panicLoading = false
})
},
spaceKey(item, index) {
const id = item && (item.spaceId || item.id)
return id != null && id !== '' ? String(id) : 's-' + index
},
spaceTitle(item) {
if (!item) return '--'
if (item.space && item.space.name) return item.space.name
return item.spaceName || item.name || item.title || '--'
},
spaceSub(item) {
if (!item) return ''
const parts = [item.address, item.remark, item.code].filter(
(v) => v !== undefined && v !== null && String(v).trim() !== ''
)
return parts.length ? parts.join(' · ') : ''
},
openSpace(item) {
const sid = item && (item.spaceId || item.id || (item.space && item.space.id))
if (!sid) {
uni.showToast({ title: this.$i18n.t('requestFailed'), icon: 'none' })
return
}
uni.navigateTo({ url: `/pages/company/space-detail?id=${sid}` })
},
panicKey(item, index) {
const id = item && item.id
return id != null && id !== '' ? String(id) : 'p-' + index
},
panicTitle(item) {
if (!item) return '--'
return item.title || item.typeName || item.content || item.msg || `Alarm #${item.id || ''}`
},
panicTime(item) {
if (!item) return ''
return item.createTime || item.createdAt || item.time || item.alarmTime || ''
},
panicStatus(item) {
if (!item) return ''
const s = item.status ?? item.state ?? item.handleStatus
if (s === undefined || s === null || s === '') return ''
return String(s)
},
openPanic(item) {
const id = item && item.id
if (!id) {
uni.showToast({ title: this.$i18n.t('requestFailed'), icon: 'none' })
return
}
uni.navigateTo({ url: `/pages/company/panic-detail?id=${id}` })
}
}
}
</script>
<style scoped lang="scss">
.page {
min-height: 100vh;
background-color: #f3f5f6;
box-sizing: border-box;
}
.tabback {
display: flex;
align-items: center;
justify-content: space-between;
width: 100%;
height: 160rpx;
padding: 0 20rpx;
padding-top: 80rpx;
box-sizing: border-box;
position: fixed;
top: 0;
left: 0;
z-index: 999;
background-color: #fff;
.rtjt {
font-size: 36rpx;
color: #333;
min-width: 48rpx;
}
.name {
font-size: 32rpx;
font-weight: 600;
color: #333;
max-width: 420rpx;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.tabback-placeholder {
width: 48rpx;
height: 1rpx;
}
}
.main-area {
position: fixed;
top: 160rpx;
left: 0;
right: 0;
bottom: calc(112rpx + env(safe-area-inset-bottom));
box-sizing: border-box;
}
.panel {
height: 100%;
padding: 16rpx 24rpx 24rpx;
box-sizing: border-box;
}
.state {
text-align: center;
padding: 48rpx 24rpx;
font-size: 28rpx;
}
.state--muted {
color: #8b9199;
}
.state.sm {
padding: 24rpx;
}
.company-card {
background: #fff;
border-radius: 16rpx;
padding: 28rpx;
margin-bottom: 24rpx;
box-shadow: 0 2rpx 12rpx rgba(0, 0, 0, 0.06);
}
.company-card-media {
margin-bottom: 20rpx;
}
.company-card-logo {
width: 120rpx;
height: 120rpx;
border-radius: 12rpx;
display: block;
background: #e8eaed;
}
.company-card-logo--ph {
border: 1rpx dashed #cfd4dc;
background: #f0f2f5;
}
.company-card-name {
display: block;
font-size: 34rpx;
font-weight: 600;
color: #1a1a1a;
line-height: 1.35;
}
.company-card-line {
display: block;
margin-top: 12rpx;
font-size: 26rpx;
color: #4b5563;
line-height: 1.4;
word-break: break-all;
}
.company-card-desc {
display: block;
margin-top: 16rpx;
font-size: 26rpx;
color: #6b7280;
line-height: 1.5;
}
.section-title {
font-size: 28rpx;
font-weight: 600;
color: #374151;
margin-bottom: 16rpx;
padding-left: 4rpx;
}
.cell {
position: relative;
background: #fff;
border-radius: 16rpx;
padding: 24rpx 56rpx 24rpx 28rpx;
margin-bottom: 16rpx;
box-shadow: 0 2rpx 12rpx rgba(0, 0, 0, 0.06);
}
.cell--panic {
padding-bottom: 20rpx;
}
.cell-title {
display: block;
font-size: 30rpx;
font-weight: 600;
color: #1a1a1a;
line-height: 1.4;
padding-right: 16rpx;
}
.cell-sub {
display: block;
margin-top: 10rpx;
font-size: 24rpx;
color: #6b7280;
line-height: 1.45;
}
.cell-arrow {
position: absolute;
right: 24rpx;
top: 50%;
transform: translateY(-50%);
font-size: 40rpx;
color: #c4c8ce;
line-height: 1;
}
.panic-row-top {
display: flex;
align-items: flex-start;
justify-content: space-between;
gap: 16rpx;
}
.panic-badge {
flex-shrink: 0;
font-size: 22rpx;
color: #b45309;
background: #fef3c7;
padding: 6rpx 14rpx;
border-radius: 8rpx;
}
.cell-link {
display: block;
margin-top: 12rpx;
font-size: 24rpx;
color: #2563eb;
}
.manage-placeholder {
padding-top: 120rpx;
}
.bottom-tabs {
position: fixed;
left: 0;
right: 0;
bottom: 0;
z-index: 998;
display: flex;
align-items: stretch;
min-height: 100rpx;
padding-bottom: env(safe-area-inset-bottom);
background: #fff;
border-top: 1rpx solid #e8eaed;
box-shadow: 0 -4rpx 24rpx rgba(0, 0, 0, 0.04);
box-sizing: border-box;
}
.bottom-tab {
flex: 1;
display: flex;
align-items: center;
justify-content: center;
padding: 20rpx 8rpx;
}
.bottom-tab-text {
font-size: 26rpx;
color: #8b9199;
text-align: center;
line-height: 1.3;
}
.bottom-tab--active .bottom-tab-text {
color: #0f0f0f;
font-weight: 600;
}
</style>