index.tsx 12 KB

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