diandan.vue 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629
  1. <template>
  2. <a-card :bordered="false" class="card-pd">
  3. <a-tabs v-model="tabPosTypeId" @change="tabPosTypeChange">
  4. <a-tab-pane
  5. :key="item.id"
  6. :tab="item.name"
  7. v-for="item in posTypeList"
  8. ></a-tab-pane>
  9. </a-tabs>
  10. <div style="display: flex; height: calc(100vh - 350px)">
  11. <a-card style="width: 30%">
  12. <a href="#" @click="remarkModal"> <a-icon type="edit" />整单备注</a>
  13. &nbsp;&nbsp;<a-icon type="user" />
  14. <span v-if="selectRoomOrder && selectRoomOrder.roomName">
  15. 房间:{{ selectRoomOrder.roomName }},姓名:{{
  16. selectRoomOrder.customerName
  17. }}
  18. </span>
  19. <a-table
  20. bordered
  21. :columns="columns"
  22. :data-source="selectGoodsList"
  23. :row-selection="rowSelection"
  24. rowKey="id"
  25. :scroll="{ y: 560 }"
  26. >
  27. <template slot="num" slot-scope="text, record, index">
  28. <div>
  29. <a-input-number
  30. v-model="record.num"
  31. :max="record.inventory"
  32. @change="(event) => numChange(event, index)"
  33. />
  34. </div>
  35. </template>
  36. <template slot="required" slot-scope="text, record, index">
  37. <div>
  38. <a-switch v-model="record.required" />
  39. </div>
  40. </template>
  41. <span slot="action" slot-scope="text, record, index">
  42. <a @click="handleDelete(index)">删除</a>
  43. </span>
  44. </a-table>
  45. <p>数量:{{ sum }}</p>
  46. <div style="display: flex; gap: 5px; flex-flow: wrap">
  47. <a-button @click="handleClear" :disabled="btnDisabled">清空</a-button>
  48. <!-- <a-button @click="handleAdd" :disabled="btnDisabled">备注</a-button> -->
  49. <!-- <a-button :disabled="btnDisabled">退货</a-button> -->
  50. <a-button v-if="!btnDisabled" @click="handleAdd">挂单</a-button>
  51. <a-button v-else @click="handlePickingGoodsOrder">取单</a-button>
  52. <a-button
  53. v-if="selectRoomOrder && selectRoomOrder.roomName && !btnDisabled"
  54. @click="handleToRoomFeePayment"
  55. >确定挂房帐</a-button
  56. >
  57. <a-button v-else @click="handleSelectCheckInRoomOrder"
  58. >挂房帐</a-button
  59. >
  60. <a-button :disabled="btnDisabled" type="danger" @click="handlePayment"
  61. >结账¥{{ amount.toFixed(2) }}</a-button
  62. >
  63. <a-button :disabled="btnDisabled" @click="refundChange">退货</a-button>
  64. </div>
  65. </a-card>
  66. <a-card style="width: 75%; position: relative">
  67. <a-tabs v-model="tabgoodsTypeId" @change="tabGoodsTypeChange">
  68. <a-tab-pane key="1" tab="全部"></a-tab-pane>
  69. <a-tab-pane
  70. :key="item.id"
  71. :tab="item.name"
  72. v-for="item in goodsTypeList"
  73. ></a-tab-pane>
  74. </a-tabs>
  75. <a-row :gutter="[5, 5]">
  76. <a-col
  77. v-for="item in dataSource"
  78. :key="item.id"
  79. :span="3"
  80. @click.stop="itemClick(item)"
  81. >
  82. <div class="room-item check">
  83. <div class="select-cell"></div>
  84. <template v-if="item.id != '0'">
  85. <div>{{ item.name }}</div>
  86. <div style="margin-top: 10px; color: red">
  87. ¥{{ item.sellingPrice.toFixed(2) }}
  88. </div>
  89. <div style="margin-top: 10px">库{{ item.inventory }}</div>
  90. <div
  91. v-if="item.isSellClear"
  92. style="display: flex; justify-content: right"
  93. >
  94. <a-tag color="#f50"> 沽清 </a-tag>
  95. </div>
  96. </template>
  97. <template v-else>
  98. <div style="font-weight: 800; text-align: center">+临时菜</div>
  99. </template>
  100. </div>
  101. </a-col>
  102. <a-col
  103. v-for="item in dataSource2"
  104. :key="item.id"
  105. :span="3"
  106. @click.stop="itemClick2(item)"
  107. >
  108. <div class="room-item check">
  109. <div class="select-cell"></div>
  110. <div style="display: flex">
  111. <a-tag color="#506fee"> 套 </a-tag>
  112. </div>
  113. <div>{{ item.name }}</div>
  114. <div style="margin-top: 10px; color: red">
  115. ¥{{ item.price.toFixed(2) }}
  116. </div>
  117. </div>
  118. </a-col>
  119. </a-row>
  120. <a-row style="margin-top: 30px">
  121. <a-space>
  122. <a-input
  123. v-if="!isSaoma"
  124. placeholder="输入名称、简拼、条码"
  125. ></a-input>
  126. <a-input v-else placeholder="请扫描条码"></a-input>
  127. <a-button v-if="!isSaoma">查询</a-button>
  128. <a-button @click="isSaoma = !isSaoma"
  129. >切换为{{ isSaoma ? "查询" : "扫码" }}模式</a-button
  130. >
  131. </a-space>
  132. </a-row>
  133. </a-card>
  134. </div>
  135. <payment-modal ref="modalPaymentForm" @ok="modalFormOk"></payment-modal>
  136. <goods-modal ref="modalGoodsForm" @ok="modalFormOk2"></goods-modal>
  137. <picking-goods-order-modal
  138. ref="modalPickingGoodsOrderForm"
  139. @ok="modalPickingGoodsOrderFormOk"
  140. ></picking-goods-order-modal>
  141. <select-check-in-room-order-modal
  142. ref="modalSelectCheckInRoomOrderModal"
  143. @ok="modalSelectCheckInRoomOrderFormOk"
  144. ></select-check-in-room-order-modal>
  145. <!-- 整单备注弹窗 -->
  146. <a-modal
  147. @cancel="isRemarkModal = false"
  148. :visible="isRemarkModal"
  149. title="添加备注"
  150. @ok="remarkModalOk"
  151. >
  152. <a-form-model>
  153. <a-form-model-item label="备注">
  154. <a-input v-model="remark" type="textarea" />
  155. </a-form-model-item>
  156. </a-form-model>
  157. </a-modal>
  158. <!-- 退货弹窗 -->
  159. <a-modal
  160. @cancel="isRefund = false"
  161. :visible="isRefund"
  162. title="退货"
  163. @ok="refundModalOk"
  164. >
  165. <a-form-model>
  166. <a-form-model-item label="备注">
  167. <a-input v-model="refundRemark" />
  168. </a-form-model-item>
  169. </a-form-model>
  170. </a-modal>
  171. </a-card>
  172. </template>
  173. <script>
  174. // import { JeecgListMixin } from "@/mixins/JeecgListMixin";
  175. // import PosRegionModal from "./modules/PosRegionModal";
  176. import { filterObj } from "@/utils/util";
  177. import { getAction, postAction, deleteAction } from "@/api/manage";
  178. import PaymentModal from "./modules/PaymentModal.vue";
  179. import goodsModal from "./modules/goodStock/goodsModal.vue";
  180. import PickingGoodsOrderModal from "./modules/PickingGoodsOrderModal.vue";
  181. import SelectCheckInRoomOrderModal from "./modules/SelectCheckInRoomOrderModal.vue";
  182. import { computed } from "vue";
  183. import { tree } from "@/api/good";
  184. const columns = [
  185. {
  186. title: "商品名称",
  187. dataIndex: "name",
  188. },
  189. {
  190. title: "数量",
  191. dataIndex: "num",
  192. scopedSlots: {
  193. customRender: "num",
  194. },
  195. },
  196. {
  197. title: "售价",
  198. dataIndex: "sellingPrice",
  199. },
  200. ];
  201. export default {
  202. name: "memberList",
  203. components: {
  204. PaymentModal,
  205. goodsModal,
  206. PickingGoodsOrderModal,
  207. SelectCheckInRoomOrderModal,
  208. },
  209. data() {
  210. return {
  211. isRemarkModal: false,
  212. isSaoma: false,
  213. remark: "",
  214. columns,
  215. isRefund: false,
  216. refundRemark: "",
  217. sellClear: 0,
  218. queryParam: {},
  219. // 分页参数
  220. ipagination: {
  221. current: 1,
  222. pageSize: 99999,
  223. pageSizeOptions: ["10", "20", "30"],
  224. showTotal: (total, range) => {
  225. return range[0] + "-" + range[1] + " 共" + total + "条";
  226. },
  227. showQuickJumper: true,
  228. showSizeChanger: true,
  229. total: 0,
  230. },
  231. url: {
  232. list: "/pos/posSellClearGoods/list",
  233. delete: "/pos/posSellClearGoods/delete",
  234. deleteBatch: "/pos/posSellClearGoods/deleteBatch",
  235. exportXlsUrl: "/pos/posSellClearGoods/exportXls",
  236. importExcelUrl: "pos/posSellClearGoods/importExcel",
  237. },
  238. dictOptions: {},
  239. superFieldList: [],
  240. selectedRowKeys: [],
  241. selectedRows: [],
  242. isorter: {
  243. column: "createTime",
  244. order: "desc",
  245. },
  246. treeData: [],
  247. selectGoods: {},
  248. posTypeList: [],
  249. tabPosTypeId: "",
  250. selectGoodsList: [],
  251. goodsTypeList: [],
  252. tabgoodsTypeId: "1",
  253. dataSource: [],
  254. dataSource2: [],
  255. oldSelectGoodsList: [],
  256. selectOrderInfo: {},
  257. selectRoomOrder: {},
  258. };
  259. },
  260. provide() {
  261. return {
  262. treeData: computed(() => this.treeData),
  263. };
  264. },
  265. computed: {
  266. rowSelection() {
  267. return {
  268. onChange: (selectedRowKeys, selectedRows) => {
  269. console.log(
  270. `selectedRowKeys: ${selectedRowKeys}`,
  271. "selectedRows: ",
  272. selectedRows
  273. );
  274. this.selectedRowKeys = selectedRowKeys;
  275. this.selectedRows = selectedRows;
  276. },
  277. getCheckboxProps: (record) => ({
  278. props: {
  279. disabled: record.name === "Disabled User", // Column configuration not to be checked
  280. name: record.name,
  281. },
  282. }),
  283. };
  284. },
  285. sum() {
  286. return this.selectGoodsList.reduce(function (total, item) {
  287. return total + item.num;
  288. }, 0);
  289. },
  290. amount() {
  291. return this.selectGoodsList.reduce(function (total, item) {
  292. return total + item.sellingPrice * item.num;
  293. }, 0);
  294. },
  295. btnDisabled() {
  296. var res = this.selectGoodsList && this.selectGoodsList.length > 0;
  297. return !res;
  298. },
  299. },
  300. created() {
  301. this.dataSource = [
  302. {
  303. id: "0",
  304. },
  305. ];
  306. getAction("/pos/posType/list", {
  307. pageNo: 1,
  308. pageSize: 99,
  309. }).then((res) => {
  310. if (res.success) {
  311. this.posTypeList = res.result.records;
  312. if (this.posTypeList && this.posTypeList.length > 0) {
  313. this.tabPosTypeId = this.posTypeList[0].id;
  314. this.loadGoodsType();
  315. }
  316. }
  317. });
  318. this.loadTree();
  319. },
  320. methods: {
  321. remarkModal() {
  322. if (!this.selectGoodsList || this.selectGoodsList.length <= 0) {
  323. this.$message.warning("请先选择商品");
  324. return;
  325. }
  326. this.isRemarkModal = true;
  327. },
  328. refundModalOk(){
  329. },
  330. /**
  331. * 退货
  332. */
  333. refundChange(){
  334. this.$message.warning("未下单餐品不支持退菜,请重新选择");
  335. return
  336. if(this.selectedRows.length == 0){
  337. this.$message.warning("请先选择菜品");
  338. return;
  339. }
  340. this.isRefund = true;
  341. },
  342. remarkModalOk() {
  343. this.handleAdd()
  344. this.remark = "";
  345. this.isRemarkModal = false;
  346. },
  347. onClearSelected() {
  348. this.selectedRowKeys = [];
  349. this.selectionRows = [];
  350. },
  351. loadTree() {
  352. var that = this;
  353. tree().then((res) => {
  354. if (res.success) {
  355. this.treeData = res.result;
  356. }
  357. });
  358. },
  359. modalFormOk() {},
  360. modalFormOk2(e) {
  361. console.log(e);
  362. var good = JSON.parse(JSON.stringify(e));
  363. this.$set(good, "num", 1);
  364. this.selectGoodsList.push(good);
  365. },
  366. modalSelectCheckInRoomOrderFormOk(e) {
  367. console.log(e);
  368. this.selectRoomOrder = e;
  369. },
  370. modalPickingGoodsOrderFormOk(e) {
  371. console.log(e);
  372. if (e && e.orderDetailList && e.orderDetailList.length > 0) {
  373. this.selectOrderInfo = e.orderInfo;
  374. e.orderDetailList.forEach((t) => {
  375. t.sellingPrice = t.payMoney;
  376. t.name = t.goodsName;
  377. t.id = t.goodsId;
  378. });
  379. this.selectGoodsList = e.orderDetailList;
  380. }
  381. },
  382. numChange(e, index) {
  383. console.log(e);
  384. if (e <= 0) {
  385. this.selectGoodsList.splice(index, 1);
  386. }
  387. },
  388. handleClear() {
  389. this.selectGoodsList = [];
  390. // this.selectOrderInfo = {};
  391. },
  392. tabPosTypeChange(e) {
  393. this.loadGoodsType();
  394. },
  395. tabGoodsTypeChange(e) {
  396. this.loadGoods();
  397. },
  398. loadGoodsType() {
  399. getAction("/rooms/cesStockType/getTopTypesByPosType", {
  400. posType: this.tabPosTypeId,
  401. }).then((res2) => {
  402. if (res2.success) {
  403. this.goodsTypeList = res2.result;
  404. if (this.goodsTypeList && this.goodsTypeList.length > 0) {
  405. this.loadGoods();
  406. }
  407. }
  408. });
  409. },
  410. loadGoods() {
  411. var ids = [];
  412. if (this.tabgoodsTypeId === "1") {
  413. this.goodsTypeList.forEach((t) => {
  414. ids.push(t.id);
  415. });
  416. } else {
  417. ids.push(this.tabgoodsTypeId);
  418. }
  419. this.dataSource = [
  420. {
  421. id: "0",
  422. },
  423. ];
  424. getAction("/pos/posSellClearGoods/list", {
  425. pageNo: 1,
  426. pageSize: 99999,
  427. goodTypes: ids,
  428. }).then((res) => {
  429. if (res.success) {
  430. this.dataSource = [...this.dataSource, ...res.result.records];
  431. }
  432. });
  433. getAction("/pos/posSellClearGoods/thali-list", {
  434. pageNo: 1,
  435. pageSize: 99999,
  436. goodTypes: ids,
  437. }).then((res) => {
  438. if (res.success) {
  439. this.dataSource2 = res.result.records;
  440. }
  441. });
  442. },
  443. handleDelete() {
  444. deleteAction("/pos/posSellClearGoods/delete", {
  445. goodsId: this.selectGoods.id,
  446. })
  447. .then((res) => {
  448. if (res.success) {
  449. this.$message.success(res.message);
  450. this.loadData();
  451. this.sellClear = 0;
  452. } else {
  453. this.$message.warning(res.message);
  454. }
  455. })
  456. .finally(() => {});
  457. },
  458. handleSelectCheckInRoomOrder() {
  459. this.$refs.modalSelectCheckInRoomOrderModal.add();
  460. this.$refs.modalSelectCheckInRoomOrderModal.title = "选择转帐人";
  461. this.$refs.modalSelectCheckInRoomOrderModal.disableSubmit = false;
  462. },
  463. handlePickingGoodsOrder() {
  464. this.$refs.modalPickingGoodsOrderForm.add();
  465. this.$refs.modalPickingGoodsOrderForm.title = "取单";
  466. this.$refs.modalPickingGoodsOrderForm.disableSubmit = false;
  467. },
  468. handleAddTempGoods() {
  469. this.$refs.modalGoodsForm.add();
  470. this.$refs.modalGoodsForm.title = "新增菜品";
  471. this.$refs.modalGoodsForm.disableSubmit = false;
  472. },
  473. handleToRoomFeePayment() {
  474. this.handleAdd();
  475. },
  476. handlePayment() {
  477. this.handleAdd((e) => {
  478. var amount = this.oldSelectGoodsList.reduce(function (total, item) {
  479. return total + item.sellingPrice * item.num;
  480. }, 0);
  481. this.$refs.modalPaymentForm.edit({
  482. billAmount: amount,
  483. deposit: 0,
  484. roomFee: amount,
  485. subjectType: 5,
  486. feeType: 2,
  487. preferentialType: 1,
  488. couponFirstAmount: 0,
  489. discount: 9,
  490. orderCode: e,
  491. });
  492. this.$refs.modalPaymentForm.title = "POS结账";
  493. this.$refs.modalPaymentForm.disableSubmit = false;
  494. });
  495. },
  496. handleAdd(callback) {
  497. if (!this.selectGoodsList || this.selectGoodsList.length <= 0) {
  498. this.$message.warning("请先选择商品");
  499. return;
  500. }
  501. var _info = JSON.parse(localStorage.getItem("storeInfo"));
  502. var model = {
  503. goodsId: this.selectGoods.id,
  504. };
  505. if (_info) {
  506. model.hotelId = _info.id;
  507. }
  508. model.id = this.selectOrderInfo.id;
  509. model.toRoomFeeOrderId = this.selectRoomOrder.livingOrderId;
  510. model.posType = this.tabPosTypeId;
  511. if (this.remark) {
  512. model.remarks = this.remark;
  513. }
  514. var posOrderGoodsDetailList = [];
  515. this.selectGoodsList.forEach((t) => {
  516. posOrderGoodsDetailList.push({
  517. goodsId: t.id,
  518. num: t.num,
  519. money: t.sellingPrice,
  520. });
  521. });
  522. model.posOrderGoodsDetailList = posOrderGoodsDetailList;
  523. postAction("/pos/posOrderGoods/add", model)
  524. .then((res) => {
  525. if (res.success) {
  526. this.$message.success(res.message);
  527. this.oldSelectGoodsList = JSON.parse(
  528. JSON.stringify(this.selectGoodsList)
  529. );
  530. this.selectGoodsList = [];
  531. this.selectOrderInfo = {};
  532. this.selectRoomOrder = {};
  533. this.loadGoods();
  534. if (callback) {
  535. callback(res.result.code);
  536. }
  537. } else {
  538. this.$message.warning(res.message);
  539. }
  540. })
  541. .finally(() => {});
  542. },
  543. itemClick(row) {
  544. console.log(row);
  545. if (row.id == "0") {
  546. this.handleAddTempGoods();
  547. return;
  548. }
  549. if (row.isSellClear) {
  550. this.$message.warning("选择的商品已沽清");
  551. return;
  552. }
  553. var good = JSON.parse(JSON.stringify(row));
  554. this.$set(good, "num", 1);
  555. var find = this.selectGoodsList.find((t) => t.id === row.id);
  556. if (find) {
  557. if (find.inventory > find.num) {
  558. find.num++;
  559. }
  560. } else {
  561. this.selectGoodsList.push(good);
  562. }
  563. },
  564. itemClick2(row) {
  565. console.log(row);
  566. var good = JSON.parse(JSON.stringify(row));
  567. this.$set(good, "num", 1);
  568. this.$set(good, "sellingPrice", good.price);
  569. var find = this.selectGoodsList.find((t) => t.id === row.id);
  570. if (find) {
  571. find.num++;
  572. } else {
  573. this.selectGoodsList.push(good);
  574. }
  575. },
  576. },
  577. };
  578. </script>
  579. <style scoped>
  580. @import "~@assets/less/common.less";
  581. .room-item {
  582. height: 110px;
  583. /* line-height: 200px; */
  584. font-size: 13px;
  585. padding: 0px 5px;
  586. border-radius: 5px;
  587. cursor: pointer;
  588. position: relative;
  589. display: flex;
  590. flex-direction: column;
  591. justify-content: center;
  592. }
  593. .check {
  594. border: #000 solid 3px;
  595. }
  596. .ant-table-wrapper {
  597. height: calc(100vh - 500px);
  598. }
  599. /deep/ .card-pd .ant-card-body {
  600. padding: 0 !important;
  601. }
  602. .select-cell {
  603. position: absolute;
  604. width: 100%;
  605. height: 100%;
  606. left: 0;
  607. top: 0;
  608. z-index: 10;
  609. -webkit-user-select: none;
  610. -moz-user-select: none;
  611. -ms-user-select: none;
  612. user-select: none;
  613. }
  614. </style>