index.tsx 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358
  1. import {
  2. PropType,
  3. defineComponent,
  4. nextTick,
  5. onMounted,
  6. reactive,
  7. ref,
  8. toRef
  9. } from 'vue';
  10. import styles from './index.module.less';
  11. import { NTabs, NTabPane, NModal } from 'naive-ui';
  12. import SelectMusicModal from '../../model/select-music';
  13. import { usePrepareStore } from '/src/store/modules/prepareLessons';
  14. import SelectResources from '../../model/select-resources';
  15. import SelectMusic, { typeFormat } from './components/select-music';
  16. import ResourceItem from './components/resource-item';
  17. import TrainUpdate from '/src/views/attend-class/model/train-update';
  18. import requestOrigin from 'umi-request';
  19. import { eventGlobal } from '/src/utils';
  20. import useDrag from '@/hooks/useDrag';
  21. import Dragbom from '@/hooks/useDrag/dragbom';
  22. import { useUserStore } from '@/store/modules/users';
  23. import { useCatchStore } from '/src/store/modules/catchData';
  24. import { modalClickMask } from '/src/state';
  25. export default defineComponent({
  26. name: 'resource-main',
  27. props: {
  28. /** 类型 */
  29. cardType: {
  30. type: String as PropType<'' | 'homerowk-record' | 'prepare'>,
  31. default: ''
  32. },
  33. from: {
  34. // 来自哪里
  35. type: String,
  36. default: ''
  37. }
  38. },
  39. setup(props, { expose }) {
  40. const prepareStore = usePrepareStore();
  41. const catchStore = useCatchStore();
  42. const forms = reactive({
  43. tabType: 'relateResources',
  44. tabWorkType: 'myMusic',
  45. selectMusicStatus: false,
  46. selectResourceStatus: false,
  47. editStatus: false,
  48. editItem: {} as any,
  49. searchGroup: {} as any
  50. });
  51. const relateResourcesRef = ref();
  52. const shareResourcesRef = ref();
  53. const myResourcesRef = ref();
  54. const myCollectRef = ref();
  55. const tabRef = ref();
  56. const workRef = ref();
  57. const onAdd = async (item: any) => {
  58. let xmlStatus = 'init';
  59. // 第一个声部小节
  60. let firstMeasures: any = null;
  61. try {
  62. // 获取文件
  63. const res = await requestOrigin.get(item.xmlFileUrl, {
  64. mode: 'cors'
  65. });
  66. const xmlParse = new DOMParser().parseFromString(res, 'text/xml');
  67. const parts = xmlParse.getElementsByTagName('part');
  68. firstMeasures = parts[0]?.getElementsByTagName('measure');
  69. xmlStatus = 'success';
  70. } catch (error) {
  71. xmlStatus = 'error';
  72. }
  73. // 判断读取小节数
  74. if (xmlStatus == 'success') {
  75. item.practiceChapterMax = firstMeasures.length;
  76. } else {
  77. item.practiceChapterMax = 0;
  78. }
  79. item.coursewareKnowledgeDetailId = prepareStore.getSelectKey;
  80. item.subjectId = prepareStore.getSubjectId;
  81. forms.editItem = item;
  82. forms.editStatus = true;
  83. };
  84. const resetTabPosition = () => {
  85. nextTick(() => {
  86. tabRef.value?.syncBarPosition();
  87. workRef.value?.syncBarPosition();
  88. });
  89. };
  90. onMounted(async () => {
  91. resetTabPosition();
  92. // 获取教材分类列表
  93. await catchStore.getMusicSheetCategory(true);
  94. });
  95. // 弹窗拖动
  96. // 曲目资源
  97. let selectResourceStatusAddBoxDragData: any;
  98. let selectResourceStatusAddBoxClass: string;
  99. if (props.from === 'class') {
  100. const users = useUserStore();
  101. selectResourceStatusAddBoxClass = 'selectResourceStatusAddBoxClass_drag';
  102. selectResourceStatusAddBoxDragData = useDrag(
  103. [
  104. `${selectResourceStatusAddBoxClass} .select-resource>.n-tabs>.n-tabs-nav--top.n-tabs-nav`,
  105. `${selectResourceStatusAddBoxClass} .bom_drag`
  106. ],
  107. selectResourceStatusAddBoxClass,
  108. toRef(forms, 'selectMusicStatus'),
  109. users.info.id
  110. );
  111. }
  112. // 曲目资源 作业设置
  113. let workSetingBoxDragData: any;
  114. let workSetingBoxClass: string;
  115. if (props.from === 'class') {
  116. const users = useUserStore();
  117. workSetingBoxClass = 'workSetingBoxClass_drag';
  118. workSetingBoxDragData = useDrag(
  119. [
  120. `${workSetingBoxClass}>.n-card-header`,
  121. `${workSetingBoxClass} .bom_drag`
  122. ],
  123. workSetingBoxClass,
  124. toRef(forms, 'editStatus'),
  125. users.info.id
  126. );
  127. }
  128. //
  129. expose({
  130. resetTabPosition
  131. });
  132. return () => (
  133. <div
  134. class={[
  135. styles['resource-main'],
  136. forms.selectMusicStatus || forms.selectResourceStatus
  137. ? styles.resourceClose
  138. : ''
  139. ]}>
  140. {prepareStore.getTabType === 'courseware' &&
  141. !['homerowk-record', 'prepare'].includes(props.cardType) ? (
  142. <NTabs
  143. id="lessonsIn-0"
  144. ref={tabRef}
  145. animated
  146. class={styles.homerowkTabs}
  147. value={forms.tabType}
  148. paneClass={styles.paneTitle}
  149. paneWrapperClass={styles.paneWrapperContainer}
  150. onUpdate:value={(val: string) => {
  151. forms.tabType = val;
  152. }}>
  153. {{
  154. suffix: () => (
  155. <div
  156. class={styles.iconScreen}
  157. onClick={() => {
  158. let searchGroup: any = {};
  159. if (forms.tabType === 'relateResources') {
  160. searchGroup = relateResourcesRef.value?.getParams();
  161. } else if (forms.tabType === 'shareResources') {
  162. searchGroup = shareResourcesRef.value?.getParams();
  163. } else if (forms.tabType === 'myResources') {
  164. searchGroup = myResourcesRef.value?.getParams();
  165. } else if (forms.tabType === 'myCollect') {
  166. searchGroup = myCollectRef.value?.getParams();
  167. }
  168. forms.searchGroup = searchGroup;
  169. forms.selectResourceStatus = true;
  170. prepareStore.setSelectResourceStatus(true);
  171. }}>
  172. <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
  173. <g fill="none">
  174. <path
  175. d="M5 6a1 1 0 0 1 1-1h2a1 1 0 0 0 0-2H6a3 3 0 0 0-3 3v2a1 1 0 0 0 2 0V6zm0 12a1 1 0 0 0 1 1h2a1 1 0 1 1 0 2H6a3 3 0 0 1-3-3v-2a1 1 0 1 1 2 0v2zM18 5a1 1 0 0 1 1 1v2a1 1 0 1 0 2 0V6a3 3 0 0 0-3-3h-2a1 1 0 1 0 0 2h2zm1 13a1 1 0 0 1-1 1h-2a1 1 0 1 0 0 2h2a3 3 0 0 0 3-3v-2a1 1 0 1 0-2 0v2z"
  176. fill="#198CFE"></path>
  177. </g>
  178. </svg>
  179. </div>
  180. ),
  181. default: () => (
  182. <>
  183. <NTabPane name="relateResources" tab="相关资源">
  184. <ResourceItem
  185. type="relateResources"
  186. ref={relateResourcesRef}
  187. />
  188. </NTabPane>
  189. <NTabPane
  190. name="shareResources"
  191. tab="共享资源"
  192. // displayDirective="show:lazy"
  193. >
  194. <ResourceItem
  195. type="shareResources"
  196. ref={shareResourcesRef}
  197. />
  198. </NTabPane>
  199. <NTabPane
  200. name="myResources"
  201. tab="我的资源"
  202. // displayDirective="show:lazy"
  203. >
  204. <ResourceItem type="myResources" ref={myResourcesRef} />
  205. </NTabPane>
  206. <NTabPane
  207. name="myCollect"
  208. tab="我的收藏"
  209. // displayDirective="show:lazy"
  210. >
  211. <ResourceItem type="myCollect" ref={myCollectRef} />
  212. </NTabPane>
  213. </>
  214. )
  215. }}
  216. </NTabs>
  217. ) : (
  218. <NTabs
  219. ref={workRef}
  220. animated
  221. value={forms.tabWorkType}
  222. paneClass={styles.paneTitle}
  223. paneWrapperClass={styles.paneWrapperContainer}
  224. onUpdate:value={(val: string) => {
  225. forms.tabWorkType = val;
  226. }}>
  227. {{
  228. suffix: () => (
  229. <div
  230. class={styles.iconScreen}
  231. onClick={() => {
  232. forms.selectMusicStatus = true;
  233. prepareStore.setSelectMusicStatus(true);
  234. }}>
  235. <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
  236. <g fill="none">
  237. <path
  238. d="M5 6a1 1 0 0 1 1-1h2a1 1 0 0 0 0-2H6a3 3 0 0 0-3 3v2a1 1 0 0 0 2 0V6zm0 12a1 1 0 0 0 1 1h2a1 1 0 1 1 0 2H6a3 3 0 0 1-3-3v-2a1 1 0 1 1 2 0v2zM18 5a1 1 0 0 1 1 1v2a1 1 0 1 0 2 0V6a3 3 0 0 0-3-3h-2a1 1 0 1 0 0 2h2zm1 13a1 1 0 0 1-1 1h-2a1 1 0 1 0 0 2h2a3 3 0 0 0 3-3v-2a1 1 0 1 0-2 0v2z"
  239. fill="#198CFE"></path>
  240. </g>
  241. </svg>
  242. </div>
  243. ),
  244. default: () => (
  245. <>
  246. <NTabPane name="myMusic" tab="我的曲目">
  247. <SelectMusic
  248. from={props.from}
  249. cardType={props.cardType}
  250. type="myMusic"
  251. />
  252. </NTabPane>
  253. <NTabPane name="sahreMusic" tab="共享曲目">
  254. <SelectMusic
  255. from={props.from}
  256. cardType={props.cardType}
  257. type="sahreMusic"
  258. />
  259. </NTabPane>
  260. <NTabPane name="collectMusic" tab="收藏曲目">
  261. <SelectMusic
  262. from={props.from}
  263. cardType={props.cardType}
  264. type="collectMusic"
  265. />
  266. </NTabPane>
  267. </>
  268. )
  269. }}
  270. </NTabs>
  271. )}
  272. <NModal
  273. maskClosable={modalClickMask}
  274. v-model:show={forms.selectResourceStatus}
  275. onUpdate:show={(val: any) => {
  276. if (!val) {
  277. prepareStore.setSelectResourceStatus(val);
  278. }
  279. }}
  280. class={['modalTitle', styles.selectMusicModal]}
  281. preset="card"
  282. title={'选择资源'}>
  283. <SelectResources
  284. type={forms.tabType}
  285. searchGroup={forms.searchGroup}
  286. />
  287. </NModal>
  288. <NModal
  289. maskClosable={modalClickMask}
  290. style={
  291. props.from === 'class'
  292. ? selectResourceStatusAddBoxDragData.styleDrag.value
  293. : {}
  294. }
  295. v-model:show={forms.selectMusicStatus}
  296. onUpdate:show={(val: any) => {
  297. if (!val) {
  298. prepareStore.setSelectMusicStatus(val);
  299. }
  300. }}
  301. class={[
  302. 'modalTitle',
  303. styles.selectMusicModal,
  304. selectResourceStatusAddBoxClass
  305. ]}
  306. preset="card"
  307. title={'选择曲目'}>
  308. <SelectMusicModal
  309. from={props.from}
  310. onAdd={(item: any) => onAdd(item)}
  311. />
  312. {props.from === 'class' && <Dragbom></Dragbom>}
  313. </NModal>
  314. <NModal
  315. maskClosable={modalClickMask}
  316. style={
  317. props.from === 'class' ? workSetingBoxDragData.styleDrag.value : {}
  318. }
  319. v-model:show={forms.editStatus}
  320. class={[
  321. 'modalTitle background',
  322. styles.trainEditModal,
  323. workSetingBoxClass
  324. ]}
  325. preset="card"
  326. title="作业设置">
  327. <TrainUpdate
  328. item={forms.editItem}
  329. onClose={() => (forms.editStatus = false)}
  330. onConfirm={(item: any) => {
  331. const tList = typeFormat(
  332. item.trainingType,
  333. item.trainingConfigJson
  334. );
  335. const train = {
  336. ...item,
  337. id: null,
  338. musicName: forms.editItem.title,
  339. typeList: tList
  340. };
  341. eventGlobal.emit('onTrainAddItem', train);
  342. }}
  343. />
  344. {props.from === 'class' && <Dragbom></Dragbom>}
  345. </NModal>
  346. </div>
  347. );
  348. }
  349. });