index.vue 12KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340
  1. <template>
  2. <div class="subPage">
  3. <div class="system-table-search">
  4. <div class="flex-h">
  5. <div class="flex-item flex-h">
  6. <el-button size="mini" v-if="!businessStatus" type="danger" @click="open">营业</el-button>
  7. <el-button size="mini" v-else type="submit" @click="close">歇业</el-button>
  8. </div>
  9. <ul>
  10. <li>
  11. <el-select v-model="caseid" placeholder="请选择案场">
  12. <el-option
  13. v-for="item in cases"
  14. :key="item.CaseId"
  15. :label="item.CaseName"
  16. :value="item.CaseId">
  17. </el-option>
  18. </el-select>
  19. </li>
  20. </ul>
  21. <el-button
  22. size="mini"
  23. type="primary" @click="init">搜索</el-button>
  24. </div>
  25. <div class="moreFilter"></div>
  26. </div>
  27. <div class="order-list-box">
  28. <div style='position:relative;' v-for="(item,index) in list" :key="index">
  29. <div>
  30. <div style="padding:25px 20px 5px;border-bottom:2px solid #cccccc;display:flex;align-items: center;">
  31. <!-- <i class="iconfont icon-yinchenglogo" style="font-size:70px;color:red;position: relative;bottom: 20px;margin-right:10px;"></i> -->
  32. <img :src="item.AreaIcon" style="width:70px;height:70px;margin-right:10px;">
  33. <div style="display:inline-block;">
  34. <span style="display:block;font-size:20px;font-weight:700;width:180px;white-space: initial;">{{item.AreaName + item.TableNo}}</span>
  35. <span style="display:block;margin-top:10px">下单时间:{{toolClass.dateFormat(item.CreateDate)}}</span>
  36. <span style="display:block;margin-top:10px">已等待:<span style="color:red;font-weight:700;">{{leftTimes[item.OrdersId]}}</span></span>
  37. </div>
  38. </div>
  39. <div style="padding:10px 20px 5px;border-bottom:1px solid #cccccc;" v-for='(item1,index1) in item.Goods' :key='index1'>
  40. <div style="display:flex;justify-content: space-between;align-items: center;padding-right: 10px;"><span>{{item1.GoodsName}}</span><span style="display:inline-block;width:20%;text-align:right" v-if='!item1.SpecName'>× {{item1.Number}}</span></div>
  41. <div style="margin-top:8px;" v-if='item1.SpecName'>
  42. <span style="display:inline-block;width:75%;text-align:left;color:#cccccc">{{item1.SpecName}}</span>
  43. <span style="display:inline-block;width:20%;text-align:right">× {{item1.Number}}</span>
  44. </div>
  45. </div>
  46. <div style="padding:10px 20px;border-bottom:1px solid #cccccc;white-space: normal;">备注:{{item.Remark}}</div>
  47. <div style="padding:10px 20px;" @click="printPdf(`item${index}`)">下单人:{{item.UserName}}</div>
  48. </div>
  49. <div class="print-area" :class="'item_' + item.OrdersId" style="width:180px;">
  50. <div style="padding:0px 10px 5px;border-bottom:2px solid #cccccc;">
  51. <div style="display:inline-block;">
  52. <img class="topIcon" style="display:block;width:60%;margin:0 0 20px 0px;" src="http://jingcheng-resourceplat.oss-cn-shanghai.aliyuncs.com/upload/111101940020.png" alt="">
  53. <span style="display:block;font-size:20px;font-weight:700;text-align: center;"> <img width='25px' height="25px" :src='item.AreaIconWhite' alt=""> {{item.AreaName + item.TableNo}}</span>
  54. </div>
  55. </div>
  56. <div style="padding:10px 10px 5px;border-bottom:1px solid #cccccc;" v-for='(item1,index1) in item.Goods' :key='index1'>
  57. <div style="font-size:12px;"><span style="display:inline-block;width:75%;text-align:left;">{{item1.GoodsName}}</span><span style="display:inline-block;width:22%;text-align:right;font-size:12px;" v-if='!item1.SpecName'>× {{item1.Number}}</span></div>
  58. <div style="margin-top:8px;" v-if='item1.SpecName'>
  59. <span style="display:inline-block;width:75%;text-align:left;color:#cccccc;font-size:12px;">{{item1.SpecName}}</span>
  60. <span style="display:inline-block;width:20%;text-align:right;font-size:12px;">× {{item1.Number}}</span>
  61. </div>
  62. </div>
  63. <div style="padding:10px 10px 5px;border-bottom:1px solid #cccccc;">
  64. <div style="font-size:12px;">下单人:{{item.UserName}}</div>
  65. <span style="display:block;margin-top:10px;font-size:12px;">下单时间:{{toolClass.dateFormat(item.CreateDate)}}</span>
  66. </div>
  67. <div style="padding:10px 10px;font-size:12px;">备注:{{item.Remark}}</div>
  68. <div style="text-align: right;font-size: 12px;">城的空间.城咖啡</div>
  69. <div style="height:10px"></div>
  70. </div>
  71. <div class="btns">
  72. <span @click="cancel(item.OrdersId,index)">取消</span>
  73. <span @click="submit(item.OrdersId,index)">确定</span>
  74. </div>
  75. </div>
  76. </div>
  77. </div>
  78. </template>
  79. <script>
  80. import { createNamespacedHelpers, mapState, mapActions } from 'vuex'
  81. import { getLodop } from '@/util/LodopFuncs'
  82. import { formatTimeBySeconds } from '@/util/util'
  83. import { replaceURLParams } from '@/util/ajax'
  84. // const WebSocket = require('ws')
  85. const { mapState: mapOrderState, mapActions: mapOrderActions } = createNamespacedHelpers('goodsorder')
  86. var LODOP
  87. export default {
  88. name: '',
  89. data () {
  90. return {
  91. total: 0,
  92. postData: { // 表格搜索条件
  93. phone: '', // 手机号
  94. page: 1, // 当前页码
  95. pagesize: 10, // 请求数据量
  96. },
  97. currentList: [],
  98. leftTimes: {},
  99. business: false,
  100. caseid: '',
  101. websockets: {},
  102. interval: () => { }
  103. }
  104. },
  105. computed: {
  106. ...mapOrderState({
  107. list: x => (x.ordersList || {}).list || [],
  108. businessStatus: x => x.businessStatus
  109. }),
  110. ...mapState({
  111. cases: x => x.app.cases.list,
  112. defaultCaseId: x => x.app.cases.default,
  113. userInfo: x => x.app.user
  114. }),
  115. CaseId: {
  116. get () {
  117. return this.caseid || this.defaultCaseId
  118. },
  119. set (val) {
  120. this.caseid = val
  121. }
  122. }
  123. },
  124. created () {
  125. this.updateSystemInfo().then(() => {
  126. if (this.caseid) {
  127. console.log(this.caseid)
  128. this.init()
  129. }
  130. })
  131. },
  132. mounted () {
  133. setTimeout(window.location.reload, 600 * 1000)
  134. },
  135. beforeRouteLeave (to, from, next) {
  136. // 导航离开该组件的对应路由时调用
  137. // 可以访问组件实例 `this`
  138. console.log(this.websockets)
  139. Object.keys(this.websockets).forEach((key) => {
  140. console.log(key, this.websockets[key])
  141. this.websockets[key].onclose()
  142. })
  143. next()
  144. },
  145. methods: {
  146. init () {
  147. Object.keys(this.websockets).forEach((key) => {
  148. console.log(key, this.websockets[key])
  149. this.websockets[key].onclose()
  150. })
  151. console.log('init')
  152. var param = []
  153. if (!this.caseid) {
  154. this.$message({
  155. type: 'info',
  156. message: '请先选择案场'
  157. })
  158. return
  159. }
  160. clearInterval(this.interval)
  161. this.GetOrdersList({ caseid: this.caseid }).then((res) => {
  162. for (var n = 0; n < (res.list || []).length; n++) {
  163. if (res.list[n].IsIntimidate === 0) {
  164. param.push(res.list[n].OrdersId)
  165. }
  166. }
  167. var bool = true
  168. var timer = setInterval(() => {
  169. if (param.length && bool) {
  170. bool = false
  171. this.printPdf(`item_${param[0]}`)
  172. this.putPrintGoodsOrder({
  173. id: param[0]
  174. }).then(() => {
  175. param.splice(0, 1)
  176. bool = true
  177. })
  178. } else {
  179. clearInterval(timer)
  180. }
  181. }, 300)
  182. this.getBusinessStatus(this.caseid).then(() => {
  183. if (this.businessStatus) {
  184. this.initWebSocket()
  185. }
  186. })
  187. })
  188. this.refreshList()
  189. },
  190. refreshList () {
  191. this.interval = setInterval(() => {
  192. const now = (new Date()).valueOf()
  193. this.leftTimes = this.list.reduce((acc, it) => {
  194. const showDT = now - ((new Date(it.CreateDate)).valueOf())
  195. return { ...acc, [`${it.OrdersId}`]: formatTimeBySeconds(showDT) }
  196. }, {})
  197. }, 1000)
  198. },
  199. timeOut (c) {
  200. let cTime = new Date(c).valueOf()
  201. let time = new Date().valueOf()
  202. let s = parseInt((time - cTime) / 1000)
  203. let m = parseInt(s / 60)
  204. s = s - m * 60
  205. m = m < 10 ? '0' + m : m
  206. s = s < 10 ? '0' + s : s
  207. return `${m} : ${s}`
  208. },
  209. ...mapOrderActions([
  210. 'GetOrdersList',
  211. 'openBusiness',
  212. 'closeBusiness',
  213. 'checkOrder',
  214. 'cancelOrder',
  215. 'getBusinessStatus',
  216. 'updateList',
  217. 'putPrintGoodsOrder',
  218. ]),
  219. ...mapActions([
  220. 'updateSystemInfo'
  221. ]),
  222. submit (id, index) {
  223. this.$confirm('确定完成此饮品?', '提示', {
  224. confirmButtonText: '确定',
  225. cancelButtonText: '取消',
  226. type: 'warning'
  227. }).then((res) => {
  228. this.checkOrder({ id: id }).then(() => {
  229. this.$message({
  230. type: 'success',
  231. message: '确认订单成功'
  232. })
  233. this.list.splice(index, 1)
  234. this.updateList({ list: this.list })
  235. })
  236. }).catch((res) => {
  237. this.$message({
  238. type: 'info',
  239. message: '已取消操作'
  240. })
  241. })
  242. },
  243. cancel (id, index) {
  244. this.$confirm('确定取消此饮品?', '提示', {
  245. confirmButtonText: '确定',
  246. cancelButtonText: '取消',
  247. type: 'warning'
  248. }).then((res) => {
  249. this.cancelOrder({ id: id }).then(() => {
  250. this.$message({
  251. type: 'success',
  252. message: '取消订单成功'
  253. })
  254. this.list.splice(index, 1)
  255. this.updateList({ list: this.list })
  256. })
  257. }).catch((res) => {
  258. this.$message({
  259. type: 'info',
  260. message: '已取消操作'
  261. })
  262. })
  263. },
  264. printPdf (cl) {
  265. this.CreateOneFormPage(cl)
  266. LODOP.PRINT()
  267. },
  268. CreateOneFormPage (cl) {
  269. LODOP = getLodop()
  270. LODOP.PRINT_INIT('订单')
  271. LODOP.SET_PRINT_PAGESIZE(3, 480, 40, '')
  272. LODOP.ADD_PRINT_HTM(0, 0, document.getElementsByClassName(cl)[0].offsetWidth, document.getElementsByClassName(cl)[0].offsetHeight, document.getElementsByClassName(cl)[0].innerHTML)
  273. },
  274. initWebSocket () {
  275. console.log('initWebSocket')
  276. // console.log(this.user)
  277. let caseid = this.caseid
  278. let id = this.userInfo.UserId
  279. const wsPath = this.$api.system.notify.newGoodsOrders.url
  280. const wsRealPath = replaceURLParams(wsPath, { grps: caseid, id })
  281. this.newWebsocket(wsRealPath)
  282. },
  283. websocketonmessage (e) {
  284. // let oldList = this.list
  285. let newList = JSON.parse(e.data).data.refreshOnlineGoodsOrders
  286. // let newinfo = newList.filter(x => this.list.filter(item => item.OrdersId === x.OrdersId).length === 0)
  287. this.updateList({ list: this.list.concat(newList) }).then(() => {
  288. newList.forEach((it) => {
  289. // console.log('it:', it)
  290. this.printPdf(`item_${it.OrdersId}`)
  291. this.putPrintGoodsOrder({
  292. id: it.OrdersId
  293. })
  294. })
  295. })
  296. },
  297. newWebsocket (wsRealPath) {
  298. const ws = this.websockets[wsRealPath]
  299. if (!ws) {
  300. const url = `${window.location.origin.replace('http', 'ws')}${wsRealPath}?token=${localStorage.getItem('JWT')}`
  301. this.websockets[wsRealPath] = new WebSocket(url)
  302. this.websockets[wsRealPath].onopen = console.log
  303. this.websockets[wsRealPath].onmessage = this.websocketonmessage
  304. this.websockets[wsRealPath].onclose = console.log
  305. setInterval(() => this.websockets[wsRealPath].send(10), 120000)
  306. }
  307. },
  308. open () {
  309. if (!this.caseid) {
  310. this.$message({
  311. type: 'info',
  312. message: '请先选择案场'
  313. })
  314. return
  315. }
  316. this.openBusiness(this.caseid).then(() => {
  317. this.init()
  318. })
  319. },
  320. close () {
  321. if (!this.caseid) {
  322. this.$message({
  323. type: 'info',
  324. message: '请先选择案场'
  325. })
  326. return
  327. }
  328. this.closeBusiness(this.caseid)
  329. }
  330. }
  331. }
  332. </script>
  333. <!-- Add "scoped" attribute to limit CSS to this component only -->
  334. <style lang="scss" scoped>
  335. @import "page.scss";
  336. </style>