387 lines
8.7 KiB
Vue
387 lines
8.7 KiB
Vue
<template>
|
|
<view class="page">
|
|
<app-top-push-notice />
|
|
<view class="tabback">
|
|
<view class="rtjt" @click="back">←</view>
|
|
<view class="name">{{ $i18n.t('companyListTitle') }}</view>
|
|
<view class="tabback-placeholder"></view>
|
|
</view>
|
|
|
|
<view class="body">
|
|
<view v-if="loadError" class="state state--error">{{ loadError }}</view>
|
|
<scroll-view
|
|
v-else
|
|
scroll-y
|
|
class="list-scroll"
|
|
@scrolltolower="loadMore"
|
|
>
|
|
<view v-if="loading && list.length === 0" class="state state--muted">{{ $i18n.t('loading') }}</view>
|
|
<view v-else-if="!loading && list.length === 0" class="state state--muted">{{ $i18n.t('companyListEmpty') }}</view>
|
|
<template v-else>
|
|
<view
|
|
v-for="(item, index) in list"
|
|
:key="companyKey(item, index)"
|
|
class="cell"
|
|
@click="openCompany(item)"
|
|
>
|
|
<view class="cell-media">
|
|
<image
|
|
v-if="companyLogo(item)"
|
|
class="cell-logo"
|
|
:src="companyLogo(item)"
|
|
mode="aspectFill"
|
|
/>
|
|
<view v-else class="cell-logo cell-logo--placeholder"></view>
|
|
</view>
|
|
<view class="cell-body">
|
|
<text class="cell-title">{{ companyTitle(item) }}</text>
|
|
<!-- <text v-if="companyEmail(item)" class="cell-email">{{ companyEmail(item) }}</text> -->
|
|
<text v-if="companySub(item)" class="cell-sub">{{ companySub(item) }}</text>
|
|
</view>
|
|
</view>
|
|
<view v-if="loadingMore" class="list-footer">{{ $i18n.t('loading') }}</view>
|
|
<view v-else-if="!hasMore && list.length > 0" class="list-footer list-footer--muted">
|
|
{{ $i18n.t('companyListNoMore') }}
|
|
</view>
|
|
</template>
|
|
</scroll-view>
|
|
</view>
|
|
|
|
<view class="footer-bar">
|
|
<view class="footer-btn" @click="goApply">{{ $i18n.t('applyCompany') }}</view>
|
|
</view>
|
|
</view>
|
|
</template>
|
|
|
|
<script>
|
|
export default {
|
|
data() {
|
|
return {
|
|
list: [],
|
|
loading: true,
|
|
loadError: '',
|
|
pageNum: 1,
|
|
pageSize: 20,
|
|
total: 0,
|
|
hasMore: true,
|
|
loadingMore: false,
|
|
refresherTriggered: false
|
|
}
|
|
},
|
|
onLoad() {},
|
|
onShow() {
|
|
this.reloadFromStart()
|
|
},
|
|
methods: {
|
|
goApply() {
|
|
uni.navigateTo({ url: '/pages/company/apply' })
|
|
},
|
|
openCompany(item) {
|
|
const id = item && (item.id != null ? item.id : item.companyId)
|
|
if (id === undefined || id === null || id === '') {
|
|
uni.showToast({ title: this.$i18n.t('requestFailed'), icon: 'none' })
|
|
return
|
|
}
|
|
uni.navigateTo({ url: `/pages/company/home-tabs?id=${encodeURIComponent(String(id))}` })
|
|
},
|
|
back() {
|
|
uni.navigateBack({ delta: 1 })
|
|
},
|
|
companyKey(item, index) {
|
|
const id = item && (item.id || item.companyId || item.code)
|
|
return id != null && id !== '' ? String(id) : 'i-' + index
|
|
},
|
|
companyTitle(item) {
|
|
if (!item) return '--'
|
|
return item.name || item.companyName || item.title || item.shortName || '--'
|
|
},
|
|
companyLogo(item) {
|
|
if (!item) return ''
|
|
const u = item.logo || ''
|
|
const s = u != null ? String(u).trim() : ''
|
|
return s
|
|
},
|
|
companyEmail(item) {
|
|
if (!item) return ''
|
|
const e = item.email || item.companyEmail || ''
|
|
const s = e != null ? String(e).trim() : ''
|
|
return s
|
|
},
|
|
companySub(item) {
|
|
if (!item) return ''
|
|
const parts = [
|
|
item.remark,
|
|
item.address,
|
|
item.code,
|
|
item.contact,
|
|
item.phone
|
|
].filter((v) => v !== undefined && v !== null && String(v).trim() !== '')
|
|
return parts.length ? parts.join(' · ') : ''
|
|
},
|
|
normalizeRows(res) {
|
|
if (!res) return []
|
|
if (Array.isArray(res.rows)) return res.rows
|
|
if (Array.isArray(res.data)) return res.data
|
|
if (res.data && typeof res.data === 'object' && !Array.isArray(res.data)) {
|
|
return [res.data]
|
|
}
|
|
if (Array.isArray(res.records)) return res.records
|
|
if (Array.isArray(res.list)) return res.list
|
|
return []
|
|
},
|
|
normalizeTotal(res) {
|
|
if (!res) return 0
|
|
const t = res.total
|
|
if (typeof t === 'number' && !isNaN(t)) return t
|
|
if (res.data && typeof res.data.total === 'number' && !isNaN(res.data.total)) {
|
|
return res.data.total
|
|
}
|
|
return 0
|
|
},
|
|
reloadFromStart() {
|
|
this.pageNum = 1
|
|
this.total = 0
|
|
this.hasMore = true
|
|
this.loadError = ''
|
|
this.list = []
|
|
this.fetchPage(1, { append: false })
|
|
},
|
|
onPullRefresh() {
|
|
if (this.loadingMore || (this.loading && this.list.length === 0)) {
|
|
this.refresherTriggered = false
|
|
return
|
|
}
|
|
this.pageNum = 1
|
|
this.hasMore = true
|
|
this.loadError = ''
|
|
this.fetchPage(1, { append: false, isPullRefresh: true })
|
|
setTimeout(()=>{
|
|
this.refresherTriggered = true
|
|
},1000)
|
|
},
|
|
loadMore() {
|
|
console.log(12121);
|
|
if (!this.hasMore || this.loading || this.loadingMore) return
|
|
this.fetchPage(this.pageNum + 1, { append: true })
|
|
},
|
|
fetchPage(page, opts) {
|
|
const append = opts && opts.append
|
|
const isPullRefresh = opts && opts.isPullRefresh
|
|
if (append) {
|
|
if (!this.hasMore || this.loadingMore || this.loading) return
|
|
this.loadingMore = true
|
|
} else if (isPullRefresh) {
|
|
// 仅下拉刷新动画,不盖全屏 loading
|
|
} else {
|
|
this.loading = true
|
|
}
|
|
if (!append && !isPullRefresh) {
|
|
this.loadError = ''
|
|
}
|
|
this.$http
|
|
.get(`/bst/company/list?pageNum=${page}&pageSize=${this.pageSize}`)
|
|
.then((res) => {
|
|
if (res.code != 200) {
|
|
const msg = res.msg || this.$i18n.t('requestFailed')
|
|
if (append) {
|
|
uni.showToast({ title: msg, icon: 'none' })
|
|
} else {
|
|
this.loadError = msg
|
|
this.list = []
|
|
}
|
|
return
|
|
}
|
|
const rows = this.normalizeRows(res)
|
|
const total = this.normalizeTotal(res)
|
|
if (append) {
|
|
this.list = this.list.concat(rows)
|
|
} else {
|
|
this.list = rows
|
|
}
|
|
this.pageNum = page
|
|
if (rows.length === 0) {
|
|
this.hasMore = false
|
|
} else if (total > 0) {
|
|
this.total = total
|
|
this.hasMore = this.list.length < total
|
|
} else {
|
|
this.hasMore = rows.length >= this.pageSize
|
|
}
|
|
})
|
|
.catch(() => {
|
|
if (append) {
|
|
uni.showToast({ title: this.$i18n.t('requestFailed'), icon: 'none' })
|
|
} else {
|
|
this.loadError = this.$i18n.t('requestFailed')
|
|
this.list = []
|
|
}
|
|
})
|
|
.finally(() => {
|
|
this.loading = false
|
|
this.loadingMore = false
|
|
if (isPullRefresh) {
|
|
this.refresherTriggered = false
|
|
}
|
|
})
|
|
}
|
|
}
|
|
}
|
|
</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;
|
|
}
|
|
|
|
.tabback-placeholder {
|
|
width: 48rpx;
|
|
height: 1rpx;
|
|
}
|
|
}
|
|
|
|
.body {
|
|
padding: 180rpx 24rpx 200rpx;
|
|
box-sizing: border-box;
|
|
}
|
|
|
|
.state {
|
|
text-align: center;
|
|
padding: 80rpx 32rpx;
|
|
font-size: 28rpx;
|
|
}
|
|
|
|
.state--muted {
|
|
color: #8b9199;
|
|
}
|
|
|
|
.state--error {
|
|
color: #c0392b;
|
|
}
|
|
|
|
.list-scroll {
|
|
height: 76vh;
|
|
}
|
|
|
|
.list-footer {
|
|
text-align: center;
|
|
padding: 24rpx 16rpx 8rpx;
|
|
font-size: 24rpx;
|
|
color: #6b7280;
|
|
}
|
|
|
|
.list-footer--muted {
|
|
color: #9ca3af;
|
|
}
|
|
|
|
.footer-bar {
|
|
position: fixed;
|
|
left: 0;
|
|
right: 0;
|
|
bottom: 0;
|
|
padding: 20rpx 24rpx calc(20rpx + env(safe-area-inset-bottom));
|
|
background: #fff;
|
|
box-shadow: 0 -4rpx 24rpx rgba(0, 0, 0, 0.06);
|
|
z-index: 998;
|
|
box-sizing: border-box;
|
|
}
|
|
|
|
.footer-btn {
|
|
height: 96rpx;
|
|
line-height: 96rpx;
|
|
text-align: center;
|
|
background: #0f0f0f;
|
|
color: #fff;
|
|
font-size: 32rpx;
|
|
font-weight: 600;
|
|
border-radius: 48rpx;
|
|
}
|
|
|
|
.cell {
|
|
display: flex;
|
|
align-items: flex-start;
|
|
background: #fff;
|
|
border-radius: 16rpx;
|
|
padding: 24rpx 28rpx;
|
|
margin-bottom: 20rpx;
|
|
box-shadow: 0 2rpx 12rpx rgba(0, 0, 0, 0.06);
|
|
}
|
|
|
|
.cell-media {
|
|
flex-shrink: 0;
|
|
margin-right: 24rpx;
|
|
}
|
|
|
|
.cell-logo {
|
|
width: 112rpx;
|
|
height: 112rpx;
|
|
border-radius: 12rpx;
|
|
background: #e8eaed;
|
|
display: block;
|
|
}
|
|
|
|
.cell-logo--placeholder {
|
|
box-sizing: border-box;
|
|
border: 1rpx dashed #cfd4dc;
|
|
background: #f0f2f5;
|
|
}
|
|
|
|
.cell-body {
|
|
flex: 1;
|
|
min-width: 0;
|
|
}
|
|
|
|
.cell-title {
|
|
display: block;
|
|
font-size: 30rpx;
|
|
font-weight: 600;
|
|
color: #1a1a1a;
|
|
line-height: 1.4;
|
|
}
|
|
|
|
.cell-email {
|
|
display: block;
|
|
margin-top: 10rpx;
|
|
font-size: 26rpx;
|
|
color: #2563eb;
|
|
line-height: 1.4;
|
|
word-break: break-all;
|
|
}
|
|
|
|
.cell-sub {
|
|
display: block;
|
|
margin-top: 10rpx;
|
|
font-size: 24rpx;
|
|
color: #6b7280;
|
|
line-height: 1.45;
|
|
}
|
|
</style>
|