|
|
@@ -7,11 +7,16 @@
|
|
|
</div>
|
|
|
</div>
|
|
|
|
|
|
- <el-button @click="backRoomList()" type="primary" icon="el-icon-back">返回包房</el-button>
|
|
|
+ <div class="order-header-actions">
|
|
|
+ <el-button v-if="hasCurrentOrder" @click="goAddDish()" type="success" icon="el-icon-plus">加菜</el-button>
|
|
|
+ <el-button v-if="hasCurrentOrder" @click="openReturnDishDialog()" type="warning"
|
|
|
+ icon="el-icon-minus">退菜</el-button>
|
|
|
+ <el-button @click="backRoomList()" type="primary" icon="el-icon-back">返回包房</el-button>
|
|
|
+ </div>
|
|
|
</div>
|
|
|
|
|
|
<div class="order-main">
|
|
|
- <div class="dish-panel">
|
|
|
+ <div v-if="!hasCurrentOrder" class="dish-panel">
|
|
|
<div class="dish-search">
|
|
|
<el-input v-model="dishSearchName" placeholder="搜索菜品名称" clearable @keyup.enter.native="searchDish()"
|
|
|
@clear="searchDish()">
|
|
|
@@ -53,12 +58,13 @@
|
|
|
</div>
|
|
|
</div>
|
|
|
|
|
|
- <div class="ordered-panel" v-loading="orderLoading">
|
|
|
+ <div class="ordered-panel" :class="{ 'ordered-panel-full': hasCurrentOrder }" v-loading="orderLoading">
|
|
|
<div class="ordered-title">
|
|
|
<span>已点菜</span>
|
|
|
<div v-if="hasCurrentOrder" class="ordered-title-actions">
|
|
|
<el-button type="primary" plain @click="viewCurrentOrder()">订单详情</el-button>
|
|
|
- <el-button type="danger" plain :loading="submitting" @click="confirmCancelOrder()">取消订单</el-button>
|
|
|
+ <el-button type="danger" plain :loading="submitting"
|
|
|
+ @click="confirmCancelOrder()">取消订单</el-button>
|
|
|
</div>
|
|
|
</div>
|
|
|
|
|
|
@@ -87,10 +93,10 @@
|
|
|
<div class="ordered-price">¥{{ formatMoney(item.salePrice) }}</div>
|
|
|
<div class="ordered-total">¥{{ formatMoney(itemTotal(item)) }}</div>
|
|
|
<div class="ordered-qty">
|
|
|
- <el-button icon="el-icon-minus" size="mini" circle
|
|
|
+ <el-button v-if="!hasCurrentOrder" icon="el-icon-minus" size="mini" circle
|
|
|
@click="reduceDish(item)"></el-button>
|
|
|
<span>{{ item.quantity }}</span>
|
|
|
- <el-button icon="el-icon-plus" size="mini" circle
|
|
|
+ <el-button v-if="!hasCurrentOrder" icon="el-icon-plus" size="mini" circle
|
|
|
@click="increaseOrderedDish(item)"></el-button>
|
|
|
</div>
|
|
|
</div>
|
|
|
@@ -98,80 +104,27 @@
|
|
|
</div>
|
|
|
<div class="ordered-footer">
|
|
|
<div class="ordered-summary">
|
|
|
- <span>总价</span>
|
|
|
+ <span>共 {{ orderedList.length }} 项</span>
|
|
|
<strong>¥{{ formatMoney(orderTotal) }}</strong>
|
|
|
</div>
|
|
|
- <div class="ordered-actions" :class="{ 'ordered-actions-with-cancel': hasCurrentOrder }">
|
|
|
+ <div class="ordered-actions"
|
|
|
+ :class="{ 'ordered-actions-settle-only': hasCurrentOrder && !hasChangedDish }">
|
|
|
|
|
|
- <el-button type="success" :loading="submitting" @click="openSettleDialog()">{{ settleButtonText
|
|
|
- }}</el-button>
|
|
|
- <el-button type="primary" :loading="submitting" @click="confirmSubmitOrder()">下单</el-button>
|
|
|
+ <el-button v-if="hasCurrentOrder && !hasChangedDish" style="width: 30%;" type="success"
|
|
|
+ :loading="submitting" @click="openSettleDialog()">结账</el-button>
|
|
|
+ <el-button v-if="!hasCurrentOrder || hasChangedDish" type="primary" :loading="submitting"
|
|
|
+ @click="confirmSubmitOrder()">下单</el-button>
|
|
|
</div>
|
|
|
</div>
|
|
|
</div>
|
|
|
</div>
|
|
|
- <el-dialog title="订单结账" :close-on-click-modal="false" top="25vh" draggable width="520px"
|
|
|
- v-model="settleDialogVisible">
|
|
|
- <el-tabs v-model="settleType">
|
|
|
- <el-tab-pane label="结账" name="0">
|
|
|
- <div class="settle-normal">
|
|
|
- <span>订单金额</span>
|
|
|
- <strong>¥{{ formatMoney(orderTotal) }}</strong>
|
|
|
- </div>
|
|
|
- </el-tab-pane>
|
|
|
- <el-tab-pane label="折扣结账" name="1">
|
|
|
- <div class="settle-preview">
|
|
|
- <div>
|
|
|
- <span>账单原金额</span>
|
|
|
- <strong>¥{{ formatMoney(orderTotal) }}</strong>
|
|
|
- </div>
|
|
|
- <div>
|
|
|
- <span>折扣比例</span>
|
|
|
- <strong>{{ formatMoney(discountRate) }}%</strong>
|
|
|
- </div>
|
|
|
- <div>
|
|
|
- <span>折扣后金额</span>
|
|
|
- <strong style="color: #f56c6c;">¥{{ formatMoney(settlePayableAmount) }}</strong>
|
|
|
- </div>
|
|
|
- </div>
|
|
|
- <el-form label-width="100px">
|
|
|
- <el-form-item label="折扣比例">
|
|
|
- <el-input-number v-model="discountRate" :min="0" :max="100" :precision="2"
|
|
|
- style="width: 100%"></el-input-number>
|
|
|
- </el-form-item>
|
|
|
- </el-form>
|
|
|
- </el-tab-pane>
|
|
|
- <el-tab-pane label="优惠结账" name="2">
|
|
|
- <div class="settle-preview">
|
|
|
- <div>
|
|
|
- <span>账单原金额</span>
|
|
|
- <strong>¥{{ formatMoney(orderTotal) }}</strong>
|
|
|
- </div>
|
|
|
- <div>
|
|
|
- <span>优惠金额</span>
|
|
|
- <strong>¥{{ formatMoney(settleDiscountAmount) }}</strong>
|
|
|
- </div>
|
|
|
- <div>
|
|
|
- <span>优惠后金额</span>
|
|
|
- <strong style="color: #f56c6c;">¥{{ formatMoney(settlePayableAmount) }}</strong>
|
|
|
- </div>
|
|
|
- </div>
|
|
|
- <el-form label-width="100px">
|
|
|
- <el-form-item label="优惠金额">
|
|
|
- <el-input-number v-model="discountAmount" :min="0" :max="orderTotal" :precision="2"
|
|
|
- style="width: 100%"></el-input-number>
|
|
|
- </el-form-item>
|
|
|
- </el-form>
|
|
|
- </el-tab-pane>
|
|
|
- </el-tabs>
|
|
|
- <template #footer>
|
|
|
- <span class="dialog-footer">
|
|
|
- <el-button @click="settleDialogVisible = false" icon="el-icon-circle-close">取消</el-button>
|
|
|
- <el-button type="primary" :loading="submitting" @click="confirmSettle()"
|
|
|
- icon="el-icon-circle-check">确认结账</el-button>
|
|
|
- </span>
|
|
|
- </template>
|
|
|
- </el-dialog>
|
|
|
+ <DishOrderSettleDialog v-model="settleDialogVisible" :order-total="orderTotal" :submitting="submitting"
|
|
|
+ @confirm="handleSettleConfirm"></DishOrderSettleDialog>
|
|
|
+ <DishOrderConfirmDialog v-model="confirmOrderDialogVisible" :current-room="currentRoom" :submitting="submitting"
|
|
|
+ @confirm="handleConfirmOrderSubmit" @continue="continueOrderDish"></DishOrderConfirmDialog>
|
|
|
+ <DishOrderReturnDialog v-model="returnDishDialogVisible" :current-room="currentRoom"
|
|
|
+ :current-order="currentOrder" :ordered-list="orderedList" :submitting="submitting"
|
|
|
+ @confirm="handleReturnDishConfirm"></DishOrderReturnDialog>
|
|
|
<DishOrderInfoDialog ref="dishOrderInfoDialog"></DishOrderInfoDialog>
|
|
|
</div>
|
|
|
</template>
|
|
|
@@ -181,10 +134,16 @@ import DishRoomService from '@/api/psi/DishRoomService'
|
|
|
import DishOrderService from '@/api/psi/DishOrderService'
|
|
|
import OSSSerivce from '@/api/sys/OSSService'
|
|
|
import DishOrderInfoDialog from './DishOrderInfoDialog'
|
|
|
+import DishOrderSettleDialog from './DishOrderSettleDialog'
|
|
|
+import DishOrderConfirmDialog from './DishOrderConfirmDialog'
|
|
|
+import DishOrderReturnDialog from './DishOrderReturnDialog'
|
|
|
import Sortable from 'sortablejs'
|
|
|
export default {
|
|
|
components: {
|
|
|
- DishOrderInfoDialog
|
|
|
+ DishOrderInfoDialog,
|
|
|
+ DishOrderSettleDialog,
|
|
|
+ DishOrderConfirmDialog,
|
|
|
+ DishOrderReturnDialog
|
|
|
},
|
|
|
data() {
|
|
|
return {
|
|
|
@@ -199,9 +158,9 @@ export default {
|
|
|
orderLoading: false,
|
|
|
submitting: false,
|
|
|
settleDialogVisible: false,
|
|
|
- settleType: '0',
|
|
|
- discountRate: 100,
|
|
|
- discountAmount: 0,
|
|
|
+ confirmOrderDialogVisible: false,
|
|
|
+ returnDishDialogVisible: false,
|
|
|
+ pendingOrderSubmit: null,
|
|
|
orderedSortable: null
|
|
|
}
|
|
|
},
|
|
|
@@ -220,9 +179,6 @@ export default {
|
|
|
hasCurrentOrder() {
|
|
|
return !!(this.currentOrder && this.currentOrder.id)
|
|
|
},
|
|
|
- settleButtonText() {
|
|
|
- return this.hasChangedDish ? '下单并结账' : '结账'
|
|
|
- },
|
|
|
submitDetailList() {
|
|
|
return this.orderedList.map((item, index) => {
|
|
|
return {
|
|
|
@@ -232,25 +188,6 @@ export default {
|
|
|
dishSort: index + 1
|
|
|
}
|
|
|
})
|
|
|
- },
|
|
|
- settleDiscountAmount() {
|
|
|
- if (this.settleType === '1') {
|
|
|
- return this.orderTotal - this.settlePayableAmount
|
|
|
- }
|
|
|
- if (this.settleType === '2') {
|
|
|
- return Math.min(Number(this.discountAmount || 0), this.orderTotal)
|
|
|
- }
|
|
|
- return 0
|
|
|
- },
|
|
|
- settlePayableAmount() {
|
|
|
- if (this.settleType === '1') {
|
|
|
- const rate = Math.min(Math.max(Number(this.discountRate || 0), 0), 100)
|
|
|
- return this.orderTotal * rate / 100
|
|
|
- }
|
|
|
- if (this.settleType === '2') {
|
|
|
- return Math.max(this.orderTotal - Number(this.discountAmount || 0), 0)
|
|
|
- }
|
|
|
- return this.orderTotal
|
|
|
}
|
|
|
},
|
|
|
dishRoomService: null,
|
|
|
@@ -320,6 +257,40 @@ export default {
|
|
|
path: '/psiManagement/dishManage/order/DishOrder'
|
|
|
})
|
|
|
},
|
|
|
+ goAddDish() {
|
|
|
+ if (!this.hasCurrentOrder) {
|
|
|
+ return
|
|
|
+ }
|
|
|
+ this.$router.push({
|
|
|
+ path: '/psiManagement/dishManage/order/DishOrderAdd',
|
|
|
+ query: {
|
|
|
+ roomId: this.$route.query.roomId,
|
|
|
+ orderId: this.currentOrder.id
|
|
|
+ }
|
|
|
+ })
|
|
|
+ },
|
|
|
+ openReturnDishDialog() {
|
|
|
+ if (!this.hasCurrentOrder) {
|
|
|
+ return
|
|
|
+ }
|
|
|
+ this.returnDishDialogVisible = true
|
|
|
+ },
|
|
|
+ handleReturnDishConfirm(detailList) {
|
|
|
+ this.submitting = true
|
|
|
+ this.dishOrderService.submit({
|
|
|
+ id: this.currentOrder.id,
|
|
|
+ roomId: this.$route.query.roomId,
|
|
|
+ settleFlag: '0',
|
|
|
+ detailList: detailList
|
|
|
+ }).then((data) => {
|
|
|
+ this.$message.success(data)
|
|
|
+ this.returnDishDialogVisible = false
|
|
|
+ this.loadRoom(this.$route.query.roomId)
|
|
|
+ this.loadCurrentOrder(this.$route.query.roomId)
|
|
|
+ }).finally(() => {
|
|
|
+ this.submitting = false
|
|
|
+ })
|
|
|
+ },
|
|
|
loadCategoryList() {
|
|
|
this.dishOrderService.typeList().then((data) => {
|
|
|
this.categoryList = [
|
|
|
@@ -392,17 +363,15 @@ export default {
|
|
|
this.$message.warning('请先选择菜品')
|
|
|
return
|
|
|
}
|
|
|
- this.settleType = '0'
|
|
|
- this.discountRate = 100
|
|
|
- this.discountAmount = 0
|
|
|
this.settleDialogVisible = true
|
|
|
},
|
|
|
- confirmSettle() {
|
|
|
- this.submitOrder('1', {
|
|
|
- settleType: this.settleType,
|
|
|
- discountRate: this.settleType === '1' ? this.discountRate : 100,
|
|
|
- discountAmount: this.settleType === '2' ? this.discountAmount : this.settleDiscountAmount
|
|
|
- }, false)
|
|
|
+ handleSettleConfirm(settleInfo) {
|
|
|
+ if (!this.hasCurrentOrder) {
|
|
|
+ this.settleDialogVisible = false
|
|
|
+ this.openConfirmOrderDialog('1', settleInfo, false)
|
|
|
+ return
|
|
|
+ }
|
|
|
+ this.submitOrder('1', settleInfo, false)
|
|
|
},
|
|
|
confirmSubmitOrder() {
|
|
|
const detailList = this.changedDetailList
|
|
|
@@ -410,6 +379,10 @@ export default {
|
|
|
this.$message.warning('请先选择菜品')
|
|
|
return
|
|
|
}
|
|
|
+ if (!this.hasCurrentOrder) {
|
|
|
+ this.openConfirmOrderDialog('0', {}, true)
|
|
|
+ return
|
|
|
+ }
|
|
|
this.$confirm('是否确认下单?', '提示', {
|
|
|
confirmButtonText: '确定',
|
|
|
cancelButtonText: '取消',
|
|
|
@@ -418,6 +391,21 @@ export default {
|
|
|
this.submitOrder('0', {}, true)
|
|
|
})
|
|
|
},
|
|
|
+ openConfirmOrderDialog(settleFlag, settleInfo = {}, requireChanged = false) {
|
|
|
+ this.pendingOrderSubmit = {
|
|
|
+ settleFlag,
|
|
|
+ settleInfo,
|
|
|
+ requireChanged
|
|
|
+ }
|
|
|
+ this.confirmOrderDialogVisible = true
|
|
|
+ },
|
|
|
+ continueOrderDish() {
|
|
|
+ this.confirmOrderDialogVisible = false
|
|
|
+ },
|
|
|
+ handleConfirmOrderSubmit(orderInfo) {
|
|
|
+ const pending = this.pendingOrderSubmit || {}
|
|
|
+ this.submitOrder(pending.settleFlag || '0', pending.settleInfo || {}, pending.requireChanged, orderInfo)
|
|
|
+ },
|
|
|
confirmCancelOrder() {
|
|
|
if (!this.hasCurrentOrder) {
|
|
|
this.$message.warning('暂无可取消的订单')
|
|
|
@@ -445,7 +433,7 @@ export default {
|
|
|
}
|
|
|
this.$refs.dishOrderInfoDialog.init(this.currentOrder.id)
|
|
|
},
|
|
|
- submitOrder(settleFlag, settleInfo = {}, requireChanged = false) {
|
|
|
+ submitOrder(settleFlag, settleInfo = {}, requireChanged = false, orderInfo = {}) {
|
|
|
const changedList = this.changedDetailList
|
|
|
const detailList = settleFlag === '1' && changedList.length === 0 ? [] : this.submitDetailList
|
|
|
if (requireChanged && changedList.length === 0) {
|
|
|
@@ -466,11 +454,13 @@ export default {
|
|
|
roomId: this.$route.query.roomId,
|
|
|
settleFlag: settleFlag,
|
|
|
...settleInfo,
|
|
|
+ ...orderInfo,
|
|
|
detailList: detailList
|
|
|
}).then((data) => {
|
|
|
this.$message.success(data)
|
|
|
this.submitting = false
|
|
|
this.settleDialogVisible = false
|
|
|
+ this.confirmOrderDialogVisible = false
|
|
|
this.loadRoom(this.$route.query.roomId)
|
|
|
this.loadCurrentOrder(this.$route.query.roomId)
|
|
|
}).catch(() => {
|
|
|
@@ -495,31 +485,31 @@ export default {
|
|
|
}
|
|
|
},
|
|
|
initOrderedSortable() {
|
|
|
- const el = this.$refs.orderedDragList
|
|
|
- if (!el) {
|
|
|
- this.destroyOrderedSortable()
|
|
|
- return
|
|
|
- }
|
|
|
- if (this.orderedSortable) {
|
|
|
- return
|
|
|
- }
|
|
|
- this.orderedSortable = Sortable.create(el, {
|
|
|
- animation: 180,
|
|
|
- filter: '.ordered-qty, .ordered-qty *',
|
|
|
- preventOnFilter: false,
|
|
|
- ghostClass: 'ordered-drag-ghost',
|
|
|
- chosenClass: 'ordered-drag-chosen',
|
|
|
- onEnd: (evt) => {
|
|
|
- if (evt.oldIndex === evt.newIndex) {
|
|
|
- return
|
|
|
- }
|
|
|
- const list = [...this.orderedList]
|
|
|
- const moved = list.splice(evt.oldIndex, 1)[0]
|
|
|
- list.splice(evt.newIndex, 0, moved)
|
|
|
- this.orderedList = list
|
|
|
- this.refreshDishSort()
|
|
|
- }
|
|
|
- })
|
|
|
+ // const el = this.$refs.orderedDragList
|
|
|
+ // if (!el) {
|
|
|
+ // this.destroyOrderedSortable()
|
|
|
+ // return
|
|
|
+ // }
|
|
|
+ // if (this.orderedSortable) {
|
|
|
+ // return
|
|
|
+ // }
|
|
|
+ // this.orderedSortable = Sortable.create(el, {
|
|
|
+ // animation: 180,
|
|
|
+ // filter: '.ordered-qty, .ordered-qty *',
|
|
|
+ // preventOnFilter: false,
|
|
|
+ // ghostClass: 'ordered-drag-ghost',
|
|
|
+ // chosenClass: 'ordered-drag-chosen',
|
|
|
+ // onEnd: (evt) => {
|
|
|
+ // if (evt.oldIndex === evt.newIndex) {
|
|
|
+ // return
|
|
|
+ // }
|
|
|
+ // const list = [...this.orderedList]
|
|
|
+ // const moved = list.splice(evt.oldIndex, 1)[0]
|
|
|
+ // list.splice(evt.newIndex, 0, moved)
|
|
|
+ // this.orderedList = list
|
|
|
+ // this.refreshDishSort()
|
|
|
+ // }
|
|
|
+ // })
|
|
|
},
|
|
|
destroyOrderedSortable() {
|
|
|
if (this.orderedSortable) {
|
|
|
@@ -598,6 +588,16 @@ export default {
|
|
|
line-height: 20px;
|
|
|
}
|
|
|
|
|
|
+.order-header-actions {
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ gap: 10px;
|
|
|
+}
|
|
|
+
|
|
|
+.order-header-actions .el-button+.el-button {
|
|
|
+ margin-left: 0;
|
|
|
+}
|
|
|
+
|
|
|
.order-main {
|
|
|
flex: 1;
|
|
|
min-height: 0;
|
|
|
@@ -607,6 +607,10 @@ export default {
|
|
|
padding-top: 16px;
|
|
|
}
|
|
|
|
|
|
+.ordered-panel-full {
|
|
|
+ grid-column: 1 / -1;
|
|
|
+}
|
|
|
+
|
|
|
.dish-panel,
|
|
|
.ordered-panel {
|
|
|
min-height: 0;
|
|
|
@@ -768,7 +772,7 @@ export default {
|
|
|
gap: 8px;
|
|
|
}
|
|
|
|
|
|
-.ordered-title-actions .el-button + .el-button {
|
|
|
+.ordered-title-actions .el-button+.el-button {
|
|
|
margin-left: 0;
|
|
|
}
|
|
|
|
|
|
@@ -827,13 +831,13 @@ export default {
|
|
|
|
|
|
.ordered-item {
|
|
|
min-height: 64px;
|
|
|
- cursor: grab;
|
|
|
+ /* cursor: grab; */
|
|
|
padding: 10px 8px;
|
|
|
border-bottom: 1px solid #ebeef5;
|
|
|
}
|
|
|
|
|
|
.ordered-item-pending {
|
|
|
- background: rgba(45, 140, 240, 0.3);
|
|
|
+ /* background: rgba(45, 140, 240, 0.3); */
|
|
|
}
|
|
|
|
|
|
.ordered-dish {
|
|
|
@@ -874,7 +878,7 @@ export default {
|
|
|
.ordered-qty {
|
|
|
display: flex;
|
|
|
align-items: center;
|
|
|
- justify-content: flex-end;
|
|
|
+ justify-content: center;
|
|
|
gap: 8px;
|
|
|
}
|
|
|
|
|
|
@@ -905,64 +909,16 @@ export default {
|
|
|
}
|
|
|
|
|
|
.ordered-actions {
|
|
|
- display: grid;
|
|
|
- grid-template-columns: 1fr 1fr;
|
|
|
- gap: 10px;
|
|
|
-}
|
|
|
-
|
|
|
-.ordered-actions-with-cancel {
|
|
|
- grid-template-columns: 1fr 1fr;
|
|
|
-}
|
|
|
-
|
|
|
-.ordered-actions .el-button {
|
|
|
- width: 100%;
|
|
|
-}
|
|
|
-
|
|
|
-.settle-normal {
|
|
|
- height: 96px;
|
|
|
display: flex;
|
|
|
- align-items: center;
|
|
|
- justify-content: space-between;
|
|
|
- padding: 0 4px;
|
|
|
- font-size: 15px;
|
|
|
- color: #606266;
|
|
|
-}
|
|
|
-
|
|
|
-.settle-normal strong {
|
|
|
- font-size: 28px;
|
|
|
- color: #f56c6c;
|
|
|
-}
|
|
|
-
|
|
|
-.settle-preview {
|
|
|
- display: grid;
|
|
|
- grid-template-columns: repeat(3, minmax(0, 1fr));
|
|
|
- gap: 10px;
|
|
|
- margin-bottom: 18px;
|
|
|
- padding: 12px;
|
|
|
- border-radius: 6px;
|
|
|
- background: #f7f8fa;
|
|
|
-}
|
|
|
-
|
|
|
-.settle-preview div {
|
|
|
- min-width: 0;
|
|
|
+ justify-content: flex-end;
|
|
|
}
|
|
|
|
|
|
-.settle-preview span {
|
|
|
- display: block;
|
|
|
- font-size: 12px;
|
|
|
- line-height: 18px;
|
|
|
- color: #909399;
|
|
|
+.ordered-actions-settle-only {
|
|
|
+ justify-content: flex-end;
|
|
|
}
|
|
|
|
|
|
-.settle-preview strong {
|
|
|
- display: block;
|
|
|
- margin-top: 4px;
|
|
|
- font-size: 15px;
|
|
|
- line-height: 22px;
|
|
|
- color: #303133;
|
|
|
- white-space: nowrap;
|
|
|
- overflow: hidden;
|
|
|
- text-overflow: ellipsis;
|
|
|
+.ordered-actions .el-button {
|
|
|
+ width: 50%;
|
|
|
}
|
|
|
|
|
|
@media (max-width: 1280px) {
|