import { computed, defineComponent, nextTick, onMounted, reactive, ref, shallowRef } from "vue" import styles from "./index.module.scss" import NavContainer from "@/businessComponents/navContainer" import { ElEmpty, ElScrollbar } from "element-plus" import Dictionary from "@/components/dictionary" import MyInput from "@/components/myInput" import { NImage, NPopselect, NSpin, NTooltip } from "naive-ui" // import PlayLoading from "./component/play-loading" import PlayItem from "./component/play-item" import icon_default from "../../img/cloudPractice/icon_default.png" import iconBtnPause from "../../img/cloudPractice/icon-btn-pause.png" import iconBtnPlay from "../../img/cloudPractice/icon-btn-play.png" import btnSubmit from "../../img/cloudPractice/btn-submit.png" import iconTransfer from "../../img/cloudPractice/icon-transfer.png" import { httpAjaxErrMsg } from "@/plugin/httpAjax" import { queryPage2_gym, queryPage2_gyt, queryPage2_klx, querySubjectIds_gym, querySubjectIds_gyt, querySubjectIds_klx, queryTree_gym, queryTree_gyt, queryTree_klx, selectCondition_klx } from "@/api/cloudPractice.api" // import { getToken } from "@/libs/auth" // import { URL_TEACH_GYM } from "@/config" import axios from "axios" import { getInstrumentName } from "@/libs/instruments" import { formatXML, getCustomInfo, onlyVisible } from "./instrument" import { useFunction } from "./useData" import userStore from "@/store/modules/user" import PlayLoading from "./component/play-loading" import PracticeForm from "@/businessComponents/practiceForm" export default defineComponent({ name: "cloudPractice", setup() { const userStoreHook = userStore() const { goToCloud, isPracticeShow, practiceUrl, handlePracticeClose } = useFunction() const navs = [ { name: "主页", url: "/" }, { name: "云练习" } ] const spinRef = ref() const state = reactive({ finshed: false, reshing: false, page: 1, rows: 20, iframeSrc: "", listActive: 0, // 当前选中的对象 firstTreeId: null as any, // 左侧 categoryId: null as any, // 类型 categoryName: "" as any, // 类型名称 categoryList: [] as any[], levelList: [] as any[], // 级别 levelId: null as any, typeList: [] as any[], // 类型 typeId: -1 as any, subjectList: [] as any[], // 声部列表 subjectId: -1 as any, list: [] as any[], searchStatus: false, queryStr: "", // 搜索条件 partList: [] as any[], partNames: [] as any[], selectedPartName: "" as any, selectedPartIndex: 0, partXmlIndex: 0, categoryShow: false, // 是否展开 playState: "pause" as "play" | "pause", // 播放状态 showPlayer: false // 是否显示播放器 }) const partColumns = ref([]) /** 选中的item */ const activeItem = computed(() => { const list = state.list[state.listActive] || {} let tempList: any = {} if (userStoreHook.roles === "GYM") { const item = list.background?.[0] const audioFileUrl = item?.musicSheetType === "CONCERT" ? item?.metronomeUrl : item?.metronomeMp3Url || item?.mp3Url tempList = { id: item?.id, name: item?.examSongName, background: list?.background, xmlUrl: item?.xmlUrl, musicSheetType: item?.musicSheetType, audioFileUrl, // titleImg: list?.titleImg, isComberRender: item?.isScoreRender } } else if (userStoreHook.roles === "GYT") { tempList = { id: list?.id, name: list?.musicSheetName, background: list?.background, xmlUrl: list?.xmlFileUrl, musicSheetType: list?.musicSheetType, audioFileUrl: list?.audioFileUrl, titleImg: list?.titleImg, isComberRender: list?.musicSubjectId === "1" } } else if (userStoreHook.roles === "KLX") { const item: any = list.background?.[0] tempList = { id: list?.id, name: list?.musicSheetName, background: list?.background, xmlUrl: list?.xmlFileUrl, musicSheetType: list?.musicSheetType, audioFileUrl: item?.audioFileUrl, titleImg: list?.titleImg, isComberRender: false } } return tempList }) const songPrevNextStatus = computed(() => { let prev = true, next = true if (state.listActive === 0) { prev = false } if (state.listActive >= state.list.length - 1) { next = false } return { prev, next } }) const loading = ref(false) const staffLoading = ref(false) const storeData = shallowRef([]) const handleSearchList_gym = async () => { loading.value = true await httpAjaxErrMsg(queryTree_gym).then(async res => { loading.value = false if (res.code === 200) { storeData.value = res.data || [] await setDefaultData() } }) } const handleGetSubject_gym = async () => { loading.value = true await httpAjaxErrMsg(querySubjectIds_gym, { categoriesId: state.categoryId || state.firstTreeId }).then(res => { loading.value = false if (res.code === 200) { const result = res.data || [] state.subjectList = result.map((item: any) => { return { label: item.name, value: item.id } }) state.subjectList.unshift({ label: "全部声部", value: -1 }) const userSubjectId = userStoreHook.userInfo.subjectId if (userSubjectId) { const tempSubjectId = userSubjectId.split(",")[0] state.subjectList.forEach((item: any) => { // 判断是否存在声部编号 if (item.value === Number(tempSubjectId)) { state.subjectId = Number(tempSubjectId) } }) } } }) } const handleGetList_gym = async () => { loading.value = true const params = { page: state.page, rows: state.rows, subjectId: state.subjectId === -1 ? null : state.subjectId, categoriesId: state.typeId === -1 ? state.levelId : state.typeId, search: state.queryStr } await httpAjaxErrMsg(queryPage2_gym, params).then(res => { loading.value = false if (res.code === 200) { const result = res.data || [] if (state.reshing) { state.list = [] state.reshing = false } if (Array.isArray(result.rows)) { state.list = [...state.list, ...result.rows] state.finshed = state.page >= result.totalPage } else { state.finshed = true } } }) } /** 管乐团数据查询 */ const handleSearchList_gyt = async () => { loading.value = true await httpAjaxErrMsg(queryTree_gyt, { enable: true, page: 1, parentId: 0, rows: 10 }).then(res => { loading.value = false if (res.code === 200) { storeData.value = res.data || [] setDefaultData() } }) } const handleGetSubject_gyt = async () => { loading.value = true await httpAjaxErrMsg(querySubjectIds_gyt, { enableFlag: true, page: 1, rows: 100 }).then(res => { loading.value = false if (res.code === 200) { const result = res.data || [] state.subjectList = result.map((item: any) => { return { label: item.name, value: item.id } }) state.subjectList.unshift({ label: "全部声部", value: -1 }) const userSubjectId = userStoreHook.userInfo.subjectId if (userSubjectId) { const tempSubjectId = userSubjectId.split(",")[0] state.subjectList.forEach((item: any) => { // 判断是否存在声部编号 if (item.value === Number(tempSubjectId)) { state.subjectId = Number(tempSubjectId) } }) } } }) } const handleGetList_gyt = async () => { loading.value = true const params = { page: state.page, rows: state.rows, musicSubject: state.subjectId === -1 ? null : state.subjectId, musicSheetCategoriesId: state.typeId === -1 ? state.levelId : state.typeId, keyword: state.queryStr, detailFlag: true, status: 1 } await httpAjaxErrMsg(queryPage2_gyt, params).then(res => { loading.value = false if (res.code === 200) { const result = res.data || {} if (state.reshing) { state.list = [] state.reshing = false } if (Array.isArray(result.rows)) { result.rows.forEach((item: any) => { item.name = item.musicSheetName }) state.list = [...state.list, ...result.rows] state.finshed = state.page >= result.pages } else { state.finshed = true } } }) } /** 酷乐秀机构数据查询 */ const handleSearchList_klx = async () => { loading.value = true await httpAjaxErrMsg(queryTree_klx, { enable: true, page: 1, parentId: 0, rows: 10 }) .then(res => { loading.value = false if (res.code === 200) { const result = res.data || [] const tempList: any = [] result.forEach((item: any) => { if (item.musicNum > 0) { const subjectCounts = item.subjectCounts ? true : false const musicCounts = item.musicCounts ? true : false const ensembleCounts = item.ensembleCounts ? true : false const list: any = [] if (subjectCounts) { list.push({ label: "基础云练", value: "SUBJECT" }) } if (musicCounts) { list.push({ label: "独奏云练", value: "MUSIC" }) } if (ensembleCounts) { list.push({ label: "合奏云练", value: "ENSEMBLE" }) } tempList.push({ value: item.id, label: item.name, musicSheetCategoriesList: list }) } }) state.categoryList = tempList setDefaultData() } }) .catch(() => { state.finshed = true }) } const handleGetSubject_klx = async () => { loading.value = true await httpAjaxErrMsg(querySubjectIds_klx, { queryType: "list", page: 1, rows: 100 }).then(res => { loading.value = false if (res.code === 200) { const result = res.data?.rows || [] state.subjectList = result.map((item: any) => { return { label: item.name, value: item.id } }) state.subjectList.unshift({ label: "全部声部", value: -1 }) const userSubjectId = userStoreHook.userInfo.subjectId if (userSubjectId) { const tempSubjectId = userSubjectId.split(",")[0] state.subjectList.forEach((item: any) => { // 判断是否存在声部编号 if (item.value === Number(tempSubjectId)) { state.subjectId = Number(tempSubjectId) } }) } } }) } const handleGetList_klx = async () => { if (!state.categoryId) return loading.value = true const params = { page: state.page, rows: state.rows, albumId: state.categoryId, subjectId: state.subjectId === -1 ? null : state.subjectId, subjectType: state.firstTreeId, level: state.levelId === -1 ? null : state.levelId, type: state.typeId === -1 ? null : state.typeId, keyword: state.queryStr } await httpAjaxErrMsg(queryPage2_klx, params).then(res => { loading.value = false if (res.code === 200) { const result = res.data || {} if (state.reshing) { state.list = [] state.reshing = false } if (Array.isArray(result.rows)) { result.rows.forEach((item: any) => { item.name = item.musicSheetName }) state.list = [...state.list, ...result.rows] state.finshed = state.page >= result.totalPage } else { state.finshed = true } } }) } const handleSelectCondition_klx = async () => { if (!state.categoryId || !state.firstTreeId) return loading.value = true const params = { tenantAlbumId: state.categoryId, subjectType: state.firstTreeId } await httpAjaxErrMsg(selectCondition_klx, params).then(res => { loading.value = false if (res.code === 200) { const result = res.data || {} if (result.levelList && result.levelList.length > 0) { state.levelList = result.levelList.map((item: any) => { return { label: item.value, value: item.id } }) state.levelList.unshift({ label: "全部级别", value: -1 }) state.levelId = -1 } else { state.levelList = [] } if (result.typeList && result.typeList.length > 0) { state.typeList = result.typeList.map((item: any) => { return { label: item.value, value: item.id } }) state.typeList.unshift({ label: "全部类型", value: -1 }) state.typeId = -1 } else { state.typeList = [] } } }) } /** 条件查询 */ const handleAllSearchList = async () => { // GYM,GYT,KLX 区分 查询搜索条件数据 if (userStoreHook.roles === "GYM") { await handleSearchList_gym() } else if (userStoreHook.roles === "GYT") { await handleSearchList_gyt() } else if (userStoreHook.roles === "KLX") { await handleSearchList_klx() } } const handleAllGetSubject = async () => { // GYM,GYT,KLX 区分 查询声部数据 if (userStoreHook.roles === "GYM") { await handleGetSubject_gym() } else if (userStoreHook.roles === "GYT") { await handleGetSubject_gyt() } else if (userStoreHook.roles === "KLX") { await handleGetSubject_klx() } } const handleAllGetList = async () => { // GYM,GYT,KLX 区分 查询声部数据· if (userStoreHook.roles === "GYM") { await handleGetList_gym() } else if (userStoreHook.roles === "GYT") { await handleGetList_gyt() } else if (userStoreHook.roles === "KLX") { await handleGetList_klx() } } /** 初始化数据 */ const setDefaultData = async (type?: "first" | "category" | "level" | "type") => { if (userStoreHook.roles === "GYM") { await initCategories_gym(type) } else if (userStoreHook.roles === "GYT") { initCategories_gyt(type) } else if (userStoreHook.roles === "KLX") { await initCategories_klx(type) } } const initCategories_gym = async (type?: "first" | "category" | "level" | "type") => { if (storeData.value.length > 0 && !["category", "level", "type"].includes(type as any)) { let result: any = [] if (type === "first" && state.firstTreeId) { result = storeData.value.find((item: any) => item.id === state.firstTreeId)?.sysMusicScoreCategoriesList || [] } else { state.firstTreeId = storeData.value[0]?.id result = storeData.value[0]?.sysMusicScoreCategoriesList || [] } state.categoryList = result.map((item: any) => { return { label: item.name, value: item.id, sysMusicScoreCategoriesList: item.sysMusicScoreCategoriesList || [] } }) state.categoryId = null state.categoryName = null state.levelId = null state.typeId = -1 } if (state.categoryList.length > 0 && !["level", "type"].includes(type as any)) { let result: any = [] if (type === "category" && state.categoryId) { result = state.categoryList.find((item: any) => item.value === state.categoryId)?.sysMusicScoreCategoriesList || [] } else { state.categoryId = state.categoryList[0]?.value state.categoryName = state.categoryList[0]?.label result = state.categoryList[0]?.sysMusicScoreCategoriesList || [] } state.levelList = result.map((item: any) => { return { label: item.name, value: item.id, sysMusicScoreCategoriesList: item.sysMusicScoreCategoriesList || [] } }) await handleGetSubject_gym() } if (state.levelList.length > 0) { let result: any = [] if (type === "level" && state.levelId) { result = state.levelList.find((item: any) => item.value === state.levelId)?.sysMusicScoreCategoriesList state.typeId = -1 } else { state.levelId = state.levelList[0]?.value result = state.levelList[0]?.sysMusicScoreCategoriesList || [] } state.typeList = result.map((item: any) => { return { label: item.name, value: item.id } }) state.typeList.unshift({ label: "全部", value: -1 }) } } const initCategories_gyt = (type?: "first" | "category" | "level" | "type") => { if (storeData.value.length > 0 && !["level", "type"].includes(type as any)) { let result: any = [] if (type === "first" && state.firstTreeId) { result = storeData.value.find((item: any) => item.id === state.firstTreeId)?.musicSheetCategoriesList || [] } else { state.firstTreeId = storeData.value[0]?.id result = storeData.value[0]?.musicSheetCategoriesList || [] } state.levelList = result.map((item: any) => { return { label: item.name, value: item.id, musicSheetCategoriesList: item.musicSheetCategoriesList || [] } }) state.levelId = null state.typeId = -1 } if (state.levelList.length > 0) { let result: any = [] if (type === "level" && state.levelId) { result = state.levelList.find((item: any) => item.value === state.levelId)?.musicSheetCategoriesList } else { state.levelId = state.levelList[0]?.value result = state.levelList[0]?.musicSheetCategoriesList || [] } state.typeList = result.map((item: any) => { return { label: item.name, value: item.id } }) state.typeList.unshift({ label: "全部", value: -1 }) state.typeId = -1 } } const initCategories_klx = async (type?: "first" | "category" | "level" | "type") => { if (state.categoryList.length > 0 && !["level", "type", "first"].includes(type as any)) { let result: any = [] if (type === "category" && state.categoryId) { result = state.categoryList.find((item: any) => item.value === state.categoryId)?.musicSheetCategoriesList || [] } else { state.categoryId = state.categoryList[0]?.value state.categoryName = state.categoryList[0]?.label result = state.categoryList[0]?.musicSheetCategoriesList || [] } storeData.value = result.map((item: any) => { return { id: item.value, name: item.label } }) } if (storeData.value.length > 0 && !["level", "type"].includes(type as any)) { if (type === "first" && state.firstTreeId) { await handleSelectCondition_klx() } else { // state.firstTreeId = storeData.value[0]?.id await handleSelectCondition_klx() } state.levelId = -1 state.typeId = -1 } } const __init = async () => { await handleAllSearchList() await handleAllGetSubject() await handleAllGetList() await toDetail() renderStaff() } __init() const handleResh = () => { if (loading.value || state.finshed) return state.page = state.page + 1 handleAllGetList() } const handleGetList = async () => { if (loading.value) return state.listActive = 0 state.selectedPartIndex = 0 state.partXmlIndex = 0 state.showPlayer = false state.playState = "pause" state.partNames = [] state.partList = [] state.selectedPartName = "" state.selectedPartIndex = 0 state.partXmlIndex = 0 document.querySelector(".musicList-container")?.scroll(0, 0) state.page = 1 state.finshed = false state.reshing = true state.list = [] await handleAllGetList() } const toDetail = async () => { const row: any = activeItem.value if (row.musicSheetType === "SINGLE") { loading.value = false return } state.partNames = await getPartNames(row.xmlUrl) let partList = row.background || [] partList = partList.filter((item: any) => !item.track?.toLocaleUpperCase()?.includes("COMMON")) partColumns.value = partList.map((item: any, index: number) => { const instrumentName = getInstrumentName(item.track) const xmlIndex = state.partNames.findIndex((name: any) => name === item.track) return { label: item.track + (instrumentName ? `(${instrumentName})` : ""), instrumentName: instrumentName, xmlIndex, value: index } }) // 初始化数据 const defaultShowStaff = partColumns.value[state.selectedPartIndex] state.selectedPartName = defaultShowStaff?.instrumentName state.partXmlIndex = defaultShowStaff?.xmlIndex } const getPartNames = async (xmlUrl: string) => { const partNames: string[] = [] try { const res: any = await axios.get(xmlUrl) const xml: any = new DOMParser().parseFromString(res.data, "text/xml") for (const item of xml.getElementsByTagName("part-name")) { if (item.textContent) { partNames.push(item.textContent) } } } catch (error) { // } return partNames.filter((text: string) => text.toLocaleUpperCase() !== "COMMON") || [] } const musicIframeLoad = async () => { const iframeRef: any = document.getElementById("staffIframeRef") if (iframeRef && iframeRef.contentWindow.renderXml) { staffLoading.value = true const res: any = await axios.get(activeItem.value.xmlUrl) const parseXmlInfo = getCustomInfo(res.data) const xml = formatXML(parseXmlInfo.parsedXML) if (activeItem.value.isComberRender) { iframeRef.contentWindow.renderXml(xml, state.partXmlIndex, activeItem.value.isComberRender) } else { const currentXml = onlyVisible(xml, state.partXmlIndex) iframeRef.contentWindow.renderXml(currentXml, state.partXmlIndex, activeItem.value.isComberRender) } } } const resetRender = async () => { const iframeRef: any = document.getElementById("staffIframeRef") if (iframeRef && iframeRef.contentWindow.renderXml) { staffLoading.value = true const res: any = await axios.get(activeItem.value.xmlUrl) const parseXmlInfo = getCustomInfo(res.data) const xml = formatXML(parseXmlInfo.parsedXML) if (activeItem.value.isComberRender) { iframeRef.contentWindow.renderXml(xml, state.partXmlIndex, activeItem.value.isComberRender) } else { console.log(state.partXmlIndex, " state.partXmlIndex") const currentXml = onlyVisible(xml, state.partXmlIndex) iframeRef.contentWindow.renderXml(currentXml, 0, activeItem.value.isComberRender) } } } const renderStaff = async () => { try { // ${location.origin}${location.pathname} state.iframeSrc = `/osmd/index.html` } catch (error) { // } } /** 音频控制 */ const handleChangeAudio = (type: "play" | "pause" | "pre" | "next") => { if (type === "play") { state.playState = "play" } else if (type === "pause") { state.playState = "pause" } else if (type === "pre") { if (state.list[state.listActive - 1]) { handlePlay(state.list[state.listActive - 1]) } } else if (type === "next") { if (state.list[state.listActive + 1]) { handlePlay(state.list[state.listActive + 1]) } } } /** 播放曲目 */ const handlePlay = (item: any) => { const index = state.list.findIndex((_item: any) => _item.id === item.id) if (index > -1) { if (state.listActive === index) { state.playState = state.playState === "play" ? "pause" : "play" } else { state.playState = "play" } state.showPlayer = true state.listActive = index } } const showLoading = async (e: any) => { if (e.data?.api === "musicStaffRender") { staffLoading.value = e.data.loading } } onMounted(() => { const obv = new IntersectionObserver(entries => { if (entries[0].intersectionRatio > 0) { handleResh() } }) obv.observe(spinRef.value) window.addEventListener("message", showLoading) }) return () => ( {/* */}
{storeData.value.length > 0 && ( {/* 基 础 云 练 */} {storeData.value.map((item: any) => (
{ if (loading.value) return state.firstTreeId = item.id await setDefaultData("first") await handleGetList() await toDetail() }} > {item.name}
))}
)}
{state.categoryList.length > 1 && (
{ const item = state.categoryList.find((item: any) => item.value === val) if (item) { state.categoryName = item.label state.categoryId = item.value await setDefaultData("category") await handleGetList() await toDetail() } }} onUpdate:show={(value: any) => { state.categoryShow = value }} trigger="click" class={"PopSelect"} > {state.categoryName}
)}
{ await handleGetList() await toDetail() }} /> {state.levelList.length ? ( { setDefaultData("level") await handleGetList() await toDetail() }} /> ) : null} {state.typeList.length > 0 ? ( { await handleGetList() await toDetail() }} /> ) : null}
(state.searchStatus = !state.searchStatus)} >
{state.searchStatus && ( { if (e.code === "Enter" || e.key === "Enter") { await handleGetList() await toDetail() } }} onHandleQuery={async () => { await handleGetList() await toDetail() }} clearable /> )}
{state.list.map((item: any, index: number) => (
{ state.listActive = index state.selectedPartIndex = 0 state.partXmlIndex = 0 await toDetail() resetRender() }} >
{ ;(e.target as any).dataset.loaded = "true" }} />
{ e.stopPropagation() handlePlay(item) if (state.listActive !== index) { resetRender() } }} > {state.listActive === index && ( <> {state.playState === "pause" ? "播放" : "暂停"} )} {state.listActive !== index && ( <> 播放 )}
))} {!state.list.length && !loading.value && ( )}
{/* */}
{activeItem.value.name} {activeItem.value.musicSheetType === "CONCERT" && state.selectedPartName ? `(${state.selectedPartName})` : ""}
{state.iframeSrc && activeItem.value?.id && ( )} {!loading.value && !activeItem.value?.id && ( )}
{ handleChangeAudio("pause") goToCloud(activeItem.value.id, state.partXmlIndex) }} />
{ console.log(value, "value") const item = partColumns.value.find((item: any) => item.value === value) state.selectedPartIndex = value state.selectedPartName = item.instrumentName state.partXmlIndex = item.xmlIndex nextTick(() => { resetRender() }) }} class={["PopSelect", "PopSelectPart"]} > {{ empty: () => "暂无数据", default: () => ( {{ trigger: () => , default: "切换声轨" }} ) }}
{/*
*/} {state.list.length !== 0 && activeItem.value.audioFileUrl && ( handleChangeAudio(value)} onShow={(status: boolean) => { state.showPlayer = status }} /> )}
) } })