|
@@ -1,447 +1,451 @@
|
|
|
<template>
|
|
|
- <view class="crowd-funding-page">
|
|
|
- <!-- 头部导航 -->
|
|
|
- <view class="navbar" ref="header">
|
|
|
- <view style="display: flex; align-items: center">
|
|
|
- <view
|
|
|
- class="nav-left"
|
|
|
- @click="goBack"
|
|
|
- >
|
|
|
- <text class="fa fa-angle-left back-icon"></text>
|
|
|
- </view>
|
|
|
- <view class="nav-title">众筹</view>
|
|
|
- </view>
|
|
|
-
|
|
|
- <!-- 搜索框 -->
|
|
|
- <view
|
|
|
- class="search-bar-container"
|
|
|
- @click="goPages('/pages/crowdFunding/Search')"
|
|
|
- >
|
|
|
- <view class="search-input-wrapper" >
|
|
|
- <image
|
|
|
- src="/static/crowdFunding/search.png"
|
|
|
- class="search-icon"
|
|
|
- ></image >
|
|
|
- <input
|
|
|
- type="text"
|
|
|
- placeholder="搜索你感兴趣的内容"
|
|
|
- class="search-input"
|
|
|
-
|
|
|
- />
|
|
|
- </view>
|
|
|
- </view>
|
|
|
-
|
|
|
- <view class="nav-right" @click="goPages('/pages/crowdFunding/favorites')">
|
|
|
- <image
|
|
|
- src="/static/crowdFunding/collect-active1.png"
|
|
|
- class="action-icon"
|
|
|
- ></image>
|
|
|
- </view>
|
|
|
- </view>
|
|
|
-
|
|
|
- <!-- Tab导航 -->
|
|
|
- <view class="tab-box" ref="tabbar">
|
|
|
- <scroll-view
|
|
|
- scroll-x
|
|
|
- class="tabs-scroll-view"
|
|
|
- :show-scrollbar="false"
|
|
|
- :scroll-into-view="'tab-' + (currentTab - 1)"
|
|
|
- scroll-with-animation
|
|
|
- >
|
|
|
- <view class="tabs-wrapper">
|
|
|
- <view
|
|
|
- v-for="(tab, index) in tabs"
|
|
|
- :key="index"
|
|
|
- :id="'tab-' + index"
|
|
|
- :class="['tab-item', currentTab === index ? 'active' : '']"
|
|
|
- @click="switchTab(index)"
|
|
|
- >
|
|
|
- <view><image v-if="tab.icon" :src="tab.icon" class="tab-icon"/>{{ tab.name }}</view>
|
|
|
-
|
|
|
- </view>
|
|
|
- <!-- 右侧占位空白 -->
|
|
|
- <view class="tab-placeholder"></view>
|
|
|
- </view>
|
|
|
- </scroll-view>
|
|
|
- <view class="mask"></view>
|
|
|
- </view>
|
|
|
- <!-- 内容区域:swiper实现左右滑动切换tab,每个tab一个scroll-view,支持下拉刷新 -->
|
|
|
- <swiper
|
|
|
- class="tab-swiper"
|
|
|
- :current="currentTab"
|
|
|
- @change="onSwiperChange"
|
|
|
- :style="{ height: swiperHeight + 'px', width: '100vw' }"
|
|
|
- >
|
|
|
- <swiper-item
|
|
|
- v-for="(tab, tabIndex) in tabs"
|
|
|
- :key="tabIndex"
|
|
|
- >
|
|
|
- <scroll-view
|
|
|
- scroll-y
|
|
|
- class="content-scroll"
|
|
|
- :style="{ height: swiperHeight + 'px' }"
|
|
|
- :refresher-enabled="true"
|
|
|
- :refresher-triggered="isRefreshing[tabIndex]"
|
|
|
- refresher-background="#f2f6f2"
|
|
|
- @refresherrefresh="onRefresh(tabIndex)"
|
|
|
- @scroll="(e) => onScroll(e, tabIndex)"
|
|
|
- :scroll-top="shouldRestoreScroll[tabIndex] ? (scrollTop[tabIndex] || 0) : undefined"
|
|
|
- @scrolltolower="onScrollToLower(tabIndex)"
|
|
|
- >
|
|
|
- <view class="items-grid">
|
|
|
- <CrowdFundingItem
|
|
|
- v-for="item in tabData[tabIndex]"
|
|
|
- :key="item.id"
|
|
|
- :item="item"
|
|
|
- @click="goToDetail(item.id)"
|
|
|
- />
|
|
|
- </view>
|
|
|
- <view v-if="loadingMore[tabIndex]" class="loading-more">加载中...</view>
|
|
|
- <view v-else-if="!hasMore[tabIndex]" class="no-more">没有更多了</view>
|
|
|
- </scroll-view>
|
|
|
- </swiper-item>
|
|
|
- </swiper>
|
|
|
- </view>
|
|
|
+ <view class="crowd-funding-page">
|
|
|
+ <!-- 头部导航 -->
|
|
|
+ <view class="navbar" ref="header">
|
|
|
+ <view style="display: flex; align-items: center">
|
|
|
+ <view class="nav-left" @click="goBack">
|
|
|
+ <text class="fa fa-angle-left back-icon"></text>
|
|
|
+ </view>
|
|
|
+ <view class="nav-title">众筹</view>
|
|
|
+ </view>
|
|
|
+
|
|
|
+ <!-- 搜索框 -->
|
|
|
+ <view class="search-bar-container" @click="goPages('/pages/crowdFunding/Search')">
|
|
|
+ <view class="search-input-wrapper">
|
|
|
+ <image src="/static/crowdFunding/search.png" class="search-icon" mode="heightFix"></image>
|
|
|
+ <input type="text" placeholder="搜索你感兴趣的内容" class="search-input" />
|
|
|
+ </view>
|
|
|
+ </view>
|
|
|
+
|
|
|
+ <view class="nav-right" @click="goPages('/pages/crowdFunding/favorites')">
|
|
|
+ <image src="/static/crowdFunding/collect-active1.png" class="action-icon"></image>
|
|
|
+ </view>
|
|
|
+ </view>
|
|
|
+
|
|
|
+ <!-- Tab导航 -->
|
|
|
+ <view class="tab-box" ref="tabbar">
|
|
|
+ <scroll-view scroll-x class="tabs-scroll-view" :show-scrollbar="false"
|
|
|
+ :scroll-into-view="'tab-' + (currentTab - 1)" scroll-with-animation>
|
|
|
+ <view class="tabs-wrapper">
|
|
|
+ <view v-for="(tab, index) in tabs" :key="index" :id="'tab-' + index"
|
|
|
+ :class="['tab-item', currentTab === index ? 'active' : '']" @click="switchTab(index)">
|
|
|
+ <view>
|
|
|
+ <image v-if="tab.icon" :src="tab.icon" class="tab-icon" />{{ tab.name }}
|
|
|
+ </view>
|
|
|
+
|
|
|
+ </view>
|
|
|
+ <!-- 右侧占位空白 -->
|
|
|
+ <view class="tab-placeholder"></view>
|
|
|
+ </view>
|
|
|
+ </scroll-view>
|
|
|
+ <view class="mask"></view>
|
|
|
+ </view>
|
|
|
+ <!-- 内容区域:swiper实现左右滑动切换tab,每个tab一个scroll-view,支持下拉刷新 -->
|
|
|
+ <swiper class="tab-swiper" :current="currentTab" @change="onSwiperChange"
|
|
|
+ :style="{ height: swiperHeight + 'px', width: '100vw' }">
|
|
|
+ <swiper-item v-for="(tab, tabIndex) in tabs" :key="tabIndex">
|
|
|
+ <scroll-view scroll-y class="content-scroll" :style="{ height: swiperHeight + 'px' }"
|
|
|
+ :refresher-enabled="true" :refresher-triggered="isRefreshing[tabIndex]"
|
|
|
+ refresher-background="#f2f6f2" @refresherrefresh="onRefresh(tabIndex)"
|
|
|
+ @scroll="(e) => onScroll(e, tabIndex)"
|
|
|
+ :scroll-top="shouldRestoreScroll[tabIndex] ? (scrollTop[tabIndex] || 0) : undefined"
|
|
|
+ @scrolltolower="onScrollToLower(tabIndex)">
|
|
|
+ <view class="items-grid">
|
|
|
+ <CrowdFundingItem v-for="item in tabData[tabIndex]" :key="item.id" :item="item"
|
|
|
+ @click="goToDetail(item.id)" />
|
|
|
+ </view>
|
|
|
+ <view v-if="loadingMore[tabIndex]" class="loading-more">加载中...</view>
|
|
|
+ <view v-else-if="!hasMore[tabIndex]" class="no-more">没有更多了</view>
|
|
|
+ </scroll-view>
|
|
|
+ </swiper-item>
|
|
|
+ </swiper>
|
|
|
+ </view>
|
|
|
</template>
|
|
|
|
|
|
<script>
|
|
|
-import CrowdFundingItem from "./components/CrowdFundingItem/CrowdFundingItem.vue";
|
|
|
-export default {
|
|
|
- components: { CrowdFundingItem },
|
|
|
- data() {
|
|
|
- return {
|
|
|
- tabs: [],
|
|
|
- currentTab: 0,
|
|
|
- tabData: [],
|
|
|
- scrollTop: {},
|
|
|
- swiperHeight: 600,
|
|
|
- isRefreshing: [],
|
|
|
- shouldRestoreScroll: [],
|
|
|
- page: [],
|
|
|
- hasMore: [],
|
|
|
- loadingMore: [],
|
|
|
- pageSize: 20,
|
|
|
- keyword: '',
|
|
|
- };
|
|
|
- },
|
|
|
- mounted() {
|
|
|
- // 动态获取头部和tab栏高度
|
|
|
- const sys = uni.getSystemInfoSync();
|
|
|
- const windowHeight = sys.windowHeight;
|
|
|
- this.$nextTick(() => {
|
|
|
- uni.createSelectorQuery()
|
|
|
- .in(this)
|
|
|
- .select('.navbar')
|
|
|
- .boundingClientRect(rect1 => {
|
|
|
- uni.createSelectorQuery()
|
|
|
- .in(this)
|
|
|
- .select('.tab-box')
|
|
|
- .boundingClientRect(rect2 => {
|
|
|
- const headerHeight = rect1 ? rect1.height : 0;
|
|
|
- const tabbarHeight = rect2 ? rect2.height : 0;
|
|
|
- this.swiperHeight = windowHeight - headerHeight - tabbarHeight;
|
|
|
- })
|
|
|
- .exec();
|
|
|
- })
|
|
|
- .exec();
|
|
|
- });
|
|
|
- // 动态获取tabs
|
|
|
- this.getTabs();
|
|
|
- },
|
|
|
- methods: {
|
|
|
- getTabs() {
|
|
|
- uni.request({
|
|
|
- url: this.$apiHost + '/crowdfund/categories',
|
|
|
- method: 'GET',
|
|
|
- success: (res) => {
|
|
|
- console.log(res.data.data,"获取分类");
|
|
|
-
|
|
|
- if (res.data && res.data.success === 'yes' && Array.isArray(res.data.data.list)) {
|
|
|
- this.tabs = [{ name: '全部', id: '' }, ...res.data.data.list.map(item => ({ name: item.name, id: item.id, icon: item.icon }))];
|
|
|
- } else {
|
|
|
- this.tabs = [{ name: '全部', id: '' }];
|
|
|
- }
|
|
|
- },
|
|
|
- fail: () => {
|
|
|
- this.tabs = [{ name: '全部', id: '' }];
|
|
|
- },
|
|
|
- complete: () => {
|
|
|
- // 初始化tab相关数组长度
|
|
|
- const len = this.tabs.length;
|
|
|
- this.tabData = Array(len).fill([]);
|
|
|
- this.isRefreshing = Array(len).fill(false);
|
|
|
- this.shouldRestoreScroll = Array(len).fill(true);
|
|
|
- this.page = Array(len).fill(1);
|
|
|
- this.hasMore = Array(len).fill(true);
|
|
|
- this.loadingMore = Array(len).fill(false);
|
|
|
- // 加载第一个tab数据
|
|
|
- this.fetchData(0);
|
|
|
- }
|
|
|
- });
|
|
|
- },
|
|
|
- goBack() {
|
|
|
- uni.navigateBack();
|
|
|
- },
|
|
|
- goPages(url) {
|
|
|
- if (url === '/pages/crowdFunding/Search') {
|
|
|
- uni.$emit("check_login", () => {
|
|
|
- uni.navigateTo({
|
|
|
- url: '/pages/crowdFunding/Search',
|
|
|
- });
|
|
|
- });
|
|
|
- } else {
|
|
|
- uni.navigateTo({
|
|
|
- url,
|
|
|
- });
|
|
|
- }
|
|
|
- },
|
|
|
- switchTab(index) {
|
|
|
- this.currentTab = index;
|
|
|
- this.$set(this.shouldRestoreScroll, index, true);
|
|
|
- if (!this.tabData[index] || this.tabData[index].length === 0) {
|
|
|
- this.fetchData(index);
|
|
|
- }
|
|
|
- },
|
|
|
- onSwiperChange(e) {
|
|
|
- this.switchTab(e.detail.current);
|
|
|
- },
|
|
|
- async onRefresh(tabIndex) {
|
|
|
- this.$set(this.isRefreshing, tabIndex, true);
|
|
|
- await this.fetchData(tabIndex, true);
|
|
|
- this.$set(this.isRefreshing, tabIndex, false);
|
|
|
- },
|
|
|
- onScroll(e, tabIndex) {
|
|
|
- this.$set(this.scrollTop, tabIndex, e.detail.scrollTop);
|
|
|
- if (this.shouldRestoreScroll[tabIndex]) {
|
|
|
- this.$set(this.shouldRestoreScroll, tabIndex, false);
|
|
|
- }
|
|
|
- },
|
|
|
- async onScrollToLower(tabIndex) {
|
|
|
- if (!this.hasMore[tabIndex] || this.loadingMore[tabIndex]) return;
|
|
|
- this.$set(this.loadingMore, tabIndex, true);
|
|
|
- await this.fetchData(tabIndex, false, true);
|
|
|
- this.$set(this.loadingMore, tabIndex, false);
|
|
|
- },
|
|
|
- async fetchData(tabIndex, isRefresh = false, isLoadMore = false) {
|
|
|
- if (isRefresh) {
|
|
|
- this.page[tabIndex] = 1;
|
|
|
- this.hasMore[tabIndex] = true;
|
|
|
- }
|
|
|
- if (isLoadMore) {
|
|
|
- this.page[tabIndex]++;
|
|
|
- } else {
|
|
|
- this.page[tabIndex] = 1;
|
|
|
- }
|
|
|
- const params = {
|
|
|
- page: this.page[tabIndex],
|
|
|
- pageSize: this.pageSize,
|
|
|
- category_id: this.tabs[tabIndex]?.id || '',
|
|
|
- keyword: this.keyword
|
|
|
- };
|
|
|
- try {
|
|
|
- const [err, res] = await uni.request({
|
|
|
- url: this.$apiHost + '/crowdfund/list',
|
|
|
- method: 'GET',
|
|
|
- data: params
|
|
|
- });
|
|
|
- if (!err && res && res.data && res.data.data) {
|
|
|
- let list = res.data.data.list;
|
|
|
- console.log(list,"获取列表");
|
|
|
- if (isLoadMore) {
|
|
|
- this.$set(this.tabData, tabIndex, [...this.tabData[tabIndex], ...list]);
|
|
|
- } else {
|
|
|
- this.$set(this.tabData, tabIndex, list);
|
|
|
- }
|
|
|
- this.$set(this.hasMore, tabIndex, list.length === this.pageSize);
|
|
|
- } else {
|
|
|
- this.$set(this.hasMore, tabIndex, false);
|
|
|
- }
|
|
|
- } catch (e) {
|
|
|
- this.$set(this.hasMore, tabIndex, false);
|
|
|
- }
|
|
|
- },
|
|
|
- goToDetail(id) {
|
|
|
- // 跳转详情页
|
|
|
- uni.navigateTo({ url: '/pages/crowdFunding/crowdfundingDetails?id=' + id });
|
|
|
- },
|
|
|
- // 搜索输入事件
|
|
|
- onSearchInput(e) {
|
|
|
- this.keyword = e.detail.value;
|
|
|
- this.fetchData(this.currentTab, true);
|
|
|
- },
|
|
|
- },
|
|
|
-};
|
|
|
+ import CrowdFundingItem from "./components/CrowdFundingItem/CrowdFundingItem.vue";
|
|
|
+ export default {
|
|
|
+ components: {
|
|
|
+ CrowdFundingItem
|
|
|
+ },
|
|
|
+ data() {
|
|
|
+ return {
|
|
|
+ tabs: [],
|
|
|
+ currentTab: 0,
|
|
|
+ tabData: [],
|
|
|
+ scrollTop: {},
|
|
|
+ swiperHeight: 600,
|
|
|
+ isRefreshing: [],
|
|
|
+ shouldRestoreScroll: [],
|
|
|
+ page: [],
|
|
|
+ hasMore: [],
|
|
|
+ loadingMore: [],
|
|
|
+ pageSize: 20,
|
|
|
+ keyword: '',
|
|
|
+ };
|
|
|
+ },
|
|
|
+ mounted() {
|
|
|
+ // 动态获取头部和tab栏高度
|
|
|
+ const sys = uni.getSystemInfoSync();
|
|
|
+ const windowHeight = sys.windowHeight;
|
|
|
+ this.$nextTick(() => {
|
|
|
+ uni.createSelectorQuery()
|
|
|
+ .in(this)
|
|
|
+ .select('.navbar')
|
|
|
+ .boundingClientRect(rect1 => {
|
|
|
+ uni.createSelectorQuery()
|
|
|
+ .in(this)
|
|
|
+ .select('.tab-box')
|
|
|
+ .boundingClientRect(rect2 => {
|
|
|
+ const headerHeight = rect1 ? rect1.height : 0;
|
|
|
+ const tabbarHeight = rect2 ? rect2.height : 0;
|
|
|
+ this.swiperHeight = windowHeight - headerHeight - tabbarHeight;
|
|
|
+ })
|
|
|
+ .exec();
|
|
|
+ })
|
|
|
+ .exec();
|
|
|
+ });
|
|
|
+ // 动态获取tabs
|
|
|
+ this.getTabs();
|
|
|
+ },
|
|
|
+ methods: {
|
|
|
+ getTabs() {
|
|
|
+ uni.request({
|
|
|
+ url: this.$apiHost + '/crowdfund/categories',
|
|
|
+ method: 'GET',
|
|
|
+ success: (res) => {
|
|
|
+ console.log(res.data.data, "获取分类");
|
|
|
+
|
|
|
+ if (res.data && res.data.success === 'yes' && Array.isArray(res.data.data.list)) {
|
|
|
+ this.tabs = [{
|
|
|
+ name: '全部',
|
|
|
+ id: ''
|
|
|
+ }, ...res.data.data.list.map(item => ({
|
|
|
+ name: item.name,
|
|
|
+ id: item.id,
|
|
|
+ icon: item.icon
|
|
|
+ }))];
|
|
|
+ } else {
|
|
|
+ this.tabs = [{
|
|
|
+ name: '全部',
|
|
|
+ id: ''
|
|
|
+ }];
|
|
|
+ }
|
|
|
+ },
|
|
|
+ fail: () => {
|
|
|
+ this.tabs = [{
|
|
|
+ name: '全部',
|
|
|
+ id: ''
|
|
|
+ }];
|
|
|
+ },
|
|
|
+ complete: () => {
|
|
|
+ // 初始化tab相关数组长度
|
|
|
+ const len = this.tabs.length;
|
|
|
+ this.tabData = Array(len).fill([]);
|
|
|
+ this.isRefreshing = Array(len).fill(false);
|
|
|
+ this.shouldRestoreScroll = Array(len).fill(true);
|
|
|
+ this.page = Array(len).fill(1);
|
|
|
+ this.hasMore = Array(len).fill(true);
|
|
|
+ this.loadingMore = Array(len).fill(false);
|
|
|
+ // 加载第一个tab数据
|
|
|
+ this.fetchData(0);
|
|
|
+ }
|
|
|
+ });
|
|
|
+ },
|
|
|
+ goBack() {
|
|
|
+ uni.navigateBack();
|
|
|
+ },
|
|
|
+ goPages(url) {
|
|
|
+ if (url === '/pages/crowdFunding/Search') {
|
|
|
+ uni.$emit("check_login", () => {
|
|
|
+ uni.navigateTo({
|
|
|
+ url: '/pages/crowdFunding/Search',
|
|
|
+ });
|
|
|
+ });
|
|
|
+ } else {
|
|
|
+ uni.navigateTo({
|
|
|
+ url,
|
|
|
+ });
|
|
|
+ }
|
|
|
+ },
|
|
|
+ switchTab(index) {
|
|
|
+ this.currentTab = index;
|
|
|
+ this.$set(this.shouldRestoreScroll, index, true);
|
|
|
+ if (!this.tabData[index] || this.tabData[index].length === 0) {
|
|
|
+ this.fetchData(index);
|
|
|
+ }
|
|
|
+ },
|
|
|
+ onSwiperChange(e) {
|
|
|
+ this.switchTab(e.detail.current);
|
|
|
+ },
|
|
|
+ async onRefresh(tabIndex) {
|
|
|
+ this.$set(this.isRefreshing, tabIndex, true);
|
|
|
+ await this.fetchData(tabIndex, true);
|
|
|
+ this.$set(this.isRefreshing, tabIndex, false);
|
|
|
+ },
|
|
|
+ onScroll(e, tabIndex) {
|
|
|
+ this.$set(this.scrollTop, tabIndex, e.detail.scrollTop);
|
|
|
+ if (this.shouldRestoreScroll[tabIndex]) {
|
|
|
+ this.$set(this.shouldRestoreScroll, tabIndex, false);
|
|
|
+ }
|
|
|
+ },
|
|
|
+ async onScrollToLower(tabIndex) {
|
|
|
+ if (!this.hasMore[tabIndex] || this.loadingMore[tabIndex]) return;
|
|
|
+ this.$set(this.loadingMore, tabIndex, true);
|
|
|
+ await this.fetchData(tabIndex, false, true);
|
|
|
+ this.$set(this.loadingMore, tabIndex, false);
|
|
|
+ },
|
|
|
+ async fetchData(tabIndex, isRefresh = false, isLoadMore = false) {
|
|
|
+ if (isRefresh) {
|
|
|
+ this.page[tabIndex] = 1;
|
|
|
+ this.hasMore[tabIndex] = true;
|
|
|
+ }
|
|
|
+ if (isLoadMore) {
|
|
|
+ this.page[tabIndex]++;
|
|
|
+ } else {
|
|
|
+ this.page[tabIndex] = 1;
|
|
|
+ }
|
|
|
+ const params = {
|
|
|
+ page: this.page[tabIndex],
|
|
|
+ pageSize: this.pageSize,
|
|
|
+ category_id: this.tabs[tabIndex]?.id || '',
|
|
|
+ keyword: this.keyword
|
|
|
+ };
|
|
|
+ try {
|
|
|
+ const [err, res] = await uni.request({
|
|
|
+ url: this.$apiHost + '/crowdfund/list',
|
|
|
+ method: 'GET',
|
|
|
+ data: params
|
|
|
+ });
|
|
|
+ if (!err && res && res.data && res.data.data) {
|
|
|
+ let list = res.data.data.list;
|
|
|
+ console.log(list, "获取列表");
|
|
|
+ if (isLoadMore) {
|
|
|
+ this.$set(this.tabData, tabIndex, [...this.tabData[tabIndex], ...list]);
|
|
|
+ } else {
|
|
|
+ this.$set(this.tabData, tabIndex, list);
|
|
|
+ }
|
|
|
+ this.$set(this.hasMore, tabIndex, list.length === this.pageSize);
|
|
|
+ } else {
|
|
|
+ this.$set(this.hasMore, tabIndex, false);
|
|
|
+ }
|
|
|
+ } catch (e) {
|
|
|
+ this.$set(this.hasMore, tabIndex, false);
|
|
|
+ }
|
|
|
+ },
|
|
|
+ goToDetail(id) {
|
|
|
+ // 跳转详情页
|
|
|
+ uni.navigateTo({
|
|
|
+ url: '/pages/crowdFunding/crowdfundingDetails?id=' + id
|
|
|
+ });
|
|
|
+ },
|
|
|
+ // 搜索输入事件
|
|
|
+ onSearchInput(e) {
|
|
|
+ this.keyword = e.detail.value;
|
|
|
+ this.fetchData(this.currentTab, true);
|
|
|
+ },
|
|
|
+ },
|
|
|
+ };
|
|
|
</script>
|
|
|
|
|
|
<style lang="scss" scoped>
|
|
|
-.crowd-funding-page {
|
|
|
- display: flex;
|
|
|
- flex-direction: column;
|
|
|
- background: #f2f6f2;
|
|
|
- height: 100vh; // 移除,避免撑死内容
|
|
|
-}
|
|
|
-
|
|
|
-.navbar {
|
|
|
- display: flex;
|
|
|
- align-items: center;
|
|
|
- justify-content: space-between;
|
|
|
- // height: 96rpx;
|
|
|
- background: #fff;
|
|
|
- padding: 46rpx 20rpx 26rpx 30rpx;
|
|
|
- padding-top: calc(var(--status-bar-height) + 46rpx);
|
|
|
- box-sizing: content-box;
|
|
|
- .nav-left {
|
|
|
- width: 36rpx;
|
|
|
- display: flex;
|
|
|
- align-items: center;
|
|
|
- .back-icon {
|
|
|
- font-size: 50rpx;
|
|
|
- }
|
|
|
- }
|
|
|
- .nav-title {
|
|
|
- font-size: 36rpx;
|
|
|
- font-weight: bold;
|
|
|
- color: #222;
|
|
|
- letter-spacing: 2rpx;
|
|
|
- }
|
|
|
-
|
|
|
- .search-bar-container {
|
|
|
- padding: 0 24rpx;
|
|
|
- display: flex;
|
|
|
- align-items: center;
|
|
|
- width: 450rpx;
|
|
|
- height: 64rpx;
|
|
|
- background: #f2f6f2;
|
|
|
- border-radius: 36rpx;
|
|
|
- ::v-deep.input-placeholder {
|
|
|
- color: #999;
|
|
|
- }
|
|
|
- .search-input-wrapper {
|
|
|
- display: flex;
|
|
|
- align-items: center;
|
|
|
- width: 100%;
|
|
|
-
|
|
|
- .search-icon {
|
|
|
- width: 32rpx;
|
|
|
- height: 32rpx;
|
|
|
- margin-right: 10rpx;
|
|
|
- }
|
|
|
- .search-input {
|
|
|
- font-size: 28rpx;
|
|
|
- color: #999;
|
|
|
- line-height: 64rpx;
|
|
|
- background: transparent;
|
|
|
- border: none;
|
|
|
- outline: none;
|
|
|
- width: 100%;
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- .nav-right {
|
|
|
- .action-icon {
|
|
|
- width: 64rpx;
|
|
|
- height: 64rpx;
|
|
|
- border-radius: 50%;
|
|
|
- }
|
|
|
- }
|
|
|
-}
|
|
|
-.tab-box {
|
|
|
- width: 100vw;
|
|
|
- height: auto;
|
|
|
- position: relative;
|
|
|
- left: 0;
|
|
|
- top: 0;
|
|
|
- border-bottom: solid 5rpx #F2F6F2;
|
|
|
- .mask {
|
|
|
- position: absolute;
|
|
|
- right: 0;
|
|
|
- top: 0;
|
|
|
- width: 200rpx;
|
|
|
- height: 100%;
|
|
|
- background: linear-gradient(90deg, rgba(255, 255, 255, 0) 0%, #ffffff 100%);
|
|
|
- pointer-events: none;
|
|
|
- }
|
|
|
-}
|
|
|
-.tabs-scroll-view {
|
|
|
- width: 100%;
|
|
|
- background: #fff;
|
|
|
- padding-bottom: 22rpx;
|
|
|
-
|
|
|
- .tabs-wrapper {
|
|
|
- display: flex;
|
|
|
- align-items: center;
|
|
|
- padding-left: 12rpx;
|
|
|
- padding-right: 200rpx;
|
|
|
- box-sizing: content-box;
|
|
|
- }
|
|
|
-}
|
|
|
-.tab-item {
|
|
|
- display: flex;
|
|
|
- align-items: center;
|
|
|
- font-size: 28rpx;
|
|
|
- color: #666;
|
|
|
- padding: 8rpx 28rpx;
|
|
|
- margin-right: 8rpx;
|
|
|
- border-radius: 32rpx;
|
|
|
- font-weight: 500;
|
|
|
- background: transparent;
|
|
|
- transition: background 0.2s, color 0.2s;
|
|
|
- view {
|
|
|
- white-space: nowrap;
|
|
|
- display: flex;
|
|
|
- align-items: center;
|
|
|
- .tab-icon{
|
|
|
- width: 40rpx;
|
|
|
- height: 40rpx;
|
|
|
- margin: 0;
|
|
|
- padding: 0;
|
|
|
- display: inline-block;
|
|
|
- }
|
|
|
- }
|
|
|
- text-wrap: nowrap;
|
|
|
- .tab-icon {
|
|
|
- width: 32rpx;
|
|
|
- height: 32rpx;
|
|
|
- margin-right: 8rpx;
|
|
|
- }
|
|
|
- &.active {
|
|
|
- font-weight: bold;
|
|
|
- color: #fff;
|
|
|
- background: #222;
|
|
|
- box-shadow: 0 2rpx 8rpx rgba(34, 34, 34, 0.08);
|
|
|
- .tab-icon {
|
|
|
- filter: brightness(1.5) saturate(2);
|
|
|
- }
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-.tab-swiper {
|
|
|
- width: 100vw;
|
|
|
- background: #f2f6f2;
|
|
|
-}
|
|
|
-.swiper-item {
|
|
|
- background: #f2f6f2;
|
|
|
-}
|
|
|
-.content-scroll {
|
|
|
- overflow-y: auto;
|
|
|
- padding-bottom: 24rpx;
|
|
|
- background: #f2f6f2;
|
|
|
-}
|
|
|
-
|
|
|
-.items-grid {
|
|
|
- display: grid;
|
|
|
- grid-template-columns: repeat(2, 1fr);
|
|
|
- gap: 24rpx 12rpx;
|
|
|
- padding: 16rpx 12rpx 0 12rpx;
|
|
|
- background: #f2f6f2;
|
|
|
-}
|
|
|
-
|
|
|
-.tab-placeholder {
|
|
|
- width: 200rpx;
|
|
|
- flex-shrink: 0;
|
|
|
- height: 1px; // 不影响高度
|
|
|
-}
|
|
|
-
|
|
|
-.loading-more { text-align: center; color: #999; font-size: 26rpx; padding: 24rpx 0; }
|
|
|
-.no-more { text-align: center; color: #ccc; font-size: 24rpx; padding: 20rpx 0; }
|
|
|
-</style>
|
|
|
+ .crowd-funding-page {
|
|
|
+ display: flex;
|
|
|
+ flex-direction: column;
|
|
|
+ background: #f2f6f2;
|
|
|
+ height: 100vh; // 移除,避免撑死内容
|
|
|
+ }
|
|
|
+
|
|
|
+ .navbar {
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ justify-content: space-between;
|
|
|
+ // height: 96rpx;
|
|
|
+ background: #fff;
|
|
|
+ padding: 46rpx 20rpx 26rpx 30rpx;
|
|
|
+ padding-top: calc(var(--status-bar-height) + 46rpx);
|
|
|
+ box-sizing: content-box;
|
|
|
+
|
|
|
+ .nav-left {
|
|
|
+ width: 36rpx;
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+
|
|
|
+ .back-icon {
|
|
|
+ font-size: 50rpx;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ .nav-title {
|
|
|
+ font-size: 36rpx;
|
|
|
+ font-weight: bold;
|
|
|
+ color: #222;
|
|
|
+ letter-spacing: 2rpx;
|
|
|
+ }
|
|
|
+
|
|
|
+ .search-bar-container {
|
|
|
+ padding: 0 24rpx;
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ width: 450rpx;
|
|
|
+ height: 64rpx;
|
|
|
+ background: #f2f6f2;
|
|
|
+ border-radius: 36rpx;
|
|
|
+
|
|
|
+ ::v-deep.input-placeholder {
|
|
|
+ color: #999;
|
|
|
+ }
|
|
|
+
|
|
|
+ .search-input-wrapper {
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ width: 100%;
|
|
|
+
|
|
|
+ .search-icon {
|
|
|
+ width: 32rpx;
|
|
|
+ height: 32rpx;
|
|
|
+ margin-right: 10rpx;
|
|
|
+ }
|
|
|
+
|
|
|
+ .search-input {
|
|
|
+ font-size: 28rpx;
|
|
|
+ color: #999;
|
|
|
+ line-height: 64rpx;
|
|
|
+ background: transparent;
|
|
|
+ border: none;
|
|
|
+ outline: none;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ .nav-right {
|
|
|
+ .action-icon {
|
|
|
+ width: 64rpx;
|
|
|
+ height: 64rpx;
|
|
|
+ border-radius: 50%;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ .tab-box {
|
|
|
+ width: 100vw;
|
|
|
+ height: auto;
|
|
|
+ position: relative;
|
|
|
+ left: 0;
|
|
|
+ top: 0;
|
|
|
+ border-bottom: solid 5rpx #F2F6F2;
|
|
|
+
|
|
|
+ .mask {
|
|
|
+ position: absolute;
|
|
|
+ right: 0;
|
|
|
+ top: 0;
|
|
|
+ width: 200rpx;
|
|
|
+ height: 100%;
|
|
|
+ background: linear-gradient(90deg, rgba(255, 255, 255, 0) 0%, #ffffff 100%);
|
|
|
+ pointer-events: none;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ .tabs-scroll-view {
|
|
|
+ width: 100%;
|
|
|
+ background: #fff;
|
|
|
+ padding-bottom: 22rpx;
|
|
|
+
|
|
|
+ .tabs-wrapper {
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ padding-left: 12rpx;
|
|
|
+ padding-right: 200rpx;
|
|
|
+ box-sizing: content-box;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ .tab-item {
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ font-size: 28rpx;
|
|
|
+ color: #666;
|
|
|
+ padding: 8rpx 28rpx;
|
|
|
+ margin-right: 8rpx;
|
|
|
+ border-radius: 32rpx;
|
|
|
+ font-weight: 500;
|
|
|
+ background: transparent;
|
|
|
+ transition: background 0.2s, color 0.2s;
|
|
|
+
|
|
|
+ view {
|
|
|
+ white-space: nowrap;
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+
|
|
|
+ .tab-icon {
|
|
|
+ width: 40rpx;
|
|
|
+ height: 40rpx;
|
|
|
+ margin: 0;
|
|
|
+ padding: 0;
|
|
|
+ display: inline-block;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ text-wrap: nowrap;
|
|
|
+
|
|
|
+ .tab-icon {
|
|
|
+ width: 32rpx;
|
|
|
+ height: 32rpx;
|
|
|
+ margin-right: 8rpx;
|
|
|
+ }
|
|
|
+
|
|
|
+ &.active {
|
|
|
+ font-weight: bold;
|
|
|
+ color: #fff;
|
|
|
+ background: #222;
|
|
|
+ box-shadow: 0 2rpx 8rpx rgba(34, 34, 34, 0.08);
|
|
|
+
|
|
|
+ .tab-icon {
|
|
|
+ filter: brightness(1.5) saturate(2);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ .tab-swiper {
|
|
|
+ width: 100vw;
|
|
|
+ background: #f2f6f2;
|
|
|
+ }
|
|
|
+
|
|
|
+ .swiper-item {
|
|
|
+ background: #f2f6f2;
|
|
|
+ }
|
|
|
+
|
|
|
+ .content-scroll {
|
|
|
+ overflow-y: auto;
|
|
|
+ padding-bottom: 24rpx;
|
|
|
+ background: #f2f6f2;
|
|
|
+ }
|
|
|
+
|
|
|
+ .items-grid {
|
|
|
+ display: grid;
|
|
|
+ grid-template-columns: repeat(2, 1fr);
|
|
|
+ gap: 24rpx 12rpx;
|
|
|
+ padding: 16rpx 12rpx 0 12rpx;
|
|
|
+ background: #f2f6f2;
|
|
|
+ }
|
|
|
+
|
|
|
+ .tab-placeholder {
|
|
|
+ width: 200rpx;
|
|
|
+ flex-shrink: 0;
|
|
|
+ height: 1px; // 不影响高度
|
|
|
+ }
|
|
|
+
|
|
|
+ .loading-more {
|
|
|
+ text-align: center;
|
|
|
+ color: #999;
|
|
|
+ font-size: 26rpx;
|
|
|
+ padding: 24rpx 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ .no-more {
|
|
|
+ text-align: center;
|
|
|
+ color: #ccc;
|
|
|
+ font-size: 24rpx;
|
|
|
+ padding: 20rpx 0;
|
|
|
+ }
|
|
|
+</style>
|