music-sheet-klx.tsx 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736
  1. import { defineComponent, onMounted, reactive, ref } from 'vue'
  2. import SaveForm from '@components/save-form'
  3. import {
  4. DataTableRowKey,
  5. NButton,
  6. NDataTable,
  7. NDatePicker,
  8. NDescriptions,
  9. NDescriptionsItem,
  10. NFormItem,
  11. NImage,
  12. NInput,
  13. NModal,
  14. NSelect,
  15. NSpace,
  16. NTag,
  17. useDialog,
  18. useMessage
  19. } from 'naive-ui'
  20. import Pagination from '@components/pagination'
  21. import TheTooltip from '@components/TheTooltip'
  22. import AddMusic from '@views/music-library/project-music-sheet/module/klx/addMusic'
  23. import { getMapValueByKey, getSelectDataFromObj } from '@/utils/objectUtil'
  24. import {
  25. appKey,
  26. musicSheetAudioType,
  27. musicSheetAvailableType,
  28. musicSheetPaymentType,
  29. musicSheetSourceType,
  30. musicSheetType
  31. } from '@/utils/constant'
  32. import {
  33. musicSheetApplicationExtendStatus,
  34. musicSheetApplicationExtendTagList,
  35. musicSheetApplicationOwnerList,
  36. musicSheetPageByApplication
  37. } from '@views/music-library/api'
  38. import { subjectPage, sysApplicationPage } from '@views/system-manage/api'
  39. import { filterTimes } from '@/utils/dateUtil'
  40. import deepClone from '@/utils/deep.clone'
  41. import { getOwnerName } from '@views/music-library/musicUtil'
  42. import UpdateMusic from '@views/music-library/project-music-sheet/module/klx/updateMusic'
  43. import MusicPreView from "@views/music-library/music-sheet/modal/musicPreView";
  44. export default defineComponent({
  45. name: 'music-sheet-KLX',
  46. props: {
  47. appKey: {
  48. type: String,
  49. default: 'KLX'
  50. }
  51. },
  52. setup(props) {
  53. const dialog = useDialog()
  54. const message = useMessage()
  55. const state = reactive({
  56. loading: false,
  57. appId: null as any,
  58. pagination: {
  59. page: 1,
  60. rows: 10,
  61. pageTotal: 0
  62. },
  63. searchForm: {
  64. keyword: null,
  65. musicSheetType: null, //曲目类型(SINGLE:单曲 CONCERT:合奏)
  66. subjectId: null, //声部ID
  67. subjectIds: null, //曲目声部ID集合
  68. status: null, //曲目状态(0:停用,1:启用)
  69. sourceType: null, //来源类型/作者属性(PLATFORM: 平台; ORG: 机构; PERSON: 个人)
  70. paymentType: null, //收费类型(FREE:免费;VIP:会员;CHARGE:单曲收费)
  71. userId: null, //所属人
  72. musicCategoryId: null, //曲目分类ID
  73. times: null, // 上传时间
  74. audioType: null, //音频类型(HOMEMODE: 自制 COMMON: 普通)
  75. exquisiteFlag: null, //精品标志
  76. topFlag: null, //是否置顶(0:否;1:是)
  77. availableType: null, //可用途径 ORG 机构 PLATFORM 平台
  78. appAuditFlag: null, //是否审核版本
  79. detailFlag: null, //是否查询详情
  80. musicTagIds: [] as any,//曲目标签
  81. applicationId: null, //所属人项目ID
  82. },
  83. subjectList: [],
  84. dataList: [] as any[],
  85. showAddDialog: false,
  86. showEditDialog: false,
  87. userIdDisable: true,
  88. userIdData: [] as any,
  89. updateRow: {} as any, // 修改选择的行
  90. musicTagList: [] as any, //曲目标签
  91. applicationId: null, //应用ID
  92. musicPreview: false,
  93. musicScore: null as any,
  94. useProjectData: [] as any, // 适用项目行数据
  95. })
  96. onMounted(async () => {
  97. state.loading = true
  98. // 获取应用APP信息
  99. try {
  100. const { data } = await sysApplicationPage({ page: 1, rows: 1, appKey: props.appKey })
  101. const tempList = data.rows || []
  102. if (!tempList || tempList.length == 0) {
  103. state.loading = false
  104. message.error('加载项目信息失败')
  105. return
  106. }
  107. state.appId = tempList[0].id
  108. state.applicationId = tempList[0].id
  109. } catch {}
  110. // 加载声部
  111. try {
  112. const { data } = await subjectPage({ page: 1, rows: 999 })
  113. const tempList = data.rows || []
  114. tempList.forEach((item: any) => {
  115. item.label = item.name
  116. item.value = item.id + ''
  117. })
  118. state.subjectList = tempList
  119. } catch {}
  120. // 加载曲目标签
  121. try {
  122. const { data } = await musicSheetApplicationExtendTagList({ applicationId: state.appId })
  123. if (data && data.length > 0) {
  124. data.forEach((item: any) => {
  125. state.musicTagList.push({
  126. ...item,
  127. label: item.name,
  128. value: item.id
  129. })
  130. })
  131. }
  132. } catch (err) {}
  133. // 加载表格数据
  134. initUseAppList()
  135. getList()
  136. })
  137. const saveForm = ref()
  138. const onSearch = () => {
  139. saveForm.value?.submit()
  140. }
  141. const onBtnReset = () => {
  142. saveForm.value?.reset()
  143. }
  144. const onSubmit = () => {
  145. state.pagination.page = 1
  146. getList()
  147. }
  148. const initUseAppList = async () => {
  149. try {
  150. const appKeys = Object.keys(appKey)
  151. const { data } = await sysApplicationPage({ page: 1, rows: 999 })
  152. const tempList = data.rows || []
  153. state.useProjectData = []
  154. const filter = tempList.filter((next: any) => {
  155. return appKeys.includes(next.appKey)
  156. })
  157. filter.forEach((item: any) => {
  158. state.useProjectData.push({
  159. ...item,
  160. label: item.appName,
  161. value: item.id
  162. })
  163. })
  164. } catch {}
  165. }
  166. const checkedRowKeysRef = ref<DataTableRowKey[]>([])
  167. const handleCheck = (rowKeys: DataTableRowKey[]) => {
  168. checkedRowKeysRef.value = rowKeys
  169. }
  170. const getList = async () => {
  171. try {
  172. state.loading = true
  173. const sourceType = state.searchForm.sourceType
  174. let userId = state.searchForm.userId
  175. let organizationRoleId = null
  176. if (sourceType && sourceType === 'ORG') {
  177. organizationRoleId = deepClone(userId)
  178. userId = null
  179. }
  180. const { data } = await musicSheetPageByApplication({
  181. ...state.pagination,
  182. ...state.searchForm,
  183. userId: (sourceType && sourceType === 'PERSON') ? state.searchForm.userId : null,
  184. organizationRoleId: (sourceType && sourceType === 'ORG') ? state.searchForm.userId : null,
  185. musicTagIds: state.searchForm.musicTagIds?.join(','),
  186. ...filterTimes(state.searchForm.times, ['startTime', 'endTime']),
  187. applicationId: state.applicationId
  188. })
  189. state.pagination.pageTotal = Number(data.total)
  190. state.dataList = data.rows || []
  191. } catch {}
  192. state.loading = false
  193. }
  194. const onChangeStatus = (row: any) => {
  195. const statusStr = row.status ? '停用' : '启用'
  196. dialog.warning({
  197. title: '提示',
  198. content: `是否${statusStr}?`,
  199. positiveText: '确定',
  200. negativeText: '取消',
  201. onPositiveClick: async () => {
  202. try {
  203. await musicSheetApplicationExtendStatus({
  204. ids: row.applicationExtendId,
  205. status: !row.status
  206. })
  207. getList()
  208. message.success(`${statusStr}成功`)
  209. } catch {}
  210. }
  211. })
  212. }
  213. const onBatchChangeStatus = (status: boolean) => {
  214. const length = checkedRowKeysRef.value.length
  215. if (length == 0) {
  216. message.warning('未选择数据')
  217. }
  218. const statusStr = !status ? '停用' : '启用'
  219. dialog.warning({
  220. title: '提示',
  221. content: `是否${statusStr}` + length + `条数据?`,
  222. positiveText: '确定',
  223. negativeText: '取消',
  224. onPositiveClick: async () => {
  225. try {
  226. await musicSheetApplicationExtendStatus({
  227. ids: checkedRowKeysRef.value.join(','),
  228. status: status
  229. })
  230. getList()
  231. message.success(`${statusStr}成功`)
  232. } catch {}
  233. }
  234. })
  235. }
  236. const getPaymentType = (paymentType: any) => {
  237. const paymentTypeName = []
  238. if (paymentType && paymentType.length > 0) {
  239. for (let i = 0; i < paymentType.length; i++) {
  240. const name = getMapValueByKey(
  241. paymentType[i],
  242. new Map(Object.entries(musicSheetPaymentType))
  243. )
  244. paymentTypeName.push(name)
  245. }
  246. }
  247. return paymentTypeName.join(',')
  248. }
  249. const updateUserIdData = async (sourceType: any) => {
  250. if (!state.searchForm.applicationId) {
  251. return
  252. }
  253. state.userIdData = []
  254. state.searchForm.userId = null
  255. if (sourceType && sourceType !== 'PLATFORM') {
  256. const { data } = await musicSheetApplicationOwnerList({
  257. page: 1,
  258. rows: 9999,
  259. sourceType: sourceType,
  260. applicationId: state.searchForm.applicationId
  261. })
  262. const temp = data.rows || []
  263. temp.forEach((next: any) => {
  264. state.userIdData.push({
  265. ...next,
  266. label: sourceType === 'PERSON' ? next.userName : next.organizationRole,
  267. value: sourceType === 'PERSON' ? next.userId : next.organizationRoleId
  268. })
  269. })
  270. }
  271. }
  272. const columns = (): any => {
  273. return [
  274. {
  275. type: 'selection'
  276. },
  277. {
  278. title: '曲目信息',
  279. key: 'id',
  280. render: (row: any) => (
  281. <>
  282. <NDescriptions labelPlacement="left" column={1}>
  283. <NDescriptionsItem label="曲目名称">
  284. <TheTooltip content={row.name} />{' '}
  285. </NDescriptionsItem>
  286. <NDescriptionsItem label="曲目编号"><TheTooltip content={row.id} />{' '}</NDescriptionsItem>
  287. </NDescriptions>
  288. </>
  289. )
  290. },
  291. {
  292. title: '封面图',
  293. key: 'musicCover',
  294. render(row: any): JSX.Element {
  295. return <NImage width={60} height={60} src={row.musicCover} />
  296. }
  297. },
  298. {
  299. title: '曲目信息',
  300. key: 'musicSheetCategoriesName',
  301. render: (row: any) => (
  302. <>
  303. <NDescriptions labelPlacement="left" column={1}>
  304. <NDescriptionsItem label="曲目来源">
  305. {getMapValueByKey(row.sourceType, new Map(Object.entries(musicSheetSourceType)))}
  306. </NDescriptionsItem>
  307. <NDescriptionsItem label="所属人">
  308. <TheTooltip content={getOwnerName(row.musicSheetExtend, row.sourceType)}/>
  309. </NDescriptionsItem>
  310. <NDescriptionsItem label="可用声部">
  311. <TheTooltip content={row.subjectNames}/>
  312. </NDescriptionsItem>
  313. </NDescriptions>
  314. </>
  315. )
  316. },
  317. {
  318. title: '同时渲染所选声轨',
  319. key: 'musicSheetType',
  320. render: (row: any) => {
  321. return (
  322. <div>
  323. {getMapValueByKey(row.musicSheetType, new Map(Object.entries(musicSheetType)))}
  324. </div>
  325. )
  326. }
  327. },
  328. {
  329. title: '伴奏类型',
  330. key: 'audioType',
  331. render: (row: any) => {
  332. return (
  333. <div>
  334. {getMapValueByKey(row.audioType, new Map(Object.entries(musicSheetAudioType)))}
  335. </div>
  336. )
  337. }
  338. },
  339. // {
  340. // title: '可用声部',
  341. // key: 'subjectNames',
  342. // render: (row: any) => {
  343. // return <TheTooltip content={row.subjectNames}/>
  344. // }
  345. // },
  346. {
  347. title: '曲目标签',
  348. key: 'musicTagNames'
  349. },
  350. {
  351. title: '可用途径',
  352. key: 'applicationAvailableType',
  353. render: (row: any) => {
  354. return (
  355. <div>
  356. {getMapValueByKey(
  357. row.applicationAvailableType,
  358. new Map(Object.entries(musicSheetAvailableType))
  359. )}
  360. </div>
  361. )
  362. }
  363. },
  364. {
  365. title: '是否置顶',
  366. key: 'topFlag',
  367. render: (row: any) => {
  368. return <div>{row.topFlag ? '是' : '否'}</div>
  369. }
  370. },
  371. {
  372. title: '是否精品',
  373. key: 'exquisiteFlag',
  374. render: (row: any) => {
  375. return <div>{row.topFlag ? '是' : '否'}</div>
  376. }
  377. },
  378. {
  379. title: '收费方式',
  380. key: 'paymentType',
  381. render: (row: any) => {
  382. return <div>{getPaymentType(row.paymentType?.split(','))}</div>
  383. }
  384. },
  385. {
  386. title: '曲目价格',
  387. key: 'musicPrice'
  388. },
  389. {
  390. title: '上传人',
  391. minWidth: '150px',
  392. key: 'composer',
  393. render(row: any) {
  394. return (
  395. <NDescriptions labelPlacement="left" column={1}>
  396. <NDescriptionsItem label="上传人">{row.createByName}</NDescriptionsItem>
  397. <NDescriptionsItem label="上传时间">{row.createTime}</NDescriptionsItem>
  398. </NDescriptions>
  399. )
  400. }
  401. },
  402. {
  403. title: '状态',
  404. key: 'status',
  405. render(row: any) {
  406. return (
  407. <NTag type={row.status ? 'primary' : 'default'}>{row.status ? '启用' : '停用'}</NTag>
  408. )
  409. }
  410. },
  411. {
  412. title: '操作',
  413. key: 'operation',
  414. fixed: 'right',
  415. render(row: any) {
  416. return (
  417. <NSpace>
  418. <NButton
  419. type="primary"
  420. size="small"
  421. text
  422. onClick={() => {
  423. state.musicPreview = true
  424. state.musicScore = row
  425. }}
  426. >
  427. 预览
  428. </NButton>
  429. <NButton
  430. type="primary"
  431. size="small"
  432. text
  433. v-auth="musicSheetApplicationExtend/status1751235210464198657"
  434. onClick={() => onChangeStatus(row)}
  435. >
  436. {row.status ? '停用' : '启用'}
  437. </NButton>
  438. <NButton
  439. type="primary"
  440. size="small"
  441. text
  442. v-auth="musicSheetApplicationExtend/update1751235573456044033"
  443. onClick={() => {
  444. state.showEditDialog = true
  445. state.updateRow = row
  446. }}
  447. >
  448. 修改
  449. </NButton>
  450. </NSpace>
  451. )
  452. }
  453. }
  454. ]
  455. }
  456. return () => {
  457. return (
  458. <div class="system-menu-container">
  459. <SaveForm
  460. ref={saveForm}
  461. model={state.searchForm}
  462. onSubmit={onSubmit}
  463. saveKey="music-sheet-klx"
  464. onSetModel={(val: any) => (state.searchForm = val)}
  465. >
  466. <NFormItem label="关键词" path="keyword">
  467. <NInput
  468. placeholder="请输入曲目名称/编号"
  469. v-model:value={state.searchForm.keyword}
  470. clearable
  471. />
  472. </NFormItem>
  473. <NFormItem label="曲目来源" path="sourceType">
  474. <NSelect
  475. placeholder="请选择曲目来源"
  476. v-model:value={state.searchForm.sourceType}
  477. options={getSelectDataFromObj(musicSheetSourceType)}
  478. onUpdateValue={async (value: any) => {
  479. state.userIdData = []
  480. state.searchForm.userId = null
  481. if (value && value !== 'PLATFORM') {
  482. await updateUserIdData(value)
  483. state.userIdDisable = !state.searchForm.applicationId
  484. } else {
  485. state.userIdDisable = true
  486. }
  487. }}
  488. clearable
  489. />
  490. </NFormItem>
  491. <NFormItem label="项目" path="applicationId">
  492. <NSelect
  493. placeholder="请选择项目"
  494. v-model:value={state.searchForm.applicationId}
  495. options={state.useProjectData}
  496. clearable
  497. onUpdateValue={async (value: any) => {
  498. state.searchForm.applicationId = value
  499. if (value) {
  500. await updateUserIdData(state.searchForm.sourceType)
  501. state.userIdDisable = !(
  502. state.searchForm.sourceType && state.searchForm.sourceType !== 'PLATFORM'
  503. )
  504. } else {
  505. state.searchForm.userId = null
  506. state.userIdDisable = true
  507. state.userIdData = []
  508. }
  509. }}
  510. />
  511. </NFormItem>
  512. <NFormItem label="所属人" path="userId">
  513. <NSelect
  514. filterable
  515. placeholder="请选择所属人"
  516. disabled={state.userIdDisable}
  517. v-model:value={state.searchForm.userId}
  518. options={state.userIdData}
  519. clearable
  520. ></NSelect>
  521. </NFormItem>
  522. <NFormItem label="曲目类型" path="subjectType">
  523. <NSelect
  524. placeholder="请选择曲目类型"
  525. v-model:value={state.searchForm.musicSheetType}
  526. options={getSelectDataFromObj(musicSheetType)}
  527. clearable
  528. />
  529. </NFormItem>
  530. <NFormItem label="伴奏类型" path="audioType">
  531. <NSelect
  532. placeholder="请选择伴奏类型"
  533. v-model:value={state.searchForm.audioType}
  534. options={getSelectDataFromObj(musicSheetAudioType)}
  535. clearable
  536. />
  537. </NFormItem>
  538. <NFormItem label="可用声部" path="subjectId">
  539. <NSelect
  540. placeholder="请选择可用声部"
  541. v-model:value={state.searchForm.subjectId}
  542. options={state.subjectList}
  543. clearable
  544. />
  545. </NFormItem>
  546. <NFormItem label="曲目标签" path="musicTagIds">
  547. <NSelect
  548. placeholder="请选择曲目标签"
  549. v-model:value={state.searchForm.musicTagIds}
  550. options={state.musicTagList}
  551. multiple
  552. maxTagCount={2}
  553. clearable
  554. />
  555. </NFormItem>
  556. {/*<NFormItem*/}
  557. {/* label="可用途径"*/}
  558. {/* path="availableType"*/}
  559. {/*>*/}
  560. {/* <NSelect*/}
  561. {/* placeholder="请选择可用途径"*/}
  562. {/* v-model:value={state.searchForm.availableType}*/}
  563. {/* options={getSelectDataFromObj(musicSheetAvailableType)}*/}
  564. {/* clearable*/}
  565. {/* >*/}
  566. {/* </NSelect>*/}
  567. {/*</NFormItem>*/}
  568. <NFormItem label="收费方式" path="paymentType">
  569. <NSelect
  570. placeholder="请选择收费方式"
  571. v-model:value={state.searchForm.paymentType}
  572. options={getSelectDataFromObj(musicSheetPaymentType)}
  573. clearable
  574. ></NSelect>
  575. </NFormItem>
  576. <NFormItem label="状态" path="status">
  577. <NSelect
  578. v-model:value={state.searchForm.status}
  579. placeholder="请选择状态"
  580. options={
  581. [
  582. {
  583. label: '启用',
  584. value: true
  585. },
  586. {
  587. label: '停用',
  588. value: false
  589. }
  590. ] as any
  591. }
  592. clearable
  593. />
  594. </NFormItem>
  595. <NFormItem label="上传时间" path="authorFrom">
  596. <NDatePicker
  597. v-model:value={state.searchForm.times}
  598. type="daterange"
  599. clearable
  600. value-format="yyyy.MM.dd"
  601. startPlaceholder="开始时间"
  602. endPlaceholder="结束时间"
  603. />
  604. </NFormItem>
  605. <NFormItem>
  606. <NSpace>
  607. <NButton type="primary" onClick={onSearch}>
  608. 搜索
  609. </NButton>
  610. <NButton type="default" onClick={onBtnReset}>
  611. 重置
  612. </NButton>
  613. </NSpace>
  614. </NFormItem>
  615. </SaveForm>
  616. <div class={['section-container']}>
  617. <NSpace style={{ paddingBottom: '12px' }}>
  618. <NButton
  619. type="primary"
  620. v-auth="musicSheetApplicationExtend/saveBatch1751234344277508097"
  621. onClick={() => {
  622. state.showAddDialog = true
  623. }}
  624. >
  625. 添加曲目
  626. </NButton>
  627. <NButton
  628. disabled={checkedRowKeysRef.value.length == 0}
  629. v-auth="musicSheetApplicationExtend/status1751235210464198657"
  630. onClick={() => {
  631. onBatchChangeStatus(false)
  632. }}
  633. >
  634. 批量停用
  635. </NButton>
  636. <NButton
  637. disabled={checkedRowKeysRef.value.length == 0}
  638. v-auth="musicSheetApplicationExtend/status1751235210464198657"
  639. onClick={() => {
  640. onBatchChangeStatus(true)
  641. }}
  642. >
  643. 批量启用
  644. </NButton>
  645. </NSpace>
  646. <NDataTable
  647. loading={state.loading}
  648. columns={columns()}
  649. data={state.dataList}
  650. rowKey={(row: any) => row.applicationExtendId}
  651. onUpdateCheckedRowKeys={handleCheck}
  652. scrollX={'2000'}
  653. ></NDataTable>
  654. <Pagination
  655. v-model:page={state.pagination.page}
  656. v-model:pageSize={state.pagination.rows}
  657. v-model:pageTotal={state.pagination.pageTotal}
  658. onList={getList}
  659. sync
  660. saveKey="music-sheet-klx"
  661. ></Pagination>
  662. </div>
  663. <NModal
  664. v-model:show={state.showAddDialog}
  665. preset="dialog"
  666. showIcon={false}
  667. title={'添加曲目'}
  668. style={{ width: '1300px' }}
  669. >
  670. <AddMusic
  671. onClose={() => (state.showAddDialog = false)}
  672. onGetList={onSubmit}
  673. subjectList={state.subjectList}
  674. appId={state.appId}
  675. musicSheetTagList={state.musicTagList}
  676. />
  677. </NModal>
  678. <NModal
  679. v-model:show={state.showEditDialog}
  680. preset="dialog"
  681. showIcon={false}
  682. title={'修改曲目'}
  683. style={{ width: '500px' }}
  684. >
  685. <UpdateMusic
  686. onClose={() => (state.showEditDialog = false)}
  687. onGetList={() => {
  688. state.pagination.page = 1
  689. getList()
  690. }}
  691. rowData={state.updateRow}
  692. appId={state.appId}
  693. musicSheetTagList={state.musicTagList}
  694. />
  695. </NModal>
  696. <NModal
  697. blockScroll={true}
  698. v-model:show={state.musicPreview}
  699. preset="dialog"
  700. showIcon={false}
  701. title={'曲目预览'}
  702. style={{ width: 'auto' }}
  703. >
  704. <MusicPreView item={state.musicScore} />
  705. </NModal>
  706. </div>
  707. )
  708. }
  709. }
  710. })