index.tsx 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351
  1. import {
  2. PropType,
  3. computed,
  4. defineComponent,
  5. onMounted,
  6. reactive,
  7. watch
  8. } from 'vue';
  9. import styles from './index.module.less';
  10. import { Button, Collapse, CollapseItem, showToast } from 'vant';
  11. import {
  12. barLineList,
  13. beatList,
  14. elementList,
  15. initSelectScorePartModal,
  16. renderScore,
  17. renderScoreModal,
  18. setting,
  19. setting_modal,
  20. tempo4,
  21. tempo8
  22. } from '../setting';
  23. import { getImage } from '../images/music';
  24. import { hendleEndTick } from '../tick';
  25. import { hendleEndBeat } from '../beat-tick';
  26. import { useRoute } from 'vue-router';
  27. import settingArrowActive from '../images/setting-arrow-active.png';
  28. import settingArrowDefault from '../images/setting-arrow-default.png';
  29. import deepClone from '@/helpers/deep-clone';
  30. export default defineComponent({
  31. emits: ['close'],
  32. props: {
  33. class: {
  34. type: Object as PropType<any>,
  35. default: () => {}
  36. }
  37. // dataJson: {
  38. // type: Object,
  39. // default: () => {}
  40. // }
  41. },
  42. name: 'setting-modal',
  43. setup(props, { emit, expose }) {
  44. const route = useRoute();
  45. // const { element, beat, barLine, tempo } = props.dataJson;
  46. const tempDeepClone = (val: any) => {
  47. return JSON.parse(JSON.stringify(val));
  48. };
  49. const state = reactive({
  50. win: route.query.win,
  51. platform: route.query.platform,
  52. activeNames: ['base', 'beat'] as any, // 折叠面板
  53. element:
  54. tempDeepClone(setting_modal.element) ||
  55. ('jianpu' as 'jianpu' | 'staff'), // 元素
  56. beat:
  57. tempDeepClone(setting_modal.beat) ||
  58. ('4-4' as '4-2' | '4-3' | '4-4' | '8-3' | '8-6'), // 拍号
  59. barLine: tempDeepClone(setting_modal.barLine) || ('1' as '1' | '2' | '4'), // 小节数
  60. tempo: tempDeepClone(setting_modal.tempo) || (['1', '2', '3'] as any[]) // 节奏形筛选
  61. });
  62. const tempoList = computed(() => {
  63. if (['4-2', '4-3', '4-4'].includes(state.beat)) {
  64. return tempo4;
  65. } else if (['8-3', '8-6'].includes(state.beat)) {
  66. return tempo8;
  67. }
  68. return tempo4;
  69. });
  70. // 重置选中数据
  71. watch(
  72. () => setting_modal,
  73. () => {
  74. state.element =
  75. tempDeepClone(setting_modal.element) ||
  76. ('jianpu' as 'jianpu' | 'staff'); // 元素
  77. state.beat =
  78. tempDeepClone(setting_modal.beat) ||
  79. ('4-4' as '4-2' | '4-3' | '4-4' | '8-3' | '8-6'); // 拍号
  80. state.barLine =
  81. tempDeepClone(setting_modal.barLine) || ('1' as '1' | '2' | '4'); // 小节数
  82. state.tempo =
  83. tempDeepClone(setting_modal.tempo) || (['1', '2', '3'] as any[]); // 节奏形筛选
  84. },
  85. {
  86. deep: true
  87. }
  88. );
  89. const getBeatUrl = (value: any) => {
  90. const prefix = state.element === 'jianpu' ? 'j-' : 'f-';
  91. return prefix + value + '.png';
  92. };
  93. const onChangeTempo = (item: any) => {
  94. let si = 0,
  95. ji = 0;
  96. let status = false;
  97. setting_modal.scorePart.forEach((part: Array<any>, i: number) => {
  98. part.forEach((child: any, j: number) => {
  99. if (child.selected) {
  100. child.url = getBeatUrl(item);
  101. child.index = item;
  102. child.selected = false;
  103. si = i;
  104. ji = j;
  105. status = true;
  106. }
  107. });
  108. });
  109. if (status) {
  110. const indexs = toNext(si, ji);
  111. if (indexs && indexs.length > 0) {
  112. initSelectScorePartModal(indexs[0], indexs[1]);
  113. }
  114. }
  115. };
  116. const toNext = (i: number, j: number) => {
  117. const scorePart = setting_modal.scorePart;
  118. let tempJ = j + 1;
  119. for (let si = i; si < scorePart.length; si++) {
  120. for (let ji = tempJ; ji < scorePart[si].length; ji++) {
  121. return [si, ji];
  122. }
  123. tempJ = 0;
  124. }
  125. };
  126. const handleStop = () => {
  127. setting_modal.playState = 'pause';
  128. if (setting_modal.playType === 'beat') {
  129. hendleEndTick();
  130. } else {
  131. hendleEndBeat();
  132. }
  133. };
  134. /** 数据有变化时重置 */
  135. const onChangeResetTempo = () => {
  136. // if (state.tempo.length <= 0) {
  137. // showToast('节奏型不能为空');
  138. // return;
  139. // }
  140. let status = false; // 是否有更改
  141. if (
  142. setting_modal.element !== state.element ||
  143. setting_modal.beat !== state.beat ||
  144. setting_modal.barLine !== state.barLine ||
  145. setting_modal.tempo.join(',') !== state.tempo.join(',')
  146. ) {
  147. status = true;
  148. }
  149. // 判断是否有数据变化
  150. handleStop();
  151. if (status) {
  152. setting_modal.element = tempDeepClone(state.element);
  153. setting_modal.beat = tempDeepClone(state.beat); //state.beat;
  154. setting_modal.barLine = tempDeepClone(state.barLine); // state.barLine;
  155. setting_modal.tempo = tempDeepClone(state.tempo); // state.tempo;
  156. renderScoreModal();
  157. }
  158. };
  159. const onSubmit = () => {
  160. // 初始化设置的数据
  161. for (let i in setting_modal) {
  162. setting[i] = JSON.parse(JSON.stringify(setting_modal[i]));
  163. }
  164. emit('close');
  165. };
  166. expose({
  167. onSubmit
  168. });
  169. return () => (
  170. <div
  171. class={[
  172. props.class,
  173. styles.settingContainer,
  174. state.win === 'pc' ? styles.pcS : '',
  175. state.platform === 'modal' && state.win !== 'pc' ? styles.modalS : ''
  176. ]}>
  177. {/* <div class={styles.title}></div> */}
  178. <div class={[styles.iconTitBox, 'iconTitBoxMove']}>
  179. <i
  180. class={styles.iconClose}
  181. onClick={() => {
  182. emit('close');
  183. setTimeout(() => {
  184. state.element = tempDeepClone(setting_modal.element);
  185. state.beat = tempDeepClone(setting_modal.beat); //state.beat;
  186. state.barLine = tempDeepClone(setting_modal.barLine); // state.barLine;
  187. state.tempo = tempDeepClone(setting_modal.tempo); // state.tempo;
  188. }, 300);
  189. }}></i>
  190. </div>
  191. <div class={styles.settingContent}>
  192. <Collapse v-model={state.activeNames} border={false}>
  193. <CollapseItem
  194. title="基础设置"
  195. name="base"
  196. border={false}
  197. isLink={false}
  198. class={[
  199. styles.collapseContainer,
  200. state.activeNames.includes('base') ? '' : styles.paddingBottom
  201. ]}>
  202. {{
  203. icon: () => (
  204. <img
  205. src={
  206. state.activeNames.includes('base')
  207. ? settingArrowActive
  208. : settingArrowDefault
  209. }
  210. class={styles.iArrow}
  211. />
  212. ),
  213. default: () => (
  214. <>
  215. <div class={styles.parmaTitle}>元素</div>
  216. <div class={styles.paramContent}>
  217. {Object.keys(elementList).map((item: any) => (
  218. <Button
  219. round
  220. class={[
  221. styles.btn,
  222. state.element === item && styles.active
  223. ]}
  224. onClick={() => {
  225. state.element = item;
  226. onChangeResetTempo();
  227. }}>
  228. {elementList[item]}
  229. </Button>
  230. ))}
  231. </div>
  232. <div class={styles.parmaTitle}>拍号</div>
  233. <div class={[styles.paramContent, styles.beatContent]}>
  234. {Object.keys(beatList).map((item: any) => (
  235. <Button
  236. round
  237. class={[
  238. styles.btn,
  239. state.beat === item && styles.active
  240. ]}
  241. onClick={() => {
  242. state.beat = item;
  243. if (['4-2', '4-3', '4-4'].includes(state.beat)) {
  244. state.tempo = ['1', '2', '3'];
  245. } else if (['8-3', '8-6'].includes(state.beat)) {
  246. state.tempo = ['15', '16', '17'];
  247. }
  248. onChangeResetTempo();
  249. }}>
  250. {beatList[item]}
  251. </Button>
  252. ))}
  253. </div>
  254. <div class={styles.parmaTitle}>每页显示小节数量</div>
  255. <div class={styles.paramContent}>
  256. {Object.keys(barLineList).map((item: any) => (
  257. <Button
  258. round
  259. class={[
  260. styles.btn,
  261. state.barLine === item && styles.active
  262. ]}
  263. onClick={() => {
  264. state.barLine = item;
  265. onChangeResetTempo();
  266. }}>
  267. {barLineList[item]}
  268. </Button>
  269. ))}
  270. </div>
  271. </>
  272. )
  273. }}
  274. </CollapseItem>
  275. <CollapseItem
  276. title="节奏型"
  277. name="beat"
  278. border={false}
  279. isLink={false}
  280. class={styles.collapseContainer}>
  281. {{
  282. icon: () => (
  283. <img
  284. src={
  285. state.activeNames.includes('beat')
  286. ? settingArrowActive
  287. : settingArrowDefault
  288. }
  289. class={styles.iArrow}
  290. />
  291. ),
  292. default: () => (
  293. <>
  294. {/* <div class={styles.parmaTitle}>节奏型筛选</div> */}
  295. <div class={[styles.paramContent, styles.tempo]}>
  296. {Object.keys(tempoList.value).map((item: any) => (
  297. <div
  298. draggable={true}
  299. onDragstart={(e: any) => {
  300. // console.log('1111');
  301. e.dataTransfer.setData(
  302. 'text',
  303. JSON.stringify({
  304. index: item,
  305. url: getBeatUrl(item)
  306. })
  307. );
  308. }}
  309. onClick={() => onChangeTempo(item)}>
  310. <img
  311. // class={state.tempo.includes(item) && styles.active}
  312. src={getImage(
  313. (state.element === 'jianpu' ? 'j-' : 'f-') +
  314. tempoList.value[item]
  315. )}
  316. />
  317. </div>
  318. ))}
  319. </div>
  320. </>
  321. )
  322. }}
  323. </CollapseItem>
  324. </Collapse>
  325. {/* <div class={styles.settingParams}></div> */}
  326. </div>
  327. {!state.win && !state.platform && (
  328. <div class={styles.btnGroup}>
  329. <Button class={styles.btnSubmit} onClick={onSubmit}></Button>
  330. </div>
  331. )}
  332. </div>
  333. );
  334. }
  335. });