国外MOSE官网
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

353 lines
8.2 KiB

6 days ago
  1. <template>
  2. <view class="shop-content">
  3. <!-- 搜索框 -->
  4. <view class="search-container">
  5. <uv-search
  6. v-model="searchValue"
  7. placeholder="搜索商品名"
  8. :show-action="false"
  9. bg-color="#f3f7f8"
  10. inputAlign="center"
  11. height="40"
  12. margin="10rpx"
  13. @search="onSearch"
  14. ></uv-search>
  15. </view>
  16. <!-- Tab栏 -->
  17. <view class="tab-container">
  18. <uv-tabs
  19. :list="tabList"
  20. :current="currentTab"
  21. @change="onTabChange"
  22. active-color="#218CDD"
  23. inactive-color="#999"
  24. line-color="#218CDD"
  25. :line-width="40"
  26. :line-height="4"
  27. font-size="26"
  28. height="80"
  29. ></uv-tabs>
  30. </view>
  31. <!-- 商品列表 -->
  32. <view class="goods-container">
  33. <view class="goods-grid">
  34. <view
  35. class="goods-item"
  36. v-for="(item, index) in filteredGoodsList"
  37. :key="index"
  38. @click="onGoodsClick(item)"
  39. >
  40. <view class="goods-image">
  41. <image :src="item.image" mode="aspectFit" class="image"></image>
  42. </view>
  43. <view class="goods-info">
  44. <text class="goods-name">{{ item.name }}</text>
  45. <view class="goods-bottom">
  46. <view class="points-info">
  47. <image src="/static/积分图标.png" class="points-icon" mode="aspectFit"></image>
  48. <text class="points-text">{{ item.points }}积分</text>
  49. </view>
  50. <uv-button
  51. type="primary"
  52. size="mini"
  53. text="立即兑换"
  54. :custom-style="buttonStyle"
  55. @click.stop="onExchange(item)"
  56. ></uv-button>
  57. </view>
  58. </view>
  59. </view>
  60. </view>
  61. </view>
  62. </view>
  63. </template>
  64. <script>
  65. export default {
  66. name: 'ShopContent',
  67. data() {
  68. return {
  69. searchValue: '',
  70. currentTab: 0,
  71. tabList: [
  72. { name: '全部' },
  73. { name: '积分兑换' },
  74. { name: '兑换量' },
  75. { name: '女装' },
  76. { name: '母婴' },
  77. { name: '水果' },
  78. { name: '竹制品' }
  79. ],
  80. goodsList: [
  81. {
  82. id: 1,
  83. name: '薄脆可口数字小饼干蘑菇饼干',
  84. points: 100,
  85. image: '/static/商城_商品1.png',
  86. category: '积分兑换',
  87. exchangeCount: 120
  88. },
  89. {
  90. id: 2,
  91. name: '幼儿园宝宝启蒙书',
  92. points: 145,
  93. image: '/static/商城_商品2.png',
  94. category: '母婴',
  95. exchangeCount: 85
  96. },
  97. {
  98. id: 3,
  99. name: '薄脆可口数字小饼干蘑菇饼干',
  100. points: 100,
  101. image: '/static/商城_商品1.png',
  102. category: '积分兑换',
  103. exchangeCount: 95
  104. },
  105. {
  106. id: 4,
  107. name: '幼儿园宝宝启蒙书',
  108. points: 145,
  109. image: '/static/商城_商品2.png',
  110. category: '母婴',
  111. exchangeCount: 67
  112. },
  113. {
  114. id: 1,
  115. name: '薄脆可口数字小饼干蘑菇饼干',
  116. points: 100,
  117. image: '/static/商城_商品1.png',
  118. category: '积分兑换',
  119. exchangeCount: 120
  120. },
  121. {
  122. id: 2,
  123. name: '幼儿园宝宝启蒙书',
  124. points: 145,
  125. image: '/static/商城_商品2.png',
  126. category: '母婴',
  127. exchangeCount: 85
  128. },
  129. {
  130. id: 3,
  131. name: '薄脆可口数字小饼干蘑菇饼干',
  132. points: 100,
  133. image: '/static/商城_商品1.png',
  134. category: '积分兑换',
  135. exchangeCount: 95
  136. },
  137. {
  138. id: 4,
  139. name: '幼儿园宝宝启蒙书',
  140. points: 145,
  141. image: '/static/商城_商品2.png',
  142. category: '母婴',
  143. exchangeCount: 67
  144. },
  145. {
  146. id: 1,
  147. name: '薄脆可口数字小饼干蘑菇饼干',
  148. points: 100,
  149. image: '/static/商城_商品1.png',
  150. category: '积分兑换',
  151. exchangeCount: 120
  152. },
  153. {
  154. id: 2,
  155. name: '幼儿园宝宝启蒙书',
  156. points: 145,
  157. image: '/static/商城_商品2.png',
  158. category: '母婴',
  159. exchangeCount: 85
  160. },
  161. {
  162. id: 3,
  163. name: '薄脆可口数字小饼干蘑菇饼干',
  164. points: 100,
  165. image: '/static/商城_商品1.png',
  166. category: '积分兑换',
  167. exchangeCount: 95
  168. },
  169. {
  170. id: 4,
  171. name: '幼儿园宝宝启蒙书',
  172. points: 145,
  173. image: '/static/商城_商品2.png',
  174. category: '母婴',
  175. exchangeCount: 67
  176. }
  177. ],
  178. buttonStyle: {
  179. width: '128rpx',
  180. height: '44rpx',
  181. borderRadius: '28rpx',
  182. fontSize: '22rpx'
  183. }
  184. }
  185. },
  186. computed: {
  187. filteredGoodsList() {
  188. let list = this.goodsList
  189. // 根据搜索关键词过滤
  190. if (this.searchValue) {
  191. list = list.filter(item =>
  192. item.name.toLowerCase().includes(this.searchValue.toLowerCase())
  193. )
  194. }
  195. // 根据tab过滤
  196. const currentTabName = this.tabList[this.currentTab].name
  197. if (currentTabName !== '全部') {
  198. if (currentTabName === '兑换量') {
  199. // 按兑换量排序
  200. list = [...list].sort((a, b) => b.exchangeCount - a.exchangeCount)
  201. } else {
  202. // 按分类过滤
  203. list = list.filter(item => item.category === currentTabName)
  204. }
  205. }
  206. return list
  207. }
  208. },
  209. methods: {
  210. onSearch(value) {
  211. console.log('搜索:', value)
  212. },
  213. onTabChange(index) {
  214. this.currentTab = index
  215. },
  216. onGoodsClick(item) {
  217. // 跳转到商品详情页
  218. uni.navigateTo({
  219. url: `/subPages/shop/goodsDetail?id=${item.id}`
  220. })
  221. },
  222. onExchange(item) {
  223. uni.showModal({
  224. title: '确认兑换',
  225. content: `确定要用${item.points}积分兑换${item.name}吗?`,
  226. success: (res) => {
  227. if (res.confirm) {
  228. // 执行兑换逻辑
  229. uni.showToast({
  230. title: '兑换成功',
  231. icon: 'success'
  232. })
  233. }
  234. }
  235. })
  236. }
  237. }
  238. }
  239. </script>
  240. <style lang="scss" scoped>
  241. .shop-content {
  242. background: #f8f8f8;
  243. min-height: calc(100vh - 400rpx);
  244. }
  245. .search-container {
  246. position: sticky;
  247. z-index: 999;
  248. top: 10rpx;
  249. padding: 15rpx 20rpx;
  250. background: #ffffff;
  251. }
  252. .tab-container {
  253. position: sticky;
  254. z-index: 999;
  255. top: 90rpx;
  256. background: #ffffff;
  257. padding: 0 30rpx;
  258. border-bottom: 1rpx solid #f0f0f0;
  259. }
  260. .goods-container {
  261. padding: 20rpx 30rpx;
  262. background: #f8f8f8;
  263. }
  264. .goods-grid {
  265. display: grid;
  266. grid-template-columns: 1fr 1fr;
  267. gap: 20rpx;
  268. }
  269. .goods-item {
  270. display: flex;
  271. flex-direction: column;
  272. background: #ffffff;
  273. border-radius: 12rpx;
  274. padding: 20rpx;
  275. box-shadow: 0 2rpx 12rpx rgba(0, 0, 0, 0.04);
  276. border: 1rpx solid #f5f5f5;
  277. .goods-image {
  278. width: 100%;
  279. height: 230rpx;
  280. border-radius: 8rpx;
  281. overflow: hidden;
  282. margin-bottom: 16rpx;
  283. border: 2rpx dashed #e0e0e0;
  284. .image {
  285. width: 100%;
  286. height: 100%;
  287. object-fit: cover;
  288. }
  289. }
  290. .goods-info {
  291. flex: 1;
  292. display: flex;
  293. flex-direction: column;
  294. .goods-name {
  295. font-size: 28rpx;
  296. color: #333333;
  297. line-height: 1.4;
  298. margin-bottom: 16rpx;
  299. font-weight: 500;
  300. display: -webkit-box;
  301. -webkit-box-orient: vertical;
  302. -webkit-line-clamp: 2;
  303. overflow: hidden;
  304. min-height: 72rpx;
  305. }
  306. .goods-bottom {
  307. display: flex;
  308. // flex-direction: column;
  309. gap: 22rpx;
  310. margin-top: auto;
  311. .points-info {
  312. display: flex;
  313. align-items: center;
  314. .points-icon {
  315. width: 24rpx;
  316. height: 24rpx;
  317. margin-right: 6rpx;
  318. }
  319. .points-text {
  320. font-size: 28rpx;
  321. color: #218CDD;
  322. font-weight: 700;
  323. }
  324. }
  325. }
  326. }
  327. }
  328. </style>