ck@123911.net 6 days ago
parent
commit
0216394566
2 changed files with 462 additions and 442 deletions
  1. 444 440
      pages/crowdFunding/crowdFunding.vue
  2. 18 2
      pages/vip/M_purchase.vue

+ 444 - 440
pages/crowdFunding/crowdFunding.vue

@@ -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>

+ 18 - 2
pages/vip/M_purchase.vue

@@ -472,6 +472,7 @@
 				// 先创建订单
 				uni.request({
 					url: this.$apiHost + "/AppleIap/submit",
+					method: "GET",
 					data: {
 						uuid: getApp().globalData.uuid,
 						product_id: this.tid,
@@ -479,6 +480,7 @@
 					},
 					header: {
 						"content-type": "application/json",
+						sign: getApp().globalData.headerSign,
 					},
 					success: (res) => {
 						console.log("苹果内购订单创建响应:", res.data);
@@ -498,10 +500,24 @@
 							that.isSubmitting = false;
 						}
 					},
+					complete: (com) => {
+						// uni.hideLoading();
+					},
 					fail: (err) => {
-						console.log("创建苹果内购订单失败:", err);
+            console.log("完整错误信息:", JSON.stringify(err));
+						console.log("错误消息:", err.errMsg);
+						console.log("状态码:", err.statusCode);
+						
+						let errorMessage = "网络错误,请重试";
+						if (err.errMsg) {
+							if (err.errMsg.includes('timeout')) {
+								errorMessage = "请求超时,请检查网络";
+							} else if (err.errMsg.includes('fail')) {
+								errorMessage = "网络连接失败";
+							}
+						}
 						uni.showToast({
-							title: "网络错误,请重试",
+							title: errorMessage,
 							icon: "none"
 						});
 						that.isSubmitting = false;