diandan.vue 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460
  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: 25%">
  12. <p v-if="selectRoomOrder && selectRoomOrder.id">
  13. 房间:{{ selectRoomOrder.tableNo }},姓名:{{ selectRoomOrder.id }}
  14. </p>
  15. <a-table
  16. bordered
  17. :columns="columns"
  18. :data-source="selectGoodsList"
  19. :pagination="false"
  20. rowKey="id"
  21. :scroll="{ y: 560 }"
  22. >
  23. <template slot="num" slot-scope="text, record, index">
  24. <div>
  25. <a-input-number
  26. v-model="record.num"
  27. :max="record.inventory"
  28. @change="(event) => numChange(event, index)"
  29. />
  30. </div>
  31. </template>
  32. <template slot="required" slot-scope="text, record, index">
  33. <div>
  34. <a-switch v-model="record.required" />
  35. </div>
  36. </template>
  37. <span slot="action" slot-scope="text, record, index">
  38. <a @click="handleDelete(index)">删除</a>
  39. </span>
  40. </a-table>
  41. <p>数量:{{ sum }}</p>
  42. <div style="display: flex; gap: 5px; flex-flow: wrap">
  43. <a-button @click="handleClear" :disabled="btnDisabled">清空</a-button>
  44. <!-- <a-button @click="handleAdd" :disabled="btnDisabled">备注</a-button> -->
  45. <!-- <a-button :disabled="btnDisabled">退货</a-button> -->
  46. <a-button v-if="!btnDisabled" @click="handleAdd">挂单</a-button>
  47. <a-button v-else @click="handlePickingGoodsOrder">取单</a-button>
  48. <a-button
  49. v-if="selectRoomOrder && selectRoomOrder.id && !btnDisabled"
  50. @click="handleToRoomFeePayment"
  51. >确定挂房帐</a-button
  52. >
  53. <a-button v-else @click="handleSelectCheckInRoomOrder"
  54. >挂房帐</a-button
  55. >
  56. <a-button :disabled="btnDisabled" type="danger" @click="handlePayment"
  57. >结账¥{{ amount.toFixed(2) }}</a-button
  58. >
  59. </div>
  60. </a-card>
  61. <a-card style="width: 75%">
  62. <a-tabs v-model="tabgoodsTypeId" @change="tabGoodsTypeChange">
  63. <a-tab-pane key="1" tab="全部"></a-tab-pane>
  64. <a-tab-pane
  65. :key="item.id"
  66. :tab="item.name"
  67. v-for="item in goodsTypeList"
  68. ></a-tab-pane>
  69. </a-tabs>
  70. <a-row :gutter="[5, 5]">
  71. <a-col
  72. v-for="item in dataSource"
  73. :key="item.id"
  74. :span="3"
  75. @click.stop="itemClick(item)"
  76. >
  77. <div class="room-item check">
  78. <div class="select-cell"></div>
  79. <template v-if="item.id != '0'">
  80. <div>{{ item.name }}</div>
  81. <div style="margin-top: 10px; color: red">
  82. ¥{{ item.sellingPrice.toFixed(2) }}
  83. </div>
  84. <div style="margin-top: 10px">库{{ item.inventory }}</div>
  85. <div
  86. v-if="item.isSellClear"
  87. style="display: flex; justify-content: right"
  88. >
  89. <a-tag color="#f50"> 沽清 </a-tag>
  90. </div></template
  91. >
  92. <template v-else>
  93. <div style="font-weight: 800; text-align: center">+临时菜</div>
  94. </template>
  95. </div>
  96. </a-col>
  97. </a-row>
  98. </a-card>
  99. </div>
  100. <payment-modal ref="modalPaymentForm" @ok="modalFormOk"></payment-modal>
  101. <goods-modal ref="modalGoodsForm" @ok="modalFormOk2"></goods-modal>
  102. <picking-goods-order-modal
  103. ref="modalPickingGoodsOrderForm"
  104. @ok="modalPickingGoodsOrderFormOk"
  105. ></picking-goods-order-modal>
  106. <select-check-in-room-order-modal
  107. ref="modalSelectCheckInRoomOrderModal"
  108. @ok="modalSelectCheckInRoomOrderFormOk"
  109. ></select-check-in-room-order-modal>
  110. </a-card>
  111. </template>
  112. <script>
  113. // import { JeecgListMixin } from "@/mixins/JeecgListMixin";
  114. // import PosRegionModal from "./modules/PosRegionModal";
  115. import { filterObj } from "@/utils/util";
  116. import { getAction, postAction, deleteAction } from "@/api/manage";
  117. import PaymentModal from "./modules/PaymentModal.vue";
  118. import goodsModal from "./modules/goodStock/goodsModal.vue";
  119. import PickingGoodsOrderModal from "./modules/PickingGoodsOrderModal.vue";
  120. import SelectCheckInRoomOrderModal from "./modules/SelectCheckInRoomOrderModal.vue";
  121. import { computed } from "vue";
  122. import { tree } from "@/api/good";
  123. const columns = [
  124. {
  125. title: "商品名称",
  126. dataIndex: "name",
  127. },
  128. {
  129. title: "数量",
  130. dataIndex: "num",
  131. scopedSlots: { customRender: "num" },
  132. },
  133. {
  134. title: "售价",
  135. dataIndex: "sellingPrice",
  136. },
  137. ];
  138. export default {
  139. name: "memberList",
  140. components: {
  141. PaymentModal,
  142. goodsModal,
  143. PickingGoodsOrderModal,
  144. SelectCheckInRoomOrderModal,
  145. },
  146. data() {
  147. return {
  148. columns,
  149. sellClear: 0,
  150. queryParam: {},
  151. // 分页参数
  152. ipagination: {
  153. current: 1,
  154. pageSize: 99999,
  155. pageSizeOptions: ["10", "20", "30"],
  156. showTotal: (total, range) => {
  157. return range[0] + "-" + range[1] + " 共" + total + "条";
  158. },
  159. showQuickJumper: true,
  160. showSizeChanger: true,
  161. total: 0,
  162. },
  163. url: {
  164. list: "/pos/posSellClearGoods/list",
  165. delete: "/pos/posSellClearGoods/delete",
  166. deleteBatch: "/pos/posSellClearGoods/deleteBatch",
  167. exportXlsUrl: "/pos/posSellClearGoods/exportXls",
  168. importExcelUrl: "pos/posSellClearGoods/importExcel",
  169. },
  170. dictOptions: {},
  171. superFieldList: [],
  172. selectedRowKeys: [],
  173. isorter: {
  174. column: "createTime",
  175. order: "desc",
  176. },
  177. treeData: [],
  178. selectGoods: {},
  179. posTypeList: [],
  180. tabPosTypeId: "",
  181. selectGoodsList: [],
  182. goodsTypeList: [],
  183. tabgoodsTypeId: "1",
  184. dataSource: [],
  185. oldSelectGoodsList: [],
  186. selectOrderInfo: {},
  187. selectRoomOrder: {},
  188. };
  189. },
  190. provide() {
  191. return {
  192. treeData: computed(() => this.treeData),
  193. };
  194. },
  195. computed: {
  196. sum() {
  197. return this.selectGoodsList.reduce(function (total, item) {
  198. return total + item.num;
  199. }, 0);
  200. },
  201. amount() {
  202. return this.selectGoodsList.reduce(function (total, item) {
  203. return total + item.sellingPrice * item.num;
  204. }, 0);
  205. },
  206. btnDisabled() {
  207. var res = this.selectGoodsList && this.selectGoodsList.length > 0;
  208. return !res;
  209. },
  210. },
  211. created() {
  212. this.dataSource = [{ id: "0" }];
  213. getAction("/pos/posType/list", { pageNo: 1, pageSize: 99 }).then((res) => {
  214. if (res.success) {
  215. this.posTypeList = res.result.records;
  216. if (this.posTypeList && this.posTypeList.length > 0) {
  217. this.tabPosTypeId = this.posTypeList[0].id;
  218. this.loadGoodsType();
  219. }
  220. }
  221. });
  222. this.loadTree();
  223. },
  224. methods: {
  225. loadTree() {
  226. var that = this;
  227. tree().then((res) => {
  228. if (res.success) {
  229. this.treeData = res.result;
  230. }
  231. });
  232. },
  233. modalFormOk() {},
  234. modalFormOk2(e) {
  235. console.log(e);
  236. var good = JSON.parse(JSON.stringify(e));
  237. this.$set(good, "num", 1);
  238. this.selectGoodsList.push(good);
  239. },
  240. modalSelectCheckInRoomOrderFormOk(e) {
  241. console.log(e);
  242. this.selectRoomOrder = e;
  243. },
  244. modalPickingGoodsOrderFormOk(e) {
  245. console.log(e);
  246. if (e && e.orderDetailList && e.orderDetailList.length > 0) {
  247. this.selectOrderInfo = e.orderInfo;
  248. e.orderDetailList.forEach((t) => {
  249. t.sellingPrice = t.payMoney;
  250. t.name = t.goodsName;
  251. t.id = t.goodsId;
  252. });
  253. this.selectGoodsList = e.orderDetailList;
  254. }
  255. },
  256. numChange(e, index) {
  257. console.log(e);
  258. if (e <= 0) {
  259. this.selectGoodsList.splice(index, 1);
  260. }
  261. },
  262. handleClear() {
  263. this.selectGoodsList = [];
  264. // this.selectOrderInfo = {};
  265. },
  266. tabPosTypeChange(e) {
  267. this.loadGoodsType();
  268. },
  269. tabGoodsTypeChange(e) {
  270. this.loadGoods();
  271. },
  272. loadGoodsType() {
  273. getAction("/rooms/cesStockType/getTopTypesByPosType", {
  274. posType: this.tabPosTypeId,
  275. }).then((res2) => {
  276. if (res2.success) {
  277. this.goodsTypeList = res2.result;
  278. if (this.goodsTypeList && this.goodsTypeList.length > 0) {
  279. this.loadGoods();
  280. }
  281. }
  282. });
  283. },
  284. loadGoods() {
  285. var ids = [];
  286. if (this.tabgoodsTypeId === "1") {
  287. this.goodsTypeList.forEach((t) => {
  288. ids.push(t.id);
  289. });
  290. } else {
  291. ids.push(this.tabgoodsTypeId);
  292. }
  293. this.dataSource = [{ id: "0" }];
  294. getAction("/pos/posSellClearGoods/list", {
  295. pageNo: 1,
  296. pageSize: 99999,
  297. goodTypes: ids,
  298. }).then((res) => {
  299. if (res.success) {
  300. this.dataSource = [...this.dataSource, ...res.result.records];
  301. }
  302. });
  303. },
  304. handleDelete() {
  305. deleteAction("/pos/posSellClearGoods/delete", {
  306. goodsId: this.selectGoods.id,
  307. })
  308. .then((res) => {
  309. if (res.success) {
  310. this.$message.success(res.message);
  311. this.loadData();
  312. this.sellClear = 0;
  313. } else {
  314. this.$message.warning(res.message);
  315. }
  316. })
  317. .finally(() => {});
  318. },
  319. handleSelectCheckInRoomOrder() {
  320. this.$refs.modalSelectCheckInRoomOrderModal.add();
  321. this.$refs.modalSelectCheckInRoomOrderModal.title = "选择转帐人";
  322. this.$refs.modalSelectCheckInRoomOrderModal.disableSubmit = false;
  323. },
  324. handlePickingGoodsOrder() {
  325. this.$refs.modalPickingGoodsOrderForm.add();
  326. this.$refs.modalPickingGoodsOrderForm.title = "取单";
  327. this.$refs.modalPickingGoodsOrderForm.disableSubmit = false;
  328. },
  329. handleAddTempGoods() {
  330. this.$refs.modalGoodsForm.add();
  331. this.$refs.modalGoodsForm.title = "新增菜品";
  332. this.$refs.modalGoodsForm.disableSubmit = false;
  333. },
  334. handleToRoomFeePayment() {
  335. this.handleAdd();
  336. },
  337. handlePayment() {
  338. this.handleAdd((e) => {
  339. var amount = this.oldSelectGoodsList.reduce(function (total, item) {
  340. return total + item.sellingPrice * item.num;
  341. }, 0);
  342. this.$refs.modalPaymentForm.edit({
  343. billAmount: amount,
  344. deposit: 0,
  345. roomFee: amount,
  346. subjectType: 5,
  347. feeType: 2,
  348. preferentialType: 1,
  349. couponFirstAmount: 0,
  350. discount: 9,
  351. orderCode: e,
  352. });
  353. this.$refs.modalPaymentForm.title = "POS结账";
  354. this.$refs.modalPaymentForm.disableSubmit = false;
  355. });
  356. },
  357. handleAdd(callback) {
  358. if (!this.selectGoodsList || this.selectGoodsList.length <= 0) {
  359. this.$message.warning("请先选择商品");
  360. return;
  361. }
  362. var _info = JSON.parse(localStorage.getItem("storeInfo"));
  363. var model = { goodsId: this.selectGoods.id };
  364. if (_info) {
  365. model.hotelId = _info.id;
  366. }
  367. model.id = this.selectOrderInfo.id;
  368. model.toRoomFeeOrderId = this.selectRoomOrder.id;
  369. model.posType = this.tabPosTypeId;
  370. var posOrderGoodsDetailList = [];
  371. this.selectGoodsList.forEach((t) => {
  372. posOrderGoodsDetailList.push({
  373. goodsId: t.id,
  374. num: t.num,
  375. money: t.sellingPrice,
  376. });
  377. });
  378. model.posOrderGoodsDetailList = posOrderGoodsDetailList;
  379. postAction("/pos/posOrderGoods/add", model)
  380. .then((res) => {
  381. if (res.success) {
  382. this.$message.success(res.message);
  383. this.oldSelectGoodsList = JSON.parse(
  384. JSON.stringify(this.selectGoodsList)
  385. );
  386. this.selectGoodsList = [];
  387. this.selectOrderInfo = {};
  388. this.selectRoomOrder = {};
  389. this.loadGoods();
  390. if (callback) {
  391. callback(res.result.code);
  392. }
  393. } else {
  394. this.$message.warning(res.message);
  395. }
  396. })
  397. .finally(() => {});
  398. },
  399. itemClick(row) {
  400. console.log(row);
  401. if (row.id == "0") {
  402. this.handleAddTempGoods();
  403. return;
  404. }
  405. if (row.isSellClear) {
  406. this.$message.warning("选择的商品已沽清");
  407. return;
  408. }
  409. var good = JSON.parse(JSON.stringify(row));
  410. this.$set(good, "num", 1);
  411. var find = this.selectGoodsList.find((t) => t.id === row.id);
  412. if (find) {
  413. if (find.inventory > find.num) {
  414. find.num++;
  415. }
  416. } else {
  417. this.selectGoodsList.push(good);
  418. }
  419. },
  420. },
  421. };
  422. </script>
  423. <style scoped>
  424. @import "~@assets/less/common.less";
  425. .room-item {
  426. height: 110px;
  427. /* line-height: 200px; */
  428. font-size: 13px;
  429. padding: 0px 5px;
  430. border-radius: 5px;
  431. cursor: pointer;
  432. position: relative;
  433. display: flex;
  434. flex-direction: column;
  435. justify-content: center;
  436. }
  437. .check {
  438. border: #000 solid 3px;
  439. }
  440. .ant-table-wrapper {
  441. height: calc(100vh - 500px);
  442. }
  443. /deep/ .card-pd .ant-card-body {
  444. padding: 0 !important;
  445. }
  446. .select-cell {
  447. position: absolute;
  448. width: 100%;
  449. height: 100%;
  450. left: 0;
  451. top: 0;
  452. z-index: 10;
  453. -webkit-user-select: none;
  454. -moz-user-select: none;
  455. -ms-user-select: none;
  456. user-select: none;
  457. }
  458. </style>