feat(uniapp_v2): 二开功能迁移与小程序主包优化

- 从 uniapp 迁移 HJF 页面、API、组件及用户/订单相关改动
- queue、assets 使用独立分包以降低主包体积
- 修复首页单根节点与支付结果页 v-if 链
- 关闭 HjfDemoPanel 全局注册;uniNoticeBar 注释 $getAppWebview 避免 __webviewId__ 报错
- 配置域名与 manifest 应用名称;cache/store 防御性处理

Made-with: Cursor
This commit is contained in:
apple
2026-03-26 12:16:01 +08:00
parent c84aeda062
commit 8e17762510
742 changed files with 184117 additions and 0 deletions

View File

@@ -0,0 +1,474 @@
<template>
<view :style="colorStyle">
<view class="page-container">
<view class="header-top relative" id="headerTop" :style="[headerBg]">
<view class="w-full fixed-lt z-20">
<view :style="{'height': sysHeight * 2 + 'rpx'}"></view>
<view class="h-80 px-20 flex-between-center">
<text class="iconfont icon-ic_leftarrow fs-40 text--w111-fff" @tap="pageBack"></text>
</view>
</view>
<!-- <view class="rule-btn w-124 flex-center fs-24 text--w111-fff" :style="{ top: 100 + sysHeight + 'px' }" @tap="goRecord">申请记录</view> -->
</view>
<view class="bg-v-gradient pl-20 pr-20 pb-24" :style="{ minHeight: contentHeight + 'rpx' }">
<scroll-view scroll-y="true" class="rd-24rpx" :style="{'height': contentHeight - 100 + 'rpx'}">
<view class="bg--w111-fff rd-24rpx content-box">
<view class="fs-30 fw-500 lh-42rpx">请填写以下信息</view>
<view class="cell flex-between-center mt-64">
<view class="fs-28 lh-40rpx">
<text class="prefix">*</text>
采购商名称
</view>
<input type="text" v-model="form.channel_name" placeholder="请输入采购商名称" placeholder-class="text--w111-ccc" class="fs-28 text-right" />
</view>
<view class="cell flex-between-center mt-64">
<view class="fs-28 lh-40rpx">
<text class="prefix">*</text>
联系人
</view>
<input type="text" v-model="form.real_name" placeholder="请输入联系人" placeholder-class="text--w111-ccc" class="fs-28 text-right" />
</view>
<view class="cell flex-between-center mt-64">
<view class="fs-28 lh-40rpx">
<text class="prefix">*</text>
联系电话
</view>
<input type="number" v-model="form.phone" placeholder="请输入联系电话" placeholder-class="text--w111-ccc" class="fs-28 text-right" />
</view>
<view v-if="channelApplyPhoneVerify" class="cell flex-between-center mt-64">
<view class="fs-28 lh-40rpx">
<text class="prefix">*</text>
验证码
</view>
<view class="flex-y-center">
<input type="number" v-model="form.code" placeholder="请输入验证码" placeholder-class="text--w111-ccc" class="fs-28 text-right" />
<button class="code-btn w-168 h-56 flex-center fs-24 ml-20" :disabled="disabled" @tap="code">{{ text }}</button>
</view>
</view>
<view class="cell flex-between-center mt-64">
<view class="fs-28 lh-40rpx">
<text class="prefix">*</text>
省市区
</view>
<view class="flex-1 flex-between-center" @tap="changeRegion">
<view class="w-full fs-28 text-right text--w111-ccc pr-10" v-if="!addressInfo.length">请选择省市区</view>
<view class="w-full fs-28 text-right pr-10" v-else>{{ addressText }}</view>
<text class="iconfont icon-ic_rightarrow fs-24 text--w111-999"></text>
</view>
</view>
<view class="cell flex-between-center mt-64">
<view class="fs-28 lh-40rpx">
<text class="prefix">*</text>
详细地址
</view>
<input type="text" v-model="form.address" placeholder="请输入详细地址" placeholder-class="text--w111-ccc" class="fs-28 text-right" />
</view>
<view class="cell flex-between-center mt-64">
<view class="fs-28 lh-40rpx pl-20">申请备注</view>
<input type="text" v-model="form.remark" placeholder="请输入申请备注" placeholder-class="text--w111-ccc" class="fs-28 text-right" />
</view>
<view class="fs-28 lh-40rpx mt-64 flex-y-center">
<text class="prefix">*</text>
资质图片
</view>
<view class="fs-24 lh-34rpx text--w111-ccc mt-12">(图片最多可上传8张图片格式支持JPGPNGJPEG</view>
<view class="grid-column-4 grid-gap-24rpx mt-24">
<view class="relative h-148" v-for="(item, index) in form.certificate" :key="index">
<image :src="item" mode="aspectFill" class="w-148 h-148 rd-16rpx"></image>
<view class="abs-rt w-32 h-32 del-pic flex-center fs-24" @click="DelPic(index)">
<text class="iconfont icon-ic_close text--w111-fff"></text>
</view>
</view>
<view class="h-148 flex-col flex-center upload bg--w111-f5f5f5 text--w111-999 rd-16rpx" @click="uploadpic" v-if="form.certificate.length < 8">
<text class="iconfont icon-ic_camera fs-42"></text>
<text class="fs-24 lh-34rpx pt-8">上传图片</text>
</view>
</view>
<view class="cell mt-64">
<view class="fs-28 lh-40rpx">申请说明</view>
<view class="text--w111-ccc mt-12">
{{ channel_apply_explain }}
</view>
</view>
<view class="flex-y-center mt-32">
<text class="iconfont fs-30" :class="isSelect ? 'icon-a-ic_CompleteSelect' : 'icon-ic_unselect'" @tap="proviceSelect"></text>
<text class="fs-24 text--w111-999 pl-12">已阅读并同意</text>
<text class="font-red" @tap="getAgreement">采购商认证协议</text>
</view>
<button class="w-full h-88 rd-44rpx flex-center text--w111-fff fs-28 mt-48" :disabled="disabled" :class="isSelectStar ? 'bg-red' : 'bg-disabled'" @tap="submitSupply">
提交申请
</button>
</view>
</scroll-view>
</view>
</view>
<Verify @success="success" :captchaType="captchaType" :imgSize="{ width: '330px', height: '155px' }" ref="verify"></Verify>
<tui-modal :show="showModal" maskClosable custom @cancel="hideModal">
<view class="tui-modal-custom">
<view class="fs-32 fw-500 lh-44rpx text-center">采购商认证协议</view>
<view class="fs-28 text--w111-666 lh-44rpx mt-24 desc-box">
<!-- #ifdef MP-WEIXIN -->
<rich-text :nodes="description"></rich-text>
<!-- #endif -->
<!-- #ifdef H5 || APP-PLUS -->
<view v-html="description"></view>
<!-- #endif -->
</view>
<view class="w-full h-72 rd-36rpx flex-center bg-red fs-26 text--w111-fff mt-32" @tap="hideModal">知道了</view>
</view>
</tui-modal>
<areaWindow ref="areaWindow" :display="display" :address="addressInfo" @submit="OnChangeAddress" @changeClose="changeClose"></areaWindow>
</view>
</template>
<script>
let sysHeight = uni.getWindowInfo().statusBarHeight;
import { toLogin } from '@/libs/login.js';
import { mapGetters } from 'vuex';
import { channelApplyApi, getCodeApi, registerVerify, channelApplyInfoApi, getUserAgreement, getAddressDetail } from '@/api/user.js';
import colors from '@/mixins/color';
import sendVerifyCode from '@/mixins/SendVerifyCode';
import { HTTP_REQUEST_URL, CAPTCHA_TYPE } from '@/config/app';
import Verify from '../components/verify/verify.vue';
import tuiModal from '@/components/tui-modal/index.vue';
import areaWindow from '@/components/areaWindow';
export default {
data() {
return {
captchaType: CAPTCHA_TYPE,
sysHeight: sysHeight,
form: {
channel_name: '', //采购商名称
real_name: '', //联系人
phone: '', //联系电话
province: '', //省市区
province_ids: [], //省市区ID
address: '', //详细地址
remark: '', //备注
code: '', //验证码
certificate: [] //资质图片
},
addressInfo: [],
canvasWidth: '',
canvasHeight: '',
canvasStatus: false,
isSelect: false,
keyCode: '',
id: 0,
showModal: false,
channelAgreement: '',
tagStyle: {
img: 'width:100%;display:block;'
},
display: false,
disabled: false,
back: '',
channel_apply_explain:'',
contentHeight: 0
};
},
components: {
Verify,
tuiModal,
areaWindow
},
mixins: [sendVerifyCode, colors],
watch: {
isLogin: {
handler: function (newV, oldV) {
if (newV) {
// #ifndef MP
this.getOrderProduct();
// #endif
}
},
deep: true
}
},
computed: {
...mapGetters(['isLogin', 'channelApplyPhoneVerify']),
addressText() {
return this.addressInfo.map((v) => v.label).join('/');
},
isSelectStar() {
if (this.form.channel_name && this.form.real_name && this.form.phone && this.form.province && this.form.address && this.form.certificate.length) {
if (this.channelApplyPhoneVerify && !this.form.code) {
return false;
}
return true;
}
},
headerBg() {
return {
backgroundImage: 'url(' + HTTP_REQUEST_URL + '/statics/images/activity/merchant_apply.png' + ')'
};
},
description() {
let description = this.channelAgreement;
if (description) {
description = description.replace(/<img/gi, '<img style="max-width:100%;height:auto;float:left;display:block" ');
description = description.replace(/<video/gi, '<video style="width:100%;height:auto;display:block" ');
}
return description;
}
},
onLoad(options) {
this.back = options.back || '';
this.getHeight();
this.getInfo();
},
methods: {
getHeight(){
let {windowHeight, statusBarHeight } = uni.getWindowInfo();
let that = this;
const query = uni.createSelectorQuery().in(this);
query.select("#headerTop")
.boundingClientRect((data) => {
that.contentHeight = (windowHeight - statusBarHeight - data.height) * 2;
})
.exec();
},
/*** 删除图片* */
DelPic: function (index) {
let that = this,
pic = this.form.certificate[index];
that.form.certificate.splice(index, 1);
that.$set(that.form, 'certificate', that.form.certificate);
},
/*** 上传文件 **/
uploadpic: function () {
let that = this;
this.canvasStatus = true;
that.$util.uploadImageChange(
{ count: 8, url: 'upload/image' },
function (res) {
if (that.form.certificate.length < 8) that.form.certificate.push(res.data.url);
},
(res) => {
this.canvasStatus = false;
},
(res) => {
this.canvasWidth = res.w;
this.canvasHeight = res.h;
}
);
},
code() {
if (!this.form.phone)
return this.$util.Tips({
title: '请填写手机号码'
});
if (!/^1(3|4|5|7|8|9|6)\d{9}$/i.test(this.form.phone))
return this.$util.Tips({
title: '请输入正确的手机号码'
});
this.$refs.verify.show();
},
success(data) {
this.$refs.verify.hide();
if (this.channelApplyPhoneVerify) {
getCodeApi()
.then((res) => {
this.keyCode = res.data.key;
this.getCode(data);
})
.catch((res) => {
this.$util.Tips({
title: res
});
});
} else {
this.channelRequest();
}
},
async getCode(data) {
let that = this;
if (!this.form.phone)
return that.$util.Tips({
title: '请填写手机号码'
});
if (!/^1(3|4|5|7|8|9|6)\d{9}$/i.test(this.form.phone))
return this.$util.Tips({
title: '请输入正确的手机号码'
});
await registerVerify({
phone: that.form.phone,
type: 'channel',
key: that.keyCode,
captchaType: CAPTCHA_TYPE,
captchaVerification: data.captchaVerification
})
.then((res) => {
that.$util.Tips({
title: res.msg
});
that.sendCode();
})
.catch((res) => {
that.$util.Tips({
title: res
});
});
},
proviceSelect() {
this.isSelect = !this.isSelect;
},
getInfo() {
channelApplyInfoApi()
.then((res) => {
this.channel_apply_explain = this.$store.state.app.channel_apply_explain;
//从状态页返回
if (this.back && res.data.id) {
let keys = Object.keys(this.form);
keys.map((i) => {
this.form[i] = res.data[i];
});
this.addressInfo = res.data.province.map((item) => ({ label: item }));
//从个人中心点进来并且填写过,需要先进入状态页
} else if (!this.back && res.data.id) {
uni.navigateTo({
url: '/pages/merchant/apply/state'
});
}
})
.catch((err) => {
return this.$util.Tips({
title: err
});
});
},
submitSupply() {
if (!this.isSelectStar)
return this.$util.Tips({
title: '请完整填写表单信息'
});
if (!this.isSelect)
return this.$util.Tips({
title: '请阅读并同意协议'
});
if (this.channelApplyPhoneVerify) {
this.channelRequest();
} else {
this.code();
}
},
channelRequest() {
channelApplyApi(this.form)
.then((res) => {
uni.navigateTo({
url: '/pages/merchant/apply/state'
});
})
.catch((err) => {
return this.$util.Tips({
title: err
});
});
},
pageBack() {
uni.reLaunch({
url: '/pages/user/index'
});
},
goRecord() {
uni.navigateTo({
url: '/pages/users/agent/record'
});
},
getAgreement() {
getUserAgreement('channel')
.then((res) => {
this.channelAgreement = res.data.content;
this.showModal = true;
})
.catch((err) => {
that.$util.Tips({
title: err.msg
});
});
},
hideModal() {
this.showModal = false;
},
changeRegion() {
this.display = true;
},
changeClose() {
this.display = false;
},
OnChangeAddress(address) {
this.latitude = '';
this.longitude = '';
this.addressInfo = address;
console.log(address);
this.form.province = address.map((v) => v.label).join(',');
this.form.province_ids = address.map((v) => v.id);
}
}
};
</script>
<style>
.page-container{
height: 100vh;
background: #eb3b26;
}
.header-top {
width: 100%;
height: 358rpx;
background-size: cover;
}
.rule-btn {
height: 48rpx;
background: rgba(0, 0, 0, 0.15);
border-radius: 24rpx 0 0 24rpx;
position: absolute;
right: 0;
}
.prefix {
color: #e93323;
font-size: 20rpx;
padding-right: 12rpx;
}
.bg-v-gradient {
background: linear-gradient(180deg, #fe7015 0%, #eb3b26 100%);
}
.content-box {
padding: 48rpx 32rpx 40rpx;
}
.code-btn {
border: 1px solid #e93323;
color: #e93323;
border-radius: 28rpx;
}
.upload {
border: 1rpx dashed #ccc;
}
.del-pic {
background-color: #999;
border-radius: 0 16rpx 0 16rpx;
}
.icon-a-ic_CompleteSelect,
.font-red {
color: #e93323;
}
.icon-ic_unselect {
color: #ccc;
}
.bg-red {
background-color: #e93323;
}
.bg-disabled {
background-color: rgba(233, 51, 35, 0.5);
}
.desc-box {
max-height: 700rpx;
overflow-y: auto;
}
.modal-bottom {
height: 136rpx;
border-radius: 0 0 32rpx 32rpx;
background-color: #fff;
}
</style>

View File

@@ -0,0 +1,172 @@
<template>
<view>
<view class="px-20 mt-40">
<view class="bg--w111-fff rd-24rpx card-bg">
<view class="h-244 pt-72">
<view class="px-122 flex-between-center">
<text class="iconfont icon-a-ic_CompleteSelect font-red fs-28"></text>
<view class="line bg-red mx-8"></view>
<text class="iconfont icon-a-ic_CompleteSelect font-red fs-28"></text>
<view class="line mx-8" :class="type > 0 ? 'bg-red' : 'bg-gray'"></view>
<text class="iconfont fs-28" :class="type > 0 ? 'icon-a-ic_CompleteSelect font-red' : 'icon-ic_unselect text--w111-ccc'"></text>
</view>
<view class="flex-between-center px-74 fs-28 lh-40rpx mt-24">
<text>提交成功</text>
<text>正在审核</text>
<text>{{ type == 2 ? '审核拒绝' : '审核通过' }}</text>
</view>
<view class="flex-between-center px-40 mt-8 fs-22 text--w111-999">
<!-- <text>{{ add_time }}</text>
<text>{{ add_time }}</text>
<text v-if="status_time">{{ status_time }}</text>
<text v-else class="w-180"></text> -->
</view>
</view>
<view class="flex-col flex-center content-box" v-if="!loading">
<image :src="imgHost + '/statics/images/supplier/verify_fail_icon.png'" class="status-pic" v-if="type == 2"></image>
<image :src="imgHost + '/statics/images/supplier/verify_ing_icon.png'" class="status-pic" v-else-if="type == 0"></image>
<image :src="imgHost + '/statics/images/supplier/verify_ok_icon.png'" class="status-pic" v-else-if="type == 1"></image>
<text class="fs-36 lh-50rpx pt-32">{{ type | typeFilter }}</text>
<text class="fs-26 lh-36rpx text--w111-999 pt-12">{{ type | descFilter }}</text>
<text class="fs-26 lh-36rpx text--w111-999 pt-12 pl-24 pr-24" v-if="refusal_reason && type == 2">拒绝原因{{ refusal_reason }}</text>
<view class="primary-btn flex-center fs-28 mt-40" @tap="edit">{{ type == 2 ? '重新填写' : '点击返回' }}</view>
<view class="border-btn flex-center fs-28 mt-24" v-if="type == 2" @tap="pageBack">点击返回</view>
</view>
</view>
</view>
</view>
</template>
<script>
import { HTTP_REQUEST_URL } from '@/config/app';
import colors from '@/mixins/color.js';
import { channelApplyInfoApi } from '@/api/user.js';
export default {
mixins: [colors],
data() {
return {
imgHost: HTTP_REQUEST_URL,
id: 0,
type: 2,
url: '',
account: '',
pwd: '',
status_time: '',
add_time: '',
refusal_reason: '',
ftype: '',
loading: true
};
},
filters: {
typeFilter(val) {
let obj = {
0: '正在审核',
1: '审核通过',
2: '审核失败'
};
return obj[val];
},
descFilter(val) {
let obj = {
0: '正在审核当中,请耐心等待',
1: '恭喜您,审核通过',
2: '请按提示修改您所填写的信息'
};
return obj[val];
}
},
onLoad(options) {
this.getInfo();
},
methods: {
getInfo() {
channelApplyInfoApi().then((res) => {
this.type = res.data.verify_status;
this.refusal_reason = res.data.reject;
this.add_time = res.data.add_time;
this.loading = false;
})
.catch((err) => {
return this.$util.Tips({
title: err
});
});
},
pageBack() {
uni.switchTab({
url: '/pages/user/index'
})
},
edit() {
if (this.type == 0 || this.type == 1) {
uni.switchTab({
url: '/pages/user/index'
})
} else {
uni.reLaunch({
url: '/pages/merchant/apply/index?back=true'
});
}
}
}
};
</script>
<style scoped>
.card-bg {
-webkit-mask: radial-gradient(circle at 16rpx 240rpx, transparent 16rpx, red 0) -16rpx;
}
.font-red {
color: #e93323;
}
.h-244 {
height: 244rpx;
border-bottom: 1px dashed #ccc;
}
.px-74 {
padding: 0 74rpx;
}
.px-122 {
padding: 0 122rpx;
}
.pt-72 {
padding-top: 72rpx;
}
.line {
width: 186rpx;
height: 1rpx;
}
.bg-red {
background-color: #e93323;
}
.bg-gray {
background-color: #dddddd;
}
.status-pic {
width: 172rpx;
height: 154rpx;
}
.content-box {
padding: 48rpx 0 72rpx;
}
.primary-btn {
width: 502rpx;
height: 88rpx;
background: linear-gradient(90deg, #ff7931 0%, #e93323 100%);
color: #fff;
border-radius: 50rpx;
}
.border-btn {
width: 502rpx;
height: 88rpx;
background: #fff;
border: 1px solid #e93323;
color: #e93323;
border-radius: 50rpx;
}
.copy-btn {
width: 64rpx;
height: 32rpx;
background: #f5f5f5;
border-radius: 20rpx;
}
</style>

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,164 @@
<script>
import baseDrawer from '@/components/tui-drawer/tui-drawer.vue';
export default {
props: {
visible: {
type: Boolean,
default: false,
},
cateList:{
type:Array,
default: () => []
},
brandList:{
type:Array,
default: () => []
},
},
data(){
return {
cateGoryList:[],
brand_id: [],
cateId:[],
sid:''
}
},
watch:{
cateList:{
handler(val){
this.cateGoryList = val;
this.cateGoryList.map(item=>{
this.$set(item,'more', true);
})
},
immediate: true
},
},
computed: {
fixedTop() {
// #ifdef MP || APP-PLUS
return uni.getWindowInfo().statusBarHeight
// #endif
// #ifdef H5
return 20
// #endif
},
},
components: {
baseDrawer
},
methods: {
closeDrawer() {
this.$emit('closeDrawer');
},
checkBrand(item){
if(this.brand_id.includes(item.id)){
this.brand_id = this.brand_id.filter(function (ele){return ele != item.id;});
}else{
this.brand_id.push(item.id);
}
},
checkCate(item){
this.sid = item.id;
},
checkMore(item){
item.more = !item.more
},
confirmFilter(){
let data = {
brand_id: this.brand_id.join(','),
sid: this.sid
};
this.$emit('filterChange',data);
},
resetFilter(){
this.brand_id = [];
this.sid = '';
let data = {
brand_id: '',
sid: ''
};
this.$emit('filterChange',data);
}
}
}
</script>
<template>
<view>
<base-drawer mode="right" :visible="visible" background-color="transparent" mask maskClosable
@close="closeDrawer">
<view class="drawer_box bg--w111-fff px-32 h-full">
<scroll-view scroll-y="true" style="height: 100vh;">
<view :style="{height:fixedTop + 'px'}"></view>
<view class="h-80 flex-center fs-34 fw-500 text--w111-333">筛选</view>
<view class="activity_box py-24">
<view v-if="brandList.length">
<view class="fs-28 text--w111-333 fw-500 mt-24">品牌</view>
<view class="grid-column-3 box_gap mt-24">
<view class="h-56 rd-28rpx bg--w111-f5f5f5 flex-center fs-24 text--w111-333"
v-for="item in brandList" :key="item.id"
:class="{active: brand_id.includes(item.id)}"
@tap="checkBrand(item)">
<text class="inline-block w-full line1 px-12 text-center">{{item.brand_name}}</text>
</view>
</view>
</view>
<view v-if="cateGoryList.length">
<view class="fs-28 text--w111-333 fw-500 mt-48">分类</view>
<view v-for="(item,i) in cateGoryList" :key="i">
<view class="flex-between-center mt-48">
<text class='fs-24'>{{item.cate_name}}</text>
<view class="flex-y-center fs-20 text--w111-999 lh-34rpx" @tap="checkMore(item)">
<text>{{ item.more ? '收起' : '展开' }}</text>
<text class="iconfont fs-20" :class="item.more ? 'icon-ic_uparrow' : 'icon-ic_downarrow'"></text>
</view>
</view>
<view class="grid-column-3 box_gap mt-24" v-show="item.more">
<view class="h-56 rd-28rpx bg--w111-f5f5f5 flex-center fs-24 text--w111-333"
v-for="(cate,k) in item.children" :key="k"
:class="{active: cate.id == sid}"
@tap="checkCate(cate)">
<text class="inline-block w-full line1 px-12 text-center">{{cate.cate_name}}</text>
</view>
</view>
</view>
</view>
</view>
<view class="pb-safe">
<view class="h-112"></view>
</view>
</scroll-view>
<view class="fixed-lb pb-safe bg--w111-fff w-full">
<view class="px-32 flex-between-center h-112">
<view class="w-296 h-72 rd-40rpx flex-center text-mer con_border bg--w111-fff"
@tap="resetFilter()">重置</view>
<view class="w-296 h-72 rd-40rpx flex-center text--w111-fff mer-bg" @tap="confirmFilter()">确定</view>
</view>
</view>
</view>
</base-drawer>
</view>
</template>
<style lang="scss">
.drawer_box {
width: 668rpx;
border-radius: 40rpx 0 0 40rpx;
overflow: auto;
}
.box_gap {
grid-row-gap: 24rpx;
grid-column-gap: 26rpx;
}
.con_border{
border: 1rpx solid $primary-merchant;
}
.active{
border: 1px solid $primary-merchant;
color: $primary-merchant;
background: $light-primary-merchant;
}
.text-mer{
color: $primary-merchant;
}
</style>

View File

@@ -0,0 +1,46 @@
<script>
import baseDrawer from '@/components/tui-drawer/tui-drawer.vue';
export default {
props: {
visible: {
type: Boolean,
default: false
},
ensureInfo: {
type: Object,
default: () => {}
}
},
components: {
baseDrawer
},
methods: {
closeDrawer() {
this.$emit('closeDrawer');
}
}
};
</script>
<template>
<view>
<base-drawer mode="bottom" :visible="visible" background-color="transparent" mask maskClosable @close="closeDrawer">
<view class="w-full bg--w111-fff rd-t-40rpx py-32">
<view class="text-center fs-32 text--w111-333 fw-500 mb-34">服务</view>
<scroll-view scroll-y="true" class="h-400">
<view class="px-32">
<view class="mb-38" v-for="(item, index) in ensureInfo.ensure" :key="index">
<view class="flex-y-center">
<image class="w-34 h-34" :src="item.image"></image>
<text class="pl-12 text--w111-333 fs-28 fw-500">{{ item.name }}</text>
</view>
<view class="mt-6 pl-40 fs-22 text--w111-999">{{ item.desc }}</view>
</view>
</view>
</scroll-view>
<view class="mx-20 pb-safe">
<view class="mt-52 h-72 flex-center rd-36px mer-bg fs-26 text--w111-fff" @click="closeDrawer">确定</view>
</view>
</view>
</base-drawer>
</view>
</template>

View File

@@ -0,0 +1,134 @@
<template>
<base-drawer mode="bottom" :visible="attr.cartAttr" background-color="transparent" zIndex="3000" mask maskClosable
@close="closeDrawer">
<view>
<view class="bg--w111-fff rd-t-40rpx">
<view class="w-full pt-32">
<view class="px-32 flex">
<image class="w-180 h-180 rd-16rpx" :src="attr.productSelect.image" @tap="showImg"></image>
<view class="pl-24">
<baseMoney :money="attr.productSelect.channel_price" symbolSize="32" integerSize="48"
decimalSize="32" color="#FF7E00" weight></baseMoney>
<view class="mt-20 fs-24 text--w111-999">库存:{{ attr.productSelect.stock }}</view>
</view>
</view>
</view>
<scroll-view class="px-32" scroll-y="true" style="max-height: 400rpx;">
<view class="item mt-32" v-for="(item, indexw) in attr.productAttr" :key="indexw">
<view class="fs-28">{{ item.attr_name }}</view>
<view class="flex-y-center flex-wrap">
<view class="sku-item" :class="item.index === itemn.attr ? 'active' : ''"
v-for="(itemn, indexn) in item.attr_value" @click="tapAttr(indexw, indexn)"
:key="indexn">
{{ itemn.attr }}
</view>
</view>
</view>
</scroll-view>
<view class="flex-between-center px-32 mt-24">
<text class="fs-28">数量</text>
<view class="flex-y-center">
<view class="jia-btn w-84 h-48 flex-center" @click="CartNumAdd(false)">
<text class="iconfont icon-ic_Reduce fs-24"></text>
</view>
<view class='w-84 h-48 text-center lh-48rpx bg--w111-f5f5f5'>{{ attr.productSelect.cart_num }}</view>
<view class="jia-btn w-84 h-48 flex-center" @click="CartNumAdd(true)">
<text class="iconfont icon-ic_increase fs-24"></text>
</view>
</view>
</view>
<view class="mx-20 pb-box">
<view class="mt-52 h-72 flex-center rd-36px mer-bg fs-26 text--w111-fff" @click="confirmCartAdd"
v-if="attr.productSelect.stock">
确定</view>
<view class="mt-52 h-72 flex-center rd-36px bg-gray fs-26 text--w111-fff" v-else>已售罄</view>
</view>
</view>
</view>
</base-drawer>
</template>
<script>
export default {
props:{
attr: {
type: Object,
default: () => {}
},
storeInfo: {
type: Object,
default: () => {}
},
},
data(){
return {
}
},
methods:{
CartNumAdd(type){
this.$emit('ChangeCartNum', type);
},
closeDrawer(){
this.$emit('myevent');
},
confirmCartAdd(){
this.$emit('onConfirm');
},
tapAttr: function(indexw, indexn) {
let that = this;
that.$emit("attrVal", {
indexw: indexw,
indexn: indexn
});
this.$set(this.attr.productAttr[indexw], 'index', this.attr.productAttr[indexw].attr_values[indexn]);
let value = that
.getCheckedValue()
.join(",");
that.$emit("ChangeAttr", value);
},
//获取被选中属性;
getCheckedValue: function() {
let productAttr = this.attr.productAttr;
let value = [];
for (let i = 0; i < productAttr.length; i++) {
for (let j = 0; j < productAttr[i].attr_values.length; j++) {
if (productAttr[i].index === productAttr[i].attr_values[j]) {
value.push(productAttr[i].attr_values[j]);
}
}
}
return value;
},
showImg(){
this.$emit('getImg');
}
}
}
</script>
<style lang="scss">
.sku-item {
height: 56rpx;
line-height: 56rpx;
border: 1px solid #F2F2F2;
font-size: 24rpx;
color: #333;
padding: 0 44rpx;
border-radius: 28rpx;
margin: 24rpx 0 0 16rpx;
background-color: #F2F2F2;
word-break: break-all;
}
.active {
color: $primary-merchant;
background: $light-primary-merchant;
border-color: $primary-merchant;
}
.pb-box{
padding-bottom: calc(20rpx + env(safe-area-inset-bottom));
}
.bg-gray{
background-color: #ccc;
}
</style>

View File

@@ -0,0 +1,45 @@
<template>
<!-- 产品参数 -->
<base-drawer mode="bottom" :visible="specsInfo.show" background-color="transparent" mask maskClosable @close="closeSpecs">
<view class="w-full bg--w111-fff rd-t-40rpx py-32">
<view class="text-center fs-32 text--w111-333 fw-500 mb-34">参数</view>
<scroll-view scroll-y="true" class="h-400">
<view class="px-32 scroll-content">
<view class="item flex break_word" v-for="(item,index) in specsInfo.specs" :key="index">
<view class="w-160 text--w111-999 mr-12">{{item.name}}</view>
<view class="flex-1">{{item.value}}</view>
</view>
</view>
</scroll-view>
<view class="mx-20 pb-safe">
<view class="mt-52 h-72 flex-center rd-36px mer-bg fs-26 text--w111-fff" @click="closeSpecs">确定</view>
</view>
</view>
</base-drawer>
</template>
<script>
import baseDrawer from '@/components/tui-drawer/tui-drawer.vue';
export default {
props: {
specsInfo: {
type: Object,
default: () => {}
},
},
components: {
baseDrawer
},
methods: {
closeSpecs() {
this.$emit('myevent');
}
}
}
</script>
<style scoped lang="scss">
.item ~ .item{
margin-top: 40rpx;
}
</style>

View File

@@ -0,0 +1,128 @@
<template>
<!-- 底部导航 -->
<keep-alive>
<view class="page-footer">
<view class="foot-item" :class="item.pagePath == activeRouter?'active':''"
v-for="(item,index) in footerList" :key="index" @click="goRouter(item)">
<block v-if="item.pagePath == activeRouter">
<image :src="item.selectedIconPath"></image>
<view class="txt">{{item.text}}</view>
</block>
<block v-else>
<image :src="item.iconPath"></image>
<view class="txt">{{item.text}}</view>
</block>
<uni-badge v-if="index == 1 && cartNum > 0" class="badge-style" :text="cartNum" absolute="rightTop"></uni-badge>
</view>
</view>
</keep-alive>
</template>
<script>
import { mapGetters } from 'vuex';
import {getCartCounts} from '@/api/order.js';
export default {
name: 'footer',
props: {},
created() {
let routes = getCurrentPages(); //获取当前打开过的页面路由数组
let curRoute = routes[routes.length - 1].route //获取当前页面路由
this.activeRouter = '/' + curRoute
},
computed: {
...mapGetters(['isLogin', 'cartNum']),
styleType(){
return this.$store.state.app.system_channel_style;
}
},
data() {
return {
activeRouter:'',
footerList:[
{
pagePath: "/pages/merchant/index/index",
iconPath: require("../../static/1-0.png"),
selectedIconPath: require("../../static/1-1.png"),
text: "首页"
},
{
pagePath: "/pages/merchant/cart/index",
iconPath: require("../../static/2-0.png"),
selectedIconPath: require("../../static/2-1.png"),
text: "购物车"
},
{
pagePath: "/pages/merchant/user/index",
iconPath: require("../../static/3-0.png"),
selectedIconPath: require("../../static/3-1.png"),
text: "我的"
}
],
// cartNum:0
}
},
mounted() {
this.getCartNum();
},
methods: {
goRouter(item) {
var pages = getCurrentPages();
var page = (pages[pages.length - 1]).$page.fullPath;
if (item.pagePath == page) return
uni.redirectTo({
url: item.pagePath,
animationType: 'none' // 关闭默认的滑动效果
});
},
getCartNum() {
this.$store.dispatch('indexData/getCartNum')
},
}
}
</script>
<style scoped lang="scss">
.page-footer {
position: fixed;
bottom: 0;
left:0;
z-index: 1000;
display: flex;
align-items: center;
justify-content: space-around;
width: 100%;
height: calc(100rpx + constant(safe-area-inset-bottom)); ///兼容 IOS<11.2/
height: calc(100rpx + env(safe-area-inset-bottom)); ///兼容 IOS>11.2/
box-sizing: border-box;
border-top: solid 1rpx #F3F3F3;
background-color: #fff;
padding-bottom: constant(safe-area-inset-bottom); ///兼容 IOS<11.2/
padding-bottom: env(safe-area-inset-bottom); ///兼容 IOS>11.2/
.foot-item {
display: flex;
width: max-content;
align-items: center;
justify-content: center;
flex-direction: column;
position: relative;
padding: 0 20rpx;
&.active {
color: $primary-merchant;
}
}
.foot-item image {
height: 40rpx;
width: 40rpx;
text-align: center;
margin: 0 auto;
}
.foot-item .txt {
font-size: 20rpx;
margin-top: 6rpx;
}
}
</style>

View File

@@ -0,0 +1,11 @@
import CryptoJS from './crypto-js.js'
/**
* @word 要加密的内容
* @keyWord String 服务器随机返回的关键字
* */
export function aesEncrypt(word,keyWord="XwKsGlMcdPMEhR1B"){
var key = CryptoJS.enc.Utf8.parse(keyWord);
var srcs = CryptoJS.enc.Utf8.parse(word);
var encrypted = CryptoJS.AES.encrypt(srcs, key, {mode:CryptoJS.mode.ECB,padding: CryptoJS.pad.Pkcs7});
return encrypted.toString();
}

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,51 @@
<template>
<view>
<template3 v-if="level == 2" :level="level"></template3>
<template2 v-else :level="level"></template2>
<tab-bar></tab-bar>
</view>
</template>
<script>
import template2 from './template/template2.vue';
import template3 from './template/template3.vue';
import tabBar from "../components/tabBar/index.vue"
import { mapGetters } from 'vuex';
export default {
data() {
return {
};
},
components: {
template2,
template3,
tabBar
},
computed:{
...mapGetters(['isLogin', 'uid', 'diyCategory']),
level(){
return this.diyCategory.level
},
},
onLoad() {
let identity = this.$store.state.app.identity;
if(identity != 1 && this.isLogin){
setTimeout(()=>{
uni.switchTab({
url: "/pages/index/index"
})
},500)
}else if(identity == 2 && this.isLogin){
uni.redirectTo({
url: "/pages/admin/work/index"
})
}
}
}
</script>
<style lang="scss">
</style>

View File

@@ -0,0 +1,746 @@
<template>
<!-- 商品列表 -->
<view>
<view class="header_box fixed-lt w-full z-20 bg--w111-fff" :style="{'padding-top': sysHeight + 'px'}">
<view class="h-80 px-20 flex-y-center">
<!-- <text class="iconfont icon-ic_leftarrow fs-40 mr-16" @tap="goBack"></text> -->
<!-- #ifdef MP-WEIXIN -->
<view class="h-58 rd-30 bg--w111-f5f5f5 flex-y-center px-32 relative" :style="[serchWidth]">
<!-- #endif -->
<!-- #ifndef MP-WEIXIN -->
<view class="flex-1 h-58 rd-30 bg--w111-f5f5f5 flex-y-center px-32 relative">
<!-- #endif -->
<text class="iconfont icon-ic_search fs-24"></text>
<input :value='where.keyword' class="pl-18 w-460 line1 fs-24" placeholder="请输入商品名称" placeholder-class="text--w111-999" @confirm="searchSubmit" />
<text class="iconfont icon-ic_close1 fs-28 text--w111-999 z-10" v-if="where.keyword" @tap="clearWord"></text>
</view>
</view>
<view class="h-88 px-32 flex-between-center relative">
<view class="text--w111-333 fs-26 fw-500 flex-y-center" @tap="toggleSortable">
<text>综合排序</text>
<text class="iconfont icon-ic_down2 fs-14 ml-6"></text>
</view>
<view class="text--w111-666 flex-y-center fs-26" @tap='set_where(3)'>
<text :class="[1,2].includes(stock) ? 'text-primary-con' : ''">销量</text>
<text v-show="stock==2" class="iconfont icon-ic_down2 fs-14 ml-6 text-primary-con"></text>
<text v-show="stock==1" class="iconfont icon-ic_up2 fs-14 ml-6 text-primary-con"></text>
<text v-show="stock==0" class="iconfont icon-ic_down2 fs-14 ml-6"></text>
</view>
<view class="text--w111-666 flex-y-center fs-26" @tap='set_where(2)'>
<text :class="[1,2].includes(price) ? 'text-primary-con' : ''">价格</text>
<text v-show="price==2" class="iconfont icon-ic_down2 fs-14 ml-6 text-primary-con"></text>
<text v-show="price==1" class="iconfont icon-ic_up2 fs-14 ml-6 text-primary-con"></text>
<text v-show="price==0" class="iconfont icon-ic_down2 fs-14 ml-6"></text>
</view>
<view class="text--w111-666 flex-y-center fs-26">
<text class="iconfont" :class="is_switch ? 'icon-a-ic_Imageandtextsorting' : 'icon-a-ic_QRcode'" @tap='Changswitch'></text>
<text class="menu_line"></text>
<view @tap="openDrawer">筛选</view>
<text class="iconfont icon-ic_sort pl-8" @tap="openDrawer"></text>
</view>
<view class="sortable-box w-full bg--w111-fff rd-b-24rpx z-999" v-if="showSortAbleBox">
<view class="flex-between-center pb-40"
v-for="(item, index) in sortableShowTab" :key="index" @tap="checkSortable(item.value)">
<text class="fs-26" :class="item.value == where.defaultOrder ? 'text-primary-con' : 'text--w111-333'">{{item.title}}</text>
<image class="w-28 h-28" src="../static/dui-icon.png" v-show="item.value == where.defaultOrder"></image>
</view>
</view>
</view>
</view>
<view class="pt-16 pl-20 pr-20 bg--w111-fff" :style="{'margin-top':marTop + 'rpx'}" v-if="is_switch==false">
<view class="flex mb-32 pro_item" v-for="(item,index) in tempArr" :key="index" @tap="goDetail(item)">
<view class="list-pic w-240 h-240 relative">
<easy-loadimage
:image-src="item.image"
:borderSrc="item.activity_frame.image"
width="240rpx"
height="240rpx"
borderRadius="20rpx"></easy-loadimage>
</view>
<view class="flex-1 pl-20 flex-col justify-between">
<view class="w-full">
<view class="w-full line2 fs-28 text--w111-333 lh-40rpx">
<text v-if="item.brand_name" class="brand-tag">{{ item.brand_name }}</text>{{item.store_name}}
</view>
</view>
<view class="flex-between-center">
<baseMoney :money="item.price" symbolSize="24" integerSize="40" decimalSize="24" color="#FF7E00" weight></baseMoney>
<view class="w-44 h-44 rd-24 mer-bg flex-center" @tap.stop="addCartTap(item)">
<text class="iconfont icon-ic_ShoppingCart1 text--w111-fff fs-26"></text>
</view>
</view>
</view>
</view>
<view class='loadingicon acea-row row-center-wrapper' v-if='tempArr.length > 0'>
<text class='loading iconfont icon-jiazai' :hidden='loading==false'></text>
</view>
</view>
<view class="p-20 relative" :style="{'margin-top':marTop + 'rpx'}" v-else>
<view class="jinabian"></view>
<waterfallsFlow :wfList="tempArr" isMerchant @itemTap="goDetail"></waterfallsFlow>
</view>
<view class="pb-safe">
<view class="h-200"></view>
</view>
<view class='px-20' v-if="tempArr.length==0 && where.page > 1">
<emptyPage :title="where.keyword ? '无搜索结果,换个词试试吧' : '暂无商品去看点别的吧'"
:src="where.keyword ? '/statics/images/noSearch.gif' : '/statics/images/empty-box.gif'"></emptyPage>
<recommend :hostProduct="hostProduct"></recommend>
</view>
<filterDrawer
:visible="showFilterDrawer"
:brandList="brandList"
:cateList="cateList"
@closeDrawer="closeFilter"
@filterChange="filterConfirm"></filterDrawer>
<view class="mask" v-if="showSortAbleBox" @tap="showSortAbleBox = false"></view>
<base-drawer mode="bottom" :visible="showSku" background-color="transparent" zIndex="3000" mask maskClosable
@close="closeDrawer">
<view>
<view class="bg--w111-fff rd-t-40rpx">
<view class="w-full pt-32">
<view class="px-32 flex">
<image class="w-180 h-180 rd-16rpx" :src="attr.productSelect.image"></image>
<view class="pl-24">
<baseMoney :money="attr.productSelect.price" symbolSize="32" integerSize="48"
decimalSize="32" color="#FF7E00" weight></baseMoney>
<view class="mt-20 fs-24 text--w111-999">库存:{{ attr.productSelect.stock }}</view>
</view>
</view>
</view>
<scroll-view class="px-32" scroll-y="true" style="max-height: 400rpx;">
<view class="item mt-32" v-for="(item, indexw) in attr.productAttr" :key="indexw">
<view class="fs-28">{{ item.attr_name }}</view>
<view class="flex-y-center flex-wrap">
<view class="sku-item" :class="item.index === itemn.attr ? 'active-sku' : ''"
v-for="(itemn, indexn) in item.attr_value" @click="tapAttr(indexw, indexn)"
:key="indexn">
{{ itemn.attr }}
</view>
</view>
</view>
</scroll-view>
<view class="flex-between-center px-32 mt-24">
<text class="fs-28">数量</text>
<view class="flex-y-center">
<view class="jia-btn w-84 h-48 flex-center" @click="CartNumAdd(false)">
<text class="iconfont icon-ic_Reduce fs-24"></text>
</view>
<view class='w-84 h-48 text-center lh-48rpx bg--w111-f5f5f5'>{{ attr.productSelect.cart_num }}</view>
<view class="jia-btn w-84 h-48 flex-center" @click="CartNumAdd(true)">
<text class="iconfont icon-ic_increase fs-24"></text>
</view>
</view>
</view>
<view class="mx-20 pb-box">
<view class="mt-52 h-72 flex-center rd-36px mer-bg fs-26 text--w111-fff" @click="confirmCartAdd">
确定</view>
</view>
</view>
</view>
</base-drawer>
<tab-bar ref="tabBar" v-show="showTabBar"></tab-bar>
</view>
</template>
<script>
let sysHeight = uni.getWindowInfo().statusBarHeight;
import productWindow from '@/components/productWindow';
import waterfallsFlow from "@/components/WaterfallsFlow/WaterfallsFlow.vue";
import {
getProductslist,
getProductHot,
searchFilterApi,
levelCategoryApi,
getAttr,
postCartAdd,
postCartNum,
getCategoryList
} from '@/api/store.js';
import {cartDel} from "@/api/order.js";
import { toLogin } from '@/libs/login.js';
import recommend from '@/components/recommend';
import filterDrawer from '../components/filterDrwer/index.vue';
import emptyPage from '@/components/emptyPage.vue';
import tabBar from "../components/tabBar/index.vue"
import { mapGetters } from "vuex";
import { goShopDetail } from '@/libs/order.js';
import { vcartList, getCartCounts, cartCompute } from '@/api/order.js';
import colors from '@/mixins/color.js';
import { HTTP_REQUEST_URL } from '@/config/app';
export default {
computed: {
...mapGetters(['uid', 'isLogin']),
serchWidth(){
let res = wx.getMenuButtonBoundingClientRect();
let windowWidth = wx.getWindowInfo().windowWidth;
return {
width: windowWidth - res.width - (windowWidth-res.right) - 20 + 'px'
};
}
},
components: {
recommend,
waterfallsFlow,
filterDrawer,
emptyPage,
tabBar
},
mixins: [colors],
data() {
return {
id: 0,
productValue: [], //系统属性
is_vip: 0, //是否是会员
attr: {
cartAttr: false,
productAttr: [],
productSelect: {}
},
productAttr: [],
attrValue: '', //已选属性
storeName: '',
sysHeight: sysHeight,
goodList: true,
currentPage: false,
tempArr: [],
is_switch: true,
where: {
sid: 0,
keyword: '',
priceOrder: '',
salesOrder: '',
news: 0,
page: 1,
limit: 10,
cid: 0,
tid: 0,
brand_id: '',
defaultOrder:0,
is_channel:1
},
price: 0,
stock: 0,
nows: false,
loadend: false,
loading: false,
loadTitle: '加载更多',
title: '',
hostProduct: [],
hotPage: 1,
hotLimit: 10,
hotScroll: false,
brandList: [],
promotionList:[],
labelList:[],
filterCateList:[],
storeInfo: {},
totalPrice: 0,
promotionsInfo: {},
totalNum: 0,
imgHost: HTTP_REQUEST_URL,
isShowAuth: false,
marTop:'',
showFilterDrawer:false,
cateSearch:false,
showSortAbleBox:false,
sortableShowTab:[
{title:'综合排序',value:0},
{title:'好评优先',value:1},
{title:'新品优先',value:2},
],
cartData: {
cartList: [],
iScart: false
},
cart_num: 0,
discountInfo:{
deduction:{},
},
showSku: false,
cateList: [],
showTabBar: true,
product_id: ''
};
},
provide() {
return {
addCartClick: this.addCartTap,
isVip: false,
merchant: true
};
},
onLoad(options) {
this.getMarTop();
this.getCateList()
this.getProductList();
this.getSearchFilter();
this.getChannel();
},
methods: {
getChannel(){
let identity = this.$store.state.app.identity;
let styleType = this.$store.state.app.system_channel_style;
if(identity != 1 && this.isLogin){
setTimeout(()=>{
uni.switchTab({
url: "/pages/index/index"
})
},500)
}else if(identity == 2 && this.isLogin){
uni.redirectTo({
url: "/pages/admin/work/index"
})
}
},
addCartTap(data){
if(data.spec_type){
this.product_id = data.id;
this.goCartDuo(data);
}else{
if (!this.isLogin) {
toLogin();
} else {
if(data.cart_button == 0){
uni.showToast({
title: '该商品不可加入购物车',
icon: 'none'
})
}else{
let params = {
num: 1,
product_id: data.id,
is_channel:1,
type: 1,
};
postCartNum(params).then(res=> {
this.$util.Tips({
title: '添加购物车成功',
});
this.$refs.tabBar.getCartNum()
}).catch(err => {
return this.$util.Tips({
title: err
});
});
}
}
}
},
goCartDuo(item) {
if (!this.isLogin) {
toLogin();
} else {
if(item.cart_button == 0){
uni.showToast({
title: '该商品不可加入购物车',
icon: 'none'
})
}else{
this.storeName = item.store_name;
this.getAttrs(item.id);
this.$set(this, 'id', item.id);
this.$set(this.attr, 'cartAttr', true);
}
}
},
// 商品详情接口;
getAttrs(id) {
let that = this;
getAttr(id, 0).then(res => {
this.$set(this.attr, 'productAttr', res.data.productAttr);
this.productAttr = res.data.productAttr;
this.$set(this, 'productValue', res.data.productValue);
this.$set(this, 'storeInfo', res.data.storeInfo);
this.DefaultSelect();
this.showSku = true;
})
},
DefaultSelect(){
let productAttr = this.productAttr;
let value = [];
for (var key in this.productValue) {
if (this.productValue[key].stock > 0) {
value = productAttr.length ? key.split(',') : [];
break;
}
}
for (let i = 0; i < productAttr.length; i++) {
this.$set(productAttr[i], 'index', value[i]);
}
let productSelect = this.productValue[value.join(',')];
this.attr.productSelect = {
image: productSelect.image,
price: productSelect.price,
unique: productSelect.unique || '',
suk: productSelect.suk || '默认',
stock: productSelect.stock,
cart_num: 1
};
},
tapAttr: function(indexw, indexn) {
let that = this;
this.$set(this.attr.productAttr[indexw], 'index', this.attr.productAttr[indexw].attr_values[indexn]);
let value = that.getCheckedValue().join(",");
this.attr.productSelect = {
price: this.productValue[value].price,
image: this.productValue[value].image,
stock: this.productValue[value].stock,
unique: this.productValue[value].unique || '',
suk: this.productValue[value].suk || '默认',
cart_num: 1
};
},
getCheckedValue: function() {
let productAttr = this.attr.productAttr;
let value = [];
for (let i = 0; i < productAttr.length; i++) {
for (let j = 0; j < productAttr[i].attr_values.length; j++) {
if (productAttr[i].index === productAttr[i].attr_values[j]) {
value.push(productAttr[i].attr_values[j]);
}
}
}
return value;
},
closeDrawer(){
this.showSku = false;
},
// 筛选
getSearchFilter() {
searchFilterApi({}).then(res => {
this.brandList = res.data.brand;
}).catch(err => {
return this.$util.Tips({
title: err.msg
});
})
},
toggleSortable(){
this.showSortAbleBox = !this.showSortAbleBox;
},
checkSortable(val){
this.where.defaultOrder = val;
this.showSortAbleBox = false;
this.loadend = false;
this.$set(this.where, 'page', 1);
this.getProductList(true);
},
clearWord(){
this.where.keyword = ''
},
cateCheck(item){
this.where.sid = item.id;
this.loadend = false;
this.$set(this.where, 'page', 1);
this.getProductList(true);
},
openDrawer(){
this.showFilterDrawer = true;
this.showTabBar = false;
},
closeFilter(){
this.showFilterDrawer = false;
this.showTabBar = true;
},
filterConfirm(data){
this.showFilterDrawer = false;
this.showTabBar = true;
Object.assign(this.where,data);
this.loadend = false;
this.$set(this.where, 'page', 1);
this.getProductList(true);
},
CartNumAdd(type){
if(type){
this.attr.productSelect.cart_num++;
}else{
if(this.attr.productSelect.cart_num == 1) return
this.attr.productSelect.cart_num--;
}
},
// 去详情页
goDetail(item) {
this.currentPage = false;
uni.navigateTo({
url: `/pages/merchant/goodsDetails/index?id=${item.id}`
});
},
Changswitch: function() {
let that = this;
this.currentPage = false
that.is_switch = !that.is_switch
},
searchSubmit: function(e) {
let that = this;
this.currentPage = false
that.$set(that.where, 'keyword', e.detail.value);
that.loadend = false;
that.$set(that.where, 'page', 1)
this.getProductList(true);
this.getSearchFilter();
},
/**
* 获取我的推荐
*/
get_host_product: function() {
let that = this;
if (that.hotScroll) return
getProductHot(
that.hotPage,
that.hotLimit,
).then(res => {
that.hotPage++
that.hotScroll = res.data.length < that.hotLimit
that.hostProduct = that.hostProduct.concat(res.data)
// that.$set(that, 'hostProduct', res.data)
});
},
//点击事件处理
set_where: function(e) {
this.currentPage = false
switch (e) {
case 1:
// #ifdef H5
return history.back();
// #endif
// #ifndef H5
return uni.navigateBack({
delta: 1,
})
// #endif
break;
case 2:
if (this.price == 0) this.price = 1;
else if (this.price == 1) this.price = 2;
else if (this.price == 2) this.price = 0;
this.stock = 0;
break;
case 3:
if (this.stock == 0) this.stock = 1;
else if (this.stock == 1) this.stock = 2;
else if (this.stock == 2) this.stock = 0;
this.price = 0
break;
case 4:
this.nows = !this.nows;
break;
}
this.loadend = false;
this.$set(this.where, 'page', 1);
this.getProductList(true);
},
//设置where条件
setWhere: function() {
if (this.price == 0) this.where.priceOrder = '';
else if (this.price == 1) this.where.priceOrder = 'asc';
else if (this.price == 2) this.where.priceOrder = 'desc';
if (this.stock == 0) this.where.salesOrder = '';
else if (this.stock == 1) this.where.salesOrder = 'asc';
else if (this.stock == 2) this.where.salesOrder = 'desc';
this.where.news = this.nows ? 1 : 0;
},
//查找产品
getProductList: function(isPage) {
let that = this;
that.setWhere();
if (that.loadend) return;
if (that.loading) return;
if (isPage === true) {
that.$set(that, 'tempArr', []);
}
that.loading = true;
that.loadTitle = '';
getProductslist(that.where).then(res => {
let list = res.data;
let productList = that.$util.SplitArray(list, that.tempArr);
let loadend = list.length < that.where.limit;
that.loadend = loadend;
that.loading = false;
that.loadTitle = loadend ? '没有更多内容啦~' : '加载更多';
that.$set(that, 'tempArr', productList);
that.$set(that.where, 'page', that.where.page + 1);
if (!that.tempArr.length) this.get_host_product();
}).catch(err => {
that.loading = false;
that.loadTitle = '加载更多';
});
},
getMarTop(){
this.$nextTick(()=>{
this.marTop = (75 + sysHeight) * 2
})
},
goBack(){
// uni.navigateBack()
let pages = getCurrentPages(); // 获取当前打开过的页面路由数,
if (pages.length > 1) {
uni.navigateBack()
} else {
uni.switchTab({
url: '/pages/index/index'
});
}
},
getCateList(){
getCategoryList().then(res => {
this.cateList = res.data;
})
},
confirmCartAdd(){
let data = {
product_id:this.product_id,
num: this.attr.productSelect.cart_num,
type: 1,
uniqueId: this.attr.productSelect.unique,
is_channel:1
};
postCartNum(data).then(res=> {
this.showSku = false;
this.$store.dispatch('indexData/getCartNum')
uni.showToast({
title: '添加购物车成功',
icon: 'none'
})
}).catch(err => {
return this.$util.Tips({
title: err
});
});
}
},
onPageScroll(e) {
this.currentPage = false;
uni.$emit('scroll');
},
onReachBottom() {
if (this.tempArr.length > 0) {
this.getProductList();
} else {
this.get_host_product();
}
},
onPullDownRefresh() {
if (this.tempArr.length > 0) {
this.getProductList();
} else {
this.get_host_product();
}
setTimeout(function () {
uni.stopPullDownRefresh();
}, 1000);
},
}
</script>
<style scoped lang="scss">
.z-200{
z-index: 200;
}
.z-101{
z-index: 101;
}
.pro_item ~ .pro_item{
margin-top: 32rpx;
}
.border-picture {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
border-radius: 16rpx 16rpx 0 0;
background: center/cover no-repeat;
}
.menu_line {
width: 1px;
height: 30rpx;
background: #B3B3B3;
margin: 0 20rpx;
}
.icon-ic_close1{
position: absolute;
right: 34rpx;
top: 50%;
transform: translateY(-50%);
}
.select_cate{
&:after{
content: '';
position: absolute;
top: 42rpx;
left:50%;
transform: translateX(-50%);
width:36rpx;
height:10rpx;
background-image: url('../static/select_zs.png');
background-size: 100%;
}
}
.jinabian{
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 330rpx;
background: linear-gradient(180deg, #FFFFFF 0%, rgba(255,255,255,0) 100%);
}
.info_box{
padding: 16rpx 20rpx;
border-radius: 0 0 20rpx 20rpx;
background-color: #fff;
}
.text-primary-con{
color: var(--view-theme);
}
.bg-primary-light{
background: var(--view-minorColorT);
}
.bg--w111-484643{
background: linear-gradient(90deg, #484643 0%, #1F1B17 100%);
}
.text--w111-FDDAA4{
color: #FDDAA4;
}
.svip_rd{
border-radius: 14rpx 0 8rpx 14rpx;
}
.op-border{
border: 1px solid #f5f5f5;
}
.active{
border: 1px solid var(--view-theme);
color: var(--view-theme);
background: var(--view-minorColorT);
}
.sortable-box{
padding: 32rpx 32rpx 0;
position: absolute;
top: 88rpx;
left: 0;
}
.sku-item {
height: 56rpx;
line-height: 56rpx;
border: 1px solid #F2F2F2;
font-size: 24rpx;
color: #333;
padding: 0 44rpx;
border-radius: 28rpx;
margin: 24rpx 0 0 16rpx;
background-color: #F2F2F2;
word-break: break-all;
}
.active-sku {
color: $primary-merchant;
background: $light-primary-merchant;
border-color: $primary-merchant;
}
.pb-box{
padding-bottom: calc(20rpx + env(safe-area-inset-bottom));
}
/deep/.brand-tag{
background-color: $primary-merchant;
}
</style>

View File

@@ -0,0 +1,870 @@
<template>
<view>
<view class="flex-col bg--w111-fff" :style="{ height: windowHeight + 'px' }">
<view :style="{paddingTop: sysHeight + 'px'}" class="text--w111-999">
<view class="h-80 px-32 flex-y-center">
<!-- #ifdef MP -->
<view class="w-508 h-58 flex-y-center rd-30rpx bg--w111-f5f5f5 px-32">
<!-- #endif -->
<!-- #ifndef MP -->
<view class="w-full h-58 flex-y-center rd-30rpx bg--w111-f5f5f5 px-32">
<!-- #endif -->
<text class="iconfont icon-ic_search fs-28"></text>
<input v-model="keyword" placeholder="请输入商品名称" placeholder-class="text--w111-999" @confirm="goSearch" class="fs-24 pl-18 text--w111-333" />
</view>
</view>
</view>
<view class="flex border_e">
<scroll-view scroll-x="true" class="white-nowrap vertical-middle w-678 pl-20 pt-24 pb-24"
show-scrollbar="false">
<view class="inline-block mr-8" v-for="(item,index) in categoryList" :key="index"
@tap="tapNav(index,item)">
<view class="flex-col flex-center">
<view :class="index == navActive ? 'active_pic' : 'scroll_pic'">
<image :src="item.pic" mode="aspectFill"></image>
</view>
<view class="w-120 h-40 flex-center fs-24 text--w111-333"
:class="index == navActive ? 'active_cate_text' : ''">{{item.cate_name}}</view>
</view>
</view>
</scroll-view>
<view class="flex-1 flex-col flex-center fs-24" @tap="openCateDrawer(true)">
<text></text>
<text></text>
<image class="w-28 h-28 block mt-8" src="@/static/img/all_pic.png"></image>
</view>
</view>
<view class="scroll_box flex flex-1">
<view class="w-168 h-full bg--w111-f5f5f5">
<scroll-view :scroll-top="0" scroll-y="true" class="h-full">
<view class="w-168 h-96 flex-center fs-26 text--w111-666"
v-for="(item,index) in categoryErList"
:key="index"
:class="[{'aside_active': index===tabClick},'aside_' + index]"
@tap="longClick(index,item)">{{item.cate_name}}
</view>
<view class="white-box"></view>
</scroll-view>
</view>
<view class="relative w-full h-full">
<view class="flex-1 pl-24 pr-20 abs-lt" v-if="threeCateList.length && level == 3">
<view class="flex mt-24 mb-16">
<scroll-view scroll-x="true" class="white-nowrap vertical-middle w-464"
show-scrollbar="false">
<view class="inline-block mr-16" v-for="(item,index) in threeCateList" :key="index"
@tap="threeCateClick(index,item)">
<view
class="w-144 h-56 rd-30rpx bg--w111-f5f5f5 flex-center fs-24 text--w111-333"
:class="index===threeClick?'cate_active':''">{{item.cate_name}}</view>
</view>
</scroll-view>
<view class="w-56 h-56 rd-30rpx bg--w111-f5f5f5 flex-center ml-16"
@tap="openCateDrawer(false)">
<text class="iconfont icon-ic_downarrow fs-32 text--w111-333"></text>
</view>
</view>
</view>
<view class="h-96" v-if="threeCateList.length && level == 3"></view>
<view v-else class="mt-24"></view>
<view class="pl-24 pr-20" :class="!threeCateList.length ? 'mt-24' : ''">
<scroll-view :scroll-top="0" scroll-y="true" @scrolltolower="lower" @scroll="scroll"
:style="{'height':scrollHeight + 'px'}">
<!-- 大图模板 -->
<view v-if="false">
<view class="mb-24" v-for="(item,index) in tempArr" :key="index"
@tap="goDetail(item)">
<view class="picture-box">
<easy-loadimage
mode="widthFix"
:image-src="item.recommend_image ? item.recommend_image : item.image"
:borderSrc="item.recommend_image ? '' :item.activity_frame.image"
width="540rpx"
borderRadius="20rpx 20rpx 0 0"></easy-loadimage>
<!-- :height="item.recommend_image ? '216rpx' : '540rpx'" -->
</view>
<view class="bg--w111-fff rd-b-20rpx pt-16 pl-24 pr-24 pb-24">
<view class="w-full line2 fs-28 text--w111-333 lh-40rpx">
<text v-if="item.brand_name" class="brand-tag">{{ item.brand_name }}</text>{{item.store_name}}
</view>
<view class="flex-between-center mt-20">
<view class="flex-y-center flex-wrap flex-1">
<baseMoney :money="item.price" symbolSize="24" integerSize="40"
decimalSize="24" weight>
</baseMoney>
<view class="svip-label ml-8" v-if="item.vip_price && item.vip_price > 0">
<text class="text">SVIP</text>
<text class="px-8 SemiBold">¥{{item.vip_price}}</text>
</view>
<text class="fs-22 text--w111-8e8e8e pl-12" v-else>已售{{item.sales}}</text>
</view>
<view
class="w-172 h-58 rd-30rpx mer-bg flex-center fs-24 text--w111-fff relative"
v-if="item.spec_type" @tap.stop="goCartDuo(item)">
<text>{{item.cart_button == 0 ? '立即购买' : '加入购物车'}}</text>
<uni-badge class="badge-style" v-if="item.cart_num > 0" :text="item.cart_num"></uni-badge>
</view>
<view v-if="!item.spec_type && !item.cart_num">
<view class="flex-center w-48 h-48 rd-30rpx mer-bg text--w111-fff "
@tap.stop="goCartDan(item,index)">
<text class="iconfont icon-ic_ShoppingCart1 fs-30"></text>
</view>
</view>
<view class="flex-y-center" v-if="!item.spec_type && item.cart_num">
<view
class="flex-center w-48 h-48 rd-30rpx bg--w111-f5f5f5 text--w111-333"
:class="{'disabled-btn': item.min_qty && item.cart_num == item.min_qty}"
@tap.stop="ChangeCartNumDan(false,index,item)">
<text class="iconfont icon-ic_Reduce fs-32"></text>
</view>
<view class="fs-30 text--w111-333 px-20" v-if="item.showInput" @tap.stop="toggleInput(item,true)">
<input v-model="item.copy_cart_num" type="text"
maxlength="2" :focus="true"
@input="inputClick($event,item)"
@confirm="setProCartNum($event,item)"
class="w-48 text-center" />
</view>
<view class="fs-30 text--w111-333 px-20" v-else @tap.stop="toggleInput(item,false)">{{item.cart_num}}</view>
<view class="flex-center w-48 h-48 rd-30rpx mer-bg text--w111-fff"
@tap.stop="CartNumAdd(index,item)">
<text class="iconfont icon-ic_increase fs-32"></text>
</view>
</view>
</view>
</view>
</view>
</view>
<!-- 小图模板 -->
<view v-if="true">
<view class="mb-24 flex justify-between" v-for="(item,index) in tempArr" :key="index"
@tap="goDetail(item)">
<easy-loadimage
mode="aspectFit"
:image-src="item.image"
:borderSrc="item.activity_frame.image"
width="176rpx"
height="176rpx"
borderRadius="16rpx"></easy-loadimage>
<view class="flex-1 flex-col justify-between pl-20">
<view class="w-full">
<view class="line2 w-346 fs-28 text-#333 h-80 lh-40rpx">
<text v-if="item.brand_name" class="brand-tag">{{ item.brand_name }}</text>{{item.store_name}}
</view>
</view>
<view class="flex-between-center">
<view class="flex-y-center flex-wrap flex-1">
<baseMoney :money="item.price" symbolSize="24" integerSize="40"
decimalSize="24" color="#FF7E00" weight>
</baseMoney>
</view>
<view class="flex-center w-48 h-48 rd-30rpx mer-bg text--w111-fff"
@tap.stop="goCartDuo(item)" v-if="item.spec_type">
<text class="iconfont icon-ic_ShoppingCart1 fs-30"></text>
</view>
<view v-else>
<view
class="flex-center w-48 h-48 rd-30rpx mer-bg text--w111-fff "
@tap.stop="goCartDan(item,index)">
<text class="iconfont icon-ic_ShoppingCart1 fs-30"></text>
</view>
</view>
<!-- <view class="flex-y-center" v-if="!item.spec_type && item.cart_num">
<view
class="flex-center w-48 h-48 rd-30rpx bg--w111-f5f5f5 text--w111-333"
:class="{'disabled-btn': item.min_qty && item.cart_num == item.min_qty}"
@tap.stop="ChangeCartNumDan(false,index,item)">
<text class="iconfont icon-ic_Reduce fs-32"></text>
</view>
<view class="fs-30 text--w111-333 px-20" v-if="item.showInput" @tap.stop="toggleInput(item,true)">
<input v-model="item.copy_cart_num" type="text"
maxlength="2" :focus="true"
@input="inputClick($event,item)"
@confirm="setProCartNum($event,item)"
class="w-48 text-center" />
</view>
<view class="fs-30 text--w111-333 px-20" v-else @tap.stop="toggleInput(item,false)">{{item.cart_num}}</view>
<view class="flex-center w-48 h-48 rd-30rpx mer-bg text--w111-fff"
@tap.stop="CartNumAdd(index,item)">
<text class="iconfont icon-ic_increase fs-32"></text>
</view>
</view> -->
</view>
</view>
</view>
</view>
<view v-if="!tempArr.length && !loading">
<emptyPage title="暂无商品,去看点别的吧~" ></emptyPage>
</view>
<view class="white-box"></view>
</scroll-view>
</view>
</view>
</view>
</view>
<view class="more_box abs-lt w-full bg--w111-fff rd-b-32rpx z-20" v-show="showCateDrawer">
<view :style="{paddingTop: sysHeight + 'px'}">
<view class="h-80 px-32 flex-y-center">
<!-- #ifdef MP -->
<view class="w-508 h-58 flex-y-center rd-30rpx bg--w111-f5f5f5 px-32">
<!-- #endif -->
<!-- #ifndef MP -->
<view class="w-full h-58 flex-y-center rd-30rpx bg--w111-f5f5f5 px-32">
<!-- #endif -->
<text class="iconfont icon-ic_search fs-28"></text>
<text class="fs-24 text--w111-999 pl-18">请输入商品名称</text>
</view>
</view>
</view>
<view class="pt-32 pl-30 pr-30">
<view v-if="!topNavShow">
<view class="fs-32 text--w111-333" v-if="categoryList.length">
{{categoryList[navActive].cate_name}}
</view>
<view class="grid-column-4 grid-gap-24rpx mt-24">
<view class="w-154 h-56 rd-30rpx flex-center fs-24 text--w111-333 bg--w111-f5f5f5"
v-for="(item,index) in threeCateList" :key="index"
@tap="threeCateClick(index,item)" :class="index===threeClick?'cate_active':''">
{{item.cate_name}}
</view>
</view>
</view>
<view class="grid-column-5 grid-gap-x-22rpx grid-gap-y-32rpx" v-if="topNavShow">
<view class="flex-col flex-center" v-for="(item,index) in categoryList" :key="index"
@tap="tapNav(index,item)">
<view :class="index == navActive ? 'active_pic' : 'scroll_pic'">
<image :src="item.pic" mode="aspectFill"></image>
</view>
<view class="w-120 h-40 flex-center fs-24 text--w111-333"
:class="index == navActive ? 'active_cate_text' : ''">{{item.cate_name}}</view>
</view>
</view>
<view class="flex-center fs-24 text--w111-999 h-80 mt-32" @tap="closeCateDrawer">
<text>点击收起 <text class="iconfont icon-ic_uparrow pl-4 fs-24"></text> </text>
</view>
</view>
</view>
<view class="mask" v-show="showCateDrawer" @tap="closeCateDrawer"></view>
<base-drawer mode="bottom" :visible="showSku" background-color="transparent" zIndex="3000" mask maskClosable
@close="closeDrawer">
<view>
<view class="bg--w111-fff rd-t-40rpx">
<view class="w-full pt-32">
<view class="px-32 flex">
<image class="w-180 h-180 rd-16rpx" :src="attr.productSelect.image"></image>
<view class="pl-24">
<baseMoney :money="attr.productSelect.price" symbolSize="32" integerSize="48"
decimalSize="32" color="#FF7E00" weight></baseMoney>
<view class="mt-20 fs-24 text--w111-999">库存:{{ attr.productSelect.stock }}</view>
</view>
</view>
</view>
<scroll-view class="px-32" scroll-y="true" style="max-height: 400rpx;">
<view class="item mt-32" v-for="(item, indexw) in attr.productAttr" :key="indexw">
<view class="fs-28">{{ item.attr_name }}</view>
<view class="flex-y-center flex-wrap">
<view class="sku-item" :class="item.index === itemn.attr ? 'active-sku' : ''"
v-for="(itemn, indexn) in item.attr_value" @click="tapAttr(indexw, indexn)"
:key="indexn">
{{ itemn.attr }}
</view>
</view>
</view>
</scroll-view>
<view class="flex-between-center px-32 mt-24">
<text class="fs-28">数量</text>
<view class="flex-y-center">
<view class="jia-btn w-84 h-48 flex-center" @click="CartNumAdd(false)">
<text class="iconfont icon-ic_Reduce fs-24"></text>
</view>
<view class='w-84 h-48 text-center lh-48rpx bg--w111-f5f5f5'>{{ attr.productSelect.cart_num }}</view>
<view class="jia-btn w-84 h-48 flex-center" @click="CartNumAdd(true)">
<text class="iconfont icon-ic_increase fs-24"></text>
</view>
</view>
</view>
<view class="mx-20 pb-box">
<view class="mt-52 h-72 flex-center rd-36px mer-bg fs-26 text--w111-fff" @click="confirmCartAdd">
确定</view>
</view>
</view>
</view>
</base-drawer>
</view>
</template>
<script>
let windowHeight = uni.getWindowInfo().windowHeight;
let sysHeight = uni.getWindowInfo().statusBarHeight;
import {
getCategoryList,
getProductslist,
getAttr,
postCartNum
} from '@/api/store.js';
import {
vcartList,
getCartCounts,
cartDel,
changeCartNum
} from '@/api/order.js';
import productWindow from '../../components/skuSelect';
import cusPreviewImg from '@/components/cusPreviewImg';
import cartList from '@/components/cartList';
import {
mapState,
mapGetters
} from 'vuex';
import {
goShopDetail
} from '@/libs/order.js';
import {
toLogin
} from '@/libs/login.js';
import skuSelect from '@/mixins/skuSelect.js'
import emptyPage from '@/components/emptyPage.vue';
export default {
props: {
level: {
type: Number,
default: 3
},
showType:{
type: Number,
default: 2
},
isFooter:{
type: Boolean,
default: false
}
},
data() {
return {
windowHeight: windowHeight - 50,
showCateDrawer: false,
sysHeight: sysHeight,
categoryList: [],
navActive: 0,
categoryTitle: '',
categoryErList: [],
tabLeft: 0,
isWidth: 0, //每个导航栏占位
tabClick: 0, //导航栏被点击
iSlong: false,
tempArr: [],
loading: false,
loadend: false,
loadTitle: '加载更多',
page: 1,
limit: 10,
cid: 0, //一级分类
sid: 0, //二级分类
tid: 0, //三级分类
isAuto: false, //没有授权的不会自动授权
isShowAuth: false, //是否隐藏授权
attr: {
cartAttr: false,
productAttr: [],
productSelect: {}
},
productAttr: [],
productValue: [],
attrValue: '', //已选属性
storeName: '', //多属性产品名称
id: 0,
cartData: {
cartList: [],
iScart: false
},
totalPrice: 0.00,
lengthCart: 0,
is_vip: 0, //是否是会员
cart_num: 0,
storeInfo: {},
scrollHeight: 0,
threeCateList: [],
threeClick: 0,
topNavShow: true,
selectSku: {},
skuArr: [],
showSku: false,
product_id: "",
keyword: ""
}
},
components: {
productWindow,
cartList,
emptyPage,
cusPreviewImg
},
mixins: [skuSelect],
computed: {
...mapGetters(['isLogin', 'uid', 'cartNum'])
},
mounted() {
this.getAllCategory();
setTimeout(() => {
this.getScrollHeight();
}, 500);
},
methods: {
getScrollHeight() {
let sysH = uni.getWindowInfo().statusBarHeight;
this.scrollHeight = windowHeight - 138 - sysH;
},
getAllCategory() {
let that = this;
getCategoryList().then(res => {
if (!res.data.length) return
let data = res.data;
that.categoryTitle = data[0].cate_name;
that.cid = data[0].id;
that.sid = 0;
that.tid = 0;
that.navActive = 0;
that.tabClick = 0;
that.categoryList = data;
that.categoryErList = res.data[0].children ? res.data[0].children : [];
that.categoryErList.unshift({
cate_name: '全部商品',
id: 0
})
that.threeCateList = res.data[0].children[0].children ? res.data[0].children[0].children : [];
if (this.threeCateList.length) {
this.threeCateList.unshift({
cate_name: '全部商品',
id: 0
})
}
that.page = 1;
that.loadend = false;
that.tempArr = [];
that.productslist();
})
},
// 产品列表
productslist() {
let that = this;
if (that.loadend) return;
if (that.loading) return;
that.loading = true;
that.loadTitle = '';
getProductslist({
page: that.page,
limit: that.limit,
type: 1,
cid: that.cid,
sid: that.sid,
tid: that.tid,
keyword: that.keyword,
is_channel:1
}).then(res => {
let list = res.data,
loadend = list.length < that.limit;
that.tempArr = that.$util.SplitArray(list, that.tempArr);
that.$set(that, 'tempArr', that.tempArr);
that.loading = false;
that.loadend = loadend;
that.loadTitle = loadend ? "没有更多内容啦~" : "加载更多";
that.page = that.page + 1;
}).catch(err => {
that.loading = false;
that.loadTitle = '加载更多'
});
},
tapNav(index, item) {
uni.pageScrollTo({
duration: 0,
scrollTop: 0
})
let list = this.categoryList[index];
this.navActive = index;
this.categoryTitle = list.cate_name;
this.categoryErList = item.children ? item.children : [];
if(this.navActive != 0 && this.categoryErList[0].id != 0){
this.categoryErList.unshift({
cate_name: '全部商品',
id: 0
})
}
this.threeCateList = [];
if (this.categoryErList.length) {
this.threeCateList = item.children[0].children ? item.children[0].children : [];
if (this.threeCateList && !this.haveAll(this.threeCateList)) {
this.threeCateList.unshift({
cate_name: '全部商品',
id: 0
})
}
}
this.tabClick = 0;
this.tabLeft = 0;
this.cid = list.id;
this.sid = 0;
this.tid = 0;
this.page = 1;
this.loadend = false;
this.tempArr = [];
this.productslist();
},
// 导航栏点击
longClick(index, item) {
this.tabClick = index; //设置导航点击了哪一个
this.threeClick = 0;
this.sid = this.categoryErList[index].id;
this.tid = 0;
this.threeCateList = item.children && item.children.length ? item.children : [];
if (this.threeCateList && this.threeCateList.length && !this.haveAll(this.threeCateList)) {
this.threeCateList.unshift({
cate_name: '全部商品',
id: 0
})
}
this.page = 1;
this.loadend = false;
this.tempArr = [];
this.productslist();
},
threeCateClick(index, item) {
this.threeClick = index;
this.tid = item.id;
this.page = 1;
this.loadend = false;
this.tempArr = [];
this.productslist();
},
deepClone(obj) {
let newObj = Array.isArray(obj) ? [] : {}
if (obj && typeof obj === "object") {
for (let key in obj) {
if (obj.hasOwnProperty(key)) {
newObj[key] = (obj && typeof obj[key] === 'object') ? this.deepClone(obj[key]) : obj[key];
}
}
}
return newObj
},
haveAll(arr) {
let cloneMap = this.deepClone(arr),
list = [];
cloneMap.forEach(item => {
list.push(item.id);
})
return list.includes(0) ? true : false
},
// 生成订单;
subOrder() {
let that = this,
list = that.cartData.cartList,
ids = [];
if (list.length) {
list.forEach(item => {
if (item.attrStatus && item.status) {
ids.push(item.id)
}
});
uni.navigateTo({
url: '/pages/goods/order_confirm/index?cartId=' + ids.join(',')
});
that.cartData.iScart = false;
} else {
return that.$util.Tips({
title: '请选择产品'
});
}
},
CartNumAdd(type){
if(type){
this.attr.productSelect.cart_num++;
}else{
if(this.attr.productSelect.cart_num == 1) return
this.attr.productSelect.cart_num--;
}
},
goCartDuo(item) {
if (!this.isLogin) {
toLogin();
} else {
if(item.cart_button == 0){
uni.showToast({
title: '该商品不可加入购物车',
icon: 'none'
})
}else{
this.storeName = item.store_name;
this.product_id = item.id;
this.getAttrs(item.id);
this.$set(this, 'id', item.id);
this.$set(this.attr, 'cartAttr', true);
}
}
},
// 点击默认单属性购物车
goCartDan(item, index) {
if (!this.isLogin) {
toLogin();
} else {
if(item.cart_button == 0){
uni.navigateTo({
url: `/pages/merchant/goodsDetails/index?id=${item.id}`
});
}else{
item.cart_num = item.min_qty ? item.min_qty : 1;
let params = {
num: item.min_qty ? item.min_qty : 1,
product_id: item.id,
is_channel:1,
type: 1,
};
postCartNum(params).then(res=> {
this.$util.Tips({
title: '添加购物车成功',
});
}).catch(err => {
return this.$util.Tips({
title: err
});
});
}
}
},
// 商品详情接口;
getAttrs(id) {
let that = this;
getAttr(id, 0, {is_channel:1}).then(res => {
this.$set(this.attr, 'productAttr', res.data.productAttr);
this.productAttr = res.data.productAttr;
this.$set(this, 'productValue', res.data.productValue);
this.$set(this, 'storeInfo', res.data.storeInfo);
this.DefaultSelect();
this.showSku = true;
})
},
DefaultSelect(){
let productAttr = this.attr.productAttr;
let value = [];
for (var key in this.productValue) {
if (this.productValue[key].stock > 0) {
value = productAttr.length ? key.split(',') : [];
break;
}
}
for (let i = 0; i < productAttr.length; i++) {
this.$set(productAttr[i], 'index', value[i]);
}
let productSelect = this.productValue[value.join(',')];
this.attr.productSelect = {
image: productSelect.image,
price: productSelect.channel_price,
unique: productSelect.unique || '',
suk: productSelect.suk || '默认',
stock: productSelect.stock,
cart_num: 1
};
},
tapAttr: function(indexw, indexn) {
let that = this;
this.$set(this.attr.productAttr[indexw], 'index', this.attr.productAttr[indexw].attr_values[indexn]);
let value = that.getCheckedValue().join(",");
this.attr.productSelect = {
price: this.productValue[value].channel_price,
image: this.productValue[value].image,
stock: this.productValue[value].stock,
unique: this.productValue[value].unique || '',
suk: this.productValue[value].suk || '默认',
cart_num: 1
};
},
getCheckedValue: function() {
let productAttr = this.attr.productAttr;
let value = [];
for (let i = 0; i < productAttr.length; i++) {
for (let j = 0; j < productAttr[i].attr_values.length; j++) {
if (productAttr[i].index === productAttr[i].attr_values[j]) {
value.push(productAttr[i].attr_values[j]);
}
}
}
return value;
},
closeDrawer(){
this.showSku = false;
},
//点击sku图片打开轮播图
showImg(index) {
this.$refs.cusPreviewImg.open(this.selectSku.suk)
},
// 去详情页
goDetail(item) {
uni.navigateTo({
url: `/pages/merchant/goodsDetails/index?id=${item.id}`
});
},
closeCateDrawer() {
this.showCateDrawer = false;
},
openCateDrawer(type) {
this.topNavShow = type;
this.showCateDrawer = true;
},
lower(e) {
this.productslist();
},
scroll(e) {
uni.$emit('scroll');
},
goSearch() {
this.page = 1;
this.loadend = false;
this.tempArr = [];
this.productslist();
},
toggleInput(item,type){
if(type) return
this.$set(item,'showInput',true);
},
inputClick(e,item) {
const o = e.detail.value
const inputRule = /[^\d]/g
this.$nextTick(() => {
item.copy_cart_num = o.replace(inputRule, '');
})
},
confirmCartAdd(){
let data = {
product_id:this.product_id,
num: this.attr.productSelect.cart_num,
type: 1,
uniqueId: this.attr.productSelect.unique,
is_channel:1
};
postCartNum(data).then(res=> {
this.showSku = false;
this.$store.dispatch('indexData/getCartNum')
uni.showToast({
title: '添加购物车成功',
icon: 'none'
})
}).catch(err => {
return this.$util.Tips({
title: err
});
});
}
}
}
</script>
<style lang="scss" scoped>
.scroll_box {
overflow: hidden;
}
.aside_active {
background-color: #fff;
width: 100%;
text-align: center;
color: $primary-merchant;
font-weight: 500;
position: relative;
&::after {
content: '';
width: 6rpx;
height: 48rpx;
background-color: $primary-merchant;
position: absolute;
left: 0;
top: 50%;
transform: translateY(-50%);
}
}
.cate_active {
color: $primary-merchant;
background: $light-primary-merchant;
border: 1rpx solid $primary-merchant;
}
.picture-box{
max-height: 382px;
overflow-y: hidden;
}
.text-primary-con {
color: $primary-merchant;
}
.bg-primary-light {
background:$light-primary-merchant;
}
.pl-30 {
padding-left: 30rpx;
}
.border_e {
border-bottom: 1px solid #eee;
}
.active_pic {
width: 104rpx;
height: 104rpx;
background-color: #fff;
padding: 3rpx;
border-radius: 50%;
border: 3rpx solid $primary-merchant;
image {
width: 100%;
height: 100%;
border-radius: 50%;
}
}
.scroll_pic {
image {
width: 92rpx;
height: 92rpx;
border-radius: 50%;
}
}
.active_cate_text {
background: $primary-merchant;
color: #fff;
border-radius: 20rpx;
margin-top: 8rpx;
}
.white-box{
height: calc(300rpx + env(safe-area-inset-bottom));
}
.bg--w111-484643{
background: linear-gradient(90deg, #484643 0%, #1F1B17 100%);
}
.disabled-btn{
color: #DEDEDE;
}
.sku-item {
height: 56rpx;
line-height: 56rpx;
border: 1px solid #F2F2F2;
font-size: 24rpx;
color: #333;
padding: 0 44rpx;
border-radius: 28rpx;
margin: 24rpx 0 0 16rpx;
background-color: #F2F2F2;
word-break: break-all;
}
.active-sku {
color: $primary-merchant;
background: $light-primary-merchant;
border-color: $primary-merchant;
}
/deep/.brand-tag{
background-color: $primary-merchant;
}
.pb-box{
padding-bottom: calc(20rpx + env(safe-area-inset-bottom));
}
</style>

View File

@@ -0,0 +1,800 @@
<template>
<view>
<view class="flex-col bg--w111-fff" :style="{ height: windowHeight + 'px' }">
<view :style="{paddingTop: sysHeight + 'px'}" class="text--w111-999">
<view class="h-80 px-32 flex-y-center">
<!-- #ifdef MP -->
<view class="w-508 h-58 flex-y-center rd-30rpx bg--w111-f5f5f5 px-32">
<!-- #endif -->
<!-- #ifndef MP -->
<view class="w-full h-58 flex-y-center rd-30rpx bg--w111-f5f5f5 px-32">
<!-- #endif -->
<text class="iconfont icon-ic_search fs-28"></text>
<input v-model="keyword" placeholder="请输入商品名称" @confirm="goSearch" placeholder-class="text--w111-999" class="flex-1 fs-24 pl-18 text--w111-333" />
</view>
</view>
</view>
<view class="scroll_box flex flex-1">
<view class="w-168 h-full bg--w111-f5f5f5">
<scroll-view :scroll-top="0" scroll-y="true" class="h-full">
<view class="w-168 h-96 flex-center fs-26 text--w111-666"
v-for="(item,index) in categoryList":key="index"
:class="index == navActive?'aside_active':''"
@tap="tapNav(index,item)">
{{item.cate_name}}
</view>
<view class="white-box"></view>
</scroll-view>
</view>
<view class="relative w-full h-full">
<view class="flex-1 pl-24 pr-20 abs-lt" v-if="categoryErList.length">
<view class="flex mt-24 mb-16">
<scroll-view scroll-x="true" class="white-nowrap vertical-middle w-464"
show-scrollbar="false">
<view class="inline-block mr-16"
v-for="(item,index) in categoryErList" :key="index"
@tap="longClick(index,item)">
<view
class="w-144 h-56 rd-30rpx bg--w111-f5f5f5 flex-center fs-24 text--w111-333"
:class="index===tabClick?'cate_active':''">{{item.cate_name}}</view>
</view>
</scroll-view>
<view class="w-56 h-56 rd-30rpx bg--w111-f5f5f5 flex-center ml-16"
v-if="categoryErList.length"
@tap="openCateDrawer(false)">
<text class="iconfont icon-ic_downarrow fs-32 text--w111-333"></text>
</view>
</view>
</view>
<view class="h-96" v-if="categoryErList.length"></view>
<view class="px-24">
<scroll-view :scroll-top="0" scroll-y="true" @scrolltolower="lower" @scroll="scroll"
:style="{'height':scrollHeight + 'px'}">
<!-- 大图模板 -->
<view v-if="false">
<view class="mb-24" v-for="(item,index) in tempArr" :key="index"
@tap="goDetail(item)">
<view class="picture-box">
<easy-loadimage
mode="widthFix"
:image-src="item.recommend_image ? item.recommend_image : item.image"
:borderSrc="item.recommend_image ? '' :item.activity_frame.image"
width="100%"
borderRadius="20rpx 20rpx 0 0"></easy-loadimage>
</view>
<view class="bg--w111-fff rd-b-20rpx pt-16 pl-24 pr-24 pb-24">
<view class="w-full line2 fs-28 text--w111-333 lh-40rpx">
<text v-if="item.brand_name" class="brand-tag">{{ item.brand_name }}</text>{{item.store_name}}
</view>
<view class="flex-between-center mt-20">
<view class="flex-y-center flex-wrap flex-1">
<baseMoney :money="item.price" symbolSize="24" integerSize="40" decimalSize="24" color="#FF7E00" weight>
</baseMoney>
</view>
<view
class="w-172 h-58 rd-30rpx mer-bg flex-center fs-24 text--w111-fff relative"
v-if="item.spec_type" @tap.stop="goCartDuo(item)">
<text>{{item.cart_button == 0 ? '立即购买' : '加入购物车'}}</text>
<uni-badge class="badge-style" v-if="item.cart_num > 0" :text="item.cart_num"></uni-badge>
</view>
<view v-if="!item.spec_type && !item.cart_num">
<view
class="flex-center w-48 h-48 rd-30rpx mer-bg text--w111-fff "
@tap.stop="goCartDan(item,index)">
<text class="iconfont icon-ic_ShoppingCart1 fs-30"></text>
</view>
</view>
<view class="flex-y-center" v-if="!item.spec_type && item.cart_num">
<view
class="flex-center w-48 h-48 rd-30rpx bg--w111-f5f5f5 text--w111-333"
:class="{'disabled-btn': item.min_qty && item.cart_num == item.min_qty}"
@tap.stop="ChangeCartNumDan(false,index,item)">
<text class="iconfont icon-ic_Reduce fs-32"></text>
</view>
<view class="fs-30 text--w111-333 px-20" v-if="item.showInput" @tap.stop="toggleInput(item,true)">
<view class="w-48 text-center">{{item.cart_num}}</view>
</view>
<view class="fs-30 text--w111-333 px-20" v-else @tap.stop="toggleInput(item,false)">{{item.cart_num}}</view>
<view class="flex-center w-48 h-48 rd-30rpx mer-bg text--w111-fff"
@tap.stop="CartNumAdd(index,item)">
<text class="iconfont icon-ic_increase fs-32"></text>
</view>
</view>
</view>
</view>
</view>
</view>
<!-- 小图模板 -->
<view v-if="true">
<view class="mb-24 flex justify-between" v-for="(item,index) in tempArr"
:key="index" @tap="goDetail(item)">
<easy-loadimage
mode="aspectFit"
:image-src="item.image"
:borderSrc="item.activity_frame.image"
width="176rpx"
height="176rpx"
borderRadius="16rpx"></easy-loadimage>
<view class="flex-1 flex-col justify-between pl-20">
<view class="w-full">
<view class="line2 w-346 fs-28 text-#333 h-80 lh-40rpx">
<text v-if="item.brand_name" class="brand-tag">{{ item.brand_name }}</text>{{item.store_name}}
</view>
</view>
<view class="flex-between-center">
<view class="flex-y-center flex-wrap flex-1">
<baseMoney :money="item.price" symbolSize="24" integerSize="40" decimalSize="24" color="#FF7E00" weight>
</baseMoney>
</view>
<view class="flex-center w-48 h-48 rd-30rpx mer-bg text--w111-fff"
@tap.stop="goCartDuo(item)" v-if="item.spec_type">
<text class="iconfont icon-ic_ShoppingCart1 fs-30"></text>
</view>
<view v-else>
<view
class="flex-center w-48 h-48 rd-30rpx mer-bg text--w111-fff "
@tap.stop="goCartDan(item,index)">
<text class="iconfont icon-ic_ShoppingCart1 fs-30"></text>
</view>
</view>
<!-- <view class="flex-y-center" v-if="!item.spec_type && item.cart_num">
<view
class="flex-center w-48 h-48 rd-30rpx bg--w111-f5f5f5 text--w111-333"
:class="{'disabled-btn': item.min_qty && item.cart_num == item.min_qty}"
@tap.stop="ChangeCartNumDan(false,index,item)">
<text class="iconfont icon-ic_Reduce fs-32"></text>
</view>
<view class="fs-30 text--w111-333 px-20" v-if="item.showInput" @tap.stop="toggleInput(item,true)">
<view class="w-48 text-center" >{{item.cart_num}}</view>
</view>
<view class="fs-30 text--w111-333 px-20" v-else @tap.stop="toggleInput(item,false)">{{item.cart_num}}</view>
<view class="flex-center w-48 h-48 rd-30rpx mer-bg text--w111-fff"
@tap.stop="CartNumAdd(index,item)">
<text class="iconfont icon-ic_increase fs-32"></text>
</view>
</view> -->
</view>
</view>
</view>
</view>
<view v-if="!tempArr.length && !loading">
<emptyPage title="暂无商品,去看点别的吧~" ></emptyPage>
</view>
<view class="white-box"></view>
</scroll-view>
</view>
</view>
</view>
</view>
<view class="more_box abs-lt w-full bg--w111-fff rd-b-32rpx z-20" v-show="showCateDrawer">
<view :style="{paddingTop: sysHeight + 'px'}">
<view class="h-80 px-32 flex-y-center">
<!-- #ifdef MP -->
<view class="w-508 h-58 flex-y-center rd-30rpx bg--w111-f5f5f5 px-32">
<!-- #endif -->
<!-- #ifndef MP -->
<view class="w-full h-58 flex-y-center rd-30rpx bg--w111-f5f5f5 px-32">
<!-- #endif -->
<text class="iconfont icon-ic_search fs-28"></text>
<text class="fs-24 text--w111-999 pl-18">请输入商品名称</text>
</view>
</view>
</view>
<view class="pt-32 pl-30 pr-30">
<view>
<view class="fs-32 text--w111-333" v-if="categoryErList.length">
{{categoryErList[tabClick].cate_name}}
</view>
<view class="grid-column-4 grid-gap-24rpx mt-24">
<view class="w-154 h-56 rd-30rpx flex-center fs-24 text--w111-333 bg--w111-f5f5f5"
v-for="(item,index) in categoryErList" :key="index" @tap="longClick(index,item)"
:class="index===tabClick?'cate_active':''">
{{item.cate_name}}
</view>
</view>
</view>
<view class="flex-center fs-24 text--w111-999 h-80 mt-32" @tap="closeCateDrawer">
<text>点击收起 <text class="iconfont icon-ic_uparrow fs-24 pl-4"></text> </text>
</view>
</view>
</view>
<view class="mask" v-show="showCateDrawer" @tap="closeCateDrawer"></view>
<base-drawer mode="bottom" :visible="showSku" background-color="transparent" zIndex="3000" mask maskClosable
@close="closeDrawer">
<view>
<view class="bg--w111-fff rd-t-40rpx">
<view class="w-full pt-32">
<view class="px-32 flex">
<image class="w-180 h-180 rd-16rpx" :src="attr.productSelect.image"></image>
<view class="pl-24">
<baseMoney :money="attr.productSelect.price" symbolSize="32" integerSize="48"
decimalSize="32" color="#FF7E00" weight></baseMoney>
<view class="mt-20 fs-24 text--w111-999">库存:{{ attr.productSelect.stock }}</view>
</view>
</view>
</view>
<scroll-view class="px-32" scroll-y="true" style="max-height: 400rpx;">
<view class="item mt-32" v-for="(item, indexw) in attr.productAttr" :key="indexw">
<view class="fs-28">{{ item.attr_name }}</view>
<view class="flex-y-center flex-wrap">
<view class="sku-item" :class="item.index === itemn.attr ? 'active-sku' : ''"
v-for="(itemn, indexn) in item.attr_value" @click="tapAttr(indexw, indexn)"
:key="indexn">
{{ itemn.attr }}
</view>
</view>
</view>
</scroll-view>
<view class="flex-between-center px-32 mt-24">
<text class="fs-28">数量</text>
<view class="flex-y-center">
<view class="jia-btn w-84 h-48 flex-center" @click="CartNumAdd(false)">
<text class="iconfont icon-ic_Reduce fs-24"></text>
</view>
<view class='w-84 h-48 text-center lh-48rpx bg--w111-f5f5f5'>{{ attr.productSelect.cart_num }}</view>
<view class="jia-btn w-84 h-48 flex-center" @click="CartNumAdd(true)">
<text class="iconfont icon-ic_increase fs-24"></text>
</view>
</view>
</view>
<view class="mx-20 pb-box">
<view class="mt-52 h-72 flex-center rd-36px mer-bg fs-26 text--w111-fff" @click="confirmCartAdd">
确定</view>
</view>
</view>
</view>
</base-drawer>
</view>
</template>
<script>
let windowHeight = uni.getWindowInfo().windowHeight;
let sysHeight = uni.getWindowInfo().statusBarHeight;
import {
getCategoryList,
getProductslist,
getAttr,
postCartNum
} from '@/api/store.js';
import {
vcartList,
getCartCounts,
cartDel,
changeCartNum
} from '@/api/order.js';
import productWindow from '../../components/skuSelect';
import cartList from '@/components/cartList';
import {
mapState,
mapGetters
} from 'vuex';
import {
goShopDetail
} from '@/libs/order.js';
import {toLogin} from '@/libs/login.js';
import emptyPage from '@/components/emptyPage.vue';
import cusPreviewImg from '@/components/cusPreviewImg';
export default {
props: {
showType: {
type: Number,
default: 1
},
isFooter:{
type: Boolean,
default: false
}
},
data() {
return {
windowHeight: windowHeight - 50,
showCateDrawer: false,
sysHeight: sysHeight,
categoryList: [],
navActive: 0,
categoryTitle: '',
categoryErList: [],
tabLeft: 0,
isWidth: 0, //每个导航栏占位
tabClick: 0, //导航栏被点击
iSlong: false,
tempArr: [],
loading: false,
loadend: false,
loadTitle: '加载更多',
page: 1,
limit: 10,
cid: 0, //一级分类
sid: 0, //二级分类
tid: 0, //三级分类
isAuto: false, //没有授权的不会自动授权
isShowAuth: false, //是否隐藏授权
attr: {
cartAttr: false,
productAttr: [],
productSelect: {}
},
productAttr: [],
productValue: [],
attrValue: '', //已选属性
storeName: '', //多属性产品名称
id: 0,
cartData: {
cartList: [],
iScart: false
},
totalPrice: 0.00,
lengthCart: 0,
is_vip: 0, //是否是会员
cart_num: 0,
storeInfo: {},
scrollHeight: 0,
threeCateList: [],
threeClick: 0,
topNavShow: true,
selectSku: {},
skuArr: [],
showSku: false,
product_id: "",
keyword: ""
}
},
components: {
productWindow,
cartList,
emptyPage,
cusPreviewImg
},
computed: {
...mapState({
cartNum: state => state.indexData.cartNum
}),
...mapGetters(['isLogin', 'uid', 'cartNum'])
},
mounted() {
this.getAllCategory();
setTimeout(() => {
this.getScrollHeight();
}, 500)
},
methods: {
getScrollHeight() {
let sysH = uni.getWindowInfo().statusBarHeight;
this.scrollHeight = windowHeight - 88 - sysH;
},
getAllCategory() {
let that = this;
getCategoryList().then(res => {
if (!res.data.length) return
res.data.map(item=>{
if(item.children && item.children.length){
item.children.unshift({
id:item.id,
cate_name: '全部商品'
})
}
})
let data = res.data;
that.categoryTitle = data[0].cate_name;
that.cid = data[0].id;
that.sid = 0;
that.tid = 0;
that.navActive = 0;
that.tabClick = 0;
that.categoryList = data;
that.categoryErList = res.data[0].children ? res.data[0].children : [];
that.page = 1;
that.loadend = false;
that.tempArr = [];
that.productslist();
})
},
// 产品列表
productslist() {
let that = this;
if (that.loadend) return;
if (that.loading) return;
that.loading = true;
that.loadTitle = '';
getProductslist({
page: that.page,
limit: that.limit,
type: 1,
cid: that.cid,
sid: that.sid,
tid: that.tid,
keyword: that.keyword,
is_channel:1
}).then(res => {
let list = res.data,
loadend = list.length < that.limit;
that.tempArr = that.$util.SplitArray(list, that.tempArr);
that.$set(that, 'tempArr', that.tempArr);
that.loading = false;
that.loadend = loadend;
that.loadTitle = loadend ? "没有更多内容啦~" : "加载更多";
that.page = that.page + 1;
}).catch(err => {
that.loading = false;
that.loadTitle = '加载更多'
});
},
tapNav(index, item) {
uni.pageScrollTo({
duration: 0,
scrollTop: 0
})
let list = this.categoryList[index];
this.navActive = index;
this.categoryTitle = list.cate_name;
this.categoryErList = item.children ? item.children : [];
this.tabClick = 0;
this.tabLeft = 0;
this.cid = list.id;
this.sid = 0;
this.page = 1;
this.loadend = false;
this.tempArr = [];
this.productslist();
},
// 导航栏点击
longClick(index, item) {
this.tabClick = index; //设置导航点击了哪一个
this.sid = this.categoryErList[index].id;
this.page = 1;
this.loadend = false;
this.tempArr = [];
this.productslist();
},
deepClone(obj) {
let newObj = Array.isArray(obj) ? [] : {}
if (obj && typeof obj === "object") {
for (let key in obj) {
if (obj.hasOwnProperty(key)) {
newObj[key] = (obj && typeof obj[key] === 'object') ? this.deepClone(obj[key]) : obj[key];
}
}
}
return newObj
},
// 生成订单;
subOrder() {
let that = this,
list = that.cartData.cartList,
ids = [];
if (list.length) {
list.forEach(item => {
if (item.attrStatus && item.status) {
ids.push(item.id)
}
});
uni.navigateTo({
url: '/pages/goods/order_confirm/index?cartId=' + ids.join(',')
});
that.cartData.iScart = false;
} else {
return that.$util.Tips({
title: '请选择产品'
});
}
},
CartNumAdd(type){
if(type){
this.attr.productSelect.cart_num++;
}else{
if(this.attr.productSelect.cart_num == 1) return
this.attr.productSelect.cart_num--;
}
},
goCartDuo(item) {
if (!this.isLogin) {
toLogin();
} else {
if(item.cart_button == 0){
uni.showToast({
title: '该商品不可加入购物车',
icon: 'none'
})
}else{
this.storeName = item.store_name;
this.product_id = item.id;
this.getAttrs(item.id);
this.$set(this, 'id', item.id);
this.$set(this.attr, 'cartAttr', true);
}
}
},
// 点击默认单属性购物车
goCartDan(item, index) {
if (!this.isLogin) {
toLogin();
} else {
if(item.cart_button == 0){
uni.navigateTo({
url: `/pages/merchant/goodsDetails/index?id=${item.id}`
});
}else{
item.cart_num = item.min_qty ? item.min_qty : 1;
let params = {
num: item.min_qty ? item.min_qty : 1,
product_id: item.id,
is_channel:1,
type: 1,
};
postCartNum(params).then(res=> {
this.$util.Tips({
title: '添加购物车成功',
});
this.$store.dispatch('indexData/getCartNum')
}).catch(err => {
return this.$util.Tips({
title: err
});
});
}
}
},
// 商品详情接口;
getAttrs(id) {
let that = this;
getAttr(id, 0, {is_channel:1}).then(res => {
this.$set(this.attr, 'productAttr', res.data.productAttr);
this.productAttr = res.data.productAttr;
this.$set(this, 'productValue', res.data.productValue);
this.$set(this, 'storeInfo', res.data.storeInfo);
this.DefaultSelect();
this.showSku = true;
})
},
DefaultSelect(){
let productAttr = this.attr.productAttr;
let value = [];
for (var key in this.productValue) {
if (this.productValue[key].stock > 0) {
value = productAttr.length ? key.split(',') : [];
break;
}
}
for (let i = 0; i < productAttr.length; i++) {
this.$set(productAttr[i], 'index', value[i]);
}
let productSelect = this.productValue[value.join(',')];
this.attr.productSelect = {
image: productSelect.image,
price: productSelect.channel_price,
unique: productSelect.unique || '',
suk: productSelect.suk || '默认',
stock: productSelect.stock,
cart_num: 1
};
},
tapAttr: function(indexw, indexn) {
let that = this;
this.$set(this.attr.productAttr[indexw], 'index', this.attr.productAttr[indexw].attr_values[indexn]);
let value = that.getCheckedValue().join(",");
this.attr.productSelect = {
price: this.productValue[value].channel_price,
image: this.productValue[value].image,
stock: this.productValue[value].stock,
unique: this.productValue[value].unique || '',
suk: this.productValue[value].suk || '默认',
cart_num: 1
};
},
getCheckedValue: function() {
let productAttr = this.attr.productAttr;
let value = [];
for (let i = 0; i < productAttr.length; i++) {
for (let j = 0; j < productAttr[i].attr_values.length; j++) {
if (productAttr[i].index === productAttr[i].attr_values[j]) {
value.push(productAttr[i].attr_values[j]);
}
}
}
return value;
},
closeDrawer(){
this.showSku = false;
},
//点击sku图片打开轮播图
showImg(index) {
this.$refs.cusPreviewImg.open(this.selectSku.suk)
},
// 去详情页
goDetail(item) {
uni.navigateTo({
url: `/pages/merchant/goodsDetails/index?id=${item.id}`
});
},
closeCateDrawer() {
this.showCateDrawer = false;
},
openCateDrawer(type) {
this.topNavShow = type;
this.showCateDrawer = true;
},
lower(e) {
this.productslist();
},
scroll(e) {
uni.$emit('scroll');
},
goSearch() {
this.page = 1;
this.loadend = false;
this.tempArr = [];
this.productslist();
},
toggleInput(item,type){
if(type) return
this.$set(item,'showInput',true);
},
inputClick(e,item) {
const o = e.detail.value
const inputRule = /[^\d]/g
this.$nextTick(() => {
item.copy_cart_num = o.replace(inputRule, '');
})
},
confirmCartAdd(){
let data = {
product_id:this.product_id,
num: this.attr.productSelect.cart_num,
type: 1,
uniqueId: this.attr.productSelect.unique,
is_channel:1
};
postCartNum(data).then(res=> {
this.showSku = false;
this.$store.dispatch('indexData/getCartNum')
uni.showToast({
title: '添加购物车成功',
icon: 'none'
})
}).catch(err => {
return this.$util.Tips({
title: err
});
});
}
}
}
</script>
<style lang="scss" scoped>
.scroll_box {
overflow: hidden;
}
.aside_active {
background-color: #fff;
width: 100%;
text-align: center;
color: $primary-merchant;
font-weight: 500;
position: relative;
&::after {
content: '';
width: 6rpx;
height: 48rpx;
background-color: $primary-merchant;
position: absolute;
left: 0;
top: 50%;
transform: translateY(-50%);
}
}
.cate_active {
color: $primary-merchant;
background: $light-primary-merchant;
border: 1rpx solid $primary-merchant;
}
.picture-box{
max-height: 382px;
overflow-y: hidden;
}
.jianbian {
background: linear-gradient(90deg, #ff7931 0%, #e93323 100%);
}
.text-primary-con {
color: $primary-merchant;
}
.bg-primary-light {
background: $light-primary-merchant;
}
.pl-30 {
padding-left: 30rpx;
}
.con_border {
border: 1px solid $primary-merchant;
}
.border_e {
border: 1px solid #eee;
}
.active_pic {
width: 104rpx;
height: 104rpx;
background-color: #fff;
padding: 3rpx;
border-radius: 50%;
border: 3rpx solid $primary-merchant;
image {
width: 100%;
height: 100%;
border-radius: 50%;
}
}
.scroll_pic {
image {
width: 92rpx;
height: 92rpx;
border-radius: 50%;
}
}
.active_cate_text {
background: $primary-merchant;
color: #fff;
border-radius: 20rpx;
margin-top: 8rpx;
}
.sku-item {
height: 56rpx;
line-height: 56rpx;
border: 1px solid #F2F2F2;
font-size: 24rpx;
color: #333;
padding: 0 44rpx;
border-radius: 28rpx;
margin: 24rpx 0 0 16rpx;
background-color: #F2F2F2;
word-break: break-all;
}
.active-sku {
color: $primary-merchant;
background: $light-primary-merchant;
border-color: $primary-merchant;
}
.w-346 {
width: 346rpx;
}
.badge-style {
position: absolute;
top: -10rpx;
right: -20rpx;
/deep/ .uni-badge--error {
background-color: $primary-merchant !important;
}
.uni-badge {
color: $primary-merchant;
border: 1px solid $primary-merchant;
z-index: 29;
}
}
.bg-gradient-mer{
}
.white-box{
height: calc(300rpx + env(safe-area-inset-bottom));
}
.disabled-btn{
color: #DEDEDE;
}
/deep/.brand-tag{
background-color: $primary-merchant;
}
.pb-box{
padding-bottom: calc(20rpx + env(safe-area-inset-bottom));
}
</style>

Binary file not shown.

After

Width:  |  Height:  |  Size: 853 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 669 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 863 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 766 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 930 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 721 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 615 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 920 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 857 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 334 B

View File

@@ -0,0 +1,371 @@
<template>
<view>
<view class="w-full bg-top relative" :style="{backgroundImage:headerBg}">
<NavBar titleText="个人中心"
textSize="34rpx"
:isScrolling="pageScrollStatus"
:showBack="false"
textColor="#333333"></NavBar>
<view class="pt-40 pl-32 pr-36 flex-between-center">
<view class="flex-y-center">
<image class="w-112 h-112 rd-50-p111-" :src="userInfo.avatar"></image>
<view class="flex-col pl-24">
<text class='fs-32 fw-500 lh-44rpx'>{{userInfo.nickname}}</text>
<view class="flex-y-center">
<text class="fs-24 pr-14">ID:{{userInfo.uid}}</text>
<view class="h-42 flex-center fs-22 pl-16 pr-14 rd-30rpx b-c" @tap="checkIdentity">普通用户
<text class="iconfont icon-ic_rightarrow fs-22"></text>
</view>
</view>
</view>
</view>
<view class="relative">
<image class="w-40 h-40" src="../static/mer_set_icon.png" @tap="intoPage('/pages/users/message_center/index')"></image>
<text v-if="userInfo.service_num" class="number-badge">{{ userInfo.service_num >= 100 ? '99+' : userInfo.service_num }}</text>
</view>
</view>
<view class="flex-between-center relative z-10 money-box">
<view class="flex-y-center">
<text class="fs-26 text--w111-999">余额</text>
<text class="fs-28 text--w111-333 fw-600 Regular pl-8">{{ userInfo.now_money }}</text>
</view>
<view class="flex-y-center">
<text class="fs-26 text--w111-999">消费</text>
<text class="fs-28 text--w111-333 fw-600 Regular pl-8">{{ userInfo.channel_pay_price }}</text>
</view>
<view class="flex-y-center">
<text class="fs-26 text--w111-999">采购节省</text>
<text class="fs-28 text--w111-333 fw-600 Regular pl-8">{{ userInfo.channel_discount_price }}</text>
</view>
</view>
</view>
<view class="check-card flex-between-center px-28" :style="{backgroundImage:merCard}">
<view class='flex-y-center'>
<image src="../static/channel_icon.png" class="w-40 h-40"></image>
<text class="fs-32 lh-44rpx fw-500 text--w111-F0E0C4 pl-12">{{ userInfo.channel_iden_name || '采购商身份' }}</text>
<view class="mer-tag fs-18 flex-center">{{userInfo.channel_discount}}</view>
</view>
<!-- <view class="w-140 h-50 check-btn rd-30rpx flex-center fs-20" @tap="checkIdentity">普通用户
<text class="iconfont icon-ic_rightarrow fs-18"></text> </view> -->
</view>
<view class="px-20">
<view class="w-full bg--w111-fff rd-20rpx mt-20 pt-32">
<view class="flex-between-center px-24">
<text class="fs-30 fw-500 lh-42rpx">订单中心</text>
<view class="flex-y-center" @tap="intoPage('/pages/goods/order_list/index')">
<text class="fs-26 text--w111-999">查看全部</text>
<text class="iconfont icon-ic_rightarrow fs-24"></text>
</view>
</view>
<view class="acea-row section-content">
<view v-for="(item,index) in orderMenu" :key="index" class="item"
@click="intoPage(item.url)">
<view class="icon"><text :class="item.icon" class="iconfont"></text></view>
<view class="">{{ item.title }}</view>
<uni-badge class="uni-badge-left-margin" v-if="item.num > 0" :text="item.num"></uni-badge>
</view>
<view class="w-full h-120 rd-16rpx bg--w111-f5f5f5 mt-32 p-10 flex-between-center" v-if="notPayOrder"
@click="intoPage('/pages/goods/order_list/index?status=0')">
<view class="flex-y-center">
<image :src="notPayOrder.img" class="w-100 h-100 rd-12rpx"></image>
<view class="ml-16">
<view class="fs-24 lh-34rpx text--w111-333 fw-500">等待付款</view>
<view class="fs-22 lh-30rpx text--w111-333 mt-12 flex-y-center">
还剩
<countDown
:is-day="false"
tip-text=" "
day-text=" "
hour-text=":"
minute-text=":"
second-text=" "
:datatime="notPayOrder.stop_time"
bgColor="#F5F5F5"
colors="var(--view-theme)"
dotColor="var(--view-theme)"
@endTime="getMenuData"
></countDown>
订单自动关闭
</view>
</view>
</view>
<view class="w-136 h-56 rd-30rpx flex-center fs-24 fw-500 text-primary-con con_border mr-14">去支付</view>
</view>
</view>
</view>
<view class="w-full bg--w111-fff rd-20rpx mt-20 py-32">
<view class="fs-30 fw-500 lh-42rpx pl-24">我的服务</view>
<view class="mt-40 px-24">
<view class="flex-between-center mer-cell" @tap="intoPage('/pages/users/user_invoice_list/index')">
<view class="flex-y-center">
<image class="w-40 h-40" src="../static/fapiao_icon.png"></image>
<text class="fs-28 lh-40rpx pl-24">发票管理</text>
</view>
<text class="iconfont icon-ic_rightarrow fs-28"></text>
</view>
<view class="flex-between-center mer-cell" @tap="intoPage('/pages/users/user_address_list/index')">
<view class="flex-y-center">
<image class="w-40 h-40" src="../static/address_icon.png"></image>
<text class="fs-28 lh-40rpx pl-24">地址管理</text>
</view>
<text class="iconfont icon-ic_rightarrow fs-28"></text>
</view>
<!-- #ifdef H5 || APP-PLUS -->
<view class="flex-between-center mer-cell" @tap="intoPage('/pages/extension/customer_list/chat')">
<view class="flex-y-center">
<image class="w-40 h-40" src="../static/kefu_icon.png"></image>
<text class="fs-28 lh-40rpx pl-24">联系客服</text>
</view>
<text class="iconfont icon-ic_rightarrow fs-28"></text>
</view>
<!-- #endif -->
<!-- #ifdef MP-WEIXIN -->
<button open-type='contact' class="flex-between-center mer-cell" v-if="routineContact">
<view class="flex-y-center">
<image class="w-40 h-40" src="../static/kefu_icon.png"></image>
<text class="fs-28 lh-40rpx pl-24">联系客服</text>
</view>
<text class="iconfont icon-ic_rightarrow fs-28"></text>
</button>
<view class="flex-between-center mer-cell" @tap="intoPage('/pages/extension/customer_list/chat')" v-else>
<view class="flex-y-center">
<image class="w-40 h-40" src="../static/kefu_icon.png"></image>
<text class="fs-28 lh-40rpx pl-24">联系客服</text>
</view>
<text class="iconfont icon-ic_rightarrow fs-28"></text>
</view>
<!-- #endif -->
</view>
</view>
</view>
<view class='h-200'></view>
<tab-bar></tab-bar>
</view>
</template>
<script>
import NavBar from "@/components/NavBar.vue";
import countDown from '@/components/countDown';
import tabBar from "../components/tabBar/index.vue";
import { checkIdentityApi, getUserInfo } from "@/api/user.js";
import { toLogin } from '@/libs/login.js';
import { mapState, mapGetters } from 'vuex';
import { HTTP_REQUEST_URL } from "@/config/app.js"
export default {
data() {
return {
pageScrollStatus: false,
orderMenu:[
{
icon: 'icon-ic_daifukuan12',
title: '待付款',
url: '/pages/goods/order_list/index?status=0'
},
{
icon: 'icon-ic_daifahuo11',
title: '待发货',
url: '/pages/goods/order_list/index?status=1'
},
{
icon: 'icon-ic_daishouhuo1',
title: '待收货',
url: '/pages/goods/order_list/index?status=2'
},
{
icon: 'icon-ic_daipingjia1',
title: '待评价',
url: '/pages/goods/order_list/index?status=3'
},
{
icon: 'icon-ic_daituikuan1',
title: '售后/退款',
url: '/pages/users/user_return_list/index'
}
],
notPayOrder: false,
userInfo:{}
}
},
components:{ NavBar, countDown, tabBar },
computed:{
...mapGetters({isLogin: 'isLogin'}),
headerBg(){
return 'url('+ HTTP_REQUEST_URL +'/statics/images/activity/mer_user_bg.png'+')'
},
merCard(){
return 'url('+ HTTP_REQUEST_URL +'/statics/images/activity/merchant_user_card.png'+')'
},
routineContact(){
return false
}
},
onPageScroll(object) {
if (object.scrollTop > 40) {
this.pageScrollStatus = true;
} else if (object.scrollTop < 40) {
this.pageScrollStatus = false;
}
uni.$emit('scroll');
},
onLoad() {
this.getInfo();
},
methods: {
getInfo(){
getUserInfo().then((res) => {
this.userInfo = res.data;
this.orderMenu.forEach((item, index) => {
switch (item.title) {
case '待付款':
this.$set(item, 'num', res.data.orderStatusNum.unpaid_count);
break;
case '待发货':
this.$set(item, 'num', res.data.orderStatusNum.unshipped_count);
break;
case '待收货':
this.$set(item, 'num', res.data.orderStatusNum.received_count);
break;
case '待评价':
this.$set(item, 'num', res.data.orderStatusNum.evaluated_count);
break;
case '售后/退款':
this.$set(item, 'num', res.data.orderStatusNum.refunding_count);
break;
}
});
this.$store.commit('UPDATE_USERINFO', res.data);
let identity = res.data.identity;
if(identity != 1 && this.isLogin){
// uni.switchTab({
// url: "/pages/index/index"
// })
}
});
},
checkIdentity(){
checkIdentityApi({identity: 0}).then(res=>{
getUserInfo().then((res) => {
this.$store.commit('UPDATE_USERINFO', res.data);
uni.switchTab({
url: '/pages/user/index'
})
});
}).catch(err=>{
return this.$util.Tips({
title: err
});
})
},
// 查看订单
intoPage(url) {
if (this.isLogin) {
this.$util.JumpPath(url);
} else {
toLogin();
}
},
}
}
</script>
<style scoped lang="scss">
.bg-top{
/* #ifdef H5 */
background-size: 100% 386rpx;
/* #endif */
/* #ifdef MP-WEIXIN || APP-PLUS */
background-size: 100% 466rpx;
/* #endif */
background-repeat: no-repeat;
}
.number-badge {
position: absolute;
top: -8rpx;
right: 0;
min-width: 10rpx;
height: 24rpx;
padding: 0 6rpx;
border: 2rpx solid $primary-merchant;
border-radius: 12rpx;
background-color: #ffffff;
transform: translateX(50%);
font-weight: 500;
font-size: 18rpx;
line-height: 24rpx;
color: $primary-merchant;
}
.check-card{
position: relative;
z-index: 10;
width: 710rpx;
height: 120rpx;
background-size: cover;
border-radius: 22rpx;
margin: -48rpx 20rpx 0;
}
.text--w111-F0E0C4{
color: #F0E0C4;
}
.money-box{
padding: 0 78rpx 76rpx 64rpx;
margin-top: 40rpx;
}
.mer-tag{
width: 60rpx;
height: 30rpx;
background: #FEF0D9;
border-radius: 20rpx;
border: 1rpx solid #FACC7D;
margin-left: 8rpx;
color: #B68229;
}
.check-btn{
// border: 1rpx solid #BFB7A8;
color: #F7F0D4;
}
.section-content {
padding: 48rpx 0 36rpx;
.item {
position: relative;
flex: 1;
text-align: center;
font-size: 26rpx;
line-height: 36rpx;
color: #333333;
.uni-badge-left-margin {
position: absolute;
top: -20rpx;
right: 26rpx;
/deep/ .uni-badge--error {
background-color: $primary-merchant !important;
}
.uni-badge {
color: $primary-merchant;
border: 1px solid $primary-merchant;
z-index: 29;
}
}
}
.icon {
margin-bottom: 18rpx;
}
.iconfont {
font-size: 48rpx;
}
.con_border {
color: $primary-merchant;
border: 1px solid $primary-merchant;
}
}
.mer-cell ~ .mer-cell{
margin-top: 56rpx;
}
.b-c{
border: 1rpx solid #ccc;
}
</style>