index.tsx 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406
  1. import { Transition, defineComponent, onMounted, ref } from 'vue';
  2. import LayoutSilder from './layoutSilder';
  3. import LayoutTop from './layoutTop';
  4. import styles from './index.module.less';
  5. import { NButton, NImage, NModal, NPopover, NSpace } from 'naive-ui';
  6. import Moveable from 'moveable';
  7. import toolStartClass from './images/toolStartClass.png';
  8. import toolbox from './images/toolbox.png';
  9. import setTimeIcon from './images/setTimeIcon.png';
  10. import beatIcon from './images/beatIcon.png';
  11. import toneIcon from './images/toneIcon.png';
  12. import beatImage from './images/beatImage.png';
  13. import toneImage from './images/toneImage.png';
  14. import setTimeImage from './images/setTimeImage.png';
  15. import dragingBoxIcon from './images/dragingBoxIcon.png';
  16. import TimerMeter from '../timerMeter';
  17. import { useRoute } from 'vue-router';
  18. import { vaildUrl } from '/src/utils/urlUtils';
  19. import ChioseModal from '/src/views/home/modals/chioseModal';
  20. import {px2vw,px2vwH} from '@/utils/index'
  21. import PlaceholderTone from './modals/placeholderTone';
  22. export default defineComponent({
  23. name: 'layoutView',
  24. setup() {
  25. const directionType = ref('left');
  26. const showClass = ref(false);
  27. const showModalBeat = ref(false);
  28. const showModalTone = ref(false);
  29. const showModalTime = ref(false);
  30. const route = useRoute();
  31. const isDragIng = ref(false);
  32. const initMoveable = async () => {
  33. if (document.querySelector('.wrap')) {
  34. const moveable = new Moveable(document.querySelector('.wrap') as any, {
  35. target: document.querySelector('#moveNPopover') as any,
  36. // If the container is null, the position is fixed. (default: parentElement(document.body))
  37. container: document.querySelector('.wrap') as any,
  38. // snappable: true,
  39. // bounds: {"left":100,"top":100,"right":100,"bottom":100},
  40. draggable: true,
  41. resizable: false,
  42. scalable: false,
  43. rotatable: false,
  44. warpable: false,
  45. pinchable: false, // ["resizable", "scalable", "rotatable"]
  46. origin: false,
  47. keepRatio: false,
  48. // Resize, Scale Events at edges.
  49. edge: false,
  50. throttleDrag: 0,
  51. throttleResize: 0,
  52. throttleScale: 0,
  53. throttleRotate: 0
  54. });
  55. moveable
  56. // .on('dragStart', ({ target, clientX, clientY }) => {
  57. // console.log('dragStart');
  58. // })
  59. .on(
  60. 'drag',
  61. ({
  62. target,
  63. // transform,
  64. left,
  65. top,
  66. right,
  67. bottom
  68. // beforeDelta,
  69. // beforeDist,
  70. // delta,
  71. // dist,
  72. // clientX,
  73. // clientY
  74. }) => {
  75. isDragIng.value = true;
  76. const subdEl = document.getElementById(
  77. `moveNPopover`
  78. ) as HTMLDivElement;
  79. // console.log(subdEl, "subdEl", "drag");
  80. const subdElStyle = getComputedStyle(subdEl, null);
  81. const RectInfo = {
  82. left: Number(subdElStyle.left.replace('px', '')),
  83. top: Number(subdElStyle.top.replace('px', '')),
  84. width: Number(subdElStyle.width.replace('px', '')),
  85. height: Number(subdElStyle.height.replace('px', ''))
  86. };
  87. const mainWidth =
  88. parseInt(
  89. window.getComputedStyle(
  90. document.querySelector('.wrap') as Element
  91. ).width
  92. ) - RectInfo.width;
  93. const mainHeight =
  94. parseInt(
  95. window.getComputedStyle(
  96. document.querySelector('.wrap') as Element
  97. ).height
  98. ) - RectInfo.height;
  99. if (left < 0) {
  100. left = 2;
  101. }
  102. if (top < 0) {
  103. top = 2;
  104. }
  105. if (right < 0) {
  106. right = 2;
  107. }
  108. if (bottom < 0) {
  109. bottom = 2;
  110. }
  111. if (left > mainWidth - 2) {
  112. left = mainWidth - 2;
  113. }
  114. if (top > mainHeight - 2) {
  115. top = mainHeight - 2;
  116. }
  117. target!.style.left = `${left}px`;
  118. target!.style.top = `${top}px`;
  119. }
  120. )
  121. .on(
  122. 'dragEnd',
  123. async ({
  124. // target, isDrag,
  125. clientX
  126. // clientY
  127. }) => {
  128. if (document.body.clientWidth / 2 - clientX > 0) {
  129. // 往左出
  130. directionType.value = 'right';
  131. } else {
  132. // 往又出
  133. directionType.value = 'left';
  134. }
  135. isDragIng.value = false;
  136. }
  137. );
  138. }
  139. };
  140. const initMoveableClass = async () => {
  141. if (document.querySelector('.wrap')) {
  142. const moveable = new Moveable(document.querySelector('.wrap') as any, {
  143. target: document.querySelector('#moveNPopover2') as any,
  144. // If the container is null, the position is fixed. (default: parentElement(document.body))
  145. container: document.querySelector('.wrap') as any,
  146. // snappable: true,
  147. // bounds: {"left":100,"top":100,"right":100,"bottom":100},
  148. draggable: true,
  149. resizable: false,
  150. scalable: false,
  151. rotatable: false,
  152. warpable: false,
  153. pinchable: false, // ["resizable", "scalable", "rotatable"]
  154. origin: false,
  155. keepRatio: false,
  156. // Resize, Scale Events at edges.
  157. edge: false,
  158. throttleDrag: 0,
  159. throttleResize: 0,
  160. throttleScale: 0,
  161. throttleRotate: 0
  162. });
  163. moveable
  164. .on(
  165. 'drag',
  166. ({
  167. target,
  168. // transform,
  169. left,
  170. top,
  171. right,
  172. bottom
  173. }) => {
  174. isDragIng.value = true;
  175. const subdEl = document.getElementById(
  176. `moveNPopover2`
  177. ) as HTMLDivElement;
  178. // console.log(subdEl, "subdEl", "drag");
  179. const subdElStyle = getComputedStyle(subdEl, null);
  180. const RectInfo = {
  181. left: Number(subdElStyle.left.replace('px', '')),
  182. top: Number(subdElStyle.top.replace('px', '')),
  183. width: Number(subdElStyle.width.replace('px', '')),
  184. height: Number(subdElStyle.height.replace('px', ''))
  185. };
  186. const mainWidth =
  187. parseInt(
  188. window.getComputedStyle(
  189. document.querySelector('.wrap') as Element
  190. ).width
  191. ) - RectInfo.width;
  192. const mainHeight =
  193. parseInt(
  194. window.getComputedStyle(
  195. document.querySelector('.wrap') as Element
  196. ).height
  197. ) - RectInfo.height;
  198. if (left < 0) {
  199. left = 2;
  200. }
  201. if (top < 0) {
  202. top = 2;
  203. }
  204. if (right < 0) {
  205. right = 2;
  206. }
  207. if (bottom < 0) {
  208. bottom = 2;
  209. }
  210. if (left > mainWidth - 2) {
  211. left = mainWidth - 2;
  212. }
  213. if (top > mainHeight - 2) {
  214. top = mainHeight - 2;
  215. }
  216. target!.style.left = `${left}px`;
  217. target!.style.top = `${top}px`;
  218. }
  219. )
  220. .on(
  221. 'dragEnd',
  222. async ({
  223. // target, isDrag,
  224. clientX
  225. // clientY
  226. }) => {
  227. if (document.body.clientWidth / 2 - clientX > 0) {
  228. // 往左出
  229. directionType.value = 'right';
  230. } else {
  231. // 往又出
  232. directionType.value = 'left';
  233. }
  234. isDragIng.value = false;
  235. }
  236. )
  237. .on('click', () => {
  238. console.log(true, '1212');
  239. showClass.value = true;
  240. });
  241. }
  242. };
  243. onMounted(() => {
  244. initMoveable();
  245. initMoveableClass();
  246. });
  247. const startShowModal = (val: 'setTimeIcon' | 'beatIcon' | 'toneIcon') => {
  248. if (val == 'setTimeIcon') {
  249. showModalTime.value = true;
  250. }
  251. if (val == 'beatIcon') {
  252. showModalBeat.value = true;
  253. }
  254. if (val == 'toneIcon') {
  255. showModalTone.value = true;
  256. }
  257. };
  258. return () => (
  259. <div class={[styles.wrap, 'wrap']}>
  260. <div>
  261. <LayoutSilder></LayoutSilder>
  262. </div>
  263. <div class={styles.Wrapcore}>
  264. <LayoutTop></LayoutTop>
  265. <div class={styles.WrapcoreView}>
  266. {/* <div class={styles.WrapcoreViewInfo}> */}
  267. <router-view>
  268. {(obj: any) => (
  269. <Transition name="fade-slide" mode="out-in">
  270. <obj.Component />
  271. </Transition>
  272. )}
  273. </router-view>
  274. {/* </div> */}
  275. </div>
  276. </div>
  277. <img
  278. src={toolStartClass}
  279. id="moveNPopover2"
  280. style={{
  281. display: ['/', '/home', '/classList', '/prepare-lessons'].includes(
  282. route.path
  283. )
  284. ? 'none'
  285. : 'block'
  286. }}
  287. class={[
  288. styles.toolClassImg,
  289. 'moveNPopover2',
  290. isDragIng.value ? styles.isDragIng : ''
  291. ]}
  292. alt=""
  293. />
  294. <NPopover
  295. raw
  296. trigger="click"
  297. show-arrow={false}
  298. placement={directionType.value as 'left' | 'right'}
  299. v-slots={{
  300. trigger: () => (
  301. // 首页不显示工具箱
  302. <img
  303. // src={isDragIng.value ? dragingBoxIcon : toolbox}
  304. src={toolbox}
  305. id="moveNPopover"
  306. style={{
  307. display: ['/', '/home'].includes(route.path)
  308. ? 'none'
  309. : 'block'
  310. }}
  311. class={[
  312. styles.toolboxImg,
  313. 'moveNPopover',
  314. isDragIng.value ? styles.isDragIng : ''
  315. ]}
  316. alt=""
  317. />
  318. )
  319. }}>
  320. <div class={styles.booxToolWrap}>
  321. <div
  322. class={styles.booxToolItem}
  323. onClick={() => startShowModal('beatIcon')}>
  324. <img src={beatIcon} alt="" />
  325. 节拍器
  326. </div>
  327. <div
  328. class={styles.booxToolItem}
  329. onClick={() => startShowModal('toneIcon')}>
  330. <img src={toneIcon} alt="" />
  331. 调音器
  332. </div>
  333. <div
  334. class={styles.booxToolItem}
  335. onClick={() => startShowModal('setTimeIcon')}>
  336. <img src={setTimeIcon} alt="" />
  337. 计时器
  338. </div>
  339. </div>
  340. </NPopover>
  341. <NModal
  342. class={['modalTitle background']}
  343. title={'节拍器'}
  344. preset="card"
  345. v-model:show={showModalBeat.value}
  346. style={{ width: '687px' }}>
  347. <div class={styles.modeWrap}>
  348. <iframe
  349. src={`${vaildUrl()}/metronome/?id=${new Date().getTime()}`}
  350. scrolling="no"
  351. frameborder="0"
  352. width="100%"
  353. height={'650px'}></iframe>
  354. </div>
  355. </NModal>
  356. <NModal
  357. v-model:show={showModalTone.value}
  358. class={['background']}
  359. >
  360. {/* <div
  361. onClick={() => {
  362. showModalTone.value = false;
  363. }}>
  364. <NImage
  365. src={toneImage}
  366. previewDisabled
  367. class={styles.beatImage}></NImage>
  368. </div> */}
  369. <div>
  370. <PlaceholderTone onClose={()=>{
  371. showModalTone.value = false
  372. }}></PlaceholderTone>
  373. </div>
  374. </NModal>
  375. <NModal
  376. v-model:show={showModalTime.value}
  377. class={['modalTitle background']}
  378. title={'计时器'}
  379. preset="card"
  380. style={{ width: px2vw(772) }}>
  381. <div>
  382. <TimerMeter></TimerMeter>
  383. </div>
  384. </NModal>
  385. <NModal
  386. v-model:show={showClass.value}
  387. class={['modalTitle background', styles.showClass]}
  388. preset="card"
  389. title={'开始上课'}>
  390. <ChioseModal onClose={() => (showClass.value = false)} />
  391. </NModal>
  392. </div>
  393. );
  394. }
  395. });