index.vue 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448
  1. <template>
  2. <div class="gesture">
  3. <Header :showTool="true" @confirmExit="getLogout" :key="key"></Header>
  4. <div class="menu" v-if="projectList.length" :key="projectList.length">
  5. <swiper :slides-per-view="5" :space-between="0" :loop="true" :observe-parents="true" :observer="true"
  6. :centered-slides="true" :modules="[Navigation]"
  7. @swiper="onSwiper">
  8. <swiper-slide v-for="(item, index) in projectList" :key="index" @click="getOption(item)">
  9. <div class="li">
  10. <div>
  11. <div class="pic"><img :src="'static/images/train/' + item.key + '.png'"></div>
  12. <div class="name">
  13. {{ item.name }}
  14. </div>
  15. </div>
  16. </div>
  17. </swiper-slide>
  18. </swiper>
  19. </div>
  20. <div class="erweima"> <img :src="erweima" />
  21. <span>扫码遥控</span>
  22. </div>
  23. <OptionWindow ref="optionWindowRef" :projectList="projectList" />
  24. </div>
  25. </template>
  26. <script setup name="Gesture" lang="ts">
  27. import { useWebSocket } from '@/utils/handWs';
  28. import { Swiper, SwiperSlide } from 'swiper/vue';
  29. import { Navigation } from 'swiper/modules';
  30. import QRCode from "qrcode";
  31. import 'swiper/css';
  32. import 'swiper/scss/navigation';
  33. const { handWs, startDevice, startHand, stateHand } = useWebSocket();
  34. const router = useRouter();
  35. const route = useRoute();
  36. const { proxy } = getCurrentInstance() as any;
  37. const optionWindowRef = ref();
  38. const data = reactive<any>({
  39. mySwiper: {},
  40. projectList: [],
  41. timerManager: {},
  42. device_info: {},
  43. erweima: '',
  44. sid: '',
  45. key: 0,
  46. });
  47. const { mySwiper, projectList, timerManager, device_info, erweima, sid, key } = toRefs(data);
  48. /**
  49. * 清空定时任务
  50. */
  51. const getClearTimer = (data?: any) => {
  52. if (data) {
  53. //清除指定
  54. clearInterval(timerManager.value[data])
  55. timerManager.value[data] = null;
  56. } else {
  57. for (let key in timerManager.value) {
  58. if (timerManager.value.hasOwnProperty(key)) {
  59. clearInterval(timerManager.value[key])
  60. timerManager.value[key] = null;
  61. }
  62. }
  63. }
  64. };
  65. /**
  66. * 初始化项目
  67. */
  68. const getInitExam = () => {
  69. getExam();
  70. //定时刷新
  71. timerManager.value.exam = setInterval(() => {
  72. getExam();
  73. }, 5000)
  74. };
  75. /**
  76. * 获取项目
  77. */
  78. const getExam = async () => {
  79. let myList = device_info.value?.project_list || [];
  80. let examList = myList.map((item: any) => {
  81. return item.exam_name;
  82. })
  83. await proxy?.$http.train.projectList().then((res: any) => {
  84. projectList.value = proxy?.$utils.getProject(res.exams).filter((item: any) => {
  85. //只显示能开的
  86. return item.area.length > 0 && examList.includes(item.key);
  87. //return item.area.length > 0;
  88. });
  89. // console.log("projectList.value", projectList.value)
  90. });
  91. };
  92. /**
  93. * 获取实例
  94. */
  95. const onSwiper = ($ev: any) => {
  96. console.log("1111111", $ev)
  97. mySwiper.value = $ev;
  98. slidePrev()
  99. };
  100. /**
  101. * 切换上一页
  102. */
  103. const slidePrev = () => {
  104. mySwiper.value.slidePrev();
  105. };
  106. /**
  107. * 切换下一页
  108. */
  109. const slideNext = () => {
  110. mySwiper.value.slideNext();
  111. };
  112. /**
  113. * 启动切换
  114. */
  115. const slideChange = () => {
  116. // if (projectList.value.length <= 3) {
  117. // slidePrev()
  118. // } else {
  119. // slideNext();
  120. // }
  121. slidePrev()
  122. };
  123. /**
  124. * 进入项目
  125. */
  126. const getOption = (data: any) => {
  127. confirm(data);
  128. };
  129. /**
  130. * 确定并进入
  131. */
  132. const confirm = (myProject?: any) => {
  133. let project = myProject || projectList.value[mySwiper.value.realIndex];
  134. console.log("projectList.value", projectList.value)
  135. console.log("mySwiper.value", mySwiper.value)
  136. console.log("mySwiper.value.realIndex", mySwiper.value.realIndex)
  137. console.log("project", project)
  138. if (project == undefined) {
  139. proxy?.$modal.msgError("获取不到项目信息");
  140. return false;
  141. }
  142. let obj = device_info.value.project_list.find((item: any) => {
  143. return item.exam_name == project.key;
  144. })
  145. if (obj == undefined) {
  146. proxy?.$modal.msgError("该项目没有配置参数");
  147. return false;
  148. }
  149. let data = {
  150. gesture: obj.gesture ? true : false,
  151. demo: obj?.demo || 0,
  152. area: obj?.area_test_id || '',
  153. ctrl: obj?.area_ctrl_id || '',
  154. time: obj?.test_time || '',
  155. music: obj?.music_info?.url || '',
  156. handcontroller: device_info.value.handcontroller_id,
  157. }
  158. optionWindowRef.value.getGesture(project, data);
  159. };
  160. /**
  161. * 退出
  162. */
  163. const getLogout = async () => {
  164. if (import.meta.env.DEV) {
  165. proxy?.$modal.msgSuccess('测试环境免密退出');
  166. await proxy?.$http.common.logout({}).then((res: any) => {
  167. });
  168. proxy?.$modal?.closeLoading()
  169. //清空缓存
  170. localStorage.clear();
  171. //跳转
  172. router.push({ path: '/login/qrcode' });
  173. } else {
  174. let myInfo: any = localStorage.getItem("userInfo");
  175. let userInfo = JSON.parse(myInfo);
  176. proxy?.$modal.prompt(`【${userInfo.login_name}】,请输入密码`, 'password').then((e: any) => {
  177. // console.log("e", e)
  178. if (e.action == 'confirm' && e.value) {
  179. let params = {
  180. password: e.value
  181. };
  182. proxy?.$http.common.checkPassword(params).then(async (res: any) => {
  183. if (res.status === 200 || res.status === 1) {
  184. await proxy?.$http.common.logout({}).then((res: any) => {
  185. });
  186. proxy?.$modal?.closeLoading()
  187. //清空缓存
  188. localStorage.clear();
  189. //跳转
  190. router.push({ path: '/login/qrcode' });
  191. } else {
  192. proxy?.$modal.msgError(res.message);
  193. }
  194. });
  195. }
  196. }).finally(() => {
  197. });
  198. }
  199. };
  200. /**
  201. * 提示语
  202. */
  203. const getTips = () => {
  204. let myTime = 7000;
  205. let num = 0;
  206. timerManager.value.tips = setInterval(() => {
  207. if (projectList.value.length) {
  208. if (num % 2 == 0) {
  209. proxy?.$modal.msgWarning({
  210. message: `手向左滑切换项目`,
  211. duration: 5000
  212. })
  213. } else {
  214. proxy?.$modal.msgWarning({
  215. message: `举左手进入测试`,
  216. duration: 5000
  217. })
  218. }
  219. num++
  220. }
  221. }, myTime)
  222. };
  223. /**
  224. * 获取个人信息
  225. */
  226. const getUserInfo = () => {
  227. let params = {};
  228. proxy?.$http.common.getUserInfo(params).then((res: any) => {
  229. //保存信息
  230. if (res.data.length) {
  231. let myData = res.data[0];
  232. let info = JSON.stringify(myData);
  233. localStorage.setItem("userInfo", info);
  234. //修改收藏夹图标
  235. proxy?.$utils.setFavicon(myData?.logo_url);
  236. key.value = key.value + 1//更新头部LOGO
  237. }
  238. });
  239. };
  240. /**
  241. * 获取设备项目
  242. */
  243. const getDevice = async () => {
  244. let deviceid = localStorage.getItem("deviceid") || '';
  245. if (deviceid) {
  246. startDevice({ deviceid: deviceid })
  247. } else {
  248. proxy?.$modal.msgError(`缺少设备信息请重新登录!`);
  249. await proxy?.$http.common.logout({}).then((res: any) => {
  250. });
  251. proxy?.$modal?.closeLoading()
  252. //清空缓存
  253. localStorage.clear();
  254. //跳转
  255. router.push({ path: '/login/qrcode' });
  256. }
  257. };
  258. /**
  259. * 获取二维码
  260. */
  261. const getErweima = () => {
  262. let deviceid = localStorage.getItem("deviceid") || '';
  263. QRCode.toDataURL(
  264. `${location.origin}/#/login/mobile?sid=${sid}&deviceid=${deviceid}`
  265. )
  266. .then((res: any) => {
  267. erweima.value = res;
  268. })
  269. }
  270. onBeforeMount(() => {
  271. //加载设备WS
  272. handWs((e: any) => {
  273. if(router.currentRoute.value.path != '/gesture'){
  274. return false;
  275. }
  276. // console.log("eeeee", e)
  277. if (e?.wksid) {
  278. //获取设备项目
  279. getDevice()
  280. }
  281. //接收设备信息
  282. if (e?.device_info) {
  283. device_info.value = e.device_info;
  284. let handcontroller_id = device_info.value.handcontroller_id;
  285. stateHand(handcontroller_id);
  286. getInitExam();
  287. }
  288. //获取手势状态
  289. if (e?.cmd == 'get_handcontroller_state' && e?.state == 0) {
  290. let handcontroller_id = device_info.value.handcontroller_id;
  291. startHand(handcontroller_id);
  292. }
  293. //左滑动
  294. if (e?.data?.result == "next_item") {
  295. proxy?.$modal.msgSuccess('手势指令:左滑动');
  296. if (projectList.value.length == 0) {
  297. return false;
  298. }
  299. slideChange();
  300. }
  301. //举左手
  302. if (e?.data?.result == "left_hand") {
  303. proxy?.$modal.msgSuccess('手势指令:举左手');
  304. confirm();
  305. }
  306. //退出
  307. if (e?.data?.result == "exit") {
  308. proxy?.$modal.msgSuccess('手势指令:交叉手');
  309. }
  310. //刷新
  311. if (e?.data?.result == "refresh") {
  312. window.location.reload()
  313. }
  314. });
  315. })
  316. onMounted(() => {
  317. getUserInfo();
  318. //登录码
  319. getErweima();
  320. //提示语
  321. // getTips();
  322. })
  323. onBeforeUnmount(() => {
  324. getClearTimer();
  325. ElMessage.closeAll();
  326. })
  327. </script>
  328. <style lang="scss" scoped>
  329. $topPadding: 5.19rem;
  330. $waiPadding: 6.51rem;
  331. .menu {
  332. width: calc(100% - ($waiPadding * 2));
  333. height: 100vh;
  334. margin: 0 auto;
  335. display: flex;
  336. align-items: center;
  337. .li {
  338. // width: calc((100% / 6) - 1rem + (1rem/6));
  339. // margin-right: 1rem;
  340. // margin-bottom: 1rem;
  341. width: 100%;
  342. height: 100%;
  343. padding: 3vh 0;
  344. border-radius: 1.6rem;
  345. box-sizing: border-box;
  346. box-shadow: inset 0px 1px 0px 2px rgba(255, 255, 255, 0.9046), inset 0px 3px 6px 0px rgba(0, 0, 0, 0.0851);
  347. display: flex;
  348. justify-content: center;
  349. align-items: center;
  350. background: radial-gradient(96% 96% at 2% 32%, #FFFFFF 0%, #FCFDFD 54%, #E1E4E7 100%);
  351. cursor: pointer;
  352. .name {
  353. width: 100%;
  354. font-size: 2.48rem;
  355. color: #1A293A;
  356. padding: 0.5rem 0;
  357. text-align: center;
  358. }
  359. .pic {
  360. width: 11.36vw;
  361. height: 11.36vw;
  362. border-radius: 50%;
  363. background: radial-gradient(78% 78% at 53% 50%, #07121A 0%, #2A4256 49%, #5180A9 100%);
  364. box-shadow: 0px 0px 2px 2px #FFFFFF;
  365. margin-bottom: 2vh;
  366. overflow: hidden;
  367. display: flex;
  368. align-items: center;
  369. justify-content: center;
  370. flex-shrink: 0;
  371. img {
  372. max-width: 88%;
  373. max-height: 88%;
  374. transition: all 1s;
  375. }
  376. }
  377. &:hover {
  378. img {
  379. transform: translateY(-0.5vw);
  380. }
  381. }
  382. }
  383. .swiper {
  384. width: 100%;
  385. }
  386. .swiper-slide {
  387. transform: scale(0.8);
  388. transition: all 0.3s ease-in-out;
  389. border-radius: 1.6rem;
  390. opacity: 0.6;
  391. overflow: hidden;
  392. }
  393. .swiper-slide-active {
  394. opacity: 1;
  395. transform: scale(1);
  396. .li {
  397. background: radial-gradient(167% 126% at 97% 6%, #35FFC6 0%, #00FFE8 100%);
  398. }
  399. }
  400. }
  401. .erweima {
  402. position: absolute;
  403. right: 3rem;
  404. bottom: 3rem;
  405. text-align: center;
  406. img {
  407. width: 6.625rem;
  408. }
  409. span {
  410. display: block;
  411. color: #FFFFFF;
  412. font-size: 1rem;
  413. padding-top: 3px;
  414. }
  415. }
  416. </style>