Init project

This commit is contained in:
lifizer
2023-09-20 21:49:33 +08:00
parent 85a5989c96
commit c9ceac9f37
710 changed files with 125705 additions and 0 deletions
+115
View File
@@ -0,0 +1,115 @@
<template>
<view class="evaluate-list" ref="container">
<view class="header">
<view class="generalComment acea-row row-between-wrapper">
<view class="acea-row row-middle font-color-red">
<text class="evaluate">评分</text>
<view class="start" :class="'star' + replyData.replyStar"></view>
</view>
<view>
<text class="font-color-red">{{ replyData.replyChance || 0 }}%</text>
<text>好评率</text>
</view>
</view>
<view class="nav acea-row row-middle">
<view
class="acea-row row-center-wrapper"
v-for="(item, navListIndex) in navList"
:key="navListIndex"
@click="changeType(navListIndex)"
>
<view
class="item"
:class="currentActive === navListIndex ? 'bg-color-red' : ''"
v-if="item.num"
>
<text>{{ item.evaluate }}({{ item.num }})</text>
</view>
</view>
</view>
</view>
<UserEvaluation :reply="reply"></UserEvaluation>
<Loading :loaded="loadend" :loading="loading"></Loading>
</view>
</template>
<script>
import UserEvaluation from "@/components/UserEvaluation";
import { getReplyConfig, getReplyList } from "@/api/store";
import Loading from "@/components/Loading";
export default {
name: "EvaluateList",
components: {
UserEvaluation,
Loading
},
props: {},
data: function() {
return {
product_id: 0,
replyData: {},
navList: [
{ evaluate: "全部", num: 0 },
{ evaluate: "好评", num: 0 },
{ evaluate: "中评", num: 0 },
{ evaluate: "差评", num: 0 }
],
currentActive: 0,
page: 1,
limit: 8,
reply: [],
loadTitle: "",
loading: false,
loadend: false
};
},
mounted: function() {
this.product_id = this.$yroute.query.id;
this.getProductReplyCount();
this.getProductReplyList();
},
onReachBottom() {
!this.loading && this.getProductReplyList();
},
methods: {
getProductReplyCount: function() {
let that = this;
getReplyConfig(that.product_id).then(res => {
that.$set(that, "replyData", res.data);
that.navList[0].num = res.data.sumCount;
that.navList[1].num = res.data.goodCount;
that.navList[2].num = res.data.inCount;
that.navList[3].num = res.data.poorCount;
});
},
getProductReplyList: function() {
let that = this;
if (that.loading) return; //阻止下次请求(false可以进行请求);
if (that.loadend) return; //阻止结束当前请求(false可以进行请求);
that.loading = true;
let q = { page: that.page, limit: that.limit, type: that.currentActive };
getReplyList(that.product_id, q).then(res => {
that.loading = false;
//apply();js将一个数组插入另一个数组;
that.reply.push.apply(that.reply, res.data);
that.loadend = res.data.length < that.limit; //判断所有数据是否加载完成;
that.page = that.page + 1;
});
},
changeType: function(index) {
let that = this;
that.currentActive = index;
that.page = 1;
that.loadend = false;
that.$set(that, "reply", []);
that.getProductReplyList();
}
}
};
</script>
<style scoped lang="less">
.noCommodity {
height: 8*100rpx;
background-color: #fff;
}
</style>
+131
View File
@@ -0,0 +1,131 @@
<template>
<view class="good-search">
<view class="header">
<view class="search-box flex jc-between ai-center">
<input v-model="search" type="text" placeholder="搜索商品" placeholder-style="color:#999"/>
<view class="btn flex-0 flex jc-center ai-center" @click="submit">
<text class="iconfont icon-sousuo2"></text>
<text>搜索</text>
</view>
</view>
</view>
<view class="page-content" v-if="keywords.length">
<view class="title">热门搜索</view>
<view class="list acea-row">
<view
class="item"
v-for="keywordsKey of keywords"
:key="keywordsKey"
@click="toSearch(keywordsKey)"
>{{ keywordsKey }}
</view>
</view>
</view>
<view class="line"></view>
</view>
</template>
<script>
import {getSearchKeyword} from "@/api/store";
import {trim} from "@/utils";
export default {
name: "GoodSearch",
props: {},
data: function () {
return {
webUrl: this.$VUE_APP_RESOURCES_URL,
keywords: [],
search: ""
};
},
mounted: function () {
this.getData();
},
methods: {
submit() {
const search = trim(this.search) || "";
if (!search) return;
this.toSearch(search);
},
toSearch(s) {
this.$yrouter.push({path: "/pages/shop/GoodsList/index", query: {s}});
},
getData() {
getSearchKeyword().then(res => {
this.keywords = res.data;
});
}
}
};
</script>
<style lang="less">
page {
min-height: 100vh;
background: #fff !important;
}
.good-search {
.header {
padding: 40rpx 32rpx 32rpx;
background: #F9F9F9;
.search-box {
width: 686rpx;
height: 72rpx;
box-sizing: border-box;
padding: 0 8rpx 0 32rpx;
border-radius: 36rpx;
background: #fff;
font-size: 24rpx;
input{
width: 100%;
}
.btn {
width: 128rpx;
height: 54rpx;
background: #FD574B;
border-radius: 28rpx;
color: #fff;
font-weight: bold;
.icon-sousuo2 {
margin-right: 4rpx;
font-size: 28rpx;
}
}
}
}
.page-content {
padding: 0 32rpx;
.title {
margin: 22rpx 0 24rpx;
color: #333;
font-size: 28rpx;
line-height: 40rpx;
font-weight: bold;
letter-spacing: 4px;
}
.list {
.item {
height: 48rpx;
box-sizing: border-box;
margin-right: 24rpx;
padding: 0 24rpx;
border-radius: 28rpx;
background: #F1F0EE;
color: #666;
font-size: 24rpx;
line-height: 48rpx;
}
}
}
}
</style>
+578
View File
@@ -0,0 +1,578 @@
<template>
<view class="productSort">
<hx-navbar :back="false" :fixed="true" color="#080F1A" :left-slot="false" :right-slot="false">
<view class="acea-row row-center row-middle" style="width: 100%;">
<view class="main-title ">分类
<!-- <text class="pink-dot"></text> -->
</view>
</view>
</hx-navbar>
<view class="index">
<view class="header acea-row row-center-wrapper" :style="{top:headerTop}">
<view @click="goGoodSearch()" class="search acea-row row-middle">
<text class="iconfont icon-xiazai5"></text>
搜索商品
</view>
</view>
</view>
<view class="aside" :style="{top:contentTop}">
<view class="item acea-row row-center-wrapper" :class="categoryDivindex === navActive ? 'on' : ''"
v-for="(item, categoryDivindex) in category" :key="categoryDivindex" @click="asideTap(categoryDivindex)">
<text>{{ item.cateName }}</text>
</view>
</view>
<view class="conter">
<mescroll-body ref="mescrollRef" top="16rpx" bottom="0" class='cotent-scroll' :up="upOption" :down="downOption"
@up="upCallback" @down="downCallback" @init="mescrollInit" @emptyclick="emptyClick">
<view class="text acea-row row-center row-middle">
<view class="h-line"></view>
<view class="cate-name">
{{curCategoryName}}
</view>
<view class="h-line"></view>
</view>
<view class="acea-row">
<view @click="goodsDetail(item)" class="item acea-row cate-goods-item" v-for="(item, index) in goodsList"
:key="index" :style="{width:goodsColumnWidth}">
<view class="img-box">
<image :style="{width:goodsColumnWidth,height:goodsColumnWidth}" :src="item.image" />
<view v-if="item.vipPrice && item.vipPrice > 0" class="price-tag">
<!-- <image style="width: 100%;height: 100%;" :src="webUrl+'/20210806130336255505.png'" mode=""></image> -->
<image style="width: 94rpx;height: 42rpx;" :src="webUrl+'/20220525103739004011.png'" mode="scaleToFill"></image>
</view>
</view>
<view class="pro-info line2"><text>{{ item.storeName }}</text></view>
<!-- <view class="market-price">¥{{item.otPrice}}</view> -->
<view class="money acea-row row-middle row-between" style="width: 100%;">
<!-- <text>¥{{ item.price }}</text> -->
<text class="num" v-if="item.vipPrice && item.vipPrice > 0">¥{{item.vipPrice}}</text>
<text class="num" v-else>¥{{ item.price }}</text>
<!-- <view class="shoppingCart acea-row row-center row-middle">
</view> -->
</view>
</view>
</view>
</mescroll-body>
</view>
<view style="height:100rpx;"></view>
</view>
</template>
<script>
import {
getCategory,
fetchNormal
} from "@/api/store";
import MescrollMixins from "@/mixins/mescroll-mixins.js";
import MescrollBody from "@/components/mescroll-uni/mescroll-body.vue";
import NP from "number-precision";
import {
trim
} from "@/utils";
import {
mapGetters
} from 'vuex';
import hxNavbar from "@/components/hx-navbar/hx-navbar.vue"
var that;
export default {
name: "GoodsClass",
components: {
hxNavbar,
MescrollBody
},
props: {},
computed: mapGetters(["userInfo"]),
mixins: [
MescrollMixins({
getPageData(mescroll) {
// 此时mescroll会携带page的参数:
let pageNum = mescroll.num; // 页码, 默认从1开始
let pageSize = mescroll.size; // 页长, 默认每页10条
var params = {
page: pageNum,
// limit: pageSize,
// keyword: that.keyword,
sid: that.sid,
// news: 0,
// priceOrder: "",
// salesOrder: ""
}
var _this = this;
fetchNormal(params)
.then(res => {
//mescroll.endByPage(res.data.length, res.data.total_pages);
if (mescroll.num == 1) {
_this.goodsList = []; //如果是第一页需手动制空列表
//_this.adjustPage();
}
_this.goodsList = _this.goodsList.concat(res.data.map((goods) => {
goods.price = _this.$force2Decimal(goods.price);
// goods.vipPrice = _this.$force2Decimal(goods.vipPrice);
if (that.$store.getters.token && that.userInfo) {
var p = NP.times(goods.price, NP.divide(parseFloat(that.userInfo.discount), 100))
goods.vipPrice = that.$force2Decimal(p);
}
return goods;
})); //追加新数据
mescroll.endSuccess(res.data.length);
})
.catch(err => {
mescroll.endErr();
//uni.hideLoading();
uni.showToast({
title: err + '',
icon: 'none',
mask: false,
duration: 1500
});
})
}
})
],
data: function() {
return {
keyword: '',
sid: 0, //二给分类id
curCategoryName: '全部商品',
category: [],
navActive: 0,
tabName: "", // 跳转初始分类名
search: "",
lock: false,
upOption: {
noMoreSize: 10, //如果列表已无数据,可设置列表的总数量要大于半页才显示无更多数据;避免列表数据过少(比如只有一条数据),显示无更多数据会不好看; 默认5
auto: false,
empty: {
tip: '暂无商品' // 提示
// btnText:'点击刷新'
}
},
downOption: {
auto: true
},
goodsList: [],
headerTop: '128rpx',
goodsColumnWidth: '246rpx',
contentTop: '224rpx',
webUrl: this.$VUE_APP_RESOURCES_URL
};
},
watch: {
"$yroute.query.id": function(n) {
if (n) {
this.activeCateId(n);
}
}
},
onShow() {
let name=uni.getStorageSync("name");
if(name){
this.tabName = name;
uni.removeStorageSync("name");
}
this.loadCategoryData();
},
onLoad: function(option) {
that = this;
uni.getSystemInfo({
success: (e) => {
// this.compareVersion(e.SDKVersion, '2.5.0')
let statusBar = 0;
let customBar = 0;
// #ifdef MP
statusBar = e.statusBarHeight
customBar = e.statusBarHeight + 45
if (e.platform === 'android') {
//this.$store.commit('SET_SYSTEM_IOSANDROID', false)
customBar = e.statusBarHeight + 50
}
// #endif
// #ifdef MP-WEIXIN
statusBar = e.statusBarHeight
// @ts-ignore
//uni.getMenuButtonBoundingClientRect();
const custom = uni.getMenuButtonBoundingClientRect()
customBar = custom.bottom + custom.top - e.statusBarHeight
// #endif
// #ifdef MP-ALIPAY
statusBar = e.statusBarHeight
customBar = e.statusBarHeight + e.titleBarHeight
// #endif
// #ifdef APP-PLUS
console.log('app-plus', e)
statusBar = e.statusBarHeight
customBar = e.statusBarHeight + 45
// #endif
// #ifdef H5
statusBar = 0
customBar = e.statusBarHeight + 45
// #endif
// 这里你可以自己决定存放方式,建议放在store中,因为store是实时变化的
// this.$store.commit('SET_STATUS_BAR', statusBar)
// this.$store.commit('SET_CUSTOM_BAR', customBar)
// this.$store.commit('SET_SYSTEM_INFO', e)
//两列商品宽度
that.goodsColumnWidth = (e.screenWidth - uni.upx2px(180 + 3 * 30)) / 2 + 'px';
console.log('goodsColumnWidth:' + that.goodsColumnWidth);
//状态栏图片高度
that.headerTop = statusBar + 44 + 'px';
that.contentTop = statusBar + 44 + uni.upx2px(96) + 'px';
}
});
},
// mounted: function() {
// document.addEventListener("scroll", this.onScroll, false);
// },
methods: {
goodsDetail: function(item) {
this.$yrouter.push({
path: '/pages/shop/GoodsCon/index',
query: {
id: item.id
}
})
},
emptyClick: function() {
//触发加载请求
this.mescroll && this.mescroll.triggerDownScroll()
},
goGoodSearch() {
this.$yrouter.push("/pages/shop/GoodSearch/index");
},
goGoodsList(child) {
this.$yrouter.push({
path: "/pages/shop/GoodsList/index",
query: {
id: child.id,
title: child.cateName
}
});
},
activeCateId(n) {
let index = 0;
n = parseInt(n);
if (!n) return;
this.category.forEach((cate, i) => {
if (cate.id === n) index = i;
});
if (index !== this.navActive) {
this.asideTap(index);
}
},
loadCategoryData() {
var that = this;
getCategory(0,35).then(res => {
//that.category = res.data;
that.category = [];
res.data.forEach(function(fcat, idx) {
if (fcat.children) {
fcat.children.forEach(function(sub, sidex) {
that.category.push(sub);
});
}
});
that.category.unshift({
"id": 0,
"pid": 0,
"cateName": "全部商品"
});
that.$nextTick(() => {
if (that.$yroute.query.id) {
that.activeCateId(that.$yroute.query.id);
}
for (let i = 0; i < that.category.length; i++) {
if (that.tabName == that.category[i].cateName)that.asideTap(i);
}
});
});
},
submitForm: function() {
var val = trim(this.search);
if (val) {
this.$yrouter.push({
path: "/pages/shop/GoodsList/index",
query: {
s: val
}
});
setTimeout(() => (this.search = ""), 500);
}
},
asideTap(index) {
this.navActive = index;
this.curCategoryName = this.category[index].cateName;
this.sid = this.category[index].id;
//触发加载请求
this.mescroll.scrollTo(0, 0);
this.mescroll && this.mescroll.resetUpScroll(false);
}
},
beforeDestroy: function() {
// document.removeEventListener("scroll", this.onScroll, false);
}
};
</script>
<style scoped lang="less">
/*产品分类*/
.productSort {
height: 100%;
background: #fff;
}
.productSort .header {
width: 100%;
height: 0.96*100rpx;
background-color: #fff;
position: fixed;
left: 0;
right: 0;
top: 0;
z-index: 9;
// border-bottom: 1px solid #f5f5f5;
border-bottom: 2rpx solid #DADCE0;
}
.productSort .header .input {
width: 7*100rpx;
height: 0.6*100rpx;
background-color: #f5f5f5;
border-radius: 0.5*100rpx;
padding: 0 0.25*100rpx;
}
.productSort .header .input .iconfont {
font-size: 0.35*100rpx;
color: #555;
}
.productSort .header .input input {
font-size: 0.26*100rpx;
height: 100%;
width: 5.97*100rpx;
}
.productSort .header .input input::placeholder {
color: #999;
}
.productSort .aside {
position: fixed;
width: 176rpx;
left: 0;
top: 0.96*100rpx;
bottom: 0 !important;
box-sizing: border-box;
border-right: 2rpx solid #DADCE0;
background-color: #fff;
overflow-y: auto;
overflow-x: hidden;
overflow-scrolling: touch;
}
.productSort .aside::-webkit-scrollbar {
width: 0 !important
}
.productSort .aside .item {
width: 100%;
height: 104rpx;
text{
display: inline-block;
width: 100%;
height: 28rpx;
font-size: 26rpx;
color: #666;
text-align: center;
}
}
.productSort .aside .item.on {
text{
border-left: 6rpx solid #FF564A;
color: #FF564A;
font-weight: bold;
}
}
.productSort .conter {
margin-left: 176rpx;
// padding: 0 0.14*100rpx;
// margin-top: 0.96*100rpx;
margin-top: 106rpx;
}
.productSort .conter .listw {
padding-top: 0.2*100rpx;
}
.productSort .conter .listw .title {
height: 0.9*100rpx;
}
.productSort .conter .listw .title .line {
width: 1*100rpx;
height: 0.02*100rpx;
background-color: #999;
}
.productSort .conter .listw .title .name {
font-size: 0.28*100rpx;
color: #333;
margin: 0 0.3*100rpx;
font-weight: bold;
}
.productSort .conter .list {
flex-wrap: wrap;
-ms-flex-wrap: wrap;
}
.productSort .conter .list .item {
width: 1.77*100rpx;
margin-top: 0.26*100rpx;
}
.productSort .conter .list .item .picture {
width: 1.2*100rpx;
height: 1.2*100rpx;
border-radius: 50%;
}
.productSort .conter .list .item .picture image {
width: 100%;
height: 100%;
border-radius: 50%;
}
.productSort .conter .list .item .name {
font-size: 0.24*100rpx;
color: #333;
height: 0.56*100rpx;
line-height: 0.56*100rpx;
width: 1.2*100rpx;
text-align: center;
}
.index .header .search {
display: flex;
justify-content: center;
background-color: #f6f6f6;
color: #C2C5CC;
font-size: 24rpx;
}
.conter .text {
margin-top: 20rpx;
}
.pink-dot {
width: 24rpx;
height: 24rpx;
background: rgba(255, 86, 74, 0.4);
border-radius: 50%;
position: absolute;
z-index: 0;
bottom: 0;
right: -12rpx;
}
.main-title {
font-size: 36rpx;
line-height: 36rpx;
color: #080F1A;
position: relative;
}
.h-line {
width: 56rpx;
height: 0px;
border: 1px solid #999999;
}
.cate-name {
font-size: 30rpx;
color: #999999; //rgba(255,45,105,1);
margin-left: 5*2rpx;
margin-right: 5*2rpx;
}
.shoppingCart {
width: 28*2rpx;
height: 28*2rpx;
background: rgba(255, 45, 105, 1);
border-radius: 50%;
}
.cart-icon {
width: 18*2rpx;
height: 18*2rpx;
}
.img-box {
position: relative;
}
.price-tag {
position: absolute;
top: 0;
left: 0;
// width: 48*2rpx;
// height: 33*2rpx;
// left: -14rpx;
// top: -20rpx;
}
.pro-info {
font-size: 14*2rpx;
}
.market-price {
font-size: 12*2rpx;
color: #C2C5CC;
text-decoration: line-through;
}
.cate-goods-item {
margin-left: 34rpx;
margin-top: 32rpx;
}
.money {
font-size: 24rpx;
color: #FF564A;
font-weight: bold;
}
</style>
+102
View File
@@ -0,0 +1,102 @@
<template>
<view ref="container">
<view class="collectionGoods" v-if="collectProductList.length > 0">
<view
class="item acea-row row-between-wrapper"
v-for="(item, collectProductListIndex) in collectProductList"
:key="collectProductListIndex"
@click="goGoodsCon(item)"
>
<view class="pictrue">
<image :src="item.image" />
</view>
<view class="text acea-row row-column-between">
<view class="infor line1">{{ item.storeName }}</view>
<view class="acea-row row-between-wrapper">
<view class="money font-color-red">¥{{ item.price }}</view>
<view class="delete" @tap.stop="delCollection(collectProductListIndex)">删除</view>
</view>
</view>
</view>
</view>
<Loading :loaded="loadend" :loading="loading"></Loading>
<view
class="noCommodity"
style="background-color:#fff;"
v-if="collectProductList.length < 1 && page > 1"
>
<view class="noPictrue">
<image :src="webUrl+'/20210203154659687348.png'" class="image" />
</view>
<Recommend></Recommend>
</view>
</view>
</template>
<script>
import Recommend from "@/components/Recommend";
import { getCollectUser, getCollectDel } from "@/api/user";
import Loading from "@/components/Loading";
export default {
name: "GoodsCollection",
components: {
Recommend,
Loading
},
props: {},
data: function() {
return {
webUrl:this.$VUE_APP_RESOURCES_URL,
page: 1,
limit: 20,
collectProductList: [],
loadTitle: "",
loading: false,
loadend: false
};
},
mounted: function() {
this.get_user_collect_product();
},
onReachBottom() {
!this.loading && this.get_user_collect_product();
},
methods: {
goGoodsCon(item) {
this.$yrouter.push({
path: "/pages/shop/GoodsCon/index",
query: { id: item.pid }
});
},
get_user_collect_product: function() {
let that = this;
if (that.loading) return; //阻止下次请求(false可以进行请求);
if (that.loadend) return; //阻止结束当前请求(false可以进行请求);
that.loading = true;
getCollectUser(that.page, that.limit).then(res => {
that.loading = false;
//apply();js将一个数组插入另一个数组;
that.collectProductList.push.apply(that.collectProductList, res.data);
that.loadend = res.data.length < that.limit; //判断所有数据是否加载完成;
that.page = that.page + 1;
});
},
//删除收藏;
delCollection: function(index) {
let that = this,
id = that.collectProductList[index].pid,
category = that.collectProductList[index].category;
getCollectDel(id, category).then(function() {
uni.showToast({
title: "删除成功",
icon: "success",
duration: 2000,
complete: () => {
that.collectProductList.splice(index, 1);
that.$set(that, "collectProductList", that.collectProductList);
}
});
});
}
}
};
</script>
File diff suppressed because it is too large Load Diff
+198
View File
@@ -0,0 +1,198 @@
<template>
<view class="evaluate-con">
<view class="goodsStyle acea-row row-between" v-if="orderCon.productInfo">
<view class="pictrue">
<image :src="orderCon.productInfo.image" class="image"/>
</view>
<view class="text acea-row row-between">
<view class="name line2">{{ orderCon.productInfo.storeName }}</view>
<view class="money">
<view>¥{{ orderCon.productInfo.price }}</view>
<view class="num">x{{ orderCon.cartNum }}</view>
</view>
</view>
</view>
<view class="score">
<view
class="item acea-row row-middle"
v-for="(item, scoreListIndexw) in scoreList"
:key="scoreListIndexw"
>
<view>{{ item.name }}</view>
<view class="starsList">
<text
@click="stars(starsIndexn, scoreListIndexw)"
v-for="(itemn, starsIndexn) in item.stars"
:key="starsIndexn"
class="iconfont"
:class="item.index >= starsIndexn ? 'icon-shitixing font-color-red': 'icon-kongxinxing'"
></text>
</view>
<text class="evaluate">{{ item.index === -1 ? "" : item.index + 1 + "分" }}</text>
</view>
<view class="textarea">
<textarea placeholder="商品满足你的期待么?说说你的想法,分享给想买的他们吧~" v-model="expect"></textarea>
<view class="list acea-row row-middle">
<view
class="pictrue"
v-for="(item, uploadPicturesIndex) in uploadPictures"
:key="uploadPicturesIndex"
>
<image :src="item"/>
<text
class="iconfont icon-guanbi1 font-color-red"
@click="uploadPictures.splice(uploadPicturesIndex, 1)"
></text>
</view>
<view class="pictrue uploadBnt acea-row row-center-wrapper row-column" @tap="chooseImage">
<text class="iconfont icon-icon25201"></text>
<view>上传图片</view>
</view>
</view>
</view>
<view class="evaluateBnt bg-color-red" @click="submit">立即评价</view>
</view>
</view>
</template>
<style scoped lang="less">
.evaluate-con .score .textarea .list .pictrue.uploadBnt {
border: 1px solid #ddd;
}
</style>
<script>
import {postOrderComment, postOrderProduct} from "@/api/store";
import {chooseImage, trim} from "@/utils";
import {required} from "@/utils/validate";
import {validatorDefaultCatch} from "@/utils/dialog";
const NAME = "GoodsEvaluate";
export default {
name: NAME,
components: {
// VueCoreImageUpload
},
props: {},
data: function () {
return {
orderCon: {
cartProduct: {
productInfo: {}
}
},
scoreList: [
{
name: "商品质量",
stars: ["", "", "", "", ""],
index: -1
},
{
name: "服务态度",
stars: ["", "", "", "", ""],
index: -1
}
],
uploadPictures: [],
expect: "",
unique: ""
};
},
mounted: function () {
this.unique = this.$yroute.query.id;
this.getOrderProduct();
},
watch: {
$yroute(n) {
if (n.name === NAME && this.unique !== n.params.id) {
this.unique = n.params.id;
this.$set(this.scoreList[0], "index", -1);
this.$set(this.scoreList[1], "index", -1);
this.expect = "";
this.uploadPictures = [];
this.getOrderProduct();
}
}
},
methods: {
getOrderProduct: function () {
let that = this,
unique = that.unique;
postOrderProduct(unique).then(res => {
that.orderCon = res.data;
});
},
stars: function (indexn, indexw) {
this.scoreList[indexw].index = indexn;
},
chooseImage() {
chooseImage(img => {
this.uploadPictures.push(img);
});
},
async submit() {
const expect = trim(this.expect),
product_score =
this.scoreList[0].index + 1 === 0 ? "" : this.scoreList[0].index + 1,
service_score =
this.scoreList[1].index + 1 === 0 ? "" : this.scoreList[1].index + 1;
try {
await this.$validator({
product_score: [
required("请选择商品质量分数", {
type: "number"
})
],
service_score: [
required("请选择服务态度分数", {
type: "number"
})
]
}).validate({
product_score,
service_score
});
} catch (e) {
return validatorDefaultCatch(e);
}
postOrderComment({
productScore: product_score,
serviceScore: service_score,
unique: this.unique,
pics: this.uploadPictures.join(","),
comment: expect
})
.then(() => {
uni.showToast({
title: "评价成功",
icon: "success",
duration: 2000
});
// ? 回跳到上一页
this.$yrouter.back();
// ? 默认跳转到详情页
// this.$yrouter.push({
// path: "/pages/order/OrderDetails/index",
// query: {
// id: this.orderCon.orderId
// }
// });
// ? 可选重定向到详情页,这时左上角会有一个返回首页的图标
// this.$yrouter.reLaunch({
// path: "/pages/home/index",
// });
})
.catch(err => {
uni.showToast({
title:
err.msg || err.response.data.msg || err.response.data.message,
icon: "none",
duration: 2000
});
});
}
}
};
</script>
+384
View File
@@ -0,0 +1,384 @@
<template>
<view class="productList" ref="container">
<form @submit.prevent="submitForm">
<view class="search bg-color-red acea-row row-between-wrapper">
<view class="input acea-row row-between-wrapper">
<text class="iconfont icon-sousuo"></text>
<input placeholder="搜索商品信息" v-model="where.keyword" confirm-type="search" @confirm="submitForm"/>
</view>
<view
class="iconfont"
:class="Switch === true ? 'icon-pailie' : 'icon-tupianpailie'"
@click="switchTap"
></view>
</view>
</form>
<view class="nav acea-row row-middle">
<view
class="item"
:class="title ? 'font-color-red' : ''"
@click="set_where(0)"
>{{ title ? title : "默认" }}
</view>
<view class="item" @click="set_where(1)">
价格
<image src="@/static/images/horn.png" v-if="price === 0"/>
<image src="@/static/images/up.png" v-if="price === 1"/>
<image src="@/static/images/down.png" v-if="price === 2"/>
</view>
<view class="item" @click="set_where(2)">
销量
<image src="@/static/images/horn.png" v-if="stock === 0"/>
<image src="@/static/images/up.png" v-if="stock === 1"/>
<image src="@/static/images/down.png" v-if="stock === 2"/>
</view>
<!-- down -->
<view class="item" :class="nows ? 'font-color-red' : ''" @click="set_where(3)">新品</view>
</view>
<view
class="list acea-row row-between-wrapper"
:class="Switch === true ? '' : 'on'"
ref="container"
>
<view
@click="goGoodsCon(item)"
class="item"
:class="Switch === true ? '' : 'on'"
v-for="(item, productListIndex) in productList"
:key="productListIndex"
:title="item.storeName"
>
<view class="pictrue" :class="Switch === true ? '' : 'on'">
<image :src="item.image" :class="Switch === true ? '' : 'on'"/>
</view>
<view class="text" :class="Switch === true ? '' : 'on'">
<view class="name more-t">{{ item.storeName }}</view>
<view class="vip acea-row row-between-wrapper" :class="Switch === true ? '' : 'on'">
<view class="flex ai-end">
<view class="money" :class="Switch === true ? '' : 'on'">
¥
<text class="num" v-if="item.vipPrice && item.vipPrice>0">{{ force2Decimal(item.vipPrice) }}</text>
<text class="num" v-else>{{ force2Decimal(item.price) }}</text>
</view>
<view class="vip-money">¥{{ force2Decimal(item.otPrice) }}</view>
</view>
<view class="sale">已售{{ item.sales }}件</view>
</view>
</view>
</view>
</view>
<Loading :loaded="loadend" :loading="loading"></Loading>
<view
class="noCommodity"
style="background-color: #fff;"
v-if="productList.length === 0 && where.page > 1"
>
<view class="noPictrue">
<image :src="webUrl+'/20210203153900181449.png'" class="image"/>
</view>
</view>
<Recommend v-if="productList.length === 0 && where.page > 1"></Recommend>
</view>
</template>
<script>
import Recommend from "@/components/Recommend";
import {getProducts} from "@/api/store";
import Loading from "@/components/Loading";
import {mapGetters} from 'vuex';
import NP from "number-precision";
export default {
name: "GoodsList",
components: {
Recommend,
Loading
},
props: {},
computed: mapGetters(["userInfo"]),
data: function () {
// const { s = "", id = 0, title = "" } = this.$yroute.query;
const s = "",
id = 0,
title = "";
return {
webUrl: this.$VUE_APP_RESOURCES_URL,
hostProduct: [],
productList: [],
Switch: true,
where: {
page: 1,
limit: 8,
keyword: s,
sid: id, //二级分类id
news: 0,
priceOrder: "",
salesOrder: ""
},
title: title && id ? title : "",
loadTitle: "",
loading: false,
loadend: false,
price: 0,
stock: 0,
nows: false
};
},
watch: {
title() {
this.updateTitle();
},
$yroute(to) {
// if (to.name !== "GoodsList") return;
// const { s = "", id = 0, title = "" } = to.query;
// if (s !== this.where.keyword || id !== this.where.sid) {
// this.where.keyword = s;
// this.loadend = false;
// this.loading = false;
// this.where.page = 1;
// this.where.sid = id;
// this.title = title && id ? title : "";
// this.nows = false;
// this.$set(this, "productList", []);
// this.price = 0;
// this.stock = 0;
// this.get_product_list();
// }
}
},
onLoad: function (e) {
const {s = "", id = 0, title = ""} = this.$yroute.query;
if (s !== this.where.keyword || id !== this.where.sid) {
this.where.keyword = s;
this.loadend = false;
this.loading = false;
this.where.page = 1;
this.where.sid = id;
this.title = title && id ? title : "";
this.nows = false;
this.$set(this, "productList", []);
this.price = 0;
this.stock = 0;
// this.get_product_list();
}
this.updateTitle();
this.get_product_list();
},
mounted: function () {
// const { s = "", id = 0, title = "" } = this.$yroute.query;
// this.updateTitle();
// this.get_product_list();
},
onReachBottom() {
!this.loading && this.get_product_list();
},
onHide() {
// this.hostProduct = [];
// this.productList = [];
// this.Switch = true;
// this.where = {
// page: 1,
// limit: 8,
// keyword: s,
// sid: id, //二级分类id
// news: 0,
// priceOrder: "",
// salesOrder: ""
// };
// this.loadTitle = "";
// this.loading = false;
// this.loadend = false;
// this.price = 0;
// this.stock = 0;
// this.nows = fals;
},
methods: {
force2Decimal(price) {
return this.$force2Decimal(price);
},
goGoodsCon(item) {
this.$yrouter.push({
path: "/pages/shop/GoodsCon/index",
query: {id: item.id}
});
},
updateTitle() {
// document.title = this.title || this.$yroute.meta.title;
},
get_product_list() {
var that = this;
this.setWhere();
// if (to.name !== "GoodsList") return;
// const { s = "", id = 0, title = "" } = this.$yroute.query;
// if (s !== this.where.keyword || id !== this.where.sid) {
// this.where.keyword = s;
// this.loadend = false;
// this.loading = false;
// this.where.page = 1;
// this.where.sid = id;
// this.title = title && id ? title : "";
// this.nows = false;
// this.$set(this, "productList", []);
// this.price = 0;
// this.stock = 0;
// // this.get_product_list();
// }
let q = that.where;
getProducts(q).then(res => {
that.loading = false;
//that.productList.push.apply(that.productList, res.data);
that.productList.push.apply(that.productList, res.data.map((item) => {
//如果已经登录获取用户信息
if (that.$store.getters.token && that.userInfo) {
var p = NP.times(item.price, NP.divide(parseFloat(that.userInfo.discount), 100))
item.vipPrice = p;
}
return item;
}));
that.loadend = res.data.length < that.where.limit; //判断所有数据是否加载完成;
that.where.page = that.where.page + 1;
});
},
submitForm: function () {
this.$set(this, "productList", []);
this.where.page = 1;
this.loadend = false;
this.loading = false;
this.get_product_list();
},
//点击事件处理
set_where: function (index) {
let that = this;
switch (index) {
case 0:
// return that.$yrouter.push({path: "/pages/shop/GoodsClass/index"});
that.nows = false;
that.price = 0;
that.stock = 0;
break;
case 1:
if (that.price === 0) that.price = 1;
else if (that.price === 1) that.price = 2;
else if (that.price === 2) that.price = 0;
that.stock = 0;
break;
case 2:
if (that.stock === 0) that.stock = 1;
else if (that.stock === 1) that.stock = 2;
else if (that.stock === 2) that.stock = 0;
that.price = 0;
break;
case 3:
that.nows = !that.nows;
break;
default:
break;
}
that.$set(that, "productList", []);
that.where.page = 1;
that.loadend = false;
that.get_product_list();
},
//设置where条件
setWhere: function () {
let that = this;
if (that.price === 0) {
that.where.priceOrder = "";
} else if (that.price === 1) {
that.where.priceOrder = "asc";
} else if (that.price === 2) {
that.where.priceOrder = "desc";
}
if (that.stock === 0) {
that.where.salesOrder = "";
} else if (that.stock === 1) {
that.where.salesOrder = "asc";
} else if (that.stock === 2) {
that.where.salesOrder = "desc";
}
that.where.news = that.nows ? "1" : "0";
},
switchTap: function () {
let that = this;
that.Switch = !that.Switch;
}
}
};
</script>
<style scoped lang="less">
.noCommodity {
border-top: 3px solid #f5f5f5;
padding-bottom: 1px;
}
.list {
.item {
.pictrue {
image {
border-radius: 8rpx;
}
}
.name {
color: #333;
font-size: 26rpx;
font-weight: bold;
}
.money {
font-size: 28rpx;
font-weight: bold;
line-height: 36rpx;
color: #DA0000;
}
.vip-money {
font-size: 22rpx !important;
color: #999 !important;
}
.sale {
font-size: 22rpx;
color: #666;
}
}
}
.list.on {
padding: 0 32rpx;
background: none;
.item {
box-sizing: border-box;
margin-top: 24rpx;
padding: 24rpx 22rpx;
border-bottom: none;
.pictrue {
width: 136rpx !important;
height: 136rpx !important;
}
.text {
display: flex;
flex-direction: column;
justify-content: space-between;
.money {
margin-top: 0;
}
.vip-money {
margin-left: 8rpx;
}
}
}
}
</style>
+78
View File
@@ -0,0 +1,78 @@
<template>
<view class="quality-recommend">
<!-- <view class="slider-banner swiper">
<swiper indicatorDots="true" v-if="banner.length > 0">
<block v-for="(item, imgUrlsIndex) in imgUrls" :key="imgUrlsIndex">
<swiper-item>
<image :src="item.img" class="slide-image" />
</swiper-item>
</block>
</swiper>
</view> -->
<view class="title acea-row row-center-wrapper">
<view class="line"></view>
<view class="name">
<text class="iconfont icon-cuxiaoguanli"></text>促销单品
</view>
<view class="line"></view>
</view>
<Promotion-good :benefit="goodsList"></Promotion-good>
</view>
</template>
<script>
// import { swiper, swiperSlide } from "vue-awesome-swiper";
import PromotionGood from "@/components/PromotionGood";
import {
getGroomList
} from "@/api/store";
export default {
name: "GoodsPromotion",
components: {
// swiper,
// swiperSlide,
PromotionGood
},
props: {},
data: function() {
return {
imgUrls: [],
goodsList: [],
RecommendSwiper: {
pagination: {
el: ".swiper-pagination",
clickable: true
},
autoplay: {
disableOnInteraction: false,
delay: 2000
},
loop: true,
speed: 1000,
observer: true,
observeParents: true
}
};
},
mounted: function() {
this.getIndexGroomList();
},
methods: {
getIndexGroomList: function() {
let that = this;
getGroomList(4)
.then(res => {
that.imgUrls = res.data.banner;
that.goodsList = res.data.list;
})
.catch((err) => {
uni.showToast({
title: err.msg || err.response.data.msg|| err.response.data.message,
icon: 'none',
duration: 2000
});
});
}
}
};
</script>
+99
View File
@@ -0,0 +1,99 @@
<template>
<view class="quality-recommend">
<view class="title acea-row row-center-wrapper">
<view class="line"></view>
<view class="name">
<text class="iconfont" :class="icon"></text>
{{ name }}
</view>
<view class="line"></view>
</view>
<GoodList :good-list="goodsList" :is-sort="false"></GoodList>
</view>
</template>
<script>
import GoodList from "@/components/GoodList";
import {getGroomList} from "@/api/store";
import NP from "number-precision";
import {mapGetters} from 'vuex';
export default {
name: "HotNewGoods",
components: {
GoodList
},
props: {},
computed: mapGetters(["userInfo"]),
data: function () {
return {
imgUrls: [],
goodsList: [],
name: "",
icon: "",
RecommendSwiper: {
pagination: {
el: ".swiper-pagination",
clickable: true
},
autoplay: {
disableOnInteraction: false,
delay: 2000
},
loop: true,
speed: 1000,
observer: true,
observeParents: true
}
};
},
mounted: function () {
this.titleInfo();
this.getIndexGroomList();
},
methods: {
titleInfo: function () {
let type = this.$yroute.query.type;
if (type === "1") {
this.name = "精品推荐";
this.icon = "icon-jingpintuijian";
// document.title = "精品推荐";
} else if (type === "2") {
this.name = "热门榜单";
this.icon = "icon-remen";
// document.title = "热门榜单";
} else if (type === "3") {
this.name = "首发新品";
this.icon = "icon-xinpin";
// document.title = "首发新品";
}
},
getIndexGroomList: function () {
let that = this;
let type = this.$yroute.query.type;
getGroomList(type)
.then(res => {
that.imgUrls = res.data.banner;
//that.goodsList = res.data.list;
that.goodsList = res.data.list.map((goods) => {
// goods.vipPrice = _this.$force2Decimal(goods.vipPrice);
if (that.$store.getters.token && that.userInfo) {
var p = NP.times(goods.price, NP.divide(parseFloat(that.userInfo.discount), 100))
goods.vipPrice = p;
}
return goods;
})
that.goodsList=[{storeName:3}]
})
.catch((err) => {
// uni.showToast({
// title: err.msg || err.response.data.msg || err.response.data.message,
// icon: 'none',
// duration: 2000
// });
});
}
}
};
</script>
+721
View File
@@ -0,0 +1,721 @@
<template>
<view class="shoppingCart">
<!-- <hx-navbar
title="购物车"
:fixed="true"
:back="false"
:left-slot="false"
:right-slot="false"
color="#ffffff"
statusBarFontColor="#ffffff"
:bgImgHeight="bgImgHeight"
:background-color="[254,82,97]"
:background-img="webUrl+'/20200729160752671638.png'"/> -->
<hx-navbar
title="购物车"
:fixed="true"
:back="false"
:left-slot="true"
:right-slot="true"
color="#333333"
statusBarFontColor="#ffffff"
:background-color="[255,255,255]"
>
<block slot="left">
<view style="padding-left: 30rpx;" class="top-delete-btn acea-row row-middle" @click="delgoods">
<image class="delete-icon" :src="webUrl+'/20210806133058078099.png'" mode=""></image>
</view>
</block>
</hx-navbar>
<view v-if="false" class="nav acea-row row-between-wrapper" style="border-top: 1px solid #f5f5f5">
<view>
<text class="num" style="color: #666666;">共{{ count }}件商品</text>
</view>
<!-- <view
v-if="cartList.valid.length > 0"
class="administrate acea-row row-center-wrapper font-color-white"
@click="manage"
>{{ footerswitch ? '取消' : '管理' }}</view> -->
<view class="top-delete-btn acea-row row-middle" @click="delgoods">
<image class="delete-icon" :src="webUrl+'/20210806133058078099.png'" mode=""></image>
</view>
</view>
<view style="border-top: 1px solid #f5f5f5" v-if="$store.getters.token||userInfo.uid">
<!-- <view style="margin-top: 80rpx;" v-if="$store.getters.token||userInfo.uid"> -->
<!-- <view class="labelNav acea-row row-around row-middle">
<view class="item">
<text class="iconfont icon-xuanzhong"></text>100%正品保证
</view>
<view class="item">
<text class="iconfont icon-xuanzhong"></text>所有商品精挑细选
</view>
<view class="item">
<text class="iconfont icon-xuanzhong"></text>售后无忧
</view>
</view> -->
<view v-if="validList.length > 0 || cartList.invalid.length > 0">
<view class="list">
<view
class="item acea-row row-between-wrapper"
v-for="(item, cartListValidIndex) in validList"
:key="cartListValidIndex"
>
<view class="select-btn">
<view class="checkbox-wrapper">
<checkbox-group @change="switchSelect(cartListValidIndex)">
<label class="well-check">
<checkbox :checked="item.checked" color="#fff"
style="border-radius: 50%;transform:scale(0.7)"></checkbox>
</label>
</checkbox-group>
</view>
</view>
<view class="picTxt acea-row row-between">
<view class="pictrue" @click="goGoodsCon(item)">
<image :src="item.productInfo.attrInfo.image" v-if="item.productInfo.attrInfo.image"/>
<image :src="item.productInfo.image" v-else/>
</view>
<view class="text acea-row row-column-between">
<view class="line1">{{ item.productInfo.storeName }}</view>
<view class="acea-row row-middle row-left">
<!-- height: 38rpx; -->
<view
class="infor"
style="background-color: #FFF3F2;border-radius: 19rpx;padding: 4rpx 20rpx;"
v-if="item.productInfo.attrInfo"
>规格:{{ item.productInfo.attrInfo.sku }}
</view>
</view>
<view class="money" style="color: #FF564A !important;">¥{{ force2Decimal(item.truePrice) }}</view>
</view>
<view class="carnum acea-row row-middle row-between">
<view
class="reduce"
:class="validList[cartListValidIndex].cartNum <= 1 ? 'on' : ''"
@click.prevent="reduce(cartListValidIndex)"
></view>
<view class="num">{{ item.cartNum }}</view>
<view
class="plus"
v-if="validList[cartListValidIndex].attrInfo"
:class="validList[cartListValidIndex].cartNum >= validList[cartListValidIndex].attrInfo.stock ? 'on' : ''"
@click.prevent="plus(cartListValidIndex)"
></view>
<view
class="plus"
v-else
:class="validList[cartListValidIndex].cartNum >= validList[cartListValidIndex].stock ? 'on' : ''"
@click.prevent="plus(cartListValidIndex)"
></view>
</view>
</view>
</view>
</view>
<!-- 失效商品开始 -->
<view class="invalidGoods" v-if="cartList.invalid.length > 0">
<view class="goodsNav acea-row row-between-wrapper">
<view @click="goodsOpen">
<text
class="iconfont"
:class="goodsHidden === true ? 'icon-xiangyou' : 'icon-xiangxia'"
></text>
失效商品
</view>
<view class="del" @click="delInvalidGoods">
<text class="iconfont icon-shanchu1"></text>
清空
</view>
</view>
<view class="goodsList" :hidden="goodsHidden">
<view
v-for="(item, cartListinvalidIndex) in cartList.invalid"
:key="cartListinvalidIndex"
>
<view
@click="goGoodsCon(item)"
class="item acea-row row-between-wrapper"
v-if="item.productInfo"
>
<view class="invalid acea-row row-center-wrapper">失效</view>
<view class="pictrue">
<image :src="item.productInfo.attrInfo.image" v-if="item.productInfo.attrInfo"/>
<image :src="item.productInfo.image" v-else/>
</view>
<view class="text acea-row row-column-between">
<view class="line1">{{ item.productInfo.storeName }}</view>
<view
class="infor line1"
v-if="item.productInfo.attrInfo"
>属性:{{ item.productInfo.attrInfo.sku }}
</view>
<view class="acea-row row-between-wrapper">
<view class="end">该商品已下架</view>
</view>
</view>
</view>
</view>
</view>
</view>
<!-- 失效商品结束 -->
</view>
<!--购物车暂无商品-->
<view class="noCart" v-if="cartList.valid.length === 0 && cartList.invalid.length === 0">
<view class="pictrue">
<image :src="webUrl+'/20210203153734554332.png'"/>
</view>
<Recommend></Recommend>
</view>
<view style="height:210rpx"></view>
<view class="footer" v-if="cartList.valid.length > 0">
<view class="footer-content acea-row row-between-wrapper">
<view class="acea-row row-middle row-between" style="flex: 1;flex-wrap: nowrap;">
<view class="select-btn">
<view class="checkbox-wrapper">
<!-- <label class="well-check">
<input
type="checkbox"
name
value
:checked="isAllSelect && cartCount > 0"
@click="allChecked"
/>
<i class="icon"></i>
<text class="checkAll">全选 ({{ cartCount }})</text>
</label>-->
<checkbox-group @change="allChecked">
<label class="well-check">
<checkbox style="transform:scale(0.7)" value="allSelect" :checked="isAllSelect && cartCount > 0"
color="#fff"></checkbox>
<text class="checkAll" style="color: #666666;">全选 ({{ cartCount }})</text>
</label>
</checkbox-group>
</view>
</view>
<view class="acea-row row-middle" style="margin-left: 20rpx">
<text style="color: #000000;font-size: 28rpx;font-weight: bold;">合计:</text>
<text style="color: #FF564A;font-size: 24rpx;">¥</text>
<text class="" style="font-size: 32rpx;color: #FF564A;">{{ force2Decimal(countmoney) }}</text>
</view>
</view>
<!-- <view class="money acea-row row-middle" v-if="footerswitch === false"> -->
<view class="money acea-row row-center row-middle" style="background: #FF564A;
height: 100%;
width: 198rpx;
text-align: center;
margin-right: -30rpx;flex-shrink: 0;margin-left: 10rpx;">
<!-- <view class="vline"></view> -->
<view class="placeOrder" @click="placeOrder">结算</view>
</view>
<!-- <view class="button acea-row row-middle" style="position: relative;" v-else>
<view class="vline"></view>
<view class="bnt cart-color" @click="collectAll">收藏</view>
<view class="bnt" @click="delgoods">删除</view>
</view> -->
</view>
</view>
</view>
</view>
</template>
<script>
import Recommend from "@/components/Recommend";
import {mapGetters} from "vuex";
import {changeCartNum, getCartCount, getCartList, postCartDel} from "@/api/store";
import {postCollectAll} from "@/api/user";
import {add, mul} from "@/utils/bc";
import cookie from "@/utils/store/cookie";
const CHECKED_IDS = "cart_checked";
var that;
export default {
name: "ShoppingCart",
components: {
Recommend
},
props: {},
data: function () {
return {
webUrl: this.$VUE_APP_RESOURCES_URL,
cartList: {
invalid: [],
valid: []
},
bgImgHeight: '20px',
validList: [],
isAllSelect: false,
cartCount: 0,
countmoney: 0,
goodsHidden: true,
footerswitch: false,
count: 0,
checkedIds: [],
loaded: false
};
},
computed: mapGetters(["userInfo", "token"]),
// watch: {
// $yroute(n) {
// if (n.name === "ShoppingCart") {
// this.carnum();
// this.countMoney();
// this.getCartList();
// this.gainCount();
// this.goodsHidden = true;
// this.footerswitch = false;
// }
// },
// cartList(list) {
// this.validList = list.valid;
// }
// },
watch: {
userInfo(user) {
if (user.uid) {
this.carnum();
this.countMoney();
this.getCartList();
this.gainCount();
}
},
token(token) {
if (this.userInfo.uid) {
this.carnum();
this.countMoney();
this.getCartList();
this.gainCount();
}
},
cartList(list) {
this.validList = list.valid;
}
},
onShow: function () {
this.carnum();
this.countMoney();
this.getCartList();
this.gainCount();
},
onLoad: function () {
that = this;
uni.getSystemInfo({
success: (e) => {
// this.compareVersion(e.SDKVersion, '2.5.0')
let statusBar = 0;
let customBar = 0;
// #ifdef MP
statusBar = e.statusBarHeight
customBar = e.statusBarHeight + 45
if (e.platform === 'android') {
//this.$store.commit('SET_SYSTEM_IOSANDROID', false)
customBar = e.statusBarHeight + 50
}
// #endif
// #ifdef MP-WEIXIN
statusBar = e.statusBarHeight
// @ts-ignore
//uni.getMenuButtonBoundingClientRect();
const custom = uni.getMenuButtonBoundingClientRect()
customBar = custom.bottom + custom.top - e.statusBarHeight
// #endif
// #ifdef MP-ALIPAY
statusBar = e.statusBarHeight
customBar = e.statusBarHeight + e.titleBarHeight
// #endif
// #ifdef APP-PLUS
console.log('app-plus', e)
statusBar = e.statusBarHeight
customBar = e.statusBarHeight + 45
// #endif
// #ifdef H5
statusBar = 0
customBar = e.statusBarHeight + 45
// #endif
// 这里你可以自己决定存放方式,建议放在store中,因为store是实时变化的
// this.$store.commit('SET_STATUS_BAR', statusBar)
// this.$store.commit('SET_CUSTOM_BAR', customBar)
// this.$store.commit('SET_SYSTEM_INFO', e)
// //两列商品宽度
// that.hotGoodsColumnWidth = (e.screenWidth - uni.upx2px(90))/2+'px';
//状态栏图片高度
that.bgImgHeight = statusBar + 'px';
}
});
},
methods: {
force2Decimal(v) {
return this.$force2Decimal(v);
},
goGoodsCon(item) {
this.$yrouter.push({
path: "/pages/shop/GoodsCon/index",
query: {
id: item.productId
}
});
},
getCartList: function () {
let that = this;
getCartList().then(res => {
that.cartList = res.data;
let checkedIds = cookie.get(CHECKED_IDS) || [];
if (!Array.isArray(checkedIds)) checkedIds = [];
this.cartList.valid.forEach(cart => {
if (checkedIds.indexOf(cart.id) !== -1) cart.checked = true;
});
if (checkedIds.length) {
that.checkedIds = checkedIds;
that.isAllSelect = checkedIds.length === this.cartList.valid.length;
that.carnum();
that.countMoney();
}
this.loaded = true;
});
},
//删除商品;
delgoods: function () {
let that = this,
id = [],
valid = [],
list = that.cartList.valid;
list.forEach(function (val) {
if (val.checked === true) {
id.push(val.id);
}
});
if (id.length === 0) {
uni.showToast({
title: "请选择产品",
icon: "none",
duration: 2000
});
return;
}
uni.showModal({
title: '确认删除已选商品?',
content: '',
showCancel: true,
cancelText: '取消',
confirmText: '确认',
success: res => {
uni.showLoading();
postCartDel(id).then(function () {
list.forEach(function (val, i) {
if (val.checked === false || val.checked === undefined)
valid.push(list[i]);
});
that.$set(that.cartList, "valid", valid);
that.carnum();
that.countMoney();
that.gainCount();
that.getCartList();
}).finally(() => {
uni.hideLoading();
});
},
fail: () => {
},
complete: () => {
}
});
},
// //获取数量
gainCount: function () {
let that = this;
getCartCount().then(res => {
that.count = res.data.count;
});
},
//清除失效产品;
delInvalidGoods: function () {
let that = this,
id = [],
list = that.cartList.invalid;
list.forEach(function (val) {
id.push(val.id);
});
postCartDel(id).then(function () {
list.splice(0, list.length);
that.gainCount();
that.getCartList();
});
},
//批量收藏;
collectAll: function () {
let that = this,
data = {
id: [],
category: ""
},
list = that.cartList.valid;
list.forEach(function (val) {
if (val.checked === true) {
data.id.push(val.product_id);
data.category = val.type;
}
});
if (data.id.length === 0) {
uni.showToast({
title: "请选择产品",
icon: "none",
duration: 2000
});
return;
}
postCollectAll(data).then(function () {
uni.showToast({
title: "收藏成功!",
icon: "none",
duration: 2000
});
});
},
//立即下单;
placeOrder: function () {
let that = this,
list = that.cartList.valid,
id = [];
list.forEach(function (val) {
if (val.checked === true) {
id.push(val.id);
}
});
if (id.length === 0) {
uni.showToast({
title: "请选择产品",
icon: "none",
duration: 2000
});
return;
}
this.$yrouter.push({
path: "/pages/order/OrderSubmission/index",
query: {
id: id.join(",")
}
});
},
manage: function () {
let that = this;
that.footerswitch = !that.footerswitch;
},
goodsOpen: function () {
let that = this;
that.goodsHidden = !that.goodsHidden;
},
//加
plus: function (index) {
let that = this;
let list = that.cartList.valid[index];
list.cartNum++;
if (list.attrInfo) {
if (list.cartNum >= list.attrInfo.stock) {
that.$set(list, "cart_num", list.attrInfo.stock);
}
} else {
if (list.cartNum >= list.stock) {
that.$set(list, "cart_num", list.stock);
}
}
that.carnum();
that.countMoney();
that.syncCartNum(list);
},
//减
reduce: function (index) {
let that = this;
let list = that.cartList.valid[index];
if (list.cartNum <= 1) {
uni.showToast({
title: "不能再少了!",
icon: "none",
duration: 2000
});
return;
}
list.cartNum--;
if (list.cartNum < 1) {
that.$set(list, "cart_num", 1);
}
that.carnum();
that.countMoney();
that.syncCartNum(list);
},
syncCartNum(cart) {
if (!cart.sync) {
changeCartNum(cart.id, Math.max(cart.cartNum, 1) || 1)
.then(res => {
this.getCartList();
this.gainCount();
})
.catch(error => {
this.gainCount();
uni.showToast({
title: error.response.data.msg,
icon: "none",
duration: 2000
});
});
}
},
//单选
switchSelect: function (index) {
let that = this,
cart = that.cartList.valid[index],
i = this.checkedIds.indexOf(cart.id);
cart.checked = !cart.checked;
if (i !== -1) this.checkedIds.splice(i, 1);
if (cart.checked) {
this.checkedIds.push(cart.id);
}
let len = that.cartList.valid.length;
let selectnum = [];
for (let i = 0; i < len; i++) {
if (that.cartList.valid[i].checked === true) {
selectnum.push(true);
}
}
that.isAllSelect = selectnum.length === len;
that.$set(that, "cartList", that.cartList);
that.$set(that, "isAllSelect", that.isAllSelect);
cookie.set(CHECKED_IDS, that.checkedIds);
that.carnum();
that.gainCount();
that.countMoney();
},
//全选
allChecked: function (e) {
console.log(e);
let that = this;
let selectAllStatus = e.mp.detail.value[0] == "allSelect" ? true : false;
console.log(selectAllStatus);
// let selectAllStatus = that.isAllSelect;
let checkedIds = [];
// for (let i = 0; i < array.length; i++) {
// array[i].checked = selectAllStatus;
// checked.push()
// }
that.cartList.valid.forEach(cart => {
cart.checked = selectAllStatus;
if (selectAllStatus) {
checkedIds.push(cart.id);
}
});
let cartList = {
...that.cartList
};
that.cartList = [];
that.cartList = cartList;
console.log(this.cartList);
this.$set(this, "cartList", this.cartList);
this.$set(this, "isAllSelect", selectAllStatus);
this.checkedIds = checkedIds;
cookie.set(CHECKED_IDS, checkedIds);
that.carnum();
that.countMoney();
this.$forceUpdate();
},
//数量
carnum: function () {
let that = this;
var carnum = 0;
var array = that.cartList.valid;
for (let i = 0; i < array.length; i++) {
if (array[i].checked === true) {
carnum += parseInt(array[i].cartNum);
}
}
that.$set(that, "cartCount", carnum);
},
//总共价钱;
countMoney: function () {
let that = this;
let carmoney = 0;
let array = that.cartList.valid;
for (let i = 0; i < array.length; i++) {
if (array[i].checked === true) {
carmoney = add(carmoney, mul(array[i].cartNum, array[i].truePrice));
}
}
that.countmoney = carmoney;
}
}
};
</script>
<style scoped lang="less">
.plus {
background-image: url("~@/static/images/num_plus_icon.png");
background-repeat: no-repeat;
background-size: 100% 100%;
border: none !important;
width: 38rpx !important;
height: 38rpx !important;
}
.reduce {
background-image: url("~@/static/images/num_minus_icon.png");
background-repeat: no-repeat;
background-size: 100% 100%;
border: none !important;
width: 38rpx !important;
height: 38rpx !important;
}
.shoppingCart .list .item .picTxt .text .money {
color: #feb655 !important;
}
.vline {
width: 0px;
height: 36rpx;
border-left: 1px solid rgba(255, 255, 255, 0.6);
margin: 26rpx 30rpx 26rpx 0;
}
.top-delete-btn {
padding: 10rpx;
//background:rgba(255,187,225,0.4);
//border-radius:12rpx;
}
.delete-icon {
width: 36rpx;
height: 36rpx;
}
.shoppingCart .footer-content {
background: #fff !important;
border-radius: 0 !important;
margin: 0 !important;
}
.shoppingCart .footer {
height: auto !important;
}
</style>
+196
View File
@@ -0,0 +1,196 @@
<template>
<view>
<view class="storeBox" ref="container">
<view
class="storeBox-box"
v-for="(item, index) in storeList"
:key="index"
@click="checked(item)"
>
<view class="store-img">
<img :src="item.image" lazy-load="true"/>
</view>
<view class="store-cent-left">
<text class="store-name">{{ item.name }}</text>
<text class="store-address line1">{{ item.address }}</text>
</view>
<view class="row-right">
<view>
<a class="store-phone" :href="'tel:' + item.phone">
<text class="iconfont icon-dadianhua01"></text>
</a>
</view>
<view class="store-distance" @click="showMaoLocation(item)">
<text class="addressTxt" v-if="item.distance">距离{{ item.distance }}千米</text>
<text class="addressTxt" v-else>查看地图</text>
<text class="iconfont icon-youjian"></text>
</view>
</view>
</view>
<Loading :loaded="loaded" :loading="loading"></Loading>
</view>
</view>
</template>
<script>
import Loading from "@/components/Loading";
import {storeListApi} from "@/api/store";
import {mapGetters} from "vuex";
import cookie from "@/utils/store/cookie";
const LONGITUDE = "user_longitude";
const LATITUDE = "user_latitude";
const MAPKEY = "mapKey";
export default {
name: "storeList",
components: {Loading},
computed: mapGetters(["location", "goName"]),
data() {
return {
page: 1,
limit: 20,
loaded: false,
loading: false,
storeList: [],
mapShow: false,
system_store: {},
mapKey: cookie.get(MAPKEY),
locationShow: false
};
},
mounted() {
this.getList();
},
onReachBottom() {
!this.loading && this.getOrderList();
},
methods: {
showMaoLocation(data) {
this.$yrouter.push({
path: "/pages/map/index",
query: data
});
},
// 选中门店
checked(e) {
if (this.goName === "orders") {
this.$store.commit("get_store", e);
this.$yrouter.back();
}
},
// 获取门店列表数据
getList: function () {
if (this.loading || this.loaded) return;
this.loading = true;
let data = {
latitude: this.location.latitude, //纬度
longitude: this.location.longitude, //经度
page: this.page,
limit: this.limit
};
storeListApi(data)
.then(res => {
this.loading = false;
this.loaded = res.data.list.length < this.limit;
this.storeList.push.apply(this.storeList, res.data.list);
this.page = this.page + 1;
this.mapKey = res.data.mapKey;
})
.catch(err => {
this.$dialog.error(err.msg);
});
}
}
};
</script>
<style scoped lang="less">
.geoPage {
position: fixed;
width: 100%;
height: 100%;
top: 0;
z-index: 10000;
}
.storeBox {
background-color: #fff;
padding: 0 0.3 * 100rpx;
}
.storeBox-box {
width: 100%;
height: auto;
display: flex;
align-items: center;
padding: 0.23 * 100rpx 0;
justify-content: space-between;
border-bottom: 1px solid #eee;
}
.store-cent {
display: flex;
align-items: center;
width: 80%;
}
.store-cent-left {
width: 45%;
text {
display: block;
}
}
.store-img {
width: 1.2 * 100rpx;
height: 1.2 * 100rpx;
border-radius: 0.06 * 100rpx;
margin-right: 0.22 * 100rpx;
}
.store-img img {
width: 100%;
height: 100%;
}
.store-name {
color: #282828;
font-size: 0.3 * 100rpx;
margin-bottom: 0.22 * 100rpx;
font-weight: 800;
}
.store-address {
color: #666666;
font-size: 0.24 * 100rpx;
}
.store-phone {
width: 0.5 * 100rpx;
height: 0.5 * 100rpx;
color: #fff;
border-radius: 50%;
display: block;
text-align: center;
line-height: 0.5 * 100rpx;
background-color: #e83323;
margin-bottom: 0.22 * 100rpx;
}
.store-distance {
font-size: 0.22 * 100rpx;
color: #e83323;
}
.iconfont {
font-size: 0.2 * 100rpx;
}
.row-right {
display: flex;
flex-direction: column;
align-items: flex-end;
width: 33.5%;
}
</style>