music-list.tsx 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620
  1. import SaveForm from '@/components/save-form'
  2. import Pagination from '@/components/pagination'
  3. import {DataTableRowKey, NButton, NDataTable, NFormItem, NIcon, NImage, NInput, NModal, NSelect, NSpace, NTag, useDialog, useMessage} from 'naive-ui'
  4. import {defineComponent, onMounted, reactive, ref, watch} from 'vue'
  5. import {musicSheetCategoriesQueryTree, musicSheetDetail, musicSheetPage, musicSheetRemove, musicSheetStatusList, musicTagPage} from '../../api'
  6. import MusicOperation from '../modal/music-operation'
  7. import {subjectPage} from '@/views/system-manage/api'
  8. import MusicPreView from '../modal/musicPreView'
  9. import {filterPointCategory} from '@/views/teaching-manage/unit-test'
  10. import UseProject from "@views/music-library/music-sheet/modal/use-project";
  11. import {getMapValueByKey} from "@/utils/filters";
  12. import {musicSheetSourceType, musicSheetType} from "@/utils/constant";
  13. import {getSelectDataFromObj} from "@/utils/objectUtil";
  14. import {sysApplicationPage} from "@views/menu-manage/api";
  15. export default defineComponent({
  16. name: 'music-list',
  17. props: ['searchId'],
  18. setup(props, {emit}) {
  19. const dialog = useDialog()
  20. const message = useMessage()
  21. const state = reactive({
  22. loading: false,
  23. pagination: {
  24. page: 1,
  25. rows: 10,
  26. pageTotal: 0
  27. },
  28. searchForm: {
  29. keyword: null,
  30. musicSheetType: null,
  31. subjectId: null, //声部ID
  32. sourceType: null, //来源类型/作者属性(PLATFORM: 平台; ORG: 机构; PERSON: 个人
  33. composer: null, //作曲人/音乐人
  34. userId: null, //所属人
  35. useAppId: null, //适用项目ID
  36. status: null, //曲目状态(0:停用,1:启用)
  37. appAuditFlag: null, //是否审核版本
  38. categoriesId: null, //是否审核版本
  39. },
  40. dataList: [] as any,
  41. subjectList: [] as any,
  42. tagList: [] as any,
  43. visiableMusic: false,
  44. musicOperation: 'add',
  45. musicData: {} as any,
  46. musicSheetCategories: [] as any,
  47. musicPreview: false,
  48. musicScore: null as any,
  49. showUseProject: false, // 适用项目
  50. useProjectData: [], // 适用项目行数据
  51. showUseProjectId: null as any, // 适用项目行数据
  52. detailReadonly: false // 新增、修改、详情是否可编辑
  53. })
  54. const columns = (): any => {
  55. return [
  56. {
  57. type: 'selection'
  58. },
  59. {
  60. title: '曲目编号',
  61. key: 'id'
  62. },
  63. // {
  64. // title (column: any) {
  65. // return <NImage width={60} height={60} src={column.titleImg}/>
  66. // },
  67. // key: 'id'
  68. // },
  69. {
  70. title: '曲目名称',
  71. key: 'name'
  72. },
  73. {
  74. title: '封面图',
  75. key: 'titleImg',
  76. render(row: any): JSX.Element {
  77. return <NImage width={60} height={60} src={row.musicCover}/>
  78. }
  79. },
  80. {
  81. title: '音乐人',
  82. key: 'composer'
  83. },
  84. {
  85. title: '曲目类型',
  86. key: 'musicSheetType',
  87. render(row: any) {
  88. return getMapValueByKey(row.musicSheetType, new Map(Object.entries(musicSheetType)));
  89. }
  90. },
  91. {
  92. title: '作者属性',
  93. key: 'sourceType',
  94. render(row: any) {
  95. return getMapValueByKey(row.sourceType, new Map(Object.entries(musicSheetSourceType)));
  96. }
  97. },
  98. {
  99. title: '所属人',
  100. key: 'composer'
  101. },
  102. {
  103. title: '上传人',
  104. key: 'createBy'
  105. },
  106. {
  107. title: '上传时间',
  108. key: 'createTime'
  109. },
  110. {
  111. title: '审核版本',
  112. key: 'userName'
  113. },
  114. {
  115. title: '适用项目',
  116. key: 'projectName',
  117. render(row: any) {
  118. return (
  119. <NSpace>
  120. <NButton type="primary"
  121. size="small"
  122. text
  123. onClick={() => {
  124. state.showUseProject = true
  125. state.showUseProjectId = row.id
  126. }}
  127. >
  128. {row.musicSheetExtend && row.musicSheetExtend.useApplicationNames ? row.musicSheetExtend.useApplicationNames : ""}
  129. <NIcon size={15} style="padding-left: 9px">
  130. <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32">
  131. <path d="M2 26h28v2H2z" fill="currentColor"></path>
  132. <path d="M25.4 9c.8-.8.8-2 0-2.8l-3.6-3.6c-.8-.8-2-.8-2.8 0l-15 15V24h6.4l15-15zm-5-5L24 7.6l-3 3L17.4 7l3-3zM6 22v-3.6l10-10l3.6 3.6l-10 10H6z" fill="currentColor"></path>
  133. </svg>
  134. </NIcon>
  135. </NButton>
  136. </NSpace>
  137. )
  138. }
  139. },
  140. {
  141. title: '状态',
  142. key: 'status',
  143. render(row: any) {
  144. return (
  145. <NTag type={row.status ? 'primary' : 'default'}>{row.status ? '启用' : '停用'}</NTag>
  146. )
  147. }
  148. },
  149. {
  150. title: '操作',
  151. key: 'operation',
  152. fixed: 'right',
  153. render(row: any) {
  154. return (
  155. <NSpace>
  156. <NButton
  157. type="primary"
  158. size="small"
  159. text
  160. onClick={() => {
  161. state.musicPreview = true
  162. state.musicScore = row
  163. }}
  164. >
  165. 预览
  166. </NButton>
  167. <NButton
  168. type="primary"
  169. size="small"
  170. text
  171. //v-auth="musicSheet/update1602302618558099458"
  172. onClick={() => {
  173. state.visiableMusic = true
  174. state.musicOperation = 'preview'
  175. state.musicData = row
  176. state.detailReadonly = true
  177. }}
  178. >
  179. 查看
  180. </NButton>
  181. <NButton
  182. type="primary"
  183. size="small"
  184. text
  185. //v-auth="musicSheet/update1602302618558099458"
  186. onClick={() => {
  187. state.visiableMusic = true
  188. state.musicOperation = 'edit'
  189. state.musicData = row
  190. state.detailReadonly = true
  191. }}
  192. >
  193. 修改
  194. </NButton>
  195. <NButton
  196. type="primary"
  197. size="small"
  198. text
  199. //v-auth="musicSheet/status1612431726029942786"
  200. onClick={() => onChangeStatus(row)}
  201. >
  202. {row.status ? '停用' : '启用'}
  203. </NButton>
  204. <NButton
  205. type="primary"
  206. size="small"
  207. text
  208. onClick={() => {
  209. }}
  210. >
  211. 生成图片
  212. </NButton>
  213. <NButton
  214. type="primary"
  215. size="small"
  216. text
  217. onClick={() => onRmove(row)}
  218. //v-auth="musicSheet/remove1602302689404088321"
  219. >
  220. 删除
  221. </NButton>
  222. {/* <NButton
  223. type="primary"
  224. size="small"
  225. text
  226. onClick={() => onRmove(row)}
  227. v-auth="musicSheet/remove1599694768375701505"
  228. >
  229. {row.topFlag ? '取消置顶' : '置顶'}
  230. </NButton> */}
  231. </NSpace>
  232. )
  233. }
  234. }
  235. ]
  236. }
  237. const checkedRowKeysRef = ref<DataTableRowKey[]>([])
  238. const handleCheck = (rowKeys: DataTableRowKey[]) => {
  239. checkedRowKeysRef.value = rowKeys
  240. }
  241. const onChangeStatus = (row: any) => {
  242. const statusStr = row.status ? '停用' : '启用'
  243. dialog.warning({
  244. title: '警告',
  245. content: `是否${statusStr}?`,
  246. positiveText: '确定',
  247. negativeText: '取消',
  248. onPositiveClick: async () => {
  249. try {
  250. await musicSheetStatusList({
  251. ids: new Array(row.id),
  252. status: !row.status
  253. })
  254. getList()
  255. message.success(`${statusStr}成功`)
  256. } catch {
  257. }
  258. }
  259. })
  260. }
  261. const onBatchChangeStatus = (status: boolean) => {
  262. const length = checkedRowKeysRef.value.length;
  263. if (length == 0) {
  264. message.warning("未选择数据")
  265. }
  266. const statusStr = !status ? '停用' : '启用'
  267. dialog.warning({
  268. title: '警告',
  269. content: `是否${statusStr}` + length + `条数据?`,
  270. positiveText: '确定',
  271. negativeText: '取消',
  272. onPositiveClick: async () => {
  273. try {
  274. await musicSheetStatusList({
  275. ids: checkedRowKeysRef.value,
  276. status: status
  277. })
  278. getList()
  279. message.success(`${statusStr}成功`)
  280. } catch {
  281. }
  282. }
  283. })
  284. }
  285. const onRmove = (row: any): void => {
  286. dialog.warning({
  287. title: '警告',
  288. content: `删除"${row.name}",是否继续?`,
  289. positiveText: '确定',
  290. negativeText: '取消',
  291. onPositiveClick: async () => {
  292. try {
  293. await musicSheetRemove({id: row.id})
  294. getList()
  295. message.success('删除成功')
  296. } catch {
  297. }
  298. }
  299. })
  300. }
  301. const getList = async () => {
  302. try {
  303. state.loading = true
  304. const {data} = await musicSheetPage({...state.pagination, ...state.searchForm})
  305. state.pagination.pageTotal = Number(data.total)
  306. state.dataList = data.rows || []
  307. } catch {
  308. }
  309. state.loading = false
  310. }
  311. // 获取标签
  312. const getTagList = async () => {
  313. try {
  314. const {data} = await musicTagPage({page: 1, rows: 999})
  315. const tempList = data.rows || []
  316. tempList.forEach((item: any) => {
  317. item.label = item.name
  318. item.value = item.id
  319. })
  320. state.tagList = tempList
  321. } catch {
  322. }
  323. }
  324. // 获取分类
  325. const getMusicSheetCategorieList = async () => {
  326. try {
  327. const {data} = await musicSheetCategoriesQueryTree({enable: true})
  328. state.musicSheetCategories = filterPointCategory(data, 'musicSheetCategoriesList')
  329. } catch (e) {
  330. }
  331. }
  332. // 获取声部
  333. const initSubjectList = async () => {
  334. try {
  335. const {data} = await subjectPage({page: 1, rows: 999})
  336. const tempList = data.rows || []
  337. tempList.forEach((item: any) => {
  338. item.label = item.name
  339. item.value = item.id + ''
  340. })
  341. state.subjectList = tempList
  342. } catch {
  343. }
  344. }
  345. // app列表
  346. const initUseAppList = async () => {
  347. try {
  348. const {data} = await sysApplicationPage({page: 1, rows: 999})
  349. const tempList = data.rows || []
  350. tempList.forEach((item: any) => {
  351. item.label = item.appName
  352. item.value = item.id
  353. })
  354. state.useProjectData = tempList
  355. } catch {
  356. }
  357. }
  358. const saveForm = ref()
  359. const onSubmit = () => {
  360. state.pagination.page = 1
  361. getList()
  362. }
  363. watch(
  364. () => props.searchId,
  365. (val) => {
  366. console.log(val, 'searchId')
  367. }
  368. )
  369. const onSearch = () => {
  370. saveForm.value?.submit()
  371. }
  372. const onBtnReset = () => {
  373. saveForm.value?.reset()
  374. }
  375. onMounted(() => {
  376. // getTagList()
  377. if (props.searchId) {
  378. state.searchForm.categoriesId = props.searchId || null
  379. }
  380. initSubjectList()
  381. initUseAppList()
  382. getList()
  383. getMusicSheetCategorieList()
  384. })
  385. return () => (
  386. <div class="system-menu-container">
  387. <SaveForm
  388. ref={saveForm}
  389. model={state.searchForm}
  390. onSubmit={onSubmit}
  391. saveKey="music-list"
  392. onSetModel={(val: any) => (state.searchForm = val)}
  393. >
  394. <NFormItem label="关键词" path="keyword">
  395. <NInput
  396. placeholder="曲目编号/名称"
  397. v-model:value={state.searchForm.keyword}
  398. clearable
  399. />
  400. </NFormItem>
  401. <NFormItem label="曲目类型" path="musicSheetType">
  402. <NSelect
  403. placeholder="请选择曲目类型"
  404. v-model:value={state.searchForm.musicSheetType}
  405. options={getSelectDataFromObj(musicSheetType)}
  406. clearable
  407. />
  408. </NFormItem>
  409. <NFormItem label="声部" path="musicSubject">
  410. <NSelect
  411. placeholder="请选择声部"
  412. v-model:value={state.searchForm.subjectId}
  413. options={state.subjectList}
  414. clearable
  415. />
  416. </NFormItem>
  417. <NFormItem label="作者属性" path="authorFrom">
  418. <NSelect
  419. placeholder="请选择作者属性"
  420. v-model:value={state.searchForm.sourceType}
  421. options={getSelectDataFromObj(musicSheetSourceType)}
  422. clearable
  423. />
  424. </NFormItem>
  425. <NFormItem label="音乐人" path="author">
  426. <NInput
  427. placeholder="请选择音乐人"
  428. v-model:value={state.searchForm.composer}
  429. clearable
  430. />
  431. </NFormItem>
  432. <NFormItem label="所属人" path="author">
  433. <NInput
  434. placeholder="请选择所属人"
  435. v-model:value={state.searchForm.userId}
  436. clearable
  437. />
  438. </NFormItem>
  439. <NFormItem label="适用项目" path="app">
  440. <NSelect
  441. placeholder="请选择适用项目"
  442. v-model:value={state.searchForm.useAppId}
  443. options={state.useProjectData}
  444. clearable
  445. />
  446. </NFormItem>
  447. <NFormItem label="状态" path="status">
  448. <NSelect
  449. v-model={[state.searchForm.status, 'value']}
  450. placeholder="请选择状态"
  451. clearable
  452. options={
  453. [
  454. {
  455. label: '启用',
  456. value: true
  457. },
  458. {
  459. label: '停用',
  460. value: false
  461. }
  462. ] as any
  463. }
  464. />
  465. </NFormItem>
  466. <NFormItem label="审核版本" path="appAuditFlag">
  467. <NSelect
  468. v-model={[state.searchForm.appAuditFlag, 'value']}
  469. placeholder="请选择审核版本"
  470. clearable
  471. options={
  472. [
  473. {
  474. label: '是',
  475. value: 1
  476. },
  477. {
  478. label: '否',
  479. value: 0
  480. }
  481. ] as any
  482. }
  483. />
  484. </NFormItem>
  485. <NFormItem>
  486. <NSpace>
  487. <NButton type="primary" onClick={onSearch}>
  488. 搜索
  489. </NButton>
  490. <NButton type="default" onClick={onBtnReset}>
  491. 重置
  492. </NButton>
  493. </NSpace>
  494. </NFormItem>
  495. </SaveForm>
  496. <div class={['section-container']}>
  497. <NSpace style={{paddingBottom: '12px'}}>
  498. <NButton
  499. type="primary"
  500. //v-auth="musicSheet/save1602302550719426561"
  501. onClick={() => {
  502. state.visiableMusic = true
  503. state.musicOperation = 'add'
  504. state.musicData = {}
  505. state.detailReadonly = true
  506. }}
  507. >
  508. 新增曲目
  509. </NButton>
  510. <NButton
  511. disabled={checkedRowKeysRef.value.length == 0}
  512. //v-auth="musicSheet/save1602302550719426561"
  513. onClick={() => {
  514. // state.musicOperation = 'unable'
  515. // state.musicData = {}
  516. onBatchChangeStatus(false)
  517. }}
  518. >
  519. 批量禁用
  520. </NButton>
  521. <NButton
  522. disabled={checkedRowKeysRef.value.length == 0}
  523. //v-auth="musicSheet/save1602302550719426561"
  524. onClick={() => {
  525. onBatchChangeStatus(true)
  526. // state.musicOperation = 'enable'
  527. // state.musicData = {}
  528. }}
  529. >
  530. 批量启用
  531. </NButton>
  532. </NSpace>
  533. <NDataTable
  534. loading={state.loading}
  535. columns={columns()}
  536. data={state.dataList}
  537. rowKey={(row: any) => row.id}
  538. onUpdateCheckedRowKeys={handleCheck}
  539. ></NDataTable>
  540. <Pagination
  541. v-model:page={state.pagination.page}
  542. v-model:pageSize={state.pagination.rows}
  543. v-model:pageTotal={state.pagination.pageTotal}
  544. onList={getList}
  545. sync
  546. saveKey="music-list"
  547. ></Pagination>
  548. </div>
  549. <NModal
  550. v-model:show={state.visiableMusic}
  551. preset="dialog"
  552. showIcon={false}
  553. maskClosable={false}
  554. title={() => {
  555. if (state.musicOperation === 'add') {
  556. return '添加曲目';
  557. } else if (state.musicOperation === 'preview') {
  558. return '曲目详情';
  559. }
  560. return '修改曲目';
  561. }}
  562. style={{width: '980px'}}
  563. >
  564. <MusicOperation
  565. type={state.musicOperation}
  566. data={state.musicData}
  567. subjectList={state.subjectList}
  568. musicSheetCategories={state.musicSheetCategories}
  569. // tagList={state.tagList}
  570. onClose={() => (state.visiableMusic = false)}
  571. onGetList={getList}
  572. />
  573. </NModal>
  574. <NModal
  575. blockScroll={true}
  576. v-model:show={state.musicPreview}
  577. preset="dialog"
  578. showIcon={false}
  579. title={'曲目预览'}
  580. style={{width: 'auto'}}
  581. >
  582. <MusicPreView item={state.musicScore}/>
  583. </NModal>
  584. <NModal
  585. blockScroll={true}
  586. v-model:show={state.showUseProject}
  587. preset="dialog"
  588. showIcon={false}
  589. title={'适用项目'}
  590. style={{width: '500px'}}
  591. >
  592. <UseProject
  593. id={state.showUseProjectId}
  594. useProject={state.useProjectData}
  595. onClose={() => (state.showUseProject = false)}
  596. onGetList={getList}
  597. />
  598. </NModal>
  599. </div>
  600. )
  601. }
  602. })