addMusic.tsx 35 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069
  1. import { defineComponent, h, onMounted, reactive, ref } from 'vue'
  2. import SaveForm from '@components/save-form'
  3. import {
  4. DataTableColumns,
  5. DataTableRowKey,
  6. NButton,
  7. NCascader,
  8. NDataTable,
  9. NFormItem,
  10. NIcon,
  11. NImage,
  12. NInput,
  13. NInputNumber,
  14. NSelect,
  15. NSpace,
  16. NStep,
  17. NSteps,
  18. useDialog,
  19. useMessage
  20. } from 'naive-ui'
  21. import Pagination from '@components/pagination'
  22. import { getMapValueByKey, getSelectDataFromObj } from '@/utils/objectUtil'
  23. import {
  24. appKey,
  25. musicSheetAvailableType,
  26. musicSheetSourceType,
  27. musicSheetType,
  28. scoreType
  29. } from '@/utils/constant'
  30. import {
  31. musicSheetApplicationExtendCategoryList,
  32. musicSheetApplicationExtendSaveBatch,
  33. musicSheetApplicationOwnerList,
  34. musicSheetPage
  35. } from '@views/music-library/api'
  36. import deepClone from '@/utils/deep.clone'
  37. import { getOwnerName } from '@views/music-library/musicUtil'
  38. import TheTooltip from '@components/TheTooltip'
  39. import { sysApplicationPage } from '@views/menu-manage/api'
  40. export default defineComponent({
  41. name: 'gyt-addMusic',
  42. props: {
  43. appId: {
  44. type: String,
  45. required: true
  46. },
  47. subjectList: {
  48. type: Array,
  49. default: () => []
  50. },
  51. musicSheetCategories: {
  52. type: Array,
  53. default: () => []
  54. }
  55. },
  56. emits: ['close', 'getList'],
  57. setup(props, { slots, attrs, emit }) {
  58. const dialogs = useDialog()
  59. const message = useMessage()
  60. const state = reactive({
  61. loading: false,
  62. pagination: {
  63. page: 1,
  64. rows: 5,
  65. pageTotal: 0
  66. },
  67. stepPagination: {
  68. page: 1,
  69. rows: 5,
  70. pageTotal: 0
  71. },
  72. searchForm: {
  73. keyword: null,
  74. // musicSheetType: null,
  75. subjectId: null,
  76. sourceType: null,
  77. composer: null,
  78. userId: null,
  79. applicationId: null
  80. },
  81. subjectList: [] as any,
  82. showAdd: false,
  83. currentStep: 1,
  84. dataList: [],
  85. selectRowData: [] as any, // 选择的数据列表
  86. musicSheetCategories: [] as any,
  87. startSortNum: null as any, // 排序起始值
  88. // projectMusicCategoryId: null as any, // 曲目分类ID
  89. isConvertibleScore: null as any, //是否支持转简谱
  90. status: false, // 是否启用
  91. scoreType: null as any, //默认谱面
  92. useProjectData: [] as any, // 适用项目行数据
  93. userIdDisable: true,
  94. userIdData: [] as any,
  95. globalAvailableType: null as any
  96. })
  97. onMounted(async () => {
  98. state.searchForm.keyword = null
  99. // state.searchForm.musicSheetType = null
  100. state.searchForm.subjectId = null
  101. state.searchForm.sourceType = null
  102. state.searchForm.composer = null
  103. state.searchForm.userId = null
  104. state.searchForm.applicationId = null
  105. state.loading = true
  106. state.subjectList = props.subjectList
  107. // state.musicSheetCategories = props.musicSheetCategories
  108. //加载曲目分类列表
  109. try {
  110. const { data } = await musicSheetApplicationExtendCategoryList({
  111. applicationIds: props.appId,
  112. enable: true
  113. })
  114. if (data && data.length > 0) {
  115. state.musicSheetCategories = data[0].musicSheetCategories
  116. }
  117. } catch {}
  118. await initUseAppList()
  119. await getList()
  120. })
  121. const initUseAppList = async () => {
  122. try {
  123. const appKeys = Object.keys(appKey)
  124. const { data } = await sysApplicationPage({ page: 1, rows: 999 })
  125. const tempList = data.rows || []
  126. state.useProjectData = []
  127. const filter = tempList.filter((next: any) => {
  128. return appKeys.includes(next.appKey)
  129. })
  130. filter.forEach((item: any) => {
  131. state.useProjectData.push({
  132. ...item,
  133. label: item.appName,
  134. value: item.id
  135. })
  136. })
  137. } catch {}
  138. }
  139. const getList = async () => {
  140. try {
  141. state.loading = true
  142. const search = {
  143. ...state.searchForm,
  144. userId:
  145. state.searchForm.sourceType && state.searchForm.sourceType == 'PERSON'
  146. ? state.searchForm.userId
  147. : null,
  148. organizationRoleId:
  149. state.searchForm.sourceType && state.searchForm.sourceType == 'ORG'
  150. ? state.searchForm.userId
  151. : null
  152. }
  153. const { data } = await musicSheetPage({
  154. ...state.pagination,
  155. ...search,
  156. addAppId: props.appId
  157. })
  158. state.pagination.pageTotal = Number(data.total)
  159. state.dataList = data.rows || []
  160. } catch {}
  161. state.loading = false
  162. }
  163. const saveForm = ref()
  164. const onSearch = () => {
  165. checkedRowKeysRef.value = []
  166. saveForm.value?.submit()
  167. }
  168. const onBtnReset = () => {
  169. saveForm.value?.reset()
  170. }
  171. const onSubmit = () => {
  172. state.pagination.page = 1
  173. getList()
  174. }
  175. const updateUserIdData = async (sourceType: any) => {
  176. if (!state.searchForm.applicationId) {
  177. return
  178. }
  179. state.userIdData = []
  180. state.searchForm.userId = null
  181. if (sourceType && sourceType !== 'PLATFORM') {
  182. const { data } = await musicSheetApplicationOwnerList({
  183. page: 1,
  184. rows: 9999,
  185. sourceType: sourceType,
  186. applicationId: state.searchForm.applicationId
  187. })
  188. const temp = data.rows || []
  189. temp.forEach((next: any) => {
  190. state.userIdData.push({
  191. ...next,
  192. label: sourceType === 'PERSON' ? next.userName : next.organizationRole,
  193. value: sourceType === 'PERSON' ? next.userId : next.organizationRoleId
  194. })
  195. })
  196. }
  197. }
  198. const onSave = async () => {
  199. if (state.selectRowData.length == 0) {
  200. message.error('未选择曲目')
  201. return
  202. }
  203. const params = [] as any[]
  204. for (let i = 0; i < state.selectRowData.length; i++) {
  205. const item = state.selectRowData[i]
  206. if (!item.availableType) {
  207. message.error('可用途径不能为空')
  208. return
  209. }
  210. // if (!item.projectMusicCategoryId) {
  211. // message.error('曲目分类不能为空')
  212. // return
  213. // }
  214. if (item.scoreType == null) {
  215. message.error('默认谱面不能为空')
  216. return
  217. }
  218. if (item.isConvertibleScore == null) {
  219. message.error('是否支持转谱不能为空')
  220. return
  221. }
  222. if (item.status == null) {
  223. message.error('是否启用不能为空')
  224. return
  225. }
  226. params.push({
  227. ...item,
  228. musicSheetId: item.id,
  229. // musicSheetCategoryId: item.projectMusicCategoryId,
  230. availableType: item.availableType,
  231. applicationId: props.appId,
  232. id: null
  233. })
  234. }
  235. const res = (await musicSheetApplicationExtendSaveBatch(params)) as any
  236. if (res && res.code == '200') {
  237. message.success(`添加成功`)
  238. emit('getList')
  239. emit('close')
  240. }
  241. }
  242. const columnsField = [
  243. {
  244. type: 'selection'
  245. },
  246. {
  247. title: '曲目编号',
  248. key: 'id'
  249. },
  250. {
  251. title: '封面图',
  252. key: 'titleImg',
  253. render(row: any) {
  254. return <NImage width={40} height={40} src={row.musicCover} />
  255. }
  256. },
  257. {
  258. title: '可用声部',
  259. key: 'subjectNames',
  260. render: (row: any) => {
  261. return <TheTooltip content={row.subjectNames} />
  262. }
  263. },
  264. {
  265. title: '曲目名称',
  266. key: 'name'
  267. },
  268. {
  269. title: '音乐人',
  270. key: 'composer'
  271. },
  272. {
  273. title: '曲目分类',
  274. key: 'musicCategoryName'
  275. },
  276. // {
  277. // title: '谱面渲染',
  278. // key: 'musicSheetType',
  279. // render: (row: any) => {
  280. // return (
  281. // <div>
  282. // {getMapValueByKey(row.musicSheetType, new Map(Object.entries(musicSheetType)))}
  283. // </div>
  284. // )
  285. // }
  286. // },
  287. {
  288. title: '曲目来源',
  289. key: 'sourceType',
  290. render(row: any) {
  291. return getMapValueByKey(row.sourceType, new Map(Object.entries(musicSheetSourceType)))
  292. }
  293. },
  294. {
  295. title: '所属人',
  296. key: 'userName',
  297. render: (row: any) => {
  298. return <TheTooltip content={getOwnerName(row.musicSheetExtend, row.sourceType)} />
  299. }
  300. }
  301. ]
  302. const columns = (): any => {
  303. return columnsField
  304. }
  305. const stepColumns = (): DataTableColumns => {
  306. const field = deepClone(columnsField)
  307. field.splice(0, 1)
  308. field.push({
  309. title(column: any) {
  310. return (
  311. <NSpace>
  312. 可用途径
  313. <NButton
  314. type="primary"
  315. size="small"
  316. text
  317. onClick={() => {
  318. dialogs.create({
  319. title: '请选择可用途径',
  320. showIcon: false,
  321. content: () => {
  322. return h(
  323. 'div',
  324. {
  325. class: 'flex flex-col justify-center items-center text-14px'
  326. },
  327. [
  328. // icon
  329. h(NSelect, {
  330. onUpdateValue(v) {
  331. state.globalAvailableType = v
  332. },
  333. clearable: true,
  334. options: [
  335. {
  336. label: '学校',
  337. value: 'ORG'
  338. },
  339. {
  340. label: '平台',
  341. value: 'PLATFORM'
  342. }
  343. ]
  344. })
  345. ]
  346. )
  347. },
  348. positiveText: '确定',
  349. negativeText: '取消',
  350. onPositiveClick: () => {
  351. for (let i = 0; i < state.selectRowData.length; i++) {
  352. const item = state.selectRowData[i]
  353. item.availableType = state.globalAvailableType
  354. }
  355. }
  356. })
  357. }}
  358. >
  359. <NIcon size={15} style="padding-left: 5px;margin-top:4px">
  360. <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32">
  361. <path d="M2 26h28v2H2z" fill="currentColor"></path>
  362. <path
  363. 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"
  364. fill="currentColor"
  365. ></path>
  366. </svg>
  367. </NIcon>
  368. </NButton>
  369. </NSpace>
  370. )
  371. },
  372. key: 'availableType',
  373. render: (row: any) => {
  374. return (
  375. <NSelect
  376. placeholder="请选择可用途径"
  377. value={row.availableType}
  378. options={[
  379. {
  380. label: '学校',
  381. value: 'ORG'
  382. },
  383. {
  384. label: '平台',
  385. value: 'PLATFORM'
  386. }
  387. ]}
  388. onUpdateValue={(value) => {
  389. row['availableType'] = value
  390. }}
  391. clearable
  392. />
  393. )
  394. }
  395. })
  396. // field.push({
  397. // title(column: any) {
  398. // return (
  399. // <NSpace>
  400. // 曲目分类
  401. // <NButton
  402. // type="primary"
  403. // size="small"
  404. // text
  405. // onClick={() => {
  406. // dialogs.create({
  407. // title: '请选择曲目分类',
  408. // showIcon: false,
  409. // content: () => {
  410. // return h(
  411. // 'div',
  412. // {
  413. // class: 'flex flex-col justify-center items-center text-14px'
  414. // },
  415. // [
  416. // // icon
  417. // h(NCascader, {
  418. // onUpdateValue(v) {
  419. // state.projectMusicCategoryId = v
  420. // },
  421. // valueField: 'id',
  422. // labelField: 'name',
  423. // childrenField: 'children',
  424. // placeholderField: '请选择曲目分类',
  425. // filterable: true,
  426. // options: state.musicSheetCategories
  427. // })
  428. // ]
  429. // )
  430. // },
  431. // positiveText: '确定',
  432. // negativeText: '取消',
  433. // onPositiveClick: () => {
  434. // for (let i = 0; i < state.selectRowData.length; i++) {
  435. // const item = state.selectRowData[i]
  436. // item.projectMusicCategoryId = state.projectMusicCategoryId
  437. // }
  438. // }
  439. // })
  440. // }}
  441. // >
  442. // <NIcon size={15} style="padding-left: 5px;margin-top:4px">
  443. // <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32">
  444. // <path d="M2 26h28v2H2z" fill="currentColor"></path>
  445. // <path
  446. // 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"
  447. // fill="currentColor"
  448. // ></path>
  449. // </svg>
  450. // </NIcon>
  451. // </NButton>
  452. // </NSpace>
  453. // )
  454. // },
  455. // key: 'projectMusicCategoryId',
  456. // width: 200,
  457. // render: (row: any) => {
  458. // // })
  459. // return (
  460. // <NCascader
  461. // valueField="id"
  462. // labelField="name"
  463. // children-field="children"
  464. // placeholder="请选择曲目分类"
  465. // value={row.projectMusicCategoryId}
  466. // options={state.musicSheetCategories}
  467. // onUpdateValue={(value: any) => {
  468. // row.projectMusicCategoryId = value
  469. // }}
  470. // filterable
  471. // clearable
  472. // />
  473. // )
  474. // }
  475. // })
  476. field.push({
  477. title(column: any) {
  478. return (
  479. <NSpace>
  480. 默认谱面
  481. <NButton
  482. type="primary"
  483. size="small"
  484. text
  485. onClick={() => {
  486. dialogs.create({
  487. title: '请选择默认谱面',
  488. showIcon: false,
  489. content: () => {
  490. return h(
  491. 'div',
  492. {
  493. class: 'flex flex-col justify-center items-center text-14px'
  494. },
  495. [
  496. // icon
  497. h(NSelect, {
  498. onUpdateValue(v) {
  499. state.scoreType = v
  500. },
  501. options: getSelectDataFromObj(scoreType)
  502. })
  503. ]
  504. )
  505. },
  506. positiveText: '确定',
  507. negativeText: '取消',
  508. onPositiveClick: () => {
  509. for (let i = 0; i < state.selectRowData.length; i++) {
  510. const item = state.selectRowData[i]
  511. item.scoreType = state.scoreType
  512. }
  513. }
  514. })
  515. }}
  516. >
  517. <NIcon size={15} style="padding-left: 5px;margin-top:4px">
  518. <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32">
  519. <path d="M2 26h28v2H2z" fill="currentColor"></path>
  520. <path
  521. 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"
  522. fill="currentColor"
  523. ></path>
  524. </svg>
  525. </NIcon>
  526. </NButton>
  527. </NSpace>
  528. )
  529. },
  530. key: 'scoreType',
  531. width: 200,
  532. render: (row: any) => {
  533. // })
  534. return (
  535. <NSelect
  536. placeholder="请选择默认谱面"
  537. value={row.scoreType}
  538. options={getSelectDataFromObj(scoreType)}
  539. onUpdateValue={(value: any) => {
  540. row.scoreType = value
  541. }}
  542. clearable
  543. />
  544. )
  545. }
  546. })
  547. field.push({
  548. title(column: any) {
  549. return (
  550. <NSpace>
  551. 是否支持转谱
  552. <NButton
  553. type="primary"
  554. size="small"
  555. text
  556. onClick={() => {
  557. dialogs.create({
  558. title: '是否支持转谱',
  559. showIcon: false,
  560. content: () => {
  561. return h(
  562. 'div',
  563. {
  564. class: 'flex flex-col justify-center items-center text-14px'
  565. },
  566. [
  567. // icon
  568. h(NSelect, {
  569. onUpdateValue(v) {
  570. state.isConvertibleScore = v
  571. },
  572. options: [
  573. {
  574. label: '是',
  575. value: true
  576. },
  577. {
  578. label: '否',
  579. value: false
  580. }
  581. ] as any
  582. })
  583. ]
  584. )
  585. },
  586. positiveText: '确定',
  587. negativeText: '取消',
  588. onPositiveClick: () => {
  589. for (let i = 0; i < state.selectRowData.length; i++) {
  590. const item = state.selectRowData[i]
  591. item.isConvertibleScore = state.isConvertibleScore
  592. }
  593. }
  594. })
  595. }}
  596. >
  597. <NIcon size={15} style="padding-left: 5px;margin-top:4px">
  598. <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32">
  599. <path d="M2 26h28v2H2z" fill="currentColor"></path>
  600. <path
  601. 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"
  602. fill="currentColor"
  603. ></path>
  604. </svg>
  605. </NIcon>
  606. </NButton>
  607. </NSpace>
  608. )
  609. },
  610. key: 'isConvertibleScore',
  611. width: 200,
  612. render: (row: any) => {
  613. // })
  614. return (
  615. <NSelect
  616. value={row.isConvertibleScore}
  617. options={[
  618. {
  619. label: '是',
  620. value: true
  621. },
  622. {
  623. label: '否',
  624. value: false
  625. } as any
  626. ]}
  627. onUpdateValue={(value: any) => {
  628. row.isConvertibleScore = value
  629. }}
  630. filterable
  631. clearable
  632. />
  633. )
  634. }
  635. })
  636. field.push({
  637. title(column: any) {
  638. return (
  639. <NSpace>
  640. 是否启用
  641. <NButton
  642. type="primary"
  643. size="small"
  644. text
  645. onClick={() => {
  646. dialogs.create({
  647. title: '是否启用',
  648. showIcon: false,
  649. content: () => {
  650. return h(
  651. 'div',
  652. {
  653. class: 'flex flex-col justify-center items-center text-14px'
  654. },
  655. [
  656. // icon
  657. h(NSelect, {
  658. onUpdateValue(v) {
  659. state.status = v
  660. },
  661. options: [
  662. {
  663. label: '是',
  664. value: true
  665. },
  666. {
  667. label: '否',
  668. value: false
  669. }
  670. ] as any
  671. })
  672. ]
  673. )
  674. },
  675. positiveText: '确定',
  676. negativeText: '取消',
  677. onPositiveClick: () => {
  678. for (let i = 0; i < state.selectRowData.length; i++) {
  679. const item = state.selectRowData[i]
  680. item.status = state.status
  681. }
  682. }
  683. })
  684. }}
  685. >
  686. <NIcon size={15} style="padding-left: 5px;margin-top:4px">
  687. <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32">
  688. <path d="M2 26h28v2H2z" fill="currentColor"></path>
  689. <path
  690. 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"
  691. fill="currentColor"
  692. ></path>
  693. </svg>
  694. </NIcon>
  695. </NButton>
  696. </NSpace>
  697. )
  698. },
  699. key: 'status',
  700. width: 200,
  701. render: (row: any) => {
  702. // })
  703. return (
  704. <NSelect
  705. value={row.status}
  706. options={[
  707. {
  708. label: '是',
  709. value: true
  710. },
  711. {
  712. label: '否',
  713. value: false
  714. } as any
  715. ]}
  716. onUpdateValue={(value: any) => {
  717. row.status = value
  718. }}
  719. filterable
  720. clearable
  721. />
  722. )
  723. }
  724. })
  725. field.push({
  726. title(column: any) {
  727. return (
  728. <NSpace>
  729. 排序
  730. <NButton
  731. type="primary"
  732. size="small"
  733. text
  734. onClick={() => {
  735. dialogs.create({
  736. title: '请输入排序起始值',
  737. showIcon: false,
  738. content: () => {
  739. return h(
  740. 'div',
  741. {
  742. class: 'flex flex-col justify-center items-center text-14px'
  743. },
  744. [
  745. // icon
  746. h(NInputNumber, {
  747. onUpdateValue(v) {
  748. state.startSortNum = v
  749. },
  750. min: 0,
  751. max: 9999
  752. })
  753. ]
  754. )
  755. },
  756. positiveText: '确定',
  757. negativeText: '取消',
  758. onPositiveClick: () => {
  759. if (state.startSortNum) {
  760. for (let i = 0; i < state.selectRowData.length; i++) {
  761. const item = state.selectRowData[i]
  762. item.sortNo = state.startSortNum + i
  763. }
  764. }
  765. }
  766. })
  767. }}
  768. >
  769. <NIcon size={15} style="padding-left: 5px;margin-top:4px">
  770. <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32">
  771. <path d="M2 26h28v2H2z" fill="currentColor"></path>
  772. <path
  773. 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"
  774. fill="currentColor"
  775. ></path>
  776. </svg>
  777. </NIcon>
  778. </NButton>
  779. </NSpace>
  780. )
  781. },
  782. key: 'sortNo',
  783. width: 150,
  784. render: (row: any) => {
  785. return h(NInputNumber, {
  786. value: row.sortNo,
  787. min: 0,
  788. max: 9999,
  789. onUpdateValue(value: any) {
  790. row.sortNo = value
  791. }
  792. })
  793. }
  794. })
  795. field.push({
  796. title: '操作',
  797. key: 'operation',
  798. fixed: 'right',
  799. render(row: any) {
  800. return (
  801. <NSpace>
  802. <NButton
  803. type="primary"
  804. size="small"
  805. text
  806. //v-auth="musicSheet/update1602302618558099458"
  807. onClick={() => {
  808. dialogs.warning({
  809. title: '提示',
  810. content: `是否删除该数据?`,
  811. positiveText: '确定',
  812. negativeText: '取消',
  813. onPositiveClick: async () => {
  814. try {
  815. const index = state.selectRowData.findIndex((item: any) => {
  816. if (item.id == row.id) {
  817. return true
  818. }
  819. })
  820. if (index > -1) {
  821. state.selectRowData.splice(index, 1)
  822. }
  823. const index1 = checkedRowKeysRef.value.findIndex((item: any) => {
  824. if (item == row.id) {
  825. return true
  826. }
  827. })
  828. if (index1 > -1) {
  829. checkedRowKeysRef.value.splice(index, 1)
  830. }
  831. } catch {}
  832. }
  833. })
  834. }}
  835. >
  836. 移除
  837. </NButton>
  838. </NSpace>
  839. )
  840. }
  841. })
  842. return field
  843. }
  844. const checkedRowKeysRef = ref<DataTableRowKey[]>([])
  845. const handleCheck = (rowKeys: DataTableRowKey[]) => {
  846. checkedRowKeysRef.value = rowKeys
  847. // 添加行更新值
  848. state.dataList.forEach((next: any) => {
  849. if (checkedRowKeysRef.value.includes(next.id)) {
  850. const find = state.selectRowData.find((row: any) => {
  851. return row.id === next.id
  852. })
  853. if (!find) {
  854. next.status = false
  855. state.selectRowData.push(next)
  856. }
  857. }
  858. })
  859. // 去掉行更新值
  860. state.selectRowData = state.selectRowData.filter((next: any) => {
  861. return checkedRowKeysRef.value.includes(next.id)
  862. })
  863. }
  864. return () => {
  865. return (
  866. <div class="system-menu-container">
  867. <NSpace vertical size="medium">
  868. <NSteps
  869. current={state.currentStep}
  870. // onUpdateCurrent={()=>{
  871. // state.currentStep = val
  872. // }}
  873. style={'margin-bottom: 10px;margin-top: 10px'}
  874. >
  875. <NStep title="选择曲目" description=""></NStep>
  876. <NStep title="设置曲目信息" description=""></NStep>
  877. </NSteps>
  878. </NSpace>
  879. {state.currentStep === 1 && (
  880. <div class="system-menu-container">
  881. <SaveForm
  882. ref={saveForm}
  883. model={state.searchForm}
  884. onSubmit={onSubmit}
  885. // saveKey="cooleshow-edu-addMusic"
  886. onSetModel={(val: any) => (state.searchForm = val)}
  887. >
  888. <NFormItem label="关键词" path="keyword">
  889. <NInput
  890. v-model:value={state.searchForm.keyword}
  891. placeholder="请输入曲目名称/编号"
  892. clearable
  893. />
  894. </NFormItem>
  895. {/* <NFormItem label="谱面渲染" path="musicSheetType">
  896. <NSelect
  897. placeholder="请选择谱面渲染"
  898. v-model:value={state.searchForm.musicSheetType}
  899. options={getSelectDataFromObj(musicSheetType)}
  900. clearable
  901. />
  902. </NFormItem> */}
  903. <NFormItem label="可用声部" path="musicSubject">
  904. <NSelect
  905. placeholder="请选择可用声部"
  906. v-model:value={state.searchForm.subjectId}
  907. options={state.subjectList}
  908. clearable
  909. />
  910. </NFormItem>
  911. <NFormItem label="音乐人" path="composer">
  912. <NInput
  913. placeholder="请选择音乐人"
  914. v-model:value={state.searchForm.composer}
  915. clearable
  916. />
  917. </NFormItem>
  918. <NFormItem label="曲目来源" path="sourceType">
  919. <NSelect
  920. placeholder="请选择曲目来源"
  921. v-model:value={state.searchForm.sourceType}
  922. options={getSelectDataFromObj(musicSheetSourceType)}
  923. onUpdateValue={async (value: any) => {
  924. state.userIdData = []
  925. state.searchForm.userId = null
  926. if (value && value !== 'PLATFORM') {
  927. await updateUserIdData(value)
  928. state.userIdDisable = false
  929. } else {
  930. state.userIdDisable = true
  931. }
  932. }}
  933. clearable
  934. />
  935. </NFormItem>
  936. <NFormItem label="所属项目" path="applicationId">
  937. <NSelect
  938. placeholder="请选择所属项目"
  939. v-model:value={state.searchForm.applicationId}
  940. options={state.useProjectData}
  941. clearable
  942. onUpdateValue={async (value: any) => {
  943. state.searchForm.applicationId = value
  944. if (value) {
  945. await updateUserIdData(state.searchForm.sourceType)
  946. state.userIdDisable = !(
  947. state.searchForm.sourceType && state.searchForm.sourceType !== 'PLATFORM'
  948. )
  949. } else {
  950. state.searchForm.userId = null
  951. state.userIdDisable = true
  952. state.userIdData = []
  953. }
  954. }}
  955. />
  956. </NFormItem>
  957. <NFormItem label="所属人" path="author">
  958. <NSelect
  959. filterable
  960. placeholder="请选择所属人"
  961. disabled={
  962. state.userIdDisable ||
  963. (!state.searchForm.applicationId && !state.searchForm.sourceType)
  964. }
  965. v-model:value={state.searchForm.userId}
  966. options={state.userIdData}
  967. clearable
  968. ></NSelect>
  969. </NFormItem>
  970. <NFormItem>
  971. <NSpace>
  972. <NButton type="primary" onClick={onSearch}>
  973. 搜索
  974. </NButton>
  975. <NButton type="default" onClick={onBtnReset}>
  976. 重置
  977. </NButton>
  978. </NSpace>
  979. </NFormItem>
  980. </SaveForm>
  981. <p style={{ paddingBottom: '12px' }}>
  982. 你选择了<span style={'color:red;padding:0 8px'}>{state.selectRowData.length}</span>
  983. 条曲目
  984. </p>
  985. <NDataTable
  986. loading={state.loading}
  987. columns={columns()}
  988. data={state.dataList}
  989. rowKey={(row: any) => row.id}
  990. onUpdateCheckedRowKeys={handleCheck}
  991. v-model:checkedRowKeys={checkedRowKeysRef.value}
  992. ></NDataTable>
  993. <Pagination
  994. v-model:page={state.pagination.page}
  995. v-model:pageSize={state.pagination.rows}
  996. v-model:pageTotal={state.pagination.pageTotal}
  997. onList={getList}
  998. sync
  999. // saveKey="cooleshow-edu-addMusic"
  1000. ></Pagination>
  1001. </div>
  1002. )}
  1003. {state.currentStep === 2 && (
  1004. <div class="system-menu-container" style={'margin-top: 15px;'}>
  1005. <NDataTable
  1006. loading={state.loading}
  1007. columns={stepColumns()}
  1008. data={state.selectRowData}
  1009. rowKey={(row: any) => row.id}
  1010. maxHeight={500}
  1011. scrollX={2000}
  1012. ></NDataTable>
  1013. </div>
  1014. )}
  1015. <NSpace justify="end" style={'margin-top:10px'}>
  1016. <NButton
  1017. type="default"
  1018. onClick={() => {
  1019. if (state.currentStep > 1) {
  1020. state.currentStep = state.currentStep - 1
  1021. } else {
  1022. emit('close')
  1023. }
  1024. }}
  1025. >
  1026. {state.currentStep === 1 ? '取消' : '上一步'}
  1027. </NButton>
  1028. <NButton
  1029. type="primary"
  1030. onClick={() => {
  1031. if (state.currentStep < 2) {
  1032. if (state.selectRowData.length == 0) {
  1033. message.warning('请选择曲目')
  1034. return
  1035. }
  1036. state.currentStep = state.currentStep + 1
  1037. } else {
  1038. onSave()
  1039. }
  1040. }}
  1041. // loading={btnLoading.value}
  1042. // disabled={btnLoading.value}
  1043. >
  1044. {state.currentStep === 2 ? '确定' : '下一步'}
  1045. </NButton>
  1046. </NSpace>
  1047. </div>
  1048. )
  1049. }
  1050. }
  1051. })