detail.vue 11 KB

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