index.tsx 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229
  1. import { defineComponent, nextTick, onMounted, onUnmounted, reactive, ref, watch } from "vue";
  2. import styles from "./index.module.less";
  3. import { NRadio, NSpace, NSpin, useDialog } from "naive-ui";
  4. import { getImage } from "../home/images";
  5. import TheCreate from "./component/the-create";
  6. import { storeData } from "/src/store";
  7. import { api_musicSheetCreationPage, api_musicSheetCreationRemove } from "../api";
  8. import ABCJS from "abcjs";
  9. import { usePageVisibility } from "@vant/use";
  10. import UploadToResources from "../component/upload-to-resources";
  11. import { getQuery } from "/src/utils/queryString";
  12. import { browser } from "/src/utils";
  13. import UploadToTasks from "../component/upload-to-tasks";
  14. import UploadFile from "../component/upload-file";
  15. import { saveUploadCatch, uploadState } from "../component/upload-to-tasks/state";
  16. export default defineComponent({
  17. name: "Create",
  18. setup() {
  19. const query = getQuery();
  20. const dialog = useDialog();
  21. console.log(storeData.user);
  22. const forms = reactive({
  23. teacherId: storeData.user.id,
  24. page: 1,
  25. keyword: "",
  26. rows: 20,
  27. });
  28. const data = reactive({
  29. list: [] as any[],
  30. addShow: query.addShow ? true : false,
  31. loading: false,
  32. finish: false,
  33. isCreated: false,
  34. uploadShow: false,
  35. item: {} as any,
  36. });
  37. const getList = async () => {
  38. data.loading = true;
  39. const res = await api_musicSheetCreationPage({ ...forms });
  40. if (res?.code == 200) {
  41. if (data.isCreated) {
  42. data.isCreated = false;
  43. handleOpenNotaion(res.data.rows[0]);
  44. }
  45. data.list = data.list.concat(res.data.rows);
  46. data.finish = res.data.rows.length < forms.rows;
  47. }
  48. data.loading = false;
  49. };
  50. const handleReset = () => {
  51. forms.page = 1;
  52. data.finish = false;
  53. data.list = [];
  54. getList();
  55. };
  56. const pageVisibility = usePageVisibility();
  57. watch(pageVisibility, (val) => {
  58. if (val === "visible") {
  59. handleReset();
  60. }
  61. });
  62. const handleDelte = (item: any) => {
  63. const checked = ref(true);
  64. dialog.warning({
  65. autoFocus: false,
  66. class: "deleteDialog",
  67. title: "删除曲谱",
  68. content: () => (
  69. <div onClick={() => (checked.value = !checked.value)}>
  70. <NRadio checked={checked.value}>同步删除我的资源中的该曲目</NRadio>
  71. </div>
  72. ),
  73. // content: () => <div>确认删除当前曲谱?</div>,
  74. positiveText: "取消",
  75. positiveButtonProps: {
  76. type: "default",
  77. },
  78. negativeText: "删除",
  79. negativeButtonProps: {
  80. type: "primary",
  81. ghost: false,
  82. },
  83. onPositiveClick: () => {},
  84. onNegativeClick: async () => {
  85. await api_musicSheetCreationRemove(item.id, checked.value ? 1 : 0);
  86. handleReset();
  87. // 删除上传记录里面的数据
  88. const index = uploadState.uploadList.findIndex((upload: any) => upload.musicSheetCreationId === item.id);
  89. if (index !== -1) {
  90. uploadState.uploadList.splice(index, 1);
  91. saveUploadCatch();
  92. }
  93. },
  94. });
  95. };
  96. const loadingRef = ref();
  97. const messageEvent = (params?: any) => {
  98. // 在老师端里面关闭要刷新
  99. if (params.data?.api == "reload") {
  100. handleReset();
  101. }
  102. };
  103. onMounted(() => {
  104. getList();
  105. if (loadingRef.value) {
  106. const obv = new IntersectionObserver((entries) => {
  107. if (entries[0].isIntersecting) {
  108. if (data.finish || data.loading) return;
  109. forms.page++;
  110. getList();
  111. }
  112. });
  113. obv.observe(loadingRef.value?.$el);
  114. }
  115. window.addEventListener("message", (params?: any) => {
  116. messageEvent(params);
  117. });
  118. });
  119. onUnmounted(() => {
  120. window.removeEventListener("message", messageEvent);
  121. });
  122. const handleOpenNotaion = (item: any) => {
  123. window.parent.postMessage(
  124. {
  125. api: "notation_open",
  126. url: `${location.origin}/notation/#/?v=${Date.now()}&id=${item.id}`,
  127. },
  128. "*"
  129. );
  130. };
  131. const productSvg = (abc: string, id: string) => {
  132. const a = ABCJS.renderAbc(id, abc, { selectTypes: false, add_classes: true })[0];
  133. return a;
  134. };
  135. const handleSuccess = () => {
  136. data.list.find((item: any) => item.id === data.item.id).uploadStatus = "YES";
  137. };
  138. return () => (
  139. <div class={styles.wrap}>
  140. <UploadFile />
  141. <div class={styles.wrapBox}>
  142. <div class={styles.itemWrap}>
  143. <div class={styles.itemWrapBox}>
  144. <div class={styles.createItem} onClick={() => (data.addShow = true)}>
  145. <img src={getImage("icon_29.png")} />
  146. <div>新建乐谱</div>
  147. </div>
  148. </div>
  149. </div>
  150. {data.list.map((item, index: number) => (
  151. <div class={styles.itemWrap}>
  152. <div class={styles.itemWrapBox}>
  153. <div class={styles.item} onClick={() => handleOpenNotaion(item)}>
  154. <div class={styles.imgBox} id={"item_" + index}>
  155. <img
  156. src={getImage("icon_staff.png")}
  157. onLoad={() => {
  158. item.visualObj = productSvg(item.creationConfig, "item_" + index);
  159. }}
  160. />
  161. </div>
  162. <div class={styles.itemBottom}>
  163. <div class={styles.bottombox}>
  164. <div class={styles.bottomLeft}>
  165. <div class={styles.itemtitle}>
  166. <span>{item.name || `未命名乐谱-${index + 1}`}</span>
  167. </div>
  168. <div class={styles.time}>{item.updateTime}</div>
  169. </div>
  170. {item.uploadStatus !== "YES" && (
  171. <img
  172. class={styles.bottomBtn}
  173. src={getImage("icon_29_2.png")}
  174. onClick={(e: Event) => {
  175. e.stopPropagation();
  176. data.item = { ...item };
  177. nextTick(() => {
  178. data.uploadShow = true;
  179. });
  180. }}
  181. />
  182. )}
  183. <img
  184. class={styles.bottomBtn}
  185. src={getImage("icon_29_3.png")}
  186. onClick={(e: Event) => {
  187. e.stopPropagation();
  188. handleDelte(item);
  189. }}
  190. />
  191. </div>
  192. </div>
  193. {item.uploadStatus === "YES" && <img class={styles.btn} src={getImage("icon_29_4.png")} />}
  194. {item.uploadStatus === "UPDATE" && <img class={styles.btn} src={getImage("icon_29_5.png")} />}
  195. </div>
  196. </div>
  197. </div>
  198. ))}
  199. </div>
  200. {!data.finish && (
  201. <NSpace ref={loadingRef} justify="center" style={{ padding: "30px" }}>
  202. <NSpin size="large" />
  203. </NSpace>
  204. )}
  205. <TheCreate
  206. v-model:show={data.addShow}
  207. onCreate={() => {
  208. data.addShow = false;
  209. }}
  210. />
  211. <UploadToResources v-model:show={data.uploadShow} item={data.item} onSuccess={() => handleSuccess()} />
  212. <UploadToTasks />
  213. </div>
  214. );
  215. },
  216. });