订单列表优化

This commit is contained in:
邓皓元 2019-03-06 15:49:08 +08:00
parent a1ca7883ab
commit d25fa514db
26 changed files with 1520 additions and 401 deletions

View File

@ -107,6 +107,13 @@ class OrderRepository extends Repository
if (isset($conditions['endtime'])) {
$query->where('order_at', '<=', Carbon::parse($conditions['endtime']));
}
if (isset($conditions['used'])) {
$operator = $conditions['used'] ? '>' : '=';
$query->whereHas('cards', function ($relation) use ($conditions) {
$relation->withoutTrashed()->where('type', $conditions['type'])->where('virtual_order_id', '<>', 0);
}, $operator, 0);
}
});
return $this;

View File

@ -36,7 +36,9 @@ class OrderService extends Service
$carrierOperators = app(Dicts::class)->get('carrier_operator');
$res = $this->orderRepository->withConditions($conditions)->applyConditions()->paginate($limit);
$res = $this->orderRepository->withCount(['cards' => function ($query) {
$query->where('virtual_order_id', '<>', 0);
}])->withConditions($conditions)->applyConditions()->paginate($limit);
$res->map(function ($item) use ($carrierOperators) {
$item->pay_channel_name = CommonService::namePayChannel($item->pay_channel);

View File

@ -134,7 +134,7 @@ class OrderService extends Service
$attributes['product_id'] = $product->id;
$rule['required'][] = 'required';
$rule['type'][] = 'required';
$rule['company_id'][] = 'required';
$rule['product_id'][] = 'required';
$rule['counts'][] = 'required';

View File

@ -68,6 +68,6 @@ class Order extends Model
public function cards()
{
return $this->belongsToMany(Card::class, 'real_order_cards', 'sim', 'sim');
return $this->hasMany(OrderCardPartition::class, 'order_id', 'id');
}
}

View File

@ -88,6 +88,7 @@ class Order extends Model
protected $casts = [
'extends' => 'array',
'area' => 'array',
];
protected $fillable = [

View File

@ -0,0 +1,221 @@
<template>
<div v-transfer-dom :data-transfer="transfer">
<transition name="fade">
<div :class="maskClasses" :style="maskStyle" v-show="visible" v-if="mask" @click="handleMask"></div>
</transition>
<div :class="wrapClasses" :style="maskStyle" @click="handleWrapClick">
<transition :name="'move-' + placement">
<div :class="classes" :style="mainStyles" v-show="visible">
<div :class="contentClasses" ref="content">
<a class="ivu-drawer-close" v-if="closable" @click="close">
<slot name="close">
<Icon type="ios-close"></Icon>
</slot>
</a>
<div :class="[prefixCls + '-header']" v-if="showHead"><slot name="header"><div :class="[prefixCls + '-header-inner']">{{ title }}</div></slot></div>
<div :class="[prefixCls + '-body']" :style="styles"><slot></slot></div>
</div>
</div>
</transition>
</div>
</div>
</template>
<script>
import { oneOf } from 'utils/assist';
import TransferDom from 'utils/transfer-dom';
import Emitter from 'mixins/emitter';
import ScrollbarMixins from 'mixins/mixins-scrollbar';
const prefixCls = 'ivu-drawer';
export default {
name: 'MDrawer',
mixins: [ Emitter, ScrollbarMixins ],
directives: { TransferDom },
props: {
value: {
type: Boolean,
default: false
},
title: {
type: String
},
width: {
type: [Number, String],
default: 256
},
closable: {
type: Boolean,
default: true
},
maskClosable: {
type: Boolean,
default: true
},
mask: {
type: Boolean,
default: true
},
maskStyle: {
type: Object
},
styles: {
type: Object
},
scrollable: {
type: Boolean,
default: false
},
placement: {
validator (value) {
return oneOf(value, ['left', 'right']);
},
default: 'right'
},
zIndex: {
type: Number,
default: 1000
},
transfer: {
type: Boolean,
default () {
return !this.$IVIEW || this.$IVIEW.transfer === '' ? true : this.$IVIEW.transfer;
}
},
className: {
type: String
},
inner: {
type: Boolean,
default: false
}
},
data () {
return {
prefixCls: prefixCls,
visible: this.value,
wrapShow: false,
showHead: true,
};
},
computed: {
wrapClasses () {
return [
`${prefixCls}-wrap`,
{
[`${prefixCls}-hidden`]: !this.wrapShow,
[`${this.className}`]: !!this.className,
[`${prefixCls}-no-mask`]: !this.mask,
[`${prefixCls}-wrap-inner`]: this.inner
}
];
},
mainStyles () {
let style = {};
const width = parseInt(this.width);
const styleWidth = {
width: width <= 100 ? `${width}%` : `${width}px`
};
Object.assign(style, styleWidth);
return style;
},
contentClasses () {
return [
`${prefixCls}-content`,
{
[`${prefixCls}-content-no-mask`]: !this.mask
}
];
},
classes () {
return [
`${prefixCls}`,
`${prefixCls}-${this.placement}`,
{
[`${prefixCls}-no-header`]: !this.showHead,
[`${prefixCls}-inner`]: this.inner
}
];
},
maskClasses () {
return [
`${prefixCls}-mask`,
{
[`${prefixCls}-mask-inner`]: this.inner
}
];
}
},
methods: {
close () {
this.visible = false;
this.$emit('input', false);
this.$emit('on-close');
},
handleMask () {
if (this.maskClosable && this.mask) {
this.close();
}
},
handleWrapClick (event) {
// use indexOf,do not use === ,because ivu-modal-wrap can have other custom className
const className = event.target.getAttribute('class');
if (className && className.indexOf(`${prefixCls}-wrap`) > -1) this.handleMask();
},
},
mounted () {
if (this.visible) {
this.wrapShow = true;
}
let showHead = true;
if (this.$slots.header === undefined && !this.title) {
showHead = false;
}
this.showHead = showHead;
},
beforeDestroy () {
this.removeScrollEffect();
},
watch: {
value (val) {
this.visible = val;
},
visible (val) {
if (val === false) {
this.timer = setTimeout(() => {
this.wrapShow = false;
this.removeScrollEffect();
}, 300);
} else {
if (this.timer) clearTimeout(this.timer);
this.wrapShow = true;
if (!this.scrollable) {
this.addScrollEffect();
}
}
this.broadcast('Table', 'on-visible-change', val);
this.broadcast('Slider', 'on-visible-change', val); // #2852
this.$emit('on-visible-change', val);
},
scrollable (val) {
if (!val) {
this.addScrollEffect();
} else {
this.removeScrollEffect();
}
},
title (val) {
if (this.$slots.header === undefined) {
this.showHead = !!val;
}
}
}
};
</script>

View File

@ -0,0 +1,3 @@
import Drawer from './drawer.vue';
export default Drawer;

View File

@ -235,11 +235,3 @@ export default {
}
};
</script>
<style scoped>
>>> .ivu-table td {
word-break: keep-all;
white-space: nowrap;
}
</style>

View File

@ -136,9 +136,9 @@
<script>
import tableHead from "./table-head.vue";
import tableBody from "./table-body.vue";
import { oneOf, getStyle, deepCopy, getScrollBarSize } from "./assist";
import { on, off } from "./dom";
import Csv from "./csv";
import { oneOf, getStyle, deepCopy, getScrollBarSize } from "utils/assist";
import { on, off } from "utils/dom";
import Csv from "utils/csv";
import ExportCsv from "./export-csv";
import elementResizeDetectorMaker from "element-resize-detector";
import {
@ -1079,3 +1079,9 @@ export default {
}
};
</script>
<style scoped>
>>> .ivu-table-cell {
word-break: keep-all;
}
</style>

View File

@ -1,4 +1,4 @@
import { deepCopy } from './assist';
import { deepCopy } from 'utils/assist';
const convertColumnOrder = (columns, fixedType) => {
let list = [];

34
frontend/src/mixins/emitter.js Executable file
View File

@ -0,0 +1,34 @@
function broadcast(componentName, eventName, params) {
this.$children.forEach(child => {
const name = child.$options.name;
if (name === componentName) {
child.$emit.apply(child, [eventName].concat(params));
} else {
// todo 如果 params 是空数组,接收到的会是 undefined
broadcast.apply(child, [componentName, eventName].concat([params]));
}
});
}
export default {
methods: {
dispatch(componentName, eventName, params) {
let parent = this.$parent || this.$root;
let name = parent.$options.name;
while (parent && (!name || name !== componentName)) {
parent = parent.$parent;
if (parent) {
name = parent.$options.name;
}
}
if (parent) {
parent.$emit.apply(parent, [eventName].concat(params));
}
},
broadcast(componentName, eventName, params) {
broadcast.call(this, componentName, eventName, params);
}
}
};

View File

@ -0,0 +1,40 @@
// used for Modal & $Spin & Drawer
import { getScrollBarSize } from 'utils/assist';
export default {
methods: {
checkScrollBar () {
let fullWindowWidth = window.innerWidth;
if (!fullWindowWidth) { // workaround for missing window.innerWidth in IE8
const documentElementRect = document.documentElement.getBoundingClientRect();
fullWindowWidth = documentElementRect.right - Math.abs(documentElementRect.left);
}
this.bodyIsOverflowing = document.body.clientWidth < fullWindowWidth;
if (this.bodyIsOverflowing) {
this.scrollBarWidth = getScrollBarSize();
}
},
checkMaskInVisible () {
let masks = document.getElementsByClassName('ivu-modal-mask') || [];
return Array.from(masks).every(m => m.style.display === 'none' || m.classList.contains('fade-leave-to'));
},
setScrollBar () {
if (this.bodyIsOverflowing && this.scrollBarWidth !== undefined) {
document.body.style.paddingRight = `${this.scrollBarWidth}px`;
}
},
resetScrollBar () {
document.body.style.paddingRight = '';
},
addScrollEffect () {
this.checkScrollBar();
this.setScrollBar();
document.body.style.overflow = 'hidden';
},
removeScrollEffect() {
if (this.checkMaskInVisible()) {
document.body.style.overflow = '';
this.resetScrollBar();
}
}
}
};

View File

@ -4,7 +4,8 @@ const state = {
real_orders: {},
cards: [],
selected: [],
params: {}
orderParams: {},
cardParams: {}
};
const mutations = {
@ -17,17 +18,49 @@ const mutations = {
SET_REAL_ORDER_SELECTED(state, data) {
state.selected = data;
},
PUSH_REAL_ORDER_SELECTED(state, obj) {
PUSH_REAL_ORDER_SELECTED(state, { order_id, cards }) {
let obj = { id: order_id, cards };
state.selected.push(obj);
},
REMOVE_REAL_ORDER_SELECTED(state, orderId) {
REMOVE_REAL_ORDER_SELECTED(state, order_id) {
let index = state.selected.findIndex(item => {
return item.id === orderId;
return item.id === order_id;
});
if (index !== -1) {
state.selected.splice(index, 1);
}
},
PUSH_CARD_SELECTED(state, { order_id, sim }) {
let select = state.selected.find(item => {
return item.id === order_id;
});
if (!select) {
state.selected.push({ id: order_id, cards: [sim] });
} else {
select.cards.push(sim);
}
},
REMOVE_CARD_SELECTED(state, { order_id, sim }) {
let select = state.selected.find(item => {
return item.id === order_id;
});
if (select) {
let index = select.cards.indexOf(sim);
if (index !== -1) {
select.cards.splice(index, 1);
if (!select.cards.length) {
let i = state.selected.findIndex(item => {
return item.id === order_id;
});
state.selected.splice(i, 1);
}
}
}
}
};
@ -41,11 +74,11 @@ const actions = {
},
getCards(context, params) {
return new Promise((resolve, reject) => {
if (JSON.stringify(this.params) == JSON.stringify(params)) {
if (JSON.stringify(this.cardParams) == JSON.stringify(params)) {
return resolve(context.state.cards);
}
this.params = params;
this.cardParams = params;
API.cards(params).then(res => {
if (res.code === 0) {

View File

@ -0,0 +1,77 @@
// Thanks to: https://github.com/airyland/vux/blob/v2/src/directives/transfer-dom/index.js
// Thanks to: https://github.com/calebroseland/vue-dom-portal
/**
* Get target DOM Node
* @param {(Node|string|Boolean)} [node=document.body] DOM Node, CSS selector, or Boolean
* @return {Node} The target that the el will be appended to
*/
function getTarget (node) {
if (node === void 0) {
node = document.body
}
if (node === true) { return document.body }
return node instanceof window.Node ? node : document.querySelector(node)
}
const directive = {
inserted (el, { value }, vnode) {
if ( el.dataset && el.dataset.transfer !== 'true') return false;
el.className = el.className ? el.className + ' v-transfer-dom' : 'v-transfer-dom';
const parentNode = el.parentNode;
if (!parentNode) return;
const home = document.createComment('');
let hasMovedOut = false;
if (value !== false) {
parentNode.replaceChild(home, el); // moving out, el is no longer in the document
getTarget(value).appendChild(el); // moving into new place
hasMovedOut = true
}
if (!el.__transferDomData) {
el.__transferDomData = {
parentNode: parentNode,
home: home,
target: getTarget(value),
hasMovedOut: hasMovedOut
}
}
},
componentUpdated (el, { value }) {
if ( el.dataset && el.dataset.transfer !== 'true') return false;
// need to make sure children are done updating (vs. `update`)
const ref$1 = el.__transferDomData;
if (!ref$1) return;
// homes.get(el)
const parentNode = ref$1.parentNode;
const home = ref$1.home;
const hasMovedOut = ref$1.hasMovedOut; // recall where home is
if (!hasMovedOut && value) {
// remove from document and leave placeholder
parentNode.replaceChild(home, el);
// append to target
getTarget(value).appendChild(el);
el.__transferDomData = Object.assign({}, el.__transferDomData, { hasMovedOut: true, target: getTarget(value) });
} else if (hasMovedOut && value === false) {
// previously moved, coming back home
parentNode.replaceChild(el, home);
el.__transferDomData = Object.assign({}, el.__transferDomData, { hasMovedOut: false, target: getTarget(value) });
} else if (value) {
// already moved, going somewhere else
getTarget(value).appendChild(el);
}
},
unbind (el) {
if (el.dataset && el.dataset.transfer !== 'true') return false;
el.className = el.className.replace('v-transfer-dom', '');
const ref$1 = el.__transferDomData;
if (!ref$1) return;
if (el.__transferDomData.hasMovedOut === true) {
el.__transferDomData.parentNode && el.__transferDomData.parentNode.appendChild(el)
}
el.__transferDomData = null
}
};
export default directive;

View File

@ -1,11 +1,12 @@
<template>
<Modal
:closable="true"
:closable="false"
:mask-closable="false"
:title="'选择流量卡'"
@on-visible-change="visibleChange"
v-model="my_show"
width="1440"
:z-index="source === 0 ? 2000 : 1000"
>
<div class="page-handle-wrap">
<ul class="handle-wraper bd-b">
@ -111,9 +112,12 @@
:loading="orderLoading"
:columns="orderColumns"
:data="orders ? orders.data : []"
@on-row-dblclick="getCards"
@on-selection-change="handleSelectOrder"
@on-row-dblclick="handleOrderRowDblclick"
></Table>
<ul class="common-tips-wraper umar-t5">
<li class="t-title">提示</li>
<li class="t-content">双击可以查看订单卡数据</li>
</ul>
<div class="page-turn-wrap" v-if="orders">
<Page
@ -141,7 +145,9 @@
<footer class="ta-c" slot="footer">
<Button @click="clear" class="w-80 umar-r5" ghost type="primary">取消</Button>
<Button :loading="loading" @click="ok" class="w-80" type="primary">提交</Button>
<Button v-if="source === 0" :loading="loading" @click="ok" class="w-80" type="primary">确定</Button>
<Button v-if="source === 1" :loading="loading" @click="order" class="w-80" type="primary">创建订单</Button>
<Button v-if="source === 2" :loading="loading" @click="ok" class="w-80" type="primary">提交</Button>
</footer>
</Modal>
</template>
@ -154,7 +160,7 @@
}
>>> .ivu-table {
font-size: 11px;
font-size: 12px;
}
</style>

View File

@ -92,7 +92,7 @@
<ul>
<li class="ui-list">
<div class="ui-list-title">收货地址:</div>
<div class="ui-list-content">{{data.area}} {{data.address}}</div>
<div class="ui-list-content">{{data.area.join(' ')}} {{data.address}}</div>
</li>
<li class="ui-list">

View File

@ -1,11 +1,12 @@
<template>
<Drawer
<MDrawer
:closable="false"
:mask-closable="false"
:title="data ? '编辑订单' : '创建订单'"
@on-visible-change="visibleChange"
v-model="my_show"
width="500"
:mask-style="{ 'z-index': source === 1 ? 2000 : 1000}"
>
<div class="page-edit-wrap uinn-lr20">
<ui-loading :show="page_loading.show"></ui-loading>
@ -131,11 +132,11 @@
</div>
<div class="ta-c">
<Button @click="cards" class="w-80 umar-r5" ghost type="success">选卡</Button>
<Button v-if="source === 0" @click="cards" class="w-80 umar-r5" ghost type="success">选卡</Button>
<Button @click="clear" class="w-80 umar-r5" ghost type="primary">取消</Button>
<Button :loading="loading" @click="ok" class="w-80" type="primary">提交</Button>
</div>
</Drawer>
</MDrawer>
</template>
<script src="./js/edit.js"></script>

View File

@ -11,7 +11,20 @@
</li>
<li class="f-r">
<div class="handle-item">
<Button @click="openEdit(true, null)" icon="md-add" type="primary" v-has="'create'">创建订单</Button>
<Button
@click="openCards(true, 1, null)"
icon="md-eye"
type="primary"
v-has="'create'"
>RD订单</Button>
</div>
<div class="handle-item">
<Button
@click="openEdit(true, 0, null)"
icon="md-add"
type="primary"
v-has="'create'"
>创建订单</Button>
</div>
<div class="handle-item">
<Button @click="search.show=!search.show" ghost icon="ios-search" type="primary">搜索</Button>
@ -127,6 +140,7 @@
<ui-edit
:data="editObj.data"
:show.sync="editObj.show"
:source="editObj.source"
:type="type"
@add-success="index"
@update-success="index(list_data.current_page)"
@ -135,7 +149,32 @@
<ui-detail :data="detailObj.data" :show.sync="detailObj.show"></ui-detail>
<ui-cards :show.sync="cardsObj.show" :type="type" @select-success="selectedCards"></ui-cards>
<ui-cards
:source="cardsObj.source"
:show.sync="cardsObj.show"
:type="type"
@create-order="openEdit(true, 1, null)"
></ui-cards>
<Modal v-model="orderConfirmShow" width="360">
<p slot="header" style="color:#f60;text-align:center">
<Icon type="ios-information-circle"></Icon>
<span>订单操作</span>
</p>
<div style="text-align:center">
<p>请选择您要进行的操作</p>
</div>
<div slot="footer">
<Row class="ta-c">
<Col span="11">
<Button type="error" long @click="orderCannel">取消订单</Button>
</Col>
<Col offset="2" span="11">
<Button type="primary" long @click="orderOut">确认出库</Button>
</Col>
</Row>
</div>
</Modal>
</div>
</template>

View File

@ -7,6 +7,10 @@ export default {
type: Boolean,
default: false
},
source: {
type: Number,
default: 0
},
type: {
type: Number,
default: 0
@ -33,7 +37,6 @@ export default {
used: '',
sim: ''
},
showCards: [],
orderColumns: [
{
width: 60,
@ -90,11 +93,12 @@ export default {
return h("Checkbox", {
props: {
indeterminate: value && indeterminate,
value: value
value: value,
disabled: context.row.counts === context.row.cards_count
},
on: {
input: value => {
this.handleSelectOrder(context.row, value);
this.handleSelectOrder(context.row.id, value);
}
}
});
@ -127,10 +131,15 @@ export default {
width: 90
},
{
title: "订单卡量",
title: "量",
key: "counts",
width: 90
},
{
title: "已用数量",
key: "cards_count",
width: 90
},
{
title: "订单金额",
key: "total_price",
@ -174,7 +183,7 @@ export default {
},
on: {
input: value => {
console.log(value);
this.handleSelectOrder(this.order_id, value);
}
}
});
@ -183,12 +192,12 @@ export default {
let value = false;
let select = this.selected.find(item => {
return item.id === this.order_id;
return item.id == this.order_id;
});
if (select) {
let card = select.cards.find(item => {
return item.sim === context.row.sim;
let card = select.cards.find(sim => {
return sim == context.row.sim;
});
if (card) {
@ -198,11 +207,12 @@ export default {
return h("Checkbox", {
props: {
value: value
value: value,
disabled: !!context.row.virtual_order_id
},
on: {
input: value => {
console.log(value);
this.handleSelectCards(context.row, value);
}
}
});
@ -268,13 +278,11 @@ export default {
return 0;
}
return selected
.map(item => {
return item.cards.length;
})
.reduce((acc, cur) => {
return acc + cur;
});
return selected.map(item => {
return item.cards.length;
}).reduce((acc, cur) => {
return acc + cur;
});
}
},
watch: {
@ -286,50 +294,40 @@ export default {
}
},
methods: {
ok() {},
ok() {
this.my_show = false;
},
index(page, limit = 10) {
let params = this.searchDataHandle({}, { page, limit }, this.params);
params.type = this.type;
this.$store.dispatch("getOrders", params);
},
getCards(row) {
this.order_id = row.id;
getCards(order_id) {
console.log(order_id);
this.order_id = order_id;
this.cardLoading = true;
return new Promise((resolve, reject) => {
let params = {
order_id: row.id,
type: this.type
};
this.$store
.dispatch("getCards", params)
.then(cards => {
this.showCards = cards.map(item => {
return [
false,
item.sim,
item.virtual_order_id ? 1 : 0,
item.counts,
item.virtual ? item.virtual.company_name : '',
item.virtual ? item.virtual.package_name : ''
];
});
this.cardLoading = false;
resolve(cards);
})
.catch(() => {
this.cardLoading = false;
this.$Message.error("服务器出错,请稍后再试");
});
let params = { order_id: order_id, type: this.type };
this.$store.dispatch("getCards", params).then(cards => {
this.cardLoading = false;
resolve(cards);
}).catch(() => {
this.cardLoading = false;
this.$Message.error("服务器出错,请稍后再试");
});
});
},
handleOrderRowDblclick(row) {
this.getCards(row.id);
},
visibleChange(bool) {
if (!bool) {
this.$emit("update:show", false);
}
},
clear() {
this.$store.commit('SET_REAL_ORDER_SELECTED', []);
this.my_show = false;
},
resetSearch() {
@ -345,33 +343,36 @@ export default {
}
this.index(1);
},
handleSelectOrder(row, value) {
handleSelectOrder(order_id, value) {
if (value) {
this.getCards(row).then(cards => {
let obj = {
id: row.id,
total: row.counts,
cards: cards
};
this.getCards(order_id).then(cards => {
cards = this.filterUsed(cards);
this.showCards = this.showCards.map(item => {
item[0] = true;
return item;
});
if (cards.length) {
let arr = cards.map(item => {
return item.sim;
});
this.$store.commit('PUSH_REAL_ORDER_SELECTED', obj);
this.$store.commit('PUSH_REAL_ORDER_SELECTED', { order_id, cards: arr });
} else {
this.$Message.error('选中零张卡');
}
});
} else {
this.showCards = this.showCards.map(item => {
item[0] = false;
return item;
});
this.$store.commit('REMOVE_REAL_ORDER_SELECTED', row.id);
this.$store.commit('REMOVE_REAL_ORDER_SELECTED', order_id);
}
},
handleSelectCards(t, a, b) {
console.log(t, a, b);
handleSelectCards(row, value) {
let action = value ? 'PUSH_CARD_SELECTED' : 'REMOVE_CARD_SELECTED';
this.$store.commit(action, { order_id: row.order_id, sim: row.sim });
},
filterUsed(cards) {
return cards.filter(item => {
return item.virtual_order_id === 0;
});
},
order() {
this.$emit('create-order');
}
}
};

View File

@ -4,11 +4,18 @@ import {
} from 'validate';
export default {
components: {
MDrawer: resolve => require(['components/drawer'], resolve)
},
props: {
show: {
type: Boolean,
default: false
},
source: {
type: Number,
default: 0
},
type: {
type: Number,
default: 0

View File

@ -34,6 +34,8 @@ export default {
search: {
show: false
},
row: {}, // 当前行
orderConfirmShow: false,
cancel_remark: '',
logistics: null,
logisticsParams: {
@ -54,7 +56,7 @@ export default {
{
title: '企业名称',
key: 'company_name',
width: 300
width: 320
},
{
title: '运营商',
@ -88,26 +90,6 @@ export default {
key: 'custom_price',
width: 120
},
{
title: '已排单数',
key: '',
width: 100,
render: (h, {
row,
column,
index
}) => {
let style = {};
if (row.shipments !== row.counts) {
style = {
'color': '#ed4014'
};
}
return h('span', {
style
}, Number(row.shipments));
}
},
{
title: '订单状态',
key: '',
@ -119,9 +101,162 @@ export default {
}) => {
let status = ['error', 'default', 'warning', 'primary', 'success'];
return h('Tag', {
return h('Button', {
props: {
color: status[row.order_status]
type: status[row.order_status],
size: 'small'
},
class: ['btn'],
on: {
click: () => {
if (this.haveJurisdiction('update')) {
this.row = row;
// 已出库 -> 已发货
if (row.order_status === 0) {
this.orderConfirmShow = true;
}
// 已出库 -> 已发货
if (row.order_status === 2) {
this.getLogistics().then(logistics => {
this.$Modal.confirm({
title: '请填写发货信息',
render: (h) => {
let Options = [];
for (const key in logistics) {
Options.push(h('Option', {
props: {
key: key,
value: key
}
}, logistics[key]));
}
let Select = h('Select', {
props: {
value: this.logisticsParams.logistics_company,
placeholder: '请选择快递公司...'
},
class: ['umar-b10'],
on: {
'on-change': (val) => {
this.logisticsParams.logistics_company = val;
}
}
}, Options);
let Input = h('Input', {
props: {
value: this.logisticsParams.logistics_no,
autofocus: true,
placeholder: '请输入快递单号...'
},
on: {
'input': (val) => {
this.logisticsParams.logistics_no = val;
}
}
});
return h('div', [Select, Input]);
},
onOk: () => {
API.update({
order_status: 3,
logistics_company: this.logisticsParams.logistics_company,
logistics_no: this.logisticsParams.logistics_no
}, row.id).then(res => {
if (res.code == 0) {
this.$Message.success('修改成功');
this.request();
}
});
}
});
});
}
// 已出库 -> 已发货
if (row.order_status === 2) {
this.getLogistics().then(logistics => {
this.$Modal.confirm({
title: '请填写发货信息',
render: (h) => {
let Options = [];
for (const key in logistics) {
Options.push(h('Option', {
props: {
key: key,
value: key
}
}, logistics[key]));
}
let Select = h('Select', {
props: {
value: this.logisticsParams.logistics_company,
placeholder: '请选择快递公司...'
},
class: ['umar-b10'],
on: {
'on-change': (val) => {
this.logisticsParams.logistics_company = val;
}
}
}, Options);
let Input = h('Input', {
props: {
value: this.logisticsParams.logistics_no,
autofocus: true,
placeholder: '请输入快递单号...'
},
on: {
'input': (val) => {
this.logisticsParams.logistics_no = val;
}
}
});
return h('div', [Select, Input]);
},
onOk: () => {
API.update({
order_status: 3,
logistics_company: this.logisticsParams.logistics_company,
logistics_no: this.logisticsParams.logistics_no
}, row.id).then(res => {
if (res.code == 0) {
this.$Message.success('修改成功');
this.request();
}
});
}
});
});
}
// 已发货 -> 已签收
if (row.order_status === 3) {
this.$Modal.confirm({
title: '提示',
content: '请确认订单是否确认签收?',
onOk: () => {
API.update({
order_status: 4
}, row.id).then(res => {
if (res.code == 0) {
this.$Message.success('修改成功');
this.request();
}
});
}
});
}
}
}
}
}, row.order_status_name);
}
@ -137,78 +272,17 @@ export default {
}) => {
let status = ['error', 'success', 'default'];
return h('Tag', {
return h('Button', {
props: {
color: status[row.transaction_status]
}
}, row.transaction_status_name);
}
},
{
title: '下单时间',
key: 'order_at',
width: 170
},
{
title: '操作',
key: 'action',
width: 340,
render: (h, {
row,
column,
index
}) => {
let html = [];
if (row.deleted_at) {
return h('Tag', {
props: {
color: 'default'
}
}, '该订单已被删除');
}
if (this.haveJurisdiction('show')) {
html.push(h('Button', {
props: {
type: 'dashed',
size: 'small',
disabled: false,
icon: 'md-eye'
},
class: ['btn'],
on: {
click: (event) => {
this.isShowLoading(true);
API.show(row.id).then(res => {
this.isShowLoading(false);
if (res.code === 0) {
this.detailObj = {
show: true,
data: res.data
};
}
}).catch(() => {
this.isShowLoading(false);
});
}
}
}, '查看'));
}
if (this.haveJurisdiction('update')) {
// 未收款 -> 已收款
if (row.transaction_status === 0) {
html.push(h('Button', {
props: {
type: 'success',
size: 'small',
disabled: false,
ghost: true
},
class: ['btn'],
on: {
click: () => {
type: status[row.transaction_status],
size: 'small'
},
class: ['btn'],
on: {
click: () => {
if (this.haveJurisdiction('update')) {
// 未收款 -> 已收款
if (row.transaction_status === 0) {
this.$Modal.confirm({
title: '提示',
content: '请确认是否已收款?',
@ -224,22 +298,9 @@ export default {
}
});
}
}
}, '确认收款'));
}
// 已收款 -> 已退款 (要先取消订单)
if (row.transaction_status === 1 && row.order_status === 1) {
html.push(h('Button', {
props: {
type: 'error',
size: 'small',
disabled: false,
ghost: true
},
class: ['btn'],
on: {
click: () => {
// 已收款 -> 已退款 (要先取消订单)
if (row.transaction_status === 1 && row.order_status === 1) {
this.$Modal.confirm({
title: '请填写退款信息并确认',
render: (h) => {
@ -335,194 +396,73 @@ export default {
});
}
}
}, '确认退款'));
}
}
}, row.transaction_status_name);
}
},
{
title: '下单时间',
key: 'order_at',
width: 170
},
{
title: '操作',
key: 'action',
width: 150,
fixed: 'right',
render: (h, {
row,
column,
index
}) => {
let html = [];
// 已下单 -> 取消订单 | 出库
if (row.order_status === 0) {
html.push(h('Button', {
if (row.deleted_at) {
return h('Tag', {
props: {
color: 'default'
}
}, '该订单已被删除');
}
if (this.haveJurisdiction('show')) {
html.push(h('Button', {
props: {
type: 'dashed',
size: 'small',
disabled: false,
icon: 'md-eye'
},
class: ['btn'],
on: {
click: (event) => {
this.show(row);
}
}
}, '查看'));
}
if (this.haveJurisdiction('update')) {
// 排单
if (row.shipments !== row.counts) {
html.push(h('Tooltip', {
props: {
type: 'info',
size: 'small',
disabled: false,
ghost: true
content: '已排单' + row.shipments + '张'
},
class: ['umar-r5']
}, [h('Button', {
props: {
type: 'success',
size: 'small'
},
class: ['btn'],
on: {
click: () => {
this.$Modal.confirm({
render: (h) => {
return h('Input', {
props: {
value: this.cancel_remark,
autofocus: true,
placeholder: '...'
},
on: {
'input': (val) => {
this.cancel_remark = val;
}
}
});
},
title: '请输入取消理由',
onOk: () => {
if (!this.cancel_remark) {
this.$Message.error('请输入取消理由');
return;
}
API.update({
order_status: 1,
extends: {
cancel_remark: this.cancel_remark
}
}, row.id).then(res => {
if (res.code == 0) {
this.$Message.success('取消成功');
this.request();
}
this.cancel_remark = '';
});
}
});
this.openCards(true, 2);
}
}
}, '取消订单'));
html.push(h('Button', {
props: {
type: 'warning',
size: 'small',
disabled: false,
ghost: true
},
class: ['btn'],
on: {
click: () => {
this.$Modal.confirm({
title: '提示',
content: '请确认订单是否已出库?',
onOk: () => {
API.update({
order_status: 2
}, row.id).then(res => {
if (res.code == 0) {
this.$Message.success('修改成功');
this.request();
}
});
}
});
}
}
}, '确认出库'));
}
// 已出库 -> 已发货
if (row.order_status === 2) {
html.push(h('Button', {
props: {
type: 'warning',
size: 'small',
disabled: false,
ghost: true
},
class: ['btn'],
on: {
click: () => {
this.getLogistics().then(logistics => {
this.$Modal.confirm({
title: '请填写发货信息',
render: (h) => {
let Options = [];
for (const key in logistics) {
Options.push(h('Option', {
props: {
key: key,
value: key
}
}, logistics[key]));
}
let Select = h('Select', {
props: {
value: this.logisticsParams.logistics_company,
placeholder: '请选择快递公司...'
},
class: ['umar-b10'],
on: {
'on-change': (val) => {
this.logisticsParams.logistics_company = val;
}
}
}, Options);
let Input = h('Input', {
props: {
value: this.logisticsParams.logistics_no,
autofocus: true,
placeholder: '请输入快递单号...'
},
on: {
'input': (val) => {
this.logisticsParams.logistics_no = val;
}
}
});
return h('div', [Select, Input]);
},
onOk: () => {
API.update({
order_status: 3,
logistics_company: this.logisticsParams.logistics_company,
logistics_no: this.logisticsParams.logistics_no
}, row.id).then(res => {
if (res.code == 0) {
this.$Message.success('修改成功');
this.request();
}
});
}
});
});
}
}
}, '订单发货'));
}
// 已发货 -> 已签收
if (row.order_status === 3) {
html.push(h('Button', {
props: {
type: 'warning',
size: 'small',
disabled: false,
ghost: true
},
class: ['btn'],
on: {
click: () => {
this.$Modal.confirm({
title: '提示',
content: '请确认订单是否确认签收?',
onOk: () => {
API.update({
order_status: 4
}, row.id).then(res => {
if (res.code == 0) {
this.$Message.success('修改成功');
this.request();
}
});
}
});
}
}
}, '确认签收'));
}, '排单')]));
}
}
@ -538,17 +478,30 @@ export default {
this.index(1);
},
methods: {
// 查看订单明细
show(row) {
this.isShowLoading(true);
API.show(row.id).then(res => {
this.isShowLoading(false);
if (res.code === 0) {
this.detailObj = {
show: true,
data: res.data
};
}
}).catch(() => {
this.isShowLoading(false);
});
},
/**
* [index 列表]
* @param {Number} page [description]
* @return {[type]} [description]
*/
index(page = 1) {
index(page = 1, limit = 15) {
this.type = Number(this.$route.params.type);
this.params.type = Number(this.$route.params.type);
let data = this.searchDataHandle({}, {
page
}, this.params);
let data = this.searchDataHandle({}, { page, limit }, this.params);
this.isShowLoading(true);
API.index(data).then(res => {
this.isShowLoading(false);
@ -562,15 +515,29 @@ export default {
/**
* [openEdit 打开编辑弹窗]
* source 0:从创建订单按钮打开 1:从选卡页面打开
* @return {[type]} [description]
*/
openEdit(bool, data = null) {
openEdit(bool, source, data = null) {
this.editObj = {
show: bool,
source,
data
};
},
/**
* [openCards 打开选卡弹窗]
* source 0:选创建订单页面打开 1:从选卡按钮打开 2:从排单按钮打开
* @return {[type]} [description]
*/
openCards(bool, source) {
this.cardsObj = {
show: bool,
source
};
},
/**
* [request 刷新]
* @return {[type]} [description]
@ -610,17 +577,66 @@ export default {
}
});
},
/**
* [openCards 打开选卡弹窗]
* @return {[type]} [description]
*/
openCards(bool) {
this.cardsObj = {
show: bool
};
// 取消订单
orderCannel() {
let row = this.row;
this.$Modal.confirm({
render: (h) => {
return h('Input', {
props: {
value: this.cancel_remark,
autofocus: true,
placeholder: '...'
},
on: {
'input': (val) => {
this.cancel_remark = val;
}
}
});
},
title: '请输入取消理由',
onOk: () => {
if (!this.cancel_remark) {
this.$Message.error('请输入取消理由');
return;
}
API.update({
order_status: 1,
extends: {
cancel_remark: this.cancel_remark
}
}, row.id).then(res => {
if (res.code == 0) {
this.$Message.success('取消成功');
this.orderConfirmShow = false;
this.request();
}
this.cancel_remark = '';
});
}
});
},
selectedCards() {
console.log(1);
// 订单出库
orderOut() {
let row = this.row;
this.$Modal.confirm({
title: '提示',
content: '请确认订单是否已出库?',
onOk: () => {
API.update({
order_status: 2
}, row.id).then(res => {
if (res.code == 0) {
this.$Message.success('修改成功');
this.orderConfirmShow = false;
this.request();
}
});
}
});
}
}
};

View File

@ -0,0 +1,633 @@
import * as API from 'api/virtual/orders';
import * as CONFIGS from 'api/virtual/configs';
export default {
name: 'Orders',
components: {
UiEdit: resolve => require(['views/virtual/orders/edit'], resolve),
UiDetail: resolve => require(['views/virtual/orders/detail'], resolve),
UiCards: resolve => require(['views/virtual/orders/cards'], resolve)
},
data() {
return {
params: {
type: 0,
sn: '',
company_name: '',
package_name: '',
order_status: '',
carrier_operator: '',
time: []
},
type: 0,
list_data: null,
editObj: {
show: false,
data: null
},
detailObj: {
show: false,
data: null
},
cardsObj: {
show: false
},
search: {
show: false
},
cancel_remark: '',
logistics: null,
logisticsParams: {
logistics_company: '',
logistics_no: ''
},
refundParams: {
channel: '',
account: '',
remark: ''
},
table_titles: [
{
title: '订单编号',
key: 'sn',
width: 230
},
{
title: '企业名称',
key: 'company_name',
width: 275
},
{
title: '运营商',
key: 'carrier_operator',
width: 75
},
{
title: '套餐名称',
key: 'package_name',
width: 100
},
{
title: '套餐单价',
key: 'unit_price',
width: 90
},
{
title: '订单数量',
key: '',
width: 90,
render: (h, {
row,
column,
index
}) => {
return h('span', Number(row.counts));
}
},
{
title: '订单金额',
key: 'custom_price',
width: 100
},
{
title: '订单状态',
key: '',
width: 100,
render: (h, {
row,
column,
index
}) => {
let status = ['error', 'default', 'warning', 'primary', 'success'];
return h('Tag', {
props: {
color: status[row.order_status]
}
}, row.order_status_name);
}
},
{
title: '收款状态',
key: '',
width: 100,
render: (h, {
row,
column,
index
}) => {
let status = ['error', 'success', 'default'];
return h('Tag', {
props: {
color: status[row.transaction_status]
}
}, row.transaction_status_name);
}
},
{
title: '下单时间',
key: 'order_at',
width: 150
},
{
title: '操作',
key: 'action',
width: 360,
render: (h, {
row,
column,
index
}) => {
let html = [];
if (row.deleted_at) {
return h('Tag', {
props: {
color: 'default'
}
}, '该订单已被删除');
}
if (this.haveJurisdiction('show')) {
html.push(h('Button', {
props: {
type: 'dashed',
size: 'small',
disabled: false,
icon: 'md-eye'
},
class: ['btn'],
on: {
click: (event) => {
this.show(row);
}
}
}, '查看'));
}
if (this.haveJurisdiction('update')) {
// 排单
if (row.shipments !== row.counts) {
html.push(h('Tooltip', {
props: {
content: '已排单' + row.shipments + '张'
},
class: ['umar-r5']
}, [h('Button', {
props: {
type: 'error',
size: 'small'
},
class: ['btn'],
on: {
click: () => {
this.openCards(true, 2);
}
}
}, '排单')]));
}
// 未收款 -> 已收款
if (row.transaction_status === 0) {
html.push(h('Button', {
props: {
type: 'success',
size: 'small',
disabled: false,
ghost: true
},
class: ['btn'],
on: {
click: () => {
this.$Modal.confirm({
title: '提示',
content: '请确认是否已收款?',
onOk: () => {
API.update({
transaction_status: 1
}, row.id).then(res => {
if (res.code == 0) {
this.$Message.success('修改成功');
this.request();
}
});
}
});
}
}
}, '确认收款'));
}
// 已收款 -> 已退款 (要先取消订单)
if (row.transaction_status === 1 && row.order_status === 1) {
html.push(h('Button', {
props: {
type: 'error',
size: 'small',
disabled: false,
ghost: true
},
class: ['btn'],
on: {
click: () => {
this.$Modal.confirm({
title: '请填写退款信息并确认',
render: (h) => {
let refundHtml = [];
let Options = [];
Options.push(h('Option', {
props: {
key: 'bank',
value: 'bank'
}
}, '银行转账'));
Options.push(h('Option', {
props: {
key: 'alipay',
value: 'alipay'
}
}, '支付宝转账'));
refundHtml.push(h('Select', {
props: {
value: this.refundParams.channel,
placeholder: '请选择退款方式...'
},
class: ['umar-b10'],
on: {
'on-change': (val) => {
this.refundParams.channel = val;
}
}
}, Options));
refundHtml.push(h('Input', {
props: {
value: this.refundParams.account,
autofocus: true,
placeholder: '请输入退款账号...'
},
class: ['umar-b10'],
on: {
'input': (val) => {
this.refundParams.account = val;
}
}
}));
refundHtml.push(h('Input', {
props: {
value: this.refundParams.remark,
autofocus: true,
placeholder: '请输入退款备注...'
},
class: ['umar-b10'],
on: {
'input': (val) => {
this.refundParams.remark = val;
}
}
}));
return h('div', refundHtml);
},
onOk: () => {
if (!this.refundParams.channel) {
this.$Message.error('请选择退款方式');
return;
}
if (!this.refundParams.account) {
this.$Message.error('请输入退款账号');
return;
}
API.update({
transaction_status: 2,
extends: {
refund_channel: this.refundParams.channel,
refund_account: this.refundParams.account,
refund_remark: this.refundParams.remark
}
}, row.id).then(res => {
if (res.code == 0) {
this.$Message.success('修改成功');
this.request();
}
this.refundParams.channel = '';
this.refundParams.account = '';
this.refundParams.remark = '';
});
}
});
}
}
}, '确认退款'));
}
// 已下单 -> 取消订单 | 出库
if (row.order_status === 0) {
html.push(h('Button', {
props: {
type: 'info',
size: 'small',
disabled: false,
ghost: true
},
class: ['btn'],
on: {
click: () => {
this.$Modal.confirm({
render: (h) => {
return h('Input', {
props: {
value: this.cancel_remark,
autofocus: true,
placeholder: '...'
},
on: {
'input': (val) => {
this.cancel_remark = val;
}
}
});
},
title: '请输入取消理由',
onOk: () => {
if (!this.cancel_remark) {
this.$Message.error('请输入取消理由');
return;
}
API.update({
order_status: 1,
extends: {
cancel_remark: this.cancel_remark
}
}, row.id).then(res => {
if (res.code == 0) {
this.$Message.success('取消成功');
this.request();
}
this.cancel_remark = '';
});
}
});
}
}
}, '取消订单'));
html.push(h('Button', {
props: {
type: 'warning',
size: 'small',
disabled: false,
ghost: true
},
class: ['btn'],
on: {
click: () => {
this.$Modal.confirm({
title: '提示',
content: '请确认订单是否已出库?',
onOk: () => {
API.update({
order_status: 2
}, row.id).then(res => {
if (res.code == 0) {
this.$Message.success('修改成功');
this.request();
}
});
}
});
}
}
}, '确认出库'));
}
// 已出库 -> 已发货
if (row.order_status === 2) {
html.push(h('Button', {
props: {
type: 'warning',
size: 'small',
disabled: false,
ghost: true
},
class: ['btn'],
on: {
click: () => {
this.getLogistics().then(logistics => {
this.$Modal.confirm({
title: '请填写发货信息',
render: (h) => {
let Options = [];
for (const key in logistics) {
Options.push(h('Option', {
props: {
key: key,
value: key
}
}, logistics[key]));
}
let Select = h('Select', {
props: {
value: this.logisticsParams.logistics_company,
placeholder: '请选择快递公司...'
},
class: ['umar-b10'],
on: {
'on-change': (val) => {
this.logisticsParams.logistics_company = val;
}
}
}, Options);
let Input = h('Input', {
props: {
value: this.logisticsParams.logistics_no,
autofocus: true,
placeholder: '请输入快递单号...'
},
on: {
'input': (val) => {
this.logisticsParams.logistics_no = val;
}
}
});
return h('div', [Select, Input]);
},
onOk: () => {
API.update({
order_status: 3,
logistics_company: this.logisticsParams.logistics_company,
logistics_no: this.logisticsParams.logistics_no
}, row.id).then(res => {
if (res.code == 0) {
this.$Message.success('修改成功');
this.request();
}
});
}
});
});
}
}
}, '订单发货'));
}
// 已发货 -> 已签收
if (row.order_status === 3) {
html.push(h('Button', {
props: {
type: 'warning',
size: 'small',
disabled: false,
ghost: true
},
class: ['btn'],
on: {
click: () => {
this.$Modal.confirm({
title: '提示',
content: '请确认订单是否确认签收?',
onOk: () => {
API.update({
order_status: 4
}, row.id).then(res => {
if (res.code == 0) {
this.$Message.success('修改成功');
this.request();
}
});
}
});
}
}
}, '确认签收'));
}
}
if (html.length) {
return h('div', html);
}
}
}
]
};
},
created() {
this.index(1);
},
methods: {
// 查看订单明细
show(row) {
this.isShowLoading(true);
API.show(row.id).then(res => {
this.isShowLoading(false);
if (res.code === 0) {
this.detailObj = {
show: true,
data: res.data
};
}
}).catch(() => {
this.isShowLoading(false);
});
},
/**
* [index 列表]
* @param {Number} page [description]
* @return {[type]} [description]
*/
index(page = 1) {
this.type = Number(this.$route.params.type);
this.params.type = Number(this.$route.params.type);
let data = this.searchDataHandle({}, {
page
}, this.params);
this.isShowLoading(true);
API.index(data).then(res => {
this.isShowLoading(false);
if (res.code == 0) {
this.list_data = res.data;
}
}).catch(() => {
this.isShowLoading(false);
});
},
/**
* [openEdit 打开编辑弹窗]
* source 0:从创建订单按钮打开 1:从选卡页面打开
* @return {[type]} [description]
*/
openEdit(bool, source, data = null) {
this.editObj = {
show: bool,
source,
data
};
},
/**
* [openCards 打开选卡弹窗]
* source 0:选创建订单页面打开 1:从选卡按钮打开 2:从排单按钮打开
* @return {[type]} [description]
*/
openCards(bool, source) {
this.cardsObj = {
show: bool,
source
};
},
/**
* [request 刷新]
* @return {[type]} [description]
*/
request() {
const result = this.list_data;
let page = result.current_page;
if (result && result.data.length == 1) {
page = this.returnPage(result.total, result.current_page, result.per_page);
}
this.index(page);
},
resetSearch() {
for (let k in this.params) {
if (k === 'time') {
this.params[k] = [];
} else {
this.params[k] = '';
}
}
this.index(1);
},
getLogistics() {
return new Promise(resolve => {
if (this.logistics) {
resolve(this.logistics);
} else {
CONFIGS.get('logistics').then(res => {
if (res.code === 0) {
this.logistics = res.data;
}
resolve(this.logistics);
});
}
});
}
}
};

View File

@ -19,11 +19,11 @@ module.exports = {
.set('mixins', resolve('src/mixins'))
.set('directives', resolve('src/directives'))
.set('assets', resolve('src/assets'))
.set('utils', resolve('src/utils'))
.set('css', resolve('src/assets/css'))
.set('images', resolve('src/assets/images'))
.set('lib', resolve('src/assets/lib'))
.set('service', resolve('src/service'))
.set('util', resolve('src/service/util'))
.set('validate', resolve('src/service/validate'));
config.module