index.tsx 27 KB

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