feat: 添加静态资源文件及基础组件

- 新增大量图片资源,包括图标、背景图、海报等,用于页面展示
- 添加字体文件及样式配置,支持自定义字体
- 引入 uni-ui 组件库,包括图标、弹窗、日期选择器等常用组件
- 添加网络状态监听、加密工具等基础工具函数
- 配置 Vuex 状态管理,包括购物车数量、热门搜索词等
- 增加页面组件,如用户协议、分销信息、提现状态等
- 配置项目构建和忽略文件,优化开发体验
This commit is contained in:
2026-02-26 17:59:51 +08:00
commit a5c5d753b6
720 changed files with 178840 additions and 0 deletions

View File

@@ -0,0 +1,417 @@
<template>
<!-- 退款页、一键改价页、订单备注页、立即退款立即退货页 -->
<view>
<!-- <view class="priceChange" :class="[change === true ? 'on' : '',status == 2 && !isRefund?'goodsOn':'']"> -->
<view class="priceChange" :class="[change === true ? 'on' : '']">
<view class="priceChange-box">
<!-- status == 0? orderInfo.refund_status === 1? "立即退款": "一键改价": "订单备注" -->
<view class="priceTitle">
{{
status == 8?'退款原因': status == 0?"一键改价": status == 1?'订单备注': isRefund?'退款审核':'退款审核'
}}
<view class="btn acea-row row-center row-middle" @click="close">
<span class="iconfont icon-ic_close"></span>
</view>
</view>
<!-- 一键改价 -->
<view class="listChange" v-if="status == 0">
<view class="item acea-row row-between-wrapper" v-if="orderInfo.refund_status === 0">
<view>商品原价</view>
<view class="money">
¥{{ orderInfo.total_price }}
</view>
</view>
<view class="item acea-row row-between-wrapper" v-if="orderInfo.refund_status === 0">
<view>商品邮费</view>
<view class="money">
¥{{ orderInfo.pay_postage }}
</view>
</view>
<view class="item acea-row row-between-wrapper" v-if="orderInfo.refund_status === 0">
<view>修改价格</view>
<view class="money">
<input type="text" v-model="price" :cursor-spacing="40" always-embed :class="focus === true ? 'on' : ''" @focus="priceChange" />
</view>
<text class="iconfont icon-ic_edit"></text>
</view>
</view>
<!-- 立即退款 -->
<!-- <view class="listChange" v-if="status == 2">
<view v-if="isRefund" class="item acea-row row-between-wrapper">
<view>实际支付(¥)</view>
<view class="money">
{{ orderInfo.pay_price }}<span class="iconfont icon-suozi"></span>
</view>
</view>
<view v-if="isRefund" class="item acea-row row-between-wrapper">
<view>退款金额(¥)</view>
<view class="money">
<input type="text" v-model="refund_price" :class="focus === true ? 'on' : ''" @focus="priceChange" />
</view>
</view>
<view class="title" v-if="!isRefund">同意退货退款</view>
</view> -->
<!-- 退款审核 -->
<view class="listChange" v-if="status == 2">
<view class="item acea-row row-between-wrapper">
<view>审核状态</view>
<view class="money acea-row row-right">
<view class="radio-item acea-row row-middle" :class="{ on: isAgree }" @click="agreeChange(true)">
<text class="iconfont" :class="isAgree?'icon-ic_Selected':'icon-ic_unselect'"></text>同意退{{isRefund?'款':'货'}}
</view>
<view v-if="orderInfo.refund_type != 4 && orderInfo.refund_type != 5" class="radio-item acea-row row-middle" :class="{ on: !isAgree }" @click="agreeChange(false)">
<text class="iconfont" :class="isAgree?'icon-ic_unselect':'icon-ic_Selected'"></text>拒绝退款
</view>
</view>
</view>
<view class="item acea-row row-between">
<view>邮费</view>
<view class="fs-32 Regular acea-row row-right">¥{{orderInfo.pay_postage}}</view>
</view>
<view class="item acea-row row-between-wrapper" v-if="isAgree && isRefund">
<view>退款金额</view>
<view class="money">
<input type="text" v-model="refund_price" :cursor-spacing="50" :class="focus === true ? 'on' : ''" always-embed @focus="priceChange" />
</view>
<text class="iconfont icon-ic_edit"></text>
</view>
<view class="item acea-row row-between" v-if="!isAgree">
<view>拒绝原因</view>
<view class="money acea-row row-right">
<textarea class="reason" placeholder="请输入" v-model="refuse_reason" fixed :cursor-spacing="100"></textarea>
</view>
</view>
</view>
<view class="listChange" v-if="status == 1">
<textarea placeholder="请填写备注信息..." v-model="remark" fixed :cursor-spacing="100"></textarea>
</view>
<!-- <view class="listChange" v-if="status == 8">
<textarea placeholder="请填写退款原因..." v-model="refuse_reason"></textarea>
</view> -->
<view class="modify-box acea-row">
<view class="cancel btn-box" @click="close">取消</view>
<view class="modify btn-box" @click="refuse" v-if="status == 8">确定</view>
<view class="modify btn-box" @click="onConfirm" v-if="status == 2 && !isRefund">确定</view>
<view class="modify btn-box" @click="save" v-if="status == 1 || status == 0">确定</view>
<view class="modify btn-box" @click="onConfirm" v-if="status == 2 && isRefund">确定</view>
</view>
<slot name="bottom"></slot>
</view>
<view class="safe-area-inset-bottom"></view>
</view>
<view class="mask" @touchmove.prevent v-show="change === true"></view>
</view>
</template>
<style lang="scss" scoped>
.safe-area-inset-bottom {
height: 0;
height: constant(safe-area-inset-bottom);
height: env(safe-area-inset-bottom);
}
.mask {
z-index: 99;
}
.priceChange .reGoods {
padding: 0 25upx;
margin-top: 50upx;
}
.priceChange .reGoods .bnt {
width: 250upx;
height: 90upx;
background-color: #2291f8;
font-size: 32upx;
color: #fff;
text-align: center;
line-height: 90upx;
border-radius: 45upx;
}
.priceChange .reGoods .bnt.grey {
background-color: #eee;
color: #312b2b;
}
.priceChange {
position: fixed;
bottom: 0;
left: 0;
z-index: 99999;
width: 100%;
border-radius: 40rpx 40rpx 0 0;
background: #FFFFFF;
transform: translateY(100%);
transition: transform 0.3s;
}
.priceChange.on {
transform: translateY(0);
}
.priceChange-box {}
.priceChange.goodsOn {
height: 380upx;
}
.priceChange .priceTitle {
position: relative;
height: 108rpx;
text-align: center;
font-weight: 500;
font-size: 32rpx;
line-height: 108rpx;
color: #333333;
}
.priceChange .priceTitle .btn {
position: absolute;
top: 50%;
right: 32rpx;
width: 36rpx;
height: 36rpx;
border-radius: 50%;
margin-top: -18rpx;
background: #EEEEEE;
text-align: center;
line-height: 36rpx;
}
.priceChange .priceTitle .iconfont {
vertical-align: text-bottom;
font-weight: normal;
font-size: 24rpx;
}
.priceChange .listChange {
padding: 32rpx;
min-height: 260rpx;
}
.priceChange .listChange .item {
margin-bottom: 64rpx;
font-size: 28rpx;
line-height: 40rpx;
color: #333333;
&:last-child {
margin-bottom: 0;
}
}
.priceChange .listChange .title {
font-size: 32rpx;
text-align: center;
margin-top: 52rpx;
}
.priceChange .listChange .item .money {
flex: 1;
text-align: right;
font-family: Regular;
font-size: 36rpx;
}
.priceChange .listChange .item .iconfont {
margin-left: 8rpx;
font-size: 32rpx;
}
.priceChange .listChange .item .money input {
color: #FF7E00;
}
.priceChange .listChange .item .money input.on {
// color: #666;
}
.priceChange .modify-box {
padding: 20rpx;
}
.priceChange .btn-box {
flex: 1;
height: 72rpx;
border: 2rpx solid $primary-admin;
border-radius: 36rpx;
margin-right: 16rpx;
text-align: center;
font-weight: 500;
font-size: 26rpx;
line-height: 68rpx;
color: $primary-admin;
&:last-child {
margin-right: 0;
}
}
.priceChange .modify {
border-color: $primary-admin;
background: $primary-admin;
color: #FFFFFF;
}
.priceChange .modify1 {
font-size: 32upx;
color: #312b2b;
width: 490upx;
height: 90upx;
text-align: center;
line-height: 90upx;
border-radius: 45upx;
background-color: #eee;
margin: 30upx auto 0 auto;
}
.priceChange .listChange textarea {
box-sizing: border-box;
border: 2rpx solid #CCCCCC;
width: 100%;
height: 224rpx;
padding: 20rpx;
border-radius: 16rpx;
font-size: 28rpx;
line-height: 40rpx;
color: #333;
}
.radio-item {
font-size: 28rpx;
color: #999999;
+.radio-item {
margin-left: 48rpx;
}
.iconfont {
margin-right: 12rpx;
font-size: 32rpx;
}
&.on {
color: #333333;
.iconfont {
color: $primary-admin;
}
}
}
.reason {
width: 462rpx !important;
height: 80rpx !important;
padding: 0 !important;
border: 0 !important;
}
</style>
<script>
export default {
name: "PriceChange",
components: {},
props: {
change: {
type: Boolean,
default: false
},
orderInfo: {
type: Object,
default: () => {}
},
status: {
type: String,
default: ""
},
isRefund: {
type: Number || String,
default: 0
}
},
data: function() {
return {
focus: false,
price: 0,
refund_price: 0,
remark: "",
refuse_reason: '',
isAgree: true,
};
},
watch: {
orderInfo: function(nVal) {
this.price = this.orderInfo.pay_price;
this.refund_price = this.orderInfo.pay_price;
this.remark = this.orderInfo.remark;
},
change(val) {
if (val) {
this.isAgree = true
this.refuse_reason = ''
}
},
isRefund(val) {
console.log(val)
},
},
methods: {
priceChange: function() {
this.focus = true;
},
close: function() {
this.price = this.orderInfo.pay_price;
this.$emit("closechange", false);
},
save: function() {
let that = this;
// if (!that.isAgree) {
// that.refuse();
// return
// }
that.$emit("savePrice", {
price: that.price,
refund_price: that.refund_price,
type: 1,
remark: that.remark
});
},
refuse: function() {
let that = this;
that.$emit("savePrice", {
price: that.price,
refund_price: that.refund_price,
type: 2,
remark: that.remark,
refuse_reason: that.refuse_reason
});
},
agreeChange(value) {
this.isAgree = value;
if (this.isAgree) {
this.refuse_reason = '';
}
},
onConfirm() {
if (this.status == 1) {
this.save();
}
if (this.status == 2) {
if (this.isRefund) {
if (this.isAgree) {
this.save();
} else {
this.refuse();
}
} else {
if (this.isAgree) {
this.save();
} else {
this.refuse();
}
}
}
},
}
};
</script>

View File

@@ -0,0 +1,118 @@
<template>
<!-- 底部导航 -->
<view class="page-footer">
<view class="foot-item" :class="item.pagePath == activeRouter?'active':''"
v-for="(item,index) in footerList" :key="index" @click="goRouter(item, index)">
<block v-if="item.pagePath == activeRouter">
<image :src="item.selectedIconPath"></image>
<view class="txt">{{item.text}}</view>
</block>
<block v-else>
<image :src="item.iconPath"></image>
<view class="txt">{{item.text}}</view>
</block>
</view>
</view>
</template>
<script>
export default {
name: 'adminFooterTab',
props: {},
created() {
let routes = getCurrentPages(); //获取当前打开过的页面路由数组
let curRoute = routes[routes.length - 1].route //获取当前页面路由
this.activeRouter = '/' + curRoute
},
mounted() {},
data() {
return {
activeRouter:'',
footerList:[
{
pagePath: "/pages/admin/work/index",
iconPath: require("../../static/footer1-1.png"),
selectedIconPath: require("../../static/footer1-2.png"),
text: "工作台"
},
{
pagePath: "/pages/admin/goods/index",
iconPath: require("../../static/footer2-1.png"),
selectedIconPath: require("../../static/footer2-2.png"),
text: "商品"
},
{
pagePath: "/pages/admin/orderList/index",
iconPath: require("../../static/footer3-1.png"),
selectedIconPath: require("../../static/footer3-2.png"),
text: "订单"
},
{
pagePath: "/pages/admin/user/list",
iconPath: require("../../static/footer4-1.png"),
selectedIconPath: require("../../static/footer4-2.png"),
text: "用户"
}
]
}
},
methods: {
goRouter(item) {
var pages = getCurrentPages();
var page = (pages[pages.length - 1]).$page.fullPath;
if (item.pagePath == page) return
uni.redirectTo({
url: item.pagePath,
animationType: 'none' // 关闭默认的滑动效果
});
}
}
}
</script>
<style scoped lang="scss">
.page-footer {
position: fixed;
bottom: 0;
left:0;
z-index: 20;
display: flex;
align-items: center;
justify-content: space-around;
width: 100%;
height: calc(100rpx + constant(safe-area-inset-bottom)); ///兼容 IOS<11.2/
height: calc(100rpx + env(safe-area-inset-bottom)); ///兼容 IOS>11.2/
box-sizing: border-box;
border-top: solid 1rpx #F3F3F3;
background-color: #fff;
// box-shadow: 0px 0px 17rpx 1rpx rgba(206, 206, 206, 0.32);
padding-bottom: constant(safe-area-inset-bottom); ///兼容 IOS<11.2/
padding-bottom: env(safe-area-inset-bottom); ///兼容 IOS>11.2/
.foot-item {
display: flex;
width: max-content;
align-items: center;
justify-content: center;
flex-direction: column;
position: relative;
padding: 0 20rpx;
&.active {
color: $primary-admin
}
}
.foot-item image {
height: 40rpx;
width: 40rpx;
text-align: center;
margin: 0 auto;
}
.foot-item .txt {
font-size: 20rpx;
margin-top: 6rpx;
}
}
</style>

View File

@@ -0,0 +1,132 @@
<template>
<!-- 悬浮导航按钮 -->
<view :style="colorStyle">
<view style="touch-action: none;">
<view class="home" style="position:fixed;" :style="{ top: top + 'px'}" id="right-nav" @touchmove.stop.prevent="setTouchMove">
<view @click="open" class="pictrueBox">
<view class="pictrue">
<image :src="
homeActive === true
? imgHost + '/statics/images/close.gif'
: imgHost + '/statics/images/open.gif'
" class="image" />
</view>
</view>
<view class="homeCon bg-color" :class="homeActive === true ? 'on' : ''" v-if="homeActive">
<navigator hover-class='none' open-type="navigate" url='/pages/admin/work/index' class='iconfont icon-ic_staging'>
</navigator>
<navigator hover-class='none' open-type="navigate" url='/pages/admin/goods/index' class='iconfont icon-ic_commodity'></navigator>
<navigator hover-class='none' open-type="navigate" url='/pages/admin/orderList/index' class='iconfont icon-ic_order'></navigator>
<navigator hover-class='none' open-type="navigate" url='/pages/admin/user/list' class='iconfont icon-ic_user1'></navigator>
<slot name="bottom"></slot>
</view>
</view>
</view>
</view>
</template>
<script>
import {
mapGetters
} from "vuex";
import colors from '@/mixins/color.js';
import {
HTTP_REQUEST_URL
} from '@/config/app';
export default {
name: "Home",
props: {},
mixins: [colors],
data: function() {
return {
top: "545",
imgHost: HTTP_REQUEST_URL
};
},
computed: mapGetters(["homeActive"]),
methods: {
setTouchMove(e) {
var that = this;
if (e.touches[0].clientY < 545 && e.touches[0].clientY > 66) {
that.top = e.touches[0].clientY
// that.setData({
// top: e.touches[0].clientY
// })
}
},
open: function() {
this.homeActive ?
this.$store.commit("CLOSE_HOME") :
this.$store.commit("OPEN_HOME");
}
},
created() {},
beforeDestroy() {
this.$store.commit("CLOSE_HOME")
}
};
</script>
<style scoped lang="scss">
.pictrueBox {
width: 130rpx;
height: 120rpx;
}
/*返回主页按钮*/
.home {
position: fixed;
color: white;
text-align: center;
z-index: 9999;
left: 15rpx;
display: flex;
}
.home .homeCon {
border-radius: 50rpx;
opacity: 0;
height: 0;
width: 0;
}
.home .homeCon.on {
opacity: 1;
animation: bounceInLeft 0.5s cubic-bezier(0.215, 0.610, 0.355, 1.000);
width: 300rpx;
height: 86rpx;
margin-bottom: 20rpx;
display: flex;
justify-content: center;
align-items: center;
/* background: var(--view-theme) !important; */
background: $primary-admin !important;
/* border: 1px solid #fff; */
}
.home .homeCon .iconfont {
font-size: 40rpx;
color: #fff;
display: inline-block;
margin: 0 auto;
}
.home .pictrue {
width: 86rpx;
height: 86rpx;
border-radius: 50%;
margin: 0 auto;
background: $primary-admin;
/* border: 1px solid #fff; */
}
.home .pictrue .image {
width: 100%;
height: 100%;
border-radius: 50%;
transform: rotate(-90deg);
ms-transform: rotate(-90deg);
moz-transform: rotate(-90deg);
webkit-transform: rotate(-90deg);
o-transform: rotate(-90deg);
}
</style>

View File

@@ -0,0 +1,164 @@
<template>
<canvas v-if="canvasId" :id="canvasId" :canvasId="canvasId" :style="{'width':cWidth*pixelRatio+'px','height':cHeight*pixelRatio+'px', 'transform': 'scale('+(1/pixelRatio)+')','margin-left':-cWidth*(pixelRatio-1)/2+'px','margin-top':-cHeight*(pixelRatio-1)/2+'px'}"
@touchstart="touchStart" @touchmove="touchMove" @touchend="touchEnd" @error="error">
</canvas>
</template>
<script>
import uCharts from './u-charts.js';
var canvases = {};
export default {
props: {
chartType: {
required: true,
type: String,
default: 'column'
},
opts: {
required: true,
type: Object,
default () {
return null;
},
},
canvasId: {
type: String,
default: 'u-canvas',
},
cWidth: {
default: 375,
},
cHeight: {
default: 250,
},
pixelRatio: {
type: Number,
default: 1,
},
},
mounted() {
this.init();
},
methods: {
init() {
switch (this.chartType) {
case 'column':
this.initColumnChart();
break;
case 'line':
this.initLineChart();
break;
default:
break;
}
},
initColumnChart() {
canvases[this.canvasId] = new uCharts({
$this: this,
canvasId: this.canvasId,
type: 'column',
legend: true,
fontSize: 11,
background: '#FFFFFF',
pixelRatio: this.pixelRatio,
animation: true,
categories: this.opts.categories,
series: this.opts.series,
enableScroll: true,
xAxis: {
disableGrid: true,
itemCount: 4,
scrollShow: true
},
yAxis: {
//disabled:true
},
dataLabel: true,
width: this.cWidth * this.pixelRatio,
height: this.cHeight * this.pixelRatio,
extra: {
column: {
type: 'group',
}
}
});
},
initLineChart() {
canvases[this.canvasId] = new uCharts({
$this: this,
canvasId: this.canvasId,
type: 'line',
fontSize: 11,
legend: true,
dataLabel: false,
dataPointShape: true,
background: '#FFFFFF',
pixelRatio: this.pixelRatio,
categories: this.opts.categories,
series: this.opts.series,
animation: true,
enableScroll: true,
xAxis: {
type: 'grid',
gridColor: '#CCCCCC',
gridType: 'dash',
dashLength: 8,
itemCount: 4,
scrollShow: true
},
yAxis: {
gridType: 'dash',
gridColor: '#CCCCCC',
dashLength: 8,
splitNumber: 5,
min: 10,
max: 180,
format: (val) => {
return val.toFixed(0) + '元'
}
},
width: this.cWidth * this.pixelRatio,
height: this.cHeight * this.pixelRatio,
extra: {
line: {
type: 'straight'
}
}
});
},
// 这里仅作为示例传入两个参数,cid为canvas-id,newdata为更新的数据,需要更多参数请自行修改
changeData(cid,newdata) {
canvases[cid].updateData({
series: newdata.series,
categories: newdata.categories
});
},
touchStart(e) {
canvases[this.canvasId].showToolTip(e, {
format: function(item, category) {
return category + ' ' + item.name + ':' + item.data
}
});
canvases[this.canvasId].scrollStart(e);
},
touchMove(e) {
canvases[this.canvasId].scroll(e);
},
touchEnd(e) {
canvases[this.canvasId].scrollEnd(e);
},
error(e) {
}
},
};
</script>
<style scoped>
.charts {
width: 100%;
height: 100%;
flex: 1;
background-color: #FFFFFF;
}
</style>

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,737 @@
<template>
<view>
<view class='shoppingCart copy-data'>
<view class="content">
<view class='list'>
<view>
<block v-for="(item,index) in cart_info" :key="index">
<view class='item acea-row row-between-wrapper' :style="{ opacity: item.is_writeoff == 1 ? 0.5 : 1 }">
<div class="xuan" @click="dan(item.cart_id,index)">
<view :class="(item.checked && !item.is_writeoff)?'iconfont icon-a-ic_CompleteSelect':'iconfont icon-ic_unselect'"></view>
</div>
<view class='picTxt acea-row row-between-wrapper'>
<view class='pictrue'>
<image :src="item.cart_info.productInfo.attrInfo?item.cart_info.productInfo.attrInfo.image:item.cart_info.productInfo.image" mode=""></image>
</view>
<view class='text'>
<view class="title">
<view class='line1'>
{{ item.cart_info.productInfo.store_name }}
</view>
<view v-if="item.is_writeoff == 1" class="txt">已核销</view>
<view v-if="item.is_writeoff == 0 && item.surplus_num == item.cart_num" class="txt bluecol">未核销</view>
<view v-if="item.is_writeoff == 0 && item.surplus_num != item.cart_num" class="txt orangcol">
已核销{{item.cart_num - item.surplus_num}}件</view>
</view>
<view class='infor line1'>
属性:{{ item.cart_info.productInfo.attrInfo.suk }}</view>
<view class='money he row-middle'>
<view>¥{{ item.cart_info.productInfo.attrInfo?item.cart_info.productInfo.attrInfo.price:item.cart_info.productInfo.price }}</view>
<view v-if="item.is_writeoff == 1" class="txt">
<view class='carnum acea-row row-center-wrapper'>
<view class="reduce">
<text class="iconfont icon-ic_Reduce"></text>
</view>
<view class='nums'>0</view>
<view class="plus">
<text class="iconfont icon-ic_increase"></text>
</view>
</view>
</view>
<view v-else class="txt">
<view class='carnum acea-row row-center-wrapper'>
<view v-if="item.surplus_num_input == 1" class="reduce bggary">
<text class="iconfont icon-ic_Reduce"></text>
</view>
<view v-else class="reduce" @click.stop='subCart(item,index)'>
<text class="iconfont icon-ic_Reduce"></text>
</view>
<view class='nums'>{{item.surplus_num_input}}</view>
<view v-if="item.surplus_num == item.surplus_num_input" class="plus bggary">
<text class="iconfont icon-ic_increase"></text>
</view>
<view v-else class="plus" @click.stop='addCart(item,index)'>
<text class="iconfont icon-ic_increase"></text>
</view>
</view>
</view>
</view>
</view>
</view>
</view>
</block>
</view>
</view>
</view>
<view class='footer acea-row row-between-wrapper'>
<view>
<view class="flex">
<div class="xuan" @click="checkAll" v-model="checked">
<view class="iconfont" :class="checked?'icon-a-ic_CompleteSelect':'icon-ic_unselect'"></view>
</div>
<text class='checkAll'>全选</text>
</view>
</view>
<view>
<button class='money' type="primary" @click="verification">{{checked?'一键':'确认'}}核销({{numChecked}})</button>
</view>
</view>
</view>
<view v-if="box">
<view class="box">
<view class="small_box">
<view class="content">
<view class="font">核销成功</view>
<view v-if="list.total_num == parseInt(list.writeoff_count)+writeOffNum" class="small_font">当前订单已完成核销</view>
<view v-else class="small_font">该订单仍有其他待核销商品</view>
</view>
<view class="acea-row btn-box">
<view v-if="lets == 1 && list.total_num == parseInt(list.writeoff_count)+writeOffNum" class="btn" @click="ok(1)">知道了</view>
<navigator v-if="lets > 1 && list.total_num != parseInt(list.writeoff_count)+writeOffNum" :url='"/pages/admin/distribution/scanning/index?code="+attr.code' hover-class='none'
open-type="redirect" class="btn">返回列表</navigator>
<navigator v-if="(lets > 1 && list.total_num == parseInt(list.writeoff_count)+writeOffNum)||(lets==1&&list.total_num != parseInt(list.writeoff_count)+writeOffNum)"
url="/pages/admin/distribution/index" hover-class='none' open-type="redirect" class="btn">返回首页</navigator>
<view v-if="list.total_num != parseInt(list.writeoff_count)+writeOffNum" class="btn on" @click="ok(0)">继续核销</view>
<navigator v-if="lets > 1 && list.total_num == parseInt(list.writeoff_count)+writeOffNum" :url='"/pages/admin/distribution/scanning/index?code="+attr.code' open-type="redirect"
hover-class='none' class="btn">核销其他订单</navigator>
</view>
</view>
</view>
</view>
</view>
</template>
<script>
import {
orderCartInfo,
orderWriteoff
} from '@/api/admin'
import {
emit
} from 'process';
export default {
props: {
list: {
type: Object,
default () {
return {}
}
},
auth: {
type: [String, Number],
default: 1
},
oid: {
type: Number,
default: 0
},
},
data() {
return {
nums: [],
newList: [],
reduce_show: -1,
plus_show: -1,
ids: [], //选定需要核销的id
lets: 0, //判断订单的数量
listlet: 0, //判断订单商品的数量
attr: { //切换组件传值
cartAttr: false,
id: [],
code: '',
type: 0
},
// id: 0, //订单ID
// list: [],
lists: {},
lengt: 0,
box: false,
checked: false,
checkModel: [],
isAllSelect: false,
data: [{
id: '1',
value: 'aaa'
}, {
id: '2',
value: 'bbb'
}, {
id: '3',
value: 'ccc'
}],
writeOffNum: 0, //每次核销商品数量
cart_info: [],
numChecked: 0,
};
},
watch: {
checkModel() {
// if (this.lengt == this.checkModel.length) {
// this.checked = true;
// } else {
// this.checked = false;
// }
},
},
mounted() {
this.cart_info = this.list.cart_info;
// this.lists = JSON.parse(JSON.stringify(this.list))
// this.listlet = this.list.cart_info.length
// this.$set(this.attr, 'id', this.list.id);
this.checkAll()
// this.num()
},
methods: {
//处理每一条数据的最大值
num() {
for (let index = 0; index < this.lists.cart_info.length; index++) {
this.nums.push({
num: 0
});
}
},
subCart(item, index) {
// if (item.surplus_num == 1) {
// this.reduce_show = index;
// } else {
// this.nums[index].num--
// item.surplus_num--
// }
this.list.cart_info[index].surplus_num_input--;
},
addCart(item, index) {
// if (item.surplus_num == item.surplus_num + this.nums[index].num) {
// this.plus_show = index;
// } else {
// item.surplus_num++
// this.nums[index].num++
// }
this.list.cart_info[index].surplus_num_input++;
},
checkAll() {
var items = this.cart_info,
data = [];
this.checkModel = [];
this.checked = !this.checked;
for (let i = 0; i < this.cart_info.length; i++) {
this.cart_info[i].checked = this.checked;
if (this.cart_info[i].checked) {
this.checkModel.push(this.cart_info[i].cart_id);
}
}
let numChecked = 0;
for (let i = 0; i < this.cart_info.length; i++) {
if (!this.cart_info[i].is_writeoff) {
if (this.cart_info[i].checked) {
numChecked = numChecked + this.cart_info[i].surplus_num_input;
}
}
}
this.numChecked = numChecked;
// if (this.checked) {
// for (var i = 0, lenI = this.list.cart_info.length; i < lenI; ++i) {
// const item = items[i]
// this.$set(item, 'checked', false)
// }
// } else {
// for (var i = 0, lenI = this.list.cart_info.length; i < lenI; ++i) {
// const item = items[i]
// this.$set(item, 'checked', true)
// if (item.is_writeoff == 1) {
// this.checkModel = this.checkModel.filter(item => item != item.cart_id)
// } else {
// this.checkModel.push(item.cart_id)
// }
// }
// this.lengt = this.checkModel.length
// }
},
dan(id, index) {
// if (this.checkModel.indexOf(id) == -1) {
// this.$set(this.list.cart_info[index], 'checked', true)
// this.checkModel.push(id)
// } else {
// this.$set(this.list.cart_info[index], 'checked', false)
// this.checkModel = this.checkModel.filter(item => item != id)
// }
this.cart_info[index].checked = !this.cart_info[index].checked;
this.checkModel = [];
for (let i = 0; i < this.cart_info.length; i++) {
if (this.cart_info[i].checked) {
this.checkModel.push(this.cart_info[i].cart_id);
}
}
let checked = true;
for (let i = 0; i < this.cart_info.length; i++) {
if (!this.cart_info[i].is_writeoff) {
if (!this.cart_info[i].checked) {
checked = false;
}
}
}
this.checked = checked;
let numChecked = 0;
for (let i = 0; i < this.cart_info.length; i++) {
if (!this.cart_info[i].is_writeoff) {
if (this.cart_info[i].checked) {
numChecked = numChecked + this.cart_info[i].surplus_num_input;
}
}
}
this.numChecked = numChecked;
},
getList: function(id) {
orderCartInfo({
oid: id,
auth: 2,
}).then(res => {
this.list = res.data
this.lists = JSON.parse(JSON.stringify(res.data))
this.listlet = res.data.cart_info.length
this.$set(this.attr, 'id', this.list.id);
this.checkAll()
this.num()
})
},
onDataId: function(id) {
this.nums.forEach((item) => {
item.num = 0
})
this.id = id;
this.getList(id)
},
switchs() {
this.attr.cartAttr = true;
this.$refs.writeOff.getList(2)
},
onMyEvent() {
this.attr.cartAttr = false;
},
verification() {
let that = this
let newObj = [];
for (let i = 0; i < this.cart_info.length; i++) {
if (this.cart_info[i].checked && !this.cart_info[i].is_writeoff) {
newObj.push({
cart_id: this.cart_info[i].cart_id,
cart_num: this.cart_info[i].surplus_num_input,
});
}
}
// return
// let obj = {};
// 将数组转化为对象
// for (let key in this.checkModel) {
// obj[key] = this.checkModel[key];
// };
// let newObj = Object.keys(obj).map(val => ({
// cart_id: obj[val],
// }));
//处理列表内对应的核销数的数值
// for (var i = 0; i < newObj.length; i++) {
// for (var j = 0; j < this.list.cart_info.length; j++) {
// if (newObj[i].cart_id == this.list.cart_info[j].cart_id) {
// newObj[i].cart_num = this.list.cart_info[j].surplus_num;
// }
// }
// }
this.newList = newObj
if (that.checkModel.length == 0) {
that.$util.Tips({
title: '请选择商品'
});
} else {
uni.showLoading({
title: '加载中',
});
let num = 0;
newObj.forEach((item) => {
num = num + parseInt(item.cart_num)
})
this.writeOffNum = num;
setTimeout(function() {
orderWriteoff({
auth: that.auth,
oid: that.oid,
cart_ids: that.newList
}).then(res => {
uni.hideLoading();
// that.box = true
let isAll = 1;
for (let i = 0; i < that.list.cart_info.length; i++) {
if (that.list.cart_info[i].checked) {
if (that.list.cart_info[i].surplus_num != that.list.cart_info[i].surplus_num_input) {
isAll = 0
break;
}
}
}
that.$emit('success', isAll);
}).catch(err => {
that.$util.Tips({
title: err
});
uni.hideLoading();
})
}, 1000);
}
},
// 所有订单核销完成
ok(type) {
this.box = false
this.nums.forEach((item) => {
item.num = 0
})
this.getList(this.id)
if (type) {
uni.redirectTo({
url: '/pages/admin/distribution/index'
})
}
}
}
}
</script>
<style scoped lang="scss">
.shoppingCart {
padding: 24rpx 20rpx;
}
.shoppingCart .content {
padding: 32rpx 24rpx;
margin-top: 20rpx;
border-radius: 24rpx;
background: #FFFFFF;
.list_top {
background-color: #FFFFFF;
font-size: 28upx;
color: #333333;
height: 90upx;
line-height: 90upx;
padding-left: 24upx;
border-bottom: 2upx solid #EEEEEE;
.bluefont {
color: $primary-admin;
display: inline-block;
margin: 0upx 10upx;
}
.garyfont {
color: #999999;
}
}
}
.shoppingCart .list .item .xuan .iconfont {
font-size: 40rpx;
color: #CCCCCC;
}
.shoppingCart .list .item .xuan .icon-a-ic_CompleteSelect {
color: $primary-admin;
}
.shoppingCart .list .item .picTxt {
// width: 627upx;
position: relative;
flex: 1;
min-width: 0;
padding-left: 16rpx;
}
.shoppingCart .list .item .picTxt .pictrue {
width: 136rpx;
height: 136rpx;
}
.shoppingCart .list .item .picTxt .pictrue image {
width: 100%;
height: 100%;
border-radius: 16rpx;
}
.shoppingCart .list .item .picTxt .text {
flex: 1;
min-width: 0;
padding-left: 20rpx;
font-size: 28upx;
color: #282828;
}
.shoppingCart .list .item .picTxt .text .reColor {
color: #999;
width: 60%;
}
.shoppingCart .list .item .picTxt .text .title {
display: flex;
justify-content: space-between;
font-size: 28rpx;
line-height: 40rpx;
color: #333333;
.bluecol {
color: $primary-admin;
}
.orangcol {
color: #FF7E00;
}
.graycol {
color: #CCCCCC;
}
}
.shoppingCart .list .item .picTxt .text .title .line1 {
flex: 1;
}
.shoppingCart .list .item .picTxt .text .title .top {
width: 70%;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
font-size: 28upx;
font-weight: 400;
}
.shoppingCart .list .item .picTxt .text .reElection {
margin-top: 20upx;
}
.shoppingCart .list .item .picTxt .text .reElection .title {
font-size: 24upx;
}
.shoppingCart .list .item .picTxt .text .reElection .reBnt {
width: 120upx;
height: 46upx;
border-radius: 23upx;
font-size: 26upx;
}
.shoppingCart .list .item .picTxt .text .infor {
font-size: 22rpx;
line-height: 30rpx;
color: #999999;
margin-top: 12rpx;
}
.shoppingCart .list .item .picTxt .text .money {
font-size: 36rpx;
line-height: 36rpx;
color: #333333;
margin-top: 18rpx;
font-family: Regular;
}
.shoppingCart .list .item .picTxt .carnum {
height: 36rpx;
// position: absolute;
// bottom: 7upx;
// right: 0;
}
.shoppingCart .list .item .picTxt .carnum view {
// border: 1upx solid #a4a4a4;
width: 32rpx;
text-align: center;
height: 100%;
line-height: 36rpx;
font-size: 24rpx;
color: #333333;
}
.shoppingCart .list .item .picTxt .carnum .reduce {
border-right: 0;
border-radius: 30upx 0 0 30upx;
}
.shoppingCart .list .item .picTxt .carnum .reduce.on {
border-color: #e3e3e3;
color: #dedede;
}
.shoppingCart .list .item .picTxt .carnum .plus {
border-left: 0;
border-radius: 0 30upx 30upx 0;
}
.shoppingCart .list .item .picTxt .carnum .num {
color: #282828;
}
.shoppingCart .list .item .picTxt .carnum .num0 {
color: #a4a4a4;
}
.shoppingCart .list .item .picTxt .carnum .nums {
width: 72rpx;
border-radius: 4rpx;
background: #F5F5F5;
}
.shoppingCart .footer {
// z-index: 999;
width: 100%;
background: #FFFFFF;
position: fixed;
padding: 0 20rpx 0 32rpx;
box-sizing: border-box;
bottom: 0;
left: 0;
height: 96rpx;
height: calc(96rpx + constant(safe-area-inset-bottom)); ///兼容 IOS<11.2/
height: calc(96rpx + env(safe-area-inset-bottom)); ///兼容 IOS>11.2/
padding-bottom: constant(safe-area-inset-bottom); ///兼容 IOS<11.2/
padding-bottom: env(safe-area-inset-bottom); ///兼容 IOS>11.2/
}
.shoppingCart .footer.on {
// #ifndef H5
bottom: 0upx;
// #endif
}
.shoppingCart .footer .iconfont {
font-size: 40rpx;
color: #CCCCCC;
}
.shoppingCart .footer .icon-a-ic_CompleteSelect {
color: $primary-admin;
}
.shoppingCart .footer .checkAll {
font-size: 28upx;
color: #282828;
margin-left: 16upx;
}
.shoppingCart .footer .money {
font-size: 24rpx;
height: 64rpx;
padding: 0 32rpx;
background: #2A7EFB;
border-radius: 32rpx;
font-weight: 400;
color: #FFFFFF;
line-height: 64rpx;
}
.shoppingCart .footer .placeOrder {
color: #fff;
font-size: 30upx;
width: 226upx;
height: 70upx;
border-radius: 50upx;
text-align: center;
line-height: 70upx;
margin-left: 22upx;
}
.shoppingCart .footer .button .bnt {
font-size: 28upx;
color: #999;
border-radius: 50upx;
border: 1px solid #999;
width: 160upx;
height: 60upx;
text-align: center;
line-height: 60upx;
}
.shoppingCart .footer .button form~form {
margin-left: 17upx;
}
.writeoff {
opacity: 0.6;
}
.he {
display: flex;
justify-content: space-between;
.txt {
font-size: 22upx;
}
}
.box {
position: fixed;
top: 0;
bottom: 0;
width: 100%;
height: 100%;
z-index: 10;
background-color: #78797a;
.small_box {
position: fixed;
top: 50%;
right: 75rpx;
left: 75rpx;
padding: 40rpx;
border-radius: 32rpx;
background: #FFFFFF;
transform: translateY(-50%);
image {
width: 100%;
height: 228upx;
}
.content {
// height: 200upx;
text-align: center;
.font {
font-weight: 500;
font-size: 32rpx;
line-height: 52rpx;
color: #333333;
}
.small_font {
margin-top: 24rpx;
font-size: 30rpx;
line-height: 42rpx;
color: #666666;
}
}
.btn-box {
margin-top: 40rpx;
}
.btn {
flex: 1;
height: 72rpx;
border: 1rpx solid $primary-admin;
border-radius: 36rpx;
margin-left: 32rpx;
transform: rotateZ(360deg);
text-align: center;
font-weight: 500;
font-size: 26rpx;
line-height: 70rpx;
color: #2A7EFB;
&:first-child {
margin-left: 0;
}
&.on {
background: $primary-admin;
color: #FFFFFF;
}
}
}
}
.uni-p-b-96 {
height: 96upx;
}
</style>

View File

@@ -0,0 +1,267 @@
<template>
<!-- 核销订单下拉列表 -->
<view>
<view class="product-window"
:class="(attr.cartAttr === true ? 'on' : '') + ' ' + (iSbnt?'join':'') + ' ' + (iScart?'joinCart':'')">
<view class="textpic acea-row row-between-wrapper">
<view class="iconfont icon-guanbi" @click="closeAttr"></view>
</view>
<view class="rollTop">
<view class="scan">
<view class="header" :style="{backgroundImage:'url('+imgHost+'/statics/images/banner.png'+')'}">
请选择当前核销订单
</view>
<view class="box">
<view class="content" v-for="(item,index) in list" :key="index" @click="sure(item.id)">
<view class="content_box">
<image :src="item.image" mode=""></image>
<view class="content_box_title">
<p class="textbox">订单号:{{ item.order_id }}</p>
<p class="attribute mar">下单时间:{{ item.add_time }}</p>
<view class="txt">
<p class="attribute">订单实付:¥{{ item.pay_price }}</p>
<p class="orange" v-if="item._status == 12">部分核销</p>
<p class="attributes blue" v-if="item._status == 11">未核销</p>
<slot name="bottom"></slot>
</view>
</view>
</view>
</view>
</view>
</view>
</view>
</view>
</view>
</template>
<script>
import {orderWriteoffInfo} from '@/api/admin'
import {HTTP_REQUEST_URL} from '@/config/app';
export default {
props: {
attr: {
type: Object,
default: () => {}
},
iSbnt: {
type: Number,
value: 0
},
iScart: {
type: Number,
value: 0
},
},
data() {
return {
verify_code:'',
list: [],
imgHost:HTTP_REQUEST_URL,
};
},
mounted() {},
methods: {
closeAttr: function() {
this.$emit('myevent');
},
getList:function(type) {
this.attr.type = type;
// uni.showLoading({
// title: '加载中'
// });
orderWriteoffInfo(type,{verify_code:this.attr.code,code_type:2}).then(res=>{
// uni.hideLoading();
this.list = res.data;
}).catch(err=>{
// uni.hideLoading();
this.$util.Tips({
title: err
});
})
},
sure:function(data) {
this.$emit('dataId',data);
this.$emit('myevent');
}
}
}
</script>
<style scoped lang="scss">
.vip-money {
color: #282828;
font-size: 28rpx;
font-weight: 700;
margin-left: 6rpx;
}
.vipImg {
width: 68rpx;
height: 27rpx;
image {
width: 100%;
height: 100%;
}
}
.product-window {
position: fixed;
bottom: 0;
width: 100%;
left: 0;
background-color: #f5f5f5;
z-index: 100;
border-radius: 16rpx 16rpx 0 0;
transform: translate3d(0, 100%, 0);
transition: all .3s cubic-bezier(.25, .5, .5, .9);
padding-bottom: 140rpx;
padding-bottom: calc(140rpx + constant(safe-area-inset-bottom)); ///兼容 IOS<11.2/
padding-bottom: calc(140rpx + env(safe-area-inset-bottom)); ///兼容 IOS>11.2/
}
.product-window.on {
transform: translate3d(0, 0, 0);
}
.product-window.join {
padding-bottom: 30rpx;
}
.product-window.joinCart {
// padding-bottom: 30rpx;
z-index: 10000;
}
.product-window .textpic {
padding: 0 130rpx 0 30rpx;
margin-top: 29rpx;
position: relative;
}
.product-window .textpic .pictrue {
width: 150rpx;
height: 150rpx;
}
.product-window .textpic .pictrue image {
width: 100%;
height: 100%;
border-radius: 10rpx;
}
.product-window .textpic .text {
width: 410rpx;
font-size: 32rpx;
color: #202020;
}
.product-window .textpic .text .money {
font-size: 24rpx;
margin-top: 40rpx;
}
.product-window .textpic .text .money .num {
font-size: 36rpx;
}
.product-window .textpic .text .money .stock {
color: #999;
margin-left: 6rpx;
}
.product-window .textpic .iconfont {
position: absolute;
right: 30rpx;
top: -5rpx;
font-size: 35rpx;
color: #8a8a8a;
}
.product-window .rollTop {
max-height: 700rpx;
overflow: auto;
margin-top: 36rpx;
.scan{
padding-bottom: 160upx;
.header {
width: 100%;
height: 220upx;
// background-image: url(../../static/images/banner.png);
background-repeat: no-repeat; //不重复
background-size: 100% 100%;
color: #FFFFFF;
font-size: 32upx;
text-align: center;
line-height: 160upx;
margin: 0 auto;
}
.box{
margin: -64upx auto 0 auto;
}
.content{
margin: 16upx auto 16upx auto;
width: 694upx;
// height: 428upx;
padding: 28upx 24upx 32upx;
background: #FFFFFF;
border-radius: 12upx;
.pad{padding: 20upx 20upx 22upx;}
.content_box{
height: 70px;
border-radius: 8upx;
padding-right: 22upx;
display: flex;
justify-content: flex-start;
align-items: center;
image{
width: 140upx;
height: 140upx;
border-radius: 8upx;
}
.content_box_title{
flex: 1;
margin-left: 18upx;
font-size: 20upx;
font-weight: 400;
.textbox{
white-space: nowrap;
text-overflow: ellipsis;
overflow: hidden;
word-break: break-all;
width: 466upx;
font-size: 30upx;
font-weight: bold;
line-height: 21px;
}
.mar{margin: 16upx 0upx;}
.attribute{
color: #999999;
// margin: 4upx 0upx 10upx;
}
.txt{
display: flex;
justify-content: space-between;
font-size: 24upx;
.orange{color: #FF7E00;}
.blue{color: #1890FF;}
}
}
}
.content_bottom{
display: flex;
justify-content: space-between;
font-size: 22upx;
padding: 0upx 20upx;
color: #666666;
.money{
font-size: 26upx;
color: #F5222D;
}
}
}
}
}
</style>

View File

@@ -0,0 +1,817 @@
<template>
<view class="deliver-goods">
<header class="header">
<view class="order-num">
<view class="num line1">订单号:{{ order_id }}</view>
</view>
<view class="address">
<view class="name">
<text class="iconfont icon-ic_location4"></text>
{{ delivery.real_name }}
<text class="phone">{{ delivery.user_phone }}</text>
</view>
<view>地址:{{ delivery.user_address }}</view>
</view>
<view class="line">
<image src="@/static/images/line.jpg" />
</view>
</header>
<view class="wrapper">
<view class="item acea-row row-between-wrapper">
<view>发货方式</view>
<view class="mode acea-row row-middle row-right">
<template v-for="(item, index) in types">
<view v-if="item.show" class="goods" :class="(active === index || productType==3) ? 'on' : ''" :key="index" @click="changeType(item, index)">
<text :class="['iconfont', active === index ? 'icon-ic_Selected' : 'icon-ic_unselect']"></text>
{{ item.title }}
</view>
</template>
</view>
</view>
<block v-if="logistics.length>0">
<view class="list" v-show="active === 0">
<view class="item acea-row row-middle" v-if="delivery.config_export_open == 1">
<view>发货类型</view>
<view class="mode acea-row row-middle row-right">
<view class="goods" :class="curExpress === item.key ? 'on' : ''" v-for="(item, index) in expressType" :key="index" @click="changeExpTpe(item, index)">
<text :class="['iconfont', curExpress === item.key ? 'icon-ic_Selected' : 'icon-ic_unselect']"></text>
{{ item.title }}
</view>
</view>
</view>
<block v-if="curExpress == 1">
<view class="item acea-row row-middle">
<view>快递公司</view>
<view class="select-box">
<picker class="pickerBox" @change="bindPickerChange" :value="seIndex" :range="logistics" range-key="name">
<view class="uni-input">{{logistics[seIndex].name}}</view>
</picker>
</view>
<text class="iconfont icon-ic_rightarrow"></text>
</view>
<view class="item acea-row row-middle">
<view>快递单号</view>
<input type="text" placeholder="请输入" v-model="delivery_id" class="mode" />
<!-- #ifdef MP -->
<text class="iconfont icon-xiangji" @click="scanCode"></text>
<!-- #endif -->
<!-- #ifdef H5 -->
<text v-if="isWeixin" class="iconfont icon-xiangji" @click="scanCode"></text>
<!-- #endif -->
</view>
<view class="item">
<view class="trip" v-if="curExpress == 1">顺丰请输入单号 :收件人或寄件人手机号后四位</view>
<view class="trip" v-if="curExpress == 1">例如:SF000000000000:3941</view>
</view>
</block>
<block v-if="curExpress == 2">
<view class="item acea-row row-between-wrapper">
<view>寄件人姓名</view>
<input type="text" placeholder="填写寄件人姓名" v-model="to_name" class="mode" />
</view>
<view class="item acea-row row-between-wrapper">
<view>寄件人电话</view>
<input type="text" placeholder="填写寄件人电话" v-model="to_tel" class="mode" />
</view>
<view class="item acea-row row-between-wrapper">
<view>寄件人地址</view>
<input type="text" placeholder="填写寄件人地址" v-model="to_addr" class="mode" />
</view>
<view class="item acea-row row-between-wrapper">
<view>快递公司</view>
<view class="select-box">
<picker class="pickerBox" @change="bindPickerChange" :value="seIndex" :range="logistics" range-key="name">
<!-- <view></view> -->
<view class="uni-input">{{logistics[seIndex].name}}</view>
</picker>
</view>
</view>
<view class="item acea-row row-between-wrapper" v-if="expTemp.length>0">
<view>电子面单</view>
<view class="picker-add">
<picker class="pickerBox" @change="bindTempChange" :value="expIndex" :range="expTemp" range-key="title">
<view class="uni-input">{{expTemp[expIndex].title}}</view>
</picker>
<view class="look" @click="previewImage">预览</view>
</view>
</view>
</block>
</view>
</block>
<view class="list" v-show="active === 1">
<view class="item acea-row row-between-wrapper">
<view>送货人</view>
<view class="select-box" v-if="postPeople.length>0">
<picker class="pickerBox" @change="bindPostChange" :value="postIndex" :range="postPeople" range-key="wx_name">
<view class="acea-row row-middle">
<view class="uni-input">{{postPeople[postIndex].wx_name}}</view>
<text class="iconfont icon-ic_rightarrow"></text>
</view>
</picker>
</view>
</view>
<view class="item acea-row row-between-wrapper" v-if="postPeople[postIndex]">
<view>手机号</view>
<view class="select-box acea-row row-middle row-right">{{postPeople[postIndex].phone}}</view>
</view>
</view>
<textarea v-show="active === 2" v-model="fictitious_content" class="textarea" @blur="bindTextAreaBlur" placeholder="备注" :maxlength="500" auto-height />
</view>
<view class="split-wrapper" v-if="totalNum>1">
<view class="split-switch acea-row row-between-wrapper">
<view>分单发货</view>
<view class="switch" :class="{ on: curGoods }" @click="changeGoods"></view>
</view>
<splitOrder :select_all="false" :splitGoods="splitGoods" @getList="getList" v-if="curGoods"></splitOrder>
</view>
<view class="height-add"></view>
<view class="confirm-wrapper">
<view class="confirm" @click="saveInfo">确认提交</view>
</view>
</view>
</template>
<script>
import {
getAdminOrderDelivery,
setAdminOrderDelivery,
getLogistics,
orderExportTemp,
orderDeliveryInfo,
orderOrderDelivery,
orderSplitInfo,
orderSplitDelivery
} from "@/api/admin";
import splitOrder from '@/components/splitOrder';
export default {
name: "GoodsDeliver",
components: {
splitOrder
},
props: {},
data: function() {
return {
types: [{
type: "express",
title: "发货",
key: 1,
show: true,
},
{
type: "send",
title: "送货",
key: 2,
show: true,
},
{
type: "fictitious",
title: "无需物流",
key: 3,
show: true,
}
],
expressType: [{
title: '手动填写',
key: 1
},
{
title: '电子面单打印',
key: 2
},
],
orderGoods: [{
title: '开启',
key: 1
},
{
title: '关闭',
key: 0
}
],
curExpress: 1,
active: 0,
order_id: "",
delivery: [],
logistics: [],
delivery_type: "1",
delivery_name: "",
delivery_id: "",
seIndex: 0,
expIndex: 0,
expTemp: [], // 快递模板
to_name: '', // 发货人名称
to_tel: '', // 发货人电话
to_addr: "", // 发货人地址
postPeople: [], //配送人
postIndex: 0,
fictitious_content: '',
listId: 0,
curGoods: 0,
splitGoods: [],
cartIds: [],
totalNum: 0,
productType: 0,
// #ifdef H5
isWeixin: this.$wechat.isWeixin()
// #endif
};
},
watch: {
"$route.params.oid": function(newVal) {
let that = this;
if (newVal != undefined) {
that.order_id = newVal;
that.getIndex();
}
}
},
onLoad: function(option) {
this.order_id = option.id;
this.listId = option.listId;
this.totalNum = option.totalNum;
this.comeType = option.comeType;
this.productType = option.productType
if (this.productType == 3) {
// this.types.splice(0, 2);
for (let i = 0; i < this.types.length; i++) {
if (i == 2) {
this.types[i].show = true;
} else {
this.types[i].show = false;
}
}
this.delivery_type = 3;
this.active = 2;
}
if (option.orderStatus == 8 || option.orderStatus == 4 || option.orderStatus == 9) {
this.curGoods = 1;
this.orderGoods.pop();
this.splitList();
}
this.getIndex();
this.getLogistics();
this.orderDeliveryInfo()
this.geTorderOrderDelivery()
},
methods: {
getList(val) {
let that = this;
that.splitGoods = val;
let cartIds = [];
val.forEach((item) => {
if (item.checked) {
let i = {
cart_id: item.cart_id,
cart_num: item.surplus_num
}
cartIds.push(i)
}
})
this.cartIds = cartIds;
},
splitList() {
orderSplitInfo(this.listId).then(res => {
let list = res.data;
list.forEach((item) => {
item.checked = false
item.numShow = item.surplus_num
})
this.splitGoods = list;
}).catch(err => {
return this.$util.Tips({
title: err
});
})
},
// 点击获取拆单列表
changeGoods() {
this.curGoods = this.curGoods ? 0 : 1;
if (this.curGoods) {
this.splitList();
}
},
// 扫描快递单号一维码
scanCode() {
// #ifdef MP
let that = this;
uni.scanCode({
scanType: ['barCode'],
success(res) {
that.delivery_id = res.result;
}
})
// #endif
// #ifdef H5
if (this.$wechat.isWeixin()) {
this.$wechat.wechatEvevt('scanQRCode', {
needResult: 1,
scanType: ['barCode']
}).then(res => {
let result = res.resultStr.split(",");
this.delivery_id = result[1];
});
}
// #endif
},
// 预览图片
previewImage() {
uni.previewImage({
urls: [this.expTemp[this.expIndex].pic],
success: function() {
},
fail: function(error) {
}
});
},
// 获取配送员列表
geTorderOrderDelivery() {
orderOrderDelivery().then(res => {
this.postPeople = res.data
})
},
// 配送员选择
bindPostChange(e) {
this.postIndex = e.detail.value
},
// 选择发货类型
changeExpTpe(item, index) {
this.curExpress = item.key
this.getLogistics(index || '');
},
changeType: function(item, index) {
this.active = index;
this.delivery_type = item.key;
},
getIndex: function() {
let that = this;
getAdminOrderDelivery(that.order_id).then(
res => {
that.delivery = res.data;
},
error => {
that.$util.Tips({
title: error
})
}
);
},
getLogistics(status) {
let that = this;
getLogistics({
status
}).then(
res => {
that.logistics = res.data;
that.getExpTemp(res.data[0].code)
},
error => {
that.$util.Tips({
title: error
})
}
);
},
async saveInfo() {
let that = this,
delivery_type = that.delivery_type,
delivery_name = that.logistics[that.seIndex].name,
delivery_id = that.delivery_id,
userName = that.delivery_name,
save = {};
save.delivery_type = delivery_type;
save.delivery_code = that.logistics[that.seIndex].code
save.delivery_name = that.logistics[that.seIndex].name
save.type = that.active + 1
if (delivery_type == 1 && this.curExpress == 1) {
if (!delivery_id) {
return this.$util.Tips({
title: '请填写快递单号'
})
}
save.express_record_type = that.curExpress
save.delivery_id = delivery_id
if (that.curGoods) {
that.setSplitInfo(save)
} else {
that.setInfo(save);
}
}
if (delivery_type == 1 && this.curExpress == 2) {
if (!that.to_name) {
return this.$util.Tips({
title: '请填写寄件人姓名'
})
}
if (!that.to_tel) {
return this.$util.Tips({
title: '请填写寄件人手机号码'
})
}
if (!(/^1[3456789]\d{9}$/.test(that.to_tel))) {
return this.$util.Tips({
title: '请填写寄件人手机号码'
})
}
if (!that.to_addr) {
return this.$util.Tips({
title: '请填写寄件人地址'
})
}
if (that.expTemp.length == 0) {
return this.$util.Tips({
title: '请选择电子面单'
})
}
save.express_record_type = that.curExpress
save.to_name = that.to_name
save.to_tel = that.to_tel
save.to_addr = that.to_addr
save.express_temp_id = that.expTemp[that.expIndex].temp_id
if (that.curGoods) {
that.setSplitInfo(save)
} else {
that.setInfo(save);
}
}
if (delivery_type == 2) {
if (!that.postPeople.length) {
return this.$util.Tips({
title: '请在平台后台添加送货人'
})
}
let obj = this.postPeople[this.postIndex]
let params = {}
params.type = that.delivery_type
params.sh_delivery_name = obj.wx_name
params.sh_delivery_id = obj.phone
params.sh_delivery_uid = obj.uid
if (that.curGoods) {
that.setSplitInfo(params)
} else {
that.setInfo(params);
}
}
if (delivery_type == 3) {
let params = {}
params.type = that.delivery_type;
params.fictitious_content = that.fictitious_content;
if (that.curGoods) {
that.setSplitInfo(params)
} else {
that.setInfo(params);
}
}
},
setInfo: function(item) {
let that = this;
setAdminOrderDelivery(that.delivery.id, item).then(
res => {
that.$util.Tips({
title: res.msg,
icon: 'success',
mask: true
})
setTimeout(res => {
if (this.comeType == 2) {
uni.navigateTo({
url: '/pages/admin/orderDetail/index?id=' + this.order_id
})
} else {
uni.navigateTo({
url: '/pages/admin/orderList/index?types=1'
})
}
}, 2000)
},
error => {
that.$util.Tips({
title: error
})
}
);
},
setSplitInfo(item) {
if (!this.cartIds.length) {
return this.$util.Tips({
title: '请选择发货商品'
})
}
item.cart_ids = this.cartIds
orderSplitDelivery(this.delivery.id, item).then(res => {
this.$util.Tips({
title: res.msg,
icon: 'success',
mask: true
})
setTimeout(res => {
if (this.comeType == 2) {
uni.navigateTo({
url: '/pages/admin/orderDetail/index?id=' + this.order_id
})
} else {
uni.navigateTo({
url: '/pages/admin/orderList/index?types=1'
})
}
}, 2000)
}).catch(err => {
this.$util.Tips({
title: err
})
})
},
bindPickerChange(e) {
this.seIndex = e.detail.value
this.getExpTemp(this.logistics[e.detail.value].code)
},
bindTempChange(e) {
this.expIndex = e.detail.value
},
getExpTemp(code) {
orderExportTemp({
com: code
}).then(res => {
this.expTemp = res.data.data
})
},
// 获取订单打印默认配置
orderDeliveryInfo() {
orderDeliveryInfo().then(res => {
this.to_name = res.data.to_name;
this.to_tel = res.data.to_tel;
this.to_addr = res.data.to_add;
})
}
}
};
</script>
<style lang="scss">
.picker-add {
display: flex;
align-items: center;
}
.height-add {
height: 120upx;
}
/*发货*/
.deliver-goods {
padding: 22rpx 20rpx;
}
.deliver-goods .header {
position: relative;
padding: 0 32rpx;
border-radius: 24rpx;
background: #FFFFFF;
overflow: hidden;
}
.deliver-goods .header .order-num {
padding: 20rpx 0;
border-bottom: 1px dotted #EEEEEE;
}
.deliver-goods .header .order-num .num {
font-size: 28rpx;
line-height: 40rpx;
color: #333333;
position: relative;
}
.deliver-goods header .order-num .num:after {}
.deliver-goods header .order-num .name {
width: 260upx;
font-size: 26upx;
color: #282828;
text-align: center;
}
.deliver-goods header .order-num .name .iconfont {
font-size: 35upx;
color: #477ef3;
vertical-align: middle;
margin-right: 10upx;
}
.deliver-goods .header .address {
padding: 20rpx 0 40rpx;
font-size: 24rpx;
line-height: 34rpx;
color: #999999;
}
.deliver-goods .header .address .name {
font-weight: 500;
font-size: 30rpx;
line-height: 42rpx;
color: #333333;
margin-bottom: 12rpx;
}
.deliver-goods .header .address .name .iconfont {
margin-right: 8rpx;
font-size: 32rpx;
}
.deliver-goods .header .address .name .phone {
margin-left: 40rpx;
}
.deliver-goods .header .line {
position: absolute;
bottom: 0;
left: 0;
width: 100%;
height: 4rpx;
}
.deliver-goods .header .line image {
width: 100%;
height: 100%;
display: block;
}
.deliver-goods .wrapper {
padding: 12rpx 0;
border-radius: 24rpx;
margin-top: 20rpx;
background-color: #fff;
}
.deliver-goods .wrapper .item {
padding: 0 24rpx;
height: 80rpx;
font-size: 28rpx;
color: #333333;
position: relative;
}
.deliver-goods .wrapper .item .mode {
flex: 1;
height: 100%;
text-align: right;
}
.deliver-goods .wrapper .item .mode .iconfont {
font-size: 32rpx;
margin-right: 12rpx;
color: #CCCCCC;
}
.deliver-goods .wrapper .item .mode .goods~.goods {
margin-left: 50rpx;
}
.deliver-goods .wrapper .item .mode .goods {
color: #999999;
}
.deliver-goods .wrapper .item .mode .goods.on {
color: #333333;
}
.deliver-goods .wrapper .item .mode .goods.on .iconfont {
color: $primary-admin;
}
.deliver-goods .wrapper .item .icon-up {
position: absolute;
font-size: 35upx;
color: #2c2c2c;
right: 30upx;
}
.deliver-goods .wrapper .item select {
direction: rtl;
padding-right: 60upx;
position: relative;
z-index: 2;
}
.deliver-goods .wrapper .item input::placeholder {
color: #bbb;
}
.deliver-goods .confirm-wrapper {
background-color: #FFFFFF;
position: fixed;
left: 0;
bottom: 0;
bottom: constant(safe-area-inset-bottom);
bottom: env(safe-area-inset-bottom);
width: 100%;
padding: 20rpx;
}
.deliver-goods .confirm {
font-weight: 500;
font-size: 28rpx;
color: #fff;
height: 80rpx;
border-radius: 40rpx;
background: #2A7EFB;
text-align: center;
line-height: 80rpx;
}
.select-box {
flex: 1;
height: 100%;
.pickerBox {
display: flex;
align-items: center;
justify-content: flex-end;
width: 100%;
height: 100%;
.iconfont {
margin-left: 8rpx;
font-size: 24rpx;
color: #999999;
}
}
}
.look {
margin-left: 20rpx;
color: $primary-admin;
}
.textarea {
display: block;
min-height: 192rpx;
padding: 24rpx;
width: 100%;
// border-bottom: 1px solid #f0f0f0;
box-sizing: border-box;
}
.icon-xiangji {
font-size: 35rpx;
color: $primary-admin;
}
.trip {
font-size: 22rpx;
color: #ccc;
padding: 6rpx 0;
}
.split-wrapper {
border-radius: 24rpx;
margin-top: 20rpx;
background: #FFFFFF;
.splitOrder {
padding: 0 24rpx 46rpx;
margin: 0;
}
}
.split-switch {
padding: 40rpx 24rpx;
font-size: 28rpx;
color: #333333;
.switch {
position: relative;
width: 79rpx;
height: 48rpx;
padding: 4rpx;
border-radius: 24rpx;
background: #DDDDDD;
transition: background 0.1s, border 0.1s;
&::after {
content: "";
position: absolute;
top: 4rpx;
left: 4rpx;
width: 40rpx;
height: 40rpx;
border-radius: 20rpx;
background: #FFFFFF;
box-shadow: 0 3rpx 6rpx 0 rgba(0, 0, 0, 0.08);
transition: transform 0.35s cubic-bezier(0.4, 0.4, 0.25, 1.35);
}
&.on {
background: #2A7EFB;
&::after {
transform: translateX(31rpx);
}
}
}
}
</style>

View File

@@ -0,0 +1,905 @@
<template>
<view>
<!-- #ifdef MP || APP -->
<NavBar titleText="配送员" :iconColor="iconColor" :textColor="iconColor" :isScrolling="isScrolling" showBack></NavBar>
<!-- #endif -->
<view class="headerBg"></view>
<view class="order-index">
<view class="header acea-row row-middle">
<image :src="user.avatar" class="avatar"></image>
<view class="text">
<view class="name line1">{{ user.nickname }}</view>
<view class="phone">{{ user.phone }}</view>
</view>
<view class="item">
<!-- #ifdef APP-PLUS || MP-WEIXIN -->
<view class="item">
<view class="iconfont icon-ic_Scan ite" @click="to"></view>
</view>
<!-- #endif -->
<!-- #ifdef H5 -->
<view v-if="isWeixin" class="item">
<view class="iconfont icon-ic_Scan ite" @click="to"></view>
</view>
<!-- #endif -->
</view>
</view>
<view v-show="footer == 'tongji'" class="">
<view class="wrapper">
<view class="title acea-row row-between row-middle">
<view class="uni-list-cell-db" @click="hiddened">
<picker @change="bindPickerChange" :range="arrays" @cancel="cancel">
<label class="aa">{{array.length && array[index].name}}</label>
<text class='iconfont' :class='hidden==true?"icon-ic_downarrow":"icon-ic_uparrow"'></text>
</picker>
</view>
<view class="tab acea-row">
<view class="box" :class="detailtabs== 'today' ? 'on':''" @click="detailtab('today')">今日</view>
<view class="box" :class="detailtabs== 'yesterday' ? 'on':''" @click="detailtab('yesterday')">昨日</view>
<view class="box" :class="detailtabs== 'month' ? 'on':''" @click="detailtab('month')">本月</view>
</view>
</view>
<Loading :loaded="loaded" :loading="loading"></Loading>
<view class="list acea-row" v-if="!loading">
<view class="item">
<view class="num">{{ census.unsend || 0 }}</view>
<view>待配送</view>
</view>
<view class="item">
<view class="num">{{ census.send || 0 }}</view>
<view>已配送</view>
</view>
<view class="item">
<view class="num">{{ census.send_price || 0 }}</view>
<view>配送金额</view>
</view>
</view>
</view>
<view class="public-wrapper">
<view class="title">
<view class="uni-list-cell-db" @click="hiddened">
详细数据
</view>
</view>
<view class="nav acea-row row-between-wrapper">
<view class="data">日期</view>
<view class="browse">订单数</view>
<view class="turnover">配送金额</view>
</view>
<Loading :loaded="loaded" :loading="loading"></Loading>
<view v-if="list.length" class="conter">
<view class="item acea-row row-between-wrapper" v-for="(item, index) in list" :key="index">
<view class="data">{{ item.time }}</view>
<view class="browse">{{ item.count }}</view>
<view class="turnover">¥ {{ item.price }}</view>
</view>
</view>
<view v-else class="unconter">
<view v-if="!loading">暂无数据</view>
</view>
</view>
</view>
<view v-show="footer == 'list'" class="tongji-index">
<view class="tabbar acea-row">
<view class="item" :class="{ active: type == 1 }">
<view class="text-box"></view>
<view class="item-box"></view>
<view class="inner acea-row row-center row-middle" @click="tab('1')">待配送({{ count.unsend }})</view>
</view>
<view class="item" :class="{ active: type == 2 }">
<view class="text-box"></view>
<view class="item-box"></view>
<view class="inner acea-row row-center row-middle" @click="tab('2')">已配送({{ count.send }})</view>
</view>
</view>
<view class="content">
<view class="item" v-for="(item,index) in orderlist" :key="index" @click="jump(item.id)">
<view class="item-top acea-row row-between row-middle">
<view class="">订单号:{{ item.order_id }}</view>
<view style="color: #FF7E00;">{{type == 1?'待配送':'已配送'}}</view>
</view>
<view class="item-center acea-row">
<scroll-view v-if="item.cart_id.length > 1" class="goods-section scroll-view" scroll-x="true">
<image v-for="(value, i) in item._info" :key="i" :src="value.cart_info.productInfo.image" class="image"></image>
</scroll-view>
<view v-else class="goods-section">
<view v-for="(value, i) in item._info" :key="i" class="acea-row">
<image :src="value.cart_info.productInfo.image" class="image"></image>
<view class="name-wrap">
<view class="name line2">{{ value.cart_info.productInfo.store_name }}</view>
<view class="attr line1">{{ value.cart_info.productInfo.attrInfo.suk }}</view>
</view>
</view>
</view>
<view class="money-section">
<baseMoney :money="item.pay_price" symbolSize="20" integerSize="32" decimalSize="20"></baseMoney>
<view class="num">共{{ item.total_num }}件</view>
</view>
</view>
<view class="item-bottom acea-row">
<view>配送地址:</view>
<view class="info">{{ item.user_address }}</view>
</view>
<!-- <view class="content_box" v-for="(val, key) in item._info" :key="key">
<image :src="val.cart_info.productInfo.image" mode=""></image>
<view class="content_box_title">
<view class="txt">
<view class="textbox"><text class="icon-color" v-if="val.cart_info.is_gift">[赠品]</text>{{ val.cart_info.productInfo.store_name }}</view>
<view>x {{ val.cart_info.cart_num }}</view>
</view>
<p class="attribute">属性:{{ val.cart_info.productInfo.attrInfo.suk }}</p>
<p>¥ {{ val.cart_info.productInfo.attrInfo.price }} </p>
</view>
</view> -->
<!-- <view class="content_bottom">
<view></view>
<view>共{{ item.total_num }}件商品,订单实付:<span class="money">¥{{ item.pay_price }}</span></view>
</view> -->
</view>
<emptyPage v-if="!orderlist.length && !loading" title="暂无数据~" src="/statics/images/noOrder.gif"></emptyPage>
</view>
<Loading :loaded="loaded" :loading="loading"></Loading>
</view>
</view>
<view class="footer">
<view class="footer-inner acea-row">
<view class="tab acea-row row-column row-center row-middle" :class="footer == 'list'?'on':''" @click="footerTab('list')">
<image v-if="footer == 'list'" :src="imgHost+'/statics/images/admin-order-menu2.png'" class="image"></image>
<image v-else :src="imgHost+'/statics/images/admin-order-menu1.png'" class="image"></image>
<view class="font">订单列表</view>
</view>
<view class="tab acea-row row-column row-center row-middle" :class="footer == 'tongji'?'on':''" @click="footerTab('tongji')">
<image v-if="footer == 'tongji'" :src="imgHost+'/statics/images/admin-order-menu4.png'" class="image"></image>
<image v-else :src="imgHost+'/statics/images/admin-order-menu3.png'" class="image"></image>
<view class="font">数据统计</view>
</view>
</view>
<view class="safe-area-inset-bottom"></view>
</view>
<view class="footer-placeholder"></view>
<view class="safe-area-inset-bottom"></view>
</view>
</template>
<script>
import {
// getStatisticsInfo,
// getStatisticsMonth,
deliveryInfo,
deliveryStatistics,
deliveryList,
deliveryOrderList,
orderWriteoffInfo
} from "@/api/admin";
import Loading from '@/components/Loading/index.vue';
import emptyPage from '@/components/emptyPage.vue'
// #ifdef MP || APP
import NavBar from '@/components/NavBar.vue';
// #endif
import {
HTTP_REQUEST_URL
} from '@/config/app';
export default {
name: 'adminOrder',
components: {
Loading,
emptyPage,
// #ifdef MP || APP
NavBar,
// #endif
},
data() {
return {
hidden: true,
index: 0,
detailtabs: 'today',
footer: 'list',
type: '1',
arrays: [], //展示下拉时的数据
array: [], //下拉时选择的数据
storeInfoid: 0, //下拉时选择的数据ID
census: {},
list: [],
orderlist: [],
count: {},
page: 1,
limit: 15,
loaded: false,
loading: false,
user: {},
ids: '',
verify_code: '',
// #ifdef H5
isWeixin: this.$wechat.isWeixin(),
// #endif
imgHost: HTTP_REQUEST_URL,
// #ifdef MP || APP
iconColor: '#FFFFFF',
isScrolling: false,
// #endif
}
},
onLoad() {
// this.getIndex();
// this.init()
this.userInfo();
this.footerTab('list')
// this.$scroll(this.$refs.container, () => {
// !this.loading && this.getList();
// });
},
methods: {
userInfo() {
deliveryInfo().then(res => {
this.user = res.data
this.array = res.data.store_info.map(a => a);
this.arrays = res.data.store_info.map(a => a.name);
let obj = {
id: 0,
name: '全部'
}
this.array.unshift(obj);
this.arrays.unshift(obj.name);
})
},
getStatistics() {
let data = {
store_id: this.storeInfoid,
data: this.detailtabs
}
deliveryStatistics(data).then(res => {
this.census = res.data
})
},
deliveryLists() {
let data = {
page: this.page,
limit: this.limit,
store_id: this.storeInfoid,
data: this.detailtabs
}
if (this.loading || this.loaded) return;
this.loading = true
deliveryList(data).then(res => {
this.loading = false
this.loaded = res.data.length < this.limit
this.page += 1
// this.list = res.data
this.list.push.apply(this.list, res.data);
})
},
getOrderList() {
if (this.loading || this.loaded) return;
this.loading = true
deliveryOrderList({
type: this.type,
page: this.page,
limit: this.limit
}).then(res => {
this.loading = false
this.count = res.data.data
this.loaded = res.data.list.length < this.limit
this.page += 1
let arr = [];
for (let i = 0; i < res.data.list.length; i++) {
arr = [];
for (let j = 0; j < res.data.list[i].user_address.length; j++) {
if (res.data.list[i].user_address[j] != ' ') {
arr.push(res.data.list[i].user_address[j]);
}
}
res.data.list[i].user_address = arr.join('');
}
this.orderlist.push.apply(this.orderlist, res.data.list);
})
},
init: function() {
this.orderlist = [];
this.list = [];
this.page = 1;
this.loaded = false;
this.loading = false;
},
to() {
var self = this;
// #ifdef MP || APP
uni.scanCode({
scanType: ["qrCode", "barCode"],
success(res) {
self.verify_code = res.result
self.codeChange();
},
fail(res) {},
})
// #endif
//#ifdef H5
this.$wechat.wechatEvevt('scanQRCode', {
needResult: 1,
scanType: ["qrCode", "barCode"]
}).then(res => {
let result = res.resultStr;
if (result.includes(',')) {
result = result.split(",")[1]
}
this.verify_code = result
this.codeChange();
});
//#endif
},
// 立即核销
codeChange: function() {
let self = this
let ref = /^[0-9]*$/;
if (!this.verify_code) return self.$util.Tips({
title: '请输入核销码'
});
if (!ref.test(this.verify_code)) return self.$util.Tips({
title: '请输入正确的核销码'
});
self.$util.Tips({
title: '查询中'
});
setTimeout(() => {
orderWriteoffInfo(2, {
verify_code: self.verify_code,
code_type: 2
}).then(res => {
if (res.status == 200) {
uni.navigateTo({
url: './scanning/index?code=' + self.verify_code
})
} else {
self.$util.Tips({
title: res.msg
});
}
}).catch(err => {
self.$util.Tips({
title: err
});
})
}, 800);
},
footerTab: function(type) {
this.footer = type
this.init()
if (type == 'tongji') {
this.deliveryLists()
this.getStatistics()
}
if (type == 'list') {
this.getOrderList()
}
},
tab(type) {
this.type = type
this.init()
this.getOrderList()
},
hiddened: function(e) {
this.hidden = !this.hidden;
},
cancel: function() {
this.hidden = !this.hidden;
},
bindPickerChange: function(e) {
this.hidden = !this.hidden;
this.index = e.target.value
this.storeInfoid = this.array[this.index].id
this.init()
this.getStatistics()
this.deliveryLists()
},
detailtab: function(type) {
this.detailtabs = type
this.init()
this.deliveryLists()
this.getStatistics()
},
jump: function(id) {
uni.navigateTo({
url: 'orderDetail/index?id=' + id
})
}
},
onReachBottom() {
if (this.footer == 'tongji') {
this.deliveryList()
}
if (this.footer == 'list') {
this.getOrderList()
}
}
}
</script>
<style lang="scss" scoped>
.footer-placeholder {
height: 100rpx;
}
.safe-area-inset-bottom {
height: 0;
height: constant(safe-area-inset-bottom);
height: env(safe-area-inset-bottom);
}
.nothing {
width: 80%;
margin: 0 auto;
margin-top: 30px;
text-align: center;
color: #cfcfcf;
}
.ite {
font-size: 20px;
}
.footer {
position: fixed;
left: 0;
bottom: 0;
width: 100%;
background: #FFFFFF;
.footer-inner {
height: 100rpx;
}
.tab {
flex: 1;
font-size: 20rpx;
line-height: 28rpx;
color: #333333;
.image {
width: 40rpx;
height: 40rpx;
margin-bottom: 6rpx;
}
}
.on {
color: #2A7EFB;
.font {
color: #2A7EFB;
}
}
}
/*订单首页*/
.headerBg {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 516rpx;
background: linear-gradient(270deg, #01ABF8 0%, #2A7EFB 100%);
}
.header {
padding: 22rpx 40rpx 32rpx 32rpx;
.avatar {
width: 80rpx;
height: 80rpx;
border-radius: 50%;
}
.text {
flex: 1;
padding-left: 16rpx;
font-size: 22rpx;
line-height: 30rpx;
color: #FFFFFF;
}
.name {
font-weight: 500;
font-size: 32rpx;
line-height: 44rpx;
}
.phone {
margin-top: 4rpx;
}
.items,
.item {
font-size: 24upx;
color: #fff;
height: 120upx;
display: flex;
align-items: center;
image {
width: 64upx;
height: 64upx;
border-radius: 60upx;
border: 2upx solid #FFFFFF;
}
.font {
display: inline-block;
margin-left: 16upx;
margin-right: 16upx;
font-size: 30upx;
}
}
}
.order-index {
position: relative;
.tongji-index {
padding: 0 20rpx;
.empty-page{
border-top-left-radius: 0;
border-top-right-radius: 0;
}
}
.tabbar {
position: relative;
z-index: 5;
height: 96rpx;
border-radius: 24rpx 24rpx 0 0;
overflow: hidden;
.item {
position: relative;
z-index: 5;
flex: 1;
font-size: 28rpx;
color: #333333;
&:last-child {
.item-box {
border-radius: 18rpx 0 0 0;
transform: perspective(80rpx) scaleX(1.4) scaleY(1.5) rotateX(20deg) translate(20rpx, 0);
}
.text-box {
border-radius: 0 24rpx 0 0;
}
}
&.active {
font-weight: 500;
color: #2A7EFB;
.item-box {
display: block;
}
}
}
.text-box {
position: absolute;
bottom: 0;
width: 100%;
height: 78rpx;
border-radius: 24rpx 0 0 0;
background: rgba(255, 255, 255, 0.95);
}
.item-box {
display: none;
position: absolute;
bottom: 0;
z-index: 2;
width: 100%;
height: 96rpx;
border-radius: 0 18rpx 0 0;
background: #FFFFFF;
transform-origin: center bottom;
transform: perspective(80rpx) scaleX(1.4) scaleY(1.5) rotateX(20deg) translate(-20rpx, 0);
}
.inner {
position: absolute;
bottom: 0;
z-index: 3;
width: 100%;
height: 78rpx;
}
}
.content {
.item {
padding: 32rpx 24rpx;
border-radius: 24rpx;
margin-bottom: 20rpx;
background: #FFFFFF;
&:first-child {
border-radius: 0 0 24rpx 24rpx;
}
}
.item-top {
font-size: 28rpx;
line-height: 40rpx;
color: #333333;
}
.item-center {
margin-top: 26rpx;
}
.goods-section {
flex: 1;
min-width: 0;
white-space: nowrap;
.image {
width: 136rpx;
height: 136rpx;
border-radius: 16rpx;
}
.name-wrap {
flex: 1;
min-width: 0;
padding-left: 20rpx;
}
.name {
font-size: 28rpx;
line-height: 40rpx;
color: #333333;
}
.attr {
margin-top: 12rpx;
font-size: 24rpx;
line-height: 34rpx;
color: #999999;
}
}
.scroll-view {
box-sizing: border-box;
.image {
margin-right: 16rpx;
}
}
.item-bottom {
padding: 18rpx 20rpx;
border-radius: 8rpx;
margin-top: 26rpx;
background: #F5F5F5;
font-size: 26rpx;
line-height: 36rpx;
color: #333333;
.info {
flex: 1;
color: #999999;
}
}
.scroll-view {
box-sizing: border-box;
.image {
margin-right: 16rpx;
}
}
.money-section {
width: 102rpx;
text-align: right;
.num {
margin-top: 8rpx;
font-size: 24rpx;
line-height: 34rpx;
color: #999999;
}
}
}
}
.order-index .header .icon-saoma {
font-size: 40rpx;
padding: 30rpx 20rpx 30rpx 80rpx;
}
.order-index .header .item,
.order-index .header .items {
font-size: 24upx;
color: #fff;
height: 120upx;
display: flex;
align-items: center;
}
.order-index .header .item .font,
.order-index .header .items .font {
display: inline-block;
margin-left: 16upx;
margin-right: 16upx;
font-size: 30upx;
}
.order-index .header .items image {
width: 64upx;
height: 64upx;
border-radius: 60upx;
border: 2upx solid #FFFFFF;
}
.order-index .wrapper {
width: 710rpx;
border-radius: 24rpx;
margin: 0 auto;
background: #FFFFFF;
}
.order-index .wrapper .title .iconfont {
color: #2291f8;
font-size: 40upx;
margin-right: 13upx;
vertical-align: middle;
}
.order-index .wrapper .title {
padding: 32rpx 24rpx;
font-weight: 500;
font-size: 30rpx;
line-height: 42rpx;
color: #333333;
.uni-list-cell-db .iconfont {
font-size: 24rpx;
color: #CCCCCC;
margin-left: 12rpx;
}
.tab {
border-radius: 24rpx;
background: #F5F5F5;
.box {
width: 96rpx;
height: 48rpx;
border-radius: 24rpx;
text-align: center;
font-weight: 400;
font-size: 24rpx;
line-height: 48rpx;
color: #999999;
}
.on {
background: #2A7EFB;
color: #FFFFFF;
}
}
}
.order-index .wrapper .list .item {
flex: 1;
padding: 30rpx 0 38rpx;
text-align: center;
font-size: 24rpx;
line-height: 34rpx;
color: #999999;
}
.order-index .wrapper .list .item .num {
margin-bottom: 10rpx;
font-family: SemiBold;
font-size: 36rpx;
line-height: 36rpx;
color: #333333;
}
.public-wrapper .title {
padding: 32rpx 24rpx 40rpx;
font-weight: 500;
font-size: 30rpx;
line-height: 42rpx;
color: #333333;
.uni-list-cell-db .iconfont {
font-size: 24upx;
color: #999;
margin-left: 14upx;
}
.tab {
width: 240upx;
height: 48upx;
background: #F5F5F5;
border-radius: 24upx;
display: flex;
justify-content: space-between;
font-weight: 400;
color: #999999;
font-size: 24upx;
.box {
width: 82upx;
height: 48upx;
border-radius: 24upx;
text-align: center;
line-height: 48upx;
}
.on {
background: #1890FF;
color: #FFFFFF;
}
}
}
.public-wrapper .title .iconfont {
color: #2291f8;
font-size: 40upx;
margin-right: 13upx;
vertical-align: middle;
}
.public-wrapper {
width: 710rpx;
border-radius: 24rpx;
margin: 20rpx auto 0;
background: #FFFFFF;
}
.public-wrapper .nav {
padding: 0 40rpx;
font-size: 24rpx;
line-height: 34rpx;
color: #999999;
}
.public-wrapper .data {
width: 45%;
text-align: left;
}
.public-wrapper .browse {
width: 25%;
}
.public-wrapper .turnover {
width: 30%;
text-align: right;
}
.public-wrapper .conter {
padding: 0 40rpx;
}
.public-wrapper .conter .item {
padding: 20rpx 0;
border-bottom: 1px solid #F1F1F1;
font-size: 24rpx;
line-height: 34rpx;
color: #333333;
}
.public-wrapper .conter .item .turnover {
color: #000000;
font-weight: 400;
}
.public-wrapper .unconter {
text-align: center;
color: #999;
padding: 25upx;
}
</style>

View File

@@ -0,0 +1,635 @@
<template>
<view>
<!-- #ifdef MP || APP -->
<NavBar titleText="订单详情" :iconColor="iconColor" :textColor="iconColor" :isScrolling="isScrolling" showBack></NavBar>
<!-- #endif -->
<view class="headerBg"></view>
<view class="order-details pos-order-details">
<view class="address">
<view v-if="orderInfo.store" class="box acea-row row-middle">
<view class="left">
<view class="text">{{orderInfo.store.name}}</view>
<view class="acea-row row-between-wrapper" @click="showMaoLocation(system_store.latitude,system_store.longitude,system_store.name,system_store.detailed_address)">
<span class="txt">{{ orderInfo.store.detailed_address }}</span>
<span class="iconfont icon-xiangyou"></span>
</view>
</view>
<view>
<view class="iconfont icon-tonghua marrt" @click="makePhone(system_store.phone)"></view>
</view>
</view>
<view class="box acea-row row-middle">
<view class="text-box">
<view class="text"><text class="iconfont icon-ic_receiving"></text>{{orderInfo.nickname}} {{orderInfo.user_phone}}</view>
<view class="acea-row row-between-wrapper">
地址:{{orderInfo.user_address}}
</view>
</view>
<view class="btn" @click.stop="makePhone(orderInfo.user_phone)">
<text class="iconfont icon-ic_phone"></text>
</view>
<view class="btn" @click.stop="showMaoLocation(orderInfo.latitude,orderInfo.longitude,orderInfo.nickname,orderInfo.user_address)">
<text class="iconfont icon-ic_location"></text>
</view>
</view>
<view class="line">
<image src="/static/images/line.jpg" />
</view>
</view>
<view class="goods-section">
<view class="">订单号:{{orderInfo.order_id}}</view>
<view class="goods acea-row" v-for="(item, index) in orderInfo.cartInfo" :key="index">
<view class="picTxt acea-row">
<image :src="item.productInfo.image" class="pictrue"></image>
<view class="text">
<view class="info line1">
{{ item.productInfo.store_name }}
</view>
<view class="attr line1">{{ item.productInfo.attrInfo.suk }}</view>
<view class="label">7天无理由退换货·放心购</view>
</view>
</view>
<view class="money">
<baseMoney :money="item.productInfo.attrInfo.price" symbolSize="20" integerSize="32" decimalSize="20"></baseMoney>
<view class="num">共{{ item.cart_num }}件</view>
</view>
</view>
<view class="giveGoods">
<view class="item acea-row row-between-wrapper" v-for="(item,index) in giveCartInfo" :key="index">
<view class="picTxt acea-row row-middle">
<view class="pictrue">
<image :src="item.productInfo.attrInfo.image" v-if="item.productInfo.attrInfo"></image>
<image :src="item.productInfo.image" v-else></image>
</view>
<view class="texts">
<view class="name line1">[赠品]{{item.productInfo.store_name}}</view>
<view class="limit line1" v-if="item.productInfo.attrInfo">{{item.productInfo.attrInfo.suk}}</view>
</view>
</view>
<view class="num">x{{item.cart_num}}</view>
</view>
<view class="item acea-row row-between-wrapper" v-for="(item,index) in giveData.give_coupon" :key="index" v-if="giveData.give_coupon.length">
<view class="picTxt acea-row row-middle">
<view class="pictrue acea-row row-center-wrapper">
<text class="iconfont icon-pc-youhuiquan"></text>
</view>
<view class="texts">
<view class="line1">[赠品]{{item.coupon_title}}</view>
</view>
</view>
</view>
<view class="item acea-row row-between-wrapper" v-if="giveData.give_integral>0">
<view class="picTxt acea-row row-middle">
<view class="pictrue acea-row row-center-wrapper">
<text class="iconfont icon-pc-jifen"></text>
</view>
<view class="texts">
<view class="line1">[赠品]{{giveData.give_integral}}积分</view>
</view>
</view>
</view>
</view>
</view>
<view class="detail-section">
<view class="item acea-row row-between">
<view>订单编号</view>
<view class="conter acea-row row-middle row-right">
{{ orderInfo.order_id }}
<span class="copy copy-data" @click="copyNum(orderInfo.order_id)">复制</span>
</view>
</view>
<view class="item acea-row row-between">
<view>支付方式</view>
<view class="conter">{{ payType }}</view>
</view>
<view class="item acea-row row-between">
<view>支付时间</view>
<view class="conter">{{ orderInfo._pay_time }}</view>
</view>
<view class="item acea-row row-between">
<view>下单时间</view>
<view class="conter">{{ orderInfo._add_time }}</view>
</view>
<view class="item acea-row row-between" v-if="orderInfo._status">
<view>配送方式</view>
<view class="conter">{{ orderInfo._status._deliveryType }}</view>
</view>
<view class="item acea-row row-between">
<view>买家留言</view>
<view class="conter">{{ orderInfo.mark }}</view>
</view>
</view>
<customForm :customForm="orderInfo.custom_form"></customForm>
<view class="wrapper topnone">
<view class="item acea-row row-between">
<view>商品总价:</view>
<view class="conter">¥{{ (parseFloat(orderInfo.total_price)+parseFloat(orderInfo.vip_true_price)).toFixed(2) }}</view>
</view>
<view class="item acea-row row-between" v-if="orderInfo.coupon_price>0">
<view>优惠券抵扣:</view>
<view class="conter">-¥{{ orderInfo.coupon_price }}</view>
</view>
<view v-if="orderInfo.pay_postage>0" class="item acea-row row-between">
<view>运费:</view>
<view class="conter">¥{{ orderInfo.pay_postage }}</view>
</view>
<view class="item acea-row row-between" v-if="orderInfo.deduction_price>0">
<view>积分抵扣金额:</view>
<view class="conter">-¥{{ orderInfo.deduction_price }}</view>
</view>
<view class="item acea-row row-between" v-if="orderInfo.vip_true_price>0">
<view>会员商品优惠:</view>
<view class="conter">-¥{{ orderInfo.vip_true_price }}</view>
</view>
<view class='item acea-row row-between' v-for="(item,index) in orderInfo.promotions_detail" :key="index" v-if="parseFloat(item.promotions_price)">
<view>{{item.title}}:</view>
<view class='conter'>-¥{{parseFloat(item.promotions_price).toFixed(2)}}</view>
</view>
<view class="actualPay acea-row row-right">
实付款:
<!-- <span class="money">¥{{ orderInfo.pay_price }}</span> -->
<baseMoney :money="orderInfo.pay_price" symbolSize="24" integerSize="40" decimalSize="24" color="#FF7E00"></baseMoney>
</view>
</view>
<view class="height-add"></view>
</view>
</view>
</template>
<script>
import customForm from "@/components/customForm";
// #ifdef MP || APP
import NavBar from "@/components/NavBar.vue";
// #endif
import {OrderDetail} from "@/api/admin";
import {
isMoney
} from '@/utils/validate.js'
export default {
name: "orderDetail",
components: {
customForm,
// #ifdef MP || APP
NavBar,
// #endif
},
props: {},
data: function() {
return {
giveData: {
give_integral: 0,
give_coupon: []
},
giveCartInfo: [],
order: false,
change: false,
order_id: "",
orderInfo: '',
status: "",
title: "",
payType: "",
types: "",
clickNum: 1,
goname: '',
system_store: '',
sum: 0,
// #ifdef MP || APP
iconColor: '#FFFFFF',
isScrolling: false,
// #endif
};
},
watch: {
"$route.params.oid": function(newVal) {
let that = this;
if (newVal != undefined) {
that.order_id = newVal;
that.getIndex();
}
}
},
onLoad: function(option) {
let self = this
this.order_id = option.id;
this.goname = option.goname
this.getIndex();
},
onPageScroll(e) {
// #ifdef MP
if (e.scrollTop > 50) {
this.isScrolling = true;
this.iconColor = '#333333';
} else if (e.scrollTop < 50) {
this.isScrolling = false;
this.iconColor = '#FFFFFF';
}
// #endif
},
methods: {
more: function() {
this.order = !this.order;
},
modify: function(status) {
this.change = true;
this.status = status;
},
changeclose: function(msg) {
this.change = msg;
},
getIndex: function() {
let that = this;
OrderDetail(that.order_id).then(
res => {
that.sum = (parseFloat(res.data.total_price) + parseFloat(res.data.vip_true_price)).toFixed(2)
that.types = res.data._status._type;
that.title = res.data._status._title;
that.payType = res.data._status._payType;
this.system_store = res.data.store
that.giveData.give_coupon = res.data.give_coupon;
that.giveData.give_integral = res.data.give_integral;
let cartObj = [],
giftObj = [];
res.data.cartInfo.forEach((item, index) => {
if (item.is_gift == 1) {
giftObj.push(item)
} else {
cartObj.push(item)
}
});
res.data.cartInfo = cartObj;
that.$set(that, 'giveCartInfo', giftObj);
let arr = [];
for (let i = 0; i < res.data.user_address.length; i++) {
if (res.data.user_address[i] != ' ') {
arr.push(res.data.user_address[i]);
}
}
res.data.user_address = arr.join('');
that.orderInfo = res.data;
},
err => {
// that.$util.Tips({
// title: err
// }, {
// tab: 3,
// url: 1
// });
}
);
},
//打开地图
showMaoLocation: function(latitude, longitude, name, detailed_address) {
if (!latitude || !longitude) return this.$util.Tips({
title: '缺少经纬度信息无法查看地图!'
});
uni.openLocation({
latitude: parseFloat(latitude),
longitude: parseFloat(longitude),
scale: 8,
name: name,
address: detailed_address,
success: function() {
},
});
},
//拨打电话
makePhone: function(phone) {
uni.makePhoneCall({
phoneNumber: phone
})
},
copyNum(id) {
uni.setClipboardData({
data: id,
});
},
// #ifdef H5
webCopy(item, index) {
let items = item
let indexs = index
let self = this
if (self.clickNum == 1) {
self.clickNum += 1
self.webCopy(items, indexs)
}
}
// #endif
}
};
</script>
<style lang="scss" scoped>
.headerBg {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 506rpx;
background: linear-gradient(360deg, #F5F5F5 0%, rgba(245, 245, 245, 0) 100%),
linear-gradient(-90deg, $gradient-primary-admin 0%, $primary-admin 100%);
background-position: left bottom, left top;
background-repeat: no-repeat;
background-size: 100% 120rpx, 100% 100%;
}
.order-details {
position: relative;
padding: 32rpx 20rpx;
.address {
position: relative;
padding: 32rpx 24rpx 28rpx 32rpx;
border-radius: 24rpx;
background: #FFFFFF;
overflow: hidden;
.text-box {
flex: 1;
font-size: 24rpx;
line-height: 34rpx;
color: #999999;
}
.text {
margin-bottom: 12rpx;
font-weight: 500;
font-size: 30rpx;
line-height: 42rpx;
color: #333333;
.iconfont {
font-size: 32rpx;
margin-right: 20rpx;
}
}
.btn {
width: 56rpx;
height: 56rpx;
border-radius: 50%;
margin-left: 24rpx;
background: rgba(42, 126, 251, 0.1);
text-align: center;
line-height: 56rpx;
.iconfont {
font-size: 28rpx;
color: #2A7EFB;
}
}
.line {
position: absolute;
bottom: 0;
left: 0;
width: 100%;
}
}
.goods-section {
padding: 32rpx 24rpx;
border-radius: 24rpx;
margin-top: 20rpx;
background: #FFFFFF;
.goods {
margin-top: 32rpx;
&:first-child {
margin-top: 0;
}
}
.picTxt {
flex: 1;
min-width: 0;
}
.pictrue {
width: 136rpx;
height: 136rpx;
border-radius: 16rpx;
}
.text {
flex: 1;
min-width: 0;
padding: 0 20rpx;
}
.info {
font-size: 28rpx;
line-height: 40rpx;
color: #333333;
}
.attr {
margin-top: 8rpx;
font-size: 24rpx;
line-height: 34rpx;
color: #999999;
}
.label {
display: inline-flex;
align-items: center;
height: 26rpx;
padding: 0 6rpx;
border: 1rpx solid #FF7E00;
border-radius: 4rpx;
margin-top: 12rpx;
font-size: 18rpx;
line-height: 26rpx;
color: #FF7E00;
}
.money {
text-align: right;
}
.num {
margin-top: 10rpx;
font-size: 24rpx;
line-height: 34rpx;
color: #999999;
}
}
.detail-section {
padding: 32rpx 24rpx;
border-radius: 24rpx;
margin-top: 20rpx;
background: #FFFFFF;
.item {
margin-top: 24rpx;
font-size: 28rpx;
line-height: 40rpx;
color: #333333;
&:first-child {
margin-top: 0;
}
}
}
}
.mt28 {
margin-top: 28rpx;
}
.height-add {
height: 120upx;
}
.giveGoods {
.item {
padding: 14rpx 0;
border-top: 1px solid #eee;
.picTxt {
.pictrue {
width: 76rpx;
height: 76rpx;
border-radius: 6rpx;
background-color: #F5F5F5;
color: $primary-admin;
.iconfont {
font-size: 34rpx;
}
image {
width: 100%;
height: 100%;
border-radius: 6rpx;
}
margin-right: 16rpx;
}
.texts {
width: 360rpx;
color: #999999;
font-size: 20rpx;
.name {
color: #333;
}
.limit {
font-size: 20rpx;
margin-top: 4rpx;
}
}
}
.num {
color: #999999;
font-size: 20rpx;
}
}
}
.order-details .line {
width: 100%;
height: 3upx;
}
.order-details .line image {
width: 100%;
height: 100%;
display: block;
}
.order-details .wrapper {
background: #FFFFFF;
}
.order-details .topnone {
padding: 32rpx 24rpx;
border-radius: 24rpx;
margin-top: 20rpx;
}
.order-details .wrapper .title {
height: 100upx;
display: flex;
justify-content: space-between;
align-items: center;
border-bottom: 1upx solid #EEEEEE;
margin-bottom: 34upx;
}
.order-details .wrapper .title .font {
font-size: 32upx;
font-weight: 600;
color: #282828;
}
.order-details .wrapper .title .mapbtn {
width: 176upx;
height: 56upx;
border: 1upx solid #1890FF;
border-radius: 28upx;
text-align: center;
line-height: 50upx;
color: #1890FF;
font-size: 26upx;
}
.order-details .wrapper .item {
font-size: 28upx;
color: #282828;
}
.order-details .wrapper .item~.item {
margin-top: 26rpx;
}
.order-details .wrapper .item .conter {
color: #868686;
/* width: 500upx; */
text-align: right;
}
.order-details .wrapper .item .conter .copy {
font-size: 20rpx;
color: #333;
border-radius: 3rpx;
border: 1px solid #666;
padding: 0rpx 15rpx;
margin-left: 10rpx;
height: 40rpx;
line-height: 38upx;
}
.order-details .wrapper .actualPay {
// border-top: 1upx solid #eee;
margin-top: 26rpx;
// padding-top: 30upx;
}
.order-details .wrapper .actualPay .money {
font-weight: bold;
font-size: 30upx;
color: #FF7E00;
}
.copy-data {
width: 68rpx;
height: 36rpx;
border-radius: 18rpx;
margin-left: 8rpx;
background: #F5F5F5;
text-align: center;
font-size: 22rpx;
line-height: 36rpx;
color: #333333;
}
</style>

View File

@@ -0,0 +1,756 @@
<template>
<view>
<view class='shoppingCart copy-data'>
<view class='nav acea-row row-between-wrapper'>
<view>订单号:<text class='num'>{{ list.order_id }}</text></view>
<navigator class="btn" :url="'/pages/admin/writeRecordList/index?id='+id" hover-class="none">
核销记录<text class="iconfont icon-ic_rightarrow"></text>
</navigator>
</view>
<view class="content">
<view class='list'>
<view>
<block v-for="(item,index) in list.cart_info" :key="index">
<view class='item acea-row row-between-wrapper' :style="{ opacity: item.is_writeoff ? 0.5: 1 }">
<div class="xuan" @click="dan(item.cart_id,index)">
<view :class="(item.checked || item.is_writeoff)?'iconfont icon-a-ic_CompleteSelect':'iconfont icon-ic_unselect'"></view>
</div>
<view class='picTxt acea-row row-between-wrapper'>
<view class='pictrue'>
<image :src="item.cart_info.productInfo.attrInfo?item.cart_info.productInfo.attrInfo.image:item.cart_info.productInfo.image" mode=""></image>
</view>
<view class='text'>
<view class="title">
<view class='line1' :class="item.attrStatus?'':'reColor'">
{{ item.cart_info.productInfo.store_name }}
</view>
<view v-if="item.is_writeoff == 1" class="txt">已核销</view>
<view v-if="item.is_writeoff == 0 && lists.cart_info[index].surplus_num == lists.cart_info[index].cart_num" class="txt bluecol">未核销</view>
<view v-if="item.is_writeoff == 0 && lists.cart_info[index].surplus_num != lists.cart_info[index].cart_num" class="txt orangcol">
已核销{{parseInt(lists.cart_info[index].cart_num-lists.cart_info[index].surplus_num)}}件</view>
</view>
<view class='infor line1'>
属性:{{ item.cart_info.productInfo.attrInfo.suk }}</view>
<view class='money he row-middle'>
<view>¥{{ item.cart_info.productInfo.attrInfo?item.cart_info.productInfo.attrInfo.price:item.cart_info.productInfo.price }}</view>
<view v-if="item.is_writeoff == 1" class="txt">
<view class='carnum acea-row row-center-wrapper'>
<view class="reduce">
<text class="iconfont icon-ic_Reduce"></text>
</view>
<view class='nums'>0</view>
<view class="plus">
<text class="iconfont icon-ic_increase"></text>
</view>
</view>
</view>
<view v-else class="txt">
<view class='carnum acea-row row-center-wrapper'>
<view v-if="item.surplus_num_input == 1" class="reduce bggary">
<text class="iconfont icon-ic_Reduce"></text>
</view>
<view v-else class="reduce" @click.stop='subCart(item,index)'>
<text class="iconfont icon-ic_Reduce"></text>
</view>
<!-- <view class='nums'>{{parseInt(item.surplus_num)}}</view> -->
<input v-model="item.surplus_num_input" class='nums' type="number" @input="numInput(index, $event)" />
<view v-if="item.surplus_num_input == item.surplus_num" class="plus bggary">
<text class="iconfont icon-ic_increase"></text>
</view>
<view v-else class="plus" @click.stop='addCart(item,index)'>
<text class="iconfont icon-ic_increase"></text>
</view>
</view>
</view>
</view>
</view>
</view>
</view>
</block>
</view>
</view>
</view>
<view class='footer acea-row row-between-wrapper'>
<view>
<view style="display: flex;" @change="checkboxAllChange">
<div class="xuan" @click="checkAll" v-model="checked">
<view class="iconfont" :class="checked?'icon-a-ic_CompleteSelect':'icon-ic_unselect'"></view>
</div>
<text class='checkAll'>全选</text>
</view>
</view>
<view>
<button class='money' type="primary" @click="verification">{{checked?'一键':'确认'}}核销({{numChecked}})</button>
</view>
</view>
</view>
<view v-if="box">
<view class="box">
<view class="small_box">
<!-- <image src="../../../static/decorate.png" mode=""></image> -->
<view class="content">
<view class="font">核销成功</view>
<view v-if="list.total_num == parseInt(list.writeoff_count)+writeOffNum" class="small_font">当前订单已完成核销</view>
<view v-else class="small_font">该订单仍有其他待核销商品</view>
</view>
<view class="acea-row btn-box">
<view v-if="lets == 1 && list.total_num == parseInt(list.writeoff_count)+writeOffNum" class="btn primary" @click="ok(1)">知道了</view>
<navigator v-if="lets > 1 && list.total_num != parseInt(list.writeoff_count)+writeOffNum" :url='"/pages/admin/distribution/scanning/index?code="+attr.code' hover-class='none'
open-type="redirect" class="btn btn_no">返回列表</navigator>
<navigator v-if="(lets > 1 && list.total_num == parseInt(list.writeoff_count)+writeOffNum)||(lets==1&&list.total_num != parseInt(list.writeoff_count)+writeOffNum)"
url="/pages/admin/distribution/index" hover-class='none' open-type="redirect" class="btn btn_no">返回首页</navigator>
<view v-if="list.total_num != parseInt(list.writeoff_count)+writeOffNum" class="btn on" @click="ok(0)">继续核销</view>
<navigator v-if="lets > 1 && list.total_num == parseInt(list.writeoff_count)+writeOffNum" :url='"/pages/admin/distribution/scanning/index?code="+attr.code' open-type="redirect"
hover-class='none' class="btn">核销其他订单</navigator>
</view>
</view>
</view>
</view>
<writeOffSwitching ref="writeOff" :attr="attr" :isShow='1' :iSplus='1' :iScart='1' @dataId="onDataId" @myevent="onMyEvent" id='product-window'></writeOffSwitching>
</view>
</template>
<script>
import writeOffSwitching from '../../../components/writeOffSwitching/index.vue';
import {
orderCartInfo,
orderWriteoff
} from '@/api/admin'
import {
nextTick
} from 'process';
export default {
components: {
writeOffSwitching
},
props: {
idss: {
type: Number,
default: 0
},
code: {
type: String,
default: ''
},
let: {
type: Number,
default: 0
},
},
data() {
return {
nums: [],
newList: [],
reduce_show: -1,
plus_show: -1,
ids: [], //选定需要核销的id
lets: 0, //判断订单的数量
listlet: 0, //判断订单商品的数量
attr: { //切换组件传值
cartAttr: false,
id: [],
code: '',
type: 0
},
id: 0, //订单ID
list: [],
lists: [],
lengt: 0,
box: false,
checked: false,
checkModel: [],
isAllSelect: false,
data: [{
id: '1',
value: 'aaa'
}, {
id: '2',
value: 'bbb'
}, {
id: '3',
value: 'ccc'
}],
writeOffNum: 0, //每次核销商品数量
auth: 1,
numChecked: 0,
};
},
watch: {
checkModel(val) {
if (this.lengt == this.checkModel.length) {
this.checked = true;
} else {
this.checked = false;
}
}
},
onLoad: function(options) {
this.id = options.id
this.attr.code = options.code
this.lets = options.let
this.auth = options.auth
this.getList(this.id)
},
onShow: function() {},
methods: {
numInput(index, event) {
let value = event.detail.value;
// if (parseInt(event.detail.value) > (this.list.cart_info[index].surplus_num + this.nums[index].num)) {
// this.$nextTick(() => {
// this.list.cart_info[index].surplus_num_input = this.list.cart_info[index].surplus_num + this.nums[index].num
// })
// }
if (value) {
value = Number(value);
this.$nextTick(() => {
if (value > this.list.cart_info[index].surplus_num) {
this.list.cart_info[index].surplus_num_input = this.list.cart_info[index].surplus_num;
} else if (value < 1) {
this.list.cart_info[index].surplus_num_input = 1;
}
let numChecked = 0;
for (let i = 0; i < this.list.cart_info.length; i++) {
if (!this.list.cart_info[i].is_writeoff) {
if (this.list.cart_info[i].checked) {
numChecked = numChecked + Number(this.list.cart_info[i].surplus_num_input)
}
}
}
this.numChecked = numChecked;
});
}
},
//处理每一条数据的最大值
num() {
for (let index = 0; index < this.lists.cart_info.length; index++) {
this.nums.push({
num: 0
});
}
},
subCart(item, index) {
if (item.surplus_num_input == 1) {
this.reduce_show = index;
} else {
this.nums[index].num--
item.surplus_num_input--
}
let numChecked = 0;
for (let i = 0; i < this.list.cart_info.length; i++) {
if (!this.list.cart_info[i].is_writeoff) {
if (this.list.cart_info[i].checked) {
numChecked = numChecked + this.list.cart_info[i].surplus_num_input
}
}
}
this.numChecked = numChecked;
},
addCart(item, index) {
if (item.surplus_num_input == item.surplus_num) {
this.plus_show = index;
} else {
item.surplus_num_input++
this.nums[index].num++
}
let numChecked = 0;
for (let i = 0; i < this.list.cart_info.length; i++) {
if (!this.list.cart_info[i].is_writeoff) {
if (this.list.cart_info[i].checked) {
numChecked = numChecked + this.list.cart_info[i].surplus_num_input
}
}
}
this.numChecked = numChecked;
},
checkAll() {
var items = this.list.cart_info,
data = [];
if (this.checked) {
this.checkModel = [];
for (var i = 0, lenI = this.list.cart_info.length; i < lenI; ++i) {
const item = items[i]
this.$set(item, 'checked', false)
}
} else {
this.checkModel = [];
for (var i = 0, lenI = this.list.cart_info.length; i < lenI; ++i) {
const item = items[i]
this.$set(item, 'checked', true)
if (item.is_writeoff == 1) {
this.checkModel = this.checkModel.filter(item => item != item.cart_id)
} else {
this.checkModel.push(item.cart_id)
}
}
this.lengt = this.checkModel.length
}
let numChecked = 0;
for (let i = 0; i < this.list.cart_info.length; i++) {
if (!this.list.cart_info[i].is_writeoff) {
if (this.list.cart_info[i].checked) {
numChecked = numChecked + Number(this.list.cart_info[i].surplus_num_input)
}
}
}
this.numChecked = numChecked;
},
dan(id, index) {
if (this.list.cart_info[index].is_writeoff) {
return
}
if (this.checkModel.indexOf(id) == -1) {
this.$set(this.list.cart_info[index], 'checked', true)
this.checkModel.push(id)
} else {
this.$set(this.list.cart_info[index], 'checked', false)
this.checkModel = this.checkModel.filter(item => item != id)
}
// let checked = true;
// for (let i = 0; i < this.cart_info.length; i++) {
// if (!this.cart_info[i].is_writeoff) {
// if (!this.cart_info[i].checked) {
// checked = false;
// }
// }
// }
// this.checked = checked;
let numChecked = 0;
for (let i = 0; i < this.list.cart_info.length; i++) {
if (!this.list.cart_info[i].is_writeoff) {
if (this.list.cart_info[i].checked) {
numChecked = numChecked + Number(this.list.cart_info[i].surplus_num_input)
}
}
}
this.numChecked = numChecked;
},
getList: function(id) {
orderCartInfo({
oid: id,
auth: this.auth,
}).then(res => {
for (let i = 0; i < res.data.cart_info.length; i++) {
res.data.cart_info[i].surplus_num_input = res.data.cart_info[i].surplus_num;
}
this.list = res.data
this.lists = JSON.parse(JSON.stringify(res.data))
this.listlet = res.data.cart_info.length
this.$set(this.attr, 'id', this.list.id);
this.checkAll()
this.num()
})
},
onDataId: function(id) {
this.nums.forEach((item) => {
item.num = 0
})
this.id = id;
this.getList(id)
},
switchs() {
this.attr.cartAttr = true;
this.$refs.writeOff.getList(2)
},
onMyEvent() {
this.attr.cartAttr = false;
},
verification() {
let that = this
let obj = {};
// 将数组转化为对象
for (let key in this.checkModel) {
obj[key] = this.checkModel[key];
};
let newObj = Object.keys(obj).map(val => ({
cart_id: obj[val],
}));
//处理列表内对应的核销数的数值
for (var i = 0; i < newObj.length; i++) {
for (var j = 0; j < this.list.cart_info.length; j++) {
if (newObj[i].cart_id == this.list.cart_info[j].cart_id) {
newObj[i].cart_num = this.list.cart_info[j].surplus_num_input;
}
}
}
this.newList = newObj
if (that.checkModel.length == 0) {
that.$util.Tips({
title: '请选择商品'
});
} else {
uni.showLoading({
title: '加载中',
});
let num = 0;
newObj.forEach((item) => {
num = num + parseInt(item.cart_num)
})
this.writeOffNum = num;
setTimeout(function() {
orderWriteoff({
auth: that.auth,
oid: that.id,
cart_ids: that.newList
}).then(res => {
uni.hideLoading();
that.box = true
}).catch(err => {
that.$util.Tips({
title: err
});
uni.hideLoading();
})
}, 1000);
}
},
// 所有订单核销完成
ok(type) {
this.box = false
this.nums.forEach((item) => {
item.num = 0
})
this.getList(this.id)
if (type) {
uni.redirectTo({
url: '/pages/admin/orderDetail/index?id='+this.list.order_id+'&types=3'
})
}
}
}
}
</script>
<style scoped lang="scss">
.shoppingCart {
padding: 24rpx 20rpx;
}
.shoppingCart .list .item .xuan .iconfont {
font-size: 40rpx;
color: #CCCCCC;
}
.he {
display: flex;
justify-content: space-between;
.txt {
font-size: 22upx;
}
}
.box {
position: fixed;
top: 0;
bottom: 0;
width: 100%;
height: 100%;
z-index: 10;
background-color: rgba(0, 0, 0, 0.3);
.small_box {
position: fixed;
top: 50%;
right: 75rpx;
left: 75rpx;
padding: 40rpx;
border-radius: 32rpx;
background: #FFFFFF;
transform: translateY(-50%);
image {
width: 100%;
height: 228upx;
}
.content {
// height: 200upx;
text-align: center;
.font {
font-weight: 500;
font-size: 32rpx;
line-height: 52rpx;
color: #333333;
}
.small_font {
margin-top: 24rpx;
font-size: 30rpx;
line-height: 42rpx;
color: #666666;
}
}
.btn-box {
margin-top: 40rpx;
}
.btn {
flex: 1;
height: 72rpx;
border: 1rpx solid $primary-admin;
border-radius: 36rpx;
margin-left: 32rpx;
transform: rotateZ(360deg);
text-align: center;
font-weight: 500;
font-size: 26rpx;
line-height: 70rpx;
color: $primary-admin;
&:first-child {
margin-left: 0;
}
&.on {
background: $primary-admin;
color: #FFFFFF;
}
&.primary {
background: $primary-admin;
color: #FFFFFF;
}
}
.btn_no {
// flex: 1;
// color: #999999;
// margin-top: 28upx;
// text-align: center;
// font-size: 30upx;
}
}
}
.shoppingCart .content {
padding: 32rpx 24rpx;
margin-top: 20rpx;
border-radius: 24rpx;
background: #FFFFFF;
.item {
margin-top: 48rpx;
&:first-child {
margin-top: 0;
}
}
}
.shoppingCart .list .item .xuan .icon-a-ic_CompleteSelect {
color: $primary-admin;
}
.shoppingCart .list .item .picTxt {
position: relative;
flex: 1;
min-width: 0;
padding-left: 16rpx;
}
.shoppingCart .list .item .picTxt .pictrue {
width: 136rpx;
height: 136rpx;
}
.shoppingCart .list .item .picTxt .pictrue image {
width: 100%;
height: 100%;
border-radius: 16rpx;
}
.shoppingCart .list .item .picTxt .text {
flex: 1;
min-width: 0;
padding-left: 20rpx;
font-size: 28upx;
color: #282828;
}
.shoppingCart .list .item .picTxt .text .reColor {
color: #333333;
width: 60%;
}
.shoppingCart .list .item .picTxt .text .title {
display: flex;
justify-content: space-between;
font-size: 28rpx;
line-height: 40rpx;
color: #333333;
.bluecol {
color: $primary-admin;
}
.orangcol {
color: #FF7E00;
}
.graycol {
color: #CCCCCC;
}
}
.shoppingCart .list .item .picTxt .text .title .top {
width: 70%;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
font-size: 28upx;
font-weight: 400;
}
.shoppingCart .list .item .picTxt .text .infor {
font-size: 22rpx;
line-height: 30rpx;
color: #999999;
margin-top: 12rpx;
}
.shoppingCart .list .item .picTxt .text .money {
font-size: 36rpx;
line-height: 36rpx;
color: #333333;
margin-top: 18rpx;
font-family: Regular;
}
.shoppingCart .list .item .picTxt .carnum {
height: 36rpx;
// position: absolute;
// bottom: 7upx;
// right: 0;
}
.shoppingCart .list .item .picTxt .carnum view {
// border: 1upx solid #a4a4a4;
width: 32rpx;
text-align: center;
height: 100%;
line-height: 36rpx;
font-size: 24rpx;
color: #333333;
}
.shoppingCart .list .item .picTxt .carnum .reduce {
border-right: 0;
border-radius: 30upx 0 0 30upx;
padding-right: 8rpx;
}
.shoppingCart .list .item .picTxt .carnum .reduce.on {
border-color: #e3e3e3;
color: #dedede;
}
.shoppingCart .list .item .picTxt .carnum .plus {
border-left: 0;
border-radius: 0 30upx 30upx 0;
padding-left: 8rpx;
}
.shoppingCart .list .item .picTxt .carnum .iconfont {
font-size: 24rpx;
}
.shoppingCart .list .item .picTxt .carnum .bggary .iconfont {
color: #CCCCCC;
}
.shoppingCart .list .item .picTxt .carnum .num {
color: #282828;
}
.shoppingCart .list .item .picTxt .carnum .num0 {
color: #a4a4a4;
}
.shoppingCart .list .item .picTxt .carnum .nums {
width: 72rpx;
border-radius: 4rpx;
background: #F5F5F5;
text-align: center;
font-family: SemiBold;
font-size: 24rpx;
color: #333333;
}
.shoppingCart .footer {
// z-index: 999;
width: 100%;
background: #FFFFFF;
position: fixed;
padding: 0 20rpx 0 32rpx;
box-sizing: border-box;
bottom: 0;
left: 0;
height: 96rpx;
height: calc(96rpx + constant(safe-area-inset-bottom)); ///兼容 IOS<11.2/
height: calc(96rpx + env(safe-area-inset-bottom)); ///兼容 IOS>11.2/
padding-bottom: constant(safe-area-inset-bottom); ///兼容 IOS<11.2/
padding-bottom: env(safe-area-inset-bottom); ///兼容 IOS>11.2/
}
.shoppingCart .footer.on {
// #ifndef H5
bottom: 0upx;
// #endif
}
.shoppingCart .footer .iconfont {
font-size: 40rpx;
color: #CCCCCC;
}
.shoppingCart .footer .icon-a-ic_CompleteSelect {
color: $primary-admin;
}
.shoppingCart .footer .checkAll {
font-size: 28upx;
color: #282828;
margin-left: 16upx;
}
.shoppingCart .footer .money {
font-size: 24rpx;
height: 64rpx;
padding: 0 32rpx;
background: $primary-admin;
border-radius: 32rpx;
font-weight: 400;
color: #FFFFFF;
line-height: 64rpx;
}
.shoppingCart .footer .placeOrder {
color: #fff;
font-size: 30upx;
width: 226upx;
height: 70upx;
border-radius: 50upx;
text-align: center;
line-height: 70upx;
margin-left: 22upx;
}
.shoppingCart .footer .button .bnt {
font-size: 28upx;
color: #999;
border-radius: 50upx;
border: 1px solid #999;
width: 160upx;
height: 60upx;
text-align: center;
line-height: 60upx;
}
.shoppingCart .footer .button form~form {
margin-left: 17upx;
}
</style>

View File

@@ -0,0 +1,451 @@
<template>
<view>
<view class="scan">
<view class="header">请选择要核销的订单</view>
<view class="box">
<view class="content" v-for="(item,index) in list" :key="index" @click="jump(item.id)">
<view class="acea-row row-between">
<view class="orange" v-if="(item._status == 4 || item._status == 12) && item.status == 5">部分核销</view>
<view class="attributes blue" v-if="item._status == 4 && item.status == 1">未核销</view>
<view class="attributes blue" v-if="item._status == 11">未核销</view>
<view class="attributes blue" v-if="item._status == 5">已核销</view>
<!-- <navigator class="btn" url="/pages/admin/writeRecordList/index" hover-class="none">核销记录<text class="iconfont icon-ic_rightarrow"></text></navigator> -->
<view class="btn" @click.stop="goRecord(item.id)">核销记录<text class="iconfont icon-ic_rightarrow"></text></view>
</view>
<view class="content_box acea-row">
<image :src="item.image" mode=""></image>
<view class="content_box_title acea-row row-column row-between">
<p class="textbox">订单号:{{ item.order_id }}</p>
<p class="attribute">下单时间:{{ item.add_time }}</p>
<view class="txt">
<p class="attribute">订单实付:¥{{ item.pay_price }}</p>
</view>
</view>
</view>
</view>
</view>
</view>
<view class="mask" v-if="popupShow" @click="closePopup"></view>
<view class="popup acea-row row-column on" v-if="popupShow">
<view class="popup-hd">
商品核销
<view class="btn" @click="closePopup">
<text class="iconfont icon-ic_close"></text>
</view>
</view>
<writeOffList class="popup-bd" :list="orderInfo" :auth="auth" :oid="id" @success="writeSuccess"></writeOffList>
</view>
<view v-if="box">
<view class="boxs">
<view class="small_box">
<view class="content">
<view class="font">核销成功</view>
<view v-if="isAll" class="small_font">当前订单已完成核销</view>
<view v-else class="small_font">该订单仍有其他待核销商品</view>
</view>
<view class="acea-row btn-box">
<view v-if="!isAll" class="btn" @click="ok(1)">返回列表</view>
<!-- <navigator v-if="!isAll" :url='"/pages/admin/distribution/scanning/index?code="+attr.code' hover-class='none' open-type="redirect" class="btn btn_no">返回列表</navigator> -->
<navigator v-if="isAll" url="/pages/admin/work/index" hover-class='none' class="btn btn_no">返回工作台</navigator>
<view v-if="!isAll" class="btn on" @click="ok(2)">继续核销</view>
<view v-if="isAll" class="btn on" @click="ok(3)">核销其他订单</view>
<!-- <navigator v-if="isAll" :url='"/pages/admin/distribution/scanning/index?code="' open-type="redirect" hover-class='none' class="btn on">核销其他订单</navigator> -->
</view>
</view>
</view>
</view>
</view>
</template>
<script>
import {
orderWriteoffInfo,
orderVerific,
orderCartInfo,
} from '@/api/admin'
import {
HTTP_REQUEST_URL
} from '@/config/app';
import {
nextTick
} from "vue";
import writeOffList from '../../components/writeOffList/index.vue';
export default {
name: 'scanning',
components: {
writeOffList,
},
data() {
return {
auth: 1,
verify_code: '',
list: [],
imgHost: HTTP_REQUEST_URL,
popupShow: false,
orderInfo: {},
id: 0,
box: false,
isAll: 1,
}
},
onLoad: function(option) {
this.auth = option.auth
this.verify_code = option.code
},
onShow(options) {
this.getList()
},
methods: {
goRecord(id) {
uni.navigateTo({
url: '/pages/admin/writeRecordList/index?id=' + id
})
},
getList: function() {
orderVerific(this.verify_code, this.auth)
.then(res => {
// self.orderInfo = res.data
this.list = res.data.data;
// self.iShidden = true
})
.catch(res => {
// self.verify_code = ''
return this.$util.Tips({
title: res
});
});
},
jump: function(id) {
this.id = id;
this.getCartList(id)
},
getCartList: function(id) {
orderCartInfo({
oid: id,
auth: this.auth,
}).then(res => {
if (res.data.product_type == 4) {
uni.navigateTo({
url: '/pages/admin/writeOffCard/index?id=' + id
})
} else {
let orderInfo = res.data;
for (let i = 0; i < orderInfo.cart_info.length; i++) {
orderInfo.cart_info[i].surplus_num_input = orderInfo.cart_info[i].surplus_num;
orderInfo.cart_info[i].checked = true;
}
this.orderInfo = orderInfo
this.popupShow = true;
}
}).catch(res => {
this.$util.Tips({
title: res
});
});
},
closePopup() {
this.popupShow = false;
},
writeSuccess(val) {
this.isAll = val;
this.box = true;
},
ok(val) {
this.box = false;
this.popupShow = false;
this.getList();
},
}
}
</script>
<style lang="scss" scoped>
.scan {
padding-bottom: 160upx;
.header {
height: 346rpx;
padding: 48rpx 0 0 32rpx;
background: linear-gradient(270deg, $gradient-primary-admin 0%, $primary-admin 100%);
font-weight: 500;
font-size: 36rpx;
line-height: 50rpx;
color: #FFFFFF;
}
.box {
padding: 0 20rpx;
margin: -216rpx 0 0;
}
.content {
padding: 32rpx 24rpx;
border-radius: 24rpx;
margin-bottom: 20rpx;
background: #FFFFFF;
.attributes {
font-size: 28rpx;
line-height: 40rpx;
color: $primary-admin;
}
.orange {
color: #FF7E00;
}
.pad {
padding: 20upx 20upx 22upx;
}
.btn {
font-size: 28rpx;
line-height: 40rpx;
color: #999999;
.iconfont {
margin-left: 4rpx;
font-size: 32rpx;
}
}
.content_box {
margin-top: 26rpx;
image {
width: 136rpx;
height: 136rpx;
border-radius: 16rpx;
}
.content_box_title {
flex: 1;
padding-left: 20rpx;
font-size: 24rpx;
line-height: 34rpx;
color: #666666;
.textbox {
font-weight: 500;
font-size: 28rpx;
line-height: 40rpx;
color: #333333;
}
.mar {
margin: 16upx 0upx;
}
.attribute {
color: #999999;
// margin: 4upx 0upx 10upx;
}
.txt {
display: flex;
justify-content: space-between;
font-size: 24upx;
.orange {
color: #FF7E00;
}
.blue {
color: $primary-admin;
}
}
}
}
.content_bottom {
display: flex;
justify-content: space-between;
font-size: 22upx;
padding: 0upx 20upx;
color: #666666;
.money {
font-size: 26upx;
color: #F5222D;
}
}
}
}
.popup {
position: fixed;
right: 0;
bottom: 0;
left: 0;
z-index: 6;
// max-height: 75%;
// min-height: 500rpx;
height: 800rpx;
padding-bottom: 0;
padding-bottom: constant(safe-area-inset-bottom);
padding-bottom: env(safe-area-inset-bottom);
border-radius: 40rpx 40rpx 0 0;
background: #FFFFFF;
overflow: hidden;
flex-wrap: nowrap;
transform: translateY(100%);
transition: transform 0.3s;
&.on {
transform: translateY(0);
}
.popup-hd {
position: relative;
height: 108rpx;
text-align: center;
font-weight: 500;
font-size: 32rpx;
line-height: 108rpx;
color: #333333;
.btn {
position: absolute;
top: 50%;
right: 32rpx;
width: 36rpx;
height: 36rpx;
border-radius: 50%;
background: #EEEEEE;
transform: translateY(-50%);
text-align: center;
line-height: 36rpx;
}
.iconfont {
vertical-align: middle;
font-size: 24rpx;
color: #333333;
}
}
.popup-bd {
position: relative;
flex: 1;
min-height: 0;
box-sizing: border-box;
/deep/.shoppingCart {
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
display: flex;
flex-direction: column;
padding: 0;
.content {
flex: 1;
min-height: 0;
overflow-y: auto;
margin-top: 0;
padding: 36rpx 32rpx;
border-radius: 0;
.item {
margin-bottom: 48rpx;
}
}
.footer {
position: static;
height: 96rpx;
padding-bottom: 0;
}
}
}
.popup-ft {
padding: 16rpx 20rpx 16rpx 32rpx;
.btn {
height: 64rpx;
padding: 0 32rpx;
border-radius: 32rpx;
background: $primary-admin;
font-weight: 500;
font-size: 24rpx;
line-height: 64rpx;
color: #FFFFFF;
}
}
}
.boxs {
position: fixed;
top: 0;
bottom: 0;
width: 100%;
height: 100%;
z-index: 10;
background-color: #78797a;
.small_box {
position: fixed;
top: 50%;
right: 75rpx;
left: 75rpx;
padding: 40rpx;
border-radius: 32rpx;
background: #FFFFFF;
transform: translateY(-50%);
image {
width: 100%;
height: 228upx;
}
.content {
// height: 200upx;
text-align: center;
.font {
font-weight: 500;
font-size: 32rpx;
line-height: 52rpx;
color: #333333;
}
.small_font {
margin-top: 24rpx;
font-size: 30rpx;
line-height: 42rpx;
color: #666666;
}
}
.btn-box {
margin-top: 40rpx;
}
.btn {
flex: 1;
height: 72rpx;
border: 1rpx solid $primary-admin;
border-radius: 36rpx;
margin-left: 32rpx;
transform: rotateZ(360deg);
text-align: center;
font-weight: 500;
font-size: 26rpx;
line-height: 70rpx;
color: $primary-admin;
&:first-child {
margin-left: 0;
}
&.on {
background: $primary-admin;
color: #FFFFFF;
}
}
}
}
</style>

View File

@@ -0,0 +1,280 @@
<template>
<base-drawer mode="bottom" :visible="visible" background-color="transparent" mask maskClosable @close="closeDrawer">
<view class="classify rd-t-40rpx">
<view class="title">修改分类
<view class="close acea-row row-center-wrapper" @tap="closeDrawer">
<text class="iconfont icon-ic_close"></text>
</view>
</view>
<checkbox-group @change="checkboxChange($event)" v-if="categoryList.length">
<view class="list acea-row">
<view class="item">
<view class="tips">一级分类</view>
<scroll-view scroll-y="true" class="scroll-Y">
<view class="itemn line1" :class="{checked: index == currentOne,on:checkedIds.includes(item.id+'')}" v-for="(item,index) in categoryList" :key="index" @click="categoryTap(index)">
<!-- #ifndef MP -->
<checkbox :value="(item.id).toString()"
:checked='checkedIds.includes(item.id+"")'
color="#ffffff" backgroundColor="#ffffff"
activeBackgroundColor="#2A7EFB" activeBorderColor="#2A7EFB"
style="transform:scale(0.9)" />
<!-- #endif -->
<!-- #ifdef MP -->
<checkbox :value="item.id" :checked='checkedIds.includes(item.id+"")' style="transform:scale(0.9)" color="#ffffff" />
<!-- #endif -->
{{item.cate_name}}
</view>
</scroll-view>
</view>
<view class="item on" :class="!categoryList[currentOne].children.length?'on3':''" v-if="categoryList[currentOne]">
<view class="tips">二级分类</view>
<scroll-view scroll-y="true" class="scroll-Y">
<view class="itemn line1" :class="{checked: jIndex == currentTwo,on:checkedIds.includes(j.id+'')}" v-for="(j,jIndex) in categoryList[currentOne].children" :key="jIndex" @click="categoryTwoTap(jIndex)">
<!-- #ifndef MP -->
<checkbox :value="(j.id).toString()" :checked='checkedIds.includes(j.id+"")'
color="#ffffff" backgroundColor="#ffffff"
activeBackgroundColor="#2A7EFB" activeBorderColor="#2A7EFB"
style="transform:scale(0.9)" />
<!-- #endif -->
<!-- #ifdef MP -->
<checkbox :value="j.id" :checked='checkedIds.includes(j.id+"")' style="transform:scale(0.9)" />
<!-- #endif -->
{{j.cate_name}}
</view>
</scroll-view>
</view>
<view class="item on2" v-if="categoryList[currentOne] && categoryList[currentOne].children.length">
<view class="tips">三级分类</view>
<scroll-view scroll-y="true" class="scroll-Y">
<view class="itemn line1" :class="{on:checkedIds.includes(x.id+'')}" v-for="(x,xIndex) in categoryList[currentOne].children[currentTwo].children" :key="xIndex">
<!-- #ifndef MP -->
<checkbox :value="(x.id).toString()" :checked='checkedIds.includes(x.id+"")'
color="#ffffff" backgroundColor="#ffffff"
activeBackgroundColor="#2A7EFB" activeBorderColor="#2A7EFB"
style="transform:scale(0.9)" />
<!-- #endif -->
<!-- #ifdef MP -->
<checkbox :value="x.id" :checked='checkedIds.includes(x.id+"")' style="transform:scale(0.9)" />
<!-- #endif -->
{{x.cate_name}}{{x.id}}
</view>
</scroll-view>
</view>
</view>
</checkbox-group>
<view class="empty-box" v-else>
<emptyPage title="暂无分类~" src="/statics/images/empty-box.png"></emptyPage>
</view>
<view class="footer acea-row row-between-wrapper">
<view class="bnt acea-row row-center-wrapper" @tap="reset">重置</view>
<view class="bnt on acea-row row-center-wrapper" @tap="define">确定</view>
</view>
</view>
</base-drawer>
</template>
<script>
import emptyPage from '@/components/emptyPage.vue';
import {
getCategory,
postBatchProcess
} from "@/api/admin";
export default {
components: {
emptyPage
},
props:{
visible: {
type: Boolean,
default: false,
},
},
data: function() {
return {
categoryList:[],
currentOne:0,
currentTwo:0,
checkedIds:[],
ids:null //父级商品id
};
},
mounted() {},
methods:{
checkboxChange(e, index, item){
this.checkedIds = e.detail.value;
},
categoryTwoTap(index){
this.currentTwo = index
},
categoryTap(index){
this.currentOne = index
this.currentTwo = 0
},
category(id,cateId){
this.ids = id;
if(cateId){
this.checkedIds = cateId.split(',')
}else{
this.checkedIds = []
}
getCategory().then(res=>{
this.categoryList = res.data;
}).catch(err=>{
this.$util.Tips({
title: err
});
})
},
reset(){
this.checkedIds = [];
},
define(){
console.log("非大概");
console.log(this.checkedIds);
if(!this.checkedIds.length){
this.$util.Tips({
title: '请选择分类'
});
return
}
let data = {
type:1,
data:{
cate_id:this.checkedIds
},
ids:this.ids
}
postBatchProcess(data).then(res=>{
this.$util.Tips({
title: res.msg
});
this.$emit('successChange');
}).catch(err=>{
this.$util.Tips({
title: err
});
})
},
closeDrawer() {
this.$emit('closeDrawer');
}
}
}
</script>
<style lang="scss" scoped>
/deep/ checkbox .wx-checkbox-input.wx-checkbox-input-checked {
border: 1px solid $primary-admin;
background-color: $primary-admin;
color: #fff;
}
/deep/checkbox{
margin-right: 13rpx;
}
/deep/uni-checkbox .uni-checkbox-input{
border-radius: 4rpx;
width: 28rpx;
height: 28rpx;
}
.classify{
background-color: #fff;
padding-bottom: 60rpx;
.title{
text-align: center;
height: 108rpx;
line-height: 108rpx;
font-size: 32rpx;
font-family: PingFang SC, PingFang SC;
font-weight: 600;
color: #333333;
position: relative;
padding: 0 30rpx;
.close{
width: 36rpx;
height: 36rpx;
line-height: 36rpx;
background: #EEEEEE;
border-radius: 50%;
position: absolute;
right: 30rpx;
top:38rpx;
.iconfont {
font-weight: 300;
font-size: 20rpx;
}
}
}
.list{
height: 770rpx;
.scroll-Y{
height: 684rpx;
}
.item{
width: 33.33%;
padding-left: 32rpx;
font-size: 26rpx;
font-family: PingFang SC, PingFang SC;
font-weight: 400;
color: #666666;
padding-top: 30rpx;
.tips{
color: #999;
font-size: 24rpx;
margin-bottom: 30rpx;
}
.itemn{
margin-bottom: 58rpx;
&.checked{
color: #000;
}
&.on{
color: $primary-admin;
}
}
&.on{
background-color: #FAFAFA;
}
&.on2{
background-color: #F5F5F5;
}
&.on3{
width: 66.66%;
}
}
}
.footer {
box-sizing: border-box;
padding: 0 20rpx;
width: 100%;
height: 112rpx;
background-color: #fff;
position: fixed;
bottom: 0;
z-index: 30;
height: calc(112rpx + constant(safe-area-inset-bottom)); ///兼容 IOS<11.2/
height: calc(112rpx + env(safe-area-inset-bottom)); ///兼容 IOS>11.2/
padding-bottom: constant(safe-area-inset-bottom); ///兼容 IOS<11.2/
padding-bottom: env(safe-area-inset-bottom); ///兼容 IOS>11.2/
left: 0;
.bnt {
width: 347rpx;
height: 72rpx;
border-radius: 50rpx;
border: 1px solid $primary-admin;
color: $primary-admin;
font-size: 26rpx;
font-family: PingFang SC, PingFang SC;
font-weight: 500;
&.on{
background-color: $primary-admin;
color: #fff;
}
}
}
}
</style>

View File

@@ -0,0 +1,153 @@
<template>
<base-drawer mode="bottom" :visible="visible" background-color="transparent" mask maskClosable @close="closeDrawer">
<view class="edit-price rd-t-40rpx" v-if="goodsInfo.attr_value">
<view class="title">修改价格/库存
<view class="close acea-row row-center-wrapper" @tap="closeDrawer">
<text class="iconfont icon-ic_close"></text>
</view>
</view>
<view class="list">
<view class="item acea-row row-between-wrapper">
<view>售价</view>
<input type="digit" :placeholder="'请填写售价'+tips" placeholder-class="placeholder" v-model="goodsInfo.attr_value.price" />
</view>
<view class="item acea-row row-between-wrapper">
<view>成本价</view>
<input type="digit" :placeholder="'请填写成本价'+tips" placeholder-class="placeholder" v-model="goodsInfo.attr_value.cost" />
</view>
<view class="item acea-row row-between-wrapper">
<view>划线</view>
<input type="digit" :placeholder="'请填写划线'+tips" placeholder-class="placeholder" v-model="goodsInfo.attr_value.ot_price" />
</view>
<view class="item acea-row row-between-wrapper">
<view>库存</view>
<input type="number" :placeholder="'请填写库存'+tips" placeholder-class="placeholder" v-model="goodsInfo.attr_value.stock" />
</view>
</view>
<view v-if="goodsInfo.spec_type" class="bnt acea-row row-center-wrapper" @tap="defineSpec">确定</view>
<view v-else class="bnt acea-row row-center-wrapper" @tap="define">保存</view>
</view>
</base-drawer>
</template>
<script>
import {
postUpdateAttrs
} from "@/api/admin";
export default {
props:{
visible: {
type: Boolean,
default: false,
},
goodsInfo: {
type: Object,
default: () => {}
},
},
data: function() {
return {
tips:''
};
},
mounted() {
this.tips = this.goodsInfo.spec_type?'(可为空)':''
},
methods:{
defineSpec(){
let info = this.goodsInfo.attr_value;
if(info.cost || info.price || info.ot_price || info.stock){
this.$emit('successChange',info);
}else{
this.$util.Tips({
title: '修改类容至少填写一项'
});
}
},
define(){
let data = {
attr_value:[]
}
data.attr_value.push(this.goodsInfo.attr_value)
postUpdateAttrs(this.goodsInfo.id,data).then(res=>{
this.$util.Tips({
title: res.msg
});
this.$emit('successChange');
}).catch(err=>{
this.$util.Tips({
title: err
});
})
},
closeDrawer() {
this.$emit('closeDrawer');
}
}
}
</script>
<style lang="scss" scoped>
.edit-price{
background-color: #fff;
padding-bottom: 60rpx;
.title{
text-align: center;
height: 108rpx;
line-height: 108rpx;
font-size: 32rpx;
font-family: PingFang SC, PingFang SC;
font-weight: 600;
color: #333333;
position: relative;
padding: 0 30rpx;
.close{
width: 36rpx;
height: 36rpx;
line-height: 36rpx;
background: #EEEEEE;
border-radius: 50%;
position: absolute;
right: 30rpx;
top:38rpx;
.iconfont {
font-weight: 300;
font-size: 20rpx;
}
}
}
.list{
padding: 0 10rpx 0 30rpx;
.item{
font-size: 28rpx;
font-family: PingFang SC, PingFang SC;
font-weight: 400;
color: #333333;
height: 72rpx;
margin-bottom: 32rpx;
box-sizing: border-box;
input {
text-align: right;
font-size: 28rpx;
height: 100%;
padding-right: 20rpx;
}
.placeholder{
font-size: 28rpx;
padding-right: 20rpx;
}
}
}
.bnt{
font-size: 26rpx;
font-family: PingFang SC, PingFang SC;
font-weight: 500;
color: #FFFFFF;
width: 710rpx;
height: 72rpx;
background: $primary-admin;
border-radius: 50rpx;
margin: 72rpx auto 0 auto;
}
}
</style>

View File

@@ -0,0 +1,252 @@
<template>
<base-drawer mode="right" :visible="visible" background-color="transparent" mask maskClosable @close="closeDrawer">
<view class="edit-lable">
<!-- #ifdef MP -->
<view class="accountTitle">
<view :style="{height:getHeight.barTop+'px'}"></view>
<view class="sysTitle acea-row row-center-wrapper" :style="{height:getHeight.barHeight+'px'}">
<view>添加标签</view>
</view>
</view>
<view :style="{height:(getHeight.barTop+getHeight.barHeight)+'px'}"></view>
<view class="list" v-if="isStore"
:style="'height: calc(100% - '+(getHeight.barTop+getHeight.barHeight*2+150)+'rpx - constant(safe-area-inset-bottom));height: calc(100% - '+(getHeight.barTop+getHeight.barHeight*2+150)+'rpx - env(safe-area-inset-bottom))'">
<!-- #endif -->
<!-- #ifndef MP -->
<view class="header">添加标签</view>
<view class="list" v-if="isStore">
<!-- #endif -->
<scroll-view scroll-y="true" style="height: 100%">
<view class="item" v-for="(item, index) in labelList" :key="index">
<view class="title" v-if="item.children && item.children.length">{{item.label_name}}</view>
<view class="listn acea-row row-middle" v-if="item.children && item.children.length">
<view class="name acea-row row-center-wrapper" :class="{on:j.disabled}" v-for="(j, indexn) in item.children" :key="indexn" @click="selectLabel(j)">
<text class="line1">{{j.label_name}}</text>
</view>
</view>
</view>
</scroll-view>
</view>
<view class="empty-box" v-else>
<emptyPage title="暂无标签~" src="/statics/images/empty-box.png"></emptyPage>
</view>
<view class="footer acea-row row-between-wrapper">
<view class="bnt acea-row row-center-wrapper" @tap="reset">重置</view>
<view class="bnt on acea-row row-center-wrapper" @tap="define">确定</view>
</view>
</view>
</base-drawer>
</template>
<script>
import emptyPage from '@/components/emptyPage.vue';
import {
getProductLabel,
postBatchProcess
} from "@/api/admin";
import { handleError } from "vue";
export default {
components: {
emptyPage
},
props:{
visible: {
type: Boolean,
default: false,
},
},
data: function() {
return {
// #ifdef MP
getHeight: this.$util.getWXStatusHeight(),
// #endif
labelList:[],
goodsInfo:{}, //列表中已存在id(固定不变)
dataLabel: [], //已存在选中id(随着选中可以变化)
isStore:false, //判断是否存在标签
num:0, // 判断是否为批量
ids:[] //批量时的id集合
};
},
mounted() {
},
methods:{
define(){
let data = {
data:{
store_label_id:this.dataLabel
},
type:2
}
if(this.num){
data.ids = this.ids
}else{
data.ids = this.goodsInfo.id
}
postBatchProcess(data).then(res=>{
this.$util.Tips({
title: res.msg
});
this.$emit('successChange');
}).catch(err=>{
this.$util.Tips({
title: err
});
})
},
reset(){
this.productLabel(this.goodsInfo,this.num,this.ids);
},
inArray: function (search, array) {
for (let i in array) {
if (array[i] == search) {
return true;
}
}
return false;
},
productLabel(data,num,ids){
this.dataLabel = data.store_label_id || [];
this.goodsInfo = JSON.parse(JSON.stringify(data));
this.num = num;
this.ids = ids;
getProductLabel().then(res=>{
res.data.map(el => {
if (el.children && el.children.length) {
this.isStore = true;
el.children.map(label => {
if (this.inArray(label.id, this.dataLabel)) {
label.disabled = true;
} else {
label.disabled = false;
}
})
}
})
this.labelList = res.data
}).catch(err=>{
this.$util.Tips({
title: err
});
})
},
selectLabel(label) {
if (label.disabled) {
let index = this.dataLabel.indexOf(this.dataLabel.filter(d => d == label.id)[0]);
this.dataLabel.splice(index, 1);
label.disabled = false
} else {
this.dataLabel.push(label.id);
label.disabled = true
}
},
closeDrawer() {
this.$emit('closeDrawer');
}
}
}
</script>
<style lang="scss" scoped>
.accountTitle{
position: fixed;
left:0;
top:0;
width: 100%;
z-index: 99;
padding-bottom: 6rpx;
.sysTitle{
width: 100%;
position: relative;
font-weight: 600;
color: #333333;
font-size: 34rpx;
font-family: PingFang SC, PingFang SC;
}
}
.edit-lable{
background-color: #fff;
width: 670rpx;
border-radius: 40rpx 0 0 40rpx;
height: 100%;
padding: 20rpx 34rpx 0 32rpx;
.header{
text-align: center;
height: 96rpx;
line-height: 96rpx;
font-size: 34rpx;
font-family: PingFang SC, PingFang SC;
font-weight: 600;
color: #333333;
position: relative;
}
.list{
overflow: auto;
height: calc(100% - 208rpx);
height: calc(100% - (208rpx + constant(safe-area-inset-bottom)));
height: calc(100% - (208rpx + env(safe-area-inset-bottom)));
.item{
margin-top: 48rpx;
.title{
font-size: 28rpx;
font-family: PingFang SC, PingFang SC;
font-weight: 600;
color: #333333;
}
.listn{
.name{
width: 184rpx;
height: 56rpx;
background-color: #F5F5F5;
border-radius: 50rpx;
border:1rpx solid #F5F5F5;
font-size: 24rpx;
font-family: PingFang SC, PingFang SC;
font-weight: 400;
color: #333333;
margin-right: 26rpx;
margin-top: 24rpx;
padding: 0 8rpx;
&.on {
background-color:$light-primary-admin;
border-color:$primary-admin;
color: $primary-admin;
}
&:nth-of-type(3n){
margin-right: 0;
}
}
}
}
}
.footer{
width: 100%;
height: 112rpx;
position: fixed;
bottom: 0;
left:0;
padding: 0 32rpx;
background-color: #fff;
border-radius: 0 0 0 40rpx;
height: calc(112rpx + constant(safe-area-inset-bottom)); ///兼容 IOS<11.2/
height: calc(112rpx + env(safe-area-inset-bottom)); ///兼容 IOS>11.2/
padding-bottom: constant(safe-area-inset-bottom); ///兼容 IOS<11.2/
padding-bottom: env(safe-area-inset-bottom); ///兼容 IOS>11.2/
.bnt{
width: 296rpx;
height: 72rpx;
border: 1px solid $primary-admin;
border-radius: 200rpx;
font-size: 26rpx;
font-family: PingFang SC, PingFang SC;
font-weight: 600;
color: $primary-admin;
&.on{
background: $primary-admin;
border-color: $primary-admin;
color: #fff;
}
}
}
}
</style>

651
pages/admin/goods/index.vue Normal file
View File

@@ -0,0 +1,651 @@
<template>
<view class="goods-list">
<!-- #ifdef MP || APP-PLUS -->
<view class="accountTitle">
<view :style="{height:getHeight.barTop+'px'}"></view>
<view class="sysTitle acea-row row-center-wrapper" :style="{height:getHeight.barHeight+'px'}">
<view>商品管理</view>
<text class="iconfont icon-ic_leftarrow" @click="goarrow"></text>
</view>
</view>
<view :style="{height:(getHeight.barTop+getHeight.barHeight)+'px'}"></view>
<!-- #endif -->
<view class="searchCon acea-row row-between-wrapper">
<view class="search acea-row row-middle">
<text class="iconfont icon-ic_search"></text>
<input class="inputs" placeholder='请输入商品名称/ID' placeholder-class='placeholder' confirm-type='search' name="search"
v-model="keyword" @confirm="searchSubmit"></input>
</view>
<view @click="manageTap" v-if="administer">取消</view>
<view class="edit acea-row row-center-wrapper" @click="manageTap" v-else>
<text class="iconfont icon-ic_batch"></text>
</view>
</view>
<view class="nav acea-row row-middle">
<view class="item" :class="current == index?'on':''" v-for="(item, index) in navList" :key="index" @click="navTap(item,index)">
{{item.name}}
<image src="../static/adorn.png" v-if="current == index"></image>
</view>
</view>
<view class="list" v-if="goodsList.length">
<checkbox-group @change="checkboxChange">
<view class="acea-row row-middle" v-for="(item, index) in goodsList" :key="index">
<!-- #ifndef MP -->
<checkbox class="checkbox" v-if="administer" :value="(item.id).toString()" :checked="item.checked"
color="#ffffff" backgroundColor="#ffffff"
activeBackgroundColor="#2A7EFB" activeBorderColor="#2A7EFB"/>
<!-- #endif -->
<!-- #ifdef MP -->
<checkbox class="checkbox" v-if="administer" :value="item.id" :checked="item.checked"
color="#ffffff"/>
<!-- #endif -->
<view class="item">
<view class="top acea-row row-center-wrapper" @tap="goDetail(item)">
<view class="pictrue">
<image :src="item.image"></image>
</view>
<view class="text">
<view class="name line1">{{item.store_name}}</view>
<view class="info">
<text>销量: {{item.sales}}</text>
<text>库存: {{item.stock}}</text>
<text>评分: {{item.star}}</text>
</view>
<baseMoney
:money="item.price"
symbolSize="20"
integerSize="32"
decimalSize="20"
color="#FF7E00"
></baseMoney>
</view>
</view>
<view class="bottom acea-row row-right" v-if="!administer">
<view class="bnt acea-row row-center-wrapper" :class="item.is_show?'':'up'" @click="setShow(item,0)">{{item.is_show?'下架':'上架'}}</view>
<view class="bnt on acea-row row-center-wrapper" @tap="openDrawer(item)">编辑</view>
</view>
</view>
</view>
</checkbox-group>
</view>
<view class="empty-box" v-if="goodsList.length == 0 && !loading">
<emptyPage title="暂无商品~" src="/statics/images/empty-box.gif"></emptyPage>
</view>
<Loading :loaded="loadend" :loading="loading"></Loading>
<view class="footerH"></view>
<view class="footer acea-row row-between-wrapper" v-if="administer">
<checkbox-group @change="checkboxAllChange">
<checkbox value="all" :checked="isAllSelect" color="#ffffff" backgroundColor="#ffffff"
activeBackgroundColor="#2A7EFB" activeBorderColor="#2A7EFB" />
<text class='checkAll'>全选({{getIds().length}})</text>
</checkbox-group>
<view class="acea-row row-middle">
<view class="bnt acea-row row-center-wrapper" @click="editLabels">添加标签</view>
<view class="bnt acea-row row-center-wrapper" @click="editClass">修改分类</view>
<view class="bnt acea-row row-center-wrapper" v-if="type == 1" @click="setShow('',1,0)">下架</view>
<view class="bnt acea-row row-center-wrapper" v-else-if="type == 2" @click="setShow('',1,1)">上架</view>
</view>
</view>
<footer-page></footer-page>
<base-drawer mode="bottom" :visible="visible" background-color="transparent" mask maskClosable @close="closeDrawer">
<view class="edit-list rd-t-40rpx">
<view class="item" v-for="(item, index) in editList" :key="index" @tap="editInfo(index)">{{item.name}}</view>
</view>
</base-drawer>
<edit-price :visible='visiblePrice' :goodsInfo='goodsInfo' @closeDrawer='priceCloseDrawer' @successChange='successChange'></edit-price>
<edit-lable ref="lable" :visible='visibleLable' @closeDrawer='lableCloseDrawer' @successChange='successChange'></edit-lable>
<classify ref="classify" :visible='visibleClass' @closeDrawer='classCloseDrawer' @successChange='successChange'></classify>
</view>
</template>
<script>
import Loading from '@/components/Loading/index';
import emptyPage from '@/components/emptyPage.vue';
import footerPage from '../components/footerPage/index.vue';
import editPrice from './components/editPrice/index.vue';
import editLable from './components/label/index.vue';
import classify from './components/classify/index.vue';
import { goShopDetail } from '@/libs/order.js';
import {
adminProductList,
productSetShow
} from "@/api/admin";
export default {
components: {
editPrice,
editLable,
classify,
footerPage,
emptyPage,
Loading
},
data() {
return {
getHeight: this.$util.getWXStatusHeight(),
navList:[
{
name:'全部',
type:''
},
{
name:'出售中',
type:1
},
{
name:'仓库中',
type:2
},
{
name:'已售罄',
type:4
},
{
name:'库存警告',
type:5
}
],
editList:[
{
name:'修改价格/库存'
},
{
name:'商品分类'
},
{
name:'商品标签'
},
],
current:0,
administer:0,
isAllSelect: false,
goodsList:[],
goodsInfo:{},
visible:false,
visiblePrice:false, //价格库存是否显示
visibleLable:false, //标签是否显示
loadTitle: '加载更多',
loading: false,
loadend: false,
limit: 20,
page: 1,
keyword:'', //搜索字段
type:'', //商品状态
visibleClass:false,
}
},
onShow() {
},
onLoad(option) {
this.type = option.type || '';
this.keyword = option.keyword || '';
for (let i = 0; i < this.navList.length; i++) {
if (this.navList[i].type == this.type) {
this.current = i;
break;
}
}
this.productList();
},
methods: {
// 去详情页
goDetail(item) {
if(!item.is_show){
this.$util.Tips({
title: '商品未上架'
});
return
}
goShopDetail(item, this.$store.state.app.uid).catch(res => {
uni.navigateTo({
url: `/pages/goods_details/index?id=${item.id}`
});
});
},
goarrow(){
uni.navigateBack()
},
editClass(){
if(!this.getIds().length){
this.$util.Tips({
title: '请选择商品'
});
return
}
this.$refs.classify.category(this.getIds(),'');
let that = this;
setTimeout(function(){
that.visibleClass = true
},200)
},
classCloseDrawer(){
this.visibleClass = false
},
successChange(){
this.visibleClass = false
this.visibleLable = false
this.visiblePrice = false
this.init();
},
//批量编辑标签
editLabels(){
if(!this.getIds().length){
this.$util.Tips({
title: '请选择商品'
});
return
}
this.visibleLable = true
this.$refs.lable.productLabel({},1,this.getIds());
},
//批量获取id集合
getIds(){
let ids = []
this.goodsList.forEach(item=>{
if(item.checked){
ids.push(item.id)
}
})
ids.slice(0, 100)
return ids
},
setShow(item,num,type){
let data = {}
if(num){
if(!this.getIds().length){
this.$util.Tips({
title: '请选择商品'
});
return
}
data = {
id:this.getIds(),
is_show:type
}
}else{
data = {
id:item.id,
is_show:item.is_show?0:1
}
}
productSetShow(data).then(res=>{
this.$util.Tips({
title: res.msg
});
this.init();
}).catch(err=>{
this.$util.Tips({
title: err
});
})
},
init(){
this.goodsList = [];
this.page = 1;
this.loadend = false;
this.loading = false;
this.productList();
},
searchSubmit(){
this.init();
},
productList(){
let that = this;
if (this.loading) return;
if (this.loadend) return;
that.loading = true;
that.loadTitle = "";
adminProductList({
page: that.page,
limit: that.limit,
store_name: that.keyword,
type: that.type,
}).then(res=>{
let goodsList = res.data.list;
goodsList.forEach(item => {
item.checked = false;
})
this.isAllSelect = false
let loadend = goodsList.length < that.limit;
that.goodsList = that.$util.SplitArray(goodsList, that.goodsList);
that.$set(that, 'goodsList', that.goodsList);
that.loadend = loadend;
that.loadTitle = loadend ? '没有更多内容啦~' : '加载更多';
that.page = that.page + 1;
that.loading = false;
}).catch(err=>{
that.loading = false;
that.loadTitle = "加载更多";
})
},
editInfo(index){
switch (index) {
case 0:
this.visible = false
if(this.goodsInfo.spec_type){
uni.navigateTo({
url: '/pages/admin/goods/specs?id='+this.goodsInfo.id
})
}else{
this.visiblePrice = true
}
break;
case 1:
this.visible = false
this.visibleClass = true
break;
case 2:
this.visibleLable = true
this.visible = false
break;
}
},
lableCloseDrawer(){
this.visibleLable = false
},
priceCloseDrawer(){
this.visiblePrice = false
},
openDrawer(item){
this.visible = true
this.goodsInfo = JSON.parse(JSON.stringify(item))
this.$refs.lable.productLabel(this.goodsInfo,0,[]);
this.$refs.classify.category(item.id,item.cate_id);
},
closeDrawer(){
this.visible = false
},
manageTap() {
this.administer = !this.administer;
},
navTap(item,index){
this.current = index;
if (this.type != item.type) {
this.type = item.type;
this.init();
}
},
checkboxChange(event) {
let idList = event.detail.value;
this.goodsList.forEach((item) => {
if (idList.indexOf(item.id + '') !== -1) {
item.checked = true;
} else {
item.checked = false;
}
})
if (idList.length == this.goodsList.length) {
this.isAllSelect = true;
} else {
this.isAllSelect = false;
}
},
forGoods(val) {
let that = this;
if (!that.goodsList.length) return
that.goodsList.forEach((item) => {
if (val) {
item.checked = true;
} else {
item.checked = false;
}
})
},
checkboxAllChange(event) {
let value = event.detail.value;
if (value.length) {
if(this.goodsList.length>100){
this.$util.Tips({
title: '每次最多只提交100条数据'
});
}
this.isAllSelect = true;
this.forGoods(1)
} else {
this.isAllSelect = false;
this.forGoods(0)
}
},
},
onReachBottom(){
this.productList();
}
}
</script>
<style lang="scss" scoped>
/deep/checkbox .wx-checkbox-input.wx-checkbox-input-checked {
border: 1px solid $primary-admin !important;
background-color: $primary-admin !important;
}
/deep/uni-checkbox .uni-checkbox-input{
margin-top: -4rpx;
}
/deep/checkbox:not([disabled]) .uni-checkbox-input:hover {
border-color: #d1d1d1 !important;
}
.empty-box{
padding: 0 20rpx;
}
.accountTitle{
background: #F5F5F5;
position: fixed;
left:0;
top:0;
width: 100%;
z-index: 99;
padding-bottom: 6rpx;
.sysTitle{
width: 100%;
position: relative;
font-weight: 500;
color: #333333;
font-size: 30rpx;
.iconfont{
position: absolute;
font-size: 42rpx;
left:20rpx;
width: 60rpx;
font-weight: 500;
}
}
}
.goods-list{
padding-top: 20rpx;
.searchCon{
padding: 0 20rpx;
.search{
width: 618rpx;
height: 72rpx;
background: #FFFFFF;
border-radius: 50rpx;
padding: 0 34rpx;
.iconfont{
color: #999;
font-size: 32rpx;
margin-right: 16rpx;
}
.inputs{
font-size: 28rpx;
width: 100%;
height: 100%;
flex: 1;
}
.placeholder{
color: #ccc;
}
}
.edit{
width: 72rpx;
height: 72rpx;
background: #FFFFFF;
border-radius: 50%;
.iconfont {
color: #666;
font-size: 36rpx;
}
}
}
.nav{
padding: 20rpx 20rpx 18rpx 34rpx;
position: sticky;
top:0;
left:0;
width: 100%;
background-color: #F5F5F5;
z-index: 9;
.item{
font-weight: 400;
font-size: 26rpx;
color: #333333;
padding: 10rpx 0;
position: relative;
&~.item{
margin-left: 72rpx;
}
&.on{
font-weight: 500;
color: $primary-admin;
font-size: 30rpx;
font-family: PingFang SC, PingFang SC;
}
image {
width: 14rpx;
height: 14rpx;
display: block;
position: absolute;
bottom: 0;
right: -4rpx;
}
}
}
.list{
padding-bottom: 20rpx;
padding: 0 20rpx 20rpx 20rpx;
/deep/uni-checkbox .uni-checkbox-input{
background-color: #f5f5f5;
margin: 0 20rpx 20rpx 0;
}
/deep/wx-checkbox .wx-checkbox-input{
background-color: #f5f5f5;
margin: 0 20rpx 20rpx 0;
}
.item {
width: 100%;
background-color: #fff;
padding: 24rpx;
box-sizing: border-box;
margin-bottom: 20rpx;
border-radius: 24rpx;
flex: 1;
overflow: hidden;
.top{
.checkbox{
margin-right: 10rpx;
}
.pictrue{
width: 136rpx;
height: 136rpx;
margin-right: 20rpx;
image {
width: 100%;
height: 100%;
border-radius: 16rpx;
}
}
.text{
flex: 1;
overflow: hidden;
.name {
font-size: 28rpx;
font-weight: 400;
color: #333333;
}
.info {
font-size: 24rpx;
font-weight: 400;
color: #666666;
margin: 10rpx 0 18rpx 0;
text {
margin-right: 40rpx;
}
}
}
}
.bottom{
margin-top: 26rpx;
.bnt{
width: 144rpx;
height: 56rpx;
border:1px solid #ccc;
font-size: 24rpx;
font-family: PingFang SC, PingFang SC;
font-weight: 400;
color: #333333;
border-radius: 50rpx;
&~.bnt{
margin-left: 16rpx;
}
&.on{
border-color: $primary-admin;
background-color: $primary-admin;
color: #fff;
}
&.up{
border-color: #FF7E00;
color: #FF7E00;
}
}
}
}
}
.footerH {
height: 110rpx;
height: calc(110rpx + constant(safe-area-inset-bottom)); ///兼容 IOS<11.2/
height: calc(110rpx + env(safe-area-inset-bottom)); ///兼容 IOS>11.2/
}
.footer {
box-sizing: border-box;
padding: 0 32rpx;
width: 100%;
height: 96rpx;
background-color: #fff;
position: fixed;
bottom: 0;
z-index: 30;
height: calc(96rpx + constant(safe-area-inset-bottom)); ///兼容 IOS<11.2/
height: calc(96rpx + env(safe-area-inset-bottom)); ///兼容 IOS>11.2/
padding-bottom: constant(safe-area-inset-bottom); ///兼容 IOS<11.2/
padding-bottom: env(safe-area-inset-bottom); ///兼容 IOS>11.2/
width: 100%;
left: 0;
.bnt {
width: 160rpx;
height: 64rpx;
border-radius: 50rpx;
border: 1rpx solid $primary-admin;
color: $primary-admin;
font-size: 24rpx;
font-family: PingFang SC, PingFang SC;
font-weight: 500;
&~.bnt{
margin-left: 16rpx;
}
}
}
.edit-list{
background-color: #fff;
padding: 45rpx 34rpx;
.item{
font-family: PingFang SC, PingFang SC;
font-weight: 400;
color: #333333;
font-size: 32rpx;
text-align: center;
height: 106rpx;
line-height: 106rpx;
}
}
}
</style>

340
pages/admin/goods/specs.vue Normal file
View File

@@ -0,0 +1,340 @@
<template>
<view class="specs">
<checkbox-group @change="checkboxChange">
<view class="list acea-row" :class="administer?'on':''" v-for="(item, index) in attrsList" :key="index">
<!-- #ifndef MP -->
<checkbox class="checkbox" v-if="administer" :value="(item.id).toString()" :checked="item.checked" />
<!-- #endif -->
<!-- #ifdef MP -->
<checkbox class="checkbox" v-if="administer" :value="item.id" :checked="item.checked" />
<!-- #endif -->
<view class="listCon">
<!-- <view class="item acea-row row-middle">
<view class="name">商品图</view>
<view class="pictrue">
<image :src="item.image" mode="aspectFill"></image>
</view>
</view> -->
<view class="item acea-row row-middle">
<view class="name">规格名称</view>
<view class="info">{{item.suk}}</view>
</view>
<view class="item acea-row row-middle">
<view class="name">售价</view>
<input type="number" :disabled="administer" min='0' v-model="item.price" placeholder="请填写售价" placeholder-class="placeholder"/>
</view>
<view class="item acea-row row-middle">
<view class="name">成本价</view>
<input type="number" :disabled="administer" v-model="item.cost" placeholder="请填写成本价" placeholder-class="placeholder"/>
</view>
<view class="item acea-row row-middle">
<view class="name">原价</view>
<input type="number" :disabled="administer" v-model="item.ot_price" placeholder="请填写原价" placeholder-class="placeholder"/>
</view>
<view class="item acea-row row-middle">
<view class="name">库存</view>
<input type="number" :disabled="administer" v-model="item.stock" placeholder="请填写库存" placeholder-class="placeholder"/>
</view>
</view>
</view>
</checkbox-group>
<view class="footer on acea-row row-between-wrapper" v-if="administer">
<checkbox-group @change="checkboxAllChange">
<checkbox value="all" :checked="isAllSelect" />
<text class='checkAll'>全选</text>
</checkbox-group>
<view class="acea-row row-middle">
<view class="bnt acea-row row-center-wrapper" @click="manageTap">取消</view>
<view class="bnt on acea-row row-center-wrapper" @click="batchEdit">批量修改</view>
</view>
</view>
<view class="footer acea-row row-between-wrapper" v-else>
<view class="bnt acea-row row-center-wrapper" @click="manageTap">批量操作</view>
<view class="bnt on acea-row row-center-wrapper" @click="define">保存</view>
</view>
<edit-price :visible='visiblePrice' :goodsInfo='goodsInfo' @closeDrawer='priceCloseDrawer' @successChange='successChange'></edit-price>
</view>
</template>
<script>
import editPrice from './components/editPrice/index.vue';
import {
getGetAttrs,
postUpdateAttrs
} from "@/api/admin";
export default {
components: {
editPrice
},
data() {
return {
attrsList:[],
id:0,
administer:false,
isAllSelect: false,
visiblePrice: false,
goodsInfo:{
id:0,
spec_type:1,
attr_value:{}
}
}
},
onShow() {
},
onLoad(option) {
this.id = option.id;
this.getAttrsList();
},
methods:{
//批量获取id集合
getIds(){
let ids = []
this.attrsList.forEach(item=>{
if(item.checked){
ids.push(item.id)
}
})
return ids
},
batchEdit(){
if(!this.getIds().length){
this.$util.Tips({
title: '请选择商品规格'
});
return
}
this.goodsInfo.id = this.id;
this.goodsInfo.attr_value = {
cost:'',
price:'',
ot_price:'',
stock:''
}
this.visiblePrice = true;
},
define(){
let data = {
attr_value:[]
}
this.attrsList.forEach(item=>{
data.attr_value.push({
cost:item.cost,
price:item.price,
ot_price:item.ot_price,
stock:item.stock,
unique:item.unique
})
})
postUpdateAttrs(this.id,data).then(res=>{
this.$util.Tips({
title: res.msg
},() => {
uni.navigateTo({
url: '/pages/admin/goods/index'
})
});
}).catch(err=>{
this.$util.Tips({
title: err
});
})
},
getAttrsList(){
getGetAttrs(this.id).then(res=>{
let data = res.data;
data.forEach(item => {
item.checked = false;
})
this.attrsList = data;
}).catch(err=>{
this.$util.Tips({
title: err
});
})
},
checkboxChange(event) {
let idList = event.detail.value;
this.attrsList.forEach((item) => {
if (idList.indexOf(item.id + '') !== -1) {
item.checked = true;
} else {
item.checked = false;
}
})
if (idList.length == this.attrsList.length) {
this.isAllSelect = true;
} else {
this.isAllSelect = false;
}
},
forGoods(val) {
let that = this;
if (!that.attrsList.length) return
that.attrsList.forEach((item) => {
if (val) {
item.checked = true;
} else {
item.checked = false;
}
})
},
checkboxAllChange(event) {
let value = event.detail.value;
if (value.length) {
this.isAllSelect = true;
this.forGoods(1)
} else {
this.isAllSelect = false;
this.forGoods(0)
}
},
manageTap() {
this.administer = !this.administer;
},
priceCloseDrawer(){
this.visiblePrice = false
},
successChange(e){
this.visiblePrice = false
let data = e;
this.attrsList.forEach(item=>{
if(item.checked){
if(data.cost){
item.cost = data.cost
}
if(data.price){
item.price = data.price
}
if(data.ot_price){
item.ot_price = data.ot_price
}
if(data.stock){
item.stock = data.stock
}
}
})
this.manageTap();
}
}
}
</script>
<style lang="scss" scoped>
/deep/checkbox .uni-checkbox-input.uni-checkbox-input-checked {
border: 1px solid $primary-admin !important;
background-color: $primary-admin !important;
}
/deep/checkbox .wx-checkbox-input.wx-checkbox-input-checked {
border: 1px solid $primary-admin !important;
background-color: $primary-admin !important;
}
.specs{
padding: 24rpx 20rpx 112rpx 20rpx;
padding-bottom: calc(112rpx + constant(safe-area-inset-bottom)); ///兼容 IOS<11.2/
padding-bottom: calc(112rpx + env(safe-area-inset-bottom)); ///兼容 IOS>11.2/
.list{
background-color: #fff;
border-radius: 24rpx;
padding: 0 24rpx;
margin-bottom: 20rpx;
.listCon{
flex: 1;
}
&.on {
input{
color: #999999 !important;
}
}
.checkbox{
margin: 32rpx 12rpx 0 0;
}
.item{
min-height: 102rpx;
font-size: 28rpx;
font-family: PingFang SC, PingFang SC;
font-weight: 400;
&~.item{
border-top: 1px solid #F1F1F1;
}
.name{
color: #333333;
width: 115rpx;
margin-right: 39rpx;
}
.info{
color: #999999;
flex: 1;
}
input {
font-size: 36rpx;
font-family: 'Regular';
color: #333333;
}
// #ifdef MP
input {
font-size: 30rpx;
}
// #endif
.placeholder{
font-size:28rpx;
}
.pictrue{
width: 100rpx;
height: 100rpx;
image {
width: 100%;
height: 100%;
border-radius: 16rpx;
}
}
}
}
.footer {
box-sizing: border-box;
padding: 0 20rpx;
width: 100%;
height: 112rpx;
background-color: #fff;
position: fixed;
bottom: 0;
z-index: 30;
height: calc(112rpx + constant(safe-area-inset-bottom)); ///兼容 IOS<11.2/
height: calc(112rpx + env(safe-area-inset-bottom)); ///兼容 IOS>11.2/
padding-bottom: constant(safe-area-inset-bottom); ///兼容 IOS<11.2/
padding-bottom: env(safe-area-inset-bottom); ///兼容 IOS>11.2/
width: 100%;
left: 0;
&.on {
height: 96rpx;
height: calc(96rpx + constant(safe-area-inset-bottom)); ///兼容 IOS<11.2/
height: calc(96rpx + env(safe-area-inset-bottom)); ///兼容 IOS>11.2/
.bnt{
width: 160rpx;
height: 64rpx;
font-size: 24rpx;
&.on{
background-color: $primary-admin;
color: #fff;
margin-left: 16rpx;
}
}
}
.bnt {
width: 346rpx;
height: 72rpx;
border-radius: 200rpx;
border: 1px solid $primary-admin;
color: $primary-admin;
font-size: 26rpx;
font-family: PingFang SC, PingFang SC;
font-weight: 500;
&.on{
background-color: $primary-admin;
color: #fff;
}
}
}
}
</style>

View File

@@ -0,0 +1,344 @@
<template>
<view>
<view class="w-full header_bg" :style="{'height': (174 + sysHeight) * 2 + 'rpx'}">
<view class="w-full abs-lb white_jianbian"></view>
</view>
<!-- #ifdef MP -->
<NavBar titleText="物流查询" :iconColor="iconColor" :textColor="iconColor" :isScrolling="isScrolling" showBack></NavBar>
<!-- #endif -->
<view class="relative px-20 z-20 express_box">
<view class="h-66 rd-t-24rpx light px-24 flex-between-center fs-20">
<text>{{orderInfo.delivery_name}} {{orderInfo.delivery_id}}</text>
<text class="inline-block copy_btn fs-22 text--w111-333" @tap="copyOrderId">复制单号</text>
</view>
<view class="rd-b-24rpx bg--w111-fff flex-between-center">
<view class="w-316 h-142 flex-col flex-center">
<text class="fs-32 fw-500 lh-44rpx">{{orderInfo.user_name}}</text>
<text class="fs-22 text--w111-999 lh-30rpx mt-8">{{orderInfo.user_phone}}</text>
</view>
<view class="flex-1 h-142 flex-center fs-28 fw-500 lh-40rpx relative city-box">
<text>{{orderInfo.send_city}}</text>
<text class="iconfont icon-a-jiantou11 mx-32"></text>
<text>{{orderInfo.user_city}}</text>
</view>
</view>
</view>
<view class="px-20 mt-20 relative">
<view class="bg--w111-fff rd-16rpx pt-32 pr-24 pl-24 pb-32">
<view class="flex-between-center">
<view class="fs-32 fw-500 text--w111-333">
<text>物流详情</text>
</view>
</view>
<view class="logisticsCon mt-50 relative" v-if="expressList.length">
<view class='item' v-for="(item,index) in logisticList" :key="index">
<view class='circular' :class='index === 0 ? "on text-center":""'>
<text class="iconfont icon-ic_complete text--w111-fff fs-24" v-if="index == 0"></text>
</view>
<view class='text' :class='index===0 ? "on-font on":""'>
<view>{{item.status}}</view>
<view class='data' :class='index===0 ? "on-font on":""'>{{item.time}}</view>
</view>
</view>
<view class="more-text fs-24" @tap="checkShowMore">
<text>{{showMore ? '收起' : '查看更多物流信息'}}</text>
<text class="iconfont fs-24 pl-8" :class="showMore ? 'icon-ic_uparrow' : 'icon-ic_downarrow'"></text>
</view>
</view>
<emptyPage title="暂无物流信息" src="/statics/images/noExpress.gif" v-else></emptyPage>
</view>
<view class="safe-area-inset-bottom"></view>
</view>
</view>
</template>
<script>
let sysHeight = uni.getWindowInfo().statusBarHeight;
import {
express
} from '@/api/order.js';
import {
getProductHot
} from '@/api/store.js';
import {
toLogin
} from '@/libs/login.js';
import {
mapGetters
} from "vuex";
import {
HTTP_REQUEST_URL
} from '@/config/app';
// #ifdef MP
import NavBar from '@/components/NavBar.vue'
// #endif
import emptyPage from '@/components/emptyPage.vue'
export default {
components: {
// #ifdef MP
NavBar,
// #endif
emptyPage,
},
data() {
return {
sysHeight: sysHeight,
imgHost: HTTP_REQUEST_URL,
orderId: '',
type: '',
product: [],
orderInfo: {},
expressList: [],
hostProduct: [],
isShowAuth: false,
pageScrollStatus: false,
showMore: true,
// #ifdef MP
iconColor: '#FFFFFF',
isScrolling: false,
// #endif
};
},
computed: {
...mapGetters(['isLogin']),
logisticList() {
if (this.showMore) {
return this.expressList
} else {
return this.expressList.slice(0, 1)
}
}
},
watch: {
isLogin: {
handler: function(newV, oldV) {
if (newV) {
//#ifndef MP
this.getExpress();
this.get_host_product();
//#endif
}
},
deep: true
}
},
onLoad: function(options) {
if (!options.orderId) return this.$util.Tips({
title: '缺少订单号'
});
if (typeof(options.type) == 'undefined') {
this.type = ''
} else {
this.type = options.type
}
this.orderId = options.orderId;
if (this.isLogin) {
this.getExpress();
this.get_host_product();
}
},
onPageScroll(object) {
if (object.scrollTop > 100) {
this.pageScrollStatus = true;
} else if (object.scrollTop < 100) {
this.pageScrollStatus = false;
}
// #ifdef MP
if (object.scrollTop > 50) {
this.isScrolling = true;
this.iconColor = '#333333';
} else if (object.scrollTop < 50) {
this.isScrolling = false;
this.iconColor = '#FFFFFF';
}
// #endif
uni.$emit('scroll');
},
onShow() {
uni.removeStorageSync('form_type_cart');
if (!this.isLogin) {
toLogin()
}
},
methods: {
// 授权关闭
authColse: function(e) {
this.isShowAuth = e
},
/**
* 授权回调
*/
onLoadFun: function() {
this.getExpress();
this.get_host_product();
this.isShowAuth = false;
},
copyOrderId: function() {
uni.setClipboardData({
data: this.orderInfo.delivery_id
});
},
getExpress: function() {
let that = this;
express(that.orderId, this.type).then(function(res) {
that.$set(that, 'product', res.data.order.cartInfo || []);
that.$set(that, 'orderInfo', res.data.order);
that.$set(that, 'expressList', res.data.express || []);
}).catch((error) => {
this.$util.Tips({
title: error
});
});
},
/**
* 获取我的推荐
*/
get_host_product: function() {
let that = this;
getProductHot().then(function(res) {
that.$set(that, 'hostProduct', res.data);
});
},
checkShowMore() {
this.showMore = !this.showMore
},
goPage(type, url) {
if (type == 1) {
uni.navigateTo({
url
})
} else if (type == 2) {
uni.switchTab({
url
})
} else if (type == 3) {
uni.navigateBack();
}
},
}
}
</script>
<style scoped lang="scss">
.safe-area-inset-bottom {
height: 0;
height: constant(safe-area-inset-bottom);
height: env(safe-area-inset-bottom);
}
.header_bg {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 369rpx;
background: linear-gradient(270deg, $gradient-primary-admin 0%, $primary-admin 100%);
}
.white_jianbian {
height: 180rpx;
background: linear-gradient(0deg, #F5F5F5 0%, rgba(245, 245, 245, 0) 100%);
}
.light {
background: rgba(255, 255, 255, 0.9);
}
.express_box {
padding-top: 30rpx;
}
.copy_btn {
width: 112rpx;
height: 34rpx;
background: #F5F5F5;
border-radius: 20rpx;
text-align: center;
line-height: 34rpx;
}
.city-box {
&:before {
content: '';
width: 1px;
height: 64rpx;
background-color: #eee;
position: absolute;
top: 40rpx;
left: 0;
}
}
.more-text {
position: absolute;
left: 40rpx;
bottom: -12rpx;
&:before {
content: '';
width: 14rpx;
height: 14rpx;
border-radius: 50%;
background-color: #ddd;
position: absolute;
left: -26rpx;
top: 8rpx;
}
}
.logisticsCon .item {
padding: 0 20rpx;
position: relative;
}
.logisticsCon .item .circular {
width: 14rpx;
height: 14rpx;
border-radius: 50%;
position: absolute;
left: 14rpx;
background-color: #ddd;
}
.logisticsCon .item .circular.on {
width: 40rpx;
height: 40rpx;
background-color: $primary-admin;
left: 0;
}
.logisticsCon .item .text.on-font {
color: $primary-admin;
}
.logisticsCon .item .text .data.on-font {
color: $primary-admin;
}
.logisticsCon .item .text {
font-size: 26rpx;
color: #666;
width: 615rpx;
border-left: 1rpx solid #e6e6e6;
padding: 0 0 40rpx 38rpx;
}
.logisticsCon .item .text .data {
font-size: 24rpx;
color: #999;
margin-top: 10rpx;
}
.logisticsCon .item .text .data .time {
margin-left: 15rpx;
}
.z-99 {
z-index: 99;
}
.product~.product {
margin-top: 20rpx;
}
</style>

View File

@@ -0,0 +1,87 @@
<template>
<view class="container">
<view class="panel">
<view class="img-box">
<image v-if="id" src="../static/result2.png" class="image"></image>
<image v-else src="../static/result1.png" class="image"></image>
<view v-if="id">订单已全部核销</view>
<view v-else>暂无待核销订单</view>
</view>
<view class="btn-box">
<navigator v-if="id" class="btn" :url="'/pages/admin/orderDetail/index?id='+id" hover-class="none">订单详情</navigator>
<navigator class="btn" url="/pages/admin/work/index" hover-class="none">返回工作台</navigator>
</view>
</view>
</view>
</template>
<script>
// import Name from './components/Name.vue'
import {
HTTP_REQUEST_URL
} from '@/config/app';
export default {
components: {
// Name
},
data() {
return {
imgHost: HTTP_REQUEST_URL,
id: 0
}
},
onLoad(option) {
this.id = option.id || 0;
},
}
</script>
<style lang="scss" scoped>
.container {
padding: 40rpx 20rpx;
.panel {
padding: 64rpx 105rpx 98rpx;
border-radius: 24rpx;
background: #FFFFFF;
}
.img-box {
text-align: center;
font-size: 36rpx;
line-height: 50rpx;
color: #333333;
}
.image {
width: 173rpx;
height: 163rpx;
margin-bottom: 34rpx;
}
.btn-box {
margin-top: 60rpx;
}
.btn {
height: 88rpx;
border: 1rpx solid $primary-admin;
border-radius: 44rpx;
text-align: center;
font-weight: 500;
line-height: 86rpx;
color: $primary-admin;
transform: rotateZ(360deg);
+.btn {
margin-top: 24rpx;
}
&:first-child {
background: $primary-admin;
color: #FFFFFF;
}
}
}
</style>

511
pages/admin/order/index.vue Normal file
View File

@@ -0,0 +1,511 @@
<template>
<view class="pagebox">
<!-- #ifdef MP || APP-PLUS -->
<NavBar titleText="数据统计" :iconColor="iconColor" :textColor="iconColor" :isScrolling="isScrolling" showBack></NavBar>
<!-- #endif -->
<view class="headerBg">
<view :style="{ height: `${getHeight.barTop}px` }"></view>
<view :style="{ height: `${getHeight.barHeight}px` }"></view>
<view class="inner"></view>
</view>
<view class="order-index" ref="container">
<view class="header">
<view class="">销售额(元)</view>
<view class="money">{{ after_price }}</view>
<view class="info">
较昨日同比增长:{{ increase_time_status == 1 ? '' : '-' }}{{ growth_rate }}%
<text :class="['iconfont', increase_time_status == 1 ? 'icon-ic_up2' : 'icon-ic_down2']"></text>
</view>
<view class="picker">
<picker mode="selector" :range="array" @change="bindPickerChange">
<view>{{ array[index] }}<text class="iconfont icon-ic_downarrow"></text></view>
</picker>
</view>
</view>
<view class="wrapper">
<view class="list acea-row">
<view class="item">
<view class="num">{{ after_number }}</view>
<view>订单数</view>
</view>
<view class="item">
<view class="num">{{ after_pay_number }}</view>
<view>支付人数</view>
</view>
<view class="item">
<view class="num">{{ today_visits }}</view>
<view>浏览量</view>
</view>
</view>
</view>
<div class="chart">
<view class="title">
销售订单趋势图
</view>
<canvas canvas-id="canvasMix" id="canvasMix" class="charts" width="680" disable-scroll @touchstart="touchMix" @touchmove="moveMix" @touchend="touchEndMix">
<!-- <cover-view class="cover-view"></cover-view> -->
</canvas>
</div>
<view class="public-wrapper">
<view class="title">
详细数据
</view>
<view class="nav acea-row row-between-wrapper">
<view class="data">日期</view>
<view class="browse">订单数</view>
<view class="turnover">成交额</view>
<view class="visit">浏览量</view>
</view>
<view class="conter">
<view class="item acea-row row-between-wrapper" v-for="(item, index) in list" :key="index">
<view class="data">{{ item.time }}</view>
<view class="browse">{{ item.count }}</view>
<view class="turnover">¥ {{ item.price }}</view>
<view class="visit">{{ item.visit }}</view>
</view>
</view>
</view>
<Loading :loaded="loaded" :loading="loading"></Loading>
</view>
<view class="safe-area-inset-bottom"></view>
</view>
</template>
<script>
let _self;
let canvaMix = null;
import {
getStatisticsInfo,
getStatisticsMonth,
getOrderTime,
getOrderChart,
} from "@/api/admin";
import Loading from '@/components/Loading/index.vue'
import uCharts from '../components/ucharts/ucharts'
// #ifdef MP || APP-PLUS
import NavBar from '@/components/NavBar.vue';
// #endif
export default {
name: 'adminOrder',
components: {
Loading,
// #ifdef MP ||APP-PLUS
NavBar,
// #endif
},
data() {
return {
iconColor: '#FFFFFF',
isScrolling: false,
getHeight: this.$util.getWXStatusHeight(),
census: {},
list: [],
where: {
page: 1,
limit: 15
},
loaded: false,
loading: false,
after_price: 0, // 销售额
after_number: 0, // 订单数
after_pay_number: 0, // 支付人数
today_visits: 0, // 浏览量
growth_rate: 0, // 增长率
increase_time: 0, // 较昨日同比增长
increase_time_status: 1, // 1 增长 2 减少
cWidth: '',
cHeight: '',
pixelRatio: 1,
textarea: '',
index: 0,
array: ['今天', '近7天', '近30天'],
arrays: [1, 7, 30],
}
},
onShow() {
_self = this;
this.cWidth = uni.upx2px(680);
this.cHeight = uni.upx2px(500);
this.getOrderTime();
this.getOrderChart();
this.getIndex();
this.getList();
// this.$scroll(this.$refs.container, () => {
// !this.loading && this.getList();
// });
},
onPageScroll(e) {
// #ifdef MP
if (e.scrollTop > 50) {
this.isScrolling = true;
this.iconColor = '#333333';
} else if (e.scrollTop < 50) {
this.isScrolling = false;
this.iconColor = '#FFFFFF';
}
// #endif
},
beforeMount() {
canvaMix = null
},
methods: {
bindPickerChange: function(e) {
console.log('picker发送选择改变,携带值为', e.detail.value)
this.index = e.detail.value
this.getOrderTime();
this.getOrderChart();
},
getOrderTime() {
getOrderTime({
type: this.arrays[this.index],
}).then(res => {
const {
after_number,
after_pay_number,
after_price,
today_visits,
growth_rate,
increase_time,
increase_time_status,
} = res.data;
this.after_number = after_number;
this.after_pay_number = after_pay_number;
this.after_price = after_price;
this.today_visits = today_visits;
this.growth_rate = growth_rate;
this.increase_time = increase_time;
this.increase_time_status = increase_time_status;
});
},
getOrderChart() {
getOrderChart({
type: this.arrays[this.index],
}).then(res => {
const data = res.data;
let Mix = {
categories: [],
series: []
};
let series = [{
"name": '销售额',
"type": "line",
"data": [],
}];
data.forEach(({
num,
price,
time
}) => {
series[0].data.push(price);
Mix.categories.push(time);
});
Mix.series = series;
this.chartData = data;
if (canvaMix) {
canvaMix.updateData(Mix);
} else {
this.showLineA("canvasMix", Mix);
}
});
},
// 创建charts
showLineA(canvasId, chartData) {
let _self = this
canvaMix = new uCharts({
$this: _self,
canvasId: canvasId,
type: 'line',
fontSize: 11,
padding: [5, 5, 0, 5],
legend: {
show: true,
position: 'bottom',
float: 'center',
padding: 5,
lineHeight: 11,
margin: 6,
},
background: '#FFFFFF',
pixelRatio: _self.pixelRatio,
categories: chartData.categories,
series: chartData.series,
animation: true,
enableScroll: true, //开启图表拖拽功能
xAxis: {
disableGrid: false,
type: 'grid',
gridType: 'dash',
itemCount: 6,
scrollShow: true,
scrollAlign: 'left',
},
yAxis: {
data: [{
calibration: true,
position: 'left',
title: '销售额(元)',
titleFontSize: 12,
format: (val) => {
return val.toFixed(0)
}
}, ],
showTitle: true,
gridType: 'dash',
dashLength: 4,
splitNumber: 7,
},
width: _self.cWidth * _self.pixelRatio,
height: _self.cHeight * _self.pixelRatio,
dataLabel: true,
dataPointShape: true,
});
},
touchMix(e) {
canvaMix.scrollStart(e);
},
moveMix(e) {
canvaMix.scroll(e);
},
touchEndMix(e) {
var index = canvaMix.getCurrentDataIndex(e);
canvaMix.scrollEnd(e);
//下面是toolTip事件,如果滚动后不需要显示,可不填写
canvaMix.touchLegend(e);
canvaMix.showToolTip(e, {
textList: [{
text: this.chartData[index].time,
color: null
},
{
text: "销售额:" + this.chartData[index].price,
color: "#1890FF"
},
{
text: "订单量:" + this.chartData[index].num,
color: "#91CB74"
}
]
});
},
getIndex: function() {
var that = this;
getStatisticsInfo().then(
res => {
that.census = res.data;
},
err => {
that.$util.Tips({
title: err
})
}
);
},
getList: function() {
var that = this;
if (that.loading || that.loaded) return;
that.loading = true;
getStatisticsMonth(that.where).then(
res => {
that.loading = false;
that.loaded = res.data.length < that.where.limit;
that.list.push.apply(that.list, res.data);
that.where.page = that.where.page + 1;
},
error => {
that.$util.Tips({
title: error
})
},
300
);
}
},
onReachBottom() {
this.getList()
}
}
</script>
<style lang="scss" scoped>
.pagebox {
position: relative;
overflow: hidden;
}
.safe-area-inset-bottom {
height: 0;
height: constant(safe-area-inset-bottom);
height: env(safe-area-inset-bottom);
}
.headerBg {
position: absolute;
top: 0;
left: -25%;
width: 150%;
border-bottom-right-radius: 100%;
border-bottom-left-radius: 100%;
background: linear-gradient(270deg, $gradient-primary-admin 0%, $primary-admin 100%);
.inner {
height: 356rpx;
}
}
/*订单首页*/
.order-index {
position: relative;
padding: 0 20rpx;
}
.order-index .header {
position: relative;
padding: 24rpx 0 40rpx 20rpx;
font-size: 28rpx;
line-height: 40rpx;
color: #FFFFFF;
.picker {
position: absolute;
top: 24rpx;
right: 0;
height: 48rpx;
padding: 0 20rpx;
border-radius: 24rpx;
background: rgba(255, 255, 255, 0.3);
text-align: center;
font-size: 24rpx;
line-height: 48rpx;
color: #FFFFFF;
.iconfont {
margin-left: 10rpx;
font-size: 24rpx;
}
}
}
.order-index .header .money {
margin-top: 26rpx;
font-family: SemiBold;
font-size: 80rpx;
line-height: 80rpx;
}
.order-index .header .info {
margin-top: 30rpx;
.iconfont {
margin-left: 6rpx;
font-size: 28rpx;
}
}
.order-index .wrapper {
background-color: #fff;
border-radius: 24rpx;
}
.order-index .wrapper .list .item {
flex: 1;
padding: 36rpx 0 26rpx;
text-align: center;
font-size: 24rpx;
line-height: 34rpx;
color: #999;
}
.order-index .wrapper .list .item .num {
margin-bottom: 8rpx;
font-family: SemiBold;
font-size: 36rpx;
color: #333;
}
.public-wrapper .title {
font-weight: 500;
font-size: 30rpx;
line-height: 42rpx;
color: #333333;
padding: 32rpx 0 40rpx 24rpx;
}
.public-wrapper {
background-color: #fff;
border-radius: 24rpx;
margin-top: 20rpx;
}
.public-wrapper .nav {
padding: 0 40rpx;
line-height: 34rpx;
font-size: 24rpx;
color: #999;
}
.public-wrapper .data {
flex: 1;
text-align: left;
}
.public-wrapper .browse {
flex: 1;
// text-align: center;
}
.public-wrapper .turnover {
flex: 1;
// text-align: center;
}
.public-wrapper .visit {
flex: 1;
text-align: right;
}
.public-wrapper .conter {
padding: 0 40rpx;
}
.public-wrapper .conter .item {
border-bottom: 1px solid #F1F1F1;
height: 74rpx;
font-size: 24rpx;
}
.chart {
border-radius: 24rpx;
margin-top: 20rpx;
background: #FFFFFF;
.title {
padding: 32rpx 0 16rpx 24rpx;
font-weight: 500;
font-size: 30rpx;
line-height: 42rpx;
color: #333333;
}
.chart-title {
padding: 40rpx 0 6rpx 42rpx;
font-size: 22rpx;
line-height: 26rpx;
color: #999999;
}
.charts {
margin: 0 auto;
width: 680rpx;
height: 514rpx;
}
}
.cover-view {
position: fixed;
top: 0;
right: 0;
bottom: 0;
left: 0;
}
</style>

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,508 @@
<template>
<view :style="colorStyle">
<view class="OrderCancellation">
<view class="header"></view>
<view class="whiteBg" v-if="tabOn == 2">
<view class="input">
<input type="number" placeholder="请输入" v-model="verify_code" />
</view>
<view class="bnt" @click="codeChange">
<text class="iconfont icon-ic_search"></text>
</view>
</view>
<view v-if="tabOn == 1" class="scan" @click="scanCode">
<text class="iconfont icon-ic_Scan"></text>
</view>
<view class="tabbar-box acea-row">
<view class="item" :class="{ on: tabOn == 1 }" @click="onTab(1)">
<view class="bg"></view>
<view class="inner"><text class="iconfont icon-ic_Scan"></text>扫码核销</view>
</view>
<view class="item" :class="{ on: tabOn == 2 }" @click="onTab(2)">
<view class="bg"></view>
<view class="inner"><text class="iconfont icon-ic_edit"></text>手动输入</view>
</view>
</view>
</view>
<view v-if="iShidden">
<view class="WriteOff">
<view class="pictrue">
<image :src="orderInfo.image" />
</view>
<view class="num acea-row row-center-wrapper">
<text>{{ orderInfo.order_id }}</text>
<view class="views" @click='goOrderDetails(orderInfo.order_id,orderInfo.order_type)'>查看<text class='iconfont icon-jiantou views-jian'></text></view>
</view>
<view class="tip">确定要核销此订单吗?</view>
<view class="sure" @click="confirm">确定核销</view>
<view class=" cancel" @click="cancel">取消</view>
</view>
<view class="mask"></view>
</view>
</view>
</template>
<script>
import {
orderVerific
} from "@/api/admin";
import colors from '@/mixins/color.js';
import {
toLogin
} from '@/libs/login.js';
import {
mapGetters
} from 'vuex';
export default {
mixins: [colors],
data() {
return {
iShidden: false,
verify_code: '',
isWeixin: '',
orderInfo: {},
tabOn: 1,
auth: 1,
}
},
computed: mapGetters(['isLogin']),
onLoad(options) {
// #ifdef H5 || APP-PLUS
this.isWeixin = this.$wechat.isWeixin();
// #endif
// #ifdef MP
if (options.scene) {
options = this.$util.getUrlParams(decodeURIComponent(options.scene));
}
// #endif
const {
auth,
code
} = options;
this.auth = auth || 1;
this.verify_code = code || '';
},
onShow() {
if (this.isLogin) {
if (this.auth == 3) {
this.codeChange();
}
} else {
toLogin();
}
},
methods: {
/**
* 去订单详情
*/
goOrderDetails: function(id, type) {
if (type == 'integral') {
uni.navigateTo({
url: '/pages/points_mall/integral_order_details?order_id=' + id
});
} else {
uni.navigateTo({
url: '/pages/admin/orderDetail/index?id=' + id + '&goname=look'
});
}
},
// 立即核销
codeChange: function() {
let self = this
let ref = /^[0-9]*$/;
if (!this.verify_code) return self.$util.Tips({
title: '请输入核销码'
});
if (!ref.test(this.verify_code)) return self.$util.Tips({
title: '请输入正确的核销码'
});
self.$util.Tips({
title: '查询中'
});
setTimeout(() => {
orderVerific(this.verify_code, this.auth)
.then(res => {
let auth = res.data.auth;
self.orderInfo = res.data
// self.iShidden = true
if (res.data.is_order_code) {
if (res.data.product_type) {
uni.navigateTo({
url: '/pages/admin/writeOffCard/index?id=' + res.data.data[0].id
})
} else {
if (res.data.data[0].status == 2) {
uni.navigateTo({
url: '/pages/admin/offOrderResult/index?id=' + res.data.data[0].order_id
})
} else {
uni.navigateTo({
url: '/pages/admin/distribution/scanning/detail/index?auth=' + auth + '&id=' + res.data.data[0].id + '&let=' + res.data.data.length +
'&code=' +
this
.verify_code
})
}
}
} else {
if (res.data.product_type) {
} else {
if (res.data.data.length) {
// 跳转多订单核销页
uni.navigateTo({
url: '/pages/admin/distribution/scanning/index?auth=' + auth + '&code=' + this.verify_code
})
} else {
// 跳转结果页
uni.navigateTo({
url: '/pages/admin/offOrderResult/index'
})
}
}
}
})
.catch(res => {
self.verify_code = ''
return self.$util.Tips({
title: res
});
});
}, 800);
},
// 扫码核
scanCode() {
var self = this;
// #ifdef MP || APP
uni.scanCode({
success(res) {
let path = decodeURIComponent(res.path);
self.verify_code = path.split('code=')[1];
self.codeChange();
},
})
// #endif
//#ifdef H5
this.$wechat.wechatEvevt('scanQRCode', {
needResult: 1,
scanType: ["qrCode", "barCode"]
}).then(res => {
let result = res.resultStr;
if (result.includes(',')) {
result = result.split(",")[1]
}
this.verify_code = result
this.codeChange();
});
//#endif
},
/**
* 确定销码
*/
confirm: function() {
let self = this
orderVerific(this.verify_code, 1)
.then(res => {
self.verify_code = ''
self.iShidden = false
self.$util.Tips({
title: res.msg
});
})
.catch(res => {
self.$util.Tips({
title: res
});
});
},
/**
* 取消
*/
cancel: function() {
this.iShidden = false
},
onTab(value) {
this.tabOn = value;
}
}
}
</script>
<style lang="scss">
.OrderCancellation {
position: absolute;
width: 100%;
overflow: hidden;
}
.OrderCancellation .header {
position: absolute;
top: 0;
left: -25%;
width: 150%;
height: 660rpx;
border-bottom-right-radius: 100%;
border-bottom-left-radius: 100%;
background: #FFFFFF;
}
.OrderCancellation {
// width: 100%;
// height: 100%;
// background: #fff;
overflow: hidden;
}
.OrderCancellation .whiteBg {
position: relative;
width: 540rpx;
height: 120rpx;
border-radius: 60rpx;
margin: 250rpx auto 416rpx;
background: #F5F5F5;
}
.OrderCancellation .whiteBg .input {
height: 100%;
}
.OrderCancellation .whiteBg .input input {
font-size: 32rpx;
color: #333333;
height: 100%;
text-align: center;
line-height: 120rpx;
padding: 0 104rpx;
box-sizing: border-box;
}
.OrderCancellation .whiteBg .input .input-placeholder {
color: #CCCCCC;
}
.OrderCancellation .whiteBg .bnt {
position: absolute;
top: 20rpx;
right: 24rpx;
width: 80rpx;
height: 80rpx;
border-radius: 40rpx;
background: $primary-admin;
text-align: center;
line-height: 80rpx;
}
.OrderCancellation .whiteBg .bnt .iconfont {
font-size: 32rpx;
color: #FFFFFF;
}
.OrderCancellation .scan {
position: relative;
width: 400rpx;
height: 400rpx;
border-radius: 200rpx;
margin: 110rpx auto 0;
background: $primary-admin;
box-shadow: 0rpx 4rpx 32rpx 0rpx $light-primary-admin;
text-align: center;
line-height: 400rpx;
}
.OrderCancellation .scan .iconfont {
font-size: 120rpx;
color: #FFFFFF;
}
.OrderCancellation .scan image {
width: 100%;
height: 100%;
display: block;
}
.WriteOff {
width: 560rpx;
height: 800rpx;
background-color: #fff;
border-radius: 20rpx;
position: fixed;
top: 50%;
left: 50%;
margin-top: -400rpx;
margin-left: -280rpx;
z-index: 99;
padding-top: 55rpx;
}
.WriteOff .pictrue {
width: 340rpx;
height: 340rpx;
margin: 0 auto;
}
.WriteOff .pictrue image {
width: 100%;
height: 100%;
display: block;
border-radius: 10rpx;
}
.WriteOff .num {
font-size: 30rpx;
color: #666;
margin: 28rpx 0 30rpx 0;
}
.WriteOff .num .see {
font-size: 16rpx;
color: #fff;
border-radius: 4rpx;
background-color: #c68937;
padding-left: 5rpx;
margin-left: 12rpx;
}
.WriteOff .num .see .iconfont {
font-size: 15rpx;
}
.WriteOff .tip {
font-size: 36rpx;
color: #282828;
text-align: center;
border-top: 1px dashed #ccc;
padding-top: 40rpx;
position: relative;
}
.WriteOff .tip:after {
content: "";
position: absolute;
width: 25rpx;
height: 25rpx;
border-radius: 50%;
background-color: #7f7f7f;
right: -12.5rpx;
top: -12.5rpx;
}
.WriteOff .tip:before {
content: "";
position: absolute;
width: 25rpx;
height: 25rpx;
border-radius: 50%;
background-color: #7f7f7f;
left: -12.5rpx;
top: -12.5rpx;
}
.WriteOff .sure {
font-size: 32rpx;
color: #fff;
text-align: center;
line-height: 82rpx;
height: 82rpx;
width: 460rpx;
border-radius: 41rpx;
margin: 40rpx auto 0 auto;
background-image: linear-gradient(to right, #f67a38 0%, #f11b09 100%);
background-color: $primary-admin;
}
.WriteOff .cancel {
line-height: 82rpx;
color: #999;
height: 82rpx;
width: 460rpx;
border-radius: 41rpx;
margin: 10rpx auto 0 auto;
text-align: center;
}
.WriteOff .cancel {}
.views {
font-size: 18rpx;
background: #C68937;
border-radius: 4px;
color: #fff;
padding: 5rpx 2rpx 5rpx 8rpx;
margin-left: 10rpx;
}
.views-jian {
font-size: 10px;
}
.tabbar-box {
width: 516rpx;
margin: 276rpx auto 0;
.item {
position: relative;
flex: 1;
z-index: 5;
min-width: 0;
height: 80rpx;
border-radius: 40rpx 0 0 40rpx;
overflow: hidden;
&:last-child {
border-radius: 0 40rpx 40rpx 0;
.bg {
height: 68rpx;
top: 0;
border-radius: 12rpx 0 0 12rpx;
transform-origin: center top;
transform: perspective(80rpx) rotateX(10deg) translateX(20rpx);
}
}
&.on {
.bg {
background: $primary-admin;
}
.inner {
color: #FFFFFF;
}
}
}
.bg {
position: absolute;
bottom: 0;
z-index: 2;
width: 100%;
height: 68rpx;
border-radius: 0 12rpx 12rpx 0;
background: #FFFFFF;
transform-origin: center bottom;
transform: perspective(80rpx) rotateX(-10deg) translateX(-20rpx);
}
.inner {
position: absolute;
z-index: 3;
width: 260rpx;
height: 80rpx;
text-align: center;
line-height: 80rpx;
font-weight: 500;
font-size: 28rpx;
color: #333333;
}
.iconfont {
vertical-align: middle;
margin-right: 16rpx;
font-size: 32rpx;
}
}
</style>

View File

@@ -0,0 +1,307 @@
<template>
<view class="refund">
<view class="money-section">
<view class="acea-row row-middle item">
<view class="">退款金额</view>
<input v-model="refundMoney" class="input" type="text" />
<text class="iconfont icon-ic_edit"></text>
</view>
<view class="acea-row row-middle item">
<view class="">退款类型</view>
<view class="acea-row row-right radio-group">
<view class="acea-row row-middle radio-item" :class="{ on: !isSplit}" @click="refundTypeChange(0)">
<text class="iconfont" :class="isSplit?'icon-ic_unselect':'icon-ic_Selected'"></text>整单退款
</view>
<view class="acea-row row-middle radio-item" :class="{ on: isSplit}" @click="refundTypeChange(1)">
<text class="iconfont" :class="isSplit?'icon-ic_Selected':'icon-ic_unselect'"></text>分单退款
</view>
</view>
</view>
</view>
<splitOrder v-if="isSplit" :splitGoods="splitGoods" :select_all="false" @getList="getList"></splitOrder>
<view class="footer acea-row row-middle">
<view class="all acea-row row-middle" v-if="isSplit" @click="allChange">
<text class="iconfont" :class="isAll?'icon-a-ic_CompleteSelect':'icon-ic_unselect'"></text>
全选
</view>
<view class="btn-box">
<view class="btn" :style="{ width: isSplit?'auto':'100%'}" @click="openRefund">
确认
<text v-if="isSplit">({{ numTotal }})</text>
</view>
</view>
</view>
</view>
</template>
<script>
import {
getAdminOrderDetail,
orderSplitInfo,
openRefund,
} from '@/api/admin.js';
import splitOrder from '@/components/splitOrder/index.vue';
export default {
components: {
splitOrder,
},
data() {
return {
refundMoney: 0,
isSplit: 0,
isAll: false,
splitGoods: [],
goodsChecked: [],
cart_ids: [],
}
},
computed: {
total() {
return this.goodsChecked.reduce((total, item) => {
return this.$util.$h.Add(total, this.$util.$h.Mul(item.refundPrice, item.surplus_num));
}, 0);
},
numTotal() {
return this.goodsChecked.reduce((total, {
surplus_num,
}) => {
return this.$util.$h.Add(total, surplus_num);
}, 0);
},
},
watch: {
total(newValue, oldValue) {
this.refundMoney = newValue
},
},
onLoad(option) {
this.order_id = option.id;
this.listId = option.listId;
this.getIndex();
// this.splitList();
},
methods: {
allChange() {
this.isAll = !this.isAll;
this.cart_ids = [];
this.goodsChecked = [];
for (let i = 0; i < this.splitGoods.length; i++) {
this.splitGoods[i].checked = this.isAll;
if (this.splitGoods[i].checked) {
this.goodsChecked.push(this.splitGoods[i]);
this.cart_ids.push(this.splitGoods[i].id);
}
}
},
refundTypeChange(value) {
this.isSplit = value;
if (value) {
this.goodsChecked = []
} else {
this.goodsChecked = this.splitGoods
}
},
splitList() {
orderSplitInfo(this.listId).then(res => {
let list = res.data;
list.forEach((item) => {
item.checked = false
item.numShow = item.surplus_num
})
// this.splitGoods = list;
}).catch(err => {
return this.$util.Tips({
title: err
});
})
},
getIndex() {
let that = this;
let obj = '';
getAdminOrderDetail(that.order_id).then(res => {
const {
cartInfo
} = res.data;
let list = cartInfo.map(item => {
return {
id: item.id,
checked: false,
numShow: item.cart_num - item.refund_num,
surplus_num: item.cart_num - item.refund_num,
cart_info: item,
refundPrice: this.$util.$h.Div(item.refund_price, item.cart_num),
};
});
this.splitGoods = list;
this.goodsChecked = list;
}).catch(err => {
that.$util.Tips({
title: err.msg
});
})
},
getList(val) {
let that = this;
let goodsChecked = [];
let cart_ids = [];
for (let i = 0; i < val.length; i++) {
if (val[i].checked) {
goodsChecked.push(val[i]);
cart_ids.push(val[i].id);
}
}
this.goodsChecked = goodsChecked;
this.cart_ids = cart_ids;
this.isAll = this.goodsChecked.length == this.splitGoods.length;
},
openRefund() {
let cart_ids = [];
let data = {
refund_price: this.refundMoney,
type: 1,
is_split_order: this.isSplit,
};
cart_ids = this.goodsChecked.map(({
id,
surplus_num
}) => {
return {
cart_id: id,
cart_num: surplus_num
}
});
data.cart_ids = cart_ids;
openRefund(this.listId, data).then(res => {
if (res.data.order_id) {
// const pages = getCurrentPages();
// pages.splice(pages.length - 2, 2)
this.$util.Tips({
title: res.msg
}, {
tab: 4,
url: '/pages/admin/orderDetail/index?id=' + res.data.order_id + '&types=',
});
} else {
this.$util.Tips({
title: res.msg
}, {
tab: 3,
url: 1,
});
}
}).catch(err => {
this.$util.Tips({
title: err
});
})
},
},
}
</script>
<style lang="scss" scoped>
.refund {
padding: 22rpx 20rpx;
}
.money-section {
padding: 12rpx 0;
border-radius: 24rpx;
background: #FFFFFF;
.item {
height: 80rpx;
padding: 0 24rpx;
font-size: 28rpx;
color: #333333;
}
.input {
flex: 1;
height: 80rpx;
text-align: right;
font-family: Regular;
font-size: 36rpx;
color: #FF7E00;
}
.icon-ic_edit {
margin-left: 8rpx;
font-size: 32rpx;
color: #999999;
}
.radio-group {
flex: 1;
}
.radio-item {
font-size: 28rpx;
color: #999999;
+.radio-item {
margin-left: 48rpx;
}
.iconfont {
margin-right: 12rpx;
font-size: 32rpx;
}
&.on {
color: #333333;
.iconfont {
color: #2A7EFB;
}
}
}
}
.footer {
position: fixed;
bottom: 0;
left: 0;
width: 100%;
padding: 16rpx 20rpx 16rpx 32rpx;
padding-bottom: calc(16rpx + constant(safe-area-inset-bottom));
padding-bottom: calc(16rpx + env(safe-area-inset-bottom));
background: #FFFFFF;
.btn {
display: inline-block;
height: 64rpx;
padding: 0 40rpx;
border-radius: 32rpx;
background: #2A7EFB;
font-weight: 500;
font-size: 26rpx;
line-height: 64rpx;
color: #FFFFFF;
}
.all {
font-size: 26rpx;
color: #333333;
.iconfont {
margin-right: 12rpx;
font-size: 40rpx;
color: #CCCCCC;
&.icon-a-ic_CompleteSelect {
color: #2A7EFB;
}
}
}
.btn-box {
flex: 1;
text-align: right;
.btn {
text-align: center;
}
}
}
</style>

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,900 @@
<template>
<view class="pos-order-list" ref="container">
<!-- #ifdef MP || APP-PLUS -->
<NavBar titleText="售后订单" bagColor="#F5F5F5" :iconColor="iconColor" :textColor="iconColor" :isScrolling="isScrolling" showBack></NavBar>
<!-- #endif -->
<view class="searchCon acea-row">
<view class="search acea-row row-middle">
<text class="iconfont icon-ic_search"></text>
<input class="inputs" placeholder='请输入订单号/售后单号/快递单号/用户ID/手机号' placeholder-class='placeholder' confirm-type='search' name="search" v-model="where.order_id"
@confirm="searchSubmit"></input>
</view>
<view class="btn" @click="filterShow = true">
<text class="iconfont icon-ic_sort"></text>
</view>
</view>
<view class="nav acea-row row-around row-middle" id="nav" :style="{
top:getHeight.barTop+getHeight.barHeight+'px'
}">
<view class="item" :class="state == 5 ? 'on' : ''" @click="changeStatus(5)">
待处理
<image src="../static/adorn.png" v-if="state == 5"></image>
</view>
<view class="item" :class="state == 0 ? 'on' : ''" @click="changeStatus(0)">
待审核
<image src="../static/adorn.png" v-if="state == 0"></image>
</view>
<view class="item" :class="state == 2 ? 'on' : ''" @click="changeStatus(2)">
待退货
<image src="../static/adorn.png" v-if="state == 2"></image>
</view>
<view class="item" :class="state == 6 ? 'on' : ''" @click="changeStatus(6)">
已完成
<image src="../static/adorn.png" v-if="state == 6"></image>
</view>
</view>
<view class="list" v-if="list.length">
<view class="item" v-for="(item, index) in list" :key="index">
<view class="order-num acea-row row-between-wrapper" @click="toDetail(item)">
<view>
<view>售后单号:{{ item.order_id }}</view>
</view>
<view class="state" v-if="[0, 1, 2].includes(item.refund_type)">待审核</view>
<view class="state" v-if="[4, 5].includes(item.refund_type)">
待退货({{ item.apply_type == 2 ? '快递' : '到店' }})
</view>
<view class="state" v-if="[3, 6].includes(item.refund_type)">已完成</view>
</view>
<view class="pos-order-goods">
<view class="goods acea-row" @click="toDetail(item)">
<scroll-view class="picTxt scroll-view" scroll-x="true" v-if="item._info.length > 1">
<view class="pictrue" v-for="(val, key) in item._info" :key="key">
<image :src="val.cart_info.productInfo.attrInfo?val.cart_info.productInfo.attrInfo.image:val.cart_info.productInfo.image" />
</view>
</scroll-view>
<view class="picTxt" v-else>
<view class="acea-row" v-for="(val, key) in item._info" :key="key">
<view class="pictrue">
<image :src="val.cart_info.productInfo.attrInfo?val.cart_info.productInfo.attrInfo.image:val.cart_info.productInfo.image" />
</view>
<view class="text">
<view class="info line2">
<!-- <text v-if="val.cart_info.is_gift == 1" class="label">[赠品]</text> -->
{{ val.cart_info.productInfo.store_name }}
</view>
<view class="attr" v-if="val.cart_info.productInfo.attrInfo">
{{ val.cart_info.productInfo.attrInfo.suk }}
</view>
</view>
</view>
</view>
<view class="money">
<!-- <view class="x-money">¥{{ item.pay_price }}</view> -->
<BaseMoney :money="item.pay_price" symbolSize="20" integerSize="32" decimalSize="20"></BaseMoney>
<view class="num">共{{ item.total_num }}件</view>
<!-- <view class="y-money">
¥{{ val.cart_info.productInfo.ot_price }}
</view> -->
<!-- <view class="info" v-if="val.cart_info.refund_num && item._status._type !=-2">{{val.cart_info.refund_num}}件退款中</view> -->
</view>
</view>
</view>
<!-- <view class="public-total">
共{{ item.total_num }}件商品,实付款
<span class="money">¥{{ item.pay_price }}</span> ( 邮费 ¥{{
item.pay_postage
}}
)
</view> -->
<view class="operation acea-row row-between-wrapper">
<view v-if="item.apply_type == 1" class="more acea-row row-middle">
<text class="iconfont icon-ic_returnmoney"></text>仅退款
</view>
<view v-else-if="item.apply_type == 2 || item.apply_type == 3" class="more acea-row row-middle">
<text class="iconfont icon-ic_returnofgoods"></text>退货退款
</view>
<view class="acea-row row-middle">
<view class="btn" @click="modify(item, 1)">订单备注</view>
<view class="btn on" :class="openErp?'on':''" @click="modify(item,'2',1)" v-if="[1].includes(item.apply_type) && [0].includes(item.refund_type)">
退款审核
</view>
<view class="btn on" :class="openErp?'on':''" @click="modify(item,'2',0)" v-if="[2,3].includes(item.apply_type) && [0].includes(item.refund_type)">
退款审核
</view>
<view class="btn" v-if="[2].includes(item.apply_type) && [5].includes(item.refund_type)" @click="goLogistics(item)">查看物流</view>
<view class="btn on" v-if="[1,2,3].includes(item.apply_type) && [4,5].includes(item.refund_type)" @click="modify(item, 2, 1)">确认收货</view>
</view>
</view>
</view>
</view>
<emptyPage v-else title="暂无订单~" src="/statics/images/noOrder.gif"></emptyPage>
<Loading :loaded="loaded" :loading="loading"></Loading>
<PriceChange :change="change" :orderInfo="orderInfo" :isRefund="isRefund" v-on:statusChange="statusChange($event)" v-on:closechange="changeclose($event)" v-on:savePrice="savePrice"
:status="status"></PriceChange>
<view class="mask" v-if="filterShow" @click="filterShow = false"></view>
<view class="filter-popup" :class="{ on: filterShow }" :style="{
top:getHeight.barTop+getHeight.barHeight+'px'
}">
<view class="content">
<view class="item">
<view class="title">按退货类型</view>
<view class="acea-row list">
<view class="cell" v-for="(item, index) in dateList" :key="index" :class="{ on: item.val == where.apply_type }" @click="dateChange(item.val)">{{ item.label }}</view>
</view>
</view>
</view>
</view>
<home></home>
</view>
</template>
<script>
import {
getAdminOrderList,
setAdminOrderPrice,
setAdminOrderRemark,
setAdminRefundRemark,
setOfflinePay,
setOrderRefund,
orderRefundAgree,
adminRefundList,
} from "@/api/admin";
import {
erpConfig
} from "@/api/esp.js";
import Loading from '@/components/Loading/index'
import PriceChange from '../components/PriceChange/index.vue'
import emptyPage from '@/components/emptyPage.vue'
import NavBar from '@/components/NavBar.vue'
import {
isMoney
} from '@/utils/validate.js';
import {
HTTP_REQUEST_URL
} from '@/config/app';
export default {
name: "AdminOrderList",
components: {
Loading,
PriceChange,
emptyPage,
NavBar,
},
data() {
return {
getHeight: this.$util.getWXStatusHeight(),
iconColor: '#333333',
isScrolling: false,
top: 0,
navHeight: 0,
isFixed: false,
filterShow: false,
openErp: false,
current: "",
change: false,
types: 0,
where: {
order_id: '',
refundTypes: 5,
apply_type: '',
page: 1,
limit: 10,
},
list: [],
loaded: false,
loading: false,
orderInfo: {},
status: "",
state: 5,
isRefund: 0, //1是仅退款;0是退货退款
imgHost: HTTP_REQUEST_URL,
dateSelected: '',
dateList: [{
label: '全部',
val: '',
},
{
label: '退货退款',
val: '2',
},
{
label: '仅退款',
val: '1',
},
],
payList: [{
label: '全部',
val: '',
},
{
label: '微信支付',
val: '1'
},
{
label: '支付宝支付',
val: '4'
},
{
label: '余额抵扣',
val: '2'
},
{
label: '线下支付',
val: '3'
},
],
};
},
onLoad(option) {
let type = option.types;
this.getErpConfig();
},
onShow() {
this.init();
},
mounted() {
const query = uni.createSelectorQuery().in(this);
query.select("#nav").boundingClientRect((data) => {
this.top = data.top;
this.navHeight = data.height;
}).exec();
},
onPageScroll(option) {
// if (this.top >= option.scrollTop) {
// this.isFixed = false;
// } else {
// this.isFixed = true;
// }
},
methods: {
searchSubmit() {
},
statusChange(e) {
this.status = e;
},
goDelivery(item) {
if (this.openErp) return
uni.navigateTo({
url: '/pages/admin/delivery/index?id=' + item.order_id + '&listId=' + item.id + '&totalNum=' + item.total_num + '&orderStatus=' + item._status + '&comeType=1&productType=' +
item.product_type
})
},
getErpConfig() {
erpConfig().then(res => {
this.openErp = res.data.open_erp;
}).catch(err => {
this.$util.Tips({
title: err
})
})
},
// 获取数据
getIndex: function() {
let that = this;
if (that.loading || that.loaded) return;
that.loading = true;
let obj = adminRefundList(that.where);
obj.then(
res => {
that.loading = false;
that.loaded = res.data.length < that.where.limit;
that.list.push.apply(that.list, res.data);
that.where.page = that.where.page + 1;
},
err => {
that.$util.Tips({
title: err
})
}
);
},
// 初始化
init: function() {
this.list = [];
this.where.page = 1;
this.loaded = false;
this.loading = false;
this.getIndex();
this.current = "";
},
searchSubmit() {
this.init();
},
// 导航切换
changeStatus(val) {
if (this.state != val) {
this.state = val;
this.where.refundTypes = val;
this.init();
}
},
// 商品操作
modify: function(item, status, type) {
if (this.openErp && status != 1) return
this.change = true;
this.status = status.toString();
this.orderInfo = item;
if (status == 2) {
this.isRefund = type
}
},
changeclose: function(msg) {
this.change = msg;
this.orderInfo = {};
},
objOrderRefund(data) {
let that = this;
setOrderRefund(data).then(
res => {
that.change = false;
that.$util.Tips({
title: res.msg
});
that.init();
},
err => {
that.change = false;
that.$util.Tips({
title: err
});
}
);
},
async savePrice(opt) {
let that = this,
data = {},
price = opt.price,
refund_price = opt.refund_price,
refund_status = that.orderInfo.refund_status,
remark = opt.remark;
data.order_id = that.orderInfo.order_id;
if (that.status == 0) {
if (!isMoney(price)) {
return that.$util.Tips({
title: '请输入正确的金额'
});
}
data.price = price;
setAdminOrderPrice(data).then(
res => {
that.change = false;
that.$util.Tips({
title: '改价成功',
icon: 'success'
})
that.init();
},
err => {
that.change = false;
that.$util.Tips({
title: '改价失败',
icon: 'none'
})
}
);
} else if (that.status == 2) {
if (this.isRefund) {
// setOrderRefund(data).then(
// res => {
// that.change = false;
// that.$util.Tips({title: res.msg});
// that.init();
// },
// err => {
// that.change = false;
// that.$util.Tips({title: err});
// }
// );
if (!isMoney(refund_price)) {
return that.$util.Tips({
title: '请输入正确的金额'
});
}
data.price = refund_price;
data.type = opt.type;
this.objOrderRefund(data);
} else {
if (opt.type == 1) {
orderRefundAgree(this.orderInfo.id).then(res => {
that.change = false;
that.$util.Tips({
title: res.msg
});
that.init();
}).catch(err => {
that.change = false;
that.$util.Tips({
title: err
});
})
}
// else{
// data.type = opt.type;
// data.refuse_reason = opt.refuse_reason;
// this.objOrderRefund(data);
// }
if (opt.type == 2) {
data.type = opt.type;
data.refuse_reason = opt.refuse_reason;
this.objOrderRefund(data);
}
}
} else if (that.status == 8) {
data.type = opt.type;
data.refuse_reason = opt.refuse_reason;
this.objOrderRefund(data);
} else {
if (!remark) {
return this.$util.Tips({
title: '请输入备注'
})
}
data.remark = remark;
let obj = '';
if (that.where.status == -3) {
obj = setAdminRefundRemark(data);
} else {
obj = setAdminOrderRemark(data);
}
obj.then(
res => {
that.change = false;
this.$util.Tips({
title: res.msg,
icon: 'success'
})
that.init();
},
err => {
that.change = false;
that.$util.Tips({
title: err
});
}
);
}
},
toDetail(item) {
uni.navigateTo({
url: `/pages/admin/refundOrderDetail/index?id=${item.order_id}`
})
},
offlinePay: function(item) {
if (this.openErp) return
setOfflinePay({
order_id: item.order_id
}).then(
res => {
this.$util.Tips({
title: res.msg,
icon: "success"
});
this.init();
},
error => {
this.$util.Tips(error);
}
);
},
dateChange(value) {
this.filterShow = false;
this.where.apply_type = value;
this.init();
},
payChange(val) {
this.filterShow = false;
this.where.pay_type = val;
this.init();
},
goLogistics(orderInfo) {
uni.navigateTo({
url: '/pages/admin/logistics/index?type=refund&orderId=' + orderInfo.order_id
})
},
},
onReachBottom() {
this.getIndex()
}
}
</script>
<style lang="scss" scoped>
.pos-order-list {
padding-bottom: constant(safe-area-inset-bottom); ///兼容 IOS<11.2/
padding-bottom: env(safe-area-inset-bottom); ///兼容 IOS>11.2/
}
.searchCon {
padding: 10rpx 20rpx;
.search {
flex: 1;
height: 72rpx;
padding: 0 32rpx;
border-radius: 36rpx;
background: #FFFFFF;
.iconfont {
margin-right: 16rpx;
font-size: 32rpx;
color: #999999;
}
.inputs {
flex: 1;
font-size: 28rpx;
color: #333333;
}
.placeholder {
font-size: 26rpx;
color: #ccc;
}
}
.btn {
width: 72rpx;
height: 72rpx;
border-radius: 50%;
margin-left: 20rpx;
background: #FFFFFF;
text-align: center;
.iconfont {
font-size: 32rpx;
line-height: 72rpx;
color: #666666;
}
}
}
.pos-order-list .nav {
position: sticky;
top: 0;
right: 0;
left: 0;
z-index: 99;
background: #F5F5F5;
font-size: 26rpx;
line-height: 42rpx;
color: #333333;
.item {
position: relative;
padding: 28rpx 0;
image {
width: 14rpx;
height: 14rpx;
display: block;
position: absolute;
bottom: 20rpx;
right: -4rpx;
}
}
}
.pos-order-list .nav .item.on {
font-weight: 500;
font-size: 30rpx;
color: #2A7EFB;
}
.pos-order-list .list {
padding: 0 20rpx;
}
.pos-order-list .nothing {
margin-top: 120upx;
text-align: center;
color: #cfcfcf;
}
.pos-order-list .list .item {
padding: 32rpx 24rpx;
border-radius: 24rpx;
background-color: #fff;
}
.pos-order-list .list .item~.item {
margin-top: 20rpx;
}
.pos-order-list .list .item .order-num {
font-size: 28rpx;
line-height: 40rpx;
color: #333333;
}
.pos-order-list .list .item .order-num .state {
color: #FF7E00;
}
.pos-order-list .list .item .order-num .state.on {
font-size: 24rpx;
width: 150rpx;
text-align: right;
}
.pos-order-list .list .item .order-num .time {
font-size: 26upx;
font-weight: normal;
color: #999;
}
.pos-order-list .list .item .operation .more {
position: relative;
font-size: 26rpx;
color: #999999;
}
.pos-order-list .list .item .operation .more .iconfont {
margin-right: 12rpx;
font-size: 34rpx;
color: #2A7EFB;
}
.pos-order-list .list .item .operation .icon-gengduo {
font-size: 50upx;
color: #aaa;
}
.pos-order-list .list .item .operation .order .arrow {
width: 0;
height: 0;
border-left: 11upx solid transparent;
border-right: 11upx solid transparent;
border-top: 20upx solid #e5e5e5;
position: absolute;
left: 15upx;
bottom: -18upx;
}
.pos-order-list .list .item .operation .order .arrow:before {
content: '';
width: 0;
height: 0;
border-left: 7upx solid transparent;
border-right: 7upx solid transparent;
border-top: 20upx solid #fff;
position: absolute;
left: -7upx;
bottom: 0;
}
.pos-order-list .list .item .operation .order {
width: 200upx;
background-color: #fff;
border: 1px solid #eee;
border-radius: 10upx;
position: absolute;
top: -100upx;
z-index: 9;
}
.pos-order-list .list .item .operation .order .items {
height: 77upx;
line-height: 77upx;
text-align: center;
}
.pos-order-list .list .item .operation .order .items~.items {
border-top: 1px solid #f5f5f5;
}
.pos-order-list .list .item .operation .btn {
height: 56rpx;
padding: 0 24rpx;
border-radius: 28rpx;
border: 1rpx solid #CCCCCC;
font-size: 24rpx;
line-height: 54rpx;
color: #333333;
&.on {
color: #FFFFFF !important;
background-color: #2A7EFB !important;
border-color: #2A7EFB !important;
}
}
.pos-order-list .list .item .operation .btn~.btn {
margin-left: 16rpx;
}
.pos-order-list .list .item .operation .wait {
margin-left: 30rpx;
}
.pos-order-goods .goods {
padding: 26rpx 0;
}
.pos-order-goods .goods~.goods {
border-top: 1px dashed #e5e5e5;
}
.pos-order-goods .goods .picTxt {
flex: 1;
min-width: 0;
}
.pos-order-goods .goods .scroll-view {
box-sizing: border-box;
white-space: nowrap;
.pictrue {
display: inline-block;
+.pictrue {
margin-left: 16rpx;
}
}
}
.pos-order-goods .goods .picTxt .pictrue {
width: 136rpx;
height: 136rpx;
}
.pos-order-goods .goods .picTxt .pictrue image {
width: 100%;
height: 100%;
border-radius: 16rpx;
}
.pos-order-goods .goods .picTxt .text {
flex: 1;
min-width: 0;
padding-left: 20rpx;
}
.pos-order-goods .goods .picTxt .text .info {
font-size: 28rpx;
line-height: 40rpx;
color: #333333;
}
.pos-order-goods .goods .picTxt .text .info .label {
color: #ff4c3c;
}
.pos-order-goods .goods .picTxt .text .attr {
margin-top: 12rpx;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
font-size: 24rpx;
line-height: 34rpx;
color: #999999;
}
.pos-order-goods .goods .money {
padding-left: 16rpx;
text-align: right;
font-size: 28upx;
}
.pos-order-goods .goods .money .info {
margin-top: 18rpx;
font-size: 24rpx;
}
.pos-order-goods .goods .money .x-money {
color: #282828;
}
.pos-order-goods .goods .money .num {
margin-top: 10rpx;
font-size: 24rpx;
line-height: 34rpx;
color: #999999;
}
.pos-order-goods .goods .money .y-money {
color: #999;
text-decoration: line-through;
}
.public-total {
font-size: 28upx;
color: #282828;
border-top: 1px solid #eee;
height: 92upx;
line-height: 92upx;
text-align: right;
padding: 0 30upx;
background-color: #fff;
}
.public-total .money {
color: #ff4c3c;
}
.mask {
z-index: 900;
}
.filter-popup {
position: fixed;
top: 0;
left: 0;
z-index: 900;
width: 100%;
border-radius: 0 0 32rpx 32rpx;
background: #FFFFFF;
transform: translateY(-100%);
transition: transform 0.3s;
&.on {
transform: translateY(0);
}
.search-box {
padding: 10rpx 32rpx;
}
.search {
height: 58rpx;
padding: 0 32rpx;
border-radius: 29rpx;
background: #F5F5F5;
}
.iconfont {
font-size: 28rpx;
color: #999999;
}
.input {
flex: 1;
height: 58rpx;
padding-left: 16rpx;
font-size: 24rpx;
}
.content {
padding: 32rpx 30rpx 58rpx;
}
.item {
margin-top: 36rpx;
&:first-child {
margin-top: 0;
}
}
.title {
font-size: 28rpx;
line-height: 40rpx;
color: #333333;
}
.list {
padding: 0;
margin-right: -24rpx;
}
.cell {
width: 154rpx;
height: 56rpx;
border: 1rpx solid #F5F5F5;
border-radius: 28rpx;
margin: 24rpx 24rpx 0 0;
background: #F5F5F5;
text-align: center;
font-size: 24rpx;
line-height: 54rpx;
color: #333333;
&.on {
border-color: #2A7EFB;
background: #E9F2FE;
color: #2A7EFB;
}
}
}
</style>

Binary file not shown.

After

Width:  |  Height:  |  Size: 335 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 955 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 860 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 955 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.3 KiB

BIN
pages/admin/static/scan.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 191 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.7 KiB

View File

@@ -0,0 +1,251 @@
<template>
<base-drawer mode="bottom" :visible="visible" background-color="transparent" mask maskClosable @close="closeDrawer">
<view class="coupon rd-t-40rpx">
<view class="title">优惠券
<view class="close acea-row row-center-wrapper" @tap="closeDrawer">
<text class="iconfont icon-ic_close"></text>
</view>
</view>
<view class="search acea-row row-middle" v-if="num !=2">
<text class="iconfont icon-ic_search"></text>
<input class="inputs" placeholder='请输入优惠券名称' placeholder-class='placeholder' confirm-type='search' name="search"
v-model="keyword" @confirm="searchSubmit"></input>
</view>
<view class="list" v-if="couponList.length">
<scroll-view scroll-y="true" style="max-height: 800rpx;min-height: 500rpx;">
<view class="item acea-row row-middle" v-for="(item,index) in couponList" :key="index">
<view class="bg">
<view class="price" v-if="item.coupon_type==1">¥<text class="num">{{item.coupon_price}}</text></view>
<view class="price" v-else><text class="num">{{parseFloat(item.coupon_price)/10}}</text>折</view>
<view class="reduction">满{{item.use_min_price}}可用</view>
</view>
<view class="text">
<view class="name line1">{{item.coupon_title}}</view>
<view class="type" v-if="item.type === 0 || item.applicable_type == 0">通用优惠券</view>
<view class="type" v-if="item.type === 1 || item.applicable_type == 1">品类优惠券</view>
<view class="type" v-if="item.type === 2 || item.applicable_type == 2">商品优惠券</view>
<view class="type" v-if="item.type === 3 || item.applicable_type == 3">品牌优惠券</view>
<view class="time" v-if="item.coupon_time">有效期:{{item.coupon_time}}</view>
<view class="time" v-else>有效期:{{ item.start_time ? item.start_time + '-' : '' }}{{ item.end_time }}</view>
</view>
<view v-if="num !=2" class="bnt acea-row row-center-wrapper" @click="send(item)">发送</view>
</view>
<view class="tips">没有更多了~</view>
</scroll-view>
</view>
<view class="empty-box" v-else>
<emptyPage title="暂无优惠券~" src="/statics/images/noCoupon.png"></emptyPage>
</view>
</view>
</base-drawer>
</template>
<script>
import emptyPage from '@/components/emptyPage.vue';
import {
getUserCoupon,
postUserUpdate
} from "@/api/admin";
export default {
components: {
emptyPage
},
props:{
visible: {
type: Boolean,
default: false,
},
uid: {
type: Number,
default: 0
}
},
data(){
return{
keyword:'',
couponList:[],
num:0, //1用户批量,0单独用户,前两个是发送优惠券;点击获取优惠券时: 2是查看当前用户优惠券,否则获取优惠券
ids:[]
}
},
mounted: function() {},
methods:{
send(item){
postUserUpdate({
type:3,
uid:this.num?this.ids:this.uid,
coupon_id:item.id
}).then(res=>{
this.$util.Tips({
title: res.msg
});
this.$emit('closeDrawer',1);
}).catch(err=>{
this.$util.Tips({
title: err
});
})
},
searchSubmit(){
this.userCoupon();
},
userCoupon(num,ids){
this.num = num;
this.ids = ids;
getUserCoupon({
coupon_title:this.keyword,
uid:this.num==2?this.uid:0
}).then(res=>{
this.couponList = res.data.list
}).catch(err=>{
this.$util.Tips({
title: err
});
})
},
closeDrawer() {
this.keyword = '';
this.$emit('closeDrawer');
}
}
}
</script>
<style lang="scss" scoped>
.empty-box{
padding: 0 20rpx;
margin-bottom: 20rpx;
}
.coupon{
background-color:#F5F5F5;
padding-bottom: 1rpx;
.title{
text-align: center;
height: 108rpx;
line-height: 108rpx;
font-size: 32rpx;
font-family: PingFang SC, PingFang SC;
font-weight: 600;
color: #333333;
position: relative;
padding: 0 30rpx;
.close{
width: 36rpx;
height: 36rpx;
line-height: 36rpx;
background: #EEEEEE;
border-radius: 50%;
position: absolute;
right: 30rpx;
top:38rpx;
.iconfont {
font-weight: 300;
font-size: 20rpx;
}
}
}
.search{
width: 710rpx;
height: 72rpx;
background: #FFFFFF;
border-radius: 50rpx;
padding: 0 34rpx;
margin: 24rpx auto;
&.on{
width: 618rpx;
}
.iconfont{
color: #999;
font-size: 32rpx;
margin-right: 16rpx;
}
.inputs{
font-size: 28rpx;
width: 100%;
height: 100%;
flex: 1;
}
.placeholder{
color: #ccc;
}
}
.list{
padding: 0 20rpx;
.item{
background-color: #fff;
border-radius: 30rpx;
margin-bottom: 20rpx;
.bg{
background-image: url('../../../static/coupon.png');
background-repeat: no-repeat;
background-size: 100% 100%;
width: 188rpx;
height: 170rpx;
font-size: 22rpx;
font-family: PingFang SC, PingFang SC;
font-weight: 400;
color: #FFFFFF;
text-align: center;
padding: 32rpx 0;
.price{
font-size: 28rpx;
font-weight: 600;
.num{
font-size: 52rpx;
font-family:'Regular';
}
}
.reduction{
margin-top: 14rpx;
color: rgba(255, 255, 255, 0.7);
}
}
.text{
margin-left: 20rpx;
font-family: PingFang SC, PingFang SC;
.name{
font-size: 28rpx;
font-weight: 600;
color: #333333;
width: 336rpx;
}
.type{
font-size: 20rpx;
font-weight: 400;
color: #666666;
margin-top: 8rpx;
}
.time{
font-size: 20rpx;
font-weight: 400;
color: #999999;
margin-top: 20rpx;
}
}
.bnt{
width: 112rpx;
height: 52rpx;
background: #E9F2FE;
border-radius: 26rpx;
font-size: 22rpx;
font-family: PingFang SC, PingFang SC;
font-weight: 500;
color: #2A7EFB;
margin-left: 34rpx;
}
}
.tips{
font-size: 26rpx;
font-family: PingFang SC, PingFang SC;
font-weight: 400;
color: #CCCCCC;
text-align: center;
margin: 32rpx 0;
margin-bottom: calc(32rpx + constant(safe-area-inset-bottom)); ///兼容 IOS<11.2/
margin-bottom: calc(32rpx + env(safe-area-inset-bottom)); ///兼容 IOS>11.2/
}
}
}
</style>

View File

@@ -0,0 +1,207 @@
<template>
<base-drawer mode="bottom" :visible="visible" background-color="transparent" mask maskClosable @close="closeDrawer">
<view class="edit-balance rd-t-40rpx">
<view class="title">修改{{type?'余额':'积分'}}
<view class="close acea-row row-center-wrapper" @tap="closeDrawer">
<text class="iconfont icon-ic_close"></text>
</view>
</view>
<view class="list">
<view class="item acea-row row-between-wrapper">
<view>修改{{type?'余额':'积分'}}</view>
<view class="acea-row row-middle">
<view class="itemn acea-row row-middle" :class="current == index?'on':''" v-for="(item, index) in navList" :key="index" @click="navTap(index)">
<text class="iconfont" :class="current == index?'icon-ic_Selected':'icon-ic_unselect'"></text>
<text>{{item}}</text>
</view>
</view>
</view>
<view class="item acea-row row-between-wrapper">
<view>{{type?'余额':'积分'}}</view>
<view class="acea-row row-middle">
<input type="number" v-model="numeral" :placeholder="type?'请填写余额':'请填写积分'" placeholder-class="placeholder"/>
<text class="iconfont icon-ic_edit"></text>
</view>
</view>
</view>
<view class="footer acea-row row-between-wrapper">
<view class="bnt acea-row row-center-wrapper" @click="closeDrawer">取消</view>
<view class="bnt on acea-row row-center-wrapper" @click="define">确定</view>
</view>
</view>
</base-drawer>
</template>
<script>
import {
postUserUpdateOther
} from "@/api/admin";
export default {
props:{
visible: {
type: Boolean,
default: false,
},
type: {
type: Number,
default: 0,
},
uid: {
type: Number,
default: 0
}
},
watch: {
type: {
handler(newValue, oldValue) {
if(newValue){
this.navList = ['增加余额','减少余额']
}else{
this.navList = ['增加积分','减少积分']
}
},
immediate: true
}
},
data(){
return{
navList:[],
current:0,
numeral:0
}
},
mounted: function() {},
methods:{
navTap(index){
this.current = index
},
define(){
if(this.numeral<=0){
let title = '';
if(this.type){
title = '请填写你要增加或减少的余额'
}else{
title = '请填写你要增加或减少的积分'
}
this.$util.Tips({
title: title
});
return
}
postUserUpdateOther(this.uid,{
status:this.current + 1,
number:this.numeral,
type:this.type
}).then(res=>{
this.$util.Tips({
title: res.msg
});
this.numeral = 0;
this.$emit('successChange');
}).catch(err=>{
this.$util.Tips({
title: err
});
})
},
closeDrawer() {
this.numeral = 0;
this.$emit('closeDrawer');
}
}
}
</script>
<style lang="scss" scoped>
.edit-balance{
background-color: #fff;
padding-bottom: 60rpx;
.title{
text-align: center;
height: 108rpx;
line-height: 108rpx;
font-size: 32rpx;
font-family: PingFang SC, PingFang SC;
font-weight: 600;
color: #333333;
position: relative;
padding: 0 30rpx;
.close{
width: 36rpx;
height: 36rpx;
line-height: 36rpx;
background: #EEEEEE;
border-radius: 50%;
position: absolute;
right: 30rpx;
top:38rpx;
.iconfont {
font-weight: 300;
font-size: 20rpx;
}
}
}
.list{
padding: 0 30rpx;
.item{
font-size: 28rpx;
font-family: PingFang SC, PingFang SC;
font-weight: 400;
color: #333333;
height: 72rpx;
margin-bottom: 32rpx;
box-sizing: border-box;
.icon-ic_edit{
color: #999999;
}
.itemn{
margin-left: 50rpx;
color: #999999;
.iconfont {
margin-top: 4rpx;
color: #CCCCCC;
margin-right: 14rpx;
}
&.on {
color: #333333;
.iconfont {
color: #2A7EFB;
}
}
}
input {
text-align: right;
font-size: 36rpx;
font-family: Regular;
color: #FF7E00;
}
/deep/.uni-input-input{
padding-right: 10rpx;
}
.placeholder{
font-size: 28rpx;
padding-right: 10rpx;
padding: 6rpx 10rpx 0 0;
}
}
}
.footer{
padding: 0 20rpx;
margin-top: 166rpx;
.bnt{
width: 346rpx;
height: 72rpx;
border: 2rpx solid #2A7EFB;
border-radius: 100rpx;
font-size: 26rpx;
font-family: PingFang SC, PingFang SC;
font-weight: 500;
color: #2A7EFB;
&.on{
background: #2A7EFB;
color: #fff;
}
}
}
}
</style>

View File

@@ -0,0 +1,246 @@
<template>
<base-drawer mode="right" :visible="visible" background-color="transparent" mask maskClosable @close="closeDrawer">
<view class="edit-lable">
<!-- #ifdef MP -->
<view class="accountTitle">
<view :style="{height:getHeight.barTop+'px'}"></view>
<view class="sysTitle acea-row row-center-wrapper" :style="{height:getHeight.barHeight+'px'}">
<view>筛选</view>
</view>
</view>
<view :style="{height:(getHeight.barTop+getHeight.barHeight)+'px'}"></view>
<view class="list"
:style="'height: calc(100% - '+(getHeight.barTop+getHeight.barHeight*2+150)+'rpx - constant(safe-area-inset-bottom));height: calc(100% - '+(getHeight.barTop+getHeight.barHeight*2+150)+'rpx - env(safe-area-inset-bottom))'">
<!-- #endif -->
<!-- #ifndef MP -->
<view class="header">筛选</view>
<view class="list">
<!-- #endif -->
<scroll-view scroll-y="true" style="height: 100%">
<view class="item">
<view class="title">分组</view>
<view class="listn acea-row row-middle">
<view class="name acea-row row-center-wrapper" :class="{on:groupIds == item.id}" v-for="(item,groupIndex) in groupArray" :key="groupIndex" @click="selectGroup(item)">
<text class="line1">{{item.group_name}}</text>
</view>
</view>
</view>
<view class="item">
<view class="title">等级</view>
<view class="listn acea-row row-middle">
<view class="name acea-row row-center-wrapper" :class="{on:levelIds == item.id}" v-for="(item,levelIndex) in levelArray" :key="levelIndex" @click="selectLevel(item)">
<text class="line1">{{item.name}}</text>
</view>
</view>
</view>
<view class="item">
<view class="title">标签</view>
<view v-for="(item, index) in labelList" :key="index">
<view class="titlen" v-if="item.label && item.label.length">{{item.name}}</view>
<view class="listn acea-row row-middle" v-if="item.label && item.label.length">
<view class="name acea-row row-center-wrapper" :class="{on:labelIds.includes(j.id)}" v-for="(j, indexn) in item.label" :key="indexn" @click="selectLabel(j)">
<text class="line1">{{j.label_name}}</text>
</view>
</view>
</view>
</view>
</scroll-view>
</view>
<view class="footer acea-row row-between-wrapper">
<view class="bnt acea-row row-center-wrapper" @tap="reset">重置</view>
<view class="bnt on acea-row row-center-wrapper" @tap="define">确定</view>
</view>
</view>
</base-drawer>
</template>
<script>
import {
getUserLabel
} from "@/api/admin";
export default {
props:{
visible: {
type: Boolean,
default: false,
},
groupArray: {
type: Array,
default: [],
},
levelArray: {
type: Array,
default: [],
},
},
data: function() {
return {
// #ifdef MP
getHeight: this.$util.getWXStatusHeight(),
// #endif
labelList:[],
labelIds:[],
groupIds:0,
levelIds:0
}
},
mounted() {
},
methods:{
reset(){
this.labelIds=[];
this.groupIds=0;
this.levelIds=0;
},
define(){
let data = {
labelIds: this.labelIds.join(','),
groupIds: this.groupIds,
levelIds: this.levelIds
};
this.$emit('successChange',data);
},
selectGroup(item){
this.groupIds = item.id;
},
selectLevel(item){
this.levelIds = item.id;
},
selectLabel(item){
if(this.labelIds.includes(item.id)){
this.labelIds = this.labelIds.filter(function (ele){return ele != item.id;});
}else{
this.labelIds.push(item.id);
}
},
productLabel(){
getUserLabel().then(res=>{
this.labelList = res.data
}).catch(err=>{
this.$util.Tips({
title: err
});
})
},
closeDrawer() {
this.$emit('closeDrawer');
}
}
}
</script>
<style lang="scss" scoped>
.accountTitle{
position: fixed;
left:0;
top:0;
width: 100%;
z-index: 99;
padding-bottom: 6rpx;
.sysTitle{
width: 100%;
position: relative;
font-weight: 600;
color: #333333;
font-size: 34rpx;
font-family: PingFang SC, PingFang SC;
}
}
.edit-lable{
background-color: #fff;
width: 670rpx;
border-radius: 40rpx 0 0 40rpx;
height: 100%;
padding: 20rpx 34rpx 0 32rpx;
.header{
text-align: center;
height: 96rpx;
line-height: 96rpx;
font-size: 34rpx;
font-family: PingFang SC, PingFang SC;
font-weight: 600;
color: #333333;
position: relative;
}
.list{
overflow: auto;
height: calc(100% - 208rpx );
height: calc(100% - (208rpx + constant(safe-area-inset-bottom)));
height: calc(100% - (208rpx + env(safe-area-inset-bottom)));
.item{
margin-top: 48rpx;
&~.item{
.titlen{
margin-top: 48rpx;
}
}
.title{
font-size: 28rpx;
font-family: PingFang SC, PingFang SC;
font-weight: 600;
color: #333333;
}
.titlen{
font-size: 24rpx;
font-family: PingFang SC, PingFang SC;
font-weight: 400;
color: #666666;
margin-top: 24rpx;
}
.listn{
.name{
width: 184rpx;
height: 56rpx;
background-color: #F5F5F5;
border-radius: 50rpx;
border:1rpx solid #F5F5F5;
font-size: 24rpx;
font-family: PingFang SC, PingFang SC;
font-weight: 400;
color: #333333;
margin-right: 26rpx;
margin-top: 24rpx;
padding: 0 8rpx;
&.on {
background-color:#E9F2FE;
border-color:#2A7EFB;
color: #2A7EFB;
}
&:nth-of-type(3n){
margin-right: 0;
}
}
}
}
}
.footer{
width: 100%;
height: 112rpx;
position: fixed;
bottom: 0;
left:0;
padding: 0 32rpx;
background-color: #fff;
border-radius: 0 0 0 40rpx;
height: calc(112rpx + constant(safe-area-inset-bottom)); ///兼容 IOS<11.2/
height: calc(112rpx + env(safe-area-inset-bottom)); ///兼容 IOS>11.2/
padding-bottom: constant(safe-area-inset-bottom); ///兼容 IOS<11.2/
padding-bottom: env(safe-area-inset-bottom); ///兼容 IOS>11.2/
.bnt{
width: 296rpx;
height: 72rpx;
border: 1px solid #2A7EFB;
border-radius: 200rpx;
font-size: 26rpx;
font-family: PingFang SC, PingFang SC;
font-weight: 600;
color: #2A7EFB;
&.on{
background: #2A7EFB;
border-color: #2A7EFB;
color: #fff;
}
}
}
}
</style>

View File

@@ -0,0 +1,197 @@
<template>
<base-drawer mode="bottom" :visible="visible" background-color="transparent" mask maskClosable @close="closeDrawer">
<view class="edit-balance rd-t-40rpx">
<view class="title">赠送会员
<view class="close acea-row row-center-wrapper" @tap="closeDrawer">
<text class="iconfont icon-ic_close"></text>
</view>
</view>
<view class="list">
<view class="item acea-row row-between-wrapper">
<view>会员到期日</view>
<view class="time">{{userInfo.svip_overdue_time || '已过期/暂未开通'}}</view>
</view>
<view class="item acea-row row-between-wrapper">
<view>剩余天数</view>
<view class="time">{{userInfo.svip_over_day}}</view>
</view>
<view class="item acea-row row-between-wrapper">
<view>修改付费会员</view>
<view class="acea-row row-middle">
<view class="itemn acea-row row-middle" :class="current == index?'on':''" v-for="(item, index) in navList" :key="index" @click="navTap(index)">
<text class="iconfont" :class="current == index?'icon-ic_Selected':'icon-ic_unselect'"></text>
<text>{{item}}</text>
</view>
</view>
</view>
<view class="item acea-row row-between-wrapper">
<view>调整时长(天)</view>
<view class="acea-row row-middle">
<input type="numeric" v-model="numeral" placeholder="请输入时长" placeholder-class="placeholder"/>
<text class="iconfont icon-ic_edit"></text>
</view>
</view>
</view>
<view class="footer acea-row row-between-wrapper">
<view class="bnt acea-row row-center-wrapper" @click="closeDrawer">取消</view>
<view class="bnt on acea-row row-center-wrapper" @click="define">确定</view>
</view>
</view>
</base-drawer>
</template>
<script>
import {
postUserUpdate
} from "@/api/admin";
export default {
props:{
visible: {
type: Boolean,
default: false,
},
userInfo: {
type: Object,
default: () => {}
}
},
data(){
return{
navList:['增加','减少'],
current:0,
numeral:0
}
},
mounted: function() {},
methods:{
navTap(index){
this.current = index
},
define(){
if(this.numeral <=0){
this.$util.Tips({
title: '请填写有效时长'
});
return
}
postUserUpdate({
type:2,
uid:this.userInfo.uid,
days_status:this.current+1,
days:this.numeral
}).then(res=>{
this.$util.Tips({
title: res.msg
});
this.numeral = 0
this.$emit('successChange');
}).catch(err=>{
this.$util.Tips({
title: err
});
})
},
closeDrawer() {
this.numeral = 0
this.$emit('closeDrawer');
}
}
}
</script>
<style lang="scss" scoped>
.edit-balance{
background-color: #fff;
padding-bottom: 60rpx;
.title{
text-align: center;
height: 108rpx;
line-height: 108rpx;
font-size: 32rpx;
font-family: PingFang SC, PingFang SC;
font-weight: 600;
color: #333333;
position: relative;
padding: 0 30rpx;
.close{
width: 36rpx;
height: 36rpx;
line-height: 36rpx;
background: #EEEEEE;
border-radius: 50%;
position: absolute;
right: 30rpx;
top:38rpx;
.iconfont {
font-weight: 300;
font-size: 20rpx;
}
}
}
.list{
padding: 0 30rpx;
.item{
font-size: 28rpx;
font-family: PingFang SC, PingFang SC;
font-weight: 400;
color: #333333;
height: 72rpx;
margin-bottom: 32rpx;
box-sizing: border-box;
.icon-ic_edit{
color: #999999;
}
.time{
color: #999999;
}
.itemn{
margin-left: 50rpx;
color: #999999;
.iconfont {
margin-top: 4rpx;
color: #CCCCCC;
margin-right: 14rpx;
}
&.on {
color: #333333;
.iconfont {
color: #2A7EFB;
}
}
}
input {
text-align: right;
font-size: 36rpx;
font-family: Regular;
color: #FF7E00;
}
/deep/.uni-input-input{
padding-right: 10rpx;
}
.placeholder{
font-size: 28rpx;
padding-right: 10rpx;
padding: 6rpx 10rpx 0 0;
}
}
}
.footer{
padding: 0 20rpx;
margin-top: 90rpx;
.bnt{
width: 346rpx;
height: 72rpx;
border: 2rpx solid #2A7EFB;
border-radius: 100rpx;
font-size: 26rpx;
font-family: PingFang SC, PingFang SC;
font-weight: 500;
color: #2A7EFB;
&.on{
background: #2A7EFB;
color: #fff;
}
}
}
}
</style>

View File

@@ -0,0 +1,252 @@
<template>
<base-drawer mode="right" :visible="visible" background-color="transparent" mask maskClosable @close="closeDrawer">
<view class="edit-lable">
<!-- #ifdef MP -->
<view class="accountTitle">
<view :style="{height:getHeight.barTop+'px'}"></view>
<view class="sysTitle acea-row row-center-wrapper" :style="{height:getHeight.barHeight+'px'}">
<view>添加标签</view>
</view>
</view>
<view :style="{height:(getHeight.barTop+getHeight.barHeight)+'px'}"></view>
<view class="list" v-if="isStore"
:style="'height: calc(100% - '+(getHeight.barTop+getHeight.barHeight*2+150)+'rpx - constant(safe-area-inset-bottom));height: calc(100% - '+(getHeight.barTop+getHeight.barHeight*2+150)+'rpx - env(safe-area-inset-bottom))'">
<!-- #endif -->
<!-- #ifndef MP -->
<view class="header">添加标签</view>
<view class="list" v-if="isStore">
<!-- #endif -->
<scroll-view scroll-y="true" style="height: 100%">
<view class="item" v-for="(item, index) in labelList" :key="index">
<view class="title" v-if="item.label && item.label.length">{{item.name}}</view>
<view class="listn acea-row row-middle" v-if="item.label && item.label.length">
<view class="name acea-row row-center-wrapper" :class="{on:j.disabled}" v-for="(j, indexn) in item.label" :key="indexn" @click="selectLabel(j)">
<text class="line1">{{j.label_name}}</text>
</view>
</view>
</view>
</scroll-view>
</view>
<view class="empty-box" v-else>
<emptyPage title="暂无标签~" src="/statics/images/empty-box.png"></emptyPage>
</view>
<view class="footer acea-row row-between-wrapper">
<view class="bnt acea-row row-center-wrapper" @tap="reset">重置</view>
<view class="bnt on acea-row row-center-wrapper" @tap="define">确定</view>
</view>
</view>
</base-drawer>
</template>
<script>
import emptyPage from '@/components/emptyPage.vue';
import {
getUserLabel,
postUserUpdate
} from "@/api/admin";
import { handleError } from "vue";
export default {
components: {
emptyPage
},
props:{
visible: {
type: Boolean,
default: false,
},
},
data: function() {
return {
// #ifdef MP
getHeight: this.$util.getWXStatusHeight(),
// #endif
labelList:[],
goodsInfo:{}, //列表中已存在id(固定不变)
dataLabel: [], //已存在选中id(随着选中可以变化)
isStore:false, //判断是否存在标签
num:0, // 判断是否为批量
ids:[] //批量时的id集合
};
},
mounted() {
},
methods:{
define(){
let labelIds = []
this.dataLabel.forEach(item=>{
labelIds.push(item.id)
})
postUserUpdate({
type:5,
uid:this.num?this.ids:this.goodsInfo.uid,
label_id:labelIds
}).then(res=>{
this.$util.Tips({
title: res.msg
});
this.$emit('closeDrawer',1);
}).catch(err=>{
this.$util.Tips({
title: err
});
})
},
reset(){
this.productLabel(this.goodsInfo,this.num,this.ids);
},
inArray: function (search, array) {
for (let i in array) {
if (array[i].id == search) {
return true;
}
}
return false;
},
productLabel(data,num,ids){
this.dataLabel = data.label_id || [];
this.goodsInfo = JSON.parse(JSON.stringify(data));
this.num = num;
this.ids = ids;
getUserLabel().then(res=>{
res.data.map(el => {
if (el.label && el.label.length) {
this.isStore = true;
el.label.map(label => {
if (this.inArray(label.id, this.dataLabel)) {
label.disabled = true;
} else {
label.disabled = false;
}
})
}
})
this.labelList = res.data
}).catch(err=>{
this.$util.Tips({
title: err
});
})
},
selectLabel(label) {
if (label.disabled) {
let index = this.dataLabel.indexOf(this.dataLabel.filter(d => d.id == label.id)[0]);
this.dataLabel.splice(index, 1);
label.disabled = false
} else {
this.dataLabel.push({
id:label.id,
label_name:label.label_name
});
label.disabled = true
}
},
closeDrawer() {
this.$emit('closeDrawer');
}
}
}
</script>
<style lang="scss" scoped>
.accountTitle{
position: fixed;
left:0;
top:0;
width: 100%;
z-index: 99;
padding-bottom: 6rpx;
.sysTitle{
width: 100%;
position: relative;
font-weight: 600;
color: #333333;
font-size: 34rpx;
font-family: PingFang SC, PingFang SC;
}
}
.edit-lable{
background-color: #fff;
width: 670rpx;
border-radius: 40rpx 0 0 40rpx;
height: 100%;
padding: 20rpx 34rpx 0 32rpx;
.header{
text-align: center;
height: 96rpx;
line-height: 96rpx;
font-size: 34rpx;
font-family: PingFang SC, PingFang SC;
font-weight: 600;
color: #333333;
position: relative;
}
.list{
overflow: auto;
height: calc(100% - 208rpx );
height: calc(100% - (208rpx + constant(safe-area-inset-bottom)));
height: calc(100% - (208rpx + env(safe-area-inset-bottom)));
.item{
margin-top: 48rpx;
.title{
font-size: 28rpx;
font-family: PingFang SC, PingFang SC;
font-weight: 600;
color: #333333;
}
.listn{
.name{
width: 184rpx;
height: 56rpx;
background-color: #F5F5F5;
border-radius: 50rpx;
border:1rpx solid #F5F5F5;
font-size: 24rpx;
font-family: PingFang SC, PingFang SC;
font-weight: 400;
color: #333333;
margin-right: 26rpx;
margin-top: 24rpx;
padding: 0 8rpx;
&.on {
background-color:#E9F2FE;
border-color:#2A7EFB;
color: #2A7EFB;
}
&:nth-of-type(3n){
margin-right: 0;
}
}
}
}
}
.footer{
width: 100%;
height: 112rpx;
position: fixed;
bottom: 0;
left:0;
padding: 0 32rpx;
background-color: #fff;
border-radius: 0 0 0 40rpx;
height: calc(112rpx + constant(safe-area-inset-bottom)); ///兼容 IOS<11.2/
height: calc(112rpx + env(safe-area-inset-bottom)); ///兼容 IOS>11.2/
padding-bottom: constant(safe-area-inset-bottom); ///兼容 IOS<11.2/
padding-bottom: env(safe-area-inset-bottom); ///兼容 IOS>11.2/
.bnt{
width: 296rpx;
height: 72rpx;
border: 1px solid #2A7EFB;
border-radius: 200rpx;
font-size: 26rpx;
font-family: PingFang SC, PingFang SC;
font-weight: 600;
color: #2A7EFB;
&.on{
background: #2A7EFB;
border-color: #2A7EFB;
color: #fff;
}
}
}
}
</style>

559
pages/admin/user/index.vue Normal file
View File

@@ -0,0 +1,559 @@
<template>
<view class="user-details">
<!-- #ifdef MP || APP-PLUS -->
<view class="accountTitle">
<view :style="{height:getHeight.barTop+'px'}"></view>
<view class="sysTitle acea-row row-center-wrapper" :style="{height:getHeight.barHeight+'px'}">
<view>用户详情</view>
<text class="iconfont icon-ic_leftarrow" @click="goarrow"></text>
</view>
</view>
<view :style="{height:(getHeight.barTop+getHeight.barHeight)+'px'}"></view>
<!-- #endif -->
<view class="header">
<view class="picTxt acea-row row-middle">
<view class="pictrue">
<image :src="infoData.avatar"></image>
</view>
<view class="text">
<view class="name acea-row row-middle">
<view class="nameCon line1">{{infoData.nickname}}</view>
<view class="svip acea-row row-center-wrapper" v-if="infoData.isMember == 1">SVIP</view>
<view class="vip acea-row row-center-wrapper" v-if="infoData.level_status == 1">
<text class="iconfont icon-huiyuandengji"></text>
V{{infoData.level_grade}}
</view>
</view>
<view v-if="infoData.phone">{{infoData.phone}}(ID:{{uid}})</view>
<view v-else>ID:{{uid}}</view>
</view>
</view>
<view class="bottom acea-row row-middle">
<view class="item">消费金额<text class="num">{{infoData.order_total_price}}</text></view>
<view class="item">消费笔数<text class="num">{{infoData.order_total_count}}</text></view>
</view>
</view>
<view class="list">
<view class="title acea-row row-between-wrapper">
<view class="name">用户信息</view>
<view class="tip" @click="openTap">{{isShow?'展开':'收起'}}<text class="iconfont" :class="isShow?'icon-ic_downarrow':'icon-ic_uparrow'"></text></view>
</view>
<view class="item acea-row row-between-wrapper">
<view>分组</view>
<view>
<picker @change="bindPickerChange" :value="groupIndex" :range="groupArray" range-key="group_name">
<view class="acea-row row-middle">
<view v-if="groupArray.length">
<text class="not" v-if="groupIndex == -1">无</text>
<text v-else>{{groupArray[groupIndex].group_name}}</text>
</view>
<text class="iconfont icon-ic_rightarrow"></text>
</view>
</picker>
</view>
</view>
<view class="item acea-row row-between-wrapper">
<view>等级</view>
<view>
<picker @change="bindLevelChange" :value="levelIndex" :range="levelArray" range-key="name">
<view class="acea-row row-middle">
<view v-if="levelArray.length">
<text class="not" v-if="levelIndex == -1">无</text>
<text v-else>{{levelArray[levelIndex].name}}</text>
</view>
<text class="iconfont icon-ic_rightarrow"></text>
</view>
</picker>
</view>
</view>
<view class="item">
<view class="acea-row row-between-wrapper">
<view>标签</view>
<view class="add" @click="editLabels"><text class="iconfont icon-ic_increase"></text>添加标签</view>
</view>
<view class="labelList acea-row row-middle" v-if="infoData.label_id && infoData.label_id.length">
<view class="label" v-for="(item,index) in infoData.label_id" :key="index">{{item.label_name}}</view>
</view>
</view>
<view class="listn" v-if="!isShow">
<view class="item acea-row row-between-wrapper" v-if="infoData.real_name">
<view>姓名</view>
<view class="info">{{infoData.real_name}}</view>
</view>
<view class="item acea-row row-between-wrapper" v-if="infoData.birthday">
<view>出生年月</view>
<view class="info">{{infoData.birthday}}</view>
</view>
<view class="item acea-row row-between-wrapper" v-if="infoData.card_id">
<view>身份证号</view>
<view class="info">{{infoData.card_id}}</view>
</view>
<view class="item acea-row row-between" v-if="infoData.addres">
<view>地址</view>
<view class="info">{{infoData.addres}}</view>
</view>
<view class="item acea-row row-between-wrapper" v-if="infoData._add_time">
<view>注册时间</view>
<view class="info">{{infoData._add_time}}</view>
</view>
</view>
</view>
<view class="property">
<view class="title">资产信息</view>
<view class="info acea-row">
<view class="item" @click="integralTap">
<view>积分</view>
<view class="bottom acea-row row-between-wrapper">
<view class="num">{{infoData.integral}}</view>
<view class="iconfont icon-ic_edit"></view>
</view>
</view>
<view class="item" @click="balanceTap">
<view>余额</view>
<view class="bottom acea-row row-between-wrapper">
<view class="num">{{infoData.now_money}}</view>
<view class="iconfont icon-ic_edit"></view>
</view>
</view>
</view>
<view class="info acea-row">
<view class="item">
<view class="acea-row row-between-wrapper">
<view>优惠券</view>
<view class="iconfont icon-ic_rightarrow" @click="couponSeeTap"></view>
</view>
<view class="bottom acea-row row-between-wrapper">
<view class="num">{{infoData.coupon_num}}张</view>
<view class="give" @click="couponTap">赠送</view>
</view>
</view>
<view class="item" @click="memberTap">
<view>会员</view>
<view class="bottom acea-row row-between-wrapper">
<view class="num" v-if="infoData.svip_over_day">{{ '剩余'+infoData.svip_over_day+'天' }}</view>
<view class="num" v-else>已过期/暂未开通</view>
<view class="iconfont icon-ic_edit"></view>
</view>
</view>
</view>
</view>
<edit-lable ref="lable" :visible='visibleLable' @closeDrawer='lableCloseDrawer'></edit-lable>
<edit-balance ref="balance" :visible='visibleBalance' :type = 'type' :uid='parseInt(uid)' @closeDrawer='balanceCloseDrawer' @successChange='successChange'></edit-balance>
<member ref="member" :visible='visibleMember' :userInfo='infoData' @closeDrawer='memberCloseDrawer' @successChange='successChange'></member>
<coupon ref="coupon" :visible='visibleCoupon' :uid='parseInt(uid)' @closeDrawer='couponCloseDrawer'></coupon>
</view>
</template>
<script>
import editLable from './components/userLable/index.vue';
import editBalance from './components/editBalance/index.vue';
import member from './components/member/index.vue';
import coupon from './components/coupon/index.vue';
import {
getUserInfo,
getGroupList,
getLevelList,
postUserUpdate
} from "@/api/admin";
export default {
components: {
editLable,
editBalance,
member,
coupon
},
data() {
return {
getHeight: this.$util.getWXStatusHeight(),
uid: 0,
infoData: {},
groupArray:[],
levelArray:[],
groupIndex:-1,
levelIndex:-1,
visibleLable:false,
visibleBalance:false,
type: 0,
visibleMember:false,
visibleCoupon:false,
isShow:false
}
},
onLoad(options) {
this.uid = options.uid
this.userInfo(1);
},
methods: {
openTap(){
this.isShow = !this.isShow
},
couponTap(){
this.$refs.coupon.userCoupon(0);
this.visibleCoupon = true;
},
couponSeeTap(){
this.$refs.coupon.userCoupon(2);
this.visibleCoupon = true;
},
couponCloseDrawer(e){
this.visibleCoupon = false;
if(e){
this.userInfo();
}
},
memberTap(){
this.visibleMember = true;
},
memberCloseDrawer(){
this.visibleMember = false;
},
balanceTap(){
this.type = 1;
this.visibleBalance = true;
},
integralTap(){
this.type = 0;
this.visibleBalance = true;
},
successChange(){
this.visibleBalance = false
this.visibleMember = false;
this.userInfo();
},
balanceCloseDrawer(){
this.visibleBalance = false
},
lableCloseDrawer(e){
this.visibleLable = false
if(e){
this.userInfo();
}
},
editLabels(){
this.visibleLable = true
this.$refs.lable.productLabel(JSON.parse(JSON.stringify(this.infoData)),0,[]);
},
bindPickerChange(e){
this.groupIndex = e.detail.value
this.userUpdate(4)
},
bindLevelChange(e){
this.levelIndex = e.detail.value
this.userUpdate(1)
},
userUpdate(num){
let data = {}
if(num == 4){
data = {
type:4,
uid:this.uid,
group_id:this.groupArray[this.groupIndex].id
}
}else{
data = {
type:1,
uid:this.uid,
level:this.levelArray[this.levelIndex].id
}
}
postUserUpdate(data).then(res=>{
this.$util.Tips({
title: res.msg
});
}).catch(err=>{
this.$util.Tips({
title: err
});
})
},
levelList(){
getLevelList().then(res=>{
let id = this.infoData.level
res.data.list.forEach((item,index)=>{
if(item.id == id){
this.levelIndex = index
}
})
this.levelArray = res.data.list;
}).catch(err=>{
this.$util.Tips({
title: err
});
})
},
groupList(){
getGroupList().then(res=>{
let id = this.infoData.group_id
res.data.forEach((item,index)=>{
if(item.id == id){
this.groupIndex = index
}
})
this.groupArray = res.data;
}).catch(err=>{
this.$util.Tips({
title: err
});
})
},
goarrow(){
uni.navigateBack()
},
userInfo(num){
getUserInfo(this.uid).then(res=>{
this.infoData = res.data;
if(num){
this.groupList();
this.levelList();
}
}).catch(err=>{
this.$util.Tips({
title: err
});
})
}
}
}
</script>
<style lang="scss" scoped>
.accountTitle{
background: linear-gradient(270deg, $gradient-primary-admin 0%, $primary-admin 100%);
position: fixed;
left:0;
top:0;
width: 100%;
z-index: 99;
.sysTitle{
width: 100%;
position: relative;
font-weight: 500;
color: #fff;
font-size: 30rpx;
.iconfont{
position: absolute;
font-size: 39rpx;
left:11rpx;
width: 60rpx;
font-weight: 600;
}
}
}
.user-details{
padding-bottom: 1rpx;
padding-bottom: calc(1rpx + constant(safe-area-inset-bottom)); ///兼容 IOS<11.2/
padding-bottom: calc(1rpx + env(safe-area-inset-bottom)); ///兼容 IOS>11.2/
.header{
background: linear-gradient(270deg, $gradient-primary-admin 0%, $primary-admin 100%);
height: 346rpx;
padding: 20rpx 30rpx 0 30rpx;
position: relative;
.picTxt{
.pictrue{
width: 112rpx;
height: 112rpx;
image {
width: 100%;
height: 100%;
border-radius: 50%;
}
}
.text{
margin-left: 32rpx;
font-size: 24rpx;
font-family: PingFang SC, PingFang SC;
font-weight: 400;
color: rgba(255, 255, 255, 0.5);
.name{
margin-bottom: 12rpx;
.nameCon{
font-size: 32rpx;
color: #fff;
max-width: 300rpx;
}
.svip{
width: 56rpx;
height: 26rpx;
background: linear-gradient(270deg, #484643 0%, #1F1B17 100%);
border-radius: 14rpx;
font-size: 18rpx;
font-weight: 600;
color: #FDDAA4;
margin-left: 12rpx;
}
.vip{
width: 68rpx;
height: 26rpx;
background: #FEF0D9;
margin-left: 12rpx;
border-radius: 50rpx;
font-size: 18rpx;
font-weight: 500;
color: #DFA541;
.iconfont{
font-size: 20rpx;
margin-right: 4rpx;
}
}
}
}
}
.bottom{
font-size: 26rpx;
font-family: PingFang SC, PingFang SC;
font-weight: 400;
color: rgba(255, 255, 255, 0.8);
margin-top: 40rpx;
.item{
margin-right: 44rpx;
.num{
margin-left: 8rpx;
color: #FFFFFF;
}
}
}
&::after{
position: absolute;
content: '';
width: 50%;
height: 88rpx;
background: linear-gradient(180deg, $primary-admin 0%, #F5F5F5 100%);
left:0;
bottom: 0;
}
&::before{
position: absolute;
content: '';
width: 50%;
height: 88rpx;
background: linear-gradient(180deg, $gradient-primary-admin 0%, #F5F5F5 100%);
right:0;
bottom: 0;
}
}
.list{
width: 710rpx;
background-color: #fff;
border-radius: 24rpx;
margin: -96rpx auto 0 auto;
position: relative;
font-family: PingFang SC, PingFang SC;
color: #333333;
padding: 32rpx 24rpx 40rpx 24rpx;
.title{
margin-bottom: 40rpx;
.name{
font-size: 30rpx;
font-weight: 600;
}
.tip{
font-size: 26rpx;
font-weight: 400;
color: #999999;
.iconfont {
font-size: 22rpx;
margin-left: 4rpx;
}
}
}
.listn{
margin-top: 52rpx;
}
.item {
font-weight: 400;
&~.item{
margin-top: 52rpx;
}
.not{
color: #999;
}
.iconfont {
font-size: 26rpx;
color: #999;
margin-left: 6rpx;
}
.info{
color: #999999;
width: 465rpx;
text-align: right;
}
.add{
font-size: 24rpx;
color: $primary-admin;
.iconfont {
margin-right: 8rpx;
color: $primary-admin;
}
}
.labelList{
margin-top: 12rpx;
.label{
border: 1px solid $primary-admin;
border-radius: 20rpx;
font-size: 20rpx;
color: $primary-admin;
padding: 4rpx 16rpx;
margin-right: 16rpx;
margin-top: 16rpx;
}
}
}
}
.property{
width: 710rpx;
background-color: #fff;
border-radius: 24rpx;
margin: 20rpx auto;
font-family: PingFang SC, PingFang SC;
.title{
font-size: 30rpx;
font-family: PingFang SC, PingFang SC;
font-weight: 600;
color: #333333;
padding: 32rpx 24rpx 2rpx 24rpx;
margin-bottom: 32rpx;
}
.info{
margin: 0 26rpx;
.item{
width: 50%;
font-size: 28rpx;
font-weight: 400;
color: #999999;
padding: 10rpx 40rpx 40rpx 18rpx;
&~.item{
border-left: 1px solid #EEEEEE;
padding-left: 40rpx;
padding-right: 14rpx;
}
.bottom{
margin-top: 20rpx;
.num{
font-size: 30rpx;
font-weight: 600;
color: #333333;
}
.give{
font-size: 24rpx;
font-weight: 400;
color: $primary-admin;
padding-left: 40rpx;
}
}
.icon-ic_rightarrow{
font-size: 26rpx;
padding: 6rpx 0 6rpx 40rpx;
}
}
&~.info{
border-top: 1px solid #EEEEEE;
.item{
padding-top: 40rpx;
}
}
}
}
}
</style>

678
pages/admin/user/list.vue Normal file
View File

@@ -0,0 +1,678 @@
<template>
<view class="user-list">
<!-- #ifdef MP || APP-PLUS -->
<view class="accountTitle">
<view :style="{height:getHeight.barTop+'px'}"></view>
<view class="sysTitle acea-row row-center-wrapper" :style="{height:getHeight.barHeight+'px'}">
<view>用户管理</view>
<text class="iconfont icon-ic_leftarrow" @click="goarrow"></text>
</view>
</view>
<view :style="{height:(getHeight.barTop+getHeight.barHeight)+'px'}"></view>
<!-- #endif -->
<view class="searchCon acea-row row-between-wrapper">
<view class="search acea-row row-middle" :class="administer?'on':''">
<text class="iconfont icon-ic_search"></text>
<input class="inputs" placeholder='请输入用户昵称/ID' placeholder-class='placeholder' confirm-type='search' name="search"
v-model="keyword" @confirm="searchSubmit"></input>
</view>
<view @click="manageTap" v-if="administer">取消</view>
<view class="edit acea-row row-center-wrapper" @click="manageTap" v-else>
<text class="iconfont icon-ic_batch"></text>
</view>
<view class="edit acea-row row-center-wrapper" @click="filterTap" v-if="!administer">
<text class="iconfont icon-ic_sort"></text>
</view>
</view>
<view class="list" v-if="userLists.length">
<checkbox-group @change="checkboxChange">
<view class="acea-row row-middle" v-for="(item, index) in userLists" :key="index">
<!-- #ifndef MP -->
<checkbox class="checkbox" v-if="administer" :value="(item.uid).toString()" :checked="item.checked"
color="#ffffff" backgroundColor="#ffffff"
activeBackgroundColor="#2A7EFB" activeBorderColor="#2A7EFB"/>
<!-- #endif -->
<!-- #ifdef MP -->
<checkbox class="checkbox" v-if="administer" :value="item.uid" :checked="item.checked" color="#ffffff" />
<!-- #endif -->
<view class="item acea-row row-center-wrapper" @click="goDetails(item)">
<view class="pictrue">
<image :src="item.avatar"></image>
</view>
<view class="text">
<view class="top acea-row row-middle">
<view class="name line1">{{item.nickname}}</view>
<view class="svip acea-row row-center-wrapper" v-if="item.isMember == 1">SVIP</view>
<view class="vip acea-row row-center-wrapper" v-if="item.level_status == 1 && item.level_grade">
<text class="iconfont icon-huiyuandengji"></text>
V{{item.level_grade}}
</view>
</view>
<view class="phone">{{item.phone}}</view>
<view class="info acea-row row-middle">
<view>积分:<text>{{item.integral}}</text></view>
<view>余额:<text>{{item.now_money}}</text></view>
</view>
</view>
<view v-if="!administer" class="iconfont icon-ic_more" @click.stop="openDrawer(item)"></view>
</view>
</view>
</checkbox-group>
</view>
<block v-if="userLists.length == 0 && !loading">
<emptyPage title="暂无用户信息~" src="/statics/images/empty-box.gif"></emptyPage>
</block>
<Loading :loaded="loadend" :loading="loading"></Loading>
<view class="footerH"></view>
<view class="footer acea-row row-between-wrapper" v-if="administer">
<checkbox-group @change="checkboxAllChange">
<checkbox value="all" :checked="isAllSelect"
color="#ffffff" backgroundColor="#ffffff"
activeBackgroundColor="#2A7EFB" activeBorderColor="#2A7EFB" />
<text class='checkAll'>全选({{getIds().length}})</text>
</checkbox-group>
<view class="acea-row row-middle">
<view class="bnt acea-row row-center-wrapper">
<picker @change="bindPickerChange" :range="groupArray" range-key="group_name">
<view>修改分组</view>
</picker>
</view>
<view class="bnt acea-row row-center-wrapper" @click="editLabels">添加标签</view>
<view class="bnt acea-row row-center-wrapper" @click="sendCoupon">发送优惠券</view>
</view>
</view>
<base-drawer mode="bottom" :visible="visible" background-color="transparent" mask maskClosable @close="closeDrawer">
<view class="edit-list rd-t-40rpx">
<view class="item" v-for="(item, index) in editList" :key="index" @tap="editInfo(index)">
<picker @change="bindLevelChange" :range="levelArray" range-key="name" v-if="index == 2">
<view class="uni-input">{{item.name}}</view>
</picker>
<text v-else>{{item.name}}</text>
</view>
</view>
</base-drawer>
<view style="height: 110rpx;"></view>
<footer-page></footer-page>
<edit-lable ref="lable" :visible='visibleLable' @closeDrawer='lableCloseDrawer'></edit-lable>
<edit-balance ref="balance" :visible='visibleBalance' :type = 'type' :uid='uid' @closeDrawer='balanceCloseDrawer' @successChange='successChange'></edit-balance>
<member ref="member" :visible='visibleMember' :userInfo='userInfo' @closeDrawer='memberCloseDrawer' @successChange='successChange'></member>
<coupon ref="coupon" :visible='visibleCoupon' :uid='uid' @closeDrawer='couponCloseDrawer'></coupon>
<user-filter ref="filter" :visible='visibleFilter' :groupArray='groupArray' :levelArray='levelArray' @closeDrawer='filterCloseDrawer' @successChange='filterChange'></user-filter>
</view>
</template>
<script>
import Loading from '@/components/Loading/index'
import emptyPage from '@/components/emptyPage.vue';
import footerPage from '../components/footerPage/index.vue';
import editLable from './components/userLable/index.vue';
import editBalance from './components/editBalance/index.vue';
import member from './components/member/index.vue';
import coupon from './components/coupon/index.vue';
import userFilter from './components/filter/index.vue';
import {
getUserList,
getGroupList,
postUserUpdate,
getLevelList
} from "@/api/admin";
export default {
components: {
editLable,
editBalance,
member,
coupon,
userFilter,
footerPage,
emptyPage,
Loading
},
data() {
return {
getHeight: this.$util.getWXStatusHeight(),
editList:[
{
name:'修改积分'
},
{
name:'修改余额'
},
{
name:'修改等级'
},
{
name:'赠送会员'
},
{
name:'赠送优惠券'
},
],
administer:0,
isAllSelect: false,
userLists:[],
visible:false,
visibleLable:false, //标签是否显示
loadTitle: '加载更多',
loading: false,
loadend: false,
limit: 20,
page: 1,
keyword:'', //搜索字段
visibleBalance: false,
type: 0,
visibleMember:false,
visibleCoupon:false,
uid: 0,
groupArray:[],
userInfo:{},
levelArray:[],
visibleFilter:false,
filterData:{
labelIds:'',
groupIds:0,
levelIds:0
}
}
},
onShow() {
},
onLoad() {
this.userList();
this.groupList();
},
methods: {
goarrow(){
uni.navigateBack()
},
filterChange(data){
this.visibleFilter = false
this.filterData = data
this.init();
},
filterCloseDrawer(){
this.visibleFilter = false
},
filterTap(){
this.visibleFilter = true;
this.$refs.filter.productLabel();
this.levelList();
// this.groupList();
},
sendCoupon(){
if(!this.getIds().length){
this.$util.Tips({
title: '请选择商品'
});
return
}
this.visibleCoupon = true;
this.$refs.coupon.userCoupon(1,this.getIds());
},
levelList(){
getLevelList().then(res=>{
this.levelArray = res.data.list;
}).catch(err=>{
this.$util.Tips({
title: err
});
})
},
groupList(){
getGroupList().then(res=>{
this.groupArray = res.data;
}).catch(err=>{
this.$util.Tips({
title: err
});
})
},
userUpdate(data){
postUserUpdate(data).then(res=>{
this.$util.Tips({
title: res.msg
});
}).catch(err=>{
this.$util.Tips({
title: err
});
})
},
bindLevelChange(e){
this.userUpdate({
type:1,
uid:this.uid,
level:this.levelArray[e.detail.value].id
})
this.init();
},
bindPickerChange(e){
if(!this.getIds().length){
this.$util.Tips({
title: '请选择商品'
});
return
}
this.userUpdate({
type:4,
uid:this.getIds(),
group_id:this.groupArray[e.detail.value].id
})
},
goDetails(item){
uni.navigateTo({
url: '/pages/admin/user/index?uid='+item.uid
})
},
couponCloseDrawer(){
this.visibleCoupon = false
},
memberCloseDrawer(){
this.visibleMember = false
},
balanceCloseDrawer(){
this.visibleBalance = false
},
successChange(){
this.visibleMember = false
this.visibleBalance = false
this.init();
},
//批量编辑标签
editLabels(){
if(!this.getIds().length){
this.$util.Tips({
title: '请选择商品'
});
return
}
this.visibleLable = true
this.visible = false
this.$refs.lable.productLabel({},1,this.getIds());
},
//批量获取id集合
getIds(){
let ids = []
this.userLists.forEach(item=>{
if(item.checked){
ids.push(item.uid)
}
})
ids.slice(0, 100)
return ids
},
init(){
this.userLists = [];
this.page = 1;
this.loadend = false;
this.loading = false;
this.userList();
},
searchSubmit(){
this.init();
},
userList(){
let that = this;
if (this.loading) return;
if (this.loadend) return;
that.loading = true;
that.loadTitle = "";
getUserList({
page: that.page,
limit: that.limit,
nickname: that.keyword,
group_id: that.filterData.groupIds,
level: that.filterData.levelIds,
label_id: that.filterData.labelIds
}).then(res=>{
let userLists = res.data.list;
userLists.forEach(item => {
item.checked = false;
})
this.isAllSelect = false
let loadend = userLists.length < that.limit;
that.userLists = that.$util.SplitArray(userLists, that.userLists);
that.$set(that, 'userLists', that.userLists);
that.loadend = loadend;
that.loadTitle = loadend ? '没有更多内容啦~' : '加载更多';
that.page = that.page + 1;
that.loading = false;
}).catch(err=>{
that.loading = false;
that.loadTitle = "加载更多";
})
},
editInfo(index){
switch (index) {
case 0:
this.visible = false
this.visibleBalance = true
this.type = 0
break;
case 1:
this.visible = false
this.visibleBalance = true
this.type = 1
break;
case 2:
this.visible = false
break;
case 3:
this.visible = false
this.visibleMember = true
break;
case 4:
this.visible = false
this.visibleCoupon = true
break;
}
},
lableCloseDrawer(){
this.visibleLable = false
},
openDrawer(item){
this.visible = true
this.uid = item.uid
this.userInfo = item;
this.levelList();
this.$refs.coupon.userCoupon(0);
},
closeDrawer(){
this.visible = false
},
manageTap() {
this.administer = !this.administer;
},
checkboxChange(event) {
let idList = event.detail.value;
this.userLists.forEach((item) => {
if (idList.indexOf(item.uid + '') !== -1) {
item.checked = true;
} else {
item.checked = false;
}
})
if (idList.length == this.userLists.length) {
this.isAllSelect = true;
} else {
this.isAllSelect = false;
}
},
forGoods(val) {
let that = this;
if (!that.userLists.length) return
that.userLists.forEach((item) => {
if (val) {
item.checked = true;
} else {
item.checked = false;
}
})
},
checkboxAllChange(event) {
let value = event.detail.value;
if (value.length) {
if(this.userLists.length>100){
this.$util.Tips({
title: '每次最多只提交100条数据'
});
}
this.isAllSelect = true;
this.forGoods(1)
} else {
this.isAllSelect = false;
this.forGoods(0)
}
},
},
onReachBottom(){
this.userList();
}
}
</script>
<style lang="scss" scoped>
/deep/checkbox .wx-checkbox-input.wx-checkbox-input-checked {
border: 1px solid $primary-admin !important;
background-color: $primary-admin !important;
}
/deep/checkbox:not([disabled]) .uni-checkbox-input:hover {
border-color: #d1d1d1 !important;
}
/deep/.empty-page{
margin-top: 20rpx;
}
.accountTitle{
background: #F5F5F5;
position: fixed;
left:0;
top:0;
width: 100%;
z-index: 99;
padding-bottom: 6rpx;
.sysTitle{
width: 100%;
position: relative;
font-weight: 500;
color: #333333;
font-size: 30rpx;
.iconfont{
position: absolute;
font-size: 42rpx;
left:20rpx;
width: 60rpx;
font-weight: 500;
}
}
}
.user-list{
padding: 20rpx 20rpx 0 20rpx;
.searchCon{
.search{
width: 526rpx;
height: 72rpx;
background: #FFFFFF;
border-radius: 50rpx;
padding: 0 34rpx;
&.on{
width: 618rpx;
}
.iconfont{
color: #999;
font-size: 32rpx;
margin-right: 16rpx;
}
.inputs{
font-size: 28rpx;
width: 100%;
height: 100%;
flex: 1;
}
.placeholder{
color: #ccc;
}
}
.edit{
width: 72rpx;
height: 72rpx;
background: #FFFFFF;
border-radius: 50%;
.iconfont {
color: #666;
font-size: 36rpx;
}
}
}
.list{
padding-bottom: 20rpx;
margin-top: 32rpx;
/deep/uni-checkbox .uni-checkbox-input{
margin: 0 20rpx 20rpx 0;
}
/deep/wx-checkbox .wx-checkbox-input{
margin: 0 20rpx 20rpx 0;
}
.item {
width: 100%;
background-color: #fff;
padding: 30rpx 24rpx;
box-sizing: border-box;
margin-bottom: 20rpx;
border-radius: 24rpx;
position: relative;
flex: 1;
.icon-ic_more{
position: absolute;
right: 20rpx;
top: 30rpx;
color: #999;
font-size: 40rpx;
}
.pictrue{
width: 96rpx;
height: 96rpx;
margin-right: 24rpx;
image {
width: 100%;
height: 100%;
border-radius: 50%;
}
}
.text{
flex: 1;
overflow: hidden;
.top{
.name {
max-width: 230rpx;
font-size: 28rpx;
font-weight: 600;
color: #333333;
font-family: PingFang SC, PingFang SC;
}
.svip {
width: 56rpx;
height: 26rpx;
background: linear-gradient(270deg, #484643 0%, #1F1B17 100%);
border-radius: 100rpx;
font-size: 18rpx;
font-family: PingFang SC, PingFang SC;
font-weight: 600;
color: #FDDAA4;
margin-left: 10rpx;
}
.vip{
width: 64rpx;
// height: 26rpx;
background: #FEF0D9;
border: 1px solid #FACC7D;
border-radius: 50rpx;
font-size: 18rpx;
font-family: PingFang SC, PingFang SC;
font-weight: 500;
color: #DFA541;
margin-left: 10rpx;
.iconfont {
font-size: 20rpx;
margin-right: 4rpx;
}
}
}
.phone{
font-size: 24rpx;
font-family: PingFang SC, PingFang SC;
font-weight: 400;
color: #999999;
margin-top: 4rpx;
}
.info {
font-size: 24rpx;
font-weight: 400;
color: #999999;
margin-top: 4rpx;
text {
color: #333333;
margin-right: 28rpx;
}
}
}
.bottom{
margin-top: 26rpx;
.bnt{
width: 144rpx;
height: 56rpx;
border:1px solid #ccc;
font-size: 24rpx;
font-family: PingFang SC, PingFang SC;
font-weight: 400;
color: #333333;
border-radius: 50rpx;
&~.bnt{
margin-left: 16rpx;
}
&.on{
border-color: #2A7EFB;
background-color: #2A7EFB;
color: #fff;
}
&.up{
border-color: #FF7E00;
color: #FF7E00;
}
}
}
}
}
.footerH {
height: calc(constant(safe-area-inset-bottom)); ///兼容 IOS<11.2/
height: calc(env(safe-area-inset-bottom)); ///兼容 IOS>11.2/
}
.footer {
box-sizing: border-box;
padding: 0 32rpx;
width: 100%;
height: 96rpx;
background-color: #fff;
position: fixed;
bottom: 0;
z-index: 30;
height: calc(96rpx + constant(safe-area-inset-bottom)); ///兼容 IOS<11.2/
height: calc(96rpx + env(safe-area-inset-bottom)); ///兼容 IOS>11.2/
padding-bottom: constant(safe-area-inset-bottom); ///兼容 IOS<11.2/
padding-bottom: env(safe-area-inset-bottom); ///兼容 IOS>11.2/
width: 100%;
left: 0;
/deep/uni-checkbox .uni-checkbox-input{
margin-bottom: 6rpx;
}
.bnt {
width: 160rpx;
height: 64rpx;
border-radius: 50rpx;
border: 1rpx solid #2A7EFB;
color: #2A7EFB;
font-size: 24rpx;
font-family: PingFang SC, PingFang SC;
font-weight: 500;
&~.bnt{
margin-left: 16rpx;
}
}
}
.edit-list{
background-color: #fff;
padding: 45rpx 34rpx;
.item{
font-family: PingFang SC, PingFang SC;
font-weight: 400;
color: #333333;
font-size: 32rpx;
text-align: center;
height: 106rpx;
line-height: 106rpx;
}
}
}
</style>

419
pages/admin/work/index.vue Normal file
View File

@@ -0,0 +1,419 @@
<template>
<view class="pagebox">
<!-- #ifdef MP || APP-PLUS -->
<NavBar titleText="工作台" :iconColor="iconColor" :textColor="iconColor" :isScrolling="isScrolling" showBack></NavBar>
<!-- #endif -->
<view class="headerBg">
<view :style="{ height: `${getHeight.barTop}px` }"></view>
<view :style="{ height: `${getHeight.barHeight}px` }"></view>
<view class="inner"></view>
</view>
<view class="page-content">
<view class="header acea-row row-middle">
<image :src="avatar" class="avatar"></image>
<view class="text-box">
<view class="flex-y-center">
<text class="fs-32 fw-500 lh-44rpx pr-16">{{ nickname }}</text>
<view class="h-42 flex-center fs-22 text--w111-fff pl-16 pr-14 rd-30rpx b-f"
@tap="checkIdentity" v-show="identity == 2">切换商城
<text class="iconfont icon-ic_rightarrow fs-22"></text>
</view>
</view>
<view class="pt-4 fs-22 lh-30rpx">{{ phone }}</view>
</view>
<!-- #ifdef MP-WEIXIN || APP-PLUS -->
<navigator url="/pages/admin/order_cancellation/index" hover-class="none">
<text class="iconfont icon-ic_Scan fs-40 text--w111-fff"></text>
</navigator>
<!-- #endif -->
</view>
<view class="today">
<view class="title-box">
<navigator class="link" url="/pages/admin/order/index" hover-class="none">
今日销售额(元)<text class="iconfont icon-ic_rightarrow"></text>
</navigator>
<view class="money">{{ after_price }}</view>
</view>
<view class="acea-row">
<view class="item">
<view class="num">{{ after_number }}</view>
<view class="">今日订单数</view>
</view>
<view class="item">
<view class="num">{{ after_pay_number }}</view>
<view class="">今日支付人数</view>
</view>
<view class="item">
<view class="num">{{ today_visits }}</view>
<view class="">今日浏览量</view>
</view>
</view>
</view>
<view class="goods grid-column-4 rd-24rpx bg--w111-fff mt-20">
<navigator url="/pages/admin/orderList/index?types=1" hover-class="none" class="w-full flex-col flex-center pt-28 pb-26rpx fs-26">
<view class="img-box">
<view class="img">
<view v-if="unshipped_count" class="num">{{ unshipped_count > 99 ? '99+' : unshipped_count }}</view>
<image :src="imgHost+'/statics/images/admin-work-order1.png'" mode=""></image>
</view>
</view>
<view class="pt-12">待发货</view>
</navigator>
<navigator url="/pages/admin/refundOrderList/index" hover-class="none" class="w-full flex-col flex-center pt-28 pb-26rpx fs-26">
<view class="img-box">
<view class="img">
<view v-if="refunding_count" class="num">{{ refunding_count > 99 ? '99+' : refunding_count }}</view>
<image :src="imgHost+'/statics/images/admin-work-order2.png'" mode=""></image>
</view>
</view>
<view class="pt-12">待售后</view>
</navigator>
<navigator url="/pages/admin/goods/index?type=4" hover-class="none" class="w-full flex-col flex-center pt-28 pb-26rpx fs-26">
<view class="img-box">
<view class="img">
<view v-if="outofstock" class="num">{{ outofstock > 99 ? '99+' : outofstock }}</view>
<image :src="imgHost+'/statics/images/admin-work-order3.png'" mode=""></image>
</view>
</view>
<view class="pt-12">待补货</view>
</navigator>
<navigator url="/pages/admin/goods/index?type=5" hover-class="none" class="w-full flex-col flex-center pt-28 pb-26rpx fs-26">
<view class="img-box">
<view class="img">
<view v-if="policeforce" class="num">{{ policeforce > 99 ? '99+' : policeforce }}</view>
<image :src="imgHost+'/statics/images/admin-work-order4.png'" mode=""></image>
</view>
</view>
<view class="pt-12">库存预警</view>
</navigator>
</view>
<view class="pt-34 pb-40 rd-24rpx mt-20 bg--w111-fff">
<view class="pl-28 fs-30 fw-500 lh-44rpx">店铺管理</view>
<view class="grid-column-4">
<navigator class="w-full py-24 flex-col flex-center" url="/pages/admin/goods/index" hover-class="none">
<image class="w-48 h-48" :src="imgHost+'/statics/images/admin-work-menu1.png'" mode=""></image>
<view class="pt-20">商品管理</view>
</navigator>
<navigator class="w-full py-24 flex-col flex-center" url="/pages/admin/orderList/index" hover-class="none">
<image class="w-48 h-48" :src="imgHost+'/statics/images/admin-work-menu2.png'" mode=""></image>
<view class="pt-20">订单管理</view>
</navigator>
<!-- #ifdef MP-WEIXIN || APP-PLUS -->
<navigator class="w-full py-24 flex-col flex-center" url="/pages/admin/order_cancellation/index" hover-class="none">
<image class="w-48 h-48" :src="imgHost+'/statics/images/admin-work-menu3.png'" mode=""></image>
<view class="pt-20">扫码核销</view>
</navigator>
<!-- #endif -->
<navigator class="w-full py-24 flex-col flex-center" url="/pages/admin/refundOrderList/index" hover-class="none">
<image class="w-48 h-48" :src="imgHost+'/statics/images/admin-work-menu4.png'" mode=""></image>
<view class="pt-20">售后维权</view>
</navigator>
<navigator class="w-full py-24 flex-col flex-center" url="/pages/admin/user/list" hover-class="none">
<image class="w-48 h-48" :src="imgHost+'/statics/images/admin-work-menu5.png'" mode=""></image>
<view class="pt-20">用户管理</view>
</navigator>
<navigator class="w-full py-24 flex-col flex-center" url="/pages/behalf/user_list/index" hover-class="none">
<image class="w-48 h-48" :src="imgHost+'/statics/images/admin-work-menu6.png'" mode=""></image>
<view class="pt-20">代客下单</view>
</navigator>
<view class="w-full py-24 flex-col flex-center" @tap="toChat">
<image class="w-48 h-48" src="../static/footer5-1.png" mode=""></image>
<view class="pt-20">客服聊天</view>
</view>
<!-- #ifdef MP-WEIXIN || APP-PLUS -->
<view class="w-full py-24 flex-col flex-center" @tap="toGoods">
<image class="w-48 h-48" :src="imgHost+'/statics/images/admin-work-menu3.png'" mode=""></image>
<view class="pt-20">扫描商品</view>
</view>
<!-- #endif -->
<!-- #ifdef H5 -->
<view class="w-full py-24 flex-col flex-center" v-if="isWechat" @tap="toGoods">
<image class="w-48 h-48" :src="imgHost+'/statics/images/admin-work-menu3.png'" mode=""></image>
<view class="pt-20">扫描商品</view>
</view>
<!-- #endif -->
</view>
</view>
</view>
<footerPage></footerPage>
</view>
</template>
<script>
// #ifdef MP || APP-PLUS
import NavBar from '@/components/NavBar.vue';
// #endif
import footerPage from '../components/footerPage/index.vue';
import { HTTP_REQUEST_URL } from '@/config/app';
import {
deliveryInfo,
getOrderStaging,
getOrderTime,
} from '@/api/admin.js';
import { getUserInfo, checkIdentityApi } from '@/api/user.js';
export default {
components: {
// #ifdef MP || APP-PLUS
NavBar,
// #endif
footerPage,
},
data() {
return {
imgHost: HTTP_REQUEST_URL,
// #ifdef MP || APP-PLUS
iconColor: '#FFFFFF',
isScrolling: false,
// #endif
avatar: '',
nickname: '',
phone: '',
outofstock: 0, // 待补货
policeforce: 0, // 库存预警
unshipped_count: 0, // 待发货
refunding_count: 0, // 待售后
after_price: 0, // 今日销售额
after_number: 0, // 今日订单数
after_pay_number: 0, // 今日支付人数
today_visits: 0, // 今日浏览量
getHeight: this.$util.getWXStatusHeight(),
identity: 0,
// #ifdef H5
isWechat: this.$wechat.isWeixin(),
// #endif
}
},
onLoad() {
console.log(this.imgHost,'host');
this.getUserInfo();
this.getOrderTime();
this.getOrderStaging();
},
methods: {
getUserInfo() {
getUserInfo().then(res => {
const {
avatar,
nickname,
phone,
} = res.data;
this.avatar = avatar;
this.nickname = nickname;
this.phone = phone;
this.identity = res.data.identity;
this.$store.commit('UPDATE_USERINFO', res.data);
});
},
getOrderTime() {
getOrderTime({
type: 1,
}).then(res => {
const {
after_number,
after_pay_number,
after_price,
today_visits,
} = res.data;
this.after_number = after_number;
this.after_pay_number = after_pay_number;
this.after_price = after_price;
this.today_visits = today_visits;
});
},
getOrderStaging() {
getOrderStaging().then(res => {
const {
outofstock,
policeforce,
unshipped_count,
refunding_count,
} = res.data;
this.outofstock = outofstock;
this.policeforce = policeforce;
this.unshipped_count = Number(unshipped_count);
this.refunding_count = Number(refunding_count);
});
},
checkIdentity(){
checkIdentityApi({identity: 0}).then(res=>{
getUserInfo().then((res) => {
this.$store.commit('UPDATE_USERINFO', res.data);
uni.switchTab({
url: '/pages/index/index'
})
});
}).catch(err=>{
return this.$util.Tips({
title: err
});
})
},
toChat(){
// #ifdef H5
this.$util.JumpPath(`${HTTP_REQUEST_URL}/kefu`);
// #endif
// #ifdef MP-WEIXIN
uni.navigateTo({
url: `/pages/annex/web_view/index?url=${HTTP_REQUEST_URL}/kefu`
});
// #endif
},
toGoods(){
var self = this;
// #ifdef MP || APP
uni.scanCode({
scanType: ['barCode'],
success(res) {
uni.navigateTo({
url: `/pages/admin/goods/index?keyword=${res.result}`
});
},
fail(res) {
console.log(res);
}
})
// #endif
//#ifdef H5
this.$wechat.wechatEvevt('scanQRCode', {
needResult: 1,
scanType: ["barCode"]
}).then(res => {
let result = res.resultStr;
uni.navigateTo({
url: `/pages/admin/goods/index?keyword=${result}`
});
});
//#endif
}
},
}
</script>
<style lang="scss" scoped>
.pagebox {
position: relative;
overflow: hidden;
}
.headerBg {
position: absolute;
top: 0;
left: -25%;
width: 150%;
border-bottom-right-radius: 100%;
border-bottom-left-radius: 100%;
background: linear-gradient(270deg, $gradient-primary-admin 0%, $primary-admin 100%);
.inner {
height: 356rpx;
}
}
.page-content {
position: relative;
padding: 0 20rpx;
.header {
padding: 22rpx 20rpx 32rpx 12rpx;
.avatar {
width: 80rpx;
height: 80rpx;
border-radius: 50%;
}
.text-box {
flex: 1;
padding-left: 16rpx;
color: #FFFFFF;
}
}
.today {
border-radius: 24rpx;
background: #FFFFFF;
.title-box {
padding: 40rpx 0 0 40rpx;
}
.link {
display: inline-block;
vertical-align: middle;
font-size: 24rpx;
line-height: 34rpx;
color: #999999;
}
.iconfont {
margin-left: 4rpx;
font-size: 24rpx;
}
.money {
margin-top: 16rpx;
font-family: SemiBold;
font-size: 56rpx;
line-height: 56rpx;
color: #FF7E00;
}
.item {
flex: 1;
padding: 54rpx 0 38rpx;
text-align: center;
font-size: 24rpx;
line-height: 34rpx;
color: #999999;
}
.num {
margin-bottom: 12rpx;
font-family: SemiBold;
font-size: 36rpx;
line-height: 36rpx;
color: #333333;
}
}
.goods {
.img-box {
position: relative;
width: 76rpx;
height: 76rpx;
border-radius: 50%;
margin: 0 auto 12rpx;
}
.img {
width: 100%;
height: 100%;
}
.num {
position: absolute;
top: -6rpx;
left: 58rpx;
z-index: 2;
min-width: 24rpx;
height: 24rpx;
padding: 0 8rpx;
border-radius: 12rpx;
background: #FF7E00;
font-weight: 500;
font-size: 18rpx;
line-height: 24rpx;
color: #FFFFFF;
}
image {
width: 100%;
height: 100%;
}
}
}
.b-f{
border: 1rpx solid #fff;
}
</style>

View File

@@ -0,0 +1,363 @@
<template>
<view class="container">
<view class="goods-box" v-if="list.cart_info">
<view class="header">订单号:{{ list.order_id }}</view>
<view class='item acea-row' v-for="(item,index) in list.cart_info" :key="index">
<view class='pictrue'>
<image :src="item.cart_info.productInfo.attrInfo.image" mode=""></image>
</view>
<view class='text acea-row row-column row-between'>
<view class="title line2">{{ item.cart_info.productInfo.store_name }}</view>
<view class='money acea-row row-between row-middle'>
<view class="orangcol">
已核销:<text>{{item.write_times - item.surplus_num}}</text>/{{item.write_times}}
</view>
<view v-if="item.is_writeoff == 1" class="txt acea-row row-middle">
核销已完成
</view>
<view v-else class="txt acea-row row-middle">
本次核销:
<view class='carnum acea-row row-center-wrapper'>
<view v-if="item.surplus_num_input == 1" class="reduce bggary">
<text class="iconfont icon-ic_Reduce"></text>
</view>
<view v-else class="reduce" @click.stop='subCart(item,index)'>
<text class="iconfont icon-ic_Reduce"></text>
</view>
<!-- <view class='nums'>{{item.surplus_num_input}}</view> -->
<input v-model="item.surplus_num_input" class='nums' type="number" @input="numInput" @blur="numBlur" />
<view v-if="item.surplus_num_input == item.surplus_num" class="plus bggary">
<text class="iconfont icon-ic_increase"></text>
</view>
<view v-else class="plus" @click.stop='addCart(item,index)'>
<text class="iconfont icon-ic_increase"></text>
</view>
</view>
</view>
</view>
</view>
</view>
</view>
<view class="record-box" v-if="recordList.length">
<view class="header">核销记录</view>
<view class="list">
<view class="item acea-row row-middle row-between" v-for="(item, index) in recordList" :key="index">
<view class="left">{{ item.add_time }}</view>
<view class="right">核销{{item.writeoff_num}}次</view>
</view>
</view>
</view>
<view class="footer acea-row row-middle row-between">
<navigator class="btn" url="/pages/admin/work/index" hover-class="none">返回工作台</navigator>
<view v-if="list.cart_info && list.cart_info[0].surplus_num" class="btn" @click="verification">确认核销</view>
</view>
</view>
</template>
<script>
import {
orderWriteoffInfo,
orderVerific,
orderCartInfo,
orderWriteoff,
orderWirteOffRecords,
} from '@/api/admin'
export default {
data() {
return {
list: {},
recordList: [],
lists: {},
checkModel: [],
nums: [],
auth: 1,
id: 0,
}
},
watch: {
checkModel() {
if (this.lengt == this.checkModel.length) {
this.checked = true;
} else {
this.checked = false;
}
}
},
onLoad(option) {
this.auth = option.auth || 1;
this.id = option.id;
this.getCartList()
this.orderWirteOffRecords()
},
methods: {
numInput(event) {
let value = event.detail.value;
if (value) {
value = Number(value);
this.$nextTick(() => {
if (value > this.list.cart_info[0].surplus_num) {
this.list.cart_info[0].surplus_num_input = this.list.cart_info[0].surplus_num;
} else if (value < 1) {
this.list.cart_info[0].surplus_num_input = 1;
}
});
}
},
numBlur(event) {
let value = event.detail.value;
if (!value) {
this.$nextTick(() => {
this.list.cart_info[0].surplus_num_input = 1;
});
}
},
orderWirteOffRecords() {
orderWirteOffRecords(this.id, {
product_type: 4
}).then(res => {
this.recordList = res.data.list;
});
},
num() {
for (let index = 0; index < this.lists.cart_info.length; index++) {
this.nums.push({
num: 0
});
}
},
getCartList: function() {
orderCartInfo({
oid: this.id,
auth: this.auth,
}).then(res => {
let list = res.data;
for (let i = 0; i < list.cart_info.length; i++) {
list.cart_info[i].surplus_num_input = 1
}
this.list = res.data
this.lists = JSON.parse(JSON.stringify(res.data))
this.listlet = res.data.cart_info.length
this.$set(this.attr, 'id', this.list.id);
this.num()
}).catch(res => {
this.$util.Tips({
title: res
});
});
},
subCart(item, index) {
this.list.cart_info[index].surplus_num_input--;
},
addCart(item, index) {
this.list.cart_info[index].surplus_num_input++;
},
verification() {
let that = this;
let cart_ids = [];
for (let i = 0; i < this.list.cart_info.length; i++) {
cart_ids.push({
cart_id: this.list.cart_info[i].cart_id,
cart_num: this.list.cart_info[i].surplus_num_input,
});
}
orderWriteoff({
auth: this.auth,
oid: this.id,
cart_ids: cart_ids
}).then(res => {
// uni.hideLoading();
this.$util.Tips({
title: res.msg
}, () => {
this.orderWirteOffRecords();
});
this.list.cart_info[0].surplus_num = this.list.cart_info[0].surplus_num - this.list.cart_info[0].surplus_num_input;
// that.getCartList();
}).catch(err => {
this.$util.Tips({
title: err
});
// uni.hideLoading();
});
}
},
}
</script>
<style lang="scss" scoped>
.container {
padding: 22rpx 20rpx;
}
.goods-box {
padding: 32rpx 24rpx;
border-radius: 24rpx;
background: #FFFFFF;
.header {
margin-bottom: 26rpx;
font-size: 28rpx;
line-height: 40rpx;
color: #333333;
}
.pictrue {
width: 136rpx;
height: 136rpx;
border-radius: 16rpx;
}
image {
width: 100%;
height: 100%;
border-radius: 16rpx;
}
.text {
flex: 1;
padding-left: 20rpx;
}
.title {
font-size: 28rpx;
line-height: 40rpx;
color: #333333;
}
.orangcol {
font-size: 24rpx;
line-height: 34rpx;
color: #666666;
text {
color: #2A7EFB;
}
}
.txt {
font-size: 24rpx;
line-height: 34rpx;
color: #666666;
}
.reduce {
width: 32rpx;
height: 36rpx;
text-align: left;
line-height: 36rpx;
.iconfont {
font-size: 24rpx;
color: #333333;
}
&.bggary {
.iconfont {
color: #CCCCCC;
}
}
}
.plus {
width: 32rpx;
height: 36rpx;
text-align: right;
line-height: 36rpx;
.iconfont {
font-size: 24rpx;
color: #333333;
}
&.bggary {
.iconfont {
color: #CCCCCC;
}
}
}
.nums {
width: 72rpx;
height: 36rpx;
border-radius: 4rpx;
background: #F5F5F5;
text-align: center;
font-family: SemiBold;
font-weight: 600;
font-size: 24rpx;
line-height: 36rpx;
color: #333333;
}
.iconfont {
font-size: 24rpx;
}
}
.record-box {
padding-bottom: 30rpx;
border-radius: 24rpx;
margin-top: 20rpx;
background: #FFFFFF;
.header {
padding: 32rpx 0 16rpx 24rpx;
font-weight: 500;
font-size: 30rpx;
line-height: 42rpx;
color: #333333;
}
.list {
padding: 0 40rpx;
}
.item {
height: 88rpx;
border-bottom: 1rpx solid #F1F1F1;
font-size: 28rpx;
color: #333333;
.right {
color: #666666;
}
}
}
.footer {
position: fixed;
bottom: 0;
left: 0;
width: 100%;
height: 112rpx;
height: calc(112rpx + constant(safe-area-inset-bottom));
height: calc(112rpx + env(safe-area-inset-bottom));
padding: 0 20rpx;
padding-bottom: constant(safe-area-inset-bottom);
padding-bottom: env(safe-area-inset-bottom);
background: #FFFFFF;
.btn {
flex: 1;
height: 72rpx;
border: 2rpx solid #2A7EFB;
border-radius: 36rpx;
margin-right: 16rpx;
text-align: center;
font-weight: 500;
font-size: 26rpx;
line-height: 68rpx;
color: #2A7EFB;
&:last-child {
margin-right: 0;
background: #2A7EFB;
color: #FFFFFF;
}
}
}
.item ~ .item{
margin-top: 40rpx;
}
</style>

View File

@@ -0,0 +1,90 @@
<template>
<view class="px-20 mt-24">
<view class="px-24 rd-24rpx bg--w111-fff" v-for="(panel, i) in records" :key="i">
<view class="h-104 fs-24 flex-y-center b-border">核销时间:{{ panel.time }}</view>
<view class="py-32">
<view class="item flex" v-for="item in panel.list" :key="item.id">
<image :src="item.cartInfo.productInfo.attrInfo?item.cartInfo.productInfo.attrInfo.image:item.cartInfo.productInfo.image" class="w-136 h-136 rd-16rpx"></image>
<view class="flex-1 flex-col flex-between-center ml-20">
<view class="w-full line2 fs-28 lh-40rpx">{{ item.cartInfo.productInfo.store_name }}</view>
<view class="w-full flex-between-center">
<BaseMoney :money="item.cartInfo.productInfo.price" symbolSize="20" integerSize="32" decimalSize="20"></BaseMoney>
<view class="fs-24 text--w111-999">核销{{ item.writeoff_num }}件</view>
</view>
</view>
</view>
</view>
</view>
<emptyPage v-if="!records.length && page" title="暂无核销记录~" src="/statics/images/noOrder.gif"></emptyPage>
</view>
</template>
<script>
import {orderWirteOffRecords} from '@/api/admin'
import emptyPage from '@/components/emptyPage.vue'
export default {
components: {
emptyPage
},
data() {
return {
id: '',
page: 1,
limit: 10,
list: [],
records: [],
loadend: false,
loading: false,
}
},
onLoad(option) {
this.id = option.id;
this.orderWirteOffRecords();
},
methods: {
orderWirteOffRecords() {
if (this.loadend || this.loading) {
return;
}
this.loading = true;
orderWirteOffRecords(this.id, {
product_type: 0,
page: this.page,
limit: this.limit,
}).then(res => {
const list = res.data.list;
let records = [];
this.list = this.list.concat(list);
for (let i = 0; i < this.list.length; i++) {
records.push({
time: this.list[i].time,
list: [this.list[i]],
});
for (let j = i + 1; j < this.list.length; j++) {
if (this.list[i].time == this.list[j].time) {
records[records.length - 1].list.push(this.list[j]);
this.list.splice(j, 1);
j--;
}
}
}
this.records = records;
this.loadend = list.length < this.limit;
this.page = this.page + 1;
this.loading = false;
}).catch(err => {
this.loading = false;
});
},
},
}
</script>
<style lang="scss" scoped>
.b-border{
border-bottom: 1rpx solid #EEEEEE;
}
.item ~ .item{
margin-top: 40rpx;
}
</style>