Browse Source

Merge branch 'iteration-20231220'

lex 1 year ago
parent
commit
c8d4706315

File diff suppressed because it is too large
+ 0 - 0
dist/assets/index-302c9360.js


File diff suppressed because it is too large
+ 0 - 0
dist/assets/index-legacy-8ca2c10c.js


+ 38 - 20
src/pc/api.ts

@@ -2,54 +2,72 @@ import request from "../utils/request";
 
 /** 获取学生信息 */
 export const studentQueryUserInfo = async () => {
-	return await request.get(`/student/queryUserInfo`);
+  return await request.get(`/student/queryUserInfo`);
 };
 /** 获取老师信息 */
 export const teacherQueryUserInfo = () => {
-	return request.get(`/user/getUserInfo`);
+  return request.get(`/user/getUserInfo`);
 };
 /** 创建曲谱 */
 export const api_musicSheetCreationSave = (data: any) => {
-	return request.post(`/musicSheetCreation/save`, { data, requestType: 'json' });
+  return request.post(`/musicSheetCreation/save`, { data, requestType: "json" });
 };
 /** 曲谱列表 */
 export const api_musicSheetCreationPage = (data: any) => {
-	return request.post(`/musicSheetCreation/page`, { data, requestType: 'json' });
+  return request.post(`/musicSheetCreation/page`, { data, requestType: "json" });
 };
 /** 删除曲谱 */
 export const api_musicSheetCreationRemove = (id: any, delMusicSheet: number) => {
-	return request.post(`/musicSheetCreation/remove?id=${id}&delMusicSheet=${delMusicSheet}`);
+  return request.post(`/musicSheetCreation/remove?id=${id}&delMusicSheet=${delMusicSheet}`);
 };
 /** 曲谱详情 */
 export const api_musicSheetCreationDetail = (data: any) => {
-	return request.get(`/musicSheetCreation/detail/${data}`);
+  return request.get(`/musicSheetCreation/detail/${data}`);
 };
 /** 曲谱更新 */
 export const api_musicSheetCreationUpdate = (data: any) => {
-	return request.post(`/musicSheetCreation/update`, {data, requestType: 'json'});
+  return request.post(`/musicSheetCreation/update`, { data, requestType: "json" });
 };
 /** 声部 */
 export const api_subjectList = () => {
-	return request.post(`/subject/list`);
+  return request.post(`/subject/list`);
 };
 
 /** 导入xml */
 export const api_xmlToAbc = (data: any) => {
-	return request.post(`/musicSheetCreation/xmlToAbc`, {
-		requestType: 'form',
-		data: data
-	});
-}
+  return request.post(`/musicSheetCreation/xmlToAbc`, {
+    requestType: "form",
+    data: data,
+  });
+};
 /** 创建曲谱 */
 export const api_musicSheetCreationSaveMusic = (data: any) => {
-	return request.post(`/musicSheetCreation/saveMusic`, {
-		data: data,
-		requestType: 'json'
-	});
-}
+  return request.post(`/musicSheetCreation/saveMusic`, {
+    data: data,
+    requestType: "json",
+  });
+};
 /** wav转mp3 */
 export const api_musicSheetCreationWav2mp3 = (data: any) => {
-	return request.get(`/musicSheetCreation/wav2mp3?url=` + data);
-}
+  return request.get(`/musicSheetCreation/wav2mp3?url=` + data);
+};
 
+/** 添加曲谱转换 */
+export const api_musicalScoreConversionRecordSave = (data: any) => {
+  return request.post("/musicalScoreConversionRecord/save", {
+    data: data,
+    requestType: "json",
+  });
+};
 
+/** 曲谱转换列表 */
+export const api_musicalScoreConversionRecordPage = (data: any) => {
+  return request.post("/musicalScoreConversionRecord/page", {
+    data: data,
+    requestType: "json",
+  });
+};
+/** 曲谱转换删除 */
+export const api_musicalScoreConversionRecordRemove = (data: any) => {
+  return request.post("/musicalScoreConversionRecord/remove?id=" + data);
+};

+ 33 - 0
src/pc/component/upload-file/index.module.less

@@ -0,0 +1,33 @@
+.uploadFile {
+  display: flex;
+  align-items: center;
+  padding-left: 10px;
+
+  :global {
+    .n-upload {
+      width: auto !important;
+    }
+
+    .n-button {
+      height: 36px !important;
+      font-size: 15px;
+      font-weight: 600;
+      color: #FFFFFF;
+      line-height: 21px;
+      border-radius: 7px !important;
+    }
+  }
+
+  .iconUpload {
+    width: 19px;
+    height: 16px;
+    margin-right: 8px;
+  }
+}
+
+.tips {
+  padding-left: 11px;
+  font-size: 15px;
+  color: #777777;
+  line-height: 21px;
+}

+ 121 - 0
src/pc/component/upload-file/index.tsx

@@ -0,0 +1,121 @@
+import { NButton, NUpload, UploadCustomRequestOptions, useMessage } from "naive-ui";
+import { defineComponent, reactive, ref } from "vue";
+import styles from "./index.module.less";
+import iconUpload from "../upload-to-tasks/images/icon-upload.png";
+import { getUploadSign, onFileUpload, onOnlyFileUpload } from "/src/utils/oss-file-upload";
+import { api_musicalScoreConversionRecordSave } from "../../api";
+import { uploadState, eventGlobal } from "../upload-to-tasks/state";
+
+export default defineComponent({
+  name: "upload-file",
+  setup() {
+    const message = useMessage();
+    const inputRef = ref();
+    const state = reactive({
+      fileList: [] as any,
+      uploading: false,
+    }) as any;
+
+    /** 选择文件 */
+    const handleSelectFiles = async (e: Event) => {
+      state.uploading = true;
+      try {
+        const files = (e.target as HTMLInputElement).files || [];
+        // console.log("🚀 ~ files:", files);
+        if (files.length > 5) {
+          message.error("最多选择5个文件");
+          state.uploading = false;
+
+          return;
+        }
+
+        for (let index = 0; index < files.length; index++) {
+          const file = files[index];
+          const type = file.type.includes("png") || file.type.includes("jpg") || file.type.includes("jpeg") ? "IMG" : file.type.includes("xml") ? "XML" : file.type.includes("application/pdf") ? "pdf" : "other";
+          if (type === "other") {
+            message.error(`文件格式不支持`);
+            state.uploading = false;
+            return false;
+          }
+          let isLt2M = true;
+          const size = 50; //type === "IMG" ? 5 : type === "XML" ? 20 : 500;
+          if (size) {
+            isLt2M = file.size / 1024 / 1024 < size;
+            if (!isLt2M) {
+              const typeStr = type === "IMG" ? "图片" : type === "XML" ? "XMl" : "";
+              message.error(`${typeStr}大小不能超过${size}M`);
+              state.uploading = false;
+              return false;
+            }
+          }
+        }
+
+        for (let index = 0; index < files.length; index++) {
+          const file = files[index];
+          const name = file.name;
+          // const suffix = name.slice(name.lastIndexOf("."));
+          const fileName = name;
+          const obj = {
+            filename: fileName,
+            bucketName: "gyt",
+            postData: {
+              filename: fileName,
+              acl: "public-read",
+              key: fileName,
+              unknowValueField: [],
+            },
+          };
+          const { data } = await getUploadSign(obj);
+
+          const fileParams = {
+            policy: data.policy,
+            signature: data.signature,
+            key: fileName,
+            KSSAccessKeyId: data.kssAccessKeyId,
+            acl: "public-read",
+            name: fileName,
+            file: file,
+          };
+          onOnlyFileUpload("action", fileParams).then(async (res: any) => {
+            console.log(res, "res");
+            const result = await api_musicalScoreConversionRecordSave([{ fileName, fileUrl: res }]);
+
+            uploadState.uploadList.push({
+              fileName,
+              fileUrl: res,
+              musicSheetCreationId: "",
+              id: result.data[0],
+              status: "WAITING",
+            });
+
+            eventGlobal.emit("resetUploadTask");
+          });
+        }
+
+        // 上传完成之后清空数据
+        inputRef.value.value = "";
+      } catch {}
+
+      state.uploading = false;
+    };
+
+    return () => (
+      <div class={styles.uploadFile}>
+        <div>
+          <NButton
+            type="primary"
+            loading={state.uploading}
+            onClick={() => {
+              inputRef.value.click();
+            }}
+          >
+            <img src={iconUpload} class={styles.iconUpload} />
+            上传曲谱
+          </NButton>
+          <input style={{ display: "none" }} ref={inputRef} type="file" accept=".jpg,.png,.jpeg,.xml,application/pdf" multiple onChange={handleSelectFiles} />
+        </div>
+        <p class={styles.tips}>(仅支持上传.PDF、JPG、PNG、XML格式文件)</p>
+      </div>
+    );
+  },
+});

BIN
src/pc/component/upload-to-tasks/images/icon-arrow.png


BIN
src/pc/component/upload-to-tasks/images/icon-close-red.png


BIN
src/pc/component/upload-to-tasks/images/icon-close.png


BIN
src/pc/component/upload-to-tasks/images/icon-error.png


BIN
src/pc/component/upload-to-tasks/images/icon-question.png


BIN
src/pc/component/upload-to-tasks/images/icon-success.png


BIN
src/pc/component/upload-to-tasks/images/icon-upload.png


BIN
src/pc/component/upload-to-tasks/images/icon-warning.png


+ 156 - 0
src/pc/component/upload-to-tasks/index.module.less

@@ -0,0 +1,156 @@
+.uploadToTasks {
+  position: fixed;
+  left: 24px;
+  bottom: 20px;
+  box-shadow: 0px 2px 9px 0px rgba(0, 0, 0, 0.1);
+  background: #FFFFFF;
+  border-radius: 9px;
+}
+
+.error {
+  color: #EA4132;
+}
+
+.success {
+  color: #009B7D;
+}
+
+.arrow {
+  width: 11px;
+  height: 11px;
+  transition: all .2s ease;
+
+  &.arrowDown {
+    transform: rotate(180deg);
+    transition: all .2s ease;
+  }
+}
+
+.loadingSection,
+.succesSection {
+  width: 394px;
+  height: 43px;
+  background: #FFFFFF;
+  box-shadow: 0px 2px 9px 0px rgba(0, 0, 0, 0.1);
+  border-radius: 8px;
+
+  font-size: 15px;
+  color: rgba(0, 0, 0, 0.88);
+  line-height: 15px;
+  display: flex;
+  align-items: center;
+  // height: 100%;
+  justify-content: space-between;
+  padding: 0 19px 0 16px;
+  cursor: pointer;
+
+  .loadingText {
+    display: flex;
+    align-items: center;
+
+    .error {
+      font-weight: bold;
+    }
+  }
+
+  .iconQuestion {
+    width: 17px;
+    height: 17px;
+    margin-right: 8px;
+  }
+
+
+}
+
+.succesSection {
+  span {
+    margin-right: 8px;
+  }
+}
+
+
+.uploadList {
+  margin: 10px 0;
+  padding: 0 11px;
+  width: 100%;
+  border-radius: 9px;
+  max-height: 40vh;
+  transition: all .2s ease;
+}
+
+.uploadItem {
+  padding: 15px 11px;
+  border-radius: 8px;
+  display: flex;
+  align-items: center;
+  justify-content: space-between;
+  font-size: 15px;
+  line-height: 21px;
+  color: #131415;
+  transition: all .2s ease;
+
+  &.uploadSuccess {
+    color: #009B7D;
+
+    .text {
+      display: none;
+    }
+
+    &:hover {
+      .text {
+        display: block;
+      }
+    }
+  }
+
+  &.uploadError {
+    color: #EA4132;
+  }
+
+  &.uploadWaiting {
+    color: #888888;
+  }
+
+  &:hover {
+    transition: all .2s ease;
+    background: #F5F6FA;
+
+    .iconClose {
+      display: block;
+    }
+
+    .text {
+      display: none;
+    }
+  }
+
+  .info {
+    display: flex;
+    align-items: center;
+  }
+
+  .icon {
+    width: 17px;
+    height: 17px;
+    margin-right: 8px;
+  }
+
+  .status {
+    display: flex;
+    align-items: center;
+    cursor: pointer;
+  }
+
+  .iconClose {
+    display: none;
+    width: 15px;
+    height: 15px;
+  }
+
+  .message {
+    max-width: 220px;
+    overflow: hidden;
+    white-space: nowrap;
+    text-overflow: ellipsis;
+  }
+}

+ 226 - 0
src/pc/component/upload-to-tasks/index.tsx

@@ -0,0 +1,226 @@
+import { computed, defineComponent, onMounted, onUnmounted, reactive } from "vue";
+import styles from "./index.module.less";
+import iconQuestion from "./images/icon-question.png";
+import iconArrow from "./images/icon-arrow.png";
+import iconSuccess from "./images/icon-success.png";
+import iconError from "./images/icon-error.png";
+import iconWarning from "./images/icon-warning.png";
+import iconClose from "./images/icon-close.png";
+import iconCloseRed from "./images/icon-close-red.png";
+import { NScrollbar, NSpin } from "naive-ui";
+import { eventGlobal, getUploadCatch, saveUploadCatch, uploadState } from "./state";
+import { api_musicalScoreConversionRecordPage, api_musicalScoreConversionRecordRemove } from "../../api";
+
+export default defineComponent({
+  name: "upload-to-tasks",
+  setup() {
+    // 等待中 WAITING 转换中:CONVERSION, 转换成功:SUCCESS, 转换失败:FAIL
+    const state = reactive({
+      showUploadList: false,
+      timer: null as any,
+    });
+
+    /** 是否有等待转换数据 */
+    const isWaiting = computed(() => {
+      const list = uploadState.uploadList || [];
+      let count = 0;
+      list.forEach((item: any) => {
+        if (item.status === "CONVERSION" || item.status === "WAITING") {
+          count++;
+        }
+      });
+      return count > 0 ? true : false;
+    });
+
+    /** 统计任务数 */
+    const taskStatNums = computed(() => {
+      const list = uploadState.uploadList || [];
+      const nums = {
+        success: 0,
+        error: 0,
+        waiting: 0,
+      };
+      list.forEach((item: any) => {
+        if (item.status === "CONVERSION" || item.status === "WAITING") {
+          nums.waiting++;
+        } else if (item.status === "SUCCESS") {
+          nums.success++;
+        } else if (item.status === "FAIL") {
+          nums.error++;
+        }
+      });
+
+      return nums;
+    });
+
+    const getRecordList = async (type?: string) => {
+      try {
+        const params: any = {
+          page: 1,
+          rows: -1,
+        };
+        if (type === "ids") {
+          const ids: string[] = [];
+          uploadState.uploadList.forEach((item: any) => {
+            // if (item.status === "CONVERSION" || item.status === "WAITING") {
+            ids.push(item.id);
+            // }
+          });
+          params.idList = ids;
+        } else {
+          params.statusList = ["WAITING", "CONVERSION"];
+        }
+        const { data } = await api_musicalScoreConversionRecordPage(params);
+        const temps = data.rows || [];
+
+        const result: any = [];
+        temps.forEach((item: any) => {
+          result.push({
+            id: item.id,
+            musicSheetCreationId: item.musicSheetCreationId,
+            status: item.status,
+            fileName: item.fileName,
+            fileUrl: item.fileUrl,
+          });
+        });
+        uploadState.uploadList = result;
+
+        // 储存
+        saveUploadCatch(result);
+      } catch {
+        //
+      }
+    };
+
+    const onOperation = async (item: any, type: string) => {
+      try {
+        if (type === "remove") {
+          await api_musicalScoreConversionRecordRemove(item.id);
+          const index = uploadState.uploadList.findIndex((child: any) => child.id === item.id);
+          uploadState.uploadList.splice(index, 1);
+          saveUploadCatch();
+          return;
+        } else if (type === "look") {
+          window.parent.postMessage(
+            {
+              api: "notation_open",
+              url: `${location.origin}/notation/#/?v=${Date.now()}&id=${item.musicSheetCreationId}`,
+            },
+            "*"
+          );
+        }
+      } catch {}
+    };
+
+    const __init = () => {
+      state.timer = setInterval(() => {
+        if (isWaiting.value) {
+          getRecordList("ids");
+        }
+      }, 5000);
+    };
+
+    onMounted(() => {
+      // 获取丝缓存数据
+      const taskUploadMusic = getUploadCatch();
+      if (taskUploadMusic.length > 0) {
+        uploadState.uploadList = taskUploadMusic;
+        getRecordList("ids");
+      } else {
+        getRecordList();
+      }
+
+      // 上传文件成功之后刷新列表
+      eventGlobal.on("resetUploadTask", () => getRecordList("ids"));
+
+      // 开启定时器
+      __init();
+    });
+
+    onUnmounted(() => {
+      eventGlobal.off("resetUploadTask", () => getRecordList());
+      clearInterval(state.timer);
+    });
+    return () => (
+      <div class={styles.uploadToTasks} style={{ display: uploadState.uploadList.length > 0 ? "block" : "none" }}>
+        <NScrollbar class={styles.uploadList} style={{ display: state.showUploadList ? "block" : "none" }}>
+          {uploadState.uploadList.map((item: any) => (
+            <>
+              {item.status === "SUCCESS" && (
+                <div class={[styles.uploadItem, styles.uploadSuccess]}>
+                  <div class={styles.info}>
+                    <img class={styles.icon} src={iconSuccess} />
+                    <p class={styles.message}>{item.fileName}</p>
+                  </div>
+
+                  <div class={styles.status} onClick={() => onOperation(item, "look")}>
+                    <span class={styles.text}>点击查看</span>
+                  </div>
+                </div>
+              )}
+              {item.status === "FAIL" && (
+                <div class={[styles.uploadItem, styles.uploadError]}>
+                  <div class={styles.info}>
+                    <img class={styles.icon} src={iconError} />
+                    <p class={styles.message}>{item.fileName}</p>
+                  </div>
+
+                  <div class={styles.status} onClick={() => onOperation(item, "remove")}>
+                    <img class={styles.iconClose} src={iconCloseRed} />
+                  </div>
+                </div>
+              )}
+
+              {item.status === "WAITING" && (
+                <div class={[styles.uploadItem, styles.uploadWaiting]}>
+                  <div class={styles.info}>
+                    <img class={styles.icon} src={iconWarning} />
+                    <p class={styles.message}>{item.fileName}</p>
+                  </div>
+
+                  <div class={styles.status} onClick={() => onOperation(item, "remove")}>
+                    <img class={styles.iconClose} src={iconClose} />
+                    <span class={styles.text}>等待上传</span>
+                  </div>
+                </div>
+              )}
+              {item.status === "CONVERSION" && (
+                <div class={[styles.uploadItem, styles.uploadLoading]}>
+                  <div class={styles.info}>
+                    <NSpin class={styles.icon} />
+                    <p class={styles.message}>{item.fileName}</p>
+                  </div>
+
+                  <div class={styles.status} onClick={() => onOperation(item, "remove")}>
+                    <img class={styles.iconClose} src={iconClose} />
+                  </div>
+                </div>
+              )}
+            </>
+          ))}
+        </NScrollbar>
+        <div onClick={() => (state.showUploadList = !state.showUploadList)}>
+          {isWaiting.value ? (
+            <div class={styles.loadingSection}>
+              <div class={styles.loadingText}>
+                <img class={styles.iconQuestion} src={iconQuestion} />
+                <p>
+                  剩余<span class={styles.error}>{taskStatNums.value.waiting}</span>个文件正在上传中…
+                </p>
+              </div>
+
+              <img class={[styles.arrow, state.showUploadList && styles.arrowDown]} src={iconArrow} />
+            </div>
+          ) : (
+            <div class={styles.succesSection}>
+              <p>
+                上传完成,<span class={styles.success}>成功{taskStatNums.value.success}</span> <span class={styles.error}>失败{taskStatNums.value.error}</span>
+              </p>
+              <img class={[styles.arrow, state.showUploadList && styles.arrowDown]} src={iconArrow} />
+            </div>
+          )}
+        </div>
+      </div>
+    );
+  },
+});

+ 37 - 0
src/pc/component/upload-to-tasks/state.ts

@@ -0,0 +1,37 @@
+import { reactive } from "vue";
+import EventEmitter from "eventemitter3";
+const UPLOADKEY = "task-upload-music";
+
+export const eventGlobal = new EventEmitter();
+// type UploadType = {
+//   id: string;
+//   musicSheetCreationId: string;
+//   fileName: string;
+//   fileUrl: string;
+//   status: string;
+// };
+// 等待中 WAITING 转换中:CONVERSION,转换成功:SUCCESS,转换失败:FAIL
+export const uploadState = reactive({
+  uploadList: [] as any[],
+});
+
+/** 保存缓存 */
+export const saveUploadCatch = (list?: any[]) => {
+  sessionStorage.setItem(UPLOADKEY, JSON.stringify(list || uploadState.uploadList));
+};
+
+/** 获取缓存 */
+export const getUploadCatch = () => {
+  const taskUploadMusicJson = sessionStorage.getItem(UPLOADKEY);
+  if (taskUploadMusicJson) {
+    const taskUploadMusic = JSON.parse(taskUploadMusicJson);
+    return taskUploadMusic;
+  } else {
+    return [];
+  }
+};
+
+/** 删除缓存 */
+export const deleteUploadCatch = () => {
+  sessionStorage.removeItem(UPLOADKEY);
+};

+ 7 - 2
src/pc/create/index.module.less

@@ -72,6 +72,7 @@
         }
     }
 }
+
 @media screen and (max-width: 600px) {
     .wrapBox {
         .itemWrap {
@@ -158,11 +159,15 @@
 
     .itemtitle {
         font-weight: 600;
+        white-space: nowrap;
+        overflow: hidden;
+        max-width: 180px;
+        display: inline-block;
+        text-overflow: ellipsis;
     }
 
     .time {
         font-size: 12px;
         color: #777;
     }
-}
-
+}

+ 204 - 194
src/pc/create/index.tsx

@@ -1,219 +1,229 @@
 import { defineComponent, nextTick, onMounted, onUnmounted, reactive, ref, watch } from "vue";
 import styles from "./index.module.less";
-import { NButton, NCheckbox, NModal, NRadio, NSpace, NSpin, useDialog } from "naive-ui";
+import { NRadio, NSpace, NSpin, useDialog } from "naive-ui";
 import { getImage } from "../home/images";
 import TheCreate from "./component/the-create";
 import { storeData } from "/src/store";
 import { api_musicSheetCreationPage, api_musicSheetCreationRemove } from "../api";
-import { useRouter } from "vue-router";
 import ABCJS from "abcjs";
 import { usePageVisibility } from "@vant/use";
 import UploadToResources from "../component/upload-to-resources";
 import { getQuery } from "/src/utils/queryString";
 import { browser } from "/src/utils";
+import UploadToTasks from "../component/upload-to-tasks";
+import UploadFile from "../component/upload-file";
+import { saveUploadCatch, uploadState } from "../component/upload-to-tasks/state";
 
 export default defineComponent({
-	name: "Create",
-	setup() {
-		const query = getQuery();
-		const dialog = useDialog();
-		console.log(storeData.user);
-		const forms = reactive({
-			teacherId: storeData.user.id,
-			page: 1,
-			keyword: "",
-			rows: 20,
-		});
-		const data = reactive({
-			list: [] as any[],
-			addShow: query.addShow ? true : false,
-			loading: false,
-			finish: false,
-			isCreated: false,
-			uploadShow: false,
-			item: {} as any,
-		});
-		const getList = async () => {
-			data.loading = true;
-			const res = await api_musicSheetCreationPage({ ...forms });
-			if (res?.code == 200) {
-				if (data.isCreated) {
-					data.isCreated = false;
-					handleOpenNotaion(res.data.rows[0]);
-				}
-				data.list = data.list.concat(res.data.rows);
-				data.finish = res.data.rows.length < forms.rows;
-			}
-			data.loading = false;
-		};
-		const handleReset = () => {
-			forms.page = 1;
-			data.finish = false;
-			data.list = [];
-			getList();
-		};
-		const pageVisibility = usePageVisibility();
-		watch(pageVisibility, (val) => {
-			if (val === "visible") {
-				handleReset();
-			}
-		});
+  name: "Create",
+  setup() {
+    const query = getQuery();
+    const dialog = useDialog();
+    console.log(storeData.user);
+    const forms = reactive({
+      teacherId: storeData.user.id,
+      page: 1,
+      keyword: "",
+      rows: 20,
+    });
+    const data = reactive({
+      list: [] as any[],
+      addShow: query.addShow ? true : false,
+      loading: false,
+      finish: false,
+      isCreated: false,
+      uploadShow: false,
+      item: {} as any,
+    });
+    const getList = async () => {
+      data.loading = true;
+      const res = await api_musicSheetCreationPage({ ...forms });
+      if (res?.code == 200) {
+        if (data.isCreated) {
+          data.isCreated = false;
+          handleOpenNotaion(res.data.rows[0]);
+        }
+        data.list = data.list.concat(res.data.rows);
+        data.finish = res.data.rows.length < forms.rows;
+      }
+      data.loading = false;
+    };
+    const handleReset = () => {
+      forms.page = 1;
+      data.finish = false;
+      data.list = [];
+      getList();
+    };
+    const pageVisibility = usePageVisibility();
+    watch(pageVisibility, (val) => {
+      if (val === "visible") {
+        handleReset();
+      }
+    });
 
-		const handleDelte = (item: any) => {
-			const checked = ref(true);
-			dialog.warning({
-				autoFocus: false,
-				class: "deleteDialog",
-				title: "删除曲谱",
-				content: () => (
-					<div onClick={() => checked.value = !checked.value}>
-						<NRadio checked={checked.value}>同步删除我的资源中的该曲目</NRadio>
-					</div>
-				),
-				// content: () => <div>确认删除当前曲谱?</div>,
-				positiveText: "取消",
-				positiveButtonProps: {
-					type: "default",
-				},
-				negativeText: "删除",
-				negativeButtonProps: {
-					type: "primary",
-					ghost: false,
-				},
-				onPositiveClick: () => {},
-				onNegativeClick: async () => {
-					await api_musicSheetCreationRemove(item.id, checked.value ? 1 : 0);
-					handleReset();
-				},
-			});
-		};
-		const loadingRef = ref();
+    const handleDelte = (item: any) => {
+      const checked = ref(true);
+      dialog.warning({
+        autoFocus: false,
+        class: "deleteDialog",
+        title: "删除曲谱",
+        content: () => (
+          <div onClick={() => (checked.value = !checked.value)}>
+            <NRadio checked={checked.value}>同步删除我的资源中的该曲目</NRadio>
+          </div>
+        ),
+        // content: () => <div>确认删除当前曲谱?</div>,
+        positiveText: "取消",
+        positiveButtonProps: {
+          type: "default",
+        },
+        negativeText: "删除",
+        negativeButtonProps: {
+          type: "primary",
+          ghost: false,
+        },
+        onPositiveClick: () => {},
+        onNegativeClick: async () => {
+          await api_musicSheetCreationRemove(item.id, checked.value ? 1 : 0);
+          handleReset();
 
-		const messageEvent = (params?: any) => {
-			// 在老师端里面关闭要刷新
-			if (params.data?.api == "reload") {
-				handleReset();
-			}
-		};
-		onMounted(() => {
-			getList();
-			if (loadingRef.value) {
-				const obv = new IntersectionObserver((entries) => {
-					if (entries[0].isIntersecting) {
-						if (data.finish || data.loading) return;
-						forms.page++;
-						getList();
-					}
-				});
-				obv.observe(loadingRef.value?.$el);
-			}
+          // 删除上传记录里面的数据
+          const index = uploadState.uploadList.findIndex((upload: any) => upload.musicSheetCreationId === item.id);
+          if (index !== -1) {
+            uploadState.uploadList.splice(index, 1);
 
-			window.addEventListener("message", (params?: any) => {
-				messageEvent(params);
-			});
-		});
+            saveUploadCatch();
+          }
+        },
+      });
+    };
+    const loadingRef = ref();
 
-		onUnmounted(() => {
-			window.removeEventListener("message", messageEvent);
-		});
-		const handleOpenNotaion = (item: any) => {
-			window.parent.postMessage(
-				{
-					api: "notation_open",
-					url: `${location.origin}/notation/#/?v=${Date.now()}&id=${item.id}`,
-				},
-				"*"
-			);
-		};
-		const productSvg = (abc: string, id: string) => {
-			const a = ABCJS.renderAbc(id, abc, { selectTypes: false, add_classes: true })[0];
-			return a;
-		};
+    const messageEvent = (params?: any) => {
+      // 在老师端里面关闭要刷新
+      if (params.data?.api == "reload") {
+        handleReset();
+      }
+    };
+    onMounted(() => {
+      getList();
+      if (loadingRef.value) {
+        const obv = new IntersectionObserver((entries) => {
+          if (entries[0].isIntersecting) {
+            if (data.finish || data.loading) return;
+            forms.page++;
+            getList();
+          }
+        });
+        obv.observe(loadingRef.value?.$el);
+      }
+
+      window.addEventListener("message", (params?: any) => {
+        messageEvent(params);
+      });
+    });
+
+    onUnmounted(() => {
+      window.removeEventListener("message", messageEvent);
+    });
+    const handleOpenNotaion = (item: any) => {
+      window.parent.postMessage(
+        {
+          api: "notation_open",
+          url: `${location.origin}/notation/#/?v=${Date.now()}&id=${item.id}`,
+        },
+        "*"
+      );
+    };
+    const productSvg = (abc: string, id: string) => {
+      const a = ABCJS.renderAbc(id, abc, { selectTypes: false, add_classes: true })[0];
+      return a;
+    };
 
     const handleSuccess = () => {
       data.list.find((item: any) => item.id === data.item.id).uploadStatus = "YES";
-    }
-		return () => (
-			<div class={styles.wrap}>
-				<div class={styles.wrapBox}>
-					<div class={styles.itemWrap}>
-						<div class={styles.itemWrapBox}>
-							<div class={styles.createItem} onClick={() => (data.addShow = true)}>
-								<img src={getImage("icon_29.png")} />
-								<div>新建乐谱</div>
-							</div>
-						</div>
-					</div>
+    };
+    return () => (
+      <div class={styles.wrap}>
+        <UploadFile />
 
-					{data.list.map((item, index: number) => (
-						<div class={styles.itemWrap}>
-							<div class={styles.itemWrapBox}>
-								<div class={styles.item} onClick={() => handleOpenNotaion(item)}>
-									<div class={styles.imgBox} id={"item_" + index}>
-										<img
-											src={getImage("icon_staff.png")}
-											onLoad={() => {
-												item.visualObj = productSvg(item.creationConfig, "item_" + index);
-											}}
-										/>
-									</div>
-									<div class={styles.itemBottom}>
-										<div class={styles.bottombox}>
-											<div class={styles.bottomLeft}>
-												<div class={styles.itemtitle}>
-													<span>{item.name || `未命名乐谱-${index + 1}`}</span>
-												</div>
-												<div class={styles.time}>{item.updateTime}</div>
-											</div>
-											{item.uploadStatus !== "YES" && (
-												<img
-													class={styles.bottomBtn}
-													src={getImage("icon_29_2.png")}
-													onClick={(e: Event) => {
+        <div class={styles.wrapBox}>
+          <div class={styles.itemWrap}>
+            <div class={styles.itemWrapBox}>
+              <div class={styles.createItem} onClick={() => (data.addShow = true)}>
+                <img src={getImage("icon_29.png")} />
+                <div>新建乐谱</div>
+              </div>
+            </div>
+          </div>
+
+          {data.list.map((item, index: number) => (
+            <div class={styles.itemWrap}>
+              <div class={styles.itemWrapBox}>
+                <div class={styles.item} onClick={() => handleOpenNotaion(item)}>
+                  <div class={styles.imgBox} id={"item_" + index}>
+                    <img
+                      src={getImage("icon_staff.png")}
+                      onLoad={() => {
+                        item.visualObj = productSvg(item.creationConfig, "item_" + index);
+                      }}
+                    />
+                  </div>
+                  <div class={styles.itemBottom}>
+                    <div class={styles.bottombox}>
+                      <div class={styles.bottomLeft}>
+                        <div class={styles.itemtitle}>
+                          <span>{item.name || `未命名乐谱-${index + 1}`}</span>
+                        </div>
+                        <div class={styles.time}>{item.updateTime}</div>
+                      </div>
+                      {item.uploadStatus !== "YES" && (
+                        <img
+                          class={styles.bottomBtn}
+                          src={getImage("icon_29_2.png")}
+                          onClick={(e: Event) => {
                             e.stopPropagation();
-														data.item = { ...item };
-														nextTick(() => {
-															data.uploadShow = true;
-														});
-													}}
-												/>
-											)}
-											<img
-												class={styles.bottomBtn}
-												src={getImage("icon_29_3.png")}
-												onClick={(e: Event) => {
-													e.stopPropagation();
-													handleDelte(item);
-												}}
-											/>
-										</div>
-									</div>
-									{item.uploadStatus === "YES" && (
-										<img class={styles.btn} src={getImage("icon_29_4.png")} />
-									)}
-									{item.uploadStatus === "UPDATE" && (
-										<img class={styles.btn} src={getImage("icon_29_5.png")} />
-									)}
-								</div>
-							</div>
-						</div>
-					))}
-				</div>
-				{!data.finish && (
-					<NSpace ref={loadingRef} justify="center" style={{ padding: "30px" }}>
-						<NSpin size="large" />
-					</NSpace>
-				)}
+                            data.item = { ...item };
+                            nextTick(() => {
+                              data.uploadShow = true;
+                            });
+                          }}
+                        />
+                      )}
+                      <img
+                        class={styles.bottomBtn}
+                        src={getImage("icon_29_3.png")}
+                        onClick={(e: Event) => {
+                          e.stopPropagation();
+                          handleDelte(item);
+                        }}
+                      />
+                    </div>
+                  </div>
+                  {item.uploadStatus === "YES" && <img class={styles.btn} src={getImage("icon_29_4.png")} />}
+                  {item.uploadStatus === "UPDATE" && <img class={styles.btn} src={getImage("icon_29_5.png")} />}
+                </div>
+              </div>
+            </div>
+          ))}
+        </div>
+        {!data.finish && (
+          <NSpace ref={loadingRef} justify="center" style={{ padding: "30px" }}>
+            <NSpin size="large" />
+          </NSpace>
+        )}
+
+        <TheCreate
+          v-model:show={data.addShow}
+          onCreate={() => {
+            data.addShow = false;
+          }}
+        />
 
-				<TheCreate
-					v-model:show={data.addShow}
-					onCreate={() => {
-						data.addShow = false;
-					}}
-				/>
+        <UploadToResources v-model:show={data.uploadShow} item={data.item} onSuccess={() => handleSuccess()} />
 
-				<UploadToResources v-model:show={data.uploadShow} item={data.item} onSuccess={() => handleSuccess()} />
-			</div>
-		);
-	},
+        <UploadToTasks />
+      </div>
+    );
+  },
 });

+ 44 - 44
vite.config.ts

@@ -11,49 +11,49 @@ import { VarletUIResolver, NaiveUiResolver } from "unplugin-vue-components/resol
 
 // https://vitejs.dev/config/
 export default defineConfig({
-	base: "./",
-	resolve: {},
-	plugins: [
-		// mkcert(), // 本地https
-		legacy({
-			targets: "last 2 versions and not dead, > 0.3%, Firefox ESR",
-		}),
-		vue(),
-		vueJsx(),
-		// components({
-		// 	resolvers: [NaiveUiResolver()],
-		// })
-	],
-	css: {
-		postcss: {
-			plugins: [
-				// postCssPxToRem({
-				// 	rootValue: 37.5,
-				// 	propList: ["*"],
-				// 	selectorBlackList: [".norem"],
-				// }),
-			],
-		},
-	},
-	build: {
-		rollupOptions: {
-			input: {
-				index: resolve(__dirname, "index.html"),
-			},
-		},
-	},
-	server: {
-		cors: true,
-		port: 3050,
-		// https: true,
-		proxy: {
-			"^/edu-app/.*": {
-				target: "https://test.lexiaoya.cn",
-				// target: "https://dev.kt.colexiu.com",
-				changeOrigin: true,
-				// rewrite: (path) => path.replace(/^\/edu-app/, ""),
-			},
-		},
-	},
+  base: "./",
+  resolve: {},
+  plugins: [
+    // mkcert(), // 本地https
+    legacy({
+      targets: "last 2 versions and not dead, > 0.3%, Firefox ESR",
+    }),
+    vue(),
+    vueJsx(),
+    // components({
+    // 	resolvers: [NaiveUiResolver()],
+    // })
+  ],
+  css: {
+    postcss: {
+      plugins: [
+        // postCssPxToRem({
+        // 	rootValue: 37.5,
+        // 	propList: ["*"],
+        // 	selectorBlackList: [".norem"],
+        // }),
+      ],
+    },
+  },
+  build: {
+    rollupOptions: {
+      input: {
+        index: resolve(__dirname, "index.html"),
+      },
+    },
+  },
+  server: {
+    cors: true,
+    port: 3050,
+    // https: true,
+    proxy: {
+      "^/edu-app/.*": {
+        // target: "https://test.lexiaoya.cn",
+        target: "https://dev.kt.colexiu.com",
+        changeOrigin: true,
+        // rewrite: (path) => path.replace(/^\/edu-app/, ""),
+      },
+    },
+  },
 });
 // vite.config.js

Some files were not shown because too many files changed in this diff