import { defineComponent, onMounted, reactive, ref } from 'vue' import SaveForm from '@components/save-form' import { DataTableRowKey, NButton, NDataTable, NDatePicker, NDescriptions, NDescriptionsItem, NFormItem, NImage, NInput, NModal, NSelect, NSpace, NTag, useDialog, useMessage } from 'naive-ui' import Pagination from '@components/pagination' import TheTooltip from '@components/TheTooltip' import AddMusic from '@views/music-library/project-music-sheet/module/klx/addMusic' import { getMapValueByKey, getSelectDataFromObj } from '@/utils/objectUtil' import { appKey, musicSheetAudioType, musicSheetAvailableType, musicSheetPaymentType, musicSheetSourceType, musicSheetType } from '@/utils/constant' import { musicSheetApplicationExtendStatus, musicSheetApplicationExtendTagList, musicSheetApplicationOwnerList, musicSheetPageByApplication } from '@views/music-library/api' import { subjectPage, sysApplicationPage } from '@views/system-manage/api' import { filterTimes } from '@/utils/dateUtil' import deepClone from '@/utils/deep.clone' import { getOwnerName } from '@views/music-library/musicUtil' import UpdateMusic from '@views/music-library/project-music-sheet/module/klx/updateMusic' import MusicPreView from "@views/music-library/music-sheet/modal/musicPreView"; export default defineComponent({ name: 'music-sheet-KLX', props: { appKey: { type: String, default: 'KLX' } }, setup(props) { const dialog = useDialog() const message = useMessage() const state = reactive({ loading: false, appId: null as any, pagination: { page: 1, rows: 10, pageTotal: 0 }, searchForm: { keyword: null, musicSheetType: null, //曲目类型(SINGLE:单曲 CONCERT:合奏) subjectId: null, //声部ID subjectIds: null, //曲目声部ID集合 status: null, //曲目状态(0:停用,1:启用) sourceType: null, //来源类型/作者属性(PLATFORM: 平台; ORG: 机构; PERSON: 个人) paymentType: null, //收费类型(FREE:免费;VIP:会员;CHARGE:单曲收费) userId: null, //所属人 musicCategoryId: null, //曲目分类ID times: null, // 上传时间 audioType: null, //音频类型(HOMEMODE: 自制 COMMON: 普通) exquisiteFlag: null, //精品标志 topFlag: null, //是否置顶(0:否;1:是) availableType: null, //可用途径 ORG 机构 PLATFORM 平台 appAuditFlag: null, //是否审核版本 detailFlag: null, //是否查询详情 musicTagIds: [] as any,//曲目标签 applicationId: null, //所属人项目ID }, subjectList: [], dataList: [] as any[], showAddDialog: false, showEditDialog: false, userIdDisable: true, userIdData: [] as any, updateRow: {} as any, // 修改选择的行 musicTagList: [] as any, //曲目标签 applicationId: null, //应用ID musicPreview: false, musicScore: null as any, useProjectData: [] as any, // 适用项目行数据 }) onMounted(async () => { state.loading = true // 获取应用APP信息 try { const { data } = await sysApplicationPage({ page: 1, rows: 1, appKey: props.appKey }) const tempList = data.rows || [] if (!tempList || tempList.length == 0) { state.loading = false message.error('加载项目信息失败') return } state.appId = tempList[0].id state.applicationId = tempList[0].id } catch {} // 加载声部 try { const { data } = await subjectPage({ page: 1, rows: 999 }) const tempList = data.rows || [] tempList.forEach((item: any) => { item.label = item.name item.value = item.id + '' }) state.subjectList = tempList } catch {} // 加载曲目标签 try { const { data } = await musicSheetApplicationExtendTagList({ applicationId: state.appId }) if (data && data.length > 0) { data.forEach((item: any) => { state.musicTagList.push({ ...item, label: item.name, value: item.id }) }) } } catch (err) {} // 加载表格数据 initUseAppList() getList() }) const saveForm = ref() const onSearch = () => { saveForm.value?.submit() } const onBtnReset = () => { saveForm.value?.reset() } const onSubmit = () => { state.pagination.page = 1 getList() } const initUseAppList = async () => { try { const appKeys = Object.keys(appKey) const { data } = await sysApplicationPage({ page: 1, rows: 999 }) const tempList = data.rows || [] state.useProjectData = [] const filter = tempList.filter((next: any) => { return appKeys.includes(next.appKey) }) filter.forEach((item: any) => { state.useProjectData.push({ ...item, label: item.appName, value: item.id }) }) } catch {} } const checkedRowKeysRef = ref<DataTableRowKey[]>([]) const handleCheck = (rowKeys: DataTableRowKey[]) => { checkedRowKeysRef.value = rowKeys } const getList = async () => { try { state.loading = true const sourceType = state.searchForm.sourceType let userId = state.searchForm.userId let organizationRoleId = null if (sourceType && sourceType === 'ORG') { organizationRoleId = deepClone(userId) userId = null } const { data } = await musicSheetPageByApplication({ ...state.pagination, ...state.searchForm, userId: (sourceType && sourceType === 'PERSON') ? state.searchForm.userId : null, organizationRoleId: (sourceType && sourceType === 'ORG') ? state.searchForm.userId : null, musicTagIds: state.searchForm.musicTagIds?.join(','), ...filterTimes(state.searchForm.times, ['startTime', 'endTime']), applicationId: state.applicationId }) state.pagination.pageTotal = Number(data.total) state.dataList = data.rows || [] } catch {} state.loading = false } const onChangeStatus = (row: any) => { const statusStr = row.status ? '停用' : '启用' dialog.warning({ title: '提示', content: `是否${statusStr}?`, positiveText: '确定', negativeText: '取消', onPositiveClick: async () => { try { await musicSheetApplicationExtendStatus({ ids: row.applicationExtendId, status: !row.status }) getList() message.success(`${statusStr}成功`) } catch {} } }) } const onBatchChangeStatus = (status: boolean) => { const length = checkedRowKeysRef.value.length if (length == 0) { message.warning('未选择数据') } const statusStr = !status ? '停用' : '启用' dialog.warning({ title: '提示', content: `是否${statusStr}` + length + `条数据?`, positiveText: '确定', negativeText: '取消', onPositiveClick: async () => { try { await musicSheetApplicationExtendStatus({ ids: checkedRowKeysRef.value.join(','), status: status }) getList() message.success(`${statusStr}成功`) } catch {} } }) } const getPaymentType = (paymentType: any) => { const paymentTypeName = [] if (paymentType && paymentType.length > 0) { for (let i = 0; i < paymentType.length; i++) { const name = getMapValueByKey( paymentType[i], new Map(Object.entries(musicSheetPaymentType)) ) paymentTypeName.push(name) } } return paymentTypeName.join(',') } const updateUserIdData = async (sourceType: any) => { if (!state.searchForm.applicationId) { return } state.userIdData = [] state.searchForm.userId = null if (sourceType && sourceType !== 'PLATFORM') { const { data } = await musicSheetApplicationOwnerList({ page: 1, rows: 9999, sourceType: sourceType, applicationId: state.searchForm.applicationId }) const temp = data.rows || [] temp.forEach((next: any) => { state.userIdData.push({ ...next, label: sourceType === 'PERSON' ? next.userName : next.organizationRole, value: sourceType === 'PERSON' ? next.userId : next.organizationRoleId }) }) } } const columns = (): any => { return [ { type: 'selection' }, { title: '曲目信息', key: 'id', render: (row: any) => ( <> <NDescriptions labelPlacement="left" column={1}> <NDescriptionsItem label="曲目名称"> <TheTooltip content={row.name} />{' '} </NDescriptionsItem> <NDescriptionsItem label="曲目编号"><TheTooltip content={row.id} />{' '}</NDescriptionsItem> </NDescriptions> </> ) }, { title: '封面图', key: 'musicCover', render(row: any): JSX.Element { return <NImage width={60} height={60} src={row.musicCover} /> } }, { title: '曲目信息', key: 'musicSheetCategoriesName', render: (row: any) => ( <> <NDescriptions labelPlacement="left" column={1}> <NDescriptionsItem label="曲目来源"> {getMapValueByKey(row.sourceType, new Map(Object.entries(musicSheetSourceType)))} </NDescriptionsItem> <NDescriptionsItem label="所属人"> <TheTooltip content={getOwnerName(row.musicSheetExtend, row.sourceType)}/> </NDescriptionsItem> <NDescriptionsItem label="可用声部"> <TheTooltip content={row.subjectNames}/> </NDescriptionsItem> </NDescriptions> </> ) }, { title: '同时渲染所选声轨', key: 'musicSheetType', render: (row: any) => { return ( <div> {getMapValueByKey(row.musicSheetType, new Map(Object.entries(musicSheetType)))} </div> ) } }, { title: '伴奏类型', key: 'audioType', render: (row: any) => { return ( <div> {getMapValueByKey(row.audioType, new Map(Object.entries(musicSheetAudioType)))} </div> ) } }, // { // title: '可用声部', // key: 'subjectNames', // render: (row: any) => { // return <TheTooltip content={row.subjectNames}/> // } // }, { title: '曲目标签', key: 'musicTagNames' }, { title: '可用途径', key: 'applicationAvailableType', render: (row: any) => { return ( <div> {getMapValueByKey( row.applicationAvailableType, new Map(Object.entries(musicSheetAvailableType)) )} </div> ) } }, { title: '是否置顶', key: 'topFlag', render: (row: any) => { return <div>{row.topFlag ? '是' : '否'}</div> } }, { title: '是否精品', key: 'exquisiteFlag', render: (row: any) => { return <div>{row.topFlag ? '是' : '否'}</div> } }, { title: '收费方式', key: 'paymentType', render: (row: any) => { return <div>{getPaymentType(row.paymentType?.split(','))}</div> } }, { title: '曲目价格', key: 'musicPrice' }, { title: '上传人', minWidth: '150px', key: 'composer', render(row: any) { return ( <NDescriptions labelPlacement="left" column={1}> <NDescriptionsItem label="上传人">{row.createByName}</NDescriptionsItem> <NDescriptionsItem label="上传时间">{row.createTime}</NDescriptionsItem> </NDescriptions> ) } }, { title: '状态', key: 'status', render(row: any) { return ( <NTag type={row.status ? 'primary' : 'default'}>{row.status ? '启用' : '停用'}</NTag> ) } }, { title: '操作', key: 'operation', fixed: 'right', render(row: any) { return ( <NSpace> <NButton type="primary" size="small" text onClick={() => { state.musicPreview = true state.musicScore = row }} > 预览 </NButton> <NButton type="primary" size="small" text v-auth="musicSheetApplicationExtend/status1751235210464198657" onClick={() => onChangeStatus(row)} > {row.status ? '停用' : '启用'} </NButton> <NButton type="primary" size="small" text v-auth="musicSheetApplicationExtend/update1751235573456044033" onClick={() => { state.showEditDialog = true state.updateRow = row }} > 修改 </NButton> </NSpace> ) } } ] } return () => { return ( <div class="system-menu-container"> <SaveForm ref={saveForm} model={state.searchForm} onSubmit={onSubmit} saveKey="music-sheet-klx" onSetModel={(val: any) => (state.searchForm = val)} > <NFormItem label="关键词" path="keyword"> <NInput placeholder="请输入曲目名称/编号" v-model:value={state.searchForm.keyword} clearable /> </NFormItem> <NFormItem label="曲目来源" path="sourceType"> <NSelect placeholder="请选择曲目来源" v-model:value={state.searchForm.sourceType} options={getSelectDataFromObj(musicSheetSourceType)} onUpdateValue={async (value: any) => { state.userIdData = [] state.searchForm.userId = null if (value && value !== 'PLATFORM') { await updateUserIdData(value) state.userIdDisable = !state.searchForm.applicationId } else { state.userIdDisable = true } }} clearable /> </NFormItem> <NFormItem label="项目" path="applicationId"> <NSelect placeholder="请选择项目" v-model:value={state.searchForm.applicationId} options={state.useProjectData} clearable onUpdateValue={async (value: any) => { state.searchForm.applicationId = value if (value) { await updateUserIdData(state.searchForm.sourceType) state.userIdDisable = !( state.searchForm.sourceType && state.searchForm.sourceType !== 'PLATFORM' ) } else { state.searchForm.userId = null state.userIdDisable = true state.userIdData = [] } }} /> </NFormItem> <NFormItem label="所属人" path="userId"> <NSelect filterable placeholder="请选择所属人" disabled={state.userIdDisable} v-model:value={state.searchForm.userId} options={state.userIdData} clearable ></NSelect> </NFormItem> <NFormItem label="曲目类型" path="subjectType"> <NSelect placeholder="请选择曲目类型" v-model:value={state.searchForm.musicSheetType} options={getSelectDataFromObj(musicSheetType)} clearable /> </NFormItem> <NFormItem label="伴奏类型" path="audioType"> <NSelect placeholder="请选择伴奏类型" v-model:value={state.searchForm.audioType} options={getSelectDataFromObj(musicSheetAudioType)} clearable /> </NFormItem> <NFormItem label="可用声部" path="subjectId"> <NSelect placeholder="请选择可用声部" v-model:value={state.searchForm.subjectId} options={state.subjectList} clearable /> </NFormItem> <NFormItem label="曲目标签" path="musicTagIds"> <NSelect placeholder="请选择曲目标签" v-model:value={state.searchForm.musicTagIds} options={state.musicTagList} multiple maxTagCount={2} clearable /> </NFormItem> {/*<NFormItem*/} {/* label="可用途径"*/} {/* path="availableType"*/} {/*>*/} {/* <NSelect*/} {/* placeholder="请选择可用途径"*/} {/* v-model:value={state.searchForm.availableType}*/} {/* options={getSelectDataFromObj(musicSheetAvailableType)}*/} {/* clearable*/} {/* >*/} {/* </NSelect>*/} {/*</NFormItem>*/} <NFormItem label="收费方式" path="paymentType"> <NSelect placeholder="请选择收费方式" v-model:value={state.searchForm.paymentType} options={getSelectDataFromObj(musicSheetPaymentType)} clearable ></NSelect> </NFormItem> <NFormItem label="状态" path="status"> <NSelect v-model:value={state.searchForm.status} placeholder="请选择状态" options={ [ { label: '启用', value: true }, { label: '停用', value: false } ] as any } clearable /> </NFormItem> <NFormItem label="上传时间" path="authorFrom"> <NDatePicker v-model:value={state.searchForm.times} type="daterange" clearable value-format="yyyy.MM.dd" startPlaceholder="开始时间" endPlaceholder="结束时间" /> </NFormItem> <NFormItem> <NSpace> <NButton type="primary" onClick={onSearch}> 搜索 </NButton> <NButton type="default" onClick={onBtnReset}> 重置 </NButton> </NSpace> </NFormItem> </SaveForm> <div class={['section-container']}> <NSpace style={{ paddingBottom: '12px' }}> <NButton type="primary" v-auth="musicSheetApplicationExtend/saveBatch1751234344277508097" onClick={() => { state.showAddDialog = true }} > 添加曲目 </NButton> <NButton disabled={checkedRowKeysRef.value.length == 0} v-auth="musicSheetApplicationExtend/status1751235210464198657" onClick={() => { onBatchChangeStatus(false) }} > 批量停用 </NButton> <NButton disabled={checkedRowKeysRef.value.length == 0} v-auth="musicSheetApplicationExtend/status1751235210464198657" onClick={() => { onBatchChangeStatus(true) }} > 批量启用 </NButton> </NSpace> <NDataTable loading={state.loading} columns={columns()} data={state.dataList} rowKey={(row: any) => row.applicationExtendId} onUpdateCheckedRowKeys={handleCheck} scrollX={'2000'} ></NDataTable> <Pagination v-model:page={state.pagination.page} v-model:pageSize={state.pagination.rows} v-model:pageTotal={state.pagination.pageTotal} onList={getList} sync saveKey="music-sheet-klx" ></Pagination> </div> <NModal v-model:show={state.showAddDialog} preset="dialog" showIcon={false} title={'添加曲目'} style={{ width: '1300px' }} > <AddMusic onClose={() => (state.showAddDialog = false)} onGetList={onSubmit} subjectList={state.subjectList} appId={state.appId} musicSheetTagList={state.musicTagList} /> </NModal> <NModal v-model:show={state.showEditDialog} preset="dialog" showIcon={false} title={'修改曲目'} style={{ width: '500px' }} > <UpdateMusic onClose={() => (state.showEditDialog = false)} onGetList={() => { state.pagination.page = 1 getList() }} rowData={state.updateRow} appId={state.appId} musicSheetTagList={state.musicTagList} /> </NModal> <NModal blockScroll={true} v-model:show={state.musicPreview} preset="dialog" showIcon={false} title={'曲目预览'} style={{ width: 'auto' }} > <MusicPreView item={state.musicScore} /> </NModal> </div> ) } } })