commit message

This commit is contained in:
Chopper
2021-05-13 10:56:04 +08:00
commit ec3e958037
728 changed files with 132685 additions and 0 deletions

View File

@@ -0,0 +1,102 @@
<template>
<div class="wrapper">
<div class="orderBox">
<!-- <ul class="orderUl">
<li>
<div class="circle">
<Icon size="50" type="ios-card" />
</div>
<div class="info">
<Badge :count="0"> 代付款 </Badge>
</div>
</li>
<li>
<div class="circle">
<Icon size="50" type="ios-card" />
</div>
<div class="info">
<Badge :count="0"> 待收货 </Badge>
</div>
</li>
<li>
<div class="circle">
<Icon size="50" type="ios-card" />
</div>
<div class="info">
<Badge :count="0"> 待评价 </Badge>
</div>
</li>
</ul> -->
<div class="userBox">
<div class="box">
<!-- 我的订单组件 -->
<myOrderPage :paging="false" :homePage="true" />
</div>
<div class="box">
<!-- 近期收藏 -->
<myFavorites :paging="false" :homePage="true" />
</div>
<div class="box">
<!-- 猜你喜欢 -->
<!-- <myLike /> -->
</div>
</div>
</div>
</div>
</template>
<script>
import myOrderPage from '@/pages/home/orderCenter/MyOrder'
import myFavorites from '@/pages/home/memberCenter/Favorites'
// import myLike from '@/components/like'
export default {
name: 'main',
components: {
myOrderPage,
myFavorites
}
}
</script>
<style scoped lang="scss">
.circle {
width: 70px;
height: 70px;
border-radius: 50%;
overflow: hidden;
background: $success_color;
margin: 0 auto;
text-align: center;
color: #fff;
> i {
line-height: 70px;
}
}
.info {
text-align: center;
font-size: 18px;
margin: 10px 0;
}
.orderUl {
overflow: hidden;
> li {
cursor: pointer;
border-radius: 0.4em;
float: left;
padding: 10px 0;
margin: 0 11px;
width: 200px;
text-align: center;
@include background_color($light_background_color);
}
}
.userBox {
padding: 0 0 20px 0;
}
</style>

View File

@@ -0,0 +1,86 @@
<template>
<div>
<Table border ref="selection" :columns="columns" :data="shoppingCart" size="large" no-data-text="您的购物车没有商品请先添加商品到购物车再点击购买"></Table>
<div class="go-to">
<Button @click="goTo" type="primary">去付款</Button>
</div>
</div>
</template>
<script>
import store from '@/vuex/store';
import { mapState, mapActions } from 'vuex';
export default {
name: 'MyShoppingCart',
data () {
return {
columns: [ // 表格表头
{
type: 'selection',
width: 58,
align: 'center'
},
{
title: '图片',
key: 'img',
width: 86,
render: (h, params) => {
return h('div', [
h('img', {
attrs: {
src: params.row.img
}
})
]);
},
align: 'center'
},
{
title: '标题',
key: 'title',
align: 'center'
},
{
title: '套餐',
width: 198,
key: 'package',
align: 'center'
},
{
title: '数量',
key: 'count',
width: 68,
align: 'center'
},
{
title: '价格',
width: 68,
key: 'price',
align: 'center'
}
]
};
},
created () {
this.loadShoppingCart();
},
computed: {
...mapState(['shoppingCart'])
},
methods: {
...mapActions(['loadShoppingCart']),
goTo () {
this.$router.push('/cart');
}
},
store
};
</script>
<style scoped>
.go-to {
margin: 15px;
display: flex;
justify-content: flex-end;
}
</style>

View File

@@ -0,0 +1,79 @@
// 订单状态
export const orderStatusList = [
{
name: '全部',
status: 'ALL'
},
{
name: '未付款',
status: 'UNPAID'
},
{
name: '已付款',
status: 'PAID'
},
{
name: '待发货',
status: 'UNDELIVERED'
},
{
name: '已发货',
status: 'DELIVERED'
},
{
name: '已完成',
status: 'COMPLETED'
},
{
name: '待核验',
status: 'TAKE'
},
{
name: '已取消',
status: 'CANCELLED'
}
]
// 订单售后状态
export const afterSaleStatusList = [
{
name: '申请中',
status: 'APPLY'
},
{
name: '通过',
status: 'PASS'
},
{
name: '拒绝',
status: 'REFUSE'
},
{
name: '买家退货,待卖家收货',
status: 'BUYER_RETURN'
},
{
name: '商家换货/补发',
status: 'SELLER_RE_DELIVERY'
},
{
name: '卖家确认收货',
status: 'SELLER_CONFIRM'
},
{
name: '卖家终止售后',
status: 'SELLER_TERMINATION'
},
{
name: '买家确认收货',
status: 'BUYER_CONFIRM'
},
{
name: '买家取消售后',
status: 'BUYER_CANCEL'
},
{
name: '完成售后',
status: 'COMPLETE'
}
]

View File

@@ -0,0 +1,53 @@
<template>
<div class="wrapper">
<card _Title="账号绑定"/>
<div>
<Row class="bindItem">
<Col :span="2">
</Col>
<Col :span="16">
<div class="setDivItem">
绑定QQ
</div>
<div class="setDivItem theme">
添加QQ号可以使用QQ登录
</div>
</Col>
<Col :span="4">
<Button>添加绑定</Button>
</Col>
</Row>
</div>
</div>
</template>
<script>
export default {
name: 'AccountBind',
data () {
return {}
},
mounted () {
},
methods: {}
}
</script>
<style scoped lang="scss">
.bindItem {
border-bottom: 1px solid $border_color;
padding: 16px 0;
/deep/ .ivu-col {
padding: 8px 0;
}
}
.setDivItem {
line-height: 1.75;
}
/deep/ .ivu-col-span-2, .ivu-col-span-4 {
text-align: center;
color: $theme_color;
}
</style>

View File

@@ -0,0 +1,177 @@
<template>
<div class="wrapper">
<card _Title="账户安全"/>
<div class="safeList">
<!-- 密码 -->
<Row class="safeItem">
<Col :span="2">
<Icon size="40" type="md-key"/>
</Col>
<Col :span="16">
<div class="setDivItem">登录密码</div>
<div class="setDivItem theme">互联网账号存在被盗风险建议您定期更改密码以保护账户安全</div>
</Col>
<Col :span="4">
<Button @click="modifyPwd">修改密码</Button>
</Col>
</Row>
<!-- 邮箱 -->
<!-- <Row class="safeItem">
<Col :span="2">
<Icon size="40" type="md-mail" />
</Col>
<Col :span="16">
<div class="setDivItem">
邮箱验证
</div>
<div class="setDivItem " v-if="true">
您的验证邮箱<span>xxxxx</span>
</div>
<div class="setDivItem " v-else>
</div>
</Col>
<Col :span="4">
<Button>修改邮箱</Button>
</Col>
</Row> -->
<!-- 手机验证 -->
<!-- <Row class="safeItem">
<Col :span="2">
<Icon size="40" type="ios-phone-portrait" />
</Col>
<Col :span="16">
<div class="setDivItem">
手机验证
</div>
<div class="setDivItem " v-if="true">
您的手机号<span>xxxxx</span>
</div>
<div class="setDivItem " v-else>
</div>
</Col>
<Col :span="4">
<Button>立即验证</Button>
</Col>
</Row> -->
<!-- 支付密码 -->
<!-- <Row class="safeItem">
<Col :span="2">
<Icon size="40" type="md-lock" />
</Col>
<Col :span="16">
<div class="setDivItem">
支付密码
</div>
<div class="setDivItem " v-if="true">
安全认证<span>xxxxx</span>
</div>
<div class="setDivItem " v-else>
</div>
</Col>
<Col :span="4">
<Button @click="goModifyPwd" v-if="pwdStatus == '设置密码'" type="error">{{pwdStatus}}</Button>
<Dropdown style="margin-left: 20px" v-if="pwdStatus == '修改密码'" @on-click="selectPwd">
<Button type="primary">
修改密码
<Icon type="ios-arrow-down"></Icon>
</Button>
<DropdownMenu slot="list" on-click="selectPwd">
<DropdownItem name = "1">修改密码</DropdownItem>
<DropdownItem name = "2">重置密码</DropdownItem>
</DropdownMenu>
</Dropdown>
</Col>
</Row> -->
<!-- 实名 -->
<!-- <Row class="safeItem">
<Col :span="2">
<Icon size="40" type="md-card" />
</Col>
<Col :span="16">
<div class="setDivItem">
实名认证
</div>
<div class="setDivItem " v-if="true">
已认证<span>xxxxx</span>
</div>
<div class="setDivItem " v-else>
您还未实名认证该账户立即实名认证可加快提现速度
</div>
</Col>
<Col :span="4">
<Button>立即认证</Button>
</Col>
</Row> -->
</div>
</div>
</template>
<script>
import card from '@/components/card'
import {
getPwdStatus
} from '@/api/account';
export default {
name: 'AccountSafe',
data () {
return {
pwdStatus: '' // 密码状态
}
},
components: {card},
mounted () {
this.getPwdStatus()
},
methods: {
// 设置支付密码
goModifyPwd () {
this.$router.push({name: 'ModifyPwd', query: { status: 2 }})
},
selectPwd (value) {
this.$router.push({name: 'ModifyPwd', query: { status: value }})
},
modifyPwd () {
this.$router.push({name: 'ModifyPwd', query: { status: 1 }})
},
// 获取密码状态
getPwdStatus () {
getPwdStatus().then(res => {
if (res) {
this.pwdStatus = '修改密码'
} else {
this.pwdStatus = '设置密码'
}
});
}
}
}
</script>
<style scoped lang="scss">
/deep/ .ivu-col-span-2, .ivu-col-span-4 {
text-align: center;
color: $theme_color;
}
.theme {
color: $theme_color;
}
.setDivItem {
line-height: 1.75;
}
.safeItem {
border-bottom: 1px solid $border_color;
padding: 16px 0;
/deep/ .ivu-col {
padding: 8px 0;
}
}
</style>

View File

@@ -0,0 +1,174 @@
<template>
<div class="wrapper">
<card _Title="评论/晒单" />
<div class="order">
<div class="order-title">
<Row class="order-row title">
<i-col span="12">订单详情</i-col>
<i-col span="4">收货人</i-col>
<i-col span="4">评价</i-col>
<i-col span="6"></i-col>
</Row>
</div>
<empty v-if="list.length === 0" />
<div class="order-item" v-else v-for="(item, index) in list" :key="index">
<div>
<div class="title order-item-title">
<span>订单号:{{item.orderNo}}</span>
<span class="color999 ml_10">{{item.createTime}}</span>
<span class="hover-pointer fontsize_12 eval-detail" @click="evaluate(item.id)">评价详情</span>
</div>
<Row class="order-item-view">
<i-col span="12" class="item-view-name">
<div class="order-img">
<img :src="item.goodsImage" alt="" />
</div>
<div class="order-name">
{{item.goodsName}}
</div>
<div>
x1
</div>
</i-col>
<i-col span="4">{{item.createBy | secrecyMobile}}</i-col>
<i-col span="4">
{{item.grade==='GOOD'?'好评' : item.grade === 'WORSE'?'差评' : '中评'}}
</i-col>
<i-col span="4">
<Tooltip >
<div class="content">{{item.content}}</div>
<div style="white-space: normal;" slot="content">
{{item.content}}
</div>
</Tooltip>
</i-col>
</Row>
</div>
</div>
<Spin v-if="loading"></Spin>
</div>
<!-- 分页 -->
<div class="page-size">
<Page :total="total" @on-change="changePageNum"
@on-page-size-change="changePageSize"
:page-size="params.pageSize"
show-sizer>
</Page>
</div>
</div>
</template>
<script>
import {evolutionList} from '@/api/order.js';
export default {
name: 'CommentList',
data () {
return {
commentWay: [`待评价`, `待追评`, `已评价`], // 评价分类
loading: false, // 加载状态
list: [], // 评价列表
total: 0, // 评价总数
params: { // 请求参数
pageNumber: 1,
pageSize: 10
}
};
},
mounted () {
this.getList()
},
methods: {
getList () {
evolutionList(this.params).then(res => {
if (res.success) {
const list = res.result.records;
list.forEach(element => {
element.descriptionScore = Number(element.descriptionScore)
});
this.list = list;
this.total = res.result.total
}
})
},
changePageNum (val) {
this.params.pageNumber = val;
this.getList()
},
changePageSize (val) {
this.pageNumber = 1;
this.params.pageSize = val;
this.getList()
},
changeIndex (index) {
console.log(index);
},
evaluate (id) {
this.$router.push({path: '/home/evalDetail', query: { id }})
}
}
};
</script>
<style scoped lang="scss">
.order-img {
> img {
width: 60px;
height: 60px;
border: 1px solid $border_color;
box-sizing: border-box;
}
}
.title {
@include background_color($light_background_color);
}
.item-view-name {
display: flex;
}
.order-name {
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 2;
overflow: hidden;
text-align: left;
padding: 0 10px;
font-size: 13px;
@include content_color($light_content_color);
}
.order-item-title {
padding: 5px 20px;
text-align: left;
font-size: 13px;
position: relative;
}
.order-item-view {
padding: 10px 20px;
}
.order-item {
text-align: center;
border: 1px solid $border_color;
margin: 10px 0;
}
.order-row {
padding: 10px 0;
text-align: center;
}
.content {
color: #999;
max-height: 60px;
overflow: hidden;
word-wrap: break-word;
}
.eval-detail {
position: absolute;
right: 20px;
&:hover{
color: $theme_color;
}
}
</style>

View File

@@ -0,0 +1,285 @@
<template>
<div class="add-eval">
<div class="title">
<card _Title="订单投诉" :_Size="16"></card>
<p>
<span class="fontsize_16 global_color">{{ statusLabel[detail.complainStatus] }}</span>
<span class="color999 ml_20">创建时间</span><span>{{ detail.createTime }}</span>
<span class="color999 ml_20">{{ detail.createTime }}</span>
</p>
</div>
<Alert class="l_title" show-icon type="warning">我的申诉信息</Alert>
<table cellspacing="0" cellpadding='0' border="1">
<tr>
<td>投诉商品</td>
<td><img :src="detail.goodsImage" width="60" alt=""> &nbsp;{{ detail.goodsName }}</td>
</tr>
<tr>
<td>投诉主题</td>
<td>{{ detail.complainTopic }}</td>
</tr>
<tr>
<td>投诉内容</td>
<td>{{ detail.content }}</td>
</tr>
<tr>
<td>补充内容</td>
<td>
<div style="display:flex;align-items:center;">
<div class="demo-upload-list" v-for="(img, index) in detail.images.split(',')" :key="index">
<img :src="img">
<div class="demo-upload-list-cover">
<Icon type="ios-eye-outline" @click.native="handleView(img)"></Icon>
</div>
</div>
</div>
</td>
</tr>
</table>
<Alert class="l_title" show-icon type="warning">商家申诉信息</Alert>
<table cellspacing="0" cellpadding='0' border="1">
<tr>
<td>申诉时间</td>
<td>{{ detail.appealTime || '暂无' }}</td>
</tr>
<tr>
<td>申诉内容</td>
<td>{{ detail.appealContent || '暂无' }}</td>
</tr>
<tr>
<td>申诉凭证</td>
<td>
<div style="display:flex;align-items:center;">
<div class="demo-upload-list" v-for="(img, index) in detail.appealImages.split(',')" :key="index">
<img :src="img">
<div class="demo-upload-list-cover">
<Icon type="ios-eye-outline" @click.native="handleView(img)"></Icon>
</div>
</div>
</div>
</td>
</tr>
</table>
<Alert class="l_title" show-icon type="warning">平台仲裁</Alert>
<table cellspacing="0" cellpadding='0' border="1">
<tr>
<td>仲裁意见</td>
<td>{{ detail.arbitrationResult || '暂无' }}</td>
</tr>
</table>
<Alert class="l_title" show-icon type="warning">对话详情</Alert>
<div class="speak-way" v-if="detail.orderComplaintCommunications.length">
<div
class="speak-msg seller"
:class="{'speak-buyer': item.owner == 'BUYER', 'speak-platform': item.owner == 'PLATFORM', 'speak-seller': item.owner == 'STORE',}"
:key="i"
v-for="(item, i) in detail.orderComplaintCommunications"
>
{{
item.owner == "PLATFORM"
? "平台"
: item.owner == "BUYER"
? "买家"
: "卖家"
}}[{{ item.createTime }}]
<span>{{ item.content }}</span>
</div>
</div>
<div v-else>暂无对话</div>
<table cellspacing="0" cellpadding='0' border="1" v-if="detail.complainStatus!='COMPLETE'">
<tr>
<td>回复</td>
<td><label>
<input type="textarea" maxlength="200" :rows="4" clearable
style="width:260px" v-model="params.content"></input>
</label></td>
</tr>
<tr>
<td></td>
<td>
<Button type="primary" :loading="submitLoading" @click="handleSubmit" style="margin-left: 5px">
回复
</Button>
</td>
</tr>
</table>
<Modal title="View Image" v-model="visible">
<img :src="previewImage" v-if="visible" style="width: 100%">
</Modal>
</div>
</template>
<script>
import {getComplainDetail} from '@/api/member.js';
import {communication} from '@/api/order';
export default {
data () {
return {
detail: {}, // 评价详情
visible: false, // 图片预览
previewImage: '', // 预览图片地址
loading: false, // 加载状态
// 状态
statusLabel: {
NO_APPLY: '未申请',
APPLYING: '申请中',
COMPLETE: '已完成',
EXPIRED: '已失效',
CANCEL: '已取消',
NEW: '待审核'
},
// 商家回复内容
params: {
content: '',
complainId: ''
}
}
},
methods: {
getDetail () {
getComplainDetail(this.$route.query.id).then(res => {
if (res.success) this.detail = res.result
})
},
goGoodsDetail (skuId, goodsId) {
let routerUrl = this.$router.resolve({
path: '/goodsDetail',
query: {skuId, goodsId}
})
window.open(routerUrl.href, '_blank')
},
handleView (name) {
this.previewImage = name;
this.visible = true;
},
// 回复
handleSubmit () {
if (this.params.content === '') {
this.$Message.error('请填写对话内容');
return;
}
this.params.complainId = this.$route.query.id;
communication(this.params).then((res) => {
this.submitLoading = false;
if (res.success) {
this.$Message.success('对话成功');
this.params.content = '';
this.getDetail();
}
});
}
},
mounted () {
this.getDetail()
}
}
</script>
<style lang="scss" scoped>
.speak-way {
background-color: #fff;
width: 100%;
border: 1px solid #999;
.speak-seller {
background-color: #fff2c6;
}
.speak-platform {
background-color: #ffe2d1;
}
.speak-buyer {
background-color: #c1d6d5;
}
}
.speak-msg {
height: 40px;
line-height: 40px;
padding: 0 5px;
border-radius: 5px;
margin: 5px;
background-color: #eee;
}
.demo-upload-list {
display: inline-block;
width: 100px;
height: 100px;
text-align: center;
line-height: 100px;
border: 1px solid transparent;
border-radius: 4px;
overflow: hidden;
background: #fff;
position: relative;
box-shadow: 0 1px 1px rgba(0, 0, 0, .2);
margin-right: 4px;
margin-top: 10px;
}
.demo-upload-list img {
width: 100%;
height: 100%;
}
.demo-upload-list-cover {
display: none;
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
background: rgba(0, 0, 0, .6);
}
.demo-upload-list:hover .demo-upload-list-cover {
display: block;
}
.demo-upload-list-cover i {
color: #fff;
font-size: 30px;
cursor: pointer;
margin: 0 2px;
}
.icon-upload {
width: 58px;
height: 58px;
line-height: 58px;
text-align: center;
display: inline-block;
border: 1px dashed #999;
border-radius: 4px;
margin-top: 10px;
&:hover {
cursor: pointer;
border-color: $theme_color;
}
}
.l_title {
margin: 10px 0;
}
table {
width: 100%;
border-color: #eee;
td {
padding: 10px;
&:nth-child(1) {
width: 120px;
color: #999;
}
}
}
</style>

View File

@@ -0,0 +1,196 @@
<template>
<div class="wrapper">
<card _Title="我的投诉" />
<div class="order">
<div class="order-title">
<Row class="order-row title">
<i-col span="12">商品信息</i-col>
<i-col span="4">投诉状态</i-col>
<i-col span="4">投诉主题</i-col>
<i-col span="6"></i-col>
</Row>
</div>
<empty v-if="list.length === 0" />
<div class="order-item" v-else v-for="(item, index) in list" :key="index">
<div>
<div class="title order-item-title">
<span>投诉单号:{{item.id}}</span>
<span class="color999 ml_10">{{item.createTime}}</span>
<span class="hover-pointer fontsize_12 eval-detail" @click="detail(item.id)">投诉详情</span>
<span class="hover-pointer fontsize_12 eval-detail" style="right: 90px" v-if="item.complainStatus != 'EXPIRED' && item.complainStatus != 'CANCEL'" @click="cancel(item.id)">取消投诉</span>
</div>
<Row class="order-item-view">
<i-col span="12" class="item-view-name">
<div class="order-img">
<img :src="item.goodsImage" alt="" />
</div>
<div class="order-name">
{{item.goodsName}}
</div>
<div>
x1
</div>
</i-col>
<i-col span="4">{{statusLabel[item.complainStatus]}}</i-col>
<i-col span="4">
<Tooltip >
<div class="content">{{item.content}}</div>
<div style="white-space: normal;" slot="content">
{{item.content}}
</div>
</Tooltip>
</i-col>
<i-col span="4">
<Tooltip >
<div class="content">{{item.content}}</div>
<div style="white-space: normal;" slot="content">
{{item.content}}
</div>
</Tooltip>
</i-col>
</Row>
</div>
</div>
<Spin v-if="loading"></Spin>
</div>
<!-- 分页 -->
<div class="page-size">
<Page :total="total" @on-change="changePageNum"
@on-page-size-change="changePageSize"
:page-size="params.pageSize"
show-sizer>
</Page>
</div>
</div>
</template>
<script>
import {complainList, clearComplain} from '@/api/member.js';
export default {
name: 'ComplainList',
data () {
return {
loading: false, // 加载状态
list: [], // 投诉列表
statusLabel: { // 投诉状态
NO_APPLY: '未申请',
APPLYING: '申请中',
COMPLETE: '已完成,此时可申请',
EXPIRED: '已失效,不可申请',
CANCEL: '已取消',
NEW: '申请中'
},
total: 0, // 投诉总数
params: { // 请求参数
pageNumber: 1,
pageSize: 10
}
};
},
mounted () {
this.getList()
},
methods: {
getList () {
complainList(this.params).then(res => {
if (res.success) {
const list = res.result.records;
this.list = list;
this.total = res.result.total
}
})
},
changePageNum (val) {
this.params.pageNumber = val;
this.getList()
},
changePageSize (val) {
this.pageNumber = 1;
this.params.pageSize = val;
this.getList()
},
cancel (id) {
this.$Modal.confirm({
title: '取消投诉',
content: '<p>确定取消投诉吗?</p>',
onOk: () => {
clearComplain(id).then((res) => {
if (res.success) {
this.$Message.success('取消投诉成功');
this.getCartList();
}
});
},
onCancel: () => { }
});
},
detail (id) {
this.$router.push({path: '/home/complainDetail', query: { id }})
}
}
};
</script>
<style scoped lang="scss">
.order-img {
> img {
width: 60px;
height: 60px;
border: 1px solid $border_color;
box-sizing: border-box;
}
}
.title {
@include background_color($light_background_color);
}
.item-view-name {
display: flex;
}
.order-name {
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 2;
overflow: hidden;
text-align: left;
padding: 0 10px;
font-size: 13px;
@include content_color($light_content_color);
}
.order-item-title {
padding: 5px 20px;
text-align: left;
font-size: 13px;
position: relative;
}
.order-item-view {
padding: 10px 20px;
}
.order-item {
text-align: center;
border: 1px solid $border_color;
margin: 10px 0;
}
.order-row {
padding: 10px 0;
text-align: center;
}
.content {
color: #999;
max-height: 60px;
overflow: hidden;
word-wrap: break-word;
}
.eval-detail {
position: absolute;
right: 20px;
&:hover{
color: $theme_color;
}
}
</style>

View File

@@ -0,0 +1,382 @@
<template>
<div class='wrapper'>
<card _Title='我的分销'/>
<!-- 分销申请 -->
<div v-if="status === 0">
<Alert type="warning">分销商申请</Alert>
<Form ref="form" :model="applyForm" :rules="rules">
<FormItem label="姓名" prop="name">
<Input v-model="applyForm.name"></Input>
</FormItem>
<FormItem label="身份证号" prop="idNumber">
<Input v-model="applyForm.idNumber"></Input>
</FormItem>
<FormItem>
<Button type="primary" :loading="applyLoading" @click="apply">提交申请</Button>
</FormItem>
</Form>
</div>
<!-- 分销审核 -->
<div v-if="status === 1">
<Alert type="success">
您提交的信息正在审核
<template slot="desc">提交认证申请后工作人员将在三个工作日进行核对完成审核</template>
</Alert>
</div>
<!-- 分销提现商品订单 -->
<div v-if="status === 2">
<div class="box">
<div class="mb_20 account-price">
<span class="subTips">可提现金额</span>
<span class="fontsize_48 global_color">{{ result.canRebate | unitPrice }}</span>
<span class="subTips">冻结金额</span>
<span class="">{{ result.commissionFrozen | unitPrice }}</span>
<Button type="primary" size="small" class="ml_20" @click="withdrawApplyModal = true">申请提现</Button>
</div>
</div>
<Tabs :value="tabName" @on-click="tabPaneChange">
<TabPane label="已选商品" name="goodsChecked">
<Table stripe :columns="goodsColumns" :data="goodsData.records">
<template slot-scope="{ row }" slot="name">
<div class="goods-msg" @click="linkTo(`/goodsDetail?skuId=${row.skuId}&goodsId=${row.id}`)"><img style="vertical-align:top;" :src="row.thumbnail" width="60" height="60" alt="">&nbsp; {{row.goodsName}}</div>
</template>
<template slot-scope="{ row }" slot="price">
<span> {{ row.price | unitPrice }}</span>
</template>
<template slot-scope="{ row }" slot="commission">
<span> {{ row.commission | unitPrice }}</span>
</template>
<template slot-scope="{ row }" slot="action">
<Button type="primary" size="small" style="margin-right: 5px" @click="fenxiao(row)">分销商品</Button>
</template>
</Table>
<div class="page-size">
<Page
:current="params.pageNumber"
:total="goodsData.total"
:page-size="params.pageSize"
@on-change="changePage"
size="small"
show-total
show-elevator
></Page>
</div>
</TabPane>
<TabPane label="未选商品" name="goodsUncheck">
<Table stripe :columns="goodsColumns" :data="goodsData.records">
<template slot-scope="{ row }" slot="name">
<div class="goods-msg" @click="linkTo(`/goodsDetail?skuId=${row.skuId}&goodsId=${row.id}`)"><img style="vertical-align:top;" :src="row.thumbnail" width="60" height="60" alt="">&nbsp; {{row.goodsName}}</div>
</template>
<template slot-scope="{ row }" slot="price">
<span> {{ row.price | unitPrice }}</span>
</template>
<template slot-scope="{ row }" slot="commission">
<span> {{ row.commission | unitPrice }}</span>
</template>
<template slot-scope="{ row }" slot="action">
<Button type="primary" size="small" style="margin-right: 5px" @click="selectGoods(row.id)">选择商品</Button>
</template>
</Table>
<div class="page-size">
<Page
:current="params.pageNumber"
:total="goodsData.total"
:page-size="params.pageSize"
@on-change="changePage"
size="small"
show-total
show-elevator
></Page>
</div>
</TabPane>
<TabPane label="提现记录" name="log">
<Table stripe :columns="logColumns" :data="logData.records">
<template slot-scope="{ row }" slot="time">
<span>{{row.createTime}}</span>
</template>
<template slot-scope="{ row }" slot="price">
<span> +{{ row.price | unitPrice }}</span>
</template>
<template slot-scope="{ row }" slot="status">
<span> {{row.distributionCashStatus == "APPLY" ? "待处理" : row.distributionCashStatus == "PASS" ? "通过" : "拒绝"}}</span>
</template>
</Table>
<div class="page-size">
<Page
:current="logParams.pageNumber"
:total="logData.total"
:page-size="logParams.pageSize"
@on-change="changePageLog"
size="small"
show-total
show-elevator
></Page>
</div>
</TabPane>
</Tabs>
</div>
<!-- 未开放 -->
<div v-if="status === 3">
<Alert type="error">
分销功能暂未开启
<template slot="desc">提交认证申请后工作人员将在三个工作日进行核对完成审核</template>
</Alert>
</div>
<Modal v-model="withdrawApplyModal" width="530">
<p slot="header">
<Icon type="edit"></Icon>
<span>提现金额</span>
</p>
<div>
<Input
v-model="withdrawPrice"
size="large"
number
maxlength="9"
><span slot="append"></span></Input>
</div>
<div slot="footer" style="text-align: center">
<Button type="primary" size="large" @click="withdraw">提现</Button>
</div>
</Modal>
<Modal v-model="qrcodeShow" title="分销商品" width="800">
<Alert type="warning">
下载二维码或者复制链接分享商品
</Alert>
<div style="width:200px;height:200px;border:1px solid #eee;">
<vue-qr :text="qrcode" :callback="qrcodeData" :margin="0" colorDark="#000" colorLight="#fff" :size="200"></vue-qr>
<Button class="download-btn" type="success" @click="downloadQrcode">下载二维码</Button>
</div>
<div class="mt_10">商品链接<Input style="width:400px" v-model="qrcode"></Input></div>
</Modal>
</div>
</template>
<script>
import {distribution, applyDistribution, distCash, distCashHistory, getDistOrderList, getDistGoodsList, selectDistGoods} from '@/api/member.js'
import { IDCard } from '@/plugins/RegExp.js';
import vueQr from 'vue-qr';
export default {
name: 'Distribution',
components: { vueQr },
data () {
return {
status: 0, // 申请状态0为未申请 1 申请中 2 申请完成 3 功能暂未开启
applyForm: {}, // 申请表单
rules: { // 验证规则
name: [{required: true, message: '请输入真实姓名'}],
idNumber: [
{required: true, message: '请输入身份证号'},
{pattern: IDCard, message: '请输入正确的身份证号'}
]
},
tabName: 'goodsChecked', // 当前所在tab
result: {}, // 审核结果
applyLoading: false, // 申请加载状态
goodsLoading: false, // 列表加载状态
withdrawApplyModal: false, // 提现表单显隐
withdrawPrice: 0, // 提现金额
goodsData: {}, // 商品数据
logData: {}, // 日志数据
goodsColumns: [ // 商品表头
{title: '商品名称', slot: 'name', width: 400},
{title: '商品价格', slot: 'price'},
{title: '佣金', slot: 'commission'},
{title: '操作', slot: 'action', width: 120}
],
logColumns: [ // 日志表头
{title: '申请时间', slot: 'time'},
{title: '提现金额', slot: 'price'},
{title: '提现状态', slot: 'status'}
],
params: { // 商品请求参数
pageNumber: 1,
pageSize: 20,
checked: true
},
orderParams: { // 订单商品请求参数
pageNumber: 1,
pageSize: 20
},
logParams: { // 日志参数
pageNumber: 1,
pageSize: 20
},
qrcode: '', // 二维码
qrcodeShow: false, // 显示二维码
base64Img: '', // base64编码
goodsNameCurr: ''// 当前分销商品名称
}
},
mounted () {
this.distribution()
},
methods: {
apply () {
this.$refs.form.validate(valid => {
if (valid) {
this.applyLoading = true
applyDistribution(this.form).then(res => {
this.applyLoading = false
if (res.success) {
this.$Message.success('申请已提交,请等待管理员审核')
this.status = 1;
}
})
}
})
},
withdraw () { // 申请提现
distCash({price: this.withdrawPrice}).then(res => {
this.withdrawApplyModal = false
this.price = 0;
if (res.success) {
this.$Message.success('提现成功')
this.distribution()
} else {
this.$Message.error(res.message)
}
})
},
qrcodeData (data64) {
this.base64Img = data64
},
downloadQrcode () {
let a = document.createElement('a'); // 生成一个a元素
let event = new MouseEvent('click'); // 创建一个单击事件
a.download = this.goodsNameCurr || 'photo'
a.href = this.base64Img; // 将生成的URL设置为a.href属性
a.dispatchEvent(event); // 触发a的单击事件
},
tabPaneChange (tab) { // tab栏切换
if (tab === 'goodsChecked') {
this.params.checked = true;
this.params.pageNUmber = 1
this.getGoodsData()
} else if (tab === 'goodsUncheck') {
this.params.checked = false
this.getGoodsData()
} else if (tab === 'order') {
this.orderParams.pageNumber = 1
this.getOrderData()
} else if (tab === 'log') {
this.logParams.pageNumber = 1
this.getLog()
}
},
changePage (val) {
this.params.pageNumber = val;
this.getGoodsData()
},
changePageLog (val) {
this.logParams.pageNumber = val;
this.getLog()
},
selectGoods (id) { // 选择商品
selectDistGoods(id).then(res => {
if (res.success) {
this.$Message.success('分销商品选择成功,请在已选商品中查看')
this.getGoodsData()
}
})
},
fenxiao (row) { // 分销商品
this.qrcode = `${location.origin}/goodsDetail?skuId=${row.skuId}&goodsId=${row.id}&distributionId=${this.result.id}`
this.goodsNameCurr = row.goodsName
this.qrcodeShow = true;
},
getGoodsData () { // 商品数据
getDistGoodsList(this.params).then(res => {
if (res.success) this.goodsData = res.result
})
},
getOrderData () { // 订单数据
getDistOrderList(this.orderParams).then(res => {
if (res.success) this.goodsData = res.result
})
},
getLog () { // 提现历史
distCashHistory(this.logParams).then(res => {
if (res.success) this.goodsData = res.result
})
},
distribution () { // 获取分销商信息
distribution().then((res) => {
if (res.result) {
this.result = res.result;
let type = res.result.distributionStatus;
if (type === 'PASS') {
this.status = 2;
this.getGoodsData()
} else if (type === 'RETREAT' || type === 'REFUSE') {
this.status = 0;
} else {
this.status = 1;
}
} else if (!res.data.success && res.data.code === 22000) {
this.status = 3;
} else {
// 没有资格申请 先去实名认证
this.status = 0
}
});
}
}
}
</script>
<style scoped lang='scss'>
.afList{
display: flex;
}
.codeImg{
display: flex;
>img{
width: 150px;
height: 150px;
}
}
.mb_40{margin-bottom: 40px;}
.box {
margin: 20px 0;
}
.page-size {
margin: 15px 0px;
display: flex;
justify-content: flex-end;
align-items: center;
}
.account-price {
font-weight: bold;
}
.subTips {
@include sub_color($light_sub_color);
}
.account-btns {
margin: 10px 0;
}
.ivu-btn {
margin: 0 4px;
}
.fontsize_48 {
font-size: 48px;
}
.goods-msg{
display: flex;
align-items: center;
padding: 3px;
&:hover{
color: $theme_color;
cursor: pointer;
}
}
.download-btn {
position: relative;
top: -200px;
left: 200px;
}
</style>

View File

@@ -0,0 +1,175 @@
<template>
<div class="wrapper">
<card _Title="近期收藏" :_Tabs="favoriteWay" @_Change="change" :_Size="16" v-if="!homePage"/>
<card _Title="近期收藏" :_Size="16" :_Tabs="favoriteWay" @_Change="change" _More="全部收藏" _Src="/home/Favorites" v-else></card>
<div v-if="list.length">
<template v-for="(item) in list">
<div class="goodsItem" :key="item.skuId">
<div class="goodsImg hover-pointer">
<img
:src="params.type === 'GOODS'? item.image : item.logo"
alt=""
/>
</div>
<div class="goodsTitle hover-pointer">
{{params.type === 'GOODS'? item.goodsName : item.storeName}}
</div>
<div class="goodsPrice">
<span v-if="params.type === 'GOODS'">{{item.price | unitPrice}}</span>
<Tag color="error" v-if="item.selfOperated">商家自营</Tag>
</div>
<div class="goodsBuy">
<Button size="small" type="primary" @click="buynow(item.skuId, item.goodsId)" v-if="params.type === 'GOODS'">立即购买</Button>
<Button size="small" type="primary" @click="goShop(item.storeId)" v-else>店铺购买</Button>
<Button size="small" type="error" ghost v-if="params.type === 'GOODS'" @click="cancel(item.skuId)">取消收藏</Button>
<Button size="small" type="error" ghost v-if="params.type === 'SHOP'" @click="cancel(item.storeId)">取消收藏</Button>
</div>
</div>
</template>
<Spin size="large" fix v-if="spinShow"></Spin>
</div>
<empty v-else />
<!-- 分页 -->
<div class="page-size mt_10" v-if="paging">
<Page :total="total" @on-change="changePageNum"
@on-page-size-change="changePageSize"
:page-size="params.pageSize"
show-sizer>
</Page>
</div>
</div>
</template>
<script>
import { collectList, cancelCollect } from '@/api/member.js'
export default {
name: 'Favorites',
props: {
paging: {
type: Boolean,
default: true
},
homePage: {
type: Boolean,
default: false
}
},
data () {
return {
favoriteWay: ['收藏商品', '收藏店铺'], // 收藏分类
list: [], // 收藏列表
total: 0, // 收藏总数
params: { // 请求参数
pageNumber: 1,
pageSize: 10,
type: 'GOODS'
},
spinShow: false // 加载状态
};
},
methods: {
getList () {
this.spinShow = true
collectList(this.params).then(res => {
this.spinShow = false
if (res.success) this.list = res.result.records;
})
},
change (index) {
if (index === 0) { this.params.type = 'GOODS' }
if (index === 1) { this.params.type = 'SHOP' }
this.getList()
},
cancel (id) {
let typeName = this.params.type === 'GOODS' ? '商品' : '店铺'
this.$Modal.confirm({
title: 'Title',
content: `<p>确定取消收藏该${typeName}吗?</p>`,
onOk: () => {
cancelCollect(this.params.type, id).then(res => {
if (res.success) {
this.getList();
}
})
}
});
},
changePageNum (val) {
this.params.pageNumber = val;
this.getList()
},
changePageSize (val) {
this.pageNumber = 1;
this.params.pageSize = val;
this.getList()
},
buynow (skuId, goodsId) {
let url = this.$router.resolve({
path: '/goodsDetail',
query: {skuId, goodsId}
})
window.open(url.href, '_blank')
},
goShop (id) {
let url = this.$router.resolve({
path: '/merchant',
query: {id}
})
window.open(url.href, '_blank')
}
},
mounted () {
if (this.homePage) this.params.pageSize = 5;
this.getList()
}
};
</script>
<style scoped lang="scss">
.goodsShop,
.goodsImg,
.goodsPrice,
.goodsShop,
.goodsTitle {
margin: 0 6px;
}
.wrapper {
margin-bottom: 40px;
}
.goodsItem {
display: flex;
height: 60px;
line-height: 60px;
margin-bottom: 10px;
> .goodsImg {
width: 60px;
height: 60px;
overflow: hidden;
> img {
width: 100%;
height: 100%;
}
}
> .goodsPrice,
.goodsShop {
width: 150px;
text-align: center;
}
> .goodsTitle {
width: 400px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
}
.goodsBuy {
margin-left: 80px;
}
.page-size{
text-align: right;
}
</style>

View File

@@ -0,0 +1,125 @@
<template>
<div class="wrapper">
<card _Title="我的发票"></card>
<empty v-if="list.length===0" />
<div v-else>
<Button size="small" @click="invoiceAvailable = true">新增发票</Button>
<div class="receipt-item" v-for="(item,index) in list" :key="index">
<p><span>发票抬头</span>{{item.receiptTitle}}</p>
<p><span>发票内容</span> {{item.receiptContent}}</p>
<p><span>纳税人识别号</span> {{item.taxpayerId}}</p>
</div>
</div>
<Modal v-model="invoiceAvailable" width="600" footer-hide>
<Form
:model="form"
ref="form"
label-position="left"
:rules="ruleInline"
:label-width="110"
>
<FormItem label="发票类型">
<RadioGroup v-model="form.type">
<Radio :label="2">单位</Radio>
</RadioGroup>
</FormItem>
<FormItem
label="发票抬头"
prop="receiptTitle"
>
<i-input v-model="form.receiptTitle"></i-input>
</FormItem>
<FormItem
label="纳税人识别号"
prop="taxpayerId"
>
<i-input v-model="form.taxpayerId"></i-input>
</FormItem>
<FormItem label="发票内容">
<RadioGroup v-model="form.receiptContent">
<Radio label="商品明细">商品明细</Radio>
</RadioGroup>
</FormItem>
</Form>
<div style="text-align: center">
<Button type="primary" :loading="loading" @click="save">保存发票信息</Button>
<Button type="default" @click="invoiceAvailable = false">取消</Button>
</div>
</Modal>
</div>
</template>
<script>
import { receiptList, saveReceipt } from '@/api/member.js';
import { TINumber } from '@/plugins/RegExp.js';
export default {
name: 'Invoice',
data () {
return {
list: [], // 发票列表
form: { // 添加发票表单
type: 2,
receiptTitle: '', // 发票抬头
taxpayerId: '', // 纳税人识别号
receiptContent: '商品明细'
},
ruleInline: { // 验证规则
receiptTitle: [{ required: true, message: '请填写公司名称' }],
taxpayerId: [
{ required: true, message: '请填写纳税人识别号' },
{ pattern: TINumber, message: '请填写正确的纳税人识别号' }
]
},
loading: false, // 加载状态
invoiceAvailable: false // 添加发票模态框显隐
};
},
mounted () {
this.getList()
},
methods: {
getList () {
receiptList().then(res => {
this.list = res.result.records;
})
},
save () {
this.$refs.form.validate((valid) => {
if (valid) {
this.loading = true;
let params = {
receiptTitle: this.form.receiptTitle,
taxpayerId: this.form.taxpayerId,
receiptContent: this.form.receiptContent
};
saveReceipt(params).then((res) => {
this.loading = false;
if (res.success) {
this.getList();
this.resetData();
this.invoiceAvailable = false;
}
}).catch(() => {
this.loading = false;
});
}
});
},
resetData () {
this.$refs.form.resetFields();
}
}
};
</script>
<style scoped lang="scss">
.receipt-item {
cursor: pointer;
font-size: 14px;
border-bottom: 1px solid #eee;
> p {
padding: 12px 0;
}
}
</style>

View File

@@ -0,0 +1,212 @@
<template>
<div class="wrapper">
<card _Title="账户安全"/>
<!-- 手机号验证 -->
<Form ref="formData" :model="formData" label-position="left" :label-width="100" :rules="ruleInLines"
v-if="(status == 2 || status == 3) && !showPwd">
<FormItem label="手机号">
<div class="phone">1234567890</div>
</FormItem>
<FormItem label="图片验证码" prop="picture" style="width: 350px">
<i-input v-model="formData.picture" size="large" maxlength="4"></i-input>
</FormItem>
<FormItem label="短信验证码" prop="msg">
<i-input v-model="formData.msg" size="large" maxlength="6" style="width: 250px">
<span slot="append">输入验证码</span>
</i-input>
</FormItem>
</Form>
<div slot="footer" v-if="(status == 2 || status == 3) && !showPwd" style="text-align: center;width: 50%">
<Button type="primary" class="ml_10" @click="submitRegister">下一步</Button>
</div>
<!-- 修改 -->
<Form ref="formRegister" :model="formRegister" :rules="ruleInline" :label-width="80" v-if="status == 1 && !showPwd">
<FormItem label="旧密码" prop="password">
<i-input type="password" v-model="formRegister.password" clearable size="large" placeholder="请输入旧密码"
style="width: 300px"
maxlength="12">
<Icon type="md-lock" slot="prepend"></Icon>
</i-input>
</FormItem>
<FormItem label="新密码" prop="newPassword">
<i-input type="password" v-model="formRegister.newPassword" clearable size="large" placeholder="请输入新密码"
style="width: 300px"
maxlength="12">
<Icon type="md-lock" slot="prepend"></Icon>
</i-input>
</FormItem>
<FormItem label="确认密码" prop="againPassword">
<i-input type="password" v-model="formRegister.againPassword" clearable size="large" placeholder="请输入确认密码"
style="width: 300px"
maxlength="12">
<Icon type="md-lock" slot="prepend"></Icon>
</i-input>
</FormItem>
</Form>
<div slot="footer" v-if="status == 1 && !showPwd" style="width: 50%;text-align: center">
<Button type="primary" class="ml_10" @click="handleRegist">修改</Button>
</div>
<!-- 设置&修改的第二种情况 -->
<Form ref="formDataUpdate" :model="formDataUpdate" label-position="left" :label-width="100" :rules="ruleIn"
v-if="showPwd">
<FormItem label="新密码" prop="newPassword">
<i-input type="password" v-model="formDataUpdate.newPassword" clearable size="large" placeholder="请输入新密码"
style="width: 300px"
maxlength="12">
<Icon type="md-lock" slot="prepend"></Icon>
</i-input>
</FormItem>
<FormItem label="确认密码" prop="againPassword">
<i-input type="password" v-model="formDataUpdate.againPassword" clearable size="large" placeholder="请输入确认密码"
style="width: 300px"
maxlength="12">
<Icon type="md-lock" slot="prepend"></Icon>
</i-input>
</FormItem>
</Form>
<div slot="footer" v-if="showPwd" style="text-align: center;width: 50%">
<Button type="primary" class="ml_10" @click="setPassword">设置</Button>
</div>
</div>
</template>
<script>
import {
setPwd,
editPwd
} from '@/api/account';
import {md5} from '@/plugins/md5.js'
export default {
name: 'modifyPwd',
data () {
return {
// 1为修改 2为设置 3为提交校验的下一步
status: '',
showPwd: false, // 显示密码
formData: { // 验证表单
picture: '',
msg: ''
},
formDataUpdate: { // 直接输入新密码表单
newPassword: '',
againPassword: ''
},
formRegister: { // 第三步 新密码表单
password: '',
againPassword: '',
newPassword: ''
},
ruleInLines: {
picture: [
{required: true, message: '请输入图片验证码', trigger: 'blur'}
],
msg: [
{required: true, message: '请输入短信验证码', trigger: 'blur'}
]
},
ruleIn: {
newPassword: [
{required: true, message: '请输入新密码', trigger: 'blur'},
{type: 'string', min: 6, message: '密码不能少于6位'}
],
againPassword: [
{required: true, message: '请输入新密码', trigger: 'blur'},
{type: 'string', min: 6, message: '密码不能少于6位'}
]
},
ruleInline: {
password: [
{required: true, message: '请输入旧密码', trigger: 'blur'}
],
newPassword: [
{required: true, message: '请输入新密码', trigger: 'blur'},
{type: 'string', min: 6, message: '密码不能少于6位'}
],
againPassword: [
{required: true, message: '请输入新密码', trigger: 'blur'},
{type: 'string', min: 6, message: '密码不能少于6位'}
]
}
}
},
mounted () {
this.status = this.$route.query.status
},
methods: {
// 修改
handleRegist () {
this.$refs['formRegister'].validate((valid) => {
if (valid) {
const {newPassword, againPassword, password} = this.formRegister
if (newPassword !== againPassword) {
this.$Message.error({
content: '新旧密码不一致'
});
return
}
const params = {newPassword, password}
params.newPassword = md5(newPassword)
params.password = md5(password)
editPwd(params).then(res => {
if (res.message === 'success' && res.result) {
this.$Message.success('修改密码成功');
this.$router.push('/home')
}
});
}
})
},
// 提交验证
submitRegister () {
this.$refs['formData'].validate((valid) => {
if (valid) {
this.showPwd = true
}
})
},
// 设置密码
setPassword () {
this.$refs['formDataUpdate'].validate((valid) => {
if (valid) {
const {newPassword, againPassword} = this.formDataUpdate
if (newPassword === '') {
this.$Message.error({
content: '请输入密码'
});
return
}
if (newPassword !== againPassword) {
this.$Message.error({
content: '新旧密码不一致'
});
return
}
const params = {password: newPassword}
params.password = md5(newPassword)
setPwd(params).then(res => {
if (res.message === 'success' && res.result) {
this.$Message.success('支付密码设置成功');
this.$router.push('/home')
}
});
}
})
}
}
}
</script>
<style scoped lang="scss">
.wrapper {
text-align: center;
}
.phone {
text-align: left;
}
</style>

View File

@@ -0,0 +1,105 @@
<template>
<div class="point">
<card _Title="我的积分" />
<div class="point-content">
<span>剩余积分<span>{{pointObj.variablePoint || 0}}</span></span>
<span>累计获得<span>{{pointObj.point || 0}}</span></span>
</div>
<h3>积分日志</h3>
<Table :columns="logColumns" :data="logData.records">
<template slot-scope="{ row }" slot="point">
<div><span>{{row.pointType == "1" ? '+' : '-'}}</span>{{ row.variablePoint }}</div>
</template>
</Table>
<!-- 分页 -->
<Page
style="float:right;margin-top:10px"
:current="params.pageNumber"
:total="logData.total"
:page-size="params.pageSize"
@on-change="changePage"
@on-page-size-change="changePageSize"
:page-size-opts="[10, 20, 50]"
size="small"
show-total
show-elevator
></Page>
</div>
</template>
<script>
import {memberPoint, memberPointHistory} from '@/api/member.js'
export default {
name: 'Point',
data () {
return {
logData: {}, // 积分日志
pointObj: {}, // 积分明细
loading: false, // 请求接口加载框
params: { // 积分列表请求参数
pageNumber: 1,
pageSize: 10
},
logColumns: [ // table展示数据
{
title: '日志内容',
key: 'content',
align: 'center'
},
{
title: '时间',
key: 'createTime',
align: 'center'
},
{
title: '积分明细',
slot: 'point',
align: 'center'
}
]
}
},
mounted () {
this.getHistory()
this.getPoint()
},
methods: {
getHistory () {
memberPointHistory(this.params).then(res => {
this.logData = res.result;
})
},
getPoint () { // 获取积分详情
memberPoint().then(res => {
if (res.success) this.pointObj = res.result
})
},
changePage (val) {
this.pageNumber = val
this.getHistory()
},
changePageSize (val) {
this.param.pageSize = val
this.params.pageNumber = 1
this.getHistory()
}
}
}
</script>
<style lang="scss" scoped>
h3 {
font-size: 16px;
margin: 20px 10px;
}
.point-content {
text-align: center;
margin-bottom: 30px;
>span{
color: #999;
margin-right: 100px;
span {
color: $theme_color;
font-size: 24px;
}
}
}
</style>

View File

@@ -0,0 +1,90 @@
<template>
<div class="wrapper">
<card _Title="用户信息" />
<Form :model="formItem" :rules="rules" ref="form" :label-width="80">
<FormItem label="头像">
<Avatar v-if="formItem.face" :src="formItem.face" size="80"/>
<Avatar v-else icon="ios-person" size="80"/>
<Upload
:show-upload-list="false"
:on-success="handleSuccess"
:before-upload="handleBeforeUpload"
:format="['jpg','jpeg','png']"
:action="action"
:headers="accessToken"
>
<Button class="mt_10">上传头像</Button>
</Upload>
</FormItem>
<FormItem label="昵称" prop="nickName">
<Input class="wrapper-user-name" style="width:187px" v-model="formItem.nickName" placeholder="" />
</FormItem>
<FormItem label="生日">
<DatePicker type="date" placeholder="选择您的生日" v-model="formItem.birthday"></DatePicker>
</FormItem>
<FormItem label="性别">
<RadioGroup v-model="formItem.sex">
<Radio :label="1"></Radio>
<Radio :label="0"></Radio>
</RadioGroup>
</FormItem>
<FormItem>
<Button type="primary" @click="save">确认修改</Button>
</FormItem>
</Form>
</div>
</template>
<script>
import storage from '@/plugins/storage.js';
import { editMemberInfo } from '@/api/account.js';
import { commonUrl } from '@/plugins/request.js';
export default {
name: 'Profile',
data () {
return {
rules: { // 验证规则
nickName: [{required: true, message: '用户昵称不能为空'}, { max: 16, message: '用户昵称不能超过15个字符' }]
},
formItem: {}, // 表单数据
action: commonUrl + '/common/upload/file', // 上传接口
accessToken: {} // 验证token
}
},
mounted () {
this.formItem = JSON.parse(storage.getItem('userInfo'))
this.accessToken.accessToken = storage.getItem('accessToken');
},
methods: {
save () {
this.$refs.form.validate(valid => {
if (valid) {
let params = {
birthday: this.$options.filters.unixToDate(this.formItem.birthday / 1000, 'yyyy-MM-dd'),
face: this.formItem.face,
nickName: this.formItem.nickName,
sex: this.formItem.sex
}
editMemberInfo(params).then(res => {
if (res.success) {
this.$Message.success('修改个人资料成功')
storage.setItem('userInfo', res.result)
}
})
}
})
},
handleSuccess (res, file) {
this.$set(this.formItem, 'face', res.result)
},
handleBeforeUpload () {}
}
}
</script>
<style scoped lang="scss">
</style>

View File

@@ -0,0 +1,249 @@
<template>
<div class="add-eval">
<div class="title">
<card _Title="订单评价" :_Size="16"></card>
<p>
<span class="color999">订单号</span><span>{{$route.query.sn}}</span>
<span class="color999 ml_20" v-if="order.order">{{order.order.paymentTime}}</span>
</p>
</div>
<!-- 物流评分服务评分 -->
<div class="delivery-rate">
<div class="fontsize_16">物流服务评价</div>
<div class="color999">
<span>物流评价<Rate v-model="form.deliveryScore" /></span>
<span>服务评价<Rate v-model="form.serviceScore" /></span>
<span>描述评价<Rate v-model="form.descriptionScore" /></span>
</div>
</div>
<!-- 添加订单评价 左侧商品详情 右侧评价框 -->
<ul class="goods-eval">
<li >
<div class="goods-con">
<img :src="orderGoods.image" class="hover-pointer" alt="" width="100" @click="goGoodsDetail(orderGoods.skuId, orderGoods.goodsId)">
<p class="hover-pointer color999" @click="goGoodsDetail(orderGoods.skuId, orderGoods.goodsId)">{{orderGoods.goodsName}}</p>
<p>{{orderGoods.goodsPrice | unitPrice('¥')}}</p>
</div>
<div class="eval-con">
<div>
<span class="color999">商品评价</span>
<RadioGroup style="margin-bottom:5px;color:#999" v-model="orderGoods.grade">
<Radio label="GOOD">好评</Radio>
<Radio label="MODERATE">中评</Radio>
<Radio label="WORSE">差评</Radio>
</RadioGroup>
<Input type="textarea" maxlength="500" show-word-limit :rows="4" v-model="orderGoods.content" />
</div>
<div style="display:flex;align-items:center;">
<div class="demo-upload-list" v-for="(img, index) in orderGoods.uploadList" :key="index">
<img :src="img">
<div class="demo-upload-list-cover">
<Icon type="ios-eye-outline" @click.native="handleView(img)"></Icon>
<Icon type="ios-trash-outline" @click.native="handleRemove(index)"></Icon>
</div>
</div>
<Upload
:show-upload-list="false"
:on-success="handleSuccess"
:before-upload="handleBeforeUpload"
:format="['jpg','jpeg','png']"
:action="action"
:headers="accessToken"
style="display: inline-block;width:58px;">
<div class="hover-pointer icon-upload" style="">
<Icon type="ios-camera" size="20"></Icon>
</div>
</Upload>
</div>
</div>
</li>
</ul>
<Button type="primary" class="mt_10" :loading="loading" @click="save">发表</Button>
<Modal title="View Image" v-model="visible">
<img :src="previewImage" v-if="visible" style="width: 100%">
</Modal>
</div>
</template>
<script>
import { orderDetail } from '@/api/order.js';
import { addEvaluation } from '@/api/member.js';
import { commonUrl } from '@/plugins/request.js';
import storage from '@/plugins/storage';
export default {
data () {
return {
order: {}, // 订单详情
orderGoods: {}, // 订单商品
form: { // 评分展示
deliveryScore: 5,
serviceScore: 5,
descriptionScore: 5
}, // 表单
visible: false, // 图片预览
action: commonUrl + '/common/upload/file', // 上传地址
accessToken: {}, // 验证token
previewImage: '', // 预览图片地址
loading: false // 提交加载状态
}
},
methods: {
getOrderDetail () {
orderDetail(this.$route.query.sn).then(res => {
this.order = res.result
this.orderGoods = res.result.orderItems[this.$route.query.index]
this.$set(this.orderGoods, 'grade', 'GOOD')
this.orderGoods.uploadList = []
})
},
save () {
if (!this.form.serviceScore || !this.form.deliveryScore) {
this.$Message.warning('物流服务评价不能为空')
return false;
}
if (!this.form.descriptionScore) {
this.$Message.warning('描述评价不能为空')
}
this.loading = true;
let goods = this.orderGoods
let params = {
goodsId: goods.goodsId,
orderItemSn: goods.sn,
skuId: goods.skuId,
descriptionScore: this.form.descriptionScore,
serviceScore: this.form.serviceScore,
deliveryScore: this.form.deliveryScore,
grade: goods.grade,
content: goods.content || '',
images: goods.uploadList.toString()
}
addEvaluation(params).then(res => {
this.loading = false
if (res.success) {
this.$Message.success('评价成功')
this.$router.push('/home/CommentList')
}
}).catch(() => {
this.loading = false;
})
},
goGoodsDetail (skuId, goodsId) {
let routerUrl = this.$router.resolve({
path: '/goodsDetail',
query: {skuId, goodsId}
})
window.open(routerUrl.href, '_blank')
},
handleView (name) {
this.previewImage = name;
this.visible = true;
},
handleRemove (index) {
this.orderGoods.uploadList.splice(index, 1)
this.$forceUpdate()
},
handleSuccess (res, file) {
this.orderGoods.uploadList.push(res.result)
this.$forceUpdate()
},
handleBeforeUpload () {
const check = this.orderGoods.uploadList.length < 10;
if (!check) {
this.$Notice.warning({
title: '最多可以上传九张图片'
});
return check;
}
}
},
mounted () {
this.accessToken.accessToken = storage.getItem('accessToken');
this.getOrderDetail()
}
}
</script>
<style lang="scss" scoped>
.delivery-rate {
display: flex;
align-items: center;
margin-top: 20px;
height: 50px;
border-bottom: 1px solid #eee;
>div:nth-child(1) {
width: 120px;
font-weight: bold;
}
}
.goods-eval li{
display: flex;
border-bottom: 1px solid #eee;
.goods-con {
width: 30%;
padding: 20px;
text-align: center;
p {
word-wrap: wrap;
&:hover{ color: $theme_color; }
}
}
.eval-con {
width: 70%;
padding: 20px;
}
}
.demo-upload-list{
display: inline-block;
width: 60px;
height: 60px;
text-align: center;
line-height: 60px;
border: 1px solid transparent;
border-radius: 4px;
overflow: hidden;
background: #fff;
position: relative;
box-shadow: 0 1px 1px rgba(0,0,0,.2);
margin-right: 4px;
margin-top: 10px;
}
.demo-upload-list img{
width: 100%;
height: 100%;
}
.demo-upload-list-cover{
display: none;
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
background: rgba(0,0,0,.6);
}
.demo-upload-list:hover .demo-upload-list-cover{
display: block;
}
.demo-upload-list-cover i{
color: #fff;
font-size: 20px;
cursor: pointer;
margin: 0 2px;
}
.icon-upload {
width: 58px;
height:58px;
line-height: 58px;
text-align:center;
display: inline-block;
border:1px dashed #999;
border-radius: 4px;
margin-top: 10px;
&:hover{
cursor: pointer;
border-color: $theme_color;
}
}
</style>

View File

@@ -0,0 +1,172 @@
<template>
<div class="add-eval">
<div class="title">
<card _Title="评价详情" :_Size="16"></card>
<p>
<span class="color999">创建人</span><span>{{orderGoods.createBy | secrecyMobile}}</span>
<span class="color999 ml_20">{{orderGoods.createTime}}</span>
</p>
</div>
<!-- 物流评分服务评分 -->
<div class="delivery-rate">
<div class="fontsize_16">物流服务评价</div>
<div class="color999">
<span>物流评价<Rate disabled :value="Number(orderGoods.deliveryScore)" /></span>
<span>服务评价<Rate disabled :value="Number(orderGoods.serviceScore)" /></span>
<span>服务评价<Rate disabled :value="Number(orderGoods.descriptionScore)" /></span>
</div>
</div>
<!-- 添加订单评价 左侧商品详情 右侧评价框 -->
<ul class="goods-eval">
<li >
<div class="goods-con">
<img :src="orderGoods.goodsImage" class="hover-pointer" alt="" width="100" @click="goGoodsDetail(orderGoods.skuId, orderGoods.goodsId)">
<p class="hover-pointer color999" @click="goGoodsDetail(orderGoods.skuId, orderGoods.goodsId)">{{orderGoods.goodsName}}</p>
</div>
<div class="eval-con">
<div>
<span class="color999">商品评价</span>
<RadioGroup style="margin-bottom:5px;color:#999" v-model="orderGoods.grade">
<Radio label="GOOD" disabled>好评</Radio>
<Radio label="MODERATE" disabled>中评</Radio>
<Radio label="WORSE" disabled>差评</Radio>
</RadioGroup>
<Input type="textarea" maxlength="500" readonly show-word-limit :rows="4" v-model="orderGoods.content" />
</div>
<div style="display:flex;align-items:center;">
<template v-if="orderGoods.image">
<div class="demo-upload-list" v-for="(img, index) in orderGoods.image.split(',')" :key="index">
<img :src="img">
<div class="demo-upload-list-cover">
<Icon type="ios-eye-outline" @click.native="handleView(img)"></Icon>
</div>
</div>
</template>
</div>
</div>
</li>
</ul>
<Modal title="View Image" v-model="visible">
<img :src="previewImage" v-if="visible" style="width: 100%">
</Modal>
</div>
</template>
<script>
import { evaluationDetail } from '@/api/member.js';
export default {
data () {
return {
order: {}, // 订单详情
orderGoods: {}, // 订单商品
visible: false, // 图片预览
previewImage: '', // 预览图片链接
loading: false // 加载状态
}
},
methods: {
getDetail () {
evaluationDetail(this.$route.query.id).then(res => {
if (res.success) this.orderGoods = res.result
})
},
goGoodsDetail (skuId, goodsId) {
let routerUrl = this.$router.resolve({
path: '/goodsDetail',
query: {skuId, goodsId}
})
window.open(routerUrl.href, '_blank')
},
handleView (name) {
this.previewImage = name;
this.visible = true;
}
},
mounted () {
this.getDetail()
}
}
</script>
<style lang="scss" scoped>
.delivery-rate {
display: flex;
align-items: center;
margin-top: 20px;
height: 50px;
border-bottom: 1px solid #eee;
>div:nth-child(1) {
width: 120px;
font-weight: bold;
}
}
.goods-eval li{
display: flex;
border-bottom: 1px solid #eee;
.goods-con {
width: 30%;
padding: 20px;
text-align: center;
p {
word-wrap: wrap;
&:hover{ color: $theme_color; }
}
}
.eval-con {
width: 70%;
padding: 20px;
}
}
.demo-upload-list{
display: inline-block;
width: 60px;
height: 60px;
text-align: center;
line-height: 60px;
border: 1px solid transparent;
border-radius: 4px;
overflow: hidden;
background: #fff;
position: relative;
box-shadow: 0 1px 1px rgba(0,0,0,.2);
margin-right: 4px;
margin-top: 10px;
}
.demo-upload-list img{
width: 100%;
height: 100%;
}
.demo-upload-list-cover{
display: none;
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
background: rgba(0,0,0,.6);
}
.demo-upload-list:hover .demo-upload-list-cover{
display: block;
}
.demo-upload-list-cover i{
color: #fff;
font-size: 20px;
cursor: pointer;
margin: 0 2px;
}
.icon-upload {
width: 58px;
height:58px;
line-height: 58px;
text-align:center;
display: inline-block;
border:1px dashed #999;
border-radius: 4px;
margin-top: 10px;
&:hover{
cursor: pointer;
border-color: $theme_color;
}
}
</style>

View File

@@ -0,0 +1,144 @@
<template>
<div>
<card _Title="收货地址" />
<div class="add-box">
<Form
:model="formData"
ref="form"
label-position="left"
:label-width="100"
:rules="ruleInline"
>
<FormItem label="收件人" prop="name">
<i-input v-model="formData.name" style="width: 600px"></i-input>
</FormItem>
<FormItem label="收件地区" prop="address">
<i-input
v-model="formData.address"
disabled
style="width: 600px"
></i-input>
<Button type="primary" size="small" @click="$refs.map.showMap = true">选择</Button>
</FormItem>
<FormItem label="详细地址" prop="detail">
<i-input v-model="formData.detail" style="width: 600px"></i-input>
</FormItem>
<FormItem label="手机号码" prop="mobile">
<i-input v-model="formData.mobile" style="width: 600px"></i-input>
</FormItem>
<FormItem label="地址别名">
<i-input
v-model="formData.alias"
length
:maxlength="4"
placeholder="请输入地址别名,例如公司"
style="width: 600px"
></i-input>
</FormItem>
<FormItem label="默认地址">
<i-switch v-model="formData.isDefault" />
</FormItem>
</Form>
</div>
<div class="mt_20">
<Button type="primary" class="mr_10" :loading="loading" @click="save"
>保存收货地址</Button
>
<Button @click="$router.back()">返回</Button>
</div>
<lili-map ref="map" @getAddress="getAddress"></lili-map>
</div>
</template>
<script>
import card from '@/components/card';
import liliMap from '@/components/map';
import {
newMemberAddress,
editMemberAddress,
getAddrDetail
} from '@/api/address';
export default {
name: 'AddAddress',
data () {
return {
formData: { // 添加地址表单
isDefault: false
},
ruleInline: { // 验证规则
name: [{ required: true, message: '请输入姓名', trigger: 'blur' }],
address: [{ required: true, message: '请输入地址', trigger: 'change' }],
detail: [
{ required: true, message: '请输入详细地址', trigger: 'blur' }
],
mobile: [
]
},
loading: false, // 加载状态
mapMsg: {} // 地图信息
};
},
methods: {
save () {
this.$refs.form.validate((valid) => {
if (valid) {
const params = JSON.parse(JSON.stringify(this.formData));
params.consigneeAddressPath = params.address.replace(/\s/g, ',');
delete params.address;
this.loading = true;
if (this.$route.query.id) {
editMemberAddress(params).then((res) => {
if (res.code === 200) {
this.loading = false;
this.$router.push('/home/MyAddress');
}
}).catch(() => { this.loading = false; });
} else {
newMemberAddress(params).then((res) => {
if (res.code === 200) {
this.loading = false;
this.$router.push('/home/MyAddress');
}
}).catch(() => { this.loading = false; });
}
}
});
},
getAddrById (id) {
// 获取地址详情
getAddrDetail(id).then((res) => {
if (res.code === 200) {
console.log(res);
const data = res.result;
data.address = res.result.consigneeAddressPath.replace(/,/g, ' ');
this.formData = data;
}
});
},
getAddress (item) {
// 获取地图选择信息
console.log(item);
this.mapMsg = item;
this.$set(this.formData, 'address', item.addr);
this.$set(this.formData, 'consigneeAddressIdPath', item.addrId);
this.$set(this.formData, 'detail', item.detail);
this.formData.lat = item.position.lat;
this.formData.lon = item.position.lng;
}
},
mounted () {
const id = this.$route.query.id;
if (id) this.getAddrById(id);
},
components: {
card,
liliMap
}
};
</script>
<style scoped lang="scss">
.add-box {
margin: 40px 0;
}
</style>

View File

@@ -0,0 +1,249 @@
<template>
<div class="wrapper">
<!-- 卡片组件 -->
<card _Title="我的售后" :_Size="16"></card>
<!-- 搜索 筛选 -->
<div class="mb_20 box">
<div class="global_float_right" >
<Input
class="width_300"
search
enter-button
v-model="params.keywords"
@on-search="getList"
placeholder="请输入订单号搜索"
/>
</div>
</div>
<!-- 列表 -->
<empty v-if="orderList.length === 0" />
<div class="order-content" v-else>
<template v-for="(order, onderIndex) in orderList">
<div
class="order-list"
:key="onderIndex"
>
<div class="order-header">
<div>
<div v-if="order.serviceStatus">{{filterOrderStatus(order.serviceStatus)}}</div>
<div>
售后单号{{ order.sn }} &nbsp; &nbsp; &nbsp;{{order.createTime}}
&nbsp; &nbsp;{{ order.memberName | secrecyMobile }}
</div>
</div>
<div>
<span>{{ order.applyRefundPrice | unitPrice("¥") }}</span>
</div>
</div>
<div class="order-body">
<div class="goods-list">
<img @click="goodsDetail(order.skuId, order.goodsId)" class="hover-color" :src="order.goodsImage" alt="" />
<div>
<div class="hover-color" @click="goodsDetail(order.skuId, order.goodsId)">{{ order.goodsName }}</div>
<div class="mt_10">
<span class="global_color"
>{{ order.flowPrice | unitPrice("¥") }} </span
>x {{ order.num }}
</div>
</div>
</div>
<div>
<span @click="shopPage(order.shopId)">{{ order.storeName }}</span>
</div>
<div>
<!-- 订单基础操作 -->
<Button @click="goDetail(order.sn)" size="small">售后详情</Button>
<Button @click="cancel(order.sn)" v-if="order.afterSaleAllowOperationVO.cancel" size="small">取消售后</Button>
</div>
</div>
</div>
</template>
<Spin size="large" fix v-if="spinShow"></Spin>
</div>
<!-- 分页 -->
<div class="page-size">
<Page :total="total" @on-change="changePageNum"
@on-page-size-change="changePageSize"
:page-size="params.pageSize"
show-sizer>
</Page>
</div>
</div>
</template>
<script>
import { afterSaleList, cancelAfterSale } from '@/api/member.js';
import { afterSaleStatusList } from '../enumeration.js'
export default {
name: 'AfterSale',
data () {
return {
orderList: [], // 订单列表
params: { // 请求参数
pageNumber: 1,
pageSize: 10,
keywords: ''
},
// 状态数组
afterSaleStatusList,
total: 0, // 订单总数
spinShow: false // 加载状态
};
},
mounted () {
this.getList();
},
methods: {
goDetail (sn) { // 跳转售后详情
this.$router.push({
name: 'AfterSaleDetail',
query: {sn}
})
},
cancel (sn) { // 取消售后申请
this.$Modal.confirm({
title: '取消',
content: '<p>确定取消此次售后申请吗?</p>',
onOk: () => {
cancelAfterSale(sn).then(res => {
if (res.success) {
this.$Message.success('取消售后申请成功')
this.getList()
}
})
},
onCancel: () => {}
});
},
goodsDetail (skuId, goodsId) {
// 跳转商品详情
let routeUrl = this.$router.resolve({
path: '/goodsDetail',
query: { skuId, goodsId }
});
window.open(routeUrl.href, '_blank');
},
// 跳转店铺首页
shopPage (id) {
let routeUrl = this.$router.resolve({
path: '/Merchant',
query: { id: id }
});
window.open(routeUrl.href, '_blank');
},
getList () {
this.spinShow = true;
let params = JSON.parse(JSON.stringify(this.params))
afterSaleList(params).then(res => {
this.spinShow = false
if (res.success) {
this.orderList = res.result.records;
this.total = res.result.total;
}
});
},
changePageNum (val) {
this.params.pageNumber = val;
this.getList()
},
changePageSize (val) {
this.pageNumber = 1;
this.params.pageSize = val;
this.getList()
},
filterOrderStatus (status) { // 获取订单状态中文
const ob = this.afterSaleStatusList.filter(e => { return e.status === status });
return ob[0].name
}
}
};
</script>
<style scoped lang="scss">
.wrapper {
margin-bottom: 40px;
}
.box {
overflow: hidden;
}
.page-size {
margin: 15px 0px;
display: flex;
justify-content: flex-end;
align-items: center;
}
/** 订单列表 */
.order-list {
border: 1px solid #ddd;
border-radius: 3px;
margin-bottom: 10px;
&:hover{
.del-btn{visibility: visible;}
}
.del-btn{
visibility: hidden;
}
.order-header {
display: flex;
align-items: center;
padding: 10px;
justify-content: space-between;
border-bottom: 1px solid #ddd;
> div:nth-child(1) > div:nth-child(2) {
font-size: 12px;
color: #999;
margin-top: 3px;
}
}
.order-body {
display: flex;
justify-content: space-between;
color: #999;
padding: 10px;
.goods-list {
width: 500px;
display: flex;
margin-bottom: 10px;
img {
width: 60px;
height: 60px;
margin-right: 10px;
}
> div {
flex: 1;
}
}
> div:nth-child(2) {
width: 150px;
text-align: center;
span {
color: #438cde;
cursor: pointer;
&:hover {
color: $theme_color;
}
}
.ivu-icon {
color: #ff8f23;
cursor: pointer;
&:hover {
color: $theme_color;
}
}
}
> div:nth-child(3) {
width: 100px;
.ivu-btn {
margin-bottom: 10px;
}
}
}
}
</style>

View File

@@ -0,0 +1,158 @@
<template>
<div class="order-detail">
<card _Title="售后详情" :_Size="16"></card>
<div class="order-card">
<h3>{{filterOrderStatus(afterSale.serviceStatus)}}</h3>
<p class="global_color fontsize_18">{{ afterSale.orderStatusValue }}</p>
<p>售后单号{{ afterSale.sn }} &nbsp;&nbsp;&nbsp;订单号{{afterSale.orderSn}}</p>
<div style="color:#999;" class="operation-time">创建时间{{afterSale.createTime}}</div>
<div class="service-after">
<div>
本次售后服务由<span>{{afterSale.storeName}}</span>为您提供
</div>
<div>
<img :src="afterSale.goodsImage" alt="" width="60" height="60">
<span>{{afterSale.goodsName}}</span>
</div>
</div>
</div>
<div class="order-card">
<h3>售后进程</h3>
<Steps class="progress" :current="logList.length" direction="vertical">
<Step
:content="'操作人:'+ log.operatorName + ' ' + log.createTime"
:title="log.message"
v-for="(log, index) in logList"
:key="index"
></Step>
</Steps>
</div>
<div class="order-card">
<h3 class="mb_10">服务单信息</h3>
<table border="1" cellpadding='0' cellspacing="0">
<tr>
<td>退款方式</td><td>{{afterSale.refundWay == 'ORIGINAL' ? '原路退回' : '账号退款'}}{{afterSale.applyRefundPrice | unitPrice('¥')}}</td>
</tr>
<tr>
<td>商品处理方式</td><td>{{afterSale.serviceType == 'RETURN_MONEY' ? '退款' : '退货'}}</td>
</tr>
<tr>
<td>退款原因</td><td>{{afterSale.reason}}</td>
</tr>
<tr>
<td>问题描述</td><td>{{afterSale.problemDesc}}</td>
</tr>
</table>
</div>
</div>
</template>
<script>
import { afterSaleDetail, afterSaleReason, afterSaleLog } from '@/api/member.js';
import { afterSaleStatusList } from '../enumeration.js'
export default {
name: 'aftersale-detail',
data () {
return {
afterSale: {}, // 售后详情数据
logList: [], // 日志
afterSaleStatusList // 售后状态列表
};
},
methods: {
getDetail () { // 售后详情
afterSaleDetail(this.$route.query.sn).then(res => {
if (res.success) {
this.afterSale = res.result;
afterSaleReason(this.afterSale.serviceType).then(res => {
res.result.forEach(element => {
if (element.id === this.afterSale.reason) {
this.$set(this.afterSale, 'reason', element.reason)
}
});
})
}
})
},
getLog () {
afterSaleLog(this.$route.query.sn).then(res => {
this.logList = res.result;
})
},
filterOrderStatus (status) { // 获取订单状态中文
const ob = this.afterSaleStatusList.filter(e => { return e.status === status });
return ob[0].name
}
},
mounted () {
this.getDetail();
this.getLog()
}
};
</script>
<style lang="scss" scoped>
.order-card {
padding: 10px;
padding-bottom: 10px;
margin-bottom: 10px;
border-bottom: 1px solid #e8eaec;
position: relative;
.global_color {
color: $theme_color;
}
p {
color: #999;
margin: 3px;
}
h3 {
font-weight: normal;
font-size: 16px;
}
.operation-time {
position: absolute;
right: 20px;
top: 10px;
}
&:last-child{
border: none;
}
}
.service-after {
border: 1px solid #eee;
display: flex;
height: 80px;
padding: 10px;
>div:nth-child(1) {
width: 400px;
font-size: 15px;
font-weight: bold;
text-align: center;
line-height: 60px;
span{color: $theme_color;}
border-right: 1px solid #eee;
}
>div:nth-child(2){
padding-left: 15px;
img{vertical-align: top;}
span{color: #999;}
}
}
/** 售后进度条 */
.progress {
margin: 15px 0;
}
table{
border-color: #eee;
width: 100%;
color: #999;
tr{
td:nth-child(1){
width: 200px;
}
}
td{
padding: 5px;
}
}
</style>

View File

@@ -0,0 +1,273 @@
<template>
<div class="apply-after-sale">
<card _Title="申请售后"></card>
<Table
border
:columns="columns"
:data="goodsData"
>
<template slot-scope="{ row }" slot="goodsName">
<div style="padding:5px;display:flex;">
<img :src="row.image" style="vertical-align: top;" width="60" alt=""> <span class="ml_10">{{row.goodsName}}</span>
</div>
</template>
<template slot-scope="{ row }" slot="goodsPrice">
<div>{{row.goodsPrice | unitPrice('¥')}}</div>
</template>
</Table>
<div>
<Form :model="form" ref="form" :rules="rules" :label-width="80">
<FormItem label="售后类别">
<RadioGroup v-model="form.serviceType" @on-change="changeReason">
<Radio label="RETURN_GOODS">退货</Radio>
<Radio label="RETURN_MONEY">退款</Radio>
</RadioGroup>
</FormItem>
<FormItem label="提交数量" prop="num">
<Input type="number" v-model="form.num" style="width:260px" />
</FormItem>
<FormItem label="提交原因" prop="reason">
<Select v-model="form.reason" style="width:260px">
<Option v-for="item in reasonList" :value="item.id" :key="item.id">{{ item.reason }}</Option>
</Select>
</FormItem>
<FormItem label="问题描述" prop="problemDesc">
<Input type="textarea" :rows="4" maxlength="500" style="width:260px" show-word-limit v-model="form.problemDesc" />
</FormItem>
<FormItem label="图片信息">
<div style="display:flex;align-items:center;">
<div class="demo-upload-list" v-for="(img, index) in uploadList" :key="index">
<img :src="img">
<div class="demo-upload-list-cover">
<Icon type="ios-eye-outline" @click.native="handleView(img)"></Icon>
<Icon type="ios-trash-outline" @click.native="handleRemove(index)"></Icon>
</div>
</div>
<Upload
:show-upload-list="false"
:on-success="handleSuccess"
:before-upload="handleBeforeUpload"
:format="['jpg','jpeg','png']"
:action="action"
:headers="accessToken"
style="display: inline-block;width:58px;">
<div class="hover-pointer icon-upload" style="">
<Icon type="md-add" size="20"></Icon>
</div>
</Upload>
</div>
</FormItem>
<FormItem label="退款方式">
<div>{{info.refundWay == 'ORIGINAL' ? '原路退回' : '账号退款'}}</div>
</FormItem>
<template v-if="info.accountType === 'BANK_TRANSFER' && info.applyRefundPrice != 0">
<FormItem label="开户行" prop="bankDepositName">
<Input v-model="form.bankDepositName" type="text" placeholder="请输入银行开户行" style="width:260px" />
</FormItem>
<FormItem label="开户名" prop="bankAccountName">
<Input v-model="form.bankAccountName" type="text" placeholder="请输入银行开户名" style="width:260px" />
</FormItem>
<FormItem label="银行账号" prop="bankAccountNumber">
<Input v-model="form.bankAccountNumber" type="text" placeholder="请输入银行账号" style="width:260px" />
</FormItem>
</template>
<FormItem label="返回方式">
<div>快递至第三方卖家</div>
</FormItem>
<FormItem>
<Button type="primary" @click="apply">提交申请</Button>
</FormItem>
</Form>
<Modal title="View Image" v-model="visible">
<img :src="previewImage" v-if="visible" style="width: 100%">
</Modal>
</div>
</div>
</template>
<script>
import { afterSaleReason, afterSaleInfo, applyAfterSale } from '@/api/member.js'
import { commonUrl } from '@/plugins/request.js';
import storage from '@/plugins/storage';
import * as RegExp from '@/plugins/RegExp'
export default {
data () {
const checkNum = (rule, value, callback) => {
if (value === '') {
console.log(RegExp);
callback(new Error('请填写提交数量'));
} else if (value > this.info.num) {
callback(new Error('提交数量不能大于购买数量'));
} else if (!RegExp.integer.test(value)) {
callback(new Error('提交数量必须为正整数'));
} else {
callback();
}
};
return {
columns: [ // 表格表头
{title: '商品名称', slot: 'goodsName'},
{title: '价格', slot: 'goodsPrice'},
{title: '购买数量', key: 'num'}
],
goodsData: [], // 商品数据
reasonList: [], // 售后原因列表
info: {}, // 售后信息
form: { // 售后数据
serviceType: 'RETURN_GOODS',
num: 1
},
uploadList: [], // 上传列表
action: commonUrl + '/common/upload/file', // 上传地址
accessToken: {}, // 验证token
visible: false, // 图片预览
previewImage: '', // 预览图片url
rules: { // 验证规则
num: [{ validator: checkNum }],
reason: [{ required: true, message: '请选择提交原因' }],
problemDesc: [{ required: true, message: '请输入问题描述' }],
bankAccountNumber: [
{ required: true, message: '请输入银行卡号' },
{
type: 'string',
pattern: /^([1-9]{1})(\d{14}|\d{18})$/,
message: '请输入正确的银行卡号'
}
],
bankAccountName: [{ required: true, message: '请输入银行开户名' }],
bankDepositName: [{ required: true, message: '请输入银行开户行' }]
}
}
},
methods: {
getInfo () {
afterSaleInfo(this.$route.query.sn).then(res => {
if (res.success) {
this.info = res.result
this.goodsData.push(res.result)
}
})
},
getReason (type) {
afterSaleReason(type).then(res => {
if (res.success) this.reasonList = res.result
})
},
changeReason (type) {
this.getReason(type)
},
apply () {
this.$refs.form.validate(valid => {
if (valid) {
let params = Object.assign(this.info, this.form)
params.images = this.uploadList.toString()
params.orderItemSn = this.$route.query.sn
applyAfterSale(params).then(res => {
if (res.success) {
this.$Message.success('售后申请提交成功,请到售后订单查看!')
this.$router.push({name: 'AfterSale'})
}
})
}
})
},
handleView (name) {
this.previewImage = name;
this.visible = true;
},
handleRemove (index) {
this.uploadList.splice(index, 1)
this.$forceUpdate()
},
handleSuccess (res, file) {
this.uploadList.push(res.result)
this.$forceUpdate()
},
handleBeforeUpload () {
const check = this.uploadList.length < 6;
if (!check) {
this.$Notice.warning({
title: '最多可以上传5张图片'
});
return check;
}
}
},
mounted () {
this.accessToken.accessToken = storage.getItem('accessToken');
this.getInfo()
this.getReason('RETURN_GOODS')
}
}
</script>
<style lang="scss" scoped>
/** 商品信息 */
.order-price {
text-align: right;
margin-top: 30px;
font-size: 16px;
color: #999;
> div > span:nth-child(2) {
width: 130px;
text-align: right;
display: inline-block;
margin-top: 10px;
}
.actrual-price {
color: $theme_color;
font-weight: bold;
font-size: 20px;
}
}
.demo-upload-list{
display: inline-block;
width: 60px;
height: 60px;
text-align: center;
line-height: 60px;
border: 1px solid transparent;
border-radius: 4px;
overflow: hidden;
background: #fff;
position: relative;
box-shadow: 0 1px 1px rgba(0,0,0,.2);
margin-right: 4px;
margin-top: 10px;
}
.demo-upload-list img{
width: 100%;
height: 100%;
}
.demo-upload-list-cover{
display: none;
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
background: rgba(0,0,0,.6);
}
.demo-upload-list:hover .demo-upload-list-cover{
display: block;
}
.demo-upload-list-cover i{
color: #fff;
font-size: 20px;
cursor: pointer;
margin: 0 2px;
}
.icon-upload {
width: 58px;
height:58px;
line-height: 58px;
text-align:center;
display: inline-block;
border:1px dashed #999;
border-radius: 4px;
margin-top: 10px;
&:hover{
cursor: pointer;
border-color: $theme_color;
}
}
</style>

View File

@@ -0,0 +1,235 @@
<template>
<div class="add-eval">
<div class="title">
<card _Title="商品投诉" :_Size="16"></card>
<p>
<span class="color999">订单号</span><span>{{$route.query.sn}}</span>
<span class="color999 ml_20" v-if="order.order">{{order.order.paymentTime}}</span>
</p>
</div>
<ul class="goods-eval">
<li >
<div class="goods-con">
<img :src="orderGoods.image" class="hover-pointer" alt="" width="100" @click="goGoodsDetail(orderGoods.skuId, orderGoods.goodsId)">
<p class="hover-pointer color999" @click="goGoodsDetail(orderGoods.skuId, orderGoods.goodsId)">{{orderGoods.goodsName}}</p>
<p>{{orderGoods.goodsPrice | unitPrice('¥')}}</p>
</div>
<div class="eval-con">
<div>
<span class="color999">投诉主题</span>
<Select v-model="form.complainTopic" style="width:260px;margin-bottom:10px">
<Option v-for="item in reasonList" :value="item.reason" :key="item.id">{{ item.reason }}</Option>
</Select>
<Input type="textarea" maxlength="500" show-word-limit :rows="4" placeholder="请输入投诉内容" v-model="form.content" />
</div>
<div style="display:flex;align-items:center;">
<div class="demo-upload-list" v-for="(img, index) in orderGoods.uploadList" :key="index">
<img :src="img">
<div class="demo-upload-list-cover">
<Icon type="ios-eye-outline" @click.native="handleView(img)"></Icon>
<Icon type="ios-trash-outline" @click.native="handleRemove(index)"></Icon>
</div>
</div>
<Upload
:show-upload-list="false"
:on-success="handleSuccess"
:before-upload="handleBeforeUpload"
:format="['jpg','jpeg','png']"
:action="action"
:headers="accessToken"
style="display: inline-block;width:58px;">
<div class="hover-pointer icon-upload" style="">
<Icon type="ios-camera" size="20"></Icon>
</div>
</Upload>
<div class="describe">上传投诉凭证最多5张</div>
</div>
</div>
</li>
</ul>
<Button type="primary" class="mt_10" :loading="loading" @click="save">提交</Button>
<Modal title="View Image" v-model="visible">
<img :src="previewImage" v-if="visible" style="width: 100%">
</Modal>
</div>
</template>
<script>
import { orderDetail } from '@/api/order.js';
import { afterSaleReason, handleComplain } from '@/api/member.js';
import { commonUrl } from '@/plugins/request.js';
import storage from '@/plugins/storage';
export default {
data () {
return {
order: {}, // 订单详情
orderGoods: {}, // 订单商品
form: { // 投诉表单
complainTopic: '',
content: ''
}, // 表单
visible: false, // 图片预览
action: commonUrl + '/common/upload/file', // 上传地址
accessToken: {}, // 验证token
previewImage: '', // 图片地址
loading: false, // 加载状态
reasonList: [] // 投诉原因
}
},
methods: {
getOrderDetail () {
orderDetail(this.$route.query.sn).then(res => {
this.order = res.result
this.orderGoods = res.result.orderItems[this.$route.query.index]
this.orderGoods.uploadList = []
})
afterSaleReason('COMPLAIN').then(res => {
if (res.success) {
this.reasonList = res.result
this.$set(this.form, 'complainTopic', res.result[0].reason)
this.$forceUpdate()
}
})
},
save () {
let params = {
goodsId: this.orderGoods.goodsId,
complainTopic: this.form.complainTopic,
content: this.form.content,
images: this.orderGoods.uploadList.toString(),
orderSn: this.$route.query.sn,
skuId: this.orderGoods.skuId
}
handleComplain(params).then(res => {
if (res.success) {
this.$Message.success('投诉申请已提交,感谢您的反馈')
this.$router.push({name: 'ComplainList'})
}
})
},
goGoodsDetail (skuId, goodsId) {
let routerUrl = this.$router.resolve({
path: '/goodsDetail',
query: {skuId, goodsId}
})
window.open(routerUrl.href, '_blank')
},
handleView (name) {
this.previewImage = name;
this.visible = true;
},
handleRemove (index) {
this.orderGoods.uploadList.splice(index, 1)
this.$forceUpdate()
},
handleSuccess (res, file) {
this.orderGoods.uploadList.push(res.result)
this.$forceUpdate()
},
handleBeforeUpload () {
const check = this.orderGoods.uploadList.length < 6;
if (!check) {
this.$Notice.warning({
title: '最多可以上传五张图片'
});
return check;
}
}
},
mounted () {
this.accessToken.accessToken = storage.getItem('accessToken');
this.getOrderDetail()
}
}
</script>
<style lang="scss" scoped>
.delivery-rate {
display: flex;
align-items: center;
margin-top: 20px;
height: 50px;
border-bottom: 1px solid #eee;
>div:nth-child(1) {
width: 30%;
font-weight: bold;
}
}
.goods-eval li{
display: flex;
border-bottom: 1px solid #eee;
.goods-con {
width: 30%;
padding: 20px;
text-align: center;
p {
word-wrap: wrap;
&:hover{ color: $theme_color; }
}
}
.eval-con {
width: 70%;
padding: 20px;
}
}
.demo-upload-list{
display: inline-block;
width: 60px;
height: 60px;
text-align: center;
line-height: 60px;
border: 1px solid transparent;
border-radius: 4px;
overflow: hidden;
background: #fff;
position: relative;
box-shadow: 0 1px 1px rgba(0,0,0,.2);
margin-right: 4px;
margin-top: 10px;
}
.demo-upload-list img{
width: 100%;
height: 100%;
}
.demo-upload-list-cover{
display: none;
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
background: rgba(0,0,0,.6);
}
.demo-upload-list:hover .demo-upload-list-cover{
display: block;
}
.demo-upload-list-cover i{
color: #fff;
font-size: 20px;
cursor: pointer;
margin: 0 2px;
}
.icon-upload {
width: 58px;
height:58px;
line-height: 58px;
text-align:center;
display: inline-block;
border:1px dashed #999;
border-radius: 4px;
margin-top: 10px;
&:hover{
cursor: pointer;
border-color: $theme_color;
}
}
.describe{
font-size: 12px;
color: #999;
position:relative;
top: 46px;
left: -60px;
}
</style>

View File

@@ -0,0 +1,132 @@
<template>
<div>
<card _Title="收货地址" _More="添加新地址" _Src="/home/addAddress"></card>
<div class="address-box" v-for="(item, index) in list" :key="index">
<div class="address-header">
<span
>{{ item.name }}
<Tag class="ml_10" v-if="item.isDefault" color="red">默认地址</Tag>
<Tag class="ml_10" v-if="item.alias" color="warning">{{
item.alias
}}</Tag>
</span>
<div class="address-action">
<span @click="edit(item.id)"><Icon type="edit"></Icon>修改</span>
<span @click="del(item.id)"><Icon type="trash-a"></Icon>删除</span>
</div>
</div>
<div class="address-content">
<p>
<span class="address-content-title"> :</span> {{ item.name }}
</p>
<p>
<span class="address-content-title">收货地区:</span
>{{ item.consigneeAddressPath | unitAddress }}
</p>
<p>
<span class="address-content-title">详细地址:</span> {{ item.detail }}
</p>
<p>
<span class="address-content-title">手机号码:</span> {{ item.mobile }}
</p>
</div>
</div>
</div>
</template>
<script>
import card from '@/components/card';
import { memberAddress, delMemberAddress } from '@/api/address.js';
export default {
name: 'MyAddress',
data () {
return {
list: [] // 地址列表
};
},
methods: {
edit (id) {
// 编辑地址
this.$router.push({ path: '/home/addAddress', query: { id: id } });
},
del (id) {
// 删除地址
this.$Modal.confirm({
title: '提示',
content: '你确定删除这个收货地址',
onOk: () => {
delMemberAddress(id).then((res) => {
if (res.code === 200) {
this.$Message.success('删除成功');
this.getAddrList();
}
});
},
onCancel: () => {
this.$Message.info('取消删除');
}
});
},
getAddrList () {
// 获取地址列表
memberAddress().then((res) => {
console.log(res);
if (res.code === 200) {
this.list = res.result.records;
}
});
}
},
mounted () {
this.getAddrList();
},
components: {
card
}
};
</script>
<style scoped lang="scss">
.address-box {
padding: 15px;
margin: 15px;
border-bottom: 1px solid $border_color;
}
.address-header {
cursor: pointer;
height: 35px;
display: flex;
justify-content: space-between;
@include title_color($light_title_color);
font-size: 18px;
}
.address-content {
cursor: pointer;
font-size: 14px;
> p {
padding: 12px 0;
}
}
.address-content-title {
@include sub_color($light_sub_color);
}
.address-action span {
margin-left: 15px;
font-size: 14px;
color: $theme_color;
cursor: pointer;
}
#map-container {
width: 500px;
height: 300px;
}
</style>

View File

@@ -0,0 +1,394 @@
<template>
<div class="wrapper">
<!-- 卡片组件 -->
<card _Title="我的订单" :_Size="16" :_Tabs="changeWay" @_Change="change" v-if="!homePage"></card>
<card _Title="我的订单" :_Size="16" :_Tabs="changeWay" @_Change="change" _More="全部订单" _Src="/home/MyOrder" v-else></card>
<!-- 搜索 筛选 -->
<div class="mb_20 box" v-if="!homePage">
<div class="global_float_right" >
<Input
class="width_300"
search
enter-button
v-model="params.keywords"
@on-search="getList"
placeholder="请输入订单号搜索"
/>
</div>
</div>
<!-- 订单列表 -->
<empty v-if="orderList.length === 0" />
<div class="order-content" v-else>
<div
class="order-list"
v-for="(order, onderIndex) in orderList"
:key="onderIndex"
>
<div class="order-header">
<div>
<div>{{ filterOrderStatus(order.orderStatus) }}</div>
<div>
订单号{{ order.sn }} &nbsp; &nbsp; &nbsp;{{order.createTime}}
&nbsp; &nbsp;{{ order.memberName | secrecyMobile }}
</div>
</div>
<div>
<Button @click="delOrder(order.sn)" class="del-btn mr_10 fontsize_16" style="margin-top:-5px;" type="text" icon="ios-trash-outline" size="small"></Button>
<span>{{ order.flowPrice | unitPrice("¥") }}</span>
</div>
</div>
<div class="order-body">
<div class="goods-list">
<div
v-for="(goods, goodsIndex) in order.orderItems"
:key="goodsIndex"
>
<img
@click="goodsDetail(goods.skuId, goods.goodsId)"
class="hover-color"
:src="goods.image"
alt=""
/>
<div>
<div class="hover-color" @click="goodsDetail(goods.skuId, goods.goodsId)">{{ goods.name }}</div>
<div class="mt_10">
<span class="global_color"
>{{ goods.goodsPrice | unitPrice("¥") }} </span
>x {{ goods.num }}
</div>
<Button v-if="goods.commentStatus == 'UNFINISHED'" @click="comment(order.sn, goodsIndex)" size="small" style="position:relative;top:-22px;left:100px">评价</Button>
<Button v-if="goods.complainStatus == 'NO_APPLY'" @click="complain(order.sn, goodsIndex)" size="small" style="position:relative;top:-22px;left:110px">投诉</Button>
</div>
</div>
</div>
<div>
<span @click="shopPage(order.storeId)">{{ order.storeName }}</span
>&nbsp;<Icon custom="iconfont icon-kefu" />
</div>
<div>
<!-- 订单基础操作 -->
<Button @click="orderDetail(order.sn)" size="small">订单详情</Button>
<Button @click="handleCancelOrder(order.sn)" v-if="order.allowOperationVO.cancel" size="small">取消订单</Button>
<Button @click="goPay(order.sn)" size="small" v-if="order.allowOperationVO.pay">去支付</Button>
<Button @click="received(order.sn)" size="small" v-if="order.allowOperationVO.rog">确认收货</Button>
<!-- 售后 -->
<Button v-if="order.groupAfterSaleStatus.includes('NOT_APPLIED')" @click="applyAfterSale(order.orderItems)" size="small">申请售后</Button>
</div>
</div>
</div>
<Spin size="large" fix v-if="spinShow"></Spin>
</div>
<!-- 分页 -->
<div class="page-size" v-if="paging">
<Page :total="total" @on-change="changePageNum"
@on-page-size-change="changePageSize"
:page-size="params.pageSize"
show-sizer>
</Page>
</div>
<!-- 选择售后商品 -->
<Modal v-model="afterSaleModal" title="请选择申请售后的商品">
<div>
<Table
border
:columns="afterSaleColumns"
:data="afterSaleArr"
@on-row-click="afterSaleSelect"
>
</Table>
</div>
<div slot="footer"></div>
</Modal>
<Modal v-model="cancelAvail" title="请选择取消订单原因" @on-ok="sureCancel" @on-cancel="cancelAvail = false">
<RadioGroup v-model="cancelParams.reason" vertical>
<Radio :label="item.reason" v-for="item in cancelReason" :key="item.id">
{{item.reason}}
</Radio>
</RadioGroup>
</Modal>
</div>
</template>
<script>
import { getOrderList, sureReceived, cancelOrder, delOrder } from '@/api/order';
import { afterSaleReason } from '@/api/member';
import { orderStatusList } from '../enumeration.js'
export default {
name: 'MyOrder',
props: {
paging: {
type: Boolean,
default: true
},
homePage: {
type: Boolean,
default: false
}
},
data () {
return {
orderList: [], // 订单列表
params: { // 请求参数
pageNumber: 1,
pageSize: 10,
// orderStatus: 'ALL',
keywords: '',
tag: 'ALL'
},
cancelParams: { // 取消售后参数
orderSn: '',
reason: ''
},
// 状态数组
orderStatusList,
changeWay: ['全部订单', '待付款', '待收货', '已完成'], // 订单状态
total: 0, // 数据总数
spinShow: false, // 加载状态
afterSaleModal: false, // 选择售后商品模态框
afterSaleColumns: [ // 售后商品表头
{title: '商品名称', key: 'name'},
{title: '价格', key: 'goodsPrice'}
],
afterSaleArr: [], // 售后商品列表
cancelAvail: false, // 取消订单modal控制
cancelReason: [] // 取消订单原因
};
},
mounted () {
if (this.homePage) this.params.pageSize = 5;
this.getList();
},
methods: {
goodsDetail (skuId, goodsId) {
// 跳转商品详情
let routeUrl = this.$router.resolve({
path: '/goodsDetail',
query: { skuId, goodsId }
});
window.open(routeUrl.href, '_blank');
},
change (index) {
switch (index) {
case 0:
this.params.tag = 'ALL'
break;
case 1:
this.params.tag = 'WAIT_PAY'
break;
case 2:
this.params.tag = 'WAIT_ROG'
break;
case 3:
this.params.tag = 'COMPLETE'
break;
}
this.getList()
},
// 跳转店铺首页
shopPage (id) {
let routeUrl = this.$router.resolve({
path: '/Merchant',
query: { id: id }
});
window.open(routeUrl.href, '_blank');
},
orderDetail (sn) {
// 跳转订单详情
this.$router.push({ name: 'OrderDetail', query: {sn} });
},
received (sn) { // 确认收货
sureReceived(sn).then(res => {
if (res.success) {
this.$Message.success('确认收货成功')
this.getList()
}
})
},
goPay (sn) { // 去支付
this.$router.push({path: '/payment', query: {orderType: 'ORDER', sn}});
},
applyAfterSale (goodsItem) { // 申请售后
let arr = []
goodsItem.forEach(e => {
if (e.afterSaleStatus === 'NOT_APPLIED') {
arr.push(e)
}
});
if (arr.length === 1) {
this.$router.push({name: 'ApplyAfterSale', query: {sn: arr[0].sn}})
} else {
this.afterSaleArr = arr;
this.afterSaleModal = true
}
},
afterSaleSelect (item) {
this.$router.push({name: 'ApplyAfterSale', query: {sn: item.sn}})
},
viewComment (sn) { // 查看评价
},
comment (sn, goodsIndex) { // 评价
this.$router.push({path: '/home/addEval', query: {sn, index: goodsIndex}})
},
addComment (sn) { // 追加评价
},
complain (sn, goodsIndex) { // 投诉
this.$router.push({name: 'Complain', query: {sn, index: goodsIndex}})
},
complainResult (sn) { // 投诉结果
},
delOrder (sn) {
this.$Modal.confirm({
title: '删除订单',
content: '<p>确认删除当前订单吗?</p>',
onOk: () => {
delOrder(sn).then(res => {
if (res.success) {
this.$Message.success('删除成功');
this.getList()
}
})
},
onCancel: () => {}
});
},
getList () {
this.spinShow = true;
let params = JSON.parse(JSON.stringify(this.params))
if (params.orderStatus === 'ALL') {
delete params.orderStatus
}
getOrderList(params).then(res => {
this.spinShow = false
if (res.success) {
this.orderList = res.result.records;
this.total = res.result.total;
}
});
},
changePageNum (val) {
this.params.pageNumber = val;
this.getList()
},
changePageSize (val) {
this.pageNumber = 1;
this.params.pageSize = val;
this.getList()
},
handleCancelOrder (sn) {
// 取消订单
this.cancelParams.orderSn = sn;
afterSaleReason('CANCEL').then(res => {
if (res.success) {
this.cancelReason = res.result;
this.cancelAvail = true
this.cancelParams.reason = this.cancelReason[0].reason
}
})
},
sureCancel () {
cancelOrder(this.cancelParams).then(res => {
if (res.success) {
this.$Message.success('取消订单成功')
this.getList()
this.cancelAvail = false
}
})
},
filterOrderStatus (status) { // 获取订单状态中文
const ob = this.orderStatusList.filter(e => { return e.status === status });
return ob[0].name
}
}
};
</script>
<style scoped lang="scss">
.wrapper {
margin-bottom: 40px;
}
.box {
overflow: hidden;
}
.page-size {
margin: 15px 0px;
display: flex;
justify-content: flex-end;
align-items: center;
}
/** 订单列表 */
.order-list {
border: 1px solid #ddd;
border-radius: 3px;
margin-bottom: 10px;
&:hover{
.del-btn{visibility: visible;}
}
.del-btn{
visibility: hidden;
}
.order-header {
display: flex;
align-items: center;
padding: 10px;
justify-content: space-between;
border-bottom: 1px solid #ddd;
> div:nth-child(1) > div:nth-child(2) {
font-size: 12px;
color: #999;
margin-top: 3px;
}
}
.order-body {
display: flex;
justify-content: space-between;
color: #999;
padding: 10px;
.goods-list > div {
width: 500px;
display: flex;
margin-bottom: 10px;
img {
width: 60px;
height: 60px;
margin-right: 10px;
}
> div {
flex: 1;
}
}
> div:nth-child(2) {
width: 150px;
text-align: center;
span {
color: #438cde;
cursor: pointer;
&:hover {
color: $theme_color;
}
}
.ivu-icon {
color: #ff8f23;
cursor: pointer;
&:hover {
color: $theme_color;
}
}
}
> div:nth-child(3) {
width: 100px;
.ivu-btn {
margin-bottom: 10px;
}
}
}
}
</style>

View File

@@ -0,0 +1,242 @@
<template>
<div class="order-detail" v-if="order.order">
<card _Title="订单详情" :_Size="16"></card>
<div class="order-card">
<p class="global_color fontsize_18">{{ order.orderStatusValue }}</p>
<p class="global_color">订单号{{ order.order.sn }}</p>
<div style="color:#999;" class="operation-time">操作时间{{order.order.updateTime}}</div>
<Steps class="progress" :current="progressList.length" direction="vertical">
<Step
:title="progress.message"
:content="progress.createTime"
v-for="(progress, index) in progressList"
:key="index"
></Step>
</Steps>
</div>
<div class="order-card">
<h3>收货人信息</h3>
<p>收货人{{order.order.consigneeName}}</p>
<p>手机号码{{order.order.consigneeMobile | secrecyMobile}}</p>
<p>收货地址{{order.order.consigneeAddressPath | unitAddress}} {{order.order.consigneeDetail}}</p>
</div>
<div class="order-card">
<h3>付款信息</h3>
<p>支付方式在线支付</p>
<p>付款状态未付款</p>
</div>
<div class="order-card">
<h3>配送信息</h3>
<p>配送方式{{order.deliveryMethodValue}}</p>
<p>配送状态{{order.deliverStatusValue}}</p>
</div>
<div class="order-card" v-if="order.order.receipt">
<h3>发票信息</h3>
<p>发票抬头{{order.order.receiptVO.receiptTitle}}</p>
<p>发票内容{{order.order.receiptVO.receiptContent}}</p>
<p v-if="order.order.receiptVO.taxpayerId">纳税人识别号{{order.order.receiptVO.taxpayerId}}</p>
</div>
<!-- 订单商品 -->
<div class="goods">
<div class="shop-name">
<span @click="shopPage(order.order.storeId)">{{ order.order.storeName }}</span> &nbsp; <Icon custom="iconfont icon-kefu" />
</div>
<table>
<thead>
<tr>
<th width="50%">商品</th>
<!-- <th width="20%">属性</th> -->
<th width="20%">货号</th>
<!-- <th width="10%">发货仓库</th> -->
<th width="10%">单价</th>
<th width="10%">数量</th>
<th width="10%">小计</th>
</tr>
</thead>
<tbody>
<tr v-for="(goods, goodsIndex) in order.orderItems" :key="goodsIndex">
<td>
<img @click="goodsDetail(goods.id, goods.goodsId)" :src="goods.image" alt="" />
<div>
<p @click="goodsDetail(goods.id, goods.goodsId)" class="hover-color">
{{ goods.goodsName }}
</p>
</div>
</td>
<td>{{ goods.id }}</td>
<td>{{ goods.goodsPrice | unitPrice }}</td>
<td>{{ goods.num }}</td>
<td>{{ (goods.goodsPrice * goods.num) | unitPrice }}</td>
</tr>
</tbody>
</table>
<!-- 订单价格 -->
<div class="order-price">
<div>
<span>商品件数</span><span>{{ order.order.goodsNum }}</span>
</div>
<div>
<span>商品总价</span><span>{{ order.order.goodsPrice | unitPrice("¥") }}</span><br>
</div>
<div>
<span>运费</span><span>+{{ order.order.freightPrice | unitPrice("¥") }}</span><br>
</div>
<div><span>优惠金额</span><span>-{{ order.order.discountPrice | unitPrice("¥") }}</span></div>
<div>
<span>应付金额</span
><span class="actrual-price">{{ order.order.flowPrice | unitPrice("¥") }}</span>
</div>
</div>
</div>
</div>
</template>
<script>
import card from '@/components/card';
import { orderDetail, getTraces } from '@/api/order.js';
export default {
components: { card },
name: 'order-detail',
data () {
return {
order: {}, // 订单详情数据
progressList: [], // 订单流程
logistics: [] // 物流数据
};
},
methods: {
goodsDetail (skuId, goodsId) {
// 跳转商品详情
let routeUrl = this.$router.resolve({
path: '/goodsDetail',
query: { skuId, goodsId }
});
window.open(routeUrl.href, '_blank');
},
// 跳转店铺首页
shopPage (id) {
let routeUrl = this.$router.resolve({
path: '/Merchant',
query: { id: id }
});
window.open(routeUrl.href, '_blank');
},
getDetail () { // 订单详情
orderDetail(this.$route.query.sn).then(res => {
if (res.success) {
this.order = res.result;
this.progressList = res.result.orderLogs
}
})
},
traces () {
getTraces(this.$route.query.sn).then(res => {
if (res.success) {
this.logistics = res.result
}
})
}
},
mounted () {
this.getDetail()
this.traces()
}
};
</script>
<style lang="scss" scoped>
.order-card {
padding: 10px;
padding-bottom: 10px;
margin-bottom: 10px;
border-bottom: 1px solid #e8eaec;
position: relative;
.global_color {
color: $theme_color;
}
p {
color: #999;
margin: 3px;
}
h3 {
font-weight: normal;
font-size: 16px;
}
.operation-time {
position: absolute;
right: 20px;
top: 10px;
}
}
/** 店铺名称 */
.shop-name {
margin: 15px 0;
span {
color: #438cde;
cursor: pointer;
&:hover {
color: $theme_color;
}
}
.ivu-icon {
color: #ff8f23;
cursor: pointer;
&:hover {
color: $theme_color;
}
}
}
/** 商品列表 */
table {
border: 1px solid #ddd;
color: #999;
border-collapse: collapse;
width: 100%;
tr {
border-top: 1px solid #ddd;
}
thead > tr {
height: 40px;
background: #eee;
}
td {
padding: 5px;
text-align: center;
&:first-child {
text-align: left;
display: flex;
img {
width: 70px;
height: 70px;
margin-right: 10px;
margin-left: 10px;
cursor: pointer;
}
}
&:last-child {
color: $theme_color;
}
}
}
/** 订单价格 */
.order-price {
text-align: right;
margin-top: 30px;
font-size: 16px;
color: #999;
> div > span:nth-child(2) {
width: 130px;
text-align: right;
display: inline-block;
margin-top: 10px;
}
.actrual-price {
color: $theme_color;
font-weight: bold;
font-size: 20px;
}
}
/** 订单进度条 */
.progress {
margin: 15px 0;
}
</style>

View File

@@ -0,0 +1,32 @@
<template>
<div class="wrapper">
<card _Title="优惠券列表" />
<Coupon/>
</div>
</template>
<script>
import Coupon from '@/components/coupon/Coupon.vue'
export default {
name: 'Coupons',
data () {
return {
couponsList: [ // 优惠券状态
'未使用',
'已使用',
'已过期',
'即将到期'
]
}
},
components: {Coupon},
mounted () {
},
methods: {}
}
</script>
<style scoped lang="scss">
</style>

View File

@@ -0,0 +1,451 @@
<template>
<div class="wrapper">
<card _Title="资金管理" />
<div class="box">
<div class="mb_20 account-price">
<span class="subTips">账户余额</span>
<span class="global_color mr_10" style="font-size:26px">{{ memberDeposit | unitPrice }}</span>
<span class="subTips">冻结金额</span>
<span class="">{{ frozenDeposit | unitPrice}}</span>
</div>
<div class="account-btns">
<Button type="primary" @click="recharge">在线充值</Button>
<Button @click="withdrawalApply">申请提现</Button>
</div>
</div>
<Modal v-model="modal" width="530">
<p slot="header">
<Icon type="edit"></Icon>
<span>充值金额</span>
</p>
<div>
<Form
ref="formData"
:model="formData"
label-position="left"
:label-width="100"
:rules="formValidate"
>
<FormItem label="充值金额" prop="price">
<Input v-model="formData.price" size="large" number maxlength="9"
><span slot="append"></span></Input>
</FormItem>
</Form>
</div>
<div slot="footer" style="text-align: center">
<Button type="success" size="large" @click="rechargePrice">充值</Button>
</div>
</Modal>
<!-- 提现申请 -->
<Modal v-model="withdrawApplyModal" width="530">
<p slot="header">
<Icon type="edit"></Icon>
<span>提现金额</span>
</p>
<div>
<Form
ref="withdrawApplyFormData"
:model="withdrawApplyFormData"
label-position="left"
:label-width="100"
:rules="withdrawApplyFormValidate"
>
<FormItem label="提现金额" prop="price">
<Input
v-model="withdrawApplyFormData.price"
size="large"
number
maxlength="9"
><span slot="append"></span></Input>
</FormItem>
</Form>
</div>
<div slot="footer" style="text-align: center">
<Button type="success" size="large" @click="withdrawal">提现</Button>
</div>
</Modal>
<!-- 余额日志 -->
<Tabs value="log" @on-click="tabPaneChange">
<TabPane label="余额日志" name="log">
<Table :columns="logColumns" :data="logColumnsData.records"></Table>
<!-- 分页 -->
<div class="page-size">
<Page
:current="searchForm.pageNumber"
:total="logColumnsData.total"
:page-size="searchForm.pageSize"
@on-change="changePage"
@on-page-size-change="changePageSize"
:page-size-opts="[10, 20, 50]"
size="small"
show-total
show-elevator
></Page>
</div>
</TabPane>
<!-- 充值记录 -->
<TabPane label="充值记录" name="recharge">
<Table
:columns="rechargeListColumns"
:data="rechargeListData.records"
></Table>
<!-- 分页 -->
<div class="page-size">
<Page
:current="rechargeSearchForm.pageNumber"
:total="rechargeListData.total"
:page-size="rechargeSearchForm.pageSize"
@on-change="rechargeChangePage"
@on-page-size-change="rechargeChangePageSize"
:page-size-opts="[10, 20, 50]"
size="small"
show-total
show-elevator
></Page>
</div>
</TabPane>
<TabPane label="提现记录" name="withdrawApply">
<Table
:columns="withdrawApplyColumns"
:data="withdrawApplyColumnsListData.records"
></Table>
<!-- 分页 -->
<div class="page-size">
<Page
:current="withdrawApplySearchForm.pageNumber"
:total="withdrawApplyColumnsListData.total"
:page-size="withdrawApplySearchForm.pageSize"
@on-change="withdrawChangePage"
@on-page-size-change="withdrawChangePageSize"
:page-size-opts="[10, 20, 50]"
size="small"
show-total
show-elevator
></Page>
</div>
</TabPane>
</Tabs>
</div>
</template>
<script>
import card from '@/components/card';
import {
getMembersWallet,
getDepositLog,
getRecharge,
getWithdrawApply,
recharge,
withdrawalApply
} from '@/api/member';
export default {
name: 'MoneyManagement',
data () {
return {
frozenDeposit: 0, // 冻结余额
memberDeposit: 0, // 余额
modal: false, // 余额充值
withdrawApplyModal: false, // 提现申请
formData: {
// 充值金额
price: 1
},
// 提现金额
withdrawApplyFormData: {
price: 1
},
// 余额日志
searchForm: {
// 搜索框初始化对象
pageNumber: 1,
pageSize: 10
},
// 充值记录
rechargeSearchForm: {
// 搜索框初始化对象
pageNumber: 1, // 当前页数
pageSize: 10 // 页面大小
},
// 提现记录
withdrawApplySearchForm: {
// 搜索框初始化对象
pageNumber: 1, // 当前页数
pageSize: 10 // 页面大小
},
// 提现申请校验
withdrawApplyFormValidate: {
price: [
{ required: true, message: '请输入大于0小于9999的合法提现金额' },
{
pattern: /^[1-9]\d{0,3}(\.\d{1,2})?$/,
message: '请输入大于0小于9999的合法提现金额',
trigger: 'change'
}
]
},
formValidate: {
price: [
{ required: true, message: '请输入大于0小于9999的合法充值金额' },
{
pattern: /^[1-9]\d{0,3}(\.\d{1,2})?$/,
message: '请输入大于0小于9999的合法充值金额',
trigger: 'change'
}
]
},
// 余额日志
logColumns: [
{
title: '时间',
key: 'createTime'
},
{
title: '金额',
key: 'money',
render: (h, params) => {
if (params.row.money > 0) {
return h('div', [
h(
'span',
{
style: {
color: 'green'
}
},
params.row.money
)
]);
} else if (params.row.money < 0) {
return h('div', [
h(
'span',
{
style: {
color: 'red'
}
},
params.row.money
)
]);
}
}
},
{
title: '变动日志',
key: 'detail'
}
],
logColumnsData: {}, // 余额日志
// 充值记录
rechargeListColumns: [
{
title: '支付单号',
key: 'rechargeSn',
width: 200
},
{
title: '支付方式',
key: 'rechargeWay'
},
{
title: '充值金额',
key: 'rechargeMoney'
},
{
title: '支付状态',
key: 'payStatus',
render: (h, params) => {
if (params.row.payStatus === 'PAID') {
return h('div', [h('span', {}, '已付款')]);
} else if (params.row.payStatus === 'UNPAID') {
return h('div', [h('span', {}, '未付款')]);
}
}
},
{
title: '支付时间',
key: 'payTime'
}
],
rechargeListData: {}, // 充值记录数据
// 提现记录
withdrawApplyColumns: [
{
title: '提现单号',
key: 'sn',
width: 215
},
{
title: '提现金额',
key: 'applyMoney',
width: 120
},
{
title: '提现状态',
key: 'applyStatus',
render: (h, params) => {
if (params.row.applyStatus === 'APPLY') {
return h('div', [h('span', {}, '申请中')]);
} else if (params.row.applyStatus === 'VIA_AUDITING') {
return h('div', [h('span', {}, '提现成功')]);
} else {
return h('div', [h('span', {}, '审核未通过')]);
}
}
},
{
title: '提现时间',
key: 'inspectTime'
},
{
title: '审核备注',
key: 'inspectRemark'
}
],
withdrawApplyColumnsListData: {} // 提现记录
};
},
components: { card },
mounted () {
this.init();
},
methods: {
init () {
getMembersWallet().then((res) => {
this.frozenDeposit = res.result.memberFrozenWallet;
this.memberDeposit = res.result.memberWallet;
});
getDepositLog(this.searchForm).then((res) => {
if (res.message === 'success') {
this.logColumnsData = res.result;
}
});
},
tabPaneChange (v) {
// 如果查询充值记录
if (v === 'recharge') {
this.getRechargeData();
}
// 如果是余额日志
if (v === 'log') {
this.init();
}
// 如果是提现记录
if (v === 'withdrawApply') {
this.getWithdrawApplyData();
}
},
// 充值记录
getRechargeData () {
getRecharge(this.rechargeSearchForm).then((res) => {
if (res.message === 'success') {
this.rechargeListData = res.result;
}
});
},
// 提现记录
getWithdrawApplyData () {
getWithdrawApply(this.withdrawApplySearchForm).then((res) => {
if (res.message === 'success') {
this.withdrawApplyColumnsListData = res.result;
}
});
},
// 余额日志
changePage (v) {
this.searchForm.pageNumber = v;
this.init();
},
changePageSize (v) {
this.searchForm.pageSize = v;
this.init();
},
// 充值记录
rechargeChangePage (v) {
this.rechargeSearchForm.pageNumber = v;
this.getRechargeData();
},
rechargeChangePageSize (v) {
this.rechargeSearchForm.pageSize = v;
this.getRechargeData();
},
// 提现记录
withdrawChangePage (v) {
this.withdrawApplySearchForm.pageNumber = v;
this.getWithdrawApplyData();
},
withdrawChangePageSize (v) {
this.withdrawApplySearchForm.pageSize = v;
this.getWithdrawApplyData();
},
// 弹出在线充值框
recharge () {
this.formData.price = 1;
this.modal = true;
},
// 在线充值
rechargePrice () {
this.$refs['formData'].validate((valid) => {
if (valid) {
recharge(this.formData).then((res) => {
if (res.message === 'success') {
// TODO 根据返回的值跳转到收银台进行支付,一下是输出sn
console.warn(res.result.rechargeSn);
this.modal = false;
}
});
}
});
},
// 申请提现弹出框
withdrawalApply () {
this.withdrawApplyFormData.price = 1;
this.withdrawApplyModal = true;
},
withdrawal () {
this.$refs['withdrawApplyFormData'].validate((valid) => {
if (valid) {
withdrawalApply(this.withdrawApplyFormData).then((res) => {
if (res && res.success) {
this.$Message.success('提现申请成功,关注提现状态');
this.withdrawApplyModal = false;
this.init(); // 余额查询
this.getWithdrawApplyData(); // 提现记录
}
});
}
});
}
}
};
</script>
<style scoped lang="scss">
.box {
margin: 20px 0;
}
.page-size {
margin: 15px 0px;
display: flex;
justify-content: flex-end;
align-items: center;
}
.account-price {
font-weight: bold;
}
.subTips {
@include sub_color($light_sub_color);
}
.account-btns {
margin: 10px 0;
}
.ivu-btn {
margin: 0 4px;
}
.fontsize_48 {
font-size: 48px;
}
</style>

View File

@@ -0,0 +1,142 @@
<template>
<div class="wrapper">
<!-- 卡片组件 -->
<card _Title="我的足迹" :_Size="16" ></card>
<Button class="del-btn" @click="clearAll" type="primary">删除全部</Button>
<!-- 订单列表 -->
<empty v-if="list.length === 0" />
<ul class="track-list" v-else>
<li v-for="(item, index) in list" :key="index" @click="goodsDetail(item.id, item.goodsId)">
<img :src="item.thumbnail" :alt="item.thumbnail" width="200" height="200">
<p class="ellipsis">{{item.goodsName}}</p>
<p>{{item.price | unitPrice('¥')}}</p>
<span class="del-icon" @click.stop="clearById(item.goodsId)">
<Icon type="md-trash" />
</span>
</li>
</ul>
</div>
</template>
<script>
import { tracksList, clearTracks, clearTracksById } from '@/api/member';
export default {
name: 'MyTrack',
data () {
return {
list: [], // 我的足迹,商品列表
spinShow: false // 控制loading是否加载
};
},
mounted () {
this.getList();
},
methods: {
goodsDetail (skuId, goodsId) {
// 跳转商品详情
let routeUrl = this.$router.resolve({
path: '/goodsDetail',
query: { skuId, goodsId }
});
window.open(routeUrl.href, '_blank');
},
// 跳转店铺首页
shopPage (id) {
let routeUrl = this.$router.resolve({
path: '/Merchant',
query: { id: id }
});
window.open(routeUrl.href, '_blank');
},
clearAll () { // 清除全部足迹
this.$Modal.confirm({
title: '删除',
content: '<p>确定要删除全部足迹吗?</p>',
onOk: () => {
clearTracks().then(res => {
if (res.success) {
this.$Message.success('删除成功')
this.getList()
}
})
},
onCancel: () => { }
});
},
clearById (id) { // 清除全部足迹
clearTracksById(id).then(res => {
if (res.success) {
this.$Message.success('删除成功')
this.getList()
}
})
},
getList () {
this.spinShow = true;
tracksList(this.params).then(res => {
this.spinShow = false
if (res.success && res.result) {
this.list = res.result;
}
});
}
}
};
</script>
<style scoped lang="scss">
.wrapper {
margin-bottom: 40px;
}
.del-btn {
margin: 0 0 10px 15px;
}
.track-list {
display: flex;
flex-wrap: wrap;
li{
width: 200px;
overflow: hidden;
margin-left: 15px;
margin-bottom: 10px;
border: 1px solid #eee;
position: relative;
&:hover{
cursor: pointer;
box-shadow:1px 1px 3px #999;
.del-icon{
display: block;
}
}
p{
padding: 0 5px;
margin: 3px 0;
}
p:nth-child(2) {
color: #999;
}
p:nth-child(3){
color: $theme_color;
}
.del-icon {
display: none;
font-size: 30px;
background-color:rgba(0,0,0,.3);
position: absolute;
width: 40px;
height: 40px;
line-height: 40px;
text-align: center;
right: 0;
top: 0;
cursor: pointer;
}
}
}
.page-size {
margin: 15px 0px;
display: flex;
justify-content: flex-end;
align-items: center;
}
</style>