231 lines
4.9 KiB
Plaintext
231 lines
4.9 KiB
Plaintext
<template>
|
|
<cl-page>
|
|
<cl-topbar title="项目详情" />
|
|
|
|
<scroll-view scroll-y class="content" v-if="project != null">
|
|
<swiper class="banner" autoplay circular indicator-dots>
|
|
<swiper-item v-for="(img, index) in projectImages" :key="index">
|
|
<image class="banner-image" :src="img" mode="aspectFill" />
|
|
</swiper-item>
|
|
</swiper>
|
|
|
|
<view class="project-info">
|
|
<text class="project-name">{{ project.name }}</text>
|
|
<view class="project-meta">
|
|
<view class="meta-item">
|
|
<text class="meta-label">周期</text>
|
|
<text class="meta-value">{{ project.duration }}天</text>
|
|
</view>
|
|
<view class="meta-item">
|
|
<text class="meta-label">权益</text>
|
|
<text class="meta-value">{{ benefits.length }}项</text>
|
|
</view>
|
|
<view class="meta-item">
|
|
<text class="meta-label">已认养</text>
|
|
<text class="meta-value">{{ project.adoptedCount }}人</text>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
|
|
<view class="benefits-section">
|
|
<text class="section-title">认养权益</text>
|
|
<view class="benefit-list">
|
|
<view v-for="(benefit, index) in benefits" :key="index" class="benefit-item">
|
|
<cl-icon name="check-circle" :size="36" color="#52c41a" />
|
|
<text class="benefit-text">{{ benefit }}</text>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
|
|
<view class="desc-section">
|
|
<text class="section-title">项目介绍</text>
|
|
<text class="desc">{{ project.description }}</text>
|
|
</view>
|
|
|
|
<view style="height: 140rpx;"></view>
|
|
</scroll-view>
|
|
|
|
<view class="bottom-bar" v-if="project != null">
|
|
<view class="price-info">
|
|
<text class="price">¥{{ project.price }}</text>
|
|
<text class="original" v-if="project.originalPrice != null">¥{{ project.originalPrice }}</text>
|
|
</view>
|
|
<cl-button type="primary" round @click="onAdopt">立即认养</cl-button>
|
|
</view>
|
|
</cl-page>
|
|
</template>
|
|
|
|
<script setup lang="uts">
|
|
import { ref, computed, onMounted } from 'vue';
|
|
import { router, useCool, parseObject } from '@/cool';
|
|
|
|
const { service } = useCool();
|
|
|
|
const project = ref<any>(null);
|
|
|
|
const projectImages = computed(() => {
|
|
if (project.value?.images == null) return ['/static/images/farm.png'];
|
|
try {
|
|
return parseObject<string[]>(project.value.images) ?? ['/static/images/farm.png'];
|
|
} catch {
|
|
return ['/static/images/farm.png'];
|
|
}
|
|
});
|
|
|
|
const benefits = computed(() => {
|
|
if (project.value?.benefits == null) return ['新鲜农产品直送', '专属认养证书', '实时生长查看'];
|
|
try {
|
|
return parseObject<string[]>(project.value.benefits) ?? ['新鲜农产品直送', '专属认养证书', '实时生长查看'];
|
|
} catch {
|
|
return ['新鲜农产品直送', '专属认养证书', '实时生长查看'];
|
|
}
|
|
});
|
|
|
|
async function loadProject() {
|
|
const pages = getCurrentPages();
|
|
const currentPage = pages[pages.length - 1];
|
|
const projectId = Number(currentPage.options?.id || 0);
|
|
|
|
if (projectId != 0) {
|
|
try {
|
|
const res = await service.nongchuang.adoption.detail({ id: projectId });
|
|
project.value = res;
|
|
} catch (e) {
|
|
project.value = {
|
|
id: projectId,
|
|
name: '有机苹果园认养',
|
|
description: '位于山东烟台的优质苹果园,采用有机种植方式',
|
|
duration: 180,
|
|
price: 299,
|
|
adoptedCount: 56
|
|
};
|
|
}
|
|
}
|
|
}
|
|
|
|
function onAdopt() {
|
|
uni.showToast({ title: '认养功能开发中', icon: 'none' });
|
|
}
|
|
|
|
onMounted(() => {
|
|
loadProject();
|
|
});
|
|
</script>
|
|
|
|
<style lang="scss" scoped>
|
|
.content {
|
|
flex: 1;
|
|
}
|
|
|
|
.banner {
|
|
height: 400rpx;
|
|
|
|
.banner-image {
|
|
width: 100%;
|
|
height: 100%;
|
|
}
|
|
}
|
|
|
|
.project-info {
|
|
padding: 30rpx;
|
|
background: #fff;
|
|
|
|
.project-name {
|
|
font-size: 36rpx;
|
|
font-weight: bold;
|
|
color: #333;
|
|
}
|
|
|
|
.project-meta {
|
|
display: flex;
|
|
flex-direction: row;
|
|
justify-content: space-around;
|
|
margin-top: 30rpx;
|
|
padding: 24rpx 0;
|
|
background: #f9f9f9;
|
|
border-radius: 12rpx;
|
|
|
|
.meta-item {
|
|
text-align: center;
|
|
|
|
.meta-label {
|
|
font-size: 24rpx;
|
|
color: #999;
|
|
}
|
|
|
|
.meta-value {
|
|
font-size: 28rpx;
|
|
color: #333;
|
|
font-weight: bold;
|
|
margin-top: 8rpx;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
.benefits-section, .desc-section {
|
|
margin-top: 20rpx;
|
|
padding: 30rpx;
|
|
background: #fff;
|
|
|
|
.section-title {
|
|
font-size: 30rpx;
|
|
font-weight: bold;
|
|
color: #333;
|
|
margin-bottom: 20rpx;
|
|
}
|
|
}
|
|
|
|
.benefit-list {
|
|
.benefit-item {
|
|
display: flex;
|
|
flex-direction: row;
|
|
align-items: center;
|
|
padding: 16rpx 0;
|
|
font-size: 28rpx;
|
|
color: #666;
|
|
|
|
.benefit-text {
|
|
margin-left: 16rpx;
|
|
}
|
|
}
|
|
}
|
|
|
|
.desc {
|
|
font-size: 28rpx;
|
|
color: #666;
|
|
line-height: 1.6;
|
|
}
|
|
|
|
.bottom-bar {
|
|
position: fixed;
|
|
bottom: 0;
|
|
left: 0;
|
|
right: 0;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: space-between;
|
|
padding: 20rpx 30rpx;
|
|
background: #fff;
|
|
box-shadow: 0 -4rpx 16rpx rgba(0, 0, 0, 0.06);
|
|
|
|
.price-info {
|
|
display: flex;
|
|
flex-direction: row;
|
|
align-items: center;
|
|
|
|
.price {
|
|
font-size: 40rpx;
|
|
font-weight: bold;
|
|
color: #ff4d4f;
|
|
}
|
|
|
|
.original {
|
|
font-size: 24rpx;
|
|
color: #999;
|
|
margin-left: 10rpx;
|
|
}
|
|
}
|
|
}
|
|
</style>
|