初始上传

This commit is contained in:
2026-04-04 17:27:12 +08:00
parent 4d80d28eb4
commit b7e11774ee
11191 changed files with 1588469 additions and 0 deletions

View File

@@ -0,0 +1,256 @@
<template>
<div class="el-row-wrap find-pass">
<ul>
<li>
<div>
<p class="ns-bg-color">1</p>
<p class="ns-text-color">输入手机号</p>
</div>
<span class="line-2 ns-border-color"></span>
</li>
<li id="current2">
<span class="line-1" :class="step >= 2 ? 'ns-border-color' : 'ns-border-color-gray'"></span>
<div>
<p :class="step >= 2 ? 'ns-bg-color' : 'ns-bg-color-gray'">2</p>
<p :class="step >= 2 ? 'ns-text-color' : 'ns-text-color-gray'">验证身份</p>
</div>
<span class="line-2" :class="step >= 2 ? 'ns-border-color' : 'ns-border-color-gray'"></span>
</li>
<li id="current3">
<span class="line-1" :class="step >= 3 ? 'ns-border-color' : 'ns-border-color-gray'"></span>
<div>
<p :class="step >= 3 ? 'ns-bg-color' : 'ns-bg-color-gray'">3</p>
<p :class="step >= 3 ? 'ns-text-color' : 'ns-text-color-gray'">重置密码</p>
</div>
<span class="line-2" :class="step >= 3 ? 'ns-border-color' : 'ns-border-color-gray'"></span>
</li>
<li id="current4">
<span class="line-1" :class="step >= 4 ? 'ns-border-color' : 'ns-border-color-gray'"></span>
<div>
<p :class="step >= 4 ? 'ns-bg-color' : 'ns-bg-color-gray'">4</p>
<p :class="step >= 4 ? 'ns-text-color' : 'ns-text-color-gray'">完成</p>
</div>
</li>
</ul>
<el-row>
<el-col :span="12" :offset="6">
<div class="grid-content bg-purple">
<el-form :model="formData" :rules="rules" ref="ruleForm" class="ns-forget-pass-form">
<div class="ns-forget-pass">
<template v-if="step == 1">
<el-form-item prop="mobile" key="1">
<el-input v-model="formData.mobile" placeholder="请输入注册手机号">
<template slot="prepend">
<i class="el-icon-mobile-phone"></i>
</template>
</el-input>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="nextStep('ruleForm')">下一步</el-button>
</el-form-item>
</template>
<template v-else-if="step == 2">
<el-form-item prop="vercode" key="2">
<el-input v-model="formData.vercode" autocomplete="off" placeholder="请输入验证码" maxlength="4">
<template slot="prepend">
<i class="el-icon-picture-outline"></i>
</template>
<template slot="append">
<img :src="captcha.img" mode class="captcha" @click="getCaptcha" />
</template>
</el-input>
</el-form-item>
<el-form-item prop="dynacode" key="3">
<el-input v-model="formData.dynacode" maxlength="4" autocomplete="off" placeholder="请输入短信动态码">
<template slot="prepend">
<i class="el-icon-mobile"></i>
</template>
<template slot="append">
<div class="dynacode" :class="dynacodeData.seconds == 120 ? 'ns-text-color' : 'ns-text-color-gray'" @click="sendMobileCode('ruleForm')">
{{ dynacodeData.codeText }}
</div>
</template>
</el-input>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="nextStepToSetPass('ruleForm')">下一步</el-button>
</el-form-item>
</template>
<template v-else-if="step == 3">
<el-form-item prop="pass" key="4">
<el-input v-model.trim="formData.pass" type="password" autocomplete="off" placeholder="请输入新的登录密码">
<template slot="prepend">
<i class="el-icon-lock"></i>
</template>
</el-input>
</el-form-item>
<el-form-item prop="repass" key="5">
<el-input v-model.trim="formData.repass" type="password" autocomplete="off" placeholder="请再次输入新密码">
<template slot="prepend">
<i class="el-icon-lock"></i>
</template>
</el-input>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="resetPass('ruleForm')">重置密码</el-button>
</el-form-item>
</template>
<template v-else-if="step == 4">
<span class="ns-reset-success">重置密码成功</span>
<el-form-item>
<router-link to="/auth/login">
<el-button type="primary">重新登录</el-button>
</router-link>
</el-form-item>
</template>
</div>
</el-form>
</div>
</el-col>
</el-row>
</div>
</template>
<script>
import find from '~/assets/js/auth/find.js';
export default {
name: 'find_pass',
layout: 'login',
mixins: [find]
};
</script>
<style lang="scss" scoped>
.el-row-wrap {
width: $width;
margin: 0 auto;
border: 1px solid #e5e5e5;
ul {
margin: 50px auto 0;
width: 1032px;
height: 51px;
li {
position: relative;
float: left;
width: 258px;
height: 51px;
text-align: center;
div p:first-child {
display: inline-block;
width: 28px;
height: 28px;
line-height: 28px;
color: #fff;
border-radius: 28px;
}
div p:nth-child(2) {
margin-top: 10px;
}
.line-1 {
position: absolute;
left: 0;
top: 14px;
display: inline-block;
width: 100px;
border-top: solid 2px;
}
.line-2 {
position: absolute;
right: 0;
top: 14px;
display: inline-block;
width: 100px;
border-top: solid 2px;
}
.ns-bg-color-gray {
background-color: #b7b7b7;
}
.ns-text-color-gray {
color: #898989;
}
.ns-border-color-gray {
border-color: #e5e5e5 !important;
}
}
}
}
.el-form {
box-sizing: border-box;
padding: 80px 0 50px;
.captcha {
vertical-align: top;
max-width: inherit;
max-height: 38px;
line-height: 38px;
cursor: pointer;
}
.dynacode {
cursor: pointer;
}
[class*=' el-icon-'],
[class^='el-icon-'] {
font-size: 16px;
}
.ns-forget-pass {
width: 60%;
margin: 0 auto;
}
button {
width: 100%;
}
.ns-reset-success {
display: inline-block;
font-size: 16px;
text-align: center;
width: 100%;
height: 50px;
line-height: 50px;
}
}
</style>
<style lang="scss">
.find-pass {
.ns-forget-pass-form {
.el-form-item__error {
/* 错误提示信息 */
padding-left: 57px;
}
.el-tabs__active-bar,
.el-tabs__nav-wrap::after {
/* 清除tab标签底部横线 */
height: 0;
}
/* 立即注册 */
.el-form-item__content {
line-height: 20px;
}
}
}
</style>

View File

@@ -0,0 +1,403 @@
<template>
<div class="ns-login-wrap" :style="{ background: backgroundColor }" v-loading="loadingAd" @keypress="keypress">
<div class="el-row-wrap el-row-wrap-login">
<el-row>
<el-col :span="13">
<el-carousel height="460px" class="ns-login-bg" @change="handleChange" v-if="adList.length">
<el-carousel-item v-for="item in adList" :key="item.adv_id">
<el-image :src="$img(item.adv_image)" fit="cover" @click="$util.pushToTab(item.adv_url.url)" />
</el-carousel-item>
</el-carousel>
</el-col>
<el-col :span="11" class="ns-login-form" style="float:right;margin-right:70px">
<div class="grid-content bg-purple">
<el-tabs v-model="activeName" @tab-click="handleClick">
<el-tab-pane label="账号登录" name="first" v-if="registerConfig.login.indexOf('username') != -1">
<el-form v-if="activeName == 'first'" :model="formData" :rules="accountRules" ref="ruleForm">
<el-form-item prop="account">
<el-input v-model="formData.account" placeholder="请输入账号">
<template slot="prepend">
<i class="iconfont icon-zhanghao"></i>
</template>
</el-input>
</el-form-item>
<el-form-item prop="password">
<el-input type="password" v-model="formData.password" autocomplete="off" placeholder="请输入登录密码">
<template slot="prepend">
<i class="iconfont icon-mima"></i>
</template>
</el-input>
</el-form-item>
<el-form-item prop="vercode">
<el-input v-model="formData.vercode" autocomplete="off" placeholder="请输入验证码" maxlength="4">
<template slot="prepend">
<i class="iconfont icon-yanzhengma"></i>
</template>
<template slot="append">
<img :src="captcha.img" mode class="captcha" @click="getCaptcha" />
</template>
</el-input>
</el-form-item>
<el-form-item>
<el-row>
<el-col :span="12">
<el-checkbox v-model="formData.checked">七天自动登录</el-checkbox>
</el-col>
<el-col :span="12" class="ns-forget-pass">
<router-link to="/auth/find" class>忘记密码</router-link>
</el-col>
</el-row>
</el-form-item>
<el-form-item style="margin-bottom: 18px;">
<el-button type="primary" @click="accountLogin('ruleForm')">登录</el-button>
</el-form-item>
<el-form-item>
<el-row>
<el-col :span="24">
<div class="bg-purple-light" style="padding: 0 0 10px 0;" :style="wechatConfigStatus ? 'border-bottom: 1px solid #ebebeb' : ''">
没有账号
<router-link to="/auth/register"><p style="color: #fd274a;">立即注册</p></router-link>
<!-- <i class="iconfont icon-arrow-right"></i> -->
</div>
</el-col>
</el-row>
<el-col :span="18" v-if="wechatConfigStatus">
<div style="margin-left: 100px; margin-top: 20px; position: relative;" class="go-wx-login iconfont icon-weixin-copy" @click="weixinLogin()">
<p style="font-size: 14px; text-indent: 10px; position: absolute;top: 1px;">使用微信扫码登录</p>
</div>
</el-col>
</el-form-item>
</el-form>
</el-tab-pane>
<el-tab-pane label="手机动态码登录" name="second" v-if="registerConfig.login.indexOf('mobile') != -1">
<el-form v-if="activeName == 'second'" :model="formData" :rules="mobileRules" ref="mobileRuleForm" class="ns-login-mobile">
<el-form-item prop="mobile">
<el-input v-model="formData.mobile" placeholder="请输入手机号">
<template slot="prepend">
<i class="iconfont icon-shouji-copy"></i>
</template>
</el-input>
</el-form-item>
<el-form-item prop="vercode">
<el-input v-model="formData.vercode" autocomplete="off" placeholder="请输入验证码" maxlength="4">
<template slot="prepend">
<i class="iconfont icon-yanzhengma"></i>
</template>
<template slot="append">
<img :src="captcha.img" mode class="captcha" @click="getCaptcha" />
</template>
</el-input>
</el-form-item>
<el-form-item prop="dynacode">
<el-input v-model="formData.dynacode" maxlength="4" placeholder="请输入短信动态码">
<template slot="prepend">
<i class="iconfont icon-dongtaima"></i>
</template>
<template slot="append">
<div class="dynacode" :class="dynacodeData.seconds == 120 ? 'ns-text-color' : 'ns-text-color-gray'" @click="sendMobileCode('mobileRuleForm')">
{{ dynacodeData.codeText }}
</div>
</template>
</el-input>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="mobileLogin('mobileRuleForm')">登录</el-button>
</el-form-item>
<el-form-item>
<el-row>
<el-col :span="24">
<div class="bg-purple-light" style="padding: 0 0 10px 0;" :style="wechatConfigStatus ? 'border-bottom: 1px solid #ebebeb' : ''">
<router-link to="/auth/register">立即注册</router-link>
<i class="iconfont icon-arrow-right"></i>
</div>
</el-col>
</el-row>
<el-col :span="18" v-if="wechatConfigStatus">
<div style="margin-left: 100px; margin-top: 20px; position: relative;" class="go-wx-login iconfont icon-weixin-copy" @click="weixinLogin()">
<p style="font-size: 14px; text-indent: 10px; position: absolute;top: 1px;">使用微信扫码登录</p>
</div>
</el-col>
</el-form-item>
</el-form>
</el-tab-pane>
</el-tabs>
</div>
</el-col>
<div class="wx-login" :class="ischecked == true ? 'wx-login-display' : ''">
<p class="wx-login-title">微信扫码登录</p>
<div class="qrcode"><img :src="img" /></div>
<div style="display: flex;">
<p class="iconfont icon-arrowLeft" @click="closeWx()"></p>
<p class="wx-login-footer" @click="closeWx()">使用账号密码登录</p>
</div>
</div>
<div class="wx-login1" :class="ischecked1 == true ? 'wx-login-display1' : ''">
<p class="wx-login-title1">扫码成功</p>
<el-col :span="11" class="ns-login-form ns-login-form2">
<div class="grid-content bg-purple">
<el-form :model="formData" :rules="wechatRules" ref="wechatRuleForm">
<el-form-item prop="mobile">
<el-input v-model="formData.mobile" placeholder="请输入手机号">
<template slot="prepend">
<i class="iconfont icon-shouji-copy"></i>
</template>
</el-input>
</el-form-item>
<el-form-item prop="vercode">
<el-input v-model="formData.vercode" autocomplete="off" placeholder="请输入验证码" maxlength="4">
<template slot="prepend">
<i class="iconfont icon-yanzhengma"></i>
</template>
<template slot="append">
<img :src="captcha.img" mode class="captcha" @click="getCaptcha" />
</template>
</el-input>
</el-form-item>
<el-form-item prop="dynacode">
<el-input v-model="formData.dynacode" maxlength="4" placeholder="请输入短信动态码">
<template slot="prepend">
<i class="iconfont icon-dongtaima"></i>
</template>
<template slot="append">
<div class="dynacode" :class="dynacodeData.seconds == 120 ? 'ns-text-color' : 'ns-text-color-gray'" @click="sendWechatMobileCode('wechatRuleForm')">
{{ dynacodeData.codeText }}
</div>
</template>
</el-input>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="wechatLogin('wechatRuleForm')">确定</el-button>
</el-form-item>
<el-form-item>
<el-row>
<el-col :span="12">
<div class="go-wx-login iconfont" @click="closeWx1()">
<p>使用其他方式登录</p>
</div>
</el-col>
<el-col :span="12">
<div class="bg-purple-light">
<router-link to="/auth/register">立即注册</router-link>
<i class="iconfont icon-arrow-right"></i>
</div>
</el-col>
</el-row>
</el-form-item>
</el-form>
</div>
</el-col>
</div>
</el-row>
</div>
</div>
</template>
<script>
import login from '~/assets/js/auth/login.js';
export default {
name: 'login',
layout: 'login',
mixins: [login]
};
</script>
<style lang="scss" scoped>
.icon-arrowLeft {
line-height: 55px;
font-size: 30px;
margin-right: 10px;
margin-left: 130px;
}
.ns-login-wrap {
width: 100%;
height: 500px;
min-width: $width;
.el-row-wrap-login {
width: 1200px;
margin: 0 auto;
.ns-login-bg {
margin-top: 40px;
}
.ns-login-form {
width: 400px;
margin-left: 50px;
background: #ffffff;
margin-top: 25px;
.el-form {
.captcha {
vertical-align: top;
max-width: inherit;
max-height: 38px;
line-height: 38px;
cursor: pointer;
}
.dynacode {
cursor: pointer;
}
[class*=' el-icon-'],
[class^='el-icon-'] {
font-size: 16px;
}
}
.grid-content {
padding: 10px 20px;
}
.el-form-item__error {
padding-left: 50px;
}
button {
width: 100%;
}
.ns-forget-pass {
text-align: right;
}
i {
font-size: 18px;
}
.bg-purple-light {
display: flex;
justify-content: flex-end;
align-items: center;
i {
width: 16px;
height: 16px;
line-height: 16px;
text-align: center;
border-radius: 50%;
background-color: $base-color;
color: #ffffff;
font-size: 12px;
margin-left: 8px;
}
}
}
.ns-login-form2 {
margin-left: 9px;
}
}
}
.icon-weixin-copy {
color: #09bb07;
font-size: 26px;
p {
font-size: 16px;
color: #000;
display: inline-block;
padding-right: 15px;
}
}
.go-wx-login {
cursor: pointer;
}
.wx-login-display {
display: block !important;
}
.wx-login {
width: 410px;
height: 460px;
background: #fff;
position: absolute;
top: 22px;
right: 90px;
z-index: 10;
display: none;
.wx-login-title {
text-align: center;
margin-top: 30px;
font-weight: 600;
font-size: 16px;
color: #fc183e;
}
img {
width: 200px;
margin: 45px 105px;
}
.wx-login-footer {
margin-top: 15px;
text-align: center;
cursor: pointer;
}
}
.wx-login-display1 {
display: block !important;
}
.wx-login1 {
width: 410px;
height: 460px;
background: #fff;
position: absolute;
top: 22px;
right: 90px;
z-index: 11;
display: none;
.wx-login-title1 {
text-align: center;
margin-top: 30px;
font-weight: 600;
}
.wx-login-footer1 {
margin-top: 15px;
text-align: center;
cursor: pointer;
}
}
</style>
<style lang="scss">
.ns-login-form {
.el-form-item__error {
/* 错误提示信息 */
padding-left: 57px;
}
.el-tabs__active-bar,
.el-tabs__nav-wrap::after {
/* 清除tab标签底部横线 */
height: 0;
}
/* 立即注册 */
.el-form-item__content {
line-height: 20px;
}
}
</style>

View File

@@ -0,0 +1,787 @@
<template>
<div class="register">
<div class="box-card">
<el-tabs v-model="activeName" @tab-click="handleClick">
<el-tab-pane label="用户注册" name="first" v-if="registerConfig.register.indexOf('username') != -1">
<el-form v-if="activeName == 'first'" :model="registerForm" :rules="registerRules" ref="registerRef" label-width="80px" label-position="right" show-message>
<el-form-item label="用户名" prop="username">
<el-input v-model="registerForm.username" placeholder="请输入用户名"></el-input>
</el-form-item>
<el-form-item label="密码" prop="password">
<el-input v-model="registerForm.password" placeholder="请输入密码" type="password"></el-input>
</el-form-item>
<el-form-item label="确认密码" prop="checkPass">
<el-input v-model="registerForm.checkPass" placeholder="请输入确认密码" type="password"></el-input>
</el-form-item>
<el-form-item label="验证码" prop="code">
<el-input v-model="registerForm.code" placeholder="请输入验证码" maxlength="4">
<template slot="append">
<img :src="captcha.img" mode class="captcha" @click="getCode" />
</template>
</el-input>
</el-form-item>
</el-form>
<div class="xy" @click="check">
<div class="xy-wrap">
<div class="iconfont" :class="ischecked ? 'icon-xuanze-duoxuan' : 'icon-xuanze'"></div>
<div class="content">
阅读并同意
<b @click.stop="getAggrement">服务协议</b>
</div>
</div>
<div class="toLogin" @click="toLogin">已有账号立即登录</div>
</div>
<el-button @click="register">立即注册</el-button>
</el-tab-pane>
<el-tab-pane label="手机动态码注册" name="second" v-if="registerConfig.register.indexOf('mobile') != -1">
<el-form v-if="activeName == 'second'" :model="registerForm" :rules="mobileRules" ref="mobileRuleForm">
<el-form-item prop="mobile">
<el-input v-model="registerForm.mobile" placeholder="请输入手机号">
<template slot="prepend">
<i class="iconfont icon-shouji-copy"></i>
</template>
</el-input>
</el-form-item>
<el-form-item prop="vercode">
<el-input v-model="registerForm.vercode" autocomplete="off" placeholder="请输入验证码" maxlength="4">
<template slot="prepend">
<i class="iconfont icon-yanzhengma"></i>
</template>
<template slot="append">
<img :src="captcha.img" mode class="captcha" @click="getCode" />
</template>
</el-input>
</el-form-item>
<el-form-item prop="dynacode">
<el-input v-model="registerForm.dynacode" maxlength="4" placeholder="请输入短信动态码">
<template slot="prepend">
<i class="iconfont icon-dongtaima"></i>
</template>
<template slot="append">
<div class="dynacode" :class="dynacodeData.seconds == 120 ? 'ns-text-color' : 'ns-text-color-gray'" @click="sendMobileCode('mobileRuleForm')">
{{ dynacodeData.codeText }}
</div>
</template>
</el-input>
</el-form-item>
</el-form>
<div class="xy" @click="check">
<div class="xy-wrap">
<div class="iconfont" :class="ischecked ? 'icon-xuanze-duoxuan' : 'icon-xuanze'"></div>
<div class="content">
阅读并同意
<b @click.stop="getAggrement">服务协议</b>
</div>
</div>
<div class="toLogin" @click="toLogin">已有账号立即登录</div>
</div>
<el-button @click="registerMobile">立即注册</el-button>
</el-tab-pane>
</el-tabs>
<el-dialog :title="agreement.title" :visible.sync="aggrementVisible" width="60%" :before-close="aggrementClose" :lock-scroll="false" center>
<div v-html="agreement.content" class="xyContent"></div>
</el-dialog>
</div>
<!-- 浮层区 -->
<div class="floatLayer-wrap" v-show="is_show && reward" :style="{ width: bgWidth, height: bgHeight }">
<div class="reward-wrap">
<img :src="$util.img('public/uniapp/register_reward/register_reward_img.png')" mode="widthFix" class="bg-img-head" />
<img :src="$util.img('public/uniapp/register_reward/register_reward_money.png')" mode="widthFix" class="bg-img-money" />
<img :src="$util.img('public/uniapp/register_reward/register_reward_head.png')" mode="widthFix" class="bg-img" />
<div class="wrap">
<div>
<div class="reward-content">
<div class="reward-item" v-if="reward && reward.point > 0">
<div class="head">积分奖励</div>
<div class="content">
<div class="info">
<div>
<span class="num">{{ reward.point }}</span>
<span class="type">积分</span>
</div>
<div class="desc">用于下单时抵现或兑换商品等</div>
</div>
<div class="tip" @click="closeRewardPopup('point')">立即查看</div>
</div>
</div>
<div class="reward-item" v-if="reward && reward.growth > 0">
<div class="head">成长值</div>
<div class="content">
<div class="info">
<div>
<span class="num">{{ reward.growth }}</span>
<span class="type">成长值</span>
</div>
<div class="desc">用于提升会员等级</div>
</div>
<div class="tip" @click="closeRewardPopup('growth')">立即查看</div>
</div>
</div>
<div class="reward-item" v-if="reward && reward.balance > 0">
<div class="head">红包奖励</div>
<div class="content">
<div class="info">
<div>
<span class="num">{{ reward.balance }}</span>
<span class="type"></span>
</div>
<div class="desc">不可提现下单时可用</div>
</div>
<div class="tip" @click="closeRewardPopup('balance')">立即查看</div>
</div>
</div>
<div class="reward-item" v-if="reward && reward.coupon_list.length > 0">
<div class="head">优惠券奖励</div>
<div class="content" v-for="(item, index) in reward.coupon_list" :key="index">
<div class="info">
<div>
<span class="num coupon-name">{{ item.coupon_name }}</span>
</div>
<div class="desc" v-if="item.at_least > 0">{{ item.at_least }}{{ item.type == 'discount' ? '' + item.discount + '' : '' + item.money }}</div>
<div class="desc" v-else>无门槛{{ item.type == 'discount' ? '' + item.discount + '' : '' + item.money }}</div>
</div>
<div class="tip" @click="closeRewardPopup('coupon')">立即查看</div>
</div>
</div>
</div>
</div>
</div>
<div class="close-btn" @click="closeRewardPopup()"><i class="iconfont icon-guanbi"></i></div>
</div>
</div>
</div>
</template>
<script>
import {getRegisterAgreement, registerConfig, registerMobileCode, getRegisterReward} from '@/api/auth/register';
import {captcha} from '@/api/website';
export default {
name: 'register',
layout: 'login',
components: {},
data() {
var checkPassValidata = (rule, value, callback) => {
if (value === '') {
callback(new Error('请再次输入密码'));
} else if (value !== this.registerForm.password) {
callback(new Error('两次输入密码不一致!'));
} else {
callback();
}
};
let self = this;
var passwordValidata = function (rule, value, callback) {
let regConfig = self.registerConfig;
if (!value) {
return callback(new Error('请输入密码'));
} else {
if (regConfig.pwd_len > 0) {
if (value.length < regConfig.pwd_len) {
return callback(new Error('密码长度不能小于' + regConfig.pwd_len + '位'));
} else {
callback();
}
}
if (regConfig.pwd_complexity != '') {
let passwordErrorMsg = '密码需包含',
reg = '';
if (regConfig.pwd_complexity.indexOf('number') != -1) {
reg += '(?=.*?[0-9])';
passwordErrorMsg += '数字';
} else if (regConfig.pwd_complexity.indexOf('letter') != -1) {
reg += '(?=.*?[a-z])';
passwordErrorMsg += '、小写字母';
} else if (regConfig.pwd_complexity.indexOf('upper_case') != -1) {
reg += '(?=.*?[A-Z])';
passwordErrorMsg += '、大写字母';
} else if (regConfig.pwd_complexity.indexOf('symbol') != -1) {
reg += '(?=.*?[#?!@$%^&*-])';
passwordErrorMsg += '、特殊字符';
} else {
reg += '';
passwordErrorMsg += '';
}
reg = new RegExp(reg);
if (reg.test(value)) {
return callback(new Error(passwordErrorMsg));
} else {
callback();
}
}
}
};
var isMobile = (rule, value, callback) => {
if (!value) {
return callback(new Error('手机号不能为空'));
} else {
if (/^\d{11}$/.test(value)) {
callback();
} else {
callback(new Error('请输入正确的手机号'));
}
}
};
return {
registerForm: {
username: '',
password: '',
checkPass: '',
code: '',
mobile: '',
vercode: '',
dynacode: '',
key: ''
},
registerRules: {
username: [
{
required: true,
message: '请输入用户名',
trigger: 'blur'
}
],
password: [
{
required: true,
validator: passwordValidata,
trigger: 'blur'
}
],
checkPass: [
{
required: true,
validator: checkPassValidata,
trigger: 'blur'
}
],
code: [
{
required: true,
message: '请输入验证码',
trigger: 'blur'
}
]
},
mobileRules: {
mobile: [
{
required: true,
validator: isMobile,
trigger: 'blur'
}
],
vercode: [
{
required: true,
message: '请输入验证码',
trigger: 'blur'
}
],
dynacode: [
{
required: true,
message: '请输入短信动态码',
trigger: 'blur'
}
]
},
dynacodeData: {
seconds: 120,
timer: null,
codeText: '获取动态码',
isSend: false
}, // 动态码
ischecked: false,
agreement: '',
aggrementVisible: false,
captcha: {
// 验证码
id: '',
img: ''
},
registerConfig: {
register: ''
},
activeName: 'first', // tab切换
reward: null,
is_show: false,
bgWidth: '',
bgHeight: ''
};
},
created() {
this.getCode();
this.registerAggrement();
this.getRegisterConfig();
this.getRegisterReward();
if (process.client) {
this.bgWidth = document.documentElement.clientWidth + 'px';
this.bgHeight = document.documentElement.clientHeight + 'px';
}
},
head() {
return {
title: '注册-' + this.$store.state.site.siteInfo.site_name
};
},
methods: {
closeRewardPopup(type) {
this.is_show = false;
switch (type) {
case 'point':
this.$router.push('/member/my_point');
break;
case 'balance':
this.$router.push('/member/account');
break;
case 'growth':
this.$router.push('/member');
break;
case 'coupon':
this.$router.push('/member/coupon');
break;
default:
this.$router.push('/member');
this.is_show = false;
}
},
getRegisterReward() {
getRegisterReward()
.then(res => {
if (res.code >= 0) {
let data = res.data;
if (data.is_use == 1 && (data.value.point > 0 || data.value.balance > 0 || data.value.growth > 0 || data.value.coupon_list.length > 0)) {
this.reward = data.value;
}
}
})
},
sendMobileCode(formName) {
if (this.dynacodeData.seconds != 120) return;
this.$refs[formName].clearValidate('dynacode');
this.$refs[formName].validateField('mobile', valid => {
if (valid) {
return false;
}
});
this.$refs[formName].validateField('vercode', valid => {
if (!valid) {
registerMobileCode({
mobile: this.registerForm.mobile,
captcha_id: this.captcha.id,
captcha_code: this.registerForm.vercode
})
.then(res => {
if (res.code >= 0) {
this.registerForm.key = res.data.key;
if (this.dynacodeData.seconds == 120 && this.dynacodeData.timer == null) {
this.dynacodeData.timer = setInterval(() => {
this.dynacodeData.seconds--;
this.dynacodeData.codeText = this.dynacodeData.seconds + 's后可重新获取';
}, 1000);
}
}
})
.catch(err => {
this.$message.error(err.message);
});
} else {
return false;
}
});
},
handleClick(tab, event) {
},
check() {
this.ischecked = !this.ischecked;
},
toLogin() {
this.$router.push('/auth/login');
},
// 获取注册配置
getRegisterConfig() {
registerConfig().then(res => {
if (res.code >= 0) {
this.registerConfig = res.data.value;
if (this.registerConfig.register == '') {
this.$message({
message: '平台未启用注册',
type: 'warning',
duration: 2000,
onClose: () => {
this.$router.push({name: 'login', params: {third_party: true}});
}
});
} else if (this.registerConfig.register.indexOf('username') != -1) {
this.activeName = 'first';
} else {
this.activeName = 'second';
}
}
});
},
// 账号密码注册
register() {
this.$refs.registerRef.validate(valid => {
if (valid) {
if (!this.ischecked) {
return this.$message({
message: '请先阅读协议并勾选',
type: 'warning'
});
}
var data = {
username: this.registerForm.username.trim(),
password: this.registerForm.password
};
var user_test = /^[A-Za-z0-9]+$/;
if (!user_test.test(data.username)) {
return this.$message({
message: '用户名只能输入数字跟英文',
type: 'warning'
});
}
if (this.captcha.id != '') {
data.captcha_id = this.captcha.id;
data.captcha_code = this.registerForm.code;
}
this.$store
.dispatch('member/register_token', data)
.then(res => {
if (res.code >= 0) {
if (this.reward) {
this.is_show = true;
} else {
this.$router.push('/member');
}
}
})
.catch(err => {
this.$message.error(err.message);
this.getCode();
});
} else {
return false;
}
});
},
// 手机号注册
registerMobile() {
this.$refs.mobileRuleForm.validate(valid => {
if (valid) {
if (!this.ischecked) {
return this.$message({
message: '请先阅读协议并勾选',
type: 'warning'
});
}
var data = {
mobile: this.registerForm.mobile,
key: this.registerForm.key,
code: this.registerForm.dynacode
};
if (this.captcha.id != '') {
data.captcha_id = this.captcha.id;
data.captcha_code = this.registerForm.code;
}
this.$store
.dispatch('member/registerMobile_token', data)
.then(res => {
if (res.code >= 0) {
if (this.reward) {
this.is_show = true;
} else {
this.$router.push('/member');
}
}
})
.catch(err => {
this.$message.error(err.message);
this.getCode();
});
} else {
return false;
}
});
},
aggrementClose() {
this.aggrementVisible = false;
},
// 获取协议
registerAggrement() {
getRegisterAgreement().then(res => {
if (res.code >= 0) {
this.agreement = res.data;
}
});
},
getAggrement() {
this.aggrementVisible = true;
},
// 获取验证码
getCode() {
captcha({
captcha_id: 'this.captcha.id'
})
.then(res => {
if (res.code >= 0) {
this.captcha = res.data;
this.captcha.img = this.captcha.img.replace(/\r\n/g, '');
}
})
.catch(err => {
this.$message.error(err.message);
});
}
}
};
</script>
<style lang="scss" scoped>
.register {
width: 100%;
height: 100%;
display: flex;
justify-content: center;
align-items: center;
margin: 20px 0;
}
.box-card {
width: 500px;
margin: 0 auto;
display: flex;
background-color: #ffffff;
padding: 0 30px 30px 30px;
flex-direction: column;
padding-bottom: 256px;
.register-title {
border-bottom: 1px solid #f1f1f1;
text-align: left;
margin-bottom: 20px;
font-size: 16px;
color: $base-color;
padding: 10px 0;
}
.register-account {
width: 100%;
text-align: center;
}
.code {
width: 80%;
text-align: left;
}
.el-form {
margin: 0 30px;
.captcha {
vertical-align: top;
max-width: inherit;
max-height: 38px;
line-height: 38px;
cursor: pointer;
}
}
.xyContent {
height: 600px;
overflow-y: scroll;
}
.xy {
margin-left: 110px;
display: flex;
justify-content: space-between;
align-items: center;
text-align: left;
margin-right: 30px;
.toLogin {
cursor: pointer;
}
.xy-wrap {
display: flex;
align-items: center;
font-size: $ns-font-size-base;
cursor: pointer;
.iconfont {
display: flex;
align-content: center;
}
.content {
margin-left: 3px;
b {
color: $base-color;
}
}
}
.icon-xuanze-duoxuan {
color: $base-color;
}
}
.el-button {
margin: 20px 0 0 25px;
background-color: $base-color;
color: #ffffff;
width: calc(100% - 60px);
}
}
.floatLayer-wrap {
height: 100%;
width: 100%;
background-color: rgba(0, 0, 0, 0.5);
z-index: 999;
position: absolute;
.reward-wrap {
width: 400px;
height: auto;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
.bg-img {
width: 100%;
will-change: transform;
}
.bg-img-head {
position: absolute;
top: -90px;
width: 100%;
}
.bg-img-money {
position: absolute;
width: 100%;
left: -20px;
top: 80px;
z-index: 10;
}
.wrap {
width: calc(100% - 1px);
height: 100%;
background-color: #ef3030;
margin-top: -40px;
padding-bottom: 30px;
border-bottom-left-radius: 5px;
border-bottom-right-radius: 5px;
& > div {
position: relative;
}
}
.reward-content {
margin: 0 25px 0 25px;
}
.reward-item {
.head {
color: #fff;
text-align: center;
line-height: 1;
margin: 10px 0;
}
.content {
display: flex;
padding: 8px 13px;
background: #fff;
border-radius: 5px;
margin-bottom: 5px;
width: auto;
.info {
flex: 1;
}
.tip {
color: #ff222d;
padding: 5px 0 5px 15px;
width: 70px;
letter-spacing: 1px;
border-left: 1px dashed #e5e5e5;
height: 40px;
line-height: 40px;
}
.num {
font-size: 26px;
color: #ff222d;
font-weight: bolder;
line-height: 1;
}
.coupon-name {
font-size: 19px;
}
.type {
font-size: $ns-font-size-base;
margin-left: 5px;
line-height: 1;
}
.desc {
margin-top: 4px;
color: $base-color;
font-size: $ns-font-size-base;
line-height: 1;
}
}
}
.btn {
position: absolute;
width: calc(100% - 50px);
bottom: 20px;
left: 25px;
.btn-img {
width: 100%;
}
}
}
}
.close-btn {
text-align: center;
margin-top: 20px;
.iconfont {
color: #fff;
font-size: 20px;
}
}
.clear {
content: '';
display: block;
clear: both;
}
</style>

View File

@@ -0,0 +1,44 @@
<template>
<div class="error-wrap">
<img src="@/assets/images/index/closed.png" />
<!-- <i class="iconfont icon404"></i> -->
<h2>{{ '网站已关闭' }}</h2>
</div>
</template>
<script>
import { getSiteStatus } from '@/api/website';
export default {
name: "close",
created() {
this.getSiteStatus();
},
layout: 'empty',
methods:{
getSiteStatus(){
getSiteStatus().then((res) => {
if (res.code == 0) {
this.$router.push('/');
}
})
}
}
}
</script>
<style lang="scss" scoped>
.error-wrap {
text-align: center;
padding: 40px;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
i {
font-size: 60px;
}
h2 {
margin: 0 0 30px;
}
}
</style>

View File

@@ -0,0 +1,129 @@
<template>
<div class="article-wrap">
<el-breadcrumb separator="/" class="path">
<el-breadcrumb-item :to="{ path: '/' }" class="path-home">首页</el-breadcrumb-item>
<el-breadcrumb-item :to="{ path: '/cms/article/list' }">文章列表</el-breadcrumb-item>
<el-breadcrumb-item class="path-help">文章详情</el-breadcrumb-item>
</el-breadcrumb>
<div class="article-detil" v-loading="loading">
<div class="article-info">
<div class="title">{{ info.article_title }}</div>
<div class="flex-wrap">
<div class="time">{{ $util.timeStampTurnTime(info.create_time) }}</div>
<div class="num-wrap" v-if="info.is_show_read_num == 1">
<img :src="$img('public/static/img/read.png')" />
{{ info.initial_read_num + info.read_num }}
</div>
<div class="num-wrap" v-if="info.is_show_dianzan_num == 1">
<img :src="$img('public/static/img/dianzan.png')" />
<span>{{ info.initial_dianzan_num + info.dianzan_num }}</span>
</div>
</div>
</div>
<div class="content" v-html="info.article_content"></div>
</div>
</div>
</template>
<script>
import {mapGetters} from 'vuex';
import {articleDetail} from '@/api/cms/article';
export default {
name: 'article_detail',
data: () => {
return {
info: {},
loading: true
};
},
created() {
this.id = this.$route.query.id;
this.getDetail();
},
computed: {
...mapGetters(['siteInfo'])
},
watch: {
$route(curr) {
this.id = curr.query.id;
this.getDetail();
}
},
methods: {
getDetail() {
articleDetail({
article_id: this.id
}).then(res => {
if (res.data) {
this.info = res.data;
this.loading = false;
window.document.title = `${this.info.article_title} - ${this.siteInfo.site_name}`;
} else {
this.$router.push({
path: '/cms/article/list'
});
}
}).catch(err => {
this.loading = false;
this.$message.error(err.message);
});
}
}
};
</script>
<style lang="scss" scoped>
.article-wrap {
width: $width;
margin: 20px auto;
}
.article-detil {
background-color: #ffffff;
min-height: 300px;
margin: 20px 0;
padding: 10px;
.title {
text-align: center;
font-size: 18px;
margin: 10px 0;
}
.flex-wrap {
display: flex;
justify-content: center;
align-items: center;
margin-bottom: 15px;
.time {
text-align: center;
color: #838383;
}
.num-wrap {
display: flex;
align-items: center;
color: #999;
img {
margin-left: 25px;
width: 16px;
height: 16px;
margin-right: 3px;
margin-bottom: 3px;
}
}
}
.article-info {
margin: 0 43px;
border-bottom: 1px dotted #e9e9e9;
}
.content {
padding-top: 10px;
margin: 0 65px;
}
}
</style>

View File

@@ -0,0 +1,275 @@
<template>
<div class="article-wrap">
<el-breadcrumb separator="/" class="path">
<el-breadcrumb-item :to="{ path: '/' }" class="path-home">首页</el-breadcrumb-item>
<el-breadcrumb-item class="path-help">文章</el-breadcrumb-item>
</el-breadcrumb>
<div class="article" v-loading="loading">
<div class="category-wrap">
<div class="item" :class="{ 'ns-text-color': queryinfo.category_id == 0 }" @click="search(0)">全部</div>
<div class="item" :class="{ 'ns-text-color': queryinfo.category_id == item.category_id }" v-for="item in categoryList" :key="item.category_id" @click="search(item.category_id)">{{ item.category_name }}</div>
</div>
<div class="list-wrap">
<template v-if="articleList.length">
<div class="item" v-for="(item, index) in articleList" :key="item.article_id" @click="toDetail(item.article_id)">
<div class="info">
<div class="title">{{ item.article_title }}</div>
<div class="desc">{{ item.article_abstract }}</div>
<div class="bottom-wrap">
<div class="left" v-if="item.is_show_release_time == 1">
<span>{{ $util.timeStampTurnTime(item.create_time) }}</span>
</div>
<div class="right">
<div v-if="item.is_show_read_num == 1">
<img :src="$img('public/static/img/read.png')" />
{{ item.initial_read_num + item.read_num }}
</div>
<div v-if="item.is_show_dianzan_num == 1">
<img :src="$img('public/static/img/dianzan.png')" />
<span>{{ item.initial_dianzan_num + item.dianzan_num }}</span>
</div>
</div>
</div>
</div>
<div class="img-wrap" v-if="item.cover_img">
<img :src="$img(item.cover_img)" @error="imageError(index)" />
</div>
</div>
</template>
<template v-else>
<div class="empty">暂无文章</div>
</template>
</div>
</div>
<div class="page">
<el-pagination
background
:pager-count="5"
:total="total"
prev-text="上一页"
next-text="下一页"
:current-page.sync="queryinfo.page"
:page-size.sync="queryinfo.page_size"
@size-change="handlePageSizeChange"
@current-change="handleCurrentPageChange"
hide-on-single-page
></el-pagination>
</div>
</div>
</template>
<script>
import {mapGetters} from 'vuex';
import {articleCategoryList, getArticleList} from '@/api/cms/article';
export default {
name: 'article',
components: {},
data: () => {
return {
queryinfo: {
page: 1,
page_size: 10,
category_id: 0
},
categoryList: [],
articleList: [],
total: 0,
loading: true
};
},
head() {
return {
title: '文章列表-' + this.$store.state.site.siteInfo.site_name
};
},
created() {
this.getCategoryList();
this.getList();
},
computed: {
...mapGetters(['defaultArticleImage'])
},
methods: {
toDetail(id) {
this.$router.push({
path: '/cms/article/detail',
query: {id: id}
});
},
getCategoryList() {
articleCategoryList().then(res => {
if (res.code == 0 && res.data) {
this.categoryList = res.data;
}
});
},
search(category_id) {
this.queryinfo.category_id = category_id;
this.getList();
},
getList() {
getArticleList(this.queryinfo).then(res => {
if (res.code == 0 && res.data) {
this.articleList = res.data.list;
this.total = res.data.count;
}
this.loading = false;
}).catch(err => {
this.loading = false;
this.$message.error(err.message);
});
},
handlePageSizeChange(newsize) {
this.queryinfo.page_size = newsize;
this.getList();
},
handleCurrentPageChange(newnum) {
this.queryinfo.page = newnum;
this.getList();
},
imageError(index) {
this.articleList[index].cover_img = '';
}
}
};
</script>
<style lang="scss" scoped>
.article-wrap {
width: $width;
margin: 20px auto;
}
.article {
padding: 20px 0;
min-height: 300px;
display: flex;
.category-wrap {
width: 210px;
min-height: 300px;
background: #ffffff;
flex-shrink: 0;
padding-left: 25px;
padding-right: 10px;
.item {
font-size: 15px;
cursor: pointer;
line-height: 40px;
border-top: 1px solid #f1f1f1;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
height: 40px;
background: #ffffff;
&:hover {
color: $base-color;
}
&:first-child {
border-top: none;
}
}
}
.list-wrap {
padding: 0 20px;
margin-left: 20px;
background-color: #fff;
flex: 1;
.item {
background: #fff;
padding: 20px 0;
cursor: pointer;
border-bottom: 1px solid #eeeeee;
display: flex;
justify-content: space-between;
.info {
width: 100%;
}
.title {
font-weight: 600;
font-size: 20px;
word-break: break-all;
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
overflow: hidden;
&:hover {
color: $base-color;
}
}
.desc {
line-height: 29px;
font-size: 16px;
word-break: break-all;
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
overflow: hidden;
margin-top: 5px;
color: #666;
height: 55px;
}
.bottom-wrap {
display: flex;
margin-top: 15px;
.left {
display: flex;
align-items: center;
color: #eee;
margin-right: 10px;
span {
color: #999;
font-size: 14px;
}
}
.right {
display: flex;
align-items: center;
& > div {
margin-left: 25px;
color: #999;
}
img {
width: 16px;
height: 16px;
margin-right: 3px;
margin-bottom: 3px;
}
}
}
.img-wrap {
display: flex;
margin-left: 15px;
img {
width: 256px;
height: 160px;
border-radius: 4px;
}
}
}
}
.empty {
font-size: 18px;
text-align: center;
line-height: 300px;
}
}
</style>

View File

@@ -0,0 +1,118 @@
<template>
<div class="detail-wrap">
<el-breadcrumb separator="/" class="path">
<el-breadcrumb-item :to="{ path: '/' }" class="path-home">首页</el-breadcrumb-item>
<el-breadcrumb-item :to="{ path: '/cms/help/list' }">帮助列表</el-breadcrumb-item>
<el-breadcrumb-item class="path-help">帮助详情</el-breadcrumb-item>
</el-breadcrumb>
<div class="help-detail" v-loading="loading">
<div class="title" @click="toLink">{{ detail.title }}</div>
<div class="info">
<div class="time">{{ $util.timeStampTurnTime(detail.create_time) }}</div>
</div>
<div class="content" v-html="detail.content"></div>
</div>
</div>
</template>
<script>
import {
mapGetters
} from 'vuex';
import {
helpDetail
} from '@/api/cms/help';
export default {
name: 'help_detail',
components: {},
data: () => {
return {
detail: [],
loading: true
};
},
created() {
this.id = this.$route.query.id;
this.getDetail();
},
computed: {
...mapGetters(['siteInfo'])
},
watch: {
$route(curr) {
this.id = curr.query.id;
this.getDetail();
}
},
methods: {
getDetail() {
helpDetail({
id: this.id
}).then(res => {
if (res.code == 0) {
if (res.data) {
this.loading = false;
this.detail = res.data;
window.document.title = `${this.detail.title} - ${this.siteInfo.site_name}`;
} else {
this.$router.push({
path: '/cms/help/list'
});
}
}
}).catch(err => {
this.loading = false;
this.$message.error(err.message);
});
},
toLink() {
if (this.detail.link_address) {
window.open(this.detail.link_address);
}
}
}
};
</script>
<style lang="scss" scoped>
.detail-wrap {
width: 1210px;
margin: 20px auto;
background-color: #fff;
}
.path {
padding: 15px;
}
.help-detail {
background-color: #ffffff;
padding: 10px;
border-radius: 5px;
margin: 10px 0;
.title {
text-align: center;
font-size: 18px;
margin: 10px 0;
cursor: pointer;
}
.info {
// margin: 0 43px;
border-bottom: 1px dotted #e9e9e9;
.time {
text-align: center;
color: #838383;
margin-bottom: 17px;
}
}
.content {
padding-top: 10px;
// margin: 0 65px;
}
}
</style>

View File

@@ -0,0 +1,195 @@
<template>
<div class="help-wrap">
<el-breadcrumb separator="/" class="path">
<el-breadcrumb-item :to="{ path: '/' }" class="path-home">首页</el-breadcrumb-item>
<el-breadcrumb-item class="path-help">帮助</el-breadcrumb-item>
</el-breadcrumb>
<div class="help" v-loading="loading">
<div class="menu">
<div class="title">帮助列表</div>
<div class="item" v-for="(item, index) in helpList" :key="index">
<div :class="currentId == item.class_id ? 'active item-name' : 'item-name'" @click="menuOther(item.class_id)">{{ item.class_name }}</div>
</div>
</div>
<div class="list-other">
<div class="item-info">
<div class="item" v-for="(item, index) in helpOther.list" :key="index" @click="detail(item.id)">
<div class="item-title">{{ item.title }}</div>
<div class="info">
<div class="time">{{ $util.timeStampTurnTime(item.create_time) }}</div>
</div>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
import {
helpList,
helpOther
} from '@/api/cms/help';
export default {
name: 'help',
components: {},
data: () => {
return {
helpList: [],
helpOther: [],
currentId: 0,
loading: true
};
},
head() {
return {
title: '帮助列表-' + this.$store.state.site.siteInfo.site_name
};
},
created() {
this.getInfo();
},
methods: {
menuOther(id) {
this.currentId = id;
this.getHelpOtherInfo();
},
getInfo() {
helpList().then(res => {
if (res.code == 0 && res.data.length > 0) {
this.currentId = res.data[0].class_id;
this.helpList = res.data;
this.getHelpOtherInfo();
}
this.loading = false;
}).catch(err => {
this.loading = false;
this.$message.error(err.message);
});
},
getHelpOtherInfo() {
helpOther({
class_id: this.currentId
}).then(res => {
if (res.code == 0 && res.data) {
this.helpOther = res.data;
}
}).catch(err => {
this.$message.error(err.message);
});
},
detail(id) {
this.$router.push({
path: '/cms/help/detail',
query: {
id: id
}
});
}
}
};
</script>
<style lang="scss" scoped>
.help-wrap {
background: #ffffff;
width: 1210px;
margin: 20px auto;
.path {
padding: 15px;
}
}
.help {
display: flex;
padding-bottom: 20px;
.menu {
width: 210px;
min-height: 300px;
background: #ffffff;
border: 1px solid #f1f1ff;
flex-shrink: 0;
.title {
padding-left: 16px;
background: #f8f8f8;
font-size: $ns-font-size-base;
height: 40px;
line-height: 40px;
cursor: pointer;
color: #666666;
}
.item-name {
font-size: $ns-font-size-base;
cursor: pointer;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
line-height: 40px;
border-top: 1px solid #f1f1f1;
padding-left: 25px;
padding-right: 10px;
height: 40px;
background: #ffffff;
color: #666666;
&:hover {
color: $base-color;
}
}
.active {
color: $base-color;
}
}
}
.list-other {
margin-left: 20px;
width: 80%;
.item-info {
padding: 10px;
background-color: #ffffff;
height: 300px;
// border: 1px solid #e9e9e9;
.item {
border-bottom: 1px #f1f1f1 solid;
padding: 10px 0;
display: flex;
justify-content: space-between;
&:last-child {
border-bottom: none;
}
&:first-child {
padding-top: 0px;
}
.item-title {
font-size: $ns-font-size-base;
color: #333333;
display: inline-block;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
cursor: pointer;
&:hover {
color: $base-color;
}
}
.info {
padding-left: 5px;
flex-shrink: 0;
}
}
}
}
</style>

View File

@@ -0,0 +1,104 @@
<template>
<div class="notice-wrap">
<el-breadcrumb separator="/" class="path">
<el-breadcrumb-item :to="{ path: '/' }" class="path-home">首页</el-breadcrumb-item>
<el-breadcrumb-item :to="{ path: '/cms/notice/list' }">公告列表</el-breadcrumb-item>
<el-breadcrumb-item class="path-help">公告详情</el-breadcrumb-item>
</el-breadcrumb>
<div class="notice-detil" v-loading="loading">
<div class="notice-info">
<div class="title">{{ info.title }}</div>
<div class="time">{{ $util.timeStampTurnTime(info.create_time) }}</div>
</div>
<div class="content" v-html="info.content"></div>
</div>
</div>
</template>
<script>
import {mapGetters} from 'vuex';
import {noticeDetail} from '@/api/cms/notice';
export default {
name: 'notice_detail',
components: {},
data: () => {
return {
info: {},
loading: true
};
},
created() {
this.id = this.$route.query.id;
this.getDetail();
},
computed: {
...mapGetters(['siteInfo'])
},
watch: {
$route(curr) {
this.id = curr.query.id;
this.getDetail();
}
},
methods: {
getDetail() {
noticeDetail({
id: this.id
}).then(res => {
if (res.data) {
this.info = res.data;
this.loading = false;
window.document.title = `${this.info.title} - ${this.siteInfo.site_name}`;
} else {
this.$router.push({
path: '/cms/notice/list'
});
}
}).catch(err => {
this.loading = false;
this.$message.error(err.message);
});
}
}
};
</script>
<style lang="scss" scoped>
.notice-wrap {
width: $width;
margin: 0 auto 45px;
}
.notice-detil {
background-color: #ffffff;
min-height: 300px;
margin: 10px 0;
padding: 10px;
.title {
text-align: center;
font-size: 18px;
margin: 10px 0;
}
.time {
text-align: center;
color: #838383;
margin-bottom: 17px;
}
.notice-info {
margin: 0 43px;
border-bottom: 1px dotted #e9e9e9;
}
.content {
padding-top: 10px;
margin: 0 65px;
}
}
.path {
padding: 15px 0;
}
</style>

View File

@@ -0,0 +1,210 @@
<template>
<div class="notice-wrap">
<el-breadcrumb separator="/" class="path">
<el-breadcrumb-item :to="{ path: '/' }" class="path-home">首页</el-breadcrumb-item>
<el-breadcrumb-item class="path-help">公告</el-breadcrumb-item>
</el-breadcrumb>
<div class="notice" v-loading="loading">
<div class="menu">
<div class="title">最新公告</div>
<div class="item" v-for="item in noticeList" :key="item.id" @click="toDetail(item.id)">
<div class="item-name">{{ item.title }}</div>
</div>
</div>
<div class="list-wrap">
<div class="notice-title">商城公告</div>
<div class="list" v-for="item in noticeList" :key="item.id" @click="toDetail(item.id)">
<div class="item">{{ item.title }}</div>
<div class="info">
<div class="time">{{ $util.timeStampTurnTime(item.create_time) }}</div>
</div>
</div>
</div>
</div>
<div class="pager">
<el-pagination
background
:pager-count="5"
:total="total"
prev-text="上一页"
next-text="下一页"
:current-page.sync="queryInfo.page"
:page-size.sync="queryInfo.page_size"
@size-change="handlePageSizeChange"
@current-change="handleCurrentPageChange"
hide-on-single-page
></el-pagination>
</div>
</div>
</template>
<script>
import {noticesList} from '@/api/cms/notice';
export default {
name: 'notice',
components: {},
data: () => {
return {
queryInfo: {
page: 1,
page_size: 10,
receiving_type: 'web'
},
noticeList: [],
total: 0,
loading: true
};
},
head() {
return {
title: '公告列表-' + this.$store.state.site.siteInfo.site_name
};
},
created() {
this.getList();
},
methods: {
toDetail(id) {
this.$router.push({
path: '/cms/notice/detail',
query: {id: id}
});
},
getList() {
noticesList(this.queryInfo).then(res => {
if (res.code == 0 && res.data) {
this.noticeList = res.data.list;
this.total = res.data.count;
}
this.loading = false;
}).catch(err => {
this.loading = false;
this.$message.error(err.message);
});
},
handlePageSizeChange(newsize) {
this.queryInfo.page_size = newsize;
this.getList();
},
handleCurrentPageChange(newnum) {
this.queryInfo.page = newnum;
this.getList();
}
}
};
</script>
<style lang="scss" scoped>
.notice-wrap {
width: $width;
margin: 20px auto;
.path {
padding: 15px 0;
}
}
.notice {
padding: 20px 0 45px;
min-height: 300px;
position: relative;
display: flex;
.menu {
width: 210px;
min-height: 300px;
background: #ffffff;
border: 1px solid #f1f1ff;
flex-shrink: 0;
.title {
padding-left: 16px;
background: #f8f8f8;
font-size: $ns-font-size-base;
height: 40px;
cursor: pointer;
color: #666666;
display: flex;
align-items: center;
}
.item-name {
font-size: $ns-font-size-base;
cursor: pointer;
line-height: 40px;
border-top: 1px solid #f1f1f1;
padding-left: 25px;
padding-right: 10px;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
height: 40px;
background: #ffffff;
color: #666666;
&:hover {
color: $base-color;
}
}
.active {
color: $base-color;
}
}
.list-wrap {
padding: 0 40px;
margin-left: 27px;
border: 1px solid #f1f1f1;
width: 100%;
margin-bottom: 10px;
background-color: #fff;
.notice-title {
padding: 37px 0 20px 0;
font-size: 18px;
border-bottom: 1px dotted #e9e9e9;
}
.list {
display: flex;
justify-content: space-between;
align-items: center;
&:last-of-type {
border-bottom: initial;
}
&:nth-child(2) {
margin-top: 10px;
}
.item {
font-size: $ns-font-size-base;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
cursor: pointer;
padding: 3px 0;
&:hover {
color: $base-color;
}
}
.info {
display: flex;
font-size: $ns-font-size-base;
.time {
margin-right: 10px;
}
}
}
}
}
.page {
text-align: center;
}
</style>

View File

@@ -0,0 +1,213 @@
<template>
<div class="ns-brand">
<el-carousel height="400px" v-loading="loadingAd">
<el-carousel-item v-for="item in adList" :key="item.adv_id">
<el-image :src="$img(item.adv_image)" fit="cover" @click="$util.pushToTab(item.adv_url.url)" />
</el-carousel-item>
</el-carousel>
<!-- 品牌列表 -->
<div class="ns-brand-box" v-loading="loading">
<div>
<div class="ns-brand-title-wrap ns-text-align">
<p class="ns-brand-title">品牌专区</p>
<img src="@/assets/images/goods/split.png" alt="" />
<p class="ns-brand-en">Brand zone</p>
</div>
<div class="ns-brand-list" v-if="brandList.length > 0">
<div class="ns-brand-li" v-for="(item, index) in brandList" :key="index" @click="$router.push({ path: '/goods/list', query: { brand_id: item.brand_id } })">
<div class="ns-brand-wrap">
<el-image fit="scale-down" :src="$img(item.image_url)" lazy @error="imageError(index)" />
<p :title="item.brand_name">{{ item.brand_name }}</p>
</div>
</div>
</div>
<div class="empty-wrap" v-if="brandList.length <= 0">
<div class="ns-text-align">暂无更多品牌,去首页看看吧</div>
</div>
<div class="pager">
<el-pagination
background
:pager-count="5"
:total="total"
prev-text="上一页"
next-text="下一页"
:current-page.sync="currentPage"
:page-size.sync="pageSize"
@size-change="handlePageSizeChange"
@current-change="handleCurrentPageChange"
hide-on-single-page
></el-pagination>
</div>
</div>
</div>
</div>
</template>
<script>
import {brandPage} from '@/api/goods/goods';
import {mapGetters} from 'vuex';
import {adList} from '@/api/website';
export default {
name: 'brand',
components: {},
data: () => {
return {
total: 0,
currentPage: 1,
pageSize: 20,
brandList: [],
siteId: 0,
loading: true,
loadingAd: true,
adList: []
};
},
created() {
this.getAdList();
this.getBrandList();
},
computed: {
...mapGetters(['defaultBrandImage', 'siteInfo'])
},
methods: {
handlePageSizeChange(size) {
this.pageSize = size;
this.refresh();
},
handleCurrentPageChange(page) {
this.currentPage = page;
this.refresh();
},
refresh() {
this.loading = true;
this.getBrandList();
},
getBrandList() {
brandPage({
page_size: this.pageSize,
page: this.currentPage,
site_id: this.siteId
}).then(res => {
this.brandList = res.data.list;
this.total = res.data.count;
this.loading = false;
window.document.title = `品牌专区 - ${this.siteInfo.site_name}`;
}).catch(err => {
this.loading = false;
this.$message.error(err.message);
});
},
/**
* 图片加载失败
*/
imageError(index) {
this.brandList[index].image_url = this.defaultBrandImage;
},
getAdList() {
adList({keyword: 'NS_PC_BRAND'}).then(res => {
this.adList = res.data.adv_list;
for (let i = 0; i < this.adList.length; i++) {
if (this.adList[i].adv_url) this.adList[i].adv_url = JSON.parse(this.adList[i].adv_url);
}
this.loadingAd = false;
}).catch(err => {
this.loadingAd = false;
});
}
}
};
</script>
<style lang="scss" scoped>
.ns-text-align {
text-align: center;
}
.ns-brand-box {
width: 100%;
background: #ffffff;
> div {
width: $width;
margin: 0 auto;
}
}
.ns-brand-title-wrap {
padding-top: 54px;
.ns-brand-title {
font-size: 26px;
font-weight: 600;
line-height: 30px;
}
.ns-brand-en {
font-size: 24px;
font-weight: 600;
color: #383838;
opacity: 0.2;
text-transform: uppercase;
letter-spacing: 5px;
line-height: 30px;
}
}
.ns-brand-list {
display: flex;
flex-wrap: wrap;
padding-top: 30px;
.ns-brand-li {
width: 20%;
padding: 8px 6px;
box-sizing: border-box;
.ns-brand-wrap {
width: 100%;
border: 1px solid #f1f1f1;
overflow: hidden;
color: #303133;
padding: 15px;
box-sizing: border-box;
cursor: pointer;
text-align: center;
.el-image {
width: 100%;
height: 120px;
line-height: 120px;
}
p {
font-size: 22px;
color: #383838;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
}
}
}
.empty-wrap {
margin-top: 30px;
}
</style>
<style lang="scss">
.ns-brand {
.el-carousel {
.el-image__inner {
width: auto;
}
}
.el-carousel__arrow--right {
right: 60px;
}
}
</style>

View File

@@ -0,0 +1,133 @@
<template>
<div class="cart" v-loading="loading">
<template v-if="cartList.length || invalidGoods.length">
<nav>
<li>
<el-checkbox v-model="checkAll" @change="allElection"></el-checkbox>
</li>
<li>商品信息</li>
<li>价格</li>
<li>数量</li>
<li>小计</li>
<li>操作</li>
</nav>
<div class="list" v-for="(siteItem, siteIndex) in cartList" :key="siteIndex">
<div class="item">
<!-- <div class="head">
<el-checkbox v-model="siteItem.checked" @change="siteAllElection(siteIndex)"></el-checkbox>
<router-link to="/shop" target="_blank">{{ siteItem.siteName }}</router-link>
<el-tag size="small" v-if="siteItem.cartList[0].is_own == 1">自营</el-tag>
</div> -->
<ul v-for="(item, cartIndex) in siteItem.cartList" :key="cartIndex">
<li>
<el-checkbox v-model="item.checked" @change="singleElection(siteIndex, cartIndex)"></el-checkbox>
</li>
<li class="goods-info-wrap" @click="$util.pushToTab({ path: '/sku/' + item.sku_id })">
<div class="img-wrap">
<img class="img-thumbnail" :src="$img(item.sku_image, { size: 'mid' })" @error="imageError(siteIndex, cartIndex)" />
</div>
<div class="info-wrap">
<h5>{{ item.sku_name }}</h5>
<template v-if="item.sku_spec_format">
<span v-for="(x, i) in item.sku_spec_format" :key="i">
{{ x.spec_name }}{{ x.spec_value_name }} {{ i < item.sku_spec_format.length - 1 ? '' : '' }}
</span>
</template>
</div>
</li>
<li>
<span>{{ item.discount_price }}</span>
</li>
<li>
<el-input-number v-model="item.num" :step="modifyNum" size="mini" :min="item.min_buy>0 ? item.min_buy :1"
:max="item.max_buy > 0 && item.max_buy < item.stock ? item.max_buy : item.stock"
@change="cartNumChange($event, { siteIndex, cartIndex })"/>
</li>
<li>
<strong class="subtotal ns-text-color" v-if="item.discount_price * item.num">{{ $util.filterPrice(item.discount_price * item.num) }}</strong>
<strong class="subtotal ns-text-color" v-else>0</strong>
</li>
<li>
<el-button type="text" @click="deleteCart(siteIndex, cartIndex)">删除</el-button>
</li>
</ul>
</div>
</div>
<div class="lose-list" v-if="invalidGoods.length">
<div class="head">
失效商品
<span class="ns-text-color">{{ invalidGoods.length }}</span>
</div>
<ul v-for="(goodsItem, goodsIndex) in invalidGoods" :key="goodsIndex">
<li>
<el-tag size="small" type="info">失效</el-tag>
</li>
<li class="goods-info-wrap">
<div class="img-wrap">
<img class="img-thumbnail" :src="$img(goodsItem.sku_image, { size: 'mid' })" @error="imageErrorInvalid(goodsIndex)" />
</div>
<div class="info-wrap">
<h5>{{ goodsItem.sku_name }}</h5>
<template v-if="goodsItem.sku_spec_format">
<span v-for="(x, i) in goodsItem.sku_spec_format" :key="i">
{{ x.spec_name }}{{ x.spec_value_name }}{{ i < goodsItem.sku_spec_format.length - 1 ? '' : '' }}
</span>
</template>
</div>
</li>
<li>
<span>{{ goodsItem.discount_price }}</span>
</li>
<li>{{ goodsItem.num }}</li>
<li>
<strong class="subtotal">{{ $util.filterPrice(goodsItem.discount_price * goodsItem.num) }}</strong>
</li>
</ul>
</div>
<footer>
<el-checkbox v-model="checkAll" @change="allElection">全选</el-checkbox>
<ul class="operation">
<li>
<el-button type="text" @click="deleteCartSelected">删除</el-button>
</li>
<li>
<el-button type="text" @click="clearInvalidGoods" v-if="invalidGoods.length!=0">清除失效宝贝</el-button>
</li>
</ul>
<div class="sum-wrap">
<div class="selected-sum">
<span>已选商品</span>
<em class="total-count">{{ totalCount }}</em>
<span></span>
</div>
<div class="price-wrap">
<span>合计不含运费</span>
<strong class="ns-text-color">{{ totalPrice }}</strong>
</div>
<el-button type="primary" v-if="totalCount != 0" @click="settlement">结算</el-button>
<el-button type="info" v-else disabled @click="settlement">结算</el-button>
</div>
</footer>
</template>
<div class="empty-wrap" v-else-if="!loading && (!cartList.length || !invalidGoods.length)">
<img src="~assets/images/goods_empty.png">
<router-link to="/">您的购物车是空的赶快去逛逛挑选商品吧</router-link>
</div>
</div>
</template>
<script>
import cart from '@/assets/js/goods/cart';
export default {
name: 'cart',
mixins: [cart]
};
</script>
<style lang="scss" scoped>
@import '@/assets/css/goods/cart.scss';
</style>

View File

@@ -0,0 +1,226 @@
<template>
<div>
<div class="newCategory" v-loading="loading">
<div class="categoryLink">
<ul id="categoryUl" :class="categoryFixed == true ? 'category-fixed' : ''">
<li v-for="(item, index) in goodsCategory" :key="index" :class="index == clickIndex ? 'selected' : ''" @click="changeCate(index, '#category' + index)">
<a>
<span>{{ item.category_name }}</span>
</a>
</li>
</ul>
</div>
<div class="categoryCon">
<div :id="'category' + index" :ref="'category' + index" class="items" :class="'items-' + index" v-for="(cate1, index) in goodsCategory" :key="index">
<h2>
<router-link :to="{ path: '/goods/list', query: { category_id: cate1.category_id, level: cate1.level } }" target="_blank">{{ cate1.category_name }}</router-link>
</h2>
<dl v-for="(cate2, index) in cate1.child_list" :key="index">
<dt>
<router-link :to="{ path: '/goods/list', query: { category_id: cate2.category_id, level: cate2.level } }" target="_blank">{{ cate2.category_name }}</router-link>
</dt>
<dd>
<router-link v-for="(cate3, index) in cate2.child_list" :key="index" :to="{ path: '/goods/list', query: { category_id: cate3.category_id, level: cate3.level } }" target="_blank">{{ cate3.category_name }}</router-link>
</dd>
</dl>
</div>
</div>
<div class="empty-wrap" v-if="goodsCategory.length <= 0">
<div class="ns-text-align">暂无商品分类</div>
</div>
</div>
</div>
</template>
<script>
import {tree} from '@/api/goods/goodscategory';
export default {
name: 'category',
components: {},
data: () => {
return {
goodsCategory: [],
categoryFixed: false,
clickIndex: 0,
loading: true
};
},
created() {
this.getGoodsCategory();
},
mounted() {
window.addEventListener('scroll', this.handleScroll);
},
methods: {
// 分类列表
getGoodsCategory() {
tree({
level: 3,
template: 2
}).then(res => {
if (res.code == 0) {
this.goodsCategory = res.data;
}
this.loading = false;
}).catch(err => {
this.$message.error(err.message);
this.loading = false;
});
},
// 监听滚动条
handleScroll() {
var scrollTop = window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop;
var offsetTop = document.querySelector('.newCategory').offsetTop;
if (scrollTop > offsetTop) {
this.categoryFixed = true;
} else {
this.categoryFixed = false;
}
var divTopArr = [];
for (let i = 0; i < this.goodsCategory.length; i++) {
var _top = this.$refs['category' + i][0].offsetTop;
divTopArr.push(_top);
var _offset = scrollTop - offsetTop;
if (_offset < divTopArr[divTopArr.length - 1]) {
if (_offset >= divTopArr[i] && _offset < divTopArr[i + 1]) {
this.clickIndex = i;
}
} else {
this.clickIndex = divTopArr.length - 1;
}
}
},
// 点击左侧分类
changeCate(index, obj) {
this.clickIndex = index;
document.querySelector(obj).scrollIntoView(true);
}
},
destroyed() {
// 离开该页面需要移除这个监听的事件,不然会报错
window.removeEventListener('scroll', this.handleScroll);
}
};
</script>
<style lang="scss" scoped>
.newCategory {
width: $width;
margin: 0 auto;
overflow: hidden;
background-color: #fff;
.categoryLink {
padding-top: 10px;
float: left;
position: relative;
width: 210px;
ul {
width: 210px;
padding-top: 20px;
background-color: #ffffff;
li {
width: 200px;
height: 30px;
text-align: left;
background-color: #f5f5f5;
border-radius: 30px;
color: #333;
line-height: 30px;
overflow: hidden;
position: relative;
cursor: pointer;
margin: 0 auto 15px;
&.selected {
background-color: $base-color;
background: -moz-linear-gradient(45deg, $base-color 0%, #ffffff 100%);
background: -webkit-gradient(45deg, color-stop(0%, $base-color), color-stop(100%, #ffffff));
background: -webkit-linear-gradient(45deg, $base-color 0%, #ffffff 100%);
background: -o-linear-gradient(45deg, $base-color 0%, #ffffff 100%);
background: -ms-linear-gradient(45deg, $base-color 0%, #ffffff 100%);
background: linear-gradient(45deg, $base-color 0%, #ffffff 100%);
a {
color: #fff;
}
}
a {
display: block;
margin-left: 30px;
}
}
}
}
.category-fixed {
position: fixed;
top: 0;
z-index: 99;
}
.categoryCon {
float: left;
padding: 0px 0 60px;
overflow: hidden;
width: 990px;
position: relative;
.items {
padding-left: 40px;
h2 {
font-size: 18px;
font-weight: 600;
line-height: 40px;
margin-top: 30px;
border-bottom: 1px solid transparent;
}
dl {
padding: 15px 0 5px;
border-bottom: 1px solid #efefef;
overflow: hidden;
display: flex;
dt {
padding-right: 10px;
width: 100px;
position: relative;
background: #fff;
float: left;
a {
float: left;
max-width: 120px;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
font-weight: 600;
}
}
dd {
a {
color: #666;
float: left;
padding: 0 12px;
margin: 0 0 10px -1px;
border-left: 1px solid #e0e0e0;
white-space: nowrap;
}
}
}
}
}
}
</style>

View File

@@ -0,0 +1,518 @@
<template>
<div class="ns-coupon">
<div class="ns-coupon-info" v-if="adList.length">
<div class="ns-coupon-wrap">
<div class="coupon-name">
<span class="ns-text-color">优惠券中心</span>
<span class="ns-text-color-gray text12">省钱更多领券更多</span>
</div>
<ul class="coupon-type clear-float">
<li>
<i></i>
<span>限时抢券</span>
</li>
<li>
<i></i>
<span>叠加使用</span>
</li>
<li>
<i></i>
<span>种类多样</span>
</li>
</ul>
<el-button @click="myCoupon">我的优惠券</el-button>
</div>
<div class="ns-coupon-img" v-loading="loadingAd">
<el-carousel height="406px">
<el-carousel-item v-for="item in adList" :key="item.adv_id">
<el-image :src="$img(item.adv_image)" fit="cover" @click="$util.pushToTab(item.adv_url.url)" />
</el-carousel-item>
</el-carousel>
</div>
</div>
<el-tabs>
<div v-loading="loading">
<ul class="ns-coupon-list">
<li class="ns-bg-color ns-coupon-li" v-for="(item, index) in couponList" :key="index" :class="item.useState == 2 ? 'no-coupon' : '' ">
<div class="describe">
<template>
<span v-if="!item.discount || item.discount == '0.00'">{{ item.money }}</span>
<span v-else>{{ item.discount }}</span>
</template>
<span>{{ activeName == 'first' ? item.coupon_name : item.platformcoupon_name }}</span>
<span v-if="activeName == 'first'">
{{item.goods_type_name}}
</span>
<template>
<span v-if="item.at_least == '0.00'">无门槛优惠券</span>
<span v-else>{{ item.at_least }}可使用</span>
</template>
<template>
<span class="coupon-wrap-time" v-if="item.validity_type == 0">领取之日起{{ item.fixed_term }}日内有效</span>
<span class="coupon-wrap-time" v-else-if="item.validity_type == 1">有效期至{{ $timeStampTurnTime(item.end_time) }}</span>
<span class="coupon-wrap-time" v-else>长期有效</span>
</template>
</div>
<div class="receive">
<!-- 如果限领数为0 或者 领取数小于最大领取数 -->
<a v-if="item.useState == 0" class="ns-text-color" @click="couponTap(item, index)">
<span>立即领取</span>
</a>
<a v-if="item.useState == 1" class="ns-text-color" @click="couponTap(item, index)">
<span>去使用</span>
</a>
<a v-if="!item.received_type && item.useState == 2" class="ns-text-color">
<span>已抢光</span>
</a>
<a v-if="item.received_type == 'out'" class="ns-text-color">
<span>已抢光</span>
</a>
<a v-if="item.received_type == 'expire'" class="ns-text-color">
<span>已过期</span>
</a>
<a v-if="item.received_type == 'limit'" class="ns-text-color">
<span>已达上限</span>
</a>
</div>
</li>
</ul>
<div class="empty-wrap" v-if="couponList.length <= 0">
<div class="ns-text-align">暂无优惠券</div>
</div>
<div class="pager">
<el-pagination background :pager-count="5" :total="total" prev-text="上一页" next-text="下一页"
:current-page.sync="currentPage" :page-size.sync="pageSize" @size-change="handlePageSizeChange"
@current-change="handleCurrentPageChange" hide-on-single-page></el-pagination>
</div>
</div>
</el-tabs>
</div>
</template>
<script>
import {
couponTypeList,
couponReceive
} from '@/api/coupon';
import {
mapGetters
} from 'vuex';
import {
adList
} from '@/api/website';
export default {
name: 'coupon',
components: {},
data: () => {
return {
couponList: [],
total: 0,
currentPage: 1,
pageSize: 9,
couponBtnSwitch: false,
activeName: 'first',
loading: true,
loadingAd: true,
adList: []
};
},
created() {
if (this.addonIsExit && this.addonIsExit.coupon != 1) {
this.$message({
message: '优惠券插件未安装',
type: 'warning',
duration: 2000,
onClose: () => {
this.$route.push('/');
}
});
} else {
this.getAdList();
this.getCanReceiveCouponQuery();
}
},
computed: {
...mapGetters(['addonIsExit'])
},
watch: {
addonIsExit() {
if (this.addonIsExit.coupon != 1) {
this.$message({
message: '优惠券插件未安装',
type: 'warning',
duration: 2000,
onClose: () => {
this.$route.push('/');
}
});
}
}
},
head() {
return {
title: '领券专区-' + this.$store.state.site.siteInfo.site_name,
meta: [{
name: 'description',
content: this.$store.state.site.siteInfo.seo_description
}, {
name: 'keyword',
content: this.$store.state.site.siteInfo.seo_keywords
}]
}
},
methods: {
getAdList() {
adList({
keyword: 'NS_PC_COUPON'
}).then(res => {
this.adList = res.data.adv_list;
for (let i = 0; i < this.adList.length; i++) {
if (this.adList[i].adv_url) this.adList[i].adv_url = JSON.parse(this.adList[i].adv_url);
}
this.loadingAd = false;
}).catch(err => {
this.loadingAd = false;
});
},
handleClick(tab, event) {
this.loading = true;
// (this.currentPage = 1), this.getCanReceiveCouponQuery();
},
/**
* 我的优惠券
*/
myCoupon() {
this.$util.pushToTab('/member/coupon');
},
/**
* 获取优惠券列表
*/
getCanReceiveCouponQuery() {
couponTypeList({
page: this.currentPage,
page_size: this.pageSize,
activeName: this.activeName
}).then(res => {
this.couponList = res.data.list;
this.total = res.data.count;
this.couponList.forEach(v => {
if (v.count == v.lead_count) v.useState = 2;
else if (v.max_fetch != 0 && v.member_coupon_num && v.member_coupon_num >= v.max_fetch) v.useState = 1;
else v.useState = 0;
if(v.received_type && v.received_type == 'expire'){
v.useState = 2;
}
});
this.loading = false;
}).catch(err => {
this.loading = false;
this.$message.error(err.message);
});
},
handlePageSizeChange(size) {
this.pageSize = size;
this.loading = true;
this.getCanReceiveCouponQuery();
},
handleCurrentPageChange(page) {
this.currentPage = page;
this.loading = true;
this.getCanReceiveCouponQuery();
},
/**
* 点击优惠券
*/
couponTap(item, index) {
if (item.useState == 0) this.receiveCoupon(item, index);
else this.toGoodsList(item);
},
/**
* 领取优惠券
*/
receiveCoupon(item, index) {
if (this.couponBtnSwitch) return;
this.couponBtnSwitch = true;
var data = {
site_id: item.site_id,
activeName: this.activeName
};
data.coupon_type_id = item.coupon_type_id;
couponReceive(data).then(res => {
var data = res.data;
let msg = res.message;
if (res.code == 0) {
msg = '领取成功';
this.$message({
message: msg,
type: 'success'
});
} else {
this.$message({
message: msg,
type: 'warning'
});
}
let list = this.couponList;
if (res.data.is_exist == 1) {
for (let i = 0; i < list.length; i++) {
if (this.activeName == 'first') {
if (list[i].coupon_type_id == item.coupon_type_id) {
list[i].useState = 1;
}
} else {
if (list[i].platformcoupon_type_id == item.platformcoupon_type_id) {
list[i].useState = 1;
}
}
}
} else {
for (let i = 0; i < list.length; i++) {
if (this.activeName == 'first') {
if (list[i].coupon_type_id == item.coupon_type_id) {
list[i].received_type = res.data.type;
list[i].useState = 2;
}
} else {
if (list[i].platformcoupon_type_id == item.platformcoupon_type_id) {
list[i].useState = 2;
}
}
}
}
this.couponBtnSwitch = false;
this.$forceUpdate();
}).catch(err => {
if (err.message == '您尚未登录,请先进行登录') {
this.$router.push('/auth/login');
} else {
this.$message.error(err.message)
}
this.couponBtnSwitch = false;
});
},
/**
* 去购买
*/
toGoodsList(item) {
if (this.activeName == 'first') {
if (item.goods_type != 1) {
this.$router.push({
path: '/goods/list',
query: {
coupon: item.coupon_type_id
}
});
} else {
this.$router.push({
path: '/goods/list',
});
}
} else {
this.$router.push('/goods/list');
}
}
}
};
</script>
<style lang="scss" scoped>
.empty-wrap {
margin-top: 20px;
}
.ns-coupon {
width: $width;
padding: 20px 0;
margin: 0 auto;
box-sizing: border-box;
}
.ns-coupon-info {
background: url(../../assets/images/coupon-bg.png) no-repeat;
background-size: cover;
width: 100%;
height: 450px;
display: flex;
.ns-coupon-wrap {
width: 320px;
padding: 20px;
box-sizing: border-box;
text-align: center;
.coupon-name {
margin: 45px 0 50px;
span:nth-child(1) {
display: block;
line-height: 45px;
font-size: 30px;
}
.ns-text-color-gray {
color: #898989 !important;
}
.text12 {
font-size: 12px;
}
}
.coupon-type {
margin-left: 20px;
li {
float: left;
width: 80px;
height: 100px;
i {
display: block;
width: 50px;
height: 50px;
margin: 8px auto;
}
&:nth-child(1) i {
background: url(../../assets/images/limited_time.png) no-repeat center;
}
&:nth-child(2) i {
background: url(../../assets/images/superposition.png) no-repeat center;
}
&:nth-child(3) i {
background: url(../../assets/images/coupon_type.png) no-repeat center;
}
}
}
.el-button {
width: 200px;
background-color: $base-color;
color: #fff;
margin-top: 70px;
font-size: 18px;
}
}
.ns-coupon-img {
width: 850px;
padding: 20px;
box-sizing: border-box;
img {
width: 100%;
height: 100%;
}
.el-carousel__item:nth-child(2n) {
background-color: #99a9bf;
}
.el-carousel__item:nth-child(2n + 1) {
background-color: #d3dce6;
}
}
}
.el-tabs {
margin-top: 20px;
}
.ns-coupon-list {
display: flex;
flex-wrap: wrap;
padding: 0 20px;
.ns-coupon-li {
background: url(../../assets/images/list_bj.png) no-repeat;
width: 32%;
height: 169px;
margin-bottom: 20px;
margin-right: 2%;
background-size: cover;
&.no-coupon {
background: url(../../assets/images/no_coupon.png) no-repeat !important;
background-color: #e6e6e6 !important;
.describe {
color: #999 !important;
}
.receive {
.ns-text-color {
color: #999 !important;
}
}
}
.describe {
float: left;
width: 250px;
height: inherit;
text-align: center;
color: #fff;
span {
display: block;
}
span:nth-child(1) {
font-size: 40px;
margin-top: 20px;
margin-bottom: 3px;
line-height: 50px;
}
span:nth-child(3),
span:nth-child(4),
span:nth-child(5) {
font-size: 12px;
margin-left: 15px;
line-height: 20px;
}
}
.receive {
float: right;
width: 95px;
height: inherit;
text-align: center;
a {
display: inline-block;
width: 30px;
height: 120px;
line-height: 120px;
padding: 0 5px;
margin-top: 25px;
background-color: #fff;
border-radius: 15px;
cursor: pointer;
box-sizing: border-box;
span {
display: inline-block;
line-height: 20px;
vertical-align: middle;
}
}
}
&:nth-child(3n) {
margin-right: 0;
}
}
}
</style>

View File

@@ -0,0 +1,704 @@
<template>
<div class="goods-container">
<div class="goods-list" v-loading="loading">
<!-- 搜索关键字 -->
<div class="goods-nav" v-if="keyword">
<router-link to="/">首页</router-link>
<span>/</span>
<span class="keyword">{{ keyword }}</span>
</div>
<div class="goods-nav" v-else-if="catewords">
<router-link to="/">首页</router-link>
<span>/</span>
<router-link :to="{ path: '/goods/list', query: $util.handleLink({ category_id: first_index, level: 1, brand_id: filters.brand_id }) }">{{ catewords.split('$_SPLIT_$')[0] }}</router-link>
<span v-if="(filters.category_level == 2 || filters.category_level == 3) && catewords.split('$_SPLIT_$')[1]">/</span>
<span v-if="(filters.category_level == 2 || filters.category_level == 3) && catewords.split('$_SPLIT_$')[1]" class="keyword">{{ catewords.split('$_SPLIT_$')[1] }}</span></div>
<!-- 品牌过滤记录区 -->
<div class="attr_filter" v-if="choosedBrand">
<el-tag type="info" closable @close="closeBrand" effect="plain">
<span v-if="choosedBrand" class="title">品牌</span>
{{ choosedBrand.brand_name }}
</el-tag>
</div>
<div class="goods-screen-wrap">
<div v-if="!keyword" class="goods-screen-item classify-info">
<span class="screen-item-name">分类</span>
<ul class="screen-item-content">
<li :class="{ active: categoryAll.isAllow && (categoryAll.id == 0 || categoryAll.id == filters.category_id) }">
<router-link :to="{ path: '/goods/list', query: $util.handleLink({ category_id: categoryAll.id, level: categoryAll.level, brand_id: filters.brand_id }) }">全部</router-link>
</li>
<li v-for="item in categoryList" :class="{ active: item.category_id == selectCategoryId }">
<router-link :to="{ path: '/goods/list', query: $util.handleLink({ category_id: item.category_id, level: item.level, brand_id: filters.brand_id }) }">{{ item.category_name }}</router-link>
</li>
</ul>
</div>
<!-- 品牌 -->
<div class="brand" v-if="brandList.length > 0">
<div class="table_head">品牌</div>
<div class="table_body" :class="{ 'more' : isShowMoreBrand }">
<!-- <div class="initial">
<span type="info" effect="plain" hit @mouseover="handleChangeInitial('')">所有品牌</span>
<span type="info" effect="plain" hit v-for="item in brandInitialList" :key="item" @mouseover="handleChangeInitial(item)">{{ (item || '').toUpperCase() }}</span>
</div> -->
<el-card v-for="item in brandList" :key="item.id" body-style="padding: 0;height: 100%;" shadow="hover" v-show="currentInitial === '' || item.brand_initial === currentInitial" class="brand-item">
<el-image :src="$img(item.image_url || defaultGoodsImage)" :alt="item.brand_name" :title="item.brand_name" fit="contain" @click="onChooseBrand(item)" />
</el-card>
</div>
<div class="more-wrap" v-if="brandList.length>14" @click="isShowMoreBrand=!isShowMoreBrand">
{{ isShowMoreBrand ? '收起' : '更多' }}
</div>
</div>
<div class="goods-screen-item other-screen-info">
<span class="screen-item-name">筛选</span>
<div class="screen-item-content">
<div class="item" @click="changeSort('')">
<div class="item-name">综合</div>
</div>
<div :class="['item', 'search-arrow', salesArrowDirection]" @click="changeSort('sale_num')">销量</div>
<div :class="['item', 'search-arrow', priceArrowDirection]" @click="changeSort('discount_price')">价格</div>
<div class="item-other">
<el-checkbox label="包邮" v-model="is_free_shipping"></el-checkbox>
</div>
<div class="input-wrap">
<div class="price_range">
<el-input placeholder="最低价格" v-model="filters.min_price"></el-input>
<span></span>
<el-input placeholder="最高价格" v-model="filters.max_price"></el-input>
</div>
<el-button plain size="mini" @click="handlePriceRange">确定</el-button>
</div>
</div>
</div>
</div>
<div class="list-wrap">
<!-- <div class="goods-recommended" v-if="goodsList.length">
<goods-recommend :page-size="goodsList.length < 5 ? 2 : 5" />
</div> -->
<div class="list-right">
<!-- 排序筛选区 -->
<div class="cargo-list" v-if="goodsList.length">
<div class="goods-info">
<div class="item" v-for="(item, index) in goodsList" :key="item.goods_id" @click="$router.push({ path: '/sku/' + item.sku_id })">
<img class="img-wrap" :src="$img(item.goods_image, { size: 'mid' })" @error="item.goods_image = defaultGoodsImage" />
<div class="price-wrap">
<div class="price">
<span></span>
<span>{{ showPrice(item) }}</span>
<div class="price-icon-wrap">
<img v-if="item.member_price && item.member_price == showPrice(item)" :src="$img('public/uniapp/index/VIP.png')" />
<img v-else-if="item.promotion_type == 1" :src="$img('public/uniapp/index/discount.png')" />
</div>
</div>
<div v-if="parseInt(item.market_price)" class="market-price">{{ item.market_price }}</div>
</div>
<div class="goods-name">{{ item.goods_name }}</div>
<div class="other-info">
<span class="sale-num">{{ item.sale_num || 0 }}人付款</span>
<div class="saling">
<div v-if="item.is_free_shipping == 1" class="free-shipping">包邮</div>
<div v-if="item.promotion_type == 1" class="free-shipping">限时折扣</div>
</div>
</div>
</div>
</div>
<div class="pager">
<el-pagination background :pager-count="5" :total="total" prev-text="上一页" next-text="下一页"
:current-page.sync="currentPage" :page-size.sync="pageSize"
@size-change="handlePageSizeChange"
@current-change="handleCurrentPageChange" hide-on-single-page></el-pagination>
</div>
</div>
<div class="empty" v-else-if="!loading">
<img src="~assets/images/goods_empty.png" />
<span>没有找到您想要的商品换个条件试试吧</span>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
import BreadCrumbs from '@/components/BreadCrumbs';
import GoodsRecommend from '@/components/GoodsRecommend';
import list from '@/assets/js/goods/list';
export default {
name: 'list',
components: {
BreadCrumbs,
GoodsRecommend
},
mixins: [list]
};
</script>
<style lang="scss" scoped>
.goods-container {
width: 100%;
background-color: #f9f9f9;
}
.goods-list {
width: $width;
margin: 0 auto;
}
%flex-center {
display: flex;
align-items: center;
}
.padd-10 {
padding: 0 10px;
}
.goods-nav {
padding: 15px 0 0 0 !important;
span,
.nuxt-link-active {
color: #666;
}
.keyword {
color: $base-color;
}
}
.goods-screen-wrap {
margin-top: 20px;
background-color: #fff;
.goods-screen-item {
display: flex;
align-items: center;
padding: 0 20px;
box-sizing: border-box;
.screen-item-name {
width: 42px;
margin-right: 35px;
font-size: 14px;
color: #999;
}
.screen-item-content {
flex: 1;
display: flex;
align-items: center;
height: 100%;
border-bottom: 1px dashed #ebeff3;
padding: 10px 0;
flex-wrap: wrap;
}
&:last-of-type .screen-item-content {
border-bottom: none;
}
}
.classify-info {
.screen-item-content > li {
padding-right: 30px;
a {
font-size: 14px;
color: #4a4a4a;
}
&:last-of-type {
padding-right: 0;
}
&.active a,
& a:hover {
color: $base-color;
}
}
}
.other-screen-info {
.screen-item-content > div {
cursor: pointer;
margin-right: 40px;
&:last-of-type {
margin-right: 0;
}
}
.input-wrap {
@extend %flex-center;
.price_range {
@extend %flex-center;
& > span {
overflow: hidden;
margin: 0 5px;
width: 10px;
}
.el-input__inner {
border: none;
width: 90px;
height: 28px;
background-color: #f3f5f7;
border-radius: 6px;
}
}
.el-button {
margin-left: 12px;
width: 56px;
height: 28px;
border-radius: 6px;
&.is-plain:focus,
&.is-plain:hover {
border-color: $base-color;
color: $base-color;
}
}
}
.search-arrow {
position: relative;
&::after,
&::before {
content: '';
position: absolute;
right: -12px;
border: 5px solid transparent;
}
&::after {
top: 1px;
border-bottom-color: #999;
}
&::before {
border-top-color: #999;
bottom: 2px;
}
&.arrow-down::before {
border-top-color: $base-color;
}
&.arrow-up::after {
border-bottom-color: $base-color;
}
}
.item-other {
.el-checkbox__inner {
&:hover {
border-color: $base-color;
}
}
.el-checkbox__input.is-checked .el-checkbox__inner,
.el-checkbox__input.is-indeterminate .el-checkbox__inner {
background-color: $base-color;
border-color: $base-color;
}
.el-checkbox__input.is-checked + .el-checkbox__label {
color: $base-color;
}
}
}
}
.search_bread {
display: inline-block;
font-size: 14px;
margin: 0px auto;
width: 100%;
padding: 10px;
p {
float: left;
}
li {
float: left;
padding: 0 10px;
}
.active a {
color: #ff547b !important;
}
}
.selected_border {
border: 1px solid $base-color;
}
.attr_filter {
margin-top: 10px;
.el-tag {
margin-right: 5px;
margin-bottom: 10px;
border-radius: 0;
.title {
color: $base-color;
font-size: 15px;
}
}
}
.category {
margin: 0 auto 10px auto;
border: 1px solid #eeeeee;
}
.brand {
border-bottom: 1px solid #eeeeee;
display: flex;
flex-direction: row;
padding: 10px 20px 10px;
&:last-child {
border-bottom: none;
}
.table_head {
color: #999;
margin-right: 15px;
width: 60px;
}
.table_body {
display: flex;
flex-direction: row;
flex-wrap: wrap;
flex: 1;
height: 105px;
overflow: hidden;
&.more {
height: 170px;
overflow-y: auto;
}
.initial {
margin: 5px auto 10px 10px;
span {
border: 0;
margin: 0;
padding: 5px 10px;
border-radius: 0;
&:hover {
background-color: $base-color;
color: #ffffff;
}
}
}
.brand-item {
margin-right: 10px;
margin-bottom: 10px;
}
.el-card {
width: 125px;
height: 45px;
&:hover {
border: 1px solid $base-color;
cursor: pointer;
}
}
span {
margin: auto 25px;
}
}
.table_op {
margin-top: 5px;
margin-right: 5px;
}
.more-wrap {
cursor: pointer;
margin-left: 15px;
}
.el-image {
width: 100%;
height: 100%;
}
}
.list-wrap {
overflow: hidden;
}
.goods-recommended {
width: 200px;
background-color: #fff;
float: left;
margin-right: 10px;
}
.sort {
display: flex;
align-items: center;
.item {
display: flex;
align-items: center;
padding: 5px 15px;
border: 1px solid #f1f1f1;
border-left: none;
cursor: pointer;
&:hover {
background: $base-color;
color: #fff;
}
}
.item-other {
display: flex;
align-items: center;
padding: 5px 15px;
border: 1px solid #f1f1f1;
border-left: none;
cursor: pointer;
}
.input-wrap {
display: flex;
align-items: center;
.price_range {
margin-left: 60px;
}
span {
padding-left: 10px;
}
.el-input {
width: 150px;
margin-left: 10px;
}
.el-button {
margin: 0 17px;
}
}
> div:first-child {
border-left: 1px solid #f1f1f1;
}
}
.cargo-list {
padding-bottom: 40px;
}
.goods-info {
margin-top: 20px;
display: flex;
flex-wrap: wrap;
.item {
width: 228px;
margin: 0 17px 18px 0;
padding: 18px;
position: relative;
background-color: #fff;
box-sizing: border-box;
&:nth-child(5n + 5) {
margin-right: 0;
}
.img-wrap {
width: 192px;
height: 192px;
cursor: pointer;
}
.goods-name {
margin-top: 5px;
overflow: hidden;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 2;
word-break: break-all;
cursor: pointer;
line-height: 1.4;
&:hover {
color: $base-color;
}
}
.other-info {
margin-top: 12px;
display: flex;
align-items: center;
justify-content: space-between;
}
.price-wrap {
margin-top: 10px;
display: flex;
align-items: center;
.price {
display: flex;
align-items: center;
color: $base-color;
& > span {
font-weight: bold;
line-height: 1;
}
span:nth-child(1) {
font-size: 12px;
}
span:nth-child(2) {
font-size: 16px;
}
}
.market-price {
color: #838383;
text-decoration: line-through;
margin-left: 10px;
line-height: 1;
}
}
.sale-num {
display: flex;
color: #999999;
font-size: $ns-font-size-sm;
p {
color: #4759a8;
}
}
.shop_name {
padding: 0 10px;
display: flex;
color: #838383;
}
.saling {
display: flex;
font-size: $ns-font-size-sm;
line-height: 1;
.free-shipping {
background: $base-color;
color: #ffffff;
padding: 3px 4px;
border-radius: 2px;
margin-right: 5px;
}
.promotion-type {
color: $base-color;
border: 1px solid $base-color;
display: flex;
align-items: center;
padding: 1px 3px;
}
}
.item-bottom {
display: flex;
margin-top: 5px;
.collection {
flex: 1;
border: 1px solid #e9e9e9;
border-right: none;
border-left: none;
height: 40px;
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
}
.cart {
flex: 2;
border: 1px solid #e9e9e9;
border-right: none;
height: 40px;
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
}
}
}
}
.price-icon-wrap {
display: inline-block;
max-width: 35px;
margin-left: 3px;
line-height: 1;
padding-bottom: 3px;
img {
max-width: 100%;
}
}
.empty {
padding: 50px 0 60px;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
box-sizing: border-box;
img {
width: 400px;
height: 244px;
}
span {
font-size: 14px;
color: #4a4a4a;
}
}
.pager {
text-align: center;
margin-top: 30px;
}
.el-pagination.is-background .el-pager li:not(.disabled).active {
background-color: $base-color;
}
.el-pagination.is-background .el-pager li:not(.disabled):hover {
color: $base-color;
}
</style>

View File

@@ -0,0 +1,187 @@
<template>
<div>
<!-- 首页固定区 -->
<div class="index-wrap" :style="{ background: backgroundColor }" v-if="adList.length">
<div class="index">
<div class="banner">
<el-carousel height="500px" arrow="never" v-loading="loadingAd" @change="handleChange">
<el-carousel-item v-for="item in adList" :key="item.adv_id">
<el-image :src="$img(item.adv_image)" fit="cover" @click="$util.pushToTab(item.adv_url.url)" />
</el-carousel-item>
</el-carousel>
</div>
</div>
</div>
<div class="index-content-wrap">
<!-- 首页中部广告位 -->
<ul class="adv-middle" v-if="adCenterList.length">
<li class="adv-middle-item" v-for="(item,index) in adCenterList" :key="index">
<el-image :src="$img(item.adv_image)" fit="cover" @error="adCenterImageError(index)" @click="$util.pushToTab(item.adv_url.url)" />
</li>
</ul>
<!-- 广告 -->
<div class="content-div" v-if="adLeftList.length > 0 || adRightList.length > 0">
<div class="ad-wrap">
<div class="ad-big" v-if="adLeftList.length > 0">
<div class="ad-big-img" v-for="(item, index) in adLeftList" :key="index">
<el-image :src="$img(item.adv_image)" fit="cover" @error="adLeftImageError(index)" @click="$util.pushToTab(item.adv_url.url)" />
</div>
</div>
<div class="ad-small" v-if="adRightList.length > 0">
<div class="ad-small-img" v-for="(item, index) in adRightList" :key="index">
<el-image :src="$img(item.adv_image)" fit="cover" @error="adRightImageError(index)" @click="$util.pushToTab(item.adv_url.url)" />
</div>
</div>
</div>
</div>
<!-- 限时秒杀 -->
<div class="content-div" v-if="addonIsExit.seckill == 1 && listData.length > 0">
<div class="seckill-wrap">
<div class="seckill-time">
<div class="seckill-time-left">
<i class="iconfont icon-miaosha1 ns-text-color"></i>
<span class="seckill-time-title ns-text-color">限时秒杀</span>
<span>{{ seckillText }}</span>
<count-down class="count-down" v-on:start_callback="countDownS_cb()" v-on:end_callback="countDownE_cb()"
:currentTime="seckillTimeMachine.currentTime" :startTime="seckillTimeMachine.startTime"
:endTime="seckillTimeMachine.endTime" :dayTxt="''" :hourTxt="''" :minutesTxt="''"
:secondsTxt="''">
</count-down>
</div>
<div class="seckill-time-right" @click="$router.push('/promotion/seckill')">
<span>更多商品</span>
<i class="iconfont icon-arrow-right"></i>
</div>
</div>
<div class="seckill-content">
<vue-seamless-scroll :data="listData" :class-option="optionLeft" class="seamless-warp2">
<ul class="item" :style="{ width: 250 * listData.length + 'px' }">
<li v-for="(item, index) in listData" :key="index">
<div class="seckill-goods" @click="$router.push('/promotion/seckill/' + item.id)">
<div class="seckill-goods-img">
<img :src="$img(item.goods_image.split(',')[0], { size: 'mid' })" @error="imageError(index)" />
</div>
<p>{{ item.goods_name }}</p>
<div class="seckill-price-wrap">
<p class="ns-text-color">
<span>{{ item.seckill_price }}</span>
</p>
<p class="primary-price">{{ item.price }}</p>
</div>
</div>
</li>
</ul>
</vue-seamless-scroll>
</div>
</div>
</div>
<!-- 楼层区 -->
<div class="content-div">
<div class="floor">
<div v-for="(item, index) in floorList" :key="index" class="floor_item">
<floor-style-1 v-if="item.block_name == 'floor-style-1'" :data="item" />
<floor-style-2 v-if="item.block_name == 'floor-style-2'" :data="item" />
<floor-style-3 v-if="item.block_name == 'floor-style-3'" :data="item" />
<floor-style-4 v-if="item.block_name == 'floor-style-4'" :data="item" />
</div>
</div>
</div>
<!-- 浮层区 -->
<div class="floatLayer-wrap" v-if="floatLayer.is_show_type">
<div class="floatLayer">
<div class="img-wrap">
<img :src="$img(floatLayer.img_url)" @click="$util.pushToTab(floatLayer.link.url)" />
</div>
<i class="el-icon-circle-close" @click="closeFloat"></i>
</div>
</div>
<!-- 悬浮搜索 -->
<div class="fixed-box" :style="{ display: isShow ? 'block' : 'none' }">
<ns-header-mid />
</div>
</div>
</div>
</template>
<script>
import {
websiteInfo
} from "@/api/website"
import floorStyle1 from './index/components/floor-style-1.vue';
import floorStyle2 from './index/components/floor-style-2.vue';
import floorStyle3 from './index/components/floor-style-3.vue';
import floorStyle4 from './index/components/floor-style-4.vue';
import index from '@/assets/js/index/index.js';
import NsHeaderMid from "@/layouts/components/NsHeaderMid.vue"
import vueSeamlessScroll from 'vue-seamless-scroll'
import {
mapGetters
} from 'vuex';
export default {
components: {
floorStyle1,
floorStyle2,
floorStyle3,
floorStyle4,
NsHeaderMid,
vueSeamlessScroll
},
computed: {
...mapGetters(['siteInfo'])
},
mixins: [index],
async fetch({store, params}) {
await store.dispatch('site/siteInfo')
},
head() {
return {
title: this.siteInfo.seo_title ? this.siteInfo.seo_title : this.siteInfo.site_title,
meta: [{
name: 'description',
content: this.siteInfo.seo_description
},
{
name: 'keyword',
content: this.siteInfo.seo_keywords
},
{
property: 'og:title',
content: this.siteInfo.seo_title
},
{
property: 'og:description',
content: this.siteInfo.seo_description
},
{
property: 'og:type',
content: 'website'
}
]
}
}
}
</script>
<style lang="scss" scoped>
@import '@/assets/css/index/index.scss';
.count-down {
span {
display: inline-block;
width: 22px;
height: 22px;
line-height: 22px;
text-align: center;
background: #383838;
color: #ffffff;
border-radius: 2px;
}
}
</style>

View File

@@ -0,0 +1,178 @@
<template>
<div class="floor-style-1">
<div class="head-wrap" v-if="data.value.title.value.text">
<h2 @click="$util.pushToTab(data.value.title.value.link.url)" :style="{ color: data.value.title.value.color }">{{ data.value.title.value.text }}</h2>
</div>
<div class="body-wrap">
<div class="left-wrap" v-if="data.value.leftImg.value.url">
<img :src="$img(data.value.leftImg.value.url)" @click="$util.pushToTab(data.value.leftImg.value.link.url)" />
</div>
<ul class="goods-list">
<li v-for="(item, index) in data.value.goodsList.value.list" :key="index" :title="item.goods_name" @click="goSku(item.sku_id)">
<div class="img-wrap">
<img alt="商品图片" :src="$img(item.goods_image.split(',')[0], {size: 'mid'})" @error="imageError(index)" />
</div>
<h3>{{ item.goods_name }}</h3>
<p class="desc">{{ item.introduction }}</p>
<p class="price">
<span class="num">{{ item.discount_price }}</span>
<del v-show="Number.parseInt(item.market_price)">{{ item.market_price }}</del>
</p>
</li>
</ul>
</div>
<div class="bottom-wrap" v-if="data.value.bottomImg.value.url">
<img :src="$img(data.value.bottomImg.value.url)" @click="$util.pushToTab(data.value.bottomImg.value.link.url)" />
</div>
</div>
</template>
<script>
import {mapGetters} from 'vuex';
export default {
name: 'floor-style-1',
props: {
data: {
type: Object
}
},
data() {
return {};
},
created() {
},
computed: {
...mapGetters(['defaultGoodsImage'])
},
methods: {
goSku(skuId) {
this.$util.pushToTab('/sku/' + skuId);
},
imageError(index) {
this.data.value.goodsList.value.list[index].goods_image = this.defaultGoodsImage;
}
}
};
</script>
<style lang="scss" scoped>
.floor-style-1 {
.head-wrap h2 {
line-height: 30px;
color: #333;
padding: 10px;
font-size: 18px;
cursor: pointer;
width: 95%;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.body-wrap {
display: flex;
.left-wrap {
width: 234px;
height: 614px;
cursor: pointer;
transition: all 0.2s linear;
&:hover {
z-index: 2;
-webkit-box-shadow: 0 15px 30px rgba(0, 0, 0, 0.1);
box-shadow: 0 15px 30px rgba(0, 0, 0, 0.1);
-webkit-transform: translate3d(0, -2px, 0);
transform: translate3d(0, -2px, 0);
}
img {
max-width: 100%;
cursor: pointer;
}
}
.goods-list {
flex: 1;
display: flex;
flex-wrap: wrap;
li {
width: 23%;
margin-left: 19px;
margin-bottom: 20px;
background: #fff;
cursor: pointer;
padding: 10px 0;
transition: all 0.2s linear;
&:hover {
z-index: 2;
-webkit-box-shadow: 0 15px 30px rgba(0, 0, 0, 0.1);
box-shadow: 0 15px 30px rgba(0, 0, 0, 0.1);
-webkit-transform: translate3d(0, -2px, 0);
transform: translate3d(0, -2px, 0);
}
.img-wrap {
width: 160px;
height: 160px;
margin: 0 auto 18px;
text-align: center;
line-height: 160px;
img {
max-width: 100%;
max-height: 100%;
}
}
h3 {
font-size: 14px;
text-align: center;
text-overflow: ellipsis;
white-space: nowrap;
overflow: hidden;
margin: 5px 15px;
font-weight: normal;
}
.desc {
margin: 0 30px 10px;
height: 20px;
font-size: 12px;
color: #b0b0b0;
text-align: center;
text-overflow: ellipsis;
white-space: nowrap;
overflow: hidden;
}
.price {
margin: 0 10px 14px;
text-align: center;
color: $base-color;
del {
margin-left: 0.5em;
color: #b0b0b0;
}
}
}
}
}
.bottom-wrap {
margin-top: 10px;
width: $width;
height: 118px;
cursor: pointer;
overflow: hidden;
img {
max-width: 100%;
}
}
}
</style>

View File

@@ -0,0 +1,171 @@
<template>
<div class="floor-style-2">
<div class="head-wrap" v-if="data.value.title.value.text">
<h2 @click="$util.pushToTab(data.value.title.value.link.url)" :style="{textAlign: data.value.title.value.textAlign, color: data.value.title.value.color }">{{ data.value.title.value.text }}</h2>
<p @click="$util.pushToTab(data.value.subTitle.value.link.url)" :style="{ color: data.value.subTitle.value.color }" v-if="data.value.subTitle.value.text">{{ data.value.subTitle.value.text }}</p>
</div>
<div class="body-wrap">
<ul class="goods-list">
<li v-for="(item, index) in data.value.goodsList.value.list" :key="index" :title="item.goods_name" @click="goSku(item.sku_id)">
<div class="img-wrap">
<img alt="商品图片" :src="item.goods_image ? $img(item.goods_image.split(',')[0], {size: 'mid'}) : defaultGoodsImage" @error="imageError(index)" />
</div>
<h3>{{ item.goods_name }}</h3>
<p class="desc">{{ item.introduction }}</p>
<p class="price">
<span class="num">{{ item.discount_price }}</span>
<del v-show="Number.parseInt(item.market_price)">{{ item.market_price }}</del>
</p>
</li>
</ul>
</div>
<div class="bottom-wrap" v-if="data.value.bottomImg.value.url">
<img :src="$img(data.value.bottomImg.value.url)" @click="$util.pushToTab(data.value.bottomImg.value.link.url)" />
</div>
</div>
</template>
<script>
import {mapGetters} from 'vuex';
export default {
name: 'floor-style-2',
props: {
data: {
type: Object
}
},
data() {
return {};
},
created() {
},
computed: {
...mapGetters(['defaultGoodsImage'])
},
methods: {
goSku(skuId) {
this.$router.push('/sku/' + skuId);
},
imageError(index) {
this.data.value.goodsList.value.list[index].goods_image = this.defaultGoodsImage;
}
}
};
</script>
<style lang="scss" scoped>
.floor-style-2 {
.head-wrap {
text-align: center;
h2 {
line-height: 30px;
color: #333;
padding: 10px;
font-size: 22px;
cursor: pointer;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
p {
color: #b0b0b0;
padding: 0 10px;
font-size: 14px;
cursor: pointer;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
margin-bottom: 20px;
}
}
.body-wrap {
.goods-list {
display: flex;
flex-wrap: wrap;
li {
width: 19%;
margin-left: 15px;
margin-bottom: 15px;
background: #fff;
cursor: pointer;
padding: 10px 0;
transition: all 0.2s linear;
&:nth-child(5n + 1) {
margin-left: 0;
}
&:hover {
z-index: 2;
-webkit-box-shadow: 0 15px 30px rgba(0, 0, 0, 0.1);
box-shadow: 0 15px 30px rgba(0, 0, 0, 0.1);
-webkit-transform: translate3d(0, -2px, 0);
transform: translate3d(0, -2px, 0);
}
.img-wrap {
width: 160px;
height: 160px;
margin: 0 auto 18px;
text-align: center;
line-height: 160px;
img {
max-width: 100%;
max-height: 100%;
}
}
h3 {
font-size: 14px;
text-align: center;
text-overflow: ellipsis;
white-space: nowrap;
overflow: hidden;
margin: 5px 15px;
font-weight: normal;
}
.desc {
margin: 0 30px 10px;
height: 20px;
font-size: 12px;
color: #b0b0b0;
text-align: center;
text-overflow: ellipsis;
white-space: nowrap;
overflow: hidden;
}
.price {
margin: 0 10px 14px;
text-align: center;
color: $base-color;
del {
margin-left: 0.5em;
color: #b0b0b0;
}
}
}
}
}
.bottom-wrap {
margin-top: 10px;
width: $width;
height: 118px;
cursor: pointer;
overflow: hidden;
img {
max-width: 100%;
}
}
}
</style>

View File

@@ -0,0 +1,256 @@
<template>
<div class="floor-style-3">
<div class="item-wrap">
<div class="head-wrap">
<div class="title-name" v-if="data.value.title.value.text">
<span :style="{ backgroundColor: data.value.title.value.color }"></span>
<h2 @click="$util.pushToTab(data.value.title.value.link.url)" :style="{ color: data.value.title.value.color }">{{ data.value.title.value.text }}</h2>
</div>
<div class="category-wrap">
<li v-for="(item, index) in data.value.categoryList.value.list" :key="index">
<router-link target="_blank" :to="{ path: '/goods/list', query: { category_id: item.category_id, level: item.level } }">{{ item.category_name }}</router-link>
</li>
</div>
</div>
<div class="body-wrap">
<div class="left-img-wrap">
<img v-if="data.value.leftImg.value.url" :src="$img(data.value.leftImg.value.url)" @click="$util.pushToTab(data.value.leftImg.value.link.url)" />
</div>
<ul class="right-goods-wrap">
<li v-for="(item, index) in data.value.rightGoodsList.value.list" :key="index" @click="goSku(item.sku_id)">
<h4>{{ item.goods_name }}</h4>
<p class="ns-text-color">{{ item.introduction }}</p>
<div class="img-wrap">
<img alt="商品图片" :src="$img(item.goods_image.split(',')[0], {size: 'mid'})" @error="imageErrorRight(index)" />
</div>
</li>
</ul>
<ul class="bottom-goods-wrap">
<li v-for="(item, index) in data.value.bottomGoodsList.value.list" :key="index" @click="goSku(item.sku_id)">
<div class="info-wrap">
<h4>{{ item.goods_name }}</h4>
<p class="ns-text-color">{{ item.introduction }}</p>
</div>
<div class="img-wrap">
<img alt="商品图片" :src="$img(item.goods_image.split(',')[0], {size: 'mid'})" @error="imageErrorBottom(index)" />
</div>
</li>
</ul>
<!-- <ul class="brand-wrap">
<li v-for="(item, index) in data.value.brandList.value.list" :key="index" @click="$util.pushToTab({ path: '/list', query: { brand_id: item.brand_id } })">
<img alt="品牌图片" :src="$img(item.image_url)" />
</li>
</ul> -->
</div>
</div>
</div>
</template>
<script>
import {mapGetters} from 'vuex';
export default {
name: 'floor-style-3',
props: {
data: {
type: Object
}
},
data() {
return {};
},
created() {
},
computed: {
...mapGetters(['defaultGoodsImage'])
},
methods: {
goSku(skuId) {
this.$util.pushToTab('/sku/' + skuId);
},
imageErrorRight(index) {
this.data.value.rightGoodsList.value.list[index].goods_image = this.defaultGoodsImage;
},
imageErrorBottom(index) {
this.data.value.bottomGoodsList.value.list[index].goods_image = this.defaultGoodsImage;
}
}
};
</script>
<style lang="scss" scoped>
.floor-style-3 {
overflow: hidden;
.item-wrap .head-wrap {
height: 50px;
line-height: 50px;
.title-name {
display: inline-block;
span {
float: left;
width: 5px;
height: 21px;
margin-top: 15px;
}
h2 {
float: left;
margin-left: 10px;
font-weight: bold;
font-size: 20px;
}
}
.category-wrap {
float: right;
display: flex;
li {
margin-right: 10px;
}
}
}
.body-wrap {
.left-img-wrap {
width: 190px;
height: 360px;
float: left;
cursor: pointer;
img {
max-width: 100%;
max-height: 100%;
}
}
.right-goods-wrap {
margin-left: 190px;
text-align: center;
overflow: hidden;
li {
float: left;
width: 19.9%;
background: #ffff;
border-width: 0 0 1px 1px;
border-color: #f9f9f9;
border-style: solid;
cursor: pointer;
h4 {
font-size: 14px;
margin: 10px 20px 5px;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
font-weight: normal;
}
p {
font-size: 12px;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
margin: 4px 30px;
height: 20px;
}
}
.img-wrap {
width: 105px;
height: 105px;
line-height: 105px;
display: inline-block;
margin-bottom: 10px;
img {
max-width: 100%;
max-height: 100%;
}
}
}
}
.bottom-goods-wrap {
overflow: hidden;
display: flex;
li {
flex: 1;
background: #fff;
border-width: 0 0 1px 1px;
border-color: #f9f9f9;
border-style: solid;
cursor: pointer;
&:first-child {
border-left: 0;
}
.info-wrap {
display: inline-block;
vertical-align: middle;
text-align: center;
h4 {
font-size: 14px;
margin: 0 10px 5px;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
width: 90px;
font-weight: normal;
}
p {
font-size: 12px;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
margin: 0 20px;
width: 70px;
}
}
.img-wrap {
width: 70px;
height: 70px;
line-height: 70px;
display: inline-block;
vertical-align: middle;
text-align: center;
padding: 10px;
img {
max-width: 100%;
max-height: 100%;
}
}
}
}
.brand-wrap {
display: flex;
background: #fff;
li {
flex: 1;
height: 50px;
cursor: pointer;
line-height: 50px;
text-align: center;
background: #fff;
img {
max-width: 100%;
max-height: 100%;
}
}
}
}
</style>

View File

@@ -0,0 +1,226 @@
<template>
<div class="floor-style-4">
<div class="head-wrap" v-if="data.value.title.value.text">
<h2 @click="$util.pushToTab(data.value.title.value.link.url)" :style="{ color: data.value.title.value.color }">{{ data.value.title.value.text }}</h2>
<div class="more" @click="$util.pushToTab(data.value.more.value.link.url)" :style="{color: data.value.more.value.color}">
<span>{{data.value.more.value.text}}</span>
<i class="el-icon-arrow-right"></i>
</div>
</div>
<div class="body-wrap">
<div class="left-wrap" v-if="data.value.leftImg.value.url">
<img :src="$img(data.value.leftImg.value.url)" @click="$util.pushToTab(data.value.leftImg.value.link.url)" />
</div>
<el-carousel trigger="click" height="324px" indicator-position="none" arrow="never">
<el-carousel-item v-for="num in itemNum" :key="num">
<ul class="goods-list">
<li v-for="(item, index) in itemList(num)" :key="index" :title="item.goods_name" @click="goSku(item.sku_id)">
<div class="img-wrap">
<img alt="商品图片" :src="$img(item.goods_image.split(',')[0], { size: 'mid' })" @error="imageError(index)" />
</div>
<div class="price">
<span class="num">{{ item.discount_price }}</span>
<del v-show="Number.parseInt(item.market_price)">{{ item.market_price }}</del>
</div>
<h3 class="name">{{ item.goods_name }}</h3>
<div class="other-info" v-if="item.sale_num">
<span>已售{{ item.sale_num }}</span>
</div>
</li>
</ul>
</el-carousel-item>
</el-carousel>
</div>
<div class="bottom-wrap" v-if="data.value.bottomImg.value.url">
<img :src="$img(data.value.bottomImg.value.url)" @click="$util.pushToTab(data.value.bottomImg.value.link.url)" />
</div>
</div>
</template>
<script>
import {mapGetters} from 'vuex';
export default {
name: 'floor-style-4',
props: {
data: {
type: Object
}
},
data() {
return {};
},
created() {
},
computed: {
...mapGetters(['defaultGoodsImage']),
goodsList() {
let arr = [];
try {
arr = this.data.value.goodsList.value.list;
} catch (e) {
arr = [];
}
return arr;
},
itemNum() {
let [num, listLen] = [0, this.goodsList.length];
num = parseInt(listLen / 3);
if (parseInt(listLen % 3) > 0) num += 1;
return num;
}
},
methods: {
goSku(skuId) {
this.$util.pushToTab('/sku/' + skuId);
},
imageError(index) {
this.data.value.goodsList.value.list[index].goods_image = this.defaultGoodsImage;
},
itemList(index) {
index -= 1;
if (!this.goodsList.length) return [];
let [start, end, arr] = [index * 3, index * 3 + 3, []];
arr = this.goodsList.slice(start, end);
return arr;
}
}
};
</script>
<style lang="scss" scoped>
.floor-style-4 {
.head-wrap {
display: flex;
align-items: center;
justify-content: space-between;
}
.head-wrap h2 {
line-height: 30px;
color: #333;
padding: 10px;
font-size: 18px;
cursor: pointer;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.body-wrap {
display: flex;
.left-wrap {
margin-right: 15px;
width: 478px;
height: 324px;
cursor: pointer;
transition: all 0.2s linear;
&:hover {
z-index: 2;
-webkit-box-shadow: 0 15px 30px rgba(0, 0, 0, 0.1);
box-shadow: 0 15px 30px rgba(0, 0, 0, 0.1);
-webkit-transform: translate3d(0, -2px, 0);
transform: translate3d(0, -2px, 0);
}
img {
max-width: 100%;
cursor: pointer;
}
}
.el-carousel {
flex: 1;
}
.goods-list {
display: flex;
li {
position: relative;
width: 228px;
height: 324px;
margin-right: 15px;
background-color: #fff;
cursor: pointer;
padding: 10px 18px;
transition: all 0.2s linear;
box-sizing: border-box;
&:last-of-type {
margin-right: 0;
}
&:hover {
z-index: 2;
-webkit-box-shadow: 0 15px 30px rgba(0, 0, 0, 0.1);
box-shadow: 0 15px 30px rgba(0, 0, 0, 0.1);
-webkit-transform: translate3d(0, -2px, 0);
transform: translate3d(0, -2px, 0);
}
.img-wrap {
width: 168px;
height: 168px;
line-height: 168px;
margin: 0 auto 18px;
img {
max-width: 100%;
max-height: 100%;
}
}
.name {
margin-top: 5px;
font-size: 14px;
color: #444;
line-height: 1.5;
font-weight: normal;
@extend .multi-hidden;
}
.other-info {
position: absolute;
bottom: 15px;
display: flex;
align-items: center;
justify-content: space-between;
span {
font-size: 14px;
color: #aaa;
}
}
.price {
.num {
color: $base-color;
font-size: 20px;
font-weight: bold;
}
del {
font-size: 14px;
margin-left: 15px;
color: #aaa;
}
}
}
}
}
.bottom-wrap {
margin-top: 35px;
width: $width;
cursor: pointer;
overflow: hidden;
img {
max-width: 100%;
}
}
}
</style>

View File

@@ -0,0 +1,235 @@
<template>
<div class="box">
<div class="null-page" v-show="yes"></div>
<div class="my-account">
<div class="account-wrap">
<div class="account-left">
<div class="title">我的可用余额()</div>
<div class="money">
<div class="balance-money">
<b>{{ integer }}</b>
<span>.{{ decimal }}</span>
</div>
<div class="tx" @click="applyWithdrawal">提现</div>
<div class="cz" @click="rechargeList">充值</div>
</div>
</div>
<div class="account-right">
<div class="item-wrap">
<div class="item">
<div class="iconfont icon-ziyuan"></div>
<div class="title">储值余额:</div>
<b class="num">{{ balanceInfo.balance_money }}</b>
</div>
<div class="item">
<div class="iconfont icon-ziyuan"></div>
<div class="title">现金余额:</div>
<b class="num">{{ balanceInfo.balance }}</b>
</div>
</div>
</div>
</div>
<div class="detail" v-loading="loading">
<el-table :data="accountList" border>
<el-table-column prop="type_name" label="来源" width="150"></el-table-column>
<el-table-column prop="account_data" label="金额" width="150"></el-table-column>
<el-table-column prop="remark" class="detail-name" label="详细说明"></el-table-column>
<el-table-column prop="time" label="时间" width="180"></el-table-column>
</el-table>
</div>
<div class="pager">
<el-pagination
background
:pager-count="5"
:total="total"
prev-text="上一页"
next-text="下一页"
:current-page.sync="account.page"
:page-size.sync="account.page_size"
@size-change="handlePageSizeChange"
@current-change="handleCurrentPageChange"
hide-on-single-page
></el-pagination>
</div>
</div>
</div>
</template>
<script>
import {balance, balanceDetail} from "@/api/member/account"
export default {
name: "account",
layout: "member",
components: {},
data: () => {
return {
account: {
page: 1,
page_size: 10
},
balanceInfo: {
balance: 0,
balance_money: 0
},
accountList: [],
total: 0,
integer: 0,
decimal: 0,
loading: true,
yes: true
}
},
created() {
this.getAccount();
this.getAccountList()
},
mounted() {
let self = this;
setTimeout(function () {
self.yes = false
}, 300)
},
methods: {
//获取余额信息
getAccount() {
balance({account_type: "balance,balance_money"}).then(res => {
if (res.code == 0 && res.data) {
this.balanceInfo = res.data;
const price = (parseFloat(this.balanceInfo.balance) + parseFloat(this.balanceInfo.balance_money)).toFixed(2)
let priceSplit = price.split(".");
this.integer = priceSplit[0];
this.decimal = priceSplit[1];
}
this.loading = false
}).catch(err => {
this.loading = false;
this.$message.error(err.message)
})
},
//获取余额明细
getAccountList() {
balanceDetail({
page_size: this.account.page_size,
page: this.account.page,
account_type: "balance"
}).then(res => {
if (res.code == 0 && res.data) {
this.accountList = res.data.list;
this.total = res.data.count;
this.accountList.forEach(item => {
item.time = this.$util.timeStampTurnTime(item.create_time)
})
}
}).catch(err => {
this.$message.error(err.message)
})
},
handlePageSizeChange(num) {
this.account.page_size = num;
this.getAccountList()
},
handleCurrentPageChange(page) {
this.account.page = page
this.getAccountList()
},
applyWithdrawal() {
this.$router.push("/member/apply_withdrawal")
},
rechargeList() {
this.$router.push("/member/recharge_list")
}
}
}
</script>
<style lang="scss" scoped>
.box {
width: 100%;
position: relative;
}
.null-page {
width: 100%;
height: 730px;
background-color: #FFFFFF;
position: absolute;
top: 0;
left: 0;
z-index: 9;
}
.my-account {
background: #ffffff;
padding: 20px;
.account-wrap {
display: flex;
margin-bottom: 10px;
.account-left {
flex: 1;
.title {
font-size: $ns-font-size-base;
font-weight: 600;
}
.money {
display: flex;
.balance-money {
b {
font-size: 30px;
}
span {
font-weight: 600;
}
}
.tx {
color: $base-color;
margin-left: 5px;
margin-top: 20px;
cursor: pointer;
}
.cz {
color: $base-color;
margin-left: 5px;
margin-top: 20px;
cursor: pointer;
}
}
}
.account-right {
flex: 1;
font-size: $ns-font-size-base;
display: flex;
align-items: center;
.item {
display: flex;
align-items: center;
.title {
margin-left: 3px;
}
.num {
margin-left: 3px;
}
}
}
}
.page {
display: flex;
justify-content: center;
align-content: center;
padding-top: 20px;
}
}
</style>

View File

@@ -0,0 +1,208 @@
<template>
<div class="box">
<div class="null-page" v-show="yes"></div>
<el-card class="box-card">
<div slot="header" class="clearfix">
<span>编辑账户</span>
</div>
<div v-loading="loading">
<el-form :model="formData" :rules="rules" ref="ruleForm" label-width="80px">
<el-form-item label="姓名" prop="realname">
<el-input v-model="formData.realname" placeholder="请输入真实姓名" class="ns-len-input"/>
</el-form-item>
<el-form-item label="手机" prop="mobile">
<el-input v-model="formData.mobile" autocomplete="off" placeholder="请输入手机号" maxlength="11" class="ns-len-input"/>
</el-form-item>
<el-form-item label="账号类型" prop="withdraw_type">
<el-select v-model="formData.withdraw_type" placeholder="请选择账号类型">
<el-option v-for="(value, key) in transferType" :key="key" :label="value" :value="key" :disabled="key == 'wechatpay'"></el-option>
</el-select>
</el-form-item>
<el-form-item label="银行名称" prop="branch_bank_name" v-if="formData.withdraw_type == 'bank'">
<el-input v-model="formData.branch_bank_name" autocomplete="off" placeholder="请输入银行名称" maxlength="50" class="ns-len-input"/>
</el-form-item>
<el-form-item label="提现账号" prop="bank_account" v-if="formData.withdraw_type != 'wechatpay' && formData.withdraw_type">
<el-input v-model="formData.bank_account" autocomplete="off" placeholder="请输入提现账号" maxlength="30" class="ns-len-input"/>
</el-form-item>
<el-form-item>
<el-button size="medium" type="primary" @click="saveAccount('ruleForm')">保存</el-button>
</el-form-item>
</el-form>
</div>
</el-card>
</div>
</template>
<script>
import {transferType, accountDetail, saveAccount} from "@/api/member/member"
export default {
name: "account_edit",
layout: "member",
data() {
var isMobile = (rule, value, callback) => {
if (!value) {
return callback(new Error("手机号不能为空"))
} else {
if (/^\d{11}$/.test(value)) {
callback()
} else {
callback(new Error("请输入正确的手机号"))
}
}
}
return {
formData: {
id: '',
realname: '',
mobile: '',
withdraw_type: '',
bank_account: '',
branch_bank_name: ''
},
flag: false, //防重复标识
payList: [],
loading: true,
index: 0,
transferType: [],
rules: {
realname: [{required: true, message: "请输入真实姓名", trigger: "blur"}],
mobile: [{required: true, validator: isMobile, trigger: "blur"}],
withdraw_type: [{required: true, message: '请选择账号类型', trigger: 'change'}],
branch_bank_name: [{required: true, message: "请输入银行名称", trigger: "blur"}],
bank_account: [{required: true, message: "请输入提现账号", trigger: "blur"}],
},
yes: true
}
},
created() {
this.formData.id = this.$route.query.id;
this.getTransferType();
if (this.formData.id) {
this.getAccountDetail(this.formData.id)
}
},
mounted() {
let self = this;
setTimeout(function () {
self.yes = false
}, 300)
},
methods: {
/**
* 获取转账方式
*/
getTransferType() {
transferType().then(res => {
this.transferType = res.data;
if (!this.formData.id) { // id为空即添加时在此结束加载
this.loading = false
}
}).catch(err => {
if (!this.formData.id) {
this.loading = false
}
})
},
/**
* 获取账户详情(编辑)
*/
getAccountDetail(id) {
accountDetail({id: this.formData.id}).then(res => {
if (res.code == 0 && res.data) {
this.formData.realname = res.data.realname;
this.formData.mobile = res.data.mobile;
this.formData.bank_account = res.data.bank_account;
this.formData.branch_bank_name = res.data.branch_bank_name;
this.formData.withdraw_type = res.data.withdraw_type;
}
this.loading = false
}).catch(err => {
this.loading = false
})
},
/**
* 保存
*/
saveAccount(formName) {
this.$refs[formName].validate(valid => {
if (valid) {
var data = {
id: this.formData.id,
realname: this.formData.realname,
mobile: this.formData.mobile,
withdraw_type: this.formData.withdraw_type,
bank_account: this.formData.bank_account,
branch_bank_name: this.formData.branch_bank_name
}
data.url = "add"
if (this.formData.id) {
data.url = "edit"
}
if (this.flag) return
this.flag = true
saveAccount(data).then(res => {
if (res.code == 0) {
this.$router.push({path: "/member/account_list"})
} else {
this.flag = false
this.$message({message: res.message, type: "warning"})
}
}).catch(err => {
this.flag = false
this.$message.error(err.message)
})
} else {
return false
}
})
}
}
}
</script>
<style lang="scss" scoped>
.box {
width: 100%;
position: relative;
}
.null-page {
width: 100%;
height: 730px;
background-color: #FFFFFF;
position: absolute;
top: 0;
left: 0;
z-index: 9;
}
.el-card.is-always-shadow,
.el-card.is-hover-shadow:focus,
.el-card.is-hover-shadow:hover {
box-shadow: unset;
}
.el-card {
border: 0;
}
.ns-len-input {
width: 350px;
}
.el-select {
margin-right: 10px;
}
</style>

View File

@@ -0,0 +1,285 @@
<template>
<div class="box">
<div class="null-page" v-show="yes"></div>
<el-card class="box-card">
<div slot="header" class="clearfix">
<span>账户列表</span>
</div>
<div v-loading="loading">
<div class="ns-member-address-list">
<div class="text item ns-add-address" @click="addAccount('add')">
<span>+ 新增账户</span>
</div>
<div class="text item ns-account-list" v-for="(item, index) in dataList" :key="index" @click="setDefault(item.id)">
<div class="text-name">
<span>{{ item.realname }}</span>
<span v-if="item.is_default == 1" class="text-default">默认</span>
</div>
<div class="text-content">
<p>手机号码{{ item.mobile }}</p>
<p v-if="item.withdraw_type == 'alipay'">提现账号{{ item.bank_account }}</p>
<p>账号类型{{ item.withdraw_type_name }}</p>
<p v-if="item.withdraw_type == 'bank'">银行名称{{ item.branch_bank_name }}</p>
</div>
<div class="text-operation">
<span v-if="item.is_default != 1" @click="setDefault(item.id)">设为默认</span>
<span @click.stop="addAccount('edit', item.id)">编辑</span>
<span v-if="item.is_default != 1" @click.stop="delAccount(item.id, item.is_default)">删除</span>
</div>
</div>
</div>
<div class="pager">
<el-pagination
background
:pager-count="5"
:total="total"
prev-text="上一页"
next-text="下一页"
:current-page.sync="currentPage"
:page-size.sync="pageSize"
@size-change="handlePageSizeChange"
@current-change="handleCurrentPageChange"
hide-on-single-page
></el-pagination>
</div>
</div>
</el-card>
</div>
</template>
<script>
import {accountList, accountDefault, delAccount} from "@/api/member/member"
export default {
name: "account_list",
layout: "member",
components: {},
data: () => {
return {
dataList: [],
total: 0,
currentPage: 1,
pageSize: 8,
loading: true,
isSub: false,
yes: true
}
},
created() {
this.back = this.$route.query.back
this.getAccountList()
},
mounted() {
let self = this;
setTimeout(function () {
self.yes = false
}, 300)
},
methods: {
handlePageSizeChange(size) {
this.pageSize = size
this.refresh()
},
handleCurrentPageChange(page) {
this.currentPage = page
this.refresh()
},
refresh() {
this.loading = true
this.getAccountList()
},
/**
* 获取账户列表
*/
getAccountList() {
accountList({
page_size: this.pageSize,
page: this.currentPage
}).then(res => {
this.dataList = res.data.list
this.total = res.data.count
let withdrawType = {
'bank': '银行',
'alipay': '支付宝',
'wechatpay': '微信'
};
this.dataList.forEach(item => {
item.withdraw_type_name = withdrawType[item.withdraw_type] ? withdrawType[item.withdraw_type] : '';
})
this.loading = false
}).catch(err => {
this.loading = false
})
},
setDefault(id) {
if (this.isSub) return;
this.isSub = true;
accountDefault({
id: id
}).then(res => {
if (this.back) {
this.$router.push(this.back);
} else {
this.refresh()
this.$message.success('修改默认账户成功')
}
this.isSub = false;
}).catch(err => {
this.isSub = false;
this.$message.error(err.message)
})
},
delAccount(id) {
this.$confirm("确定要删除该账户吗?", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning"
}).then(() => {
delAccount({
id: id
}).then(res => {
this.refresh()
this.$message.success(res.message)
}).catch(err => {
this.$message.error(err.message)
})
})
},
/**
* 添加/编辑地址
*/
addAccount(type, id) {
if (type == "edit") {
this.$router.push({path: "/member/account_edit", query: {id: id}})
} else {
this.$router.push({path: "/member/account_edit"})
}
}
}
}
</script>
<style lang="scss" scoped>
.box {
width: 100%;
position: relative;
}
.null-page {
width: 100%;
height: 730px;
background-color: #FFFFFF;
position: absolute;
top: 0;
left: 0;
z-index: 9;
}
.el-card.is-always-shadow,
.el-card.is-hover-shadow:focus,
.el-card.is-hover-shadow:hover {
box-shadow: unset;
}
.el-card {
border: 0;
}
.ns-member-address-list {
display: flex;
flex-wrap: wrap;
.ns-account-list {
cursor: pointer;
}
.text {
width: 32%;
height: 170px;
margin-right: 2%;
border-radius: 5px;
border: 1px solid #d8d8d8;
margin-bottom: 20px;
padding: 0 15px;
box-sizing: border-box;
position: relative;
.text-name {
height: 37px;
line-height: 40px;
padding: 0 10px;
border-bottom: 1px solid #eeeeee;
}
.text-default {
display: inline-block;
margin-left: 10px;
background: $base-color;
color: #ffffff;
width: 35px;
height: 20px;
line-height: 20px;
text-align: center;
border-radius: 3px;
}
.text-content {
padding: 10px;
p {
font-size: 12px;
}
}
.ns-address-detail {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.text-operation {
// 操作
position: absolute;
right: 12px;
bottom: 5px;
span {
margin: 0 5px;
color: #999999;
cursor: pointer;
font-size: 12px;
}
span:hover {
color: $base-color;
}
}
}
.text:nth-child(3n) {
margin-right: 0;
}
.ns-add-address {
border: 1px dashed #d8d8d8;
text-align: center;
color: #999999;
line-height: 170px;
cursor: pointer;
}
.ns-add-address:hover {
border-color: $base-color;
color: $base-color;
}
}
</style>

View File

@@ -0,0 +1,365 @@
<template>
<div class="box">
<div class="null-page" v-show="yes"></div>
<el-card class="box-card order-list">
<div slot="header" class="clearfix"><span>退款/售后</span></div>
<div v-loading="loading">
<nav>
<li>商品信息</li>
<li>退款金额</li>
<li>退款类型</li>
<li>退款状态</li>
<li>操作</li>
</nav>
<div class="list" v-if="refundList.length > 0">
<div class="item" v-for="(refundItem, refundIndex) in refundList" :key="refundIndex">
<div class="head">
<span class="create-time">{{ $util.timeStampTurnTime(refundItem.refund_action_time) }}</span>
<span class="order-no">退款编号{{ refundItem.refund_no }}</span>
<router-link :to="'/shop-' + refundItem.site_id" target="_blank">{{ refundItem.site_name }}</router-link>
<span class="order-type">{{ refundItem.refund_status == 3 ? '退款成功' : '退款中' }}</span>
</div>
<ul>
<li>
<div class="img-wrap" @click="$util.pushToTab('/sku/' + refundItem.sku_id)">
<img :src="$img(refundItem.sku_image, { size: 'mid' })" @error="imageError(refundIndex)" />
</div>
<div class="info-wrap">
<h5 @click="$util.pushToTab('/sku/' + refundItem.sku_id)">{{ refundItem.sku_name }}</h5>
<!-- <span>规格规格值</span> -->
</div>
</li>
<li>
<span>{{ (Number(refundItem.refund_status == 3 ? refundItem.refund_real_money : refundItem.refund_apply_money) + Number(refundItem.shop_active_refund_money)).toFixed(2) }}</span>
</li>
<li>
<span>{{ refundItem.refund_type == 1 ? '退款' : '退货' }}</span>
</li>
<li>
<span class="ns-text-color">{{ refundItem.refund_status_name }}</span>
<el-link :underline="false" @click="orderDetail(refundItem)">退款详情</el-link>
</li>
<li>
<template v-if="refundItem.refund_action.length > 0">
<el-button
type="primary"
size="mini"
:plain="true"
v-for="(operationItem, operationIndex) in refundItem.refund_action"
:key="operationIndex"
@click="operation(operationItem.event, refundItem)"
>{{ operationItem.title }}</el-button>
</template>
</li>
</ul>
</div>
</div>
<div v-else-if="!loading && refundList.length == 0" class="empty-wrap">暂无相关订单</div>
</div>
<div class="pager">
<el-pagination
background
:pager-count="5"
:total="total"
prev-text="上一页"
next-text="下一页"
:current-page.sync="currentPage"
:page-size.sync="pageSize"
@size-change="handlePageSizeChange"
@current-change="handleCurrentPageChange"
hide-on-single-page
></el-pagination>
</div>
</el-card>
</div>
</template>
<script>
import {mapGetters} from 'vuex';
import {refundList, cancleRefund} from '@/api/order/refund';
export default {
name: 'activist',
layout: "member",
components: {},
data: () => {
return {
orderStatus: 'all',
loading: true,
refundList: [],
currentPage: 1,
pageSize: 10,
total: 0,
yes: true
};
},
created() {
this.orderStatus = this.$route.query.status || 'all';
this.getRefundList();
},
computed: {
...mapGetters(['defaultGoodsImage'])
},
mounted() {
let self = this;
setTimeout(function () {
self.yes = false
}, 300)
},
methods: {
handleClick(tab, event) {
this.currentPage = 1;
this.orderStatus = tab.name;
this.refresh();
},
getRefundList() {
refundList({
page: this.currentPage,
page_size: this.pageSize
}).then(res => {
let list = [];
if (res.code == 0 && res.data) {
list = res.data.list;
this.total = res.data.count;
}
this.refundList = list;
this.loading = false;
}).catch(res => {
this.loading = false;
});
},
handlePageSizeChange(size) {
this.pageSize = size;
this.refresh();
},
handleCurrentPageChange(page) {
this.currentPage = page;
this.refresh();
},
refresh() {
this.loading = true;
this.getRefundList();
},
operation(action, orderData) {
switch (action) {
case 'orderRefundCancel': // 撤销维权
this.cancleRefund(orderData.order_goods_id);
break;
case 'orderRefundDelivery': // 退款发货
this.$router.push({
path: '/order/refund_detail',
query: {order_goods_id: orderData.order_goods_id, action: 'returngoods'}
});
break;
case 'orderRefundAsk':
this.$router.push({path: '/order/refund?order_goods_id=' + orderData.order_goods_id});
break;
case 'orderRefundApply':
this.$router.push({
path: '/order/refund',
query: { order_goods_id: orderData.order_goods_id, order_id: orderData.order_id },
});
break;
}
},
orderDetail(data) {
this.$router.push({path: '/order/refund_detail', query: {order_goods_id: data.order_goods_id}});
},
imageError(refundIndex) {
this.refundList[refundIndex].sku_image = this.defaultGoodsImage;
},
cancleRefund(order_goods_id) {
this.$confirm('撤销之后本次申请将会关闭,如后续仍有问题可再次发起申请', '提示', {
confirmButtonText: '确认撤销',
cancelButtonText: '暂不撤销',
type: 'warning'
}).then(() => {
if (this.isSub) return;
this.isSub = true;
cancleRefund({order_goods_id: order_goods_id}).then(res => {
const {code, message, data} = res;
if (code >= 0) {
this.$message({
message: '撤销成功',
type: 'success'
});
this.getRefundList();
} else {
this.$message({message: message, type: 'warning'});
}
}).catch(err => {
this.$message.error(err.message);
});
})
}
}
};
</script>
<style lang="scss" scoped>
.box {
width: 100%;
position: relative;
}
.null-page {
width: 100%;
height: 730px;
background-color: #FFFFFF;
position: absolute;
top: 0;
left: 0;
z-index: 9;
}
.order-list {
nav {
overflow: hidden;
padding: 10px 0;
background: #fff;
margin-bottom: 10px;
border-bottom: 1px solid #eeeeee;
li {
float: left;
&:nth-child(1) {
width: 45%;
}
&:nth-child(2) {
width: 15%;
}
&:nth-child(3) {
width: 10%;
}
&:nth-child(4) {
width: 15%;
}
&:nth-child(5) {
width: 15%;
}
}
}
.list {
.item {
margin-bottom: 20px;
border: 1px solid #eeeeee;
border-top: 0;
.head {
padding: 8px 10px;
background: #f7f7f7;
font-size: 12px;
.create-time {
margin-right: 10px;
}
border-bottom: 1px solid #eeeeee;
a {
margin: 0 10px 0 20px;
}
.order-type {
margin-left: 30px;
}
}
}
ul {
background-color: #fff;
padding: 10px;
overflow: hidden;
li {
float: left;
line-height: 60px;
&:nth-child(1) {
width: 45%;
line-height: inherit;
.img-wrap {
width: 60px;
height: 60px;
float: left;
margin-right: 10px;
cursor: pointer;
}
.info-wrap {
margin-left: 70px;
h5 {
font-weight: normal;
font-size: $ns-font-size-base;
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 2;
overflow: hidden;
margin-right: 10px;
cursor: pointer;
display: inline-block;
&:hover {
color: $base-color;
}
}
span {
font-size: $ns-font-size-sm;
color: #9a9a9a;
}
}
}
&:nth-child(2) {
width: 15%;
}
&:nth-child(3) {
width: 10%;
}
&:nth-child(4) {
width: 14%;
line-height: 30px;
a {
display: block;
}
}
&:nth-child(5) {
width: 15%;
line-height: initial;
button {
margin-left: 0;
margin-bottom: 10px;
&:last-child {
margin-bottom: 0;
}
}
}
}
}
}
.empty-wrap {
text-align: center;
padding: 10px;
}
}
</style>

View File

@@ -0,0 +1,477 @@
<template>
<div class="box">
<div class="null-page" v-show="yes"></div>
<el-card class="box-card">
<div slot="header" class="clearfix">
<span>编辑收货地址</span>
</div>
<div v-loading="loading" class="ns-member-address-list">
<el-form :model="formData" :rules="rules" ref="ruleForm" label-width="80px">
<el-form-item label="姓名" prop="name">
<el-input v-model="formData.name" placeholder="收货人姓名" class="ns-len-input" />
</el-form-item>
<el-form-item label="手机" prop="mobile">
<el-input v-model="formData.mobile" autocomplete="off" placeholder="收货人手机号" class="ns-len-input" />
</el-form-item>
<el-form-item label="电话">
<el-input v-model.trim="formData.telephone" autocomplete="off" placeholder="收货人固定电话(选填)" class="ns-len-input" />
</el-form-item>
<el-form-item label="地址" prop="full_address">
<el-select :value="formData.province_id" placeholder="请选择省" @change="changeProvice">
<el-option v-for="option in province" :key="option.id" :label="option.name" :value="option.id">
{{ option.name }}
</el-option>
</el-select>
<el-select :value="formData.city_id" placeholder="请选择市" @change="changeCity">
<el-option v-for="option in city" :key="option.id" :label="option.name" :value="option.id">
{{ option.name }}
</el-option>
</el-select>
<el-select :value="formData.district_id" placeholder="请选择区/县" @change="changeDistrict">
<el-option v-for="option in district" :key="option.id" :label="option.name" :value="option.id">
{{ option.name }}
</el-option>
</el-select>
</el-form-item>
<el-form-item label="详细地址" prop="address">
<el-input v-model.trim="formData.address" autocomplete="off" placeholder="定位到小区、街道、写字楼" class="ns-len-input" />
</el-form-item>
<el-form-item label="是否默认">
<el-radio-group v-model="formData.is_default">
<el-radio :label="1"></el-radio>
<el-radio :label="0"></el-radio>
</el-radio-group>
</el-form-item>
<el-form-item>
<el-button type="primary" size="medium" @click="saveAddress('ruleForm')">保存</el-button>
</el-form-item>
</el-form>
</div>
</el-card>
</div>
</template>
<script>
import {
addressInfo,
saveAddress
} from "@/api/member/member"
import {
getArea
} from "@/api/address"
export default {
name: "address_edit",
layout: "member",
components: {},
data() {
let self = this
var isMobile = (rule, value, callback) => {
if (!value) {
return callback(new Error("手机号不能为空"))
} else {
if (/^\d{11}$/.test(value)) {
callback()
} else {
callback(new Error("请输入正确的手机号"))
}
}
}
var fullAddress = (rule, value, callback) => {
if (self.formData.province_id) {
if (self.formData.city_id) {
if (self.district.length > 0) {
if (self.formData.district_id) {
return callback()
} else {
return callback(new Error("请选择区/县"))
}
} else {
return callback()
}
} else {
return callback(new Error("请选择市"))
}
} else {
return callback(new Error("请选择省"))
}
}
return {
formData: {
id: 0,
name: "",
mobile: "",
telephone: "",
province_id: "",
city_id: "",
district_id: "",
community_id: "",
address: "",
full_address: "",
latitude: 0,
longitude: 0,
is_default: 1
},
addressValue: "",
flag: false, //防重复标识
defaultRegions: [],
rules: {
name: [{
required: true,
message: "请输入收货人姓名",
trigger: "blur"
}],
mobile: [{
required: true,
validator: isMobile,
trigger: "blur"
}],
address: [{
required: true,
message: "请输入详细地址",
trigger: "blur"
}],
full_address: [{
required: true,
validator: fullAddress,
trigger: "blur"
}]
},
province: [],
city: [],
district: [],
pickerValueArray: [],
multiIndex: [0, 0, 0],
isInitMultiArray: false,
// 是否加载完默认地区
isLoadDefaultAreas: false,
loading: true,
yes: true
}
},
created() {
this.formData.id = this.$route.query.id
this.getAddressDetail()
this.getDefaultAreas(0, {
level: 0
})
},
mounted() {
let self = this;
setTimeout(function () {
self.yes = false
}, 300)
},
watch: {
defaultRegions: {
handler(arr, oldArr = []) {
// 避免传的是字面量的时候重复触发
if (arr.length !== 3 || arr.join("") === oldArr.join("")) return
this.handleDefaultRegions()
},
immediate: true
}
},
computed: {
pickedArr() {
// 进行初始化
if (this.isInitMultiArray) {
return [this.pickerValueArray[0], this.pickerValueArray[1], this.pickerValueArray[2]]
}
return [this.pickerValueArray[0], this.city, this.district]
}
},
methods: {
/**
* 改变省
*/
changeProvice(id) {
this.formData.province_id = id;
this.getAreas(id, data => (this.city = data))
let obj = {}
obj = this.province.find(item => {
//这里的province就是上面遍历的数据源
return item.id === id //筛选出匹配数据
})
this.formData.city_id = ""
this.formData.district_id = ""
this.formData.full_address = obj.name // 设置选中的地址
},
/**
* 改变市
*/
changeCity(id) {
this.formData.city_id = id;
this.getAreas(id, data => (this.district = data))
let obj = {}
obj = this.city.find(item => {
//这里的province就是上面遍历的数据源
return item.id === id //筛选出匹配数据
})
this.formData.district_id = ""
this.formData.full_address = this.formData.full_address + "-" + obj.name
},
/**
* 改变区
*/
changeDistrict(id) {
this.formData.district_id = id;
let obj = {}
obj = this.district.find(item => {
//这里的province就是上面遍历的数据源
return item.id === id //筛选出匹配数据
})
this.formData.full_address = this.formData.full_address + "-" + obj.name
},
/**
* 获取地址信息
*/
getAddressDetail() {
addressInfo({
id: this.formData.id
}).then(res => {
let data = res.data
if (data != null) {
this.formData.name = data.name
this.formData.mobile = data.mobile
this.formData.telephone = data.telephone
this.formData.address = data.address
this.formData.full_address = data.full_address
this.formData.latitude = data.latitude
this.formData.longitude = data.longitude
this.formData.is_default = data.is_default
this.formData.province_id = data.province_id
this.formData.city_id = data.city_id
this.formData.district_id = data.district_id
this.defaultRegions = [data.province_id, data.city_id, data.district_id]
}
})
},
// 异步获取地区
getAreas(pid, callback) {
getArea({
pid: pid
}).then(res => {
if (res.code == 0) {
var data = []
res.data.forEach((item, index) => {
data.push(item)
})
if (callback) callback(data)
}
})
},
/**
* 获取省市区列表
*/
getDefaultAreas(pid, obj) {
getArea({
pid: pid
}).then(res => {
if (res.code == 0) {
var data = []
var selected = undefined
res.data.forEach((item, index) => {
if (obj != undefined) {
if (obj.level == 0 && obj.province_id != undefined) {
selected = obj.province_id
} else if (obj.level == 1 && obj.city_id != undefined) {
selected = obj.city_id
} else if (obj.level == 2 && obj.district_id != undefined) {
selected = obj.district_id
}
}
if (selected == undefined && index == 0) {
selected = item.id
}
data.push(item)
})
this.pickerValueArray[obj.level] = data
if (obj.level + 1 < 3) {
obj.level++
this.getDefaultAreas(selected, obj)
} else {
this.isInitMultiArray = true
this.isLoadDefaultAreas = true
}
this.province = this.pickerValueArray[0]
}
setTimeout(() => {
this.loading = false
}, 500)
}).catch(err => {
this.loading = false
})
},
/**
* 渲染默认值
*/
handleDefaultRegions() {
var time = setInterval(() => {
if (!this.isLoadDefaultAreas) return
this.isInitMultiArray = false
for (let i = 0; i < this.defaultRegions.length; i++) {
for (let j = 0; j < this.pickerValueArray[i].length; j++) {
this.province = this.pickerValueArray[0]
// 匹配省
if (this.defaultRegions[i] == this.pickerValueArray[i][j].id) {
// 设置选中省
this.$set(this.multiIndex, i, j)
// 查询市
this.getAreas(this.pickerValueArray[i][j].id, data => {
this.city = data
for (let k = 0; k < this.city.length; k++) {
if (this.defaultRegions[1] == this.city[k].id) {
// 设置选中市
this.$set(this.multiIndex, 1, k)
// 查询区县
this.getAreas(this.city[k].id, data => {
this.district = data
// 设置选中区县
for (let u = 0; u < this.district.length; u++) {
if (this.defaultRegions[2] == this.district[u].id) {
this.$set(this.multiIndex, 2, u)
this.handleValueChange({
detail: {
value: [j, k, u]
}
})
break
}
}
})
break
}
}
})
}
}
}
if (this.isLoadDefaultAreas) clearInterval(time)
}, 100)
},
handleValueChange(e) {
// 结构赋值
let [index0, index1, index2] = e.detail.value
let [arr0, arr1, arr2] = this.pickedArr
let address = [arr0[index0], arr1[index1], arr2[index2]]
this.formData.full_address = ""
for (let i = 0; i < address.length; i++) {
if (this.formData.full_address) {
this.formData.full_address = this.formData.full_address + "-" + address[i].name
} else {
this.formData.full_address = this.formData.full_address + address[i].name
}
}
},
/**
* 保存地址
*/
saveAddress(formName) {
this.$refs[formName].validate(valid => {
if (valid) {
var data = {
name: this.formData.name,
mobile: this.formData.mobile,
telephone: this.formData.telephone,
province_id: this.formData.province_id,
city_id: this.formData.city_id,
district_id: this.formData.district_id,
community_id: "",
address: this.formData.address,
full_address: this.formData.full_address,
latitude: this.formData.latitude,
longitude: this.formData.longitude,
is_default: this.formData.is_default
}
data.url = "add"
if (this.formData.id) {
data.url = "edit"
data.id = this.formData.id
}
if (this.flag) return
this.flag = true
saveAddress(data).then(res => {
if (res.code == 0) {
this.$router.push({
path: "/member/delivery_address"
})
} else {
this.flag = false
this.$message({
message: res.message,
type: "warning"
})
}
}).catch(err => {
this.flag = false
this.$message.error(err.message)
})
} else {
return false
}
})
}
}
}
</script>
<style lang="scss" scoped>
.box {
width: 100%;
position: relative;
}
.null-page {
width: 100%;
height: 730px;
background-color: #FFFFFF;
position: absolute;
top: 0;
left: 0;
z-index: 9;
}
.el-card.is-always-shadow,
.el-card.is-hover-shadow:focus,
.el-card.is-hover-shadow:hover {
box-shadow: unset;
}
.el-card {
border: 0;
}
.ns-len-input {
width: 350px;
}
.el-select {
margin-right: 10px;
}
</style>

View File

@@ -0,0 +1,308 @@
<template>
<div class="box">
<div class="null-page" v-show="yes"></div>
<el-card class="box-card">
<div slot="header" class="clearfix">
<el-breadcrumb separator="/">
<el-breadcrumb-item :to="{ path: '/member/account' }">账户余额</el-breadcrumb-item>
<el-breadcrumb-item>提现申请</el-breadcrumb-item>
</el-breadcrumb>
</div>
<div class="apply-withdrawal" v-loading="loading">
<div class="apply-wrap">
<div class="apply-account" v-if="bankAccountInfo.withdraw_type" @click="goAccount()">
<span class="ns-width">提现到</span>
<div class="apply-account-info">
<!-- <span v-if="bankAccountInfo.withdraw_type == 'wechatpay'">{{ bankAccountInfo.mobile }}</span> -->
<span v-if="bankAccountInfo.withdraw_type == 'wechatpay'">暂不支持微信提现请选择支付宝</span>
<span v-else>{{ bankAccountInfo.bank_account }}</span>
<el-image v-if="bankAccountInfo.withdraw_type == 'alipay'" :src="$img('public/uniapp/member/apply_withdrawal/alipay.png')" fit="contain"/>
<el-image v-else-if="bankAccountInfo.withdraw_type == 'bank'" :src="$img('public/uniapp/member/apply_withdrawal/bank.png')" fit="contain"/>
<!-- <el-image v-else-if="bankAccountInfo.withdraw_type == 'wechatpay'" :src="$img('public/uniapp/member/apply_withdrawal/wechatpay.png')" fit="contain"></el-image> -->
<i class="iconfont iconarrow-right"></i>
</div>
</div>
<div class="apply-account" v-else @click="goAccount()">
<span class="ns-width">提现账户</span>
<div class="apply-account-info">
<span class="ns-text-color">请选择提现账户</span>
</div>
</div>
<div class="apply-account-money demo-input-suffix">
<span class="ns-width">提现金额</span>
<el-input type="number" placeholder="0" v-model="withdrawMoney" :disabled="bankAccountInfo.withdraw_type == 'wechatpay'">
<template slot="prepend"></template>
</el-input>
</div>
<div class="apply-account-desc">
<p>
<span class="ns-width"></span>
<span>可提现余额为</span>
<span class="balance">{{ withdrawInfo.member_info.balance_money | moneyFormat }}</span>
<span @click="allTx">全部提现</span>
</p>
<p>
<span class="ns-width"></span>
<span>最小提现金额为{{ withdrawInfo.config.min | moneyFormat }}手续费为{{ withdrawInfo.config.rate + '%' }}</span>
</p>
</div>
<div class="apply-account-btn">
<span class="ns-width"></span>
<el-button type="primary" size="medium" @click="withdraw" :class="{ disabled: withdrawMoney == '' || withdrawMoney == 0 }" :disabled="bankAccountInfo.withdraw_type == 'wechatpay'">提现</el-button>
<!-- <router-link to="/member/withdrawal">提现记录</router-link> -->
</div>
</div>
</div>
</el-card>
</div>
</template>
<script>
import {withdrawInfo, accountInfo, withdraw} from "@/api/member/account"
export default {
name: "apply_withdrawal",
layout: "member",
components: {},
data: () => {
return {
withdrawInfo: {
config: {
is_use: 0,
min: 1,
rate: 0
},
member_info: {
balance_money: 0,
balance_withdraw: 0,
balance_withdraw_apply: 0
}
},
bankAccountInfo: {},
withdrawMoney: '',
isSub: false,
loading: true,
yes: true
}
},
filters: {
/**
* 金额格式化输出
* @param {Object} money
*/
moneyFormat(money) {
return parseFloat(money).toFixed(2);
}
},
created() {
this.getWithdrawInfo();
this.getBankAccountInfo();
},
mounted() {
let self = this;
setTimeout(function () {
self.yes = false
}, 300)
},
methods: {
/**
* 获取提现信息
*/
getWithdrawInfo() {
withdrawInfo().then(res => {
if (res.code >= 0 && res.data) {
this.withdrawInfo = res.data;
if (this.withdrawInfo.config.is_use == 0) {
this.$router.push('/member');
}
}
this.loading = false
}).catch(err => {
this.loading = false
})
},
/**
* 银行账号信息
*/
getBankAccountInfo() {
accountInfo().then(res => {
if (res.code >= 0 && res.data) {
this.bankAccountInfo = res.data;
}
})
},
/**
* 全部提现
*/
allTx() {
this.withdrawMoney = this.withdrawInfo.member_info.balance_money;
},
/**
* 账户列表
*/
goAccount() {
let back = "/member/apply_withdrawal"
this.$router.push({path: "/member/account_list", query: {back: back}})
},
withdraw() {
if (!this.bankAccountInfo.withdraw_type) {
this.$message({
message: "请先添加提现方式",
type: "warning"
})
return;
}
if (this.withdrawMoney == '' || this.withdrawMoney == 0 || isNaN(parseFloat(this.withdrawMoney))) {
this.$message({
message: '请输入提现金额',
type: "warning"
});
return false;
}
if (parseFloat(this.withdrawMoney) > parseFloat(this.withdrawInfo.member_info.balance_money)) {
this.$message({
message: '提现金额超出可提现金额',
type: "warning"
});
return false;
}
if (parseFloat(this.withdrawMoney) < parseFloat(this.withdrawInfo.config.min)) {
this.$message({
message: '提现金额小于最低提现金额',
type: "warning"
});
return false;
}
if (this.isSub) return;
this.isSub = true;
withdraw({
apply_money: this.withdrawMoney,
transfer_type: this.bankAccountInfo.withdraw_type, //转账提现类型
realname: this.bankAccountInfo.realname,
mobile: this.bankAccountInfo.mobile,
bank_name: this.bankAccountInfo.branch_bank_name,
account_number: this.bankAccountInfo.bank_account
}).then(res => {
if (res.code >= 0) {
this.$message({
message: '提现申请成功!',
type: 'success',
duration: 2000,
onClose: () => {
this.$router.push('/member/withdrawal');
}
});
} else {
this.isSub = false;
this.$message({
message: res.message,
type: "warning"
});
}
}).catch(err => {
this.isSub = false;
this.$message({
message: err.message,
type: "warning"
});
})
},
}
}
</script>
<style lang="scss" scoped>
.box {
width: 100%;
position: relative;
}
.null-page {
width: 100%;
height: 730px;
background-color: #FFFFFF;
position: absolute;
top: 0;
left: 0;
z-index: 9;
}
.apply-withdrawal {
width: 100%;
background-color: #FFFFFF;
.apply-wrap {
display: inline-block;
width: 500px;
box-sizing: border-box;
.apply-account {
display: flex;
align-items: center;
cursor: pointer;
.apply-account-info {
display: flex;
align-items: center;
span {
margin-right: 5px;
}
.el-image {
width: 20px;
height: 20px;
margin-right: 10px;
}
}
}
.apply-account-money {
display: flex;
align-items: center;
margin-top: 30px;
span {
flex-shrink: 0;
}
}
.apply-account-desc {
margin-top: 30px;
text-align: left;
p:first-child {
span.balance {
margin-right: 10px;
}
span:nth-child(4) {
color: $base-color;
cursor: pointer;
}
}
p:nth-child(2) {
color: #999999;
}
}
.apply-account-btn {
margin-top: 30px;
.el-button {
margin-right: 20px;
}
}
}
.ns-width {
display: inline-block;
width: 115px;
text-align: right;
}
}
</style>

View File

@@ -0,0 +1,431 @@
<template>
<div class="box">
<div class="null-page" v-show="yes"></div>
<div class="collection" v-loading="loading">
<el-tabs v-model="activeName" @tab-click="handleClick">
<el-tab-pane label="宝贝" name="goods">
<div v-if="goodsList.length > 0">
<div class="goods">
<div class="goods-wrap" v-for="(item, index) in goodsList" :key="item.goods_id">
<div class="goods-item">
<div class="img" @click="$util.pushToTab({ path: '/sku/' + item.sku_id })">
<img :src="$img(item.goods_image.split(',')[0], { size: 'mid' })" @error="imageError(index)" />
<i class="del el-icon-delete" @click.stop="deleteGoods(item.goods_id)"></i>
</div>
<div class="goods-name">{{ item.goods_name }}</div>
<div class="price">{{ item.price }}</div>
</div>
</div>
</div>
<div class="pager">
<el-pagination @size-change="handleSizeChange" @current-change="handleCurrentChange" :current-page="goodsInfo.page" :page-size="goodsInfo.page_size" background :pager-count="5" prev-text="上一页" next-text="下一页" hide-on-single-page :total="goodsTotal"></el-pagination>
</div>
</div>
<div v-else-if="!loading && !goodsList.length" class="empty">您还没有关注商品哦</div>
</el-tab-pane>
</el-tabs>
</div>
<div class="goods-recommended">
<div class="youLike">
<span>猜你喜欢</span>
</div>
<div class="body-wrap">
<ul class="goods-list">
<li v-for="(item, index) in list" :key="index" :title="item.goods_name" @click="$util.pushToTab({ path: '/sku/' + item.sku_id })">
<div class="img-wrap">
<img alt="商品图片" :src="$img(item.goods_image.split(',')[0], {size: 'mid'})" @error="imageImgError(index)" />
</div>
<h3>{{ item.goods_name }}</h3>
<p class="price">
<span class="num">{{ item.discount_price }}</span>
<del>{{ item.market_price }}</del>
</p>
</li>
</ul>
</div>
</div>
</div>
</template>
<script>
import {
goodsCollect,
deleteGoods
} from "@/api/member/collection"
import {
mapGetters
} from "vuex"
import {
goodsRecommend
} from '@/api/goods/goods';
export default {
name: "collection",
layout: "member",
components: {},
data() {
return {
goodsInfo: {
page: 1,
page_size: 10
},
shopInfo: {
page: 1,
page_size: 10
},
activeName: "goods",
goodsTotal: 0,
goodsList: [],
loading: true,
yes: true,
list: [],
page: 1,
pageSize: 5
}
},
created() {
this.getGoodsCollect()
this.getGoodsRecommend()
},
computed: {
...mapGetters(["defaultGoodsImage"])
},
mounted() {
let self = this;
setTimeout(function () {
self.yes = false
}, 300)
},
methods: {
// 获取推荐商品列列表
getGoodsRecommend() {
goodsRecommend({
page: this.page,
page_size: this.pageSize
}).then(res => {
if (res.code == 0) this.list = res.data.list;
this.loading = false;
}).catch(res => {
this.loading = false;
});
},
//获取关注商品
getGoodsCollect() {
goodsCollect(this.goodsInfo).then(res => {
this.goodsTotal = res.data.count
this.goodsList = res.data.list
this.loading = false
}).catch(err => {
this.loading = false
this.$message.error(err.message)
})
},
//删除关注商品
deleteGoods(id) {
deleteGoods({
goods_id: id
}).then(res => {
if (res.code == 0) {
this.$message({
message: "取消关注成功",
type: "success"
})
this.getGoodsCollect()
}
}).catch(err => {
this.$message.error(err.message)
})
},
handleClick(tab, event) {
if (tab.index == "0") {
this.loading = true
this.getGoodsCollect()
}
},
handleSizeChange(size) {
this.goodsInfo.page_size = size
this.loading = true
this.getGoodsCollect()
},
handleCurrentChange(page) {
this.goodsInfo.page = page
this.loading = true
this.getGoodsCollect()
},
imageError(index) {
this.goodsList[index].sku_image = this.defaultGoodsImage
},
imageImgError(index) {
this.list[index].sku_image = this.defaultGoodsImage;
}
}
}
</script>
<style lang="scss" scoped>
.goods-recommended {
width: 100%;
margin-top: 15px;
background-color: #fff;
.youLike {
width: 955px;
box-sizing: border-box;
border-bottom: 2px solid #dedede;
margin: 0 20px 20px;
span {
display: inline-block;
font-size: 14px;
padding: 10px 0;
}
}
.body-wrap {
.goods-list {
display: flex;
flex-wrap: wrap;
li {
width: 23%;
margin-left: 19px;
margin-bottom: 20px;
background: #fff;
cursor: pointer;
padding: 10px 0;
transition: all 0.2s linear;
&:hover {
z-index: 2;
-webkit-box-shadow: 0 15px 30px rgba(0, 0, 0, 0.1);
box-shadow: 0 15px 30px rgba(0, 0, 0, 0.1);
-webkit-transform: translate3d(0, -2px, 0);
transform: translate3d(0, -2px, 0);
}
.img-wrap {
width: 160px;
height: 160px;
margin: 0 auto 18px;
text-align: center;
line-height: 160px;
img {
max-width: 100%;
max-height: 100%;
}
}
h3 {
font-size: 14px;
text-align: center;
text-overflow: ellipsis;
white-space: nowrap;
overflow: hidden;
margin: 5px 15px;
}
.desc {
margin: 0 30px 10px;
height: 20px;
font-size: 12px;
color: #b0b0b0;
text-align: center;
text-overflow: ellipsis;
white-space: nowrap;
overflow: hidden;
}
.price {
margin: 0 10px 14px;
text-align: center;
color: $base-color;
del {
margin-left: 0.5em;
color: #b0b0b0;
}
}
}
}
}
.bottom-wrap {
margin-top: 10px;
width: $width;
height: 118px;
cursor: pointer;
overflow: hidden;
img {
max-width: 100%;
}
}
}
.box {
width: 100%;
position: relative;
}
.null-page {
width: 100%;
height: 730px;
background-color: #FFFFFF;
position: absolute;
top: 0;
left: 0;
z-index: 9;
}
.collection {
background: #ffffff;
padding: 10px 20px;
.goods {
display: flex;
flex-wrap: wrap;
.goods-wrap {
width: 19%;
margin-right: 1.25%;
margin-bottom: 20px;
&:nth-child(5n) {
margin-right: 0;
}
.goods-item {
border: 1px solid #f1f1f1;
box-sizing: border-box;
padding: 10px;
.img {
width: 100%;
height: 160px;
cursor: pointer;
position: relative;
img {
width: 100%;
height: 100%;
}
.del {
font-size: 20px;
position: absolute;
top: 2px;
right: 2px;
padding: 3px;
background: rgba($color: #000000, $alpha: 0.3);
display: none;
color: #ffffff;
}
&:hover {
.del {
display: block;
}
}
}
.goods-name {
width: 100%;
margin-top: 10px;
overflow: hidden;
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
height: 55px;
}
.price {
color: $base-color;
}
}
}
}
.shop {
display: flex;
flex-wrap: wrap;
.shop-wrap {
margin: 0 15px 20px 0;
&:nth-child(5n) {
margin-right: 0;
}
.shop-item {
width: 156px;
height: 227px;
border: 1px solid #eeeeee;
padding: 0 10px;
cursor: pointer;
.head-wrap {
text-align: center;
padding: 10px 0;
border-bottom: 1px solid #eeeeee;
position: relative;
.del {
font-size: 20px;
position: absolute;
top: 0px;
right: 0px;
padding: 3px;
background: rgba($color: #000000, $alpha: 0.3);
display: none;
color: #ffffff;
cursor: pointer;
}
&:hover {
.del {
display: block;
}
}
.img-wrap {
width: 60px;
height: 60px;
line-height: 60px;
display: inline-block;
}
.name {
display: block;
width: 100%;
height: 24px;
line-height: 24px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.tag {
margin-left: 5px;
}
}
.info-wrap {
padding: 10px 0;
}
}
}
}
.empty {
text-align: center;
}
.page {
text-align: center;
}
}
</style>

View File

@@ -0,0 +1,272 @@
<template>
<div class="box">
<div class="null-page" v-show="yes"></div>
<el-card class="box-card member-coupon">
<div slot="header" class="clearfix"><span>我的优惠券</span></div>
<div>
<div v-loading="loading">
<el-tabs v-model="couponstatus" @tab-click="handleClickStatus">
<el-tab-pane label="未使用" name="1"></el-tab-pane>
<el-tab-pane label="已使用" name="2"></el-tab-pane>
<el-tab-pane label="已过期" name="3"></el-tab-pane>
</el-tabs>
<div class="coupon-wrap">
<div class="text item" :class="state == '1' ? 'coupon-not-used' : state == '2' ? 'coupon-used' : 'coupon-expire'" v-for="(item, index) in couponList" :key="index" @click="useCoupon(item)">
<template>
<p class="coupon-wrap-money" v-if="item.discount == '0.00' || !item.discount">
<span>{{ item.money }}</span>
</p>
<p class="coupon-wrap-money" v-else>
<span>{{ item.discount }}</span>
</p>
</template>
<p class="coupon-wrap-name">{{ item.platformcoupon_name }}</p>
<template>
<p class="coupon-wrap-least coupon-wrap-info" v-if="item.at_least > 0">{{ item.at_least }}元可用</p>
<p class="coupon-wrap-least coupon-wrap-info" v-else>无门槛优惠券</p>
</template>
<template>
<p class="coupon-wrap-time coupon-wrap-info">{{item.end_time > 0 ? '有效期至' + $timeStampTurnTime(item.end_time) : '长期有效' }}</p>
</template>
</div>
<div class="empty-text" v-if="couponList.length == 0">{{ text }}</div>
</div>
<div class="pager">
<el-pagination
background
:pager-count="5"
:total="total"
prev-text="上一页"
next-text="下一页"
:current-page.sync="currentPage"
:page-size.sync="pageSize"
@size-change="handlePageSizeChange"
@current-change="handleCurrentPageChange"
hide-on-single-page
></el-pagination>
</div>
</div>
</div>
</el-card>
</div>
</template>
<script>
import {couponList as getCouponList} from '@/api/member/member';
import {mapGetters} from 'vuex';
export default {
name: 'my_coupon',
layout: "member",
components: {},
data: () => {
return {
total: 0,
currentPage: 1,
pageSize: 9,
couponstatus: '1',
couponList: [],
type: '',
state: 1,
text: '您还没有优惠券哦',
loading: true,
yes: true
};
},
created() {
if (this.addonIsExit && this.addonIsExit.coupon != 1) {
this.$message({
message: '优惠券插件未安装',
type: 'warning',
duration: 2000,
onClose: () => {
this.$route.push('/member');
}
});
} else {
this.getListData();
}
},
mounted() {
let self = this;
setTimeout(function () {
self.yes = false
}, 300)
},
computed: {
...mapGetters(['addonIsExit'])
},
watch: {
addonIsExit() {
if (this.addonIsExit.coupon != 1) {
this.$message({
message: '优惠券插件未安装',
type: 'warning',
duration: 2000,
onClose: () => {
this.$route.push('/member');
}
});
}
}
},
methods: {
/**
* 优惠券状态(未使用/已使用/已过期)
*/
handleClickStatus(tab, event) {
if (tab.name == '1') {
this.state = 1;
this.text = '您还没有优惠券哦';
} else if (tab.name == '2') {
this.state = 2;
this.text = '您还没有使用过优惠券哦';
} else {
this.state = 3;
this.text = '您还没有过期优惠券哦';
}
this.refresh();
},
handlePageSizeChange(size) {
this.pageSize = size;
this.refresh();
},
handleCurrentPageChange(page) {
this.currentPage = page;
this.refresh();
},
refresh() {
this.loading = true;
this.getListData();
},
// 获取优惠券列表
getListData() {
getCouponList({
page: this.currentPage,
page_size: this.pageSize,
state: this.state,
is_own: this.type,
}).then(res => {
if (res.code >= 0) {
this.total = res.data.count;
this.couponList = res.data.list;
}
this.loading = false;
}).catch(err => {
this.loading = false;
this.$message.error(err.message);
});
},
// 去使用优惠券
useCoupon(item) {
if (item.state == 1) {
if (item.use_scenario != 1) {
this.$router.push({path: '/goods/list', query: {coupon: item.coupon_type_id}});
} else {
this.$router.push('/goods/list');
}
}
}
}
};
</script>
<style lang="scss" scoped>
.box {
width: 100%;
position: relative;
}
.null-page {
width: 100%;
height: 730px;
background-color: #FFFFFF;
position: absolute;
top: 0;
left: 0;
z-index: 9;
}
.el-card.is-always-shadow,
.el-card.is-hover-shadow:focus,
.el-card.is-hover-shadow:hover {
box-shadow: unset;
}
.el-card {
border: 0;
}
.coupon-wrap {
display: flex;
align-items: center;
flex-wrap: wrap;
.text {
width: 32%;
height: 140px;
margin-right: 2%;
border-radius: 5px;
border: 1px dashed #fff;
margin-bottom: 20px;
padding: 0 15px;
box-sizing: border-box;
color: #ffffff;
.coupon-wrap-money {
span {
font-size: 30px;
margin-right: 5px;
}
}
.coupon-wrap-info {
font-size: 12px;
line-height: 18px;
}
}
.text:nth-child(3n) {
margin-right: 0;
}
.coupon-not-used {
background-color: $base-color;
cursor: pointer;
}
.coupon-used {
background-color: hsl(360, 50%, 70%);
}
.coupon-expire {
background-color: #d0d0d0;
}
.coupon-wrap-info {
font-size: 12px;
line-height: 20px;
}
.empty-text {
margin: 0 auto;
}
}
</style>
<style lang="scss">
.member-coupon {
.el-tabs__active-bar,
.el-tabs__nav-wrap::after {
/* 清除tab标签底部横线 */
height: 0;
}
}
</style>

View File

@@ -0,0 +1,280 @@
<template>
<div class="box" v-loading="loading">
<div class="null-page" v-show="yes"></div>
<el-card class="box-card">
<div slot="header" class="clearfix">
<span>收货地址</span>
</div>
<div>
<div class="ns-member-address-list">
<div class="text item ns-add-address" @click="addAddress('add')">
<span>+ 添加收货地址</span>
</div>
<div class="text item" v-for="(item, index) in addressList" :key="index">
<div class="text-name">
<span>{{ item.name }}</span>
<span v-if="item.is_default == 1" class="text-default">默认</span>
</div>
<div class="text-content">
<p>{{ item.mobile }}</p>
<p :title="item.full_address + item.address" class="ns-address-detail">
{{ item.full_address }}{{ item.address }}</p>
</div>
<div class="text-operation">
<span v-if="item.is_default != 1" @click="setDefault(item.id)">设为默认</span>
<span @click="addAddress('edit', item.id)">编辑</span>
<span v-if="item.is_default != 1" @click="delAddress(item.id, item.is_default)">删除</span>
</div>
</div>
</div>
<div class="pager">
<el-pagination background :pager-count="5" :total="total" prev-text="上一页" next-text="下一页"
:current-page.sync="currentPage" :page-size.sync="pageSize" @size-change="handlePageSizeChange"
@current-change="handleCurrentPageChange" hide-on-single-page></el-pagination>
</div>
</div>
</el-card>
</div>
</template>
<script>
import {
addressList,
setDefault,
deleteAddress
} from "@/api/member/member"
export default {
name: "delivery_address",
layout: "member",
components: {},
data: () => {
return {
addressList: [],
total: 0,
currentPage: 1,
pageSize: 8,
loading: true,
yes: true
}
},
created() {
this.getListData()
},
mounted() {
let self = this;
setTimeout(function () {
self.yes = false
}, 300)
},
methods: {
getListData() {
addressList({
page: this.currentPage,
page_size: this.pageSize,
type: 1
})
.then(res => {
const {
count,
page_count,
list
} = res.data
this.total = count
this.addressList = list
this.loading = false
})
.catch(err => {
this.loading = false
this.$message.error(err.message)
})
},
handlePageSizeChange(size) {
this.pageSize = size
this.refresh()
},
handleCurrentPageChange(page) {
this.currentPage = page
this.refresh()
},
refresh() {
this.loading = true
this.getListData()
},
/**
* 设为默认
*/
setDefault(id) {
setDefault({
id: id
}).then(res => {
this.refresh()
this.$message({
message: "修改默认地址成功",
type: "success"
})
}).catch(err => {
this.$message.error(err.message)
})
},
/**
* 添加/编辑地址
*/
addAddress(type, id) {
if (type == "edit") {
this.$router.push({
path: "/member/address_edit",
query: {
id: id
}
})
} else {
this.$router.push({
path: "/member/address_edit"
})
}
},
/**
* 删除地址
*/
delAddress(id, is_default) {
this.$confirm("确定要删除该地址吗?", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning"
}).then(() => {
if (is_default == 1) {
this.$message({
type: "warning",
message: "默认地址,不能删除!"
})
return
}
deleteAddress({
id: id
}).then(res => {
this.refresh()
this.$message({
message: res.message,
type: "success"
})
}).catch(err => {
this.$message.error(err.message)
})
})
}
}
}
</script>
<style lang="scss" scoped>
.box {
width: 100%;
position: relative;
}
.null-page {
width: 100%;
height: 730px;
background-color: #FFFFFF;
position: absolute;
top: 0;
left: 0;
z-index: 9;
}
.el-card.is-always-shadow,
.el-card.is-hover-shadow:focus,
.el-card.is-hover-shadow:hover {
box-shadow: unset;
}
.el-card {
border: 0;
}
.ns-member-address-list {
display: flex;
flex-wrap: wrap;
.text {
width: 32%;
height: 140px;
margin-right: 2%;
border-radius: 5px;
border: 1px solid #d8d8d8;
margin-bottom: 20px;
padding: 0 15px;
box-sizing: border-box;
.text-name {
height: 37px;
line-height: 40px;
padding: 0 10px;
border-bottom: 1px solid #eeeeee;
}
.text-default {
display: inline-block;
margin-left: 10px;
background: $base-color;
color: #ffffff;
width: 35px;
height: 20px;
line-height: 20px;
text-align: center;
border-radius: 3px;
}
.text-content {
padding: 10px;
}
.ns-address-detail {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.text-operation {
// 操作
text-align: right;
span {
margin: 0 5px;
color: #999999;
cursor: pointer;
}
span:hover {
color: $base-color;
}
}
}
.text:nth-child(3n) {
margin-right: 0;
}
.ns-add-address {
border: 1px dashed #d8d8d8;
text-align: center;
color: #999999;
line-height: 140px;
cursor: pointer;
}
.ns-add-address:hover {
border-color: $base-color;
color: $base-color;
}
}
</style>

View File

@@ -0,0 +1,223 @@
<template>
<div class="box">
<div class="null-page" v-show="yes"></div>
<el-card class="box-card foot-print">
<div slot="header" class="clearfix">
<span>我的足迹</span>
</div>
<div v-loading="loading" v-if="timesArr != ''">
<el-timeline>
<el-timeline-item class="ns-time-line" v-for="(item, index) in timesArr" :timestamp="item" placement="top" :key="index">
<el-card>
<div class="ns-goods-list">
<div class="ns-goods-li" v-for="(value, name) in footPrintData" :key="name" v-if="item == value.browse_time" @click="$util.pushToTab('/sku/' + value.sku_id)">
<span class="ns-btn-del" @click.stop="deleteFootprint(value.id)"><i class="iconfont icon-shanchu"></i></span>
<el-image :src="$img(value.goods_image, { size: 'mid' })" fit="contain" @error="imageError(name)"/>
<p class="goods-name" :title="value.goods_name">{{ value.goods_name }}</p>
<span class="goods-price">{{ value.goods_price }}</span>
</div>
</div>
</el-card>
</el-timeline-item>
</el-timeline>
</div>
<div v-else class="footprint">
<router-link to="/">暂时没有足迹~</router-link>
</div>
</el-card>
</div>
</template>
<script>
import {footPrint, delFootprint} from "@/api/member/member"
import {mapGetters} from "vuex"
export default {
name: "footprint",
layout: "member",
components: {},
data: () => {
return {
timesArr: [],
footPrintData: [],
loading: true,
yes: true
}
},
created() {
this.getFootPrintData()
},
computed: {
...mapGetters(["defaultGoodsImage"])
},
mounted() {
let self = this;
setTimeout(function () {
self.yes = false
}, 300)
},
methods: {
/**
* 商品列表
*/
getFootPrintData() {
footPrint({
page: 1,
page_size: 0
}).then(res => {
var data = res.data.list
this.footPrintData = []
this.timesArr = []
for (let i = 0; i < data.length; i++) {
var date = this.$util.timeStampTurnTime(data[i].browse_time).split(" ")[0]
var flag = this.$util.inArray(date, this.timesArr)
if (flag == -1) {
this.timesArr.push(date)
}
var goods = {}
goods.id = data[i].id
goods.sku_id = data[i].sku_id
goods.browse_time = date
goods.goods_image = data[i].sku_image.split(",")[0]
goods.goods_name = data[i].sku_name
goods.goods_price = data[i].discount_price
this.footPrintData.push(goods)
}
this.loading = false
}).catch(err => {
this.loading = false
})
},
/**
* 图片加载失败
*/
imageError(index) {
this.footPrintData[index].goods_image = this.defaultGoodsImage
},
/**
* 删除某个足迹
*/
deleteFootprint(id) {
delFootprint({
id: id
}).then(res => {
this.loading = false
this.getFootPrintData()
this.$message({message: res.message, type: "success"})
}).catch(err => {
this.loading = false
this.$message.error(err.message)
})
},
mouseenter(scope) {
this.$set(scope, "del", true)
},
mouseleave(scope) {
this.$set(scope, "del", false)
}
}
}
</script>
<style lang="scss" scoped>
.footprint {
width: 100%;
text-align: center;
}
.box {
width: 100%;
position: relative;
}
.null-page {
width: 100%;
height: 730px;
background-color: #FFFFFF;
position: absolute;
top: 0;
left: 0;
z-index: 9;
}
.el-card.is-always-shadow,
.el-card.is-hover-shadow:focus,
.el-card.is-hover-shadow:hover {
box-shadow: unset;
}
.el-card {
border: 0;
}
.ns-goods-list {
display: flex;
flex-wrap: wrap;
.ns-goods-li {
width: 32%;
margin-right: 2%;
margin-bottom: 20px;
padding: 15px;
box-sizing: border-box;
background-color: #f1f1f1;
border-radius: 5px;
cursor: pointer;
position: relative;
.el-image {
width: 100%;
height: 250px;
}
.goods-name {
margin-top: 10px;
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 2;
overflow: hidden;
}
.goods-price {
color: $base-color;
font-size: 20px;
}
.ns-btn-del {
position: absolute;
top: -6px;
right: -6px;
color: #999999;
cursor: pointer;
display: none;
width: 20px;
height: 20px;
text-align: center;
line-height: 20px;
i {
font-size: 20px;
}
}
&:hover {
.ns-btn-del {
display: inline-block;
}
}
}
.ns-goods-li:nth-child(3n) {
margin-right: 0;
}
}
</style>
<style lang="scss">
.foot-print .ns-time-line .el-timeline-item__timestamp.is-top {
font-size: 18px;
color: #333333;
}
</style>

View File

@@ -0,0 +1,720 @@
<template>
<div class="box">
<div class="null-page" v-show="yes"></div>
<div class="member-index" v-loading="loading">
<div class="member-top">
<div class="info-wrap">
<div class="info-top">
<div class="avtar">
<router-link to="/member/info">
<img v-if="member.headimg" :src="$img(member.headimg)" @error="member.headimg = defaultHeadImage" />
<img v-else :src="$img(defaultHeadImage)" />
</router-link>
</div>
<div class="member-wrap">
<template v-if="member">
<div class="name member-name" v-if="member.nickname">
<router-link to="/member/info">{{ member.nickname }}</router-link>
</div>
<div class="level" v-if="member.member_level_name">{{ member.member_level_name }}</div>
<div class="growth">
成长值
<el-progress :text-inside="true" :stroke-width="10" :percentage="progress" :show-text="false"></el-progress>
<div></div>
</div>
</template>
<div class="no-login name" v-else>未登录</div>
</div>
</div>
<div class="account">
<div class="content">
<div class="item">
<router-link to="/member/coupon" class="item-content">
<img src="@/assets/images/coupon.png" alt />
<div class="name">优惠券</div>
<div class="num" v-if="member.member_id && couponNum">{{ couponNum }}</div>
<div class="num" v-else>0</div>
</router-link>
</div>
<div class="item">
<router-link to="/member/my_point" class="item-content">
<img src="@/assets/images/point.png" alt />
<div class="name">积分</div>
<div class="num" v-if="member.point">{{ member.point }}</div>
<div class="num" v-else>0</div>
</router-link>
</div>
<div class="item">
<router-link to="/member/account" class="item-content">
<img src="@/assets/images/balance.png" alt />
<div class="name">余额</div>
<div class="num" v-if="member.balance || member.balance_money">{{ (parseFloat(member.balance) + parseFloat(member.balance_money)).toFixed(2) }}</div>
<div class="num" v-else>0</div>
</router-link>
</div>
</div>
</div>
</div>
<div class="collection">
<router-link to="/member/collection" class="item-content">
<div class="title">我的关注</div>
<div class="xian"></div>
<div class="item-wrap">
<div class="item">
<div class="num">{{ goodsTotal }}</div>
<div class="collect">商品关注</div>
</div>
</div>
</router-link>
</div>
</div>
<div class="member-bottom">
<div class="my-order">
<div class="order-title">我的订单</div>
<div class="xian"></div>
<div class="order-item">
<router-link to="/member/order_list?status=waitpay" class="item">
<i class="iconfont icon-daifukuan"></i>
<div v-if="orderNum.waitPay" class="order-num">{{ orderNum.waitPay }}</div>
<div class="name">待付款</div>
</router-link>
<router-link to="/member/order_list?status=waitsend" class="item">
<i class="iconfont icon-daifahuo"></i>
<div v-if="orderNum.readyDelivery" class="order-num">{{ orderNum.readyDelivery }}</div>
<div class="name">待发货</div>
</router-link>
<router-link to="/member/order_list?status=waitconfirm" class="item">
<i class="iconfont icon-tubiaolunkuo-"></i>
<div v-if="orderNum.waitDelivery" class="order-num">{{ orderNum.waitDelivery }}</div>
<div class="name">待收货</div>
</router-link>
<router-link to="/member/order_list?status=waitrate" class="item">
<i class="iconfont icon-daipingjia"></i>
<div v-if="orderNum.waitEvaluate" class="order-num">{{ orderNum.waitEvaluate }}</div>
<div class="name">待评价</div>
</router-link>
<router-link to="/member/activist" class="item">
<i class="iconfont icon-shouhou"></i>
<div v-if="orderNum.refunding" class="order-num">{{ orderNum.refunding }}</div>
<div class="name">退款/售后</div>
</router-link>
</div>
<div v-if="orderList.length">
<div class="order-goods-wrap" v-for="(orderItem, orderIndex) in orderList" :key="orderIndex">
<div class="order-goods" v-for="(goodsItem, goodsIndex) in orderItem.order_goods" :key="goodsIndex">
<div class="goods-item">
<div class="goods-img" @click="$util.pushToTab({ path: '/sku/' + goodsItem.sku_id })">
<img :src="$img(goodsItem.sku_image, { size: 'mid' })" @error="imageErrorOrder(orderIndex, goodsIndex)" />
</div>
<div class="info-wrap">
<div class="goods-name" @click="$util.pushToTab({ path: '/sku/' + goodsItem.sku_id })">{{ goodsItem.sku_name }}</div>
<div class="price">{{ goodsItem.price }}</div>
</div>
<div class="payment">{{ orderItem.order_status_name }}</div>
<div class="goods-detail" @click="orderDetail(orderItem)">
<p>查看详情</p>
</div>
</div>
</div>
</div>
</div>
<div class="empty" v-else>
<img src="@/assets/images/member-empty.png" alt />
<div>
<router-link to="/">您买的东西太少了这里都空空的快去挑选合适的商品吧</router-link>
</div>
</div>
</div>
<div class="bottom-right">
<div class="my-foot">
<div class="title">我的足迹</div>
<div class="xian"></div>
<div class="foot-content" v-for="(item, index) in footList" :key="item.goods_id">
<div class="foot-item" @click="$util.pushToTab({ path: '/sku/' + item.sku_id })">
<div class="foot-img">
<img :src="$img(item.sku_image, { size: 'mid' })" @error="imageErrorFoot(index)" />
</div>
<div class="foot-info">
<div class="foot-name">{{ item.goods_name }}</div>
<div class="foot-price">{{ item.discount_price }}</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
import {
orderNum,
couponNum,
footprint,
levelList
} from '@/api/member/index';
import {
goodsCollect
} from '@/api/member/collection';
import {
apiOrderList
} from '@/api/order/order';
import {
mapGetters
} from 'vuex';
export default {
name: 'member',
components: {},
layout: 'member',
data: () => {
return {
couponNum: 0,
orderNum: {
waitPay: 0, //待付款
readyDelivery: 0, //待发货
waitDelivery: 0, //待收货
refunding: 0 // 退款中
},
orderList: [],
orderStatus: 'all',
footInfo: {
page: 1,
page_size: 6
},
total: 0,
footList: [],
currentPage: 1,
loading: true,
goodsTotal: 0,
state: '',
growth: '',
levelList: [],
member_level: {},
progress: 0,
yes: true
};
},
created() {
this.getCouponNum();
this.getOrderNum();
this.getOrderList();
this.getFootprint();
this.getGoodsCollect();
// this.$store.dispatch("member/member_detail")
this.$forceUpdate()
},
computed: {
...mapGetters(['defaultHeadImage', 'defaultGoodsImage', 'member'])
},
watch: {
member: {
handler() {
if (this.member) this.getLevelList();
},
immediate: true,
deep: true,
}
},
mounted() {
let self = this;
setTimeout(function () {
self.yes = false;
}, 300);
},
methods: {
getLevelList() {
levelList().then(res => {
if (res.data && res.code == 0) {
this.levelList = res.data;
let listIndex = this.levelList.findIndex(item => item.level_id == this.member.member_level);
const max = this.levelList.length;
if (max > listIndex + 1) {
if (this.member.growth > this.levelList[listIndex + 1].growth) {
this.progress = 100;
} else {
this.progress = (this.member.growth / this.levelList[listIndex + 1].growth) * 100;
}
} else {
this.progress = 100;
}
} else {
this.$message.error(err.message);
}
})
},
//获取优惠券数量
getCouponNum() {
couponNum().then(res => {
this.couponNum = res.data;
})
},
//获取订单数量
getOrderNum() {
orderNum({
order_status: 'waitpay,waitsend,waitconfirm,waitrate,refunding'
}).then(res => {
if (res.code == 0) {
this.orderNum.waitPay = res.data.waitpay;
this.orderNum.readyDelivery = res.data.waitsend;
this.orderNum.waitDelivery = res.data.waitconfirm;
this.orderNum.waitEvaluate = res.data.waitrate;
this.orderNum.refunding = res.data.refunding;
}
})
},
//获取订单列表
getOrderList() {
apiOrderList({
order_status: this.orderStatus,
page: 1,
page_size: 3
}).then(res => {
if (res.code == 0 && res.data) {
this.orderList = res.data.list;
}
this.loading = false;
}).catch(err => {
this.loading = false;
this.$message.error(err.message);
});
},
//获取我的足迹
getFootprint() {
footprint(this.footInfo).then(res => {
if (res.code == 0 && res.data) {
this.footList = res.data.list;
this.total = res.data.count;
}
})
},
orderDetail(data) {
switch (parseInt(data.order_type)) {
case 2:
// 自提订单
this.$router.push({
path: '/member/order_detail_pickup',
query: {
order_id: data.order_id
}
});
break;
case 3:
// 本地配送订单
this.$router.push({
path: '/member/order_detail_local_delivery',
query: {
order_id: data.order_id
}
});
break;
case 4:
// 虚拟订单
this.$router.push({
path: '/member/order_detail_virtual',
query: {
order_id: data.order_id
}
});
break;
default:
this.$router.push({
path: '/member/order_detail',
query: {
order_id: data.order_id
}
});
break;
}
},
imageErrorOrder(orderIndex, goodsIndex) {
this.orderList[orderIndex].order_goods[goodsIndex].sku_image = this.defaultGoodsImage;
},
imageErrorFoot(index) {
this.footList[index].sku_image = this.defaultGoodsImage;
},
getGoodsCollect() {
goodsCollect()
.then(res => {
this.goodsTotal = res.data.count;
})
.catch(err => {
this.loading = false;
console.log(err.message);
});
}
}
};
</script>
<style lang="scss" scoped>
.box {
width: 100%;
position: relative;
}
.null-page {
width: 100%;
height: 730px;
background-color: #ffffff;
position: absolute;
top: 0;
left: 0;
z-index: 9;
}
.member-index {
.member-top {
width: 100%;
display: flex;
.info-wrap {
width: 75%;
height: 160px;
border: 1px solid #e9e9e9;
background: #ffffff;
display: flex;
.info-top {
display: flex;
align-items: center;
margin: 22px;
margin-right: 0;
width: 300px;
border-right: 1px solid #e9e9e9;
.avtar {
width: 84px;
height: 84px;
margin: 20px 0 10px 0;
border: 1px solid #e9e9e9;
border-radius: 50%;
overflow: hidden;
display: block;
cursor: pointer;
margin-left: 21px;
text-align: center;
line-height: 84px;
img {
display: inline-block;
}
}
.member-wrap {
margin-left: 20px;
.name {
font-size: 18px;
font-weight: 600;
cursor: pointer;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.growth {
display: flex;
align-items: center;
}
.el-progress {
width: 100px;
}
.level {
padding: 3px 4px;
line-height: 1;
color: #ffffc1;
margin: 6px 0;
cursor: default;
background: linear-gradient(#636362, #4e4e4d);
border-radius: 3px;
display: inline-block;
}
}
}
.account {
width: 400px;
display: flex;
align-items: center;
.content {
display: flex;
justify-content: center;
align-items: center;
width: 100%;
.item {
flex: 1;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
.item-content {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
}
img {
width: 50px;
height: 50px;
}
.name {
margin-top: 5px;
color: #666666;
&:hover {
color: $base-color;
}
}
.num {
color: $ns-text-color-black;
}
}
}
}
}
.collection {
background: #ffffff;
margin-left: 20px;
width: 210px;
border: 1px solid #e9e9e9;
padding-left: 20px;
.title {
padding: 10px 0;
display: inline-block;
border-bottom: 1px solid $base-color;
}
.xian {
height: 1px;
background: #f1f1f1;
}
.item-wrap {
display: flex;
justify-content: center;
align-items: center;
.item {
flex: 1;
margin-top: 37px;
.num {
}
.collect {
color: #666666;
}
}
}
}
}
.member-bottom {
width: 100%;
margin-top: 15px;
height: 553px;
display: flex;
overflow: hidden;
.my-order {
width: 75%;
background-color: #ffffff;
.order-title {
font-size: $ns-font-size-base;
padding: 10px 0;
margin-left: 15px;
border-bottom: 1px solid $base-color;
display: inline-block;
}
.xian {
height: 1px;
background: #f1f1f1;
margin-left: 15px;
}
.order-item {
display: flex;
justify-content: center;
align-content: center;
.item {
flex: 1;
text-align: center;
height: 85px;
padding-top: 20px;
cursor: pointer;
position: relative;
&:hover {
background: #ffffff;
box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
}
.order-num {
position: absolute;
top: 23px;
right: 25px;
background: $base-color;
border-radius: 50%;
width: 18px;
height: 18px;
line-height: 18px;
color: #ffff;
}
i {
font-size: 30px;
}
.name {
font-size: $ns-font-size-base;
}
}
}
.order-goods {
.goods-item {
display: flex;
padding: 14px;
border-top: 1px solid #f1f1f1;
.goods-img {
flex: 1;
display: flex;
justify-content: center;
align-items: center;
cursor: pointer;
img {
width: 60px;
height: 60px;
}
}
.info-wrap {
flex: 3;
width: 80%;
.goods-name {
height: 46px;
overflow: hidden;
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
}
.price {
color: $base-color;
}
}
.payment {
flex: 2;
display: flex;
align-items: center;
justify-content: center;
text-overflow: ellipsis;
}
.goods-detail {
flex: 2;
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
&:hover {
color: $base-color;
}
}
}
}
}
.bottom-right {
.my-foot {
background: #ffffff;
margin-left: 20px;
width: 230px;
.title {
font-size: $ns-font-size-base;
padding: 10px 0;
display: inline-block;
border-bottom: 1px solid $base-color;
margin: 0 15px;
}
.xian {
margin-left: 15px;
background: #f1f1f1;
height: 1px;
}
.foot-content {
.foot-item {
display: flex;
padding: 10px 0;
margin: 0 15px;
.foot-img {
width: 57px;
height: 57px;
cursor: pointer;
img {
width: 100%;
height: 100%;
}
}
.foot-info {
margin-left: 5px;
display: flex;
flex-direction: column;
justify-content: space-between;
.foot-name {
overflow: hidden;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
line-height: 1;
width: 140px;
}
.foot-price {
color: $base-color;
}
}
}
}
}
}
}
}
.empty {
text-align: center;
margin-top: 65px;
}
</style>

View File

@@ -0,0 +1,240 @@
<template>
<div class="box">
<div class="null-page" v-show="yes"></div>
<div class="member-info" v-loading="loading">
<el-tabs v-model="activeName" type="card" @tab-click="handleClick">
<el-tab-pane label="基本信息" name="first">
<el-form ref="infoRef" :model="memberInfo" :rules="infoRules" label-width="80px">
<el-form-item label="账号" v-if="memberInfo.userName">
<p>{{ memberInfo.userName }}</p>
</el-form-item>
<!-- <el-form-item label="邮箱">
<p v-if="memberInfo.email">{{ memberInfo.email }}</p>
<p v-else class="toBind" @click="$router.push({ path: '/member/security' })">去绑定</p>
</el-form-item> -->
<el-form-item label="手机号">
<p v-if="memberInfo.tell">{{ memberInfo.tell }}</p>
<p v-else class="toBind" @click="$router.push({ path: '/member/security' })">去绑定</p>
</el-form-item>
<el-form-item label="昵称" prop="nickName">
<el-input v-model="memberInfo.nickName"></el-input>
</el-form-item>
</el-form>
<div class="btn">
<el-button size="medium" type="primary" @click="saveInfo">保存</el-button>
</div>
</el-tab-pane>
<el-tab-pane label="头像照片" name="second">
<div class="preview">
<div class="title">头像预览</div>
<div class="content">
完善个人信息资料上传头像图片有助于您结识更多的朋友
<br />
头像最佳默认尺寸为120x120像素
</div>
</div>
<el-upload :action="uploadActionUrl" :show-file-list="false" :on-success="handleAvatarSuccess" class="upload" accept=".png,.jpg,.jpeg">
<div class="img-wrap">
<img v-if="memberInfo.userHeadImg" :src="$img(memberInfo.userHeadImg)" />
<img v-else :src="$img(defaultHeadImage)" />
</div>
</el-upload>
<div class="btn">
<el-button size="medium" type="primary" @click="uploadHeadImg">保存</el-button>
</div>
</el-tab-pane>
</el-tabs>
</div>
</div>
</template>
<script>
import {info, nickName, headImg} from '@/api/member/info';
import Config from '@/plugins/config';
import {mapGetters} from 'vuex';
import {email} from '@/api/member/security';
export default {
name: 'info',
layout: "member",
components: {},
data: () => {
return {
memberInfo: {
userHeadImg: '',
userName: '', //账号
nickName: '', //昵称
email: '',
tell: ''
},
infoRules: {
nickName: [{required: true, message: '请输入昵称', trigger: 'blur'}, {
max: 30,
message: '最大长度为30个字符',
trigger: 'blur'
}]
},
activeName: 'first',
loading: true,
uploadActionUrl: Config.baseUrl + '/api/upload/headimg',
imgUrl: '',
yes: true
};
},
created() {
this.getInfo();
},
mounted() {
let self = this;
setTimeout(function () {
self.yes = false
}, 300)
},
methods: {
getInfo() {
info().then(res => {
if (res.code == 0) {
this.memberInfo.userHeadImg = res.data.headimg;
this.memberInfo.userName = res.data.username;
this.memberInfo.nickName = res.data.nickname;
this.memberInfo.email = res.data.email;
this.memberInfo.tell = res.data.mobile;
}
this.loading = false;
}).catch(err => {
this.loading = false;
this.$message.error(err.message);
});
},
handleClick(tab, event) {
},
saveInfo() {
this.$refs.infoRef.validate(valid => {
if (valid) {
nickName({nickname: this.memberInfo.nickName}).then(res => {
if (res.code == 0) {
this.$message({message: '修改昵称成功', type: 'success'});
this.getInfo();
this.$store.dispatch('member/member_detail', {refresh: 1});
}
}).catch(err => {
this.$message.error(err.message);
});
} else {
return false;
}
});
},
handleAvatarSuccess(res, file) {
this.imgUrl = res.data.pic_path;
this.memberInfo.userHeadImg = URL.createObjectURL(file.raw);
},
uploadHeadImg() {
headImg({headimg: this.imgUrl}).then(res => {
if (res.code == 0) {
this.$message({message: '头像修改成功', type: 'success'});
this.$store.dispatch('member/member_detail', {refresh: 1});
}
}).catch(err => {
this.$message.error(err.message);
});
}
},
computed: {
...mapGetters(['defaultHeadImage'])
}
};
</script>
<style>
.member-info .el-upload {
display: flex;
justify-content: center;
margin-bottom: 20px;
}
</style>
<style lang="scss" scoped>
.box {
width: 100%;
position: relative;
}
.null-page {
width: 100%;
height: 730px;
background-color: #FFFFFF;
position: absolute;
top: 0;
left: 0;
z-index: 9;
}
.member-info {
background: #ffffff;
padding: 20px;
.el-tab-pane {
display: flex;
flex-direction: column;
justify-content: center;
align-content: center;
.preview {
display: flex;
justify-content: center;
margin-bottom: 20px;
.title {
margin-right: 20px;
line-height: 3;
}
.content {
color: $base-color;
line-height: 1.5;
}
}
.upload {
display: flex;
justify-content: center;
}
.el-upload {
width: 120px;
}
.img-wrap {
width: 120px;
height: 120px;
display: block;
line-height: 120px;
overflow: hidden;
border: 1px solid #f1f1f1;
cursor: pointer;
img {
display: inline-block;
}
}
.el-form {
margin-top: 20px;
width: 500px;
margin-left: 200px;
.toBind {
cursor: pointer;
&:hover {
color: $base-color;
}
}
}
.btn {
text-align: center;
}
}
}
</style>

View File

@@ -0,0 +1,144 @@
<template>
<div class="box">
<div class="null-page" v-show="yes"></div>
<div class="my-point" v-loading="loading">
<div class="member-point">
<div class="title">我的积分</div>
<div class="num">{{ memberPoint.point ? Math.ceil(memberPoint.point) : 0 }}</div>
</div>
<div class="detail">
<el-table :data="pointList" border>
<el-table-column prop="type_name" label="来源" width="150"></el-table-column>
<el-table-column prop="pointNum" label="积分" width="150"></el-table-column>
<el-table-column prop="remark" label="详细说明"></el-table-column>
<el-table-column prop="time" label="时间" width="180"></el-table-column>
</el-table>
</div>
<div class="pager">
<el-pagination
background
:pager-count="5"
:total="total"
prev-text="上一页"
next-text="下一页"
:current-page.sync="pointInfo.page"
:page-size.sync="pointInfo.page_size"
@size-change="handlePageSizeChange"
@current-change="handleCurrentPageChange"
hide-on-single-page
></el-pagination>
</div>
</div>
</div>
</template>
<script>
import {pointInfo, pointList} from "@/api/member/my_point"
export default {
name: "my_point",
layout: "member",
components: {},
data: () => {
return {
pointInfo: {
page: 1,
page_size: 10,
account_type: "point"
},
pointList: [],
memberPoint: {
point: 0
},
total: 0,
loading: true,
yes: true
}
},
created() {
this.getPointInfo();
this.getPointList()
},
mounted() {
let self = this;
setTimeout(function () {
self.yes = false
}, 300)
},
methods: {
getPointInfo() {
pointInfo({account_type: this.pointInfo.account_type}).then(res => {
if (res.code == 0 && res.data) {
this.memberPoint = res.data
}
this.loading = false
}).catch(err => {
this.loading = false
this.$message.error(err.message)
})
},
getPointList() {
pointList(this.pointInfo).then(res => {
if (res.code == 0 && res.data) {
this.pointList = res.data.list
this.total = res.data.count
this.pointList.forEach(item => {
item.time = this.$util.timeStampTurnTime(item.create_time)
item.pointNum = item.account_data > 0 ? "+" + parseInt(item.account_data) : parseInt(item.account_data)
})
}
}).catch(err => {
this.$message.error(err.message)
})
},
handlePageSizeChange(num) {
this.pointInfo.page_size = num
this.getPointList()
},
handleCurrentPageChange(page) {
this.pointInfo.page = page
this.getPointList()
}
}
}
</script>
<style lang="scss" scoped>
.box {
width: 100%;
position: relative;
}
.null-page {
width: 100%;
height: 730px;
background-color: #FFFFFF;
position: absolute;
top: 0;
left: 0;
z-index: 9;
}
.my-point {
background: #ffffff;
padding: 20px;
.member-point {
font-size: $ns-font-size-base;
font-weight: 600;
margin-bottom: 10px;
.num {
font-size: 30px;
font-weight: 600;
}
}
.page {
display: flex;
justify-content: center;
align-content: center;
padding-top: 20px;
}
}
</style>

View File

@@ -0,0 +1,558 @@
<template>
<div class="box">
<div class="null-page" v-show="yes"></div>
<el-card class="box-card order-detail">
<div slot="header" class="clearfix">
<el-breadcrumb separator="/">
<el-breadcrumb-item :to="{ path: '/member/order_list' }">订单列表</el-breadcrumb-item>
<el-breadcrumb-item>订单详情</el-breadcrumb-item>
</el-breadcrumb>
</div>
<div v-loading="loading">
<template v-if="orderDetail">
<div class="order-status">
<h4>
订单状态
<span class="ns-text-color">{{ orderDetail.order_status_name }}</span>
</h4>
<div v-if="orderDetail.order_status == 0" class="go-pay">
<p>
需付款
<span>{{ orderDetail.pay_money }}</span>
</p>
</div>
<div class="operation" v-if="orderDetail.action.length > 0">
<el-button type="primary" size="mini" plain v-if="orderDetail.is_evaluate == 1" @click="operation('memberOrderEvaluation')">
<template v-if="orderDetail.evaluate_status == 0">评价</template>
<template v-else-if="orderDetail.evaluate_status == 1">追评</template>
</el-button>
<el-button type="primary" size="mini" :plain="operationItem.action == 'orderPay' ? false : true" v-for="(operationItem, operationIndex) in orderDetail.action" :key="operationIndex" @click="operation(operationItem.action)">
{{ operationItem.title }}
</el-button>
</div>
<div class="operation" v-else-if="orderDetail.action.length == 0 && orderDetail.is_evaluate == 1">
<el-button type="primary" size="mini" plain v-if="orderDetail.is_evaluate == 1" @click="operation('memberOrderEvaluation')">
<template v-if="orderDetail.evaluate_status == 0">评价</template>
<template v-else-if="orderDetail.evaluate_status == 1">追评</template>
</el-button>
</div>
</div>
<div class="order-info">
<h4>订单信息</h4>
<ul>
<!-- <li>
<i class="iconfont iconmendian"></i>
店铺
<router-link :to="'/shop-' + orderDetail.site_id" target="_blank">{{ orderDetail.site_name }}</router-link>
</li> -->
<li>订单类型{{ orderDetail.order_type_name }}</li>
<li>订单编号{{ orderDetail.order_no }}</li>
<li>订单交易号{{ orderDetail.out_trade_no }}</li>
<li>配送方式{{ orderDetail.delivery_type_name }}</li>
<li v-if="orderDetail.order_status == -1">退款途径{{ orderDetail.refund_money_type == 1 ? '原路退款' : orderDetail.refund_money_type == 2 ? '线下退款' : '退款到余额' }}</li>
<li>创建时间{{ $util.timeStampTurnTime(orderDetail.create_time) }}</li>
<li v-if="orderDetail.close_time > 0">关闭时间{{ $util.timeStampTurnTime(orderDetail.close_time) }}</li>
<template v-if="orderDetail.pay_status > 0">
<li>支付方式{{ orderDetail.pay_type_name }}</li>
<li>支付时间{{ $util.timeStampTurnTime(orderDetail.pay_time) }}</li>
</template>
<li v-if="orderDetail.promotion_type_name != ''">店铺活动{{ orderDetail.promotion_type_name }}</li>
<li v-if="orderDetail.buyer_message != ''">买家留言{{ orderDetail.buyer_message }}</li>
</ul>
</div>
<div class="order-info" v-if="orderDetail.pay_type=='offlinepay'&&orderDetail.offline_pay_info">
<h4>线下支付</h4>
<ul>
<li v-if="orderDetail.offline_pay_info.status_info.const=='WAIT_AUDIT'">
支付状态审核中
</li>
<li v-if="orderDetail.offline_pay_info.status_info.const=='AUDIT_REFUSE'">
支付状态审核被拒
</li>
<li v-if="orderDetail.offline_pay_info.status_info.const=='AUDIT_REFUSE'">
审核备注{{orderDetail.offline_pay_info.audit_remark}}
</li>
</ul>
</div>
<div class="take-delivery-info">
<h4>收货信息</h4>
<ul>
<li>收货人{{ orderDetail.name }}</li>
<li>手机号码{{ orderDetail.mobile }}</li>
<li>收货地址{{ orderDetail.full_address }} {{ orderDetail.address }}</li>
</ul>
</div>
<!-- 发票信息 -->
<div class="take-delivery-info" v-if="orderDetail.is_invoice ==1">
<h4>发票信息</h4>
<ul>
<li>发票类型{{ orderDetail.invoice_type == 1 ? '纸质发票' : '电子发票' }}</li>
<li>发票抬头类型{{ orderDetail.invoice_title_type ==1 ? '个人' : '企业' }}</li>
<li>发票抬头{{ orderDetail.invoice_title }}</li>
<li>发票内容{{ orderDetail.invoice_content }}</li>
<li v-if="orderDetail.invoice_type == 1">发票邮寄地址地址{{ orderDetail.invoice_full_address }}</li>
<li v-else>发票接收邮箱{{ orderDetail.invoice_email }}</li>
</ul>
</div>
<nav>
<li :class="{ 'no-operation': !orderDetail.is_enable_refund }">商品信息</li>
<li>单价</li>
<li>数量</li>
<li>小计</li>
<li v-if="orderDetail.is_enable_refund">操作</li>
</nav>
<!-- 订单项·商品 -->
<div class="list">
<ul class="item" v-for="(goodsItem, goodsIndex) in orderDetail.order_goods" :key="goodsIndex">
<li :class="{ 'no-operation': !orderDetail.is_enable_refund }">
<div class="img-wrap" @click="$util.pushToTab('/sku/' + goodsItem.sku_id)">
<img :src="$img(goodsItem.sku_image, { size: 'mid' })" @error="imageError(goodsIndex)" />
</div>
<div class="info-wrap">
<h5 @click="$util.pushToTab('/sku/' + goodsItem.sku_id)">{{ goodsItem.sku_name }}</h5>
<!-- <span>规格规格值</span> -->
</div>
</li>
<li>
<span>{{ goodsItem.price }}</span>
</li>
<li>
<span>{{ goodsItem.num }}</span>
</li>
<li>
<span>{{ (goodsItem.price * goodsItem.num).toFixed(2) }}</span>
</li>
<li>
<el-button type="primary" plain size="mini" v-if="orderDetail.is_enable_refund == 1 && goodsItem.refund_status == 0 && orderDetail.order_scene == 'online' && goodsItem.promotion_type != 'blindbox'" @click="$router.push({ path: '/order/refund', query: { order_goods_id: goodsItem.order_goods_id, order_id: orderId } })">申请退款</el-button>
<el-button type="primary" plain size="mini" v-if="goodsItem.refund_status != 0" @click="$router.push({ path: '/order/refund_detail', query: { order_goods_id: goodsItem.order_goods_id } })">{{goodsItem.refund_status_name}}</el-button>
</li>
</ul>
</div>
<!-- 订单总计 -->
<ul class="total">
<li>
<label>商品金额</label>
<span>{{ orderDetail.goods_money }}</span>
</li>
<li>
<label>运费</label>
<span>{{ orderDetail.delivery_money }}</span>
</li>
<li v-if="orderDetail.member_card_money > 0">
<label>会员卡</label>
<span>{{ orderDetail.member_card_money }}</span>
</li>
<li v-if="orderDetail.invoice_money > 0">
<label>税费</label>
<span>{{ orderDetail.invoice_money }}</span>
</li>
<li v-if="orderDetail.invoice_delivery_money > 0">
<label>发票邮寄费</label>
<span>{{ orderDetail.invoice_delivery_money }}</span>
</li>
<li v-if="orderDetail.adjust_money != 0">
<label>订单调整</label>
<span>
<template v-if="orderDetail.adjust_money < 0">-</template>
<template v-else>+</template>
{{ orderDetail.adjust_money | abs }}
</span>
</li>
<li v-if="orderDetail.promotion_money > 0">
<label>优惠</label>
<span>{{ orderDetail.promotion_money }}</span>
</li>
<li v-if="orderDetail.coupon_money > 0">
<label>优惠券</label>
<span>{{ orderDetail.coupon_money }}</span>
</li>
<li v-if="orderDetail.point_money > 0">
<label>积分抵扣</label>
<span>{{ orderDetail.point_money }}</span>
</li>
<li v-if="orderDetail.balance_money > 0">
<label>使用余额</label>
<span>{{ orderDetail.balance_money }}</span>
</li>
<li class="pay-money">
<label>实付款</label>
<span>{{ orderDetail.pay_money }}</span>
</li>
</ul>
</template>
</div>
</el-card>
</div>
</template>
<script>
import {
apiOrderDetail
} from '@/api/order/order';
import orderMethod from '@/utils/orderMethod';
import {
mapGetters
} from 'vuex';
export default {
name: 'order_detail',
components: {},
mixins: [orderMethod],
data: () => {
return {
orderId: 0,
orderDetail: null,
loading: true,
yes: true
};
},
created() {
this.orderId = this.$route.query.order_id;
this.getOrderDetail();
},
mounted() {
let self = this;
setTimeout(function () {
self.yes = false
}, 300)
},
computed: {
...mapGetters(['defaultGoodsImage'])
},
layout: 'member',
methods: {
getOrderDetail() {
apiOrderDetail({
order_id: this.orderId
}).then(res => {
if (res.code >= 0) {
this.orderDetail = res.data;
this.loading = false;
} else {
this.$message({
message: '未获取到订单信息',
type: 'warning',
duration: 2000,
onClose: () => {
this.$router.push({
path: '/member/order_list'
});
}
});
}
}).catch(err => {
this.loading = false;
this.$message.error({
message: err.message,
duration: 2000,
onClose: () => {
this.$router.push({
path: '/member/order_list'
});
}
});
});
},
operation(action) {
switch (action) {
case 'orderPay': // 支付
this.orderPay(this.orderDetail);
break;
case 'orderClose': //关闭
this.orderClose(this.orderDetail.order_id, () => {
this.getOrderDetail();
});
break;
case 'memberTakeDelivery': //收货
this.orderDelivery(this.orderDetail.order_id, () => {
this.getOrderDetail();
});
break;
case 'trace': //查看物流
this.$router.push({
path: '/order/logistics',
query: {
order_id: this.orderDetail.order_id
}
});
break;
case 'memberOrderEvaluation': //评价
this.$util.pushToTab({
path: '/order/evaluate',
query: {
order_id: this.orderDetail.order_id
}
});
break;
case 'memberBatchRefund': //批量退款
this.$router.push({
path: '/order/batchrefund',
query: {
order_id: this.orderId
}
});
break;
case 'orderOfflinePay': //线下支付
this.$router.push({
path: '/pay',
query: {
code: this.orderDetail.offline_pay_info.out_trade_no
}
});
break;
case 'orderDelete':
this.orderDelete(this.orderDetail.order_id, () => {
this.$router.push({
path: '/member/order_list',
});
});
break;
}
},
imageError(index) {
this.orderDetail.order_goods[index].sku_image = this.defaultGoodsImage;
}
},
filters: {
abs(value) {
return Math.abs(parseFloat(value)).toFixed(2);
}
}
};
</script>
<style lang="scss" scoped>
.box {
width: 100%;
position: relative;
}
.null-page {
width: 100%;
height: 730px;
background-color: #FFFFFF;
position: absolute;
top: 0;
left: 0;
z-index: 9;
}
.order-detail {
.order-status {
background-color: #fff;
margin-bottom: 20px;
h4 {
margin: 10px 0 20px;
border-bottom: 1px solid #eeeeee;
padding-bottom: 10px;
}
.go-pay {
p {
display: inline-block;
vertical-align: middle;
span {
font-weight: bold;
color: $base-color;
font-size: 18px;
}
}
}
.operation {
margin-top: 10px;
}
}
.order-info {
background-color: #fff;
margin-bottom: 10px;
h4 {
margin: 10px 0 20px;
border-bottom: 1px solid #eeeeee;
padding-bottom: 10px;
}
ul {
display: flex;
flex-wrap: wrap;
li {
flex: 0 0 33.3333%;
margin-bottom: 10px;
&:last-child {
flex: initial;
}
}
}
}
.take-delivery-info {
background-color: #fff;
margin-bottom: 10px;
h4 {
margin: 10px 0 20px;
border-bottom: 1px solid #eeeeee;
padding-bottom: 10px;
}
ul {
display: flex;
flex-wrap: wrap;
li {
flex: 0 0 33.3333%;
margin-bottom: 10px;
&:last-child {
flex: initial;
}
}
}
}
nav {
overflow: hidden;
padding: 10px 0;
background: #fff;
border-bottom: 1px solid #eeeeee;
li {
float: left;
&:nth-child(1) {
width: 50%;
&.no-operation {
width: 60%;
}
}
&:nth-child(2) {
width: 15%;
}
&:nth-child(3) {
width: 10%;
}
&:nth-child(4) {
width: 15%;
}
&:nth-child(5) {
width: 10%;
}
}
}
.list {
border-bottom: 1px solid #eeeeee;
.item {
background-color: #fff;
padding: 10px 0;
overflow: hidden;
li {
float: left;
line-height: 60px;
&:nth-child(1) {
width: 50%;
line-height: inherit;
&.no-operation {
width: 60%;
}
.img-wrap {
width: 60px;
height: 60px;
float: left;
margin-right: 10px;
cursor: pointer;
}
.info-wrap {
margin-left: 70px;
h5 {
font-weight: normal;
font-size: $ns-font-size-base;
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 2;
overflow: hidden;
margin-right: 10px;
display: inline-block;
cursor: pointer;
&:hover {
color: $base-color;
}
}
span {
font-size: $ns-font-size-sm;
color: #9a9a9a;
}
}
}
&:nth-child(2) {
width: 15%;
}
&:nth-child(3) {
width: 10%;
}
&:nth-child(4) {
width: 15%;
}
&:nth-child(5) {
width: 10%;
}
}
}
}
// 总计
.total {
padding: 20px;
background-color: #fff;
text-align: right;
li {
span {
width: 150px;
display: inline-block;
}
&.pay-money {
font-weight: bold;
span {
color: $base-color;
font-size: 16px;
vertical-align: middle;
}
}
}
}
}
</style>

View File

@@ -0,0 +1,490 @@
<template>
<div class="box">
<div class="null-page" v-show="yes"></div>
<el-card class="box-card order-detail">
<div slot="header" class="clearfix">
<el-breadcrumb separator="/">
<el-breadcrumb-item :to="{ path: '/member/order_list' }">订单列表</el-breadcrumb-item>
<el-breadcrumb-item>订单详情</el-breadcrumb-item>
</el-breadcrumb>
</div>
<div v-loading="loading">
<template v-if="orderDetail">
<div class="order-status">
<h4>
订单状态
<span class="ns-text-color">{{ orderDetail.order_status_name }}</span>
</h4>
<div v-if="orderDetail.order_status == 0" class="go-pay">
<p>
需付款
<span>{{ orderDetail.pay_money }}</span>
</p>
</div>
<div class="operation" v-if="orderDetail.action.length > 0">
<el-button type="primary" size="mini" plain v-if="orderDetail.is_evaluate == 1" @click="operation('memberOrderEvaluation')">
<template v-if="orderDetail.evaluate_status == 0">评价</template>
<template v-else-if="orderDetail.evaluate_status == 1">追评</template>
</el-button>
<el-button type="primary" size="mini" :plain="operationItem.action == 'orderPay' ? false : true" v-for="(operationItem, operationIndex) in orderDetail.action" :key="operationIndex" @click="operation(operationItem.action)">
{{ operationItem.title }}
</el-button>
</div>
<div class="operation" v-else-if="orderDetail.action.length == 0 && orderDetail.is_evaluate == 1">
<el-button type="primary" size="mini" plain v-if="orderDetail.is_evaluate == 1" @click="operation('memberOrderEvaluation')">
<template v-if="orderDetail.evaluate_status == 0">评价</template>
<template v-else-if="orderDetail.evaluate_status == 1">追评</template>
</el-button>
</div>
</div>
<div class="order-info">
<h4>订单信息</h4>
<ul>
<!-- <li>
<i class="iconfont iconmendian"></i>
店铺
<router-link :to="'/shop-' + orderDetail.site_id" target="_blank">{{ orderDetail.site_name }}</router-link>
</li> -->
<li>订单类型{{ orderDetail.order_type_name }}</li>
<li>订单编号{{ orderDetail.order_no }}</li>
<li>订单交易号{{ orderDetail.out_trade_no }}</li>
<li>配送方式{{ orderDetail.delivery_type_name }}</li>
<li>创建时间{{ $util.timeStampTurnTime(orderDetail.create_time) }}</li>
<li v-if="orderDetail.close_time > 0">关闭时间{{ $util.timeStampTurnTime(orderDetail.close_time) }}</li>
<template v-if="orderDetail.pay_status > 0">
<li>支付方式{{ orderDetail.pay_type_name }}</li>
<li>支付时间{{ $util.timeStampTurnTime(orderDetail.pay_time) }}</li>
</template>
<li v-if="orderDetail.promotion_type_name != ''">店铺活动{{ orderDetail.promotion_type_name }}</li>
<li v-if="orderDetail.buyer_message != ''">买家留言{{ orderDetail.buyer_message }}</li>
</ul>
</div>
<div class="take-delivery-info">
<h4>收货信息</h4>
<ul>
<li>收货人{{ orderDetail.name }}</li>
<li>手机号码{{ orderDetail.mobile }}</li>
<li>收货地址{{ orderDetail.full_address }} {{ orderDetail.address }}</li>
</ul>
</div>
<nav>
<li :class="{ 'no-operation': !orderDetail.is_enable_refund }">商品信息</li>
<li>单价</li>
<li>数量</li>
<li>小计</li>
<li v-if="orderDetail.is_enable_refund">操作</li>
</nav>
<!-- 订单项·商品 -->
<div class="list">
<ul class="item" v-for="(goodsItem, goodsIndex) in orderDetail.order_goods" :key="goodsIndex">
<li :class="{ 'no-operation': !orderDetail.is_enable_refund }">
<div class="img-wrap" @click="$util.pushToTab('/sku/' + goodsItem.sku_id)">
<img :src="$img(goodsItem.sku_image, { size: 'mid' })" @error="imageError(goodsIndex)" />
</div>
<div class="info-wrap">
<h5 @click="$util.pushToTab('/sku/' + goodsItem.sku_id)">{{ goodsItem.sku_name }}</h5>
<!-- <span>规格规格值</span> -->
</div>
</li>
<li>
<span>{{ goodsItem.price }}</span>
</li>
<li>
<span>{{ goodsItem.num }}</span>
</li>
<li>
<span>{{ (goodsItem.price * goodsItem.num).toFixed(2) }}</span>
</li>
<li v-if="orderDetail.is_enable_refund">
<el-button type="primary" plain size="mini" v-if="goodsItem.refund_status == 0 || goodsItem.refund_status == -1" @click="$router.push({ path: '/order/refund', query: { order_goods_id: goodsItem.order_goods_id } })">退款</el-button>
<el-button type="primary" plain size="mini" v-else @click="$router.push({ path: '/order/refund_detail', query: { order_goods_id: goodsItem.order_goods_id } })">查看退款</el-button>
</li>
</ul>
</div>
<!-- 订单总计 -->
<ul class="total">
<li>
<label>商品金额</label>
<span>{{ orderDetail.goods_money }}</span>
</li>
<li>
<label>运费</label>
<span>{{ orderDetail.delivery_money }}</span>
</li>
<li v-if="orderDetail.member_card_money > 0">
<label>会员卡</label>
<span>{{ orderDetail.member_card_money }}</span>
</li>
<li v-if="orderDetail.invoice_money > 0">
<label>税费</label>
<span>{{ orderDetail.invoice_money }}</span>
</li>
<li v-if="orderDetail.invoice_delivery_money > 0">
<label>发票邮寄费</label>
<span>{{ orderDetail.invoice_delivery_money }}</span>
</li>
<li v-if="orderDetail.adjust_money != 0">
<label>订单调整</label>
<span>
<template v-if="orderDetail.adjust_money < 0">-</template>
<template v-else>+</template>
{{ orderDetail.adjust_money | abs }}
</span>
</li>
<li v-if="orderDetail.promotion_money > 0">
<label>优惠</label>
<span>{{ orderDetail.promotion_money }}</span>
</li>
<li v-if="orderDetail.coupon_money > 0">
<label>优惠券</label>
<span>{{ orderDetail.coupon_money }}</span>
</li>
<li v-if="orderDetail.point_money > 0">
<label>积分抵扣</label>
<span>{{ orderDetail.point_money }}</span>
</li>
<li v-if="orderDetail.balance_money > 0">
<label>使用余额</label>
<span>{{ orderDetail.balance_money }}</span>
</li>
<li class="pay-money">
<label>实付款</label>
<span>{{ orderDetail.pay_money }}</span>
</li>
</ul>
</template>
</div>
</el-card>
</div>
</template>
<script>
import {apiOrderDetail} from '@/api/order/order';
import orderMethod from '@/utils/orderMethod';
import {mapGetters} from 'vuex';
export default {
name: 'order_detail_local_delivery',
components: {},
mixins: [orderMethod],
data: () => {
return {
orderId: 0,
orderDetail: null,
loading: true,
yes: true
};
},
created() {
this.orderId = this.$route.query.order_id;
this.getOrderDetail();
},
computed: {
...mapGetters(['defaultGoodsImage'])
},
layout: 'member',
mounted() {
let self = this;
setTimeout(function () {
self.yes = false
}, 300)
},
methods: {
getOrderDetail() {
apiOrderDetail({
order_id: this.orderId
}).then(res => {
if (res.code >= 0) {
this.orderDetail = res.data;
this.loading = false;
} else {
this.$message({
message: '未获取到订单信息',
type: 'warning',
duration: 2000,
onClose: () => {
this.$router.push({path: '/member/order_list'});
}
});
}
}).catch(err => {
this.loading = false;
this.$message.error({
message: err.message,
duration: 2000,
onClose: () => {
this.$router.push({path: '/member/order_list'});
}
});
});
},
operation(action) {
switch (action) {
case 'orderPay': // 支付
this.orderPay(this.orderDetail);
break;
case 'orderClose': //关闭
this.orderClose(this.orderDetail.order_id, () => {
this.getOrderDetail();
});
break;
case 'memberTakeDelivery': //收货
this.orderDelivery(this.orderDetail.order_id, () => {
this.getOrderDetail();
});
break;
case 'trace': //查看物流
this.$router.push({path: '/order/logistics', query: {order_id: this.orderDetail.order_id}});
break;
case 'memberOrderEvaluation': //评价
this.$util.pushToTab({path: '/order/evaluate', query: {order_id: this.orderDetail.order_id}});
break;
}
},
imageError(index) {
this.orderDetail.order_goods[index].sku_image = this.defaultGoodsImage;
}
},
filters: {
abs(value) {
return Math.abs(parseFloat(value)).toFixed(2);
}
}
};
</script>
<style lang="scss" scoped>
.box {
width: 100%;
position: relative;
}
.null-page {
width: 100%;
height: 730px;
background-color: #FFFFFF;
position: absolute;
top: 0;
left: 0;
z-index: 9;
}
.order-detail {
.order-status {
background-color: #fff;
margin-bottom: 20px;
h4 {
margin: 10px 0 20px;
border-bottom: 1px solid #eeeeee;
padding-bottom: 10px;
}
.go-pay {
p {
display: inline-block;
vertical-align: middle;
span {
font-weight: bold;
color: $base-color;
font-size: 18px;
}
}
}
.operation {
margin-top: 10px;
}
}
.order-info {
background-color: #fff;
margin-bottom: 10px;
h4 {
margin: 10px 0 20px;
border-bottom: 1px solid #eeeeee;
padding-bottom: 10px;
}
ul {
display: flex;
flex-wrap: wrap;
li {
flex: 0 0 33.3333%;
margin-bottom: 10px;
&:last-child {
flex: initial;
}
}
}
}
.take-delivery-info {
background-color: #fff;
margin-bottom: 10px;
h4 {
margin: 10px 0 20px;
border-bottom: 1px solid #eeeeee;
padding-bottom: 10px;
}
ul {
display: flex;
flex-wrap: wrap;
li {
flex: 0 0 33.3333%;
margin-bottom: 10px;
&:last-child {
flex: initial;
}
}
}
}
nav {
overflow: hidden;
padding: 10px 0;
background: #fff;
border-bottom: 1px solid #eeeeee;
li {
float: left;
&:nth-child(1) {
width: 50%;
&.no-operation {
width: 60%;
}
}
&:nth-child(2) {
width: 15%;
}
&:nth-child(3) {
width: 10%;
}
&:nth-child(4) {
width: 15%;
}
&:nth-child(5) {
width: 10%;
}
}
}
.list {
border-bottom: 1px solid #eeeeee;
.item {
background-color: #fff;
padding: 10px 0;
overflow: hidden;
li {
float: left;
line-height: 60px;
&:nth-child(1) {
width: 55%;
line-height: inherit;
&.no-operation {
width: 60%;
}
.img-wrap {
width: 60px;
height: 60px;
float: left;
margin-right: 10px;
cursor: pointer;
}
.info-wrap {
margin-left: 70px;
h5 {
font-weight: normal;
font-size: $ns-font-size-base;
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 2;
overflow: hidden;
margin-right: 10px;
cursor: pointer;
display: inline-block;
&:hover {
color: $base-color;
}
}
span {
font-size: $ns-font-size-sm;
color: #9a9a9a;
}
}
}
&:nth-child(2) {
width: 15%;
}
&:nth-child(3) {
width: 10%;
}
&:nth-child(4) {
width: 15%;
}
&:nth-child(5) {
width: 10%;
}
}
}
}
// 总计
.total {
padding: 20px;
background-color: #fff;
text-align: right;
li {
span {
width: 150px;
display: inline-block;
}
&.pay-money {
font-weight: bold;
span {
color: $base-color;
font-size: 16px;
vertical-align: middle;
}
}
}
}
}
</style>

View File

@@ -0,0 +1,583 @@
<template>
<div class="box">
<div class="null-page" v-show="yes"></div>
<el-card class="box-card order-detail">
<div slot="header" class="clearfix">
<el-breadcrumb separator="/">
<el-breadcrumb-item :to="{ path: '/member/order_list' }">订单列表</el-breadcrumb-item>
<el-breadcrumb-item>订单详情</el-breadcrumb-item>
</el-breadcrumb>
</div>
<div v-loading="loading">
<template v-if="orderDetail">
<div class="order-status">
<h4>
订单状态
<span class="ns-text-color">{{ orderDetail.order_status_name }}</span>
</h4>
<div v-if="orderDetail.order_status == 0" class="go-pay">
<p>
需付款
<span>{{ orderDetail.pay_money }}</span>
</p>
</div>
<div class="operation" v-if="orderDetail.action.length > 0">
<el-button type="primary" size="mini" plain v-if="orderDetail.is_evaluate == 1" @click="operation('memberOrderEvaluation')">
<template v-if="orderDetail.evaluate_status == 0">评价</template>
<template v-else-if="orderDetail.evaluate_status == 1">追评</template>
</el-button>
<el-button type="primary" size="mini" :plain="operationItem.action == 'orderPay' ? false : true" v-for="(operationItem, operationIndex) in orderDetail.action" :key="operationIndex" @click="operation(operationItem.action)">{{ operationItem.title }}</el-button>
</div>
<div class="operation" v-else-if="orderDetail.action.length == 0 && orderDetail.is_evaluate == 1">
<el-button type="primary" size="mini" plain v-if="orderDetail.is_evaluate == 1" @click="operation('memberOrderEvaluation')">
<template v-if="orderDetail.evaluate_status == 0">评价</template>
<template v-else-if="orderDetail.evaluate_status == 1">追评</template>
</el-button>
</div>
</div>
<div class="pickup-info" v-if="orderDetail.pay_status">
<h4>
自提点
<span class="ns-text-color">{{ orderDetail.delivery_store_name }}</span>
</h4>
<ul>
<li>
提货码
<span class="ns-text-color">{{ orderDetail.delivery_code }}</span>
</li>
<li v-if="orderDetail.delivery_store_info && orderDetail.delivery_store_info.open_date">营业时间{{ orderDetail.delivery_store_info.open_date }}</li>
<li v-if="orderDetail.delivery_store_info && orderDetail.delivery_store_info.telphone">联系方式{{ orderDetail.delivery_store_info.telphone }}</li>
<li v-if="orderDetail.delivery_store_info && orderDetail.delivery_store_info.full_address">详细地址{{ orderDetail.delivery_store_info.full_address }}</li>
</ul>
<img :src="$img(orderDetail.pickup)" />
</div>
<nav>
<li :class="{ 'no-operation': !orderDetail.is_enable_refund }">商品信息</li>
<li>单价</li>
<li>数量</li>
<li>小计</li>
<li v-if="orderDetail.is_enable_refund">操作</li>
</nav>
<div class="order-info">
<h4>订单信息</h4>
<ul>
<!-- <li>
<i class="iconfont iconmendian"></i>
店铺
<router-link :to="'/shop-' + orderDetail.site_id" target="_blank">{{ orderDetail.site_name }}</router-link>
</li> -->
<li>订单类型{{ orderDetail.order_type_name }}</li>
<li>订单编号{{ orderDetail.order_no }}</li>
<li>订单交易号{{ orderDetail.out_trade_no }}</li>
<li>配送方式{{ orderDetail.delivery_type_name }}</li>
<li>创建时间{{ $util.timeStampTurnTime(orderDetail.create_time) }}</li>
<li v-if="orderDetail.close_time > 0">关闭时间{{ $util.timeStampTurnTime(orderDetail.close_time) }}</li>
<template v-if="orderDetail.pay_status > 0">
<li>支付方式{{ orderDetail.pay_type_name }}</li>
<li>支付时间{{ $util.timeStampTurnTime(orderDetail.pay_time) }}</li>
</template>
<li v-if="orderDetail.promotion_type_name != ''">店铺活动{{ orderDetail.promotion_type_name }}</li>
<li v-if="orderDetail.buyer_message != ''">买家留言{{ orderDetail.buyer_message }}</li>
</ul>
</div>
<div class="order-info" v-if="orderDetail.pay_type=='offlinepay'&&orderDetail.offline_pay_info">
<h4>线下支付</h4>
<ul>
<li v-if="orderDetail.offline_pay_info.status_info.const=='WAIT_AUDIT'">
支付状态审核中
</li>
<li v-if="orderDetail.offline_pay_info.status_info.const=='AUDIT_REFUSE'">
支付状态审核被拒
</li>
<li v-if="orderDetail.offline_pay_info.status_info.const=='AUDIT_REFUSE'">
审核备注{{orderDetail.offline_pay_info.audit_remark}}
</li>
</ul>
</div>
<div class="take-delivery-info">
<h4>收货信息</h4>
<ul>
<li>收货人{{ orderDetail.name }}</li>
<li>手机号码{{ orderDetail.mobile }}</li>
<li>收货地址{{ orderDetail.full_address }} {{ orderDetail.address }}</li>
</ul>
</div>
<!-- 订单项·商品 -->
<div class="list">
<ul class="item" v-for="(goodsItem, goodsIndex) in orderDetail.order_goods" :key="goodsIndex">
<li :class="{ 'no-operation': !orderDetail.is_enable_refund }">
<div class="img-wrap" @click="$util.pushToTab('/sku/' + goodsItem.sku_id)">
<img :src="$img(goodsItem.sku_image, { size: 'mid' })" @error="imageError(goodsIndex)" />
</div>
<div class="info-wrap">
<h5 @click="$util.pushToTab('/sku/' + goodsItem.sku_id)">{{ goodsItem.sku_name }}</h5>
<!-- <span>规格规格值</span> -->
</div>
</li>
<li>
<span>{{ goodsItem.price }}</span>
</li>
<li>
<span>{{ goodsItem.num }}</span>
</li>
<li>
<span>{{ (goodsItem.price * goodsItem.num).toFixed(2) }}</span>
</li>
<li v-if="orderDetail.is_enable_refund">
<el-button type="primary" plain size="mini" v-if="goodsItem.refund_status == 0 || goodsItem.refund_status == -1" @click="$router.push({ path: '/order/refund', query: { order_goods_id: goodsItem.order_goods_id } })">退款</el-button>
<el-button type="primary" plain size="mini" v-else @click="$router.push({ path: '/order/refund_detail', query: { order_goods_id: goodsItem.order_goods_id } })">查看退款</el-button>
</li>
</ul>
</div>
<!-- 订单总计 -->
<ul class="total">
<li>
<label>商品金额</label>
<span>{{ orderDetail.goods_money }}</span>
</li>
<li>
<label>运费</label>
<span>{{ orderDetail.delivery_money }}</span>
</li>
<li v-if="orderDetail.member_card_money > 0">
<label>会员卡</label>
<span>{{ orderDetail.member_card_money }}</span>
</li>
<li v-if="orderDetail.invoice_money > 0">
<label>税费</label>
<span>{{ orderDetail.invoice_money }}</span>
</li>
<li v-if="orderDetail.invoice_delivery_money > 0">
<label>发票邮寄费</label>
<span>{{ orderDetail.invoice_delivery_money }}</span>
</li>
<li v-if="orderDetail.adjust_money != 0">
<label>订单调整</label>
<span>
<template v-if="orderDetail.adjust_money < 0">-</template>
<template v-else>+</template>
{{ orderDetail.adjust_money | abs }}
</span>
</li>
<li v-if="orderDetail.promotion_money > 0">
<label>优惠</label>
<span>{{ orderDetail.promotion_money }}</span>
</li>
<li v-if="orderDetail.coupon_money > 0">
<label>优惠券</label>
<span>{{ orderDetail.coupon_money }}</span>
</li>
<li v-if="orderDetail.balance_money > 0">
<label>使用余额</label>
<span>{{ orderDetail.balance_money }}</span>
</li>
<li v-if="orderDetail.point_money > 0">
<label>积分抵扣</label>
<span>{{ orderDetail.point_money }}</span>
</li>
<li class="pay-money">
<label>实付款</label>
<span>{{ orderDetail.pay_money }}</span>
</li>
</ul>
</template>
</div>
</el-card>
</div>
</template>
<script>
import {
apiOrderDetail
} from '@/api/order/order';
import orderMethod from '@/utils/orderMethod';
import {
mapGetters
} from 'vuex';
export default {
name: 'order_detail_pickup',
components: {},
mixins: [orderMethod],
data: () => {
return {
orderId: 0,
orderDetail: null,
loading: true,
yes: true
};
},
created() {
this.orderId = this.$route.query.order_id;
this.getOrderDetail();
},
mounted() {
let self = this;
setTimeout(function () {
self.yes = false
}, 300)
},
computed: {
...mapGetters(['defaultGoodsImage'])
},
layout: 'member',
methods: {
getOrderDetail() {
apiOrderDetail({
order_id: this.orderId
}).then(res => {
if (res.code >= 0) {
this.orderDetail = res.data;
if (this.orderDetail.delivery_store_info != '') this.orderDetail.delivery_store_info = JSON.parse(this.orderDetail
.delivery_store_info);
this.loading = false;
} else {
this.$message({
message: '未获取到订单信息',
type: 'warning',
duration: 2000,
onClose: () => {
this.$router.push({
path: '/member/order_list'
});
}
});
}
}).catch(err => {
this.loading = false;
this.$message.error({
message: err.message,
duration: 2000,
onClose: () => {
this.$router.push({
path: '/member/order_list'
});
}
});
});
},
operation(action) {
switch (action) {
case 'orderPay': // 支付
this.orderPay(this.orderDetail);
break;
case 'orderClose': //关闭
this.orderClose(this.orderDetail.order_id, () => {
this.getOrderDetail();
});
break;
case 'memberTakeDelivery': //收货
this.orderDelivery(this.orderDetail.order_id, () => {
this.getOrderDetail();
});
break;
case 'trace': //查看物流
this.$router.push({
path: '/order/logistics',
query: {
order_id: this.orderDetail.order_id
}
});
break;
case 'memberOrderEvaluation': //评价
this.$router.push({
path: '/order/evaluate',
query: {
order_id: this.orderDetail.order_id
}
});
break;
case 'memberBatchRefund': //批量退款
this.$router.push({
path: '/order/batchrefund',
query: {
order_id: this.orderId
}
});
break;
case 'orderOfflinePay': //线下支付
this.$router.push({
path: '/pay',
query: {
code: this.orderDetail.offline_pay_info.out_trade_no
}
});
break;
}
},
imageError(index) {
this.orderDetail.order_goods[index].sku_image = this.defaultGoodsImage;
}
},
filters: {
abs(value) {
return Math.abs(parseFloat(value)).toFixed(2);
}
}
};
</script>
<style lang="scss" scoped>
.box {
width: 100%;
position: relative;
}
.null-page {
width: 100%;
height: 730px;
background-color: #FFFFFF;
position: absolute;
top: 0;
left: 0;
z-index: 9;
}
.order-detail {
.order-status {
background-color: #fff;
margin-bottom: 20px;
h4 {
margin: 10px 0 20px;
border-bottom: 1px solid #eeeeee;
padding-bottom: 10px;
}
.go-pay {
p {
display: inline-block;
vertical-align: middle;
span {
font-weight: bold;
color: $base-color;
font-size: 18px;
}
}
}
.operation {
margin-top: 10px;
}
}
.order-info {
background-color: #fff;
margin-bottom: 10px;
h4 {
margin: 10px 0 20px;
border-bottom: 1px solid #eeeeee;
padding-bottom: 10px;
}
ul {
display: flex;
flex-wrap: wrap;
li {
flex: 0 0 33.3333%;
margin-bottom: 10px;
&:last-child {
flex: initial;
}
}
}
}
.take-delivery-info {
background-color: #fff;
margin-bottom: 10px;
h4 {
margin: 10px 0 20px;
border-bottom: 1px solid #eeeeee;
padding-bottom: 10px;
}
ul {
display: flex;
flex-wrap: wrap;
li {
flex: 0 0 33.3333%;
margin-bottom: 10px;
&:last-child {
flex: initial;
}
}
}
}
.pickup-info {
background-color: #fff;
margin-bottom: 10px;
h4 {
margin: 10px 0 20px;
border-bottom: 1px solid #eeeeee;
padding-bottom: 10px;
}
ul {
display: flex;
flex-wrap: wrap;
li {
flex: 0 0 33.3333%;
margin-bottom: 10px;
&:last-child {
flex: initial;
}
}
}
img {
width: 100px;
}
}
nav {
overflow: hidden;
padding: 10px 0;
background: #fff;
border-bottom: 1px solid #eeeeee;
li {
float: left;
&:nth-child(1) {
width: 50%;
&.no-operation {
width: 60%;
}
}
&:nth-child(2) {
width: 15%;
}
&:nth-child(3) {
width: 10%;
}
&:nth-child(4) {
width: 15%;
}
&:nth-child(5) {
width: 10%;
}
}
}
.list {
border-bottom: 1px solid #eeeeee;
.item {
background-color: #fff;
padding: 10px 0;
overflow: hidden;
li {
float: left;
line-height: 60px;
&:nth-child(1) {
width: 50%;
line-height: inherit;
&.no-operation {
width: 60%;
}
.img-wrap {
width: 60px;
height: 60px;
float: left;
margin-right: 10px;
cursor: pointer;
}
.info-wrap {
margin-left: 70px;
cursor: pointer;
h5 {
font-weight: normal;
font-size: $ns-font-size-base;
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 2;
overflow: hidden;
margin-right: 10px;
display: inline-block;
&:hover {
color: $base-color;
}
}
span {
font-size: $ns-font-size-sm;
color: #9a9a9a;
}
}
}
&:nth-child(2) {
width: 15%;
}
&:nth-child(3) {
width: 10%;
}
&:nth-child(4) {
width: 15%;
}
&:nth-child(5) {
width: 10%;
}
}
}
}
// 总计
.total {
padding: 20px;
background-color: #fff;
text-align: right;
li {
span {
width: 150px;
display: inline-block;
}
&.pay-money {
font-weight: bold;
span {
color: $base-color;
font-size: 16px;
vertical-align: middle;
}
}
}
}
}
</style>

View File

@@ -0,0 +1,622 @@
<template>
<div class="box">
<div class="null-page" v-show="yes"></div>
<el-card class="box-card order-detail">
<div slot="header" class="clearfix">
<el-breadcrumb separator="/">
<el-breadcrumb-item :to="{ path: '/member/order_list' }">订单列表</el-breadcrumb-item>
<el-breadcrumb-item>订单详情</el-breadcrumb-item>
</el-breadcrumb>
</div>
<div v-loading="loading">
<template v-if="orderDetail">
<div class="order-status">
<h4 style="position: relative;">
订单状态
<span class="ns-text-color">{{ orderDetail.order_status_name }}</span>
<div class="edit-time" v-if="orderDetail.order_status == 0">
<img src="../../assets/images/order_time.png" style="width: 15px;height: 15px;margin-right: 6px;" />距离订单自动关闭剩余
<count-down
style="color: #f00;margin-left: 10px;"
class="count-down"
v-on:start_callback="countDownS_cb()"
v-on:end_callback="countDownE_cb()"
:currentTime="orderDetail.currentTime"
:startTime="orderDetail.startTime"
:endTime="orderDetail.endTime"
:dayTxt="':'"
:hourTxt="':'"
:minutesTxt="':'"
:secondsTxt="''"
></count-down>
</div>
</h4>
<div v-if="orderDetail.order_status == 0" class="go-pay">
<p>
需付款
<span>{{ orderDetail.pay_money }}</span>
</p>
</div>
<div class="operation" v-if="orderDetail.action.length > 0">
<el-button type="primary" size="mini" plain v-if="orderDetail.is_evaluate == 1" @click="operation('memberOrderEvaluation')">
<template v-if="orderDetail.evaluate_status == 0">评价</template>
<template v-else-if="orderDetail.evaluate_status == 1">追评</template>
</el-button>
<el-button type="primary" size="mini" :plain="operationItem.action == 'orderPay' ? false : true" v-for="(operationItem, operationIndex) in orderDetail.action" :key="operationIndex" @click="operation(operationItem.action)">{{ operationItem.title }}</el-button>
</div>
<div class="operation" v-else-if="orderDetail.action.length == 0 && orderDetail.is_evaluate == 1">
<el-button type="primary" size="mini" plain v-if="orderDetail.is_evaluate == 1" @click="operation('memberOrderEvaluation')">
<template v-if="orderDetail.evaluate_status == 0">评价</template>
<template v-else-if="orderDetail.evaluate_status == 1">追评</template>
</el-button>
</div>
</div>
<div class="verify-code-wrap" v-if="orderDetail.virtual_goods">
<template v-if="orderDetail.goods_class == 2">
<h4>核销码</h4>
<div class="virtual-code">
<img :src="$img(orderDetail.virtualgoods)" />
<div class="tips">请将二维码出示给核销员</div>
<div>核销码{{ orderDetail.virtual_code }}</div>
</div>
<h4>核销信息</h4>
<ul>
<li>核销次数剩余{{ orderDetail.virtual_goods.total_verify_num - orderDetail.virtual_goods.verify_num }}/{{ orderDetail.virtual_goods.total_verify_num }}</li>
<li>有效期
<span v-if="orderDetail.virtual_goods.expire_time > 0"> {{ $util.timeStampTurnTime(orderDetail.virtual_goods.expire_time) }}</span>
<span v-else>永久有效</span>
</li>
</ul>
<template v-if="orderDetail.virtual_goods.verify_record.length">
<h4>核销记录</h4>
<ul v-for="(item, index) in orderDetail.virtual_goods.verify_record" :key="index">
<li>核销人{{ item.verifier_name }}</li>
<li>核销时间{{ $util.timeStampTurnTime(item.verify_time) }}</li>
</ul>
</template>
</template>
<template v-if="orderDetail.goods_class == 3">
<h4>卡密信息</h4>
<ul v-for="(item, index) in orderDetail.virtual_goods" :key="index">
<li>
<span>卡号{{ item.card_info.cardno }}</span>
</li>
<li>
<span>密码{{ item.card_info.password }}</span>
</li>
</ul>
</template>
<!-- <h4>核销信息</h4>
<ul>
<li>
核销码
<span class="ns-text-color">{{ orderDetail.virtual_code }}</span>
</li>
<template v-if="orderDetail.virtual_goods.is_veirfy">
<li>核销状态已核销</li>
<li>核销时间{{ $util.timeStampTurnTime(orderDetail.virtual_goods.verify_time) }}</li>
</template>
</ul>
<img :src="$img(orderDetail.virtualgoods)" /> -->
</div>
<div class="order-info">
<h4>订单信息</h4>
<ul>
<!-- <li>
<i class="iconfont iconmendian"></i>
店铺
<router-link :to="'/shop-' + orderDetail.site_id" target="_blank">{{ orderDetail.site_name }}</router-link>
</li> -->
<li>订单类型{{ orderDetail.order_type_name }}</li>
<li>订单编号{{ orderDetail.order_no }}</li>
<li>订单交易号{{ orderDetail.out_trade_no }}</li>
<li>创建时间{{ $util.timeStampTurnTime(orderDetail.create_time) }}</li>
<li v-if="orderDetail.close_time > 0">关闭时间{{ $util.timeStampTurnTime(orderDetail.close_time) }}</li>
<template v-if="orderDetail.pay_status > 0">
<li>支付方式{{ orderDetail.pay_type_name }}</li>
<li>支付时间{{ $util.timeStampTurnTime(orderDetail.pay_time) }}</li>
</template>
<li v-if="orderDetail.promotion_type_name != ''">店铺活动{{ orderDetail.promotion_type_name }}</li>
<li v-if="orderDetail.buyer_message != ''">买家留言{{ orderDetail.buyer_message }}</li>
</ul>
</div>
<div class="order-info" v-if="orderDetail.pay_type=='offlinepay'&&orderDetail.offline_pay_info">
<h4>线下支付</h4>
<ul>
<li v-if="orderDetail.offline_pay_info.status_info.const=='WAIT_AUDIT'">
支付状态审核中
</li>
<li v-if="orderDetail.offline_pay_info.status_info.const=='AUDIT_REFUSE'">
支付状态审核被拒
</li>
<li v-if="orderDetail.offline_pay_info.status_info.const=='AUDIT_REFUSE'">
审核备注{{orderDetail.offline_pay_info.audit_remark}}
</li>
</ul>
</div>
<!-- 发票信息 -->
<div class="take-delivery-info" v-if="orderDetail.is_invoice ==1">
<h4>发票信息</h4>
<ul>
<li>发票类型{{ orderDetail.invoice_type == 1 ? '纸质发票' : '电子发票' }}</li>
<li>发票抬头类型{{ orderDetail.invoice_title_type ==1 ? '个人' : '企业' }}</li>
<li>发票抬头{{ orderDetail.invoice_title }}</li>
<li>发票内容{{ orderDetail.invoice_content }}</li>
<li v-if="orderDetail.invoice_type == 1">发票邮寄地址地址{{ orderDetail.invoice_full_address }}</li>
<li v-else>发票接收邮箱{{ orderDetail.invoice_email }}</li>
</ul>
</div>
<nav>
<li :class="{ 'no-operation': !orderDetail.is_enable_refund }">商品信息</li>
<li>单价</li>
<li>数量</li>
<li>小计</li>
<li v-if="orderDetail.is_enable_refund">操作</li>
</nav>
<!-- 订单项·商品 -->
<div class="list">
<ul class="item" v-for="(goodsItem, goodsIndex) in orderDetail.order_goods" :key="goodsIndex">
<li :class="{ 'no-operation': !orderDetail.is_enable_refund }">
<div class="img-wrap" @click="$util.pushToTab('/sku/' + goodsItem.sku_id)">
<img :src="$img(goodsItem.sku_image, { size: 'mid' })" @error="imageError(goodsIndex)" />
</div>
<div class="info-wrap">
<h5 @click="$util.pushToTab('/sku/' + goodsItem.sku_id)">{{ goodsItem.sku_name }}</h5>
<!-- <span>规格规格值</span> -->
</div>
</li>
<li>
<span>{{ goodsItem.price }}</span>
</li>
<li>
<span>{{ goodsItem.num }}</span>
</li>
<li>
<span>{{ (goodsItem.price * goodsItem.num).toFixed(2) }}</span>
</li>
<li v-if="orderDetail.is_enable_refund">
<el-button type="primary" plain size="mini" v-if="goodsItem.refund_status == 0 || goodsItem.refund_status == -1" @click="$router.push({ path: '/order/refund', query: { order_goods_id: goodsItem.order_goods_id } })">退款</el-button>
<el-button type="primary" plain size="mini" v-else @click="$router.push({ path: '/order/refund_detail', query: { order_goods_id: goodsItem.order_goods_id } })">查看退款</el-button>
</li>
</ul>
</div>
<!-- 订单总计 -->
<ul class="total">
<li>
<label>商品金额</label>
<span>{{ orderDetail.goods_money }}</span>
</li>
<li v-if="orderDetail.member_card_money > 0">
<label>会员卡</label>
<span>{{ orderDetail.member_card_money }}</span>
</li>
<li v-if="orderDetail.invoice_money > 0">
<label>税费</label>
<span>{{ orderDetail.invoice_money }}</span>
</li>
<li v-if="orderDetail.invoice_delivery_money > 0">
<label>发票邮寄费</label>
<span>{{ orderDetail.invoice_delivery_money }}</span>
</li>
<li v-if="orderDetail.adjust_money != 0">
<label>订单调整</label>
<span>
<template v-if="orderDetail.adjust_money < 0">-</template>
<template v-else>+</template>
{{ orderDetail.adjust_money | abs }}
</span>
</li>
<li v-if="orderDetail.promotion_money > 0">
<label>优惠</label>
<span>{{ orderDetail.promotion_money }}</span>
</li>
<li v-if="orderDetail.coupon_money > 0">
<label>优惠券</label>
<span>{{ orderDetail.coupon_money }}</span>
</li>
<li v-if="orderDetail.point_money > 0">
<label>积分抵扣</label>
<span>{{ orderDetail.point_money }}</span>
</li>
<li v-if="orderDetail.balance_money > 0">
<label>使用余额</label>
<span>{{ orderDetail.balance_money }}</span>
</li>
<li class="pay-money">
<label>实付款</label>
<span>{{ orderDetail.pay_money }}</span>
</li>
</ul>
</template>
</div>
</el-card>
</div>
</template>
<script>
import {apiOrderDetail} from '@/api/order/order';
import orderMethod from '@/utils/orderMethod';
import {mapGetters} from 'vuex';
import CountDown from "vue2-countdown"
export default {
name: 'order_detail_virtual',
components: {
CountDown
},
mixins: [orderMethod],
data: () => {
return {
orderId: 0,
orderDetail: null,
loading: true,
yes: true
};
},
created() {
this.orderId = this.$route.query.order_id;
this.getOrderDetail();
},
mounted() {
let self = this;
setTimeout(function () {
self.yes = false
}, 300)
},
computed: {
...mapGetters(['token', 'defaultGoodsImage'])
},
layout: 'member',
methods: {
countDownS_cb() {
},
countDownE_cb() {
},
getOrderDetail() {
apiOrderDetail({
order_id: this.orderId
}).then(res => {
if (res.code >= 0) {
let date = (Date.parse(new Date())) / 1000;
res.data.currentTime = date
res.data.startTime = date
res.data.endTime = res.data.create_time + res.data.auto_close
this.orderDetail = res.data;
if (this.orderDetail.delivery_store_info != '') this.orderDetail.delivery_store_info = JSON.parse(this.orderDetail.delivery_store_info);
this.loading = false;
} else {
this.$message({
message: '未获取到订单信息',
type: 'warning',
duration: 2000,
onClose: () => {
this.$router.push({path: '/member/order_list'});
}
});
}
}).catch(err => {
this.loading = false;
this.$message.error({
message: err.message,
duration: 2000,
onClose: () => {
this.$router.push({path: '/member/order_list'});
}
});
});
},
operation(action) {
switch (action) {
case 'orderPay': // 支付
this.orderPay(this.orderDetail);
break;
case 'orderClose': //关闭
this.orderClose(this.orderDetail.order_id, () => {
this.getOrderDetail();
});
break;
case 'memberOrderEvaluation': //评价
this.$util.pushToTab({path: '/order/evaluate', query: {order_id: this.orderDetail.order_id}});
break;
case 'orderOfflinePay': //线下支付
this.$router.push({
path: '/pay',
query: {
code: this.orderDetail.offline_pay_info.out_trade_no
}
});
break;
}
},
imageError(index) {
this.orderDetail.order_goods[index].sku_image = this.defaultGoodsImage;
}
},
filters: {
abs(value) {
return Math.abs(parseFloat(value)).toFixed(2);
}
}
};
</script>
<style lang="scss" scoped>
.box {
width: 100%;
position: relative;
}
.null-page {
width: 100%;
height: 730px;
background-color: #FFFFFF;
position: absolute;
top: 0;
left: 0;
z-index: 9;
}
.order-detail {
.order-status {
background-color: #fff;
margin-bottom: 20px;
h4 {
margin: 10px 0 20px;
border-bottom: 1px solid #eeeeee;
padding-bottom: 10px;
.edit-time {
position: absolute;
left: 160px;
top: 2px;
display: flex;
align-items: center;
font-size: 10px;
}
}
.go-pay {
p {
display: inline-block;
vertical-align: middle;
span {
font-weight: bold;
color: $base-color;
font-size: 18px;
}
}
}
.operation {
margin-top: 10px;
}
}
.order-info {
background-color: #fff;
margin-bottom: 10px;
h4 {
margin: 10px 0 20px;
border-bottom: 1px solid #eeeeee;
padding-bottom: 10px;
}
ul {
display: flex;
flex-wrap: wrap;
li {
flex: 0 0 33.3333%;
margin-bottom: 10px;
&:last-child {
flex: initial;
}
}
}
}
.verify-code-wrap {
background-color: #fff;
margin-bottom: 10px;
h4 {
margin: 10px 0 20px;
border-bottom: 1px solid #eeeeee;
padding-bottom: 10px;
}
ul {
display: flex;
flex-wrap: wrap;
li {
flex: 0 0 33.3333%;
margin-bottom: 10px;
}
}
img {
width: 100px;
}
.virtual-code {
text-align: center;
.tips {
color: #999;
font-size: 12px;
margin-top: 5px;
}
}
}
nav {
overflow: hidden;
padding: 10px 0;
background: #fff;
border-bottom: 1px solid #eeeeee;
li {
float: left;
&:nth-child(1) {
width: 50%;
&.no-operation {
width: 60%;
}
}
&:nth-child(2) {
width: 15%;
}
&:nth-child(3) {
width: 10%;
}
&:nth-child(4) {
width: 15%;
}
&:nth-child(5) {
width: 10%;
}
}
}
.list {
border-bottom: 1px solid #eeeeee;
.item {
background-color: #fff;
padding: 10px 0;
overflow: hidden;
li {
float: left;
line-height: 60px;
&:nth-child(1) {
width: 50%;
line-height: inherit;
&.no-operation {
width: 60%;
}
.img-wrap {
width: 60px;
height: 60px;
float: left;
margin-right: 10px;
cursor: pointer;
}
.info-wrap {
margin-left: 70px;
h5 {
font-weight: normal;
font-size: $ns-font-size-base;
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 2;
overflow: hidden;
margin-right: 10px;
display: inline-block;
cursor: pointer;
&:hover {
color: $base-color;
}
}
span {
font-size: $ns-font-size-sm;
color: #9a9a9a;
}
}
}
&:nth-child(2) {
width: 15%;
}
&:nth-child(3) {
width: 10%;
}
&:nth-child(4) {
width: 15%;
}
&:nth-child(5) {
width: 10%;
}
}
}
}
// 总计
.total {
padding: 20px;
background-color: #fff;
text-align: right;
li {
span {
width: 150px;
display: inline-block;
}
&.pay-money {
font-weight: bold;
span {
color: $base-color;
font-size: 16px;
vertical-align: middle;
}
}
}
}
}
.take-delivery-info {
background-color: #fff;
margin-bottom: 10px;
h4 {
margin: 10px 0 20px;
border-bottom: 1px solid #eeeeee;
padding-bottom: 10px;
}
ul {
display: flex;
flex-wrap: wrap;
li {
flex: 0 0 33.3333%;
margin-bottom: 10px;
&:last-child {
flex: initial;
}
}
}
}
</style>

View File

@@ -0,0 +1,461 @@
<template>
<div class="box">
<div class="null-page" v-show="yes"></div>
<el-card class="box-card order-list">
<div slot="header" class="clearfix"><span>我的订单</span></div>
<el-tabs v-model="orderStatus" @tab-click="handleClick">
<el-tab-pane label="全部订单" name="all"></el-tab-pane>
<el-tab-pane label="待付款" name="waitpay"></el-tab-pane>
<el-tab-pane label="待发货" name="waitsend"></el-tab-pane>
<el-tab-pane label="待收货" name="waitconfirm"></el-tab-pane>
<el-tab-pane label="待评价" name="waitrate"></el-tab-pane>
</el-tabs>
<div v-loading="loading">
<nav>
<li>商品信息</li>
<li>单价</li>
<li>数量</li>
<li>实付款</li>
<li>订单状态</li>
<li>操作</li>
</nav>
<div class="list" v-if="orderList.length > 0">
<div class="item" v-for="(orderItem, orderIndex) in orderList" :key="orderIndex">
<div class="head">
<span class="create-time">{{ $util.timeStampTurnTime(orderItem.create_time) }}</span>
<span class="order-no">订单号{{ orderItem.order_no }}</span>
<!-- <router-link :to="'/shop-' + orderItem.site_id" target="_blank">{{ orderItem.site_name }}</router-link> -->
<span class="order-type">{{ orderItem.order_type_name }}</span>
</div>
<ul v-for="(goodsItem, goodsIndex) in orderItem.order_goods" :key="goodsIndex">
<li>
<div class="img-wrap" @click="$router.push('/sku/' + goodsItem.sku_id)">
<img :src="$img(goodsItem.sku_image, { size: 'mid' })" @error="imageError(orderIndex, goodsIndex)" />
</div>
<div class="info-wrap" @click="$router.push('/sku/' + goodsItem.sku_id)">
<h5>{{ goodsItem.sku_name }}</h5>
<!-- <span>规格规格值</span> -->
</div>
<div class="order-time" v-if="orderItem.order_status == 0">
<img src="../../assets/images/order_time.png" style="width: 15px;height: 15px;margin-right: 6px;" />距离订单自动关闭剩余
<count-down style="color: #f00;margin-left: 10px;" class="count-down"
v-on:start_callback="countDownS_cb()" v-on:end_callback="countDownE_cb()"
:currentTime="orderItem.currentTime" :startTime="orderItem.startTime"
:endTime="orderItem.endTime"
:dayTxt="':'" :hourTxt="':'" :minutesTxt="':'" :secondsTxt="''"></count-down>
</div>
</li>
<li>
<span>{{ goodsItem.price }}</span>
</li>
<li>
<span>{{ goodsItem.num }}</span>
</li>
<li>
<span>{{ orderItem.pay_money }}</span>
</li>
<template v-if="goodsIndex == 0">
<li>
<span class="ns-text-color">{{ orderItem.order_status_name }}</span>
<el-link :underline="false" @click="orderDetail(orderItem)">订单详情</el-link>
</li>
<li>
<template v-if="orderItem.action.length > 0">
<el-button type="primary" size="mini" plain v-if="orderItem.is_evaluate == 1" @click="operation('memberOrderEvaluation', orderItem)">
<template v-if="orderItem.evaluate_status == 0">评价</template>
<template v-else-if="orderItem.evaluate_status == 1">追评</template>
</el-button>
<el-button type="primary" size="mini" :plain="operationItem.action == 'orderPay' ? false : true" v-for="(operationItem, operationIndex) in orderItem.action" :key="operationIndex" @click="operation(operationItem.action, orderItem)">
{{ operationItem.title }}
</el-button>
</template>
<template class="order-operation" v-else-if="orderItem.action.length == 0 && orderItem.is_evaluate == 1">
<el-button type="primary" size="mini" plain v-if="orderItem.is_evaluate == 1" @click="operation('memberOrderEvaluation', orderItem)">
<template v-if="orderItem.evaluate_status == 0">评价</template>
<template v-else-if="orderItem.evaluate_status == 1">追评</template>
</el-button>
</template>
</li>
</template>
</ul>
</div>
</div>
<div v-else-if="!loading && orderList.length == 0" class="empty-wrap">暂无相关订单</div>
</div>
<div class="pager">
<el-pagination background :pager-count="5" :total="total" prev-text="上一页" next-text="下一页"
:current-page.sync="currentPage" :page-size.sync="pageSize" @size-change="handlePageSizeChange"
@current-change="handleCurrentPageChange" hide-on-single-page></el-pagination>
</div>
</el-card>
</div>
</template>
<script>
import {
mapGetters
} from 'vuex';
import {
apiOrderList
} from '@/api/order/order';
import orderMethod from '@/utils/orderMethod';
import CountDown from "vue2-countdown"
export default {
name: 'order_list',
components: {
CountDown
},
layout: 'member',
data: () => {
return {
orderStatus: 'all',
loading: true,
orderList: [],
currentPage: 1,
pageSize: 10,
total: 0,
yes: true
};
},
mixins: [orderMethod],
created() {
this.orderStatus = this.$route.query.status || 'all';
this.getOrderList();
},
computed: {
...mapGetters(['defaultGoodsImage'])
},
mounted() {
let self = this;
setTimeout(function () {
self.yes = false
}, 300)
},
methods: {
countDownS_cb() {
},
countDownE_cb() {
},
handleClick(tab, event) {
this.currentPage = 1;
this.orderStatus = tab.name;
this.refresh();
},
getOrderList() {
apiOrderList({
page: this.currentPage,
page_size: this.pageSize,
order_status: this.orderStatus
}).then(res => {
let list = [];
let auto_close = 0
if (res.code == 0 && res.data) {
auto_close = res.data.auto_close
let date = (Date.parse(new Date())) / 1000
for (let i = 0; i < res.data.list.length; i++) {
res.data.list[i].currentTime = date
res.data.list[i].startTime = date
res.data.list[i].endTime = res.data.list[i].create_time + auto_close
}
list = res.data.list;
this.total = res.data.count;
}
this.orderList = list;
this.loading = false;
}).catch(res => {
this.loading = false;
});
},
handlePageSizeChange(size) {
this.pageSize = size;
this.refresh();
},
handleCurrentPageChange(page) {
this.currentPage = page;
this.refresh();
},
refresh() {
this.loading = true;
this.getOrderList();
},
operation(action, orderData) {
let index = this.status;
switch (action) {
case 'orderPay': // 支付
this.orderPay(orderData);
break;
case 'orderClose': //关闭
this.orderClose(orderData.order_id, () => {
this.refresh();
});
break;
case 'memberTakeDelivery': //收货
this.orderDelivery(orderData.order_id, () => {
this.refresh();
});
break;
case 'trace': //查看物流
this.$router.push({
path: '/order/logistics',
query: {
order_id: orderData.order_id
}
});
break;
case 'memberOrderEvaluation': //评价
this.$router.push({
path: '/order/evaluate',
query: {
order_id: orderData.order_id
}
});
break;
case 'memberVirtualTakeDelivery': // 虚拟商品 确认使用
this.orderVirtualDelivery(orderData.order_id, () => {
this.refresh();
});
break;
case 'orderOfflinePay': //线下支付
this.$router.push({
path: '/pay',
query: {
code: orderData.offline_pay_info.out_trade_no
}
});
break;
case 'orderDelete':
this.orderDelete(orderData.order_id, () => {
this.refresh();
});
break;
}
},
orderDetail(data) {
switch (parseInt(data.order_type)) {
case 2:
// 自提订单
this.$router.push({
path: '/member/order_detail_pickup',
query: {
order_id: data.order_id
}
});
break;
case 3:
// 本地配送订单
this.$router.push({
path: '/member/order_detail_local_delivery',
query: {
order_id: data.order_id
}
});
break;
case 4:
// 虚拟订单
this.$router.push({
path: '/member/order_detail_virtual',
query: {
order_id: data.order_id
}
});
break;
default:
this.$router.push({
path: '/member/order_detail',
query: {
order_id: data.order_id
}
});
break;
}
},
imageError(orderIndex, goodsIndex) {
this.orderList[orderIndex].order_goods[goodsIndex].sku_image = this.defaultGoodsImage;
}
}
};
</script>
<style lang="scss" scoped>
.box {
width: 100%;
position: relative;
}
.null-page {
width: 100%;
height: 730px;
background-color: #FFFFFF;
position: absolute;
top: 0;
left: 0;
z-index: 9;
}
.order-list {
nav {
overflow: hidden;
padding: 10px 0;
background: #fff;
margin-bottom: 10px;
border-bottom: 1px solid #eeeeee;
li {
float: left;
&:nth-child(1) {
width: 45%;
}
&:nth-child(2) {
width: 10%;
}
&:nth-child(3) {
width: 10%;
}
&:nth-child(4) {
width: 10%;
}
&:nth-child(5) {
width: 15%;
}
&:nth-child(6) {
width: 10%;
}
}
}
.list {
.item {
margin-bottom: 20px;
border: 1px solid #eeeeee;
border-top: 0;
.head {
padding: 8px 10px;
background: #f7f7f7;
font-size: 12px;
.create-time {
margin-right: 10px;
}
border-bottom: 1px solid #eeeeee;
a {
margin: 0 10px 0 20px;
}
.order-type {
margin-left: 30px;
}
}
.order-time {
display: flex;
align-items: center;
font-size: 10px;
}
}
ul {
background-color: #fff;
padding: 10px;
overflow: hidden;
li {
float: left;
line-height: 60px;
&:nth-child(1) {
width: 45%;
line-height: inherit;
.img-wrap {
width: 60px;
height: 60px;
float: left;
margin-right: 10px;
cursor: pointer;
}
.info-wrap {
margin-left: 70px;
h5 {
font-weight: normal;
font-size: $ns-font-size-base;
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 2;
overflow: hidden;
margin-right: 10px;
display: inline-block;
cursor: pointer;
&:hover {
color: $base-color;
}
}
span {
font-size: $ns-font-size-sm;
color: #9a9a9a;
}
}
}
&:nth-child(2) {
width: 10%;
}
&:nth-child(3) {
width: 10%;
}
&:nth-child(4) {
width: 10%;
}
&:nth-child(5) {
width: 15%;
line-height: 30px;
a {
display: block;
}
}
&:nth-child(6) {
width: 10%;
line-height: initial;
button {
margin-left: 0;
margin-bottom: 10px;
&:last-child {
margin-bottom: 0;
}
}
}
}
}
}
.empty-wrap {
text-align: center;
padding: 10px;
}
}
</style>

View File

@@ -0,0 +1,164 @@
<template>
<div class="box">
<div class="null-page" v-show="yes"></div>
<el-card class="box-card recharge-detail-wrap">
<div slot="header" class="clearfix">
<el-breadcrumb separator="/">
<el-breadcrumb-item :to="{ path: '/member/account' }">账户余额</el-breadcrumb-item>
<el-breadcrumb-item :to="{ path: '/member/recharge_list' }">充值套餐列表</el-breadcrumb-item>
<el-breadcrumb-item>充值套餐详情</el-breadcrumb-item>
</el-breadcrumb>
</div>
<div class="recharge-detail" v-loading="loading">
<el-image :src="$img(rechargeInfo.cover_img)" fit="contain"></el-image>
<p class="recharge-money">
<span class="buy-price">{{ rechargeInfo.buy_price }}</span>
<span class="face-price">{{ rechargeInfo.face_value }}</span>
</p>
<p class="recharge-name">{{ rechargeInfo.recharge_name }}</p>
<p class="recharge-point">额外赠送{{ rechargeInfo.point }}积分</p>
<p class="recharge-growth">额外赠送{{ rechargeInfo.growth }}成长值</p>
<div class="recharge-btn">
<el-button @click="recharge">立即充值</el-button>
</div>
</div>
</el-card>
</div>
</template>
<script>
import {rechargeDetail, recharge} from "@/api/member/account"
import {mapGetters} from 'vuex';
export default {
name: "recharge-detail",
layout: "member",
components: {},
data: () => {
return {
id: '',
rechargeInfo: {},
loading: true,
isSub: false,
yes: true
}
},
created() {
this.id = this.$route.query.id;
this.getRechargeInfo();
},
computed: {
...mapGetters(['defaultGoodsImage'])
},
mounted() {
let self = this;
setTimeout(function () {
self.yes = false
}, 300)
},
methods: {
//获取详情
getRechargeInfo() {
rechargeDetail({
recharge_id: this.id
}).then(res => {
if (res.code == 0 && res.data) {
this.rechargeInfo = res.data;
if (res.data.cover_img == '') {
this.rechargeInfo.cover_img = this.defaultGoodsImage;
}
} else {
this.$message.warning(res.message)
}
this.loading = false
}).catch(err => {
this.loading = false
})
},
recharge() {
if (this.isSub) return
this.isSub = true
recharge({
recharge_id: this.id
}).then(res => {
if (res.data && res.code == 0) {
this.$router.push({path: '/pay', query: {code: res.data}});
} else {
this.$message.warning(res.message)
}
this.isSub = false
}).catch(err => {
this.isSub = false
this.$message.error(err.message)
})
}
}
}
</script>
<style lang="scss" scoped>
.box {
width: 100%;
position: relative;
}
.null-page {
width: 100%;
height: 730px;
background-color: #FFFFFF;
position: absolute;
top: 0;
left: 0;
z-index: 9;
}
.el-card.is-always-shadow,
.el-card.is-hover-shadow:focus,
.el-card.is-hover-shadow:hover {
box-shadow: unset;
}
.el-card {
border: 0;
}
.recharge-detail-wrap {
}
.recharge-detail {
width: 300px;
.recharge-money {
.buy-price {
font-size: 25px;
color: $base-color;
font-weight: 600;
margin-right: 10px;
}
.face-price {
text-decoration: line-through;
color: #898989;
}
}
.recharge-name {
margin: 10px 0;
font-size: 16px;
}
.recharge-btn {
margin-top: 30px;
text-align: center;
.el-button {
width: 300px;
background-color: $base-color;
color: #FFFFFF;
}
}
}
</style>

View File

@@ -0,0 +1,291 @@
<template>
<div class="box">
<div class="null-page" v-show="yes"></div>
<el-card class="box-card">
<div slot="header" class="clearfix">
<el-breadcrumb separator="/">
<el-breadcrumb-item :to="{ path: '/member/account' }">账户余额</el-breadcrumb-item>
<el-breadcrumb-item>充值套餐列表</el-breadcrumb-item>
</el-breadcrumb>
</div>
<div class="recharge-wrap" v-loading="loading">
<div class="account-wrap">
<div class="account-left">
<div class="title">我的可用余额()</div>
<div class="money">
<div class="balance-money">
<b>{{ integer }}</b>
<span>.{{ decimal }}</span>
</div>
<div class="tx" @click="rechargeOrder">充值记录</div>
</div>
</div>
<div class="account-right">
<div class="item-wrap">
<div class="item">
<div class="iconfont icon-ziyuan"></div>
<div class="title">可提现余额:</div>
<b class="num">{{ balanceInfo.balance_money }}</b>
</div>
<div class="item">
<div class="iconfont icon-ziyuan"></div>
<div class="title">不可提现余额:</div>
<b class="num">{{ balanceInfo.balance }}</b>
</div>
</div>
</div>
</div>
<div class="recharge-table">
<el-table :data="rechargeList" border>
<el-table-column label="套餐名称">
<template slot-scope="scope">
<div class="recharge-info">
<el-image :src="$img(scope.row.cover_img)" fit="contain" @error="imageError(scope.$index)"></el-image>
<p :title="scope.row.recharge_name">{{ scope.row.recharge_name }}</p>
</div>
</template>
</el-table-column>
<el-table-column label="面值" width="150">
<template slot-scope="scope">
<div>价格{{ scope.row.face_value }}</div>
<div>充值面额{{ scope.row.buy_price }}</div>
</template>
</el-table-column>
<el-table-column prop="point" label="赠送积分" width="150"></el-table-column>
<el-table-column prop="growth" label="赠送成长值" width="150"></el-table-column>
<el-table-column label="操作" width="150">
<template slot-scope="scope">
<el-button size="mini" @click="handleDetail(scope.$index, scope.row)">充值</el-button>
</template>
</el-table-column>
</el-table>
<div class="pager">
<el-pagination
background
:pager-count="5"
:total="total"
prev-text="上一页"
next-text="下一页"
:current-page.sync="currentPage"
:page-size.sync="pageSize"
@size-change="handlePageSizeChange"
@current-change="handleCurrentPageChange"
hide-on-single-page
></el-pagination>
</div>
</div>
</div>
</el-card>
</div>
</template>
<script>
import {balance, rechargeList} from "@/api/member/account"
import {mapGetters} from 'vuex';
export default {
name: "recharge_list",
layout: "member",
components: {},
data: () => {
return {
balanceInfo: {
balance: 0,
balance_money: 0
},
integer: 0,
decimal: 0,
rechargeList: [],
total: 0,
currentPage: 1,
pageSize: 10,
loading: true,
yes: true
}
},
created() {
this.getUserInfo()
this.getData()
},
mounted() {
let self = this;
setTimeout(function () {
self.yes = false
}, 300)
},
computed: {
...mapGetters(['defaultGoodsImage'])
},
methods: {
handlePageSizeChange(size) {
this.pageSize = size
this.refresh()
},
handleCurrentPageChange(page) {
this.currentPage = page
this.refresh()
},
refresh() {
this.loading = true
this.getData()
},
/**
* 获取余额信息
*/
getUserInfo() {
balance({
account_type: 'balance,balance_money'
}).then(res => {
if (res.code == 0 && res.data) {
this.balanceInfo = res.data
const price = (parseFloat(this.balanceInfo.balance) + parseFloat(this.balanceInfo.balance_money)).toFixed(2)
let priceSplit = price.split(".")
this.integer = priceSplit[0]
this.decimal = priceSplit[1]
} else {
this.$message.warning(res.message)
}
}).catch(err => {
this.$message.error(err.message)
})
},
/**
* 获取充值套餐列表
*/
getData() {
rechargeList({
page: this.currentPage,
page_size: this.pageSize
}).then(res => {
if (res.code == 0 && res.data.list) {
this.rechargeList = res.data.list
this.total = res.data.count
} else {
this.$message.warning(res.message)
}
this.loading = false
}).catch(err => {
this.loading = false
this.$message.error(err.message)
})
},
imageError(index) {
this.rechargeList[index].cover_img = this.defaultGoodsImage;
},
handleDetail(index, row) {
this.$router.push({path: '/member/recharge_detail', query: {id: row.recharge_id}})
},
rechargeOrder() {
this.$router.push('/member/recharge_order')
}
}
}
</script>
<style lang="scss" scoped>
.box {
width: 100%;
position: relative;
}
.null-page {
width: 100%;
height: 730px;
background-color: #FFFFFF;
position: absolute;
top: 0;
left: 0;
z-index: 9;
}
.el-card.is-always-shadow,
.el-card.is-hover-shadow:focus,
.el-card.is-hover-shadow:hover {
box-shadow: unset;
}
.el-card {
border: 0;
}
.account-wrap {
display: flex;
margin-bottom: 10px;
.account-left {
flex: 1;
.title {
font-size: $ns-font-size-base;
font-weight: 600;
}
.money {
display: flex;
.balance-money {
b {
font-size: 30px;
}
span {
font-weight: 600;
}
}
.tx {
color: $base-color;
margin-left: 5px;
margin-top: 20px;
cursor: pointer;
}
}
}
.account-right {
flex: 1;
font-size: $ns-font-size-base;
display: flex;
align-items: center;
.item {
display: flex;
align-items: center;
.title {
margin-left: 3px;
}
.num {
margin-left: 3px;
}
}
}
}
.recharge-table {
.recharge-info {
display: flex;
align-items: center;
.el-image {
width: 60px;
height: 60px;
margin-right: 10px;
flex-shrink: 0;
}
p {
overflow: hidden;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
}
}
}
</style>

View File

@@ -0,0 +1,294 @@
<template>
<div class="box">
<div class="null-page" v-show="yes"></div>
<el-card class="box-card">
<div slot="header" class="clearfix">
<el-breadcrumb separator="/">
<el-breadcrumb-item :to="{ path: '/member/account' }">账户余额</el-breadcrumb-item>
<el-breadcrumb-item :to="{ path: '/member/recharge_list' }">充值套餐列表</el-breadcrumb-item>
<el-breadcrumb-item>充值记录</el-breadcrumb-item>
</el-breadcrumb>
</div>
<div v-loading="loading">
<div class="order-list">
<nav>
<li>套餐名称</li>
<li>面值</li>
<li>购买价格</li>
<li>赠送积分</li>
<li>赠送成长值</li>
</nav>
<div class="list" v-if="orderList.length > 0">
<div class="item" v-for="(orderItem, orderIndex) in orderList" :key="orderIndex">
<div class="head">
<span class="create-time">{{ $util.timeStampTurnTime(orderItem.create_time) }}</span>
<span class="order-no">订单号{{ orderItem.order_no }}</span>
</div>
<ul>
<li>
<div class="img-wrap">
<el-image :src="$img(orderItem.cover_img)" fit="cover" @error="imageError(orderIndex)"></el-image>
</div>
<div class="info-wrap">
<h5 :title="orderItem.recharge_name">{{ orderItem.recharge_name }}</h5>
<!-- <span>规格规格值</span> -->
</div>
</li>
<li>
<span>{{ orderItem.face_value }}</span>
</li>
<li>
<span>{{ orderItem.buy_price }}</span>
</li>
<li>
<span>{{ orderItem.point }}</span>
</li>
<li>
<span>{{ orderItem.growth }}</span>
</li>
</ul>
</div>
</div>
<div v-else-if="!loading && orderList.length == 0" class="empty-wrap">暂无相关订单</div>
</div>
<div class="pager">
<el-pagination
background
:pager-count="5"
:total="total"
prev-text="上一页"
next-text="下一页"
:current-page.sync="currentPage"
:page-size.sync="pageSize"
@size-change="handlePageSizeChange"
@current-change="handleCurrentPageChange"
hide-on-single-page
></el-pagination>
</div>
</div>
</el-card>
</div>
</template>
<script>
import {rechargeOrder} from "@/api/member/account"
import {mapGetters} from 'vuex';
export default {
name: "recharge_list",
layout: "member",
components: {},
data: () => {
return {
orderList: [],
total: 0,
currentPage: 1,
pageSize: 10,
loading: true,
yes: true
}
},
created() {
this.getListData()
},
mounted() {
let self = this;
setTimeout(function () {
self.yes = false
}, 300)
},
computed: {
...mapGetters(['defaultGoodsImage'])
},
methods: {
handlePageSizeChange(size) {
this.pageSize = size
this.refresh()
},
handleCurrentPageChange(page) {
this.currentPage = page
this.refresh()
},
refresh() {
this.loading = true
this.getListData()
},
getListData() {
rechargeOrder({
page: this.currentPage,
page_size: this.pageSize
}).then(res => {
if (res.code == 0 && res.data) {
this.orderList = res.data.list;
} else {
this.$message.warning(res.message)
}
this.loading = false
}).catch(err => {
this.loading = false
})
},
imageError(index) {
this.orderList[index].cover_img = this.defaultGoodsImage;
},
}
}
</script>
<style lang="scss" scoped>
.box {
width: 100%;
position: relative;
}
.null-page {
width: 100%;
height: 730px;
background-color: #FFFFFF;
position: absolute;
top: 0;
left: 0;
z-index: 9;
}
.el-card.is-always-shadow,
.el-card.is-hover-shadow:focus,
.el-card.is-hover-shadow:hover {
box-shadow: unset;
}
.el-card {
border: 0;
}
.order-list {
nav {
overflow: hidden;
padding: 10px;
background: #fff;
margin-bottom: 10px;
border-bottom: 1px solid #eeeeee;
li {
float: left;
&:nth-child(1) {
width: 40%;
}
&:nth-child(2) {
width: 15%;
}
&:nth-child(3) {
width: 15%;
}
&:nth-child(4) {
width: 15%;
}
&:nth-child(5) {
width: 15%;
}
}
}
.list {
.item {
margin-bottom: 20px;
border: 1px solid #eeeeee;
border-top: 0;
.head {
padding: 8px 10px;
background: #f7f7f7;
font-size: 12px;
.create-time {
margin-right: 10px;
}
border-bottom: 1px solid #eeeeee;
a {
margin: 0 10px 0 20px;
}
.order-type {
margin-left: 30px;
}
}
}
ul {
background-color: #fff;
padding: 10px;
overflow: hidden;
li {
float: left;
line-height: 60px;
&:nth-child(1) {
width: 40%;
line-height: inherit;
.img-wrap {
width: 60px;
height: 60px;
float: left;
margin-right: 10px;
border-radius: 5px;
overflow: hidden;
.el-image {
width: 100%;
height: 100%;
}
}
.info-wrap {
margin-left: 70px;
h5 {
font-weight: normal;
font-size: $ns-font-size-base;
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 2;
overflow: hidden;
margin-right: 10px;
}
}
}
&:nth-child(2) {
width: 15%;
}
&:nth-child(3) {
width: 15%;
}
&:nth-child(4) {
width: 15%;
}
&:nth-child(5) {
width: 15%;
}
}
}
}
.empty-wrap {
text-align: center;
padding: 10px;
}
}
</style>

View File

@@ -0,0 +1,322 @@
<template>
<div class="box">
<div class="null-page" v-show="yes"></div>
<div class="security" v-loading="loading">
<div class="item-wrap" v-if="type == 'all'">
<div class="item">
<div class="item-content">
<i class="iconfont icon-xiugaidenglumima"></i>
<div class="name-wrap">
<div class="name">登录密码</div>
<div class="info">互联网账号存在被盗风险建议您定期更改密码以保护账户安全</div>
</div>
</div>
<div class="btn">
<el-button type="primary" size="medium" @click="edit('password')">修改</el-button>
</div>
</div>
<!-- <div class="item">
<div class="item-content">
<i class="iconfont iconyouxiang1"></i>
<div class="name-wrap">
<div class="name">邮箱绑定</div>
<div class="info">验证后可用于快速找回登录密码及支付密码</div>
</div>
</div>
<div class="btn"><el-button type="primary" size="medium" @click="edit('email')">修改</el-button></div>
</div> -->
<div class="item">
<div class="item-content">
<i class="iconfont icon-shoujiyanzheng"></i>
<div class="name-wrap">
<div class="name">手机验证</div>
<div class="info">验证后可用于快速找回登录密码及支付密码接收账户余额变动提醒</div>
</div>
</div>
<div class="btn">
<el-button type="primary" size="medium" @click="edit('tell')">修改</el-button>
</div>
</div>
<!-- <div class="item">
<div class="item-content">
<i class="el-icon-lock"></i>
<div class="name-wrap">
<div class="name">支付密码</div>
<div class="content">互联网支付存在被盗风险建议您定期更改支付密码以保护账户安全</div>
</div>
</div>
<div class="btn"><el-button type="primary" size="medium" @click="edit('payPassWord')">修改</el-button></div>
</div> -->
</div>
<div class="edit" v-if="type == 'password'">
<div class="title">修改登录密码</div>
<div v-if="memberInfo.password">
<div class="pass-form">
<el-form :model="passWordForm" :rules="passWordRules" ref="passWordRef" label-width="100px">
<el-form-item label="原密码" prop="oldPass">
<el-input type="password" placeholder="当前密码" v-model="passWordForm.oldPass"></el-input>
</el-form-item>
<el-form-item label="新密码" prop="pass">
<el-input type="password" placeholder="新密码" v-model="passWordForm.pass"></el-input>
</el-form-item>
<el-form-item label="确认密码" prop="checkPass">
<el-input type="password" placeholder="请确认新密码" v-model="passWordForm.checkPass"></el-input>
</el-form-item>
</el-form>
</div>
<div class="btn">
<el-button type="primary" @click="save">保存</el-button>
<el-button @click="type = 'all'">取消</el-button>
</div>
</div>
<div v-else class="tell-pass">
<el-form :model="tellPassForm" :rules="tellPassRules" ref="tellPassRef" label-width="100px">
<el-form-item label="验证码" prop="code">
<el-input placeholder="请输入验证码" maxlength="4" v-model="tellPassForm.code">
<template slot="append">
<img :src="captcha.img" mode class="captcha" @click="getcaptcha" />
</template>
</el-input>
</el-form-item>
<el-form-item label="动态码" prop="tellPassDynacode">
<el-input placeholder="请输入动态码" v-model="tellPassForm.tellPassDynacode">
<template slot="append">
<el-button type="primary" @click="getTellPassCode">{{ tellPassForm.tellPassCodeText }}</el-button>
</template>
</el-input>
</el-form-item>
<p class="tell-code">点击获取动态码将会向您已绑定的手机号{{ memberInfo.mobile | mobile }}发送验证码</p>
<el-form-item label="新密码" prop="pass">
<el-input type="password" placeholder="新密码" v-model="tellPassForm.pass"></el-input>
</el-form-item>
<el-form-item label="确认密码" prop="checkPass">
<el-input type="password" placeholder="请确认新密码" v-model="tellPassForm.checkPass"></el-input>
</el-form-item>
</el-form>
<div class="btn">
<el-button type="primary" @click="tellPassSave">保存</el-button>
<el-button @click="type = 'all'">取消</el-button>
</div>
</div>
</div>
<div class="edit" v-if="type == 'email'">
<div class="title">绑定邮箱</div>
<div class="pass-form">
<el-form :model="emailForm" :rules="emailRules" ref="emailRef" label-width="100px">
<el-form-item label="当前邮箱" prop="email" v-if="emailForm.currEmail">
<p>{{ emailForm.currEmail }}</p>
</el-form-item>
<el-form-item label="邮箱" prop="email">
<el-input type="email" placeholder="请输入邮箱" v-model="emailForm.email"></el-input>
</el-form-item>
<el-form-item label="验证码" prop="code">
<el-input placeholder="请输入验证码" maxlength="4" v-model="emailForm.code">
<template slot="append">
<img :src="captcha.img" mode class="captcha" @click="getcaptcha" />
</template>
</el-input>
</el-form-item>
<el-form-item label="动态码" prop="emailDynacode">
<el-input placeholder="请输入动态码" v-model="emailForm.emailDynacode">
<template slot="append">
<el-button type="primary" @click="getEmailCode">{{ emailForm.emailCodeText }}</el-button>
</template>
</el-input>
</el-form-item>
</el-form>
</div>
<div class="btn">
<el-button type="primary" @click="bindEmail">保存</el-button>
<el-button @click="type = 'all'">取消</el-button>
</div>
</div>
<div class="edit" v-if="type == 'tell'">
<div class="title">绑定手机号</div>
<div class="pass-form">
<el-form :model="tellForm" :rules="tellRules" ref="tellRef" label-width="100px">
<el-form-item label="当前手机号" prop="email" v-if="tellForm.currTell">
<p>{{ tellForm.currTell }}</p>
</el-form-item>
<el-form-item label="手机号" prop="tell">
<el-input type="tell" placeholder="请输入手机号" v-model="tellForm.tell"></el-input>
</el-form-item>
<el-form-item label="验证码" prop="code">
<el-input placeholder="请输入验证码" maxlength="4" v-model="tellForm.code">
<template slot="append">
<img :src="captcha.img" mode class="captcha" @click="getcaptcha" />
</template>
</el-input>
</el-form-item>
<el-form-item label="动态码" prop="tellDynacode">
<el-input placeholder="请输入动态码" v-model="tellForm.tellDynacode">
<template slot="append">
<el-button type="primary" @click="gettellCode">{{ tellForm.tellCodeText }}</el-button>
</template>
</el-input>
</el-form-item>
</el-form>
</div>
<div class="btn">
<el-button type="primary" @click="bindtell">保存</el-button>
<el-button @click="type = 'all'">取消</el-button>
</div>
</div>
<div class="edit-pay" v-if="type == 'payPassWord'">
<div class="title">绑定支付密码</div>
<div class="container">
<div class="name" v-if="step != 0">请输入6位支付密码建议不要使用重复或连续数字</div>
<div class="name" v-else-if="isSend">验证码已发送至{{ tellForm.currTell | mobile }}</div>
<div class="password-wrap">
<el-input :maxlength="step == 0 ? 4 : 6" @change="input" ref="input" :auto-focus="true" v-model="payInput" :placeholder="palceText" v-if="step == 0"/>
<el-input :maxlength="step == 0 ? 4 : 6" @change="input" ref="input" :auto-focus="true" v-model="payInput" type="password" :placeholder="palceText" v-else />
<div v-show="step == 0" class="dynacode" @click="sendMobileCode">{{ payCodeText }}</div>
</div>
</div>
<div class="btn">
<el-button type="primary" @click="bindPayPwd" :disabled="isClick">保存</el-button>
<el-button @click="type = 'all'">取消</el-button>
</div>
</div>
</div>
</div>
</template>
<script>
import security from './security';
export default {
name: 'security',
layout: "member",
mixins: [security]
};
</script>
<style lang="scss" scoped>
.box {
width: 100%;
position: relative;
}
.null-page {
width: 100%;
height: 730px;
background-color: #FFFFFF;
position: absolute;
top: 0;
left: 0;
z-index: 9;
}
.security {
background: #ffffff;
.el-form {
margin: 0 30px;
.captcha {
vertical-align: top;
max-width: inherit;
width: 74px;
max-height: 38px;
line-height: 38px;
cursor: pointer;
}
}
.item {
border-bottom: 1px solid #f1f1ff;
display: flex;
align-items: center;
justify-content: space-between;
padding: 20px;
.item-content {
display: flex;
align-items: center;
i {
font-size: 40px;
}
.name-wrap {
margin-left: 20px;
}
}
}
.edit {
padding: 20px;
.title {
padding-bottom: 5px;
font-size: $ns-font-size-base;
border-bottom: 1px solid #f1f1f1;
}
.pass-form {
margin-top: 20px;
display: flex;
justify-content: center;
.el-form {
width: 500px;
}
}
.btn {
display: flex;
justify-content: center;
}
}
.tell-pass {
margin-top: 20px;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
.el-form {
width: 500px;
}
.tell-code {
margin-left: 66px;
margin-bottom: 20px;
}
}
.edit-pay {
padding: 20px;
text-align: center;
.title {
font-size: $ns-font-size-base;
border-bottom: 1px solid #f1f1f1;
text-align: left;
padding-bottom: 5px;
}
.dynacode {
cursor: pointer;
text-align: right;
margin-right: 329px;
color: $base-color;
margin-bottom: 20px;
}
.el-input {
width: 300px;
margin-top: 20px;
}
.btn {
margin-top: 20px;
}
.name {
margin-top: 10px;
}
}
}
</style>

View File

@@ -0,0 +1,600 @@
import {
passWord,
emailCode,
checkEmail,
email,
tellCode,
tell,
verifyPayPwdCode,
modifyPayPassword,
payPwdCode,
pwdMoblieCode
} from "@/api/member/security"
import {
info
} from "@/api/member/info"
import {
captcha
} from "@/api/website"
export default {
name: "security",
components: {},
data() {
var validatePass = (rule, value, callback) => {
if (value === "") {
callback(new Error("请输入新密码"))
} else if (value == this.passWordForm.oldPass) {
callback(new Error("新密码不能与原密码相同!"))
} else {
if (this.passWordForm.checkPass !== "") {
this.$refs.passWordRef.validateField("checkPass")
}
callback()
}
}
var validatePass2 = (rule, value, callback) => {
if (value === "") {
callback(new Error("请再次输入密码"))
} else if (value !== this.passWordForm.pass) {
callback(new Error("两次输入密码不一致!"))
} else {
callback()
}
}
var validateTellPass = (rule, value, callback) => {
if (value === "") {
callback(new Error("请输入新密码"))
} else if (value == this.tellPassForm.oldPass) {
callback(new Error("新密码不能与原密码相同!"))
} else {
if (this.tellPassForm.checkPass !== "") {
this.$refs.tellPassRef.validateField("checkPass")
}
callback()
}
}
var validateTellPass2 = (rule, value, callback) => {
if (value === "") {
callback(new Error("请再次输入密码"))
} else if (value !== this.tellPassForm.pass) {
callback(new Error("两次输入密码不一致!"))
} else {
callback()
}
}
var checkemail = (rules, value, callback) => {
const regEmail = /^\w+@\w+(\.\w+)+$/
if (regEmail.test(value)) {
return callback()
}
callback(new Error("请输入正确的的邮箱"))
}
var checkTell = (rules, value, callback) => {
const regMobile = /^1[3|4|5|6|7|8|9][0-9]{9}$/
if (regMobile.test(value)) {
return callback()
}
callback(new Error("请输入正确的手机号"))
}
return {
type: "all",
passWordForm: {
oldPass: "",
pass: "",
checkPass: ""
},
emailForm: {
email: "",
code: "", //邮箱验证码
emailDynacode: "", //邮箱动态验证码
emailCodeText: "",
key: "",
currEmail: ""
},
passWordRules: {
oldPass: [{
required: true,
message: "请输入原密码",
trigger: "blur"
}],
pass: [{
required: true,
validator: validatePass,
trigger: "blur"
}],
checkPass: [{
required: true,
validator: validatePass2,
trigger: "blur"
}]
},
emailRules: {
email: [{
required: true,
message: "请输入正确的邮箱",
trigger: "blur"
}, {
validator: checkemail,
trigger: "blur"
}],
code: [{
required: true,
message: "请输入验证码",
trigger: "blur"
}],
emailDynacode: [{
required: true,
message: "请输入动态验证码",
trigger: "blur"
}]
},
captcha: {
id: "",
img: ""
},
seconds: 120,
timer: null,
isSend: false,
isMobileSend: false,
tellForm: {
tell: "",
code: "", //邮箱验证码
tellDynacode: "", //邮箱动态验证码
tellCodeText: "",
key: "",
currTell: ""
},
tellRules: {
tell: [{
required: true,
message: "请输入正确的手机号",
trigger: "blur"
}, {
validator: checkTell,
trigger: "blur"
}],
code: [{
required: true,
message: "请输入验证码",
trigger: "blur"
}],
tellDynacode: [{
required: true,
message: "请输入动态验证码",
trigger: "blur"
}]
},
isClick: true,
payCodeText: '获取验证码',
step: 0,
payCode: '', // 动态码
payPassword: '', // 支付密码
payRepassword: '', // 重复支付密码
payKey: '', // 短信key
payInput: '',
palceText: '输入短信验证码',
memberInfo: {},
tellPassForm: {
code: "",
tellPassCodeText: "",
key: "",
tellPassDynacode: "",
pass: '',
checkPass: ''
},
tellPassRules: {
code: [{
required: true,
message: "请输入验证码",
trigger: "blur"
}],
tellPassDynacode: [{
required: true,
message: "请输入动态验证码",
trigger: "blur"
}],
pass: [{
required: true,
validator: validateTellPass,
trigger: "blur"
}],
checkPass: [{
required: true,
validator: validateTellPass2,
trigger: "blur"
}]
},
loading: true,
yes: true
}
},
created() {
this.getcaptcha()
this.seconds = 120
this.tellForm.tellCodeText = "获取动态码"
this.emailForm.emailCodeText = "获取动态码"
this.tellPassForm.tellPassCodeText = "获取动态码"
this.isSend = false
this.isMobileSend = false
clearInterval(this.timer)
this.getInfo()
},
mounted() {
let self = this;
setTimeout(function () {
self.yes = false
}, 300)
},
methods: {
//获取个人信息
async getInfo() {
await info().then(res => {
if (res.code == 0) {
this.memberInfo = res.data
this.emailForm.currEmail = res.data.email
this.tellForm.currTell = res.data.mobile
}
this.loading = false
}).catch(err => {
this.loading = false
this.$message.error(err.message)
})
},
async edit(type) {
await this.getInfo()
if (type == 'payPassWord') {
if (!this.tellForm.currTell) {
this.$confirm("你还未绑定手机号,请先绑定手机号?", "提示信息", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning"
}).then(res => {
if (res = 'confirm') {
this.type = 'tell'
} else {
this.type = 'all'
}
})
} else {
this.type = type
}
} else {
this.type = type
}
},
//获取验证码
getcaptcha() {
captcha({
captcha_id: this.captcha.id
}).then(res => {
if (res.code >= 0) {
this.captcha = res.data
this.captcha.img = this.captcha.img.replace(/\r\n/g, "")
}
}).catch(err => {
this.$message.error(err.message)
})
},
//修改密码
save() {
this.$refs.passWordRef.validate(valid => {
if (valid) {
passWord({
new_password: this.passWordForm.pass,
old_password: this.passWordForm.oldPass
}).then(res => {
this.$message({
message: "修改密码成功",
type: "success"
});
this.type = "all";
this.$store.dispatch("member/member_detail", {
refresh: 1
});
this.passWordForm.pass = "";
this.passWordForm.oldPass = "";
this.passWordForm.checkPass = "";
}).catch(err => {
this.$message.error(err.message)
})
} else {
return false
}
})
},
// 检测邮箱是否存在
async getCheckEmail() {
let result = await checkEmail({
email: this.emailForm.email
}).then(res => {
if (res.code != 0) {
this.$message({
message: res.message,
type: "success"
});
return false
}
return true
}).catch(err => {
this.$message.error(err.message)
});
return result
},
//绑定邮箱
async bindEmail() {
this.$refs.emailRef.validate(valid => {
if (valid) {
email({
email: this.emailForm.email,
captcha_id: this.captcha.id,
captcha_code: this.emailForm.code,
code: this.emailForm.emailDynacode,
key: this.emailForm.key
}).then(res => {
if (res.code == 0) {
this.$message({
message: "邮箱绑定成功",
type: "success"
});
this.type = "all";
this.emailForm.email = "";
this.emailForm.code = "";
this.emailForm.emailDynacode = "";
clearInterval(this.timer);
this.getcaptcha()
}
}).catch(err => {
this.getcaptcha();
this.$message.error(err.message)
})
} else {
return false
}
})
},
//获取手机验证码
async gettellCode() {
if (!this.isMobileSend) {
this.isMobileSend = true;
await tellCode({
mobile: this.tellForm.tell,
captcha_id: this.captcha.id,
captcha_code: this.tellForm.code
}).then(res => {
let data = res.data;
if (data.key) {
if (this.seconds == 120 && this.timer == null) {
this.timer = setInterval(() => {
this.seconds--;
this.tellForm.tellCodeText = "已发送(" + this.seconds + "s)"
}, 1000)
}
this.tellForm.key = data.key
} else {
this.$message({
message: res.message,
type: "warning"
});
this.isMobileSend = false
}
}).catch(err => {
this.getcaptcha();
this.$message.error(err.message);
if (err.message == '当前手机号已存在') {
this.isMobileSend = false
}
})
} else {
this.$message({
message: "请勿重复点击",
type: "warning"
})
}
},
//绑定手机号
bindtell() {
this.$refs.tellRef.validate(valid => {
if (valid) {
tell({
mobile: this.tellForm.tell,
captcha_id: this.captcha.id,
captcha_code: this.tellForm.code,
code: this.tellForm.tellDynacode,
key: this.tellForm.key
}).then(res => {
if (res.code == 0) {
this.$message({
message: "手机号绑定成功",
type: "success"
});
this.type = "all";
this.tellForm.email = "";
this.tellForm.code = "";
this.tellForm.emailDynacode = "";
clearInterval(this.timer);
this.getcaptcha()
}
}).catch(err => {
this.getcaptcha();
this.$message.error(err.message);
})
} else {
return false
}
})
},
//获取输入框数据
input(val) {
this.isClick = false;
if (this.step == 0 && val.length == 4) {
this.payCode = val;
} else if (this.step == 1 && val.length == 6) {
this.payPassword = val;
} else if (val.length == 6) {
this.payRepassword = val;
}
},
//获取支付验证码
sendMobileCode() {
if (!this.isSend) {
payPwdCode().then(res => {
let data = res.data;
if (data.key) {
if (this.seconds == 120 && this.timer == null) {
this.timer = setInterval(() => {
this.seconds--;
this.payCodeText =
"已发送(" + this.seconds + "s)";
}, 1000);
}
this.payKey = data.key;
} else {
this.$message({
message: res.message,
type: 'warning'
});
this.isSend = false;
}
}).catch(err => {
this.$message.error(err.message);
});
}
},
//点击确定
bindPayPwd() {
clearInterval(this.timer);
const reg = /^[0-9]*$/;
if (this.step == 0) {
verifyPayPwdCode({
code: this.payCode,
key: this.payKey
}).then(res => {
if (res.code == 0) {
this.$refs.input.clear();
this.step = 1;
this.palceText = '请设置支付密码'
}
}).catch(err => {
this.$message.error(err.message);
})
} else if (this.step == 1) {
if (reg.test(this.$refs.input.value)) {
this.$refs.input.clear();
this.step = 2;
this.palceText = '请再次输入'
} else {
this.$message.error('请输入数字');
this.step = 1;
this.$refs.input.clear();
}
} else {
if (this.payPassword == this.payRepassword) {
if (this.isSub) return;
this.isSub = true;
modifyPayPassword({
key: this.payKey,
code: this.payCode,
password: this.payPassword
}).then(res => {
if (res.code >= 0) {
this.$message({
message: "修改支付密码成功",
type: "success"
});
this.type = 'all';
this.step = 0;
this.$refs.input.clear();
clearInterval(this.timer)
}
}).catch(err => {
this.$message.error(err.message);
})
} else {
this.$message.error('两次密码输入不一样');
this.initInfo();
}
}
},
//初始化信息
initInfo() {
this.step = 1;
this.palceText = '请设置支付密码';
this.password = '';
this.repassword = '';
this.oldpassword = '';
this.isSub = false;
this.$refs.input.clear();
},
//获取动态码
getTellPassCode() {
if (!this.isSend) {
this.isSend = true;
pwdMoblieCode({
captcha_id: this.captcha.id,
captcha_code: this.tellPassForm.code,
}).then(res => {
let data = res.data;
if (data.key) {
if (this.seconds == 120 && this.timer == null) {
this.timer = setInterval(() => {
this.seconds--;
this.tellPassForm.tellPassCodeText = "已发送(" + this.seconds + "s)"
}, 1000)
}
this.tellPassForm.key = data.key
} else {
this.$message({
message: res.message,
type: "warning"
});
this.isSend = false
}
}).catch(err => {
this.getcaptcha();
this.$message.error(err.message)
})
} else {
this.$message({
message: "请勿重复点击",
type: "warning"
})
}
},
//修改密码
tellPassSave() {
this.$refs.tellPassRef.validate(valid => {
if (valid) {
passWord({
new_password: this.tellPassForm.pass,
code: this.tellPassForm.tellPassDynacode,
key: this.tellPassForm.key,
}).then(res => {
this.$message({
message: "修改密码成功",
type: "success"
});
this.type = "all";
this.$store.dispatch("member/member_detail", {
refresh: 1
});
this.tellPassForm.pass = "";
this.tellPassForm.checkPass = "";
this.tellPassForm.key = "";
this.tellPassForm.tellPassDynacode = "";
}).catch(err => {
this.$message.error(err.message)
})
} else {
return false
}
})
},
},
filters: {
mobile(mobile) {
return mobile.substring(0, 4 - 1) + '****' + mobile.substring(6 + 1);
}
},
}

View File

@@ -0,0 +1,142 @@
<template>
<div class="box">
<div class="null-page" v-show="yes"></div>
<el-card class="box-card">
<div slot="header" class="clearfix">
<span>提现记录</span>
</div>
<div v-loading="loading" class="withdrawal-list">
<el-table v-if="dataList.length > 0" :data="dataList" border>
<el-table-column prop="transfer_type_name" label="账户类型" width="150"></el-table-column>
<el-table-column prop="apply_money" label="提现金额" width="150"></el-table-column>
<el-table-column prop="apply_time" label="提现时间"></el-table-column>
<el-table-column prop="status_name" label="提现状态" width="150"></el-table-column>
<el-table-column label="操作" width="150">
<template slot-scope="scope">
<el-button size="mini" @click="handleEdit(scope.$index, scope.row)">详情</el-button>
</template>
</el-table-column>
</el-table>
<div v-else-if="!loading && dataList.length == 0" class="ns-text-align">暂无提现记录</div>
</div>
<div class="pager">
<el-pagination
background
:pager-count="5"
:total="total"
prev-text="上一页"
next-text="下一页"
:current-page.sync="currentPage"
:page-size.sync="pageSize"
@size-change="handlePageSizeChange"
@current-change="handleCurrentPageChange"
hide-on-single-page
></el-pagination>
</div>
</el-card>
</div>
</template>
<script>
import {withdrawList} from "@/api/member/account"
export default {
name: 'withdrawal',
layout: "member",
components: {},
data: () => {
return {
dataList: [],
currentPage: 1,
pageSize: 10,
total: 0,
loading: true,
yes: true
};
},
created() {
this.getDateList();
},
mounted() {
let self = this;
setTimeout(function () {
self.yes = false
}, 300)
},
methods: {
handlePageSizeChange(size) {
this.pageSize = size
this.refresh()
},
handleCurrentPageChange(page) {
this.currentPage = page
this.refresh()
},
refresh() {
this.loading = true
this.getDateList()
},
getDateList() {
withdrawList({
page_size: this.pageSize,
page: this.currentPage
}).then(res => {
if (res.code == 0 && res.data) {
this.dataList = res.data.list
this.dataList.forEach(item => {
item.apply_time = this.$util.timeStampTurnTime(item.apply_time)
})
this.total = res.data.count
}
this.loading = false
}).catch(err => {
this.loading = false
})
},
handleEdit(index, row) {
this.$router.push({path: '/member/withdrawal_detail', query: {id: row.id}})
}
}
};
</script>
<style lang="scss" scoped>
.box {
width: 100%;
position: relative;
}
.null-page {
width: 100%;
height: 730px;
background-color: #FFFFFF;
position: absolute;
top: 0;
left: 0;
z-index: 9;
}
.el-card.is-always-shadow,
.el-card.is-hover-shadow:focus,
.el-card.is-hover-shadow:hover {
box-shadow: unset;
}
.el-card {
border: 0;
}
.ns-len-input {
width: 350px;
}
.el-select {
margin-right: 10px;
}
.page-wrap {
margin-top: 10px;
}
</style>

View File

@@ -0,0 +1,146 @@
<template>
<div class="box">
<div class="null-page" v-show="yes"></div>
<el-card class="box-card">
<div slot="header" class="clearfix">
<el-breadcrumb separator="/">
<el-breadcrumb-item :to="{ path: '/member/withdrawal' }">提现记录</el-breadcrumb-item>
<el-breadcrumb-item>提现详情</el-breadcrumb-item>
</el-breadcrumb>
</div>
<div v-loading="loading">
<div class="money-wrap">
<span>-{{ detail.apply_money }}</span>
</div>
<div class="line-wrap">
<span class="label">当前状态</span>
<span class="value">{{ detail.status_name }}</span>
</div>
<div class="line-wrap">
<span class="label">交易号</span>
<span class="value">{{ detail.withdraw_no }}</span>
</div>
<div class="line-wrap">
<span class="label">手续费</span>
<span class="value">{{ detail.service_money }}</span>
</div>
<div class="line-wrap">
<span class="label">申请时间</span>
<span class="value">{{ $util.timeStampTurnTime(detail.apply_time) }}</span>
</div>
<div class="line-wrap" v-if="detail.status">
<span class="label">审核时间</span>
<span class="value">{{ $util.timeStampTurnTime(detail.audit_time) }}</span>
</div>
<div class="line-wrap" v-if="detail.bank_name">
<span class="label">银行名称</span>
<span class="value">{{ detail.bank_name }}</span>
</div>
<div class="line-wrap">
<span class="label">收款账号</span>
<span class="value">{{ detail.account_number }}</span>
</div>
<div class="line-wrap" v-if="detail.status == -1 && detail.refuse_reason">
<span class="label">拒绝理由</span>
<span class="value">{{ detail.refuse_reason }}</span>
</div>
<div class="line-wrap" v-if="detail.status == 2">
<span class="label">转账方式名称</span>
<span class="value">{{ detail.transfer_type_name }}</span>
</div>
<div class="line-wrap" v-if="detail.status == 2">
<span class="label">转账时间</span>
<span class="value">{{ $util.timeStampTurnTime(detail.payment_time) }}</span>
</div>
</div>
</el-card>
</div>
</template>
<script>
import {withdrawDetail} from "@/api/member/account"
export default {
name: 'withdrawal_detail',
layout: "member",
components: {},
data: () => {
return {
loading: true,
id: '',
detail: {},
yes: true
};
},
created() {
this.getDetail();
},
mounted() {
let self = this;
setTimeout(function () {
self.yes = false
}, 300)
},
methods: {
//获得提现详情
getDetail() {
this.id = this.$route.query.id
withdrawDetail({
id: this.id
}).then(res => {
if (res.data) {
this.detail = res.data;
}
this.loading = false
}).catch(err => {
this.loading = false
})
}
}
};
</script>
<style lang="scss" scoped>
.box {
width: 100%;
position: relative;
}
.null-page {
width: 100%;
height: 730px;
background-color: #FFFFFF;
position: absolute;
top: 0;
left: 0;
z-index: 9;
}
.el-card.is-always-shadow,
.el-card.is-hover-shadow:focus,
.el-card.is-hover-shadow:hover {
box-shadow: unset;
}
.el-card {
border: 0;
}
.money-wrap {
font-size: 20px;
font-weight: 600;
}
.line-wrap {
margin-top: 20px;
.label {
display: inline-block;
width: 100px;
color: #898989;
}
}
</style>

View File

@@ -0,0 +1,134 @@
<template>
<div class="box">
<div class="null-page" v-show="yes"></div>
<el-card class="box-card">
<div slot="header" class="title clearfix">
<el-breadcrumb separator="/">
<el-breadcrumb-item :to="{ path: '/member/order_list' }">我的订单</el-breadcrumb-item>
<el-breadcrumb-item :to="{ path: '/member/order_detail?order_id=' + order_id }">订单详情</el-breadcrumb-item>
<el-breadcrumb-item>批量退款</el-breadcrumb-item>
</el-breadcrumb>
</div>
<div slot="header" class="shopings clearfix">
<span>选择退款商品</span>
</div>
<el-table ref="multipleTable" :data="orderData" tooltip-effect="dark" style="width: 100%" @selection-change="handleSelectionChange">
<el-table-column type="selection" width="55"></el-table-column>
<el-table-column label="商品图片" width="100" prop="goods_image">
<template slot-scope="scope">
<img class="box-img" :src="$img(scope.row.sku_image, { size: 'mid' })" alt="" @error="scope.row.sku_image = defaultGoodsImage" />
</template>
</el-table-column>
<el-table-column label="商品名称" prop="goods_name"></el-table-column>
<el-table-column label="价格" width="180" prop="price"></el-table-column>
</el-table>
<div class="flooter">
<div class="flooter-left">
<!-- <el-checkbox v-model="checked">全选</el-checkbox> -->
</div>
<div class="flooter-right">
共计选中{{order_goods_ids.length}}件商品
<el-button v-if="order_goods_ids.length" class="but" type="primary" @click="next">下一步</el-button>
<el-button v-else class="but" type="info">请选择退款商品</el-button>
</div>
</div>
</el-card>
</div>
</template>
<script>
import {
apiOrderDetail
} from "@/api/order/order"
import {
mapGetters
} from 'vuex';
export default {
name: "account_edit",
components: {},
data() {
return {
yes: true,
order_id: 0,
orderData: [],
checked: false,
order_goods_ids: []
}
},
created() {
this.order_id = this.$route.query.order_id
this.getOrderInfo()
},
mounted() {
},
computed: {
...mapGetters(['defaultGoodsImage'])
},
layout: 'member',
methods: {
/**
* 获取商品数据
*/
getOrderInfo() {
apiOrderDetail({
order_id: this.order_id
}).then((res) => {
if (res.code >= 0) {
this.orderData = [];
res.data.order_goods.forEach((item) => {
if (item.refund_status == 0) {
this.orderData.push(item);
}
})
}
})
},
handleSelectionChange(e) {
this.order_goods_ids = e.map((item, index) => {
return item.order_goods_id;
});
},
next() {
this.$router.push({
path: '/order/orderbatch_refund',
query: {
order_goods_id: this.order_goods_ids.join(','),
order_id: this.order_id
}
});
},
}
}
</script>
<style lang="scss" scoped>
.box-img {
width: 70px;
height: auto;
}
.flooter {
padding: 18px 20px;
box-sizing: border-box;
display: flex;
align-content: center;
justify-content: space-between;
.but {
padding: 10px 20px;
margin-left: 10px;
}
}
.title {
padding: 0 0 18px;
border-bottom: 1px solid #EBEEF5;
}
.shopings {
padding: 18px 0 0;
}
</style>

View File

@@ -0,0 +1,524 @@
<template>
<div class="box">
<div class="null-page" v-show="yes"></div>
<div v-loading="loading">
<!--申请退款 start-->
<div v-if="!complainData.complain_info || action == 'apply'">
<el-card class="box-card order-list">
<div slot="header" class="clearfix">
<el-breadcrumb separator="/">
<el-breadcrumb-item :to="{ path: '/member/activist' }">退款/售后</el-breadcrumb-item>
<el-breadcrumb-item :to="{ path: '/order/refund_detail?order_goods_id=' + orderGoodsId }">退款详情
</el-breadcrumb-item>
<el-breadcrumb-item>平台维权</el-breadcrumb-item>
</el-breadcrumb>
</div>
<!--商品信息-->
<div>
<div class="goods-list">
<table>
<tr>
<td width="62.5%">商品</td>
<td width="12.5%">数量</td>
<td width="12.5%">金额</td>
</tr>
</table>
</div>
</div>
<div>
<div class="goods-list">
<table>
<tr>
<td width="62.5%">
<div class="goods-info">
<div class="goods-info-left">
<router-link :to="{ path: '/sku/' + complainData.order_goods_info.sku_id }" target="_blank">
<img class="goods-img" :src="$img(complainData.order_goods_info.sku_image, { size: 'mid' })" @error="complainData.order_goods_info.sku_image = defaultGoodsImage" />
</router-link>
</div>
<div class="goods-info-right">
<router-link :to="{ path: '/sku/' + complainData.order_goods_info.sku_id }" target="_blank">
<div class="goods-name">{{ complainData.order_goods_info.sku_name }}</div>
</router-link>
</div>
</div>
</td>
<td width="12.5%" class="goods-num">{{ complainData.order_goods_info.num }}</td>
<td width="12.5%" class="goods-money">{{ complainData.order_goods_info.goods_money }}</td>
</tr>
</table>
</div>
</div>
</el-card>
<!--退款填写-->
<div class="item-block">
<div class="block-text"></div>
<el-form ref="form" label-width="80px" class="refund-form">
<el-form-item label="退款金额">
<el-input disabled="" :value="complainData.refund_money"></el-input>
</el-form-item>
<el-form-item label="退款原因">
<el-select placeholder="请选择" v-model="complainReason">
<el-option v-for="(item, itemIndex) in complainData.refund_reason_type" :key="itemIndex" :label="item" :value="item"></el-option>
</el-select>
</el-form-item>
<el-form-item label="退款说明">
<el-input maxlength="140" show-word-limit resize="none" rows="5" placeholder="请输入退款说明(选填)" type="textarea" v-model="complainRemark"/>
</el-form-item>
</el-form>
</div>
<div class="item-block">
<div class="order-submit">
<el-button type="primary" class="el-button--primary" @click="submit">提交</el-button>
</div>
<div class="clear"></div>
</div>
</div>
<!--申请退款 end-->
<div v-else>
<div class="item-block">
<div class="block-text">{{ detail.complain_status_name }}</div>
</div>
<!--协商记录-->
<div class="item-block">
<div class="action-box">
<span class="media-left">协商记录</span>
<div class="media-right">
<div class="el-button--text" @click="actionOpen ? (actionOpen = false) : (actionOpen = true)">
协商记录
<i :class="actionOpen ? 'rotate' : ''" class="el-icon-arrow-down"></i>
</div>
</div>
<div class="clear"></div>
</div>
<div v-if="actionOpen">
<el-timeline>
<el-timeline-item :class="{ buyer: logItem.action_way == 1, seller: logItem.action_way == 2, platform: logItem.action_way == 3 }" v-for="(logItem, logIndex) in detail.refund_log_list" :key="logIndex" :timestamp="$util.timeStampTurnTime(logItem.action_time)" placement="top">
<div>
<h4 v-if="logItem.action_way == 1">买家</h4>
<h4 v-else-if="logItem.action_way == 2">卖家</h4>
<h4 v-else-if="logItem.action_way == 3">平台</h4>
<p>{{ logItem.action }}</p>
</div>
</el-timeline-item>
</el-timeline>
</div>
</div>
<!--退款详情-->
<div class="item-block">
<div class="goods-list">
<table>
<tr>
<td width="62.5%">商品</td>
<td width="12.5%">数量</td>
<td width="12.5%">退款金额</td>
</tr>
</table>
</div>
</div>
<div class="item-block">
<div class="goods-list">
<table>
<tr>
<td width="62.5%">
<div class="goods-info">
<div class="goods-info-left">
<router-link :to="{ path: '/sku/' + detail.sku_id }" target="_blank">
<img class="goods-img" :src="$img(detail.sku_image, { size: 'mid' })" @error="detail.sku_image = defaultGoodsImage" />
</router-link>
</div>
<div class="goods-info-right">
<router-link :to="{ path: '/sku/' + detail.sku_id }" target="_blank">
<div class="goods-name">{{ detail.sku_name }}</div>
</router-link>
</div>
</div>
</td>
<td width="12.5%" class="goods-num">{{ detail.num }}</td>
<td width="12.5%" class="goods-money">{{ detail.complain_apply_money }}</td>
</tr>
</table>
</div>
</div>
<div class="item-block">
<div class="order-statistics">
<table>
<tr>
<td align="right">退款原因</td>
<td align="left">{{ detail.complainReason }}</td>
</tr>
<tr>
<td align="right">退款金额</td>
<td align="left">{{ detail.complain_apply_money }}</td>
</tr>
<tr>
<td align="right">退款编号</td>
<td align="left">{{ detail.complain_no }}</td>
</tr>
<tr>
<td align="right">申请时间</td>
<td align="left">{{ $util.timeStampTurnTime(detail.complain_apply_time) }}</td>
</tr>
<tr v-if="detail.complain_time">
<td align="right">退款时间</td>
<td align="left">{{ $util.timeStampTurnTime(detail.complain_time) }}</td>
</tr>
</table>
</div>
<div class="clear"></div>
</div>
<div class="item-block" v-if="detail.complain_action.length">
<div class="order-submit" v-for="(actionItem, actionIndex) in detail.complain_action" :key="actionIndex">
<el-button type="primary" class="el-button--primary" @click="refundAction(actionItem.event)">{{ actionItem.title }}</el-button>
</div>
<div class="clear"></div>
</div>
</div>
</div>
</div>
</template>
<script>
import {mapGetters} from 'vuex';
import {complainData, complain, complainCancel} from '@/api/order/refund';
export default {
name: 'refund',
components: {},
data: () => {
return {
orderGoodsId: 0,
complainData: {
order_goods_info: {
sku_image: '',
sku_name: ''
}
},
detail: {
sku_image: ''
},
complainReason: '',
complainRemark: '',
action: '',
actionOpen: false,
loading: false,
yes: true
};
},
created() {
this.loading = true;
if (this.$route.query.order_goods_id) this.orderGoodsId = this.$route.query.order_goods_id;
this.getComplainData();
},
mounted() {
let self = this;
setTimeout(function () {
self.yes = false
}, 300)
},
computed: {
...mapGetters(['defaultGoodsImage'])
},
layout: 'member',
methods: {
/**
* 选择退款方式
* @param {Object} type
*/
selectRefundType(type) {
this.refund_type = type;
},
getComplainData() {
this.loading = true;
complainData({order_goods_id: this.orderGoodsId}).then(res => {
const {code, message, data} = res;
if (code >= 0) {
this.complainData = res.data;
this.detail = this.complainData.complain_info;
this.loading = false;
} else {
this.$message({
message: '未获取到该订单项退款信息',
type: 'warning',
duration: 2000,
onClose: () => {
this.$router.push({path: '/member/order_list'});
}
});
}
}).catch(err => {
this.loading = false;
this.$message.error({
message: err.message,
duration: 2000,
onClose: () => {
this.$router.push({path: '/member/order_list'});
}
});
});
},
submit() {
if (this.verify()) {
if (this.isSub) return;
this.isSub = true;
let submit_data = {
order_goods_id: this.orderGoodsId,
complain_reason: this.complainReason,
complain_remark: this.complainRemark
};
complain(submit_data).then(res => {
const {code, message, data} = res;
if (code >= 0) {
this.$message({
message: message,
type: 'success'
});
this.getComplainData();
this.$forceUpdate();
this.action = '';
} else {
this.isSub = false;
this.$message({message: message, type: 'warning'});
}
}).catch(err => {
this.$message.error({
message: err.message,
duration: 2000,
onClose: () => {
this.$router.push({path: '/member/order_list'});
}
});
});
}
},
verify() {
if (this.complainReason == '') {
this.$message({message: '请选择退款原因', type: 'warning'});
return false;
}
return true;
},
refundAction(event) {
switch (event) {
case 'complainCancel':
this.cancelRefund(this.detail.order_goods_id);
break;
case 'complainApply':
this.action = 'apply';
break;
}
},
cancelRefund(order_goods_id) {
this.$confirm('撤销之后本次申请将会关闭,如后续仍有问题可再次发起申请', '提示', {
confirmButtonText: '确认撤销',
cancelButtonText: '暂不撤销',
type: 'warning'
}).then(() => {
if (this.isSub) return;
this.isSub = true;
complainCancel({order_goods_id: order_goods_id}).then(res => {
const {code, message, data} = res;
if (code >= 0) {
this.$message({
message: '撤销成功',
type: 'success',
duration: 2000,
onClose: () => {
this.$router.push({path: '/member/order_list'});
}
});
} else {
this.$message({message: message, type: 'warning'});
}
}).catch(err => {
this.$message.error({
message: err.message,
duration: 2000,
onClose: () => {
this.$router.push({path: '/member/order_list'});
}
});
});
})
}
}
};
</script>
<style lang="scss" scoped>
.box {
width: 100%;
position: relative;
}
.null-page {
width: 100%;
height: 730px;
background-color: #FFFFFF;
position: absolute;
top: 0;
left: 0;
z-index: 9;
}
.el-card.is-always-shadow,
.el-card.is-hover-shadow:focus,
.el-card.is-hover-shadow:hover {
box-shadow: unset;
}
.el-card {
border: 0;
}
.clear {
clear: both;
}
.item-block {
padding: 0 15px 1px;
margin: 10px 0;
border-radius: 0;
border: none;
background: #ffffff;
.block-text {
border-color: #eeeeee;
color: $ns-text-color-black;
padding: 7px 0;
border-bottom: 1px;
}
}
.refund-form {
width: 350px;
.el-select {
width: 100%;
}
}
.order-submit {
text-align: center;
padding: 10px;
}
.goods-list {
padding: 15px 0;
table {
width: 100%;
}
.goods-info-left {
width: 60px;
height: 60px;
float: left;
.goods-img {
width: 60px;
height: 60px;
}
}
.goods-info-right {
float: left;
height: 60px;
margin-left: 10px;
color: $base-color;
width: 80%;
.goods-name {
line-height: 20px;
padding-top: 10px;
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 2;
overflow: hidden;
}
.goods-spec {
color: #999;
}
}
}
.pay-type-list {
padding: 20px 0;
}
.pay-type-item {
display: inline-block;
border: 2px solid #eeeeee;
padding: 5px 20px;
margin-right: 20px;
cursor: pointer;
}
.pay-type-item.active {
border-color: $base-color;
}
.status-wrap {
color: #999;
}
.media-left {
float: left;
}
.media-right {
float: right;
i.rotate {
transform: rotate(180deg);
transition: 0.3s;
}
}
.action-box {
padding: 10px 0;
}
.action-way {
float: left;
color: #999;
}
.head .time {
float: right;
color: #999;
}
.record-item {
margin-bottom: 10px;
}
.order-statistics {
float: left;
padding: 10px;
// color: #999;
}
.el-textarea .el-input__count {
line-height: 20px;
}
</style>

View File

@@ -0,0 +1,434 @@
<template>
<el-form class="ns-evalute" v-loading="loading">
<div class="ns-eva-li" v-for="(item, index) in goodsList" :key="index">
<!-- 商品信息 -->
<div class="ns-eva-good">
<el-image fit="scale-down" :src="$img(item.sku_image, { size: 'mid' })" @error="imageError(index)" @click="toGoodsDetail(item.sku_id)"/>
<p class="ns-eva-good-name" :title="item.sku_name" @click="toGoodsDetail(item.sku_id)">{{ item.sku_name }}</p>
<p>{{ item.price }}</p>
</div>
<!-- 评价表单 -->
<div class="ns-eva-form">
<div class="block" v-if="!isEvaluate">
<span class="demonstration">描述相符</span>
<el-rate v-model="goodsEvalList[index].scores" @change="setStar(index)"></el-rate>
<div class="level">
<i class="iconfont" :class="
goodsEvalList[index].explain_type == '1'
? 'iconhaoping1 ns-text-color'
: goodsEvalList[index].explain_type == '2'
? 'iconzhongchaping ns-text-color'
: goodsEvalList[index].explain_type == '3'
? 'iconzhongchaping'
: ''
"></i>
<span>
{{ goodsEvalList[index].explain_type == '1' ? '好评' : goodsEvalList[index].explain_type == '2' ? '中评' : goodsEvalList[index].explain_type == '3' ? '差评' : ''}}
</span>
</div>
</div>
<div class="ns-textarea">
<el-input v-if="!isEvaluate" type="textarea" :rows="5" placeholder="请在此处输入您的评价" v-model="goodsEvalList[index].content" maxlength="200" show-word-limit/>
<el-input v-else type="textarea" :rows="5" placeholder="请在此处输入您的追评" v-model="goodsEvalList[index].again_content" maxlength="200" show-word-limit/>
</div>
<div class="upload-wrap">
<el-upload ref="upload" :class="{ ishide: hide[index] }" :action="uploadActionUrl" :data="uploadData"
list-type="picture-card" :on-success="
(file, fileList) => {
return handleSuccess(file, fileList, index);
}
" :on-preview="handlePictureCardPreview" :on-remove="
(file, fileList) => {
return handleRemove(file, fileList, index);
}
" :on-exceed="handleExceed" multiple drag :limit="6">
<i class="el-icon-plus"></i>
<!-- <i class="el-icon-upload"></i> -->
<!-- <div class="el-upload__text">将文件拖到此处,或<em>点击上传</em></div>
<div class="el-upload__tip" slot="tip">只能上传jpg/png文件且不超过500kb</div> -->
</el-upload>
<el-dialog :visible.sync="dialogVisible"><img width="100%" :src="dialogImageUrl" alt="" /></el-dialog>
<div class="tips">共6张还能上传{{ imgList[index].length ? 6 - imgList[index].length : 6 }}张</div>
</div>
</div>
</div>
<div class="save-btn-wrap">
<el-button @click="save" type="primary">提交</el-button>
</div>
</el-form>
</template>
<script>
import {
mapGetters
} from 'vuex';
import {
orderInfo,
save,
uploadImg
} from '@/api/order/order';
import Config from '@/plugins/config';
export default {
name: 'evaluate',
components: {},
data: () => {
return {
loading: true,
value1: 5,
memberName: '',
memberHeadimg: '',
orderId: null,
orderNo: '',
isAnonymous: 0, //是否匿名发布 1.匿名0.公开
goodsList: [], //订单列表
goodsEvalList: [], //评价列表
imgList: [],
isEvaluate: 0, //判断是否为追评
flag: false, //防止重复点击
siteName: '', // 店铺名称
shop_deliverycredit: 5, // 配送服务分值
shop_desccredit: 5, // 描述相符分值
shop_servicecredit: 5, // 服务态度分值
uploadActionUrl: Config.baseUrl + '/api/upload/evaluateimg',
uploadData: {
app_type: "pc",
app_type_name: "PC"
},
dialogImageUrl: '',
dialogVisible: false,
hide: []
};
},
created() {
this.orderId = this.$route.query.order_id;
this.getUserInfo();
if (this.orderId) {
this.getOrderInfo();
}
},
computed: {
...mapGetters(['defaultGoodsImage'])
},
layout: 'member',
methods: {
handleSuccess(file, fileList, index) {
let arr = this.imgList[index];
arr = arr.concat(file.data.pic_path);
this.imgList[index] = [];
this.$set(this.imgList, index, arr);
if (this.isEvaluate) {
this.goodsEvalList[index].again_images = this.imgList[index].toString();
} else {
this.goodsEvalList[index].images = this.imgList[index].toString();
}
if (this.imgList[index].length >= 6) {
this.hide[index] = true;
}
},
handleRemove(file, fileList, index) {
let i = this.$util.inArray(file.response.data.pic_path, this.imgList[index]);
this.imgList[index].splice(i, 1);
if (this.isEvaluate) {
this.goodsEvalList[index].again_images = this.imgList[index].toString();
} else {
this.goodsEvalList[index].images = this.imgList[index].toString();
}
if (this.imgList[index].length < 6) {
this.hide[index] = false;
}
},
handleExceed(file, fileList) {
// 图片数量大于6
this.$message.warning('上传图片最大数量为6张');
},
handlePictureCardPreview(file) {
// 点开大图
this.dialogImageUrl = file.url;
this.dialogVisible = true;
},
//获取用户信息
getUserInfo() {
this.$store
.dispatch('member/member_detail', {
refresh: 1
}).then(res => {
this.memberName = res.data.nickname;
this.memberHeadimg = res.data.headimg;
}).catch(err => {
this.$message.error(err.message);
});
},
//获取订单信息
getOrderInfo() {
//获取订单信息
orderInfo({
order_id: this.orderId
}).then(res => {
if (res.code == 0) {
this.isEvaluate = res.data.evaluate_status;
this.orderNo = res.data.list[0].order_no;
this.goodsList = res.data.list;
this.siteName = res.data.list[0].site_name;
if (this.isEvaluate) {
for (let i = 0; i < res.data.list.length; i++) {
let array = [];
this.imgList.push(array);
this.hide.push(false);
this.goodsEvalList.push({
order_goods_id: res.data.list[i].order_goods_id,
goods_id: res.data.list[i].goods_id,
sku_id: res.data.list[i].sku_id,
again_content: '',
again_images: '',
site_id: res.data.list[i].site_id
});
}
} else {
for (let i = 0; i < res.data.list.length; i++) {
let array = [];
this.imgList.push(array);
this.goodsEvalList.push({
content: '', // 评价内容
images: '', //图片数组
scores: 5, // 评分
explain_type: 1, // 评价类型
order_goods_id: res.data.list[i].order_goods_id,
goods_id: res.data.list[i].goods_id,
sku_id: res.data.list[i].sku_id,
sku_name: res.data.list[i].sku_name,
sku_price: res.data.list[i].price,
sku_image: res.data.list[i].sku_image,
site_id: res.data.list[i].site_id
});
}
}
}
this.loading = false;
}).catch(err => {
this.$message.error(err.message);
this.$router.push('/member/order_list');
this.loading = false;
});
},
//监听评分变化
setStar(index) {
if (this.goodsEvalList[index].scores >= 4) {
this.goodsEvalList[index].explain_type = 1;
} else if (1 < this.goodsEvalList[index].scores && this.goodsEvalList[index].scores < 4) {
this.goodsEvalList[index].explain_type = 2;
} else {
this.goodsEvalList[index].explain_type = 3;
}
},
imageError(index) {
this.goodsList[index].sku_image = this.defaultGoodsImage;
},
/**
* 提交
*/
save() {
for (let i = 0; i < this.goodsEvalList.length; i++) {
if (this.isEvaluate) {
if (!this.goodsEvalList[i].again_content.trim().length) {
this.$message({
message: '商品的评价不能为空哦',
type: 'warning'
});
return;
}
} else {
if (!this.goodsEvalList[i].content.trim().length) {
this.$message({
message: '商品的评价不能为空哦',
type: 'warning'
});
return;
}
}
}
let goodsEvaluate = JSON.stringify(this.goodsEvalList);
let data = {
order_id: this.orderId,
goods_evaluate: goodsEvaluate,
isEvaluate: this.isEvaluate
};
if (!this.isEvaluate) {
data.order_no = this.orderNo;
data.member_name = this.memberName;
data.member_headimg = this.memberHeadimg;
data.is_anonymous = this.isAnonymous;
}
if (this.flag) return;
this.flag = true;
save(data).then(res => {
if (res.code == 0) {
this.$message({
message: '评价成功',
type: 'success',
duration: 2000,
onClose: () => {
this.$router.push({
path: '/member/order_list'
});
}
});
} else {
this.$message({
message: res.message,
type: 'warning'
});
this.flag = false;
}
}).catch(err => {
this.$message.error(err.message);
this.flag = false;
});
},
/**
* 跳转到商品详情
*/
toGoodsDetail(id) {
this.$util.pushToTab('sku-' + id);
}
}
};
</script>
<style lang="scss" scoped>
.ns-evalute {
margin: 20px 0;
background: #ffffff;
padding: 30px;
border-radius: 5px;
.ns-eva-li {
display: flex;
padding: 20px 0;
border-bottom: 1px solid #eeeeee;
.ns-eva-good {
width: 30%;
text-align: center;
.el-image {
width: 125px;
height: 125px;
cursor: pointer;
}
.ns-eva-good-name {
width: 250px;
margin: 0 auto;
overflow: hidden;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
cursor: pointer;
}
}
}
.ns-eva-form {
width: 70%;
.ns-textarea {
position: relative;
}
.upload-wrap {
.tips {
margin-top: 10px;
}
}
.level {
display: inline-block;
margin-left: 50px;
i {
margin-right: 5px;
vertical-align: top;
}
}
.el-textarea {
margin: 10px 0;
}
}
.el-rate {
display: inline-block;
vertical-align: middle;
}
.save-btn-wrap {
text-align: center;
margin-top: 20px;
}
.el-dialog {
img {
width: auto;
margin: 0 auto;
}
}
}
</style>
<style lang="scss">
.ns-evalute {
.el-upload--picture-card {
border: none;
}
.el-upload--picture-card,
.el-upload-list--picture-card .el-upload-list__item {
width: 70px;
height: 70px;
line-height: 80px;
position: relative;
}
.el-upload-list--picture-card .el-upload-list__item-thumbnail {
width: 100%;
height: auto;
position: absolute;
top: 50%;
transform: translateY(-50%);
}
.el-upload-list__item.is-success .el-upload-list__item-status-label {
display: none;
}
.ishide .el-upload--picture-card {
display: none;
}
.upload-wrap .el-upload-dragger {
width: 70px;
height: 70px;
}
.el-dialog {
.el-dialog__body {
text-align: center;
}
}
}
</style>

View File

@@ -0,0 +1,184 @@
<template>
<div class="box">
<div class="null-page" v-show="yes"></div>
<el-card class="box-card logistics">
<div slot="header" class="clearfix">
<el-breadcrumb separator="/">
<el-breadcrumb-item :to="{ path: '/member/order_list' }">订单列表</el-breadcrumb-item>
<el-breadcrumb-item>物流详情</el-breadcrumb-item>
</el-breadcrumb>
</div>
<div v-loading="loading">
<el-tabs v-model="activeParcel">
<el-tab-pane v-for="(packageItem, packageIndex) in packageList" :key="packageIndex" :label="packageItem.package_name" :name="'parcel_' + packageIndex">
<div class="trace" v-if="packageItem.trace.success && packageItem.trace.list.length > 0">
<el-timeline>
<el-timeline-item v-for="(traceItem, traceIndex) in packageItem.trace.list" :timestamp="traceItem.datetime" placement="top" :type="traceIndex == 0 ? 'primary' : ''" :key="traceIndex">
<p>{{ traceItem.remark }}</p>
</el-timeline-item>
</el-timeline>
</div>
<div class="trace" v-else>
<p class="empty-wrap">{{ packageItem.trace.reason }}</p>
</div>
<ul class="info-wrap">
<li>
<label>运单号码</label>
<span>{{ packageItem.delivery_no }}</span>
</li>
<li>
<label>物流公司</label>
<span>{{ packageItem.express_company_name }}</span>
</li>
</ul>
<ul class="goods-wrap">
<li v-for="(goodsItem, goodsIndex) in packageItem.goods_list" :key="goodsIndex" @click="$util.pushToTab('/sku/' + goodsItem.sku_id)">
<div class="img-wrap">
<img :src="$img(goodsItem.sku_image, { size: 'mid' })" @error="imageError(packageIndex, goodsIndex)" />
</div>
<p class="sku-name">{{ goodsItem.sku_name }} x {{ goodsItem.num }}</p>
</li>
</ul>
</el-tab-pane>
</el-tabs>
</div>
</el-card>
</div>
</template>
<script>
import {apiOrderPackageInfo} from '@/api/order/order';
import {mapGetters} from 'vuex';
export default {
name: 'logistics',
components: {},
data: () => {
return {
orderId: 0,
loading: true,
activeParcel: 'parcel_0',
packageList: [],
yes: true
};
},
created() {
this.orderId = this.$route.query.order_id;
if (!this.orderId) this.$router.push({path: '/member/order_list'});
this.getOrderPackageInfo();
},
computed: {
...mapGetters(['defaultGoodsImage'])
},
layout: 'member',
mounted() {
let self = this;
setTimeout(function () {
self.yes = false
}, 300)
},
methods: {
getOrderPackageInfo() {
apiOrderPackageInfo({
order_id: this.orderId
}).then(res => {
if (res.code >= 0) {
this.packageList = res.data;
this.packageList.forEach(item => {
if (item.trace.list) {
item.trace.list = item.trace.list.reverse();
}
});
this.loading = false;
} else {
this.$message({
message: '未获取到订单包裹信息!',
type: 'warning',
duration: 2000,
onClose: () => {
this.$router.push({path: '/member/order_list'});
}
});
}
}).catch(res => {
this.loading = false;
});
},
imageError(packageIndex, goodsIndex) {
this.packageList[packageIndex].goods_list[goodsIndex].sku_image = this.defaultGoodsImage;
}
}
};
</script>
<style lang="scss" scoped>
.box {
width: 100%;
position: relative;
}
.null-page {
width: 100%;
height: 730px;
background-color: #FFFFFF;
position: absolute;
top: 0;
left: 0;
z-index: 9;
}
.logistics {
.trace {
.empty-wrap {
padding: 10px 0;
}
}
.info-wrap {
overflow: hidden;
display: flex;
flex-wrap: wrap;
li {
flex: 0 0 33.3333%;
margin-bottom: 10px;
span {
font-weight: bold;
}
}
}
.goods-wrap {
overflow: hidden;
margin: 10px 0;
li {
float: left;
width: 130px;
margin-right: 7px;
cursor: pointer;
&:nth-child(n + 7) {
margin-right: 0;
}
.img-wrap {
width: 120px;
}
.sku-name {
margin-top: 5px;
overflow: hidden;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
font-size: $ns-font-size-sm;
}
}
}
}
</style>

View File

@@ -0,0 +1,377 @@
<template>
<div class="box">
<div class="null-page" v-show="yes"></div>
<div v-loading="loading">
<el-card class="box-card order-list">
<div slot="header" class="clearfix">
<el-breadcrumb separator="/">
<el-breadcrumb-item :to="{ path: '/member/order_list' }">我的订单</el-breadcrumb-item>
<el-breadcrumb-item :to="{ path: '/member/order_detail?order_id=' + orderId }">订单详情</el-breadcrumb-item>
<el-breadcrumb-item>退款</el-breadcrumb-item>
</el-breadcrumb>
</div>
<!--商品信息-->
<div class="goods-list">
<table>
<tr>
<td width="62.5%">商品</td>
<td width="12.5%">数量</td>
<td width="12.5%">金额</td>
</tr>
</table>
</div>
<div class="goods-list">
<table>
<tr v-for="(item,index) in refundData.order_goods_info" :key="index">
<td width="62.5%">
<div class="goods-info">
<div class="goods-info-left" v-if="item.sku_image">
<router-link :to="{ path: '/sku/' + item.sku_id }" target="_blank">
<img class="goods-img" :src="$img(item.sku_image, { size: 'mid' })" @error="item.sku_image = defaultGoodsImage" />
</router-link>
</div>
<div class="goods-info-right">
<router-link :to="{ path: '/sku/' + item.sku_id }" target="_blank">
<div class="goods-name">{{ item.sku_name }}</div>
</router-link>
</div>
</div>
</td>
<td width="12.5%" class="goods-num">{{ item.num }}</td>
<td width="12.5%" class="goods-money">{{ item.goods_money }}</td>
</tr>
</table>
</div>
</el-card>
<!--退款类型 -->
<div class="item-block">
<div class="block-text">退款类型</div>
<div class="pay-type-list">
<div class="pay-type-item" :class="refundType == 1 ? 'active' : ''" @click="selectRefundType(1)">退款无需退货</div>
<div v-if="refundData.refund_type.length == 2" class="pay-type-item" :class="refundType == 2 ? 'active' : ''" @click="selectRefundType(2)">退货退款</div>
<div class="clear"></div>
</div>
</div>
<!--退款填写-->
<div class="item-block">
<div class="block-text"></div>
<el-form ref="form" label-width="80px" class="refund-form">
<el-form-item label="退款金额">
<el-input disabled="" :value="refundData.refund_money"></el-input>
</el-form-item>
<el-form-item label="退款原因">
<el-select placeholder="请选择" v-model="refundReason">
<el-option v-for="(item, itemIndex) in refundData.refund_reason_type" :key="itemIndex" :label="item" :value="item"></el-option>
</el-select>
</el-form-item>
<el-form-item label="退款说明">
<el-input maxlength="140" show-word-limit resize="none" rows="5" placeholder="请输入退款说明(选填)" type="textarea" v-model="refundRemark"/>
</el-form-item>
</el-form>
</div>
<div class="item-block">
<div class="order-submit">
<el-button type="primary" class="el-button--primary" @click="submit">提交</el-button>
</div>
<div class="clear"></div>
</div>
</div>
</div>
</template>
<script>
import {refundDataBatch, refund} from '@/api/order/refund';
import {mapGetters} from 'vuex';
export default {
name: 'refund',
components: {},
data: () => {
return {
orderGoodsId: '',
orderId: '',
refundType: 1,
refundReason: '',
refundRemark: '',
isIphoneX: false,
refundData: {
refund_type: [],
order_goods_info: {
sku_image: ''
}
},
isSub: false,
show_type: 0, //退款状态 1-待退款 2-已退款
detail: {
refund_action: []
},
loading: true,
yes: true
};
},
created() {
if (this.$route.query.order_goods_id) this.orderGoodsId = this.$route.query.order_goods_id;
if (this.$route.query.order_id) this.orderId = this.$route.query.order_id;
this.getRefundData();
},
computed: {
...mapGetters(['defaultGoodsImage'])
},
layout: 'member',
mounted() {
let self = this;
setTimeout(function () {
self.yes = false
}, 300)
},
methods: {
/**
* 选择退款方式
* @param {Object} type
*/
selectRefundType(type) {
this.refundType = type;
},
getRefundData() {
refundDataBatch({order_goods_ids: this.orderGoodsId}).then(res => {
const {code, message, data} = res;
if (code >= 0) {
this.refundData = data;
} else {
this.$message({
message: '未获取到该订单项退款信息!',
type: 'warning',
duration: 2000,
onClose: () => {
this.$router.push({path: '/member/activist'});
}
});
}
this.loading = false;
}).catch(err => {
this.loading = false;
this.$message.error({
message: err.message,
duration: 2000,
onClose: () => {
this.$router.push({path: '/member/activist'});
}
});
});
},
submit() {
if (this.verify()) {
if (this.isSub) return;
this.isSub = true;
let submit_data = {
order_goods_ids: this.orderGoodsId,
refund_type: this.refundType,
refund_reason: this.refundReason,
refund_remark: this.refundRemark
};
refund(submit_data).then(res => {
const {code, message, data} = res;
if (code >= 0) {
this.$message({
message: '申请成功!',
type: 'success',
duration: 2000,
onClose: () => {
this.$router.push({path: '/member/activist'});
}
});
} else {
this.isSub = false;
this.$message({message: message, type: 'warning'});
}
}).catch(err => {
this.$message.error({
message: err.message,
duration: 2000,
onClose: () => {
this.$router.push({path: '/member/activist'});
}
});
});
}
},
verify() {
if (this.refundReason == '') {
this.$message({message: '请选择退款原因', type: 'warning'});
return false;
}
return true;
}
}
};
</script>
<style lang="scss" scoped>
.box {
width: 100%;
position: relative;
}
.null-page {
width: 100%;
height: 730px;
background-color: #FFFFFF;
position: absolute;
top: 0;
left: 0;
z-index: 9;
}
.el-card.is-always-shadow,
.el-card.is-hover-shadow:focus,
.el-card.is-hover-shadow:hover {
box-shadow: unset;
}
.el-card {
border: 0;
}
.clear {
clear: both;
}
.item-block {
padding: 0 15px 1px;
margin: 10px 0;
border-radius: 0;
border: none;
background: #ffffff;
.block-text {
border-color: #eeeeee;
color: $ns-text-color-black;
padding: 7px 0;
border-bottom: 1px;
}
}
.refund-form {
width: 350px;
.el-select {
width: 100%;
}
}
.order-submit {
text-align: center;
padding: 10px;
}
.goods-list {
padding: 15px 0;
table {
width: 100%;
}
.goods-info-left {
width: 60px;
height: 60px;
float: left;
.goods-img {
width: 60px;
height: 60px;
}
}
.goods-info-right {
float: left;
height: 60px;
margin-left: 10px;
color: $base-color;
width: 80%;
.goods-name {
line-height: 20px;
padding-top: 10px;
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 2;
overflow: hidden;
}
.goods-spec {
color: #999;
}
}
}
.pay-type-list {
padding: 20px 0;
}
.pay-type-item {
display: inline-block;
border: 2px solid #eeeeee;
padding: 5px 20px;
margin-right: 20px;
cursor: pointer;
}
.pay-type-item.active {
border-color: $base-color;
}
.status-wrap {
color: #999;
}
.media-left {
float: left;
}
.media-right {
float: right;
i.rotate {
transform: rotate(180deg);
transition: 0.3s;
}
}
.action-box {
padding: 10px 0;
}
.action-way {
float: left;
color: #999;
}
.head .time {
float: right;
color: #999;
}
.record-item {
margin-bottom: 10px;
}
.order-statistics {
float: left;
padding: 10px;
// color: #999;
}
.el-textarea .el-input__count {
line-height: 20px;
}
</style>

View File

@@ -0,0 +1,417 @@
<template>
<div class="payment-wrap" v-loading="fullscreenLoading">
<!--购买虚拟类商品需填写您的手机号-->
<div class="item-block" v-if="orderPaymentData.is_virtual == 1">
<div class="block-text">购买虚拟类商品需填写您的手机号以方便商家与您联系</div>
<el-form ref="form" size="mini" class="mobile-wrap" label-width="80px">
<el-form-item label="手机号码">
<el-input placeholder="请输入您的手机号码" maxlength="11" v-model="orderCreateData.member_address.mobile" @input="virtualMobileChange" />
</el-form-item>
</el-form>
</div>
<!--收货地址-->
<div class="item-block" v-if="orderPaymentData.is_virtual == 0">
<div class="block-text">收货地址</div>
<div class="address-list">
<div class="address-item" @click="addAddressShow">
<div class="add-address">
<i class="el-icon-circle-plus-outline"></i>
添加收货地址
</div>
</div>
<div class="address-item" v-for="(item, key) in memberAddress" :key="item.id" :class="addressId == item.id ? 'active' : ''" v-if="key < 3 || (addressShow && key >= 3)">
<div class="address-info">
<div class="options">
<div @click="editAddress(item.id)">编辑</div>
<template v-if="item.is_default == 0">
<el-popconfirm title="确定要删除该地址吗?" @onConfirm="deleteMemberAddress(item.id)">
<div slot="reference">删除</div>
</el-popconfirm>
</template>
</div>
<div class="address-name">{{ item.name }}</div>
<div class="address-mobile" @click="setMemberAddress(item.id)">{{ item.mobile }}</div>
<div class="address-desc" @click="setMemberAddress(item.id)">{{ item.full_address }} {{ item.address }}
</div>
</div>
</div>
<div v-if="memberAddress.length > 3 && !addressShow" @click="addressShow = true" class="el-button--text address-open">
<i class="el-icon-arrow-down"></i>
更多收货地址
</div>
<div class="clear"></div>
</div>
</div>
<!--收货地址添加-->
<el-dialog :title="addressForm.id == 0 ? '添加收货地址' : '编辑收货地址'" :visible.sync="dialogVisible" width="32%">
<el-form ref="form" :rules="addressRules" :model="addressForm" label-width="80px">
<el-form-item label="姓名" prop="name">
<el-input v-model="addressForm.name" placeholder="收货人姓名" />
</el-form-item>
<el-form-item label="手机" prop="mobile">
<el-input v-model="addressForm.mobile" maxlength="11" placeholder="收货人手机号" />
</el-form-item>
<el-form-item label="电话">
<el-input v-model="addressForm.telephone" placeholder="收货人固定电话(选填)" />
</el-form-item>
<el-form-item class="area" label="地区" prop="area">
<el-row :gutter="10">
<el-col :span="7">
<el-select prop="province" ref="province" v-model="addressForm.province_id" @change="getAddress(1)" placeholder="请选择省">
<el-option label="请选择省" value="0"></el-option>
<el-option v-for="item in pickerValueArray" :key="item.id" :label="item.name" :value="item.id"></el-option>
</el-select>
</el-col>
<el-col :span="7">
<el-select ref="city" prop="city" v-model="addressForm.city_id" @change="getAddress(2)" placeholder="请选择市">
<el-option label="请选择市" value="0"></el-option>
<el-option v-for="item in cityArr" :key="item.id" :label="item.name" :value="item.id"></el-option>
</el-select>
</el-col>
<el-col :span="7">
<el-select ref="district" prop="district" v-model="addressForm.district_id" placeholder="请选择区/县">
<el-option label="请选择区/县" value="0"></el-option>
<el-option v-for="item in districtArr" :key="item.id" :label="item.name" :value="item.id"></el-option>
</el-select>
</el-col>
</el-row>
</el-form-item>
<el-form-item label="详细地址" prop="address">
<el-input v-model="addressForm.address" placeholder="定位小区、街道、写字楼" />
</el-form-item>
</el-form>
<span slot="footer" class="dialog-footer">
<el-button @click="dialogVisible = false"> </el-button>
<el-button type="primary" @click="addmemberAddress('form')"> </el-button>
</span>
</el-dialog>
<!--使用余额-->
<div class="item-block" v-if="orderPaymentData.member_account.balance_total > 0 && balance_show == 1">
<div class="block-text">是否使用余额</div>
<div class="pay-type-list">
<div class="pay-type-item" :class="orderCreateData.is_balance ? '' : 'active'" @click="useBalance(0)">不使用余额
</div>
<div class="pay-type-item" :class="orderCreateData.is_balance ? 'active' : ''" @click="useBalance(1)">使用余额</div>
<div class="clear"></div>
</div>
</div>
<!-- 支付密码 -->
<el-dialog title="使用余额" :visible.sync="dialogpay" width="350px">
<template v-if="orderPaymentData.member_account.is_pay_password == 0">
<p>为了您的账户安全,请您先设置的支付密码</p>
<p>可到"会员中心","账号安全","支付密码"中设置</p>
<span slot="footer" class="dialog-footer">
<el-button size="small" @click="dialogpay = false">暂不设置</el-button>
<el-button size="small" type="primary" @click="setPayPassword">立即设置</el-button>
</span>
</template>
<el-form v-else status-icon ref="ruleForm" label-width="100px">
<el-form-item label="支付密码" class="pay-password-item">
<!--添加一个不可见的input,欺骗浏览器自动填充-->
<el-input type="password" class="pay-password hide-password" :maxlength="6"></el-input>
<el-input type="password" class="pay-password" :maxlength="6" v-model="password" @input="input"></el-input>
</el-form-item>
<p class="ns-text-color forget-password" @click="setPayPassword">忘记密码</p>
</el-form>
</el-dialog>
<!--使用积分抵扣-->
<div class="item-block" v-if="calculateData && calculateData.max_usable_point > 0">
<div class="block-text">是否使用积分</div>
<div class="pay-type-list">
<div class="pay-type-item" :class="orderCreateData.is_point ? '' : 'active'" @click="usePoint(0)">不使用积分</div>
<div class="pay-type-item" :class="orderCreateData.is_point ? 'active' : ''" @click="usePoint(1)">使用积分</div>
<div class="clear"></div>
</div>
</div>
<!-- 配送方式 -->
<div class="item-block padd-bom-20" v-if="orderPaymentData.delivery.express_type.length > 0">
<div class="block-text">
<span>配送方式</span>
<span class="distribution" v-if="orderCreateData.delivery.delivery_type == 'store'">{{ orderCreateData.delivery.store_name }}</span>
</div>
<div class="pay-type-item" v-for="(item, index) in orderPaymentData.delivery.express_type" :key="index" @click="selectDeliveryType(item)" :class="item.name == orderCreateData.delivery.delivery_type ? 'active' : ''">
{{ item.title }}
</div>
</div>
<!--配送方式 门店 -->
<el-dialog title="选择门店" :visible.sync="dialogStore" width="50%">
<el-table ref="singleTable" :data="storeList" highlight-current-row @row-click="selectStore" class="cursor-pointer">
<el-table-column label="" width="55">
<template slot-scope="scope">
<el-radio v-model="storeRadio" :label="scope.row"><i></i></el-radio>
</template>
</el-table-column>
<el-table-column prop="store_name" label="名称" width="160"></el-table-column>
<el-table-column prop="store_address" label="地址"></el-table-column>
<el-table-column prop="open_date" label="营业时间"></el-table-column>
</el-table>
</el-dialog>
<div class="item-block" v-if="orderPaymentData.invoice && orderPaymentData.invoice.invoice_status == 1">
<div class="block-text">发票信息</div>
<div class="pay-type-list">
<div class="pay-type-item" :class="orderCreateData.is_invoice == 0 ? 'active' : ''" @click="changeIsInvoice">
无需发票
</div>
<div class="pay-type-item" :class="orderCreateData.is_invoice == 1 ? 'active' : ''" @click="changeIsInvoice">
需要发票
</div>
<div class="clear"></div>
</div>
<div class="invoice-information" v-if="orderCreateData.is_invoice == 1">
<div class="invoice-title">
<div class="invoice-type-box invoice-title-box">
<span class="invoice-name">发票类型</span>
<label class="invoice-to-type">
<i class="invoice-i-input" :class="orderCreateData.invoice_type == 1 ? 'active' : ''" @click="clickType(1)"></i>
<span>纸质</span>
</label>
<label class="invoice-to-type">
<i class="invoice-i-input" :class="orderCreateData.invoice_type == 2 ? 'active' : ''" @click="clickType(2)"></i>
<span>电子</span>
</label>
</div>
<div class="invoice-type-box invoice-title-box">
<span class="invoice-name">抬头类型</span>
<label class="invoice-to-type">
<i class="invoice-i-input" :class="orderCreateData.invoice_title_type == 1 ? 'active' : ''" @click="clickTitleType(1)"></i>
<span>个人</span>
</label>
<label class="invoice-to-type">
<i class="invoice-i-input" :class="orderCreateData.invoice_title_type == 2 ? 'active' : ''" @click="clickTitleType(2)"></i>
<span>企业</span>
</label>
</div>
</div>
<div class="invoice-type-box">
<span class="invoice-name">发票信息</span>
<div class="invoice-box-form">
<input type="text" placeholder="请填写抬头名称" v-model.trim="orderCreateData.invoice_title" />
<input type="text" placeholder="请填写纳税人识别号" v-model.trim="orderCreateData.taxpayer_number" v-if="orderCreateData.invoice_title_type == 2" />
<input type="text" placeholder="请填写邮寄地址" v-model.trim="orderCreateData.invoice_full_address" v-show="orderCreateData.invoice_type == 1" />
<input type="text" placeholder="请填写邮箱" v-model.trim="orderCreateData.invoice_email" v-show="orderCreateData.invoice_type == 2" />
</div>
</div>
<div class="invoice-condition">
<span class="invoice-name">发票内容</span>
<div class="invoice-box-form">
<span class="option-item" :key="index" v-for="(item, index) in orderPaymentData.invoice.invoice_content_array" @click="changeInvoiceContent(item)" :class="{ 'color-base-bg active': item == orderCreateData.invoice_content }">{{ item }}</span>
</div>
</div>
<div class="invoice-tops">发票内容将以根据税法调整具体请以展示为准发票内容显示详细商品名 称及价格信息</div>
</div>
</div>
<!--商品信息-->
<div class="item-block">
<div class="goods-list">
<table>
<tr>
<td width="50%">商品</td>
<td width="12.5%">价格</td>
<td width="12.5%">数量</td>
<td width="12.5%">小计</td>
</tr>
</table>
</div>
</div>
<div>
<div class="item-block" v-if="calculateData">
<div class="goods-list">
<table>
<tr v-for="(goodsItem, goodsIndex) in calculateData.goods_list" :key="goodsIndex">
<td width="50%">
<div class="goods-info">
<div class="goods-info-left">
<router-link :to="{ path: '/sku/' + goodsItem.sku_id }" target="_blank">
<img class="goods-img" :src="$img(goodsItem.sku_image, { size: 'mid' })" @error="imageError(goodsIndex)" />
</router-link>
</div>
<div class="goods-info-right">
<router-link :to="{ path: '/sku/' + goodsItem.sku_id }" target="_blank">
<div class="goods-name">{{ goodsItem.goods_name }}</div>
</router-link>
<!-- 规格 -->
<div class="goods-spec" v-if="goodsItem.sku_spec_format">
<span v-for="(x, i) in goodsItem.sku_spec_format" :key="i">{{ x.spec_value_name }}</span>
</div>
</div>
</div>
</td>
<td width="12.5%" class="goods-price">{{ goodsItem.price }}</td>
<td width="12.5%" class="goods-num">{{ goodsItem.num }}</td>
<td width="12.5%" class="goods-money">{{ (goodsItem.price * goodsItem.num).toFixed(2) }}</td>
</tr>
</table>
</div>
</div>
</div>
<!--优惠券-->
<div class="item-block" v-if="calculateData && couponList.length">
<div class="block-text">优惠券</div>
<div class="order-cell platform-coupon">
<div v-if="calculateData.coupon_money != 0">
<span class="ns-text-color" @click="openPlatformCoupon">已选择优惠券已优惠</span>
<span class="ns-text-color" @click="openPlatformCoupon">
<span class="inline"></span>
{{ calculateData.coupon_money }}
</span>
</div>
<div v-else>
<div class="box ns-text-color" @click="openPlatformCoupon">不使用优惠券</div>
</div>
</div>
</div>
<!-- 活动优惠 -->
<div class="item-block" v-if="promotionInfo">
<div class="block-text">{{ promotionInfo.title }}</div>
<div class="order-cell platform-coupon">
<div class="box ns-text-color" v-html="promotionInfo.content"></div>
</div>
</div>
<!--优惠券弹框-->
<el-dialog title="选择优惠券" :visible.sync="dialogPlatcoupon" width="50%" @close="savePlatformCoupon()">
<el-table ref="platformCouponTable" :data="couponList" highlight-current-row @row-click="selectPlatformCoupon" class="cursor-pointer">
<el-table-column label="" width="55">
<template slot-scope="scope">
<div class="disabled-selected-wrap">
<el-radio v-model="platformCouponRadio" :label="scope.row"><i></i></el-radio>
</div>
</template>
</el-table-column>
<el-table-column prop="platformcoupon_name" label="名称" width="200">
<template slot-scope="scope">
<span>{{ scope.row.coupon_name }}</span>
</template>
</el-table-column>
<el-table-column prop="money" label="优惠">
<template slot-scope="scope">
<template v-if="scope.row.type == 'divideticket'">
<span class="money">{{ parseFloat(scope.row.money) }}</span>
</template>
<template v-else-if="scope.row.type == 'reward'">
<span class="money">{{ parseFloat(scope.row.money) }}</span>
</template>
<template v-else-if="scope.row.type == 'discount'">
<span class="money">{{ parseFloat(scope.row.discount) }}</span>
</template>
</template>
</el-table-column>
<el-table-column label="使用">
<template slot-scope="scope">
<span class="ns-text-color-gray ns-font-size-sm" v-if="scope.row.at_least > 0">{{ scope.row.at_least }}可用</span>
<span class="ns-text-color-gray ns-font-size-sm" v-else>无门槛</span>
</template>
</el-table-column>
<el-table-column label="有效期">
<template slot-scope="scope">
<span>{{ scope.row.end_time ? $util.timeStampTurnTime(scope.row.end_time) : '长期有效' }}</span>
</template>
</el-table-column>
</el-table>
<br />
<div class="align-right">
<el-button @click="dialogPlatcoupon = false">取消</el-button>
<el-button @click="dialogPlatcoupon = false" type="primary">确认选择</el-button>
</div>
</el-dialog>
<!-- 买家留言 -->
<div class="item-block padd-bom-10">
<div class="block-text">买家留言</div>
<el-input rows="3" type="textarea" placeholder="留言前建议先与商家协调一致" v-model="orderCreateData.buyer_message" class="buyer-message" @input="textarea" maxlength="140" show-word-limit resize="none" />
</div>
<!-- 总计 -->
<div class="item-block" v-if="calculateData">
<div class="order-statistics">
<table>
<tr>
<td align="right">商品金额</td>
<td align="left">{{ calculateData.goods_money | moneyFormat }}</td>
</tr>
<tr v-if="calculateData.is_virtual == 0 && calculateData.delivery_money > 0">
<td align="right">运费</td>
<td align="left">{{ calculateData.delivery_money | moneyFormat }}</td>
</tr>
<tr v-if="calculateData.invoice_money > 0">
<td align="right">发票税费<span class="ns-text-color">({{ calculateData.invoice.invoice_rate }}%)</span></td>
<td align="left">{{ calculateData.invoice_money | moneyFormat }}</td>
</tr>
<tr v-if="calculateData.invoice_delivery_money > 0">
<td align="right">发票邮寄费</td>
<td align="left">{{ calculateData.invoice_delivery_money | moneyFormat }}</td>
</tr>
<tr v-if="calculateData.promotion_money > 0">
<td align="right">优惠</td>
<td align="left">{{ calculateData.promotion_money | moneyFormat }}</td>
</tr>
<tr v-if="calculateData.coupon_money > 0">
<td align="right">优惠券</td>
<td align="left">{{ calculateData.coupon_money | moneyFormat }}</td>
</tr>
<tr v-if="calculateData.point_money > 0">
<td align="right">积分抵扣</td>
<td align="left">{{ calculateData.point_money | moneyFormat }}</td>
</tr>
<tr v-if="calculateData.balance_money > 0">
<td align="right">使用余额</td>
<td align="left">{{ calculateData.balance_money | moneyFormat }}</td>
</tr>
</table>
</div>
<div class="clear"></div>
</div>
<!--结算-->
<div class="item-block" v-if="calculateData">
<div class="order-submit">
<div class="order-money">
{{ calculateData.goods_num }}应付金额
<div class="ns-text-color">{{ calculateData.pay_money | moneyFormat }}</div>
</div>
<el-button type="primary" class="el-button--primary" @click="orderCreate">订单结算</el-button>
</div>
<div class="clear"></div>
</div>
</div>
</template>
<script>
import detail from '@/assets/js/order/payment.js';
export default {
name: 'payment',
mixins: [detail]
};
</script>
<style lang="scss" scoped>
@import '@/assets/css/order/payment.scss';
</style>

View File

@@ -0,0 +1,482 @@
<template>
<div class="box">
<div class="null-page" v-show="yes"></div>
<div v-loading="loading">
<el-card class="box-card order-list">
<div slot="header" class="clearfix">
<el-breadcrumb separator="/">
<el-breadcrumb-item :to="{ path: '/member/order_list' }">我的订单</el-breadcrumb-item>
<el-breadcrumb-item :to="{ path: '/member/order_detail?order_id=' + orderId }">订单详情</el-breadcrumb-item>
<el-breadcrumb-item>退款</el-breadcrumb-item>
</el-breadcrumb>
</div>
<!--商品信息-->
<div class="goods-list">
<table>
<tr>
<td width="62.5%">商品</td>
<td width="12.5%">数量</td>
<td width="12.5%">金额</td>
</tr>
</table>
</div>
<div class="goods-list">
<table>
<tr>
<td width="62.5%">
<div class="goods-info">
<div class="goods-info-left">
<router-link :to="{ path: '/sku/' + refundData.order_goods_info.sku_id }" target="_blank">
<img class="goods-img" :src="$img(refundData.order_goods_info.sku_image, { size: 'mid' })" @error="refundData.order_goods_info.sku_image = defaultGoodsImage" />
</router-link>
</div>
<div class="goods-info-right">
<router-link :to="{ path: '/sku/' + refundData.order_goods_info.sku_id }" target="_blank">
<div class="goods-name">{{ refundData.order_goods_info.sku_name }}</div>
</router-link>
</div>
</div>
</td>
<td width="12.5%" class="goods-num">{{ refundData.order_goods_info.num }}</td>
<td width="12.5%" class="goods-money">{{ refundData.order_goods_info.goods_money }}</td>
</tr>
</table>
</div>
</el-card>
<!--退款类型 -->
<div class="item-block">
<div class="block-text">退款类型</div>
<div class="pay-type-list">
<div class="pay-type-item" :class="refundType == 1 ? 'active' : ''" @click="selectRefundType(1)">退款无需退货</div>
<div v-if="refundData.refund_type.length == 2" class="pay-type-item" :class="refundType == 2 ? 'active' : ''" @click="selectRefundType(2)">退货退款</div>
<div class="clear"></div>
</div>
</div>
<!--退款填写-->
<div class="item-block">
<div class="block-text"></div>
<el-form ref="form" label-width="80px" class="refund-form">
<el-form-item label="退款金额">
<el-input disabled="" :value="refundData.refund_money"></el-input>
</el-form-item>
<el-form-item label="退款原因">
<el-select placeholder="请选择" v-model="refundReason">
<el-option v-for="(item, itemIndex) in refundData.refund_reason_type" :key="itemIndex" :label="item" :value="item"></el-option>
</el-select>
</el-form-item>
<el-form-item label="退款说明">
<el-input maxlength="140" show-word-limit resize="none" rows="5" placeholder="请输入退款说明(选填)" type="textarea" v-model="refundRemark"/>
</el-form-item>
<el-form-item label="退款图片">
<div class="upload-wrap">
<el-upload ref="upload" :class="{ ishide: hide }" :action="uploadActionUrl" :data="uploadData"
list-type="picture-card" :on-success="
(file, fileList) => {
return handleSuccess(file, fileList);
}
" :on-preview="handlePictureCardPreview" :on-remove="
(file, fileList) => {
return handleRemove(file, fileList);
}
" :on-exceed="handleExceed" multiple drag :limit="5">
<i class="el-icon-plus"></i>
<!-- <i class="el-icon-upload"></i> -->
<!-- <div class="el-upload__text">将文件拖到此处,或<em>点击上传</em></div>
<div class="el-upload__tip" slot="tip">只能上传jpg/png文件且不超过500kb</div> -->
</el-upload>
<el-dialog :visible.sync="dialogVisible"><img width="100%" :src="dialogImageUrl" alt="" /></el-dialog>
<div class="tips">共5张还能上传{{ imgList.length ? 5 - imgList.length : 5 }}张</div>
</div>
</el-form-item>
</el-form>
</div>
<div class="item-block">
<div class="order-submit">
<el-button type="primary" class="el-button--primary" @click="submit">提交</el-button>
</div>
<div class="clear"></div>
</div>
</div>
</div>
</template>
<script>
import {refundData, refund, detail, delivery} from '@/api/order/refund';
import {mapGetters} from 'vuex';
import Config from '@/plugins/config';
export default {
name: 'refund',
components: {},
data: () => {
return {
orderGoodsId: '',
orderId: '',
refundType: 1,
refundReason: '',
refundRemark: '',
isIphoneX: false,
refundData: {
refund_type: [],
order_goods_info: {
sku_image: ''
}
},
isSub: false,
show_type: 0, //退款状态 1-待退款 2-已退款
detail: {
refund_action: []
},
loading: true,
yes: true,
dialogVisible: false,
hide: false,
uploadActionUrl: Config.baseUrl + '/api/upload/refundimg',
uploadData: {
app_type: "pc",
app_type_name: "PC"
},
imgList: [],
dialogImageUrl: '',
};
},
created() {
if (this.$route.query.order_goods_id) this.orderGoodsId = this.$route.query.order_goods_id;
if (this.$route.query.order_id) this.orderId = this.$route.query.order_id;
this.getRefundData();
},
computed: {
...mapGetters(['defaultGoodsImage'])
},
layout: 'member',
mounted() {
let self = this;
setTimeout(function () {
self.yes = false
}, 300)
},
methods: {
handleRemove(file, fileList) {
let i = this.$util.inArray(file.response.data.pic_path, this.imgList);
this.imgList.splice(i, 1);
if (this.imgList.length < 5) {
this.hide = false;
}
},
handleSuccess(file, fileList) {
let arr = this.imgList;
arr = arr.concat(file.data.pic_path);
this.imgList = arr;
if (this.imgList.length >= 5) {
this.hide = true;
}
},
handleExceed(file, fileList) {
// 图片数量大于5
this.$message.warning('上传图片最大数量为5张');
},
handlePictureCardPreview(file) {
// 点开大图
this.dialogImageUrl = file.url;
this.dialogVisible = true;
},
/**
* 选择退款方式
* @param {Object} type
*/
selectRefundType(type) {
this.refundType = type;
},
getRefundData() {
refundData({order_goods_id: this.orderGoodsId}).then(res => {
const {code, message, data} = res;
if (code >= 0) {
this.refundData = data;
} else {
this.$message({
message: '未获取到该订单项退款信息!',
type: 'warning',
duration: 2000,
onClose: () => {
this.$router.push({path: '/member/activist'});
}
});
}
this.loading = false;
}).catch(err => {
this.loading = false;
this.$message.error({
message: err.message,
duration: 2000,
onClose: () => {
this.$router.push({path: '/member/activist'});
}
});
});
},
submit() {
if (this.verify()) {
if (this.isSub) return;
this.isSub = true;
let submit_data = {
order_goods_ids: this.orderGoodsId,
refund_type: this.refundType,
refund_reason: this.refundReason,
refund_remark: this.refundRemark,
refund_images: this.imgList.toString()
};
refund(submit_data).then(res => {
const {code, message, data} = res;
if (code >= 0) {
this.$message({
message: '申请成功!',
type: 'success',
duration: 2000,
onClose: () => {
this.$router.push({path: '/member/activist'});
}
});
} else {
this.isSub = false;
this.$message({message: message, type: 'warning'});
}
}).catch(err => {
this.$message.error({
message: err.message,
duration: 2000,
onClose: () => {
this.$router.push({path: '/member/activist'});
}
});
});
}
},
verify() {
if (this.refundReason == '') {
this.$message({message: '请选择退款原因', type: 'warning'});
return false;
}
return true;
}
}
};
</script>
<style lang="scss">
.upload-wrap .el-upload--picture-card {
border: none;
}
.upload-wrap .el-upload--picture-card,
.upload-wrap .el-upload-list--picture-card .el-upload-list__item {
width: 70px;
height: 70px;
line-height: 80px;
position: relative;
}
.upload-wrap .el-upload-list--picture-card .el-upload-list__item-thumbnail {
width: 100%;
height: auto;
position: absolute;
top: 50%;
transform: translateY(-50%);
}
.upload-wrap .el-upload-list__item.is-success .el-upload-list__item-status-label {
display: none;
}
.upload-wrap .ishide .el-upload--picture-card {
display: none;
}
.upload-wrap .el-upload-dragger {
width: 70px;
height: 70px;
}
.upload-wrap .el-upload--picture-card {
border: none;
}
.upload-wrap .el-upload-dragger {
width: 70px;
height: 70px;
}
</style>
<style lang="scss" scoped>
.upload-wrap {
.tips {
margin-top: 10px;
}
}
.box {
width: 100%;
position: relative;
}
.null-page {
width: 100%;
height: 730px;
background-color: #FFFFFF;
position: absolute;
top: 0;
left: 0;
z-index: 9;
}
.el-card.is-always-shadow,
.el-card.is-hover-shadow:focus,
.el-card.is-hover-shadow:hover {
box-shadow: unset;
}
.el-card {
border: 0;
}
.clear {
clear: both;
}
.item-block {
padding: 0 15px 1px;
margin: 10px 0;
border-radius: 0;
border: none;
background: #ffffff;
.block-text {
border-color: #eeeeee;
color: $ns-text-color-black;
padding: 7px 0;
border-bottom: 1px;
}
}
.refund-form {
width: 350px;
.el-select {
width: 100%;
}
}
.order-submit {
text-align: center;
padding: 10px;
}
.goods-list {
padding: 15px 0;
table {
width: 100%;
}
.goods-info-left {
width: 60px;
height: 60px;
float: left;
.goods-img {
width: 60px;
height: 60px;
}
}
.goods-info-right {
float: left;
height: 60px;
margin-left: 10px;
color: $base-color;
width: 80%;
.goods-name {
line-height: 20px;
padding-top: 10px;
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 2;
overflow: hidden;
}
.goods-spec {
color: #999;
}
}
}
.pay-type-list {
padding: 20px 0;
}
.pay-type-item {
display: inline-block;
border: 2px solid #eeeeee;
padding: 5px 20px;
margin-right: 20px;
cursor: pointer;
}
.pay-type-item.active {
border-color: $base-color;
}
.status-wrap {
color: #999;
}
.media-left {
float: left;
}
.media-right {
float: right;
i.rotate {
transform: rotate(180deg);
transition: 0.3s;
}
}
.action-box {
padding: 10px 0;
}
.action-way {
float: left;
color: #999;
}
.head .time {
float: right;
color: #999;
}
.record-item {
margin-bottom: 10px;
}
.order-statistics {
float: left;
padding: 10px;
// color: #999;
}
.el-textarea .el-input__count {
line-height: 20px;
}
</style>

View File

@@ -0,0 +1,630 @@
<template>
<div class="box">
<div class="null-page" v-show="yes"></div>
<div v-loading="loading">
<!-- 退款详情start -->
<div>
<el-card class="box-card order-list">
<div slot="header" class="clearfix">
<el-breadcrumb separator="/">
<el-breadcrumb-item :to="{ path: '/member/activist' }">退款/售后</el-breadcrumb-item>
<el-breadcrumb-item>退款详情</el-breadcrumb-item>
</el-breadcrumb>
</div>
<div>
<div class="block-text color-red" v-if="detail.refund_status==-1">{{ detail.refund_status_name }}</div>
<div class="block-text color-green" v-if="detail.refund_status==3">{{ detail.refund_status_name }}</div>
<div class="fail-text" v-if="detail.refund_status==-1">
<div class="fail-title">拒绝原因:</div>
<div class="fail-detail">{{ detail.refund_refuse_reason }}</div>
</div>
<div class="block-text" v-if="detail.refund_status!=-1 && detail.refund_status!=3">
{{ detail.refund_status_name }}
</div>
<div class="status-wrap">
<div class="refund-explain" v-if="detail.refund_status == 1">
<div>如果商家拒绝你可重新发起申请</div>
<div>如果商家同意将通过申请并退款给你</div>
<div>如果商家逾期未处理平台将自动通过申请并退款给你</div>
</div>
<div class="refund-explain" v-if="detail.refund_status == 5">
<div>如果商家确认收货将会退款给你</div>
<div>如果商家拒绝收货该次退款将会关闭你可以重新发起退款</div>
</div>
</div>
</div>
</el-card>
<!--协商记录-->
<div class="item-block">
<div class="action-box">
<span class="media-left">协商记录</span>
<div class="media-right">
<div class="el-button--text" @click="actionOpen ? (actionOpen = false) : (actionOpen = true)">
协商记录
<i :class="actionOpen ? 'rotate' : ''" class="el-icon-arrow-down"></i>
</div>
</div>
<div class="clear"></div>
</div>
<div v-if="actionOpen">
<el-timeline>
<el-timeline-item :class="logItem.action_way == 1 ? 'buyer' : 'seller'" v-for="(logItem, logIndex) in detail.refund_log_list" :key="logIndex" :timestamp="$util.timeStampTurnTime(logItem.action_time)" placement="top">
<div>
<h4>{{ logItem.action_way == 1 ? '买家' : '卖家' }}</h4>
<p>{{ logItem.action }}</p>
</div>
</el-timeline-item>
</el-timeline>
</div>
</div>
<!-- 退货地址 -->
<div class="item-block" v-if="detail.refund_status == 4">
<div class="block-text">
<span>收货人{{ detail.shop_contacts }}</span>
<span>联系电话{{ detail.shop_mobile }}</span>
</div>
<div class="block-text">
<span>退货地址{{ detail.shop_address }}</span>
</div>
</div>
<!--退款详情-->
<div class="item-block">
<div class="goods-list">
<table>
<tr>
<td width="62.5%">商品</td>
<td width="12.5%">数量</td>
<td width="12.5%">退款金额</td>
</tr>
</table>
</div>
</div>
<div class="item-block">
<div class="goods-list">
<table>
<tr>
<td width="62.5%">
<div class="goods-info">
<div class="goods-info-left">
<router-link :to="{ path: '/sku/' + detail.sku_id }" target="_blank">
<img class="goods-img" :src="$img(detail.sku_image)" @error="detail.sku_image = defaultGoodsImage" />
</router-link>
</div>
<div class="goods-info-right">
<router-link :to="{ path: '/sku/' + detail.sku_id }" target="_blank">
<div class="goods-name">{{ detail.sku_name }}</div>
</router-link>
</div>
</div>
</td>
<td width="12.5%" class="goods-num">{{ detail.num }}</td>
<td width="12.5%" class="goods-money">{{ detail.refund_apply_money }}</td>
</tr>
</table>
</div>
</div>
<div class="item-block">
<div class="order-statistics">
<table v-if="detail.refund_apply_money > 0">
<!-- 申请信息 -->
<tr>
<td align="right">退款方式</td>
<td align="left">{{ detail.refund_type == 1 ? '仅退款' : '退款退货' }}</td>
</tr>
<tr>
<td align="right">申请原因</td>
<td align="left">{{ detail.refund_reason }}</td>
</tr>
<tr>
<td align="right">申请金额</td>
<td align="left">{{ detail.refund_apply_money }}</td>
</tr>
<tr>
<td align="right">申请时间</td>
<td align="left">{{ $util.timeStampTurnTime(detail.refund_action_time) }}</td>
</tr>
<tr class="refund-images" v-if="detail.refund_images">
<td align="right refund-title">退款图片</td>
<td align="left">
<img class="image" v-for="(item,index) in detail.refund_images.split(',')" :key="index" :src="$img(item)" alt="" />
</td>
</tr>
</table>
<table v-if="detail.refund_apply_money > 0 && detail.refund_status == 3">
<!-- 退款信息 -->
<tr>
<td align="right">退款金额</td>
<td align="left">{{ detail.refund_apply_money }} ({{ detail.refund_money_type_name }})</td>
</tr>
<tr>
<td align="right">退款编号</td>
<td align="left">{{ detail.refund_no }}</td>
</tr>
<tr v-if="detail.refund_time">
<td align="right">退款时间</td>
<td align="left">{{ $util.timeStampTurnTime(detail.refund_time) }}</td>
</tr>
</table>
<table v-if="detail.shop_active_refund == 1">
<!-- 主动退款信息 -->
<tr>
<td align="right">主动退款金额</td>
<td align="left">{{ detail.shop_active_refund_money }} ({{ detail.shop_active_refund_money_type_name }})</td>
</tr>
<tr>
<td align="right">主动退款编号</td>
<td align="left">{{ detail.shop_active_refund_no }}</td>
</tr>
<tr>
<td align="right">主动退款说明</td>
<td align="left">{{ detail.shop_active_refund_remark }}</td>
</tr>
</table>
</div>
<div class="clear"></div>
</div>
<div class="item-block" v-if="detail.refund_action.length">
<div class="order-submit" v-for="(actionItem, actionIndex) in detail.refund_action" :key="actionIndex">
<el-button type="primary" class="el-button--primary" @click="refundAction(actionItem.event)">{{ actionItem.title }}</el-button>
</div>
<div class="order-submit" v-if="detail.complain_action">
<el-button type="primary" class="el-button--primary" @click="refundAction('complain')">平台维权</el-button>
</div>
<div class="clear"></div>
</div>
</div>
<!-- 退款详情end -->
<!-- 输入物流信息弹出 -->
<el-dialog title="输入发货物流" :visible.sync="refundDeliveryDialog" width="50%">
<el-form ref="form" :model="formData" label-width="80px">
<el-form-item label="物流公司">
<el-input v-model="formData.refund_delivery_name" placeholder="请输入物流公司"></el-input>
</el-form-item>
<el-form-item label="物流单号">
<el-input v-model="formData.refund_delivery_no" placeholder="请输入物流单号"></el-input>
</el-form-item>
<el-form-item label="物流说明">
<el-input v-model="formData.refund_delivery_remark" placeholder="选填"></el-input>
</el-form-item>
</el-form>
<span slot="footer" class="dialog-footer">
<el-button @click="refundDeliveryDialog = false"> </el-button>
<el-button type="primary" @click="refundGoods('form')"> </el-button>
</span>
</el-dialog>
</div>
</div>
</template>
<script>
import {
refundData,
refund,
detail,
delivery,
cancleRefund
} from '@/api/order/refund';
import {
mapGetters
} from 'vuex';
export default {
name: 'refund_detail',
components: {},
data: () => {
return {
orderGoodsId: '',
isSub: false,
detail: {
refund_action: []
},
formData: {
refund_delivery_name: '',
refund_delivery_no: '',
refund_delivery_remark: ''
},
actionOpen: false, //协商记录
refundDeliveryDialog: false, //发货地址弹出
loading: true,
yes: true
};
},
created() {
if (this.$route.query.order_goods_id) this.orderGoodsId = this.$route.query.order_goods_id;
this.getRefundDetail();
// if (this.$route.query.action && this.$route.query.action == 'returngoods') {
// this.refundDeliveryDialog = true;
// }
},
computed: {
...mapGetters(['defaultGoodsImage'])
},
layout: 'member',
mounted() {
let self = this;
setTimeout(function () {
self.yes = false
}, 300)
},
methods: {
//退款详情相关
getRefundDetail() {
this.loading = true;
detail({
order_goods_id: this.orderGoodsId
}).then(res => {
const {
code,
message,
data
} = res;
if (code >= 0) {
this.detail = data;
} else {
this.$message({
message: '未获取到该订单项退款信息!',
type: 'warning',
duration: 2000,
onClose: () => {
this.$router.push({
path: '/member/activist'
});
}
});
}
this.loading = false;
}).catch(err => {
this.loading = false;
this.$message.error({
message: err.message,
duration: 2000,
onClose: () => {
this.$router.push({
path: '/member/activist'
});
}
});
});
},
refundAction(event) {
switch (event) {
case 'orderRefundCancel':
this.cancleRefund(this.detail.order_goods_id);
break;
case 'orderRefundDelivery':
this.refundDeliveryDialog = true;
break;
case 'orderRefundAsk':
this.$router.push({
path: '/order/refund?order_goods_id=' + this.detail.order_goods_id
});
break;
case 'complain':
this.$router.push({
path: '/order/complain?order_goods_id=' + this.detail.order_goods_id
});
break;
case 'orderRefundApply':
this.$router.push({
path: '/order/refund',
query: { order_goods_id: this.detail.order_goods_id, order_id: this.detail.order_id },
});
break;
}
},
refundGoods() {
if (this.formData.refund_delivery_name == '') {
this.$message({
message: '请输入物流公司',
type: 'warning'
});
return false;
}
if (this.formData.refund_delivery_no == '') {
this.$message({
message: '请输入物流单号',
type: 'warning'
});
return false;
}
this.formData.order_goods_id = this.orderGoodsId;
if (this.isSub) return;
this.isSub = true;
delivery(this.formData).then(res => {
const {
code,
message,
data
} = res;
if (code >= 0) {
this.getRefundDetail();
this.refundDeliveryDialog = false;
} else {
this.$message({
message: '未获取到该订单项退款信息!',
type: 'warning',
duration: 2000,
onClose: () => {
this.$router.push({
path: '/member/activist'
});
}
});
}
}).catch(err => {
this.$message.error({
message: err.message,
duration: 2000,
onClose: () => {
this.$router.push({
path: '/member/activist'
});
}
});
});
},
cancleRefund(order_goods_id) {
this.$confirm('撤销之后本次申请将会关闭,如后续仍有问题可再次发起申请', '提示', {
confirmButtonText: '确认撤销',
cancelButtonText: '暂不撤销',
type: 'warning'
})
.then(() => {
if (this.isSub) return;
this.isSub = true;
cancleRefund({
order_goods_id: order_goods_id
}).then(res => {
const {
code,
message,
data
} = res;
if (code >= 0) {
this.$message({
message: '撤销成功!',
type: 'success',
duration: 2000,
onClose: () => {
this.$router.push({
path: '/member/activist'
});
}
});
} else {
this.$message({
message: message,
type: 'warning'
});
}
}).catch(err => {
this.$message.error({
message: err.message,
duration: 2000,
onClose: () => {
this.$router.push({
path: '/member/activist'
});
}
});
});
})
}
}
};
</script>
<style lang="scss" scoped>
.box {
width: 100%;
position: relative;
}
.null-page {
width: 100%;
height: 730px;
background-color: #FFFFFF;
position: absolute;
top: 0;
left: 0;
z-index: 9;
}
.el-card.is-always-shadow,
.el-card.is-hover-shadow:focus,
.el-card.is-hover-shadow:hover {
box-shadow: unset;
}
.el-card {
border: 0;
}
.clear {
clear: both;
}
.item-block {
padding: 0 20px 1px;
margin: 10px 0;
border-radius: 0;
border: none;
background: #ffffff;
.block-text {
border-color: #eeeeee;
color: $ns-text-color-black;
padding: 7px 0;
border-bottom: 1px;
span {
margin-right: 60px;
}
}
}
.fail-text {
display: flex;
align-items: flex-start;
color: #F94460;
padding: 7px 0;
border-bottom: 1px;
.fail-title {
width: 7%;
}
.fail-detail {
width: 93%;
}
}
.color-green {
color: #34C25D;
}
.color-red {
color: #F94460;
}
.order-submit {
float: right;
padding: 10px;
}
.goods-list {
padding: 15px 0;
table {
width: 100%;
}
.goods-info-left {
width: 60px;
height: 60px;
float: left;
.goods-img {
width: 60px;
height: 60px;
}
}
.goods-info-right {
float: left;
height: 60px;
margin-left: 10px;
color: $base-color;
width: 80%;
.goods-name {
line-height: 20px;
padding-top: 10px;
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 2;
overflow: hidden;
}
.goods-spec {
color: #999;
}
}
}
.pay-type-list {
padding: 20px 0;
}
.pay-type-item {
display: inline-block;
border: 2px solid #eeeeee;
padding: 5px 20px;
margin-right: 20px;
cursor: pointer;
}
.pay-type-item.active {
border-color: $base-color;
}
.status-wrap {
color: #999;
}
.media-left {
float: left;
}
.media-right {
float: right;
cursor: pointer;
i.rotate {
transform: rotate(180deg);
transition: 0.3s;
}
}
.action-box {
padding: 10px 0;
}
.action-way {
float: left;
color: #999;
}
.head .time {
float: right;
color: #999;
}
.record-item {
margin-bottom: 10px;
}
.order-statistics {
float: left;
padding: 10px;
// color: #999;
table{
margin-bottom:10px;
}
table:last-child{
margin-bottom: 0;
}
}
</style>
<style lang="scss">
.refund-images{
td{
&:first-child{
vertical-align: baseline;
}
}
.image{
width: 60px;
height: 60px;
margin-right: 10px;
}
}
</style>

View File

@@ -0,0 +1,147 @@
<template>
<div class="box">
<div class="null-page" v-show="yes"></div>
<el-card class="box-card order-list">
<div slot="header" class="clearfix"><span>核销台</span></div>
<div class="ns-verification">
<div class="ns-verification-flow">
<div class="ns-verification-icon">
<div><i class="iconfont icon-shurutianxiebi"></i></div>
<p>输入核销码</p>
</div>
<div><i class="iconfont icon-jiang-copy"></i></div>
<div class="ns-verification-icon">
<div><i class="iconfont icon-hexiao"></i></div>
<p>核销</p>
</div>
</div>
<div class="ns-verification-wrap">
<el-input v-model="verify_code" placeholder="请输入核销码"></el-input>
<el-button @click="confirm">确认</el-button>
</div>
</div>
</el-card>
</div>
</template>
<script>
import {
verifyInfo
} from "@/api/order/verification"
export default {
name: "verification",
components: {},
data: () => {
return {
verify_code: "",
yes: true
}
},
created() {
},
layout: 'member',
mounted() {
let self = this;
setTimeout(function () {
self.yes = false
}, 300)
},
methods: {
confirm() {
var reg = /[\S]+/
if (!reg.test(this.verify_code)) {
this.$message({
message: "请输入核销码",
type: "warning"
})
return false
}
verifyInfo({
verify_code: this.verify_code
}).then(res => {
if (res.code >= 0) {
this.$router.push({
path: "/order/verification_detail",
query: {
code: this.verify_code
}
})
} else {
this.$message({
message: res.message,
type: "warning"
})
}
}).catch(err => {
this.$message.error(err.message)
})
}
}
}
</script>
<style lang="scss" scoped>
.box {
width: 100%;
position: relative;
}
.null-page {
width: 100%;
height: 730px;
background-color: #FFFFFF;
position: absolute;
top: 0;
left: 0;
z-index: 9;
}
.ns-verification {
margin: 20px 0;
background: #ffffff;
padding: 80px;
text-align: center;
.ns-verification-flow {
display: flex;
justify-content: center;
.ns-verification-icon {
width: 150px;
margin: 0 20px;
div {
display: inline-block;
background: #eee;
width: 60px;
height: 60px;
text-align: center;
line-height: 60px;
border-radius: 50%;
}
p {
color: #999999;
margin-top: 5px;
}
}
i {
font-size: 30px;
color: #999999;
}
}
.ns-verification-wrap {
display: inline-block;
width: 500px;
margin-top: 50px;
.el-button {
margin-top: 50px;
background: $base-color;
color: #ffffff;
}
}
}
</style>

View File

@@ -0,0 +1,155 @@
<template>
<el-card class="box-card order-list">
<div slot="header" class="clearfix">
<el-breadcrumb separator="/">
<el-breadcrumb-item :to="{ path: '/order/verification_list' }">核销记录</el-breadcrumb-item>
<el-breadcrumb-item>核销验证</el-breadcrumb-item>
</el-breadcrumb>
</div>
<div class="ns-verification" v-loading="loading">
<div class="ns-verification-order">
<p class="ns-site-name">{{ verifyInfo.site_name }}</p>
<div class="ns-goods-list" v-for="(item, index) in verifyInfo.item_array" :key="index">
<div class="ns-goods-img">
<el-image fit="cover" :src="$img(item.img)" @error="imageError(index)"></el-image>
</div>
<div class="ns-goods-info">
<p>{{ item.name }}</p>
<p class="ns-goods-price ns-text-color">{{ item.price }}</p>
<p>数量{{ item.num }}</p>
</div>
</div>
<div class="ns-order-info">
<p v-for="(item, index) in verifyInfo.remark_array" :key="index">{{ item.title }}{{ item.value }}</p>
<p>核销类型{{ verifyInfo.verify_type_name }}</p>
<template v-if="verifyInfo.is_verify">
<p>核销状态已核销</p>
<p v-if="verifyInfo.verify_time">核销人员{{ verifyInfo.verifier_name }}</p>
<p v-if="verifyInfo.verify_time">核销时间{{ $timeStampTurnTime(verifyInfo.verify_time) }}</p>
</template>
</div>
<div class="ns-btn">
<el-button @click="verify" v-if="verifyInfo.is_verify == 0">确认使用</el-button>
</div>
</div>
</div>
</el-card>
</template>
<script>
import {verifyInfo, verify} from '@/api/order/verification';
import {mapGetters} from 'vuex';
export default {
name: 'verification_detail',
components: {},
data: () => {
return {
verify_code: '',
verifyInfo: {},
isSub: false,
loading: true
};
},
created() {
this.verify_code = this.$route.query.code;
this.getVerifyInfo();
},
computed: {
...mapGetters(['defaultGoodsImage'])
},
layout: 'member',
methods: {
getVerifyInfo() {
verifyInfo({
verify_code: this.verify_code
}).then(res => {
if (res.code >= 0) {
this.verifyInfo = res.data;
} else {
this.$message({message: res.message, type: 'warning'});
this.$router.push('/member');
}
this.loading = false;
}).catch(err => {
this.$message.error(err.message);
this.$router.push('/member');
this.loading = false;
});
},
verify() {
if (this.isSub) return;
this.isSub = true;
verify({
verify_code: this.verify_code
}).then(res => {
if (res.code >= 0) {
this.$message({
message: res.message,
type: 'success',
duration: 2000,
onClose: () => {
this.$router.push('/order/verification_list');
}
});
} else {
this.$message({message: res.message, type: 'warning'});
this.isSub = false;
}
}).catch(err => {
this.$message.error(err.message);
this.isSub = false;
});
},
/**
* 图片加载失败
*/
imageError(index) {
this.verifyInfo.item_array[index].img = this.defaultGoodsImage;
}
}
};
</script>
<style lang="scss" scoped>
.ns-verification {
.ns-verification-order {
.ns-goods-list {
display: flex;
margin: 10px 0;
.el-image {
width: 80px;
height: 80px;
line-height: 80px;
text-align: center;
margin-right: 10px;
border-radius: 5px;
}
.ns-goods-price span:first-child {
font-weight: 600;
font-size: 16px;
}
}
.ns-order-info {
border-top: 1px solid #eeeeee;
padding-top: 20px;
color: $base-color-info;
line-height: 30px;
}
.ns-btn {
text-align: right;
.el-button {
background: $base-color;
color: #ffffff;
}
}
}
}
</style>

View File

@@ -0,0 +1,301 @@
<template>
<div class="box">
<div class="null-page" v-show="yes"></div>
<el-card class="box-card order-list">
<div slot="header" class="clearfix"><span>核销记录</span></div>
<div v-loading="loading">
<el-tabs v-model="orderType" @tab-click="handleClick">
<el-tab-pane v-for="(item, index) in typeList" :key="index" :label="item.name" :name="item.type"></el-tab-pane>
</el-tabs>
<div>
<nav>
<li>商品信息</li>
<li>单价</li>
<li>数量</li>
</nav>
<div class="list" v-if="verifyList.length > 0">
<div class="item" v-for="(item, index) in verifyList" :key="index">
<div class="head">
<span class="create-time">{{ $util.timeStampTurnTime(item.create_time) }}</span>
<router-link :to="'/shop-' + item.site_id" target="_blank">{{ item.site_name }}</router-link>
<span class="order-type">{{ item.order_type_name }}</span>
<span class="order-type">核销员{{ item.verifier_name }}</span>
</div>
<ul v-for="(goodsItem, goodsIndex) in item.item_array" :key="goodsIndex">
<li>
<div class="img-wrap" @click="toVerifyDetail(item.verify_code)">
<img :src="$img(goodsItem.img)" @error="imageError(index, goodsIndex)" />
</div>
<div class="info-wrap">
<h5 @click="toVerifyDetail(item.verify_code)">{{ goodsItem.name }}</h5>
</div>
</li>
<li>
<span>{{ goodsItem.price }}</span>
</li>
<li>
<span>{{ goodsItem.num }}</span>
</li>
</ul>
</div>
</div>
<div v-else-if="!loading && verifyList.length == 0" class="empty-wrap">暂无相关订单</div>
</div>
</div>
<div class="pager">
<el-pagination
background
:pager-count="5"
:total="total"
prev-text="上一页"
next-text="下一页"
:current-page.sync="currentPage"
:page-size.sync="pageSize"
@size-change="handlePageSizeChange"
@current-change="handleCurrentPageChange"
hide-on-single-page
></el-pagination>
</div>
</el-card>
</div>
</template>
<script>
import {mapGetters} from 'vuex';
import {getVerifyType, verifyList} from '@/api/order/verification';
export default {
name: 'verification_list',
components: {},
data: () => {
return {
orderType: '',
loading: true,
typeList: [],
verifyList: [],
currentPage: 1,
pageSize: 10,
total: 0,
yes: true
};
},
created() {
this.getVerifyType();
},
computed: {
...mapGetters(['defaultGoodsImage'])
},
layout: 'member',
mounted() {
let self = this;
setTimeout(function () {
self.yes = false
}, 300)
},
methods: {
handlePageSizeChange(size) {
this.pageSize = size;
this.refresh();
},
handleCurrentPageChange(page) {
this.currentPage = page;
this.refresh();
},
refresh() {
this.loading = true;
this.getVerifyType();
},
/**
* 订单类型(自提/虚拟)
*/
handleClick(tab, event) {
this.refresh();
},
getVerifyType() {
getVerifyType().then(res => {
if (res.code >= 0) {
this.typeList = [];
this.verifyList = [];
Object.keys(res.data).forEach(key => {
this.typeList.push({
type: key,
name: res.data[key].name
});
});
if (this.orderType == 0) {
for (let i = 0; i < this.typeList.length; i++) {
if (i == 0) {
this.orderType = this.typeList[i].type;
}
}
}
this.getVerifyList(this.orderType);
}
})
},
/**
* 获取核销记录
*/
getVerifyList(type) {
verifyList({
verify_type: type,
page: this.currentPage,
page_size: this.pageSize
}).then(res => {
this.verifyList = res.data.list;
this.total = res.data.count;
this.loading = false;
}).catch(err => {
this.$message.error(err.message);
this.loading = false;
});
},
imageError(orderIndex, goodsIndex) {
this.verifyList[orderIndex].item_array[goodsIndex].img = this.defaultGoodsImage;
},
toVerifyDetail(code) {
this.$router.push({path: '/order/verification_detail', query: {code: code}});
}
}
};
</script>
<style lang="scss" scoped>
.box {
width: 100%;
position: relative;
}
.null-page {
width: 100%;
height: 730px;
background-color: #FFFFFF;
position: absolute;
top: 0;
left: 0;
z-index: 9;
}
.order-list {
nav {
overflow: hidden;
padding: 10px 0;
background: #fff;
margin-bottom: 10px;
border-bottom: 1px solid #eeeeee;
li {
float: left;
&:nth-child(1) {
width: 70%;
}
&:nth-child(2) {
width: 20%;
}
&:nth-child(3) {
width: 10%;
}
}
}
.list {
.item {
margin-bottom: 20px;
border: 1px solid #eeeeee;
border-top: 0;
.head {
padding: 8px 10px;
background: #f7f7f7;
font-size: 12px;
.create-time {
margin-right: 10px;
}
border-bottom: 1px solid #eeeeee;
a {
margin: 0 10px 0 20px;
}
.order-type {
margin-left: 30px;
}
}
}
ul {
background-color: #fff;
padding: 10px;
overflow: hidden;
li {
float: left;
line-height: 60px;
&:nth-child(1) {
width: 70%;
line-height: inherit;
.img-wrap {
width: 60px;
height: 60px;
float: left;
margin-right: 10px;
cursor: pointer;
}
.info-wrap {
margin-left: 70px;
h5 {
cursor: pointer;
font-weight: normal;
font-size: $ns-font-size-base;
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 2;
overflow: hidden;
margin-right: 10px;
display: inline-block;
&:hover {
color: $base-color;
}
}
span {
font-size: $ns-font-size-sm;
color: #9a9a9a;
}
}
}
&:nth-child(2) {
width: 20%;
}
&:nth-child(3) {
width: 10%;
}
}
}
}
.empty-wrap {
text-align: center;
padding: 10px;
}
}
</style>

View File

@@ -0,0 +1,851 @@
<template>
<div class="pay-wrap" v-loading="loading">
<div class="item-block">
<div class="payment-detail">
<div class="payment-media">
<el-row>
<el-col :span="4">
<div class="media-left"><i class="el-icon-circle-check ns-text-color"></i></div>
</el-col>
<el-col :span="16">
<div class="media-body">
<el-row>
<el-col :span="12">
<div class="payment-text">您的订单已提交成功正在等待处理</div>
<div>
<span>应付金额</span>
<span class="payment-money ns-text-color">{{ payInfo.pay_money }}</span>
</div>
</el-col>
<el-col :span="12"></el-col>
</el-row>
</div>
</el-col>
<el-col :span="4">
<div class="media-right">
<div class="el-button--text" @click="orderOpen ? (orderOpen = false) : (orderOpen = true)">
订单信息
<i :class="orderOpen ? 'rotate' : ''" class="el-icon-arrow-down"></i>
</div>
</div>
</el-col>
</el-row>
</div>
<div class="order-info" v-if="orderOpen">
<el-row>
<el-col :span="4" class="order-info-left"></el-col>
<el-col :span="20">
<div class="line"></div>
<div class="order-item">
<div class="item-label">交易单号</div>
<div class="item-value">{{ payInfo.out_trade_no }}</div>
</div>
<div class="order-item">
<div class="item-label">订单内容</div>
<div class="item-value">{{ payInfo.pay_detail }}</div>
</div>
<div class="order-item">
<div class="item-label">订单金额</div>
<div class="item-value">{{ payInfo.pay_money }}</div>
</div>
<div class="order-item">
<div class="item-label">创建时间</div>
<div class="item-value">{{ $timeStampTurnTime(payInfo.create_time) }}</div>
</div>
</el-col>
</el-row>
</div>
</div>
</div>
<div class="item-block">
<div class="block-text">支付方式</div>
<div class="pay-type-list" v-if="payTypeList.length">
<template v-for="(item, index) in payTypeList">
<div class="pay-type-item" :key="index" v-if="item.type!='offlinepay'|| (item.type=='offlinepay'&&payInfo.event=='OrderPayNotify')" :class="{'active' : payIndex == index,'disable':type=='edit'&&item.type!='offlinepay'}" @click="payTypeChange(index)">
{{ item.name }}
</div>
</template>
<div class="clear"></div>
</div>
<div class="no-pay-type" v-else>
<p>商家未配置支付方式</p>
</div>
<div class="offlinepay" v-if="payTypeList[payIndex].type==='offlinepay'">
<template v-for="item in offlinepayConfig">
<div class="offlinepay-item bank" v-if="item.key=='bank'" :key="item.key">
<div class="title">
银行卡
<!-- {{item.key=='bank'?'银行卡':item.key=='wechat'?'微信支付':'支付宝支付'}} -->
</div>
<div class="item">
<div class="item-label">银行名称</div>
<div class="item-value">{{ item.bank_name }}</div>
</div>
<div class="item">
<div class="item-label">账号名称</div>
<div class="item-value">{{ item.account_name }}</div>
</div>
<div class="item">
<div class="item-label">银行账号</div>
<div class="item-value">
<span>{{ item.account_number }}</span>
<span class="copy ns-text-color" @click="copy(item.account_number)">复制</span>
</div>
</div>
<div class="item">
<div class="item-label">开户支行</div>
<div class="item-value">{{ item.branch_name }}</div>
</div>
</div>
<div class="offlinepay-item" v-else>
<div class="title">
{{item.key=='wechat'?'微信支付':'支付宝支付'}}
</div>
<div class="code">
<div class="centent">
<el-image :src="$util.img(item.payment_code)" :key="item.key" fit="cover" class="qrcode" />
</div>
<div class="bottom">
{{ item.account_name }}
</div>
</div>
</div>
</template>
</div>
</div>
<div class="item-block " v-if="payTypeList[payIndex].type==='offlinepay'">
<div class="offlinepay-form">
<div class="upload-wrap-title">
<div class="title">上传支付凭证</div>
<div class="title-tips">最多还可上传{{5 - offlinepayInfo.imgList.length }}</div>
</div>
<div class="upload-wrap">
<el-upload ref="upload" :class="{ 'ishide': hide}" :action="uploadActionUrl"
:file-list="imgList"
list-type="picture-card" :on-success="
(file, fileList) => {
return handleSuccess(file, fileList);
}
" :on-preview="handlePictureCardPreview" :on-remove="
(file, fileList) => {
return handleRemove(file, fileList);
}
" :on-exceed="handleExceed" multiple drag :limit="5">
<i class="el-icon-plus"></i>
</el-upload>
<el-dialog :visible.sync="imgDialogVisible"><img width="100%" :src="dialogImageUrl" alt="" /></el-dialog>
</div>
<div class="bottom">
<el-input v-model="offlinepayInfo.desc" placeholder="请详细说明您的支付情况" type="textarea" class="remark" :maxlength="200"/>
</div>
</div>
</div>
<div class="item-block" v-if="payTypeList.length">
<div class="order-submit">
<el-button type="primary" class="el-button--primary" @click="pay">立即支付</el-button>
</div>
<div class="clear"></div>
</div>
<el-dialog title="请确认支付是否完成" :visible.sync="dialogVisible" width="23%" top="30vh" class="confirm-pay-wrap">
<div class="info-wrap">
<i class="el-message-box__status el-icon-warning"></i>
<span>完成支付前请根据您的情况点击下面的按钮</span>
</div>
<span slot="footer" class="dialog-footer">
<el-button @click="goIndex" size="small">返回首页</el-button>
<el-button type="primary" @click="goOrderList" size="small">已完成支付</el-button>
</span>
</el-dialog>
<!-- 微信支付弹框 -->
<el-dialog title="请用微信扫码支付" :visible.sync="openQrcode" width="300px" center>
<div class="wechatpay-box"><img :src="payQrcode" /></div>
</el-dialog>
</div>
</template>
<script>
import {
getPayInfo,
getPayType,
checkPayStatus,
pay,
getOfflinepayConfig,
offlinepay,
getOfflinepayPayInfo
} from '@/api/pay';
import Config from '@/plugins/config';
export default {
name: 'pay',
components: {},
data: () => {
return {
orderOpen: false,
outTradeNo: '',
payInfo: {
pay_money: 0
},
payIndex: 0,
payTypeList: [{
name: '支付宝支付',
icon: 'iconzhifubaozhifu-',
type: 'alipay'
},
{
name: '微信支付',
icon: 'iconweixinzhifu',
type: 'wechatpay'
},
{
name: '线下支付',
icon: '',
type: 'offlinepay'
}
],
payUrl: '',
timer: null,
payQrcode: '',
openQrcode: false,
loading: true,
test: null,
dialogVisible: false,
offlinepayConfig: [],
offlinepayInfo:{
out_trade_no:'',
imgs:'',
imgList:[],
desc:'',
},
type:'add',
dialogImageUrl:'',
imgDialogVisible:false,
uploadActionUrl: Config.baseUrl + '/offlinepay/api/pay/uploadimg',
hide:false,
imgList:[],
allRequestSuccess: 0,
};
},
created() {
if (!this.$route.query.code) {
this.$router.push({
path: '/'
});
return;
}
this.outTradeNo = this.$route.query.code;
this.getPayType();
this.getPayInfo();
},
watch: {
allRequestSuccess(newValue, oldValue) {
if ( newValue == 2 ) {
if ( this.payInfo.pay_type == 'offlinepay' ) {
this.payTypeList = [{icon: '', name: '线下支付', type: "offlinepay"}];
}
}
}
},
methods: {
getPayInfo() {
getPayInfo({
out_trade_no: this.outTradeNo,
forceLogin: true
}).then(res => {
const {
code,
message,
data
} = res;
if (data) {
this.payInfo = res.data;
this.allRequestSuccess ++ ;
if ( res.data.pay_type == 'offlinepay' ) {
this.getOfflinepayPayInfoFn(this.outTradeNo);
}
}
this.loading = false;
}).catch(err => {
this.loading = false;
this.$message.error({
message: err.message,
duration: 2000,
onClose: () => {
this.$router.push({
path: '/member/order_list'
});
}
});
});
},
getPayType() {
getPayType({}).then(res => {
const {
code,
message,
data
} = res;
if (code >= 0) {
if (res.data.pay_type == '') {
this.payTypeList = [];
} else {
this.payTypeList = this.payTypeList.filter((val, key) => {
return res.data.pay_type.indexOf(val.type) != -1
});
if(this.payTypeList.some(el=>el.type=='offlinepay')){
this.getOfflinepayConfigFn()
}
}
this.allRequestSuccess ++ ;
}
}).catch(err => {
this.$message.error(err.message);
});
},
//切换支付方式
payTypeChange(index){
if(this.type=='edit') return
this.payIndex = index
this.offlinepayInfo={
out_trade_no:'',
imgs:'',
imgList:[],
desc:'',
}
},
//获取线下支付配置
getOfflinepayConfigFn(){
getOfflinepayConfig({}).then(res => {
const {
code,
message,
data
} = res;
if (code >= 0) {
let config = data.value
Object.keys(config).forEach(key=>{
if(config[key].status=='1'){
config[key].key = key
this.offlinepayConfig.push(config[key])
}
});
}
}).catch(()=>{})
},
//复制银行账号
copy(val){
this.$copy(val)
},
//获取线下支付信息
getOfflinepayPayInfoFn(out_trade_no){
getOfflinepayPayInfo({out_trade_no}).then(res => {
const {
code,
message,
data
} = res;
if (code >= 0&&data) {
this.type='edit'
// this.payIndex = 2
this.offlinepayInfo = data
this.offlinepayInfo.imgList = this.offlinepayInfo.imgs?this.offlinepayInfo.imgs.split(',').map(el=>{return {url:el}}):[]
this.imgList = this.$util.deepClone(this.offlinepayInfo.imgList);
this.$forceUpdate();
}else{
this.type = 'add'
this.offlinepayInfo={
out_trade_no,
imgs:'',
imgList:[],
desc:'',
}
}
}).catch(()=>{})
},
handleSuccess(file, fileList) {
// 上传成功
this.offlinepayInfo.imgList = this.offlinepayInfo.imgList.concat({url:file.data.pic_path});
this.offlinepayInfo.imgs = this.offlinepayInfo.imgList.map(el=>el.url).toString()
if ( this.offlinepayInfo.imgList.length >= 5) {
this.hide = true;
}
},
handleRemove(file, fileList) {
this.offlinepayInfo.imgList = fileList.map(el=>{return {url:el.url}});
},
handlePictureCardPreview(file) {
// 点开大图
this.dialogImageUrl = file.url;
this.imgDialogVisible = true;
},
handleExceed(file, fileList) {
// 图片数量大于5
this.$message.warning('上传图片最大数量为5张');
},
checkPayStatus() {
this.timer = setInterval(() => {
checkPayStatus({
out_trade_no: this.outTradeNo
}).then(res => {
const {
code,
message,
data
} = res;
if (code >= 0) {
if (code == 0) {
if (data.pay_status == 2) {
clearInterval(this.timer);
this.dialogVisible = false;
this.$router.push({
path: '/pay/result?code=' + this.payInfo.out_trade_no
});
}
} else {
clearInterval(this.timer);
}
}
}).catch(err => {
clearInterval(this.timer);
this.$router.push({
path: '/'
});
});
}, 2000);
},
pay() {
var payType = this.payTypeList[this.payIndex];
if (!payType) return;
let return_url = encodeURIComponent(Config.webDomain + '/pay/result?code=' + this.outTradeNo);
if(payType.type!='offlinepay'){
pay({
out_trade_no: this.payInfo.out_trade_no,
pay_type: payType.type,
app_type: 'pc',
return_url
}).then(res => {
const {
code,
message,
data
} = res;
if (code >= 0) {
this.checkPayStatus();
switch (payType.type) {
case 'alipay':
this.payUrl = res.data.data;
window.open(this.payUrl)
this.open();
break;
case 'wechatpay':
this.payQrcode = res.data.qrcode;
this.openQrcode = true;
break;
}
} else {
this.$message({
message: message,
type: 'warning'
});
}
}).catch(err => {
this.$message.error(err.message);
});
}else{
if(!this.offlinepayInfo.imgList.length){
this.$message({
message: '请至少上传一张凭证',
type: 'warning'
});
return;
}
this.offlinepayInfo.out_trade_no = this.outTradeNo;
offlinepay(this.offlinepayInfo).then(res => {
const {
code,
message,
data
} = res;
if (code >= 0) {
let payPath = {
1: '/member/order_detail',
2: '/member/order_detail_pickup',
3: '/member/order_detail_local_delivery',
4: '/member/order_detail_virtual',
}
this.$router.push({
path: payPath[this.payInfo.order_type],
query: {
order_id: this.payInfo.order_id
}
});
} else {
this.$message({
message: message,
type: 'warning'
});
}
}).catch(()=>{})
}
},
open() {
this.dialogVisible = true;
},
goIndex() {
clearInterval(this.timer);
this.dialogVisible = false;
this.$router.push({
path: '/'
});
},
goOrderList() {
clearInterval(this.timer);
this.dialogVisible = false;
this.$router.push({
path: '/member/order_list'
});
}
}
};
</script>
<style lang="scss" scoped>
.pay-wrap {
width: 1210px;
margin: 20px auto;
}
.clear {
clear: both;
}
.item-block {
padding:20px;
margin: 10px 0;
border-radius: 0;
border: none;
background: #ffffff;
.block-text {
border-color: #eeeeee;
color: $ns-text-color-black;
height: 22px;
line-height: 22px;
border-bottom: 1px;
}
}
.media-left {
text-align: center;
i {
font-size: 65px;
}
}
.payment-detail {
padding: 30px 0;
transition: 2s;
}
.media-right {
text-align: center;
line-height: 65px;
cursor: pointer;
i.rotate {
transform: rotate(180deg);
transition: 0.3s;
}
}
.payment-text {
font-size: 20px;
}
.payment-time {
font-size: 12px;
line-height: 65px;
color: #999;
}
//支付方式
.order-submit {
float: right;
padding: 10px;
}
.pay-type-list {
// padding: 20px 0;
margin-top: 16px;
}
.no-pay-type {
padding: 30px 0;
text-align: center;
}
.pay-type-item {
display: inline-block;
border: 2px solid #eeeeee;
padding: 5px 20px;
margin-right: 20px;
cursor: pointer;
}
.pay-type-item.active {
border-color: $base-color;
}
.pay-type-item.disable{
// pointer-events: none;
cursor: not-allowed;
}
.mobile-wrap {
width: 300px;
}
.order-info {
.order-item {
padding: 1px 0;
.item-label {
display: inline-block;
width: 100px;
}
.item-value {
display: inline-block;
}
}
.line {
width: 100%;
height: 1px;
background: #f2f2f2;
margin: 20px 0 10px 0;
}
.order-info-left {
height: 1px;
}
}
.wechatpay-box {
text-align: center;
img {
width: 80%;
}
}
.confirm-pay-wrap {
.el-dialog__body {
padding: 10px 15px;
}
.info-wrap {
i {
position: initial;
vertical-align: middle;
transform: initial;
}
span {
vertical-align: middle;
padding: 0 10px;
}
}
}
</style>
<style lang="scss">
.confirm-pay-wrap {
.el-dialog__body {
padding: 10px 15px;
}
.el-dialog__footer {
padding-top: 0;
padding-bottom: 10px;
}
}
.offlinepay{
padding-top: 30px;
margin-top: 20px;
padding-bottom: 10px;
border-top:1px solid #E2E6F0;
display: flex;
width: 100%;
.offlinepay-item{
width: 380px;
height: 305px;
padding: 20px;
margin-right: 15px;
background: linear-gradient( 180deg, #F8F9FD 0%, #FFFFFF 21%);
border-radius: 16px 16px 16px 16px;
border: 1px solid #EFF2FF;
box-sizing: border-box;
&:last-child{
margin-right: 0;
}
.title{
height: 25px;
line-height: 25px;
font-weight: 500;
font-size: 18px;
text-align: center;
margin-bottom: 20px;
}
&.bank{
.title{
margin-bottom: 30px;
}
.item{
display: flex;
height: 22px;
font-weight: 400;
font-size: 16px;
margin-bottom: 20px;
.item-label{
color: #626779;
}
.copy{
margin-left: 10px;
cursor: pointer;
}
}
}
.code{
width: 100%;
display: flex;
justify-content: center;
justify-content: center;
align-items: center;
flex-direction: column;
.centent{
border-radius: 8px;
border: 1px solid #DEDEDE;
padding: 14px;
width: 180px;
height: 180px;
box-sizing: border-box;
.qrcode{
width: 150px;
height: 150px;
img{
width: 100%;
height: 100%;
}
}
}
.bottom{
height: 20px;
line-height: 20px;
font-weight: 500;
font-size: 14px;
margin-top: 10px;
}
}
}
}
.offlinepay-form{
.upload-wrap-title{
display: flex;
align-items: baseline;
margin-bottom: 16px;
.title{
height: 22px;
line-height: 22px;
font-weight: 500;
font-size: 16px;
}
.title-tips{
height: 17px;
font-weight: 400;
font-size: 12px;
color: #626779;
margin-left: 10px;
}
}
.upload-wrap{
height: 100px;
>div:first-child{
height: 100px;
}
.tips{
margin-top: 5px;
}
}
.el-upload--picture-card {
border: none;
}
.el-upload--picture-card,
.el-upload-list--picture-card .el-upload-list__item {
width: 100px;
height: 100px;
line-height: 80px;
position: relative;
}
.el-upload-list--picture-card .el-upload-list__item-thumbnail {
width: 100%;
height: auto;
position: absolute;
top: 50%;
transform: translateY(-50%);
}
.el-upload-list__item.is-success .el-upload-list__item-status-label {
display: none;
}
.ishide .el-upload--picture-card {
display: none;
}
.upload-wrap .el-upload-dragger {
width: 100px;
height: 100px;
display: flex;
justify-content: center;
align-items: center;
}
.el-dialog {
.el-dialog__body {
text-align: center;
}
}
.bottom{
margin-top: 20px;
padding-top: 16px;
font-size: 14px !important;
border-top: 1px dashed #E2E6F0;
.remark{
.el-textarea__inner{
border-width: 0;
padding: 0;
}
}
}
}
</style>
<style lang="sss" scoped>
</style>

View File

@@ -0,0 +1,142 @@
<template>
<div class="pay-wrap" v-loading="fullscreenLoading">
<div class="pay">
<div class="pay-icon">
<i class="ns-text-color" :class="payInfo.pay_status ? 'el-icon-circle-check' : 'el-icon-circle-close'"></i>
</div>
<div class="pay-text">{{ payInfo.pay_status ? '支付成功' : '支付失败' }}</div>
<div class="pay-money">支付金额{{ payInfo.pay_money }}</div>
<div class="pay-footer">
<router-link to="/member">
<el-button type="primary">会员中心</el-button>
</router-link>
<router-link to="/" class="pay-button">
<el-button>回到首页</el-button>
</router-link>
</div>
</div>
</div>
</template>
<script>
import {
getPayInfo
} from '@/api/pay';
import {
memberInfo
} from '@/api/member/index.js'
export default {
name: 'pay_result',
components: {},
data: () => {
return {
payInfo: {},
outTradeNo: '',
fullscreenLoading: true
};
},
created() {
if (!this.$route.query.code) {
this.$router.push({
path: '/'
});
return;
}
this.outTradeNo = this.$route.query.code;
this.getPayInfo();
this.memberInfo()
},
methods: {
getPayInfo() {
getPayInfo({
out_trade_no: this.outTradeNo,
forceLogin: true
}).then(res => {
const {
code,
message,
data
} = res;
if (code >= 0 && data) {
this.payInfo = res.data;
} else {
this.$message({
message: '未获取到支付信息',
type: 'warning',
duration: 2000,
onClose: () => {
this.$router.push({
path: '/member/order_list'
});
}
});
}
this.fullscreenLoading = false;
}).catch(err => {
this.fullscreenLoading = false;
this.$message.error({
message: err.message,
duration: 2000,
onClose: () => {
this.$router.push({
path: '/member/order_list'
});
}
});
});
},
memberInfo() {
memberInfo().then(res => {
const {
data
} = res
this.$store.commit("member/SET_MEMBER", data)
})
}
}
};
</script>
<style lang="scss" scoped>
.pay-wrap {
width: 1210px;
margin: 20px auto;
}
.pay {
padding: 40px 15px;
margin: 10px 0;
border-radius: 0;
border: none;
background: #ffffff;
.pay-icon {
text-align: center;
i {
font-size: 65px;
}
}
.pay-text {
text-align: center;
font-size: 16px;
margin-top: 10px;
}
.pay-money {
text-align: center;
color: $base-color;
font-size: $ns-font-size-lg;
}
.pay-footer {
text-align: center;
margin-top: 30px;
.pay-button {
margin-left: 15px;
}
}
}
</style>

View File

@@ -0,0 +1,282 @@
<template>
<div class="combo-detail" v-loading="loading">
<div class="combo-title">
<div class="title-goods">商品信息</div>
<div class="title-orther">
<div class="title-price">价格</div>
<div class="title-num">数量</div>
</div>
</div>
<div class="item-wrap" v-for="(item, index) in goodsList.bundling_goods" :key="item.sku_item">
<div class="item">
<div class="info">
<div class="img-wrap" @click="$util.pushToTab({ path: '/sku/' + item.sku_id })">
<img :src="$img(item.sku_image, { size: 'mid' })" @error="imageError(index)" />
</div>
<div class="name">
{{ item.sku_name }}
<p v-if="num > item.stock">库存不足剩余{{ item.stock }}</p>
</div>
</div>
<div class="price-wrap">
<div class="price">{{ item.price }}</div>
<div class="num">x1</div>
</div>
</div>
</div>
<div class="combo-bottom">
<div class="num">
<p>购买数量:</p>
<el-input v-model="num" type="number" @change="changeNum(false)"></el-input>
</div>
<div class="bottom-right">
<div class="price">
<div class="save-price">为您节省:{{ saveThePrice }}</div>
<div class="old-price">
套餐价:
<p>{{ packagePrice }}</p>
</div>
</div>
<el-button type="primary" :disabled="isDisabled ? true : false" @click="comboBuy">立即购买</el-button>
</div>
</div>
</div>
</template>
<script>
import {
detail
} from '@/api/combo';
import {
mapGetters
} from 'vuex';
export default {
name: 'combo',
components: {},
data: () => {
return {
id: 0,
goodsList: [],
num: 1,
packagePrice: 0, //套餐价
saveThePrice: 0, //节省价格
isDisabled: false, //按钮失效
loading: true
};
},
created() {
this.id = this.$route.params.id;
this.getDetail();
},
computed: {
...mapGetters(['defaultGoodsImage'])
},
watch: {
$route(curr) {
this.id = curr.query.id;
this.getDetail();
}
},
methods: {
getDetail() {
detail({
bl_id: this.id
}).then(res => {
if (res.data) {
this.goodsList = res.data;
this.changeNum();
}
this.loading = false;
}).catch(err => {
this.loading = false;
this.$message.error(err.message);
});
},
changeNum(flag, callback) {
setTimeout(() => {
var disabledCount = 0;
// 防止空
if (this.num.length == 0) {
this.num = 1;
// disabledCount++;
}
// 防止输入0和负数、非法输入
if (this.num <= 0 || isNaN(this.num)) {
this.num = 1;
}
this.num = parseInt(this.num);
var price = 0;
for (var i = 0; i < this.goodsList.bundling_goods.length; i++) {
price += parseFloat(this.goodsList.bundling_goods[i].price);
//检测库存
if (this.goodsList.bundling_goods[i].stock < this.num) disabledCount++;
}
this.isDisabled = disabledCount > 0;
this.saveThePrice = ((price - this.goodsList.bl_price) * this.num).toFixed(2);
this.packagePrice = (this.goodsList.bl_price * this.num).toFixed(2);
if (callback) callback();
}, 0);
},
comboBuy() {
if (this.isDisabled) return;
var data = {
bl_id: this.id,
num: this.num
};
this.$store.dispatch('order/setComboOrderCreateData', data);
this.$router.push({
path: '/promotion/combo/payment'
});
},
imageError(index) {
this.goodsList.bundling_goods[index].sku_image = this.defaultGoodsImage;
}
}
};
</script>
<style lang="scss" scoped>
.combo-detail {
width: 1210px;
margin: 20px auto;
.combo-title {
display: flex;
background: #ffffff;
padding: 10px;
margin-bottom: 20px;
justify-content: space-between;
.title-orther {
display: flex;
justify-content: space-between;
align-items: center;
width: 150px;
.title-price {
margin-right: 10px;
}
.title-num {
margin-right: 10px;
}
}
}
.item-wrap {
padding: 0 10px 10px 10px;
background: #ffffff;
.item {
display: flex;
justify-content: space-between;
padding-top: 10px;
.info {
display: flex;
.img-wrap {
width: 80px;
height: 80px;
img {
width: 100%;
height: 100%;
}
}
.name {
margin-left: 5px;
font-size: $ns-font-size-base;
width: 500px;
overflow: hidden;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 2;
position: relative;
p {
position: absolute;
bottom: 0;
color: $base-color;
}
}
}
.price-wrap {
display: flex;
justify-content: space-between;
align-items: center;
width: 150px;
.price {
margin-right: 10px;
display: flex;
justify-content: center;
align-items: center;
}
.num {
padding-right: 10px;
display: flex;
justify-content: center;
align-items: center;
}
}
}
}
.combo-bottom {
background: #ffffff;
padding: 10px;
margin: 20px 0;
display: flex;
justify-content: space-between;
.num {
display: flex;
align-items: center;
input {
border: none;
}
p {
width: 80px;
}
}
.bottom-right {
display: flex;
.price {
display: flex;
align-items: center;
margin-right: 50px;
.save-price {
margin-right: 10px;
}
.old-price {
margin-right: 10px;
font-weight: 600;
display: flex;
p {
color: $base-color;
font-size: $ns-font-size-lg;
}
}
}
}
}
}
</style>

View File

@@ -0,0 +1,327 @@
<template>
<div class="payment-wrap" v-loading="fullscreenLoading">
<!--购买虚拟类商品需填写您的手机号-->
<div class="item-block" v-if="orderPaymentData.is_virtual == 1">
<div class="block-text">购买虚拟类商品需填写您的手机号以方便商家与您联系</div>
<el-form ref="form" size="mini" class="mobile-wrap" label-width="80px">
<el-form-item label="手机号码">
<el-input placeholder="请输入您的手机号码" maxlength="11" v-model="orderCreateData.member_address.mobile" />
</el-form-item>
</el-form>
</div>
<!--收货地址-->
<div class="item-block" v-if="orderPaymentData.is_virtual == 0">
<div class="block-text">收货地址</div>
<div class="address-list">
<div class="address-item" @click="addAddressShow">
<div class="add-address">
<i class="el-icon-circle-plus-outline"></i>
添加收货地址
</div>
</div>
<div class="address-item" v-for="(item, key) in memberAddress" :key="item.id" :class="addressId == item.id ? 'active' : ''" v-if="key < 3 || (addressShow && key >= 3)">
<div class="address-info">
<div class="options">
<div @click="editAddress(item.id)">编辑</div>
<template v-if="item.is_default == 0">
<el-popconfirm title="确定要删除该地址吗?" @onConfirm="deleteMemberAddress(item.id)">
<div slot="reference">删除</div>
</el-popconfirm>
</template>
</div>
<div class="address-name">{{ item.name }}</div>
<div class="address-mobile" @click="setMemberAddress(item.id)">{{ item.mobile }}</div>
<div class="address-desc" @click="setMemberAddress(item.id)">{{ item.full_address }} {{ item.address }}
</div>
</div>
</div>
<div v-if="memberAddress.length > 3 && !addressShow" @click="addressShow = true" class="el-button--text address-open">
<i class="el-icon-arrow-down"></i>
更多收货地址
</div>
<div class="clear"></div>
</div>
</div>
<!--收货地址添加-->
<el-dialog :title="addressForm.id == 0 ? '添加收货地址' : '编辑收货地址'" :visible.sync="dialogVisible" width="32%">
<el-form ref="form" :rules="addressRules" :model="addressForm" label-width="80px">
<el-form-item label="姓名" prop="name">
<el-input v-model="addressForm.name" placeholder="收货人姓名" />
</el-form-item>
<el-form-item label="手机" prop="mobile">
<el-input v-model="addressForm.mobile" maxlength="11" placeholder="收货人手机号" />
</el-form-item>
<el-form-item label="电话">
<el-input v-model="addressForm.telephone" placeholder="收货人固定电话(选填)" />
</el-form-item>
<el-form-item class="area" label="地区" prop="area">
<el-row :gutter="10">
<el-col :span="7">
<el-select prop="province" ref="province" v-model="addressForm.province_id" @change="getAddress(1)" placeholder="请选择省">
<el-option label="请选择省" value="0"></el-option>
<el-option v-for="item in pickerValueArray" :key="item.id" :label="item.name" :value="item.id"></el-option>
</el-select>
</el-col>
<el-col :span="7">
<el-select ref="city" prop="city" v-model="addressForm.city_id" @change="getAddress(2)" placeholder="请选择市">
<el-option label="请选择市" value="0"></el-option>
<el-option v-for="item in cityArr" :key="item.id" :label="item.name" :value="item.id"></el-option>
</el-select>
</el-col>
<el-col :span="7">
<el-select ref="district" prop="district" v-model="addressForm.district_id" placeholder="请选择区/县">
<el-option label="请选择区/县" value="0"></el-option>
<el-option v-for="item in districtArr" :key="item.id" :label="item.name" :value="item.id"></el-option>
</el-select>
</el-col>
</el-row>
</el-form-item>
<el-form-item label="详细地址" prop="address">
<el-input v-model="addressForm.address" placeholder="定位小区、街道、写字楼" />
</el-form-item>
</el-form>
<span slot="footer" class="dialog-footer">
<el-button @click="dialogVisible = false"> </el-button>
<el-button type="primary" @click="addmemberAddress('form')"> </el-button>
</span>
</el-dialog>
<!--使用余额-->
<div class="item-block" v-if="orderPaymentData.member_account.balance_total > 0 && balance_show == 1">
<div class="block-text">是否使用余额</div>
<div class="pay-type-list">
<div class="pay-type-item" :class="orderCreateData.is_balance ? '' : 'active'" @click="useBalance(0)">不使用余额
</div>
<div class="pay-type-item" :class="orderCreateData.is_balance ? 'active' : ''" @click="useBalance(1)">使用余额</div>
<div class="clear"></div>
</div>
</div>
<!-- 支付密码 -->
<el-dialog title="使用余额" :visible.sync="dialogpay" width="350px">
<template v-if="orderPaymentData.member_account.is_pay_password == 0">
<p>为了您的账户安全,请您先设置的支付密码</p>
<p>可到"会员中心","账号安全","支付密码"中设置</p>
<span slot="footer" class="dialog-footer">
<el-button size="small" @click="dialogpay = false">暂不设置</el-button>
<el-button size="small" type="primary" @click="setPayPassword">立即设置</el-button>
</span>
</template>
<el-form v-else status-icon ref="ruleForm" label-width="100px">
<el-form-item label="支付密码" class="pay-password-item">
<!--添加一个不可见的input,欺骗浏览器自动填充-->
<el-input type="password" class="pay-password hide-password" :maxlength="6"></el-input>
<el-input type="password" class="pay-password" :maxlength="6" v-model="password" @input="input"></el-input>
</el-form-item>
<p class="ns-text-color forget-password" @click="setPayPassword">忘记密码</p>
</el-form>
</el-dialog>
<!-- 配送方式 -->
<div class="item-block padd-bom-20" v-if="orderPaymentData.delivery.express_type.length > 0">
<div class="block-text">
<span>配送方式</span>
<span class="distribution" v-if="orderCreateData.delivery.delivery_type == 'store'">{{ orderCreateData.delivery.store_name }}</span>
</div>
<div class="pay-type-item" v-for="(item, index) in orderPaymentData.delivery.express_type" :key="index" @click="selectDeliveryType(item)" :class="item.name == orderCreateData.delivery.delivery_type ? 'active' : ''">
{{ item.title }}
</div>
</div>
<!--配送方式 门店 -->
<el-dialog title="选择门店" :visible.sync="dialogStore" width="50%">
<el-table ref="singleTable" :data="storeList" highlight-current-row @row-click="selectStore" class="cursor-pointer">
<el-table-column label="" width="55">
<template slot-scope="scope">
<el-radio v-model="storeRadio" :label="scope.row"><i></i></el-radio>
</template>
</el-table-column>
<el-table-column prop="store_name" label="名称" width="160"></el-table-column>
<el-table-column prop="store_address" label="地址"></el-table-column>
<el-table-column prop="open_date" label="营业时间"></el-table-column>
</el-table>
</el-dialog>
<div class="item-block" v-if="orderPaymentData.invoice && orderPaymentData.invoice.invoice_status == 1">
<div class="block-text">发票信息</div>
<div class="pay-type-list">
<div class="pay-type-item" :class="orderCreateData.is_invoice == 0 ? 'active' : ''" @click="changeIsInvoice">
无需发票
</div>
<div class="pay-type-item" :class="orderCreateData.is_invoice == 1 ? 'active' : ''" @click="changeIsInvoice">
需要发票
</div>
<div class="clear"></div>
</div>
<div class="invoice-information" v-if="orderCreateData.is_invoice == 1">
<div class="invoice-title">
<div class="invoice-type-box invoice-title-box">
<span class="invoice-name">发票类型</span>
<label class="invoice-to-type">
<i class="invoice-i-input" :class="orderCreateData.invoice_type == 1 ? 'active' : ''" @click="clickType(1)"></i>
<span>纸质</span>
</label>
<label class="invoice-to-type">
<i class="invoice-i-input" :class="orderCreateData.invoice_type == 2 ? 'active' : ''" @click="clickType(2)"></i>
<span>电子</span>
</label>
</div>
<div class="invoice-type-box invoice-title-box">
<span class="invoice-name">抬头类型</span>
<label class="invoice-to-type">
<i class="invoice-i-input" :class="orderCreateData.invoice_title_type == 1 ? 'active' : ''" @click="clickTitleType(1)"></i>
<span>个人</span>
</label>
<label class="invoice-to-type">
<i class="invoice-i-input" :class="orderCreateData.invoice_title_type == 2 ? 'active' : ''" @click="clickTitleType(2)"></i>
<span>企业</span>
</label>
</div>
</div>
<div class="invoice-type-box">
<span class="invoice-name">发票信息</span>
<div class="invoice-box-form">
<input type="text" placeholder="请填写抬头名称" v-model.trim="orderCreateData.invoice_title" />
<input type="text" placeholder="请填写纳税人识别号" v-model.trim="orderCreateData.taxpayer_number" v-if="orderCreateData.invoice_title_type == 2" />
<input type="text" placeholder="请填写邮寄地址" v-model.trim="orderCreateData.invoice_full_address" v-show="orderCreateData.invoice_type == 1" />
<input type="text" placeholder="请填写邮箱" v-model.trim="orderCreateData.invoice_email" v-show="orderCreateData.invoice_type == 2" />
</div>
</div>
<div class="invoice-condition">
<span class="invoice-name">发票内容</span>
<div class="invoice-box-form">
<span class="option-item" :key="index" v-for="(item, index) in orderPaymentData.invoice.invoice_content_array" @click="changeInvoiceContent(item)" :class="{ 'color-base-bg active': item == orderCreateData.invoice_content }">
{{ item }}
</span>
</div>
</div>
<div class="invoice-tops">发票内容将以根据税法调整具体请以展示为准发票内容显示详细商品名 称及价格信息</div>
</div>
</div>
<!--商品信息-->
<div class="item-block">
<div class="goods-list">
<table>
<tr>
<td width="70%">商品</td>
<td width="15%">价格</td>
<td width="15%">数量</td>
</tr>
</table>
</div>
</div>
<div>
<div class="item-block" v-if="calculateData">
<div class="goods-list">
<table>
<tr v-for="(goodsItem, goodsIndex) in calculateData.goods_list" :key="goodsIndex">
<td width="50%">
<div class="goods-info">
<div class="goods-info-left">
<router-link :to="{ path: '/sku/' + goodsItem.sku_id }" target="_blank">
<img class="goods-img" :src="$img(goodsItem.sku_image, { size: 'mid' })" @error="imageError(goodsIndex)" />
</router-link>
</div>
<div class="goods-info-right">
<router-link :to="{ path: '/sku/' + goodsItem.sku_id }" target="_blank">
<div class="goods-name">{{ goodsItem.goods_name }}</div>
</router-link>
<!-- 规格 -->
<div class="goods-spec" v-if="goodsItem.sku_spec_format">
<span v-for="(x, i) in goodsItem.sku_spec_format" :key="i">{{ x.spec_value_name }}</span>
</div>
</div>
</div>
</td>
<td width="12.5%" class="goods-price">{{ goodsItem.price }}</td>
<td width="12.5%" class="goods-num">{{ goodsItem.num }}</td>
<td width="12.5%" class="goods-money">{{ (goodsItem.price * goodsItem.num).toFixed(2) }}</td>
</tr>
</table>
</div>
</div>
</div>
<!--活动优惠-->
<div class="item-block" v-if="promotionInfo">
<div class="block-text">{{ promotionInfo.title }}</div>
<div class="order-cell platform-coupon">
<div class="box ns-text-color" v-html="promotionInfo.content"></div>
</div>
</div>
<!-- 买家留言 -->
<div class="item-block padd-bom-10">
<div class="block-text">买家留言</div>
<el-input rows="3" type="textarea" placeholder="留言前建议先与商家协调一致" v-model="orderCreateData.buyer_message" class="buyer-message" @input="textarea" maxlength="140" show-word-limit resize="none" />
</div>
<!-- 总计 -->
<div class="item-block" v-if="calculateData">
<div class="order-statistics">
<table>
<tr>
<td align="right">商品金额</td>
<td align="left">{{ calculateData.goods_money | moneyFormat }}</td>
</tr>
<tr v-if="calculateData.is_virtual == 0 && calculateData.delivery_money > 0">
<td align="right">运费</td>
<td align="left">{{ calculateData.delivery_money | moneyFormat }}</td>
</tr>
<tr v-if="calculateData.invoice_money > 0">
<td align="right">发票税费<span class="ns-text-color">({{ calculateData.invoice.invoice_rate }}%)</span></td>
<td align="left">{{ calculateData.invoice_money | moneyFormat }}</td>
</tr>
<tr v-if="calculateData.invoice_delivery_money > 0">
<td align="right">发票邮寄费</td>
<td align="left">{{ calculateData.invoice_delivery_money | moneyFormat }}</td>
</tr>
<tr v-if="calculateData.balance_money > 0">
<td align="right">使用余额</td>
<td align="left">{{ calculateData.balance_money | moneyFormat }}</td>
</tr>
</table>
</div>
<div class="clear"></div>
</div>
<!--结算-->
<div class="item-block" v-if="calculateData">
<div class="order-submit">
<div class="order-money">
{{ calculateData.goods_num }}应付金额
<div class="ns-text-color">{{ calculateData.pay_money | moneyFormat }}</div>
</div>
<el-button type="primary" class="el-button--primary" @click="orderCreate">订单结算</el-button>
</div>
<div class="clear"></div>
</div>
</div>
</template>
<script>
import detail from '@/assets/js/promotion/payment_combo.js';
export default {
name: 'combo_payment',
mixins: [detail]
};
</script>
<style lang="scss" scoped>
@import '@/assets/css/promotion/payment_combo.scss';
</style>

View File

@@ -0,0 +1,347 @@
<template>
<div class="goods-detail-wrap">
<div class="detail-nav-wrap" v-if="categoryNameArr">
<div class="detail-nav" v-if="categoryNameArr.length">
<template v-for="(item,index) in categoryNameArr" :keys="index">
<router-link :to="{ path: '/goods/list', query: { category_id: item.category_id, level: index } }">
{{item.name}}
</router-link>
<span class="iconfont icon-arrow-right"></span>
</template>
<span class="goods-name">{{goodsSkuDetail.goods_name}}</span>
</div>
</div>
<div class="detail-main">
<div class="goods-detail">
<div class="preview-wrap">
<div class="video-player-wrap" :class="{ show: switchMedia == 'video' }" v-if="goodsSkuDetail.video_url != ''">
<video-player v-if="goodsSkuDetail.video_url != ''" ref="videoPlayer" :playsinline="true"
:options="playerOptions" @play="onPlayerPlay($event)" @pause="onPlayerPause($event)"
@ended="onPlayerEnded($event)" @waiting="onPlayerWaiting($event)"
@playing="onPlayerPlaying($event)"
@loadeddata="onPlayerLoadeddata($event)" @timeupdate="onPlayerTimeupdate($event)"
@canplay="onPlayerCanplay($event)" @canplaythrough="onPlayerCanplaythrough($event)"
@statechanged="playerStateChanged($event)" @ready="playerReadied"></video-player>
<div class="media-mode" v-if="goodsSkuDetail.video_url != ''">
<span :class="{ 'ns-bg-color': switchMedia == 'video' }" @click="switchMedia = 'video'">视频</span>
<span :class="{ 'ns-bg-color': switchMedia == 'img' }" @click="switchMedia = 'img'">图片</span>
</div>
</div>
<div class="magnifier-wrap">
<pic-zoom ref="PicZoom" :url="$img(picZoomUrl)" :scale="2"></pic-zoom>
</div>
<div class="spec-items">
<span class="left-btn iconfont icon-weibiaoti35" :class="{ move: moveThumbLeft }" @click="changeThumbImg('prev')"></span>
<span class="right-btn iconfont icon-weibiaoti35" :class="{ move: moveThumbRight }" @click="changeThumbImg('next')"></span>
<ul :style="{ top: 42 + thumbPosition + 'px' }">
<!-- 商品缩率图 -->
<li v-for="(item, index) in goodsSkuDetail.sku_images" :key="index" @mousemove="picZoomUrl = item" :class="{ selected: picZoomUrl == item }">
<img :src="$img(item, { size: 'small' })" @error="imageErrorSpec(index)" />
</li>
</ul>
</div>
</div>
<!-- 商品信息 -->
<div class="basic-info-wrap" v-loading="loading">
<h1>{{ goodsSkuDetail.sku_name }}</h1>
<p class="desc ns-text-color" v-if="goodsSkuDetail.introduction">{{ goodsSkuDetail.introduction }}</p>
<div class="discount-banner ns-bg-color" v-if="groupbuyTimeMachine.currentTime">
<div class="activity-name">
<i class="discount-icon iconfont iconicon_naozhong"></i>
<span>团购</span>
</div>
<div class="surplus-time">
<span>{{ groupbuyText }}</span>
<count-down class="count-down" v-on:start_callback="countDownS_cb()" v-on:end_callback="countDownE_cb()"
:currentTime="groupbuyTimeMachine.currentTime" :startTime="groupbuyTimeMachine.startTime"
:endTime="groupbuyTimeMachine.endTime" :dayTxt="'天'" :hourTxt="'小时'" :minutesTxt="'分钟'"
:secondsTxt="'秒'">
</count-down>
</div>
</div>
<div class="item-block">
<div class="promotion-price">
<dl class="item-line">
<dt class="ns-text-color-gray">团购价</dt>
<dd>
<em class="yuan ns-text-color">¥</em>
<span class="price ns-text-color">{{ goodsSkuDetail.groupbuy_price }}</span>
</dd>
</dl>
<dl class="item-line">
<dt class="ns-text-color-gray">原价</dt>
<dd>
<em class="market-yuan">¥</em>
<span class="market-price">{{ goodsSkuDetail.price }}</span>
</dd>
</dl>
<!-- <div class="statistical">
<ul>
<li>
<p>累计评价</p>
<span>{{ goodsSkuDetail.evaluate }}</span>
</li>
<li>
<p>累计销量</p>
<span>{{ goodsSkuDetail.sale_num }}{{ goodsSkuDetail.unit }}</span>
</li>
</ul>
</div> -->
<dl class="item-line" v-if="goodsSkuDetail.is_virtual == 0">
<dt>运费</dt>
<dd>
<i class="i-activity-flag ns-text-color ns-border-color" v-if="goodsSkuDetail.is_free_shipping">快递免邮</i>
<i class="i-activity-flag ns-text-color ns-border-color" v-else>快递不免邮</i>
</dd>
</dl>
</div>
</div>
<dl class="item-line delivery" v-if="goodsSkuDetail.is_virtual == 0">
<dt>配送至</dt>
<dd>
<div class="region-selected ns-border-color-gray">
<span>
<template v-if="selectedAddress['level_1']">
<template v-for="item in selectedAddress">{{ item.name }}</template>
</template>
<template v-else>请选择配送地址</template>
</span>
<i class="el-icon-arrow-down"></i>
</div>
<div class="region-list ns-border-color-gray" :class="{ hide: hideRegion }">
<ul class="nav-tabs">
<li :class="{ active: currTabAddres == 'province' }" @click="currTabAddres = 'province'">
<div>
<span>{{ selectedAddress['level_1'] ? selectedAddress['level_1'].name : '请选择省' }}</span>
<i class="el-icon-arrow-down"></i>
</div>
</li>
<li :class="{ active: currTabAddres == 'city' }" @click="currTabAddres = 'city'">
<div>
<span>{{ selectedAddress['level_2'] ? selectedAddress['level_2'].name : '请选择市' }}</span>
<i class="el-icon-arrow-down"></i>
</div>
</li>
<li :class="{ active: currTabAddres == 'district' }" @click="currTabAddres = 'district'">
<div>
<span>{{ selectedAddress['level_3'] ? selectedAddress['level_3'].name : '请选择区/县' }}</span>
<i class="el-icon-arrow-down"></i>
</div>
</li>
</ul>
<div class="tab-content">
<div class="tab-pane" :class="{ active: currTabAddres == 'province' }">
<ul class="province">
<li v-for="(item, index) in provinceArr" :key="index" :class="{ selected: selectedAddress['level_' + item.level] && selectedAddress['level_' + item.level].id == item.id }">
<span @click="getAddress('city', item)">{{ item.name }}</span>
</li>
</ul>
</div>
<div class="tab-pane" :class="{ active: currTabAddres == 'city' }">
<ul class="city">
<li v-for="(item, index) in cityArr" :key="index" :class="{ selected: selectedAddress['level_' + item.level] && selectedAddress['level_' + item.level].id == item.id }">
<span @click="getAddress('district', item)">{{ item.name }}</span>
</li>
</ul>
</div>
<div class="tab-pane" :class="{ active: currTabAddres == 'district' }">
<ul class="district">
<li v-for="(item, index) in districtArr" :key="index" :class="{ selected: selectedAddress['level_' + item.level] && selectedAddress['level_' + item.level].id == item.id }">
<span @click="getAddress('community', item)">{{ item.name }}</span>
</li>
</ul>
</div>
</div>
</div>
</dd>
</dl>
<dl class="item-line service">
<dt>服务</dt>
<dd>
<span>
<span class="ns-text-color">{{siteInfo.site_name}}</span>
发货并提供售后服务
</span>
</dd>
</dl>
<hr class="divider" />
<div class="sku-list" v-if="goodsSkuDetail.goods_spec_format">
<dl class="item-line" v-for="(item, index) in goodsSkuDetail.goods_spec_format" :key="index">
<dt>{{ item.spec_name }}</dt>
<dd>
<ul>
<li v-for="(item_value, index_value) in item.value" :key="index_value">
<div :class="{
'selected ns-border-color': item_value['selected'] || skuId == item_value.sku_id,
disabled: item_value['disabled'] || (!item_value['selected'] && specDisabled)
}" @click="changeSpec(item_value.sku_id, item_value.spec_id)">
<img v-if="item_value.image" :src="$img(item_value.image, { size: 'small' })" />
<span>{{ item_value.spec_value_name }}</span>
<i class="iconfont iconduigou1 ns-text-color"></i>
</div>
</li>
</ul>
</dd>
</dl>
</div>
<div class="buy-number">
<dl class="item-line">
<dt>数量</dt>
<dd>
<div class="num-wrap">
<div class="operation">
<span class="decrease el-icon-minus" @click="changeNum('-')"></span>
<el-input v-model="number" placeholder="0" @input="keyInput()"></el-input>
<span class="increase el-icon-plus" @click="changeNum('+')"></span>
</div>
</div>
<span class="unit">{{ goodsSkuDetail.unit }}</span>
<span class="inventory">库存{{ goodsSkuDetail.stock }}{{ goodsSkuDetail.unit }}</span>
<!-- 限购 -->
<em v-if="limitNumber > 0">({{ limitNumber }}{{ goodsSkuDetail.unit }}起购)</em>
</dd>
</dl>
</div>
<dl class="item-line buy-btn">
<dt></dt>
<dd v-if="goodsSkuDetail.goods_state == 1">
<template v-if="goodsSkuDetail.goods_stock < goodsSkuDetail.buy_num && !goodsSkuDetail.sku_spec_format">
<el-button type="info" plain disabled>库存不足</el-button>
</template>
<template v-else>
<el-button type="primary" plain @click="buyNow">立即抢购</el-button>
</template>
<div class="go-phone icon-item" @click="editCollection">
<span :class="['iconfont',(whetherCollection == 1 ? 'icon-_shouzang2 selected' : 'icon-shouzang')]"></span>
<span>收藏</span>
</div>
</dd>
<dd v-else>
<template>
<el-button type="info" plain disabled>该商品已下架</el-button>
</template>
<div class="go-phone icon-item" @click="editCollection">
<span :class="['iconfont',(whetherCollection == 1 ? 'icon-_shouzang2 selected' : 'icon-shouzang')]"></span>
<span>收藏</span>
</div>
</dd>
</dl>
<dl class="item-line merchant-service" v-show="service_list.length">
<dt>商品服务</dt>
<div>
<dd class="service-li" v-for="item in service_list">
<i class="el-icon-success"></i>
<span class="ns-text-color-gray" :title="item.service_name">{{item.service_name}}</span>
</dd>
</div>
</dl>
</div>
<div class="detail-wrap">
<el-tabs class="goods-tab" v-model="tabName" type="card" @tab-click="tabChange">
<el-tab-pane label="商品详情" name="detail">
<div v-html="goodsSkuDetail.goods_content"></div>
</el-tab-pane>
<el-tab-pane label="商品属性" name="attr">
<ul class="attr-list">
<template v-if="goodsSkuDetail.goods_attr_format && goodsSkuDetail.goods_attr_format.length > 0">
<li v-for="(item, index) in goodsSkuDetail.goods_attr_format" :key="index">{{ item.attr_name }}{{ item.attr_value_name }}</li>
</template>
</ul>
</el-tab-pane>
<el-tab-pane v-if="evaluate_show" :label="goodsEvaluateList.length ? '商品评价(' + goodsEvaluateList.length + ')' : '商品评价'" name="evaluate" class="evaluate">
<template v-if="goodsEvaluateList.length">
<nav>
<li :class="evaluaType == 0 ? 'selected' : ''" @click="evaluationType(0)">全部评价({{evaluteCount.total}})</li>
<li :class="evaluaType == 1 ? 'selected' : ''" @click="evaluationType(1)">好评({{evaluteCount.haoping}})</li>
<li :class="evaluaType == 2 ? 'selected' : ''" @click="evaluationType(2)">中评({{evaluteCount.zhongping}})</li>
<li :class="evaluaType == 3 ? 'selected' : ''" @click="evaluationType(3)">差评({{evaluteCount.chaping}})</li>
</nav>
<ul class="list">
<li v-for="(item, index) in goodsEvaluateList" :key="index">
<div class="member-info">
<img :src="$img(item.member_headimg)" @error="imageErrorEvaluate(index)" class="avatar" />
<span>{{ item.member_name }}</span>
</div>
<div class="info-wrap">
<el-rate v-model="item.star" disabled></el-rate>
<p class="content">{{ item.content }}</p>
<div class="img-list" v-if="item.images">
<el-image v-for="(img, img_index) in item.images" :key="img_index" :src="$img(img)" :preview-src-list="item.imagesFormat"/>
</div>
<div class="sku-info">
<span>{{ item.sku_name }}</span>
<span class="create-time">{{ $util.timeStampTurnTime(item.create_time) }}</span>
</div>
<div class="evaluation-reply" v-if="item.explain_first != ''">店家回复{{ item.explain_first }}</div>
<template v-if="item.again_content != ''">
<div class="review-evaluation">
<span>追加评价</span>
<span class="review-time">{{ $util.timeStampTurnTime(item.again_time) }}</span>
</div>
<p class="content">{{ item.again_content }}</p>
<div class="img-list">
<el-image v-for="(again_img, again_index) in item.again_images" :key="again_index" :src="$img(again_img)" :preview-src-list="item.againImagesFormat"/>
</div>
<div class="evaluation-reply" v-if="item.again_explain != ''">店家回复{{ item.again_explain }}
</div>
</template>
</div>
</li>
</ul>
<div class="pager">
<el-pagination background :pager-count="5" :total="total" prev-text="上一页" next-text="下一页"
:current-page.sync="currentPage" :page-size.sync="pageSize"
@size-change="handlePageSizeChange"
@current-change="handleCurrentPageChange" hide-on-single-page></el-pagination>
</div>
</template>
<div class="empty" v-else>该商品暂无评价哦</div>
</el-tab-pane>
<template v-if="service">
<el-tab-pane v-if="service.is_display == 1" label="售后保障" name="after_sale" class="after-sale">
<div v-html="service.content"></div>
</el-tab-pane>
</template>
</el-tabs>
</div>
<!--联系客服弹窗-->
<servicerMessage ref="servicerMessage" class="kefu" :shop="{shop_id:shopInfo.site_id,logo:shopInfo.logo,shop_name:shopInfo.site_name}"></servicerMessage>
</div>
</div>
</div>
</template>
<script>
import PicZoom from 'vue-piczoom';
import detail from '@/assets/js/promotion/detail_groupbuy.js';
import GoodsRecommend from '@/components/GoodsRecommend';
import servicerMessage from "@/components/message/servicerMessage";
export default {
name: 'groupbuy_detail',
components: {
PicZoom,
GoodsRecommend,
servicerMessage
},
mixins: [detail]
};
</script>
<style lang="scss">
@import '@/assets/css/promotion/detail_groupbuy.scss';
</style>

View File

@@ -0,0 +1,337 @@
<template>
<div class="ns-groupbuy">
<div class="ns-groupbuy-head">
<el-carousel height="420px" v-loading="loadingAd" v-if="adList.length">
<el-carousel-item v-for="item in adList" :key="item.adv_id">
<el-image :src="$img(item.adv_image)" fit="cover" @click="$util.pushToTab(item.adv_url.url)" />
</el-carousel-item>
</el-carousel>
</div>
<!-- 商品列表 -->
<div class="ns-groupbuy-box" v-loading="loading">
<div class="ns-groupbuy-title" v-if="goodsList.length">
<span class="groupbuy-title-left">团购专区</span>
</div>
<div class="goods-list" v-if="goodsList.length">
<div class="goods" v-for="(item,index) in goodsList" :key="item.groupbuy_id" @click="$router.push('/promotion/groupbuy/' + item.groupbuy_id)">
<!-- 商品图片区 -->
<div class="img">
<el-image fit="scale-down" :src="$img(item.goods_image, { size: 'mid' })" lazy @error="imageError(index)"/>
</div>
<!-- 商品名称 -->
<div class="name">
<p :title="item.goods_name">{{ item.goods_name }}</p>
</div>
<!-- 价格展示区 -->
<div class="price">
<div class="curr-price">
<span>团购价</span>
<span></span>
<span class="main_price">{{ item.groupbuy_price }}</span>
</div>
<span class="primary_price">{{ item.price }}</span>
</div>
<el-button>立即拼购</el-button>
</div>
</div>
<div v-else-if="!loading" class="empty-wrap">
<img src="~assets/images/goods_empty.png">
<span>暂无正在进行团购的商品<router-link to="/" class="ns-text-color">去首页</router-link>看看吧</span>
</div>
<div class="pager">
<el-pagination
background
:pager-count="5"
:total="total"
prev-text="上一页"
next-text="下一页"
:current-page.sync="currentPage"
:page-size.sync="pageSize"
@size-change="handlePageSizeChange"
@current-change="handleCurrentPageChange"
hide-on-single-page
></el-pagination>
</div>
</div>
</div>
</template>
<script>
import {goodsPage} from '@/api/groupbuy';
import {mapGetters} from 'vuex';
import {adList} from '@/api/website';
export default {
name: 'groupbuy',
data: () => {
return {
loading: true,
goodsList: [],
total: 0,
currentPage: 1,
pageSize: 25,
loadingAd: true,
adList: []
};
},
created() {
if (this.addonIsExit && this.addonIsExit.groupbuy != 1) {
this.$message({
message: '团购插件未安装',
type: 'warning',
duration: 2000,
onClose: () => {
this.$route.push('/');
}
});
} else {
this.getAdList();
this.getGoodsList();
}
},
computed: {
...mapGetters(['defaultGoodsImage', 'addonIsExit'])
},
head() {
return {
title: '团购专区-' + this.$store.state.site.siteInfo.site_name,
meta: [{
name: 'description',
content: this.$store.state.site.siteInfo.seo_description
}, {
name: 'keyword',
content: this.$store.state.site.siteInfo.seo_keywords
}]
}
},
watch: {
addonIsExit() {
if (this.addonIsExit.groupbuy != 1) {
this.$message({
message: '团购插件未安装',
type: 'warning',
duration: 2000,
onClose: () => {
this.$route.push('/');
}
});
}
}
},
methods: {
getAdList() {
adList({keyword: 'NS_PC_GROUPBUY'}).then(res => {
this.adList = res.data.adv_list;
for (let i = 0; i < this.adList.length; i++) {
if (this.adList[i].adv_url) this.adList[i].adv_url = JSON.parse(this.adList[i].adv_url);
}
this.loadingAd = false;
}).catch(err => {
this.loadingAd = false;
});
},
/**
* 团购商品
*/
getGoodsList() {
goodsPage({
page_size: this.pageSize,
page: this.currentPage
}).then(res => {
this.goodsList = res.data.list;
this.total = res.data.count;
this.loading = false;
}).catch(err => {
this.loading = false;
this.$message.error(err.message);
});
},
handlePageSizeChange(size) {
this.pageSize = size;
this.refresh();
},
handleCurrentPageChange(page) {
this.currentPage = page;
this.refresh();
},
refresh() {
this.loading = true;
this.getGoodsList();
},
/**
* 图片加载失败
*/
imageError(index) {
this.goodsList[index].goods_image = this.defaultGoodsImage;
}
}
};
</script>
<style lang="scss" scoped>
.ns-groupbuy {
.ns-groupbuy-box {
padding: 48px 0;
width: $width;
margin: 0 auto;
.ns-groupbuy-title {
display: flex;
align-items: center;
border-bottom: 1px solid #e8e8e8;
.groupbuy-title-left {
font-size: 30px;
color: #333;
border-bottom: 4px solid #F42424;
}
}
}
.goods-list {
display: flex;
flex-direction: row;
flex-wrap: wrap;
justify-content: flex-start;
margin-top: 32px;
.goods {
margin-right: 17px;
margin-bottom: 18px;
width: 228px;
background-color: #ffffff;
overflow: hidden;
color: #303133;
transition: 0.3s;
padding: 18px;
box-sizing: border-box;
cursor: pointer;
&:nth-child(5n+5) {
margin-right: 0;
}
}
.img {
width: 192px;
height: 192px;
.el-image {
max-width: 100%;
max-height: 100%;
}
}
.price {
display: flex;
align-items: baseline;
.curr-price {
display: flex;
align-items: baseline;
height: 24px;
font-weight: bold;
color: $base-color;
span:first-child {
font-size: 14px;
margin-right: 1px;
}
span:nth-child(2) {
font-size: 12px;
}
}
.main_price {
color: $base-color;
font-size: 14px;
line-height: 24px;
}
.primary_price {
text-decoration: line-through;
color: $base-color-info;
margin-left: 5px;
font-size: 12px;
}
}
.el-button {
width: 100%;
height: 42px;
line-height: 42px;
background: $base-color;
color: #ffffff;
margin-top: 10px;
border: none;
border-radius: 0;
padding: 0;
font-size: 16px;
}
.name {
margin-top: 12px;
font-size: 14px;
line-height: 1.4;
margin-bottom: 5px;
white-space: normal;
overflow: hidden;
p {
line-height: 24px;
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 2;
overflow: hidden;
height: 50px;
}
}
}
.empty-wrap {
padding: 50px 0 60px;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
box-sizing: border-box;
img {
width: 400px;
height: 244px;
}
span {
font-size: 14px;
color: #4A4A4A;
}
}
}
</style>
<style lang="scss">
.ns-groupbuy {
.ns-groupbuy-head {
width: $width;
margin: auto;
}
.el-carousel {
.el-image {
height: 100%;
}
.el-image__inner {
width: auto;
}
}
.el-carousel__arrow--right {
right: 60px;
}
}
</style>

View File

@@ -0,0 +1,326 @@
<template>
<div class="payment-wrap" v-loading="fullscreenLoading">
<!--购买虚拟类商品需填写您的手机号-->
<div class="item-block" v-if="orderPaymentData.is_virtual == 1">
<div class="block-text">购买虚拟类商品需填写您的手机号以方便商家与您联系</div>
<el-form ref="form" size="mini" class="mobile-wrap" label-width="80px">
<el-form-item label="手机号码">
<el-input placeholder="请输入您的手机号码" maxlength="11" v-model="orderCreateData.member_address.mobile" />
</el-form-item>
</el-form>
</div>
<!--收货地址-->
<div class="item-block" v-if="orderPaymentData.is_virtual == 0">
<div class="block-text">收货地址</div>
<div class="address-list">
<div class="address-item" @click="addAddressShow">
<div class="add-address">
<i class="el-icon-circle-plus-outline"></i>
添加收货地址
</div>
</div>
<div class="address-item" v-for="(item, key) in memberAddress" :key="item.id" :class="addressId == item.id ? 'active' : ''" v-if="key < 3 || (addressShow && key >= 3)">
<div class="address-info">
<div class="options">
<div @click="editAddress(item.id)">编辑</div>
<template v-if="item.is_default == 0">
<el-popconfirm title="确定要删除该地址吗?" @onConfirm="deleteMemberAddress(item.id)">
<div slot="reference">删除</div>
</el-popconfirm>
</template>
</div>
<div class="address-name">{{ item.name }}</div>
<div class="address-mobile" @click="setMemberAddress(item.id)">{{ item.mobile }}</div>
<div class="address-desc" @click="setMemberAddress(item.id)">{{ item.full_address }} {{ item.address }}
</div>
</div>
</div>
<div v-if="memberAddress.length > 3 && !addressShow" @click="addressShow = true" class="el-button--text address-open">
<i class="el-icon-arrow-down"></i>
更多收货地址
</div>
<div class="clear"></div>
</div>
</div>
<!--收货地址添加-->
<el-dialog :title="addressForm.id == 0 ? '添加收货地址' : '编辑收货地址'" :visible.sync="dialogVisible" width="32%">
<el-form ref="form" :rules="addressRules" :model="addressForm" label-width="80px">
<el-form-item label="姓名" prop="name">
<el-input v-model="addressForm.name" placeholder="收货人姓名" />
</el-form-item>
<el-form-item label="手机" prop="mobile">
<el-input v-model="addressForm.mobile" maxlength="11" placeholder="收货人手机号" />
</el-form-item>
<el-form-item label="电话">
<el-input v-model="addressForm.telephone" placeholder="收货人固定电话(选填)" />
</el-form-item>
<el-form-item class="area" label="地区" prop="area">
<el-row :gutter="10">
<el-col :span="7">
<el-select prop="province" ref="province" v-model="addressForm.province_id" @change="getAddress(1)" placeholder="请选择省">
<el-option label="请选择省" value="0"></el-option>
<el-option v-for="item in pickerValueArray" :key="item.id" :label="item.name" :value="item.id"></el-option>
</el-select>
</el-col>
<el-col :span="7">
<el-select ref="city" prop="city" v-model="addressForm.city_id" @change="getAddress(2)" placeholder="请选择市">
<el-option label="请选择市" value="0"></el-option>
<el-option v-for="item in cityArr" :key="item.id" :label="item.name" :value="item.id"></el-option>
</el-select>
</el-col>
<el-col :span="7">
<el-select ref="district" prop="district" v-model="addressForm.district_id" placeholder="请选择区/县">
<el-option label="请选择区/县" value="0"></el-option>
<el-option v-for="item in districtArr" :key="item.id" :label="item.name" :value="item.id"></el-option>
</el-select>
</el-col>
</el-row>
</el-form-item>
<el-form-item label="详细地址" prop="address">
<el-input v-model="addressForm.address" placeholder="定位小区、街道、写字楼" />
</el-form-item>
</el-form>
<span slot="footer" class="dialog-footer">
<el-button @click="dialogVisible = false"> </el-button>
<el-button type="primary" @click="addmemberAddress('form')"> </el-button>
</span>
</el-dialog>
<!--使用余额-->
<div class="item-block" v-if="orderPaymentData.member_account.balance_total > 0 && balance_show == 1">
<div class="block-text">是否使用余额</div>
<div class="pay-type-list">
<div class="pay-type-item" :class="orderCreateData.is_balance ? '' : 'active'" @click="useBalance(0)">不使用余额</div>
<div class="pay-type-item" :class="orderCreateData.is_balance ? 'active' : ''" @click="useBalance(1)">使用余额</div>
<div class="clear"></div>
</div>
</div>
<!-- 支付密码 -->
<el-dialog title="使用余额" :visible.sync="dialogpay" width="350px">
<template v-if="orderPaymentData.member_account.is_pay_password == 0">
<p>为了您的账户安全,请您先设置的支付密码</p>
<p>可到"会员中心","账号安全","支付密码"中设置</p>
<span slot="footer" class="dialog-footer">
<el-button size="small" @click="dialogpay = false">暂不设置</el-button>
<el-button size="small" type="primary" @click="setPayPassword">立即设置</el-button>
</span>
</template>
<el-form v-else status-icon ref="ruleForm" label-width="100px">
<el-form-item label="支付密码" class="pay-password-item">
<!--添加一个不可见的input,欺骗浏览器自动填充-->
<el-input type="password" class="pay-password hide-password" :maxlength="6"></el-input>
<el-input type="password" class="pay-password" :maxlength="6" v-model="password" @input="input"></el-input>
</el-form-item>
<p class="ns-text-color forget-password" @click="setPayPassword">忘记密码</p>
</el-form>
</el-dialog>
<!-- 配送方式 -->
<div class="item-block padd-bom-20" v-if="orderPaymentData.delivery.express_type.length > 0">
<div class="block-text">
<span>配送方式</span>
<span class="distribution" v-if="orderCreateData.delivery.delivery_type == 'store'">{{ orderCreateData.delivery.store_name }}</span>
</div>
<div class="pay-type-item" v-for="(item, index) in orderPaymentData.delivery.express_type" :key="index" @click="selectDeliveryType(item)" :class="item.name == orderCreateData.delivery.delivery_type ? 'active' : ''">
{{ item.title }}
</div>
</div>
<!--配送方式 门店 -->
<el-dialog title="选择门店" :visible.sync="dialogStore" width="50%">
<el-table ref="singleTable" :data="storeList" highlight-current-row @row-click="selectStore" class="cursor-pointer">
<el-table-column label="" width="55">
<template slot-scope="scope">
<el-radio v-model="storeRadio" :label="scope.row"><i></i></el-radio>
</template>
</el-table-column>
<el-table-column prop="store_name" label="名称" width="160"></el-table-column>
<el-table-column prop="store_address" label="地址"></el-table-column>
<el-table-column prop="open_date" label="营业时间"></el-table-column>
</el-table>
</el-dialog>
<div class="item-block" v-if="orderPaymentData.invoice && orderPaymentData.invoice.invoice_status == 1">
<div class="block-text">发票信息</div>
<div class="pay-type-list">
<div class="pay-type-item" :class="orderCreateData.is_invoice == 0 ? 'active' : ''" @click="changeIsInvoice">无需发票</div>
<div class="pay-type-item" :class="orderCreateData.is_invoice == 1 ? 'active' : ''" @click="changeIsInvoice">需要发票</div>
<div class="clear"></div>
</div>
<div class="invoice-information" v-if="orderCreateData.is_invoice == 1">
<div class="invoice-title">
<div class="invoice-type-box invoice-title-box">
<span class="invoice-name">发票类型</span>
<label class="invoice-to-type">
<i class="invoice-i-input" :class="orderCreateData.invoice_type == 1 ? 'active' : ''" @click="clickType(1)"></i>
<span>纸质</span>
</label>
<label class="invoice-to-type">
<i class="invoice-i-input" :class="orderCreateData.invoice_type == 2 ? 'active' : ''" @click="clickType(2)"></i>
<span>电子</span>
</label>
</div>
<div class="invoice-type-box invoice-title-box">
<span class="invoice-name">抬头类型</span>
<label class="invoice-to-type">
<i class="invoice-i-input" :class="orderCreateData.invoice_title_type == 1 ? 'active' : ''" @click="clickTitleType(1)"></i>
<span>个人</span>
</label>
<label class="invoice-to-type">
<i class="invoice-i-input" :class="orderCreateData.invoice_title_type == 2 ? 'active' : ''" @click="clickTitleType(2)"></i>
<span>企业</span>
</label>
</div>
</div>
<div class="invoice-type-box">
<span class="invoice-name">发票信息</span>
<div class="invoice-box-form">
<input type="text" placeholder="请填写抬头名称" v-model.trim="orderCreateData.invoice_title" />
<input type="text" placeholder="请填写纳税人识别号" v-model.trim="orderCreateData.taxpayer_number" v-if="orderCreateData.invoice_title_type == 2" />
<input type="text" placeholder="请填写邮寄地址" v-model.trim="orderCreateData.invoice_full_address" v-show="orderCreateData.invoice_type == 1" />
<input type="text" placeholder="请填写邮箱" v-model.trim="orderCreateData.invoice_email" v-show="orderCreateData.invoice_type == 2" />
</div>
</div>
<div class="invoice-condition">
<span class="invoice-name">发票内容</span>
<div class="invoice-box-form">
<span class="option-item" :key="index" v-for="(item, index) in orderPaymentData.invoice.invoice_content_array" @click="changeInvoiceContent(item)" :class="{ 'color-base-bg active': item == orderCreateData.invoice_content }">
{{ item }}
</span>
</div>
</div>
<div class="invoice-tops">发票内容将以根据税法调整具体请以展示为准发票内容显示详细商品名 称及价格信息</div>
</div>
</div>
<!--商品信息-->
<div class="item-block">
<div class="goods-list">
<table>
<tr>
<td width="50%">商品</td>
<td width="12.5%">价格</td>
<td width="12.5%">数量</td>
<td width="12.5%">小计</td>
</tr>
</table>
</div>
</div>
<div>
<div class="item-block" v-if="calculateData">
<div class="goods-list">
<table>
<tr v-for="(goodsItem, goodsIndex) in calculateData.goods_list" :key="goodsIndex">
<td width="50%">
<div class="goods-info">
<div class="goods-info-left">
<router-link :to="{ path: '/sku/' + goodsItem.sku_id }" target="_blank">
<img class="goods-img" :src="$img(goodsItem.sku_image, { size: 'mid' })" @error="imageError(goodsIndex)" />
</router-link>
</div>
<div class="goods-info-right">
<router-link :to="{ path: '/sku/' + goodsItem.sku_id }" target="_blank">
<div class="goods-name">{{ goodsItem.goods_name }}</div>
</router-link>
<!-- 规格 -->
<div class="goods-spec" v-if="goodsItem.sku_spec_format">
<span v-for="(x, i) in goodsItem.sku_spec_format" :key="i">{{ x.spec_value_name }}</span>
</div>
</div>
</div>
</td>
<td width="12.5%" class="goods-price">{{ goodsItem.price }}</td>
<td width="12.5%" class="goods-num">{{ goodsItem.num }}</td>
<td width="12.5%" class="goods-money">{{ (goodsItem.price * goodsItem.num).toFixed(2) }}</td>
</tr>
</table>
</div>
</div>
</div>
<!-- 活动优惠 -->
<div class="item-block" v-if="promotionInfo">
<div class="block-text">{{ promotionInfo.title }}</div>
<div class="order-cell platform-coupon">
<div class="box ns-text-color" v-html="promotionInfo.content"></div>
</div>
</div>
<!-- 买家留言 -->
<div class="item-block padd-bom-10">
<div class="block-text">买家留言</div>
<el-input rows="3" type="textarea" placeholder="留言前建议先与商家协调一致" v-model="orderCreateData.buyer_message" class="buyer-message" @input="textarea" maxlength="140" show-word-limit resize="none" />
</div>
<!-- 总计 -->
<div class="item-block" v-if="calculateData">
<div class="order-statistics">
<table>
<tr>
<td align="right">商品金额</td>
<td align="left">{{ calculateData.goods_money | moneyFormat }}</td>
</tr>
<tr v-if="calculateData.is_virtual == 0 && calculateData.delivery_money > 0">
<td align="right">运费</td>
<td align="left">{{ calculateData.delivery_money | moneyFormat }}</td>
</tr>
<tr v-if="calculateData.invoice_money > 0">
<td align="right">发票税费<span class="ns-text-color">({{ calculateData.invoice.invoice_rate }}%)</span></td>
<td align="left">{{ calculateData.invoice_money | moneyFormat }}</td>
</tr>
<tr v-if="calculateData.invoice_delivery_money > 0">
<td align="right">发票邮寄费</td>
<td align="left">{{ calculateData.invoice_delivery_money | moneyFormat }}</td>
</tr>
<tr v-if="calculateData.promotion_money > 0">
<td align="right">优惠</td>
<td align="left">{{ calculateData.promotion_money | moneyFormat }}</td>
</tr>
<tr v-if="calculateData.balance_money > 0">
<td align="right">使用余额</td>
<td align="left">{{ calculateData.balance_money | moneyFormat }}</td>
</tr>
</table>
</div>
<div class="clear"></div>
</div>
<!--结算-->
<div class="item-block" v-if="calculateData">
<div class="order-submit">
<div class="order-money">
{{ calculateData.goods_num }}应付金额
<div class="ns-text-color">{{ calculateData.pay_money | moneyFormat }}</div>
</div>
<el-button type="primary" class="el-button--primary" @click="orderCreate">订单结算</el-button>
</div>
<div class="clear"></div>
</div>
</div>
</template>
<script>
import detail from '@/assets/js/promotion/payment_groupbuy.js';
export default {
name: 'groupbuy_payment',
mixins: [detail]
};
</script>
<style lang="scss" scoped>
@import '@/assets/css/promotion/payment_groupbuy.scss';
</style>

View File

@@ -0,0 +1,354 @@
<template>
<div class="goods-detail-wrap">
<div class="detail-nav-wrap" v-if="categoryNameArr">
<div class="detail-nav" v-if="categoryNameArr.length">
<template v-for="(item,index) in categoryNameArr" :keys="index">
<router-link :to="{ path: '/goods/list', query: { category_id: item.category_id, level: index } }">
{{item.name}}
</router-link>
<span class="iconfont icon-arrow-right"></span>
</template>
<span class="goods-name">{{goodsSkuDetail.goods_name}}</span>
</div>
</div>
<div class="detail-main">
<div class="goods-detail">
<div class="preview-wrap">
<div class="video-player-wrap" :class="{ show: switchMedia == 'video' }" v-if="goodsSkuDetail.video_url != ''">
<video-player v-if="goodsSkuDetail.video_url != ''" ref="videoPlayer" :playsinline="true"
:options="playerOptions" @play="onPlayerPlay($event)" @pause="onPlayerPause($event)"
@ended="onPlayerEnded($event)" @waiting="onPlayerWaiting($event)"
@playing="onPlayerPlaying($event)"
@loadeddata="onPlayerLoadeddata($event)" @timeupdate="onPlayerTimeupdate($event)"
@canplay="onPlayerCanplay($event)" @canplaythrough="onPlayerCanplaythrough($event)"
@statechanged="playerStateChanged($event)" @ready="playerReadied"></video-player>
<div class="media-mode" v-if="goodsSkuDetail.video_url != ''">
<span :class="{ 'ns-bg-color': switchMedia == 'video' }" @click="switchMedia = 'video'">视频</span>
<span :class="{ 'ns-bg-color': switchMedia == 'img' }" @click="switchMedia = 'img'">图片</span>
</div>
</div>
<div class="magnifier-wrap">
<pic-zoom ref="PicZoom" :url="$img(picZoomUrl)" :scale="2"></pic-zoom>
</div>
<div class="spec-items">
<span class="left-btn iconfont icon-weibiaoti35" :class="{ move: moveThumbLeft }" @click="changeThumbImg('prev')"></span>
<span class="right-btn iconfont icon-weibiaoti35" :class="{ move: moveThumbRight }" @click="changeThumbImg('next')"></span>
<ul :style="{ top: 42 + thumbPosition + 'px' }">
<!-- 商品缩率图 -->
<li v-for="(item, index) in goodsSkuDetail.sku_images" :key="index" @mousemove="picZoomUrl = item" :class="{ selected: picZoomUrl == item }">
<img :src="$img(item, { size: 'small' })" @error="imageErrorSpec(index)" />
</li>
</ul>
</div>
<!-- <div class="share-collect">
<div @click="editCollection">
<i class="iconfont" :class="whetherCollection == 1 ? 'iconlikefill ns-text-color' : 'iconlike'"></i>
<span data-collects="0">关注商品{{ goodsSkuDetail.collect_num }}</span>
</div>
<div v-if="kefuConfig.system == 0 && kefuConfig.open_pc == 1">
<i class="iconfont iconzhanghao"></i>
<span data-collects="0"><a :href="kefuConfig.open_url" target="_blank">联系客服</a></span>
</div>
<div @click="service_link" v-else-if="kefuConfig.system == 1">
<i class="iconfont iconzhanghao"></i>
<span data-collects="0">联系客服</span>
</div>
</div> -->
</div>
<!-- 商品信息 -->
<div class="basic-info-wrap" v-loading="loading">
<h1>{{ goodsSkuDetail.sku_name }}</h1>
<p class="desc ns-text-color" v-if="goodsSkuDetail.introduction">{{ goodsSkuDetail.introduction }}</p>
<div class="discount-banner ns-bg-color" v-if="seckillTimeMachine.currentTime">
<div class="activity-name"><i class="discount-icon iconfont iconicon_naozhong"></i><span>限时秒杀</span></div>
<div class="surplus-time">
<span>{{ seckillText }}</span>
<count-down class="count-down" v-on:start_callback="countDownS_cb()" v-on:end_callback="countDownE_cb()"
:currentTime="seckillTimeMachine.currentTime" :startTime="seckillTimeMachine.startTime"
:endTime="seckillTimeMachine.endTime" :dayTxt="'天'" :hourTxt="'小时'" :minutesTxt="'分钟'"
:secondsTxt="'秒'">
</count-down>
</div>
</div>
<div class="item-block">
<div class="promotion-price">
<dl class="item-line">
<dt class="ns-text-color-gray">秒杀价</dt>
<dd>
<em class="yuan ns-text-color">¥</em>
<span class="price ns-text-color">{{ goodsSkuDetail.seckill_price }}</span>
</dd>
</dl>
<dl class="item-line">
<dt class="ns-text-color-gray">原价</dt>
<dd>
<em class="market-yuan">¥</em>
<span class="market-price">{{ goodsSkuDetail.price }}</span>
</dd>
</dl>
<!-- <div class="statistical">
<ul>
<li>
<p>累计评价</p>
<span>{{ goodsSkuDetail.evaluate }}</span>
</li>
<li>
<p>累计销量</p>
<span>{{ goodsSkuDetail.sale_num }}{{ goodsSkuDetail.unit }}</span>
</li>
</ul>
</div> -->
<dl class="item-line" v-if="goodsSkuDetail.is_virtual == 0">
<dt>运费</dt>
<dd>
<i class="i-activity-flag ns-text-color ns-border-color" v-if="goodsSkuDetail.is_free_shipping">快递免邮</i>
<i class="i-activity-flag ns-text-color ns-border-color" v-else>快递不免邮</i>
</dd>
</dl>
</div>
</div>
<dl class="item-line delivery" v-if="goodsSkuDetail.is_virtual == 0">
<dt>配送至</dt>
<dd>
<div class="region-selected ns-border-color-gray">
<span>
<template v-if="selectedAddress['level_1']">
<template v-for="item in selectedAddress">{{ item.name }}</template>
</template>
<template v-else>请选择配送地址</template>
</span>
<i class="el-icon-arrow-down"></i>
</div>
<div class="region-list ns-border-color-gray" :class="{ hide: hideRegion }">
<ul class="nav-tabs">
<li :class="{ active: currTabAddres == 'province' }" @click="currTabAddres = 'province'">
<div>
<span>{{ selectedAddress['level_1'] ? selectedAddress['level_1'].name : '请选择省' }}</span>
<i class="el-icon-arrow-down"></i>
</div>
</li>
<li :class="{ active: currTabAddres == 'city' }" @click="currTabAddres = 'city'">
<div>
<span>{{ selectedAddress['level_2'] ? selectedAddress['level_2'].name : '请选择市' }}</span>
<i class="el-icon-arrow-down"></i>
</div>
</li>
<li :class="{ active: currTabAddres == 'district' }" @click="currTabAddres = 'district'">
<div>
<span>{{ selectedAddress['level_3'] ? selectedAddress['level_3'].name : '请选择区/县' }}</span>
<i class="el-icon-arrow-down"></i>
</div>
</li>
</ul>
<div class="tab-content">
<div class="tab-pane" :class="{ active: currTabAddres == 'province' }">
<ul class="province">
<li v-for="(item, index) in provinceArr" :key="index" :class="{ selected: selectedAddress['level_' + item.level] && selectedAddress['level_' + item.level].id == item.id }">
<span @click="getAddress('city', item)">{{ item.name }}</span>
</li>
</ul>
</div>
<div class="tab-pane" :class="{ active: currTabAddres == 'city' }">
<ul class="city">
<li v-for="(item, index) in cityArr" :key="index" :class="{ selected: selectedAddress['level_' + item.level] && selectedAddress['level_' + item.level].id == item.id }">
<span @click="getAddress('district', item)">{{ item.name }}</span>
</li>
</ul>
</div>
<div class="tab-pane" :class="{ active: currTabAddres == 'district' }">
<ul class="district">
<li v-for="(item, index) in districtArr" :key="index" :class="{ selected: selectedAddress['level_' + item.level] && selectedAddress['level_' + item.level].id == item.id }">
<span @click="getAddress('community', item)">{{ item.name }}</span>
</li>
</ul>
</div>
</div>
</div>
</dd>
</dl>
<dl class="item-line service">
<dt>服务</dt>
<dd>
<span>
<span class="ns-text-color">{{siteInfo.site_name}}</span>发货并提供售后服务
</span>
</dd>
</dl>
<hr class="divider" />
<div class="sku-list" v-if="goodsSkuDetail.goods_spec_format">
<dl class="item-line" v-for="(item, index) in goodsSkuDetail.goods_spec_format" :key="index">
<dt>{{ item.spec_name }}</dt>
<dd>
<ul>
<li v-for="(item_value, index_value) in item.value" :key="index_value">
<div :class="{ 'selected ns-border-color': item_value['selected'] || skuId == item_value.sku_id, disabled: item_value['disabled'] }" @click="changeSpec(item_value.sku_id, item_value.spec_id, item_value.disabled)">
<img v-if="item_value.image" :src="$img(item_value.image, { size: 'small' })" />
<span>{{ item_value.spec_value_name }}</span>
<i class="iconfont iconduigou1 ns-text-color"></i>
</div>
</li>
</ul>
</dd>
</dl>
</div>
<div class="buy-number">
<dl class="item-line">
<dt>数量</dt>
<dd>
<div class="num-wrap">
<div class="operation">
<span class="decrease el-icon-minus" @click="changeNum('-')"></span>
<el-input v-model="number" placeholder="0" @input="keyInput()"></el-input>
<span class="increase el-icon-plus" @click="changeNum('+')"></span>
</div>
</div>
<span class="unit">{{ goodsSkuDetail.unit }}</span>
<span class="inventory">库存{{ goodsSkuDetail.stock }}{{ goodsSkuDetail.unit }}</span>
</dd>
</dl>
</div>
<dl class="item-line buy-btn">
<dt></dt>
<dd v-if="goodsSkuDetail.goods_state == 1">
<template>
<el-button type="primary" plain @click="buyNow" v-if="goodsSkuDetail.stock > 0">立即抢购</el-button>
<el-button type="info" plain v-else disabled>库存不足</el-button>
</template>
<div class="go-phone icon-item" @click="editCollection">
<span :class="['iconfont',(whetherCollection == 1 ? 'icon-_shouzang2 selected' : 'icon-shouzang')]"></span>
<span>收藏</span>
</div>
</dd>
<dd v-else>
<template>
<el-button type="info" plain disabled>该商品已下架</el-button>
</template>
<div class="go-phone icon-item" @click="editCollection">
<span :class="['iconfont',(whetherCollection == 1 ? 'icon-_shouzang2 selected' : 'icon-shouzang')]"></span>
<span>收藏</span>
</div>
</dd>
</dl>
<dl class="item-line merchant-service" v-show="service_list.length">
<dt>商品服务</dt>
<div>
<dd v-for="item in service_list">
<i class="el-icon-success"></i>
<span class="ns-text-color-gray" :title="item.service_name">{{item.service_name}}</span>
</dd>
</div>
</dl>
</div>
<div class="detail-wrap">
<!-- <div class="goods-recommended">
<goods-recommend />
</div> -->
<el-tabs class="goods-tab" v-model="tabName" type="card" @tab-click="tabChange">
<el-tab-pane label="商品详情" name="detail">
<div v-html="goodsSkuDetail.goods_content"></div>
</el-tab-pane>
<el-tab-pane label="商品属性" name="attr">
<ul class="attr-list">
<template v-if="goodsSkuDetail.goods_attr_format && goodsSkuDetail.goods_attr_format.length > 0">
<li v-for="(item, index) in goodsSkuDetail.goods_attr_format" :key="index">
{{ item.attr_name }}{{ item.attr_value_name }}
</li>
</template>
</ul>
</el-tab-pane>
<el-tab-pane v-if="evaluate_show" :label="goodsEvaluateList.length ? '商品评价(' + goodsEvaluateList.length + ')' : '商品评价'" name="evaluate" class="evaluate">
<template v-if="goodsEvaluateList.length">
<nav>
<li :class="evaluaType == 0 ? 'selected' : ''" @click="evaluationType(0)">全部评价({{evaluteCount.total}})</li>
<li :class="evaluaType == 1 ? 'selected' : ''" @click="evaluationType(1)">好评({{evaluteCount.haoping}})</li>
<li :class="evaluaType == 2 ? 'selected' : ''" @click="evaluationType(2)">中评({{evaluteCount.zhongping}})</li>
<li :class="evaluaType == 3 ? 'selected' : ''" @click="evaluationType(3)">差评({{evaluteCount.chaping}})</li>
</nav>
<ul class="list">
<li v-for="(item, index) in goodsEvaluateList" :key="index">
<div class="member-info">
<img :src="$img(item.member_headimg)" @error="imageErrorEvaluate(index)" class="avatar" />
<span>{{ item.member_name }}</span>
</div>
<div class="info-wrap">
<el-rate v-model="item.star" disabled></el-rate>
<p class="content">{{ item.content }}</p>
<div class="img-list" v-if="item.images">
<el-image v-for="(img, img_index) in item.images" :key="img_index" :src="$img(img)" :preview-src-list="item.imagesFormat"/>
</div>
<div class="sku-info">
<span>{{ item.sku_name }}</span>
<span class="create-time">{{ $util.timeStampTurnTime(item.create_time) }}</span>
</div>
<div class="evaluation-reply" v-if="item.explain_first != ''">店家回复{{ item.explain_first }}</div>
<template v-if="item.again_content != ''">
<div class="review-evaluation">
<span>追加评价</span>
<span class="review-time">{{ $util.timeStampTurnTime(item.again_time) }}</span>
</div>
<p class="content">{{ item.again_content }}</p>
<div class="img-list">
<el-image v-for="(again_img, again_index) in item.again_images" :key="again_index" :src="$img(again_img)" :preview-src-list="item.againImagesFormat"/>
</div>
<div class="evaluation-reply" v-if="item.again_explain != ''">店家回复{{ item.again_explain }}
</div>
</template>
</div>
</li>
</ul>
<div class="pager">
<el-pagination background :pager-count="5" :total="total" prev-text="上一页" next-text="下一页"
:current-page.sync="currentPage" :page-size.sync="pageSize"
@size-change="handlePageSizeChange"
@current-change="handleCurrentPageChange" hide-on-single-page></el-pagination>
</div>
</template>
<div class="empty" v-else>该商品暂无评价哦</div>
</el-tab-pane>
<template v-if="service">
<el-tab-pane v-if="service.is_display == 1" label="售后保障" name="after_sale" class="after-sale">
<div v-html="service.content"></div>
</el-tab-pane>
</template>
</el-tabs>
</div>
<!--联系客服弹窗-->
<servicerMessage ref="servicerMessage" class="kefu" :shop="{shop_id:shopInfo.site_id,logo:shopInfo.logo,shop_name:shopInfo.site_name}"></servicerMessage>
</div>
</div>
</div>
</template>
<script>
import PicZoom from "vue-piczoom"
import detail from "@/assets/js/promotion/detail_seckill.js"
import GoodsRecommend from "@/components/GoodsRecommend"
import servicerMessage from "@/components/message/servicerMessage";
export default {
name: "seckill_detail",
components: {
PicZoom,
GoodsRecommend,
servicerMessage
},
mixins: [detail]
}
</script>
<style lang="scss">
@import "@/assets/css/promotion/detail_seckill.scss";
</style>

View File

@@ -0,0 +1,151 @@
<template>
<div class="ns-seckill">
<div class="ns-seckill-head" v-loading="loadingAd">
<el-carousel height="420px" v-if="adList.length" indicator-position="none">
<el-carousel-item v-for="item in adList" :key="item.adv_id">
<el-image :src="$img(item.adv_image)" @click="$util.pushToTab(item.adv_url.url)" />
</el-carousel-item>
</el-carousel>
<div class="ns-seckill-time-box" v-if="timeList.length > 0">
<span v-if="timeList.length > 4" class="left-btn el-icon-arrow-left" @click="changeThumbImg('prev')"></span>
<span v-if="timeList.length > 4" class="right-btn el-icon-arrow-right" @click="changeThumbImg('next')"></span>
<div class="ns-seckill-time-list" ref="seckillTime">
<ul class="seckill-time-ul" :style="{ left: thumbPosition + 'px' }">
<!-- 商品缩率图 -->
<li v-for="(item, key) in timeList" :key="key" slot="label" class="seckill-time-li" :class="{ 'selected-tab': seckillId == item.id }" @click="handleSelected(key, item)">
<div>{{ item.seckill_start_time_show + " - " + item.seckill_end_time_show }}</div>
<div v-if="item.type == 'today'">
<p class="em font-size-tag " v-if="!item.isNow">即将开始</p>
<p class="em font-size-tag " v-else-if="item.isNow">抢购中</p>
</div>
<div v-else>
<p>敬请期待</p>
</div>
</li>
</ul>
</div>
</div>
</div>
<!-- 商品列表 -->
<div class="ns-seckill-box" v-loading="loading" ref="seckillGoods" v-if="timeList.length > 0 && goodsList.length > 0">
<div class="ns-seckill-title">
<div class="seckill-title-left">
<span class="name">限时秒杀</span>
<span class="desc">限时秒杀每款限购一件</span>
</div>
<div class="ns-seckill-right" v-show="seckillIndex == index && isTrue && isNoClick == false">
<span>{{ seckillText }}</span>
<count-down class="count-down" v-on:start_callback="countDownS_cb()" v-on:end_callback="countDownE_cb()"
:currentTime="seckillTimeMachine.currentTime" :startTime="seckillTimeMachine.startTime"
:endTime="seckillTimeMachine.endTime" :dayTxt="''" :hourTxt="''" :minutesTxt="''"
:secondsTxt="''">
</count-down>
</div>
</div>
<div>
<div class="goods-list">
<div class="goods" v-for="(item, key) in goodsList" :key="key" @click="toGoodsDetail(item.id)">
<div class="img">
<el-image fit="scale-down" :src="$img(item.goods_image, { size: 'mid' })" lazy @error="imageError(index)"/>
</div>
<div class="name">
<p :title="item.goods_name">{{ item.goods_name }}</p>
</div>
<!-- 价格展示区 -->
<div class="price">
<div class="curr-price">
<span>秒杀价</span>
<span></span>
<span class="main_price">{{ item.seckill_price }}</span>
</div>
<span class="primary_price">{{ item.price }}</span>
</div>
<el-button v-if="seckillIndex == index && timeList[index].isNow && shouType == true">立即抢购</el-button>
</div>
</div>
</div>
<div class="pager">
<el-pagination background :pager-count="5" :total="total" prev-text="上一页" next-text="下一页"
:current-page.sync="currentPage" :page-size.sync="pageSize" @size-change="handlePageSizeChange"
@current-change="handleCurrentPageChange" hide-on-single-page></el-pagination>
</div>
</div>
<div class="empty-wrap" v-else-if="!loading">
<img src="~assets/images/goods_empty.png">
<span>暂无正在进行秒杀的商品<router-link to="/" class="ns-text-color">去首页</router-link>看看吧</span>
</div>
</div>
</template>
<script>
import list from "@/assets/js/promotion/list_seckill.js"
export default {
name: "seckill",
components: {},
mixins: [list]
}
</script>
<style lang="scss" scoped>
@import "@/assets/css/promotion/list_seckill.scss";
</style>
<style lang="scss">
.seckill-time {
.el-tabs__nav-wrap {
height: 56px;
.el-tabs__nav {
height: 56px;
}
.el-tabs__nav-next,
.el-tabs__nav-prev {
line-height: 56px;
}
.el-tabs__item {
width: 150px;
height: 56px;
padding: 0;
}
}
.el-tabs__nav-wrap::after {
height: 0;
}
}
.ns-seckill {
.el-carousel {
.el-image__inner {
width: auto;
}
}
.el-carousel__arrow--right {
right: 60px;
}
.count-down {
span {
display: inline-block;
width: 32px;
height: 32px;
line-height: 32px;
text-align: center;
background: #383838;
color: #fff;
border-radius: 6px;
font-size: 20px;
}
}
}
</style>

View File

@@ -0,0 +1,327 @@
<template>
<div class="payment-wrap" v-loading="fullscreenLoading">
<!--购买虚拟类商品需填写您的手机号-->
<div class="item-block" v-if="orderPaymentData.is_virtual == 1">
<div class="block-text">购买虚拟类商品需填写您的手机号以方便商家与您联系</div>
<el-form ref="form" size="mini" class="mobile-wrap" label-width="80px">
<el-form-item label="手机号码">
<el-input placeholder="请输入您的手机号码" maxlength="11" v-model="orderCreateData.member_address.mobile" />
</el-form-item>
</el-form>
</div>
<!--收货地址-->
<div class="item-block" v-if="orderPaymentData.is_virtual == 0">
<div class="block-text">收货地址</div>
<div class="address-list">
<div class="address-item" @click="addAddressShow">
<div class="add-address">
<i class="el-icon-circle-plus-outline"></i>
添加收货地址
</div>
</div>
<div class="address-item" v-for="(item, key) in memberAddress" :key="item.id" :class="addressId == item.id ? 'active' : ''" v-if="key < 3 || (addressShow && key >= 3)">
<div class="address-info">
<div class="options">
<div @click="editAddress(item.id)">编辑</div>
<template v-if="item.is_default == 0">
<el-popconfirm title="确定要删除该地址吗?" @onConfirm="deleteMemberAddress(item.id)">
<div slot="reference">删除</div>
</el-popconfirm>
</template>
</div>
<div class="address-name">{{ item.name }}</div>
<div class="address-mobile" @click="setMemberAddress(item.id)">{{ item.mobile }}</div>
<div class="address-desc" @click="setMemberAddress(item.id)">{{ item.full_address }} {{ item.address }}
</div>
</div>
</div>
<div v-if="memberAddress.length > 3 && !addressShow" @click="addressShow = true" class="el-button--text address-open">
<i class="el-icon-arrow-down"></i>
更多收货地址
</div>
<div class="clear"></div>
</div>
</div>
<!--收货地址添加-->
<el-dialog :title="addressForm.id == 0 ? '添加收货地址' : '编辑收货地址'" :visible.sync="dialogVisible" width="32%">
<el-form ref="form" :rules="addressRules" :model="addressForm" label-width="80px">
<el-form-item label="姓名" prop="name">
<el-input v-model="addressForm.name" placeholder="收货人姓名" />
</el-form-item>
<el-form-item label="手机" prop="mobile">
<el-input v-model="addressForm.mobile" maxlength="11" placeholder="收货人手机号" />
</el-form-item>
<el-form-item label="电话">
<el-input v-model="addressForm.telephone" placeholder="收货人固定电话(选填)" />
</el-form-item>
<el-form-item class="area" label="地区" prop="area">
<el-row :gutter="10">
<el-col :span="7">
<el-select prop="province" ref="province" v-model="addressForm.province_id" @change="getAddress(1)" placeholder="请选择省">
<el-option label="请选择省" value="0"></el-option>
<el-option v-for="item in pickerValueArray" :key="item.id" :label="item.name" :value="item.id"></el-option>
</el-select>
</el-col>
<el-col :span="7">
<el-select ref="city" prop="city" v-model="addressForm.city_id" @change="getAddress(2)" placeholder="请选择市">
<el-option label="请选择市" value="0"></el-option>
<el-option v-for="item in cityArr" :key="item.id" :label="item.name" :value="item.id"></el-option>
</el-select>
</el-col>
<el-col :span="7">
<el-select ref="district" prop="district" v-model="addressForm.district_id" placeholder="请选择区/县">
<el-option label="请选择区/县" value="0"></el-option>
<el-option v-for="item in districtArr" :key="item.id" :label="item.name" :value="item.id"></el-option>
</el-select>
</el-col>
</el-row>
</el-form-item>
<el-form-item label="详细地址" prop="address">
<el-input v-model="addressForm.address" placeholder="定位小区、街道、写字楼" />
</el-form-item>
</el-form>
<span slot="footer" class="dialog-footer">
<el-button @click="dialogVisible = false"> </el-button>
<el-button type="primary" @click="addmemberAddress('form')"> </el-button>
</span>
</el-dialog>
<!--使用余额-->
<div class="item-block" v-if="orderPaymentData.member_account.balance_total > 0 && balance_show == 1">
<div class="block-text">是否使用余额</div>
<div class="pay-type-list">
<div class="pay-type-item" :class="orderCreateData.is_balance ? '' : 'active'" @click="useBalance(0)">不使用余额
</div>
<div class="pay-type-item" :class="orderCreateData.is_balance ? 'active' : ''" @click="useBalance(1)">使用余额</div>
<div class="clear"></div>
</div>
</div>
<!-- 支付密码 -->
<el-dialog title="使用余额" :visible.sync="dialogpay" width="350px">
<template v-if="orderPaymentData.member_account.is_pay_password == 0">
<p>为了您的账户安全,请您先设置的支付密码</p>
<p>可到"会员中心","账号安全","支付密码"中设置</p>
<span slot="footer" class="dialog-footer">
<el-button size="small" @click="dialogpay = false">暂不设置</el-button>
<el-button size="small" type="primary" @click="setPayPassword">立即设置</el-button>
</span>
</template>
<el-form v-else status-icon ref="ruleForm" label-width="100px">
<el-form-item label="支付密码" class="pay-password-item">
<!--添加一个不可见的input,欺骗浏览器自动填充-->
<el-input type="password" class="pay-password hide-password" :maxlength="6"></el-input>
<el-input type="password" class="pay-password" :maxlength="6" v-model="password" @input="input"></el-input>
</el-form-item>
<p class="ns-text-color forget-password" @click="setPayPassword">忘记密码</p>
</el-form>
</el-dialog>
<!-- 配送方式 -->
<div class="item-block padd-bom-20" v-if="orderPaymentData.delivery.express_type.length > 0">
<div class="block-text">
<span>配送方式</span>
<span class="distribution" v-if="orderCreateData.delivery.delivery_type == 'store'">{{ orderCreateData.delivery.store_name }}</span>
</div>
<div class="pay-type-item" v-for="(item, index) in orderPaymentData.delivery.express_type" :key="index" @click="selectDeliveryType(item)" :class="item.name == orderCreateData.delivery.delivery_type ? 'active' : ''">
{{ item.title }}
</div>
</div>
<!--配送方式 门店 -->
<el-dialog title="选择门店" :visible.sync="dialogStore" width="50%">
<el-table ref="singleTable" :data="storeList" highlight-current-row @row-click="selectStore" class="cursor-pointer">
<el-table-column label="" width="55">
<template slot-scope="scope">
<el-radio v-model="storeRadio" :label="scope.row"><i></i></el-radio>
</template>
</el-table-column>
<el-table-column prop="store_name" label="名称" width="160"></el-table-column>
<el-table-column prop="store_address" label="地址"></el-table-column>
<el-table-column prop="open_date" label="营业时间"></el-table-column>
</el-table>
</el-dialog>
<div class="item-block" v-if="orderPaymentData.invoice">
<div class="block-text">发票信息</div>
<div class="pay-type-list">
<div class="pay-type-item" :class="orderCreateData.is_invoice == 0 ? 'active' : ''" @click="changeIsInvoice">无需发票</div>
<div class="pay-type-item" :class="orderCreateData.is_invoice == 1 ? 'active' : ''" @click="changeIsInvoice">需要发票</div>
<div class="clear"></div>
</div>
<div class="invoice-information" v-if="orderCreateData.is_invoice == 1">
<div class="invoice-title">
<div class="invoice-type-box invoice-title-box">
<span class="invoice-name">发票类型</span>
<label class="invoice-to-type">
<i class="invoice-i-input" :class="orderCreateData.invoice_type == 1 ? 'active' : ''" @click="clickType(1)"></i>
<span>纸质</span>
</label>
<label class="invoice-to-type">
<i class="invoice-i-input" :class="orderCreateData.invoice_type == 2 ? 'active' : ''" @click="clickType(2)"></i>
<span>电子</span>
</label>
</div>
<div class="invoice-type-box invoice-title-box">
<span class="invoice-name">抬头类型</span>
<label class="invoice-to-type">
<i class="invoice-i-input" :class="orderCreateData.invoice_title_type == 1 ? 'active' : ''" @click="clickTitleType(1)"></i>
<span>个人</span>
</label>
<label class="invoice-to-type">
<i class="invoice-i-input" :class="orderCreateData.invoice_title_type == 2 ? 'active' : ''" @click="clickTitleType(2)"></i>
<span>企业</span>
</label>
</div>
</div>
<div class="invoice-type-box">
<span class="invoice-name">发票信息</span>
<div class="invoice-box-form">
<input type="text" placeholder="请填写抬头名称" v-model.trim="orderCreateData.invoice_title" />
<input type="text" placeholder="请填写纳税人识别号" v-model.trim="orderCreateData.taxpayer_number" v-if="orderCreateData.invoice_title_type == 2" />
<input type="text" placeholder="请填写邮寄地址" v-model.trim="orderCreateData.invoice_full_address" v-show="orderCreateData.invoice_type == 1" />
<input type="text" placeholder="请填写邮箱" v-model.trim="orderCreateData.invoice_email" v-show="orderCreateData.invoice_type == 2" />
</div>
</div>
<div class="invoice-condition">
<span class="invoice-name">发票内容</span>
<div class="invoice-box-form">
<span class="option-item" :key="index" v-for="(item, index) in orderPaymentData.invoice.invoice_content_array" @click="changeInvoiceContent(item)" :class="{ 'color-base-bg active': item == orderCreateData.invoice_content }">
{{ item }}
</span>
</div>
</div>
<div class="invoice-tops">发票内容将以根据税法调整具体请以展示为准发票内容显示详细商品名 称及价格信息</div>
</div>
</div>
<!--商品信息-->
<div class="item-block">
<div class="goods-list">
<table>
<tr>
<td width="50%">商品</td>
<td width="12.5%">价格</td>
<td width="12.5%">数量</td>
<td width="12.5%">小计</td>
</tr>
</table>
</div>
</div>
<div>
<div class="item-block" v-if="calculateData">
<div class="goods-list">
<table>
<tr v-for="(goodsItem, goodsIndex) in calculateData.goods_list" :key="goodsIndex">
<td width="50%">
<div class="goods-info">
<div class="goods-info-left">
<router-link :to="{ path: '/sku/' + goodsItem.sku_id }" target="_blank">
<img class="goods-img" :src="$img(goodsItem.sku_image, { size: 'mid' })" @error="imageError(goodsIndex)" />
</router-link>
</div>
<div class="goods-info-right">
<router-link :to="{ path: '/sku/' + goodsItem.sku_id }" target="_blank">
<div class="goods-name">{{ goodsItem.goods_name }}</div>
</router-link>
<!-- 规格 -->
<div class="goods-spec" v-if="goodsItem.sku_spec_format">
<span v-for="(x, i) in goodsItem.sku_spec_format" :key="i">{{ x.spec_value_name }}</span>
</div>
</div>
</div>
</td>
<td width="12.5%" class="goods-price">{{ goodsItem.price }}</td>
<td width="12.5%" class="goods-num">{{ goodsItem.num }}</td>
<td width="12.5%" class="goods-money">{{ (goodsItem.price * goodsItem.num).toFixed(2) }}</td>
</tr>
</table>
</div>
</div>
</div>
<!-- 活动优惠 -->
<div class="item-block" v-if="promotionInfo">
<div class="block-text">{{ promotionInfo.title }}</div>
<div class="order-cell platform-coupon">
<div class="box ns-text-color" v-html="promotionInfo.content"></div>
</div>
</div>
<!-- 买家留言 -->
<div class="item-block padd-bom-10">
<div class="block-text">买家留言</div>
<el-input rows="3" type="textarea" placeholder="留言前建议先与商家协调一致" v-model="orderCreateData.buyer_message" class="buyer-message" @input="textarea" maxlength="140" show-word-limit resize="none" />
</div>
<!-- 总计 -->
<div class="item-block" v-if="calculateData">
<div class="order-statistics">
<table>
<tr>
<td align="right">商品金额</td>
<td align="left">{{ calculateData.goods_money | moneyFormat }}</td>
</tr>
<tr v-if="calculateData.is_virtual == 0 && calculateData.delivery_money > 0">
<td align="right">运费</td>
<td align="left">{{ calculateData.delivery_money | moneyFormat }}</td>
</tr>
<tr v-if="calculateData.invoice_money > 0">
<td align="right">发票税费<span class="ns-text-color">({{ calculateData.invoice.invoice_rate }}%)</span></td>
<td align="left">{{ calculateData.invoice_money | moneyFormat }}</td>
</tr>
<tr v-if="calculateData.invoice_delivery_money > 0">
<td align="right">发票邮寄费</td>
<td align="left">{{ calculateData.invoice_delivery_money | moneyFormat }}</td>
</tr>
<tr v-if="calculateData.promotion_money > 0">
<td align="right">优惠</td>
<td align="left">{{ calculateData.promotion_money | moneyFormat }}</td>
</tr>
<tr v-if="calculateData.balance_money > 0">
<td align="right">使用余额</td>
<td align="left">{{ calculateData.balance_money | moneyFormat }}</td>
</tr>
</table>
</div>
<div class="clear"></div>
</div>
<!--结算-->
<div class="item-block" v-if="calculateData">
<div class="order-submit">
<div class="order-money">
{{ calculateData.goods_num }}应付金额
<div class="ns-text-color">{{ calculateData.pay_money | moneyFormat }}</div>
</div>
<el-button type="primary" class="el-button--primary" @click="orderCreate">订单结算</el-button>
</div>
<div class="clear"></div>
</div>
</div>
</template>
<script>
import detail from '@/assets/js/promotion/payment_seckill.js';
export default {
name: 'seckill_payment',
mixins: [detail]
};
</script>
<style lang="scss" scoped>
@import '@/assets/css/promotion/payment_seckill.scss';
</style>

View File

@@ -0,0 +1,511 @@
<template>
<div class="goods-detail-wrap">
<div class="detail-nav-wrap" v-if="categoryNameArr">
<div class="detail-nav" v-if="categoryNameArr.length">
<template v-for="(item, index) in categoryNameArr" :keys="index">
<router-link :to="{ path: '/goods/list', query: { category_id: item.category_id, level: index } }">{{ item.name }}
</router-link>
<span class="iconfont icon-arrow-right"></span>
</template>
<span class="goods-name">{{ goodsSkuDetail.goods_name }}</span>
</div>
</div>
<div class="detail-main">
<div class="goods-detail">
<div class="preview-wrap">
<div class="video-player-wrap" :class="{ show: switchMedia == 'video' }" v-if="goodsSkuDetail.video_url != ''">
<client-only>
<video-player
v-if="goodsSkuDetail.video_url != ''"
ref="videoPlayer"
:playsinline="true"
:options="playerOptions"
@play="onPlayerPlay($event)"
@pause="onPlayerPause($event)"
@ended="onPlayerEnded($event)"
@waiting="onPlayerWaiting($event)"
@playing="onPlayerPlaying($event)"
@loadeddata="onPlayerLoadeddata($event)"
@timeupdate="onPlayerTimeupdate($event)"
@canplay="onPlayerCanplay($event)"
@canplaythrough="onPlayerCanplaythrough($event)"
@statechanged="playerStateChanged($event)"
@ready="playerReadied"
></video-player>
</client-only>
<div class="media-mode" v-if="goodsSkuDetail.video_url != ''">
<span :class="{ 'ns-bg-color': switchMedia == 'video' }" @click="switchMedia = 'video'">视频</span>
<span :class="{ 'ns-bg-color': switchMedia == 'img' }" @click="switchMedia = 'img'">图片</span>
</div>
</div>
<!-- , { size: 'big' } -->
<div class="magnifier-wrap">
<pic-zoom ref="PicZoom" :url="$img(picZoomUrl)" :scale="2"></pic-zoom>
</div>
<div class="spec-items">
<span class="left-btn iconfont icon-weibiaoti35" :class="{ move: moveThumbLeft }" @click="changeThumbImg('prev')"></span>
<span class="right-btn iconfont icon-weibiaoti35" :class="{ move: moveThumbRight }" @click="changeThumbImg('next')"></span>
<ul :style="{ top: 42 + thumbPosition + 'px' }">
<!-- 商品缩率图 -->
<li v-for="(item, index) in goodsSkuDetail.sku_images" :key="index" @mousemove="picZoomUrl = item" :class="{ selected: picZoomUrl == item }">
<img :src="$img(item, { size: 'small' })" @error="imageErrorSpec(index)" />
</li>
</ul>
</div>
<!-- <div class="share-collect">
<div @click="editCollection">
<i class="iconfont" :class="whetherCollection == 1 ? 'iconlikefill ns-text-color' : 'iconlike'"></i>
<span data-collects="0">关注商品{{ goodsSkuDetail.collect_num }}</span>
</div>
<div v-if="kefuConfig.system == 0 && kefuConfig.open_pc == 1">
<i class="iconfont icon-zhanghao"></i>
<span data-collects="0"><a :href="kefuConfig.open_url" target="_blank">联系客服</a></span>
</div>
<div @click="service_link" v-else-if="kefuConfig.system == 1">
<i class="iconfont icon-zhanghao"></i>
<span data-collects="0">联系客服</span>
</div>
</div> -->
</div>
<!-- 商品信息 -->
<div class="basic-info-wrap" v-loading="loading">
<h1>{{ goodsSkuDetail.goods_name }}</h1>
<p class="desc" v-if="goodsSkuDetail.introduction">{{ goodsSkuDetail.introduction }}</p>
<div class="discount-banner ns-bg-color" v-if="goodsSkuDetail.promotion_type == 1 && discountTimeMachine.currentTime && addonIsExit.discount">
<div class="activity-name">
<i class="discount-icon iconfont icon-icon_naozhong"></i>
<span>限时折扣</span>
</div>
<div class="surplus-time">
<span>{{ discountText }}</span>
<count-down
class="count-down"
v-on:start_callback="countDownS_cb()"
v-on:end_callback="countDownE_cb()"
:currentTime="discountTimeMachine.currentTime"
:startTime="discountTimeMachine.startTime"
:endTime="discountTimeMachine.endTime"
:dayTxt="'天'"
:hourTxt="'小时'"
:minutesTxt="'分钟'"
:secondsTxt="'秒'"
></count-down>
<!-- :tipText="'距离开始文字1'"
:tipTextEnd="'距离结束文字1'"
:endText="'结束自定义文字2'"-->
</div>
</div>
<div class="item-block">
<div class="promotion-price">
<dl class="item-line">
<dt class="ns-text-color-gray">销售价</dt>
<dd>
<em class="yuan ns-text-color">¥</em>
<span class="price ns-text-color">{{ goodsSkuDetail.discount_price }}</span>
</dd>
</dl>
<dl class="item-line" v-if="goodsSkuDetail.promotion_type == 1 && discountTimeMachine.currentTime">
<dt class="ns-text-color-gray">原价</dt>
<dd>
<em class="market-yuan">¥</em>
<span class="market-price">{{ goodsSkuDetail.price }}</span>
</dd>
</dl>
<dl class="item-line" v-if="goodsSkuDetail.member_price > 0">
<dt class="ns-text-color-gray">会员价</dt>
<dd>
<em class="market-yuan">¥</em>
<span class="member_price">{{ goodsSkuDetail.member_price }}</span>
</dd>
</dl>
<dl class="item-line" v-if="goodsSkuDetail.market_price > 0">
<dt class="ns-text-color-gray">市场价</dt>
<dd>
<em class="market-yuan">¥</em>
<span class="market-price">{{ goodsSkuDetail.market_price }}</span>
</dd>
</dl>
<!-- <div class="statistical">
<ul>
<li>
<p>累计评价</p>
<span>{{ goodsSkuDetail.evaluate }}</span>
</li>
<li>
<p>累计销量</p>
<span>{{ goodsSkuDetail.sale_num }}{{ goodsSkuDetail.unit }}</span>
</li>
</ul>
</div> -->
<dl class="item-line coupon-list" v-if="addonIsExit.coupon && couponList.length">
<dt class="ns-text-color-gray">优惠券</dt>
<div>
<dd>
<p v-for="(item, index) in couponList" :key="index" class="ns-text-color" @click="receiveCoupon(item.coupon_type_id)">
<span class="ns-border-color" v-if="item.type == 'discount'">{{ item.discount }}</span>
<span class="ns-border-color" v-if="item.type == 'reward'">{{ item.money }}</span>
</p>
</dd>
</div>
</dl>
<dl class="item-line manjian" v-if="manjian.manjian" style="align-items: top;">
<dt>满减</dt>
<dd>
<i class="i-activity-flag ns-text-color ns-border-color">{{ manjian.manjian_name }}</i>
<span>{{ manjian.manjian }}</span>
<!-- <view class="item" v-if="manjian.manjian != undefined" style="display: flex;">
<view class="free-tip color-base-text color-base-border">满减</view>
<text class="font-size-base">{{ manjian.manjian }}</text>
</view> -->
</dd>
</dl>
<dl class="item-line mansong" v-if="manjian.mansong != undefined">
<dt>满送</dt>
<dd>
<i class="i-activity-flag ns-text-color ns-border-color" style="height: 14px;line-height: 14px;margin-top: 5px;">{{ manjian.manjian_name }}</i>
<span>{{ manjian.mansong }}</span>
</dd>
</dl>
<dl class="item-line" v-if="manjian.free_shipping != undefined">
<dt>包邮</dt>
<dd>
<i class="i-activity-flag ns-text-color ns-border-color">{{ manjian.free_shipping}}</i>
</dd>
</dl>
<!-- <div class="manjian-box">
<dl class="item-line manjian manjian-hide" v-if="addonIsExit.manjian && manjian.manjian_name">
<dt>满减</dt>
<dd>
<i class="i-activity-flag ns-text-color ns-border-color">{{ manjian.manjian_name }}</i>
<span v-if="manjian.manjian"><i class="i-activity-flag ns-text-color ns-border-color">满减</i></span>
<span v-if="manjian.mansong"><i class="i-activity-flag ns-text-color ns-border-color">满送</i></span>
<span v-if="manjian.free_shipping"><i class="i-activity-flag ns-text-color ns-border-color">包邮</i></span>
</dd>
<span class="manjian-open">展开促销<i class="el-icon-arrow-down"></i></span>
</dl>
<dl class="item-line manjian manjian-show" v-if="addonIsExit.manjian && manjian.manjian_name">
<dt>满减</dt>
<dd>
<span v-if="manjian.manjian"><i class="i-activity-flag ns-text-color ns-border-color">满减</i>{{ manjian.manjian }}</span></br>
<span v-if="manjian.mansong"><i class="i-activity-flag ns-text-color ns-border-color">满送</i>{{ manjian.mansong }}</span></br>
<span v-if="manjian.free_shipping"><i class="i-activity-flag ns-text-color ns-border-color">包邮</i>{{ manjian.free_shipping }}</span>
</dd>
</dl>
</div> -->
</div>
</div>
<!-- <dl class="item-line" v-if="goodsSkuDetail.is_virtual == 0">
<dt>运费</dt>
<dd>
<i class="i-activity-flag ns-text-color ns-border-color" v-if="goodsSkuDetail.is_free_shipping">快递免邮</i>
<i class="i-activity-flag ns-text-color ns-border-color" v-else>快递不免邮</i>
</dd>
</dl> -->
<dl class="item-line delivery" v-if="goodsSkuDetail.is_virtual == 0">
<dt>配送至</dt>
<dd>
<div class="region-selected ns-border-color-gray">
<span>
<template v-if="selectedAddress['level_1']">
<template v-for="item in selectedAddress">
{{ item.name }}
</template>
</template>
<template v-else>
请选择配送地址
</template>
</span>
<i class="el-icon-arrow-down"></i>
</div>
<div class="region-list ns-border-color-gray" :class="{ hide: hideRegion }">
<ul class="nav-tabs">
<li :class="{ active: currTabAddres == 'province' }" @click="currTabAddres = 'province'">
<div>
<span>{{ selectedAddress['level_1'] ? selectedAddress['level_1'].name : '请选择省' }}</span>
<i class="el-icon-arrow-down"></i>
</div>
</li>
<li :class="{ active: currTabAddres == 'city' }" @click="currTabAddres = 'city'">
<div>
<span>{{ selectedAddress['level_2'] ? selectedAddress['level_2'].name : '请选择市' }}</span>
<i class="el-icon-arrow-down"></i>
</div>
</li>
<li :class="{ active: currTabAddres == 'district' }" @click="currTabAddres = 'district'">
<div>
<span>{{ selectedAddress['level_3'] ? selectedAddress['level_3'].name : '请选择区/县' }}</span>
<i class="el-icon-arrow-down"></i>
</div>
</li>
</ul>
<div class="tab-content">
<div class="tab-pane" :class="{ active: currTabAddres == 'province' }">
<ul class="province">
<li v-for="(item, index) in provinceArr" :key="index" :class="{ selected: selectedAddress['level_' + item.level] && selectedAddress['level_' + item.level].id == item.id }">
<span @click="getAddress('city', item)">{{ item.name }}</span>
</li>
</ul>
</div>
<div class="tab-pane" :class="{ active: currTabAddres == 'city' }">
<ul class="city">
<li v-for="(item, index) in cityArr" :key="index" :class="{ selected: selectedAddress['level_' + item.level] && selectedAddress['level_' + item.level].id == item.id }">
<span @click="getAddress('district', item)">{{ item.name }}</span>
</li>
</ul>
</div>
<div class="tab-pane" :class="{ active: currTabAddres == 'district' }">
<ul class="district">
<li v-for="(item, index) in districtArr" :key="index" :class="{ selected: selectedAddress['level_' + item.level] && selectedAddress['level_' + item.level].id == item.id }">
<span @click="getAddress('community', item)">{{ item.name }}</span>
</li>
</ul>
</div>
</div>
</div>
</dd>
</dl>
<dl class="item-line service">
<dt>服务</dt>
<dd>
<span>
<span class="ns-text-color">{{ siteInfo.site_name }}</span>
发货并提供售后服务
</span>
</dd>
</dl>
<hr class="divider" />
<div class="sku-list" v-if="goodsSkuDetail.goods_spec_format">
<dl class="item-line" v-for="(item, index) in goodsSkuDetail.goods_spec_format" :key="index">
<dt>{{ item.spec_name }}</dt>
<dd>
<ul>
<li v-for="(item_value, index_value) in item.value" :key="index_value">
<div :class="{ 'selected ns-border-color': item_value['selected'] || skuId == item_value.sku_id,disabled: item_value['disabled'] || (!item_value['selected'] && specDisabled) }" @click="changeSpec(item_value.sku_id, item_value.spec_id)">
<img v-if="item_value.image" :src="$img(item_value.image, { size: 'small' })" />
<span>{{ item_value.spec_value_name }}</span>
<!-- <i class="iconfont icon-duigou1 ns-text-color"></i> -->
</div>
</li>
</ul>
</dd>
</dl>
</div>
<div class="buy-number">
<dl class="item-line">
<dt>数量</dt>
<dd>
<div class="num-wrap">
<div class="operation">
<span class="decrease el-icon-minus" @click="changeNum('-')"></span>
<el-input v-model="number" placeholder="0" @input="keyInput()"></el-input>
<span class="increase el-icon-plus" @click="changeNum('+')"></span>
</div>
</div>
<span class="unit">{{ goodsSkuDetail.unit }}</span>
<span class="inventory" v-if="goodsSkuDetail.stock_show">库存{{ goodsSkuDetail.stock }}{{ goodsSkuDetail.unit }}</span>
<!-- 限购 -->
<em v-if="(goodsSkuDetail.is_limit == 1 && goodsSkuDetail.max_buy > 0) || goodsSkuDetail.min_buy > 1" class="restrictions">
<span v-if="(goodsSkuDetail.is_limit == 1 && goodsSkuDetail.max_buy > 0) && goodsSkuDetail.min_buy > 1">({{ goodsSkuDetail.min_buy }}{{ goodsSkuDetail.unit }}起售限购{{ goodsSkuDetail.max_buy }}{{ goodsSkuDetail.unit }})</span>
<span v-else-if="goodsSkuDetail.is_limit == 1 && goodsSkuDetail.max_buy > 0">(限购{{ goodsSkuDetail.max_buy }}{{ goodsSkuDetail.unit }})</span>
<span v-else-if="goodsSkuDetail.min_buy > 1">({{ goodsSkuDetail.min_buy }}{{ goodsSkuDetail.unit }}起售)</span>
</em>
</dd>
</dl>
</div>
<dl class="item-line buy-btn">
<dt></dt>
<dd v-if="goodsSkuDetail.goods_state == 1">
<template v-if="goodsSkuDetail.stock == 0">
<el-button type="info" plain disabled>库存不足</el-button>
</template>
<template v-else-if="goodsSkuDetail.max_buy != 0 && goodsSkuDetail.purchased_num >= goodsSkuDetail.max_buy">
<el-button type="info" plain disabled>已达最大限购数量</el-button>
</template>
<template v-else>
<el-button type="primary" plain @click="buyNow">立即购买</el-button>
<el-button type="primary" icon="el-icon-shopping-cart-2" v-if="goodsSkuDetail.is_virtual == 0" @click="joinCart">加入购物车</el-button>
</template>
<div class="go-phone icon-item" @click="editCollection">
<span :class="['iconfont', whetherCollection == 1 ? 'icon-_shouzang2 selected' : 'icon-shouzang']"></span>
<span>收藏</span>
</div>
<div href="javascript:;" class="go-phone">
<img src="@/assets/images/goods/qrcode.png" />
<span>二维码</span>
<div class="qrcode-wrap"><img :src="qrcode" alt="二维码图片" /></div>
</div>
</dd>
<dd v-else>
<template>
<el-button type="info" plain disabled>该商品已下架</el-button>
</template>
<div class="go-phone icon-item" @click="editCollection">
<span :class="['iconfont', whetherCollection == 1 ? 'icon-_shouzang2 selected' : 'icon-shouzang']"></span>
<span>收藏</span>
</div>
<div href="javascript:;" class="go-phone">
<img src="@/assets/images/goods/qrcode.png" />
<span>二维码</span>
<div class="qrcode-wrap"><img :src="qrcode" alt="二维码图片" /></div>
</div>
</dd>
</dl>
<dl class="item-line merchant-service" v-show="service_list.length">
<dt>商品服务</dt>
<div>
<dd v-for="item in service_list">
<i class="el-icon-success"></i>
<span class="ns-text-color-gray" :title="item.service_name">{{ item.service_name }}</span>
</dd>
</div>
</dl>
</div>
<!-- 组合套餐 -->
<el-tabs class="bundling-wrap" v-model="tabBundling" @tab-click="bundlingChange" v-if="addonIsExit.bundling && bundling.length && bundling[0].bl_name">
<el-tab-pane :label="item.bl_name" :name="'bundling_' + item.bl_id" v-for="(item, index) in bundling" :key="index">
<!-- <div class="master">
<div class="sku-img"><img :src="$img(goodsSkuDetail.sku_image, { size: 'mid' })" /></div>
<div class="sku-name">{{ goodsSkuDetail.sku_name }}</div>
<div class="sku-price ns-text-color">{{ goodsSkuDetail.discount_price }}</div>
<i class="el-icon-plus"></i>
</div> -->
<div class="operation">
<div class="price-wrap">
<span>组合套餐价</span>
<strong class="bl-price ns-text-color">{{ item.bl_price }}</strong>
</div>
<el-button type="primary" size="medium" @click="$router.push('/promotion/combo/' + item.bl_id)">立即购买</el-button>
<i class="equal">=</i>
</div>
<div class="suits">
<ul>
<li v-for="(goods, goods_index) in item.bundling_goods" :key="goods_index" @click="$util.pushToTab({ path: '/sku/' + goods.sku_id })">
<div class="sku-img"><img :src="$img(goods.sku_image, { size: 'mid' })" /></div>
<div class="sku-name">{{ goods.sku_name }}</div>
<div class="sku-price ns-text-color">{{ goods.price }}</div>
</li>
</ul>
</div>
</el-tab-pane>
</el-tabs>
<div class="detail-wrap">
<!-- <div class="goods-recommended">
<goods-recommend />
</div> -->
<el-tabs class="goods-tab" v-model="tabName" type="card" @tab-click="tabChange">
<el-tab-pane label="商品详情" name="detail">
<div v-html="goodsSkuDetail.goods_content"></div>
</el-tab-pane>
<el-tab-pane label="商品属性" name="attr">
<ul class="attr-list">
<template v-if="goodsSkuDetail.goods_attr_format && goodsSkuDetail.goods_attr_format.length > 0">
<li v-for="(item, index) in goodsSkuDetail.goods_attr_format" :key="index">{{ item.attr_name }}{{ item.attr_value_name }}</li>
</template>
</ul>
</el-tab-pane>
<el-tab-pane v-if="evaluate_show" :label="evaluteCount.total ? '商品评价(' + evaluteCount.total + ')' : '商品评价'" name="evaluate" class="evaluate">
<template v-if="evaluteCount.total">
<nav>
<li :class="evaluaType == 0 ? 'selected' : ''" @click="evaluationType(0)">全部评价({{ evaluteCount.total }})</li>
<li :class="evaluaType == 1 ? 'selected' : ''" @click="evaluationType(1)">好评({{ evaluteCount.haoping }})</li>
<li :class="evaluaType == 2 ? 'selected' : ''" @click="evaluationType(2)">中评({{ evaluteCount.zhongping }})</li>
<li :class="evaluaType == 3 ? 'selected' : ''" @click="evaluationType(3)">差评({{ evaluteCount.chaping }})</li>
</nav>
<ul class="list">
<li v-for="(item, index) in goodsEvaluateList" :key="index">
<div class="member-info">
<img :src="$img(item.member_headimg)" @error="imageErrorEvaluate(index)" class="avatar" />
<span>{{ item.member_name }}</span>
</div>
<div class="info-wrap">
<el-rate v-model="item.star" disabled></el-rate>
<p class="content">{{ item.content }}</p>
<div class="img-list" v-if="item.images">
<el-image v-for="(img, img_index) in item.images" :key="img_index" :src="$img(img)" :preview-src-list="item.imagesFormat"/>
</div>
<div class="sku-info">
<span>{{ item.sku_name }}</span>
<span class="create-time">{{ $util.timeStampTurnTime(item.create_time) }}</span>
</div>
<div class="evaluation-reply" v-if="item.explain_first != ''">店家回复{{ item.explain_first }}</div>
<template v-if="item.again_is_audit == 1">
<div class="review-evaluation">
<span>追加评价</span>
<span class="review-time">{{ $util.timeStampTurnTime(item.again_time) }}</span>
</div>
<p class="content">{{ item.again_content }}</p>
<div class="img-list">
<el-image v-for="(again_img, again_index) in item.again_images" :key="again_index" :src="$img(again_img)" :preview-src-list="item.againImagesFormat" />
</div>
<div class="evaluation-reply" v-if="item.again_explain != ''">店家回复{{ item.again_explain }}
</div>
</template>
</div>
</li>
</ul>
<div class="pager">
<el-pagination
background
:pager-count="5"
:total="total"
prev-text="上一页"
next-text="下一页"
:current-page.sync="currentPage"
:page-size.sync="pageSize"
@size-change="handlePageSizeChange"
@current-change="handleCurrentPageChange"
hide-on-single-page
></el-pagination>
</div>
</template>
<div class="empty" v-else>该商品暂无评价哦</div>
</el-tab-pane>
<template v-if="service">
<el-tab-pane v-if="service_is_display.is_display == 1" :label="service.title" name="after_sale" class="after-sale">
<div v-html="service.content"></div>
</el-tab-pane>
</template>
</el-tabs>
</div>
</div>
</div>
</div>
</template>
<script>
import PicZoom from 'vue-piczoom';
import detail from '@/assets/js/goods/detail';
import GoodsRecommend from '@/components/GoodsRecommend';
export default {
name: 'detail',
components: {
PicZoom,
GoodsRecommend,
},
mixins: [detail]
};
</script>
<style lang="scss">
@import '@/assets/css/goods/detail.scss';
</style>