index.vue 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620
  1. <template>
  2. <div class="m-container">
  3. <!-- <h2>
  4. <div class="squrt"></div>
  5. 教学伴奏
  6. </h2> -->
  7. <div class="m-core">
  8. <el-button
  9. @click="open('COMMON')"
  10. type="primary"
  11. v-permission="'musicSheetApplicationExtend/saveBatch'"
  12. >添加曲目</el-button
  13. >
  14. <saveform
  15. ref="searchForm"
  16. :model.sync="searchForm"
  17. inline
  18. style="margin-top: 20px"
  19. >
  20. <el-form-item prop="search">
  21. <el-input
  22. v-model="searchForm.search"
  23. @submit="submit"
  24. @reset="reset"
  25. @keyup.enter.native="
  26. e => {
  27. e.target.blur();
  28. $refs.searchForm.save();
  29. submit();
  30. }
  31. "
  32. clearable
  33. placeholder="伴奏编号/伴奏名称"
  34. />
  35. </el-form-item>
  36. <el-form-item prop="categoriesId">
  37. <el-cascader
  38. ref="myCascader"
  39. popper-class="myCascader"
  40. @change="changeCategor"
  41. :show-all-levels="true"
  42. clearable
  43. v-model="searchForm.categoriesId"
  44. style="width: 100%"
  45. :options="tree"
  46. placeholder="请选择分类"
  47. :props="treeProps"
  48. ></el-cascader>
  49. </el-form-item>
  50. <el-form-item prop="subjectId">
  51. <el-select
  52. v-model="searchForm.subjectId"
  53. clearable
  54. placeholder="请选择声部"
  55. >
  56. <el-option
  57. v-for="item in selects.subjects"
  58. :value="item.id"
  59. :label="item.name"
  60. :key="item.id"
  61. ></el-option>
  62. </el-select>
  63. </el-form-item>
  64. <el-form-item prop="rankType">
  65. <el-select
  66. v-model="searchForm.rankType"
  67. clearable
  68. filterable
  69. placeholder="请选择是否收费"
  70. >
  71. <el-option :value="0" label="免费"></el-option>
  72. <el-option :value="1" label="收费"></el-option>
  73. </el-select>
  74. </el-form-item>
  75. <el-form-item prop="showFlag">
  76. <el-select
  77. v-model="searchForm.showFlag"
  78. clearable
  79. filterable
  80. placeholder="请选择状态"
  81. >
  82. <el-option :value="1" label="启用"></el-option>
  83. <el-option :value="0" label="停用"></el-option>
  84. </el-select>
  85. </el-form-item>
  86. <el-form-item>
  87. <el-button @click="submit" type="primary">搜索</el-button>
  88. <el-button @click="reset" type="danger">重置</el-button>
  89. <!-- <el-button
  90. @click="onExport"
  91. type="primary"
  92. v-permission="'export/exportMusicScoreList'"
  93. >导出</el-button
  94. > -->
  95. </el-form-item>
  96. </saveform>
  97. <el-table
  98. style="width: 100%"
  99. :header-cell-style="{ background: '#EDEEF0', color: '#444' }"
  100. :data="tableList"
  101. >
  102. <el-table-column
  103. align="center"
  104. prop="cbsMusicSheetId"
  105. label="编号"
  106. width="120px"
  107. >
  108. <template slot-scope="scope">
  109. <div>
  110. <copy-text>{{ scope.row.cbsMusicSheetId }}</copy-text>
  111. </div>
  112. </template>
  113. </el-table-column>
  114. <el-table-column align="center" prop="name" label="名称" width="180px">
  115. <template slot-scope="scope">
  116. <div>
  117. <copy-text>{{ scope.row.name }}</copy-text>
  118. </div>
  119. </template>
  120. </el-table-column>
  121. <el-table-column
  122. align="center"
  123. prop="subjectName"
  124. label="所属声部"
  125. width="180px"
  126. >
  127. <template slot-scope="scope">
  128. <div>
  129. <Tooltip :content="scope.row.subjectName" />
  130. </div>
  131. </template>
  132. </el-table-column>
  133. <el-table-column align="center" prop="type" label="类型">
  134. <template slot-scope="scope">
  135. {{ scope.row.type | songUseTypeFormat }}
  136. </template>
  137. </el-table-column>
  138. <el-table-column
  139. align="center"
  140. prop="categoriesName"
  141. label="分类"
  142. width="180px"
  143. />
  144. <el-table-column align="center" label="是否收费">
  145. <template slot-scope="scope">
  146. {{ scope.row.rankIds ? "收费" : "免费" }}
  147. </template>
  148. </el-table-column>
  149. <el-table-column align="center" label="状态">
  150. <template slot-scope="scope">
  151. {{ scope.row.showFlag ? "启用" : "停用" }}
  152. </template>
  153. </el-table-column>
  154. <el-table-column align="center" prop="createUserName" label="上传人" />
  155. <el-table-column align="center" prop="createTime" label="上传时间" />
  156. <el-table-column
  157. align="center"
  158. width="180px"
  159. label="操作"
  160. fixed="right"
  161. >
  162. <template slot-scope="scope">
  163. <el-button type="text" @click="looker(scope.row, 1)"
  164. >预览</el-button
  165. >
  166. <el-button
  167. v-permission="'musicSheetApplicationExtend/status'"
  168. type="text"
  169. @click="changeStatus(scope.row)"
  170. >{{ scope.row.showFlag ? "停用" : "启用" }}</el-button
  171. >
  172. <!-- <el-button
  173. type="text"
  174. @click="transcod(scope.row)"
  175. :disabled="!!scope.row.showFlag"
  176. v-permission="'sysMusicScore/transcod'"
  177. >转码</el-button
  178. > -->
  179. <el-button
  180. type="text"
  181. @click="edit(scope.row)"
  182. :disabled="!!scope.row.showFlag"
  183. v-permission="'sysMusicScore/update'"
  184. >修改</el-button
  185. >
  186. <!-- <el-button
  187. type="text"
  188. @click="remove(scope.row)"
  189. v-permission="'sysMusicScore/del'"
  190. >删除</el-button
  191. > -->
  192. </template>
  193. </el-table-column>
  194. </el-table>
  195. <pagination
  196. sync
  197. :total.sync="rules.total"
  198. :page.sync="rules.page"
  199. :limit.sync="rules.limit"
  200. :page-sizes="rules.page_size"
  201. @pagination="FetchList"
  202. />
  203. </div>
  204. <el-dialog :title="title" :visible.sync="visible" width="1100px">
  205. <EditMusic
  206. v-if="visible"
  207. :tree="this.tree"
  208. @close="visible = false"
  209. @getList="FetchList"
  210. />
  211. </el-dialog>
  212. <el-dialog title="修改曲谱" :visible.sync="muiscVisible" width="500px">
  213. <EditExtra
  214. v-if="muiscVisible"
  215. :tree="this.tree"
  216. :detail="detail"
  217. @close="muiscVisible = false"
  218. @getList="FetchList"
  219. />
  220. </el-dialog>
  221. <el-dialog
  222. v-if="lookVisible"
  223. width="667px"
  224. class="lookForm"
  225. :visible.sync="lookVisible"
  226. title="预览"
  227. >
  228. <template slot="title">
  229. <span style="color: #fff;">预览</span>
  230. <el-select
  231. v-model="selectPart"
  232. placeholder="请选择分谱"
  233. @change="onPartChange"
  234. >
  235. <el-option
  236. v-for="(item, index) in parts"
  237. :key="item"
  238. :label="item"
  239. :value="index"
  240. >
  241. </el-option>
  242. </el-select>
  243. </template>
  244. <iframe
  245. id="iframe"
  246. v-if="lookVisible"
  247. style="width: 667px; height: 386px"
  248. ref="iframe"
  249. :src="accompanyUrl"
  250. />
  251. <div class="iframe_back"></div>
  252. <div class="iframe_help"></div>
  253. <div class="iframe_header_back"></div>
  254. </el-dialog>
  255. </div>
  256. </template>
  257. <script>
  258. import saveform from "@/components/save-form";
  259. import pagination from "@/components/Pagination/index";
  260. import { songUseType } from "@/constant";
  261. import {
  262. QueryPage,
  263. Del,
  264. api_sysMusicScoreState,
  265. queryTree,
  266. Transcod,
  267. musicSheetApplicationExtendStatus
  268. } from "./api";
  269. import form from "./modals/form";
  270. import EditMusic from "./modals/edit-music";
  271. import EditExtra from "./modals/edit-extra";
  272. import { vaildTeachingUrl } from "@/utils/validate";
  273. import { getToken } from "@/utils/auth";
  274. import deepClone from "@/helpers/deep-clone/";
  275. import Tooltip from "@/components/Tooltip/index";
  276. import { Export } from "@/utils/downLoadFile";
  277. import qs from "qs";
  278. import cleanDeep from "clean-deep";
  279. export default {
  280. name: "accompaniment",
  281. components: {
  282. saveform,
  283. pagination,
  284. "submit-form": form,
  285. Tooltip,
  286. EditMusic,
  287. EditExtra
  288. },
  289. data() {
  290. return {
  291. parts: [],
  292. selectPart: 0,
  293. tabName: "first",
  294. type: "",
  295. activeUrl: "",
  296. songUseType,
  297. lookVisible: false,
  298. lookNum: 0,
  299. lookRow: {},
  300. accompanyUrl: null, // 预览地址
  301. accompanyUrl2: null, // 预览地址
  302. tableList: [],
  303. searchForm: {
  304. search: "",
  305. // type: "",
  306. subjectId: "",
  307. categoriesId: [],
  308. clientType: "",
  309. rankType: null,
  310. showFlag: null
  311. },
  312. rules: {
  313. // 分页规则
  314. limit: 10, // 限制显示条数
  315. page: 1, // 当前页
  316. total: 0, // 总条数
  317. page_size: [10, 20, 40, 50] // 选择限制显示条数
  318. },
  319. detail: null,
  320. visible: false,
  321. muiscVisible: false,
  322. tree: [],
  323. treeProps: {
  324. value: "id",
  325. label: "name",
  326. children: "sysMusicScoreCategoriesList",
  327. checkStrictly: true,
  328. expandTrigger: "hover"
  329. }
  330. };
  331. },
  332. computed: {
  333. title() {
  334. const t1 = this.detail ? "修改" : "添加";
  335. // let t2 = this.type === "COMMON" ? "公用" : "个人";
  336. // if (this.detail) {
  337. // t2 = this.detail.type === "COMMON" ? "公用" : "个人";
  338. // }
  339. return t1 + "曲目";
  340. }
  341. },
  342. async mounted() {
  343. const { query, params } = this.$route;
  344. await this.FetchTree();
  345. if (params.categoriesId) {
  346. // console.log(this.tree)
  347. // console.log(this.formatParentId(params.categoriesId, this.tree))
  348. this.searchForm.categoriesId = this.formatParentId(
  349. params.categoriesId,
  350. this.tree
  351. );
  352. }
  353. this.$store.dispatch("setSubjects");
  354. this.$store.dispatch("setBranchs");
  355. await this.FetchList();
  356. // 点击Cascader label选中
  357. },
  358. methods: {
  359. formatParentId(id, list, ids = []) {
  360. for (const item of list) {
  361. if (item.sysMusicScoreCategoriesList) {
  362. const cIds = this.formatParentId(
  363. id,
  364. item.sysMusicScoreCategoriesList,
  365. [...ids, item.id]
  366. );
  367. if (cIds.includes(id)) {
  368. return cIds;
  369. }
  370. }
  371. if (item.id === id) {
  372. return [...ids, id];
  373. }
  374. }
  375. return ids;
  376. },
  377. async FetchTree() {
  378. try {
  379. const res = await queryTree();
  380. this.tree = res.data;
  381. this.formatTree(this.tree);
  382. console.log(this.tree);
  383. } catch (error) {}
  384. },
  385. formatTree(data) {
  386. for (let i of data) {
  387. if (
  388. i.sysMusicScoreCategoriesList &&
  389. i.sysMusicScoreCategoriesList.length > 0
  390. ) {
  391. this.formatTree(i.sysMusicScoreCategoriesList, i);
  392. } else {
  393. i.sysMusicScoreCategoriesList = null;
  394. }
  395. }
  396. },
  397. async FetchList() {
  398. try {
  399. let { categoriesId, organId, ...search } = deepClone(this.searchForm);
  400. const res = await QueryPage({
  401. ...search,
  402. categoriesId:
  403. categoriesId && categoriesId.length > 0 ? categoriesId.pop() : null,
  404. page: this.rules.page,
  405. rows: this.rules.limit
  406. });
  407. this.tableList = res.data.rows;
  408. this.$set(this.rules, "total", res.data.total);
  409. } catch (error) {}
  410. },
  411. submit() {
  412. this.$set(this.rules, "page", 1);
  413. this.$refs.searchForm.validate(valid => {
  414. if (valid) {
  415. this.FetchList();
  416. }
  417. });
  418. },
  419. reset() {
  420. this.$refs.searchForm.resetFields();
  421. this.FetchList();
  422. },
  423. getPartListNames(xml) {
  424. if (!xml) return [];
  425. const xmlParse = new DOMParser().parseFromString(xml, "text/xml");
  426. const partList =
  427. xmlParse
  428. .getElementsByTagName("part-list")?.[0]
  429. ?.getElementsByTagName("score-part") || [];
  430. const partListNames = Array.from(partList).map(
  431. item => item.getElementsByTagName("part-name")?.[0].textContent || ""
  432. );
  433. this.xmlFirstSpeed =
  434. xmlParse.getElementsByTagName("per-minute")?.[0]?.textContent || "";
  435. return partListNames.filter(
  436. text => text.toLocaleUpperCase() !== "COMMON"
  437. );
  438. },
  439. async looker(row, num) {
  440. try {
  441. this.selectPart = 0;
  442. const res = await fetch(row.xmlUrl);
  443. const text = await res.text();
  444. this.parts = this.getPartListNames(text);
  445. } catch (error) {
  446. this.parts = [];
  447. this.selectPart = 0;
  448. }
  449. let url = location.origin + "/accompany-web/";
  450. if (/dayaedu.com/.test(location.origin)) {
  451. url = location.origin + "/accompany/";
  452. }
  453. this.accompanyUrl =
  454. url +
  455. "?Authorization=" +
  456. getToken() +
  457. "&platform=web" +
  458. "#/detail/" +
  459. row.id +
  460. "?part-index=" +
  461. this.selectPart;
  462. this.lookVisible = true;
  463. this.lookNum = num;
  464. this.lookRow = row;
  465. // this.$nextTick(() => {
  466. // console.log(this.$refs.iframe)
  467. // let iframe = this.$refs.iframe
  468. // iframe.onload = function() {
  469. // console.log('完成', iframe)
  470. // iframe.contentWindow.document.querySelector('#tips-step-0').style.display = 'none'
  471. // }
  472. // })
  473. },
  474. onPartChange(val) {
  475. let url = location.origin + "/accompany-web/";
  476. if (/dayaedu.com/.test(location.origin)) {
  477. url = location.origin + "/accompany/";
  478. }
  479. // url +
  480. this.accompanyUrl =
  481. url +
  482. "?Authorization=" +
  483. getToken() +
  484. "&platform=web&isOpenMetronome=" +
  485. this.lookNum +
  486. "&t=" +
  487. new Date().getTime() +
  488. "#/detail/" +
  489. this.lookRow.id +
  490. "?part-index=" +
  491. val;
  492. },
  493. async changeStatus(row) {
  494. try {
  495. let status = row.showFlag ? "停用" : "启用";
  496. await this.$confirm("是否确认" + status + "此曲目?", "提示", {
  497. type: "warning"
  498. });
  499. await api_sysMusicScoreState(row.id);
  500. this.$message.success(status + "成功");
  501. this.FetchList();
  502. } catch (error) {}
  503. },
  504. edit(row) {
  505. this.detail = row;
  506. this.muiscVisible = true;
  507. },
  508. async transcod(row) {
  509. try {
  510. const res = await Transcod(row);
  511. console.log(res);
  512. } catch (error) {}
  513. },
  514. open(type) {
  515. this.type = type;
  516. this.detail = null;
  517. this.visible = true;
  518. },
  519. async remove(row) {
  520. try {
  521. await this.$confirm("是否确认删除此伴奏?", "提示", {
  522. type: "warning"
  523. });
  524. await Del(row.id);
  525. this.$message.success("删除成功");
  526. this.FetchList();
  527. } catch (error) {}
  528. },
  529. changeCategor(e) {
  530. this.$refs.myCascader.dropDownVisible = false;
  531. },
  532. onExport() {
  533. let { categoriesId, organId, ...search } = deepClone(this.searchForm);
  534. Export(
  535. this,
  536. {
  537. url: "/api-web/export/exportMusicScoreList",
  538. params: {
  539. ...search,
  540. categoriesId:
  541. categoriesId && categoriesId.length > 0
  542. ? categoriesId.pop()
  543. : null
  544. },
  545. fileName: `教学伴奏导出.xls`,
  546. method: "get"
  547. },
  548. "确定导出教学伴奏"
  549. );
  550. }
  551. }
  552. };
  553. </script>
  554. <style lang="less" scoped>
  555. .myCascader {
  556. .el-radio {
  557. width: 100%;
  558. height: 100%;
  559. z-index: 10;
  560. position: absolute;
  561. top: 10px;
  562. right: 10px;
  563. }
  564. .el-radio__input {
  565. visibility: hidden;
  566. }
  567. .el-cascader-node__postfix {
  568. top: 10px;
  569. }
  570. }
  571. ::v-deep .el-dropdown {
  572. margin-right: 10px;
  573. color: #14928a;
  574. }
  575. .remark {
  576. display: inline;
  577. overflow: hidden;
  578. white-space: pre;
  579. }
  580. .lookForm {
  581. ::v-deep .el-dialog__body {
  582. padding: 0;
  583. }
  584. }
  585. .iframe_back {
  586. width: 195px;
  587. height: 45px;
  588. position: absolute;
  589. bottom: 50px;
  590. background: transparent;
  591. left: 50%;
  592. z-index: 99;
  593. margin-left: -100px;
  594. }
  595. .iframe_help {
  596. position: absolute;
  597. background: transparent;
  598. width: 50px;
  599. height: 120px;
  600. top: 50%;
  601. right: 0;
  602. margin-top: -35px;
  603. }
  604. .iframe_header_back {
  605. background: transparent;
  606. width: 225px;
  607. height: 50px;
  608. position: absolute;
  609. top: 65px;
  610. left: 20px;
  611. }
  612. </style>