index.tsx 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672
  1. import { Row, showToast, showConfirmDialog } from "vant";
  2. import { defineComponent, onMounted, onUnmounted, reactive, nextTick, ref } from "vue";
  3. import state from "/src/state";
  4. import request from "/src/utils/request";
  5. import { getQuery } from "/src/utils/queryString";
  6. import styles from "./index.module.less";
  7. import { Button, ButtonGroup, Icon, Switch, Tooltip } from "@varlet/ui";
  8. import "@varlet/ui/es/tooltip/style";
  9. import "@varlet/ui/es/button-group/style";
  10. import "@varlet/ui/es/switch/style";
  11. import { storeData } from "/src/store";
  12. import rightHideIcon from './image/right_hide_icon.png';
  13. import editIcon from './image/edit.png';
  14. import editCloseIcon from './image/edit_close.png';
  15. import editSaveIcon from './image/edit_save.png';
  16. import editPreIcon from './image/edit_pre.png';
  17. import editDeleteIcon from './image/edit_delete.png';
  18. import editResetIcon from './image/edit_reset.png';
  19. import editReduceIcon from './image/edit_reduce.png';
  20. import editAddIcon from './image/edit_add.png';
  21. let extStyleConfigJson: any = {};
  22. const clientWidth = window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth;
  23. const showToolBox = ref(true);
  24. export const moveData = reactive({
  25. /** 开启移动 */
  26. open: false,
  27. zoom: 1,
  28. partIndex: "0",
  29. hasExtJson: false,
  30. isWeb: false,
  31. modelList: [] as any[],
  32. activeIndex: -1,
  33. sw: 0,
  34. tool: {
  35. isAddAndSub: false,
  36. },
  37. noteCoords: [] as any[],
  38. });
  39. // 所以可点击音符的dom坐标集合
  40. const initNoteCoord = () => {
  41. const allNoteDot: any = Array.from(document.querySelectorAll('.node-dot'));
  42. moveData.noteCoords = allNoteDot.map((note: any) => {
  43. const note_bbox = note?.getBoundingClientRect?.() || { x: 0, y: 0 };
  44. return {
  45. x: note_bbox.x,
  46. y: note_bbox.y
  47. }
  48. })
  49. }
  50. // 找出离目标元素最近的音符
  51. const computedDistance = (x: number, y: number) => {
  52. let minDistance = -1, minidx = 0;
  53. let a, b, c;
  54. moveData.noteCoords.forEach((note: any, idx: any) => {
  55. //a,b为直角三角形的两个直角边
  56. a = Math.abs(note.x - x)
  57. b = Math.abs(note.y - y)
  58. //c为直角三角形的斜边
  59. c = Math.sqrt(a * a + b * b) as 0
  60. c = Number(c.toFixed(0)) as 0
  61. if (c !== 0 && (minDistance === - 1 || c < minDistance)) {
  62. //min为元素中离目标元素最近元素的距离
  63. minDistance = c
  64. minidx = idx
  65. }
  66. })
  67. return minidx
  68. }
  69. function initSvgId() {
  70. const svg = document.querySelector("#osmdSvgPage1");
  71. if (!svg) return;
  72. const vfstavetempo: HTMLElement[] = Array.from(svg.querySelectorAll(".vf-stavetempo"));
  73. const vftext: HTMLElement[] = Array.from(svg.querySelectorAll(".vf-text"));
  74. const vfstaveSection: HTMLElement[] = Array.from(svg.querySelectorAll(".vf-StaveSection"));
  75. const vfRepetition: HTMLElement[] = Array.from(svg.querySelectorAll(".vf-Repetition"));
  76. const vflineGroup: HTMLElement[] = Array.from(svg.querySelectorAll(".vf-lineGroup"));
  77. // console.log('速度标记',vfstavetempo)
  78. let tempIndex = 1;
  79. [...vfstavetempo].forEach((ele) => {
  80. setEleId(ele, "temp" + tempIndex);
  81. tempIndex++;
  82. });
  83. let textIndex = 1;
  84. [...vftext].forEach((ele) => {
  85. // console.log(ele.textContent,textIndex)
  86. setEleId(ele, "text" + textIndex);
  87. textIndex++;
  88. });
  89. let sectionIndex = 1;
  90. [...vfstaveSection].forEach((ele) => {
  91. setEleId(ele, "section" + sectionIndex);
  92. sectionIndex++;
  93. });
  94. let repIndex = 1;
  95. [...vfRepetition].forEach((ele) => {
  96. setEleId(ele, "repet" + repIndex);
  97. repIndex++;
  98. });
  99. let lineIndex = 1;
  100. [...vflineGroup].forEach((ele) => {
  101. setEleId(ele, "line" + lineIndex);
  102. lineIndex++;
  103. });
  104. // if (moveData.isWeb) {
  105. // readerModelBox();
  106. // }
  107. // if (moveData.hasExtJson) {
  108. // setTimeout(reloadReader, 2);
  109. // }
  110. }
  111. /**赋值id */
  112. function setEleId(ele: HTMLElement, eleId: string) {
  113. if (!ele || !eleId) return;
  114. const id = ele.getAttribute("id");
  115. if (!id) {
  116. ele.setAttribute("id", eleId);
  117. }
  118. createModelBox(ele as any, eleId as any);
  119. }
  120. function createModelBox(ele: SVGAElement, eleId?: any) {
  121. const musicContainer = document.getElementById("musicAndSelection")?.getBoundingClientRect() || { x: 0, y: 0 };
  122. const parentLeft = musicContainer.x || 0;
  123. const parentTop = musicContainer.y || 0;
  124. const noteBbox = ele.getBoundingClientRect();
  125. const bbox = {
  126. left: noteBbox.x - parentLeft + "px",
  127. top: noteBbox.y - parentTop + "px",
  128. width: noteBbox.width + "px",
  129. height: noteBbox.height + "px",
  130. };
  131. const type = ele.getAttribute("class");
  132. moveData.modelList.push({
  133. id: eleId || ele.getAttribute("id"),
  134. bbox,
  135. type,
  136. isMove: false,
  137. left: noteBbox.left,
  138. top: noteBbox.top,
  139. width: noteBbox.width,
  140. height: noteBbox.height,
  141. x: 0,
  142. y: 0,
  143. zoom: state.zoom,
  144. isDelete: false,
  145. d2: getLineGroupPathDx(ele as any),
  146. dx: 0,
  147. });
  148. }
  149. function getBox(ele: SVGAElement) {
  150. if (!ele) return {};
  151. const musicContainer = document.getElementById("musicAndSelection")?.getBoundingClientRect() || { x: 0, y: 0 };
  152. const parentLeft = musicContainer.x || 0;
  153. const parentTop = musicContainer.y || 0;
  154. const box = ele.getBoundingClientRect();
  155. return {
  156. left: box.x - parentLeft,
  157. top: box.y - parentTop,
  158. width: box.width,
  159. height: box.height,
  160. };
  161. }
  162. // 切换开关
  163. const switchMoveState = () => {
  164. // 如果编辑过,没有保存,点击取消状态,需要提醒用户是否取消
  165. if (moveData.open && undoData.undoList.length) {
  166. showConfirmDialog({
  167. className: "noSaveModal",
  168. title: "温馨提示",
  169. message: "您有新的修改还未保存,取消后本次编辑的内容将不会保存",
  170. }).then(() => {
  171. moveData.open = false
  172. });
  173. } else {
  174. moveData.open = !moveData.open
  175. }
  176. }
  177. // 过滤数据
  178. export const filterMoveData = async () => {
  179. const examSongId = state.examSongId;
  180. if (examSongId) {
  181. const fontSize = (window as any).fontSize
  182. const list = moveData.modelList
  183. .filter((n) => n.isMove)
  184. .map((n) => {
  185. /**
  186. * 找到移动后,此时与此元素距离最近的音符,并记录音符的索引和此元素与音符的x轴,y轴的间距
  187. */
  188. // 元素的位置
  189. const elementX = n.left + n.x, elementY = n.top + n.y;
  190. // 找出距离元素最近的音符
  191. const noteIdx = computedDistance(elementX, elementY);
  192. // 此元素距离最近音符的x轴,y轴距离
  193. const noteRelativeX = elementX - moveData.noteCoords[noteIdx]?.x, noteRelativeY = elementY - moveData.noteCoords[noteIdx]?.y;
  194. let item: any = {
  195. id: n.id,
  196. isMove: n.isMove,
  197. isDelete: n.isDelete,
  198. x: n.x,
  199. y: n.y,
  200. xRem: Math.abs(n.x / fontSize),
  201. yRem: Math.abs(n.y / fontSize),
  202. zoom: n.zoom,
  203. w: moveData.sw,
  204. type: n.type,
  205. noteIdx,
  206. noteRelativeX,
  207. noteRelativeY
  208. };
  209. if (n.type === "vf-lineGroup") {
  210. item.dx = n.dx;
  211. }
  212. if (n.id.includes('text')) {
  213. // let copyDom = document.querySelector("#" + n.id)!.cloneNode(true) as SVGSVGElement
  214. const textContent = document.querySelector("#" + n.id)?.querySelector("text")?.innerHTML || ''
  215. item.textContent = textContent
  216. }
  217. return item;
  218. });
  219. // if (!list.length) {
  220. // showToast("请移动元素后再保存");
  221. // return
  222. // }
  223. extStyleConfigJson[moveData.partIndex] = list;
  224. console.log("🚀 ~ extStyleConfigJson", extStyleConfigJson)
  225. const res = await request.post("/musicSheet/img", {
  226. requestType: "json",
  227. data: {
  228. id: examSongId,
  229. extStyleConfigJson: JSON.stringify(extStyleConfigJson),
  230. }
  231. });
  232. if (res && res.code == 200) {
  233. showToast("保存成功");
  234. undoData.undoList = [];
  235. undoData.activeItem = null;
  236. state.extStyleConfigJson = JSON.stringify(extStyleConfigJson)
  237. }
  238. clearActiveModel();
  239. }
  240. };
  241. // 移动
  242. const dragData = {
  243. open: false,
  244. startX: 0,
  245. startY: 0,
  246. x: 0,
  247. y: 0,
  248. repeatEdit: false,
  249. };
  250. // 记录
  251. export const undoData = reactive({
  252. undoList: [] as Array<any>, // 撤销列表
  253. redoList: [] as Array<any>, // 回退列表
  254. activeItem: null,
  255. });
  256. function onDown(e: MouseEvent) {
  257. const el: any = e.target;
  258. const index = moveData.modelList.findIndex((n) => n.id === el.dataset.id);
  259. if (index > -1) {
  260. const item = moveData.modelList[index];
  261. moveData.activeIndex = index;
  262. dragData.startX = e.clientX;
  263. dragData.startY = e.clientY;
  264. dragData.x = item.x;
  265. dragData.y = item.y;
  266. dragData.repeatEdit = item.noteIdx >= 0 ? true : false;
  267. // console.log("🚀 ~ 按下", index, el, item.x, item.y);
  268. document.onmousemove = onMove;
  269. document.onmouseup = onUp;
  270. dragData.open = true;
  271. if (item.type === "vf-lineGroup") {
  272. moveData.tool.isAddAndSub = true;
  273. } else {
  274. moveData.tool.isAddAndSub = false;
  275. }
  276. undoData.activeItem = { ...item };
  277. return;
  278. }
  279. moveData.activeIndex = -1;
  280. }
  281. function onMove(e: MouseEvent) {
  282. if (dragData.open) {
  283. const _x = e.clientX - dragData.startX + dragData.x;
  284. const _y = e.clientY - dragData.startY + dragData.y;
  285. setModelPostion(moveData.modelList[moveData.activeIndex], _x, _y, dragData.repeatEdit);
  286. }
  287. }
  288. function onUp(e: MouseEvent) {
  289. // console.log("🚀 ~ 抬起");
  290. document.onmousemove = null;
  291. document.onmouseup = null;
  292. dragData.open = false;
  293. const _x = e.clientX - dragData.startX + dragData.x;
  294. const _y = e.clientY - dragData.startY + dragData.y;
  295. if (_x || _y) {
  296. moveData.modelList[moveData.activeIndex].isMove = true;
  297. moveData.modelList[moveData.activeIndex].x = _x;
  298. moveData.modelList[moveData.activeIndex].y = _y;
  299. if (undoData.activeItem) {
  300. undoData.undoList.push({ ...(undoData.activeItem as any) });
  301. }
  302. }
  303. undoData.activeItem = null;
  304. }
  305. /** 渲染svg元素的属性 */
  306. const renderSvgItem = (item: any) => {
  307. setModelPostion(item, item.x, item.y);
  308. if (item.isDelete) {
  309. const g = document.querySelector("#" + item.id)!;
  310. g && ((g as any).style.display = "none");
  311. } else {
  312. const g = document.querySelector("#" + item.id)!;
  313. g && ((g as any).style.display = "");
  314. }
  315. };
  316. /** 设置元素位置 */
  317. async function setModelPostion(item: any, x: number, y: number, repeatEdit?: boolean) {
  318. // console.log(item)
  319. //console.log('位置',x,y)
  320. if (item) {
  321. const g = document.querySelector("#" + item.id)!; // svg元素
  322. const el: HTMLElement = document.querySelector(`[data-id=${item.id}]`)!; // svg元素的背景div
  323. if (x === 0 && y === 0) {
  324. g && g.removeAttribute("transform");
  325. el && (el.style.transform = "");
  326. } else {
  327. /** 如果是app内嵌打开,需要通过rem转换 */
  328. let tsX = x, tsY = y;
  329. // if (storeData.isApp && (item.xRem || item.yRem)) {
  330. // tsX = item.xRem * clientWidth/10
  331. // tsY = item.yRem * clientWidth/10
  332. // }
  333. if (item.noteIdx >= 0 && !repeatEdit) {
  334. if (!moveData.noteCoords.length) {
  335. await initNoteCoord()
  336. }
  337. const targetX = moveData.noteCoords[item.noteIdx].x + item.noteRelativeX, targetY = moveData.noteCoords[item.noteIdx].y + item.noteRelativeY;
  338. const original = document.getElementById(item.id)?.getBoundingClientRect() || { x: 0, y: 0 };
  339. tsX = targetX - original.x;
  340. tsY = targetY - original.y;
  341. // console.log('距离',tsX,tsY,x,y)
  342. g && g.setAttribute("transform", `translate(${tsX / moveData.zoom}, ${tsY / moveData.zoom})`);
  343. el && (el.style.transform = `translate(${tsX}px, ${tsY}px)`);
  344. } else {
  345. g && g.setAttribute("transform", `translate(${tsX / moveData.zoom}, ${tsY / moveData.zoom})`);
  346. el && (el.style.transform = `translate(${tsX}px, ${tsY}px)`);
  347. }
  348. }
  349. }
  350. }
  351. /** 删除元素 */
  352. const handleDeleteMoveNote = () => {
  353. const item = moveData.modelList[moveData.activeIndex];
  354. if (item) {
  355. moveData.modelList[moveData.activeIndex].isMove = true;
  356. undoData.undoList.push({ ...moveData.modelList[moveData.activeIndex] });
  357. moveData.modelList[moveData.activeIndex].isDelete = !item.isDelete;
  358. const g = document.querySelector("#" + item.id)!;
  359. g && ((g as any).style.display = moveData.modelList[moveData.activeIndex].isDelete ? "none" : '');
  360. } else {
  361. showToast("选中需要删除的元素");
  362. }
  363. };
  364. /** 重置数据 */
  365. const resetMoveNote = () => {
  366. for (let i = 0; i < moveData.modelList.length; i++) {
  367. moveData.modelList[i].x = 0;
  368. moveData.modelList[i].y = 0;
  369. moveData.modelList[i].isMove = false;
  370. moveData.modelList[i].isDelete = false;
  371. moveData.modelList[i].dx = 0;
  372. renderSvgItem(moveData.modelList[i]);
  373. if (moveData.modelList[i].type === "vf-lineGroup") {
  374. renderLineGroup(moveData.modelList[i]);
  375. }
  376. }
  377. clearActiveModel();
  378. };
  379. function clearActiveModel() {
  380. for (let i = 0; i < moveData.modelList.length; i++) {
  381. const item: HTMLElement = document.querySelector(`[data-id=${moveData.modelList[i].id}]`)!;
  382. if (item?.classList?.contains("activeModel")) {
  383. item.classList.remove("activeModel");
  384. }
  385. }
  386. moveData.activeIndex = -1;
  387. moveData.tool.isAddAndSub = false;
  388. }
  389. // 增加或减少, 渐强和渐弱的线长
  390. const handleAddAndSub = (type: 'add' | 'sub') => {
  391. if (!["add", "sub"].includes(type)) return;
  392. const lineGroup = moveData.modelList[moveData.activeIndex];
  393. if (!lineGroup || lineGroup.type !== "vf-lineGroup") return;
  394. lineGroup.isMove = true;
  395. const step = type === "add" ? 10 : -10;
  396. undoData.undoList.push({ ...moveData.modelList[moveData.activeIndex] });
  397. moveData.modelList[moveData.activeIndex].dx = lineGroup.dx + step;
  398. renderLineGroup(moveData.modelList[moveData.activeIndex]);
  399. };
  400. // 获取line的dx
  401. function getLineGroupPathDx(lineGroup: HTMLElement) {
  402. if (!lineGroup) return 0;
  403. const lines = lineGroup.querySelectorAll("path");
  404. if (lines?.length) {
  405. for (let i = 0; i < lines.length; i++) {
  406. const path = lines[i];
  407. let d = path.getAttribute("d");
  408. if (d) {
  409. let dx1: any = d.split("M")?.[1]?.split(" ") || [];
  410. let dx2: any = d.split("L")?.[1]?.split(" ") || [];
  411. dx1 = dx1[0] && !isNaN(Number(dx1[0])) ? Number(dx1[0]) : 0;
  412. dx2 = dx2[0] && !isNaN(Number(dx2[0])) ? Number(dx2[0]) : 0;
  413. if (dx1 && dx2) {
  414. if (dx1 < dx2) {
  415. return dx2;
  416. } else {
  417. return dx1;
  418. }
  419. }
  420. }
  421. }
  422. }
  423. return 0;
  424. }
  425. function renderLineGroup(lineGroup: any) {
  426. const group = document.querySelector("#" + lineGroup.id);
  427. if (!group) return;
  428. const lines = group.querySelectorAll("path");
  429. if (lines?.length) {
  430. for (let i = 0; i < lines.length; i++) {
  431. const path = lines[i];
  432. let d = path.getAttribute("d");
  433. if (d) {
  434. let dx1: any = d.split("M")?.[1]?.split(" ") || [];
  435. let dx2: any = d.split("L")?.[1]?.split(" ") || [];
  436. dx1 = dx1[0] && !isNaN(Number(dx1[0])) ? Number(dx1[0]) : 0;
  437. dx2 = dx2[0] && !isNaN(Number(dx2[0])) ? Number(dx2[0]) : 0;
  438. if (dx1 && dx2) {
  439. if (dx1 < dx2) {
  440. d = d.replace(dx2, lineGroup.d2 + lineGroup.dx + "");
  441. } else {
  442. d = d.replace(dx1, lineGroup.d2 + lineGroup.dx + "");
  443. }
  444. path.setAttribute("d", d);
  445. }
  446. }
  447. }
  448. const { width } = getBox(group as any);
  449. const div: HTMLElement = document.querySelector(`[data-id=${lineGroup.id}]`)!;
  450. div && (div.style.width = width + "px");
  451. }
  452. }
  453. /** 撤销 */
  454. const handleUndo = () => {
  455. const preItem = undoData.undoList.pop();
  456. // console.log("🚀 ~ preItem", preItem)
  457. if (preItem) {
  458. const itemIndex = moveData.modelList.findIndex((n: any) => n.id === preItem.id);
  459. if (itemIndex > -1) {
  460. moveData.modelList[itemIndex] = preItem;
  461. renderSvgItem(moveData.modelList[itemIndex])
  462. if (preItem.type === "vf-lineGroup") {
  463. renderLineGroup(preItem);
  464. }
  465. }
  466. }
  467. };
  468. /** 根据移动数据渲染 */
  469. export const renderForMoveData = () => {
  470. if (state.isSingleLine || state.musicRenderType !== 'staff') return;
  471. if (state.extStyleConfigJson) {
  472. try {
  473. extStyleConfigJson = JSON.parse(state.extStyleConfigJson);
  474. } catch (error) {
  475. extStyleConfigJson = {};
  476. }
  477. }
  478. if (!extStyleConfigJson || !extStyleConfigJson?.[moveData.partIndex]){
  479. initSvgId();
  480. return
  481. } else {
  482. initSvgId();
  483. }
  484. const list = extStyleConfigJson?.[moveData.partIndex];
  485. if (list && Array.isArray(list)) {
  486. nextTick(() => {
  487. console.log("🚀 ~ list", list);
  488. list.forEach((item: any) => {
  489. let index = moveData.modelList.findIndex((n: any) => n.id === item.id);
  490. if (item.type === 'vf-text' && item.textContent) {
  491. let textValue = document.querySelector("#" + moveData.modelList[index]?.id)?.querySelector("text")?.innerHTML || ''
  492. let targetIndex = index, preEnd = false, done = false, preIndex = index, nextIndex = index;
  493. // while (textValue !== item.textContent) {
  494. // if (preEnd) {
  495. // targetIndex = targetIndex + 1
  496. // } else {
  497. // targetIndex = targetIndex > 0 ? targetIndex - 1 : targetIndex
  498. // }
  499. // if (targetIndex == 0) preEnd = true
  500. // textValue = document.querySelector("#" + moveData.modelList[targetIndex].id)?.querySelector("text")?.innerHTML || ''
  501. // }
  502. if (textValue !== item.textContent) {
  503. while (!done) {
  504. let text1 = moveData.modelList[preIndex] ? document.querySelector("#" + moveData.modelList[preIndex].id)?.querySelector("text")?.innerHTML || '' : ''
  505. let text2 = moveData.modelList[nextIndex] ? document.querySelector("#" + moveData.modelList[nextIndex].id)?.querySelector("text")?.innerHTML || '' : ''
  506. if (text1 === item.textContent || text2 === item.textContent) {
  507. done = true
  508. targetIndex = text1 === item.textContent ? preIndex : nextIndex
  509. } else {
  510. // 有可能后台编辑的元素在部分屏幕尺寸下没有该元素,比如小节索引数,可能后台显示的是1,3,5,部分屏幕尺寸显示的1,3,6
  511. if (!text1 && !text2) {
  512. done = true
  513. targetIndex = -1
  514. }
  515. preIndex = preIndex - 1
  516. nextIndex = nextIndex + 1
  517. }
  518. }
  519. }
  520. index = targetIndex
  521. item.id = moveData.modelList[targetIndex].id
  522. }
  523. // console.log(66666666,index)
  524. if (index > -1) {
  525. moveData.modelList[index] = {
  526. ...moveData.modelList[index],
  527. ...item
  528. };
  529. renderSvgItem(moveData.modelList[index]);
  530. if (item.type === "vf-lineGroup") {
  531. renderLineGroup(moveData.modelList[index]);
  532. }
  533. }
  534. });
  535. });
  536. }
  537. };
  538. export default defineComponent({
  539. name: "move-music-score",
  540. setup() {
  541. moveData.zoom = state.zoom;
  542. const query = getQuery();
  543. const isOpen = query.isMove === "1" ? true : false;
  544. console.log("🚀 ~ isOpen:", isOpen);
  545. onMounted(() => {
  546. // if (isOpen) {
  547. // initSvgId();
  548. // }
  549. // renderForMoveData();
  550. moveData.modelList = []
  551. nextTick(() => initNoteCoord())
  552. // const hasToolDom = Array.from(document.body.children)?.some((item: any) => item?.id === 'toolBox')
  553. // if (!hasToolDom) {
  554. // const toolBox = document.getElementById("toolBox");
  555. // toolBox && document.body.appendChild(toolBox);
  556. // }
  557. const toolBox = document.getElementById("toolBox");
  558. toolBox && document.body.appendChild(toolBox);
  559. });
  560. onUnmounted(() => {
  561. moveData.modelList = []
  562. const toolBox = document.getElementById("toolBox");
  563. toolBox && document.body.removeChild(toolBox);
  564. })
  565. return () => (
  566. <div class={[moveData.open ? "" : styles.moveDisabled]}>
  567. <div id="toolBox">
  568. {/* <div class={[styles.toolBox, !showToolBox.value && styles.hideTool]} >
  569. <Switch v-model={moveData.open} />
  570. {moveData.open && (
  571. <>
  572. {moveData.tool.isAddAndSub && (
  573. <ButtonGroup size="small" elevation={false}>
  574. <Button onClick={() => handleAddAndSub('add')}>加</Button>
  575. <Button onClick={() => handleAddAndSub('sub')}>减</Button>
  576. </ButtonGroup>
  577. )}
  578. <Button size="small" onClick={handleUndo} disabled={undoData.undoList.length ? false : true}>
  579. <Icon name="arrow-down" style={{ transform: "rotate(90deg)" }} />
  580. </Button>
  581. <Button size="small" onClick={handleDeleteMoveNote} disabled={moveData.activeIndex > -1 ? false : true}>
  582. {moveData.modelList[moveData.activeIndex]?.isDelete ? '显示元素' : '删除元素'}
  583. </Button>
  584. <Button size="small" onClick={resetMoveNote}>
  585. 重置数据
  586. </Button>
  587. <Button size="small" type="primary" onClick={filterMoveData}>
  588. 保存数据
  589. </Button>
  590. <Button size="small" type="primary" onClick={() => showToolBox.value = false}>
  591. 收起
  592. </Button>
  593. </>
  594. )}
  595. </div>
  596. {
  597. !showToolBox.value &&
  598. <img
  599. class={[styles.rightHideIcon, !showToolBox.value ? styles.rightIconShow : '']}
  600. src={rightHideIcon}
  601. onClick={() => showToolBox.value = true } />
  602. } */}
  603. <div class={[styles.editToolBox, !moveData.open && styles.itemDisabled]}>
  604. {
  605. state.musicRenderType === 'staff' && !state.isSingleLine &&
  606. <>
  607. <div class={[styles.editItem, styles.canEdit]} onClick={switchMoveState}>
  608. <img src={moveData.open ? editCloseIcon : editIcon} />
  609. <span>{moveData.open ? '取消' : '编辑'}</span>
  610. </div>
  611. <div class={styles.editItem} onClick={filterMoveData}>
  612. <img src={editSaveIcon} />
  613. <span>保存</span>
  614. </div>
  615. <div class={[styles.editItem, !undoData.undoList.length && styles.disabled]} onClick={handleUndo}>
  616. <img src={editPreIcon} />
  617. <span>撤回</span>
  618. </div>
  619. <div class={[styles.editItem, moveData.activeIndex <= -1 && styles.disabled]} onClick={handleDeleteMoveNote}>
  620. <img src={editDeleteIcon} />
  621. <span>{moveData.modelList[moveData.activeIndex]?.isDelete ? '回显' : '删除'}</span>
  622. </div>
  623. <div class={styles.editItem} onClick={resetMoveNote}>
  624. <img src={editResetIcon} />
  625. <span>重置</span>
  626. </div>
  627. {
  628. moveData.tool.isAddAndSub &&
  629. <div class={styles.extraItem}>
  630. <img src={editReduceIcon} onClick={() => handleAddAndSub('sub')} />
  631. <img src={editAddIcon} onClick={() => handleAddAndSub('add')} />
  632. </div>
  633. }
  634. </>
  635. }
  636. </div>
  637. </div>
  638. {moveData.modelList.map((item: any, index: number) => {
  639. return (
  640. <div class={[styles.noteMove, moveData.activeIndex === index && styles.activeModel]} style={item.bbox} data-id={item.id} onMousedown={onDown}></div>
  641. );
  642. })}
  643. </div>
  644. );
  645. },
  646. });