index.vue 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406
  1. <template>
  2. <Theme>
  3. <view class="wrap">
  4. <Navbar autoBack fixed @leftClick="leftClick" @rightClick="rightClick">
  5. <template #left>
  6. <view class="nav_left">
  7. <uni-icons type="cart" color="var(--light)" size="24"></uni-icons>
  8. </view>
  9. </template>
  10. <template #center>
  11. <view class="nav_title">
  12. <trans _t="tabbar.商城" />
  13. </view>
  14. <view class="bg_logo">{{ verConfig.appNames }}</view>
  15. </template>
  16. <template #right>
  17. <view class="nav_right">
  18. <uni-icons type="star" color="var(--light)" size="24"></uni-icons>
  19. </view>
  20. </template>
  21. </Navbar>
  22. <view class="content">
  23. <view class="search">
  24. <Search
  25. v-model="searchValue"
  26. :placeholder="t('请输入关键字')"
  27. @confirm="searchConfirm"
  28. >
  29. <template #prefix>
  30. <i class="icon-font icon-search"></i>
  31. </template>
  32. <template #suffix>
  33. <!-- <popOver placement="bottom-end" :options="optionsList" isArrow ref="popoverRef">
  34. <i class="icon-font icon-camera"></i>
  35. </popOver> -->
  36. </template>
  37. </Search>
  38. </view>
  39. <view class="tops" id="tabs">
  40. <view class="tab">
  41. <Tab
  42. :active="actvieNum"
  43. keyName="text"
  44. :tabList="tabList"
  45. @confirm="tabClick"
  46. />
  47. </view>
  48. <view class="product_sort">
  49. <view
  50. class="sort_list"
  51. :class="sortActive == index ? 'sort_active' : ''"
  52. v-for="(item, index) in sortList"
  53. :key="index"
  54. @click="item.callback(item, index)"
  55. >
  56. <trans :_t="item.text" />
  57. <template v-if="item.isTrue == 1">
  58. <view class="sort_arrow">
  59. <view
  60. class="sort_arrow_top"
  61. :style="
  62. defaultParams.sort == 'moneyAsc'
  63. ? { borderBottom: '4px solid var(--black)' }
  64. : {}
  65. "
  66. ></view>
  67. <view
  68. class="sort_arrow_bottom"
  69. :style="
  70. defaultParams.sort == 'moneyDesc'
  71. ? { borderTop: '4px solid var(--black)' }
  72. : {}
  73. "
  74. ></view>
  75. </view>
  76. </template>
  77. </view>
  78. </view>
  79. </view>
  80. <view class="content">
  81. <List
  82. url="/shop/goods/list"
  83. :topHeight="tabHeight"
  84. isCache
  85. :defaultParams="defaultParams"
  86. ref="listRef"
  87. @datas="getList"
  88. >
  89. <template #item="{ item, index }">
  90. <shopList
  91. :channel="defaultParams.channel"
  92. :search="defaultParams.keyWord"
  93. :item="item"
  94. @collect="collectClick($event, index)"
  95. />
  96. </template>
  97. </List>
  98. </view>
  99. </view>
  100. </view>
  101. </Theme>
  102. </template>
  103. <script setup>
  104. import Navbar from "@/components/navbar";
  105. import verConfig from "@/ver.config";
  106. import Search from "@/components/input";
  107. import popOver from "@/components/popover";
  108. import Tab from "@/components/tabs";
  109. import List from "@/components/list";
  110. import { query, systemInfo } from "@/utils";
  111. import shopList from "../index/components/shop_list";
  112. import { onShow, onReachBottom } from "@dcloudio/uni-app";
  113. import { SHOP_USER_COLLECT } from "@/api";
  114. import { ref, nextTick, reactive, onMounted } from "vue";
  115. import { t } from "@/locale";
  116. import { useCacheStore, useTabbarStore } from "@/store";
  117. const useCache = useCacheStore();
  118. const useTabbar = useTabbarStore();
  119. const searchValue = ref("");
  120. const listRef = ref(null);
  121. const actvieNum = ref(1);
  122. const sortActive = ref(0);
  123. const tabHeight = ref(0);
  124. const dataList = ref([]);
  125. const tabList = ref([
  126. {
  127. img: "../../static/shop/icon_0.png",
  128. text: "1688",
  129. channel: 0,
  130. },
  131. {
  132. img: "../../static/shop/icon_1.png",
  133. text: "淘宝",
  134. channel: 1,
  135. },
  136. {
  137. img: "../../static/shop/icon_3.png",
  138. text: "JD",
  139. channel: 3,
  140. },
  141. ]);
  142. const defaultParams = reactive({
  143. channel: tabList.value[actvieNum.value].channel,
  144. keyWord: "",
  145. start_price: "",
  146. end_price: "",
  147. sort: "",
  148. img: "",
  149. });
  150. const sortList = reactive([
  151. {
  152. text: "综合",
  153. sort: "",
  154. callback: (item, index) => {
  155. sortActive.value = index;
  156. defaultParams.sort = "";
  157. nextTick(() => {
  158. listRef.value && listRef.value.handleRefresh();
  159. });
  160. },
  161. },
  162. {
  163. text: "价格",
  164. isTrue: 1,
  165. sort: "moneyDesc", // moneyAsc 升序
  166. callback: (item, index) => {
  167. priceClick(item, index);
  168. },
  169. },
  170. ]);
  171. const leftClick = () => {
  172. uni.switchTab({ url: "/pages/shop/cart" });
  173. useTabbar.getPageCur("shop");
  174. };
  175. const rightClick = () => {
  176. uni.navigateTo({ url: `/pages/dashboard/favorites` });
  177. };
  178. const getList = (list) => {
  179. dataList.value = list;
  180. };
  181. const searchConfirm = () => {
  182. defaultParams.keyWord = searchValue.value;
  183. nextTick(() => {
  184. listRef.value && listRef.value.handleRefresh();
  185. });
  186. };
  187. const priceClick = (item, index) => {
  188. if (sortActive.value == index) {
  189. if (defaultParams.sort == "moneyAsc") {
  190. defaultParams.sort = "";
  191. sortActive.value = 0;
  192. } else {
  193. defaultParams.sort = "moneyAsc";
  194. }
  195. } else {
  196. sortActive.value = index;
  197. defaultParams.sort = item.sort;
  198. }
  199. nextTick(() => {
  200. listRef.value && listRef.value.handleRefresh();
  201. });
  202. };
  203. const tabClick = (item, index) => {
  204. defaultParams.channel = item.channel;
  205. if (actvieNum.value == index) return;
  206. actvieNum.value = index;
  207. nextTick(() => {
  208. listRef.value && listRef.value.handleRefresh();
  209. });
  210. };
  211. const collectClick = (item, index) => {
  212. setCollect(
  213. {
  214. channel: tabList.value[actvieNum.value].channel,
  215. type: "good",
  216. goods_id: item.num_iid,
  217. seller_id: item.seller_id,
  218. title: item.title,
  219. pic_url: item.pic_url,
  220. price: item.price,
  221. },
  222. index
  223. );
  224. };
  225. const setCollect = async (params, index) => {
  226. try {
  227. const res = await SHOP_USER_COLLECT(params);
  228. nextTick(() => {
  229. dataList.value[index].isCollect = res.data.collect;
  230. listRef.value && listRef.value.setList(dataList.value);
  231. useCache.changeShopCollect({
  232. channel: params.channel,
  233. goods_id: params.goods_id,
  234. isCollect: res.data.collect,
  235. });
  236. });
  237. } catch (error) {
  238. Toast(error.msg);
  239. }
  240. };
  241. onMounted(() => {
  242. nextTick(async () => {
  243. const res = await query("#tabs", this);
  244. // tabTop.value = res.top + systemInfo().statusBarHeight;
  245. tabHeight.value = res.height;
  246. nextTick(() => {
  247. // listRef.value && listRef.value.getData();
  248. });
  249. });
  250. });
  251. onShow(() => {
  252. nextTick(async () => {
  253. listRef.value && listRef.value.handleRefresh();
  254. });
  255. });
  256. onReachBottom(() => {
  257. nextTick(() => {
  258. listRef.value && listRef.value.scrolltolower();
  259. });
  260. });
  261. uni.hideTabBar();
  262. </script>
  263. <style lang="less" scoped>
  264. @import url("@/style.less");
  265. .wrap {
  266. background: var(--bg);
  267. overflow: hidden;
  268. .flex();
  269. flex-direction: column;
  270. :deep(.u-navbar__content) {
  271. background-color: var(--black) !important;
  272. }
  273. .bg_logo {
  274. position: absolute;
  275. .size(128rpx);
  276. color: var(--inputBg);
  277. opacity: 0.06;
  278. top: 0;
  279. left: 50%;
  280. font-weight: bold;
  281. transform: translateX(-50%);
  282. line-height: 88rpx;
  283. text-transform: uppercase;
  284. font-family: "HarmonyOS_Sans";
  285. text-wrap: nowrap;
  286. }
  287. .nav_title {
  288. color: var(--light);
  289. }
  290. .nav_right {
  291. color: var(--primary);
  292. .size(24rpx);
  293. font-weight: 500;
  294. }
  295. .content {
  296. .search {
  297. padding: 20rpx 30rpx;
  298. background-color: var(--black);
  299. .icon-camera {
  300. color: #adb8cc;
  301. font-size: 60rpx;
  302. }
  303. :deep(.u-input) {
  304. padding: 0 32rpx !important;
  305. .u-input__content__field-wrapper__field {
  306. height: 47px;
  307. }
  308. }
  309. }
  310. .tops {
  311. // position: fixed;
  312. // top: 44px;
  313. // left: 0;
  314. // right: 0;
  315. // background-color: var(--bg);
  316. // z-index: 1;
  317. .tab {
  318. padding: 0 24rpx;
  319. }
  320. .product_sort {
  321. .flex();
  322. padding: 24rpx 32rpx;
  323. .sort_list {
  324. color: var(--text-01);
  325. .size(24rpx);
  326. line-height: 40rpx;
  327. margin-right: 72rpx;
  328. padding: 16rpx 0;
  329. .ver();
  330. .sort_arrow {
  331. margin-left: 20rpx;
  332. &_top {
  333. border-bottom: 4px solid #adb8cc;
  334. border-left: 4px solid transparent;
  335. border-right: 4px solid transparent;
  336. font-size: 0;
  337. height: 0;
  338. line-height: 0;
  339. margin-bottom: 1px;
  340. width: 0;
  341. }
  342. &_bottom {
  343. border-left: 4px solid transparent;
  344. border-right: 4px solid transparent;
  345. border-top: 4px solid #adb8cc;
  346. font-size: 0;
  347. height: 0;
  348. line-height: 0;
  349. margin-top: 1px;
  350. width: 0;
  351. }
  352. }
  353. }
  354. .sort_active {
  355. color: var(--black);
  356. }
  357. }
  358. }
  359. .content {
  360. padding: 16rpx 32rpx;
  361. /deep/ .wrap_list {
  362. .uni-scroll-view-content {
  363. > uni-view {
  364. .flex();
  365. flex-wrap: wrap;
  366. gap: 16rpx;
  367. .u-list-item {
  368. width: calc((100% - 16rpx) / 2);
  369. }
  370. }
  371. }
  372. }
  373. }
  374. }
  375. }
  376. </style>