detail.vue 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237
  1. <template>
  2. <div class="bg-[#f5f5f5]">
  3. <div class="main-container" v-loading ="goodsTableData.loading">
  4. <div class="pt-[10px] flex justify-between mt-[25px]">
  5. <div class="w-[224px] flex flex-col">
  6. <info />
  7. <category @categoryClick="categoryClick" />
  8. </div>
  9. <div class="flex-1 ml-[18px] pb-[30px]">
  10. <div class="flex items-center text-[14px] bg-[#fff] px-[20px] py-[10px] rounded-[var(--rounded-mid)]">
  11. <span class="mr-[20px] text-[#969696]">排序:</span>
  12. <div class="flex-1 flex items-center text-[#424242] ">
  13. <span class="mr-[30px] cursor-pointer" :class="{'text-primary': goodsTableData.searchParam.order == ''}" @click="orderClick('')">综合</span>
  14. <div class="mr-[30px] cursor-pointer flex items-center" @click="orderClick('sale_num')">
  15. <span :class="{'text-primary': goodsTableData.searchParam.order == 'sale_num'}">销量</span>
  16. <div class="h-[20px] overflow-hidden ml-[6px] text-[#999]">
  17. <div class="!text-[14px] iconfont icon-shangV6xx-1" :class="{'text-primary': goodsTableData.searchParam.order == 'sale_num'&&goodsTableData.searchParam.sort != 'desc'}"></div>
  18. <div class="!text-[14px] iconfont icon-xiaV6xx mt-[-7px]" :class="{'text-primary': goodsTableData.searchParam.order == 'sale_num'&&goodsTableData.searchParam.sort == 'desc'}"></div>
  19. </div>
  20. </div>
  21. <div class="mr-[30px] cursor-pointer flex items-center" @click="orderClick('price')">
  22. <span :class="{'text-primary': goodsTableData.searchParam.order == 'price'}">价格</span>
  23. <div class="h-[20px] overflow-hidden ml-[6px] text-[#999]">
  24. <div class="!text-[14px] iconfont icon-shangV6xx-1" :class="{'text-primary': goodsTableData.searchParam.order == 'price'&&goodsTableData.searchParam.sort != 'desc'}"></div>
  25. <div class="!text-[14px] iconfont icon-xiaV6xx mt-[-7px]" :class="{'text-primary': goodsTableData.searchParam.order == 'price'&&goodsTableData.searchParam.sort == 'desc'}"></div>
  26. </div>
  27. </div>
  28. <div class="" style="margin-left: 15px">
  29. <el-input style="width: 84px" size="mini" v-model="start_price" onkeyup="this.value = this.value.replace(/[^\d.]/g,'');">
  30. <template #prefix>
  31. <span>¥</span>
  32. </template>
  33. </el-input>
  34. <span> ~ </span>
  35. <el-input style="width: 84px" size="mini" v-model="end_price" onkeyup="this.value = this.value.replace(/[^\d.]/g,'');">
  36. <template #prefix>
  37. <span>¥</span>
  38. </template>
  39. </el-input>
  40. <el-button type="primary" size="mini" style="margin-left: 15px" @click="inputUp">确定</el-button>
  41. </div>
  42. </div>
  43. </div>
  44. <div class="mt-[20px]" v-if="goodsTableData.data.length">
  45. <div class="flex flex-wrap items-center" >
  46. <div class="bg-[#fff] w-[224px] cursor-pointer rounded-[var(--rounded-big)] mb-[20px] overflow-hidden" :class="{'mr-[20px]':(index + 1) % 4}" v-for="(item,index) in goodsTableData.data" :key="index" @click="toDetail(item.goods_id)">
  47. <div class="w-[224px] h-[224px]">
  48. <el-image class="w-[224px] h-[224px]" :src="img(item.goods_cover_thumb_mid ? item.goods_cover_thumb_mid : '')" fit="cover">
  49. <template #error>
  50. <img src="@/assets/images/goods_default.png" class="w-[224px] h-[224px]">
  51. </template>
  52. </el-image>
  53. </div>
  54. <div class="p-[15px]">
  55. <div class="text-[22px] text-primary flex items-baseline mb-[8px]">
  56. <span class="price-font">¥{{parseFloat(goodsPrice(item)).toFixed(2)}}</span>
  57. <img v-if="priceType(item) == 'member_price'" class="h-[14px] ml-[3px] w-[24px]" src="@/assets/images/addon/VIP.png" />
  58. <img v-if="priceType(item) == 'discount_price'" class="h-[12px] ml-[3px] w-[36px]" src="@/assets/images/addon/discount.png" />
  59. </div>
  60. <div class="text-[#333] h-[40px] multi-hidden text-[14px] leading-[20px] mb-[12px]">{{ item.goods_name }}</div>
  61. <div class="text-[#999] text-[12px] leading-[16px]">
  62. <div>已售{{item.sale_num}}{{item.unit || '件' }}</div>
  63. </div>
  64. </div>
  65. </div>
  66. </div>
  67. <div class="mt-[20px] flex justify-center">
  68. <el-pagination v-if="route.query.coupon_id" background small hide-on-single-page v-model:current-page="goodsTableData.page" v-model:page-size="goodsTableData.limit"
  69. layout="prev, pager, next" :total="goodsTableData.total" @size-change="getGoodsCouponPagesFn()"
  70. @current-change="getGoodsCouponPagesFn" />
  71. <el-pagination v-else background small hide-on-single-page v-model:current-page="goodsTableData.page" v-model:page-size="goodsTableData.limit"
  72. layout="prev, pager, next" :total="goodsTableData.total" @size-change="loadGoodsList()"
  73. @current-change="loadGoodsList" />
  74. </div>
  75. </div>
  76. <div class="min-h-[320px] bg-[#fff]" v-else>
  77. <el-empty description="暂无数据" :image-size="200" :image="img('static/resource/images/system/empty.png')"/>
  78. </div>
  79. </div>
  80. </div>
  81. </div>
  82. </div>
  83. </template>
  84. <script lang="ts" setup>
  85. import { ref,reactive } from 'vue'
  86. import category from './components/category/index.vue'
  87. import info from './components/info/index.vue'
  88. import { getShopGoodsPages, getGoodsCouponPages} from '@/addon/mall/api/goods'
  89. import { useRouter, useRoute } from 'vue-router'
  90. import { getToken} from '@/utils/common'
  91. const router = useRouter()
  92. const route = useRoute()
  93. const goodsTableData = reactive({
  94. page: 1,
  95. limit: 16,
  96. total: 0,
  97. loading: true,
  98. data: [],
  99. searchParam: {
  100. keyword: '',
  101. goods_category: '',
  102. coupon_id: '',
  103. site_id:'',
  104. order:'',
  105. sort:'desc',
  106. start_price:'',
  107. end_price:''
  108. }
  109. })
  110. goodsTableData.searchParam = Object.assign(goodsTableData.searchParam,route.query)
  111. //获取店铺列表
  112. const loadGoodsList = (page = 1) => {
  113. goodsTableData.page = page
  114. goodsTableData.loading = true
  115. getShopGoodsPages({
  116. page: goodsTableData.page,
  117. limit: goodsTableData.limit,
  118. ...goodsTableData.searchParam
  119. }).then(res =>{
  120. goodsTableData.data = res.data.data,
  121. goodsTableData.total = res.data.total
  122. goodsTableData.loading = false
  123. })
  124. }
  125. // 获取优惠劵可用商品列表
  126. const getGoodsCouponPagesFn = (page = 1) =>{
  127. goodsTableData.page = page
  128. goodsTableData.loading = true
  129. getGoodsCouponPages({
  130. page: goodsTableData.page,
  131. limit: goodsTableData.limit,
  132. ...goodsTableData.searchParam
  133. }).then(res =>{
  134. goodsTableData.data = res.data.data,
  135. goodsTableData.total = res.data.total
  136. goodsTableData.loading = false
  137. })
  138. }
  139. if(route.query.coupon_id){
  140. getGoodsCouponPagesFn()
  141. }else{
  142. loadGoodsList()
  143. }
  144. const toDetail = (goods_id) => {
  145. router.push(`/goods/detail?id=${goods_id}`)
  146. }
  147. //input价格控制
  148. const start_price = ref()
  149. const end_price = ref()
  150. const inputUp=()=>{
  151. let input1 = start_price.value == "" ? "0" : start_price.value;
  152. let input2 = end_price.value == "" ? "0" : end_price.value;
  153. if (input1 === "0" && input2 === "0") return false;
  154. if (!isNaN(parseInt(input1)) && !isNaN(parseInt(input2))) {
  155. if (parseInt(input1) > parseInt(input2) && input2 != "0") {
  156. ElMessage({
  157. message: "你所选择的区间不对哦!",
  158. type: "warning",
  159. });
  160. start_price.value = "";
  161. end_price.value = "";
  162. return false;
  163. }
  164. goodsTableData.searchParam.start_price = start_price.value
  165. goodsTableData.searchParam.end_price = end_price.value
  166. if(route.query.coupon_id){
  167. getGoodsCouponPagesFn()
  168. }else{
  169. loadGoodsList()
  170. }
  171. } else {
  172. ElMessage({
  173. message: "请输入正确的内容",
  174. type: "warning",
  175. });
  176. }
  177. }
  178. const categoryClick = (id:any)=>{
  179. goodsTableData.searchParam.goods_category = id
  180. if(route.query.coupon_id){
  181. getGoodsCouponPagesFn()
  182. }else{
  183. loadGoodsList()
  184. }
  185. router.push({path:'/shop/detail',query:goodsTableData.searchParam})
  186. }
  187. const orderClick=(item:string)=>{
  188. if(item == '' && item == goodsTableData.searchParam.order){
  189. return false
  190. }else if(item == goodsTableData.searchParam.order){
  191. goodsTableData.searchParam.sort = goodsTableData.searchParam.sort=='desc'?'asc':'desc'
  192. }else{
  193. goodsTableData.searchParam.order = item
  194. goodsTableData.searchParam.sort = 'desc'
  195. }
  196. if(route.query.coupon_id){
  197. getGoodsCouponPagesFn()
  198. }else{
  199. loadGoodsList()
  200. }
  201. }
  202. // 价格类型
  203. let priceType = (data: any) =>{
  204. let type = "";
  205. if(data.is_discount && data.goodsSku.sale_price != data.goodsSku.price){
  206. type = 'discount_price'// 折扣
  207. }else if(data.member_discount && getToken() && data.goodsSku.member_price != data.goodsSku.price){
  208. type = 'member_price' // 会员价
  209. }else{
  210. type = ""
  211. }
  212. return type;
  213. }
  214. // 商品价格
  215. let goodsPrice = (data: any) =>{
  216. let price = "0.00";
  217. if(data.is_discount && data.goodsSku.sale_price != data.goodsSku.price){
  218. price = data.goodsSku.sale_price ? data.goodsSku.sale_price : data.goodsSku.price // 折扣价
  219. }else if(data.member_discount && getToken() && data.goodsSku.member_price != data.goodsSku.price){
  220. price = data.goodsSku.member_price?data.goodsSku.member_price:data.goodsSku.price // 会员价
  221. }else{
  222. price = data.goodsSku.price
  223. }
  224. return price;
  225. }
  226. </script>
  227. <style lang="scss" scoped>
  228. </style>