index.tsx 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795
  1. import {
  2. Transition,
  3. defineComponent,
  4. onMounted,
  5. ref,
  6. reactive,
  7. onUnmounted,
  8. watch
  9. } from 'vue';
  10. import LayoutSilder from './layoutSilder';
  11. import LayoutTop from './layoutTop';
  12. import styles from './index.module.less';
  13. import { NButton, NImage, NModal, NPopover, NSpace, useDialog } from 'naive-ui';
  14. import Moveable from 'moveable';
  15. import toolStartClass from './images/toolStartClass.png';
  16. import toolbox from './images/toolbox.png';
  17. import setTimeIcon from './images/setTimeIcon.png';
  18. import beatIcon from './images/beatIcon.png';
  19. import toneIcon from './images/toneIcon.png';
  20. import iconWhiteBorad from './images/icon-whiteborad.png';
  21. import iconPen from './images/icon-pen.png';
  22. import iconNote from './images/icon-note.png';
  23. import beatImage from './images/beatImage.png';
  24. import toneImage from './images/toneImage.png';
  25. import setTimeImage from './images/setTimeImage.png';
  26. import dragingBoxIcon from './images/dragingBoxIcon.png';
  27. import TimerMeter from '../timerMeter';
  28. import { useRoute, useRouter } from 'vue-router';
  29. import { vaildUrl } from '/src/utils/urlUtils';
  30. import ChioseModal from '/src/views/home/modals/chioseModal';
  31. import { eventGlobal, px2vw, px2vwH } from '@/utils/index';
  32. import PlaceholderTone from './modals/placeholderTone';
  33. import { state } from '/src/state';
  34. import PreviewWindow from '/src/views/preview-window';
  35. import { fscreen } from '@/utils/index';
  36. import AttendClass from '/src/views/prepare-lessons/model/attend-class';
  37. import Pen from '/src/views/attend-class/component/tools/pen';
  38. import study from '/src/views/home/components/study';
  39. export default defineComponent({
  40. name: 'layoutView',
  41. setup() {
  42. const router = useRouter();
  43. const previewModal = ref(false);
  44. const previewItem = ref({});
  45. const directionType = ref('left');
  46. const showClass = ref(false);
  47. const showModalBeat = ref(false);
  48. const showModalTone = ref(false);
  49. const showModalTime = ref(false);
  50. const showBoxConent = ref(false);
  51. const dialog = useDialog();
  52. const boxBoundaryInfo = reactive({
  53. isBoundary: false,
  54. isBoundaryType: '' as any,
  55. mainWidth: '' as any,
  56. mainHeight: '' as any,
  57. subWidth: '' as any,
  58. subHeight: '' as any
  59. });
  60. const classBoundaryInfo = reactive({
  61. isBoundary: true,
  62. isBoundaryType: 'right' as any,
  63. mainWidth: '' as any,
  64. mainHeight: '' as any,
  65. subWidth: '' as any,
  66. subHeight: '' as any
  67. });
  68. const route = useRoute();
  69. const isDragIng = ref(false);
  70. const NPopoverRef = ref();
  71. const initMoveable = async () => {
  72. if (document.querySelector('.wrap')) {
  73. const moveable = new Moveable(document.querySelector('.wrap') as any, {
  74. target: document.querySelector('#moveNPopover') as any,
  75. // If the container is null, the position is fixed. (default: parentElement(document.body))
  76. container: document.querySelector('.wrap') as any,
  77. // snappable: true,
  78. // bounds: {"left":100,"top":100,"right":100,"bottom":100},
  79. draggable: true,
  80. resizable: false,
  81. scalable: false,
  82. rotatable: false,
  83. warpable: false,
  84. pinchable: false, // ["resizable", "scalable", "rotatable"]
  85. origin: false,
  86. keepRatio: false,
  87. // Resize, Scale Events at edges.
  88. edge: false,
  89. throttleDrag: 0,
  90. throttleResize: 0,
  91. throttleScale: 0,
  92. throttleRotate: 0
  93. });
  94. moveable
  95. // .on('dragStart', ({ target, clientX, clientY }) => {
  96. // console.log('dragStart');
  97. // })
  98. .on(
  99. 'drag',
  100. ({
  101. target,
  102. // transform,
  103. left,
  104. top,
  105. right,
  106. bottom
  107. // beforeDelta,
  108. // beforeDist,
  109. // delta,
  110. // dist,
  111. // clientX,
  112. // clientY
  113. }) => {
  114. isDragIng.value = true;
  115. if (NPopoverRef.value) {
  116. NPopoverRef.value.setShow(false);
  117. }
  118. const subdEl = document.getElementById(
  119. `moveNPopover`
  120. ) as HTMLDivElement;
  121. // console.log(subdEl, "subdEl", "drag");
  122. const subdElStyle = getComputedStyle(subdEl, null);
  123. const RectInfo = {
  124. left: Number(subdElStyle.left.replace('px', '')),
  125. top: Number(subdElStyle.top.replace('px', '')),
  126. width: Number(subdElStyle.width.replace('px', '')),
  127. height: Number(subdElStyle.height.replace('px', ''))
  128. };
  129. // target.style.transition = ''
  130. const mainWidth =
  131. parseInt(
  132. window.getComputedStyle(
  133. document.querySelector('.wrap') as Element
  134. ).width
  135. ) - RectInfo.width;
  136. const mainHeight =
  137. parseInt(
  138. window.getComputedStyle(
  139. document.querySelector('.wrap') as Element
  140. ).height
  141. ) - RectInfo.height;
  142. subdEl.style.transition = '';
  143. boxBoundaryInfo.isBoundary = false;
  144. boxBoundaryInfo.isBoundaryType = '';
  145. boxBoundaryInfo.mainHeight = mainHeight;
  146. boxBoundaryInfo.mainWidth = mainWidth;
  147. boxBoundaryInfo.subWidth = RectInfo.width;
  148. boxBoundaryInfo.subHeight = RectInfo.height;
  149. if (left < 0) {
  150. left = 2;
  151. boxBoundaryInfo.isBoundary = true;
  152. boxBoundaryInfo.isBoundaryType = 'left';
  153. }
  154. if (top < 0) {
  155. top = 2;
  156. boxBoundaryInfo.isBoundary = true;
  157. boxBoundaryInfo.isBoundaryType = 'top';
  158. }
  159. if (right < 0) {
  160. right = 2;
  161. }
  162. if (bottom < 0) {
  163. bottom = 2;
  164. }
  165. if (left > mainWidth - 2) {
  166. left = mainWidth - 2;
  167. // top = 2;
  168. boxBoundaryInfo.isBoundary = true;
  169. boxBoundaryInfo.isBoundaryType = 'right';
  170. }
  171. if (top > mainHeight - 2) {
  172. top = mainHeight - 2;
  173. boxBoundaryInfo.isBoundary = true;
  174. boxBoundaryInfo.isBoundaryType = 'bottom';
  175. }
  176. target!.style.left = `${left}px`;
  177. target!.style.top = `${top}px`;
  178. }
  179. )
  180. .on(
  181. 'dragEnd',
  182. async ({
  183. target,
  184. // isDrag,
  185. clientX
  186. // clientY
  187. }) => {
  188. if (document.body.clientWidth / 2 - clientX > 0) {
  189. // 往左出
  190. directionType.value = 'right';
  191. } else {
  192. // 往又出
  193. directionType.value = 'left';
  194. }
  195. isDragIng.value = false;
  196. // 在这里进行动画
  197. if (boxBoundaryInfo.isBoundary) {
  198. // 这里说明贴边了
  199. target.style.transition = '.3s';
  200. actionEnd(target, boxBoundaryInfo.isBoundaryType);
  201. }
  202. }
  203. );
  204. }
  205. };
  206. const initMoveableClass = async () => {
  207. if (document.querySelector('.wrap')) {
  208. const moveable = new Moveable(document.querySelector('.wrap') as any, {
  209. target: document.querySelector('#moveNPopover2') as any,
  210. // If the container is null, the position is fixed. (default: parentElement(document.body))
  211. container: document.querySelector('.wrap') as any,
  212. // snappable: true,
  213. // bounds: {"left":100,"top":100,"right":100,"bottom":100},
  214. draggable: true,
  215. resizable: false,
  216. scalable: false,
  217. rotatable: false,
  218. warpable: false,
  219. pinchable: false, // ["resizable", "scalable", "rotatable"]
  220. origin: false,
  221. keepRatio: false,
  222. // Resize, Scale Events at edges.
  223. edge: false,
  224. throttleDrag: 0,
  225. throttleResize: 0,
  226. throttleScale: 0,
  227. throttleRotate: 0
  228. });
  229. moveable
  230. .on(
  231. 'drag',
  232. ({
  233. target,
  234. // transform,
  235. left,
  236. top,
  237. right,
  238. bottom
  239. }) => {
  240. isDragIng.value = true;
  241. const subdEl = document.getElementById(
  242. `moveNPopover2`
  243. ) as HTMLDivElement;
  244. // console.log(subdEl, "subdEl", "drag");
  245. const subdElStyle = getComputedStyle(subdEl, null);
  246. const RectInfo = {
  247. left: Number(subdElStyle.left.replace('px', '')),
  248. top: Number(subdElStyle.top.replace('px', '')),
  249. width: Number(subdElStyle.width.replace('px', '')),
  250. height: Number(subdElStyle.height.replace('px', ''))
  251. };
  252. const mainWidth =
  253. parseInt(
  254. window.getComputedStyle(
  255. document.querySelector('.wrap') as Element
  256. ).width
  257. ) - RectInfo.width;
  258. const mainHeight =
  259. parseInt(
  260. window.getComputedStyle(
  261. document.querySelector('.wrap') as Element
  262. ).height
  263. ) - RectInfo.height;
  264. subdEl.style.transition = '';
  265. classBoundaryInfo.isBoundary = false;
  266. classBoundaryInfo.isBoundaryType = '';
  267. classBoundaryInfo.mainHeight = mainHeight;
  268. classBoundaryInfo.mainWidth = mainWidth;
  269. classBoundaryInfo.subWidth = RectInfo.width;
  270. classBoundaryInfo.subHeight = RectInfo.height;
  271. if (left < 0) {
  272. left = 2;
  273. classBoundaryInfo.isBoundary = true;
  274. classBoundaryInfo.isBoundaryType = 'left';
  275. }
  276. if (top < 0) {
  277. top = 2;
  278. classBoundaryInfo.isBoundary = true;
  279. classBoundaryInfo.isBoundaryType = 'top';
  280. }
  281. if (right < 0) {
  282. right = 2;
  283. }
  284. if (bottom < 0) {
  285. bottom = 2;
  286. }
  287. if (left > mainWidth - 2) {
  288. left = mainWidth - 2;
  289. // top = 2;
  290. classBoundaryInfo.isBoundary = true;
  291. classBoundaryInfo.isBoundaryType = 'right';
  292. }
  293. if (top > mainHeight - 2) {
  294. top = mainHeight - 2;
  295. classBoundaryInfo.isBoundary = true;
  296. classBoundaryInfo.isBoundaryType = 'bottom';
  297. }
  298. target!.style.left = `${left}px`;
  299. target!.style.top = `${top}px`;
  300. }
  301. )
  302. .on(
  303. 'dragEnd',
  304. async ({
  305. target,
  306. // isDrag,
  307. clientX
  308. // clientY
  309. }) => {
  310. if (document.body.clientWidth / 2 - clientX > 0) {
  311. // 往左出
  312. directionType.value = 'right';
  313. } else {
  314. // 往又出
  315. directionType.value = 'left';
  316. }
  317. if (classBoundaryInfo.isBoundary) {
  318. // 这里说明贴边了
  319. target.style.transition = '.3s';
  320. actionEnd(target, classBoundaryInfo.isBoundaryType);
  321. }
  322. isDragIng.value = false;
  323. }
  324. )
  325. .on('click', () => {
  326. showClass.value = true;
  327. });
  328. }
  329. };
  330. watch(
  331. () => route.path,
  332. (val: any) => {
  333. const elDoc = document.getElementById('WrapcoreViewWrap') as any;
  334. if (elDoc) {
  335. elDoc.scrollTo(0, 0);
  336. window.scrollTo(0, 0);
  337. }
  338. }
  339. );
  340. onMounted(() => {
  341. initMoveable();
  342. // // initMoveableClass();
  343. const subdEl = document.getElementById(`moveNPopover`) as HTMLDivElement;
  344. // // const classEl = document.getElementById(
  345. // // `moveNPopover2`
  346. // // ) as HTMLDivElement;
  347. // // initBoxRectInfo(classEl, classBoundaryInfo);
  348. initBoundaryWrap(subdEl, boxBoundaryInfo);
  349. initBoxRectInfo(subdEl, boxBoundaryInfo);
  350. // // initBoundaryWrap(classEl, classBoundaryInfo);
  351. window.addEventListener('resize', resetSize);
  352. });
  353. const resetSize = () => {
  354. const subdEl = document.getElementById(`moveNPopover`) as HTMLDivElement;
  355. subdEl.style.display = 'none';
  356. // const boxBoundaryInfo = reactive({
  357. // isBoundary: true,
  358. // isBoundaryType: 'right' as any,
  359. // mainWidth: '' as any,
  360. // mainHeight: '' as any,
  361. // subWidth: '' as any,
  362. // subHeight: '' as any
  363. // });
  364. // boxBoundaryInfo.isBoundary = true;
  365. // boxBoundaryInfo.isBoundaryType= 'right'
  366. if (NPopoverRef.value) {
  367. NPopoverRef.value.setShow(false);
  368. }
  369. setTimeout(() => {
  370. subdEl.style.transition = '';
  371. initBoxRectInfo(subdEl, boxBoundaryInfo);
  372. initBoundaryWrap(subdEl, boxBoundaryInfo);
  373. console.log('resize');
  374. subdEl.style.display = 'block';
  375. }, 100);
  376. };
  377. onUnmounted(() => {
  378. window.removeEventListener('resize', resetSize);
  379. });
  380. const initBoundaryWrap = (target: any, wrapInfo: any) => {
  381. target.addEventListener('mouseover', () => {
  382. if (wrapInfo.isBoundary) {
  383. // 如果在边框 就得还原 元素位置 还原完毕后 去除transition
  384. if (wrapInfo.isBoundaryType == 'left') {
  385. target.style.left = '2px';
  386. } else if (wrapInfo.isBoundaryType == 'right') {
  387. target.style.left = `${wrapInfo.mainWidth - 2}px`;
  388. } else if (wrapInfo.isBoundaryType == 'top') {
  389. target.style.top = `${2}px`;
  390. } else if (wrapInfo.isBoundaryType == 'bottom') {
  391. target.style.top = `${wrapInfo.mainHeight - 2}px`;
  392. }
  393. }
  394. rate(target, 0);
  395. });
  396. target.addEventListener('mouseout', () => {
  397. if (wrapInfo.isBoundary) {
  398. // 如果在边框 就得还原 元素位置 还原完毕后 去除transition
  399. if (wrapInfo.isBoundaryType == 'left') {
  400. actionEnd(target, 'left');
  401. } else if (wrapInfo.isBoundaryType == 'right') {
  402. actionEnd(target, 'right');
  403. } else if (wrapInfo.isBoundaryType == 'top') {
  404. actionEnd(target, 'top');
  405. } else if (wrapInfo.isBoundaryType == 'bottom') {
  406. actionEnd(target, 'bottom');
  407. }
  408. }
  409. // rate(target, 0)
  410. });
  411. target.addEventListener('contextmenu', (event: any) => {
  412. event.preventDefault();
  413. dialog.warning({
  414. title: '提示',
  415. content: '是否收入托盘',
  416. positiveText: '确定',
  417. negativeText: '取消',
  418. onPositiveClick: () => {
  419. console.log('确定');
  420. },
  421. onNegativeClick: () => {
  422. console.log('取消');
  423. }
  424. });
  425. });
  426. // actionEnd(target, 'right');
  427. };
  428. const startShowModal = (
  429. val:
  430. | 'setTimeIcon'
  431. | 'beatIcon'
  432. | 'toneIcon'
  433. | 'iconWhiteBorad'
  434. | 'iconPen'
  435. | 'iconNote'
  436. ) => {
  437. if (val == 'setTimeIcon') {
  438. showModalTime.value = true;
  439. }
  440. if (val == 'beatIcon') {
  441. showModalBeat.value = true;
  442. }
  443. if (val == 'toneIcon') {
  444. showModalTone.value = true;
  445. }
  446. if (val == 'iconNote') {
  447. if (NPopoverRef.value) {
  448. NPopoverRef.value.setShow(false);
  449. }
  450. console.log(route.name, 'guideInfo');
  451. eventGlobal.emit('teacher-guideInfo', route.name);
  452. }
  453. if (val == 'iconWhiteBorad') {
  454. studyData.whiteboardShow = true;
  455. studyData.type = 'whiteboard';
  456. studyData.homeStatus = false;
  457. if (NPopoverRef.value) {
  458. NPopoverRef.value.setShow(false);
  459. }
  460. }
  461. if (val == 'iconPen') {
  462. studyData.penShow = true;
  463. studyData.type = 'pen';
  464. studyData.homeStatus = false;
  465. if (NPopoverRef.value) {
  466. NPopoverRef.value.setShow(false);
  467. }
  468. }
  469. };
  470. // const moveTargetBoundary = (target: any, type: any) => {
  471. // console.log('moveTargetBoundary', target, type);
  472. // };
  473. // 这里是旋转
  474. const rate = (target: any, rate: any) => {
  475. target.style.transform = ' rotate(' + rate + ')';
  476. };
  477. // 这里是选装的方式
  478. const actionEnd = (target: any, type: any) => {
  479. switch (type) {
  480. case 'left':
  481. rate(target, '90deg');
  482. target!.style.left = `${2 - boxBoundaryInfo.subWidth / 2}px`;
  483. target!.style.top = `${top}px`;
  484. break;
  485. case 'right':
  486. rate(target, '-90deg');
  487. target!.style.left = `${
  488. boxBoundaryInfo.mainWidth - 2 + boxBoundaryInfo.subWidth / 2
  489. }px`;
  490. target!.style.top = `${top}px`;
  491. break;
  492. case 'top':
  493. target!.style.top = `${2 - boxBoundaryInfo.subHeight / 2}px`;
  494. rate(target, '-180deg');
  495. break;
  496. case 'bottom':
  497. target!.style.top = `${
  498. boxBoundaryInfo.mainHeight - 2 + boxBoundaryInfo.subHeight / 2
  499. }px`;
  500. break;
  501. default:
  502. rate(target, '-0');
  503. break;
  504. }
  505. };
  506. const initBoxRectInfo = (target: any, wrapInfo: any) => {
  507. // const subdEl = document.getElementById(`moveNPopover`) as HTMLDivElement;
  508. // console.log(subdEl, "subdEl", "drag");
  509. const subdElStyle = getComputedStyle(target, null);
  510. const RectInfo = {
  511. left: Number(subdElStyle.left.replace('px', '')),
  512. top: Number(subdElStyle.top.replace('px', '')),
  513. width: Number(subdElStyle.width.replace('px', '')),
  514. height: Number(subdElStyle.height.replace('px', ''))
  515. };
  516. // target.style.transition = ''
  517. const mainWidth =
  518. parseInt(
  519. window.getComputedStyle(document.querySelector('.wrap') as Element)
  520. .width
  521. ) - RectInfo.width;
  522. const mainHeight =
  523. parseInt(
  524. window.getComputedStyle(document.querySelector('.wrap') as Element)
  525. .height
  526. ) - RectInfo.height;
  527. // boxBoundaryInfo.isBoundary = false;
  528. // boxBoundaryInfo.isBoundaryType = '';
  529. wrapInfo.mainHeight = mainHeight;
  530. wrapInfo.mainWidth = mainWidth;
  531. wrapInfo.subWidth = RectInfo.width;
  532. wrapInfo.subHeight = RectInfo.height;
  533. target.style.transition = '.3s .3s';
  534. };
  535. /** 教学数据 */
  536. const studyData = reactive({
  537. homeStatus: true, // 是否显示首页
  538. type: '',
  539. penShow: false,
  540. whiteboardShow: false
  541. });
  542. return () => (
  543. <div class={[styles.wrap, 'wrap']}>
  544. <div>
  545. <LayoutSilder></LayoutSilder>
  546. </div>
  547. <div class={styles.Wrapcore}>
  548. <LayoutTop></LayoutTop>
  549. <div class={styles.WrapcoreView} id="WrapcoreViewWrap">
  550. {/* <div class={styles.WrapcoreViewInfo}> */}
  551. <router-view>
  552. {(obj: any) => (
  553. <Transition name="fade-slide" mode="out-in">
  554. <obj.Component />
  555. </Transition>
  556. )}
  557. </router-view>
  558. {/* </div> */}
  559. </div>
  560. </div>
  561. {/* <img
  562. src={toolStartClass}
  563. id="moveNPopover2"
  564. style={{
  565. display: ['/', '/home', '/classList', '/prepare-lessons'].includes(
  566. route.path
  567. )
  568. ? 'none'
  569. : 'block'
  570. }}
  571. class={[
  572. styles.toolClassImg,
  573. 'moveNPopover2',
  574. isDragIng.value ? styles.isDragIng : ''
  575. ]}
  576. alt=""
  577. /> */}
  578. <NPopover
  579. raw
  580. trigger="click"
  581. ref={NPopoverRef}
  582. show-arrow={false}
  583. placement={directionType.value as 'left' | 'right'}
  584. v-slots={{
  585. trigger: () => (
  586. // 首页不显示工具箱 ['/', '/home'].includes(route.path) ||
  587. <img
  588. // src={isDragIng.value ? dragingBoxIcon : toolbox}
  589. src={toolbox}
  590. id="moveNPopover"
  591. style={{
  592. display: !studyData.homeStatus ? 'none' : 'block'
  593. }}
  594. class={[
  595. styles.toolboxImg,
  596. 'moveNPopover',
  597. isDragIng.value ? styles.isDragIng : ''
  598. ]}
  599. alt=""
  600. />
  601. )
  602. }}>
  603. <div class={styles.booxToolWrap}>
  604. <div>
  605. <div
  606. class={styles.booxToolItem}
  607. onClick={() => startShowModal('beatIcon')}>
  608. <img src={beatIcon} alt="" />
  609. 节拍器
  610. </div>
  611. <div
  612. class={styles.booxToolItem}
  613. onClick={() => startShowModal('toneIcon')}>
  614. <img src={toneIcon} alt="" />
  615. 调音器
  616. </div>
  617. <div
  618. class={styles.booxToolItem}
  619. onClick={() => startShowModal('setTimeIcon')}>
  620. <img src={setTimeIcon} alt="" />
  621. 计时器
  622. </div>
  623. <div
  624. class={styles.booxToolItem}
  625. onClick={() => {
  626. showClass.value = true;
  627. }}
  628. style={{
  629. display: [
  630. '/',
  631. '/home',
  632. '/classList',
  633. '/prepare-lessons'
  634. ].includes(route.path)
  635. ? 'none'
  636. : 'block'
  637. }}>
  638. <img
  639. src={toolStartClass}
  640. style={{
  641. display: [
  642. '/',
  643. '/home',
  644. '/classList',
  645. '/prepare-lessons'
  646. ].includes(route.path)
  647. ? 'none'
  648. : 'block'
  649. }}
  650. class={[styles.toolClassImg]}
  651. alt=""
  652. />
  653. 开始上课
  654. </div>
  655. </div>
  656. <div>
  657. <div
  658. class={styles.booxToolItem}
  659. onClick={() => startShowModal('iconNote')}>
  660. <img src={iconNote} alt="" />
  661. 帮助指引
  662. </div>
  663. <div
  664. class={styles.booxToolItem}
  665. onClick={() => startShowModal('iconPen')}>
  666. <img src={iconWhiteBorad} alt="" />
  667. 批注
  668. </div>
  669. <div
  670. class={styles.booxToolItem}
  671. onClick={() => startShowModal('iconWhiteBorad')}>
  672. <img src={iconPen} alt="" />
  673. 白板
  674. </div>
  675. </div>
  676. </div>
  677. </NPopover>
  678. {/* 批注 */}
  679. {studyData.penShow && (
  680. <Pen
  681. show={studyData.type === 'pen'}
  682. type={studyData.type as any}
  683. close={() => {
  684. studyData.type = 'init';
  685. studyData.homeStatus = true;
  686. }}
  687. />
  688. )}
  689. {studyData.whiteboardShow && (
  690. <Pen
  691. show={studyData.type === 'whiteboard'}
  692. type={studyData.type as any}
  693. close={() => {
  694. studyData.type = 'init';
  695. studyData.homeStatus = true;
  696. }}
  697. />
  698. )}
  699. <NModal
  700. class={['modalTitle background']}
  701. style={{ width: '687px' }}
  702. title={'节拍器'}
  703. preset="card"
  704. v-model:show={showModalBeat.value}>
  705. <div class={styles.modeWrap}>
  706. <iframe
  707. src={`${vaildUrl()}/metronome/?id=${new Date().getTime()}`}
  708. scrolling="no"
  709. frameborder="0"
  710. width="100%"
  711. height={'650px'}></iframe>
  712. </div>
  713. </NModal>
  714. <NModal v-model:show={showModalTone.value} class={['background']}>
  715. {/* <div
  716. onClick={() => {
  717. showModalTone.value = false;
  718. }}>
  719. <NImage
  720. src={toneImage}
  721. previewDisabled
  722. class={styles.beatImage}></NImage>
  723. </div> */}
  724. <div>
  725. <PlaceholderTone
  726. onClose={() => {
  727. showModalTone.value = false;
  728. }}></PlaceholderTone>
  729. </div>
  730. </NModal>
  731. <NModal
  732. v-model:show={showModalTime.value}
  733. class={['modalTitle background']}
  734. title={'计时器'}
  735. preset="card"
  736. style={{ width: px2vw(772) }}>
  737. <div>
  738. <TimerMeter></TimerMeter>
  739. </div>
  740. </NModal>
  741. <NModal
  742. v-model:show={showClass.value}
  743. class={['modalTitle background', styles.showClass]}
  744. preset="card"
  745. title={'开始上课'}>
  746. <AttendClass
  747. onClose={() => (showClass.value = false)}
  748. type="change"
  749. onConfirm={(item: any) => {
  750. showClass.value = false;
  751. router.push({
  752. path: '/prepare-lessons',
  753. query: {
  754. ...item
  755. }
  756. });
  757. }}
  758. />
  759. </NModal>
  760. {/* 弹窗查看 */}
  761. <PreviewWindow
  762. v-model:show={previewModal.value}
  763. type="attend"
  764. params={previewItem.value}
  765. />
  766. </div>
  767. );
  768. }
  769. });