189 lines
4.7 KiB
Vue
189 lines
4.7 KiB
Vue
<script setup lang="ts">
|
|
import { computed, ref } from 'vue'
|
|
import { onLoad, onShow } from '@dcloudio/uni-app'
|
|
import { getProjectSubmissionDetail } from '@/api/project-submission'
|
|
import type { ProjectSubmissionItem, ProjectServiceType } from '@/types/project-submission'
|
|
import { ensureLoggedIn } from '@/utils/auth-guard'
|
|
import { navigateBackWithFallback } from '@/utils/navigate-back'
|
|
import { resolveProjectSubmissionMedia } from '@/utils/resolve-project-submission-media'
|
|
import heroBg from '@/static/icons/background.png'
|
|
|
|
const detail = ref<ProjectSubmissionItem | null>(null)
|
|
const loading = ref(true)
|
|
const heroLogo = ref('')
|
|
const serviceIcons = ref<Record<string, string>>({})
|
|
|
|
const sortedServiceTypes = computed<ProjectServiceType[]>(() => {
|
|
if (!detail.value?.serviceTypes?.length)
|
|
return []
|
|
return [...detail.value.serviceTypes].sort(
|
|
(a, b) => (a.sortOrder ?? 0) - (b.sortOrder ?? 0),
|
|
)
|
|
})
|
|
|
|
async function loadDetail(id: string) {
|
|
loading.value = true
|
|
uni.showLoading({ title: '加载中...', mask: true })
|
|
|
|
try {
|
|
const data = await getProjectSubmissionDetail(id)
|
|
detail.value = data
|
|
|
|
const media = await resolveProjectSubmissionMedia(data)
|
|
heroLogo.value = media.logoUrl || ''
|
|
serviceIcons.value = media.serviceIcons
|
|
}
|
|
catch {
|
|
detail.value = null
|
|
uni.showToast({ title: '加载失败', icon: 'none' })
|
|
}
|
|
finally {
|
|
loading.value = false
|
|
uni.hideLoading()
|
|
}
|
|
}
|
|
|
|
onLoad((options) => {
|
|
const id = options?.id as string
|
|
if (!id) {
|
|
loading.value = false
|
|
uni.showToast({ title: '参数错误', icon: 'none' })
|
|
return
|
|
}
|
|
loadDetail(id)
|
|
})
|
|
|
|
onShow(() => {
|
|
ensureLoggedIn()
|
|
})
|
|
|
|
function handleBack() {
|
|
navigateBackWithFallback('/pages/home-index/index')
|
|
}
|
|
|
|
function handleSubmit() {
|
|
if (!detail.value)
|
|
return
|
|
|
|
const businessType = detail.value.businessType || detail.value.title
|
|
uni.navigateTo({
|
|
url: `/pages/home-index/requirement-submit/index?submissionId=${detail.value.id}&businessType=${encodeURIComponent(businessType)}`,
|
|
})
|
|
}
|
|
</script>
|
|
|
|
<template>
|
|
<view
|
|
v-if="detail"
|
|
class="business-detail"
|
|
>
|
|
<view class="business-detail__navbar">
|
|
<view
|
|
class="business-detail__back"
|
|
@tap="handleBack"
|
|
>
|
|
<image
|
|
class="business-detail__back-icon"
|
|
src="/static/icons/icon-back.svg"
|
|
mode="aspectFit"
|
|
/>
|
|
</view>
|
|
<text class="business-detail__navbar-title">
|
|
业务详情
|
|
</text>
|
|
<view class="business-detail__navbar-placeholder" />
|
|
</view>
|
|
|
|
<scroll-view
|
|
class="business-detail__scroll"
|
|
scroll-y
|
|
:show-scrollbar="false"
|
|
>
|
|
<view class="business-detail__hero">
|
|
<image
|
|
class="business-detail__hero-bg"
|
|
:src="heroBg"
|
|
mode="scaleToFill"
|
|
/>
|
|
<view class="business-detail__hero-inner">
|
|
<image
|
|
v-if="heroLogo"
|
|
class="business-detail__hero-icon"
|
|
:src="heroLogo"
|
|
mode="aspectFit"
|
|
/>
|
|
<text class="business-detail__hero-title">
|
|
{{ detail.title }}
|
|
</text>
|
|
<text
|
|
v-if="detail.subtitle"
|
|
class="business-detail__hero-subtitle"
|
|
>
|
|
{{ detail.subtitle }}
|
|
</text>
|
|
</view>
|
|
</view>
|
|
|
|
<view
|
|
v-if="sortedServiceTypes.length"
|
|
class="business-detail__section"
|
|
>
|
|
<text class="business-detail__section-title">
|
|
服务类型
|
|
</text>
|
|
<view class="business-detail__type-row">
|
|
<view
|
|
v-for="type in sortedServiceTypes"
|
|
:key="type.id"
|
|
class="business-detail__type-item"
|
|
>
|
|
<image
|
|
v-if="serviceIcons[String(type.id)]"
|
|
class="business-detail__type-icon"
|
|
:src="serviceIcons[String(type.id)]"
|
|
mode="aspectFit"
|
|
/>
|
|
<text class="business-detail__type-label">
|
|
{{ type.serviceName }}
|
|
</text>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
</scroll-view>
|
|
|
|
<view class="business-detail__footer">
|
|
<view
|
|
class="business-detail__submit-btn"
|
|
@tap="handleSubmit"
|
|
>
|
|
立即提报
|
|
</view>
|
|
</view>
|
|
</view>
|
|
|
|
<view
|
|
v-else-if="!loading"
|
|
class="business-detail business-detail--empty"
|
|
>
|
|
<text class="business-detail__empty-text">
|
|
暂无详情
|
|
</text>
|
|
</view>
|
|
</template>
|
|
|
|
<style scoped lang="scss">
|
|
@import '../business-detail/index.scss';
|
|
|
|
.business-detail--empty {
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
min-height: 100vh;
|
|
}
|
|
|
|
.business-detail__empty-text {
|
|
font-size: 28rpx;
|
|
color: #999999;
|
|
}
|
|
</style>
|