App.vue 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259
  1. <template>
  2. <div v-if="pageState === State.Load" class="full-screen flex">
  3. <AppLoading :size="80"/>
  4. <p>加载中...</p>
  5. </div>
  6. <WineControlPage v-else-if="pageState === State.Show" class="full-screen" ref="ListPage" @to_adv="play_adv"/>
  7. <AdvertisePage v-else-if="pageState === State.Play" class="full-screen" :ads="ads" @to_wine="show_wine"/>
  8. <WineChangePage v-else-if="pageState === State.Change" class="full-screen" :who="who" @to_wine="show_wine"/>
  9. <DeviceFixPage v-else-if="pageState === State.Fix" class="full-screen" :who="who" @to_wine="show_wine"/>
  10. <div v-else class="full-screen flex">illegal operation</div>
  11. <div class="fixed-info" @click="_onSetDebug(true)">{{ info.seq }} [{{ info.ver }}]</div>
  12. <AlertPopup class="full-screen" v-if="alert.show" ref="alert" @mounted="AlertReady" @close="HideAlert"/>
  13. <div class="debug" v-if="debug.show">
  14. <div class="debug-clear" @click="debug.texts = [];">清 空</div>
  15. <pre class="debug-text">{{ debug.texts.join('\n') }}</pre>
  16. </div>
  17. </template>
  18. <script>
  19. import AdvertisePage from "@/pages/AdvertisePage";
  20. import WineControlPage from "@/pages/WineControlPage";
  21. import AppLoading from "@/components/AppLoading";
  22. import WineChangePage from "@/pages/WineChangePage";
  23. import DeviceFixPage from "@/pages/DeviceFixPage";
  24. import AlertPopup from "@/components/AlertPopup";
  25. const GapTime = 200;
  26. export default {
  27. directives: {
  28. click: {
  29. mounted(el, binding) {
  30. let timer = null, count = 0, timeout = 150;
  31. const clearTimer = () => {
  32. clearTimeout(timer);
  33. timer = null;
  34. }
  35. const handler = function () {
  36. if (timer === null) {
  37. count = 0;
  38. timer = setTimeout(clearTimer, 1000);
  39. }
  40. count++;
  41. if (count === 5) {
  42. setTimeout(() => {
  43. if (count === 5) {
  44. count = 0;
  45. binding.value.t5();
  46. }
  47. }, timeout);
  48. } else if (count === 7) {
  49. setTimeout(() => {
  50. if (count === 7) {
  51. count = 0;
  52. binding.value.t7();
  53. }
  54. }, timeout);
  55. }
  56. }
  57. el.__my_click = handler;
  58. el.addEventListener("click", handler);
  59. },
  60. unmounted(el) {
  61. el.removeEventListener("click", el.__my_click);
  62. delete el.__my_click;
  63. }
  64. }
  65. },
  66. components: {
  67. AlertPopup,
  68. DeviceFixPage,
  69. WineChangePage,
  70. AppLoading,
  71. AdvertisePage,
  72. WineControlPage
  73. },
  74. name: "App",
  75. data() {
  76. let state = {Load: "Loading", Show: "Showing", Play: "Playing", Change: "Changing", Fix: "Fixing"};
  77. return {
  78. info: {seq: "NULL-Device-Seq", ver: "V0.0"},
  79. alert: {
  80. show: false, time: -1, title: "", color: "", subtitle: "", icon: "",
  81. button: {need: false, text: "", callback: null, countdown: -1}
  82. },
  83. debug: {show: false, texts: []},
  84. State: state,
  85. pageState: state.Load,
  86. who: "",
  87. ads: [],
  88. wines: []
  89. }
  90. },
  91. methods: {
  92. _start(device, version) {
  93. this.info.seq = device;
  94. this.info.ver = version;
  95. this.$utils.EventBus["ShowAlert"] = this.ShowAlert;
  96. this.$utils.EventBus["ShowError"] = this.ShowError;
  97. this.$utils.EventBus["HideAlert"] = this.HideAlert;
  98. this.$utils.EventBus["debug"] = this.addDebug;
  99. this.$utils.ConnectSocket(device);
  100. this.$utils.SockEventMap["__Error_Event__"] = this.ShowError;
  101. this.$utils.SockEventMap["setDebug"] = this._onSetDebug;
  102. this.$utils.SockEventMap["ppvUpdate"] = this._onPpvUpdate;
  103. this.$utils.SockEventMap["wineResult"] = this._onWineResult;
  104. this.$utils.SockEventMap["advResult"] = this._onAdvResult;
  105. this.$utils.SockEventMap["runParamResult"] = this._onRunParamResult;
  106. this.$utils.SockEventMap["initFinish"] = this._onInitFinish;
  107. this.$utils.SockEventMap["openGate"] = this._onOpenGateCommand;
  108. },
  109. _onSetDebug(debug) {
  110. this.$utils.DebugMode = this.debug.show = debug;
  111. this.$utils.Android(debug ? "show" : "hide");
  112. this.addDebug(`set debug: ${debug}`);
  113. },
  114. _onPpvUpdate(data) {
  115. this.addDebug(`update ppv${data.index + 1} => ${data.value}`);
  116. this.$utils.Wines[data.index].ppv = data.value;
  117. },
  118. _onWineResult(wines) {
  119. for (let i = 0; i < wines.length; ++i) {
  120. wines[i].cell = i;
  121. wines[i].density = wines[i].density / 1000;
  122. wines[i].price_in_yuan = wines[i].price / 100; // 分 -> 元
  123. wines[i].remain_in_weight = this.$utils.Volume2Weight(wines[i].remain, wines[i].density); // ml -> 两
  124. }
  125. this.$utils.Wines = wines;
  126. },
  127. _onAdvResult(ads) {
  128. this.ads = ads;
  129. },
  130. _onRunParamResult(params) {
  131. params.forEach(e => this.$utils.ParamMap[e.key] = e.value);
  132. },
  133. _onInitFinish() {
  134. this.pageState = this.State.Show;
  135. },
  136. _onOpenGateCommand(data) {
  137. this.addDebug(`open gate: ${JSON.stringify(data)}`);
  138. if (this.pageState === data.kind) return;
  139. this.HideAlert(true);
  140. if (this.pageState !== this.State.Show) this.pageState = this.State.Show;
  141. setTimeout(() => {
  142. this.$refs.ListPage.Over();
  143. this.who = data.who;
  144. this.pageState = data.kind;
  145. }, GapTime);
  146. },
  147. show_wine() {
  148. this.pageState = this.State.Show;
  149. this.$utils.Android("setVolume", this.$utils.ParamMap.VolumeNormal);
  150. },
  151. play_adv() {
  152. this.pageState = this.State.Play;
  153. this.$utils.Android("setVolume", this.$utils.ParamMap.VolumeAdv);
  154. },
  155. addDebug(msg) {
  156. this.debug.texts.unshift(msg);
  157. },
  158. AlertReady() {
  159. this.$refs.alert.Update(this.alert.options);
  160. },
  161. ShowError(msg) {
  162. this.alert.show = false;
  163. this.alert = {
  164. show: true, callback: null, options: {
  165. time: 2, title: "发 生 错 误", color: "red",
  166. subtitle: msg, icon: `${process.env.BASE_URL}icon/error.svg`,
  167. button: {need: false, text: "", countdown: -1}
  168. }
  169. };
  170. },
  171. ShowAlert(options) {
  172. this.alert.show = false;
  173. setTimeout(() => this.alert = {options: options, callback: options.callback, show: true}, GapTime);
  174. },
  175. HideAlert(restrain = false) {
  176. this.alert.show = false;
  177. !restrain && this.alert.callback && this.alert.callback();
  178. }
  179. },
  180. mounted() {
  181. if (window.android === undefined) this.$utils.VmAndroid();
  182. this.$utils.Register("__Error_Happened__", this.ShowError);
  183. this.$utils.Register("pon", () => {
  184. });
  185. this.$utils.Register("startApp", this._start);
  186. this.$utils.Android("onWebMounted");
  187. setInterval(() => this.$utils.Android("pin"), 10 * 60 * 1000);
  188. }
  189. }
  190. </script>
  191. <style scoped>
  192. .fixed-info {
  193. position: fixed;
  194. top: 10px;
  195. right: 10px;
  196. color: lightgray;
  197. cursor: pointer;
  198. z-index: 100100;
  199. }
  200. .full-screen {
  201. width: 100%;
  202. height: 100%;
  203. }
  204. .flex {
  205. display: flex;
  206. flex-direction: column;
  207. justify-content: center;
  208. align-items: center;
  209. }
  210. .debug {
  211. width: 40%;
  212. height: 50%;
  213. position: fixed;
  214. left: 5px;
  215. bottom: 5px;
  216. z-index: 20020;
  217. box-sizing: border-box;
  218. background-color: ghostwhite;
  219. border-radius: 2px;
  220. border: 1px solid lightgray;
  221. padding: 2px 4px;
  222. display: flex;
  223. flex-direction: column;
  224. justify-content: space-between;
  225. }
  226. .debug-clear {
  227. width: 100%;
  228. border-bottom: 1px solid black;
  229. cursor: pointer;
  230. line-height: 24px;
  231. text-align: center;
  232. font-weight: bold;
  233. }
  234. .debug-clear:active {
  235. font-weight: normal;
  236. }
  237. .debug-text {
  238. width: 100%;
  239. height: calc(100% - 22px);
  240. overflow-y: scroll;
  241. }
  242. .debug-text::-webkit-scrollbar {
  243. display: none;
  244. }
  245. </style>